code wiki / (root) / nx_boneheat_lib.nx

nx_boneheat_lib.nx

buildroot/runtime/nx_boneheat_lib.nx

38086 B824 linesdepth 2pulls 5 transitivereach 17 importersview sourcekind library
docsdependenciesstructsconstsfunctions

about

nx_boneheat_lib.nx -- SOVEREIGN AUTO-WEIGHTS: geodesic bone-heat skin weights over the VOXELISED VOLUME of a mesh. WHY (2026-09-05). modding MD4 and dcc DC16 both price auto-rigging, and MD4's pre-declared accept rule says the learned rig must beat a nearest-joint heat-weight CONTROL -- an organ the estate did not have (nx_catalog: nx_boneheat ABSENT; nx_capsearch: no voxel flood-fill and no geodesic-weight ruler anywhere in 7,414 sources). nx_nxa_skin's autoskin is nearest-segment inverse-distance, which bleeds across air: a hand resting on a hip takes hip weight. That is the failure Blender's Automatic Weights (bone heat, Baran and Popovic 2007) avoids and the one Maya's geodesic voxel bind (Dionne and de Lasa 2013) avoids more robustly, because it never needs a manifold mesh -- it needs a volume. This lib is that class, integer and deterministic, first byte up: 1. VOXELISE: rasterise every triangle into a grid sized from knowledge/boneheat.conf, flood the EXTERIOR from the padded border through non-surface cells, and call the rest INTERIOR. The partition is printed and SUMS. A mesh that is not sealed simply has interior=0 and the solve runs over its shell: no refusal, announced. 2. SEED: each joint owns the segment from itself to the mean of its children (a leaf owns a point); the segment's cells are distance 0. A joint whose segment lies outside the volume is PROJECTED to the nearest domain cell and COUNTED, never silently dropped. 3. SOLVE: per joint, Dijkstra over the 26-connected domain with chamfer weights 10/14/17 (Dial buckets, an exact push bound of 26 per settled cell). Air is not domain, so distance cannot cross it -- that is the whole difference from nearest-joint, and the gate proves it on two shells. 4. WEIGH: per vertex keep the four nearest joints at 2^40/(d+half)^2, normalise to the NXA sum of 4096 with the residual folded into the largest influence (the estate's own zero-volume-loss rule). Vertices no joint can reach fall back to the nearest segment and are COUNTED. The NEAREST mode is the control MD4 names: one joint, weight 4096, the nearest segment by Euclidean distance. It shares every reader and the writer, so the two modes cannot disagree about the asset. UNITS: VERT and SKEL are 0.01 mm model units (NXA v1); the grid cell is derived from the bounding box. license_tier: ORIGINAL

dependencies 3 imports · 6 importers

nx_syscalls.nx nx_nxa.nx nx_vecmath.nx nx_boneheat_lib.nx nx_boneheat.nx nx_boneheat_gate.nx nx_curveskel_lib.nx nx_motion_gate.nx nx_motion_serve_gate.nx nx_profile_semantic_overlay_t239.n

imports: nx_syscalls.nxnx_nxa.nxnx_vecmath.nx

imported by: nx_boneheat.nxnx_boneheat_gate.nxnx_curveskel_lib.nxnx_motion_gate.nxnx_motion_serve_gate.nxnx_profile_semantic_overlay_t239.nx

structs

none

consts

