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}