ifcviewer: de-Qt math types (Eigen everywhere)

Replace Qt math wrappers with Eigen across ViewportWindow, OverlayRenderer,
Federation, and the bonsai-side viewport modules. Eigen was already the
canonical type for the actually-important matrix work (InstanceCompose,
ModelGpuData, federation matrices); QVector3D/QVector4D/QMatrix4x4 were
leftover from when Qt was the path of least resistance. They offered
nothing over Eigen for our use case beyond a few graphics helpers
(lookAt / perspective / ortho) which were 30 lines to write.

Substitutions:
  QMatrix4x4 → Eigen::Matrix4f
  QVector2D  → Eigen::Vector2f
  QVector3D  → Eigen::Vector3f
  QVector4D  → Eigen::Vector4f

API rewrites:
  .lengthSquared()         → .squaredNorm()
  .length()                → .norm()
  .isNull()                → .isZero()
  .setToIdentity()         → .setIdentity()
  .constData()             → .data()
  .toVector3D()            → .head<3>()
  .inverted(&ok)           → tryInvert4f(M, out)
  Q::dotProduct(a,b)       → a.dot(b)
  Q::crossProduct(a,b)     → a.cross(b)
  QMat4x4(... row-major)   → Eigen::Map<const Matrix4f>(col-major buf)
  QMat4x4().lookAt(...)    → lookAtRH(eye, target, up)
  QMat4x4().perspective(.) → perspectiveYFovGL(fovy, aspect, n, f)
  QMat4x4().ortho(...)     → orthoGL(l, r, b, t, n, f)

Default-init divergence handled explicitly (QMatrix4x4() = identity,
QVector3D() = zero; Eigen leaves both uninitialized). Public API
(CameraState, HomeView, ViewportWindow::computeObjectAabb, the
addSectionPlaneAtSurface / pickSurfaceAt / raycast signatures) follows
through to Eigen too; bonsai-side View.cpp and Commands.cpp updated to
match.

Camera helpers (lookAtRH, perspectiveYFovGL, orthoGL, tryInvert4f)
extracted to a new CameraMath.h so OverlayRenderer's gizmo MVP and
ViewportWindow's buildViewProj share the same definitions. Federation
drops its <QVector3D> include in favour of <Eigen/Dense> (already had
the latter for the georef matrices).

Builds: desktop IfcViewerMinimal ✓, BonsaiViewer ✓, web IfcViewerWeb ✓.
Tests: 100/100 pass. Closes #78 + #79; opens the door for #80-#83.
This commit is contained in:
Dion Moult
2026-06-05 08:33:22 +10:00
parent c314dd3ca8
commit 77cf535b45
8 changed files with 305 additions and 231 deletions
+9 -10
View File
@@ -21,10 +21,10 @@
#define WGPUOVERLAYRENDERER_H
#include <QHash>
#include <QMatrix4x4>
#include <QPoint>
#include <QString>
#include <QVector3D>
#include <Eigen/Dense>
#include <webgpu/webgpu.h>
@@ -35,8 +35,8 @@
// at the top of render() and passed by const-ref to each encodeX() call so
// the overlay renderer never reaches back into the viewport.
struct OverlayFrame {
QMatrix4x4 view_proj;
QVector3D camera_target;
Eigen::Matrix4f view_proj = Eigen::Matrix4f::Identity();
Eigen::Vector3f camera_target = Eigen::Vector3f::Zero();
float camera_distance = 5.0f;
float camera_yaw_deg = 0.0f;
float camera_pitch_deg = 0.0f;
@@ -51,12 +51,11 @@ struct OverlayFrame {
// reads from a non-owning span every frame. Held by value because the
// struct is small and copies happen at most six times per frame.
struct SectionPlane {
QVector3D n; // unit normal (camera-facing after auto-flip)
float d; // -dot(n, origin)
QVector3D origin; // surface point at the moment the plane was added
float visual_radius; // unused by the visualizer (kept here so the
// section tool's state struct round-trips
// through this overlay-facing definition).
Eigen::Vector3f n = Eigen::Vector3f::UnitZ(); // unit normal
float d = 0.0f; // -dot(n, origin)
Eigen::Vector3f origin = Eigen::Vector3f::Zero(); // surface point at the
// moment the plane was added
float visual_radius = 0.0f;
};
// All viewport overlays in one place: axis indicator (corner + pivot),