nx_fbx_clip_t30.nx source
↩ module page · 122 lines · 5652 B
1// Authored AnimationStack reachability for the existing NXA animation importer.
2// Selects object identities only. Does not evaluate, retarget or claim affine fidelity.
3import "nx_fbx_bind.nx"
4const FC_BAD:i64=0-40
5const FC_MISSING:i64=0-41
6const FC_AMBIGUOUS:i64=0-42
7const FC_CAPACITY:i64=0-43
8const FC_STACK:i64=1
9const FC_LAYER:i64=2
10const FC_NODE:i64=3
11const FC_CURVE:i64=4
12const FC_MODEL:i64=5
13struct FbxClipObject { id:i64,kind:i64,offset:i64,name_offset:i64,name_bytes:i64,selected:i64, }
14struct FbxClipLink { src:i64,dst:i64,offset:i64,kind:i64,scale:i64, }
15struct FbxClipGraph { objects:*FbxClipObject,count:i64,links:*FbxClipLink,link_count:i64, }
16struct FbxClipSelection { stack_id:i64,layers:i64,nodes:i64,curves:i64,scale_nodes:i64, }
17func fc_object(g:*FbxClipGraph,i:i64)->*FbxClipObject{return ((g.objects as i64)+i*__size_of(FbxClipObject)) as *FbxClipObject}
18func fc_link(g:*FbxClipGraph,i:i64)->*FbxClipLink{return ((g.links as i64)+i*__size_of(FbxClipLink)) as *FbxClipLink}
19func fc_find(g:*FbxClipGraph,id:i64)->i64 {
20 var found:i64=FC_MISSING;var i:i64=0
21 while i<g.count{let o:*FbxClipObject=fc_object(g,i);if o.id==id{if found>=0{return FC_AMBIGUOUS};found=i};i=i+1}
22 return found
23}
24func fc_load(b:*u8,n:i64,g:*FbxClipGraph)->i64 {
25 let version:i64=fbxc_version(b,n);if version<0{return FC_BAD}
26 let big:i64=fbxc_big(version)
27 let h:*i64=sys_mmap(FBXC_OUTN*8) as *i64
28 if fbb_find_child(b,n,FBXC_TOPOFF,n,big,"Objects" as *u8,h)!=1{return FC_BAD}
29 var p:i64=h[FBXC_PROPSOFF]+h[FBXC_PLEN];let end:i64=h[FBXC_END]
30 let count:i64=fbb_sibling_count(b,n,p,end,big);if count<=0{return FC_BAD}
31 g.objects=sys_mmap(count*__size_of(FbxClipObject)) as *FbxClipObject;g.count=count
32 var i:i64=0
33 while i<count{
34 if fbb_node(b,n,p,end,big,h)!=1{return FC_BAD}
35 let o:*FbxClipObject=fc_object(g,i);o.offset=p
36 let po:i64=h[FBXC_PROPSOFF];let pe:i64=po+h[FBXC_PLEN]
37 if fbb_property_size(b,po,pe)!=9||b[po]!=(76 as u8){return FC_BAD}
38 o.id=fbxc_i64le(b,po+1)
39 let ns:i64=fbb_property_size(b,po+9,pe)
40 if ns<5||b[po+9]!=(83 as u8){return FC_BAD}
41 o.name_offset=po+14;o.name_bytes=ns-5
42 if fbxc_name_is(b,h[FBXC_NAMEOFF],h[FBXC_NAMELEN],"AnimationStack" as *u8)==1{o.kind=FC_STACK}
43 if fbxc_name_is(b,h[FBXC_NAMEOFF],h[FBXC_NAMELEN],"AnimationLayer" as *u8)==1{o.kind=FC_LAYER}
44 if fbxc_name_is(b,h[FBXC_NAMEOFF],h[FBXC_NAMELEN],"AnimationCurveNode" as *u8)==1{o.kind=FC_NODE}
45 if fbxc_name_is(b,h[FBXC_NAMEOFF],h[FBXC_NAMELEN],"AnimationCurve" as *u8)==1{o.kind=FC_CURVE}
46 if fbxc_name_is(b,h[FBXC_NAMEOFF],h[FBXC_NAMELEN],"Model" as *u8)==1{o.kind=FC_MODEL}
47 p=h[FBXC_END];i=i+1
48 }
49 if fbb_find_child(b,n,FBXC_TOPOFF,n,big,"Connections" as *u8,h)!=1{return FC_BAD}
50 p=h[FBXC_PROPSOFF]+h[FBXC_PLEN];let ce:i64=h[FBXC_END]
51 let links:i64=fbb_sibling_count(b,n,p,ce,big);if links<0{return FC_BAD}
52 g.links=sys_mmap((links+1)*__size_of(FbxClipLink)) as *FbxClipLink;g.link_count=0
53 i=0
54 while i<links{
55 if fbb_node(b,n,p,ce,big,h)!=1{return FC_BAD}
56 let po:i64=h[FBXC_PROPSOFF];let pe:i64=po+h[FBXC_PLEN]
57 if fbb_string(b,po,pe,"OO" as *u8)==1||fbb_string(b,po,pe,"OP" as *u8)==1{
58 let a:i64=po+fbb_property_size(b,po,pe)
59 if fbb_property_size(b,a,pe)!=9||fbb_property_size(b,a+9,pe)!=9||b[a]!=(76 as u8)||b[a+9]!=(76 as u8){return FC_BAD}
60 let l:*FbxClipLink=fc_link(g,g.link_count);l.src=fbxc_i64le(b,a+1);l.dst=fbxc_i64le(b,a+10);l.offset=p;l.kind=1
61 if fbb_string(b,po,pe,"OP" as *u8)==1{l.kind=2}
62 if l.kind==2{if fbb_string(b,a+18,pe,"Lcl Scaling" as *u8)==1{l.scale=1}}
63 g.link_count=g.link_count+1
64 }
65 p=h[FBXC_END];i=i+1
66 }
67 sys_munmap(h as *u8,FBXC_OUTN*8);return 0
68}
69// Exactly one parent at the previous animation level prevents mixing stack/layer ownership.
70func fc_select(g:*FbxClipGraph,id:i64,max_nodes:i64,max_curves:i64,s:*FbxClipSelection)->i64 {
71 s.stack_id=id;s.layers=0;s.nodes=0;s.curves=0;s.scale_nodes=0
72 var i:i64=0;while i<g.count{let o:*FbxClipObject=fc_object(g,i);o.selected=0;i=i+1}
73 let selected:i64=fc_find(g,id);if selected<0{return selected}
74 let stack:*FbxClipObject=fc_object(g,selected);if stack.kind!=FC_STACK{return FC_MISSING};stack.selected=1
75 var kind:i64=FC_LAYER
76 while kind<=FC_CURVE{
77 i=0
78 while i<g.count{
79 let o:*FbxClipObject=fc_object(g,i)
80 if o.kind==kind{
81 var j:i64=0;var parents:i64=0;var chosen:i64=0
82 while j<g.link_count{
83 let l:*FbxClipLink=fc_link(g,j)
84 if l.src==o.id{
85 let parent:i64=fc_find(g,l.dst)
86 if parent==FC_AMBIGUOUS{return FC_AMBIGUOUS}
87 if parent>=0{let p:*FbxClipObject=fc_object(g,parent);if p.kind==kind-1{if kind==FC_CURVE{if l.kind!=2{return FC_BAD}}else{if l.kind!=1{return FC_BAD}};parents=parents+1;if p.selected==1{chosen=chosen+1}}}
88 }
89 j=j+1
90 }
91 if chosen>0{
92 if parents!=1||chosen!=1||fc_find(g,o.id)!=i{return FC_AMBIGUOUS}
93 o.selected=1
94 if kind==FC_LAYER{s.layers=s.layers+1}
95 if kind==FC_NODE{s.nodes=s.nodes+1;if s.nodes>max_nodes{return FC_CAPACITY}}
96 if kind==FC_CURVE{s.curves=s.curves+1;if s.curves>max_curves{return FC_CAPACITY}}
97 }
98 }
99 i=i+1
100 }
101 kind=kind+1
102 }
103 i=0
104 while i<g.count{
105 let o:*FbxClipObject=fc_object(g,i)
106 if o.kind==FC_NODE&&o.selected==1{
107 var j:i64=0;var models:i64=0
108 while j<g.link_count{
109 let l:*FbxClipLink=fc_link(g,j)
110 if l.src==o.id&&l.kind==2{
111 let m:i64=fc_find(g,l.dst);if m==FC_AMBIGUOUS{return FC_AMBIGUOUS}
112 if m>=0{let model:*FbxClipObject=fc_object(g,m);if model.kind==FC_MODEL{models=models+1;if l.scale==1{s.scale_nodes=s.scale_nodes+1}}}
113 }
114 j=j+1
115 }
116 if models!=1{return FC_AMBIGUOUS}
117 }
118 i=i+1
119 }
120 if s.layers==0||s.nodes==0||s.curves==0{return FC_MISSING}
121 return 0
122}