code wiki / (root) / nx_avatar_splat.nx

nx_avatar_splat.nx source

↩ module page · 643 lines · 35824 B

1// nx_avatar_splat.nx -- ★THE LEAP (charsim R25; operator 2026-08-16: "dont build iterative junk, you 2// can get us there from all the published research without gumby layers and then we can iterate on 3// the last miles"). GENOME -> ANTHROPOMETRIC BODY MESH -> GAUSSIAN SPLAT COAT -> PORTRAIT PNG. 4// 5// A COMPOSITION OF PROVEN PARTS, ZERO NEW ALGORITHMS -- the published GaussianAvatars/HumanSplat 6// architecture (mesh -> per-element gaussians -> splat) that nx_gsplat_face_gate already proves at 7// face scale on this estate's own stack, generalized to the full body: 8// nx_body_gen (forked; anthropometric .nxmesh from stature + the FEMALE canon knowledge/canon_f.dat; 9// every non-genome knob passed = body_gen's OWN defaults, transcribed from its main: 10// RS 28, SUB 4, RLF 1000, FAT 250 -- so only stature and canon vary from stock) 11// nx_skin_ita (published ITA -> L*a*b* -> sRGB skin albedo; genome skin bits, face/torso region dl) 12// nx_gsplat (sovereign integer 3DGS: one ANISOTROPIC surface-flattened gaussian per triangle, 13// normal from the winding, tangent radius DERIVED from the triangle's own mean edge) 14// nx_png (write_png, the face gate's own call) 15// Genome bit layout TRANSCRIBED from the documented MC_GENE map: skin tone bits 9-10, height bits 5-6. 16// Female stature band cited (ANSUR/NHANES women P5..P95 ~ 1505..1730mm): bits 0..3 -> 1520 + 70*b mm. 17// 18// ⚠DUPLICATE-DECODER DEBT, NAMED: av_rdbits/av_f32mul are the FOURTH inline copy of the NXMSH2 f32 19// decode (anat_sov, bodybench, curvebench carry the others). Extracting nx_nxmesh_lib and migrating 20// all four is the named follow-on; a fifth copy is forbidden. 21// LAST-MILE (after the leap, by order): photofit color refinement (gs_color_grad_step), hair as splat 22// volume, head-band eye/mouth features, wasm delivery budget, yaw/pose drive via nx_gsplat4d_lib. 23// nx_avatar_splat <out.png> [gene] 24import "nx_syscalls.nx" 25import "nx_itoa_lib.nx" 26import "nx_tool_run.nx" 27import "nx_itrig.nx" 28import "nx_gsplat.nx" 29import "nx_skin_ita.nx" 30import "nx_png.nx" 31 32const AV_BODYGEN: *u8 = "/volume1/homes/elderwesto/nishihost/nx_body_gen.elf" 33const AV_CANON: *u8 = "/volume1/homes/elderwesto/nishihost/knowledge/canon_f.dat" // ABSOLUTE: this 34 // organ runs under nx_sov_build_run (CWD anchored to buildroot/) 35 // AND as a promoted tool (CWD nishihost) -- a relative path is 36 // correct in exactly one of those and silently wrong in the other 37const AV_MESH: *u8 = "/tmp/avatar_splat.nxmesh" 38const AV_OUTCAP: i64 = 65536 39const AV_TIMEOUT_MS: i64 = 120000 40const AV_POSQ0: i64 = 4096 // fixed pre-pass precision (anat_sov's own scale-invariance pattern) 41const AV_SPAN: i64 = 1200 // normalized max-axis span in gsplat model units 42const AV_TARGET: i64 = 200000 // DECODE precision target (anat_sov's own AS_TARGET, transcribed): 43 // the f32 multiplier must stay an integer >= 1 for millimetre 44 // meshes, so decode at this span and rescale to AV_SPAN at 45 // coat-build time -- targeting 1200 directly truncates posq to 0 46const AV_CAMZ: i64 = 2 // R = 2048: half-height on screen = 586*600/2048 = 171 of 192 px 47 // -- 89 percent frame fill, DERIVED from GFOCAL/GHH, not tasted 48const AV_F32_MANT_SCALE: i64 = 8388608 49const AV_F32_MANT_MASK: i64 = 8388607 50const AV_BIG: i64 = 2000000000 51const AV_OP: i64 = 235 // splat opacity: the face gate's proven value, transcribed 52const AV_RTAN_NUM: i64 = 1 // tangent radius = mean edge / 2: 3-sigma still covers 1.5 edges 53const AV_RTAN_DEN: i64 = 2 // (closed surface holds) -- 3/4 melted every feature, measured by 54 // the operator's own verdict on v1 ("looks like a monster") 55const AV_SKIN_SH: i64 = 9 // MC_GENE skin bits (transcribed) 56const AV_SKIN_MASK: i64 = 3 57const AV_HGT_SH: i64 = 5 // MC_GENE height bits (transcribed) 58const AV_HGT_MASK: i64 = 3 59const AV_STAT_BASE_MM: i64 = 1520 // ANSUR/NHANES female stature band, P5..P95 in 4 stops 60const AV_STAT_STEP_MM: i64 = 70 61const AV_LIGHT_X: i64 = 0-121 // the face gate's proven key light direction, transcribed 62const AV_LIGHT_Y: i64 = 191 63const AV_LIGHT_Z: i64 = 0-121 64const AV_HEAD_BAND: i64 = 2 // head = top 2/15 of stature -- the 7.5-head canon unit 65const AV_HEAD_DEN: i64 = 15 66 67// ---- v2 (2026-08-19, GR2 leg 2): SHADING + HAIR ARE POLICY AND LIVE IN A CONF, NOT IN CODE ---- 68// knowledge/avatar_splat.conf is the SSOT; the named defaults below reproduce the v1 render exactly 69// when the conf is absent (announced), so behaviour never silently changes with a missing file. 70const AV_CONF: *u8 = "knowledge/avatar_splat.conf" 71const AV_PERMIL: i64 = 1000 72const AV_NFX: i64 = 256 // the fx256 unit-normal scale gs_set_aniso declares 73const AV_DEF_SH_AMB: i64 = 130 // v1 shipped shade base 74const AV_DEF_SH_GAIN: i64 = 90 // v1 shipped lambert gain 75const AV_DEF_SH_MIN: i64 = 70 // v1 shipped shade floor 76const AV_DEF_SH_MAX: i64 = 255 77const AV_DEF_HAIR_ON: i64 = 0 // hair OFF by default = v1 behaviour; the conf turns it on 78const AV_DEF_HAIR_TOP_PERMIL: i64 = 550 79const AV_DEF_HAIR_LEN_PERMIL: i64 = 1400 80const AV_DEF_HAIR_RAD_PERMIL: i64 = 60 81const AV_DEF_HAIR_STEP_PERMIL: i64 = 1200 // step between strand discs, permil of disc radius 82const AV_DEF_HAIR_SEED_EVERY: i64 = 3 83const AV_DEF_HAIR_DROOP: i64 = 820 84const AV_DEF_HAIR_R: i64 = 144 // measured mean of the banked WebGL reference's hair band 85const AV_DEF_HAIR_G: i64 = 118 // (cjc_ref_rig_03, 10330 px, 2026-08-19) -- a measurement, not a taste 86const AV_DEF_HAIR_B: i64 = 89 87const AV_DEF_HAIR_JITTER: i64 = 28 88const AV_DEF_HAIR_FACE_Z: i64 = 1 // +z is the face (measured, y90 profile 2026-08-19) 89const AV_DEF_HAIR_CROWN_PERMIL: i64 = 300 90const AV_DEF_HAIR_DROOP_BASE: i64 = 0 // v1-equivalent: no initial bend 91const AV_DEF_HAIR_CROWN_BACK: i64 = 0 // v1-equivalent: no backward sweep on face-side crown strands 92const AV_DEF_SKIN_JITTER: i64 = 0 // v1-equivalent: no per-splat skin variation 93const AV_DEF_FACE_ON: i64 = 0 // v1-equivalent: no face features 94const AV_DEF_EYE_LINE_PERMIL: i64 = 450 // eye line below head top, permil of head height 95const AV_DEF_EYE_SEP_PERMIL: i64 = 420 // eye separation, permil of head width at the eye line 96const AV_DEF_EYE_RAD_PERMIL: i64 = 70 // sclera radius, permil of head height 97const AV_DEF_MOUTH_LINE_PERMIL: i64 = 760 98const AV_DEF_MOUTH_W_PERMIL: i64 = 280 // mouth half-width, permil of head width 99const AV_FACE_GAUSS: i64 = 16 // fixed feature budget added to the buffer bound 100const AV_HAIR_HASH_A: i64 = 1103515245 // the estate's LCG constants (charjudge gate), per-strand jitter 101const AV_HAIR_HASH_C: i64 = 12345 102const AV_HAIR_HASH_M: i64 = 2147483647 103 104// anchored key=value conf reader (same contract as the census organ's cjp_conf_int; the shared-lib 105// extraction of this fourth copy is the named nx_conf_lib debt beside the NXMSH2 one in the header) 106func av_conf_int(cf: *u8, n: i64, key: *u8, def: i64) -> i64 { 107 var kn: i64 = 0 108 while key[kn] != (0 as u8) { kn = kn + 1 } 109 var i: i64 = 0 110 while i < n { 111 var e: i64 = i 112 var go: i64 = 1 113 while go == 1 { if e >= n { go = 0 } else { if (cf[e] as i64) == 10 { go = 0 } else { e = e + 1 } } } 114 if (cf[i] as i64) != 35 { 115 if e - i > kn { 116 var k: i64 = 0 117 var hit: i64 = 1 118 while k < kn { if cf[i+k] != key[k] { hit = 0; k = kn } if hit == 1 { k = k + 1 } } 119 if hit == 1 { if (cf[i+kn] as i64) == 61 { 120 var q: i64 = i + kn + 1 121 var neg: i64 = 0 122 if q < e { if (cf[q] as i64) == 45 { neg = 1; q = q + 1 } } 123 var v: i64 = 0 124 var got: i64 = 0 125 var g2: i64 = 1 126 while g2 == 1 { 127 if q >= e { g2 = 0 } else { 128 let c: i64 = cf[q] as i64 129 if c >= 48 { if c <= 57 { v = v*10 + (c-48); got = 1; q = q + 1 } else { g2 = 0 } } else { g2 = 0 } 130 } 131 } 132 if got == 1 { if neg == 1 { return 0 - v } return v } 133 } } 134 } 135 } 136 i = e + 1 137 } 138 return def 139} 140 141func av_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 142func av_puts(s: *u8) -> i64 { sys_write(1, s, av_len(s)); return 0 } 143func av_pn(v: i64) -> i64 { nxi_out(v); return 0 } 144func av_num(d: *u8, off: i64, v: i64) -> i64 { 145 var x: i64 = v 146 var ng: i64 = 0 147 if x < 0 { ng = 1; x = 0 - x } 148 let tmp: *u8 = sys_mmap(32) as *u8 149 var n: i64 = 0 150 if x == 0 { tmp[0] = 48 as u8; n = 1 } 151 while x > 0 { tmp[n] = (48 + x % 10) as u8; x = x / 10; n = n + 1 } 152 var o: i64 = off 153 if ng == 1 { d[o] = 45 as u8; o = o + 1 } 154 var i: i64 = n 155 while i > 0 { d[o] = tmp[i-1]; o = o + 1; i = i - 1 } 156 d[o] = 0 as u8 157 return o - off + 1 158} 159func av_rdbits(b: *u8, o: i64) -> i64 { 160 return (b[o] as i64) | ((b[o+1] as i64)<<8) | ((b[o+2] as i64)<<16) | ((b[o+3] as i64)<<24) 161} 162func av_f32mul(b: *u8, o: i64, mul: i64) -> i64 { 163 let bits: i64 = av_rdbits(b, o) 164 let sign: i64 = (bits>>31) & 1 165 let exp: i64 = (bits>>23) & 255 166 let mant: i64 = bits & AV_F32_MANT_MASK 167 if exp == 0 { return 0 } 168 let m: i64 = (mant | AV_F32_MANT_SCALE) * mul 169 var e: i64 = exp - 127 - 23 170 var v: i64 = 0 171 if e >= 0 { v = m << e } else { let sh: i64 = 0 - e; v = (m + (1 << (sh-1))) >> sh } 172 if sign == 1 { v = 0 - v } 173 return v 174} 175 176func main(argc: i64, argv: *i64) -> i64 { 177 if argc < 2 { 178 av_puts("usage: nx_avatar_splat <out.png> [gene]\n" as *u8) 179 return 2 180 } 181 // body_gen reads its shape-basis and canon confs as BARE paths -- they resolve against CWD, and 182 // its every proven caller (nx_bodyfit, the registered surface) runs it from the serving root. 183 // Anchor there BEFORE the fork so this organ behaves identically under nx_sov_build_run (which 184 // anchors CWD to buildroot/) and as a promoted tool. Announced on failure, not silent. 185 if sys_chdir("/volume1/homes/elderwesto/nishihost" as *u8) != 0 { 186 av_puts("AVATAR-SPLAT REFUSE: cannot chdir to the serving root\n" as *u8) 187 return 4 188 } 189 let outp: *u8 = argv[1] as *u8 190 var gene: i64 = 0 191 if argc > 2 { let gs2: *u8 = argv[2] as *u8; var gi: i64 = 0; while gs2[gi] != (0 as u8) { gene = gene*10 + (gs2[gi] as i64) - 48; gi = gi + 1 } } 192 // argv[3] = camera yaw in DEGREES (multi-view: the anat_sov judge's own pattern); it-units for gsplat 193 var yawd: i64 = 0 194 if argc > 3 { let ys2: *u8 = argv[3] as *u8; var yi: i64 = 0; while ys2[yi] != (0 as u8) { yawd = yawd*10 + (ys2[yi] as i64) - 48; yi = yi + 1 } } 195 let yawit: i64 = yawd * IT_PI / 180 196 // argv[4] = subcutaneous-fat knob 0..1000 for body_gen (default = body_gen's own 250). A GENOME-LANE 197 // parameter, not a tuned constant: bodyfit's conf envelope is the legal band and its SEARCH is the 198 // v2 chooser -- this argv exists so a caller can pass a searched value instead of the stock default. 199 var fatv: i64 = 250 200 if argc > 4 { fatv = 0; let fs2: *u8 = argv[4] as *u8; var fi: i64 = 0; while fs2[fi] != (0 as u8) { fatv = fatv*10 + (fs2[fi] as i64) - 48; fi = fi + 1 } } 201 if fatv < 0 { fatv = 0 } 202 if fatv > 1000 { fatv = 1000 } 203 // argv[5] = relief per-mille (default = body_gen's own 1000). Same genome-lane contract as fat: 204 // the value to pass is the bodyfit SEARCH's pick, mapped through knowledge/bodyfit.conf's envelope. 205 var rlfv: i64 = 1000 206 if argc > 5 { rlfv = 0; let rs3: *u8 = argv[5] as *u8; var ri: i64 = 0; while rs3[ri] != (0 as u8) { rlfv = rlfv*10 + (rs3[ri] as i64) - 48; ri = ri + 1 } } 207 if rlfv < 0 { rlfv = 0 } 208 if rlfv > 1200 { rlfv = 1200 } 209 let hbits: i64 = (gene >> AV_HGT_SH) & AV_HGT_MASK 210 let hmm: i64 = AV_STAT_BASE_MM + AV_STAT_STEP_MM * hbits 211 let shue: i64 = ((gene >> AV_SKIN_SH) & AV_SKIN_MASK) * SI_GENE_MAX / AV_SKIN_MASK 212 213 // ---- 1. GENERATE (fork nx_body_gen, bodyfit's own tr_run_capture_to pattern) ---- 214 let nums: *u8 = sys_mmap(256) as *u8 215 var no: i64 = 0 216 let a_h: i64 = (nums as i64) + no; no = no + av_num(nums, no, hmm) 217 let a_rs: i64 = (nums as i64) + no; no = no + av_num(nums, no, 28) 218 let a_sub: i64 = (nums as i64) + no; no = no + av_num(nums, no, 4) 219 let a_rlf: i64 = (nums as i64) + no; no = no + av_num(nums, no, rlfv) 220 let a_fat: i64 = (nums as i64) + no; no = no + av_num(nums, no, fatv) 221 let av1: *i64 = sys_mmap(128) as *i64 222 av1[0] = AV_BODYGEN as i64 223 av1[1] = AV_MESH as i64 224 av1[2] = a_h 225 av1[3] = a_rs 226 av1[4] = a_sub 227 av1[5] = a_rlf 228 av1[6] = AV_CANON as i64 229 av1[7] = a_fat 230 av1[8] = 0 231 let cap: *u8 = sys_mmap(AV_OUTCAP) as *u8 232 let clen: *i64 = sys_mmap(16) as *i64 233 clen[0] = 0 234 if tr_run_capture_to(AV_BODYGEN, av1, cap, AV_OUTCAP, clen, AV_TIMEOUT_MS) != 0 { 235 av_puts("AVATAR-SPLAT REFUSE: nx_body_gen failed -- its output follows (a refusal that hides\n" as *u8) 236 av_puts("the child's own words costs the next reader the whole investigation):\n" as *u8) 237 if clen[0] > 0 { sys_write(1, cap, clen[0]) } 238 return 4 239 } 240 241 // ---- 2. READ the NXMSH2 (header: nlayers at 8, ntris at 12; tris at 16+nlayers*24, stride 84, 242 // verts 3x3xf32 at record start -- the layout anat_sov's framing passes read) ---- 243 let lenp: *i64 = sys_mmap(16) as *i64 244 let mb: *u8 = sys_read_file(AV_MESH, lenp) 245 if (mb as i64) == 0 { av_puts("AVATAR-SPLAT REFUSE: cannot read mesh\n" as *u8); return 4 } 246 let nlayers: i64 = av_rdbits(mb, 8) 247 let ntris: i64 = av_rdbits(mb, 12) 248 let triBase: i64 = 16 + nlayers*24 249 if ntris < 1 { av_puts("AVATAR-SPLAT REFUSE: empty mesh\n" as *u8); return 4 } 250 251 // pass 0: measure at fixed precision, derive posq so the max-axis span == AV_SPAN (anat_sov's own 252 // scale-invariance pattern -- a metre mesh and a millimetre mesh land identically) 253 var mn0: i64 = AV_BIG 254 var mx0: i64 = 0-AV_BIG 255 var t0: i64 = 0 256 while t0 < ntris { 257 var c0: i64 = 0 258 while c0 < 9 { 259 let vq: i64 = av_f32mul(mb, triBase + t0*84 + c0*4, AV_POSQ0) 260 if vq < mn0 { mn0 = vq } 261 if vq > mx0 { mx0 = vq } 262 c0 = c0 + 1 263 } 264 t0 = t0 + 1 265 } 266 var span0: i64 = mx0 - mn0 267 if span0 < 1 { span0 = 1 } 268 let posq: i64 = AV_POSQ0 * AV_TARGET / span0 269 if posq < 1 { av_puts("AVATAR-SPLAT REFUSE: mesh span overflows the decode target\n" as *u8); return 4 } 270 271 // pass 1: AABB at working precision -> center offsets 272 var mnx: i64 = AV_BIG; var mny: i64 = AV_BIG; var mnz: i64 = AV_BIG 273 var mxx: i64 = 0-AV_BIG; var mxy: i64 = 0-AV_BIG; var mxz: i64 = 0-AV_BIG 274 var t1: i64 = 0 275 while t1 < ntris { 276 var v1: i64 = 0 277 while v1 < 3 { 278 let o: i64 = triBase + t1*84 + v1*12 279 let x: i64 = av_f32mul(mb, o, posq) 280 let y: i64 = av_f32mul(mb, o+4, posq) 281 let z: i64 = av_f32mul(mb, o+8, posq) 282 if x < mnx { mnx = x } if x > mxx { mxx = x } 283 if y < mny { mny = y } if y > mxy { mxy = y } 284 if z < mnz { mnz = z } if z > mxz { mxz = z } 285 v1 = v1 + 1 286 } 287 t1 = t1 + 1 288 } 289 let cx: i64 = (mnx+mxx)/2 290 let cy: i64 = (mny+mxy)/2 291 let cz: i64 = (mnz+mxz)/2 292 let headline: i64 = mxy - (mxy-mny)*AV_HEAD_BAND/AV_HEAD_DEN // above this y = the head band 293 294 // ---- v2 policy load (shading + hair). Conf absent => v1 defaults, announced. ---- 295 let avcl: *i64 = sys_mmap(16) as *i64 296 avcl[0] = 0 297 var avcf: *u8 = sys_read_file(AV_CONF, avcl) 298 var avcn: i64 = 0 299 var conf_src: *u8 = "defaults" as *u8 300 if (avcf as i64) != 0 { avcn = avcl[0]; conf_src = AV_CONF } else { avcf = sys_mmap(16); avcf[0] = 0 as u8 } 301 let sh_amb: i64 = av_conf_int(avcf, avcn, "shade_ambient" as *u8, AV_DEF_SH_AMB) 302 let sh_gain: i64 = av_conf_int(avcf, avcn, "shade_gain" as *u8, AV_DEF_SH_GAIN) 303 let sh_min: i64 = av_conf_int(avcf, avcn, "shade_min" as *u8, AV_DEF_SH_MIN) 304 let sh_max: i64 = av_conf_int(avcf, avcn, "shade_max" as *u8, AV_DEF_SH_MAX) 305 let hair_on: i64 = av_conf_int(avcf, avcn, "hair_on" as *u8, AV_DEF_HAIR_ON) 306 let hair_top: i64 = av_conf_int(avcf, avcn, "hair_top_permil" as *u8, AV_DEF_HAIR_TOP_PERMIL) 307 let hair_len_pm: i64 = av_conf_int(avcf, avcn, "hair_len_permil" as *u8, AV_DEF_HAIR_LEN_PERMIL) 308 let hair_rad_pm: i64 = av_conf_int(avcf, avcn, "hair_rad_permil" as *u8, AV_DEF_HAIR_RAD_PERMIL) 309 let hair_step_pm: i64 = av_conf_int(avcf, avcn, "hair_step_permil" as *u8, AV_DEF_HAIR_STEP_PERMIL) 310 var hair_seed_every: i64 = av_conf_int(avcf, avcn, "hair_seed_every" as *u8, AV_DEF_HAIR_SEED_EVERY) 311 if hair_seed_every < 1 { hair_seed_every = 1 } 312 let hair_droop: i64 = av_conf_int(avcf, avcn, "hair_droop_permil" as *u8, AV_DEF_HAIR_DROOP) 313 let hair_r: i64 = av_conf_int(avcf, avcn, "hair_r" as *u8, AV_DEF_HAIR_R) 314 let hair_g: i64 = av_conf_int(avcf, avcn, "hair_g" as *u8, AV_DEF_HAIR_G) 315 let hair_b: i64 = av_conf_int(avcf, avcn, "hair_b" as *u8, AV_DEF_HAIR_B) 316 let hair_jit: i64 = av_conf_int(avcf, avcn, "hair_tone_jitter" as *u8, AV_DEF_HAIR_JITTER) 317 // face side measured 2026-08-19 (y90 profile: bust+toes at screen-left = +z): strands never seed on 318 // the face half except the crown band, so the face stays visible under the fringe 319 let hair_face_z: i64 = av_conf_int(avcf, avcn, "hair_face_z" as *u8, AV_DEF_HAIR_FACE_Z) 320 let hair_crown: i64 = av_conf_int(avcf, avcn, "hair_crown_permil" as *u8, AV_DEF_HAIR_CROWN_PERMIL) 321 let hair_droop0: i64 = av_conf_int(avcf, avcn, "hair_droop_base_permil" as *u8, AV_DEF_HAIR_DROOP_BASE) 322 let hair_crown_back: i64 = av_conf_int(avcf, avcn, "hair_crown_back_permil" as *u8, AV_DEF_HAIR_CROWN_BACK) 323 let skin_jit: i64 = av_conf_int(avcf, avcn, "skin_tone_jitter" as *u8, AV_DEF_SKIN_JITTER) 324 let face_on: i64 = av_conf_int(avcf, avcn, "face_on" as *u8, AV_DEF_FACE_ON) 325 let eye_line: i64 = av_conf_int(avcf, avcn, "eye_line_permil" as *u8, AV_DEF_EYE_LINE_PERMIL) 326 let eye_sep: i64 = av_conf_int(avcf, avcn, "eye_sep_permil" as *u8, AV_DEF_EYE_SEP_PERMIL) 327 let eye_rad: i64 = av_conf_int(avcf, avcn, "eye_rad_permil" as *u8, AV_DEF_EYE_RAD_PERMIL) 328 let mouth_line: i64 = av_conf_int(avcf, avcn, "mouth_line_permil" as *u8, AV_DEF_MOUTH_LINE_PERMIL) 329 let mouth_w: i64 = av_conf_int(avcf, avcn, "mouth_w_permil" as *u8, AV_DEF_MOUTH_W_PERMIL) 330 // head geometry in the decode domain; every hair dimension DERIVES from it (no absolute units) 331 let head_h: i64 = mxy - headline 332 var hair_len: i64 = head_h * hair_len_pm / AV_PERMIL 333 var hair_rad: i64 = head_h * hair_rad_pm / AV_PERMIL 334 if hair_rad < 1 { hair_rad = 1 } 335 var hair_step: i64 = hair_rad * hair_step_pm / AV_PERMIL 336 if hair_step < 1 { hair_step = 1 } 337 var hair_seg: i64 = 0 338 if hair_on == 1 { hair_seg = hair_len / hair_step + 1 } 339 let scalp_y: i64 = mxy - head_h * hair_top / AV_PERMIL // scalp = centroid y above this 340 341 // ---- 3. THE COAT: one anisotropic gaussian per triangle -- centroid position, winding normal, 342 // tangent radius from the triangle's OWN mean edge, ITA albedo shaded by the key light ---- 343 // CAMERA-RELATIVE KEY LIGHT: the light must ride with the camera or every rotated view is lit 344 // from behind (the yaw-180 render proved it: front view, chest in its own shadow). A model-space 345 // vector that lands at the face gate's key direction IN CAMERA SPACE is the inverse of the 346 // projection rotation: mx = LX*cos + LZ*sin, mz = -LX*sin + LZ*cos. 347 let sy4l: i64 = it_sin4096(yawit) 348 let cy4l: i64 = it_cos4096(yawit) 349 let mlx: i64 = (AV_LIGHT_X*cy4l + AV_LIGHT_Z*sy4l)/4096 350 let mlz: i64 = (0-AV_LIGHT_X*sy4l + AV_LIGHT_Z*cy4l)/4096 351 let mly: i64 = AV_LIGHT_Y 352 let ab3: *i64 = sys_mmap(24) as *i64 353 si_albedo_of_gene(shue, si_dl_of_region(0), ab3) 354 let fr0: i64 = ab3[0]; let fg0: i64 = ab3[1]; let fb0: i64 = ab3[2] 355 si_albedo_of_gene(shue, si_dl_of_region(1), ab3) 356 let tr0: i64 = ab3[0]; let tg0: i64 = ab3[1]; let tb0: i64 = ab3[2] 357 // count the scalp seeds BEFORE allocating. This pass counts EVERY strided scalp seed; the emission 358 // pass below additionally drops face-half seeds, so this is a declared UPPER BOUND on the buffer, 359 // and ng tracks the exact count -- an over-allocation can never corrupt, an under-allocation would. 360 var nseed: i64 = 0 361 if hair_on == 1 { 362 var tc: i64 = 0 363 var scalp_i: i64 = 0 364 while tc < ntris { 365 let oc: i64 = triBase + tc*84 366 let cyv: i64 = (av_f32mul(mb, oc+4, posq) + av_f32mul(mb, oc+16, posq) + av_f32mul(mb, oc+28, posq))/3 367 if cyv > scalp_y { 368 if scalp_i % hair_seed_every == 0 { nseed = nseed + 1 } 369 scalp_i = scalp_i + 1 370 } 371 tc = tc + 1 372 } 373 } 374 let gauss: *i64 = sys_mmap((ntris + nseed*hair_seg + AV_FACE_GAUSS)*12*8) as *i64 375 var ng: i64 = 0 376 var t: i64 = 0 377 while t < ntris { 378 let o: i64 = triBase + t*84 379 let ax: i64 = av_f32mul(mb, o, posq) - cx 380 let ay: i64 = av_f32mul(mb, o+4, posq) - cy 381 let az: i64 = av_f32mul(mb, o+8, posq) - cz 382 let bx: i64 = av_f32mul(mb, o+12, posq) - cx 383 let by: i64 = av_f32mul(mb, o+16, posq) - cy 384 let bz: i64 = av_f32mul(mb, o+20, posq) - cz 385 let ex: i64 = av_f32mul(mb, o+24, posq) - cx 386 let ey: i64 = av_f32mul(mb, o+28, posq) - cy 387 let ez: i64 = av_f32mul(mb, o+32, posq) - cz 388 let px: i64 = (ax+bx+ex)/3 389 let py: i64 = (ay+by+ey)/3 390 let pz: i64 = (az+bz+ez)/3 391 var nx: i64 = (by-ay)*(ez-az) - (bz-az)*(ey-ay) 392 var ny: i64 = (bz-az)*(ex-ax) - (bx-ax)*(ez-az) 393 var nz: i64 = (bx-ax)*(ey-ay) - (by-ay)*(ex-ax) 394 let nl: i64 = gs_isqrt(nx*nx + ny*ny + nz*nz) 395 if nl > 0 { 396 let e1: i64 = gs_isqrt((bx-ax)*(bx-ax) + (by-ay)*(by-ay) + (bz-az)*(bz-az)) 397 let e2: i64 = gs_isqrt((ex-bx)*(ex-bx) + (ey-by)*(ey-by) + (ez-bz)*(ez-bz)) 398 let e3: i64 = gs_isqrt((ax-ex)*(ax-ex) + (ay-ey)*(ay-ey) + (az-ez)*(az-ez)) 399 var rt: i64 = (e1+e2+e3)/3 * AV_RTAN_NUM / AV_RTAN_DEN 400 if rt < 1 { rt = 1 } 401 let nfx: i64 = nx*256/nl 402 let nfy: i64 = ny*256/nl 403 let nfz: i64 = nz*256/nl 404 var cr: i64 = tr0; var cg: i64 = tg0; var cb2: i64 = tb0 405 if py > headline - cy { cr = fr0; cg = fg0; cb2 = fb0 } 406 // per-splat skin micro-variation: the flat-run killer. Same LCG as the hair jitter; the 407 // amplitude is conf policy and 0 reproduces v1 exactly. 408 if skin_jit > 0 { 409 let ssh2: i64 = (t * AV_HAIR_HASH_A + AV_HAIR_HASH_C) % AV_HAIR_HASH_M 410 let sj: i64 = (ssh2 % (skin_jit*2+1)) - skin_jit 411 cr = cr + sj 412 cg = cg + sj 413 cb2 = cb2 + sj 414 if cr < 0 { cr = 0 } 415 if cr > 255 { cr = 255 } 416 if cg < 0 { cg = 0 } 417 if cg > 255 { cg = 255 } 418 if cb2 < 0 { cb2 = 0 } 419 if cb2 > 255 { cb2 = 255 } 420 } 421 // lambert on the face-gate's key light, its own shade band (70..255 scaled onto albedo) 422 // cos(normal,light) in permil: dt2/(|n|*|L|). The face gate's dt/glen form assumed the 423 // small surface-nets gradients; these decode-domain cross products are ~1e10, so that 424 // form underflows to a flat ambient -- the first render proved it as a shadeless cutout. 425 let dt2: i64 = nx*mlx + ny*mly + nz*mlz 426 let ll: i64 = gs_isqrt(mlx*mlx + mly*mly + mlz*mlz) 427 var cosp: i64 = 0 428 if nl > 0 { if ll > 0 { cosp = dt2/nl*1000/ll } } 429 if cosp > 1000 { cosp = 1000 } 430 if cosp < 0-1000 { cosp = 0-1000 } 431 var sh: i64 = sh_amb + cosp*sh_gain/AV_PERMIL 432 if sh < sh_min { sh = sh_min } 433 if sh > sh_max { sh = sh_max } 434 // rescale from the decode domain (span AV_TARGET) into the splat model box (span AV_SPAN) 435 var rtm: i64 = rt * AV_SPAN / AV_TARGET 436 if rtm < 1 { rtm = 1 } 437 gs_set_aniso(gauss, ng, px*AV_SPAN/AV_TARGET, py*AV_SPAN/AV_TARGET, pz*AV_SPAN/AV_TARGET, nfx, nfy, nfz, rtm, cr*sh/255, cg*sh/255, cb2*sh/255, AV_OP) 438 ng = ng + 1 439 } 440 t = t + 1 441 } 442 443 // ---- 3b. HAIR AS SPLAT VOLUME (GR2 leg 2): a strand = a chain of small discs whose normal rides 444 // the strand direction (a coin-stack tube through gs_set_aniso -- zero new primitives). 445 // Seeds = every Nth scalp triangle by the conf's declared generative density, applied over 446 // the WHOLE scalp population; direction starts along the surface normal and bends to 447 // gravity by hair_droop per unit progress; per-strand tone jitter from the LCG hash. ---- 448 var nhair: i64 = 0 449 if hair_on == 1 { 450 var th: i64 = 0 451 var scalp_j: i64 = 0 452 while th < ntris { 453 let oh: i64 = triBase + th*84 454 let hax: i64 = av_f32mul(mb, oh, posq) - cx 455 let hay: i64 = av_f32mul(mb, oh+4, posq) - cy 456 let haz: i64 = av_f32mul(mb, oh+8, posq) - cz 457 let hbx: i64 = av_f32mul(mb, oh+12, posq) - cx 458 let hby: i64 = av_f32mul(mb, oh+16, posq) - cy 459 let hbz: i64 = av_f32mul(mb, oh+20, posq) - cz 460 let hex: i64 = av_f32mul(mb, oh+24, posq) - cx 461 let hey: i64 = av_f32mul(mb, oh+28, posq) - cy 462 let hez: i64 = av_f32mul(mb, oh+32, posq) - cz 463 let hcy: i64 = (hay+hby+hey)/3 + cy 464 if hcy > scalp_y { 465 var take: i64 = 0 466 if scalp_j % hair_seed_every == 0 { take = 1 } 467 scalp_j = scalp_j + 1 468 // the face half carries no seeds unless this triangle sits in the crown band 469 let hpz0: i64 = (haz+hbz+hez)/3 470 var faceside: i64 = 0 471 if hair_face_z > 0 { if hpz0 > 0 { faceside = 1 } } 472 if hair_face_z < 0 { if hpz0 < 0 { faceside = 1 } } 473 var crown: i64 = 0 474 if hcy > mxy - head_h*hair_crown/AV_PERMIL { crown = 1 } 475 if faceside == 1 { if crown == 0 { take = 0 } } 476 if take == 1 { 477 var hpx: i64 = (hax+hbx+hex)/3 478 var hpy: i64 = (hay+hby+hey)/3 479 var hpz: i64 = (haz+hbz+hez)/3 480 var hnx: i64 = (hby-hay)*(hez-haz) - (hbz-haz)*(hey-hay) 481 var hny: i64 = (hbz-haz)*(hex-hax) - (hbx-hax)*(hez-haz) 482 var hnz: i64 = (hbx-hax)*(hey-hay) - (hby-hay)*(hex-hax) 483 let hnl: i64 = gs_isqrt(hnx*hnx + hny*hny + hnz*hnz) 484 if hnl > 0 { 485 hnx = hnx*AV_PERMIL/hnl 486 hny = hny*AV_PERMIL/hnl 487 hnz = hnz*AV_PERMIL/hnl 488 // a face-side CROWN strand sweeps backward so the fringe clears the face 489 if faceside == 1 { 490 hnz = (hnz*(AV_PERMIL-hair_crown_back) + (0-hair_face_z*AV_PERMIL)*hair_crown_back) / AV_PERMIL 491 } 492 let hsh: i64 = (th * AV_HAIR_HASH_A + AV_HAIR_HASH_C) % AV_HAIR_HASH_M 493 let jit: i64 = (hsh % (hair_jit*2+1)) - hair_jit 494 var hr: i64 = hair_r + jit 495 var hg: i64 = hair_g + jit 496 var hb: i64 = hair_b + jit 497 if hr < 0 { hr = 0 } 498 if hr > 255 { hr = 255 } 499 if hg < 0 { hg = 0 } 500 if hg > 255 { hg = 255 } 501 if hb < 0 { hb = 0 } 502 if hb > 255 { hb = 255 } 503 var sgk: i64 = 0 504 while sgk < hair_seg { 505 let prog: i64 = sgk * AV_PERMIL / hair_seg 506 var bend: i64 = hair_droop0 + (hair_droop - hair_droop0) * prog / AV_PERMIL 507 if bend > AV_PERMIL { bend = AV_PERMIL } 508 var dx: i64 = hnx * (AV_PERMIL - bend) / AV_PERMIL 509 var dy: i64 = hny * (AV_PERMIL - bend) / AV_PERMIL - bend 510 var dz: i64 = hnz * (AV_PERMIL - bend) / AV_PERMIL 511 let dl: i64 = gs_isqrt(dx*dx + dy*dy + dz*dz) 512 if dl > 0 { 513 hpx = hpx + dx * hair_step / dl 514 hpy = hpy + dy * hair_step / dl 515 hpz = hpz + dz * hair_step / dl 516 let hdt: i64 = dx*mlx + dy*mly + dz*mlz 517 let hll: i64 = gs_isqrt(mlx*mlx + mly*mly + mlz*mlz) 518 var hcos: i64 = 0 519 if hll > 0 { hcos = hdt/dl*AV_PERMIL/hll } 520 if hcos < 0 { hcos = 0 - hcos } 521 var hs2: i64 = sh_amb + hcos*sh_gain/AV_PERMIL 522 if hs2 < sh_min { hs2 = sh_min } 523 if hs2 > sh_max { hs2 = sh_max } 524 var hrt: i64 = hair_rad * AV_SPAN / AV_TARGET 525 if hrt < 1 { hrt = 1 } 526 gs_set_aniso(gauss, ng, hpx*AV_SPAN/AV_TARGET, hpy*AV_SPAN/AV_TARGET, hpz*AV_SPAN/AV_TARGET, dx*AV_NFX/dl, dy*AV_NFX/dl, dz*AV_NFX/dl, hrt, hr*hs2/255, hg*hs2/255, hb*hs2/255, AV_OP) 527 ng = ng + 1 528 nhair = nhair + 1 529 } 530 sgk = sgk + 1 531 } 532 } 533 } 534 } 535 th = th + 1 536 } 537 } 538 539 // ---- 3c. FACE FEATURES (GR2 leg 3, first tooth): eye pair + mouth ANCHORED TO THE MEASURED HEAD 540 // GEOMETRY -- the GaussianAvatars idea (features ride the mesh) at lowest order. Every 541 // position derives from the head band's own extents; nothing is an absolute pixel. ---- 542 if face_on == 1 { 543 // head-band extents (model-centred coords) 544 var fhx0: i64 = AV_BIG 545 var fhx1: i64 = 0-AV_BIG 546 var fhz1: i64 = 0-AV_BIG 547 var fhz0: i64 = AV_BIG 548 var tf: i64 = 0 549 while tf < ntris { 550 let of2: i64 = triBase + tf*84 551 let fyc: i64 = (av_f32mul(mb, of2+4, posq) + av_f32mul(mb, of2+16, posq) + av_f32mul(mb, of2+28, posq))/3 552 if fyc > headline { 553 let fxc: i64 = (av_f32mul(mb, of2, posq) + av_f32mul(mb, of2+12, posq) + av_f32mul(mb, of2+24, posq))/3 - cx 554 let fzc: i64 = (av_f32mul(mb, of2+8, posq) + av_f32mul(mb, of2+20, posq) + av_f32mul(mb, of2+32, posq))/3 - cz 555 if fxc < fhx0 { fhx0 = fxc } 556 if fxc > fhx1 { fhx1 = fxc } 557 if fzc > fhz1 { fhz1 = fzc } 558 if fzc < fhz0 { fhz0 = fzc } 559 } 560 tf = tf + 1 561 } 562 let head_w: i64 = fhx1 - fhx0 563 var facez: i64 = fhz1 564 if hair_face_z < 0 { facez = fhz0 } 565 let eye_y: i64 = (mxy - cy) - head_h * eye_line / AV_PERMIL 566 let mouth_y: i64 = (mxy - cy) - head_h * mouth_line / AV_PERMIL 567 let ex_off: i64 = head_w * eye_sep / (AV_PERMIL*2) 568 var er: i64 = head_h * eye_rad / AV_PERMIL 569 if er < 1 { er = 1 } 570 // outward-facing normal so the discs face the camera at the front view 571 var fnz: i64 = AV_NFX 572 if hair_face_z < 0 { fnz = 0 - AV_NFX } 573 // z stacking: sclera on the skin, iris a step out, pupil another step, sized from the radius 574 let zs: i64 = er / 2 575 var side: i64 = 0 576 while side < 2 { 577 var exc: i64 = ex_off 578 if side == 1 { exc = 0 - ex_off } 579 gs_set_aniso(gauss, ng, exc*AV_SPAN/AV_TARGET, eye_y*AV_SPAN/AV_TARGET, (facez+zs)*AV_SPAN/AV_TARGET, 0, 0, fnz, er*AV_SPAN/AV_TARGET, 242, 240, 234, AV_OP) 580 ng = ng + 1 581 gs_set_aniso(gauss, ng, exc*AV_SPAN/AV_TARGET, eye_y*AV_SPAN/AV_TARGET, (facez+zs*2)*AV_SPAN/AV_TARGET, 0, 0, fnz, er*55*AV_SPAN/(AV_TARGET*100), 96, 64, 40, AV_OP) 582 ng = ng + 1 583 gs_set_aniso(gauss, ng, exc*AV_SPAN/AV_TARGET, eye_y*AV_SPAN/AV_TARGET, (facez+zs*3)*AV_SPAN/AV_TARGET, 0, 0, fnz, er*25*AV_SPAN/(AV_TARGET*100), 22, 18, 16, AV_OP) 584 ng = ng + 1 585 side = side + 1 586 } 587 // mouth: one wide low disc in a lip tone derived from the face albedo (redder, darker) 588 var mw: i64 = head_w * mouth_w / AV_PERMIL 589 if mw < 1 { mw = 1 } 590 var lipr: i64 = fr0 * 88 / 100 591 var lipg: i64 = fg0 * 55 / 100 592 var lipb: i64 = fb0 * 55 / 100 593 if lipr > 255 { lipr = 255 } 594 gs_set_aniso(gauss, ng, 0, mouth_y*AV_SPAN/AV_TARGET, (facez+zs)*AV_SPAN/AV_TARGET, 0, 0, fnz, mw*AV_SPAN/AV_TARGET, lipr, lipg, lipb, AV_OP) 595 ng = ng + 1 596 } 597 598 // ---- 4. SPLAT (the face gate's exact buffer recipe, aniso lane) ---- 599 let W: i64 = gs_w() 600 let H: i64 = gs_h() 601 let npx: i64 = W*H 602 let fb: *i64 = sys_mmap(npx*8) as *i64 603 let acc: *i64 = sys_mmap(npx*3*8) as *i64 604 let trans: *i64 = sys_mmap(npx*8) as *i64 605 let depth: *i64 = sys_mmap(ng*8) as *i64 606 let sxb: *i64 = sys_mmap(ng*8) as *i64 607 let syb: *i64 = sys_mmap(ng*8) as *i64 608 let pa: *i64 = sys_mmap(ng*8) as *i64 609 let pb: *i64 = sys_mmap(ng*8) as *i64 610 let pc: *i64 = sys_mmap(ng*8) as *i64 611 let pdet: *i64 = sys_mmap(ng*8) as *i64 612 let order: *i64 = sys_mmap(ng*8) as *i64 613 let count: *i64 = sys_mmap((gs_nb()+2)*8) as *i64 614 let explut: *i64 = sys_mmap(gs_expn()*8) as *i64 615 gs_build_explut(explut) 616 gs_render_aniso(gauss, ng, yawit, AV_CAMZ, fb, acc, trans, depth, sxb, syb, pa, pb, pc, pdet, order, count, explut, 26, 28, 44) 617 // A WRITE THAT IS NOT CHECKED IS A SUCCESS THAT IS NOT EARNED: the v2 first run wrote into a 618 // nonexistent ../sites path, write_png failed, and this organ still printed wrote= -- measured 619 // 2026-08-19. The announce line now only exists when the artifact does. 620 let wrc: i64 = write_png(fb, W, H, outp) 621 if wrc != 0 { 622 av_puts("AVATAR-SPLAT REFUSE: write_png failed rc=" as *u8); av_pn(wrc) 623 av_puts(" path=" as *u8); av_puts(outp) 624 av_puts(" (cwd is the nishihost serving root -- pass sites/... not ../sites/...)\n" as *u8) 625 sys_unlinkat(AV_MESH) 626 return 4 627 } 628 sys_unlinkat(AV_MESH) 629 630 av_puts("AVATAR-SPLAT canon=" as *u8); av_puts(AV_CANON) 631 av_puts(" gene=" as *u8); av_pn(gene) 632 av_puts(" height_mm=" as *u8); av_pn(hmm) 633 av_puts(" skin_hue=" as *u8); av_pn(shue) 634 av_puts(" ntris=" as *u8); av_pn(ntris) 635 av_puts(" gaussians=" as *u8); av_pn(ng) 636 av_puts(" hair_gaussians=" as *u8); av_pn(nhair) 637 av_puts(" policy=" as *u8); av_puts(conf_src) 638 av_puts(" span0=" as *u8); av_pn(span0) 639 av_puts(" posq=" as *u8); av_pn(posq) 640 av_puts(" wrote=" as *u8); av_puts(outp) 641 av_puts("\n" as *u8) 642 return 0 643}