nx_softbind.nx
buildroot/runtime/nx_softbind.nx
about
nx_softbind.nx -- LIB: BINDS nx_softdyn to character geometry (roadmap rung A4, 2026-08-01).
The solver was proven 7/7 in isolation but bound to NOTHING -- no body part consumed it, so
nothing in the game visibly jiggled. This lib is the missing joint-anchor contract: each mob
owns SB_PTS spring points (hair / chest / skirt class), each seated at a fixed local offset
from the mob ROOT, stepped once per sim tick from root motion ONLY (organ truth -- the same
source as the mobdx/mobdz/mobdy doors), yielding signed Q8 offsets a renderer ADDS to its
designated joints on top of the animated pose (spring-decomposed-skinning pattern: helper
offsets over the animation, never replacing it). Pure function of the root trajectory =>
bit-deterministic, so replay / netsync / save-transparency hold by construction.
license_tier: ORIGINAL No hw writes (Rule 26).
dependencies 2 imports · 6 importers
imports: nx_syscalls.nxnx_softdyn.nx
imported by: nx_cg_restprobe.nxnx_mr_lagprobe.nxnx_softbind_gate.nxnx_softtissue_conserve_gate.nxnx_softtissue_mr_gate.nxnx_wasm_craft.nx
structs
| none |
consts
| 13 | const SB_MAGIC_5381: i64 = 5381 |
| 14 | const SB_MAGIC_1000000007: i64 = 1000000007 |
| 16 | const SB_PTS: i64 = 3 |
| 17 | const SB_HAIR: i64 = 0 |
| 18 | const SB_CHEST: i64 = 1 |
| 19 | const SB_SKIRT: i64 = 2 |
| 25 | const SB_K_HAIR: i64 = 200 |
| 26 | const SB_C_HAIR: i64 = 60 |
| 27 | const SB_K_CHEST: i64 = 85 |
| 28 | const SB_C_CHEST: i64 = 110 |
| 29 | const SB_K_SKIRT: i64 = 300 |
| 30 | const SB_C_SKIRT: i64 = 80 |
| 36 | const SB_K_CHEST_BASE: i64 = 60 |
| 37 | const SB_K_CHEST_STEP: i64 = 25 |
| 38 | const SB_C_CHEST_BASE: i64 = 100 |
| 39 | const SB_C_CHEST_STEP: i64 = 16 |
| 41 | const SB_MAXD_HAIR: i64 = 6 |
| 42 | const SB_MAXD_CHEST: i64 = 2 // +-3.1cm: tissue-vs-bone p2p <= 6.2cm, the cited band |
| 43 | const SB_MAXD_SKIRT: i64 = 5 |
| 45 | const SB_OFFY_HAIR: i64 = 17 |
| 46 | const SB_OFFY_CHEST: i64 = 12 |
| 47 | const SB_OFFY_SKIRT: i64 = 7 |
functions
| 49 | func sb_k(kind: i64) -> i64 { if kind == SB_HAIR { return SB_K_HAIR } if kind == SB_CHEST { return SB_K_CHEST } return SB_K_SKIRT } called by 1: sb_tick_mob |
| 50 | func sb_c(kind: i64) -> i64 { if kind == SB_HAIR { return SB_C_HAIR } if kind == SB_CHEST { return SB_C_CHEST } return SB_C_SKIRT } called by 1: sb_tick_mob |
| 51 | func sb_maxd(kind: i64) -> i64 { if kind == SB_HAIR { return SB_MAXD_HAIR } if kind == SB_CHEST { return SB_MAXD_CHEST } return SB_MAXD_SKIRT } |
| 52 | func sb_offy(kind: i64) -> i64 { if kind == SB_HAIR { return SB_OFFY_HAIR } if kind == SB_CHEST { return SB_OFFY_CHEST } return SB_OFFY_SKIRT } |
| 55 | func sb_alloc(nmobs: i64) -> *i64 { return sd_alloc(nmobs*SB_PTS) } |
| 58 | func sb_seat_mob(st: *i64, mobi: i64, rx: i64, ry: i64, rz: i64) -> i64 |
| 65 | func sb_tick_mob(st: *i64, mobi: i64, rx: i64, ry: i64, rz: i64) -> i64 |
| 74 | func sb_tick_pt(st: *i64, mobi: i64, kind: i64, rx: i64, ry: i64, rz: i64, K: i64, C: i64, maxd: i64) -> i64 |
| 79 | func sb_tick_mob_firm(st: *i64, mobi: i64, rx: i64, ry: i64, rz: i64, firm: i64) -> i64 |
| 91 | func sb_impulse_mob(st: *i64, mobi: i64, ix: i64, iy: i64, iz: i64) -> i64 |
| 100 | func sb_off_x_q8(st: *i64, mobi: i64, kind: i64, rx: i64) -> i64 |
| 103 | func sb_off_y_q8(st: *i64, mobi: i64, kind: i64, ry: i64) -> i64 |
| 106 | func sb_off_z_q8(st: *i64, mobi: i64, kind: i64, rz: i64) -> i64 |
| 110 | func sb_disp_q8(st: *i64, mobi: i64, kind: i64, rx: i64, ry: i64, rz: i64) -> i64 |
| 114 | func sb_energy(st: *i64, mobi: i64, kind: i64) -> i64 { return sd_energy(st, mobi*SB_PTS + kind) } |
| 117 | func sb_ck(st: *i64, nmobs: i64) -> i64 |