ifcviewer: viewport overlay subsystem (highlight tris + HUD text)

New OverlayRenderer module owns every client-supplied overlay primitive
drawn after the main pass: tinted, depth-aware highlight triangles via
its own GL shader, and top-left HUD text via QPainter on a
QOpenGLPaintDevice.  Public surface on ViewportWindow is just two
forwarders (setHighlightTriangles, setHudText).

ViewportWindow's MeshLocalPick now exposes the instance's composed
transform so consumers can map mesh-local geometry back to world
space without re-querying.  AreaMeasurement uses both: its selection
key is now (object_id, tri) so per-instance highlighting works for
two distinct walls sharing a mesh, and on every pick it rebuilds the
world-space tri list and the HUD readout.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Dion Moult
2026-05-07 16:43:38 +10:00
parent d565dc3ff3
commit ad62dd6d91
7 changed files with 414 additions and 21 deletions
+24
View File
@@ -45,6 +45,7 @@ QT_END_NAMESPACE
#include "BvhAccel.h"
#include "InstancedGeometry.h"
#include "OverlayRenderer.h"
#include "SidecarCache.h"
// Matches GL_DRAW_INDIRECT_BUFFER layout for glMultiDrawElementsIndirect.
@@ -221,6 +222,11 @@ public:
float mesh_local[3] = {0, 0, 0};
float world_pos[3] = {0, 0, 0};
float world_normal[3]= {0, 0, 0};
// The instance's composed (FederatedFalseOrigin · ModelTransformation
// · CoordinateOperation · placement_transformation) matrix in
// column-major form. Mesh-local positions × this = world. Caching
// by callers becomes stale if any federation matrix is later edited.
float composed_transform[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
};
bool pickMeshLocalAt(int x, int y, MeshLocalPick& out);
@@ -231,6 +237,19 @@ public:
void toggleAreaTool();
bool areaToolActive() const { return area_tool_active_; }
// Replace the overlay highlight-triangle list rendered after the main
// pass. `world_xyz` is 3 floats per vertex, 3 verts per triangle, in
// world space. Empty disables the overlay. Triggers a viewport
// update so the change becomes visible immediately.
void setHighlightTriangles(const std::vector<float>& world_xyz,
float r, float g, float b, float a);
// Top-left HUD text drawn via QPainter on top of the GL surface at
// the end of each frame. Empty hides the HUD. Used today by the
// area-measurement tool for the running total; later tools can pile
// additional readouts in by extending this with a multi-line API.
void setHudText(const QString& text);
// Federation pipeline: composed instance transform =
// FederatedFalseOrigin · ModelTransformation · CoordinateOperation
// · placement_transformation
@@ -635,6 +654,11 @@ private:
// Area-measurement tool: see toggleAreaTool / surfacePickedInTool.
bool area_tool_active_ = false;
// Renders any client-supplied overlay primitives (highlight triangles
// today; lines/points/labels later) in their own pass after the main
// geometry, with depth-test on / depth-write off.
OverlayRenderer overlay_renderer_;
// Active section planes. Uploaded as uniform array each frame to the
// main + pick programs; capped at MaxSectionPlanes.
std::vector<SectionPlane> section_planes_;