code wiki / _hdl_build / nx_gsplatbind.nx
nx_gsplatbind.nx
buildroot/runtime/_hdl_build/nx_gsplatbind.nx
about
nx_gsplatbind.nx -- ★THE HYBRID: OUTSIDE SPLAT, INSIDE PARAMETRIC MESH (operator 2026-07-27,
"do the outside splat the inside the same as gnm google").
This is the mid-2026 industry architecture and it resolves the 3DGS-vs-poly-mesh question without
choosing: a low-resolution parametric mesh acts as the DRIVING CAGE, and millions of Gaussians are
anchored to its triangles. When the rig deforms the cage, the splat cloud is carried with it. You get
the animation, physics, collision and EDITABILITY of a mesh with the photorealism of splats -- and,
decisively for this program, the mesh keeps the INTERIOR that a splat cloud cannot have at all.
★WHY THE MESH MUST STAY THE SOURCE OF TRUTH HERE: every load-bearing claim of the twin program --
layered bone/muscle/fascia, surgical prediction, joint limits, self-penetration, centre-of-mass --
needs structured solid geometry. Splats are an APPEARANCE representation with no inside. So the
binding is deliberately one-directional: the mesh drives, the splats follow, never the reverse.
★THE BINDING (GaussianAvatars-class): each Gaussian is stored in the LOCAL FRAME of its triangle --
barycentric position within the face, a signed offset along the face normal, and a scale expressed as
a RATIO of the face's own size. Rebuilding from a deformed triangle then reproduces the splat in the
deformed configuration for free, at any pose, with no re-fit.
⚠DECLARED LIMIT: nx_gsplat v0 Gaussians are ISOTROPIC {x,y,z,scale,r,g,b,opacity} -- there is no
orientation term, so this binding carries POSITION and SIZE but has no rotation to carry. When
anisotropic covariance lands (nx_gsplat's own named next rung), the binding MUST also rotate each
Gaussian into the triangle's frame, and a splat that translates without rotating is the classic bug
-- highlights that slide across a turning surface. T4 is written now so that rung has a tooth waiting.
nx_gsplatbind selftest
license_tier: ORIGINAL expect_exit: 0 No hw writes (Rule 26).
dependencies 1 imports · 0 importers
imports: nx_gate_verdict.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 30 | const GB_FX: i64 = 1024 // fixed point for barycentric weights and scale ratios |
| 31 | const GB_GS: i64 = 8 // nx_gsplat gaussian stride {x,y,z,scale,r,g,b,opacity} |
| 32 | const GB_TS: i64 = 9 // triangle stride: 3 verts * xyz |
| 33 | const GB_BS: i64 = 5 // bind record: tri, u, v, h, scale_ratio |
| 169 | const GB_NT: i64 = 2 |
| 170 | const GB_NG: i64 = 6 |
functions
| 35 | func gb_isqrt(v: i64) -> i64 |
| 42 | func gb_iabs(v: i64) -> i64 { if v < 0 { return 0-v } return v } called by 1: main |
| 46 | func gb_face(tri: *i64, t: i64, n3: *i64) -> i64 |
| 63 | func gb_bind(g: *i64, ng: i64, tri: *i64, nt: i64, bind: *i64) -> i64 |
| 127 | func gb_drive(bind: *i64, g: *i64, ng: i64, tri: *i64, out: *i64) -> i64 |
| 173 | func gb_cage(tri: *i64, sc: i64, offx: i64, rot90: i64) -> i64 called by 1: main |
| 197 | func gb_cloud(g: *i64) -> i64 called by 1: main |
| 211 | func main(argc: i64, argv: *i64) -> i64 |