nx_faceanat.nx source
↩ module page · 154 lines · 10639 B
1// nx_faceanat.nx -- ★INSIDE-OUT face (operator 2026-07-08: "get the skeleton then muscles then skin, not
2// outside-in"; nx_anatomy_census verdict: build the SKULL+TISSUE-DEPTH rung FIRST). Instead of placing ellipsoids
3// by eyeball, DERIVE the face:
4// (1) POSITIONS from the anthropometric FACIAL CANONS -- rule of THIRDS (hairline->brow->subnasale->chin, equal)
5// + rule of FIFTHS (face width = 5 eye-widths; eyes are fifths 2 & 4; nose = 1 fifth; mouth ~1.5 eye-widths).
6// (2) Z-RELIEF from FORENSIC SOFT-TISSUE-DEPTH tables (Rhine/De Greef-class, adult female, mm): the skin sits
7// proud of the bony skull by a MEASURED amount per landmark -- brow ridge proud, nasal root shallow,
8// cheekbone proud, temple recessed. = anatomically DERIVED form, not sculpted.
9// Fills the SAME nx_sdfrender arena as sdf_face (parts/mats/ops/blend) so it renders + PROJECTS + is measured by
10// the identical pipeline (the shared eye-line@178 / mouth@-390 frame keeps the A-R2 projection constants valid).
11// license_tier: ORIGINAL (data-driven per CLAUDE #2/#11: every number is a canon ratio or a tissue-depth value)
12import "nx_syscalls.nx"
13import "nx_sdfrender.nx"
14
15// model scale: skull half-width ~150mm -> 525u => ~3.5 u/mm. Depth args are passed as mm*10 (45 = 4.5mm),
16// MMU = u/mm * 10 = 35, so relief = depth_mm10 * MMU / 100 = mm * 3.5 u/mm (CORRECT). (v0 used /10 = 10x too
17// proud -> a bulgy caricature that fit the reference WORSE; the gate's rs_err measurement caught it.)
18const MMU: i64 = 35
19// shared landmark frame (identical to sdf_face so projection reuses): eye line y=+178, subnasale ~ y=-150,
20// stomion (mouth) y=-390, gnathion (chin bottom) y=-676, glabella (brow) y=+322, trichion (hairline) y=+760.
21// rule of THIRDS check: brow322 -> subnasale-150 = 472 ; subnasale-150 -> chin-676 = 526 ~ within canon band.
22// rule of FIFTHS: face half-width 525 = 2.5 eye-widths -> eye width 210 (half 105); eye centers at +-258
23// (outer fifth boundary); nose half-width ~64 (1 fifth/2); mouth half-width ~150 (~1.4 eye-widths).
24
25func fa_tissue_z(base_z: i64, depth_mm10: i64) -> i64 { return base_z - depth_mm10 * MMU / 100 } // proud toward -z (camera); mm*10 in
26
27func faceanat_build(base: i64) -> i64 {
28 let p: *i64 = (base + O_PARTS) as *i64
29 let kb: *i64 = (base + O_KBLEND) as *i64; kb[0] = 18
30 let nb: *i64 = (base + O_NPART) as *i64; nb[0] = 27
31 sdf_clear_ops(base, 27)
32 sdf_set_floor(base, 0)
33 sdf_set_mtx_amp(base, 0)
34 var i: i64 = 0
35 // 0 CRANIUM: the bony skull mass (widest at the parietal/temporal). Fifths width -> half 525.
36 p[i]=0; p[i+1]=120; p[i+2]=0; p[i+3]=520; p[i+4]=760; p[i+5]=615; i=i+6
37 // 1 FOREHEAD (frontal bone; tissue ~4.5mm, shallow -> follows bone). Upper third.
38 p[i]=0; p[i+1]=425; p[i+2]=fa_tissue_z(0-360, 45); p[i+3]=420; p[i+4]=285; p[i+5]=315; i=i+6
39 // 2 JAW (mandible body; gonial tissue ~14mm but the body is narrow in a female). Lower third, fifths-narrow.
40 p[i]=0; p[i+1]=0-375; p[i+2]=fa_tissue_z(0-150, 90); p[i+3]=315; p[i+4]=335; p[i+5]=380; i=i+6
41 // 3 CHIN (mental eminence; tissue ~11mm). Gnathion at y-676.
42 p[i]=0; p[i+1]=0-540; p[i+2]=fa_tissue_z(0-300, 110); p[i+3]=175; p[i+4]=170; p[i+5]=245; i=i+6
43 // 4 NASAL BRIDGE (nasion/rhinion; tissue VERY shallow ~2.5-4mm -> the skin hugs bone = the nose ridge).
44 p[i]=0; p[i+1]=105; p[i+2]=fa_tissue_z(0-600, 30); p[i+3]=80; p[i+4]=205; p[i+5]=225; i=i+6
45 // 5 NASAL TIP (pronasale; cartilage, projects most). Subnasale y~-150.
46 p[i]=0; p[i+1]=0-120; p[i+2]=fa_tissue_z(0-660, 60); p[i+3]=86; p[i+4]=100; p[i+5]=150; i=i+6
47 // 6/7 CHEEKBONE (zygomatic; bone-point tissue ~10mm but SURFACE-EFFECTIVE malar relief ~7mm once the soft
48 // tissue smooths the bony point; rule-of-fifths puts the prominence narrower than the face edge). Below+lateral.
49 p[i]=0-315; p[i+1]=15; p[i+2]=fa_tissue_z(0-400, 70); p[i+3]=175; p[i+4]=250; p[i+5]=180; i=i+6
50 p[i]=315; p[i+1]=15; p[i+2]=fa_tissue_z(0-400, 70); p[i+3]=175; p[i+4]=250; p[i+5]=180; i=i+6
51 // 8/9 BROW RIDGE (supraorbital; tissue ~7mm over the ridge, female = LOW ridge). At glabella line.
52 p[i]=0-250; p[i+1]=322; p[i+2]=fa_tissue_z(0-560, 70); p[i+3]=225; p[i+4]=42; p[i+5]=86; i=i+6
53 p[i]=250; p[i+1]=322; p[i+2]=fa_tissue_z(0-560, 70); p[i+3]=225; p[i+4]=42; p[i+5]=86; i=i+6
54 // 10/11 LIPS (labial; upper ~10mm, lower ~11mm). Lower third; mouth half-width ~1.4 eye-width.
55 p[i]=0; p[i+1]=0-330; p[i+2]=fa_tissue_z(0-560, 100); p[i+3]=152; p[i+4]=88; p[i+5]=122; i=i+6
56 p[i]=0; p[i+1]=0-442; p[i+2]=fa_tissue_z(0-545, 110); p[i+3]=132; p[i+4]=114; p[i+5]=122; i=i+6
57 // 12/13 EARS (external; at the skull side, y ~ eye line, z ~ mid). Fifths: ears frame fifths 1 & 5.
58 p[i]=0-545; p[i+1]=20; p[i+2]=40; p[i+3]=75; p[i+4]=235; p[i+5]=130; i=i+6
59 p[i]=545; p[i+1]=20; p[i+2]=40; p[i+3]=75; p[i+4]=235; p[i+5]=130; i=i+6
60 // 14/15 TEMPLE (temporal fossa; tissue THIN + bone RECESSED -> the temples sit BACK, not proud). +z (back).
61 p[i]=0-505; p[i+1]=320; p[i+2]=fa_tissue_z(0-200, 30); p[i+3]=150; p[i+4]=300; p[i+5]=260; i=i+6
62 p[i]=505; p[i+1]=320; p[i+2]=fa_tissue_z(0-200, 30); p[i+3]=150; p[i+4]=300; p[i+5]=260; i=i+6
63 // 16/17 CARVE eye sockets (orbits; the eye SITS IN a bony hole -> concavity). Fifths 2 & 4, eye line.
64 p[i]=0-258; p[i+1]=180; p[i+2]=0-650; p[i+3]=148; p[i+4]=118; p[i+5]=235; i=i+6
65 p[i]=258; p[i+1]=180; p[i+2]=0-650; p[i+3]=148; p[i+4]=118; p[i+5]=235; i=i+6
66 // 18/19 EYEBALLS (globe seated in the orbit; sclera/iris/pupil material).
67 p[i]=0-258; p[i+1]=178; p[i+2]=0-560; p[i+3]=94; p[i+4]=94; p[i+5]=104; i=i+6
68 p[i]=258; p[i+1]=178; p[i+2]=0-560; p[i+3]=94; p[i+4]=94; p[i+5]=104; i=i+6
69 // 20 CARVE mouth slit (oral fissure). 21/22 CARVE nostrils (nasal aperture).
70 p[i]=0; p[i+1]=0-390; p[i+2]=0-600; p[i+3]=142; p[i+4]=34; p[i+5]=110; i=i+6
71 p[i]=0-64; p[i+1]=0-210; p[i+2]=0-745; p[i+3]=46; p[i+4]=52; p[i+5]=80; i=i+6
72 p[i]=64; p[i+1]=0-210; p[i+2]=0-745; p[i+3]=46; p[i+4]=52; p[i+5]=80; i=i+6
73 // 23 HAIR crown cap. 24 nape.
74 p[i]=0; p[i+1]=438; p[i+2]=180; p[i+3]=665; p[i+4]=700; p[i+5]=700; i=i+6
75 p[i]=0; p[i+1]=0-80; p[i+2]=430; p[i+3]=520; p[i+4]=430; p[i+5]=330; i=i+6
76 // 25/26 upper lashes.
77 p[i]=0-258; p[i+1]=276; p[i+2]=0-632; p[i+3]=116; p[i+4]=17; p[i+5]=92; i=i+6
78 p[i]=258; p[i+1]=276; p[i+2]=0-632; p[i+3]=116; p[i+4]=17; p[i+5]=92; i=i+6
79 sdf_set_op(base, 16, 1)
80 sdf_set_op(base, 17, 1)
81 sdf_set_op(base, 20, 1)
82 sdf_set_op(base, 21, 1)
83 sdf_set_op(base, 22, 1)
84 sdf_set_mat(base, 18, 1)
85 sdf_set_mat(base, 19, 1)
86 sdf_set_mat(base, 23, 2)
87 sdf_set_mat(base, 24, 2)
88 sdf_set_mat(base, 8, 3)
89 sdf_set_mat(base, 9, 3)
90 sdf_set_mat(base, 25, 4)
91 sdf_set_mat(base, 26, 4)
92 sdf_set_rot(base, 4, 0 - 300) // nasal bridge slopes forward-down (a real ridge)
93 return 0
94}
95
96// ★B-R6 PARAMETRIC MORPH BASIS (operator: our own base mesh better than DAZ). Because the face is DERIVED from
97// numbers, a "morph" is a DELTA on those numbers -- the FLAME/SMPL 'learned basis' built PARAMETRICALLY from
98// anatomy. Each morph mutates the emitted parts AFTER faceanat_build; pct=100 is neutral; they COMPOSE. These
99// are real anthropometric axes (unlike DAZ's fixed artist-sculpt morphs, these are adjustable + measured).
100// ★UNIFORM SCALE of the whole face (all 6 fields per part + the global blend radius). Used by the hi-res mesh
101// rung: scale the object UP to fill the fixed meshgen grid -> many more surface-nets cells across it -> a
102// denser mesh at the SAME grid resolution (then scale the verts back down). Free resolution, no meshgen change.
103func faceanat_scale(base: i64, pct: i64) -> i64 {
104 let p: *i64 = (base + O_PARTS) as *i64
105 let nb: *i64 = (base + O_NPART) as *i64
106 var i: i64 = 0
107 while i < nb[0] {
108 p[i*6] = p[i*6] * pct / 100; p[i*6+1] = p[i*6+1] * pct / 100; p[i*6+2] = p[i*6+2] * pct / 100
109 p[i*6+3] = p[i*6+3] * pct / 100; p[i*6+4] = p[i*6+4] * pct / 100; p[i*6+5] = p[i*6+5] * pct / 100
110 i = i + 1
111 }
112 let kb: *i64 = (base + O_KBLEND) as *i64
113 if kb[0] > 0 { kb[0] = kb[0] * pct / 100 }
114 return 0
115}
116// scale field f of part idx about pivot 0 (symmetric-safe): v' = v*pct/100
117func fa_scale(base: i64, idx: i64, field: i64, pct: i64) -> i64 {
118 let p: *i64 = (base + O_PARTS) as *i64
119 p[idx*6+field] = p[idx*6+field] * pct / 100
120 return 0
121}
122// FACE WIDTH: scale every part's cx (position) AND rx (feature width) about x=0 -> a genuinely wider/narrower
123// face (wider-set AND wider features), symmetry preserved.
124func faceanat_morph_width(base: i64, pct: i64) -> i64 {
125 let p: *i64 = (base + O_PARTS) as *i64
126 let nb: *i64 = (base + O_NPART) as *i64
127 var i: i64 = 0
128 while i < nb[0] { p[i*6] = p[i*6] * pct / 100; p[i*6+3] = p[i*6+3] * pct / 100; i = i + 1 }
129 return 0
130}
131// FACE LENGTH: scale every part's cy (position) AND ry (feature height) about y=0 -> longer/shorter face.
132func faceanat_morph_length(base: i64, pct: i64) -> i64 {
133 let p: *i64 = (base + O_PARTS) as *i64
134 let nb: *i64 = (base + O_NPART) as *i64
135 var i: i64 = 0
136 while i < nb[0] { p[i*6+1] = p[i*6+1] * pct / 100; p[i*6+4] = p[i*6+4] * pct / 100; i = i + 1 }
137 return 0
138}
139// JAW/CHIN width (parts 2 jaw, 3 chin rx) -> strong vs soft jaw.
140func faceanat_morph_jaw(base: i64, pct: i64) -> i64 { fa_scale(base,2,3,pct); fa_scale(base,3,3,pct); return 0 }
141// EYE size: eyeballs 18/19 + sockets 16/17 + lashes 25/26 (rx,ry,rz) -> bigger/smaller eyes (youthful axis).
142func faceanat_morph_eyes(base: i64, pct: i64) -> i64 {
143 fa_scale(base,16,3,pct); fa_scale(base,16,4,pct); fa_scale(base,17,3,pct); fa_scale(base,17,4,pct)
144 fa_scale(base,18,3,pct); fa_scale(base,18,4,pct); fa_scale(base,18,5,pct)
145 fa_scale(base,19,3,pct); fa_scale(base,19,4,pct); fa_scale(base,19,5,pct)
146 fa_scale(base,25,3,pct); fa_scale(base,26,3,pct)
147 return 0
148}
149// LIP fullness (parts 10 upper, 11 lower ry).
150func faceanat_morph_lips(base: i64, pct: i64) -> i64 { fa_scale(base,10,4,pct); fa_scale(base,11,4,pct); return 0 }
151// NOSE length (bridge 4 ry + tip 5 cy toward the tip).
152func faceanat_morph_nose(base: i64, pct: i64) -> i64 { fa_scale(base,4,4,pct); fa_scale(base,5,4,pct); return 0 }
153// CHEEKBONE prominence (parts 6/7 rz depth = how proud the malar reads).
154func faceanat_morph_cheek(base: i64, pct: i64) -> i64 { fa_scale(base,6,5,pct); fa_scale(base,7,5,pct); return 0 }