ifcviewer: per-element visibility (H / Shift+H / Alt+H)

Adds VisibilityState, a CPU-only sibling to SelectionState.  It owns
the canonical hidden-id set plus a flat per-object_id byte vector that
the cull's hot path queries inline (bounds check + byte load + compare
per surviving instance).  Hidden elements never reach the visible[]
SSBO so they don't draw or pick — matching Blender/CAD convention.

ViewportWindow registers every streamed and sidecar-cached object_id
with the new state, resets it on clearScene, and connects the changed
signal to invalidate cached cull state.  Three convenience verbs:
hideSelectedElements (union into hidden), isolateSelectedElements
(replace hidden with live-object_ids minus selection, skipping
model-hidden models so element-hide doesn't pile on top of model-hide),
and showAllElements (clears the override; model-hidden models stay
hidden, per the user's spec).

Bound in the View menu: H hide, Shift+H isolate, Alt+H show all.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Dion Moult
2026-05-11 07:33:09 +10:00
parent 742561c56d
commit 1c598a981e
5 changed files with 269 additions and 3 deletions
+24
View File
@@ -49,6 +49,7 @@ QT_END_NAMESPACE
#include "OverlayRenderer.h"
#include "Selection.h"
#include "SidecarCache.h"
#include "Visibility.h"
// Matches GL_DRAW_INDIRECT_BUFFER layout for glMultiDrawElementsIndirect.
struct DrawElementsIndirectCommand {
@@ -328,6 +329,26 @@ public:
// or off-surface.
std::unordered_set<uint32_t> picksInRect(const QRect& rect);
// Per-element visibility (independent of model-level hidden flag).
// External callers go through the convenience verbs below; the
// VisibilityState getter is exposed for read access (e.g. the host
// mirroring its state into a tree's grey-out style).
VisibilityState& visibility() { return visibility_; }
const VisibilityState& visibility() const { return visibility_; }
// Hide every currently-selected element. Selection itself is
// preserved — toggling them back on with showAllElements() leaves
// the same items selected.
void hideSelectedElements();
// Hide every element NOT in the current selection (limited to
// visible models — model-hidden objects are left as-is so they
// stay model-hidden rather than picking up a redundant
// element-hidden flag too). No-op when nothing is selected.
void isolateSelectedElements();
// Clear element-level visibility overrides for every loaded model.
// Model-level `hidden` flags are not touched — a hidden model stays
// hidden, matching the user's expectation of "show all *elements*".
void showAllElements();
// Extended pick: returns the object id, world-space hit point, and
// world-space surface normal at (x, y). Renders the same pick pass as
// pickObjectAt but reads back from two extra color attachments
@@ -729,6 +750,9 @@ private:
// Selection — set + active id + per-object_id flags SSBO (binding=3).
SelectionState selection_;
// Per-element visibility — CPU-only flag vector consulted by the
// cull, plus a canonical hidden-id set for mutation/reporting.
VisibilityState visibility_;
// LMB-press state. press_pick_id_ caches the object hit at press
// time so the release path can apply click semantics without a