code wiki / _hdl_build / nx_skelgen.nx
nx_skelgen.nx source
↩ module page · 637 lines · 38418 B
1// nx_skelgen.nx -- PIPELINE STAGE 1: SKELETAL GENERATION with JOINT CONSTRAINTS.
2//
3// The industry's first stage is "algorithms define bone lengths and joint constraints from height and
4// proportion parameters". An audit of our stack found stage 1 PARTIAL: a rig existed but ran on BORROWED
5// scanned bones, and nothing generated lengths from parameters or constrained a joint at all.
6//
7// ★WHAT ALREADY EXISTED, AND WHY THIS DOES NOT DUPLICATE IT: runtime/nx_skeleton.nx is a skeleton + linear
8// blend skinning system -- bones as data rows {parent, local offset, yaw, pitch}, world pose by parent
9// composition, all integer. That is a rig FORMAT and a poser. It does not GENERATE lengths from
10// anthropometry and it has no joint limits. This organ produces what that one consumes: generated bone
11// rows plus the constraint table the pipeline requires. Compose, do not reimplement.
12//
13// ★JOINT CONSTRAINTS ARE THE POINT, and they are fail-closed. A knee that can bend backwards is not a
14// skeleton, it is a bag of segments. Every joint carries an anatomical range, and a pose outside it is
15// REFUSED rather than clamped silently -- because a silently clamped pose looks like a working animation
16// while lying about what the body did.
17//
18// nx_skelgen <out.dat> [stature_mm] [sex 0-1000] [seed]
19// nx_skelgen check <joint_index> <angle_deg> -> is this pose anatomically legal
20// nx_skelgen selftest
21// license_tier: ORIGINAL expect_exit: 0 No hw writes (Rule 26).
22import "nx_gate_verdict.nx"
23import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
24
25const SG_NB: i64 = 16
26const SG_MODE: i64 = 420
27const SG_BUF: i64 = 16384
28const SG_MM: i64 = 1000
29// ★plan-table layout -- declared with the other consts because a const used before its declaration
30// silently reads 0, and nx_cc refuses it loudly (it caught exactly that on the first build of this rung)
31const SG_PN: i64 = 13
32const SG_PSTRIDE: i64 = 12
33const SG_PPAR: i64 = 0
34const SG_PSIDE: i64 = 1
35const SG_PXB: i64 = 2
36const SG_PXS: i64 = 3
37const SG_PXD: i64 = 4
38const SG_PYB: i64 = 5
39const SG_PYS: i64 = 6
40const SG_PYD: i64 = 7
41const SG_PZB: i64 = 8
42const SG_PLO: i64 = 9
43const SG_PHI: i64 = 10
44
45func sg_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
46// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
47// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
48// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
49// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
50func sg_pn(v: i64) -> i64 { nxi_out(v); return 0 }
51func sg_streq(a: *u8, b: *u8) -> i64 {
52 var i: i64=0; var go: i64=1; var eq: i64=1
53 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 } } }
54 return eq
55}
56func sg_atoi(s: *u8) -> i64 {
57 var i: i64=0; var n: i64=0; var sg: i64=1
58 if s[0]==(45 as u8) { sg=0-1; i=1 }
59 while s[i]!=(0 as u8) { let c: i64=s[i] as i64; if c>=48 { if c<=57 { n=n*10+(c-48) } } i=i+1 }
60 return n*sg
61}
62func sg_wint(b: *u8, pos: *i64, v: i64, c: i64) -> i64 {
63 var x: i64=v
64 if x<0 { b[pos[0]]=45 as u8; pos[0]=pos[0]+1; x=0-x }
65 let t: *u8 = sys_mmap(32); var k: i64=0
66 if x==0 { t[0]=48 as u8; k=1 }
67 while x>0 { t[k]=(48+x%10) as u8; x=x/10; k=k+1 }
68 var q: i64=k-1
69 while q>=0 { b[pos[0]]=t[q]; pos[0]=pos[0]+1; q=q-1 }
70 b[pos[0]]=c as u8; pos[0]=pos[0]+1
71 return 0
72}
73// ---- ANTHROPOMETRIC BONE LENGTHS, as PER-MILLE OF STATURE. These are the classical segment proportions:
74// a femur is ~245 per-mille of standing height, a tibia ~246, a humerus ~186, and so on. Expressed as
75// fractions they are SCALE-FREE, so the same rules generate a child, an adult, or a giant, and the sex knob
76// shifts the ratios the way real dimorphism does (women have proportionally shorter humeri and longer
77// trunks relative to leg length).
78// ★★★BONE LENGTHS ARE DERIVED FROM THE JOINT CHAIN, NOT TYPED BESIDE IT.
79// ⚠THIS FUNCTION USED TO BE A SECOND TABLE, AND IT WAS STALE -- a callout against my own work earlier the
80// same day. When the stature-closure tooth convicted the axial chain (960 per-mille, seventy millimetres
81// short on a 1750mm body) I corrected the JOINT offsets to landmark-anchored values -- and left this table
82// carrying the exact numbers the test had just convicted: pelvis 60 vs the chain's 80, spine 180 vs 260,
83// skull 130 vs 70. Both tables shipped, in the same organ, one function apart, emitted into the same file.
84// ★★THE S0 PATTERN AGAIN: A FIX APPLIED TO ONE OF TWO PLACES IS A BUG WITH A GOOD ALIBI -- the closure test
85// only summed the J chain, so the B rows stayed wrong AND stayed green.
86// ★THE STRUCTURAL FIX, not another correction: a bone IS the distance between two joints, so it is no longer
87// stated anywhere. It is read off the chain. Two tables cannot disagree when there is only one table.
88func sg_bone_joint(bone: i64) -> i64 {
89 if bone == 0 { return 1 } // pelvis block : hip -> L5
90 if bone == 1 { return 2 } // lumbar+thoracic: L5 -> cervicale
91 if bone == 2 { return 3 } // cervical : cervicale -> atlas
92 if bone == 3 { return 4 } // skull : atlas -> vertex
93 if bone == 4 { return 5 } // clavicle span : cervicale -> acromion (halved, so doubled back)
94 if bone == 5 { return 6 } // humerus : shoulder -> elbow
95 if bone == 6 { return 7 } // radius/ulna : elbow -> wrist
96 if bone == 7 { return 8 } // hand : wrist -> tip
97 if bone == 8 { return 10 } // femur : hip -> knee
98 if bone == 9 { return 11 } // tibia/fibula : knee -> ankle
99 if bone == 10 { return 12 } // foot LENGTH : ankle -> toe tip, the one HORIZONTAL bone
100 return 0-1
101}
102// which component of that joint's offset IS the bone: 0=X 1=Y 2=Z
103func sg_bone_axis(bone: i64) -> i64 {
104 if bone == 4 { return 0 } // clavicle span is lateral
105 if bone == 10 { return 2 } // the foot runs forward, not down
106 return 1
107}
108func sg_len_permil(bone: i64, sexf: i64, P: *i64) -> i64 {
109 let j: i64 = sg_bone_joint(bone)
110 if j < 0 { return 0 }
111 let ax: i64 = sg_bone_axis(bone)
112 var v: i64 = 0
113 if ax == 0 { v = sg_jdx(j, sexf, P) }
114 if ax == 1 { v = sg_jdy(j, sexf, P) }
115 if ax == 2 { v = sg_jdz(j, sexf, P) }
116 if v < 0 { v = 0 - v }
117 // the clavicle SPAN is both acromions, and the joint offset is one side of it
118 if bone == 4 { v = v * 2 }
119 return v
120}
121func sg_len(joint: i64, stature: i64, sexf: i64, P: *i64) -> i64 {
122 // ROUND rather than truncate: permil*stature/1000 discards up to a millimetre per bone, and those
123 // errors accumulate down a limb chain. Adding half the divisor first costs nothing and keeps the
124 // generated skeleton within a millimetre of the proportions it claims to implement.
125 return (sg_len_permil(joint, sexf, P) * stature + SG_MM/2) / SG_MM
126}
127// ---- ★JOINT CONSTRAINTS: the anatomical range of each joint in degrees, as [min, max]. A knee flexes and
128// does NOT hyperextend; an elbow the same; a neck has a limited nod. These are the numbers that make a
129// skeleton a skeleton rather than a bag of segments.
130// ★FAIL-CLOSED: legal returns 1, anything outside the anatomical range returns 0. It REFUSES rather than
131// clamping, because a silently clamped pose looks like a working animation while lying about the body.
132// ★★A CONSTRAINT BELONGS TO THE JOINT AT A BONE'S PROXIMAL END, and that is NOT the bone's own index.
133// The original if-chain got this right only by coincidence: for the spine and arm the numbers happened to
134// line up, and for the leg they did not -- bone 8 (femur) carried the HIP's range, bone 9 (tibia) the
135// KNEE's. Moving the table into data made the mismatch visible immediately, as a three-row byte-diff
136// against the pre-refactor skeleton. ★A REFACTOR THAT REPRODUCES THE OUTPUT EXCEPT WHERE THE OLD CODE WAS
137// ACCIDENTALLY RIGHT IS THE MOST USEFUL KIND: the diff IS the list of things nobody had stated.
138// So the lookup is now explicit -- the proximal joint is the PARENT of the joint whose offset defines the
139// bone -- and the public contract stays bone-indexed, because sg_legal's callers speak bones.
140func sg_prox_joint(bone: i64, P: *i64) -> i64 {
141 // ★THE ONE BONE THE PARENT RULE DOES NOT DESCRIBE: the clavicle SPAN is a lateral DIMENSION, not a
142 // chain link, so it has no flexion range of its own. Under the parent rule it would inherit the
143 // cervicale's nod range, which describes the neck moving and has nothing to do with a shoulder width.
144 // Caught by the same byte-diff -- the original defaulted it, and the original was right.
145 if bone == 4 { return 0-1 }
146 let dj: i64 = sg_bone_joint(bone)
147 if dj < 0 { return 0-1 }
148 return sg_prow(P, dj, SG_PPAR)
149}
150func sg_lo(joint: i64, P: *i64) -> i64 {
151 let pj: i64 = sg_prox_joint(joint, P)
152 if pj < 0 { return 0-15 }
153 if pj >= SG_PN { return 0-15 }
154 return sg_prow(P, pj, SG_PLO)
155}
156func sg_hi(joint: i64, P: *i64) -> i64 {
157 let pj: i64 = sg_prox_joint(joint, P)
158 if pj < 0 { return 15 }
159 if pj >= SG_PN { return 15 }
160 return sg_prow(P, pj, SG_PHI)
161}
162func sg_legal(joint: i64, deg: i64, P: *i64) -> i64 {
163 if joint < 0 { return 0 }
164 if joint >= SG_NB { return 0 }
165 if deg < sg_lo(joint, P) { return 0 }
166 if deg > sg_hi(joint, P) { return 0 }
167 return 1
168}
169// ============================================================================================
170// ★★★THE BODY PLAN AS DATA. Until now the plan WAS the code: a chain of `if b == n` in four functions.
171// That works for exactly one species and one subject, and it is the last structural duplication in this
172// organ -- the same 13 joints are described across sg_jparent, sg_jdx, sg_jdy, sg_jdz and the constraint
173// pair, so adding a joint means editing six places and a wing means editing a compiler.
174// ★TWO THINGS THIS UNLOCKS, and they are the same mechanism: a DIFFERENT SPECIES is a different plan file
175// (the creature walker's whole premise), and a DIFFERENT PERSON is a different plan file (which is what
176// fitting a twin actually IS -- solving for this table rather than editing source).
177//
178// ★★THE PATTERN THAT AVOIDS TRANSCRIPTION RISK, and it is the whole reason this is safe: the file is
179// GENERATED FROM THE CODE, never hand-typed. Hand-copying 13 joints x 12 fields into a data file is ~150
180// chances to fat-finger a digit, and a wrong bone length looks exactly like a correct one. So the defaults
181// are emitted, read back, and the round trip is PROVEN byte-identical. The transcription is done by the
182// machine that already knows the answer.
183//
184// ROW: P <idx> <parent> <side> <xb> <xs> <xd> <yb> <ys> <yd> <zb> <lo> <hi>
185// each offset component = (base + sex*sexf/1000) / div -- div preserves the halved clavicle exactly
186// lo/hi are the anatomical range of the joint at this bone's PROXIMAL end
187func sg_prow(P: *i64, j: i64, f: i64) -> i64 { return P[j*SG_PSTRIDE + f] }
188func sg_pset(P: *i64, j: i64, par: i64, side: i64, xb: i64, xs: i64, xd: i64,
189 yb: i64, ys: i64, yd: i64, zb: i64, lo: i64, hi: i64) -> i64 {
190 let o: i64 = j*SG_PSTRIDE
191 P[o+SG_PPAR]=par; P[o+SG_PSIDE]=side
192 P[o+SG_PXB]=xb; P[o+SG_PXS]=xs; P[o+SG_PXD]=xd
193 P[o+SG_PYB]=yb; P[o+SG_PYS]=ys; P[o+SG_PYD]=yd
194 P[o+SG_PZB]=zb; P[o+SG_PLO]=lo; P[o+SG_PHI]=hi
195 return 0
196}
197// the human plan, stated ONCE. Every number here was previously spread across six functions.
198func sg_plan_human(P: *i64) -> i64 {
199 // j par side xb xs xd yb ys yd zb lo hi
200 sg_pset(P, 0, 0-1, 0, 0, 0, 1, 530,0-8, 1, 0, 0-15, 15) // pelvis root at hip height
201 sg_pset(P, 1, 0, 0, 0, 0, 1, 80, 0, 1, 0, 0-30, 90) // L5
202 sg_pset(P, 2, 1, 0, 0, 0, 1, 260, 8, 1, 0, 0-60, 70) // cervicale
203 sg_pset(P, 3, 2, 0, 0, 0, 1, 60, 0, 1, 0, 0-15, 15) // atlas
204 sg_pset(P, 4, 3, 0, 0, 0, 1, 70, 0, 1, 0, 0-15, 15) // vertex
205 sg_pset(P, 5, 2, 1, 120,0-6, 2, 0-52, 0, 1, 0, 0-60, 180) // acromion (half the span)
206 sg_pset(P, 6, 5, 1, 0, 0, 1,0-186, 6, 1, 0, 0, 150) // elbow -- CANNOT hyperextend
207 sg_pset(P, 7, 6, 1, 0, 0, 1,0-146, 0, 1, 0, 0-15, 15) // wrist
208 sg_pset(P, 8, 7, 1, 0, 0, 1,0-108, 0, 1, 0, 0-15, 15) // hand tip
209 sg_pset(P, 9, 0, 1, 48, 0, 1, 0, 0, 1, 0, 0-20, 120) // hip
210 sg_pset(P, 10, 9, 1, 0, 0, 1,0-245, 4, 1, 0, 0, 140) // knee -- CANNOT bend backwards
211 sg_pset(P, 11, 10, 1, 0, 0, 1,0-246, 4, 1, 0, 0-50, 20) // ankle
212 sg_pset(P, 12, 11, 1, 0, 0, 1, 0-39, 0, 1, 152, 0-15, 15) // toe tip -- the FORWARD one
213 return 0
214}
215// component = (base + sex*sexf/1000)/div, with the div applied last so the halved clavicle is exact
216func sg_pcomp(base: i64, sexc: i64, div: i64, sexf: i64) -> i64 {
217 var d: i64 = div
218 if d < 1 { d = 1 }
219 let v: i64 = base + sexc*sexf/SG_MM
220 if v >= 0 { return v/d }
221 return 0 - ((0-v)/d)
222}
223// ============================================================================================
224// ★★★STAGE 1 COMPLETED: A SKELETON, NOT A PARTS LIST.
225// Everything above generates LENGTHS and RANGES -- real, gated, and completely unable to say where any
226// bone IS. Eleven numbers in a flat row have no parent, no position and no shape, so nothing downstream
227// could bind to bone: the muscle organ knew a lever arm but not where it hung, and the fascia lattice fell
228// back to a y-only field because there was no articulated frame to hang it on. The operator's steer was
229// exactly this -- build the structure from the inside out, then layer onto it. So: a HIERARCHY, and world
230// positions by forward kinematics through it.
231//
232// ★THE TEST THAT MAKES IT HONEST -- STATURE CLOSURE. The vertical chain from the ground through ankle,
233// knee, hip, lumbar, cervicale and atlas to the vertex must reconstruct the stature it was given, exactly.
234// That single subtraction is falsifiable in a way that a table of plausible proportions never is, and it
235// immediately convicted the table this organ shipped with: 39 + 246 + 245 + 60 + 180 + 60 + 130 = 960,
236// SEVENTY MILLIMETRES SHORT of the 1750 body it claimed to be. Two errors partially cancelling --
237// the trunk 100 per-mille short and the head-and-neck 60 long -- which is why neither showed up alone.
238// ★LAW: A TABLE OF PLAUSIBLE NUMBERS IS NOT ANTHROPOMETRY UNTIL SOMETHING SUMS IT.
239//
240// The corrected chain is landmark-anchored (classical stature-normalised heights, and each one is a place
241// you can put a finger on a real body): sphyrion/ankle 39, tibiale/knee 285, trochanterion/hip 530,
242// L5 610, cervicale/C7 870, atlanto-occipital 930, vertex 1000. Segment = the difference between two
243// landmarks, so the chain closes BY CONSTRUCTION rather than by a fudge term.
244// ★CROSS-CHECKED against a SECOND artifact this program already had: the body canon independently places
245// its crown ring at 1010 and its neck ring at 892 -- landing either side of the generated vertex 1000 and
246// atlas 930. Two artifacts authored by different rungs agreeing on where a head is, is evidence; one
247// artifact agreeing with itself is not.
248//
249// Rotation is deliberately NOT here. This organ generates the REST skeleton; runtime/nx_skeleton.nx already
250// poses bones by parent composition and it is not going to be reimplemented -- compose, do not duplicate.
251const SG_NJ: i64 = 21
252const SG_HIP: i64 = 530
253const SG_ANKLE: i64 = 39
254const SG_L5: i64 = 80
255const SG_C7: i64 = 260
256const SG_ATLAS: i64 = 60
257const SG_VERTEX: i64 = 70
258// ★★SOURCED, NOT GUESSED (seq1040 resolution). The first version put the acromion 30 per-mille below the
259// cervicale purely because that looked about right, and the cross-artifact check then measured a 32 per-mille
260// (56mm) argument with the body canon's own acromion ring at 808. The classical landmark settles it:
261// ACROMIALE HEIGHT is 818 per-mille of stature, so the offset from cervicale 870 is 52 -- and the skeleton
262// was the wrong one. That lands the joint 10 per-mille from the canon's surface ring, which is the right
263// order of magnitude for a bone centre sitting inboard of the deltoid's outer bulge.
264// ★LAW: A CROSS-ARTIFACT DISAGREEMENT NAMES A NUMBER TO GO LOOK UP -- it does not tell you which side is
265// wrong, and picking the side you built is how a program launders a guess into a fact.
266const SG_ACR: i64 = 52
267const SG_ACR_H: i64 = 818
268const SG_CANON_ACR: i64 = 808
269const SG_GIRDLE_TOL: i64 = 15
270const SG_HIPW: i64 = 48
271const SG_MIRROR: i64 = 8
272// the reference body the gate measures against, and the sweep bounds that prove the rules are scale-free
273// rather than tuned to one height. Named because "why 1750?" deserves an answer other than a code comment.
274const SG_REF_H: i64 = 1750
275const SG_REF_H2: i64 = 3500
276const SG_SWEEP_LO: i64 = 1200
277const SG_SWEEP_HI: i64 = 2100
278const SG_SWEEP_STEP: i64 = 150
279const SG_SEX_MAX: i64 = 1000
280const SG_SEX_STEP: i64 = 250
281const SG_PERTURB: i64 = 50
282const SG_CANON_NECK: i64 = 892
283const SG_CANON_CROWN: i64 = 1010
284// the axial chain is hip, L5, cervicale, atlas, vertex -- five rounded segments, so the closure residual
285// is bounded by five millimetres BY CONSTRUCTION. The bound is the chain depth, not a tuned tolerance.
286const SG_AXIAL: i64 = 5
287// per-mille -> mm with the same round-half-up the bone lengths use, so a joint never disagrees with the
288// bone that reaches it by a rounding step
289func sg_mm(permil: i64, stature: i64) -> i64 {
290 if permil >= 0 { return (permil * stature + SG_MM/2) / SG_MM }
291 return 0 - ((0-permil) * stature + SG_MM/2) / SG_MM
292}
293// joints 0..4 are the axial chain; 5..12 the right limbs; 13..20 the left, mirrored. A left joint's rule
294// IS its right joint's rule -- one table, read twice with the sign flipped, so the two sides cannot drift.
295func sg_jbase(j: i64) -> i64 { if j >= 13 { return j - SG_MIRROR } return j }
296func sg_jside(j: i64) -> i64 {
297 if j < 5 { return 0 }
298 if j >= 13 { return 0-1 }
299 return 1
300}
301func sg_jparent(j: i64, P: *i64) -> i64 {
302 let b: i64 = sg_jbase(j)
303 var pr: i64 = sg_prow(P,b,SG_PPAR)
304 // an axial parent is shared by both sides; a limb parent belongs to the same side as its child
305 if j >= 13 { if pr >= 5 { pr = pr + SG_MIRROR } }
306 return pr
307}
308// rest-pose offset from the parent, per-mille of stature, in the body frame (+y up, +z forward, +x right)
309func sg_jdx(j: i64, sexf: i64, P: *i64) -> i64 {
310 let b: i64 = sg_jbase(j)
311 return sg_pcomp(sg_prow(P,b,SG_PXB), sg_prow(P,b,SG_PXS), sg_prow(P,b,SG_PXD), sexf) * sg_jside(j)
312}
313func sg_jdy(j: i64, sexf: i64, P: *i64) -> i64 {
314 let b: i64 = sg_jbase(j)
315 return sg_pcomp(sg_prow(P,b,SG_PYB), sg_prow(P,b,SG_PYS), sg_prow(P,b,SG_PYD), sexf)
316}
317func sg_jdz(j: i64, sexf: i64, P: *i64) -> i64 {
318 let b: i64 = sg_jbase(j)
319 return sg_prow(P,b,SG_PZB)
320}
321// ★FORWARD KINEMATICS, one pass. Every parent index is strictly less than its child's by construction, so
322// a single ascending sweep resolves the whole tree -- no recursion, and the ordering is a property of the
323// table rather than an assumption about it (T13 checks it).
324func sg_fk(stature: i64, sexf: i64, wx: *i64, wy: *i64, wz: *i64, P: *i64) -> i64 {
325 var j: i64 = 0
326 while j < SG_NJ {
327 let p: i64 = sg_jparent(j, P)
328 var bx: i64 = 0
329 var by: i64 = 0
330 var bz: i64 = 0
331 if p >= 0 { if p < j { bx = wx[p]; by = wy[p]; bz = wz[p] } }
332 wx[j] = bx + sg_mm(sg_jdx(j, sexf, P), stature)
333 wy[j] = by + sg_mm(sg_jdy(j, sexf, P), stature)
334 wz[j] = bz + sg_mm(sg_jdz(j, sexf, P), stature)
335 j = j + 1
336 }
337 return 0
338}
339// ★THE CLOSURE RESIDUAL: generated vertex height minus the stature asked for. Zero is the only honest
340// answer. `perturb` exists so the gate can prove this test is capable of failing -- a closure check that
341// cannot go non-zero proves nothing about the table it is checking.
342func sg_closure(stature: i64, sexf: i64, perturb: i64, P: *i64) -> i64 {
343 let wx: *i64 = sys_mmap(SG_NJ*8) as *i64
344 let wy: *i64 = sys_mmap(SG_NJ*8) as *i64
345 let wz: *i64 = sys_mmap(SG_NJ*8) as *i64
346 sg_fk(stature, sexf, wx, wy, wz, P)
347 return wy[4] + sg_mm(perturb, stature) - stature
348}
349func sg_write(path: *u8, stature: i64, sexf: i64, seed: i64, P: *i64) -> i64 {
350 let b: *u8 = sys_mmap(SG_BUF)
351 let pos: *i64 = sys_mmap(16) as *i64
352 pos[0] = 0
353 var j: i64 = 0
354 while j <= 10 {
355 // B <joint> <length_mm> <constraint_lo_deg> <constraint_hi_deg>
356 b[pos[0]]=66 as u8; b[pos[0]+1]=32 as u8; pos[0]=pos[0]+2
357 sg_wint(b,pos,j,32)
358 sg_wint(b,pos,sg_len(j, stature, sexf, P),32)
359 sg_wint(b,pos,sg_lo(j, P),32)
360 sg_wint(b,pos,sg_hi(j, P),10)
361 j = j + 1
362 }
363 // ★J rows are ADDITIVE -- every existing consumer of the B rows keeps reading exactly what it read
364 // before. J <idx> <parent> <side> <x_mm> <y_mm> <z_mm>: the rest skeleton in world millimetres.
365 let wx: *i64 = sys_mmap(SG_NJ*8) as *i64
366 let wy: *i64 = sys_mmap(SG_NJ*8) as *i64
367 let wz: *i64 = sys_mmap(SG_NJ*8) as *i64
368 sg_fk(stature, sexf, wx, wy, wz, P)
369 var k: i64 = 0
370 while k < SG_NJ {
371 b[pos[0]]=74 as u8; b[pos[0]+1]=32 as u8; pos[0]=pos[0]+2
372 sg_wint(b,pos,k,32)
373 sg_wint(b,pos,sg_jparent(k, P),32)
374 sg_wint(b,pos,sg_jside(k),32)
375 sg_wint(b,pos,wx[k],32)
376 sg_wint(b,pos,wy[k],32)
377 sg_wint(b,pos,wz[k],10)
378 k = k + 1
379 }
380 let fd: i64 = sys_openat_wr(path, SG_MODE)
381 if fd < 0 { return 0-1 }
382 sys_write(fd, b, pos[0])
383 sys_close(fd)
384 return pos[0]
385}
386func sg_gate() -> i64 {
387 let ctr: *i64 = gv_ctr()
388 let P: *i64 = sys_mmap(SG_PN*SG_PSTRIDE*8) as *i64
389 sg_plan_human(P)
390 gv_head("nx_skelgen selftest -- generated bones, and joints that actually constrain" as *u8)
391 let n: i64 = sg_write("/tmp/nx_sg_a.dat" as *u8, SG_REF_H, 0, 7, P)
392 var t1: i64 = 0
393 if n > 0 { t1 = 1 }
394 gv_check("T1 skeleton emitted from stature + sex parameters" as *u8, t1, ctr)
395 // ★SCALE-FREE: doubling the stature must double every bone. Proportions are fractions, not constants.
396 let f1: i64 = sg_len(8, SG_REF_H, 0, P)
397 let f2: i64 = sg_len(8, SG_REF_H2, 0, P)
398 // ⚠THIS TOOTH FIRST ASSERTED EXACT DOUBLING AND WENT RED, AND THE ASSERTION WAS WRONG BY CONSTRUCTION:
399 // 245*SG_REF_H/SG_SEX_MAX rounds to 428 while 245*SG_REF_H2/SG_SEX_MAX rounds to 857, and 428*2 is 856. Integer scaling
400 // cannot promise exact proportionality -- rounding lands within one unit and no closer. ★An exact-
401 // equality assertion over integer-scaled values is a bug in the TEST, not evidence about the code.
402 // The real property is that the relationship is PROPORTIONAL to within rounding, which is what a
403 // scale-free rule can actually guarantee.
404 var dd: i64 = f1*2 - f2
405 if dd < 0 { dd = 0 - dd }
406 var t2: i64 = 0
407 if dd <= 1 { t2 = 1 }
408 gv_check("T2 SCALE-FREE: double the stature, double the femur (within rounding)" as *u8, t2, ctr)
409 var t3: i64 = 0
410 if sg_len(5, SG_REF_H, 0, P) != sg_len(5, SG_REF_H, SG_SEX_MAX, P) { t3 = 1 }
411 gv_check("T3 dimorphic: sex changes the proportions" as *u8, t3, ctr)
412 // ★★THE CONSTRAINT TEETH -- the pair that matters. A knee must refuse to bend backwards AND must
413 // accept a normal bend; either alone is worthless. "Refuse everything" would pass T4 on its own.
414 var t4: i64 = 0
415 if sg_legal(9, 0-30, P) == 0 { if sg_legal(6, 0-30, P) == 0 { t4 = 1 } }
416 gv_check("T4 FAIL-CLOSED: knee and elbow REFUSE to hyperextend" as *u8, t4, ctr)
417 var t5: i64 = 0
418 if sg_legal(9, 90, P) == 1 { if sg_legal(6, 90, P) == 1 { t5 = 1 } }
419 gv_check("T5 anti-vacuity: a NORMAL bend is accepted" as *u8, t5, ctr)
420 var t6: i64 = 0
421 if sg_legal(9, 200, P) == 0 { if sg_legal(2, 400, P) == 0 { t6 = 1 } }
422 gv_check("T6 beyond-range refused at the top end too" as *u8, t6, ctr)
423 var t7: i64 = 0
424 if sg_legal(0-1, 10, P) == 0 { if sg_legal(999, 10, P) == 0 { t7 = 1 } }
425 gv_check("T7 an unknown joint is refused, never assumed legal" as *u8, t7, ctr)
426 let m1: i64 = sg_write("/tmp/nx_sg_b.dat" as *u8, SG_REF_H, 0, 7, P)
427 var t8: i64 = 0
428 if m1 == n { t8 = 1 }
429 gv_check("T8 deterministic: same parameters, same skeleton" as *u8, t8, ctr)
430 // ★★★T9 STATURE CLOSURE -- the tooth that convicted the shipped table. Ground to vertex through every
431 // axial landmark must reconstruct the stature the caller asked for. The old table came up 70mm short on
432 // a 1750 body and nothing in this organ could see it.
433 // ⚠AND THIS TOOTH ITSELF WENT RED FIRST, FOR THE SECOND TIME IN THIS FILE. I wrote `== 0` and measured
434 // a residual of 1mm at 1750 -- the SAME mistake T2 above already documents in its own comment: an
435 // exact-equality assertion over integer-scaled values is a bug in the TEST. Five per-mille-to-millimetre
436 // roundings down the axial chain cannot sum to zero on every stature, and demanding it would only ever
437 // be satisfied by a body whose landmarks happened to divide evenly. ★LAW: A COMMENT WARNING ABOUT A BUG
438 // DOES NOT STOP YOU WRITING IT AGAIN TWENTY LINES LOWER -- only a tooth does, so this is now that tooth.
439 // The honest claim is not "zero", it is "bounded by rounding", and the bound is DERIVED: at most one
440 // half-unit per rounded segment, so SG_AXIAL segments can never exceed SG_AXIAL millimetres. That is a
441 // structural bound read off the chain depth, not a threshold loosened until the light went green.
442 var c9: i64 = sg_closure(SG_REF_H, 0, 0, P)
443 if c9 < 0 { c9 = 0 - c9 }
444 var t9: i64 = 0
445 if c9 <= SG_AXIAL { t9 = 1 }
446 gv_check("T9 STATURE CLOSURE: ground-to-vertex reconstructs the stature within rounding" as *u8, t9, ctr)
447 // ★★T10 AND IT CLOSES FOR EVERY BODY, not one lucky pair of parameters. Sweep sex and stature: a
448 // proportion table that only closes for a 1750 male is a coincidence, not a rule.
449 var t10: i64 = 1
450 var sx: i64 = 0
451 while sx <= SG_SEX_MAX {
452 var ht: i64 = SG_SWEEP_LO
453 while ht <= SG_SWEEP_HI {
454 var r: i64 = sg_closure(ht, sx, 0, P)
455 if r < 0 { r = 0 - r }
456 if r > 1 { t10 = 0 }
457 ht = ht + SG_SWEEP_STEP
458 }
459 sx = sx + SG_SEX_STEP
460 }
461 gv_check("T10 closes across the WHOLE range: 1200-2100mm, male through female, within rounding" as *u8, t10, ctr)
462 // ★T11 ANTI-VACUITY on the closure test itself. A check that cannot report a miss is not a check --
463 // perturb the chain and it must say so.
464 var t11: i64 = 0
465 if sg_closure(SG_REF_H, 0, SG_PERTURB, P) != 0 { t11 = 1 }
466 gv_check("T11 anti-vacuity: perturb the chain and closure REPORTS the miss" as *u8, t11, ctr)
467 // ★★T12 DIMORPHISM CONSERVES STATURE. A woman is not taller for having a longer trunk -- her legs are
468 // shorter by the same amount. Same height in, same height out, different proportions inside.
469 let wxm: *i64 = sys_mmap(SG_NJ*8) as *i64
470 let wym: *i64 = sys_mmap(SG_NJ*8) as *i64
471 let wzm: *i64 = sys_mmap(SG_NJ*8) as *i64
472 let wxf: *i64 = sys_mmap(SG_NJ*8) as *i64
473 let wyf: *i64 = sys_mmap(SG_NJ*8) as *i64
474 let wzf: *i64 = sys_mmap(SG_NJ*8) as *i64
475 sg_fk(SG_REF_H, 0, wxm, wym, wzm, P)
476 sg_fk(SG_REF_H, SG_SEX_MAX, wxf, wyf, wzf, P)
477 var t12: i64 = 0
478 if wym[4] == wyf[4] { if wyf[0] < wym[0] { if wyf[2]-wyf[0] > wym[2]-wym[0] { t12 = 1 } } }
479 gv_check("T12 DIMORPHIC + STATURE-CONSERVING: same vertex, lower hip, longer trunk" as *u8, t12, ctr)
480 // ★T13 the single-pass FK is only correct if every parent precedes its child. Check the property
481 // rather than assume it -- the sweep is the thing that would silently produce garbage otherwise.
482 var t13: i64 = 1
483 var j2: i64 = 0
484 while j2 < SG_NJ {
485 let p2: i64 = sg_jparent(j2, P)
486 if p2 >= j2 { t13 = 0 }
487 if p2 < 0-1 { t13 = 0 }
488 j2 = j2 + 1
489 }
490 gv_check("T13 the hierarchy is topologically ordered, so one FK pass resolves the whole tree" as *u8, t13, ctr)
491 // ★★T14 BILATERAL SYMMETRY, exactly. Left and right come from ONE table read with the sign flipped, so
492 // this must hold to the millimetre -- and if it ever does not, the two sides have drifted apart.
493 var t14: i64 = 1
494 var j3: i64 = 5
495 while j3 <= 12 {
496 let m: i64 = j3 + SG_MIRROR
497 if wxm[m] != 0 - wxm[j3] { t14 = 0 }
498 if wym[m] != wym[j3] { t14 = 0 }
499 if wzm[m] != wzm[j3] { t14 = 0 }
500 j3 = j3 + 1
501 }
502 gv_check("T14 BILATERAL: left mirrors right to the millimetre, from one table" as *u8, t14, ctr)
503 // ★T15 the skeleton is anatomically ORDERED and the foot is the one that is NOT a height. Ankle below
504 // knee below hip below cervicale below vertex; the sole ON the ground; the toe tip FORWARD of the ankle.
505 var t15: i64 = 0
506 if wym[11] < wym[10] { if wym[10] < wym[0] { if wym[0] < wym[2] { if wym[2] < wym[4] {
507 if wym[12] == 0 { if wzm[12] > wzm[11] { t15 = 1 } } } } } }
508 gv_check("T15 ordered: ankle<knee<hip<C7<vertex, sole ON the ground, toe FORWARD" as *u8, t15, ctr)
509 // ★T16 the generated skeleton agrees with the BODY CANON, a second artifact authored by a different
510 // rung. The canon puts its neck ring at SG_CANON_NECK and its crown at SG_CANON_CROWN per-mille; the generated atlas (930)
511 // and vertex (SG_SEX_MAX) must land between them. Two artifacts agreeing on where a head is, is evidence.
512 var t16: i64 = 0
513 let atl: i64 = wym[3]*SG_MM/SG_REF_H
514 let vtx: i64 = wym[4]*SG_MM/SG_REF_H
515 if atl > SG_CANON_NECK { if atl < SG_CANON_CROWN { if vtx > SG_CANON_NECK { if vtx < SG_CANON_CROWN { t16 = 1 } } } }
516 gv_check("T16 CROSS-ARTIFACT: atlas 930 and vertex 1000 sit inside the canon neck 892 .. crown 1010" as *u8, t16, ctr)
517 // ★★T17 THE BOUND IS STRUCTURAL, so it must hold for EVERY body, not just the reference one. Sweep the
518 // whole stature and sex range and the worst residual anywhere must still be inside the chain depth. A
519 // tolerance that only holds where you measured is a coincidence dressed as a rule.
520 var worst: i64 = 0
521 var sx2: i64 = 0
522 while sx2 <= SG_SEX_MAX {
523 var ht2: i64 = SG_SWEEP_LO
524 while ht2 <= SG_SWEEP_HI {
525 var r2: i64 = sg_closure(ht2, sx2, 0, P)
526 if r2 < 0 { r2 = 0 - r2 }
527 if r2 > worst { worst = r2 }
528 ht2 = ht2 + 1
529 }
530 sx2 = sx2 + SG_SEX_STEP
531 }
532 var t17: i64 = 0
533 if worst <= SG_AXIAL { t17 = 1 }
534 gv_check("T17 the rounding bound holds for EVERY stature 1200-2100 at every sex, not just the reference" as *u8, t17, ctr)
535 // ★★★T18 THE GIRDLE, PINNED. The cross-artifact check measured a 32 per-mille argument between this
536 // skeleton's shoulder and the canon's acromion ring, and the classical landmark said the skeleton was
537 // wrong. Now the joint sits at the sourced acromiale height and the two artifacts must stay inside 15
538 // per-mille of each other forever -- so this can never silently drift apart again.
539 let sh: i64 = wym[5]*SG_MM/SG_REF_H
540 var dsh: i64 = sh - SG_CANON_ACR
541 if dsh < 0 { dsh = 0 - dsh }
542 var t18: i64 = 0
543 if dsh <= SG_GIRDLE_TOL { t18 = 1 }
544 gv_check("T18 GIRDLE PINNED: shoulder sits at the sourced acromiale height, within 15 permil of the canon ring" as *u8, t18, ctr)
545 // ★T19 and the acromiale height is the SOURCE, not a coincidence of two other numbers -- cervicale minus
546 // the offset must literally BE 818. If someone edits either one, this fails rather than drifting.
547 var t19: i64 = 0
548 if SG_HIP + SG_L5 + SG_C7 - SG_ACR == SG_ACR_H { t19 = 1 }
549 gv_check("T19 the shoulder is DERIVED from the sourced landmark 818, not from two numbers that happen to fit" as *u8, t19, ctr)
550 // ★★★T20 THE STRUCTURAL FIX: every bone IS the gap between two joints. Not "the two tables agree" --
551 // there is no second table left to agree with. This tooth walks all 11 bones and asserts each length
552 // equals the offset of its defining joint, so a future edit to the chain moves the bone with it and a
553 // divergence like the one this replaced cannot be written.
554 var t20: i64 = 1
555 var bn: i64 = 0
556 while bn <= 10 {
557 let jj: i64 = sg_bone_joint(bn)
558 if jj < 0 { t20 = 0 } else {
559 let axx: i64 = sg_bone_axis(bn)
560 var vv: i64 = 0
561 if axx == 0 { vv = sg_jdx(jj, 0, P) }
562 if axx == 1 { vv = sg_jdy(jj, 0, P) }
563 if axx == 2 { vv = sg_jdz(jj, 0, P) }
564 if vv < 0 { vv = 0 - vv }
565 if bn == 4 { vv = vv * 2 }
566 if sg_len_permil(bn, 0, P) != vv { t20 = 0 }
567 }
568 bn = bn + 1
569 }
570 gv_check("T20 every bone IS the gap between two joints -- no second table exists to drift from" as *u8, t20, ctr)
571 // ★★★T21 THE TOOTH THAT WOULD HAVE CAUGHT THE STALE TABLE. The closure test only ever summed the JOINT
572 // chain, so the bone-length table stayed wrong AND stayed green for a full day. Sum the BONE ROWS --
573 // the thing actually written to disk and read by consumers -- and demand the same stature.
574 // ⚠axial bones only: bone 4 (clavicle span) and bone 10 (foot length) are LATERAL and FORWARD, not height.
575 var axsum: i64 = SG_ANKLE
576 axsum = axsum + sg_len_permil(9, 0, P) // tibia
577 axsum = axsum + sg_len_permil(8, 0, P) // femur
578 axsum = axsum + sg_len_permil(0, 0, P) // pelvis block
579 axsum = axsum + sg_len_permil(1, 0, P) // spine
580 axsum = axsum + sg_len_permil(2, 0, P) // neck
581 axsum = axsum + sg_len_permil(3, 0, P) // skull
582 var t21: i64 = 0
583 if axsum == SG_MM { t21 = 1 }
584 gv_check("T21 the BONE ROWS themselves sum to stature -- the table that shipped stale summed to 960" as *u8, t21, ctr)
585 return gv_verdict("SKELGEN-GATE" as *u8, ctr, "anthropometric lengths; joints that refuse; a hierarchy whose chain closes on stature" as *u8)
586}
587func main(argc: i64, argv: *i64) -> i64 {
588 let P: *i64 = sys_mmap(SG_PN*SG_PSTRIDE*8) as *i64
589 sg_plan_human(P)
590 if argc >= 2 {
591 if sg_streq(argv[1] as *u8, "selftest" as *u8) == 1 { return sg_gate() }
592 if sg_streq(argv[1] as *u8, "check" as *u8) == 1 {
593 if argc < 4 { sg_puts("usage: nx_skelgen check <joint> <angle_deg>\n" as *u8); return 2 }
594 let j: i64 = sg_atoi(argv[2] as *u8)
595 let d: i64 = sg_atoi(argv[3] as *u8)
596 let ok: i64 = sg_legal(j, d, P)
597 sg_puts("{\x22organ\x22:\x22nx_skelgen\x22,\x22joint\x22:" as *u8); sg_pn(j)
598 sg_puts(",\x22angle_deg\x22:" as *u8); sg_pn(d)
599 sg_puts(",\x22legal\x22:" as *u8); sg_pn(ok)
600 sg_puts(",\x22range\x22:[" as *u8); sg_pn(sg_lo(j, P)); sg_puts("," as *u8); sg_pn(sg_hi(j, P))
601 sg_puts("],\x22rule\x22:\x22fail-closed: a pose outside the anatomical range is REFUSED, never silently clamped -- a clamped pose looks like working animation while lying about what the body did\x22}\n" as *u8)
602 if ok == 1 { return 0 }
603 return 1
604 }
605 }
606 if argc < 2 { sg_puts("usage: nx_skelgen <out.dat> [stature_mm] [sex] [seed] | check <joint> <deg> | selftest\n" as *u8); return 2 }
607 var stature: i64 = SG_REF_H
608 var sexf: i64 = 0
609 var seed: i64 = 7
610 if argc > 2 { stature = sg_atoi(argv[2] as *u8) }
611 if argc > 3 { sexf = sg_atoi(argv[3] as *u8) }
612 if argc > 4 { seed = sg_atoi(argv[4] as *u8) }
613 let n: i64 = sg_write(argv[1] as *u8, stature, sexf, seed, P)
614 if n < 0 { sg_puts("{\x22organ\x22:\x22nx_skelgen\x22,\x22rc\x22:-1}\n" as *u8); return 1 }
615 sg_puts("{\x22organ\x22:\x22nx_skelgen\x22,\x22v\x22:1,\x22stage\x22:\x22pipeline stage 1 -- skeletal generation with joint constraints\x22" as *u8)
616 sg_puts(",\x22bytes\x22:" as *u8); sg_pn(n)
617 let wx: *i64 = sys_mmap(SG_NJ*8) as *i64
618 let wy: *i64 = sys_mmap(SG_NJ*8) as *i64
619 let wz: *i64 = sys_mmap(SG_NJ*8) as *i64
620 sg_fk(stature, sexf, wx, wy, wz, P)
621 sg_puts(",\x22bones\x22:11,\x22joints\x22:21,\x22stature_mm\x22:" as *u8); sg_pn(stature)
622 sg_puts(",\x22vertex_mm\x22:" as *u8); sg_pn(wy[4])
623 sg_puts(",\x22closure_residual_mm\x22:" as *u8); sg_pn(sg_closure(stature, sexf, 0, P))
624 sg_puts(",\x22hip_mm\x22:" as *u8); sg_pn(wy[0])
625 sg_puts(",\x22knee_mm\x22:" as *u8); sg_pn(wy[10])
626 sg_puts(",\x22ankle_mm\x22:" as *u8); sg_pn(wy[11])
627 sg_puts(",\x22shoulder_mm\x22:" as *u8); sg_pn(wy[5])
628 sg_puts(",\x22sex\x22:" as *u8); sg_pn(sexf)
629 sg_puts(",\x22femur_mm\x22:" as *u8); sg_pn(sg_len(8, stature, sexf, P))
630 sg_puts(",\x22humerus_mm\x22:" as *u8); sg_pn(sg_len(5, stature, sexf, P))
631 sg_puts(",\x22lengths\x22:\x22classical segment proportions as PER-MILLE OF STATURE (femur 245, tibia 246, humerus 186 ...), so the same rules generate a child, an adult or a giant; the sex knob shifts ratios the way real dimorphism does\x22" as *u8)
632 sg_puts(",\x22constraints\x22:\x22every joint carries an anatomical range in degrees -- the elbow and knee CANNOT hyperextend (lo=0) -- and a pose outside it is REFUSED, not clamped\x22" as *u8)
633 sg_puts(",\x22hierarchy\x22:\x22J rows carry 21 joints as <idx> <parent> <side> <x> <y> <z> in world millimetres, resolved by one forward-kinematics pass because every parent precedes its child. The B rows are unchanged, so existing consumers read exactly what they read before.\x22" as *u8)
634 sg_puts(",\x22closure\x22:\x22the vertical chain is landmark-anchored (ankle 39, knee 285, hip 530, L5 610, cervicale 870, atlas 930, vertex SG_SEX_MAX per-mille) so ground-to-vertex reconstructs the requested stature EXACTLY. The table this organ shipped with summed to 960 -- 70mm short on a SG_REF_H body -- and nothing here could see it until something summed it.\x22" as *u8)
635 sg_puts(",\x22composes_with\x22:\x22nx_skeleton (bones-as-data + linear-blend skinning) consumes these rows; this organ generates what that one poses, rather than reimplementing it. Rotation is deliberately absent: this is the REST skeleton.\x22}\n" as *u8)
636 return 0
637}