perf(mesh): skip per-vertex snap tables above 50k vertices

The subdivision MESH converter emitted one snap candidate and one key
vertex per mesh vertex — ~56 B/vertex retained in every copy of the
wire set. On NWD-scale imports (#358: tens of millions of vertices)
that is GBs spent on snap targets far too dense to distinguish on
screen. PolyfaceMesh and PolygonMesh already ship empty tables at any
size.

Above 50,000 vertices, ship none. Smaller meshes (including the #358
repro sample at 34.6k vertices per mesh) keep vertex snap unchanged.

Measured (mem_probe_meshent, 1M-triangle MESH): 646 -> 589 B/face
resident; wire content 210 -> 183 MB per 1M triangles.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
Kevin GriffinandClaude Fable 5 committed 2026-07-22 12:59:07 -07:00
1 parent f347a20a4c
commit 5aecdff12e
1 file changed
+17 -6
+17 -6
View File
@@ -685,12 +685,23 @@ impl TruckConvertible for Mesh {
}
}
let snap_pts: Vec<(glam::DVec3, SnapHint)> = self
.vertices
.iter()
.map(|v| (glam::DVec3::new(v.x, v.y, v.z), SnapHint::Node))
.collect();
let key_vertices: Vec<[f64; 3]> = self.vertices.iter().map(|v| [v.x, v.y, v.z]).collect();
// Per-vertex snap tables cost ~56 B/vertex and are retained in every
// copy of the wire set. On NWD-scale imports (#358: tens of millions
// of mesh vertices) that is GBs for snap targets far too dense to
// pick apart on screen — so past this size ship none, which is what
// PolyfaceMesh / PolygonMesh already do at any size.
const SNAP_TABLE_MAX_VERTICES: usize = 50_000;
let (snap_pts, key_vertices) = if self.vertices.len() > SNAP_TABLE_MAX_VERTICES {
(Vec::new(), Vec::new())
} else {
(
self.vertices
.iter()
.map(|v| (glam::DVec3::new(v.x, v.y, v.z), SnapHint::Node))
.collect(),
self.vertices.iter().map(|v| [v.x, v.y, v.z]).collect(),
)
};
Some(TruckEntity {
pick_tris: Vec::new(),