perf(snap): keep snap/hover responsive on block-heavy drawings

Snap and hover hit-testing scanned the whole model wire set every cursor move; a heavily block-instanced drawing explodes to millions of wires, so this stalled for over a second per move. Add a cached spatial grid (wire_grid) keyed on the geometry epoch and query only the cursor neighbourhood via Scene::hit_test_wires_near. Gate the O(in-range segments squared) intersection passes on the in-range POINT count, not the wire count — a handful of curved wires, each hundreds of tessellated points, blew the quadratic up while the wire count looked modest. Give zero-size entities away from the origin (POINTs) a real cullable AABB, and fall back to a block sub-wire's own world points when its entity bounding box is degenerate.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-07-09 01:00:51 +03:00
1 parent f91e45a62a
commit e1c19d8af3
6 files changed
+313 -15

No files matched your search

+8 -4
View File
@@ -731,7 +731,7 @@ pub(super) fn on_tick(&mut self, t: Instant) -> Task<Message> {
{
self.tabs[i].scene.model_wires_for_viewport_arc(h, bounds.height)
} else {
self.tabs[i].scene.hit_test_wires()
self.tabs[i].scene.hit_test_wires_near(raw, view_rot, bounds)
};
// Grip drag has no single rubber-band origin for a perp foot.
self.snapper.from_point = None;
@@ -853,7 +853,9 @@ pub(super) fn on_tick(&mut self, t: Instant) -> Task<Message> {
{
self.tabs[i].scene.model_wires_for_viewport_arc(h, bounds.height)
} else {
self.tabs[i].scene.hit_test_wires()
self.tabs[i]
.scene
.hit_test_wires_near(snap_cursor, view_rot, bounds)
};
let needs_entity = self.tabs[i]
.active_cmd
@@ -1347,7 +1349,7 @@ pub(super) fn on_tick(&mut self, t: Instant) -> Task<Message> {
{
self.tabs[i].scene.model_wires_for_viewport_arc(h, bounds.height)
} else {
self.tabs[i].scene.hit_test_wires()
self.tabs[i].scene.hit_test_wires_near(raw, view_rot, bounds)
};
self.snapper.grid_spacing = crate::ui::overlay::compute_grid_step(view_rot, bounds);
// No rubber-band origin (perp/extension feet don't apply to a free drag).
@@ -1801,7 +1803,9 @@ pub(super) fn on_tick(&mut self, t: Instant) -> Task<Message> {
{
self.tabs[i].scene.model_wires_for_viewport_arc(h, bounds.height)
} else {
self.tabs[i].scene.hit_test_wires()
self.tabs[i]
.scene
.hit_test_wires_near(snap_cursor, view_rot, bounds)
};
let needs_tan = self.tabs[i]
.active_cmd