nx_gltf_rig_descriptor_candidate_t230.nx source
↩ module page · 61 lines · 4961 B
1// Source rig evidence; composes the existing descriptor writer and native pose mathematics.
2// Node identities are source indices. Names are preserved, never treated as anatomical proof.
3// Matrices use the existing FBB_Q representation and column-major source coordinates.
4import "nx_gltf_render_descriptor_candidate_t181.nx"
5func grj_matrix(w:*i64,m:*i64)->i64{
6 gpd_s(w,"[");var k:i64=0;while k<16{if k>0{gpd_s(w,",")};if gpd_i(w,m[k])!=0{w[3]=-3;return -3};k=k+1};return gpd_s(w,"]")
7}
8// Metadata validation follows the existing accessor decoder; omitted IBM remains explicitly unexercised.
9func grj_skin_metadata(cx:*i64,sk:i64,count:i64,joints:i64,parents:*i64)->i64{
10 let root:i64=gld_int(cx,sk,"skeleton",-1);let rootHave:i64=gli_member(cx,sk,"skeleton")
11 if rootHave<0||rootHave==1&&(root<0||root>=count){return -2}
12 if rootHave==1{var i:i64=0;while i<joints{let at:i64=gld_nth(cx,sk,"joints",i);let t:*NxJsonTok=cx[2] as *NxJsonTok;glp_reset(t,cx[0] as *u8,cx[1],at);var p:i64=gld_uint(t);while p>=0&&p!=root{p=parents[p]};if p!=root{return -2};i=i+1}}
13 let have:i64=gli_member(cx,sk,"inverseBindMatrices");if have<0{return -2};if have==0{return 0}
14 let index:i64=gld_int(cx,sk,"inverseBindMatrices",-1);if index<0{return -2}
15 let bytes:i64=(GLD_VIEW_WORDS+1)*__size_of(i64);let v:*i64=sys_mmap_try(bytes) as *i64;if (v as i64)==0{return -7}
16 let st:*i64=cx[5] as *i64;var rc:i64=gltf_accessor_view(cx,index,st[2],v)
17 if rc==0{if v[3]!=5126||v[5]!=16||v[1]!=joints{rc=-2}}
18 var i:i64=0;while i<joints&&rc==0{var k:i64=0;while k<16{if gld_view_float(cx,v,i,k,FBB_Q,(v as i64+GLD_VIEW_WORDS*8) as *i64)!=0{rc=-2;break};k=k+1};i=i+1}
19 sys_munmap_direct(v as *u8,bytes);return rc
20}
21func gltf_rig_descriptor(cx:*i64,skin:i64,w:*i64)->i64{
22 if (cx as i64)<=0||(w as i64)<=0{return -1}
23 let st:*i64=cx[5] as *i64;let count:i64=st[5];let sk:i64=gld_nth(cx,0,"skins",skin);if sk<0||count<=0{return -1}
24 let joints:i64=gli_array(cx,sk,"joints",0);if joints<=0||joints>count{return -2}
25 let stride:i64=__size_of(i64)*(1+16+16+1);let scratch:i64=__size_of(i64)*10
26 if count>(GLD_I64_MAX-scratch)/stride{return -7}
27 let bytes:i64=count*stride+scratch;let mem:*u8=sys_mmap_try(bytes);if (mem as i64)==0{return -7}
28 let parents:*i64=mem as *i64;let local:*i64=(mem as i64+count*8) as *i64;let world:*i64=(local as i64+count*128) as *i64;let done:*i64=(world as i64+count*128) as *i64;let trs:*i64=(done as i64+count*8) as *i64
29 var rc:i64=gld_parents(cx,count,parents);var i:i64=0
30 while i<count&&rc==0{
31 let at:i64=gld_nth(cx,0,"nodes",i);let h:i64=gli_member(cx,at,"name")
32 if h<0{rc=-2;break};if h==1{let sp:*i64=cx[4] as *i64;let t:*NxJsonTok=cx[2] as *NxJsonTok;glp_reset(t,cx[0] as *u8,cx[1],sp[0]);if t.kind!=NX_JSON_STRING{rc=-2;break}}
33 if gld_node_trs(cx,i,trs,(local as i64+i*128) as *i64)<0{rc=-2;break};i=i+1
34 }
35 if rc==0{rc=gld_world_matrices(count,parents,local,world,done)}
36 // Validate ordered skin indices independently; duplicated names are legal, duplicated joint nodes are not.
37 i=0;while i<count{done[i]=0;i=i+1};i=0
38 while i<joints&&rc==0{
39 let at:i64=gld_nth(cx,sk,"joints",i);if at<0{rc=-2;break}
40 let t:*NxJsonTok=cx[2] as *NxJsonTok;glp_reset(t,cx[0] as *u8,cx[1],at);let node:i64=gld_uint(t)
41 if node<0||node>=count{rc=-2;break};if done[node]!=0{rc=-2;break};done[node]=1;i=i+1
42 }
43 if rc==0{rc=grj_skin_metadata(cx,sk,count,joints,parents)}
44 if rc!=0{sys_munmap_direct(mem,bytes);return rc}
45 gpd_s(w,"{");if gpd_source_identity(w,cx)!=0{sys_munmap_direct(mem,bytes);return -7}
46 gpd_s(w,"\"schema\":\"nishi-source-rig/1\",\"scope\":\"source-identity-and-rest-hierarchy\",\"basis\":\"gltf-Y-up\",\"matrixOrder\":\"column-major\",\"physicalScale\":null,\"q\":");gpd_n(w,FBB_Q)
47 gpd_s(w,",\"skin\":");gpd_n(w,skin);gpd_s(w,",\"sourceSkeleton\":");if gpd_raw(w,cx,sk,"skeleton","null")!=0{rc=-2}
48 gpd_s(w,",\"inverseBindAccessor\":");if gpd_raw(w,cx,sk,"inverseBindMatrices","null")!=0{rc=-2}
49 gpd_s(w,",\"jointNodes\":");if gpd_raw(w,cx,sk,"joints","null")!=0{rc=-2};gpd_s(w,",\"nodes\":[")
50 i=0;while i<count&&rc==0{
51 let at:i64=gld_nth(cx,0,"nodes",i);if i>0{gpd_s(w,",")};gpd_s(w,"{\"sourceNode\":");gpd_n(w,i);gpd_s(w,",\"parent\":");gpd_i(w,parents[i]);gpd_s(w,",\"name\":");if gpd_raw(w,cx,at,"name","null")!=0{rc=-2;break}
52 gpd_s(w,",\"localRest\":");grj_matrix(w,(local as i64+i*128) as *i64);gpd_s(w,",\"worldRest\":");grj_matrix(w,(world as i64+i*128) as *i64);gpd_s(w,"}");i=i+1
53 };gpd_s(w,"]}");sys_munmap_direct(mem,bytes);if w[3]!=0{return -3};return rc
54}
55
56// Additive existing render descriptor: consumers retain the same descriptor contract and source identity.
57func gltf_render_descriptor_with_rig(cx:*i64,mesh:i64,skin:i64,w:*i64)->i64{
58 let start:i64=w[2];let rc:i64=gltf_render_descriptor(cx,mesh,skin,w);if rc!=0{return rc}
59 if w[2]<=start||w[3]!=0{return -3};w[2]=w[2]-1;gpd_s(w,",\"rig\":")
60 let rigrc:i64=gltf_rig_descriptor(cx,skin,w);if rigrc!=0{return rigrc};gpd_s(w,"}");if w[3]!=0{return -3};return 0
61}