mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-28 07:49:59 +00:00
ifcviewer: extract ChunkPlanner + InstanceCompose; add Tier-1 test trio
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.
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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
|
||||
Reference in New Issue
Block a user