code wiki / (root) / nx_gsplat_density.nx

nx_gsplat_density.nx

buildroot/runtime/nx_gsplat_density.nx

10426 B215 linesdepth 3pulls 5 transitivereach 1 importersview sourcekind librarytopic gsplat
docsdependenciesstructsconstsfunctions

about

nx_gsplat_density.nx -- ADAPTIVE SPLAT DENSITY (split / clone / prune), rung 4 of the fitting ladder. The fitter (gs_pos_grad_step_aniso) already measures, per primitive, everything this decision needs: gradbuf[g*3], gradbuf[g*3+1] -- the screen-space residual gradient gradbuf[g*3+2], wnorm[g] -- the Gauss-Newton curvature denominators pa/pc[g] -- the conic, hence the screen footprint via gs_splat_rx/ry depth[g] >= 0 -- visible in this view So densification is a CLASSIFIER over state that already exists. It derives no new quantity and re-renders nothing; a second measurement here would be a second ruler. EVERY THRESHOLD IS DERIVED FROM THE POPULATION OR THE FORMAT. NONE IS PICKED. The published 3DGS rule densifies on a view-space gradient above a FIXED tau (0.0002 in the paper). That constant is calibrated to their units, their scene scale and their float pipeline; copying it into an integer fixed-point renderer would be a picked number wearing a citation. So the bar here is the population's OWN MEAN, recomputed every step: DENSIFY iff |gx| + |gy| > mean(|gx| + |gy|) over VISIBLE primitives A mean needs no parameter, adapts to scene scale and to fitting progress by construction, and cannot go stale. L1 is used rather than L2 because this is an ORDERING against a mean of the same measure -- no square root, exact in integers, and monotone in the same direction as L2. SPLIT vs CLONE, also against the population's own mean, and the reasoning is the paper's: footprint > mean footprint -> SPLIT (over-reconstruction: one large splat spanning detail it cannot represent; two smaller ones can) footprint <= mean footprint -> CLONE (under-reconstruction: the region is under-covered, so add a second primitive of the same size) Footprint is the screen half-extent gs_splat_rx(ca) + gs_splat_ry(cc) -- the renderer's OWN support radius, so a splat is judged by exactly the extent it actually paints. PRUNE, derived from the FIXED-POINT FORMAT rather than from the population: a splat contributes c*T*alpha/GFXA to a channel; peak over T<=GFXA and alpha<=op gives c*op/GFXA. With the framebuffer quantised to 8 bits (c <= 255), that peak is below one quantisation step when op * 255 < GFXA Such a primitive CANNOT change any pixel at any depth or colour. It is invisible by the arithmetic of the format, not by a judgement about smallness. A view-dependent prune was CONSIDERED AND REJECTED, and the reason is multi-view correctness. Pruning on zero accumulated footprint in this view, or on depth[g] < 0, would delete primitives that are culled HERE and visible from another camera -- and the fitter is now multi-view (it cycles yaw across steps). A prune rule that is correct per-view and wrong per-scene is the worst kind, because every single-view test passes. Opacity is view-independent, so the shipped rule is.

dependencies 2 imports · 1 importers

nx_syscalls.nx nx_gsplat.nx nx_gsplat_density.nx nx_gsplat_density_gate.nx

imports: nx_syscalls.nxnx_gsplat.nx

imported by: nx_gsplat_density_gate.nx

structs

none

consts

55const GD_S_IN: i64 = 0
56const GD_S_KEPT: i64 = 1
57const GD_S_SPLIT: i64 = 2
58const GD_S_CLONED: i64 = 3
59const GD_S_PRUNED: i64 = 4
60const GD_S_OUT: i64 = 5
61const GD_S_GMEAN: i64 = 6
62const GD_S_RMEAN: i64 = 7
63const GD_S_VIS: i64 = 8
64const GD_S_REFUSED: i64 = 9
71const GD_S_ABOVEBAR: i64 = 10
72const GD_STATN: i64 = 11
74const GD_C_PRUNE: i64 = 0
75const GD_C_KEEP: i64 = 1
76const GD_C_SPLIT: i64 = 2
77const GD_C_CLONE: i64 = 3

functions

79func gd_stat_count() -> i64 { return GD_STATN }
called by 1: main
80func gd_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
called by 2: gd_meansgd_classify
84func gd_invisible(op: i64) -> i64 { if op * 255 < gs_fxa() { return 1 } return 0 }
called by 2: gd_classifymain calls 1: gs_fxa
88func gd_means(ng: i64, depth: *i64, pa: *i64, pc: *i64, gradbuf: *i64, out2: *i64) -> i64
111func gd_classify(gauss: *i64, ng: i64, depth: *i64, pa: *i64, pc: *i64, gradbuf: *i64, gmean: i64, rmean: i64, stats: *i64) -> i64
139func gd_copy(src: *i64, si: i64, dst: *i64, di: i64, st: i64) -> i64
called by 1: gs_densify
148func gs_densify(gauss: *i64, ng: i64, ngmax: i64, depth: *i64, pa: *i64, pc: *i64, gradbuf: *i64, outbuf: *i64, m2: *i64, stats: *i64) -> i64