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}