mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 02:23:34 +00:00
1fe4570860
The chunk planner (Morton sort + greedy pack) and instance composition (federation × placement matrix chain + world-AABB derive) were inline helpers in ViewportWindow.cpp. Pulled both out as free-function modules so the math + lookup logic can be exercised without a Qt window or a wgpu device. ViewportWindow now delegates; InstanceLookup is a using- alias to InstanceCompose::InstanceLookup. Also added an addSubBufferForTesting / clearSubPoolsForTesting seam to BufferPool so the sub-allocator invariants can be pinned with fake WGPUBuffer handles. The fakes are never dereferenced; the guard drops the sub-pools before destructor would call wgpuBufferRelease. Three new test binaries under src/ifcviewer/tests/, 33 cases / 173 assertions: BufferPool first-fit + alignment + coalescing + multi- sub-pool isolation; ChunkPlanner Morton split / interleave / stable sort / greedy-pack monotonicity and single-mesh-oversize; InstanceCompose identity / translation / order-of-multiplication / large-placement cancellation against federation false origin / column-major writeback / findInstance lookup paths.
91 lines
4.2 KiB
C++
91 lines
4.2 KiB
C++
/********************************************************************************
|
|
* *
|
|
* This file is part of IfcOpenShell. *
|
|
* *
|
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the Lesser GNU General Public License as published by *
|
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* Lesser GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the Lesser GNU General Public License *
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
********************************************************************************/
|
|
|
|
#ifndef INSTANCECOMPOSE_H
|
|
#define INSTANCECOMPOSE_H
|
|
|
|
// Instance-transform composition + per-instance world AABB derivation,
|
|
// plus the cross-model object-id → (model, mesh, placement) lookup.
|
|
// Pulled out of ViewportWindow as a free-function module so the matrix
|
|
// math + lookup logic can be unit-tested without spinning up a Qt window
|
|
// or a wgpu device.
|
|
|
|
#include <Eigen/Dense>
|
|
|
|
#include <cstdint>
|
|
#include <unordered_map>
|
|
|
|
#include "ModelGpuData.h"
|
|
|
|
namespace InstanceCompose {
|
|
|
|
// Transform the 8 corners of [local_min, local_max] through the
|
|
// column-major 4x4 matrix M (float[16]) and bound the result in
|
|
// world space. Called after every recompose so per-instance world
|
|
// AABBs (and the chunk AABBs derived from them) reflect the current
|
|
// federation matrices.
|
|
void worldAabbFromLocal(const float local_min[3], const float local_max[3],
|
|
const float M[16],
|
|
float world_min_out[3], float world_max_out[3]);
|
|
|
|
// composed = federated_false_origin
|
|
// * model_transformation
|
|
// * coordinate_operation
|
|
// * placement
|
|
//
|
|
// Maths in double; narrow only at the end. Large IFC placements need
|
|
// to be cancelled by federated_false_origin before the float cast or
|
|
// precision is lost. The composed float matrix is written into
|
|
// transform_col_major_out (column-major, GPU-uploadable), then the
|
|
// local AABB is transformed by the same matrix to produce the
|
|
// world-space AABB.
|
|
void composeInstance(
|
|
const double placement_col_major[16],
|
|
const Eigen::Matrix4d& federated_false_origin,
|
|
const Eigen::Matrix4d& model_transformation,
|
|
const Eigen::Matrix4d& coordinate_operation,
|
|
const float local_aabb_min[3], const float local_aabb_max[3],
|
|
float transform_col_major_out[16],
|
|
float world_aabb_min_out[3], float world_aabb_max_out[3]);
|
|
|
|
// Result of a successful findInstance lookup. The placement_transformation
|
|
// is double[16] column-major (pre-CoordinateOperation / FederatedFalseOrigin
|
|
// / ModelTransformation) — the same convention as InstanceCpu so the
|
|
// measurement / picking tools can re-compose at need.
|
|
struct InstanceLookup {
|
|
uint32_t model_id = 0;
|
|
uint32_t mesh_id = 0;
|
|
double placement_transformation[16]{};
|
|
};
|
|
|
|
// Walk a map of models looking for the one that owns `object_id`,
|
|
// fill `out` with that instance's (model_id, mesh_id, placement) and
|
|
// return true. Returns false for object_id == 0 (the sentinel for
|
|
// "no object") or when no model owns the id. Defensive: skips
|
|
// instances whose stored index is out-of-range for the model's
|
|
// instance array.
|
|
bool findInstanceInModels(
|
|
uint32_t object_id,
|
|
const std::unordered_map<uint32_t, ModelGpuData>& models,
|
|
InstanceLookup& out);
|
|
|
|
} // namespace InstanceCompose
|
|
|
|
#endif // INSTANCECOMPOSE_H
|