30const BH_Q12: i64 = 4096 // NXA v1: q12 weights summing 4096 (format-fixed)
31const BH_INF_SLOTS: i64 = 4 // NXA v1: 4 influences per vertex (format-fixed)
32const BH_JOINT_WORDS: i64 = 8 // SKEL row: parent tx ty tz qx qy qz qw
33const BH_SKIN_WORDS: i64 = 8 // SKIN row: 4 joint ids then 4 q12 weights
34const BH_VERT_WORDS: i64 = 3
35const BH_TRI_WORDS: i64 = 3
36const BH_HDR_BYTES: i64 = 32 // magic ver ns toc-check
37const BH_TOC_WORDS: i64 = 4 // tag byte-offset word-len payload-check
38const BH_TOC_BYTES: i64 = 32
39const BH_MAX_SECTIONS: i64 = 64 // nxa_find's own bound
40const BH_KIND_EXTERIOR: i64 = 0
41const BH_KIND_SURFACE: i64 = 1
42const BH_KIND_INTERIOR: i64 = 2
43const BH_KIND_UNSEEN: i64 = 3
44const BH_DILATE_STEPS: i64 = 1 // bh_dilate runs ONE 6-dilation; the shell depth below is derived from it
45const BH_WALL_DEPTH: i64 = 3 // 1 (the raster's own cell) + 2 x BH_DILATE_STEPS: the deepest six-step a REAL shell cell can sit from the exterior
46const BG_WALLS: i64 = 21 // internal-wall cells stripped to INTERIOR by bh_flood (grid descriptor slot)
47const BR_WALLS: i64 = 20 // the same count in the report, so the caller can print walls=
48const BH_WALL_HIST: i64 = 10 // shell-depth census buckets d1..d9 (d9 = nine or deeper): the measurement the strip depth is DERIVED from
49const BH_STEP: i64 = 10 // one face step = 10 so the chamfer weights stay integer
50const BH_W_FACE: i64 = 10 // sqrt(1) x 10
51const BH_W_EDGE: i64 = 14 // sqrt(2) x 10, rounded
52const BH_W_CORNER: i64 = 17 // sqrt(3) x 10, rounded
53const BH_NBUCKET: i64 = 18 // Dial buckets = largest edge weight + 1
54const BH_PUSH_PER_CELL: i64 = 26 // a settled cell relaxes at most its 26 neighbours: the pool bound is EXACT
55const BH_DIST_INF: i64 = 1152921504606846976
56const BH_HALF_STEP: i64 = 5 // half a face step: the smallest distance the grid resolves
57const BH_WSCALE_SHIFT: i64 = 40 // raw weight = 2^40 / (d + half)^2
58const BH_PAD_CELLS: i64 = 2 // DERIVED = 1 + BH_DILATE_STEPS: bh_dilate grows the shell OUTWARD by one cell, so a one-cell pad is FILLED wherever a face touches the bounding box and the exterior flood is starved there. MEASURED 2026-09-06 on a lone 60 mm prism (no internal geometry): exterior 472 of 14,112 cells, shell-depth census RISING with depth (d1=1352 d3=2424 d5=2136) and 4,416 false walls; the sheet neg-control stopped being refused. One spare layer beyond the dilation keeps a flood seed on every side.
59const BH_SAMPLE_DIV: i64 = 2 // triangles and segments are sampled at half a cell: no cell is skipped
60const BH_GRID_DEFAULT: i64 = 96 // used ONLY when the conf is absent; provenance is printed
61const BH_MODE_GEODESIC: i64 = 1
62const BH_MODE_NEAREST: i64 = 2
63const BH_Q10: i64 = 1024 // segment parameter fixed point for the nearest control
64const BH_MODE_0644: i64 = 420
65const BH_NOJOINT: i64 = 0 - 1
66const BH_CONF_KEY: *u8 = "grid_cells_longest="
67const BH_CONF_PATH: *u8 = "knowledge/boneheat.conf"
69const BG_NX: i64 = 0
70const BG_NY: i64 = 1
71const BG_NZ: i64 = 2
72const BG_CELL: i64 = 3
73const BG_OX: i64 = 4
74const BG_OY: i64 = 5
75const BG_OZ: i64 = 6
76const BG_N: i64 = 7
77const BG_KIND: i64 = 8
78const BG_DIST: i64 = 9
79const BG_SET: i64 = 10
80const BG_POOLC: i64 = 11
81const BG_POOLN: i64 = 12
82const BG_POOLCAP: i64 = 13
83const BG_HEAD: i64 = 14
84const BG_EXT: i64 = 15
85const BG_SURF: i64 = 16
86const BG_INT: i64 = 17
87const BG_DOMAIN: i64 = 18
88const BG_POOLUSED: i64 = 19
89const BG_QUEUE: i64 = 20
90const BG_WORDS: i64 = 24
92const BR_VERTS: i64 = 0
93const BR_TRIS: i64 = 1
94const BR_JOINTS: i64 = 2
95const BR_CELLS: i64 = 3
96const BR_EXT: i64 = 4
97const BR_SURF: i64 = 5
98const BR_INT: i64 = 6
99const BR_SEALED: i64 = 7
100const BR_SEEDS: i64 = 8
101const BR_PROJECTED: i64 = 9
102const BR_UNREACH_J: i64 = 10
103const BR_UNREACH_V: i64 = 11
104const BR_MIXED: i64 = 12
105const BR_BYTES: i64 = 13
106const BR_NX: i64 = 14
107const BR_NY: i64 = 15
108const BR_NZ: i64 = 16
109const BR_CELL: i64 = 17
110const BR_CONF: i64 = 18
111const BR_GRIDN: i64 = 19
112const BR_WORDS: i64 = 24
114const BH_EXIT_OK: i64 = 0
115const BH_EXIT_USAGE: i64 = 2
116const BH_EXIT_REFUSE: i64 = 3

