From b2fe9c4a716b23605a6921b3c3108422ecd2e6e1 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 5 Jun 2026 13:54:28 +1000 Subject: [PATCH] ifcviewer: move const-lookup methods into ViewportCore (#84-e) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move two pure-read methods (no GPU touch, no Qt) that the bonsai measurement / federation-origin paths use: bool findInstance(uint32_t, InstanceLookup&) const bool firstGeometryPointWorldM(uint32_t, Vector3d&) const ViewportWindow keeps both public-API method names — they now forward to core_ for the implementation so existing callers in bonsaiviewer/Measurement.cpp + Federation hooks don't have to change. The InstanceLookup type also stays a `using` alias in ViewportWindow (was added in #74). Both methods were already de-Qt'd (`findInstance` delegates to InstanceCompose; `firstGeometryPointWorldM` is pure Eigen). The move is a straight transplant — no behaviour change. Builds: desktop / bonsai / web all green. Tests 100/100. --- src/ifcviewer/ViewportCore.cpp | 35 ++++++++++++++++++++++++++++++++ src/ifcviewer/ViewportCore.h | 13 ++++++++++++ src/ifcviewer/ViewportWindow.cpp | 31 +++------------------------- 3 files changed, 51 insertions(+), 28 deletions(-) diff --git a/src/ifcviewer/ViewportCore.cpp b/src/ifcviewer/ViewportCore.cpp index bc9d168839..8026507ecf 100644 --- a/src/ifcviewer/ViewportCore.cpp +++ b/src/ifcviewer/ViewportCore.cpp @@ -24,6 +24,41 @@ ViewportCore::ViewportCore(ViewportHost* host) : host_(host) {} ViewportCore::~ViewportCore() = default; +bool ViewportCore::findInstance(uint32_t object_id, + InstanceCompose::InstanceLookup& out) const { + return InstanceCompose::findInstanceInModels(object_id, models_gpu_, out); +} + +bool ViewportCore::firstGeometryPointWorldM(uint32_t model_id, + Eigen::Vector3d& out) const { + auto it = models_gpu_.find(model_id); + if (it == models_gpu_.end()) return false; + const ModelGpuData& m = it->second; + if (m.instances.empty()) return false; + + const InstanceCpu& inst0 = m.instances[0]; + if (inst0.mesh_id >= m.meshes.size()) return false; + const MeshInfo& mesh0 = m.meshes[inst0.mesh_id]; + + // Mesh-local AABB centre — a point that's actually on the geometry. + // Using AABB centre (vs. literal vertex 0) gives a centroid-like + // anchor rather than a corner, which is more representative of where + // the mesh "is" for the false-origin guess. + const Eigen::Vector3d local_center_m( + 0.5 * (double(mesh0.local_aabb_min[0]) + double(mesh0.local_aabb_max[0])), + 0.5 * (double(mesh0.local_aabb_min[1]) + double(mesh0.local_aabb_max[1])), + 0.5 * (double(mesh0.local_aabb_min[2]) + double(mesh0.local_aabb_max[2]))); + + // placement_transformation is double[16] column-major in metres, + // pre-CoordinateOperation / FederatedFalseOrigin / ModelTransformation + // (same convention as InstanceLookup above). + using Mat4dCol = Eigen::Matrix; + const Eigen::Matrix4d P = + Eigen::Map(inst0.placement_transformation); + out = (P * local_center_m.homogeneous()).head<3>(); + return true; +} + void ViewportCore::composeInstanceFromPlacement(InstanceCpu& inst, const ModelGpuData& m) const { if (inst.mesh_id < m.meshes.size()) { diff --git a/src/ifcviewer/ViewportCore.h b/src/ifcviewer/ViewportCore.h index 52ce2ef7a8..604a4c31c8 100644 --- a/src/ifcviewer/ViewportCore.h +++ b/src/ifcviewer/ViewportCore.h @@ -41,6 +41,7 @@ #include #include "BufferPool.h" +#include "InstanceCompose.h" #include "InstancedGeometry.h" #include "ModelGpuData.h" #include "StreamingThread.h" @@ -68,6 +69,18 @@ public: void composeInstanceFromPlacement(InstanceCpu& inst, const ModelGpuData& m) const; + // Cross-model object_id lookup. Delegates to + // InstanceCompose::findInstanceInModels; the wrapper exists so + // callers don't have to know about the underlying map of models. + bool findInstance(uint32_t object_id, + InstanceCompose::InstanceLookup& out) const; + + // A point that actually lies on the model's first instance — used + // by the federation false-origin guess on first geometry. Pure + // read of models_gpu_; no GPU touch. + bool firstGeometryPointWorldM(uint32_t model_id, + Eigen::Vector3d& out) const; + // Friend access for ViewportWindow's reference proxies. As each // render method moves into ViewportCore it stops needing these // (it touches the fields directly); once everything has migrated diff --git a/src/ifcviewer/ViewportWindow.cpp b/src/ifcviewer/ViewportWindow.cpp index 71f3e5f7ce..a92e29ec72 100644 --- a/src/ifcviewer/ViewportWindow.cpp +++ b/src/ifcviewer/ViewportWindow.cpp @@ -1427,37 +1427,12 @@ void ViewportWindow::recomposeAndUploadModel(uint32_t model_id) { } bool ViewportWindow::findInstance(uint32_t object_id, InstanceLookup& out) const { - return InstanceCompose::findInstanceInModels(object_id, models_gpu_, out); + return core_.findInstance(object_id, out); } bool ViewportWindow::firstGeometryPointWorldM(uint32_t model_id, - Eigen::Vector3d& out) const { - auto it = models_gpu_.find(model_id); - if (it == models_gpu_.end()) return false; - const ModelGpuData& m = it->second; - if (m.instances.empty()) return false; - - const InstanceCpu& inst0 = m.instances[0]; - if (inst0.mesh_id >= m.meshes.size()) return false; - const MeshInfo& mesh0 = m.meshes[inst0.mesh_id]; - - // Mesh-local AABB centre — a point that's actually on the geometry. - // Using AABB centre (vs. literal vertex 0) gives a centroid-like - // anchor rather than a corner, which is more representative of where - // the mesh "is" for the false-origin guess. - const Eigen::Vector3d local_center_m( - 0.5 * (double(mesh0.local_aabb_min[0]) + double(mesh0.local_aabb_max[0])), - 0.5 * (double(mesh0.local_aabb_min[1]) + double(mesh0.local_aabb_max[1])), - 0.5 * (double(mesh0.local_aabb_min[2]) + double(mesh0.local_aabb_max[2]))); - - // placement_transformation is double[16] column-major in metres, - // pre-CoordinateOperation / FederatedFalseOrigin / ModelTransformation - // (same convention as InstanceLookup above). - using Mat4dCol = Eigen::Matrix; - const Eigen::Matrix4d P = - Eigen::Map(inst0.placement_transformation); - out = (P * local_center_m.homogeneous()).head<3>(); - return true; + Eigen::Vector3d& out) const { + return core_.firstGeometryPointWorldM(model_id, out); } void ViewportWindow::frameOnFederatedOrigin(uint32_t model_id,