nx_gltf_clip_pack_t321.nx source
↩ module page · 88 lines · 6377 B
1// Full authored glTF tracks, not sampled palettes. Reuses native accessor/pose owners.
2// Caller owns returned storage. ABI GPA1 v1:20headerwords,8words/track; all offsets words.
3import "nx_gltf_render_descriptor_candidate_t181.nx"
4import "nx_atomic_rewrite.nx"
5import "nx_itoa_lib.nx"
6const GCP_HEADER:i64=20
7const GCP_TRACK:i64=8
8const GCP_MAGIC:i64=0x47504131
9func gcp_track(cx:*i64,an:i64,index:i64,row:*i64,iv:*i64,ov:*i64)->i64{
10 let channel:i64=gld_nth(cx,an,"channels",index);if channel<0{return -1}
11 let sampler:i64=gld_int(cx,channel,"sampler",-1);if sampler<0||gli_member(cx,channel,"target")!=1{return -1}
12 let sp:*i64=cx[4] as *i64;let target:i64=sp[0];let node:i64=gld_int(cx,target,"node",-1);let st:*i64=cx[5] as *i64
13 if node<0||node>=st[5]||gli_member(cx,target,"path")!=1{return -1}
14 let tok:*NxJsonTok=cx[2] as *NxJsonTok;glp_reset(tok,cx[0] as *u8,cx[1],sp[0]);var flag:i64=0;var components:i64=3
15 if glp_eq(tok,"translation")==1{flag=1};if glp_eq(tok,"rotation")==1{flag=2;components=4};if glp_eq(tok,"scale")==1{flag=4}
16 if flag==0{return -2};let nat:i64=gld_nth(cx,0,"nodes",node);if gli_member(cx,nat,"matrix")!=0{return -2}
17 let sa:i64=gld_nth(cx,an,"samplers",sampler);if sa<0{return -1};var mode:i64=0;let ih:i64=gli_member(cx,sa,"interpolation");if ih<0{return -1}
18 if ih==1{glp_reset(tok,cx[0] as *u8,cx[1],sp[0]);if glp_eq(tok,"STEP")==1{mode=1}else{if glp_eq(tok,"LINEAR")!=1{return -2}}}
19 let input:i64=gld_int(cx,sa,"input",-1);let output:i64=gld_int(cx,sa,"output",-1)
20 if gltf_accessor_view(cx,input,st[2],iv)!=0||gltf_accessor_view(cx,output,st[2],ov)!=0{return -1}
21 if iv[3]!=5126||iv[5]!=1||iv[1]<1||ov[3]!=5126||ov[5]!=components||iv[1]!=ov[1]{return -1}
22 row[0]=node;row[1]=flag;row[2]=mode;row[3]=iv[1];row[4]=input;row[5]=output;row[6]=components;row[7]=0;return 0
23}
24func gltf_clip_pack(cx:*i64,animation:i64,skin:i64,result:*i64)->i64{
25 result[0]=0;result[1]=0
26 let st:*i64=cx[5] as *i64;let nodes:i64=st[5];let sk:i64=gld_nth(cx,0,"skins",skin);let an:i64=gld_nth(cx,0,"animations",animation)
27 if sk<0||an<0||nodes<1{return -1};let joints:i64=gli_array(cx,sk,"joints",0);let tracks:i64=gli_array(cx,an,"channels",0)
28 let max:i64=GLD_I64_MAX/8
29 if joints<1||joints>nodes||tracks<1||nodes>(max-GCP_HEADER)/28{return -1}
30 var words:i64=GCP_HEADER+nodes*28
31 if joints>(max-words)/17{return -1};words=words+joints*17
32 if tracks>(max-words)/GCP_TRACK{return -1};words=words+tracks*GCP_TRACK
33 let scratchBytes:i64=(GLD_VIEW_WORDS*2+GCP_TRACK+8+nodes)*8
34 let scratch:*u8=sys_mmap_try(scratchBytes);if (scratch as i64)==0{return -7}
35 let iv:*i64=scratch as *i64;let ov:*i64=(scratch as i64+GLD_VIEW_WORDS*8) as *i64
36 let row:*i64=(ov as i64+GLD_VIEW_WORDS*8) as *i64;let val:*i64=(row as i64+GCP_TRACK*8) as *i64
37 let masks:*i64=(val as i64+64) as *i64
38 var i:i64=0;var rc:i64=0;while i<nodes{masks[i]=0;i=i+1}
39 i=0;while i<tracks&&rc==0{
40 rc=gcp_track(cx,an,i,row,iv,ov);if rc!=0{break}
41 if (masks[row[0]]&row[1])!=0{rc=-1;break};masks[row[0]]=masks[row[0]]|row[1]
42 if row[3]>(max-words)/(row[6]+1){rc=-1;break};words=words+row[3]*(row[6]+1);i=i+1
43 }
44 if rc!=0{sys_munmap_direct(scratch,scratchBytes);return rc}
45 let p:*i64=sys_mmap_try(words*8) as *i64;if (p as i64)==0{sys_munmap_direct(scratch,scratchBytes);return -7}
46 p[0]=GCP_MAGIC;p[1]=1;p[2]=words;p[3]=nodes;p[4]=joints;p[5]=tracks;p[6]=0;p[7]=FBB_Q;p[8]=VM_Q30
47 p[9]=GCP_HEADER;p[10]=p[9]+nodes;p[11]=p[10]+nodes*10;p[12]=p[11]+nodes*16;p[13]=p[12]+nodes;p[14]=p[13]+joints;p[15]=p[14]+joints*16;p[16]=p[15]+tracks*GCP_TRACK;p[17]=animation;p[18]=skin;p[19]=0
48 let parents:*i64=(p as i64+p[9]*8) as *i64;let trs:*i64=(p as i64+p[10]*8) as *i64;let matrices:*i64=(p as i64+p[11]*8) as *i64;let flags:*i64=(p as i64+p[12]*8) as *i64
49 rc=gld_parents(cx,nodes,parents);i=0
50 while i<nodes&&rc==0{let f:i64=gld_node_trs(cx,i,(trs as i64+i*80) as *i64,(matrices as i64+i*128) as *i64);if f<0{rc=f;break};flags[i]=f;i=i+1}
51 let ib:i64=gld_int(cx,sk,"inverseBindMatrices",-1)
52 if rc==0{if ib<0{rc=-2}else{rc=gltf_accessor_view(cx,ib,st[2],iv)}}
53 if rc==0{if iv[3]!=5126||iv[5]!=16||iv[1]!=joints{rc=-1}}
54 i=0;while i<nodes{masks[i]=0;i=i+1};i=0
55 while i<joints&&rc==0{
56 let at:i64=gld_nth(cx,sk,"joints",i);let tok:*NxJsonTok=cx[2] as *NxJsonTok
57 if at<0{rc=-1;break};glp_reset(tok,cx[0] as *u8,cx[1],at);let node:i64=gld_uint(tok)
58 if node<0||node>=nodes||masks[node]!=0{rc=-1;break};masks[node]=1;p[p[13]+i]=node
59 var k:i64=0;while k<16{rc=gld_view_float(cx,iv,i,k,FBB_Q,(p as i64+(p[14]+i*16+k)*8) as *i64);if rc!=0{break};k=k+1};i=i+1
60 }
61 var cursor:i64=p[16];i=0
62 while i<tracks&&rc==0{
63 rc=gcp_track(cx,an,i,row,iv,ov);if rc!=0{break}
64 let rec:i64=p[15]+i*GCP_TRACK;var k:i64=0;while k<GCP_TRACK{p[rec+k]=row[k];k=k+1}
65 p[rec+4]=cursor;p[rec+5]=cursor+row[3];cursor=cursor+row[3]*(row[6]+1)
66 var last:i64=-1;k=0
67 while k<row[3]&&rc==0{
68 rc=gld_view_float(cx,iv,k,0,VM_Q30,val);if rc!=0{break};if val[0]<0||val[0]<=last{rc=-1;break};last=val[0];p[p[rec+4]+k]=last;if last>p[6]{p[6]=last}
69 var q:i64=FBB_Q;if row[1]==2{q=VM_Q30};var c:i64=0
70 while c<row[6]{rc=gld_view_float(cx,ov,k,c,q,(p as i64+(p[rec+5]+k*row[6]+c)*8) as *i64);if rc!=0{break};c=c+1}
71 if row[1]==2&&rc==0{rc=vm_q_norm_q30((p as i64+(p[rec+5]+k*4)*8) as *i64,val,1024)}
72 k=k+1
73 };i=i+1
74 }
75 sys_munmap_direct(scratch,scratchBytes)
76 if rc!=0||cursor!=words||p[6]<=0{sys_munmap_direct(p as *u8,words*8);if rc==0{return -1};return rc}
77 result[0]=p as i64;result[1]=words;return 0
78}
79func gcp_s(s:*u8)->i64{return sys_write(1,s,gll_slen(s))}
80func main(argc:i64,argv:*i64)->i64{
81 if argc!=3{return 2};let ln:*i64=sys_mmap(8) as *i64;let src:*u8=sys_read_file(argv[1] as *u8,ln);if (src as i64)==0{return 3}
82 let cx:*i64=sys_mmap(GLD_CONTEXT_WORDS*8) as *i64;if gltf_view_open(src,ln[0],cx)!=0{return 4}
83 let result:*i64=sys_mmap(16) as *i64;let rc:i64=gltf_clip_pack(cx,0,0,result)
84 if rc!=0{gcp_s("clip_pack_failed\n" as *u8);return 5}
85 let p:*i64=result[0] as *i64;let written:i64=atomic_rewrite_checked(argv[2] as *u8,p as *u8,result[1]*8)
86 if written!=0{return 6};gcp_s("FULL_CLIP_PACK_OK nodes=" as *u8);nxi_out(p[3]);gcp_s(" joints=" as *u8);nxi_out(p[4]);gcp_s(" tracks=" as *u8);nxi_out(p[5]);gcp_s(" durationQ30=" as *u8);nxi_out(p[6]);gcp_s(" words=" as *u8);nxi_out(p[2]);gcp_s("\n" as *u8)
87 sys_munmap_direct(p as *u8,result[1]*8);gltf_view_close(cx);sys_free_file(src,ln[0]);return 0
88}