functions

118func bh_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
119func bh_num(v: i64) -> i64
called by 1: bh_kv calls 2: sys_mmapsys_write
132func bh_kv(k: *u8, v: i64) -> i64 { bh_puts(k); bh_num(v); return 0 }
called by 3: bh_floodbh_reportmain calls 2: bh_putsbh_num
133func bh_max(a: i64, b: i64) -> i64 { if a > b { return a } return b }
134func bh_min(a: i64, b: i64) -> i64 { if a < b { return a } return b }
called by 1: bh_grid_build
135func bh_abs(a: i64) -> i64 { if a < 0 { return 0 - a } return a }
136func bh_streq(a: *u8, b: *u8) -> i64
called by 1: main
144func bh_conf_cells(path: *u8) -> i64
177func bh_idx(g: *i64, ix: i64, iy: i64, iz: i64) -> i64
186func bh_cell_of(g: *i64, x: i64, y: i64, z: i64) -> i64
190func bh_kind(g: *i64, c: i64) -> i64 { let k: *u8 = g[BG_KIND] as *u8; return k[c] as i64 }
called by 1: bh_is_domain
191func bh_is_domain(g: *i64, c: i64) -> i64
199func bh_grid_build(g: *i64, w: *i64, vwo: i64, nv: i64, cells: i64) -> i64
233func bh_mark_surface(g: *i64, x: i64, y: i64, z: i64) -> i64
called by 1: bh_raster calls 1: bh_cell_of
240func bh_seglen(ax: i64, ay: i64, az: i64, bx: i64, by: i64, bz: i64) -> i64
called by 2: bh_rasterbh_seed_segment calls 1: vm_isqrt
245func bh_raster(g: *i64, w: *i64, vwo: i64, two: i64, nt: i64) -> i64
277func bh_dilate(g: *i64) -> i64
called by 1: bh_flood calls 2: sys_mmapbh_idx
307func bh_flood(g: *i64) -> i64
438func bh_reset(g: *i64) -> i64
449func bh_push(g: *i64, c: i64, d: i64) -> i64
called by 2: bh_seedbh_dijkstra
462func bh_seed(g: *i64, c: i64) -> i64
471func bh_dijkstra(g: *i64) -> i64
526func bh_project(g: *i64, x: i64, y: i64, z: i64) -> i64
555func bh_seed_segment(g: *i64, ax: i64, ay: i64, az: i64, bx: i64, by: i64, bz: i64, projected: *i64) -> i64
575func bh_joint_segments(w: *i64, swo: i64, nj: i64, seg: *i64) -> i64
called by 1: bh_run calls 1: sys_mmap
605func bh_seg_dist2(seg: *i64, j: i64, x: i64, y: i64, z: i64) -> i64
called by 1: bh_nearest_joint
620func bh_nearest_joint(seg: *i64, nj: i64, x: i64, y: i64, z: i64) -> i64
called by 1: bh_run calls 1: bh_seg_dist2
632func bh_top4_insert(tj: *i64, tw: *i64, v: i64, j: i64, wgt: i64) -> i64
called by 1: bh_run
641func bh_nxa_write(path: *u8, ns: i64, tags: *i64, ptrs: *i64, wls: *i64) -> i64
671func bh_run(inpath: *u8, outpath: *u8, mode: i64, cells_conf: i64, rep: *i64) -> i64
811func bh_report(mode: i64, rep: *i64, inpath: *u8, outpath: *u8) -> i64
called by 4: mainmainmainmain calls 2: bh_putsbh_kv