code wiki / (root) / nx_gsplat4d_lib.nx

nx_gsplat4d_lib.nx

buildroot/runtime/nx_gsplat4d_lib.nx

16221 B356 linesdepth 3pulls 5 transitivereach 1 importersview sourcekind library
docsdependenciesstructsconstsfunctions

about

nx_gsplat4d_lib.nx -- ★4D SPATIOTEMPORAL GAUSSIAN SPLATTING: the temporal axis the estate did not have. WHAT WAS ALREADY HERE (measured 2026-08-14 three independent ways: nx_capsearch over 1033 registered tools, a coverage-complete grep of 23,023 sources, and reading the source): nx_gsplat is a real, gated, sovereign 3D splatter -- isotropic blobs AND anisotropic surfels whose 2D covariance Sigma' is computed EXACTLY by projecting the principal axes through the camera (the Jacobian, applied as a finite projection rather than a symbolic J R S S^T R^T J^T), a conic power test against an integer exp-LUT, a counting sort by depth, and front-to-back compositing C = sum c_i a_i prod(1-a_j). That is the rasterizer. It is NOT re-implemented here. WHAT WAS ABSENT: time. Every Gaussian in the estate was static. This organ adds the 4th axis and nothing else -- it deforms state and hands the result to gs_render_aniso. One rasterizer, still. THE KERNEL is the standard 4DGS temporal radial basis, integer-exact: x_t = x_0 + v * (t - t_mu) * exp(-(t - t_mu)^2 / (2 * t_sigma^2)) ★AND THE ENVELOPE COSTS NOTHING NEW: the incumbent's exp-LUT is explut[k] = GFXA*exp(-k/(2*GLUTU)), so indexing it at k = GLUTU * dt^2/sigma^2 yields exp(-dt^2/(2 sigma^2)) EXACTLY -- the Gaussian envelope, from the table the renderer already builds. A second exp table would have been a duplicate ruler. ★★NO RE-DECLARED CONSTANTS. The fixed-point scale, the LUT resolution and the record stride are FACTS OF THE RASTERIZER and are read from it (gs_fxa / gs_lutu / gs_stride_aniso). An earlier revision of this file hardcoded 256, 16 and 12; nx_magic at threshold 2 found them. They are not cosmetic: each was a SECOND RULER, and the failure mode of a second ruler is that the two disagree silently, compile cleanly, and render something plausible. There is no symptom to notice. ★★THE ARENA COUNTS ITSELF. Every allocation goes through g4_alloc, which accumulates the byte total as a side effect of allocating -- so g4_bytes() cannot drift from reality. The previous revision multiplied a HAND-WRITTEN COUNT of the field arrays; adding a field and forgetting to bump it would have silently under-reported the resource envelope, which is a fabricated number wearing the shape of a measurement. LAYOUT: Structure-of-Arrays, one array per field -- a field sweep touches contiguous memory instead of striding over a record. Arrays are lazily allocated once against a declared capacity. ⚠DELIBERATE, DECLARED DIFFERENCES FROM A LITERAL FIELD-LIST TRANSCRIPTION -- each is a defect avoided: - POSITION uses the signed ramp x envelope above (the kernel as specified). - RADIUS uses the envelope ALONE, not the ramp. A signed ramp on a radius crosses zero and inverts the splat, which the rasterizer cannot represent. A breathing surfel is the honest analogue. - NORMAL uses ramp x envelope and is then RENORMALISED, so the surfel tips without its length drifting. It is also the G-buffer normal the lighting rung will read. - QUATERNION and 3-axis SCALE are NOT stored. The incumbent surfel is a DISK (normal + in-plane

dependencies 2 imports · 1 importers

nx_syscalls.nx nx_gsplat.nx nx_gsplat4d_lib.nx nx_gsplat4d_gate.nx

imports: nx_syscalls.nxnx_gsplat.nx

imported by: nx_gsplat4d_gate.nx

structs

none

consts

53const G4_TSCALE: i64 = 1000
57const G4_RING_MIN: i64 = 2
58const G4_ERRFD: i64 = 2
59const G4_W64: i64 = 8 // the machine word this SoA is built from
60const G4_E_CAP: i64 = 4
61const G4_E_SIGMA: i64 = 3
62const G4_E_RANGE: i64 = 5
63const G4_E_RING: i64 = 6

functions

96func g4_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
called by 2: maing4_err
97func g4_err(s: *u8) -> i64 { sys_write(G4_ERRFD, s, g4_slen(s)); return 0 }
102func g4_alloc(n: i64) -> i64
called by 1: g4_init calls 1: sys_mmap
108func g4_init(cap: i64, ring: i64) -> i64
146func g4_cap() -> i64 { return G4_CAP }
called by 1: main
147func g4_n() -> i64 { return G4_N }
called by 1: main
148func g4_bytes() -> i64 { return G4_ALLOC }
called by 1: main
149func g4_ring_depth() -> i64 { return G4_RINGN }
called by 1: main
150func g4_tscale() -> i64 { return G4_TSCALE }
called by 1: main
151func g4_ring_min() -> i64 { return G4_RING_MIN }
called by 1: main
155func g4_set_rest(i: i64, x: i64, y: i64, z: i64, nx: i64, ny: i64, nz: i64, rt: i64, r: i64, g: i64, b: i64, op: i64) -> i64
called by 2: gg_scenemain calls 1: g4_err
188func g4_set_time(i: i64, tmu: i64, tsig: i64) -> i64
called by 2: gg_scenemain calls 1: g4_err
200func g4_set_motion(i: i64, vx: i64, vy: i64, vz: i64, drt: i64, dnx: i64, dny: i64, dnz: i64) -> i64
called by 1: gg_scene calls 1: g4_err
218func g4_envelope(i: i64, t: i64) -> i64
called by 2: maing4_bake calls 1: gs_lutu
231func g4_wfull() -> i64 { let el: *i64 = G4_EXPLUT as *i64; return el[0] }
called by 1: main
235func g4_lut(k: i64) -> i64
called by 1: main
243func g4_horizon_sigma() -> i64 { return gs_isqrt(G4_EXPN/gs_lutu()) }
called by 1: main calls 2: gs_isqrtgs_lutu
248func g4_bake(t: i64, out: *i64) -> i64
305func g4_ring_init() -> i64
called by 1: g4_ring_prime
312func g4_ring_frame(s: i64) -> *i64
called by 2: maing4_ring_fill calls 1: gs_stride_aniso
315func g4_ring_time(s: i64) -> i64 { let rt: *i64 = G4_RT_T as *i64; return rt[s] }
316func g4_ring_valid(s: i64) -> i64 { let rv: *i64 = G4_RVALID as *i64; return rv[s] }
called by 1: main
317func g4_ring_head() -> i64 { return G4_RHEAD }
319func g4_ring_fill(s: i64, t: i64) -> i64
327func g4_ring_prime(t0: i64, step: i64) -> i64
called by 1: main calls 2: g4_ring_initg4_ring_fill
335func g4_ring_find(t: i64) -> i64
called by 1: main
347func g4_ring_advance(step: i64) -> i64
called by 1: main calls 1: g4_ring_fill