mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-01 01:16:27 +00:00
wgpu: area measurement tool (A hotkey, BFS coplanar patch + cyan highlight)
Ports Bonsai's AreaMeasurement onto WgpuViewportWindow as a new WgpuAreaMeasurement class. Each LMB pick resolves to (instance, triangle), BFS-expands the coplanar patch (dot(normal, seed_normal) > 0.9999, ~0.81° tolerance), and toggles it in/out of the running set. Alt+LMB skips BFS for single-triangle accumulate. Connected-components sweep over the selected set produces one "X.XXXX m²" label per patch at its area-weighted centroid in world space; HUD shows the running total + triangle count. Dependencies layered in: - WgpuOverlayRenderer.setHighlightTriangles / encodeHighlightTriangles: translucent world-space triangle list (cyan @ 0.45 alpha), depth- tested but depth-write off so the corner gizmo + labels still sit on top. - WgpuViewportWindow.pickMeshLocalAt: reuses pickSurfaceAt for the world hit, then inverts the instance's composed transform to express it in mesh-local space — what the BFS needs. Uses the live map key (`mid`) rather than InstanceCpu.model_id, which is whatever the GL streamer wrote at sidecar-write time and goes stale across sessions. - WgpuViewportWindow.readbackMeshTriangles: CPU mesh shadow lookup. The shadow itself is populated during the same dequant pass that computes mesh-local volume — applyCachedModel for full loads and applyStreamedChunk for streaming, so the BFS has data the moment the user can pick it. WgpuModelGpuData gains a MeshTriangles vector indexed by mesh_id; doubles per-vertex CPU memory (12 B/vert) but skips wgpu mapAsync plumbing for now. Bounds-check at pick time gracefully no-ops when a stale sidecar field is out of range. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -288,6 +288,24 @@ struct WgpuModelGpuData {
|
||||
// until the chunk holding the mesh has been delivered.
|
||||
std::vector<double> mesh_local_volumes;
|
||||
|
||||
// CPU shadow of each mesh's mesh-local positions + LOD0 indices.
|
||||
// Populated at applyCachedModel (or per-chunk in streaming) from
|
||||
// the same raw vertex bytes the volume calc dequantises. The Area
|
||||
// measurement tool reads this directly — no GPU readback, matching
|
||||
// the Volume tool's policy.
|
||||
//
|
||||
// Doubles per-vertex memory (12 B/vert GPU + 12 B/vert CPU). The
|
||||
// alternative is a wgpu mapAsync readback per first-touched mesh,
|
||||
// which adds async plumbing and a per-click stall; pay the memory
|
||||
// upfront instead. Trim by sizing each entry down at population
|
||||
// (reserve exact). For huge federations this can be a real
|
||||
// working-set cost — revisit if it shows up in profiles.
|
||||
struct MeshTriangles {
|
||||
std::vector<float> positions; // 3 * vertex_count, mesh-local
|
||||
std::vector<uint32_t> indices; // 3 * triangle_count, LOD0
|
||||
};
|
||||
std::vector<MeshTriangles> mesh_triangles_cache;
|
||||
|
||||
// object_id (globally rebased) → instance index in `instances`.
|
||||
// Populated alongside the instance vector so the Volume tool can do
|
||||
// O(1) instance lookup instead of linear-scanning every model.
|
||||
|
||||
Reference in New Issue
Block a user