code wiki / (root) / nx_bodypose.nx

nx_bodypose.nx source

↩ module page · 105 lines · 6019 B

1// nx_bodypose.nx -- SKIN THE MANNEQUIN (swap+motion S-ladder, toward S6): pose the CONTINUOUS SDF body from 2// the FK rig, so a MOVE renders on the PHOTOREAL-path raymarcher (nx_sdfrender shading: SSS/pores/spec/AO) 3// instead of the flat mannequin discs. Mapping (a BINDING IS DATA, per nx_bodybind doctrine): 4// * TORSO/HEAD parts = the sdf_body ellipsoids, each anchored to a bone (center = boneWorld + rest offset). 5// * LIMBS = SPHERE-CHAINS along each posed bone segment (3 tapered spheres shoulder->elbow etc.): spheres are 6// ROTATION-INVARIANT, so a bent limb is orientation-correct BY CONSTRUCTION (no ellipsoid-rotation math), 7// and smin fuses the chain into one smooth limb. 36 parts total (PARTS_CAP 48). 8// bodypose_fill(base, sk) rewrites base's O_PARTS/O_NPART/O_KBLEND from the CURRENT skeleton pose; call after 9// sk_update, before rendering. license_tier: ORIGINAL 10import "nx_syscalls.nx" 11import "nx_sdfrender.nx" 12import "nx_skeleton.nx" 13import "nx_figure_render.nx" 14const K_MAGIC_4096: i64 = 4096 15 16func bp_part(base: i64, i: i64, cx: i64, cy: i64, cz: i64, rx: i64, ry: i64, rz: i64) -> i64 { 17 let p: *i64 = (base + O_PARTS) as *i64 18 p[i * 6] = cx; p[i * 6 + 1] = cy; p[i * 6 + 2] = cz 19 p[i * 6 + 3] = rx; p[i * 6 + 4] = ry; p[i * 6 + 5] = rz 20 return 0 21} 22// ellipsoid part anchored to a bone: center = boneWorld + rest offset (v0 rigid attach, no rotation of the 23// offset -- torso/head angles are small). off/rad packed {ox,oy,oz,rx,ry,rz} to stay under the arg cap. 24func bp_anchor(base: i64, i: i64, sk: i64, bone: i64, orr: *i64) -> i64 { 25 let b: *i64 = sk_bone(sk, bone) 26 let cx: i64 = b[15] + orr[0] 27 let cy: i64 = b[16] + orr[1] 28 let cz: i64 = b[17] + orr[2] 29 bp_part(base, i, cx, cy, cz, orr[3], orr[4], orr[5]) 30 return 0 31} 32// tapered 3-sphere chain from bone b0's world pos to bone b1's world pos, radius r0 -> r1. 33// Writes parts idx, idx+1, idx+2; returns idx+3. 34func bp_chain(base: i64, idx: i64, sk: i64, b0: i64, b1: i64, r0: i64, r1: i64) -> i64 { 35 let p0: *i64 = sk_bone(sk, b0) 36 let p1: *i64 = sk_bone(sk, b1) 37 let x0: i64 = p0[15]; let y0: i64 = p0[16]; let z0: i64 = p0[17] 38 let x1: i64 = p1[15]; let y1: i64 = p1[16]; let z1: i64 = p1[17] 39 var s: i64 = 0 40 while s < 3 { 41 let t: i64 = s * K_MAGIC_4096 / 2 42 let cx: i64 = x0 + (x1 - x0) * t / K_MAGIC_4096 43 let cy: i64 = y0 + (y1 - y0) * t / K_MAGIC_4096 44 let cz: i64 = z0 + (z1 - z0) * t / K_MAGIC_4096 45 let r: i64 = r0 + (r1 - r0) * t / K_MAGIC_4096 46 bp_part(base, idx + s, cx, cy, cz, r, r, r) 47 s = s + 1 48 } 49 return idx + 3 50} 51// single sphere at a bone (+offset packed in o4 = {ox,oy,oz,r}). Returns idx+1. 52func bp_ball(base: i64, idx: i64, sk: i64, bone: i64, o4: *i64) -> i64 { 53 let b: *i64 = sk_bone(sk, bone) 54 let cx: i64 = b[15] + o4[0] 55 let cy: i64 = b[16] + o4[1] 56 let cz: i64 = b[17] + o4[2] 57 bp_part(base, idx, cx, cy, cz, o4[3], o4[3], o4[3]) 58 return idx + 1 59} 60 61// fill base with the POSED body (36 parts). Returns the part count. 62func bodypose_fill(base: i64, sk: i64) -> i64 { 63 let orr: *i64 = sys_mmap(6 * 8) as *i64 64 let o4: *i64 = sys_mmap(4 * 8) as *i64 65 // --- torso/head ellipsoids (anchored; offsets = sdf_body rest center - rig rest joint) --- 66 orr[0]=0; orr[1]=0; orr[2]=0; orr[3]=225; orr[4]=285; orr[5]=235 67 bp_anchor(base, 0, sk, RG_HEAD, orr) // head 68 orr[0]=0; orr[1]=0; orr[2]=0; orr[3]=115; orr[4]=160; orr[5]=115 69 bp_anchor(base, 1, sk, RG_NECK, orr) // neck 70 orr[0]=0; orr[1]=0-10; orr[2]=0; orr[3]=330; orr[4]=300; orr[5]=235 71 bp_anchor(base, 2, sk, RG_CHEST, orr) // chest 72 orr[0]=0; orr[1]=0; orr[2]=0; orr[3]=250; orr[4]=250; orr[5]=200 73 bp_anchor(base, 3, sk, RG_SPINE, orr) // waist 74 orr[0]=0; orr[1]=210; orr[2]=0; orr[3]=305; orr[4]=225; orr[5]=215 75 bp_anchor(base, 4, sk, RG_PELVIS, orr) // belly 76 orr[0]=0; orr[1]=0; orr[2]=0; orr[3]=410; orr[4]=280; orr[5]=270 77 bp_anchor(base, 5, sk, RG_PELVIS, orr) // hips 78 orr[0]=0-155; orr[1]=20; orr[2]=215; orr[3]=180; orr[4]=180; orr[5]=175 79 bp_anchor(base, 6, sk, RG_CHEST, orr) // breast L 80 orr[0]=155; orr[1]=20; orr[2]=215; orr[3]=180; orr[4]=180; orr[5]=175 81 bp_anchor(base, 7, sk, RG_CHEST, orr) // breast R 82 // --- limbs as tapered sphere-chains along the POSED segments --- 83 var i: i64 = 8 84 i = bp_chain(base, i, sk, RG_SHL, RG_ELL, 150, 122) // upper arm L 85 i = bp_chain(base, i, sk, RG_ELL, RG_WRL, 115, 92) // forearm L 86 o4[0]=0; o4[1]=0-40; o4[2]=0; o4[3]=100 87 i = bp_ball(base, i, sk, RG_WRL, o4) // hand L 88 i = bp_chain(base, i, sk, RG_SHR, RG_ELR, 150, 122) // upper arm R 89 i = bp_chain(base, i, sk, RG_ELR, RG_WRR, 115, 92) // forearm R 90 o4[0]=0; o4[1]=0-40; o4[2]=0; o4[3]=100 91 i = bp_ball(base, i, sk, RG_WRR, o4) // hand R 92 i = bp_chain(base, i, sk, RG_HIPL, RG_KNL, 210, 172) // thigh L 93 i = bp_chain(base, i, sk, RG_KNL, RG_ANL, 168, 118) // calf L 94 o4[0]=0; o4[1]=0-40; o4[2]=115; o4[3]=125 95 i = bp_ball(base, i, sk, RG_ANL, o4) // foot L 96 i = bp_chain(base, i, sk, RG_HIPR, RG_KNR, 210, 172) // thigh R 97 i = bp_chain(base, i, sk, RG_KNR, RG_ANR, 168, 118) // calf R 98 o4[0]=0; o4[1]=0-40; o4[2]=115; o4[3]=125 99 i = bp_ball(base, i, sk, RG_ANR, o4) // foot R 100 // header 101 let np: *i64 = (base + O_NPART) as *i64; np[0] = i 102 let kb: *i64 = (base + O_KBLEND) as *i64; kb[0] = 130 103 sdf_clear_ops(base, i) 104 return i 105}