ifcviewer-full: volume tool with HUD + per-object labels

Mirrors the Area tool's display: HUD shows total volume + object count,
each selected object gets a label at its world-AABB centroid showing
its individual volume.  Gated behind ToolMode::Volume (Ctrl+Shift+V) so
it stays out of the way until invoked.

Volume is a passive tool — selection works as in None (multi-select,
modifier toggle, box-select all keep working).  Area / Length still
intercept clicks through surfacePickedInTool.

Adds volumesPerObject() reusing the same mesh-cached readback path as
volumeOfObjects, so the per-object split costs no extra GL readbacks.
computeObjectAabb is promoted to public for the centroid lookup.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Dion Moult
2026-05-10 08:45:08 +10:00
parent bba2f30816
commit 0a297babea
6 changed files with 124 additions and 16 deletions
+14 -4
View File
@@ -3596,8 +3596,11 @@ void ViewportWindow::handleMousePress(QMouseEvent* e) {
// drag that happens to start on an object still box-selects, which
// matches user intuition: the start point shouldn't disqualify the
// gesture. Tool-mode LMB defers pick handling to surfacePickedInTool
// on release.
if (e->button() == Qt::LeftButton && tool_mode_ == ToolMode::None) {
// on release for tools that consume clicks (Area / Length); Volume is
// passive and routes input through normal selection.
const bool tool_consumes_clicks =
(tool_mode_ == ToolMode::Area || tool_mode_ == ToolMode::Length);
if (e->button() == Qt::LeftButton && !tool_consumes_clicks) {
press_pick_id_ = pickObjectAt(e->pos().x(), e->pos().y());
box_select_start_pos_ = e->pos();
box_select_current_pos_ = e->pos();
@@ -3637,8 +3640,11 @@ void ViewportWindow::handleMouseRelease(QMouseEvent* e) {
selection_.setSelection(picks, selection_.activeObjectId());
}
} else if (!was_drag) {
// Click — apply press-time pick + modifiers.
if (tool_mode_ != ToolMode::None) {
// Click — apply press-time pick + modifiers. Area / Length
// intercept clicks; None and Volume drive normal selection.
const bool tool_consumes_clicks =
(tool_mode_ == ToolMode::Area || tool_mode_ == ToolMode::Length);
if (tool_consumes_clicks) {
emit surfacePickedInTool(e->pos().x(), e->pos().y(),
int(e->modifiers()));
} else {
@@ -4225,6 +4231,10 @@ void ViewportWindow::toggleLengthTool() {
setToolMode(tool_mode_ == ToolMode::Length ? ToolMode::None : ToolMode::Length);
}
void ViewportWindow::toggleVolumeTool() {
setToolMode(tool_mode_ == ToolMode::Volume ? ToolMode::None : ToolMode::Volume);
}
void ViewportWindow::setHighlightTriangles(const std::vector<float>& world_xyz,
float r, float g, float b, float a) {
if (!gl_initialized_) return;