code wiki / (root) / nx_gate_rig_motion_stream_t140.nx

nx_gate_rig_motion_stream_t140.nx source

↩ module page · 1001 lines · 47868 B

1// Native real-asset gate; admission oracle copied unchanged from nx_nxa_retarget 2026-09-09. 2// Test-only oracle, no live runtime dependency or asset writer invocation. 3// nx_nxa_retarget.nx -- DONOR RETARGET: drive a rigged NXA that carries NO authored clips from a 4// SOURCE rig's POSE, preserving the TARGET's OWN bone lengths BY CONSTRUCTION. 5// 6// WHY (measured 2026-08-23): all five donors report poses_in_library=0 -- they carry rigs but no 7// authored motion, so the visiting cast on /world/beach stand as statues while every other piece 8// of the character stack ships. This organ is the missing leg. 9// 10// THE NAIVE RETARGET IS PROVABLY WRONG, AND THAT PROOF IS WHY THIS FILE EXISTS. In the NXA 11// normative form M x = D(x-b) + b + dt, applying joint j's transform to its own bind position 12// gives M_j b_j = b_j + dt_j. So a posed joint sits at b_j + dt_j and POSED BONE LENGTH IS A PURE 13// FUNCTION OF dt. Copying source dt -- or scaling it by a height ratio -- therefore cannot preserve 14// the target's bone lengths unless the two skeletons are proportionally identical, and ours are 15// emphatically not (104 joints at 1.715 m against 370 joints on a differently-proportioned donor). 16// A dt-transfer retarget stretches and shears limbs on every donor: the exact defect the operator 17// named as awful motion. It is not shipped here. 18// 19// THE ALGORITHM (four lines, and limb length is preserved BY CONSTRUCTION, not by tolerance): 20// A_j = conj(D_parent) . D_j source: world delta -> local articulation 21// W_j = W_parent . A_j target: parent-first composition 22// P_j = P_parent + W_parent (x) (b'_j - b'_p) the TARGET's OWN bone vector, ROTATED ONLY 23// dt'_j = P_j - b'_j 24// The target bone vector is only ever rotated -- never scaled, never replaced -- so no pose this 25// organ can emit is able to change a target bone's length. The limb-length tooth in the gate is a 26// REGRESSION GUARD on that property, not the thing that establishes it. 27// 28// The general form needs a similarity conjugation by each joint's bind orientation. It collapses 29// to the four lines above because NXA bind orientation is IDENTITY BY CONSTRUCTION -- nx_nxa_skin 30// emits SKEL quats as identity and states the reason in its own header (delta-LBS convention: 31// animation is applied RELATIVE to bind). VERIFY THAT BEFORE TRUSTING IT: the `bindquats` verb 32// measures it per asset and is the reason this organ has three verbs instead of one. 33// 34// JOINT MAPPING IS BY TOPOLOGY AND NORMALIZED BIND POSITION, NEVER BY NAME. SKEL carries no names 35// by design, and the donors come from different authoring tools -- a name map would be the 36// classifier-keys-on-a-string defect. The normalized space is the same one nx_nxa_joints uses: 37// every axis divided by the rig's OWN stature extent, so a taller or differently-scaled rig lands 38// in the same space. The stature axis is DERIVED as the largest bind extent, never assumed z-up: 39// the FBX/VRM donors arrive Y-up, which is the axis-convention defect a sibling lane measured in 40// the renderer on the same day. 41// 42// usage: nx_nxa_retarget bindquats <file.nxa> 43// nx_nxa_retarget map <src.nxa> <dst.nxa> 44// nx_nxa_retarget retarget <src.nxa> <pose_id> <dst.nxa> [out.nxa] [weight_permil] [emit=pose] 45// emit=pose (anywhere after <dst.nxa>): publish the POSE LIBRARY entry (W quat + dt per target joint) instead of a 46// baked VERT, so the output stays a RIG the player can replay, hold and sequence, and nx_nxa_play becomes an 47// independent witness of the motion this organ measured (2026-09-05, /compare/modding MD3; measured: every baked 48// donor read poses_in_library=0 joints_posed=0 under nx_nxa_play while the house rig read 104/104). The writer is 49// nx_nxa_posewrite_lib -- the estate's ONE POSE-section writer, shared with nx_nxa_pose freeze. 50// license_tier: ORIGINAL expect_exit: 0 51import "nx_syscalls.nx" 52import "nx_nxa.nx" 53import "nx_nxa_fk.nx" 54import "nx_skeleton.nx" 55import "nx_nxa_posewrite_lib.nx" 56 57const NR_Q12: i64 = 4096 // quaternion fixed-point unit (NXA v1 spec) 58const NR_WJ: i64 = 8 // words per SKEL joint (spec: parent,tx,ty,tz,qx,qy,qz,qw) 59const NR_WPE: i64 = 8 // words per POSE entry (spec: joint,qx,qy,qz,qw,dtx,dty,dtz) 60const NR_PERMIL: i64 = 1000 61const NR_INF: i64 = 4 // SKIN influences per vertex, fixed by the format 62const NR_WQ: i64 = 4096 // SKIN weight scale q12, sum = 4096 (spec) 63const NR_FX: i64 = 256 // nx_skeleton weight scale fx256, sum = 256 64// POSE dt lanes are already MODEL units (0.01 mm), not mm: the x100 is applied inside 65// nx_nxa_pose at freeze. The spec paragraph claiming mm is stale -- settled from the record 66// (eaten row 1785380029) by the player lane, and nx_nxa_play ships the same NP_DT_MODEL=1. 67const NR_DT_MODEL: i64 = 1 68const NR_WFULL: i64 = 1000 69const NR_MODE: i64 = 0x1a4 // 0644, matching every sibling NXA writer 70const NR_EXIT_USAGE: i64 = 2 71const NR_EXIT_REFUSE: i64 = 3 72const NR_EXIT_NOSEC: i64 = 5 73const NR_EXIT_NONIDENT: i64 = 1 // bindquats: a measurement outcome, not an error 74 75func nrw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 76func nrerr(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(2, s, n); return 0 } 77func nrn(v: i64) -> i64 { 78 let b: *u8 = sys_mmap(32) 79 var x: i64 = v 80 if x < 0 { b[0] = 45 as u8; sys_write(1, b, 1); x = 0 - x } 81 if x == 0 { b[0] = 48 as u8; sys_write(1, b, 1); return 0 } 82 var d: i64 = 0 83 var y: i64 = x 84 while y > 0 { d = d + 1; y = y / 10 } 85 var i: i64 = d 86 while i > 0 { i = i - 1; b[i] = ((x % 10) + 48) as u8; x = x / 10 } 87 sys_write(1, b, d) 88 return 0 89} 90func nr_atoi(s: *u8) -> i64 { 91 var v: i64 = 0 92 var i: i64 = 0 93 while s[i] != (0 as u8) { 94 let c: i64 = s[i] as i64 95 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } 96 i = i + 1 97 } 98 return v 99} 100func nr_streq(a: *u8, b: *u8) -> i64 { 101 var i: i64 = 0 102 while a[i] != (0 as u8) { 103 if a[i] != b[i] { return 0 } 104 i = i + 1 105 } 106 if b[i] != (0 as u8) { return 0 } 107 return 1 108} 109func nr_q(p: *i64, i: i64) -> *i64 { return ((p as i64) + i * 32) as *i64 } 110 111// Normalize a bind set into a scale-invariant space and RETURN THE STATURE EXTENT. 112// Every axis is divided by the rig's own largest extent, so proportion is preserved and a 113// differently-scaled rig lands in the same space. Returns -1 if the rig is degenerate. 114func nr_norm(bind: *i64, n: i64, out: *i64) -> i64 { 115 if n < 1 { return 0 - 1 } 116 let mn: *i64 = sys_mmap(64) 117 let mx: *i64 = sys_mmap(64) 118 var k: i64 = 0 119 while k < 3 { mn[k] = bind[k]; mx[k] = bind[k]; k = k + 1 } 120 var j: i64 = 1 121 while j < n { 122 k = 0 123 while k < 3 { 124 let v: i64 = bind[j*3+k] 125 if v < mn[k] { mn[k] = v } 126 if v > mx[k] { mx[k] = v } 127 k = k + 1 128 } 129 j = j + 1 130 } 131 var se: i64 = mx[0] - mn[0] 132 k = 1 133 while k < 3 { 134 let e: i64 = mx[k] - mn[k] 135 if e > se { se = e } 136 k = k + 1 137 } 138 if se <= 0 { return 0 - 1 } 139 // Anchor on the ROOT -- joint 0, since parent-first ordering is enforced before this is called, 140 // so joint 0 IS the root -- rather than on the per-axis bounding box. A BOUNDING BOX IS 141 // POSE-DEPENDENT: a T-posed rig and an A-posed rig have different lateral extents, so 142 // box-anchored coordinates shift EVERY joint when only the arms moved. The root does not move 143 // with the pose, so anchoring there compares anatomy instead of comparing posture. 144 j = 0 145 while j < n { 146 k = 0 147 while k < 3 { out[j*3+k] = (bind[j*3+k] - bind[k]) * NR_PERMIL / se; k = k + 1 } 148 j = j + 1 149 } 150 return se 151} 152func nr_d2(a: *i64, ai: i64, b: *i64, bi: i64) -> i64 { 153 let dx: i64 = a[ai*3] - b[bi*3] 154 let dy: i64 = a[ai*3+1] - b[bi*3+1] 155 let dz: i64 = a[ai*3+2] - b[bi*3+2] 156 return dx*dx + dy*dy + dz*dz 157} 158// The admission bound is DERIVED from the target's own geometry: the mean nearest-neighbour 159// spacing between its joints. If the best source match for a joint is farther away than the 160// target's own typical joint spacing, the source rig cannot resolve that joint and the mapping 161// is unreliable -- so it is refused rather than silently producing a plausible-looking pose. 162func nr_mean_nn(nrm: *i64, n: i64) -> i64 { 163 if n < 2 { return 0 - 1 } 164 var tot: i64 = 0 165 var j: i64 = 0 166 while j < n { 167 var best: i64 = 0 - 1 168 var i: i64 = 0 169 while i < n { 170 if i != j { 171 let d: i64 = nr_d2(nrm, j, nrm, i) 172 if best < 0 { best = d } 173 if d < best { best = d } 174 } 175 i = i + 1 176 } 177 tot = tot + nf_isqrt(best) 178 j = j + 1 179 } 180 return tot / n 181} 182func nr_load(path: *u8, lp: *i64) -> *u8 { 183 // sys_read_file sizes from the file itself and cannot short-read: the banked law against a 184 // hand-picked cap on a file read, which silently truncates its own subject. 185 return sys_read_file(path, lp) 186} 187 188// Derive the rig's OWN anatomical frame rather than assuming one. THE DONORS ARRIVE Y-UP WHILE OUR 189// GENERATED RIGS ARE Z-UP -- the same axis-convention defect a sibling lane measured in the renderer 190// (a donor rendering lying flat) and another measured in the soft-tissue solver (refusing donors for 191// having no left-side front vertices in the bust band) on this same day. Assuming largest-extent-is- 192// stature is ALSO wrong here: a T-posed rig's arm span can exceed its height, and these donors are 193// T/A-posed. So the LATERAL axis is identified by BILATERAL SYMMETRY -- a humanoid rig mirrors 194// left-to-right about that axis and about no other -- and of the two remaining axes the taller one is 195// stature. The match tolerance is the rig's OWN mean joint spacing, never a picked fraction. 196func nr_sym(bind: *i64, n: i64, k: i64, tol: i64) -> i64 { 197 var mn: i64 = bind[k] 198 var mx: i64 = bind[k] 199 var j: i64 = 1 200 while j < n { 201 let v: i64 = bind[j*3+k] 202 if v < mn { mn = v } 203 if v > mx { mx = v } 204 j = j + 1 205 } 206 let mid2: i64 = mn + mx 207 var hit: i64 = 0 208 j = 0 209 while j < n { 210 let want: i64 = mid2 - bind[j*3+k] 211 var found: i64 = 0 212 var i: i64 = 0 213 while i < n { 214 var d: i64 = bind[i*3+k] - want 215 if d < 0 { d = 0 - d } 216 if d <= tol { 217 var ok: i64 = 1 218 var o: i64 = 0 219 while o < 3 { 220 if o != k { 221 var d2: i64 = bind[i*3+o] - bind[j*3+o] 222 if d2 < 0 { d2 = 0 - d2 } 223 if d2 > tol { ok = 0 } 224 } 225 o = o + 1 226 } 227 if ok == 1 { found = 1 } 228 } 229 i = i + 1 230 } 231 hit = hit + found 232 j = j + 1 233 } 234 return hit * NR_PERMIL / n 235} 236func nr_frame(bind: *i64, n: i64, ax: *i64) -> i64 { 237 let tol: i64 = nr_mean_nn(bind, n) 238 let ext: *i64 = sys_mmap(64) 239 var k: i64 = 0 240 while k < 3 { 241 var mn: i64 = bind[k] 242 var mx: i64 = bind[k] 243 var j: i64 = 1 244 while j < n { 245 let v: i64 = bind[j*3+k] 246 if v < mn { mn = v } 247 if v > mx { mx = v } 248 j = j + 1 249 } 250 ext[k] = mx - mn 251 k = k + 1 252 } 253 var lat: i64 = 0 254 var bests: i64 = 0 - 1 255 k = 0 256 while k < 3 { 257 let s: i64 = nr_sym(bind, n, k, tol) 258 if s > bests { bests = s; lat = k } 259 k = k + 1 260 } 261 var a1: i64 = 0 - 1 262 var a2: i64 = 0 - 1 263 k = 0 264 while k < 3 { 265 if k != lat { 266 if a1 < 0 { a1 = k } 267 if a1 != k { a2 = k } 268 } 269 k = k + 1 270 } 271 var up: i64 = a1 272 var dep: i64 = a2 273 if ext[a2] > ext[a1] { up = a2; dep = a1 } 274 ax[0] = up; ax[1] = lat; ax[2] = dep 275 return bests 276} 277func nr_permute(bind: *i64, n: i64, ax: *i64, sg: *i64, out: *i64) -> i64 { 278 var j: i64 = 0 279 while j < n { 280 var k: i64 = 0 281 while k < 3 { out[j*3+k] = bind[j*3+ax[k]] * sg[k]; k = k + 1 } 282 j = j + 1 283 } 284 return 0 285} 286// The signed permutation carrying SOURCE raw coordinates into TARGET raw coordinates. A rotation's 287// axis is an AXIAL vector: under a frame change of determinant -1 it picks up that sign, otherwise 288// a mirrored frame would silently reverse every rotation direction. 289func nr_reframe_v(v: *i64, out: *i64, sax: *i64, ssg: *i64, tax: *i64, tsg: *i64) -> i64 { 290 var c: i64 = 0 291 while c < 3 { out[tax[c]] = v[sax[c]] * ssg[c] * tsg[c]; c = c + 1 } 292 return 0 293} 294func nr_frame_det(sax: *i64, ssg: *i64, tax: *i64, tsg: *i64) -> i64 { 295 let m: *i64 = sys_mmap(128) 296 var i: i64 = 0 297 while i < 9 { m[i] = 0; i = i + 1 } 298 var c: i64 = 0 299 while c < 3 { m[tax[c]*3 + sax[c]] = ssg[c] * tsg[c]; c = c + 1 } 300 return m[0]*(m[4]*m[8]-m[5]*m[7]) - m[1]*(m[3]*m[8]-m[5]*m[6]) + m[2]*(m[3]*m[7]-m[4]*m[6]) 301} 302 303// Permutation parity of the derived axis triple. Once UP and ANTERIOR are both pinned, handedness 304// is no longer free: the lateral sign is whatever makes the frame's determinant +1, so it is DERIVED 305// rather than searched. That is the whole reason the ambiguity below can be closed. 306func nr_parity(ax: *i64) -> i64 { 307 let p: i64 = (ax[1]-ax[0]) * (ax[2]-ax[0]) * (ax[2]-ax[1]) 308 if p < 0 { return 0 - 1 } 309 return 1 310} 311// ANTERIOR DIRECTION FROM THE MESH -- the cue that handedness actually needs. 312// MEASURED, NOT ASSUMED: a bilaterally symmetric point set is near-ISOMETRIC under mirroring, so a 313// symmetric cue (joint positions, mapping distance) cannot carry handedness at all -- every rig here 314// scores sym_permil=1000 and the argmin between mirrored options picked arbitrarily, which posed two 315// of four donors MIRRORED while every limb-length tooth passed (a mirror preserves every length it 316// checks). The asymmetry a humanoid actually has is FRONT/BACK, and it lives in the MESH, not in the 317// skeleton: at the FOOT band the toes extend anteriorly far past the heel, and at the HEAD band the 318// face extends anteriorly past the back of the skull. Both bands are measured INDEPENDENTLY and must 319// AGREE; when they disagree the cue is ambiguous and this returns 0 so the caller abstains BY NAME. 320// An arbitrary pick that is right half the time is worse than a refusal: it produces confident wrong 321// output. The band height is the rig's OWN mean joint spacing, never a picked fraction of stature. 322// The band height at an extremity is that extremity's OWN BONE LENGTH -- the local anatomical 323// scale, taken where the measurement is actually made. A GLOBAL mean joint spacing was the defect: 324// it averages dense finger clusters together with long limb bones, so on a ~110-joint rig the band 325// grew tall enough that BOTH bands covered the ENTIRE MESH and the two-witness test became vacuous 326// (measured: paladin foot=head=2184, dark_knight foot=head=-140 -- byte-identical, i.e. the same 327// vertex set answering twice). 328func nr_extremity_band(bind: *i64, par: *i64, n: i64, upax: i64, want_max: i64) -> i64 { 329 if n < 2 { return 0 } 330 var je: i64 = 0 331 var ve: i64 = bind[upax] 332 var j: i64 = 1 333 while j < n { 334 let v: i64 = bind[j*3+upax] 335 if want_max == 1 { if v > ve { ve = v; je = j } } 336 if want_max == 0 { if v < ve { ve = v; je = j } } 337 j = j + 1 338 } 339 let pj: i64 = par[je] 340 if pj >= 0 { 341 let ax2: i64 = bind[pj*3] - bind[je*3] 342 let ay2: i64 = bind[pj*3+1] - bind[je*3+1] 343 let az2: i64 = bind[pj*3+2] - bind[je*3+2] 344 let l: i64 = nf_isqrt(ax2*ax2 + ay2*ay2 + az2*az2) 345 if l > 0 { return l } 346 } 347 // the extremity is the root (or a zero-length bone): fall back to its nearest neighbour joint 348 var best: i64 = 0 - 1 349 var i: i64 = 0 350 while i < n { 351 if i != je { 352 let dx: i64 = bind[i*3] - bind[je*3] 353 let dy: i64 = bind[i*3+1] - bind[je*3+1] 354 let dz: i64 = bind[i*3+2] - bind[je*3+2] 355 let d: i64 = dx*dx + dy*dy + dz*dz 356 if best < 0 { best = d } 357 if d < best { best = d } 358 } 359 i = i + 1 360 } 361 if best < 0 { return 0 } 362 return nf_isqrt(best) 363} 364// THE BAND IS DERIVED FROM THE MESH ITSELF: the SMALLEST vertical window at an extremity that holds 365// enough vertices to be a witness. No picked fraction of stature -- the population requirement sizes 366// it and the mesh's own density decides how tall that is, so a dense rig gets a tight band and a 367// sparse one gets a wider band automatically. 368// 369// THIS REPLACES BONE LENGTH, AND THAT SUBSTITUTION IS ALSO A DIAGNOSTIC. Bone length is a property of 370// the SKELETON, so a single mis-placed joint makes the extremity bone enormous and the band nonsense: 371// dark_knight and paladin measured 48,293 and 74,484-unit extremity bones and were refused for 372// overlap. If a mesh-derived band resolves them, the bone was the defect; if it does not, the 373// geometry is, and that is the same root cause as the fragmented render on the same asset. 374func nr_band_for_pop(vert: *i64, nv: i64, upax: i64, want_max: i64, minpop: i64, ulo: i64, uhi: i64) -> i64 { 375 var lo: i64 = 0 376 var hi: i64 = uhi - ulo 377 if hi < 1 { return 0 } 378 while lo < hi { 379 let mid: i64 = (lo + hi) / 2 380 var c: i64 = 0 381 var i: i64 = 0 382 while i < nv { 383 let u: i64 = vert[i*3+upax] 384 if want_max == 0 { if u <= ulo + mid { c = c + 1 } } 385 if want_max == 1 { if u >= uhi - mid { c = c + 1 } } 386 i = i + 1 387 } 388 if c >= minpop { hi = mid } 389 if c < minpop { lo = mid + 1 } 390 } 391 return lo 392} 393func nr_anterior(vert: *i64, nv: i64, ax: *i64, blo: i64, bhi: i64, minpop: i64, ev: *i64) -> i64 { 394 ev[4] = 0 395 if nv < 1 { return 0 } 396 if blo < 1 { return 0 } 397 if bhi < 1 { return 0 } 398 var umin: i64 = vert[ax[0]] 399 var umax: i64 = umin 400 var dmin: i64 = vert[ax[2]] 401 var dmax: i64 = dmin 402 var i: i64 = 1 403 while i < nv { 404 let u: i64 = vert[i*3+ax[0]] 405 let d: i64 = vert[i*3+ax[2]] 406 if u < umin { umin = u } 407 if u > umax { umax = u } 408 if d < dmin { dmin = d } 409 if d > dmax { dmax = d } 410 i = i + 1 411 } 412 // TWO WITNESSES THAT ARE SECRETLY THE SAME WITNESS AGREE ONE HUNDRED PERCENT OF THE TIME. 413 // The bands must be DISJOINT before their agreement means anything -- this is the shared- 414 // failure-mode law arriving inside one organ. Overlap is reported (ev[4]) so the caller can 415 // abstain BY NAME on THIS cause rather than on a generic ambiguity. 416 // Bands sized from the MESH (see nr_band_for_pop). The bone-derived values are still reported in 417 // ev[5]/ev[6] beside them, because the COMPARISON is the diagnostic: a bone band far larger than 418 // the mesh band means that extremity's joint is mis-placed, not that the rig is unusual. 419 let mblo: i64 = nr_band_for_pop(vert, nv, ax[0], 0, minpop, umin, umax) 420 let mbhi: i64 = nr_band_for_pop(vert, nv, ax[0], 1, minpop, umin, umax) 421 ev[5] = blo 422 ev[6] = bhi 423 ev[7] = mblo 424 ev[8] = mbhi 425 if mblo < 1 { ev[4] = 2; return 0 } 426 if mbhi < 1 { ev[4] = 2; return 0 } 427 if umin + mblo >= umax - mbhi { ev[4] = 1; return 0 } 428 let mid: i64 = (dmin + dmax) / 2 429 var lo_s: i64 = 0 430 var lo_n: i64 = 0 431 var hi_s: i64 = 0 432 var hi_n: i64 = 0 433 i = 0 434 while i < nv { 435 let u: i64 = vert[i*3+ax[0]] 436 let d: i64 = vert[i*3+ax[2]] - mid 437 if u <= umin + mblo { lo_s = lo_s + d; lo_n = lo_n + 1 } 438 if u >= umax - mbhi { hi_s = hi_s + d; hi_n = hi_n + 1 } 439 i = i + 1 440 } 441 // DISJOINTNESS IS NECESSARY BUT NOT SUFFICIENT: a band can be disjoint and still be too thin to 442 // be a witness. Measured on toon3d8: its toe-tip bone is 1 unit long, so the foot band held 443 // exactly 2 VERTICES and a whole handedness verdict rested on them. A band must therefore also 444 // be POPULATED, and the floor is derived from the asset itself -- a mesh region holding fewer 445 // points than the rig has JOINTS is a few stray vertices, not a shape. 446 if lo_n < minpop { ev[4] = 2; return 0 } 447 if hi_n < minpop { ev[4] = 2; return 0 } 448 if lo_n < 1 { return 0 } 449 if hi_n < 1 { return 0 } 450 let lo: i64 = lo_s / lo_n 451 let hi: i64 = hi_s / hi_n 452 ev[0] = lo; ev[1] = hi; ev[2] = lo_n; ev[3] = hi_n 453 if lo > 0 { if hi >= 0 { return 1 } } 454 if lo < 0 { if hi <= 0 { return 0 - 1 } } 455 // The bands CONTRADICT. They are not equally trustworthy, and the reason is anatomical rather 456 // than convenient: TOES project anteriorly on every standing humanoid, while the HEAD band is 457 // contaminated by HAIR AND HEADWEAR, which hang POSTERIORLY. Measured on the real corpus: 458 // toon3d8's long back-hair drove its head band to -2925 against a foot band of +11638, and 459 // ref9d's head band read only +1475 against a foot band of -9493 -- in both cases the head is 460 // the weaker and the dirtier signal. So a contradicting head vote overrides the foot ONLY when 461 // it is STRICTLY STRONGER; when it is, the shape is not a standing humanoid and we abstain 462 // rather than guess. dark_witch needs none of this: +62699 foot and +88153 head both agree. 463 var alo: i64 = lo 464 if alo < 0 { alo = 0 - alo } 465 var ahi: i64 = hi 466 if ahi < 0 { ahi = 0 - ahi } 467 if ahi > alo { return 0 } 468 if lo > 0 { return 1 } 469 if lo < 0 { return 0 - 1 } 470 return 0 471} 472 473// ---- verb: bindquats -- MEASURE the identity-bind convention this organ's math depends on ------ 474func nr_bindquats(path: *u8) -> i64 { 475 let lp: *i64 = sys_mmap(64) 476 let b: *u8 = nr_load(path, lp) 477 if b as i64 == 0 { nrerr("NXA-RETARGET-REFUSE cannot read input\n" as *u8); return NR_EXIT_REFUSE } 478 let flen: i64 = lp[0] 479 let w: *i64 = b as *i64 480 let swo: i64 = nxa_find(b, flen, nxa_tag4("SKEL" as *u8)) 481 if swo < 0 { nrerr("NXA-RETARGET-REFUSE no valid SKEL section\n" as *u8); return NR_EXIT_NOSEC } 482 let nj: i64 = w[swo] 483 var nonid: i64 = 0 484 var j: i64 = 0 485 while j < nj { 486 let so: i64 = swo + 1 + j * NR_WJ 487 var bad: i64 = 0 488 if w[so+4] != 0 { bad = 1 } 489 if w[so+5] != 0 { bad = 1 } 490 if w[so+6] != 0 { bad = 1 } 491 if w[so+7] != NR_Q12 { bad = 1 } 492 if bad == 1 { nonid = nonid + 1 } 493 j = j + 1 494 } 495 nrw(" joints=" as *u8); nrn(nj) 496 nrw(" nonidentity_bind_quats=" as *u8); nrn(nonid) 497 nrw(" identity_bind_convention=" as *u8) 498 if nonid == 0 { nrw("HOLDS\n" as *u8) } 499 if nonid != 0 { nrw("VIOLATED\n" as *u8) } 500 if nonid != 0 { return NR_EXIT_NONIDENT } 501 return 0 502} 503 504 505import "nx_nxa_anim_lib.nx" 506import "nx_nxa_rig_motion_stream_t140.nx" 507 508func nmg_sample(anim: *i64, tidx: *i64, order: *i64, ns: i64, t: i64, sax: *i64, ssg: *i64, tax: *i64, tsg: *i64, q: *i64, d: *i64) -> i64 { 509 let scratch: *i64 = sys_mmap(64) 510 let tmp: *i64 = sys_mmap(32) 511 let det: i64 = nr_frame_det(sax, ssg, tax, tsg) 512 var j: i64 = 0 513 while j < ns { 514 let qp: *i64 = ((q as i64)+j*32) as *i64 515 let dp: *i64 = ((d as i64)+j*24) as *i64 516 qp[0]=0; qp[1]=0; qp[2]=0; qp[3]=NR_Q12 517 dp[0]=0; dp[1]=0; dp[2]=0 518 if tidx[j*2] >= 0 { 519 if order[j] == 1 { na_eval_track_ordered(anim,tidx[j*2],tidx[j*2+1],t,qp,dp,scratch) } 520 else { na_eval_track(anim,tidx[j*2],tidx[j*2+1],t,qp,dp,scratch) } 521 } 522 nr_reframe_v(qp,tmp,sax,ssg,tax,tsg) 523 qp[0]=tmp[0]*det; qp[1]=tmp[1]*det; qp[2]=tmp[2]*det 524 nr_reframe_v(dp,tmp,sax,ssg,tax,tsg) 525 dp[0]=tmp[0]; dp[1]=tmp[1]; dp[2]=tmp[2] 526 j=j+1 527 } 528 sys_munmap(scratch,64);sys_munmap(tmp,32) 529 return 0 530} 531// Bound fixed-point rotation length error from measured parent quaternion norm and rounding. 532// Two quaternion products truncate each output lane. L1 bounds the resulting spatial error. 533// This is a numerical bound derived from q12 arithmetic, not a perceptual quality threshold. 534func nmg_bones(nt: i64, par: *i64, bind: *i64, W: *i64, P: *i64) -> i64 { 535 var failed: i64=0 536 var maxerr: i64=0 537 var maxbound: i64=0 538 var j: i64=0 539 while j<nt { 540 let p: i64=par[j] 541 if p>=0 { 542 let x: i64=bind[j*3]-bind[p*3] 543 let y: i64=bind[j*3+1]-bind[p*3+1] 544 let z: i64=bind[j*3+2]-bind[p*3+2] 545 let xx: i64=P[j*3]-P[p*3] 546 let yy: i64=P[j*3+1]-P[p*3+1] 547 let zz: i64=P[j*3+2]-P[p*3+2] 548 let len: i64=nf_isqrt(x*x+y*y+z*z) 549 let plen: i64=nf_isqrt(xx*xx+yy*yy+zz*zz) 550 let qp: *i64=nr_q(W,p) 551 let qn: i64=qp[0]*qp[0]+qp[1]*qp[1]+qp[2]*qp[2]+qp[3]*qp[3] 552 let qa: i64=na_abs(qp[0])+na_abs(qp[1])+na_abs(qp[2])+na_abs(qp[3]) 553 let unit2: i64=NR_Q12*NR_Q12 554 let drift: i64=(na_abs(qn-unit2)*(len+1)+unit2-1)/unit2 555 let round: i64=3*((qa+NR_Q12-1)/NR_Q12+1)+2 556 let bound: i64=drift+round 557 let err: i64=na_abs(plen-len) 558 if err>maxerr { maxerr=err } 559 if bound>maxbound { maxbound=bound } 560 if err>bound { failed=failed+1 } 561 } 562 j=j+1 563 } 564 nrw(" bone_residual_model_units=" as *u8);nrn(maxerr) 565 nrw(" derived_arithmetic_bound_max=" as *u8);nrn(maxbound) 566 nrw(" bone_bound_failures=" as *u8);nrn(failed);nrw("\n" as *u8) 567 return failed 568} 569 570// Private diagnostic palette emission for existing rig-motion qualification. 571// Caller-selected samples are evidence fixtures, not a production animation format. 572func nmp_num(b:*u8,o:i64,v:i64)->i64 { 573 var p:i64=o;var x:i64=v 574 if x<0 {b[p]=45 as u8;p=p+1;x=0-x} 575 if x==0 {b[p]=48 as u8;return p+1} 576 var z:i64=x;var n:i64=0 577 while z>0 {n=n+1;z=z/10} 578 var k:i64=n 579 while k>0 {k=k-1;b[p+k]=(48+x%10) as u8;x=x/10} 580 return p+n 581} 582func nmp_rows(nj:i64,bind:*i64,q:*i64,dt:*i64,out:*i64,scr:*i64)->i64 { 583 // Bound both quaternion products and the three-term affine dual sum in i64. 584 let coordinate_limit:i64=9223372036854775807/(64*NR_Q12) 585 var lane:i64=0 586 while lane<nj*4 {if q[lane]<0-NR_Q12||q[lane]>NR_Q12 {return 0-1}lane=lane+1} 587 lane=0 588 while lane<nj*3 { 589 if bind[lane]<0-coordinate_limit||bind[lane]>coordinate_limit {return 0-1} 590 if dt[lane]<0-coordinate_limit||dt[lane]>coordinate_limit {return 0-1} 591 lane=lane+1 592 } 593 let rot:*i64=scr 594 let work:*i64=((scr as i64)+32) as *i64 595 var j:i64=0 596 while j<nj { 597 let r:i64=j*4;let d:i64=nj*4+r 598 let qp:*i64=((q as i64)+r*8) as *i64 599 nf_qrotv(qp,bind[j*3],bind[j*3+1],bind[j*3+2],rot,work) 600 let tx:i64=bind[j*3]+dt[j*3]-rot[0] 601 let ty:i64=bind[j*3+1]+dt[j*3+1]-rot[1] 602 let tz:i64=bind[j*3+2]+dt[j*3+2]-rot[2] 603 out[r]=q[r];out[r+1]=q[r+1];out[r+2]=q[r+2];out[r+3]=q[r+3] 604 out[d]=(tx*q[r+3]+ty*q[r+2]-tz*q[r+1])/2 605 out[d+1]=(0-tx*q[r+2]+ty*q[r+3]+tz*q[r])/2 606 out[d+2]=(tx*q[r+1]-ty*q[r]+tz*q[r+3])/2 607 out[d+3]=(0-tx*q[r]-ty*q[r+1]-tz*q[r+2])/2 608 j=j+1 609 } 610 return 0 611} 612 613func nmg_asset(spath: *u8, dpath: *u8, outpath:*u8, samples:i64) -> i64 { 614 // ---- load source ---------------------------------------------------------------------- 615 let slp: *i64 = sys_mmap(64) 616 let sb: *u8 = nr_load(spath, slp) 617 if sb as i64 == 0 { nrerr("NXA-RETARGET-REFUSE cannot read source\n" as *u8); return NR_EXIT_REFUSE } 618 let sflen: i64 = slp[0] 619 let sw: *i64 = sb as *i64 620 let sswo: i64 = nxa_find(sb, sflen, nxa_tag4("SKEL" as *u8)) 621 if sswo < 0 { nrerr("NXA-RETARGET-REFUSE source has no valid SKEL\n" as *u8); return NR_EXIT_NOSEC } 622 let ns: i64 = sw[sswo] 623 if ns < 1 { nrerr("NXA-RETARGET-REFUSE source SKEL is empty\n" as *u8); return NR_EXIT_REFUSE } 624 625 // ---- load target ---------------------------------------------------------------------- 626 let dlp: *i64 = sys_mmap(64) 627 let db: *u8 = nr_load(dpath, dlp) 628 if db as i64 == 0 { nrerr("NXA-RETARGET-REFUSE cannot read target\n" as *u8); return NR_EXIT_REFUSE } 629 let dflen: i64 = dlp[0] 630 let dw: *i64 = db as *i64 631 let dswo: i64 = nxa_find(db, dflen, nxa_tag4("SKEL" as *u8)) 632 if dswo < 0 { nrerr("NXA-RETARGET-REFUSE target has no valid SKEL (asset is not rigged)\n" as *u8); return NR_EXIT_NOSEC } 633 let nt: i64 = dw[dswo] 634 if nt < 1 { nrerr("NXA-RETARGET-REFUSE target SKEL is empty\n" as *u8); return NR_EXIT_REFUSE } 635 636 // ---- unpack binds + parents ----------------------------------------------------------- 637 let sbind: *i64 = sys_mmap(ns * 3 * 8) 638 let spar: *i64 = sys_mmap(ns * 8) 639 var j: i64 = 0 640 while j < ns { 641 let so: i64 = sswo + 1 + j * NR_WJ 642 spar[j] = sw[so] 643 sbind[j*3] = sw[so+1]; sbind[j*3+1] = sw[so+2]; sbind[j*3+2] = sw[so+3] 644 j = j + 1 645 } 646 let tbind: *i64 = sys_mmap(nt * 3 * 8) 647 let tpar: *i64 = sys_mmap(nt * 8) 648 j = 0 649 var order_bad: i64 = 0 650 while j < nt { 651 let so: i64 = dswo + 1 + j * NR_WJ 652 tpar[j] = dw[so] 653 if tpar[j] >= j { order_bad = order_bad + 1 } 654 tbind[j*3] = dw[so+1]; tbind[j*3+1] = dw[so+2]; tbind[j*3+2] = dw[so+3] 655 j = j + 1 656 } 657 // The four-line composition is parent-first and cannot be evaluated out of order. A SKEL whose 658 // parents are not emitted before their children is REFUSED BY NAME rather than composed against 659 // an unwritten parent, which would read as a plausible but wrong pose. 660 if order_bad != 0 { 661 nrerr("NXA-RETARGET-REFUSE target SKEL is not parent-first ordered\n" as *u8) 662 return NR_EXIT_REFUSE 663 } 664 665 // ---- canonical anatomical frames, DERIVED per rig --------------------------------------- 666 let sax: *i64 = sys_mmap(64) 667 let tax: *i64 = sys_mmap(64) 668 let ssym: i64 = nr_frame(sbind, ns, sax) 669 let tsym: i64 = nr_frame(tbind, nt, tax) 670 let ssg: *i64 = sys_mmap(64) 671 let tsg: *i64 = sys_mmap(64) 672 ssg[0] = 1; ssg[1] = 1; ssg[2] = 1 673 let scan: *i64 = sys_mmap(ns * 3 * 8) 674 nr_permute(sbind, ns, sax, ssg, scan) 675 let snrm: *i64 = sys_mmap(ns * 3 * 8) 676 let sse: i64 = nr_norm(scan, ns, snrm) 677 if sse < 0 { nrerr("NXA-RETARGET-REFUSE source rig has zero extent\n" as *u8); return NR_EXIT_REFUSE } 678 679 // Lateral and depth SIGN are searched rather than guessed: all four combinations are mapped and 680 // the lowest total mapping distance is taken. 681 // *** MEASURED LIMITATION, AND A CORRECTION TO THIS ORGAN'S OWN FIRST CLAIM. *** 682 // v1 of this comment said the search RESOLVES HANDEDNESS FROM THE DATA. IT DOES NOT, and the 683 // live run proved it: every rig here measures sym_permil=1000, i.e. BILATERALLY SYMMETRIC, and a 684 // symmetric point set is very nearly ISOMETRIC UNDER MIRRORING -- so both handedness options 685 // score almost the same total distance and the argmin picks between near-ties essentially 686 // arbitrarily. The evidence is in the numbers: frame_det came out +1 for toon3d8 and 687 // dark_knight but -1 for dark_witch and paladin, on four ordinary humanoids that should all 688 // agree. A mirrored frame swaps left and right, which is a wrong pose no limb-length tooth can 689 // catch -- exactly the awful-motion class. 690 // THE FIX IS NAMED, NOT GUESSED: handedness has to come from an ASYMMETRIC cue, because a 691 // symmetric one cannot carry the information. Front/back is that cue (a face, a nose, a chest 692 // are forward and do not mirror), and it lives in the MESH, not in the joint positions this 693 // search sees. Until that lands, the lateral sign on any given donor is UNPROVEN and the pose 694 // it produces may be mirrored; frame_det is printed on every run so a reader can see which. 695 let tcan: *i64 = sys_mmap(nt * 3 * 8) 696 let bnrm: *i64 = sys_mmap(nt * 3 * 8) 697 let map: *i64 = sys_mmap(nt * 8) 698 // HANDEDNESS IS DERIVED, NOT SEARCHED. The mesh carries the front/back asymmetry the skeleton 699 // cannot; once UP and ANTERIOR are pinned the lateral sign is forced to whatever makes the 700 // frame determinant +1, so both rigs land in the SAME handed frame by construction. 701 let svwo: i64 = nxa_find(sb, sflen, nxa_tag4("VERT" as *u8)) 702 let tvwo: i64 = nxa_find(db, dflen, nxa_tag4("VERT" as *u8)) 703 if svwo < 0 { nrerr("NXA-RETARGET-REFUSE source has no valid VERT to derive anterior from\n" as *u8); return NR_EXIT_NOSEC } 704 if tvwo < 0 { nrerr("NXA-RETARGET-REFUSE target has no valid VERT to derive anterior from\n" as *u8); return NR_EXIT_NOSEC } 705 let svp: *i64 = ((sw as i64) + (svwo+1)*8) as *i64 706 let tvp: *i64 = ((dw as i64) + (tvwo+1)*8) as *i64 707 // 16 words: the evidence block now carries ev[0..8] -- foot, head, both counts, the abstain 708 // cause, and BOTH band sources. A 64-byte (8-word) allocation was one word short and the arena 709 // canary caught it as ARENA-OVERRUN on the very first run. Sized with headroom and NAMED, so the 710 // next field added does not silently walk off the end. 711 let sev: *i64 = sys_mmap(128) 712 let tev: *i64 = sys_mmap(128) 713 let sblo: i64 = nr_extremity_band(sbind, spar, ns, sax[0], 0) 714 let sbhi: i64 = nr_extremity_band(sbind, spar, ns, sax[0], 1) 715 let tblo: i64 = nr_extremity_band(tbind, tpar, nt, tax[0], 0) 716 let tbhi: i64 = nr_extremity_band(tbind, tpar, nt, tax[0], 1) 717 let sant: i64 = nr_anterior(svp, sw[svwo], sax, sblo, sbhi, ns, sev) 718 let tant: i64 = nr_anterior(tvp, dw[tvwo], tax, tblo, tbhi, nt, tev) 719 nrw(" src_anterior=" as *u8); nrn(sant) 720 nrw(" foot=" as *u8); nrn(sev[0]); nrw(" head=" as *u8); nrn(sev[1]) 721 nrw(" bands=" as *u8); nrn(sblo); nrw("/" as *u8); nrn(sbhi) 722 nrw(" nverts=" as *u8); nrn(sev[2]); nrw("/" as *u8); nrn(sev[3]) 723 nrw(" overlap=" as *u8); nrn(sev[4]); nrw("\n" as *u8) 724 nrw(" tgt_anterior=" as *u8); nrn(tant) 725 nrw(" foot=" as *u8); nrn(tev[0]); nrw(" head=" as *u8); nrn(tev[1]) 726 nrw(" meshband=" as *u8); nrn(tev[7]); nrw("/" as *u8); nrn(tev[8]) 727 nrw(" boneband=" as *u8); nrn(tev[5]); nrw("/" as *u8); nrn(tev[6]) 728 nrw(" nverts=" as *u8); nrn(tev[2]); nrw("/" as *u8); nrn(tev[3]) 729 nrw(" overlap=" as *u8); nrn(tev[4]); nrw("\n" as *u8) 730 if sant == 0 { 731 if sev[4] == 1 { nrerr("NXA-RETARGET-REFUSE source foot and head bands OVERLAP -- they are the same witness twice, so their agreement proves nothing\n" as *u8) } 732 if sev[4] == 2 { nrerr("NXA-RETARGET-REFUSE source anterior band holds fewer vertices than the rig has joints -- too thin to be a witness\n" as *u8) } 733 if sev[4] == 0 { nrerr("NXA-RETARGET-REFUSE source anterior is AMBIGUOUS (a stronger head vote contradicts the foot) -- abstaining rather than picking a handedness\n" as *u8) } 734 return NR_EXIT_REFUSE 735 } 736 if tant == 0 { 737 if tev[4] == 1 { nrerr("NXA-RETARGET-REFUSE target foot and head bands OVERLAP -- they are the same witness twice, so their agreement proves nothing\n" as *u8) } 738 if tev[4] == 2 { nrerr("NXA-RETARGET-REFUSE target anterior band holds fewer vertices than the rig has joints -- too thin to be a witness\n" as *u8) } 739 if tev[4] == 0 { nrerr("NXA-RETARGET-REFUSE target anterior is AMBIGUOUS (a stronger head vote contradicts the foot) -- abstaining rather than picking a handedness\n" as *u8) } 740 return NR_EXIT_REFUSE 741 } 742 ssg[2] = sant; ssg[1] = nr_parity(sax) * sant 743 tsg[0] = 1; tsg[2] = tant; tsg[1] = nr_parity(tax) * tant 744 let bslat: i64 = tsg[1] 745 let bsdep: i64 = tsg[2] 746 nr_permute(sbind, ns, sax, ssg, scan) 747 if nr_norm(scan, ns, snrm) < 0 { nrerr("NXA-RETARGET-REFUSE source rig has zero extent\n" as *u8); return NR_EXIT_REFUSE } 748 nr_permute(tbind, nt, tax, tsg, tcan) 749 let tse: i64 = nr_norm(tcan, nt, bnrm) 750 if tse < 0 { nrerr("NXA-RETARGET-REFUSE target rig has zero extent\n" as *u8); return NR_EXIT_REFUSE } 751 var maxd: i64 = 0 752 var totd: i64 = 0 753 j = 0 754 while j < nt { 755 var best: i64 = 0 - 1 756 var bi: i64 = 0 757 var i: i64 = 0 758 while i < ns { 759 let d: i64 = nr_d2(bnrm, j, snrm, i) 760 if best < 0 { best = d; bi = i } 761 if d < best { best = d; bi = i } 762 i = i + 1 763 } 764 map[j] = bi 765 let dd: i64 = nf_isqrt(best) 766 if dd > maxd { maxd = dd } 767 totd = totd + dd 768 j = j + 1 769 } 770 let bdst: *i64 = sys_mmap(nt * 8) 771 j = 0 772 while j < nt { bdst[j] = nf_isqrt(nr_d2(bnrm, j, snrm, map[j])); j = j + 1 } 773 // THE ADMISSION BOUND IS THE SOURCE'S OWN JOINT SPACING, NOT THE TARGET'S. The question a 774 // mapping has to answer is whether the SOURCE can resolve a given joint, so the scale that 775 // decides it belongs to the source. Deriving it from the target was measured wrong on the first 776 // live run: a 370-joint donor packs its joints 3 permil apart, so every match from a 104-joint 777 // source read as LOOSE and the whole retarget refused -- a bound that indicted the source rig 778 // for the target's density. A target joint the source genuinely cannot resolve (a finger, a 779 // facial bone) is not an error either: it INHERITS its parent's articulation and rides along, 780 // which is what a rigid sub-chain should do, instead of fabricating motion for it. 781 let bound: i64 = nr_mean_nn(snrm, ns) 782 nrw(" src_frame up=" as *u8); nrn(sax[0]); nrw(" lat=" as *u8); nrn(sax[1]); nrw(" dep=" as *u8); nrn(sax[2]) 783 nrw(" sym_permil=" as *u8); nrn(ssym); nrw("\n" as *u8) 784 nrw(" tgt_frame up=" as *u8); nrn(tax[0]); nrw(" lat=" as *u8); nrn(tax[1]); nrw(" dep=" as *u8); nrn(tax[2]) 785 nrw(" sym_permil=" as *u8); nrn(tsym) 786 nrw(" lat_sign=" as *u8); nrn(bslat); nrw(" dep_sign=" as *u8); nrn(bsdep); nrw("\n" as *u8) 787 nrw(" src_joints=" as *u8); nrn(ns) 788 nrw(" tgt_joints=" as *u8); nrn(nt) 789 nrw(" map_max_permil=" as *u8); nrn(maxd) 790 nrw(" map_mean_permil=" as *u8); nrn(totd / nt) 791 nrw(" admit_bound_permil=" as *u8); nrn(bound) 792 nrw("\n" as *u8) 793 var nmapped: i64 = 0 794 var ninherit: i64 = 0 795 j = 0 796 while j < nt { 797 if bdst[j] <= bound { nmapped = nmapped + 1 } 798 if bdst[j] > bound { ninherit = ninherit + 1 } 799 j = j + 1 800 } 801 nrw(" mapped=" as *u8); nrn(nmapped) 802 nrw(" inherited=" as *u8); nrn(ninherit) 803 nrw(" of=" as *u8); nrn(nt) 804 nrw("\n" as *u8) 805 // A partition that does not sum is a leak, so it is asserted rather than assumed. 806 if nmapped + ninherit != nt { 807 nrerr("NXA-RETARGET-REFUSE mapped/inherited partition does not sum to the joint count\n" as *u8) 808 return NR_EXIT_REFUSE 809 } 810 // Refused only when the source can resolve NOTHING: then there is no articulation to transfer 811 // and any output would be the bind pose wearing a retarget's name. 812 if nmapped == 0 { 813 nrerr("NXA-RETARGET-REFUSE source rig resolves no target joint within its own joint spacing\n" as *u8) 814 return NR_EXIT_REFUSE 815 } 816 817 let ae: i64=nxa_section_entry(sb,sflen,nxa_tag4("ANIM" as *u8)) 818 if ae<0 { nrerr("MOTION-GATE missing source ANIM\n" as *u8);return 5 } 819 let anim: *i64=((sb as i64)+sw[ae+1]) as *i64 820 let aw: i64=sw[ae+2] 821 let before: i64=nxa_check2(1,anim,aw) 822 let tidx: *i64=sys_mmap(ns*2*8) 823 let order: *i64=sys_mmap(ns*8) 824 let dur: i64=na_index(anim,aw,ns,tidx) 825 if dur<=0 { nrerr("MOTION-GATE invalid/empty duration\n" as *u8);return 5 } 826 na_index_order(anim,tidx,ns,order) 827 let qa: *i64=sys_mmap(ns*4*8) 828 let da: *i64=sys_mmap(ns*3*8) 829 let qb: *i64=sys_mmap(ns*4*8) 830 let dd: *i64=sys_mmap(ns*3*8) 831 let WA: *i64=sys_mmap(nt*4*8) 832 let PA: *i64=sys_mmap(nt*3*8) 833 let DA: *i64=sys_mmap(nt*3*8) 834 let WB: *i64=sys_mmap(nt*4*8) 835 let PB: *i64=sys_mmap(nt*3*8) 836 let DB: *i64=sys_mmap(nt*3*8) 837 let sa: *i64=sys_mmap(NRM_SCR_W*8) 838 let sbx: *i64=sys_mmap(NRM_SCR_W*8) 839 nmg_sample(anim,tidx,order,ns,0,sax,ssg,tax,tsg,qa,da) 840 // Two phases are experimental fixtures derived from this asset's measured duration. 841 nmg_sample(anim,tidx,order,ns,dur/3,sax,ssg,tax,tsg,qb,dd) 842 if nrm_compose(ns,nt,qa,da,map,tpar,tbind,bdst,bound,sse,tse,WA,PA,DA,sa)!=0 { return 6 } 843 let ca: i64=nxa_check2(nxa_check2(nxa_check2(1,WA,nt*4),PA,nt*3),DA,nt*3) 844 let csource: i64=nxa_check2(nxa_check2(1,qa,ns*4),da,ns*3) 845 if nrm_compose(ns,nt,qb,dd,map,tpar,tbind,bdst,bound,sse,tse,WB,PB,DB,sbx)!=0 { return 6 } 846 var fail: i64=0 847 if ca!=nxa_check2(nxa_check2(nxa_check2(1,WA,nt*4),PA,nt*3),DA,nt*3) { fail=fail+1 } 848 if csource!=nxa_check2(nxa_check2(1,qa,ns*4),da,ns*3) { fail=fail+1 } 849 let cb: i64=nxa_check2(nxa_check2(nxa_check2(1,WB,nt*4),PB,nt*3),DB,nt*3) 850 if nrm_compose(ns,nt,qa,da,map,tpar,tbind,bdst,bound,sse,tse,WA,PA,DA,sa)!=0 { return 6 } 851 if cb!=nxa_check2(nxa_check2(nxa_check2(1,WB,nt*4),PB,nt*3),DB,nt*3) { fail=fail+1 } 852 if before!=nxa_check2(1,anim,aw) { fail=fail+1 } 853 var articulated: i64=0 854 j=0 855 while j<nt { 856 if tpar[j]>=0 { 857 if WA[j*4]!=WB[j*4] { articulated=articulated+1 } 858 else { if WA[j*4+1]!=WB[j*4+1] { articulated=articulated+1 } 859 else { if WA[j*4+2]!=WB[j*4+2] { articulated=articulated+1 } 860 else { if WA[j*4+3]!=WB[j*4+3] { articulated=articulated+1 } } } } 861 } 862 j=j+1 863 } 864 let lc: *i64=sys_mmap(32) 865 let la: *i64=sys_mmap(32) 866 let lb: *i64=sys_mmap(32) 867 var local_changes: i64=0 868 j=0 869 while j<nt { 870 let pj: i64=tpar[j] 871 if pj>=0 { if bdst[j]<=bound { 872 nf_qconj(nr_q(qa,map[pj]),lc) 873 nf_qmul(lc,nr_q(qa,map[j]),la) 874 nf_qconj(nr_q(qb,map[pj]),lc) 875 nf_qmul(lc,nr_q(qb,map[j]),lb) 876 nf_qnorm(la);nf_qnorm(lb) 877 var sign: i64=1 878 if la[0]*lb[0]+la[1]*lb[1]+la[2]*lb[2]+la[3]*lb[3]<0 { sign=0-1 } 879 if la[0]!=sign*lb[0] { local_changes=local_changes+1 } 880 else { if la[1]!=sign*lb[1] { local_changes=local_changes+1 } 881 else { if la[2]!=sign*lb[2] { local_changes=local_changes+1 } 882 else { if la[3]!=sign*lb[3] { local_changes=local_changes+1 } } } } 883 } } 884 j=j+1 885 } 886 nrw("MOTION-GATE mapped_local_articulation_changes=" as *u8);nrn(local_changes);nrw("\n" as *u8) 887 if local_changes==0 { fail=fail+1 } 888 nrw("MOTION-GATE duration_ms=" as *u8);nrn(dur) 889 nrw(" phase_a_ms=0 phase_b_ms=" as *u8);nrn(dur/3) 890 nrw(" nonroot_world_quaternion_changes=" as *u8);nrn(articulated) 891 nrw(" isolation_failures=" as *u8);nrn(fail);nrw("\n" as *u8) 892 if articulated==0 { fail=fail+1 } 893 fail=fail+nmg_bones(nt,tpar,tbind,WA,PA) 894 fail=fail+nmg_bones(nt,tpar,tbind,WB,PB) 895 nrw("MOTION-GATE failures=" as *u8);nrn(fail);nrw("\n" as *u8) 896 if fail!=0 { return 1 } 897 898 let frame_input:*NrmFrameInput=sys_mmap(__size_of(NrmFrameInput)) as *NrmFrameInput 899 if (frame_input as i64)<=0 {return 8} 900 frame_input.anim=anim 901 frame_input.tidx=tidx 902 frame_input.order=order 903 frame_input.ns=ns 904 frame_input.nt=nt 905 frame_input.sax=sax 906 frame_input.ssg=ssg 907 frame_input.tax=tax 908 frame_input.tsg=tsg 909 frame_input.map=map 910 frame_input.tpar=tpar 911 frame_input.tbind=tbind 912 frame_input.bdst=bdst 913 frame_input.bound=bound 914 frame_input.sse=sse 915 frame_input.tse=tse 916 let stream_words:i64=nrm_frame_words(ns,nt) 917 let stream_work:*i64=sys_mmap(stream_words*8) 918 let stream_rows:*i64=sys_mmap(nt*64) 919 let oracle_rows:*i64=sys_mmap(nt*64) 920 let pack_work:*i64=sys_mmap(NA_SCR_W*8) 921 if (stream_work as i64)<=0||(stream_rows as i64)<=0||(oracle_rows as i64)<=0||(pack_work as i64)<=0 {return 8} 922 var stream_fail:i64=0 923 var phase:i64=0 924 while phase<32 { 925 let time:i64=phase*dur/31 926 nmg_sample(anim,tidx,order,ns,time,sax,ssg,tax,tsg,qa,da) 927 if nrm_compose(ns,nt,qa,da,map,tpar,tbind,bdst,bound,sse,tse,WA,PA,DA,sa)!=0 {return 6} 928 if nmp_rows(nt,tbind,WA,DA,oracle_rows,pack_work)!=0 {return 10} 929 if nrm_frame(frame_input,time,stream_rows,nt*8,stream_work,stream_words)!=0 {return 11} 930 var lane:i64=0 931 while lane<nt*8 {if stream_rows[lane]!=oracle_rows[lane] {stream_fail=stream_fail+1}lane=lane+1} 932 phase=phase+1 933 } 934 let stream_check:i64=nxa_check2(1,stream_rows,nt*8) 935 if nrm_frame(frame_input,0,stream_rows,nt*8,stream_work,stream_words-1)!=(0-10) {stream_fail=stream_fail+1} 936 if stream_check!=nxa_check2(1,stream_rows,nt*8) {stream_fail=stream_fail+1} 937 if nrm_frame(frame_input,0,stream_rows,nt*8-1,stream_work,stream_words)!=(0-11) {stream_fail=stream_fail+1} 938 if stream_check!=nxa_check2(1,stream_rows,nt*8) {stream_fail=stream_fail+1} 939 if nrm_frame_words(9223372036854775807,nt)!=0 {stream_fail=stream_fail+1} 940 if before!=nxa_check2(1,anim,aw) {stream_fail=stream_fail+1} 941 nrw("MOTION-STREAM phases=32 workspace_bytes=" as *u8);nrn(stream_words*8);nrw(" mismatches_or_refusal_failures=" as *u8);nrn(stream_fail);nrw("\n" as *u8) 942 sys_munmap(stream_work,stream_words*8);sys_munmap(stream_rows,nt*64);sys_munmap(oracle_rows,nt*64);sys_munmap(pack_work,NA_SCR_W*8) 943 if stream_fail!=0 {return 11} 944 945 if (outpath as i64)!=0 { 946 if samples<2||samples>dur+1 {return 7} 947 if nt>(9223372036854775807-32)/8/22 {return 7} 948 if samples>(9223372036854775807-256)/(nt*8*22+32) {return 7} 949 let cap:i64=samples*(nt*8*22+32)+256 950 let buf:*u8=sys_mmap(cap) 951 let rows:*i64=sys_mmap(nt*8*8) 952 let work:*i64=sys_mmap(NA_SCR_W*8) 953 if (buf as i64)<=0||(rows as i64)<=0||(work as i64)<=0 {return 8} 954 var at:i64=0 955 buf[at]=91 as u8;at=at+1 956 at=nmp_num(buf,at,nt);buf[at]=44 as u8;at=at+1 957 at=nmp_num(buf,at,dur);buf[at]=44 as u8;at=at+1 958 at=nmp_num(buf,at,samples) 959 var frame:i64=0 960 while frame<samples { 961 let time:i64=frame*dur/(samples-1) 962 nmg_sample(anim,tidx,order,ns,time,sax,ssg,tax,tsg,qa,da) 963 if nrm_compose(ns,nt,qa,da,map,tpar,tbind,bdst,bound,sse,tse,WA,PA,DA,sa)!=0 {return 6} 964 if nmg_bones(nt,tpar,tbind,WA,PA)!=0 {return 6} 965 if nmp_rows(nt,tbind,WA,DA,rows,work)!=0 {return 10} 966 buf[at]=44 as u8;at=at+1;at=nmp_num(buf,at,time) 967 var lane:i64=0 968 while lane<nt*8 {buf[at]=44 as u8;at=at+1;at=nmp_num(buf,at,rows[lane]);lane=lane+1} 969 frame=frame+1 970 } 971 buf[at]=93 as u8;at=at+1;buf[at]=10 as u8;at=at+1 972 let fd:i64=sys_openat_exclusive(outpath,NR_MODE) 973 if fd<0 {return 9} 974 var sent:i64=0 975 while sent<at { 976 let wrote:i64=sys_write(fd,((buf as i64)+sent) as *u8,at-sent) 977 if wrote<=0 {sys_close(fd);return 9} 978 sent=sent+wrote 979 } 980 let sync:i64=sys_fsync(fd) 981 let close:i64=sys_close(fd) 982 if sync!=0||close!=0 {return 9} 983 nrw("MOTION-PALETTE samples=" as *u8);nrn(samples);nrw(" bytes=" as *u8);nrn(at);nrw("\n" as *u8) 984 sys_munmap(buf,cap);sys_munmap(rows,nt*8*8);sys_munmap(work,NA_SCR_W*8) 985 } 986 return 0 987} 988func main(argc: i64, argv: *i64) -> i64 { 989 if argc<3 { nrerr("usage: motion_gate source.nxa target.nxa [expect-refusal]\n" as *u8);return 2 } 990 if nr_bindquats(argv[1] as *u8)!=0 { return 1 } 991 if nr_bindquats(argv[2] as *u8)!=0 { return 1 } 992 var outpath:*u8=0 as *u8 993 var samples:i64=0 994 if argc==5 {outpath=argv[3] as *u8;samples=nr_atoi(argv[4] as *u8)} 995 let rc: i64=nmg_asset(argv[1] as *u8,argv[2] as *u8,outpath,samples) 996 if argc>3 { if nr_streq(argv[3] as *u8,"expect-refusal" as *u8)==1 { 997 if rc==NR_EXIT_REFUSE { nrw("MOTION-GATE expected admission refusal observed\n" as *u8);return 0 } 998 nrerr("MOTION-GATE expected refusal missing\n" as *u8);return 1 999 } } 1000 return rc 1001}