code wiki / _hdl_build / nx_ng_avatar_rig.nx

nx_ng_avatar_rig.nx source

↩ module page · 174 lines · 10398 B

1// nx_ng_avatar_rig.nx -- CAP-NEURAL-AVATAR RUNG-2: the SKELETAL RIG. Extends nx_ng_avatar's 1-DOF single- 2// gaussian deform to a multi-gaussian character driven by a multi-BONE skeleton via LINEAR BLEND SKINNING 3// (LBS) -- the exact deformation math a DAZ Genesis figure / Unreal MetaHuman rig uses: each gaussian k's 4// posed center = mu0[k] + SUM_b w[k][b]*pose[b] (a learned per-gaussian skinning weight w binds it to the 5// bones). The KEY S-class rung toward beating DAZ/Unreal characters (shared primitive behind offline + real- 6// time). Honest gated proof, Q16 no-float, reuses the gaussian-splat + GD-fit spine from nx_ng_avatar: 7// T1 LEARNED-RIG: fit the skinning weights from posed frames -> loss->~0 AND w recovers the true binding. 8// T2 NOVEL-POSE: an untrained skeleton pose renders correctly (LBS is linear = generalizes, not memorized). 9// T3 NEG-CONTROL: a RIGID rig (all gaussians share one bone) CANNOT match a pose where the bones differ = 10// the skeleton is load-bearing. T4 BIT-EXACT. 11// HONEST: 1D positions, 2 bones, 2 gaussians, translation-LBS (no rotation), linear skinning. Full production 12// = 3D + rotational LBS + blendshapes (expression) + many bones/gaussians = the follow-on rungs. Sovereign: 13// nx_nofloat_autograd + syscalls. license_tier: ORIGINAL expect_exit: 0 14import "nx_nofloat_autograd.nx" 15import "nx_syscalls.nx" 16const K_MAGIC_1500: i64 = 1500 17const K_MAGIC_22938: i64 = 22938 18const K_MAGIC_42598: i64 = 42598 19const K_MAGIC_19661: i64 = 19661 20const K_MAGIC_32768: i64 = 32768 21const K_MAGIC_8192: i64 = 8192 22const K_MAGIC_26214: i64 = 26214 23const K_MAGIC_3000: i64 = 3000 24 25const RLOG: *u8 = "knowledge/status/ng_avatar_rig.log" 26const Q16: i64 = 65536 27const NP: i64 = 16 28const INV2S2: i64 = 2275555 // 1/(2 sigma^2) Q16, sigma=0.12 29const EPOCHS: i64 = 6000 30const LRQ: i64 = 48 31const NB: i64 = 2 // bones 32const NK: i64 = 2 // gaussians (character parts) 33const NPOSE: i64 = 4 // training skeleton poses 34 35func ap(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 36func apn(v: i64) -> i64 { let b: *u8=sys_mmap(28); var x: i64=v; if x<0{b[0]=45;sys_write(1,b,1);x=0-x} if x==0{b[0]=48;sys_write(1,b,1);return 0} var d: i64=0; var y: i64=x; while y>0{d=d+1;y=y/10} var i: i64=d-1; y=x; while i>=0{b[i]=(48+(y%10)) as u8; y=y/10; i=i-1} sys_write(1,b,d); return 0 } 37func a_abs(v: i64) -> i64 { if v<0 { return 0-v } return v } 38func aqm(a: i64, b: i64) -> i64 { return (a*b)>>16 } 39func rl_ws(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 40func rl_wn(fd: i64, v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(fd,"-" as *u8,1);m=0-m} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(fd,b,k); return 0 } 41 42// single gaussian value at pixel p for a given center. 43func gval(center: i64, p: i64) -> i64 { 44 let pos: i64 = p*(Q16/NP) + (Q16/(2*NP)) 45 let dlt: i64 = pos - center 46 let d2: i64 = aqm(dlt, dlt) 47 return nfa_fxexp(0 - aqm(d2, INV2S2)) 48} 49// LBS posed center of gaussian k: mu0[k] + sum_b w[k*NB+b]*pose[b]. 50func rig_center(mu0: *i64, w: *i64, pose: *i64, k: i64) -> i64 { 51 var c: i64 = mu0[k] 52 var b: i64 = 0 53 while b < NB { c = c + aqm(w[k*NB+b], pose[b]); b = b + 1 } 54 return c 55} 56// render the whole rig (sum of NK gaussians at their posed centers) into out[NP]. 57func render_rig(mu0: *i64, w: *i64, pose: *i64, out: *i64) -> i64 { 58 var p: i64 = 0 59 while p < NP { out[p] = 0; p = p + 1 } 60 var k: i64 = 0 61 while k < NK { 62 let c: i64 = rig_center(mu0, w, pose, k) 63 var p2: i64 = 0 64 while p2 < NP { out[p2] = out[p2] + gval(c, p2); p2 = p2 + 1 } 65 k = k + 1 66 } 67 return 0 68} 69func sse(a: *i64, b: *i64) -> i64 { var s: i64=0; var p: i64=0; while p<NP { let d: i64=a[p]-b[p]; s=s+aqm(d,d); p=p+1 } return s } 70 71// GD-fit the skinning weights w (NK*NB) so render_rig matches the posed frames. Analytic LBS gradient 72// (chain through gaussian k: dg_k/dcenter_k = g_k*(x-center)/sigma^2 ; dcenter_k/dw[k][b] = pose[b]). 73func fit_skin(mu0: *i64, poses: *i64, frames: *i64, w: *i64, lf: *i64, ll: *i64) -> i64 { 74 let cur: *i64 = sys_mmap(NP*8) as *i64 75 let g: *i64 = sys_mmap(NK*NB*8) as *i64 76 var ep: i64 = 0 77 while ep < EPOCHS { 78 var gi: i64 = 0; while gi < NK*NB { g[gi] = 0; gi = gi + 1 } 79 var loss: i64 = 0 80 var f: i64 = 0 81 while f < NPOSE { 82 let pose_f: *i64 = ((poses as i64) + f*NB*8) as *i64 83 render_rig(mu0, w, pose_f, cur) 84 let fr: i64 = f*NP 85 var p0: i64 = 0 86 while p0 < NP { let resid0: i64 = cur[p0] - frames[fr+p0]; loss = loss + aqm(resid0, resid0); p0 = p0 + 1 } 87 var k: i64 = 0 88 while k < NK { 89 let c: i64 = rig_center(mu0, w, pose_f, k) 90 var p: i64 = 0 91 while p < NP { 92 let resid: i64 = cur[p] - frames[fr+p] 93 let gk: i64 = gval(c, p) 94 let pos: i64 = p*(Q16/NP) + (Q16/(2*NP)) 95 let dxc: i64 = pos - c 96 let drdc: i64 = aqm(gk, aqm(dxc, 2 * INV2S2)) 97 var b: i64 = 0 98 while b < NB { g[k*NB+b] = g[k*NB+b] + aqm(aqm(2 * resid, drdc), pose_f[b]); b = b + 1 } 99 p = p + 1 100 } 101 k = k + 1 102 } 103 f = f + 1 104 } 105 if ep == 0 { *lf = loss } 106 *ll = loss 107 if ep % K_MAGIC_1500 == 0 { ap(" fit ep " as *u8); apn(ep); ap(" loss=" as *u8); apn(loss); ap(" w=[" as *u8); apn(w[0]); ap(" " as *u8); apn(w[1]); ap(" | " as *u8); apn(w[2]); ap(" " as *u8); apn(w[3]); ap("]\n" as *u8) } 108 var wi: i64 = 0; while wi < NK*NB { w[wi] = w[wi] - aqm(LRQ, g[wi]); wi = wi + 1 } 109 ep = ep + 1 110 } 111 return 0 112} 113 114func main() -> i64 { 115 ap("nx_ng_avatar_rig: CAP-NEURAL-AVATAR rung-2 -- SKELETAL RIG (multi-bone linear blend skinning)\n" as *u8) 116 let mu0: *i64 = sys_mmap(NK*8) as *i64 117 mu0[0] = K_MAGIC_22938; mu0[1] = K_MAGIC_42598 // two gaussians at 0.35 and 0.65 118 // TRUE skinning: gaussian0 bound to bone0, gaussian1 to bone1. 119 let wt: *i64 = sys_mmap(NK*NB*8) as *i64 120 wt[0]=Q16; wt[1]=0; wt[2]=0; wt[3]=Q16 121 // training skeleton poses (bone translations, Q16): exercise each bone independently + together. 122 let poses: *i64 = sys_mmap(NPOSE*NB*8) as *i64 123 poses[0]=0; poses[1]=0 124 poses[2]=K_MAGIC_19661; poses[3]=0 // ( 0.3, 0.0) 125 poses[4]=0; poses[5]=K_MAGIC_19661 // ( 0.0, 0.3) 126 poses[6]=K_MAGIC_19661; poses[7]=0-K_MAGIC_19661 // ( 0.3,-0.3) 127 let frames: *i64 = sys_mmap(NPOSE*NP*8) as *i64 128 var f: i64=0 129 while f<NPOSE { let pf: *i64=((poses as i64)+f*NB*8) as *i64; let tmp: *i64=sys_mmap(NP*8) as *i64; render_rig(mu0, wt, pf, tmp); var p: i64=0; while p<NP { frames[f*NP+p]=tmp[p]; p=p+1 } f=f+1 } 130 131 // T1: FIT the skinning weights from posed frames (init uniform 0.5). 132 let w: *i64 = sys_mmap(NK*NB*8) as *i64 133 w[0]=K_MAGIC_32768; w[1]=K_MAGIC_32768; w[2]=K_MAGIC_32768; w[3]=K_MAGIC_32768 134 let lf: *i64=sys_mmap(8) as *i64; let ll: *i64=sys_mmap(8) as *i64 135 fit_skin(mu0, poses, frames, w, lf, ll) 136 var t1: i64=0 137 if (*ll)*50 < (*lf) { if a_abs(w[0]-Q16)<K_MAGIC_8192 { if a_abs(w[1])<K_MAGIC_8192 { if a_abs(w[2])<K_MAGIC_8192 { if a_abs(w[3]-Q16)<K_MAGIC_8192 { t1=1 } } } } } 138 139 // T2: NOVEL skeleton pose (-0.4, 0.4), NOT trained -> learned rig matches the true rig (LBS generalizes). 140 let np2: *i64=sys_mmap(NB*8) as *i64; np2[0]=0-K_MAGIC_26214; np2[1]=K_MAGIC_26214 141 let gen: *i64=sys_mmap(NP*8) as *i64; let refn: *i64=sys_mmap(NP*8) as *i64 142 render_rig(mu0, w, np2, gen); render_rig(mu0, wt, np2, refn) 143 let novel_err: i64 = sse(gen, refn) 144 var t2: i64=0; if novel_err < K_MAGIC_3000 { t2=1 } 145 146 // T3: NEG-CONTROL -- a RIGID rig (both gaussians share bone0) can't match a pose where bone1 moves. 147 let wr: *i64=sys_mmap(NK*NB*8) as *i64; wr[0]=Q16; wr[1]=0; wr[2]=Q16; wr[3]=0 148 let rigid: *i64=sys_mmap(NP*8) as *i64 149 var rigid_loss: i64=0 150 f=0; while f<NPOSE { let pf: *i64=((poses as i64)+f*NB*8) as *i64; render_rig(mu0, wr, pf, rigid); var p: i64=0; while p<NP { let d: i64=rigid[p]-frames[f*NP+p]; rigid_loss=rigid_loss+aqm(d,d); p=p+1 } f=f+1 } 151 var t3: i64=0; if rigid_loss > (*ll)*20 { t3=1 } 152 153 // T4: BIT-EXACT (re-fit -> same weights) 154 let w2: *i64=sys_mmap(NK*NB*8) as *i64; w2[0]=K_MAGIC_32768; w2[1]=K_MAGIC_32768; w2[2]=K_MAGIC_32768; w2[3]=K_MAGIC_32768 155 let lf2: *i64=sys_mmap(8) as *i64; let ll2: *i64=sys_mmap(8) as *i64 156 fit_skin(mu0, poses, frames, w2, lf2, ll2) 157 var t4: i64=0; if w2[0]==w[0] { if w2[3]==w[3] { t4=1 } } 158 159 ap(" T1 LEARNED-RIG: fit loss " as *u8); apn(*lf); ap("->" as *u8); apn(*ll); ap(" w=[" as *u8); apn(w[0]); ap(" " as *u8); apn(w[1]); ap(" | " as *u8); apn(w[2]); ap(" " as *u8); apn(w[3]); ap("] vs true[65536 0|0 65536] ok=" as *u8); apn(t1); ap("\n" as *u8) 160 ap(" T2 NOVEL-POSE(-0.4,0.4 untrained): err vs true rig=" as *u8); apn(novel_err); ap(" generalizes=" as *u8); apn(t2); ap("\n" as *u8) 161 ap(" T3 NEG-CONTROL rigid(shared-bone) loss=" as *u8); apn(rigid_loss); ap(" >> fitted " as *u8); apn(*ll); ap(" skeleton-load-bearing=" as *u8); apn(t3); ap("\n" as *u8) 162 ap(" T4 bit-exact=" as *u8); apn(t4); ap("\n" as *u8) 163 var ok: i64=1 164 if t1!=1 { ok=0 } 165 if t2!=1 { ok=0 } 166 if t3!=1 { ok=0 } 167 if t4!=1 { ok=0 } 168 let logf: i64=sys_openat_append(RLOG, 420) 169 if logf>=0 { rl_ws(logf,"NGRIG authored=organ skeletal-LBS t1=" as *u8); rl_wn(logf,t1); rl_ws(logf," t2_novel=" as *u8); rl_wn(logf,t2); rl_ws(logf," t3_negctl=" as *u8); rl_wn(logf,t3); rl_ws(logf," t4=" as *u8); rl_wn(logf,t4); if ok==1 { rl_ws(logf," verdict=GREEN\n" as *u8) } else { rl_ws(logf," verdict=RED\n" as *u8) } sys_close(logf) } 170 ap(" verdict=" as *u8) 171 if ok==1 { ap("GREEN (a multi-bone skeleton deforms a multi-gaussian character via learned LBS; generalizes to novel poses; skeleton load-bearing = the DAZ/MetaHuman rig primitive, sovereign no-float)\n" as *u8); sys_exit(0); return 0 } 172 ap("RED\n" as *u8) 173 sys_exit(1); return 1 174}