code wiki / _hdl_build / nx_gltf_anim_gate.nx

nx_gltf_anim_gate.nx source

↩ module page · 80 lines · 4558 B

1// nx_gltf_anim_gate.nx -- ★export the being as a SKINNED, WALKING .glb. Mesh the skin, bind each vertex to its nearest 2// part's deepest FK bone, export with a walk-cycle animation, self-verify the container + names. Writes nishi_being_walk.glb. 3// license_tier: ORIGINAL expect_exit: 0 4import "nx_syscalls.nx" 5import "nx_trimesh.nx" 6import "nx_isosurf.nx" 7import "nx_bodyatlas.nx" 8import "nx_gltf_anim.nx" 9 10func hw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 11func pn(v: i64) -> i64 { let b: *u8=sys_mmap(32) as *u8; var x: i64=v; var ng: i64=0; if x<0{ng=1;x=0-x} var i: i64=31; if x==0{b[i]=48 as u8;i=i-1} while x>0{b[i]=(48+x%10) as u8;x=x/10;i=i-1} if ng==1{b[i]=45 as u8;i=i-1} sys_write(1,(b as i64+i+1) as *u8,31-i); return 0 } 12func ru32(buf: *u8, at: i64) -> i64 { return (buf[at] as i64) + ((buf[at+1] as i64)<<8) + ((buf[at+2] as i64)<<16) + ((buf[at+3] as i64)<<24) } 13func hasstr(buf: *u8, n: i64, needle: *u8) -> i64 { var m: i64=0; while needle[m]!=(0 as u8){m=m+1} var i: i64=0; while i+m<=n { var k: i64=0; while k<m { if buf[i+k]!=needle[k] {k=m+9} else {k=k+1} } if k==m {return 1} i=i+1 } return 0 } 14 15const GX: i64 = 32 16const GY: i64 = 110 17const GZ: i64 = 20 18const GC: i64 = 18 19const OX: i64 = 0-288 20const OY: i64 = 0-990 21const OZ: i64 = 0-180 22 23func main() -> i64 { 24 hw("=== nx_gltf_anim_gate -- skinned WALKING being -> .glb ===\n" as *u8) 25 var fails: i64 = 0 26 atlas_build(0) 27 let grid: *i64 = sys_mmap((GX+1)*(GY+1)*(GZ+1)*8) as *i64 28 var i: i64 = 0 29 while i <= GX { var jj: i64=0; while jj<=GY { var k: i64=0; while k<=GZ { grid[(i*(GY+1)+jj)*(GZ+1)+k] = ba_sdf(OX+i*GC, OY+jj*GC, OZ+k*GC, 1); k=k+1 } jj=jj+1 } i=i+1 } 30 tm_reset() 31 surface_nets(grid, GX, GY, GZ, OX, OY, OZ, GC, 0, 216+172*256+152*65536) 32 let NV: i64 = tm_nv() 33 // per-vertex joint + colour, from nearest part 34 let jarr: *i64 = sys_mmap(NV*8) as *i64 35 let vp: *i64 = sys_mmap(24) as *i64 36 let jc: *i64 = sys_mmap(9*8) as *i64 37 var b: i64 = 0 38 while b < 9 { jc[b]=0; b=b+1 } 39 i = 0 40 while i < NV { 41 tm_vpos(i, vp) 42 let kk: i64 = ba_nearest(vp[0], vp[1], vp[2], 1) 43 var jt: i64 = 0 44 if kk >= 0 { jt = ba_part_bone(kk); tm_vcol(i, ba_part_color(kk)) } else { tm_vcol(i, 216+172*256+152*65536) } 45 jarr[i] = jt 46 jc[jt] = jc[jt] + 1 47 i = i + 1 48 } 49 hw(" verts="); pn(NV); hw(" joint spread root="); pn(jc[0]); hw(" Lsh="); pn(jc[1]); hw(" Lel="); pn(jc[2]); hw(" Rsh="); pn(jc[3]); hw(" Lhip="); pn(jc[5]); hw(" Lkn="); pn(jc[6]); hw("\n" as *u8) 50 var t0: i64 = 0 51 if jc[1] > 20 { if jc[5] > 20 { if jc[6] > 20 { t0 = 1 } } } // limbs actually got bound to bones 52 if t0 == 1 { hw("T0 PASS vertices bound across the FK bones (arms + legs rigged)\n" as *u8) } else { fails=fails+1; hw("T0 FAIL binding\n" as *u8) } 53 54 let out: *u8 = sys_mmap(8388608) 55 let total: i64 = gltf_anim_export(out, jarr) 56 hw(" glb bytes="); pn(total); hw("\n" as *u8) 57 // self-verify container + rigging/animation presence 58 var t1: i64 = 0 59 if (out[0] as i64)==103 { if ru32(out,8)==total { t1=1 } } 60 if t1 == 1 { hw("T1 PASS glTF header + length\n" as *u8) } else { fails=fails+1; hw("T1 FAIL\n" as *u8) } 61 let jsonLen: i64 = ru32(out,12) 62 let binLenPos: i64 = 20+jsonLen 63 let binLen: i64 = ru32(out,binLenPos) 64 var t2: i64 = 0 65 if (12+8+jsonLen+8+binLen)==total { if (out[binLenPos+4] as i64)==66 { t2=1 } } 66 if t2 == 1 { hw("T2 PASS chunk arithmetic + BIN type\n" as *u8) } else { fails=fails+1; hw("T2 FAIL\n" as *u8) } 67 var t3: i64 = 0 68 if hasstr(out,20+jsonLen,"animations"as *u8)==1 { if hasstr(out,20+jsonLen,"skins"as *u8)==1 { if hasstr(out,20+jsonLen,"JOINTS_0"as *u8)==1 { if hasstr(out,20+jsonLen,"\"walk\""as *u8)==1 { t3=1 } } } } 69 if t3 == 1 { hw("T3 PASS JSON declares skin + JOINTS_0 + a 'walk' animation\n" as *u8) } else { fails=fails+1; hw("T3 FAIL\n" as *u8) } 70 71 let fd: i64 = sys_openat_wr("knowledge/nishi_being_walk.glb\x00" as *u8, 0x1a4) 72 sys_write(fd, out, total) 73 sys_close(fd) 74 hw("wrote knowledge/nishi_being_walk.glb ("); pn(total); hw(" bytes)\n" as *u8) 75 76 if fails == 0 { hw("GLTF-ANIM-GATE GREEN -- the being exports as a SKINNED, WALKING .glb (11-joint rig: 9 FK bones + 2 ankle calf-landmarks, walk-cycle quaternion keyframes). Plays in any glTF viewer. Residual: skinning in our own web viewer (next).\n" as *u8); sys_exit(0); return 0 } 77 hw("GLTF-ANIM-GATE RED fails="); pn(fails); hw("\n" as *u8) 78 sys_exit(1) 79 return 1 80}