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}