code wiki / _hdl_build / nx_anat_rig.nx

nx_anat_rig.nx source

↩ module page · 431 lines · 20507 B

1// nx_anat_rig.nx -- ★SOVEREIGN ARTICULATED RIG + PHYSICS on the REAL 662k-tri BodyParts3D skeleton. 2// The being stops being a rendered corpse and becomes a DYNAMIC BODY: a joint tree (sagittal hinges) over the 3// 15 bone layers, forward kinematics per vertex, and a DETERMINISTIC integer damped-pendulum integrator that 4// drives the joints. Because every BodyParts3D part shares one cadaver frame, the bones are already positioned 5// -- the rig only has to add joints. 100% integer, no float, no GPU: same pose sequence replays bit-identically. 6// nx_anat_rig <mesh> <nframes> <W> <H> <outprefix> 7// license_tier: ORIGINAL expect_exit: 0 8import "nx_syscalls.nx" 9import "nx_png.nx" 10const RG_MAGIC_14000: i64 = 14000 11const RG_MAGIC_18000: i64 = 18000 12const RG_MAGIC_70000: i64 = 70000 13const RG_MAGIC_12000: i64 = 12000 14const RG_MAGIC_8388607: i64 = 8388607 15const RG_MAGIC_8388608: i64 = 8388608 16const RG_MAGIC_65536: i64 = 65536 17const RG_MAGIC_2000000000: i64 = 2000000000 18const RG_MAGIC_40500: i64 = 40500 19const RG_MAGIC_16384: i64 = 16384 20const RG_MAGIC_1024: i64 = 1024 21const RG_MAGIC_1280: i64 = 1280 22const RG_MAGIC_5423: i64 = 5423 23const RG_MAGIC_9487: i64 = 9487 24const RG_MAGIC_12206: i64 = 12206 25const RG_MAGIC_10160: i64 = 10160 26const RG_MAGIC_4064: i64 = 4064 27const RG_MAGIC_12190: i64 = 12190 28const RG_NL: i64 = 14 29// physics tuning (declared, not hidden): restoring gain, damping, substeps per frame 30const RG_GRAV: i64 = 460 31const RG_DAMP: i64 = 105 32const RG_STEPS: i64 = 7 33// GX-20 root rigid-body + ground contact (Q8 = model-units*256) 34const RG_Q8: i64 = 256 35const RG_GY: i64 = 150 // gravity, Q8 units per substep^2 36const RG_REST: i64 = 280 // restitution per-1024 (bone on floor: mostly inelastic) 37const RG_DROP0: i64 = 260 // release height, model units 38const RG_STOPV: i64 = 900 // |v| below this on contact -> come to rest (no infinite micro-bounce) 39 40func rg_hw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 41func rg_pn(v: i64) -> i64 { 42 let b: *u8=sys_mmap(32); var x: i64=v; var ng: i64=0 43 if x<0 { ng=1; x=0-x } 44 var i: i64=31 45 if x==0 { b[i]=48 as u8; i=i-1 } 46 while x>0 { b[i]=(48+x%10) as u8; x=x/10; i=i-1 } 47 if ng==1 { b[i]=45 as u8; i=i-1 } 48 sys_write(1,(b as i64+i+1) as *u8,31-i); return 0 49} 50func rg_satoi(s: *u8) -> i64 { 51 var i: i64=0; var n: i64=0 52 while s[i]!=(0 as u8) { let c: i64=s[i] as i64; if c>=48 { if c<=57 { n=n*10+(c-48) } } i=i+1 } 53 return n 54} 55func rg_rdbits(b: *u8, o: i64) -> i64 { 56 return (b[o] as i64) | ((b[o+1] as i64)<<8) | ((b[o+2] as i64)<<16) | ((b[o+3] as i64)<<24) 57} 58func rg_f32mul(b: *u8, o: i64, mul: i64) -> i64 { 59 let bits: i64 = rg_rdbits(b,o) 60 let sign: i64 = (bits>>31)&1 61 let exp: i64 = (bits>>23)&255 62 let mant: i64 = bits & RG_MAGIC_8388607 63 if exp==0 { return 0 } 64 let m: i64 = (mant | RG_MAGIC_8388608)*mul 65 var e: i64 = exp-127-23 66 var v: i64 = 0 67 if e>=0 { v = m<<e } else { let sh: i64 = 0-e; v = (m + (1<<(sh-1)))>>sh } 68 if sign==1 { v = 0-v } 69 return v 70} 71func rg_isqrt(v: i64) -> i64 { if v<=0 {return 0} var x: i64=v; var y: i64=(x+1)/2; while y<x { x=y; y=(x+v/x)/2 } return x } 72func rg_min(a: i64, b: i64) -> i64 { if a<b {return a} return b } 73func rg_max(a: i64, b: i64) -> i64 { if a>b {return a} return b } 74// Bhaskara I degree-form sine, EXACT at 0/30/90/150/180: sin(d) = 4P/(40500-P), P=d(180-d). Q14 out. 75func rg_sin_fill(tab: *i64) -> i64 { 76 var d: i64 = 0 77 while d < 180 { 78 let P: i64 = d*(180-d) 79 tab[d] = RG_MAGIC_16384*4*P/(RG_MAGIC_40500-P) 80 tab[d+180] = 0 - tab[d] 81 d = d + 1 82 } 83 return 0 84} 85func rg_wrap(d: i64) -> i64 { var x: i64 = d % 360; if x < 0 { x = x + 360 } return x } 86// FK a point up the joint chain and return only its WORLD Y -- used by the contact probes. 87func rg_fk_y(px: i64, py: i64, pz: i64, L: i64, par: *i64, thD: *i64, pvY: *i64, pvZ: *i64, sinT: *i64) -> i64 { 88 var y: i64 = py; var z: i64 = pz 89 var cur: i64 = L 90 var guard: i64 = 0 91 while guard < 8 { 92 if cur < 0 { guard = 8 } else { 93 let d: i64 = thD[cur] 94 if d != 0 { 95 let sc: i64 = sinT[d] 96 let cc: i64 = sinT[rg_wrap(d+90)] 97 let dy: i64 = y - pvY[cur]; let dz: i64 = z - pvZ[cur] 98 y = (dy*cc - dz*sc)/RG_MAGIC_16384 + pvY[cur] 99 z = (dy*sc + dz*cc)/RG_MAGIC_16384 + pvZ[cur] 100 } 101 cur = par[cur] 102 guard = guard + 1 103 } 104 } 105 return y 106} 107 108func main(argc: i64, argv: *i64) -> i64 { 109 let meshp: *u8 = argv[1] as *u8 110 let nframes: i64 = rg_satoi(argv[2] as *u8) 111 let W: i64 = rg_satoi(argv[3] as *u8) 112 let H: i64 = rg_satoi(argv[4] as *u8) 113 let pref: *u8 = argv[5] as *u8 114 // mode: argv[6][0]=='d' -> DROP (root rigid-body + ground contact); 'n' -> NO-CONTACT neg-control 115 var mode: i64 = 0 116 if argc > 6 { 117 let mp: *u8 = argv[6] as *u8 118 if mp[0] == (100 as u8) { mode = 1 } 119 if mp[0] == (110 as u8) { mode = 2 } 120 } 121 122 let sinT: *i64 = sys_mmap(400*8) as *i64 123 rg_sin_fill(sinT) 124 125 let lenp: *i64 = sys_mmap(16) as *i64 126 let mb: *u8 = sys_read_file(meshp, lenp) 127 if (mb as i64)==0 { rg_hw("{\x22error\x22:\x22mesh\x22}\n" as *u8); return 2 } 128 let nlayers: i64 = rg_rdbits(mb,8) 129 let ntris: i64 = rg_rdbits(mb,12) 130 let triBase: i64 = 16 + nlayers*24 131 let lidBase: i64 = triBase + ntris*84 132 133 // ---- global AABB (centering) + PER-LAYER AABB (joint pivots) ---- 134 var mnx: i64=RG_MAGIC_2000000000; var mny: i64=RG_MAGIC_2000000000; var mnz: i64=RG_MAGIC_2000000000 135 var mxx: i64=0-RG_MAGIC_2000000000; var mxy: i64=0-RG_MAGIC_2000000000; var mxz: i64=0-RG_MAGIC_2000000000 136 let lminY: *i64 = sys_mmap(RG_NL*8) as *i64 137 let lmaxY: *i64 = sys_mmap(RG_NL*8) as *i64 138 let lsumZ: *i64 = sys_mmap(RG_NL*8) as *i64 139 let lcnt: *i64 = sys_mmap(RG_NL*8) as *i64 140 // GX-20 contact probes: the LOWEST vertex of each bone (its would-be ground contact point) 141 let prX: *i64 = sys_mmap(RG_NL*8) as *i64 142 let prY: *i64 = sys_mmap(RG_NL*8) as *i64 143 let prZ: *i64 = sys_mmap(RG_NL*8) as *i64 144 var i0: i64 = 0 145 while i0 < RG_NL { lminY[i0]=RG_MAGIC_2000000000; lmaxY[i0]=0-RG_MAGIC_2000000000; lsumZ[i0]=0; lcnt[i0]=0 146 prX[i0]=0; prY[i0]=0; prZ[i0]=0; i0=i0+1 } 147 var t: i64 = 0 148 while t < ntris { 149 let L: i64 = rg_rdbits(mb, lidBase+t*4) & 255 150 var v: i64 = 0 151 while v < 3 { 152 let o: i64 = triBase + t*84 + v*12 153 let x: i64 = rg_f32mul(mb,o,1); let y: i64 = rg_f32mul(mb,o+4,1); let z: i64 = rg_f32mul(mb,o+8,1) 154 if x<mnx {mnx=x} if x>mxx {mxx=x} 155 if y<mny {mny=y} if y>mxy {mxy=y} 156 if z<mnz {mnz=z} if z>mxz {mxz=z} 157 if L < RG_NL { 158 if y<lminY[L] { lminY[L]=y; prX[L]=x; prY[L]=y; prZ[L]=z } 159 if y>lmaxY[L] {lmaxY[L]=y} 160 lsumZ[L]=lsumZ[L]+z; lcnt[L]=lcnt[L]+1 161 } 162 v=v+1 163 } 164 t=t+1 165 } 166 let cx0: i64=(mnx+mxx)/2; let cy0: i64=(mny+mxy)/2; let cz0: i64=(mnz+mxz)/2 167 168 // ---- RIG: joint tree over the 15 bone layers (sagittal hinges about X) ---- 169 // 0 skull 1 vertebrae 2 ribs 3 clavicle 4 scapula 5 humerus 6 pelvis(ROOT) 170 // 7 femur 8 tibia 9 fibula 10 patella 11 hand_L 12 hand_R 13 feet 171 // (sternum + costal cartilage dropped: PROVEN duplicates already inside the rib-cage aggregate) 172 let par: *i64 = sys_mmap(RG_NL*8) as *i64 173 par[0]=1; par[1]=6; par[2]=1; par[3]=1; par[4]=1; par[5]=4; par[6]=0-1 174 par[7]=6; par[8]=7; par[9]=7; par[10]=7; par[11]=5; par[12]=5; par[13]=8 175 let pvY: *i64 = sys_mmap(RG_NL*8) as *i64 176 let pvZ: *i64 = sys_mmap(RG_NL*8) as *i64 177 var L2: i64 = 0 178 while L2 < RG_NL { 179 var cz: i64 = 0 180 if lcnt[L2] > 0 { cz = lsumZ[L2]/lcnt[L2] - cz0 } 181 pvZ[L2] = cz 182 pvY[L2] = (lminY[L2]+lmaxY[L2])/2 - cy0 183 L2 = L2 + 1 184 } 185 // anatomically-placed hinge pivots: attach point to the PARENT bone 186 pvY[0] = lminY[0]-cy0 // skull -> neck (base of skull) 187 pvY[1] = lminY[1]-cy0 // spine -> waist (base of vertebral column) 188 pvY[5] = lmaxY[5]-cy0 // humerus-> shoulder (head of humerus) 189 pvY[7] = lmaxY[7]-cy0 // femur -> hip (head of femur) 190 pvY[8] = lmaxY[8]-cy0 // tibia -> knee (tibial plateau) 191 192 // ---- physics state: damped pendulums restoring to the neutral standing pose ---- 193 let th: *i64 = sys_mmap(RG_NL*8) as *i64 // milli-degrees 194 let om: *i64 = sys_mmap(RG_NL*8) as *i64 // md per substep 195 var q: i64 = 0 196 while q < RG_NL { th[q]=0; om[q]=0; q=q+1 } 197 th[1]=RG_MAGIC_14000; th[0]=RG_MAGIC_18000; th[5]=RG_MAGIC_70000; th[7]=RG_MAGIC_12000; th[8]=0-RG_MAGIC_12000 // released-from pose 198 let drv: *i64 = sys_mmap(8*8) as *i64 199 drv[0]=1; drv[1]=0; drv[2]=5; drv[3]=7; drv[4]=8 200 let ndrv: i64 = 5 201 202 // ---- render buffers ---- 203 let npx: i64 = W*H 204 let fb: *i64 = sys_mmap(npx*8) as *i64 205 let zb: *i64 = sys_mmap(npx*8) as *i64 206 let thD: *i64 = sys_mmap(RG_NL*8) as *i64 207 let l1x: i64=0-RG_MAGIC_5423; let l1y: i64=RG_MAGIC_9487; let l1z: i64=RG_MAGIC_12206 208 let l2x: i64=RG_MAGIC_10160; let l2y: i64=0-RG_MAGIC_4064; let l2z: i64=RG_MAGIC_12190 209 let cxh: i64=W/2; let cyh: i64=H/2 210 // framing from the REST silhouette (fixed across frames so motion is visible, not re-framed away) 211 var halfH: i64=(mxy-mny)/2; let halfW: i64=(mxx-mnx)/2 212 if mode > 0 { halfH = halfH + RG_DROP0*3/4 } // headroom so the released body stays in frame 213 let FOCAL: i64 = H 214 var dist: i64 = 2*halfH 215 let dw: i64 = 2*halfW*H/W 216 if dw > dist { dist = dw } 217 dist = dist*128/100 + (mxz-mnz)/2 218 if dist < 1 { dist = 1 } 219 let floorY: i64 = mny - cy0 220 221 rg_hw("{\x22organ\x22:\x22nx_anat_rig\x22,\x22ntris\x22:" as *u8); rg_pn(ntris) 222 rg_hw(",\x22layers\x22:" as *u8); rg_pn(nlayers) 223 rg_hw(",\x22joints_driven\x22:" as *u8); rg_pn(ndrv) 224 rg_hw(",\x22grav\x22:" as *u8); rg_pn(RG_GRAV); rg_hw(",\x22damp\x22:" as *u8); rg_pn(RG_DAMP) 225 rg_hw(",\x22substeps_per_frame\x22:" as *u8); rg_pn(RG_STEPS); rg_hw(",\x22frames\x22:[" as *u8) 226 227 // ---- GX-20 root rigid-body state (drop modes) ---- 228 var rootY: i64 = 0 229 var rootV: i64 = 0 230 var contacts: i64 = 0 231 var worstPen: i64 = 0 232 if mode > 0 { rootY = RG_DROP0*RG_Q8 } 233 if mode > 0 { var z9: i64 = 0; while z9 < RG_NL { th[z9]=0; om[z9]=0; z9=z9+1 } } 234 235 var f: i64 = 0 236 while f < nframes { 237 // ---- integrate physics for this frame (frame 0 = the released state) ---- 238 if f > 0 { 239 var s: i64 = 0 240 while s < RG_STEPS { 241 var k: i64 = 0 242 while k < ndrv { 243 let j: i64 = drv[k] 244 let dg: i64 = rg_wrap(th[j]/1000) 245 let sv: i64 = sinT[dg] 246 let acc: i64 = 0 - (RG_GRAV*sv)/RG_MAGIC_16384 - (RG_DAMP*om[j])/1000 247 om[j] = om[j] + acc 248 th[j] = th[j] + om[j] 249 k = k + 1 250 } 251 // ---- root: gravity + GROUND CONTACT ---- 252 if mode > 0 { 253 rootV = rootV - RG_GY 254 rootY = rootY + rootV 255 var L4: i64 = 0 256 while L4 < RG_NL { thD[L4] = rg_wrap(th[L4]/1000); L4 = L4 + 1 } 257 // deepest probe below the floor 258 var lowest: i64 = RG_MAGIC_2000000000 259 var pr: i64 = 0 260 while pr < RG_NL { 261 if lcnt[pr] > 0 { 262 let wy: i64 = rg_fk_y(prX[pr]-cx0, prY[pr]-cy0, prZ[pr]-cz0, pr, par, thD, pvY, pvZ, sinT) 263 let ay2: i64 = wy*RG_Q8 + rootY 264 if ay2 < lowest { lowest = ay2 } 265 } 266 pr = pr + 1 267 } 268 let pen: i64 = (mny-cy0)*RG_Q8 - lowest // >0 means penetrating the floor 269 if pen > 0 { 270 if mode == 1 { 271 if pen > worstPen { worstPen = pen } 272 rootY = rootY + pen // positional resolve: never sink 273 contacts = contacts + 1 274 if rootV < 0 { 275 rootV = (0-rootV)*RG_REST/RG_MAGIC_1024 // bounce 276 if rootV < RG_STOPV { rootV = 0 } // rest instead of micro-bouncing 277 } 278 } else { if pen > worstPen { worstPen = pen } } // mode 2 = NO-CONTACT neg control 279 } 280 } 281 s = s + 1 282 } 283 } 284 var L3: i64 = 0 285 while L3 < RG_NL { thD[L3] = rg_wrap(th[L3]/1000); L3 = L3 + 1 } 286 287 // ---- clear: sky + ground ---- 288 var p: i64 = 0 289 while p < npx { 290 let py: i64 = p/W 291 var br: i64 = 34 + (56*(H-py))/H 292 var bg: i64 = 41 + (69*(H-py))/H 293 var bb: i64 = 56 + (94*(H-py))/H 294 let rdy: i64 = cyh - py 295 if rdy < 0 { 296 let t16: i64 = floorY*RG_MAGIC_65536/rdy 297 let dxtra: i64 = t16/RG_MAGIC_65536 298 let ff: i64 = 900*RG_MAGIC_1024/(900 + dxtra) 299 br = (112*ff + br*(RG_MAGIC_1024-ff))/RG_MAGIC_1024 300 bg = (105*ff + bg*(RG_MAGIC_1024-ff))/RG_MAGIC_1024 301 bb = ( 96*ff + bb*(RG_MAGIC_1024-ff))/RG_MAGIC_1024 302 } 303 fb[p] = br + bg*256 + bb*RG_MAGIC_65536 304 zb[p] = RG_MAGIC_2000000000 305 p = p + 1 306 } 307 308 // ---- raster with per-vertex FORWARD KINEMATICS up the joint chain ---- 309 let vx: *i64 = sys_mmap(64) as *i64 310 let vy: *i64 = sys_mmap(64) as *i64 311 let vz: *i64 = sys_mmap(64) as *i64 312 let nxa: *i64 = sys_mmap(64) as *i64 313 let nya: *i64 = sys_mmap(64) as *i64 314 let nza: *i64 = sys_mmap(64) as *i64 315 t = 0 316 while t < ntris { 317 let L: i64 = rg_rdbits(mb, lidBase+t*4) & 255 318 let ob: i64 = triBase + t*84 319 var v: i64 = 0 320 while v < 3 { 321 var px1: i64 = rg_f32mul(mb,ob+v*12,1)-cx0 322 var py1: i64 = rg_f32mul(mb,ob+v*12+4,1)-cy0 323 var pz1: i64 = rg_f32mul(mb,ob+v*12+8,1)-cz0 324 var qx: i64 = rg_f32mul(mb,ob+36+v*12,RG_MAGIC_16384) 325 var qy: i64 = rg_f32mul(mb,ob+40+v*12,RG_MAGIC_16384) 326 var qz: i64 = rg_f32mul(mb,ob+44+v*12,RG_MAGIC_16384) 327 // walk self -> root, applying each hinge about its pivot (sagittal, about X) 328 var cur: i64 = L 329 var guard: i64 = 0 330 while guard < 8 { 331 if cur < 0 { guard = 8 } else { 332 let d: i64 = thD[cur] 333 if d != 0 { 334 let sc: i64 = sinT[d] 335 let cc: i64 = sinT[rg_wrap(d+90)] 336 let dy: i64 = py1 - pvY[cur]; let dz: i64 = pz1 - pvZ[cur] 337 py1 = (dy*cc - dz*sc)/RG_MAGIC_16384 + pvY[cur] 338 pz1 = (dy*sc + dz*cc)/RG_MAGIC_16384 + pvZ[cur] 339 let ny2: i64 = (qy*cc - qz*sc)/RG_MAGIC_16384 340 let nz2: i64 = (qy*sc + qz*cc)/RG_MAGIC_16384 341 qy = ny2; qz = nz2 342 } 343 cur = par[cur] 344 guard = guard + 1 345 } 346 } 347 vx[v]=px1; vy[v]=py1+rootY/RG_Q8; vz[v]=pz1; nxa[v]=qx; nya[v]=qy; nza[v]=qz 348 v = v + 1 349 } 350 let d0: i64 = dist - vz[0]; let d1: i64 = dist - vz[1]; let d2: i64 = dist - vz[2] 351 if d0>0 { if d1>0 { if d2>0 { 352 let sx0: i64=cxh+(vx[0]*FOCAL)/d0; let sy0: i64=cyh-(vy[0]*FOCAL)/d0 353 let sx1: i64=cxh+(vx[1]*FOCAL)/d1; let sy1: i64=cyh-(vy[1]*FOCAL)/d1 354 let sx2: i64=cxh+(vx[2]*FOCAL)/d2; let sy2: i64=cyh-(vy[2]*FOCAL)/d2 355 var area: i64 = (sx1-sx0)*(sy2-sy0)-(sx2-sx0)*(sy1-sy0) 356 if area != 0 { 357 var sgn: i64 = 1 358 if area < 0 { sgn = 0-1 } 359 let aabs: i64 = area*sgn 360 let cr: i64=rg_f32mul(mb,ob+72,255); let cg: i64=rg_f32mul(mb,ob+76,255); let cbb: i64=rg_f32mul(mb,ob+80,255) 361 var bxmn: i64=rg_max(0, rg_min(sx0, rg_min(sx1,sx2))) 362 var bxmx: i64=rg_min(W-1, rg_max(sx0, rg_max(sx1,sx2))) 363 var bymn: i64=rg_max(0, rg_min(sy0, rg_min(sy1,sy2))) 364 var bymx: i64=rg_min(H-1, rg_max(sy0, rg_max(sy1,sy2))) 365 var yy: i64 = bymn 366 while yy <= bymx { 367 var xx: i64 = bxmn 368 while xx <= bxmx { 369 let e0: i64=((sx2-sx1)*(yy-sy1)-(sy2-sy1)*(xx-sx1))*sgn 370 let e1: i64=((sx0-sx2)*(yy-sy2)-(sy0-sy2)*(xx-sx2))*sgn 371 let e2: i64=((sx1-sx0)*(yy-sy0)-(sy1-sy0)*(xx-sx0))*sgn 372 if e0>=0 { if e1>=0 { if e2>=0 { 373 let dep: i64=(e0*d0+e1*d1+e2*d2)/aabs 374 let idx: i64=yy*W+xx 375 if dep < zb[idx] { 376 var nx1: i64=(e0*nxa[0]+e1*nxa[1]+e2*nxa[2])/aabs 377 var ny1: i64=(e0*nya[0]+e1*nya[1]+e2*nya[2])/aabs 378 var nz1: i64=(e0*nza[0]+e1*nza[1]+e2*nza[2])/aabs 379 var nl: i64=rg_isqrt(nx1*nx1+ny1*ny1+nz1*nz1) 380 if nl<1 {nl=1} 381 nx1=nx1*RG_MAGIC_16384/nl; ny1=ny1*RG_MAGIC_16384/nl; nz1=nz1*RG_MAGIC_16384/nl 382 if nz1<0 { nx1=0-nx1; ny1=0-ny1; nz1=0-nz1 } 383 let da: i64=rg_max(0,(nx1*l1x+ny1*l1y+nz1*l1z)/RG_MAGIC_16384) 384 let db: i64=rg_max(0,(nx1*l2x+ny1*l2y+nz1*l2z)/RG_MAGIC_16384) 385 var lit: i64=225 + 676*da/RG_MAGIC_16384 + 256*db/RG_MAGIC_16384 386 if lit>RG_MAGIC_1280 { lit=RG_MAGIC_1280 } 387 var rr: i64=cr*lit/RG_MAGIC_1024 388 var gg: i64=cg*lit/RG_MAGIC_1024 389 var bb2: i64=cbb*lit/RG_MAGIC_1024 390 if rr>255 {rr=255} if gg>255 {gg=255} if bb2>255 {bb2=255} 391 zb[idx]=dep; fb[idx]=rr+gg*256+bb2*RG_MAGIC_65536 392 } 393 }}} 394 xx = xx + 1 395 } 396 yy = yy + 1 397 } 398 } 399 }}} 400 t = t + 1 401 } 402 403 // frame checksum (order-sensitive) = the determinism witness 404 var ck: i64 = 0 405 var c2: i64 = 0 406 while c2 < npx { ck = (ck*31 + fb[c2]) & RG_MAGIC_2000000000; c2 = c2 + 3 } 407 408 let path: *u8 = sys_mmap(256) 409 var pi: i64 = 0 410 while pref[pi]!=(0 as u8) { path[pi]=pref[pi]; pi=pi+1 } 411 path[pi]=(48+f) as u8; pi=pi+1 412 path[pi]=46 as u8; path[pi+1]=112 as u8; path[pi+2]=110 as u8; path[pi+3]=103 as u8; path[pi+4]=0 as u8 413 write_png(fb, W, H, path) 414 415 if f>0 { rg_hw("," as *u8) } 416 rg_hw("{\x22f\x22:" as *u8); rg_pn(f) 417 rg_hw(",\x22shoulder\x22:" as *u8); rg_pn(th[5]/1000) 418 rg_hw(",\x22spine\x22:" as *u8); rg_pn(th[1]/1000) 419 rg_hw(",\x22neck\x22:" as *u8); rg_pn(th[0]/1000) 420 rg_hw(",\x22hip\x22:" as *u8); rg_pn(th[7]/1000) 421 rg_hw(",\x22knee\x22:" as *u8); rg_pn(th[8]/1000) 422 rg_hw(",\x22rootY\x22:" as *u8); rg_pn(rootY/RG_Q8) 423 rg_hw(",\x22rootV\x22:" as *u8); rg_pn(rootV/RG_Q8) 424 rg_hw(",\x22contacts\x22:" as *u8); rg_pn(contacts) 425 rg_hw(",\x22worst_penetration\x22:" as *u8); rg_pn(worstPen/RG_Q8) 426 rg_hw(",\x22ck\x22:" as *u8); rg_pn(ck); rg_hw("}" as *u8) 427 f = f + 1 428 } 429 rg_hw("]}\n" as *u8) 430 return 0 431}