mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-22 01:31:00 +00:00
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:
@@ -23,7 +23,6 @@
|
||||
#include <QWindow>
|
||||
#include <QColor>
|
||||
#include <QElapsedTimer>
|
||||
#include <QMatrix4x4>
|
||||
#include <QPoint>
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
@@ -178,7 +177,7 @@ public:
|
||||
// Snapshot of the orbit camera. Mirrors GL ViewportWindow::CameraState
|
||||
// so bonsai's "save view" / "restore view" commands port unchanged.
|
||||
struct CameraState {
|
||||
QVector3D target;
|
||||
Eigen::Vector3f target;
|
||||
float distance;
|
||||
float yaw; // degrees
|
||||
float pitch; // degrees
|
||||
@@ -218,7 +217,7 @@ private:
|
||||
// the view matrix and a WebGPU-correct projection (z mapped to [0, 1]).
|
||||
// Single helper so projection_ortho_ and the up-vector switch at near-
|
||||
// vertical pitch land identically everywhere.
|
||||
void buildViewProj(QMatrix4x4& view_out, QMatrix4x4& proj_out) const;
|
||||
void buildViewProj(Eigen::Matrix4f& view_out, Eigen::Matrix4f& proj_out) const;
|
||||
// Per-frame WASD integration when fps_mode_ is true. Called near the
|
||||
// top of render() so the displayed frame already reflects movement.
|
||||
void fpsIntegrate();
|
||||
@@ -226,11 +225,11 @@ private:
|
||||
bool computeObjectAabb(uint32_t object_id,
|
||||
float mn[3], float mx[3]) const;
|
||||
public:
|
||||
// QVector3D overload — matches GL ViewportWindow::computeObjectAabb so
|
||||
// Eigen::Vector3f overload — matches GL ViewportWindow::computeObjectAabb so
|
||||
// bonsai's volume readout / focus callers compile unchanged. Just a
|
||||
// thin wrapper around the float[3] version.
|
||||
bool computeObjectAabb(uint32_t object_id,
|
||||
QVector3D& mn, QVector3D& mx) const;
|
||||
Eigen::Vector3f& mn, Eigen::Vector3f& mx) const;
|
||||
private:
|
||||
// Re-aim the orbit camera so the bounding sphere of [mn, mx] fits.
|
||||
void frameAabb(const float mn[3], const float mx[3], float padding);
|
||||
@@ -242,7 +241,7 @@ private:
|
||||
// chunk-priority metric — extracted from driveStreamingLoads as a
|
||||
// member so the click-and-track diagnostic can compare scores.
|
||||
float chunkScreenAreaPx(const ModelGpuData::Chunk& c,
|
||||
const QMatrix4x4& vp_mat) const;
|
||||
const Eigen::Matrix4f& vp_mat) const;
|
||||
|
||||
public:
|
||||
|
||||
@@ -346,7 +345,7 @@ private:
|
||||
// (decoded from ×0.5+0.5 packing) so the section tool can drop
|
||||
// perpendicular cuts.
|
||||
uint32_t pickObjectAt(int x_pixels, int y_pixels,
|
||||
QVector3D* normal_out = nullptr);
|
||||
Eigen::Vector3f* normal_out = nullptr);
|
||||
// Pick + ray-cast — returns the object's id, the world-space point
|
||||
// where the pick-pixel pillar enters that instance's AABB, and a
|
||||
// camera-facing normal. Returns false on a background miss. We do
|
||||
@@ -356,8 +355,8 @@ private:
|
||||
// enough to the click for the section tool's "drop a plane here" UX.
|
||||
bool pickSurfaceAt(int x_pixels, int y_pixels,
|
||||
uint32_t& object_id_out,
|
||||
QVector3D& world_pos_out,
|
||||
QVector3D& world_normal_out,
|
||||
Eigen::Vector3f& world_pos_out,
|
||||
Eigen::Vector3f& world_normal_out,
|
||||
float* aabb_radius_out = nullptr);
|
||||
// Rectangle pick: render the pick pass, copy the rect region of the
|
||||
// R32UInt color attachment, and return every unique non-zero
|
||||
@@ -374,8 +373,8 @@ public:
|
||||
// Esc deactivate tool
|
||||
bool sectionToolActive() const { return section_tool_active_; }
|
||||
void toggleSectionTool();
|
||||
bool addSectionPlaneAtSurface(const QVector3D& point,
|
||||
const QVector3D& normal,
|
||||
bool addSectionPlaneAtSurface(const Eigen::Vector3f& point,
|
||||
const Eigen::Vector3f& normal,
|
||||
float visual_radius = 0.0f);
|
||||
void removeSectionPlane(int index);
|
||||
void clearSectionPlanes();
|
||||
@@ -561,7 +560,7 @@ private:
|
||||
int encodeHizResolve(WGPUCommandEncoder enc);
|
||||
// Issues a non-blocking mapAsync on `slot` after submit, so the
|
||||
// callback can fire whenever the GPU has actually finished writing.
|
||||
void startHizMap(int slot, const QMatrix4x4& vp_used);
|
||||
void startHizMap(int slot, const Eigen::Matrix4f& vp_used);
|
||||
// Drains pending mapAsync callbacks (via processEvents — does NOT
|
||||
// block on GPU work). For any slot that just signalled Mapped, reads
|
||||
// it, unmaps it, max-reduces the mip pyramid, and updates hiz_vp_.
|
||||
@@ -826,7 +825,7 @@ private:
|
||||
bool section_drag_active_ = false;
|
||||
int section_drag_index_ = -1;
|
||||
QPoint section_drag_start_mouse_;
|
||||
QVector3D section_drag_start_origin_;
|
||||
Eigen::Vector3f section_drag_start_origin_;
|
||||
// Mirrors GL ViewportWindow::hitTestSectionGizmo: returns the index of
|
||||
// the plane whose arrow gizmo is within grab_px of (x, y), or -1.
|
||||
int hitTestSectionGizmo(int x, int y) const;
|
||||
@@ -838,7 +837,7 @@ private:
|
||||
enum class HizSlotState : uint8_t { Idle, Mapping, Mapped };
|
||||
static constexpr int HIZ_SLOTS = 2;
|
||||
WGPUBuffer hiz_staging_buffers_[HIZ_SLOTS] = { nullptr, nullptr };
|
||||
QMatrix4x4 hiz_slot_vp_ [HIZ_SLOTS];
|
||||
Eigen::Matrix4f hiz_slot_vp_ [HIZ_SLOTS];
|
||||
HizSlotState hiz_slot_state_ [HIZ_SLOTS] = { HizSlotState::Idle,
|
||||
HizSlotState::Idle };
|
||||
int hiz_write_idx_ = 0;
|
||||
@@ -848,7 +847,7 @@ private:
|
||||
std::vector<uint32_t> hiz_mip_offset_;
|
||||
std::vector<uint32_t> hiz_mip_w_;
|
||||
std::vector<uint32_t> hiz_mip_h_;
|
||||
QMatrix4x4 hiz_vp_;
|
||||
Eigen::Matrix4f hiz_vp_;
|
||||
bool hiz_valid_ = false;
|
||||
uint32_t hiz_reject_count_ = 0; // per-frame stat
|
||||
|
||||
|
||||
Reference in New Issue
Block a user