code wiki / (root) / nx_tissuefield_lib.nx

nx_tissuefield_lib.nx source

↩ module page · 1947 lines · 99682 B

1// nx_tissuefield_lib.nx -- THE SKULL-BOUND TISSUE-DEPTH SKIN SURFACE (aesthetictwin AT46, 2026-09-18). 2// 3// Operator 2026-09-18: "we were trying to render a skull then every layer up ... controllable every layer up generative 4// capabilities". Today's faces are blended SDF blobs on a frame; nx_faceanat never reads the skull it was meant to sit on 5// (`nxmesh` count 0 in that file). This library builds the FIRST layer ON the generated skull: the skin is an OFFSET SURFACE of 6// the skull mesh, offset along the skull's own vertex normals by a tissue-depth FIELD interpolated from the forensic 7// tissue-depth table at anatomical landmarks that are LOCATED ON THE SKULL ITSELF (midline profile extrema, support 8// directions, canon ratios of the bony span), plus controllable fat compartments and named patches for the features that have 9// no bone behind them (globes and lids over the orbits, the nose over the empty aperture, the vermilion band). 10// 11// EVERY NUMBER IS DATA OR IS DERIVED FROM THE RESOURCE IT DESCRIBES: depths, compartment magnitudes and construction ratios come 12// from knowledge/tissue_depth.conf (each row names its source; rows the research lane has not pinned say PENDING-REF), the 13// interpolation kernel width is the median nearest-landmark spacing of the located landmarks, grid steps are the mesh's own 14// mean edge length, the units are the skull's own (NXMSH2 float32 millimetres read as tenths of a millimetre, so one 15// tissue-depth unit mm10 IS one model unit u10), and the camera distance is derived from the head height and a declared frame 16// fraction. Nothing here reads nx_faceanat, nx_sdfrender or nx_skullsdf as code: the skull is consumed as the MESH those organs 17// emit, and the depth values nx_faceanat typed inline were carried into the conf with their source named. 18// 19// FRAME: the skull mesh is anterior +z, superior +y, the subject's left +x (nx_meshview front view = camera on +z). The 20// rasteriser (nx_trimesh) looks down +z with the camera at -camz, so every vertex is pushed through a rotation of half a turn 21// about y (x -> -x, z -> -z): a proper rotation, never a mirror, so the subject's right eye lands on the image left as in a 22// photograph (the photo ruler's side convention). 23// 24// LIB, no main. Composes nx_nxmesh_lib (the ONE NXMSH2 layout), nx_vecmath (isqrt, float32 codec), nx_trimesh (the 25// rasteriser), nx_png (the encoder), nx_itoa_lib (zero-alloc decimal). license_tier: ORIGINAL No hw writes (Rule 26). 26import "nx_syscalls.nx" 27import "nx_vecmath.nx" 28import "nx_nxmesh_lib.nx" 29import "nx_trimesh.nx" 30import "nx_png.nx" 31import "nx_itoa_lib.nx" 32 33// ---- units and fixed points (products of small literals: the build refuses a bare literal at or above 1024) ---- 34const TFL_I64: i64 = 8 35const TFL_Q16: i64 = 256 * 256 // the kernel's fixed point (weights and exp) 36const TFL_NQ: i64 = 64 * 64 // the normal scale surface_nets emits and NXMSH2 stores (4096) 37const TFL_ZNONE: i64 = 0 - 1000 * 1000 * 1000 // "no surface in this cell" for the frontal depth maps 38const TFL_FAR: i64 = 1000 * 1000 * 1000 39const TFL_PERMIL: i64 = 1000 40const TFL_MODE644: i64 = 420 41const TFL_MODE755: i64 = 493 42const TFL_PATHB: i64 = 512 43const TFL_STDOUT: i64 = 1 44const TFL_PIPE: i64 = 124 45const TFL_NL: i64 = 10 46const TFL_HASH: i64 = 35 47const TFL_MINUS: i64 = 45 48const TFL_COMMA: i64 = 44 49const TFL_ZERO: i64 = 48 50const TFL_NINE: i64 = 57 51const TFL_BYTE: i64 = 255 52// the fixture cap on the frontal depth map and the landmark tables: the map is sized from the mesh (bbox / edge), never capped 53const TFL_EXP_TERMS: i64 = 12 // Taylor terms for e^-1; the 12th term is below one Q16 unit 54const TFL_EXP_MAX_INT: i64 = 24 // exp(-24) is below one Q16 unit: the weight is zero past this 55const TFL_SUPPORT_SIGMAS: i64 = 3 // a Gaussian compartment's support for the partition tooth: 3 sigma 56const TFL_RIM_SAMPLES: i64 = 16 // boundary samples of the lid ellipse for the rim depth 57const TFL_SPHERE_RINGS: i64 = 12 58const TFL_SPHERE_SEGS: i64 = 16 59const TFL_LID_SUBDIV: i64 = 2 // lid and nose patches are gridded at half the mesh edge 60const TFL_COL_WHITE: i64 = 255 + 255 * 256 + 255 * 256 * 256 61const TFL_COL_IRIS: i64 = 60 + 90 * 256 + 110 * 256 * 256 // a blue-grey iris: hue is a later layer's data 62const TFL_COL_PUPIL: i64 = 8 + 8 * 256 + 8 * 256 * 256 63const TFL_COL_BROW: i64 = 60 + 45 * 256 + 35 * 256 * 256 64const TFL_COL_SEAM: i64 = 70 + 40 * 256 + 40 * 256 * 256 65const TFL_COL_BONE: i64 = 232 + 224 * 256 + 216 * 256 * 256 // the bone tint nx_skullsdf stores (910,890,845 permil) 66const TFL_BG: i64 = 20 + 28 * 256 + 40 * 256 * 256 // the dark slate every mesh render uses (nx_meshview MV_BG) 67 68// ---- the mesh record: an i64 block, pointers carried as i64 ---- 69const TFL_M_NV: i64 = 0 70const TFL_M_NT: i64 = 1 71const TFL_M_VX: i64 = 2 72const TFL_M_VY: i64 = 3 73const TFL_M_VZ: i64 = 4 74const TFL_M_NX: i64 = 5 75const TFL_M_NY: i64 = 6 76const TFL_M_NZ: i64 = 7 77const TFL_M_TA: i64 = 8 78const TFL_M_TB: i64 = 9 79const TFL_M_TC: i64 = 10 80const TFL_M_X0: i64 = 11 81const TFL_M_X1: i64 = 12 82const TFL_M_Y0: i64 = 13 83const TFL_M_Y1: i64 = 14 84const TFL_M_Z0: i64 = 15 85const TFL_M_Z1: i64 = 16 86const TFL_M_EDGE: i64 = 17 // mean triangle edge length, u10 (the mesh's own resolution) 87const TFL_M_FM: i64 = 18 // frontal depth map ptr (max z per (x,y) cell), or 0 88const TFL_M_FMW: i64 = 19 89const TFL_M_FMH: i64 = 20 90const TFL_M_FMCELL: i64 = 21 91const TFL_M_RAW: i64 = 22 // triangle-soup vertex count before welding 92const TFL_M_N: i64 = 24 93 94// ---- the conf tables: depth rows (landmarks), fat rows (compartments), patch rows (key=value) ---- 95const TFL_T_NROWS: i64 = 0 96const TFL_T_NFAT: i64 = 1 97const TFL_T_NPATCH: i64 = 2 98const TFL_T_NPENDING: i64 = 3 99const TFL_T_MALFORMED: i64 = 4 100const TFL_T_HDR: i64 = 8 101const TFL_R_FIELDS: i64 = 16 102const TFL_R_NAME: i64 = 0 103const TFL_R_DEPTH: i64 = 1 // mm10, or -1 for a row that is located but does not vote 104const TFL_R_SRC: i64 = 2 105const TFL_R_NOTE: i64 = 3 106const TFL_R_X: i64 = 4 107const TFL_R_Y: i64 = 5 108const TFL_R_Z: i64 = 6 109const TFL_R_AX: i64 = 7 // anchor: the skull vertex nearest the located point 110const TFL_R_AY: i64 = 8 111const TFL_R_AZ: i64 = 9 112const TFL_R_AIDX: i64 = 10 113const TFL_R_ADIST: i64 = 11 114const TFL_R_STATE: i64 = 12 // 0 not located, 1 located, 2 located by a named fallback 115const TFL_R_PENDING: i64 = 13 116const TFL_ROWS_CAP: i64 = 64 117const TFL_FAT_CAP: i64 = 16 118const TFL_PATCH_CAP: i64 = 64 119const TFL_T_I64S: i64 = TFL_T_HDR + (TFL_ROWS_CAP + TFL_FAT_CAP + TFL_PATCH_CAP) * TFL_R_FIELDS 120const TFL_ST_NONE: i64 = 0 121const TFL_ST_LOCATED: i64 = 1 122const TFL_ST_FALLBACK: i64 = 2 123 124// ---- the landmark receipt: the values every consumer prints ---- 125const TFL_K_SIGMA: i64 = 0 126const TFL_K_DMIN: i64 = 1 127const TFL_K_DMED: i64 = 2 128const TFL_K_DMAX: i64 = 3 129const TFL_K_LOCATED: i64 = 4 130const TFL_K_FALLBACK: i64 = 5 131const TFL_K_UNLOCATED: i64 = 6 132const TFL_K_ANCHOR_MAX: i64 = 7 133const TFL_K_VOTERS: i64 = 8 134const TFL_K_N: i64 = 16 135 136static TFL_E_INV_Q16: i64 // e^-1 in Q16, derived once by series, never typed 137 138func tfl_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(TFL_STDOUT, s, n); return 0 } 139func tfl_pn(v: i64) -> i64 { nxi_out(v); return 0 } 140func tfl_kv(k: *u8, v: i64) -> i64 { tfl_puts(k); tfl_pn(v); return 0 } 141func tfl_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 142func tfl_streq(a: *u8, b: *u8) -> i64 { 143 var i: i64 = 0 144 var go: i64 = 1 145 var eq: i64 = 1 146 while go == 1 { if a[i] != b[i] { eq = 0; go = 0 } else { if a[i] == (0 as u8) { go = 0 } else { i = i + 1 } } } 147 return eq 148} 149func tfl_atoi(s: *u8) -> i64 { 150 var i: i64 = 0 151 var n: i64 = 0 152 var sg: i64 = 1 153 if s[0] == (TFL_MINUS as u8) { sg = 0 - 1; i = 1 } 154 while s[i] != (0 as u8) { let c: i64 = s[i] as i64; if c >= TFL_ZERO { if c <= TFL_NINE { n = n * 10 + (c - TFL_ZERO) } } i = i + 1 } 155 return n * sg 156} 157func tfl_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } 158func tfl_min(a: i64, b: i64) -> i64 { if a < b { return a } return b } 159func tfl_max(a: i64, b: i64) -> i64 { if a > b { return a } return b } 160// does the string carry the substring (used to flag PENDING-REF sources) 161func tfl_has(s: *u8, lit: *u8) -> i64 { 162 let n: i64 = tfl_slen(s) 163 let m: i64 = tfl_slen(lit) 164 var i: i64 = 0 165 while i + m <= n { 166 var k: i64 = 0 167 var ok: i64 = 1 168 while k < m { if s[i + k] != lit[k] { ok = 0; k = m } else { k = k + 1 } } 169 if ok == 1 { return 1 } 170 i = i + 1 171 } 172 return 0 173} 174func tfl_cat(d: *u8, o: i64, s: *u8) -> i64 { var p: i64 = o; var i: i64 = 0; while s[i] != (0 as u8) { d[p] = s[i]; p = p + 1; i = i + 1 } d[p] = 0 as u8; return p } 175func tfl_catn(d: *u8, o: i64, v: i64) -> i64 { let p: i64 = nxi_buf(d, o, v); d[p] = 0 as u8; return p } 176 177// ==== the kernel: exp(-t) in Q16, t in Q16, derived arithmetic (no typed constant) ==== 178func tfl_exp_init() -> i64 { 179 if TFL_E_INV_Q16 != 0 { return TFL_E_INV_Q16 } 180 // e^-1 = sum_k (-1)^k / k! in Q16: term_0 = Q, term_k = -term_{k-1} / k 181 var term: i64 = TFL_Q16 182 var sum: i64 = 0 183 var k: i64 = 0 184 while k < TFL_EXP_TERMS { sum = sum + term; k = k + 1; term = 0 - term / k } 185 TFL_E_INV_Q16 = sum 186 return sum 187} 188// exp(-t) for t >= 0 (Q16 in, Q16 out): integer part by repeated e^-1, fraction by a 5-term series 189func tfl_exp_q16(t: i64) -> i64 { 190 if t <= 0 { return TFL_Q16 } 191 let einv: i64 = tfl_exp_init() 192 let n: i64 = t / TFL_Q16 193 if n > TFL_EXP_MAX_INT { return 0 } 194 let f: i64 = t - n * TFL_Q16 195 // e^-f = 1 - f + f^2/2 - f^3/6 + f^4/24 (f in [0,1) Q16) 196 let f2: i64 = f * f / TFL_Q16 197 let f3: i64 = f2 * f / TFL_Q16 198 let f4: i64 = f3 * f / TFL_Q16 199 var r: i64 = TFL_Q16 - f + f2 / 2 - f3 / 6 + f4 / 24 200 var k: i64 = 0 201 while k < n { r = r * einv / TFL_Q16; k = k + 1 } 202 if r < 0 { r = 0 } 203 return r 204} 205// the Gaussian weight of a squared distance d2 (u10^2) at kernel width sigma (u10): exp(-d2 / (2 sigma^2)), Q16 206func tfl_gauss_q16(d2: i64, sigma: i64) -> i64 { 207 if sigma <= 0 { return 0 } 208 let den: i64 = 2 * sigma * sigma 209 // t = d2 * Q16 / den, guarded against overflow for far points (they weigh zero anyway) 210 if d2 / den > TFL_EXP_MAX_INT { return 0 } 211 let t: i64 = d2 * TFL_Q16 / den 212 return tfl_exp_q16(t) 213} 214 215// ==== the conf ==== 216func tfl_tab_new() -> *i64 { 217 let T: *i64 = sys_mmap(TFL_T_I64S * TFL_I64) as *i64 218 var i: i64 = 0 219 while i < TFL_T_I64S { T[i] = 0; i = i + 1 } 220 return T 221} 222func tfl_row(T: *i64, i: i64) -> *i64 { return ((T as i64) + (TFL_T_HDR + i * TFL_R_FIELDS) * TFL_I64) as *i64 } 223func tfl_fatrow(T: *i64, i: i64) -> *i64 { return ((T as i64) + (TFL_T_HDR + (TFL_ROWS_CAP + i) * TFL_R_FIELDS) * TFL_I64) as *i64 } 224func tfl_patchrow(T: *i64, i: i64) -> *i64 { return ((T as i64) + (TFL_T_HDR + (TFL_ROWS_CAP + TFL_FAT_CAP + i) * TFL_R_FIELDS) * TFL_I64) as *i64 } 225// split a line at its pipes in place (0 written over each pipe); f[k] = pointer to field k; returns the field count 226func tfl_split(line: *u8, f: *i64, cap: i64) -> i64 { 227 var n: i64 = 0 228 var i: i64 = 0 229 f[0] = line as i64 230 n = 1 231 while line[i] != (0 as u8) { 232 if line[i] == (TFL_PIPE as u8) { 233 line[i] = 0 as u8 234 if n < cap { f[n] = (line as i64) + i + 1; n = n + 1 } 235 } 236 i = i + 1 237 } 238 return n 239} 240// load knowledge/tissue_depth.conf: depth|<landmark>|<mm10 or ->|<source>|<note> ; fat|<name>|<mm10>|<source>|<note> ; 241// patch|<key>|<value>|<source>|<note>. Returns 1 loaded, 0 unreadable. 242func tfl_conf_load(path: *u8, T: *i64) -> i64 { 243 let lp: *i64 = sys_mmap(2 * TFL_I64) as *i64 244 lp[0] = 0 245 let buf: *u8 = sys_read_file(path, lp) 246 if (buf as i64) == 0 { return 0 } 247 let n: i64 = lp[0] 248 let f: *i64 = sys_mmap(8 * TFL_I64) as *i64 249 var i: i64 = 0 250 while i < n { 251 var e: i64 = i 252 var going: i64 = 1 253 while going == 1 { if e >= n { going = 0 } else { if buf[e] == (TFL_NL as u8) { going = 0 } else { e = e + 1 } } } 254 if e < n { buf[e] = 0 as u8 } 255 let line: *u8 = ((buf as i64) + i) as *u8 256 var skip: i64 = 0 257 if e == i { skip = 1 } 258 if skip == 0 { if line[0] == (TFL_HASH as u8) { skip = 1 } } 259 if skip == 0 { 260 let nf: i64 = tfl_split(line, f, 8) 261 if nf < 4 { T[TFL_T_MALFORMED] = T[TFL_T_MALFORMED] + 1 } else { 262 let kind: *u8 = f[0] as *u8 263 var note: *u8 = "" as *u8 264 if nf >= 5 { note = f[4] as *u8 } 265 let src: *u8 = f[3] as *u8 266 var pending: i64 = 0 267 if tfl_has(src, "PENDING" as *u8) == 1 { pending = 1 } 268 var placed: i64 = 0 269 if tfl_streq(kind, "depth" as *u8) == 1 { 270 if T[TFL_T_NROWS] < TFL_ROWS_CAP { 271 let r: *i64 = tfl_row(T, T[TFL_T_NROWS]) 272 r[TFL_R_NAME] = f[1] 273 let vs: *u8 = f[2] as *u8 274 if vs[0] == (TFL_MINUS as u8) { r[TFL_R_DEPTH] = 0 - 1 } else { r[TFL_R_DEPTH] = tfl_atoi(vs) } 275 r[TFL_R_SRC] = src as i64 276 r[TFL_R_NOTE] = note as i64 277 r[TFL_R_STATE] = TFL_ST_NONE 278 r[TFL_R_PENDING] = pending 279 T[TFL_T_NROWS] = T[TFL_T_NROWS] + 1 280 placed = 1 281 } 282 } 283 if tfl_streq(kind, "fat" as *u8) == 1 { 284 if T[TFL_T_NFAT] < TFL_FAT_CAP { 285 let r: *i64 = tfl_fatrow(T, T[TFL_T_NFAT]) 286 r[TFL_R_NAME] = f[1] 287 r[TFL_R_DEPTH] = tfl_atoi(f[2] as *u8) 288 r[TFL_R_SRC] = src as i64 289 r[TFL_R_NOTE] = note as i64 290 r[TFL_R_PENDING] = pending 291 T[TFL_T_NFAT] = T[TFL_T_NFAT] + 1 292 placed = 1 293 } 294 } 295 if tfl_streq(kind, "patch" as *u8) == 1 { 296 if T[TFL_T_NPATCH] < TFL_PATCH_CAP { 297 let r: *i64 = tfl_patchrow(T, T[TFL_T_NPATCH]) 298 r[TFL_R_NAME] = f[1] 299 r[TFL_R_DEPTH] = tfl_atoi(f[2] as *u8) 300 r[TFL_R_SRC] = src as i64 301 r[TFL_R_NOTE] = note as i64 302 r[TFL_R_PENDING] = pending 303 T[TFL_T_NPATCH] = T[TFL_T_NPATCH] + 1 304 placed = 1 305 } 306 } 307 if placed == 1 { if pending == 1 { T[TFL_T_NPENDING] = T[TFL_T_NPENDING] + 1 } } 308 if placed == 0 { T[TFL_T_MALFORMED] = T[TFL_T_MALFORMED] + 1 } 309 } 310 } 311 i = e + 1 312 } 313 return 1 314} 315func tfl_row_find(T: *i64, name: *u8) -> i64 { 316 var i: i64 = 0 317 while i < T[TFL_T_NROWS] { let r: *i64 = tfl_row(T, i); if tfl_streq(r[TFL_R_NAME] as *u8, name) == 1 { return i } i = i + 1 } 318 return 0 - 1 319} 320func tfl_fat_find(T: *i64, name: *u8) -> i64 { 321 var i: i64 = 0 322 while i < T[TFL_T_NFAT] { let r: *i64 = tfl_fatrow(T, i); if tfl_streq(r[TFL_R_NAME] as *u8, name) == 1 { return i } i = i + 1 } 323 return 0 - 1 324} 325// a patch value by key; absent keys are announced and read as 0 (the caller sees the announcement, never a silent default) 326func tfl_patch(T: *i64, key: *u8) -> i64 { 327 var i: i64 = 0 328 while i < T[TFL_T_NPATCH] { let r: *i64 = tfl_patchrow(T, i); if tfl_streq(r[TFL_R_NAME] as *u8, key) == 1 { return r[TFL_R_DEPTH] } i = i + 1 } 329 tfl_puts("TFL-PATCH-ABSENT key=" as *u8); tfl_puts(key); tfl_puts(" value=0 -- add the row to knowledge/tissue_depth.conf\n" as *u8) 330 return 0 331} 332func tfl_patch_set(T: *i64, key: *u8, v: i64) -> i64 { 333 var i: i64 = 0 334 while i < T[TFL_T_NPATCH] { let r: *i64 = tfl_patchrow(T, i); if tfl_streq(r[TFL_R_NAME] as *u8, key) == 1 { r[TFL_R_DEPTH] = v; return 1 } i = i + 1 } 335 return 0 336} 337// Apply the shared configured material contract before any scene render. Consumers may override rows in T for a controlled experiment. 338func tfl_material_apply(T: *i64) -> i64 { 339 let tex: i64 = tfl_patch(T, "skin_texture_scale" as *u8) 340 let spec: i64 = tfl_patch(T, "skin_specular_strength" as *u8) 341 tm_set_tex(tex); tm_set_spec(spec) 342 tfl_kv("TFL-MATERIAL texture_scale=" as *u8, tex); tfl_kv(" specular=" as *u8, spec); tfl_puts("\n" as *u8) 343 return 1 344} 345func tfl_fat_set(T: *i64, name: *u8, v: i64) -> i64 { 346 let i: i64 = tfl_fat_find(T, name) 347 if i < 0 { return 0 } 348 let r: *i64 = tfl_fatrow(T, i) 349 r[TFL_R_DEPTH] = v 350 return 1 351} 352// set or clear every voting depth (the zero-depth neg-control): scale in permil 353func tfl_depths_scale(T: *i64, permil: i64) -> i64 { 354 var i: i64 = 0 355 while i < T[TFL_T_NROWS] { let r: *i64 = tfl_row(T, i); if r[TFL_R_DEPTH] >= 0 { r[TFL_R_DEPTH] = r[TFL_R_DEPTH] * permil / TFL_PERMIL } i = i + 1 } 356 var k: i64 = 0 357 while k < T[TFL_T_NFAT] { let q: *i64 = tfl_fatrow(T, k); q[TFL_R_DEPTH] = q[TFL_R_DEPTH] * permil / TFL_PERMIL; k = k + 1 } 358 return 0 359} 360 361// ==== the mesh: NXMSH2 in, welded vertex list with averaged normals ==== 362func tfl_mesh_new() -> *i64 { 363 let M: *i64 = sys_mmap(TFL_M_N * TFL_I64) as *i64 364 var i: i64 = 0 365 while i < TFL_M_N { M[i] = 0; i = i + 1 } 366 return M 367} 368func tfl_hash3(x: i64, y: i64, z: i64) -> i64 { 369 var h: i64 = x * 73 + y * 151 + z * 379 370 h = h ^ (h >> 13) 371 h = h * 97 + 1 372 if h < 0 { h = 0 - h } 373 return h 374} 375// read a mesh file; weld identical vertices; average their normals; measure the bbox and the mean edge. 1 ok, 0 refused 376func tfl_mesh_load(path: *u8, M: *i64) -> i64 { 377 let lp: *i64 = sys_mmap(2 * TFL_I64) as *i64 378 lp[0] = 0 379 let b: *u8 = sys_read_file(path, lp) 380 if (b as i64) == 0 { return 0 } 381 let sz: i64 = lp[0] 382 if sz < NM_HDR { return 0 } 383 if b[0] != (78 as u8) { return 0 } 384 if b[1] != (88 as u8) { return 0 } 385 let nt: i64 = nm_ntris(b) 386 if nt <= 0 { return 0 } 387 let tb: i64 = nm_tri_base(b) 388 if tb + nt * NM_TRI_REC > sz { return 0 } 389 let raw: i64 = nt * 3 390 var hs: i64 = 1 391 while hs < raw * 2 { hs = hs * 2 } 392 let hk: *i64 = sys_mmap(hs * TFL_I64) as *i64 393 var q: i64 = 0 394 while q < hs { hk[q] = 0 - 1; q = q + 1 } 395 let vx: *i64 = sys_mmap(raw * TFL_I64) as *i64 396 let vy: *i64 = sys_mmap(raw * TFL_I64) as *i64 397 let vz: *i64 = sys_mmap(raw * TFL_I64) as *i64 398 let nx: *i64 = sys_mmap(raw * TFL_I64) as *i64 399 let ny: *i64 = sys_mmap(raw * TFL_I64) as *i64 400 let nz: *i64 = sys_mmap(raw * TFL_I64) as *i64 401 let ta: *i64 = sys_mmap(nt * TFL_I64) as *i64 402 let tb2: *i64 = sys_mmap(nt * TFL_I64) as *i64 403 let tc: *i64 = sys_mmap(nt * TFL_I64) as *i64 404 var nv: i64 = 0 405 var x0: i64 = TFL_FAR; var x1: i64 = 0 - TFL_FAR 406 var y0: i64 = TFL_FAR; var y1: i64 = 0 - TFL_FAR 407 var z0: i64 = TFL_FAR; var z1: i64 = 0 - TFL_FAR 408 var t: i64 = 0 409 while t < nt { 410 var v: i64 = 0 411 while v < 3 { 412 let x: i64 = nm_coord(b, tb, t, v, 0) 413 let y: i64 = nm_coord(b, tb, t, v, 1) 414 let z: i64 = nm_coord(b, tb, t, v, 2) 415 let no: i64 = tb + t * NM_TRI_REC + 36 + v * NM_VERT_STRIDE 416 let fnx: i64 = vm_f32_to_int(nm_u32(b, no), TFL_NQ) 417 let fny: i64 = vm_f32_to_int(nm_u32(b, no + NM_F32_BYTES), TFL_NQ) 418 let fnz: i64 = vm_f32_to_int(nm_u32(b, no + 2 * NM_F32_BYTES), TFL_NQ) 419 var h: i64 = tfl_hash3(x, y, z) & (hs - 1) 420 var idx: i64 = 0 - 1 421 var probing: i64 = 1 422 while probing == 1 { 423 let k: i64 = hk[h] 424 if k < 0 { probing = 0 } else { 425 if vx[k] == x { if vy[k] == y { if vz[k] == z { idx = k; probing = 0 } } } 426 if probing == 1 { h = (h + 1) & (hs - 1) } 427 } 428 } 429 if idx < 0 { 430 idx = nv 431 hk[h] = nv 432 vx[nv] = x; vy[nv] = y; vz[nv] = z 433 nx[nv] = 0; ny[nv] = 0; nz[nv] = 0 434 nv = nv + 1 435 if x < x0 { x0 = x } if x > x1 { x1 = x } 436 if y < y0 { y0 = y } if y > y1 { y1 = y } 437 if z < z0 { z0 = z } if z > z1 { z1 = z } 438 } 439 nx[idx] = nx[idx] + fnx; ny[idx] = ny[idx] + fny; nz[idx] = nz[idx] + fnz 440 if v == 0 { ta[t] = idx } 441 if v == 1 { tb2[t] = idx } 442 if v == 2 { tc[t] = idx } 443 v = v + 1 444 } 445 t = t + 1 446 } 447 // renormalise the averaged normals to TFL_NQ (a zero sum keeps +z so the offset still moves outward-ish, announced by count) 448 var zeroed: i64 = 0 449 var i: i64 = 0 450 while i < nv { 451 let l: i64 = vm_isqrt(nx[i] * nx[i] + ny[i] * ny[i] + nz[i] * nz[i]) 452 if l > 0 { nx[i] = nx[i] * TFL_NQ / l; ny[i] = ny[i] * TFL_NQ / l; nz[i] = nz[i] * TFL_NQ / l } else { nz[i] = TFL_NQ; zeroed = zeroed + 1 } 453 i = i + 1 454 } 455 // the mesh's own resolution: the mean edge |AB| over every triangle (the whole population, no sample) 456 var esum: i64 = 0 457 var t2: i64 = 0 458 while t2 < nt { 459 let a: i64 = ta[t2]; let c: i64 = tb2[t2] 460 let dx: i64 = vx[a] - vx[c]; let dy: i64 = vy[a] - vy[c]; let dz: i64 = vz[a] - vz[c] 461 esum = esum + vm_isqrt(dx * dx + dy * dy + dz * dz) 462 t2 = t2 + 1 463 } 464 M[TFL_M_NV] = nv; M[TFL_M_NT] = nt 465 M[TFL_M_VX] = vx as i64; M[TFL_M_VY] = vy as i64; M[TFL_M_VZ] = vz as i64 466 M[TFL_M_NX] = nx as i64; M[TFL_M_NY] = ny as i64; M[TFL_M_NZ] = nz as i64 467 M[TFL_M_TA] = ta as i64; M[TFL_M_TB] = tb2 as i64; M[TFL_M_TC] = tc as i64 468 M[TFL_M_X0] = x0; M[TFL_M_X1] = x1; M[TFL_M_Y0] = y0; M[TFL_M_Y1] = y1; M[TFL_M_Z0] = z0; M[TFL_M_Z1] = z1 469 var edge: i64 = esum / nt 470 if edge < 1 { edge = 1 } 471 M[TFL_M_EDGE] = edge 472 M[TFL_M_RAW] = raw 473 M[TFL_M_FM] = 0 474 if zeroed > 0 { tfl_kv("TFL-MESH zero-normal-vertices=" as *u8, zeroed); tfl_puts(" (normal set to +z)\n" as *u8) } 475 return 1 476} 477// a copy of the mesh record with NEW position arrays (the skin shares topology and normals with the skull) 478func tfl_mesh_clone_positions(M: *i64) -> *i64 { 479 let S: *i64 = tfl_mesh_new() 480 var i: i64 = 0 481 while i < TFL_M_N { S[i] = M[i]; i = i + 1 } 482 let nv: i64 = M[TFL_M_NV] 483 let sx: *i64 = sys_mmap(nv * TFL_I64) as *i64 484 let sy: *i64 = sys_mmap(nv * TFL_I64) as *i64 485 let sz: *i64 = sys_mmap(nv * TFL_I64) as *i64 486 S[TFL_M_VX] = sx as i64; S[TFL_M_VY] = sy as i64; S[TFL_M_VZ] = sz as i64 487 S[TFL_M_FM] = 0 488 return S 489} 490func tfl_mesh_bbox_refresh(M: *i64) -> i64 { 491 let vx: *i64 = M[TFL_M_VX] as *i64; let vy: *i64 = M[TFL_M_VY] as *i64; let vz: *i64 = M[TFL_M_VZ] as *i64 492 var x0: i64 = TFL_FAR; var x1: i64 = 0 - TFL_FAR 493 var y0: i64 = TFL_FAR; var y1: i64 = 0 - TFL_FAR 494 var z0: i64 = TFL_FAR; var z1: i64 = 0 - TFL_FAR 495 var i: i64 = 0 496 while i < M[TFL_M_NV] { 497 if vx[i] < x0 { x0 = vx[i] } if vx[i] > x1 { x1 = vx[i] } 498 if vy[i] < y0 { y0 = vy[i] } if vy[i] > y1 { y1 = vy[i] } 499 if vz[i] < z0 { z0 = vz[i] } if vz[i] > z1 { z1 = vz[i] } 500 i = i + 1 501 } 502 M[TFL_M_X0] = x0; M[TFL_M_X1] = x1; M[TFL_M_Y0] = y0; M[TFL_M_Y1] = y1; M[TFL_M_Z0] = z0; M[TFL_M_Z1] = z1 503 return 0 504} 505// write the mesh as NXMSH2 (one layer, positions u10 -> float mm, normals /TFL_NQ, one colour); returns bytes or -1 506func tfl_mesh_write(M: *i64, path: *u8, col_r_permil: i64, col_g_permil: i64, col_b_permil: i64) -> i64 { 507 let nt: i64 = M[TFL_M_NT] 508 let nl: i64 = 1 509 let bytes: i64 = nm_file_bytes(nl, nt) + nt * 4 510 let b: *u8 = sys_mmap(bytes) 511 var i: i64 = 0 512 while i < bytes { b[i] = 0 as u8; i = i + 1 } 513 b[0] = 78 as u8; b[1] = 88 as u8; b[2] = 77 as u8; b[3] = 83 as u8; b[4] = 72 as u8; b[5] = 50 as u8 514 nm_put_u32(b, NM_OFF_NLAYERS, nl) 515 nm_put_u32(b, NM_OFF_NTRIS, nt) 516 let tb: i64 = nm_tri_base(b) 517 let vx: *i64 = M[TFL_M_VX] as *i64; let vy: *i64 = M[TFL_M_VY] as *i64; let vz: *i64 = M[TFL_M_VZ] as *i64 518 let nx: *i64 = M[TFL_M_NX] as *i64; let ny: *i64 = M[TFL_M_NY] as *i64; let nz: *i64 = M[TFL_M_NZ] as *i64 519 let ta: *i64 = M[TFL_M_TA] as *i64; let tb2: *i64 = M[TFL_M_TB] as *i64; let tc: *i64 = M[TFL_M_TC] as *i64 520 let xyz: *i64 = sys_mmap(9 * TFL_I64) as *i64 521 var t: i64 = 0 522 while t < nt { 523 let a: i64 = ta[t]; let c: i64 = tb2[t]; let d: i64 = tc[t] 524 xyz[0] = vx[a]; xyz[1] = vy[a]; xyz[2] = vz[a] 525 xyz[3] = vx[c]; xyz[4] = vy[c]; xyz[5] = vz[c] 526 xyz[6] = vx[d]; xyz[7] = vy[d]; xyz[8] = vz[d] 527 nm_put_tri(b, tb, t, xyz) 528 let o: i64 = tb + t * NM_TRI_REC + 36 529 nm_put_u32(b, o, vm_int_to_f32(nx[a], TFL_NQ)); nm_put_u32(b, o + 4, vm_int_to_f32(ny[a], TFL_NQ)); nm_put_u32(b, o + 8, vm_int_to_f32(nz[a], TFL_NQ)) 530 nm_put_u32(b, o + 12, vm_int_to_f32(nx[c], TFL_NQ)); nm_put_u32(b, o + 16, vm_int_to_f32(ny[c], TFL_NQ)); nm_put_u32(b, o + 20, vm_int_to_f32(nz[c], TFL_NQ)) 531 nm_put_u32(b, o + 24, vm_int_to_f32(nx[d], TFL_NQ)); nm_put_u32(b, o + 28, vm_int_to_f32(ny[d], TFL_NQ)); nm_put_u32(b, o + 32, vm_int_to_f32(nz[d], TFL_NQ)) 532 nm_col_put(b, tb, t, col_r_permil, col_g_permil, col_b_permil) 533 nm_put_u32(b, tb + nt * NM_TRI_REC + t * 4, 0) 534 t = t + 1 535 } 536 let fd: i64 = sys_openat_wr(path, TFL_MODE644) 537 if fd < 0 { return 0 - 1 } 538 var off: i64 = 0 539 var stuck: i64 = 0 540 while off < bytes { 541 if stuck == 1 { off = bytes } else { 542 let k: i64 = sys_write(fd, ((b as i64) + off) as *u8, bytes - off) 543 if k <= 0 { stuck = 1 } else { off = off + k } 544 } 545 } 546 sys_close(fd) 547 if stuck == 1 { return 0 - 1 } 548 return bytes 549} 550 551// TFL/NXMSH2 evaluation reducer. Cell size is an explicit caller policy; geometry, normals and topology are preserved 552// in the same record used by tfl_mesh_load/tfl_mesh_write. A zero/overflow/degenerate request refuses. 553const TFL_DECIM_MAX_CELLS: i64 = 6000000 554func tfl_mesh_decimate(M: *i64, cell: i64) -> *i64 { 555 if (M as i64) == 0 { return 0 as *i64 } 556 if cell <= 0 { return 0 as *i64 } 557 let x0: i64 = M[TFL_M_X0]; let x1: i64 = M[TFL_M_X1] 558 let y0: i64 = M[TFL_M_Y0]; let y1: i64 = M[TFL_M_Y1] 559 let z0: i64 = M[TFL_M_Z0]; let z1: i64 = M[TFL_M_Z1] 560 let nxg: i64 = (x1 - x0) / cell + 1 561 let nyg: i64 = (y1 - y0) / cell + 1 562 let nzg: i64 = (z1 - z0) / cell + 1 563 let nc: i64 = nxg * nyg * nzg 564 if nxg <= 0 { return 0 as *i64 } 565 if nyg <= 0 { return 0 as *i64 } 566 if nzg <= 0 { return 0 as *i64 } 567 if nc <= 0 { return 0 as *i64 } 568 if nc > TFL_DECIM_MAX_CELLS { return 0 as *i64 } 569 let map: *i64 = sys_mmap(nc * TFL_I64) as *i64 570 let sx: *i64 = sys_mmap(nc * TFL_I64) as *i64 571 let sy: *i64 = sys_mmap(nc * TFL_I64) as *i64 572 let sz: *i64 = sys_mmap(nc * TFL_I64) as *i64 573 let snx: *i64 = sys_mmap(nc * TFL_I64) as *i64 574 let sny: *i64 = sys_mmap(nc * TFL_I64) as *i64 575 let snz: *i64 = sys_mmap(nc * TFL_I64) as *i64 576 let cnt: *i64 = sys_mmap(nc * TFL_I64) as *i64 577 var i: i64 = 0 578 while i < nc { map[i] = 0 - 1; sx[i] = 0; sy[i] = 0; sz[i] = 0; snx[i] = 0; sny[i] = 0; snz[i] = 0; cnt[i] = 0; i = i + 1 } 579 let vx: *i64 = M[TFL_M_VX] as *i64; let vy: *i64 = M[TFL_M_VY] as *i64; let vz: *i64 = M[TFL_M_VZ] as *i64 580 let nnx: *i64 = M[TFL_M_NX] as *i64; let nny: *i64 = M[TFL_M_NY] as *i64; let nnz: *i64 = M[TFL_M_NZ] as *i64 581 var v: i64 = 0 582 while v < M[TFL_M_NV] { 583 let cx: i64 = (vx[v] - x0) / cell; let cy: i64 = (vy[v] - y0) / cell; let cz: i64 = (vz[v] - z0) / cell 584 let ci: i64 = cx + cy * nxg + cz * nxg * nyg 585 if ci >= 0 { if ci < nc { sx[ci] = sx[ci] + vx[v]; sy[ci] = sy[ci] + vy[v]; sz[ci] = sz[ci] + vz[v]; snx[ci] = snx[ci] + nnx[v]; sny[ci] = sny[ci] + nny[v]; snz[ci] = snz[ci] + nnz[v]; cnt[ci] = cnt[ci] + 1 } } 586 v = v + 1 587 } 588 var nv: i64 = 0 589 i = 0 590 while i < nc { if cnt[i] > 0 { map[i] = nv; nv = nv + 1 } i = i + 1 } 591 if nv < 3 { return 0 as *i64 } 592 let ta: *i64 = M[TFL_M_TA] as *i64; let tb: *i64 = M[TFL_M_TB] as *i64; let tc: *i64 = M[TFL_M_TC] as *i64 593 var nt: i64 = 0 594 var t: i64 = 0 595 while t < M[TFL_M_NT] { 596 let a: i64 = map[((vx[ta[t]] - x0) / cell) + ((vy[ta[t]] - y0) / cell) * nxg + ((vz[ta[t]] - z0) / cell) * nxg * nyg] 597 let b: i64 = map[((vx[tb[t]] - x0) / cell) + ((vy[tb[t]] - y0) / cell) * nxg + ((vz[tb[t]] - z0) / cell) * nxg * nyg] 598 let c: i64 = map[((vx[tc[t]] - x0) / cell) + ((vy[tc[t]] - y0) / cell) * nxg + ((vz[tc[t]] - z0) / cell) * nxg * nyg] 599 if a != b { if b != c { if a != c { nt = nt + 1 } } } 600 t = t + 1 601 } 602 if nt < 1 { return 0 as *i64 } 603 let O: *i64 = tfl_mesh_new() 604 let ovx: *i64 = sys_mmap(nv * TFL_I64) as *i64; let ovy: *i64 = sys_mmap(nv * TFL_I64) as *i64; let ovz: *i64 = sys_mmap(nv * TFL_I64) as *i64 605 let onx: *i64 = sys_mmap(nv * TFL_I64) as *i64; let ony: *i64 = sys_mmap(nv * TFL_I64) as *i64; let onz: *i64 = sys_mmap(nv * TFL_I64) as *i64 606 O[TFL_M_NV] = nv; O[TFL_M_NT] = nt; O[TFL_M_VX] = ovx as i64; O[TFL_M_VY] = ovy as i64; O[TFL_M_VZ] = ovz as i64; O[TFL_M_NX] = onx as i64; O[TFL_M_NY] = ony as i64; O[TFL_M_NZ] = onz as i64 607 i = 0 608 while i < nc { if cnt[i] > 0 { let q: i64 = map[i]; ovx[q] = sx[i] / cnt[i]; ovy[q] = sy[i] / cnt[i]; ovz[q] = sz[i] / cnt[i]; onx[q] = snx[i] / cnt[i]; ony[q] = sny[i] / cnt[i]; onz[q] = snz[i] / cnt[i] } i = i + 1 } 609 let ota: *i64 = sys_mmap(nt * TFL_I64) as *i64; let otb: *i64 = sys_mmap(nt * TFL_I64) as *i64; let otc: *i64 = sys_mmap(nt * TFL_I64) as *i64 610 O[TFL_M_TA] = ota as i64; O[TFL_M_TB] = otb as i64; O[TFL_M_TC] = otc as i64 611 var w: i64 = 0; t = 0 612 while t < M[TFL_M_NT] { 613 let a: i64 = map[((vx[ta[t]] - x0) / cell) + ((vy[ta[t]] - y0) / cell) * nxg + ((vz[ta[t]] - z0) / cell) * nxg * nyg] 614 let b: i64 = map[((vx[tb[t]] - x0) / cell) + ((vy[tb[t]] - y0) / cell) * nxg + ((vz[tb[t]] - z0) / cell) * nxg * nyg] 615 let c: i64 = map[((vx[tc[t]] - x0) / cell) + ((vy[tc[t]] - y0) / cell) * nxg + ((vz[tc[t]] - z0) / cell) * nxg * nyg] 616 if a != b { if b != c { if a != c { ota[w] = a; otb[w] = b; otc[w] = c; w = w + 1 } } } 617 t = t + 1 618 } 619 O[TFL_M_X0] = x0; O[TFL_M_X1] = x1; O[TFL_M_Y0] = y0; O[TFL_M_Y1] = y1; O[TFL_M_Z0] = z0; O[TFL_M_Z1] = z1; O[TFL_M_EDGE] = cell; O[TFL_M_RAW] = M[TFL_M_RAW]; O[TFL_M_FM] = 0 620 return O 621} 622 623// ==== the frontal depth map: per (x,y) cell of the mesh's own edge length, the most anterior z ==== 624func tfl_frontmap(M: *i64) -> i64 { 625 let cell: i64 = M[TFL_M_EDGE] 626 let w: i64 = (M[TFL_M_X1] - M[TFL_M_X0]) / cell + 2 627 let h: i64 = (M[TFL_M_Y1] - M[TFL_M_Y0]) / cell + 2 628 let fm: *i64 = sys_mmap(w * h * TFL_I64) as *i64 629 var i: i64 = 0 630 while i < w * h { fm[i] = TFL_ZNONE; i = i + 1 } 631 let vx: *i64 = M[TFL_M_VX] as *i64; let vy: *i64 = M[TFL_M_VY] as *i64; let vz: *i64 = M[TFL_M_VZ] as *i64 632 var v: i64 = 0 633 while v < M[TFL_M_NV] { 634 let cx: i64 = (vx[v] - M[TFL_M_X0]) / cell 635 let cy: i64 = (vy[v] - M[TFL_M_Y0]) / cell 636 let k: i64 = cy * w + cx 637 if vz[v] > fm[k] { fm[k] = vz[v] } 638 v = v + 1 639 } 640 M[TFL_M_FM] = fm as i64; M[TFL_M_FMW] = w; M[TFL_M_FMH] = h; M[TFL_M_FMCELL] = cell 641 return w * h 642} 643// the most anterior surface at (x,y), searching outward up to `reach` cells for the nearest filled cell; TFL_ZNONE if none 644func tfl_front_at(M: *i64, x: i64, y: i64, reach: i64) -> i64 { 645 if M[TFL_M_FM] == 0 { tfl_frontmap(M) } 646 let fm: *i64 = M[TFL_M_FM] as *i64 647 let w: i64 = M[TFL_M_FMW]; let h: i64 = M[TFL_M_FMH]; let cell: i64 = M[TFL_M_FMCELL] 648 let cx: i64 = (x - M[TFL_M_X0]) / cell 649 let cy: i64 = (y - M[TFL_M_Y0]) / cell 650 var r: i64 = 0 651 while r <= reach { 652 var best: i64 = TFL_ZNONE 653 var dy: i64 = 0 - r 654 while dy <= r { 655 var dx: i64 = 0 - r 656 while dx <= r { 657 let px: i64 = cx + dx; let py: i64 = cy + dy 658 if px >= 0 { if px < w { if py >= 0 { if py < h { 659 let z: i64 = fm[py * w + px] 660 if z > best { best = z } 661 } } } } 662 dx = dx + 1 663 } 664 dy = dy + 1 665 } 666 if best > TFL_ZNONE { return best } 667 r = r + 1 668 } 669 return TFL_ZNONE 670} 671 672// ==== landmarks located ON the skull ==== 673// the midline profile: per y band (band = mesh edge), the most anterior vertex within one edge of the bbox x centre. 674// prof[b] = z (TFL_ZNONE for a band with no midline surface), pidx[b] = that vertex. Returns the band count. 675func tfl_profile(M: *i64, prof: *i64, pidx: *i64, cap: i64) -> i64 { 676 let cell: i64 = M[TFL_M_EDGE] 677 var nb: i64 = (M[TFL_M_Y1] - M[TFL_M_Y0]) / cell + 1 678 if nb > cap { nb = cap } 679 var b: i64 = 0 680 while b < nb { prof[b] = TFL_ZNONE; pidx[b] = 0 - 1; b = b + 1 } 681 let xc: i64 = (M[TFL_M_X0] + M[TFL_M_X1]) / 2 682 let vx: *i64 = M[TFL_M_VX] as *i64; let vy: *i64 = M[TFL_M_VY] as *i64; let vz: *i64 = M[TFL_M_VZ] as *i64 683 var v: i64 = 0 684 while v < M[TFL_M_NV] { 685 if tfl_abs(vx[v] - xc) <= cell { 686 var k: i64 = (vy[v] - M[TFL_M_Y0]) / cell 687 if k >= nb { k = nb - 1 } 688 if vz[v] > prof[k] { prof[k] = vz[v]; pidx[k] = v } 689 } 690 v = v + 1 691 } 692 return nb 693} 694// the prominence a swing must beat: twice the median adjacent-band |dz| (nx_facemark's law), floored at one edge 695func tfl_noisefloor(prof: *i64, nb: i64, edge: i64) -> i64 { 696 let d: *i64 = sys_mmap((nb + 1) * TFL_I64) as *i64 697 var n: i64 = 0 698 var prev: i64 = TFL_ZNONE 699 var i: i64 = 0 700 while i < nb { 701 if prof[i] > TFL_ZNONE { 702 if prev > TFL_ZNONE { d[n] = tfl_abs(prof[i] - prev); n = n + 1 } 703 prev = prof[i] 704 } 705 i = i + 1 706 } 707 if n == 0 { return edge } 708 var a: i64 = 1 709 while a < n { 710 let key: i64 = d[a] 711 var b: i64 = a - 1 712 var go: i64 = 1 713 while go == 1 { if b < 0 { go = 0 } else { if d[b] > key { d[b + 1] = d[b]; b = b - 1 } else { go = 0 } } } 714 d[b + 1] = key 715 a = a + 1 716 } 717 var th: i64 = d[n / 2] * 2 718 if th < edge { th = edge } 719 return th 720} 721// extrema by prominence, walking from the TOP band (high y) down. ex[k] = band, ty[k] = 1 max / 0 min. Returns the count. 722func tfl_extrema(prof: *i64, nb: i64, swing: i64, ex: *i64, ty: *i64, cap: i64) -> i64 { 723 var n: i64 = 0 724 var lastV: i64 = 0 725 var dir: i64 = 0 726 var pI: i64 = 0 - 1 727 var pV: i64 = 0 728 var i: i64 = nb - 1 729 while i >= 0 { 730 let v: i64 = prof[i] 731 if v > TFL_ZNONE { 732 if pI < 0 { pI = i; pV = v; lastV = v } else { 733 var d: i64 = 0 734 if v > pV { d = 1 } 735 if v < pV { d = 0 - 1 } 736 if d != 0 { 737 if dir == 0 { dir = d } else { 738 if d != dir { 739 if tfl_abs(pV - lastV) >= swing { 740 if n < cap { ex[n] = pI; if dir > 0 { ty[n] = 1 } else { ty[n] = 0 } n = n + 1; lastV = pV } 741 } 742 dir = d 743 } 744 } 745 } 746 pI = i; pV = v 747 } 748 } 749 i = i - 1 750 } 751 return n 752} 753// argmax of dx*x + dy*y + dz*z over vertices with y in [ylo,yhi], z >= zlo, and x on the given side (1 +x, -1 -x, 0 any) 754func tfl_support(M: *i64, dx: i64, dy: i64, dz: i64, ylo: i64, yhi: i64, zlo: i64, xside: i64) -> i64 { 755 let vx: *i64 = M[TFL_M_VX] as *i64; let vy: *i64 = M[TFL_M_VY] as *i64; let vz: *i64 = M[TFL_M_VZ] as *i64 756 let xc: i64 = (M[TFL_M_X0] + M[TFL_M_X1]) / 2 757 var best: i64 = 0 - 1 758 var bs: i64 = 0 - TFL_FAR 759 var v: i64 = 0 760 while v < M[TFL_M_NV] { 761 var ok: i64 = 1 762 if vy[v] < ylo { ok = 0 } 763 if vy[v] > yhi { ok = 0 } 764 if vz[v] < zlo { ok = 0 } 765 if xside > 0 { if vx[v] <= xc { ok = 0 } } 766 if xside < 0 { if vx[v] >= xc { ok = 0 } } 767 if ok == 1 { 768 let s: i64 = dx * vx[v] + dy * vy[v] + dz * vz[v] 769 if s > bs { bs = s; best = v } 770 } 771 v = v + 1 772 } 773 return best 774} 775// tfl_support restricted to the lateral band |x - centre| >= xmin (the ramus and the arch live off the midline) 776func tfl_support_lat(M: *i64, dx: i64, dy: i64, dz: i64, ylo: i64, yhi: i64, zlo: i64, xside: i64, xmin: i64) -> i64 { 777 let vx: *i64 = M[TFL_M_VX] as *i64; let vy: *i64 = M[TFL_M_VY] as *i64; let vz: *i64 = M[TFL_M_VZ] as *i64 778 let xc: i64 = (M[TFL_M_X0] + M[TFL_M_X1]) / 2 779 var best: i64 = 0 - 1 780 var bs: i64 = 0 - TFL_FAR 781 var v: i64 = 0 782 while v < M[TFL_M_NV] { 783 var ok: i64 = 1 784 if vy[v] < ylo { ok = 0 } 785 if vy[v] > yhi { ok = 0 } 786 if vz[v] < zlo { ok = 0 } 787 if xside > 0 { if vx[v] - xc < xmin { ok = 0 } } 788 if xside < 0 { if xc - vx[v] < xmin { ok = 0 } } 789 if ok == 1 { 790 let s: i64 = dx * vx[v] + dy * vy[v] + dz * vz[v] 791 if s > bs { bs = s; best = v } 792 } 793 v = v + 1 794 } 795 return best 796} 797// the rim crest: walking from (x,y) in direction (dx,dy) from half to one and a half of `reach`, the most anterior front-map 798// point; out[0..2] = its x, y, z (z = TFL_ZNONE when the whole walk is empty) 799func tfl_crest(M: *i64, x: i64, y: i64, dx: i64, dy: i64, reach: i64, out: *i64) -> i64 { 800 if M[TFL_M_FM] == 0 { tfl_frontmap(M) } 801 let step: i64 = tfl_max(M[TFL_M_FMCELL] / 2, 1) 802 var best: i64 = TFL_ZNONE 803 out[0] = x + dx * reach; out[1] = y + dy * reach; out[2] = TFL_ZNONE 804 var r: i64 = reach / 2 805 while r <= reach + reach / 2 { 806 let px: i64 = x + dx * r 807 let py: i64 = y + dy * r 808 let z: i64 = tfl_front_at(M, px, py, 0) 809 if z > best { best = z; out[0] = px; out[1] = py; out[2] = z } 810 r = r + step 811 } 812 return best 813} 814// the vertex nearest a point; out[0] = index, out[1] = distance (u10) 815func tfl_nearest(M: *i64, x: i64, y: i64, z: i64, out: *i64) -> i64 { 816 let vx: *i64 = M[TFL_M_VX] as *i64; let vy: *i64 = M[TFL_M_VY] as *i64; let vz: *i64 = M[TFL_M_VZ] as *i64 817 var best: i64 = 0 - 1 818 var bd: i64 = TFL_FAR 819 var v: i64 = 0 820 while v < M[TFL_M_NV] { 821 let dx: i64 = vx[v] - x; let dy: i64 = vy[v] - y; let dz: i64 = vz[v] - z 822 let d2: i64 = dx * dx + dy * dy + dz * dz 823 if d2 < bd { bd = d2; best = v } 824 v = v + 1 825 } 826 out[0] = best 827 out[1] = vm_isqrt(bd) 828 return best 829} 830// set a row's located point (by name); state 1 located, 2 fallback. Silent when the conf carries no such row. 831func tfl_place(T: *i64, name: *u8, x: i64, y: i64, z: i64, state: i64) -> i64 { 832 let i: i64 = tfl_row_find(T, name) 833 if i < 0 { return 0 } 834 let r: *i64 = tfl_row(T, i) 835 r[TFL_R_X] = x; r[TFL_R_Y] = y; r[TFL_R_Z] = z; r[TFL_R_STATE] = state 836 return 1 837} 838func tfl_place_v(T: *i64, name: *u8, M: *i64, v: i64, state: i64) -> i64 { 839 if v < 0 { return 0 } 840 let vx: *i64 = M[TFL_M_VX] as *i64; let vy: *i64 = M[TFL_M_VY] as *i64; let vz: *i64 = M[TFL_M_VZ] as *i64 841 return tfl_place(T, name, vx[v], vy[v], vz[v], state) 842} 843func tfl_get(T: *i64, name: *u8, out3: *i64) -> i64 { 844 let i: i64 = tfl_row_find(T, name) 845 if i < 0 { return 0 } 846 let r: *i64 = tfl_row(T, i) 847 if r[TFL_R_STATE] == TFL_ST_NONE { return 0 } 848 out3[0] = r[TFL_R_X]; out3[1] = r[TFL_R_Y]; out3[2] = r[TFL_R_Z] 849 return 1 850} 851// the landmark set. Every location is a geometric definition on the skull (a profile extremum, a support direction, a canon 852// ratio between two located bone points); fallbacks are NAMED (state 2). Returns the count located. 853func tfl_locate(M: *i64, T: *i64, K: *i64) -> i64 { 854 let edge: i64 = M[TFL_M_EDGE] 855 let cap: i64 = (M[TFL_M_Y1] - M[TFL_M_Y0]) / edge + 2 856 let prof: *i64 = sys_mmap(cap * TFL_I64) as *i64 857 let pidx: *i64 = sys_mmap(cap * TFL_I64) as *i64 858 let nb: i64 = tfl_profile(M, prof, pidx, cap) 859 let swing: i64 = tfl_noisefloor(prof, nb, edge) 860 let ex: *i64 = sys_mmap(cap * TFL_I64) as *i64 861 let ty: *i64 = sys_mmap(cap * TFL_I64) as *i64 862 let ne: i64 = tfl_extrema(prof, nb, swing, ex, ty, cap) 863 let vx: *i64 = M[TFL_M_VX] as *i64; let vy: *i64 = M[TFL_M_VY] as *i64; let vz: *i64 = M[TFL_M_VZ] as *i64 864 tfl_kv("TFL-PROFILE bands=" as *u8, nb); tfl_kv(" swing=" as *u8, swing); tfl_kv(" extrema=" as *u8, ne); tfl_puts("\n" as *u8) 865 // top and bottom bands with surface 866 var top: i64 = nb - 1 867 while top > 0 { if prof[top] > TFL_ZNONE { top = 0 - top } else { top = top - 1 } } 868 if top < 0 { top = 0 - top } 869 var bot: i64 = 0 870 while bot < nb - 1 { if prof[bot] > TFL_ZNONE { bot = bot + nb } else { bot = bot + 1 } } 871 if bot >= nb { bot = bot - nb } 872 if ne < 2 { tfl_puts("TFL-LOCATE REFUSED: fewer than two profile extrema -- not a skull profile\n" as *u8); return 0 } 873 // the nasal aperture: the deepest minimum between the first and the last maximum 874 var ap: i64 = 0 - 1 875 var apz: i64 = TFL_FAR 876 var k: i64 = 0 877 while k < ne { if ty[k] == 0 { if prof[ex[k]] < apz { apz = prof[ex[k]]; ap = k } } k = k + 1 } 878 if ap < 0 { tfl_puts("TFL-LOCATE REFUSED: no minimum on the midline profile\n" as *u8); return 0 } 879 // nasion: the minimum just above the aperture (state 1) else a quarter of the glabella->aperture descent (state 2) 880 var nas: i64 = 0 - 1 881 var gla: i64 = 0 - 1 882 var rhi: i64 = 0 - 1 883 k = ap - 1 884 while k >= 0 { if nas < 0 { if ty[k] == 0 { nas = k } } if gla < 0 { if ty[k] == 1 { if nas >= 0 { gla = k } } } k = k - 1 } 885 var glab: i64 = 0 - 1 886 var nasb: i64 = 0 - 1 887 var nasst: i64 = TFL_ST_LOCATED 888 var glast: i64 = TFL_ST_LOCATED 889 if nas >= 0 { nasb = ex[nas]; if gla >= 0 { glab = ex[gla] } } 890 if nas < 0 { 891 // no separate nasion minimum: glabella = the first maximum above the aperture, nasion a quarter of the way down 892 k = ap - 1 893 while k >= 0 { if gla < 0 { if ty[k] == 1 { gla = k } } k = k - 1 } 894 if gla >= 0 { glab = ex[gla] } else { glab = top; glast = TFL_ST_FALLBACK } 895 nasb = glab - (glab - ex[ap]) / 4 896 nasst = TFL_ST_FALLBACK 897 } 898 if glab < 0 { glab = top; glast = TFL_ST_FALLBACK } 899 // rhinion: a maximum between the nasion and the aperture, else the midpoint of the descent (named fallback) 900 var rhib: i64 = 0 - 1 901 var rhist: i64 = TFL_ST_LOCATED 902 k = 0 903 while k < ne { if ty[k] == 1 { if ex[k] < nasb { if ex[k] > ex[ap] { rhib = ex[k] } } } k = k + 1 } 904 if rhib < 0 { rhib = nasb - (nasb - ex[ap]) / 2; rhist = TFL_ST_FALLBACK } 905 // below the aperture: the first maximum = prosthion (the alveolar front); nasospinale = the aperture's lower rim 906 var pro: i64 = 0 - 1 907 k = ap + 1 908 while k < ne { if pro < 0 { if ty[k] == 1 { pro = k } } k = k + 1 } 909 var prob: i64 = 0 - 1 910 var prost: i64 = TFL_ST_LOCATED 911 if pro >= 0 { prob = ex[pro] } else { prob = ex[ap] - (ex[ap] - bot) / 3; prost = TFL_ST_FALLBACK } 912 var nsb: i64 = ex[ap] - 1 913 var going: i64 = 1 914 while going == 1 { if nsb <= prob { going = 0 } else { if prof[nsb] > TFL_ZNONE { if prof[nsb] >= prof[prob] - swing { going = 0 } } if going == 1 { nsb = nsb - 1 } } } 915 // pogonion: the last maximum below the prosthion, else the most anterior band of the lower half below it (fallback) 916 var pog: i64 = 0 - 1 917 k = ne - 1 918 while k >= 0 { if pog < 0 { if ty[k] == 1 { if ex[k] < prob { pog = k } } } k = k - 1 } 919 var pogb: i64 = 0 - 1 920 var pogst: i64 = TFL_ST_LOCATED 921 if pog >= 0 { pogb = ex[pog] } else { 922 var bz: i64 = TFL_ZNONE 923 var bb: i64 = bot 924 while bb < prob - (prob - bot) / 2 { if prof[bb] > bz { bz = prof[bb]; pogb = bb } bb = bb + 1 } 925 pogst = TFL_ST_FALLBACK 926 if pogb < 0 { pogb = bot } 927 } 928 // supramentale: the minimum between the prosthion and the pogonion, else their midpoint (fallback) 929 var supb: i64 = 0 - 1 930 var supst: i64 = TFL_ST_LOCATED 931 k = 0 932 while k < ne { if ty[k] == 0 { if ex[k] < prob { if ex[k] > pogb { supb = ex[k] } } } k = k + 1 } 933 if supb < 0 { supb = pogb + (prob - pogb) / 2; supst = TFL_ST_FALLBACK } 934 // midline placements 935 tfl_place_v(T, "vertex" as *u8, M, pidx[top], TFL_ST_LOCATED) 936 tfl_place_v(T, "gnathion" as *u8, M, pidx[bot], TFL_ST_LOCATED) 937 tfl_place_v(T, "glabella" as *u8, M, pidx[glab], glast) 938 tfl_place_v(T, "nasion" as *u8, M, pidx[nasb], nasst) 939 tfl_place_v(T, "rhinion" as *u8, M, pidx[rhib], rhist) 940 tfl_place_v(T, "aperture_floor" as *u8, M, pidx[ex[ap]], TFL_ST_LOCATED) 941 tfl_place_v(T, "nasospinale" as *u8, M, pidx[nsb], TFL_ST_LOCATED) 942 tfl_place_v(T, "prosthion" as *u8, M, pidx[prob], prost) 943 tfl_place_v(T, "supramentale" as *u8, M, pidx[supb], supst) 944 tfl_place_v(T, "pogonion" as *u8, M, pidx[pogb], pogst) 945 let g: *i64 = sys_mmap(3 * TFL_I64) as *i64 946 let n3: *i64 = sys_mmap(3 * TFL_I64) as *i64 947 let ns: *i64 = sys_mmap(3 * TFL_I64) as *i64 948 let gn: *i64 = sys_mmap(3 * TFL_I64) as *i64 949 let vt: *i64 = sys_mmap(3 * TFL_I64) as *i64 950 let pg: *i64 = sys_mmap(3 * TFL_I64) as *i64 951 tfl_get(T, "glabella" as *u8, g); tfl_get(T, "nasion" as *u8, n3); tfl_get(T, "nasospinale" as *u8, ns) 952 tfl_get(T, "gnathion" as *u8, gn); tfl_get(T, "vertex" as *u8, vt); tfl_get(T, "pogonion" as *u8, pg) 953 // zygion: the most lateral point between the aperture rim and the nasion, in the anterior half of the skull 954 let zc: i64 = (M[TFL_M_Z0] + M[TFL_M_Z1]) / 2 955 let zyl: i64 = tfl_support(M, 1, 0, 0, ns[1], n3[1], zc, 1) 956 let zyr: i64 = tfl_support(M, 0 - 1, 0, 0, ns[1], n3[1], zc, 0 - 1) 957 tfl_place_v(T, "zygion_l" as *u8, M, zyl, TFL_ST_LOCATED) 958 tfl_place_v(T, "zygion_r" as *u8, M, zyr, TFL_ST_LOCATED) 959 let zl: *i64 = sys_mmap(3 * TFL_I64) as *i64 960 tfl_get(T, "zygion_l" as *u8, zl) 961 let xc: i64 = (M[TFL_M_X0] + M[TFL_M_X1]) / 2 962 let halfzy: i64 = tfl_abs(zl[0] - xc) 963 // THE CANON SUBNASALE: the aperture the skull carries is a named hole (skullfit nasal n_ours=0 n_oracle=0), so the 964 // nasal base is DERIVED from the canon thirds instead -- glabella-to-subnasale equals subnasale-to-menton (facecanon 965 // vthird_mid = vthird_lower) -- and the offset between the two is printed as the hole's size 966 let sny: i64 = (g[1] + gn[1]) / 2 967 tfl_place(T, "subnasale_canon" as *u8, xc, sny, tfl_front_at(M, xc, sny, 3), TFL_ST_LOCATED) 968 tfl_kv("TFL-HOLE aperture_rim_y=" as *u8, ns[1]); tfl_kv(" canon_subnasale_y=" as *u8, sny); tfl_kv(" offset_u10=" as *u8, ns[1] - sny) 969 tfl_puts(" (the skull's aperture rim against the canon's nasal base; the nose and mouth stations use the canon)\n" as *u8) 970 let sn: *i64 = sys_mmap(3 * TFL_I64) as *i64 971 tfl_get(T, "subnasale_canon" as *u8, sn) 972 // gonion: the mandibular angle -- the most inferior-posterior point (support in (0,-1,-1)) of the LATERAL lower face: 973 // at least half a zygion half-width off the midline, below the nasal base, no further back than one half-width behind the 974 // zygion (the ramus hangs under the arch; the occiput is excluded by that bound) 975 let gol: i64 = tfl_support_lat(M, 0, 0 - 1, 0 - 1, M[TFL_M_Y0], sny, zl[2] - halfzy, 1, halfzy / 2) 976 let gor: i64 = tfl_support_lat(M, 0, 0 - 1, 0 - 1, M[TFL_M_Y0], sny, zl[2] - halfzy, 0 - 1, halfzy / 2) 977 tfl_place_v(T, "gonion_l" as *u8, M, gol, TFL_ST_LOCATED) 978 tfl_place_v(T, "gonion_r" as *u8, M, gor, TFL_ST_LOCATED) 979 // the skull's own prognathism, printed: how far the alveolar front and the chin stand ahead of the brow 980 let pr: *i64 = sys_mmap(3 * TFL_I64) as *i64 981 tfl_get(T, "prosthion" as *u8, pr) 982 tfl_kv("TFL-SKULL prosthion_minus_glabella_z=" as *u8, pr[2] - g[2]); tfl_kv(" pogonion_minus_glabella_z=" as *u8, pg[2] - g[2]) 983 tfl_kv(" vertex_minus_glabella_z=" as *u8, vt[2] - g[2]); tfl_puts(" (u10; the generated skull's own geometry, not this layer's)\n" as *u8) 984 // the eye centres: pupil span = pupil_span_permil of the bizygomatic (facecanon interocular_over_width), eye line at 985 // eye_line_permil of the glabella->subnasale drop (nx_faceanat frame), depth read from the rim later (patches) 986 let pspan: i64 = tfl_patch(T, "pupil_span_permil" as *u8) * (2 * halfzy) / TFL_PERMIL 987 let eyey: i64 = g[1] - tfl_patch(T, "eye_line_permil" as *u8) * (g[1] - sny) / TFL_PERMIL 988 let exl: i64 = xc + pspan / 2 989 let exr: i64 = xc - pspan / 2 990 let reach: i64 = 3 991 let zel: i64 = tfl_front_at(M, exl, eyey, reach) 992 let zer: i64 = tfl_front_at(M, exr, eyey, reach) 993 tfl_place(T, "eye_l" as *u8, exl, eyey, zel, TFL_ST_LOCATED) 994 tfl_place(T, "eye_r" as *u8, exr, eyey, zer, TFL_ST_LOCATED) 995 // orbit stations = the RIM CRESTS: the most anterior front-map point along the eye's column (supraorbital above, 996 // infraorbital below) and its row (ectoconchion outward), searched from half to one and a half lid semi-axes out -- 997 // a single cell on a 2 mm mesh can land inside the socket hole, a crest cannot 998 let flen: i64 = tfl_patch(T, "fissure_len_permil" as *u8) * (2 * halfzy) / TFL_PERMIL 999 let semx: i64 = flen * tfl_patch(T, "lid_semi_x_permil_of_fissure" as *u8) / TFL_PERMIL 1000 let semy: i64 = semx * tfl_patch(T, "lid_semi_y_permil_of_semi_x" as *u8) / TFL_PERMIL 1001 let cr: *i64 = sys_mmap(3 * TFL_I64) as *i64 1002 tfl_crest(M, exl, eyey, 0, 1, semy, cr); tfl_place(T, "supraorbital_l" as *u8, cr[0], cr[1], cr[2], TFL_ST_LOCATED) 1003 tfl_crest(M, exr, eyey, 0, 1, semy, cr); tfl_place(T, "supraorbital_r" as *u8, cr[0], cr[1], cr[2], TFL_ST_LOCATED) 1004 tfl_crest(M, exl, eyey, 0, 0 - 1, semy, cr); tfl_place(T, "infraorbital_l" as *u8, cr[0], cr[1], cr[2], TFL_ST_LOCATED) 1005 tfl_crest(M, exr, eyey, 0, 0 - 1, semy, cr); tfl_place(T, "infraorbital_r" as *u8, cr[0], cr[1], cr[2], TFL_ST_LOCATED) 1006 tfl_crest(M, exl, eyey, 1, 0, semx, cr); tfl_place(T, "ectoconchion_l" as *u8, cr[0], cr[1], cr[2], TFL_ST_LOCATED) 1007 tfl_crest(M, exr, eyey, 0 - 1, 0, semx, cr); tfl_place(T, "ectoconchion_r" as *u8, cr[0], cr[1], cr[2], TFL_ST_LOCATED) 1008 // frontal eminence: a third of the way from the glabella to the vertex, at the eye's column, on the front surface 1009 let fey: i64 = g[1] + (vt[1] - g[1]) / 3 1010 tfl_place(T, "frontal_eminence_l" as *u8, exl, fey, tfl_front_at(M, exl, fey, reach), TFL_ST_LOCATED) 1011 tfl_place(T, "frontal_eminence_r" as *u8, exr, fey, tfl_front_at(M, exr, fey, reach), TFL_ST_LOCATED) 1012 // temple: between the ectoconchion and the zygion, at the glabella's height, halfway back to the zygion's depth 1013 let ecl: *i64 = sys_mmap(3 * TFL_I64) as *i64 1014 tfl_get(T, "ectoconchion_l" as *u8, ecl) 1015 let tx: i64 = ecl[0] + (zl[0] - ecl[0]) / 2 1016 let tz: i64 = ecl[2] - (ecl[2] - zl[2]) / 2 1017 tfl_place(T, "temple_l" as *u8, tx, g[1], tz, TFL_ST_LOCATED) 1018 tfl_place(T, "temple_r" as *u8, 2 * xc - tx, g[1], tz, TFL_ST_LOCATED) 1019 // the mouth stations on the midline: stomion at stomion_permil of the canon subnasale->gnathion span (facecanon 1020 // lower_split_upper), labrale superius/inferius one vermilion height above/below, mid-philtrum halfway up to the nose 1021 let stoy: i64 = sny - tfl_patch(T, "stomion_permil" as *u8) * (sny - gn[1]) / TFL_PERMIL 1022 let lsy: i64 = stoy + tfl_patch(T, "upper_vermilion_mm10" as *u8) 1023 let liy: i64 = stoy - tfl_patch(T, "lower_vermilion_mm10" as *u8) 1024 let mpy: i64 = lsy + (sny - lsy) / 2 1025 tfl_place(T, "stomion" as *u8, xc, stoy, tfl_front_at(M, xc, stoy, reach), TFL_ST_LOCATED) 1026 tfl_place(T, "labrale_superius" as *u8, xc, lsy, tfl_front_at(M, xc, lsy, reach), TFL_ST_LOCATED) 1027 tfl_place(T, "labrale_inferius" as *u8, xc, liy, tfl_front_at(M, xc, liy, reach), TFL_ST_LOCATED) 1028 tfl_place(T, "mid_philtrum" as *u8, xc, mpy, tfl_front_at(M, xc, mpy, reach), TFL_ST_LOCATED) 1029 // anchor every located row to its nearest skull vertex; count and print 1030 let o2: *i64 = sys_mmap(2 * TFL_I64) as *i64 1031 var located: i64 = 0 1032 var fallback: i64 = 0 1033 var unlocated: i64 = 0 1034 var amax: i64 = 0 1035 var voters: i64 = 0 1036 var i: i64 = 0 1037 while i < T[TFL_T_NROWS] { 1038 let r: *i64 = tfl_row(T, i) 1039 if r[TFL_R_STATE] == TFL_ST_NONE { unlocated = unlocated + 1 } else { 1040 tfl_nearest(M, r[TFL_R_X], r[TFL_R_Y], r[TFL_R_Z], o2) 1041 r[TFL_R_AIDX] = o2[0]; r[TFL_R_ADIST] = o2[1] 1042 r[TFL_R_AX] = vx[o2[0]]; r[TFL_R_AY] = vy[o2[0]]; r[TFL_R_AZ] = vz[o2[0]] 1043 if o2[1] > amax { amax = o2[1] } 1044 if r[TFL_R_STATE] == TFL_ST_FALLBACK { fallback = fallback + 1 } else { located = located + 1 } 1045 if r[TFL_R_DEPTH] >= 0 { voters = voters + 1 } 1046 } 1047 i = i + 1 1048 } 1049 K[TFL_K_LOCATED] = located; K[TFL_K_FALLBACK] = fallback; K[TFL_K_UNLOCATED] = unlocated; K[TFL_K_ANCHOR_MAX] = amax; K[TFL_K_VOTERS] = voters 1050 return located + fallback 1051} 1052// print every row: name, located point, anchor distance, depth, state, source 1053func tfl_print_rows(T: *i64) -> i64 { 1054 var i: i64 = 0 1055 while i < T[TFL_T_NROWS] { 1056 let r: *i64 = tfl_row(T, i) 1057 tfl_puts("TFL-LANDMARK " as *u8); tfl_puts(r[TFL_R_NAME] as *u8) 1058 if r[TFL_R_STATE] == TFL_ST_NONE { tfl_puts(" UNLOCATED" as *u8) } else { 1059 tfl_kv(" x=" as *u8, r[TFL_R_X]); tfl_kv(" y=" as *u8, r[TFL_R_Y]); tfl_kv(" z=" as *u8, r[TFL_R_Z]) 1060 tfl_kv(" anchor_dist=" as *u8, r[TFL_R_ADIST]) 1061 if r[TFL_R_STATE] == TFL_ST_FALLBACK { tfl_puts(" FALLBACK" as *u8) } 1062 } 1063 tfl_kv(" depth_mm10=" as *u8, r[TFL_R_DEPTH]); tfl_puts(" source=" as *u8); tfl_puts(r[TFL_R_SRC] as *u8) 1064 tfl_puts("\n" as *u8) 1065 i = i + 1 1066 } 1067 return 0 1068} 1069 1070// ==== the depth field ==== 1071// kernel width: the median over voting landmarks of the distance to the nearest OTHER voting landmark (u10) 1072func tfl_sigma(T: *i64) -> i64 { 1073 let n: i64 = T[TFL_T_NROWS] 1074 let d: *i64 = sys_mmap((n + 1) * TFL_I64) as *i64 1075 var m: i64 = 0 1076 var i: i64 = 0 1077 while i < n { 1078 let r: *i64 = tfl_row(T, i) 1079 if r[TFL_R_STATE] != TFL_ST_NONE { if r[TFL_R_DEPTH] >= 0 { 1080 var bd: i64 = TFL_FAR 1081 var j: i64 = 0 1082 while j < n { 1083 if j != i { 1084 let q: *i64 = tfl_row(T, j) 1085 if q[TFL_R_STATE] != TFL_ST_NONE { if q[TFL_R_DEPTH] >= 0 { 1086 let dx: i64 = r[TFL_R_AX] - q[TFL_R_AX]; let dy: i64 = r[TFL_R_AY] - q[TFL_R_AY]; let dz: i64 = r[TFL_R_AZ] - q[TFL_R_AZ] 1087 let d2: i64 = dx * dx + dy * dy + dz * dz 1088 if d2 < bd { bd = d2 } 1089 } } 1090 } 1091 j = j + 1 1092 } 1093 if bd < TFL_FAR { d[m] = vm_isqrt(bd); m = m + 1 } 1094 } } 1095 i = i + 1 1096 } 1097 if m == 0 { return 0 } 1098 var a: i64 = 1 1099 while a < m { 1100 let key: i64 = d[a] 1101 var b: i64 = a - 1 1102 var go: i64 = 1 1103 while go == 1 { if b < 0 { go = 0 } else { if d[b] > key { d[b + 1] = d[b]; b = b - 1 } else { go = 0 } } } 1104 d[b + 1] = key 1105 a = a + 1 1106 } 1107 return d[m / 2] 1108} 1109// the median of the voting depths (the prior a far vertex falls back to) 1110func tfl_depth_median(T: *i64) -> i64 { 1111 let n: i64 = T[TFL_T_NROWS] 1112 let d: *i64 = sys_mmap((n + 1) * TFL_I64) as *i64 1113 var m: i64 = 0 1114 var i: i64 = 0 1115 while i < n { let r: *i64 = tfl_row(T, i); if r[TFL_R_STATE] != TFL_ST_NONE { if r[TFL_R_DEPTH] >= 0 { d[m] = r[TFL_R_DEPTH]; m = m + 1 } } i = i + 1 } 1116 if m == 0 { return 0 } 1117 var a: i64 = 1 1118 while a < m { 1119 let key: i64 = d[a] 1120 var b: i64 = a - 1 1121 var go: i64 = 1 1122 while go == 1 { if b < 0 { go = 0 } else { if d[b] > key { d[b + 1] = d[b]; b = b - 1 } else { go = 0 } } } 1123 d[b + 1] = key 1124 a = a + 1 1125 } 1126 return d[m / 2] 1127} 1128// the fat compartments: centres and radii DERIVED from located landmarks; magnitude is the conf row (controllable). 1129// Each fat row gets X,Y,Z = centre and ADIST = radius (u10). Unknown compartment names are announced and skipped. 1130func tfl_fat_place(T: *i64) -> i64 { 1131 let zl: *i64 = sys_mmap(3 * TFL_I64) as *i64 1132 let zr: *i64 = sys_mmap(3 * TFL_I64) as *i64 1133 let ns: *i64 = sys_mmap(3 * TFL_I64) as *i64 1134 let st: *i64 = sys_mmap(3 * TFL_I64) as *i64 1135 let gl: *i64 = sys_mmap(3 * TFL_I64) as *i64 1136 let gr: *i64 = sys_mmap(3 * TFL_I64) as *i64 1137 let pg: *i64 = sys_mmap(3 * TFL_I64) as *i64 1138 let el: *i64 = sys_mmap(3 * TFL_I64) as *i64 1139 let er: *i64 = sys_mmap(3 * TFL_I64) as *i64 1140 var ok: i64 = 1 1141 if tfl_get(T, "zygion_l" as *u8, zl) == 0 { ok = 0 } 1142 if tfl_get(T, "zygion_r" as *u8, zr) == 0 { ok = 0 } 1143 if tfl_get(T, "subnasale_canon" as *u8, ns) == 0 { ok = 0 } 1144 if tfl_get(T, "stomion" as *u8, st) == 0 { ok = 0 } 1145 if tfl_get(T, "gonion_l" as *u8, gl) == 0 { ok = 0 } 1146 if tfl_get(T, "gonion_r" as *u8, gr) == 0 { ok = 0 } 1147 if tfl_get(T, "pogonion" as *u8, pg) == 0 { ok = 0 } 1148 if tfl_get(T, "eye_l" as *u8, el) == 0 { ok = 0 } 1149 if tfl_get(T, "eye_r" as *u8, er) == 0 { ok = 0 } 1150 if ok == 0 { tfl_puts("TFL-FAT REFUSED: a compartment anchor landmark is unlocated\n" as *u8); return 0 } 1151 var placed: i64 = 0 1152 var i: i64 = 0 1153 while i < T[TFL_T_NFAT] { 1154 let r: *i64 = tfl_fatrow(T, i) 1155 let nm: *u8 = r[TFL_R_NAME] as *u8 1156 var have: i64 = 1 1157 var cx: i64 = 0; var cy: i64 = 0; var cz: i64 = 0; var rad: i64 = 0 1158 var side: i64 = 0 1159 if tfl_has(nm, "_l" as *u8) == 1 { side = 1 } 1160 if tfl_has(nm, "_r" as *u8) == 1 { side = 0 - 1 } 1161 var zy: *i64 = zl; var go: *i64 = gl; var ey: *i64 = el 1162 if side < 0 { zy = zr; go = gr; ey = er } 1163 if tfl_has(nm, "malar" as *u8) == 1 { 1164 // the malar pad hangs from the cheekbone toward the nasal base: a third of the way, radius a third of the span 1165 cx = zy[0] + (ns[0] - zy[0]) / 3; cy = zy[1] + (ns[1] - zy[1]) / 3; cz = zy[2] + (ns[2] - zy[2]) / 3 1166 let dx: i64 = zy[0] - ns[0]; let dy: i64 = zy[1] - ns[1]; let dz: i64 = zy[2] - ns[2] 1167 rad = vm_isqrt(dx * dx + dy * dy + dz * dz) / 3 1168 } else { if tfl_has(nm, "nasolabial" as *u8) == 1 { 1169 // beside the philtrum, between the nasal base and the stomion, a lip-reach out from the midline 1170 let half: i64 = tfl_abs(ey[0] - ns[0]) / 2 1171 cx = ns[0] + side * half; cy = (ns[1] + st[1]) / 2; cz = (ns[2] + st[2]) / 2 1172 rad = (ns[1] - st[1]) 1173 if rad < 0 { rad = 0 - rad } 1174 } else { if tfl_has(nm, "jowl" as *u8) == 1 { 1175 // two thirds of the way from the mandibular angle to the chin, radius a third of that span 1176 cx = go[0] + (pg[0] - go[0]) * 2 / 3; cy = go[1] + (pg[1] - go[1]) * 2 / 3; cz = go[2] + (pg[2] - go[2]) * 2 / 3 1177 let dx: i64 = pg[0] - go[0]; let dy: i64 = pg[1] - go[1]; let dz: i64 = pg[2] - go[2] 1178 rad = vm_isqrt(dx * dx + dy * dy + dz * dz) / 3 1179 } else { have = 0 } } } 1180 if have == 1 { r[TFL_R_X] = cx; r[TFL_R_Y] = cy; r[TFL_R_Z] = cz; r[TFL_R_ADIST] = rad; r[TFL_R_STATE] = TFL_ST_LOCATED; placed = placed + 1 } 1181 if have == 0 { r[TFL_R_STATE] = TFL_ST_NONE; tfl_puts("TFL-FAT UNKNOWN compartment=" as *u8); tfl_puts(nm); tfl_puts(" (no placement rule)\n" as *u8) } 1182 i = i + 1 1183 } 1184 return placed 1185} 1186// the field: D[v] (mm10) = normalised Gaussian RBF of the voting depths at their anchors (kernel width sigma, a prior of the 1187// table's median weighted as one landmark one sigma away) + every placed fat compartment's Gaussian bump. K carries the stats. 1188func tfl_depth_field(M: *i64, T: *i64, D: *i64, K: *i64) -> i64 { 1189 let nv: i64 = M[TFL_M_NV] 1190 let vx: *i64 = M[TFL_M_VX] as *i64; let vy: *i64 = M[TFL_M_VY] as *i64; let vz: *i64 = M[TFL_M_VZ] as *i64 1191 var sigma: i64 = tfl_sigma(T) 1192 if sigma <= 0 { sigma = M[TFL_M_EDGE] } 1193 K[TFL_K_SIGMA] = sigma 1194 let dmed: i64 = tfl_depth_median(T) 1195 let wprior: i64 = tfl_gauss_q16(sigma * sigma, sigma) 1196 let n: i64 = T[TFL_T_NROWS] 1197 let nf: i64 = T[TFL_T_NFAT] 1198 var dmin: i64 = TFL_FAR 1199 var dmax: i64 = 0 - TFL_FAR 1200 var v: i64 = 0 1201 while v < nv { 1202 var wsum: i64 = wprior 1203 var dsum: i64 = wprior * dmed 1204 var i: i64 = 0 1205 while i < n { 1206 let r: *i64 = tfl_row(T, i) 1207 if r[TFL_R_STATE] != TFL_ST_NONE { if r[TFL_R_DEPTH] >= 0 { 1208 let dx: i64 = vx[v] - r[TFL_R_AX]; let dy: i64 = vy[v] - r[TFL_R_AY]; let dz: i64 = vz[v] - r[TFL_R_AZ] 1209 let w: i64 = tfl_gauss_q16(dx * dx + dy * dy + dz * dz, sigma) 1210 wsum = wsum + w 1211 dsum = dsum + w * r[TFL_R_DEPTH] 1212 } } 1213 i = i + 1 1214 } 1215 var d: i64 = dsum / wsum 1216 var f: i64 = 0 1217 while f < nf { 1218 let q: *i64 = tfl_fatrow(T, f) 1219 if q[TFL_R_STATE] == TFL_ST_LOCATED { if q[TFL_R_ADIST] > 0 { 1220 let dx: i64 = vx[v] - q[TFL_R_X]; let dy: i64 = vy[v] - q[TFL_R_Y]; let dz: i64 = vz[v] - q[TFL_R_Z] 1221 d = d + q[TFL_R_DEPTH] * tfl_gauss_q16(dx * dx + dy * dy + dz * dz, q[TFL_R_ADIST]) / TFL_Q16 1222 } } 1223 f = f + 1 1224 } 1225 D[v] = d 1226 if d < dmin { dmin = d } 1227 if d > dmax { dmax = d } 1228 v = v + 1 1229 } 1230 // the median by counting (depths are small non-negative integers; a negative depth is counted in bin 0 and is a defect) 1231 var span: i64 = dmax - dmin + 1 1232 if span < 1 { span = 1 } 1233 let hist: *i64 = sys_mmap(span * TFL_I64) as *i64 1234 var h: i64 = 0 1235 while h < span { hist[h] = 0; h = h + 1 } 1236 v = 0 1237 while v < nv { hist[D[v] - dmin] = hist[D[v] - dmin] + 1; v = v + 1 } 1238 var acc: i64 = 0 1239 var med: i64 = dmin 1240 h = 0 1241 var found: i64 = 0 1242 while h < span { if found == 0 { acc = acc + hist[h]; if acc * 2 >= nv { med = dmin + h; found = 1 } } h = h + 1 } 1243 K[TFL_K_DMIN] = dmin; K[TFL_K_DMED] = med; K[TFL_K_DMAX] = dmax 1244 return nv 1245} 1246// the skin: every vertex pushed along its unit normal by its depth (mm10 == u10). S must come from tfl_mesh_clone_positions. 1247func tfl_offset(M: *i64, D: *i64, S: *i64) -> i64 { 1248 let nv: i64 = M[TFL_M_NV] 1249 let vx: *i64 = M[TFL_M_VX] as *i64; let vy: *i64 = M[TFL_M_VY] as *i64; let vz: *i64 = M[TFL_M_VZ] as *i64 1250 let nx: *i64 = M[TFL_M_NX] as *i64; let ny: *i64 = M[TFL_M_NY] as *i64; let nz: *i64 = M[TFL_M_NZ] as *i64 1251 let sx: *i64 = S[TFL_M_VX] as *i64; let sy: *i64 = S[TFL_M_VY] as *i64; let sz: *i64 = S[TFL_M_VZ] as *i64 1252 var v: i64 = 0 1253 while v < nv { 1254 sx[v] = vx[v] + nx[v] * D[v] / TFL_NQ 1255 sy[v] = vy[v] + ny[v] * D[v] / TFL_NQ 1256 sz[v] = vz[v] + nz[v] * D[v] / TFL_NQ 1257 v = v + 1 1258 } 1259 tfl_mesh_bbox_refresh(S) 1260 return nv 1261} 1262// the largest vertex displacement between two position sets (u10) -- the zero-depth control reads 0 here 1263func tfl_max_displacement(A: *i64, B: *i64) -> i64 { 1264 let ax: *i64 = A[TFL_M_VX] as *i64; let ay: *i64 = A[TFL_M_VY] as *i64; let az: *i64 = A[TFL_M_VZ] as *i64 1265 let bx: *i64 = B[TFL_M_VX] as *i64; let by: *i64 = B[TFL_M_VY] as *i64; let bz: *i64 = B[TFL_M_VZ] as *i64 1266 var worst: i64 = 0 1267 var v: i64 = 0 1268 while v < A[TFL_M_NV] { 1269 let dx: i64 = ax[v] - bx[v]; let dy: i64 = ay[v] - by[v]; let dz: i64 = az[v] - bz[v] 1270 let d: i64 = vm_isqrt(dx * dx + dy * dy + dz * dz) 1271 if d > worst { worst = d } 1272 v = v + 1 1273 } 1274 return worst 1275} 1276// the partition of a change between two depth fields against ONE compartment's support (TFL_SUPPORT_SIGMAS radii): 1277// out[0] moved inside, out[1] moved outside, out[2] unmoved. The doubled-cheek control reads out[1] == 0. 1278func tfl_moved_partition(M: *i64, D0: *i64, D1: *i64, cx: i64, cy: i64, cz: i64, rad: i64, out: *i64) -> i64 { 1279 let vx: *i64 = M[TFL_M_VX] as *i64; let vy: *i64 = M[TFL_M_VY] as *i64; let vz: *i64 = M[TFL_M_VZ] as *i64 1280 let sup: i64 = rad * TFL_SUPPORT_SIGMAS 1281 out[0] = 0; out[1] = 0; out[2] = 0 1282 var v: i64 = 0 1283 while v < M[TFL_M_NV] { 1284 if D0[v] == D1[v] { out[2] = out[2] + 1 } else { 1285 let dx: i64 = vx[v] - cx; let dy: i64 = vy[v] - cy; let dz: i64 = vz[v] - cz 1286 if dx * dx + dy * dy + dz * dz <= sup * sup { out[0] = out[0] + 1 } else { out[1] = out[1] + 1 } 1287 } 1288 v = v + 1 1289 } 1290 return out[0] + out[1] + out[2] 1291} 1292 1293// ==== the scene: skull, skin and the non-bone patches pushed into the rasteriser ==== 1294// push one vertex (skull frame -> render frame: half a turn about y) with a per-vertex colour; returns the trimesh index 1295func tfl_push(x: i64, y: i64, z: i64, nx: i64, ny: i64, nz: i64, col: i64) -> i64 { 1296 let i: i64 = tm_vert_n(0 - x, y, 0 - z, 0 - nx, ny, 0 - nz) 1297 tm_vcol(i, col) 1298 return i 1299} 1300// a whole mesh with one colour; keep_side: 0 all, 1 keep x >= centre only (the cutaway), -1 keep x < centre only 1301func tfl_push_mesh(M: *i64, col: i64, keep_side: i64) -> i64 { 1302 let nv: i64 = M[TFL_M_NV] 1303 let vx: *i64 = M[TFL_M_VX] as *i64; let vy: *i64 = M[TFL_M_VY] as *i64; let vz: *i64 = M[TFL_M_VZ] as *i64 1304 let nx: *i64 = M[TFL_M_NX] as *i64; let ny: *i64 = M[TFL_M_NY] as *i64; let nz: *i64 = M[TFL_M_NZ] as *i64 1305 let ta: *i64 = M[TFL_M_TA] as *i64; let tb: *i64 = M[TFL_M_TB] as *i64; let tc: *i64 = M[TFL_M_TC] as *i64 1306 let xc: i64 = (M[TFL_M_X0] + M[TFL_M_X1]) / 2 1307 let base: i64 = tm_nv() 1308 var v: i64 = 0 1309 while v < nv { tfl_push(vx[v], vy[v], vz[v], nx[v], ny[v], nz[v], col); v = v + 1 } 1310 var t: i64 = 0 1311 var kept: i64 = 0 1312 while t < M[TFL_M_NT] { 1313 var keep: i64 = 1 1314 if keep_side != 0 { 1315 let mx: i64 = (vx[ta[t]] + vx[tb[t]] + vx[tc[t]]) / 3 1316 if keep_side > 0 { if mx < xc { keep = 0 } } 1317 if keep_side < 0 { if mx >= xc { keep = 0 } } 1318 } 1319 if keep == 1 { tm_tri(base + ta[t], base + tb[t], base + tc[t], col); kept = kept + 1 } 1320 t = t + 1 1321 } 1322 return kept 1323} 1324// recolour skin vertices by anatomical bands: the vermilion (a tint of the skin) with a dark seam, and the brows. 1325// Bands are located from the landmark table; widths are canon/conf rows. Returns vertices recoloured. 1326func tfl_paint_skin(S: *i64, T: *i64, base: i64, skin_col: i64) -> i64 { 1327 let vx: *i64 = S[TFL_M_VX] as *i64; let vy: *i64 = S[TFL_M_VY] as *i64; let vz: *i64 = S[TFL_M_VZ] as *i64 1328 let st: *i64 = sys_mmap(3 * TFL_I64) as *i64 1329 let el: *i64 = sys_mmap(3 * TFL_I64) as *i64 1330 let er: *i64 = sys_mmap(3 * TFL_I64) as *i64 1331 let sol: *i64 = sys_mmap(3 * TFL_I64) as *i64 1332 let sor: *i64 = sys_mmap(3 * TFL_I64) as *i64 1333 if tfl_get(T, "stomion" as *u8, st) == 0 { return 0 } 1334 if tfl_get(T, "eye_l" as *u8, el) == 0 { return 0 } 1335 if tfl_get(T, "eye_r" as *u8, er) == 0 { return 0 } 1336 if tfl_get(T, "supraorbital_l" as *u8, sol) == 0 { return 0 } 1337 if tfl_get(T, "supraorbital_r" as *u8, sor) == 0 { return 0 } 1338 let pspan: i64 = tfl_abs(el[0] - er[0]) 1339 let iris: i64 = tfl_patch(T, "iris_radius_mm10" as *u8) 1340 let mouth_half: i64 = (pspan - 2 * iris) / 2 * tfl_patch(T, "mouth_width_permil_of_pupil_span" as *u8) / TFL_PERMIL 1341 let hu: i64 = tfl_patch(T, "upper_vermilion_mm10" as *u8) 1342 let hl: i64 = tfl_patch(T, "lower_vermilion_mm10" as *u8) 1343 let seam: i64 = tfl_patch(T, "seam_mm10" as *u8) 1344 let tint: i64 = tfl_patch(T, "vermilion_tint_permil" as *u8) 1345 let browh: i64 = tfl_patch(T, "brow_thickness_mm10" as *u8) 1346 // the brow band sits one lid semi-height above the eye centre on BOTH sides (the crest station's y may differ per side 1347 // on a 2 mm mesh; the band is a canon placement, its depth anchor is the crest) 1348 let zl: *i64 = sys_mmap(3 * TFL_I64) as *i64 1349 let zr: *i64 = sys_mmap(3 * TFL_I64) as *i64 1350 tfl_get(T, "zygion_l" as *u8, zl); tfl_get(T, "zygion_r" as *u8, zr) 1351 let flen: i64 = tfl_patch(T, "fissure_len_permil" as *u8) * tfl_abs(zl[0] - zr[0]) / TFL_PERMIL 1352 let semx: i64 = flen * tfl_patch(T, "lid_semi_x_permil_of_fissure" as *u8) / TFL_PERMIL 1353 let semy: i64 = semx * tfl_patch(T, "lid_semi_y_permil_of_semi_x" as *u8) / TFL_PERMIL 1354 let browy: i64 = el[1] + semy 1355 let browhalf: i64 = semx 1356 let sr: i64 = skin_col & TFL_BYTE 1357 let sg: i64 = (skin_col >> 8) & TFL_BYTE 1358 let sb: i64 = (skin_col >> 16) & TFL_BYTE 1359 let verm: i64 = sr + (sg * tint / TFL_PERMIL) * 256 + (sb * tint / TFL_PERMIL) * 256 * 256 1360 let xc: i64 = st[0] 1361 let zfront: i64 = st[2] 1362 var n: i64 = 0 1363 var v: i64 = 0 1364 while v < S[TFL_M_NV] { 1365 var col: i64 = 0 - 1 1366 // the vermilion: within the mouth width, between the two borders, and on the front (not the mouth's interior) 1367 if tfl_abs(vx[v] - xc) <= mouth_half { if vy[v] <= st[1] + hu { if vy[v] >= st[1] - hl { if vz[v] >= zfront - hl { 1368 col = verm 1369 if tfl_abs(vy[v] - st[1]) <= seam { col = TFL_COL_SEAM } 1370 } } } } 1371 // the brows: a band one brow-thickness tall, one lid semi-height above each eye centre, on the front surface 1372 if tfl_abs(vx[v] - el[0]) <= browhalf { if tfl_abs(vy[v] - browy) <= browh / 2 { if vz[v] >= sol[2] - browh { col = TFL_COL_BROW } } } 1373 if tfl_abs(vx[v] - er[0]) <= browhalf { if tfl_abs(vy[v] - browy) <= browh / 2 { if vz[v] >= sor[2] - browh { col = TFL_COL_BROW } } } 1374 if col >= 0 { tm_vcol(base + v, col); n = n + 1 } 1375 v = v + 1 1376 } 1377 return n 1378} 1379// the globe: a sphere with sclera, iris and pupil colours by the vertex's forward offset; returns triangles pushed 1380func tfl_push_globe(cx: i64, cy: i64, cz: i64, r: i64, iris: i64, pupil: i64, lid: i64) -> i64 { 1381 let rings: i64 = TFL_SPHERE_RINGS 1382 let segs: i64 = TFL_SPHERE_SEGS 1383 let idx: *i64 = sys_mmap((rings + 1) * (segs + 1) * TFL_I64) as *i64 1384 let cols: *i64 = sys_mmap((rings + 1) * (segs + 1) * TFL_I64) as *i64 1385 var i: i64 = 0 1386 while i <= rings { 1387 let th: i64 = IT_PI * i / rings // 0..pi from the top (+y) pole 1388 let sy: i64 = it_cos4096(th) 1389 let sr: i64 = it_sin4096(th) 1390 var j: i64 = 0 1391 while j <= segs { 1392 let ph: i64 = 2 * IT_PI * j / segs 1393 let nx: i64 = sr * it_cos4096(ph) / IT_FX 1394 let nz: i64 = sr * it_sin4096(ph) / IT_FX 1395 let ny: i64 = sy 1396 let px: i64 = cx + nx * r / IT_FX 1397 let py: i64 = cy + ny * r / IT_FX 1398 let pz: i64 = cz + nz * r / IT_FX 1399 var col: i64 = TFL_COL_WHITE 1400 // The skull frame is anterior +z; tfl_push rotates it into the rasterizer's visible -z side. 1401 if nz > 0 { 1402 let lat2: i64 = (nx * nx + ny * ny) / IT_FX * r / IT_FX * r 1403 if lat2 <= iris * iris { col = TFL_COL_IRIS } 1404 if lat2 <= pupil * pupil { col = TFL_COL_PUPIL } 1405 } 1406 let qidx: i64 = i * (segs + 1) + j 1407 idx[qidx] = tfl_push(px, py, pz, nx, ny, nz, col) 1408 cols[qidx] = col 1409 j = j + 1 1410 } 1411 i = i + 1 1412 } 1413 var n: i64 = 0 1414 i = 0 1415 while i < rings { 1416 var j: i64 = 0 1417 while j < segs { 1418 let a: i64 = idx[i * (segs + 1) + j]; let b: i64 = idx[i * (segs + 1) + j + 1] 1419 let c: i64 = idx[(i + 1) * (segs + 1) + j + 1]; let d: i64 = idx[(i + 1) * (segs + 1) + j] 1420 var tri_col: i64 = TFL_COL_WHITE 1421 if (cols[a] == TFL_COL_IRIS) + (cols[b] == TFL_COL_IRIS) + (cols[c] == TFL_COL_IRIS) + (cols[d] == TFL_COL_IRIS) > 0 { tri_col = TFL_COL_IRIS } 1422 if (cols[a] == TFL_COL_PUPIL) + (cols[b] == TFL_COL_PUPIL) + (cols[c] == TFL_COL_PUPIL) + (cols[d] == TFL_COL_PUPIL) > 0 { tri_col = TFL_COL_PUPIL } 1423 tm_tri(a, b, c, tri_col); tm_tri(a, c, d, tri_col) 1424 n = n + 2 1425 j = j + 1 1426 } 1427 i = i + 1 1428 } 1429 // Explicit front-facing iris and pupil discs make the material witness independent of sphere tessellation and winding. 1430 let iring: *i64 = sys_mmap((segs + 1) * TFL_I64) as *i64 1431 let ic: i64 = tfl_push(cx, cy, cz + r + lid + TFL_LID_SUBDIV, 0, 0, 1, TFL_COL_IRIS) 1432 var dj: i64 = 0 1433 while dj <= segs { let da: i64 = 2 * IT_PI * dj / segs; iring[dj] = tfl_push(cx + iris * it_cos4096(da) / IT_FX, cy + iris * it_sin4096(da) / IT_FX, cz + r + lid + TFL_LID_SUBDIV, 0, 0, 1, TFL_COL_IRIS); dj = dj + 1 } 1434 dj = 0 1435 while dj < segs { let dn: i64 = (dj + 1) % (segs + 1); tm_tri(ic, iring[dj], iring[dn], TFL_COL_IRIS); dj = dj + 1 } 1436 let pring: *i64 = sys_mmap((segs + 1) * TFL_I64) as *i64 1437 let pc: i64 = tfl_push(cx, cy, cz + r + lid + TFL_LID_SUBDIV + TFL_LID_SUBDIV, 0, 0, 1, TFL_COL_PUPIL) 1438 dj = 0 1439 while dj <= segs { let da: i64 = 2 * IT_PI * dj / segs; pring[dj] = tfl_push(cx + pupil * it_cos4096(da) / IT_FX, cy + pupil * it_sin4096(da) / IT_FX, cz + r + lid + TFL_LID_SUBDIV + TFL_LID_SUBDIV, 0, 0, 1, TFL_COL_PUPIL); dj = dj + 1 } 1440 dj = 0 1441 while dj < segs { let dn: i64 = (dj + 1) % (segs + 1); tm_tri(pc, pring[dj], pring[dn], TFL_COL_PUPIL); dj = dj + 1 } 1442 return n 1443} 1444// the lid patch over one orbit: a heightfield over the lid ellipse (semi-axes from the fissure length), following the globe 1445// plus the lid thickness inside the globe's projection and blending to the skin's front at the rim; the palpebral fissure 1446// (an almond of the canon length and height, rotated by tilt deg10) is left OPEN so the globe shows. Returns quads pushed. 1447func tfl_push_lid(S: *i64, T: *i64, cx: i64, cy: i64, cz: i64, r: i64, semx: i64, semy: i64, flen: i64, fh: i64, tilt10: i64, col: i64) -> i64 { 1448 let step: i64 = tfl_max(S[TFL_M_EDGE] / TFL_LID_SUBDIV, 1) 1449 let lid: i64 = tfl_patch(T, "lid_thickness_mm10" as *u8) 1450 let nu: i64 = 2 * semx / step + 1 1451 let nvv: i64 = 2 * semy / step + 1 1452 let idx: *i64 = sys_mmap((nu + 1) * (nvv + 1) * TFL_I64) as *i64 1453 let ang: i64 = tilt10 * IT_PI / (180 * 10) 1454 let ca: i64 = it_cos4096(ang) 1455 let sa: i64 = it_sin4096(ang) 1456 var i: i64 = 0 1457 while i <= nvv { 1458 let v: i64 = 0 - semy + i * step 1459 var j: i64 = 0 1460 while j <= nu { 1461 let u: i64 = 0 - semx + j * step 1462 var id: i64 = 0 - 1 1463 // inside the lid ellipse? 1464 let e: i64 = (u * u) * (semy * semy) + (v * v) * (semx * semx) 1465 if e <= (semx * semx) * (semy * semy) { 1466 let s2: i64 = u * u + v * v 1467 let s: i64 = vm_isqrt(s2) 1468 var z: i64 = 0 1469 if s < r { z = cz + vm_isqrt(r * r - s2) + lid } else { 1470 // from the globe's equator out to the rim: blend toward the skin's own front surface there 1471 var zr: i64 = tfl_front_at(S, cx + u, cy + v, 4) 1472 if zr <= TFL_ZNONE { zr = cz + lid } 1473 // the ellipse radius along this direction 1474 let rr: i64 = vm_isqrt((s2 * (semx * semx) * (semy * semy)) / tfl_max(e, 1)) 1475 var tq: i64 = 0 1476 if rr > r { tq = (s - r) * TFL_Q16 / (rr - r) } 1477 if tq > TFL_Q16 { tq = TFL_Q16 } 1478 z = (cz + lid) + (zr - (cz + lid)) * tq / TFL_Q16 1479 } 1480 // the normal: the globe's where the lid follows it, +z on the blend 1481 var nx: i64 = 0; var ny: i64 = 0; var nz: i64 = TFL_NQ 1482 if s < r { let l: i64 = vm_isqrt(s2 + (z - lid - cz) * (z - lid - cz)); if l > 0 { nx = u * TFL_NQ / l; ny = v * TFL_NQ / l; nz = (z - lid - cz) * TFL_NQ / l } } 1483 id = tfl_push(cx + u, cy + v, z, nx, ny, nz, col) 1484 } 1485 idx[i * (nu + 1) + j] = id 1486 j = j + 1 1487 } 1488 i = i + 1 1489 } 1490 let a2: i64 = flen / 2 1491 let b2: i64 = fh / 2 1492 // THE LASH LINE: the lid margin one grid step around the opening is painted dark, because the photo ruler grows each 1493 // fissure from the pupil by local darkness out to the canthi -- a margin the same colour as the lid stops the growth at 1494 // the iris and reads a fissure a third of its length (measured: intercanthal_index 555 against the canon 380..420) 1495 var pi2: i64 = 0 1496 while pi2 <= nvv { 1497 var pj: i64 = 0 1498 while pj <= nu { 1499 let id: i64 = idx[pi2 * (nu + 1) + pj] 1500 if id >= 0 { 1501 let u: i64 = 0 - semx + pj * step 1502 let v: i64 = 0 - semy + pi2 * step 1503 let ur: i64 = (u * ca + v * sa) / IT_FX 1504 let vr: i64 = (v * ca - u * sa) / IT_FX 1505 var inside: i64 = 0 1506 var ring: i64 = 0 1507 if a2 > 0 { if b2 > 0 { 1508 if (ur * ur) * (b2 * b2) + (vr * vr) * (a2 * a2) < (a2 * a2) * (b2 * b2) { inside = 1 } 1509 let a3: i64 = a2 + step; let b3: i64 = b2 + step 1510 if (ur * ur) * (b3 * b3) + (vr * vr) * (a3 * a3) < (a3 * a3) * (b3 * b3) { ring = 1 } 1511 } } 1512 if ring == 1 { if inside == 0 { tm_vcol(id, TFL_COL_BROW) } } 1513 } 1514 pj = pj + 1 1515 } 1516 pi2 = pi2 + 1 1517 } 1518 var n: i64 = 0 1519 i = 0 1520 while i < nvv { 1521 var j: i64 = 0 1522 while j < nu { 1523 let q0: i64 = idx[i * (nu + 1) + j]; let q1: i64 = idx[i * (nu + 1) + j + 1] 1524 let q2: i64 = idx[(i + 1) * (nu + 1) + j + 1]; let q3: i64 = idx[(i + 1) * (nu + 1) + j] 1525 if q0 >= 0 { if q1 >= 0 { if q2 >= 0 { if q3 >= 0 { 1526 // the quad's centre against the tilted almond: skip the opening 1527 let uc: i64 = 0 - semx + j * step + step / 2 1528 let vc: i64 = 0 - semy + i * step + step / 2 1529 let ur: i64 = (uc * ca + vc * sa) / IT_FX 1530 let vr: i64 = (vc * ca - uc * sa) / IT_FX 1531 var open: i64 = 0 1532 if tfl_abs(ur) < a2 { if b2 > 0 { 1533 // |vr| < b2 * sqrt(1 - (ur/a2)^2) 1534 let lim2: i64 = (b2 * b2) * (a2 * a2 - ur * ur) / (a2 * a2) 1535 if vr * vr < lim2 { open = 1 } 1536 } } 1537 if open == 0 { tm_tri(q0, q1, q2, col); tm_tri(q0, q2, q3, col); n = n + 2 } 1538 } } } } 1539 j = j + 1 1540 } 1541 i = i + 1 1542 } 1543 return n 1544} 1545// both eyes: globe centre depth = the skull's front at the lid ellipse boundary (the orbital rim, sampled) + the 1546// globe-ahead-of-rim row; the globe, then the lid over it. out[0]=eye count, out[1]=rim z left, out[2]=rim z right 1547func tfl_push_eyes(M: *i64, S: *i64, T: *i64, tilt10: i64, skin_col: i64, out: *i64) -> i64 { 1548 let el: *i64 = sys_mmap(3 * TFL_I64) as *i64 1549 let er: *i64 = sys_mmap(3 * TFL_I64) as *i64 1550 if tfl_get(T, "eye_l" as *u8, el) == 0 { return 0 } 1551 if tfl_get(T, "eye_r" as *u8, er) == 0 { return 0 } 1552 let pspan: i64 = tfl_abs(el[0] - er[0]) 1553 let zl: *i64 = sys_mmap(3 * TFL_I64) as *i64 1554 let zr: *i64 = sys_mmap(3 * TFL_I64) as *i64 1555 tfl_get(T, "zygion_l" as *u8, zl); tfl_get(T, "zygion_r" as *u8, zr) 1556 let bizy: i64 = tfl_abs(zl[0] - zr[0]) 1557 let flen: i64 = tfl_patch(T, "fissure_len_permil" as *u8) * bizy / TFL_PERMIL 1558 let fh: i64 = tfl_patch(T, "fissure_height_mm10" as *u8) 1559 let semx: i64 = flen * tfl_patch(T, "lid_semi_x_permil_of_fissure" as *u8) / TFL_PERMIL 1560 let semy: i64 = semx * tfl_patch(T, "lid_semi_y_permil_of_semi_x" as *u8) / TFL_PERMIL 1561 let r: i64 = tfl_patch(T, "globe_radius_mm10" as *u8) 1562 let iris: i64 = tfl_patch(T, "iris_radius_mm10" as *u8) 1563 let pupil: i64 = tfl_patch(T, "pupil_radius_mm10" as *u8) 1564 let ahead: i64 = tfl_patch(T, "globe_ahead_of_rim_mm10" as *u8) 1565 let lid: i64 = tfl_patch(T, "lid_thickness_mm10" as *u8) 1566 var eyes: i64 = 0 1567 var side: i64 = 0 1568 while side < 2 { 1569 var c: *i64 = el 1570 if side == 1 { c = er } 1571 // the rim: the CREST of the skull's front along each of TFL_RIM_SAMPLES directions out of the eye centre (a sample on 1572 // the socket hole reads deep; a crest cannot), and the rim depth is the MEDIAN of the crests 1573 let crests: *i64 = sys_mmap(TFL_RIM_SAMPLES * TFL_I64) as *i64 1574 let cr: *i64 = sys_mmap(3 * TFL_I64) as *i64 1575 var zn: i64 = 0 1576 var k: i64 = 0 1577 while k < TFL_RIM_SAMPLES { 1578 let ph: i64 = 2 * IT_PI * k / TFL_RIM_SAMPLES 1579 let ex: i64 = semx * it_cos4096(ph) / IT_FX 1580 let ey: i64 = semy * it_sin4096(ph) / IT_FX 1581 // walk the ellipse direction in unit steps of the mesh cell: (dx,dy) normalised to the larger component 1582 var dxs: i64 = 0 1583 var dys: i64 = 0 1584 var reachk: i64 = 0 1585 if tfl_abs(ex) >= tfl_abs(ey) { if ex > 0 { dxs = 1 } else { dxs = 0 - 1 } reachk = tfl_abs(ex) } else { if ey > 0 { dys = 1 } else { dys = 0 - 1 } reachk = tfl_abs(ey) } 1586 tfl_crest(M, c[0], c[1], dxs, dys, reachk, cr) 1587 if cr[2] > TFL_ZNONE { crests[zn] = cr[2]; zn = zn + 1 } 1588 k = k + 1 1589 } 1590 if zn > 0 { 1591 var a: i64 = 1 1592 while a < zn { 1593 let key: i64 = crests[a] 1594 var b: i64 = a - 1 1595 var go: i64 = 1 1596 while go == 1 { if b < 0 { go = 0 } else { if crests[b] > key { crests[b + 1] = crests[b]; b = b - 1 } else { go = 0 } } } 1597 crests[b + 1] = key 1598 a = a + 1 1599 } 1600 let rimz: i64 = crests[zn / 2] 1601 let gz: i64 = rimz + ahead 1602 out[1 + side] = rimz 1603 tfl_push_globe(c[0], c[1], gz, r, iris, pupil, lid) 1604 tfl_push_lid(S, T, c[0], c[1], gz, r, semx, semy, flen, fh, tilt10, skin_col) 1605 eyes = eyes + 1 1606 } 1607 side = side + 1 1608 } 1609 out[0] = eyes 1610 return eyes 1611} 1612// the nose over the empty aperture: a cosine-bell ridge from the nasion's skin point over the pronasale (projection and 1613// height rows, PENDING the Rynn regression) to the subnasale, half-width growing from the bridge to the alar base (nasal 1614// width from the canon nasal index), raised above the skin's own front where it stands proud. Returns quads pushed. 1615func tfl_push_nose(S: *i64, T: *i64, col: i64, out: *i64) -> i64 { 1616 let n3: *i64 = sys_mmap(3 * TFL_I64) as *i64 1617 let ns: *i64 = sys_mmap(3 * TFL_I64) as *i64 1618 if tfl_get(T, "nasion" as *u8, n3) == 0 { return 0 } 1619 if tfl_get(T, "subnasale_canon" as *u8, ns) == 0 { return 0 } 1620 let step: i64 = tfl_max(S[TFL_M_EDGE] / TFL_LID_SUBDIV, 1) 1621 let nh: i64 = n3[1] - ns[1] // nasal height on the bone (nasion -> aperture rim) 1622 if nh <= 0 { return 0 } 1623 let wbase: i64 = tfl_patch(T, "nasal_width_permil" as *u8) * nh / TFL_PERMIL / 2 1624 let wbridge: i64 = wbase * tfl_patch(T, "nasal_bridge_width_permil" as *u8) / TFL_PERMIL 1625 let proj: i64 = tfl_patch(T, "pronasale_projection_mm10" as *u8) 1626 let tipy: i64 = ns[1] + tfl_patch(T, "pronasale_height_permil" as *u8) * nh / TFL_PERMIL 1627 // the skin's own front at the three midline stations 1628 let xc: i64 = n3[0] 1629 let zn: i64 = tfl_front_at(S, xc, n3[1], 3) 1630 let zsn: i64 = tfl_front_at(S, xc, ns[1], 3) 1631 if zn <= TFL_ZNONE { return 0 } 1632 if zsn <= TFL_ZNONE { return 0 } 1633 let ztip: i64 = ns[2] + proj 1634 out[0] = xc; out[1] = tipy; out[2] = ztip 1635 let ylo: i64 = ns[1] - step * 2 1636 let yhi: i64 = n3[1] 1637 let ny: i64 = (yhi - ylo) / step + 1 1638 let nx: i64 = 2 * wbase / step + 1 1639 let idx: *i64 = sys_mmap((nx + 1) * (ny + 1) * TFL_I64) as *i64 1640 let hz: *i64 = sys_mmap((nx + 1) * (ny + 1) * TFL_I64) as *i64 1641 // pass 1: the heightfield 1642 var i: i64 = 0 1643 while i <= ny { 1644 let y: i64 = ylo + i * step 1645 // the ridge height and half-width at this y 1646 var zr: i64 = zsn 1647 var w: i64 = wbase 1648 if y >= tipy { if yhi > tipy { zr = ztip + (zn - ztip) * (y - tipy) / (yhi - tipy) } w = wbase - (wbase - wbridge) * (y - tipy) / tfl_max(yhi - tipy, 1) } 1649 if y < tipy { if tipy > ylo { zr = zsn + (ztip - zsn) * (y - ylo) / (tipy - ylo) } } 1650 var j: i64 = 0 1651 while j <= nx { 1652 let x: i64 = xc - wbase + j * step 1653 var z: i64 = TFL_ZNONE 1654 let zb: i64 = tfl_front_at(S, x, y, 3) 1655 if zb > TFL_ZNONE { 1656 z = zb 1657 let ax: i64 = tfl_abs(x - xc) 1658 if ax < w { if w > 0 { 1659 // the bell: (1 + cos(pi ax / w)) / 2 1660 let bell: i64 = (IT_FX + it_cos4096(IT_PI * ax / w)) / 2 1661 let zn2: i64 = zb + (zr - zb) * bell / IT_FX 1662 if zn2 > z { z = zn2 } 1663 } } 1664 } 1665 hz[i * (nx + 1) + j] = z 1666 j = j + 1 1667 } 1668 i = i + 1 1669 } 1670 // pass 2: vertices with finite-difference normals (the surface's own slope, so the nose shades as a form) 1671 i = 0 1672 while i <= ny { 1673 var j: i64 = 0 1674 while j <= nx { 1675 var id: i64 = 0 - 1 1676 let z: i64 = hz[i * (nx + 1) + j] 1677 if z > TFL_ZNONE { 1678 var zl2: i64 = z; var zr2: i64 = z; var zd: i64 = z; var zu: i64 = z 1679 if j > 0 { if hz[i * (nx + 1) + j - 1] > TFL_ZNONE { zl2 = hz[i * (nx + 1) + j - 1] } } 1680 if j < nx { if hz[i * (nx + 1) + j + 1] > TFL_ZNONE { zr2 = hz[i * (nx + 1) + j + 1] } } 1681 if i > 0 { if hz[(i - 1) * (nx + 1) + j] > TFL_ZNONE { zd = hz[(i - 1) * (nx + 1) + j] } } 1682 if i < ny { if hz[(i + 1) * (nx + 1) + j] > TFL_ZNONE { zu = hz[(i + 1) * (nx + 1) + j] } } 1683 var nxv: i64 = 0 - (zr2 - zl2) 1684 var nyv: i64 = 0 - (zu - zd) 1685 var nzv: i64 = 2 * step 1686 let l: i64 = vm_isqrt(nxv * nxv + nyv * nyv + nzv * nzv) 1687 if l > 0 { nxv = nxv * TFL_NQ / l; nyv = nyv * TFL_NQ / l; nzv = nzv * TFL_NQ / l } else { nzv = TFL_NQ } 1688 id = tfl_push(xc - wbase + j * step, ylo + i * step, z, nxv, nyv, nzv, col) 1689 } 1690 idx[i * (nx + 1) + j] = id 1691 j = j + 1 1692 } 1693 i = i + 1 1694 } 1695 var n: i64 = 0 1696 i = 0 1697 while i < ny { 1698 var j: i64 = 0 1699 while j < nx { 1700 let q0: i64 = idx[i * (nx + 1) + j]; let q1: i64 = idx[i * (nx + 1) + j + 1] 1701 let q2: i64 = idx[(i + 1) * (nx + 1) + j + 1]; let q3: i64 = idx[(i + 1) * (nx + 1) + j] 1702 if q0 >= 0 { if q1 >= 0 { if q2 >= 0 { if q3 >= 0 { tm_tri(q0, q1, q2, col); tm_tri(q0, q2, q3, col); n = n + 2 } } } } 1703 j = j + 1 1704 } 1705 i = i + 1 1706 } 1707 return n 1708} 1709// SOFT TISSUE SMOOTHS BONE DETAIL below the tissue-depth scale (nx_faceanat's own note: the malar bone point reads 1710// ~10 mm but the SURFACE-EFFECTIVE relief is ~7 mm once the tissue smooths it). A uniform Laplacian over the welded 1711// skin, with the iteration count DERIVED as (median depth / mesh edge)^2 (a random walk of that many steps spreads one 1712// tissue depth), on positions and on the gradient normals alike; then every vertex is held at least half its depth off 1713// the bone along the bone's normal (the offset must not be smoothed INTO the skull). Returns the vertices clamped. 1714func tfl_smooth_skin(M: *i64, S: *i64, D: *i64, dmed: i64) -> i64 { 1715 let nv: i64 = M[TFL_M_NV] 1716 let nt: i64 = M[TFL_M_NT] 1717 let ta: *i64 = M[TFL_M_TA] as *i64; let tb: *i64 = M[TFL_M_TB] as *i64; let tc: *i64 = M[TFL_M_TC] as *i64 1718 // adjacency in CSR form from the triangles (both directions of every edge, duplicates harmless as weights) 1719 let deg: *i64 = sys_mmap((nv + 1) * TFL_I64) as *i64 1720 var i: i64 = 0 1721 while i <= nv { deg[i] = 0; i = i + 1 } 1722 var t: i64 = 0 1723 while t < nt { deg[ta[t]] = deg[ta[t]] + 2; deg[tb[t]] = deg[tb[t]] + 2; deg[tc[t]] = deg[tc[t]] + 2; t = t + 1 } 1724 let off: *i64 = sys_mmap((nv + 1) * TFL_I64) as *i64 1725 off[0] = 0 1726 i = 0 1727 while i < nv { off[i + 1] = off[i] + deg[i]; i = i + 1 } 1728 let adj: *i64 = sys_mmap((off[nv] + 1) * TFL_I64) as *i64 1729 let fill: *i64 = sys_mmap((nv + 1) * TFL_I64) as *i64 1730 i = 0 1731 while i < nv { fill[i] = 0; i = i + 1 } 1732 t = 0 1733 while t < nt { 1734 let a: i64 = ta[t]; let b: i64 = tb[t]; let c: i64 = tc[t] 1735 adj[off[a] + fill[a]] = b; fill[a] = fill[a] + 1; adj[off[a] + fill[a]] = c; fill[a] = fill[a] + 1 1736 adj[off[b] + fill[b]] = a; fill[b] = fill[b] + 1; adj[off[b] + fill[b]] = c; fill[b] = fill[b] + 1 1737 adj[off[c] + fill[c]] = a; fill[c] = fill[c] + 1; adj[off[c] + fill[c]] = b; fill[c] = fill[c] + 1 1738 t = t + 1 1739 } 1740 let edge: i64 = tfl_max(M[TFL_M_EDGE], 1) 1741 var iters: i64 = (dmed / edge) * (dmed / edge) 1742 if iters < 1 { iters = 1 } 1743 if iters > 32 { iters = 32 } 1744 let sx: *i64 = S[TFL_M_VX] as *i64; let sy: *i64 = S[TFL_M_VY] as *i64; let sz: *i64 = S[TFL_M_VZ] as *i64 1745 let nx: *i64 = sys_mmap(nv * TFL_I64) as *i64; let ny: *i64 = sys_mmap(nv * TFL_I64) as *i64; let nz: *i64 = sys_mmap(nv * TFL_I64) as *i64 1746 let mnx: *i64 = M[TFL_M_NX] as *i64; let mny: *i64 = M[TFL_M_NY] as *i64; let mnz: *i64 = M[TFL_M_NZ] as *i64 1747 i = 0 1748 while i < nv { nx[i] = mnx[i]; ny[i] = mny[i]; nz[i] = mnz[i]; i = i + 1 } 1749 let tx: *i64 = sys_mmap(nv * TFL_I64) as *i64; let ty: *i64 = sys_mmap(nv * TFL_I64) as *i64; let tz: *i64 = sys_mmap(nv * TFL_I64) as *i64 1750 let ux: *i64 = sys_mmap(nv * TFL_I64) as *i64; let uy: *i64 = sys_mmap(nv * TFL_I64) as *i64; let uz: *i64 = sys_mmap(nv * TFL_I64) as *i64 1751 var it: i64 = 0 1752 while it < iters { 1753 i = 0 1754 while i < nv { 1755 let d: i64 = off[i + 1] - off[i] 1756 if d > 0 { 1757 var ax: i64 = 0; var ay: i64 = 0; var az: i64 = 0 1758 var bx: i64 = 0; var by: i64 = 0; var bz: i64 = 0 1759 var k: i64 = off[i] 1760 while k < off[i + 1] { let j: i64 = adj[k]; ax = ax + sx[j]; ay = ay + sy[j]; az = az + sz[j]; bx = bx + nx[j]; by = by + ny[j]; bz = bz + nz[j]; k = k + 1 } 1761 // half toward the neighbourhood mean (lambda one half) 1762 tx[i] = (sx[i] + ax / d) / 2; ty[i] = (sy[i] + ay / d) / 2; tz[i] = (sz[i] + az / d) / 2 1763 ux[i] = (nx[i] + bx / d) / 2; uy[i] = (ny[i] + by / d) / 2; uz[i] = (nz[i] + bz / d) / 2 1764 } else { tx[i] = sx[i]; ty[i] = sy[i]; tz[i] = sz[i]; ux[i] = nx[i]; uy[i] = ny[i]; uz[i] = nz[i] } 1765 i = i + 1 1766 } 1767 i = 0 1768 while i < nv { sx[i] = tx[i]; sy[i] = ty[i]; sz[i] = tz[i]; nx[i] = ux[i]; ny[i] = uy[i]; nz[i] = uz[i]; i = i + 1 } 1769 it = it + 1 1770 } 1771 // renormalise the smoothed normals and install them as the skin's own; hold every vertex off the bone 1772 let vx: *i64 = M[TFL_M_VX] as *i64; let vy: *i64 = M[TFL_M_VY] as *i64; let vz: *i64 = M[TFL_M_VZ] as *i64 1773 var clamped: i64 = 0 1774 i = 0 1775 while i < nv { 1776 let l: i64 = vm_isqrt(nx[i] * nx[i] + ny[i] * ny[i] + nz[i] * nz[i]) 1777 if l > 0 { nx[i] = nx[i] * TFL_NQ / l; ny[i] = ny[i] * TFL_NQ / l; nz[i] = nz[i] * TFL_NQ / l } else { nx[i] = mnx[i]; ny[i] = mny[i]; nz[i] = mnz[i] } 1778 let h: i64 = ((sx[i] - vx[i]) * mnx[i] + (sy[i] - vy[i]) * mny[i] + (sz[i] - vz[i]) * mnz[i]) / TFL_NQ 1779 let floor: i64 = D[i] / 2 1780 if h < floor { 1781 let push: i64 = floor - h 1782 sx[i] = sx[i] + mnx[i] * push / TFL_NQ; sy[i] = sy[i] + mny[i] * push / TFL_NQ; sz[i] = sz[i] + mnz[i] * push / TFL_NQ 1783 clamped = clamped + 1 1784 } 1785 i = i + 1 1786 } 1787 S[TFL_M_NX] = nx as i64; S[TFL_M_NY] = ny as i64; S[TFL_M_NZ] = nz as i64 1788 S[TFL_M_FM] = 0 1789 tfl_mesh_bbox_refresh(S) 1790 tfl_kv("TFL-SMOOTH iterations=" as *u8, iters); tfl_kv(" clamped_off_bone=" as *u8, clamped); tfl_kv(" median_depth_mm10=" as *u8, dmed); tfl_kv(" edge_u10=" as *u8, edge); tfl_puts("\n" as *u8) 1791 return clamped 1792} 1793// recompute smooth normals of everything pushed so far (patches carry rough normals); nx_trimesh owns the arithmetic 1794func tfl_scene_normals() -> i64 { return tm_compute_normals() } 1795// render the scene: camera distance derived from the head height and the frame fraction row; focal = the frame height. 1796// yaw in rad*4096 (0 frontal). Writes W*H pixels into fb (a caller-owned buffer of W*H i64). 1797func tfl_render(fb: *i64, W: i64, H: i64, yaw: i64, head_u10: i64, frame_permil: i64) -> i64 { 1798 let zb: *i64 = sys_mmap(W * H * TFL_I64) as *i64 1799 trimesh_zclear(zb, W * H) 1800 var i: i64 = 0 1801 while i < W * H { fb[i] = TFL_BG; i = i + 1 } 1802 let focal: i64 = H 1803 var camz: i64 = head_u10 * TFL_PERMIL / tfl_max(frame_permil, 1) 1804 if camz < 1 { camz = 1 } 1805 // the caller re-centred the scene (tfl_recentre); the camera sits at (0,0,-camz) looking at the origin 1806 trimesh_render(fb, zb, W, H, yaw, 0, camz, focal, 2) 1807 sys_munmap_direct(zb as *u8, W * H * TFL_I64) 1808 return camz 1809} 1810// shift every pushed vertex by (-cx, -cy, -cz) IN RENDER SPACE: the rasteriser's camera looks at the origin 1811func tfl_recentre(cx: i64, cy: i64, cz: i64) -> i64 { 1812 let n: i64 = tm_nv() 1813 tm_place(0, n, 0 - cx, 0 - cy, 0 - cz, TFL_PERMIL) 1814 return n 1815} 1816// the scene as a mesh record in SKULL space (x and z un-negated): the rendered skin with its patches, exportable and 1817// measurable by the same profile the skull was located with 1818func tfl_scene_to_mesh() -> *i64 { 1819 let M: *i64 = tfl_mesh_new() 1820 let nv: i64 = tm_nv() 1821 let nt: i64 = tm_nt() 1822 let vx: *i64 = sys_mmap(nv * TFL_I64) as *i64; let vy: *i64 = sys_mmap(nv * TFL_I64) as *i64; let vz: *i64 = sys_mmap(nv * TFL_I64) as *i64 1823 let nx: *i64 = sys_mmap(nv * TFL_I64) as *i64; let ny: *i64 = sys_mmap(nv * TFL_I64) as *i64; let nz: *i64 = sys_mmap(nv * TFL_I64) as *i64 1824 let ta: *i64 = sys_mmap(nt * TFL_I64) as *i64; let tb: *i64 = sys_mmap(nt * TFL_I64) as *i64; let tc: *i64 = sys_mmap(nt * TFL_I64) as *i64 1825 var i: i64 = 0 1826 while i < nv { 1827 vx[i] = 0 - tm_vx(i); vy[i] = tm_vy(i); vz[i] = 0 - tm_vz(i) 1828 nx[i] = 0 - tm_vnx(i); ny[i] = tm_vny(i); nz[i] = 0 - tm_vnz(i) 1829 i = i + 1 1830 } 1831 var esum: i64 = 0 1832 var t: i64 = 0 1833 while t < nt { 1834 ta[t] = tm_ta(t); tb[t] = tm_tb(t); tc[t] = tm_tc(t) 1835 let dx: i64 = vx[ta[t]] - vx[tb[t]]; let dy: i64 = vy[ta[t]] - vy[tb[t]]; let dz: i64 = vz[ta[t]] - vz[tb[t]] 1836 esum = esum + vm_isqrt(dx * dx + dy * dy + dz * dz) 1837 t = t + 1 1838 } 1839 M[TFL_M_NV] = nv; M[TFL_M_NT] = nt 1840 M[TFL_M_VX] = vx as i64; M[TFL_M_VY] = vy as i64; M[TFL_M_VZ] = vz as i64 1841 M[TFL_M_NX] = nx as i64; M[TFL_M_NY] = ny as i64; M[TFL_M_NZ] = nz as i64 1842 M[TFL_M_TA] = ta as i64; M[TFL_M_TB] = tb as i64; M[TFL_M_TC] = tc as i64 1843 tfl_mesh_bbox_refresh(M) 1844 var edge: i64 = 1 1845 if nt > 0 { edge = esum / nt } 1846 if edge < 1 { edge = 1 } 1847 M[TFL_M_EDGE] = edge 1848 M[TFL_M_RAW] = nv 1849 return M 1850} 1851// compose two frames side by side into one buffer of (2W) x H 1852func tfl_pair(a: *i64, b: *i64, W: i64, H: i64, out: *i64) -> i64 { 1853 var y: i64 = 0 1854 while y < H { 1855 var x: i64 = 0 1856 while x < W { out[y * 2 * W + x] = a[y * W + x]; out[y * 2 * W + W + x] = b[y * W + x]; x = x + 1 } 1857 y = y + 1 1858 } 1859 return 2 * W * H 1860} 1861// ==== THE ONE CALL (the board's contract sks_surface): skull mesh -> skin mesh ==== 1862// Loads the skull, locates every landmark the table names on it, places the compartments, derives the depth field, offsets 1863// and smooths the skin. T must already carry the conf (tfl_conf_load) and any parameter overrides. Mout receives the skull 1864// record, Dout[0] the depth array pointer, K the receipt values. Returns the skin record, or 0 with the refusal announced. 1865func sks_surface(skull_path: *u8, T: *i64, Mout: *i64, Dout: *i64, K: *i64) -> *i64 { 1866 let M: *i64 = tfl_mesh_new() 1867 if tfl_mesh_load(skull_path, M) == 0 { tfl_puts("SKS-SURFACE REFUSED skull mesh unreadable: " as *u8); tfl_puts(skull_path); tfl_puts("\n" as *u8); return 0 as *i64 } 1868 var i: i64 = 0 1869 while i < TFL_M_N { Mout[i] = M[i]; i = i + 1 } 1870 let nloc: i64 = tfl_locate(M, T, K) 1871 if nloc == 0 { tfl_puts("SKS-SURFACE REFUSED landmarks not located\n" as *u8); return 0 as *i64 } 1872 tfl_print_rows(T) 1873 tfl_kv("SKS-SURFACE landmarks located=" as *u8, K[TFL_K_LOCATED]); tfl_kv(" fallback=" as *u8, K[TFL_K_FALLBACK]); tfl_kv(" unlocated=" as *u8, K[TFL_K_UNLOCATED]) 1874 tfl_kv(" voters=" as *u8, K[TFL_K_VOTERS]); tfl_kv(" anchor_dist_max_u10=" as *u8, K[TFL_K_ANCHOR_MAX]); tfl_puts("\n" as *u8) 1875 let nfat: i64 = tfl_fat_place(T) 1876 let D: *i64 = sys_mmap(M[TFL_M_NV] * TFL_I64) as *i64 1877 tfl_depth_field(M, T, D, K) 1878 let S: *i64 = tfl_mesh_clone_positions(M) 1879 tfl_offset(M, D, S) 1880 let clamped: i64 = tfl_smooth_skin(M, S, D, K[TFL_K_DMED]) 1881 tfl_kv("SKS-SURFACE field sigma_u10=" as *u8, K[TFL_K_SIGMA]); tfl_kv(" depth_min_mm10=" as *u8, K[TFL_K_DMIN]); tfl_kv(" depth_median_mm10=" as *u8, K[TFL_K_DMED]); tfl_kv(" depth_max_mm10=" as *u8, K[TFL_K_DMAX]) 1882 tfl_kv(" compartments_placed=" as *u8, nfat); tfl_kv(" smooth_clamped=" as *u8, clamped); tfl_puts("\n" as *u8) 1883 var ci: i64 = 0 1884 while ci < T[TFL_T_NFAT] { 1885 let cr: *i64 = tfl_fatrow(T, ci) 1886 tfl_puts("SKS-SURFACE compartment " as *u8); tfl_puts(cr[TFL_R_NAME] as *u8) 1887 tfl_kv(" mm10=" as *u8, cr[TFL_R_DEPTH]); tfl_kv(" cx=" as *u8, cr[TFL_R_X]); tfl_kv(" cy=" as *u8, cr[TFL_R_Y]); tfl_kv(" cz=" as *u8, cr[TFL_R_Z]); tfl_kv(" radius_u10=" as *u8, cr[TFL_R_ADIST]); tfl_puts("\n" as *u8) 1888 ci = ci + 1 1889 } 1890 Dout[0] = D as i64 1891 return S 1892} 1893// the peak resident set of this process, kilobytes, read from /proc/self/status (VmHWM); -1 when unreadable 1894func tfl_peak_rss_kb() -> i64 { 1895 let lp: *i64 = sys_mmap(2 * TFL_I64) as *i64 1896 lp[0] = 0 1897 let b: *u8 = sys_read_file("/proc/self/status" as *u8, lp) 1898 if (b as i64) == 0 { return 0 - 1 } 1899 let n: i64 = lp[0] 1900 let key: *u8 = "VmHWM:" as *u8 1901 var i: i64 = 0 1902 while i + 6 < n { 1903 var k: i64 = 0 1904 var ok: i64 = 1 1905 while k < 6 { if b[i + k] != key[k] { ok = 0; k = 6 } else { k = k + 1 } } 1906 if ok == 1 { 1907 var p: i64 = i + 6 1908 var v: i64 = 0 1909 var seen: i64 = 0 1910 while p < n { let c: i64 = b[p] as i64; if c >= TFL_ZERO { if c <= TFL_NINE { v = v * 10 + (c - TFL_ZERO); seen = 1 } else { if seen == 1 { p = n } } } else { if seen == 1 { p = n } } p = p + 1 } 1911 return v 1912 } 1913 i = i + 1 1914 } 1915 return 0 - 1 1916} 1917// run the promoted skull generator as a child (./nx_skullsdf.elf from the estate root) into out; returns its exit code or 1918// -1 when it could not be started. The child's stdout goes to <out>.log. 1919func tfl_run_skullsdf(out: *u8, sex: i64, robust: i64, cell_um: i64) -> i64 { 1920 let elf: *u8 = "./nx_skullsdf.elf" as *u8 1921 let a1: *u8 = sys_mmap(32) 1922 let a2: *u8 = sys_mmap(32) 1923 let a3: *u8 = sys_mmap(32) 1924 let a4: *u8 = sys_mmap(32) 1925 let a5: *u8 = sys_mmap(32) 1926 tfl_catn(a1, 0, sex); tfl_catn(a2, 0, robust); tfl_catn(a3, 0, 0); tfl_catn(a4, 0, cell_um) 1927 let argv: *i64 = sys_mmap(8 * TFL_I64) as *i64 1928 argv[0] = elf as i64; argv[1] = out as i64; argv[2] = a1 as i64; argv[3] = a2 as i64; argv[4] = a3 as i64; argv[5] = a4 as i64; argv[6] = 0 1929 let envp: *i64 = sys_mmap(TFL_I64) as *i64 1930 envp[0] = 0 1931 let logp: *u8 = sys_mmap(TFL_PATHB) 1932 var o: i64 = tfl_cat(logp, 0, out) 1933 o = tfl_cat(logp, o, ".log" as *u8) 1934 let pid: i64 = sys_fork() 1935 if pid < 0 { return 0 - 1 } 1936 if pid == 0 { 1937 let fd: i64 = sys_openat_wr(logp, TFL_MODE644) 1938 if fd >= 0 { sys_dup3(fd, TFL_STDOUT, 0) } 1939 sys_execve(elf, argv, envp) 1940 sys_exit_group(127) 1941 } 1942 let st: *i64 = sys_mmap(2 * TFL_I64) as *i64 1943 st[0] = 0 1944 let w: i64 = sys_wait4(pid, st, 0) 1945 if w < 0 { return 0 - 1 } 1946 return wait_exit_code(st[0]) 1947}