ifcviewer: rename sidecar transfer/record types; drop unused element hierarchy (sidecar v17)

Rename the streamer/sidecar transfer and record types to describe what
they are rather than how they move:

  MeshChunk         -> StreamedMesh
  InstanceChunk     -> StreamedInstance
  InstanceCpu       -> InstanceInfo
  PackedElementInfo -> ElementTableRecord
  uploadMeshChunk   -> uploadStreamedMesh
  uploadInstanceChunk -> uploadStreamedInstance
  buildMeshChunk    -> buildStreamedMesh

and the two post-index sidecar metadata blocks:

  "critical" metadata -> "geometry" metadata  (meshes/instances/georef/TOC)
  "deferred" metadata -> "element"  metadata  (elements + string table)
  parseSidecarCritical -> parseSidecarGeometryMetadata
  parseSidecarDeferred -> parseSidecarElementMetadata

The one behavioural change: the element hierarchy (parent_id) was
carried through ElementInfo, ElementTableRecord, and the sidecar element
table but never consumed, so drop it and bump SIDECAR_VERSION 16 -> 17.
No back-compat: regenerate sidecars. sample.ifcview is regenerated at v17.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Dion Moult
2026-07-03 19:26:31 +10:00
parent da5c0b7991
commit 66d558ec2d
30 changed files with 240 additions and 240 deletions
+33 -34
View File
@@ -144,7 +144,7 @@ std::vector<ElementInfo> GeometryStreamer::drainElements() {
return result;
}
// Build a mesh chunk (local coords, 28-byte interleaved vertices) from a
// Build a streamed mesh record (local coords, 28-byte interleaved vertices) from a
// TriangulationElement. Per-vertex color is baked from material_ids so that
// triangulations with per-face materials still render correctly.
// Vertex rebasing: when `offset` is non-zero, every vertex position is
@@ -153,13 +153,13 @@ std::vector<ElementInfo> GeometryStreamer::drainElements() {
// compensates by post-multiplying each instance's PlacementTransformation
// by T(+offset), which is mathematically the identity overall but moves
// the magnitude off the float-precision-sensitive vertex column.
static MeshChunk buildMeshChunk(uint32_t model_id,
static StreamedMesh buildStreamedMesh(uint32_t model_id,
uint32_t local_mesh_id,
const IfcGeom::TriangulationElement* elem,
const Eigen::Vector3d& offset) {
MeshChunk chunk;
chunk.model_id = model_id;
chunk.local_mesh_id = local_mesh_id;
StreamedMesh mesh;
mesh.model_id = model_id;
mesh.local_mesh_id = local_mesh_id;
const auto& geom = elem->geometry();
const auto& verts = geom.verts();
@@ -168,7 +168,7 @@ static MeshChunk buildMeshChunk(uint32_t model_id,
const auto& materials = geom.materials();
const auto& material_ids = geom.material_ids();
if (verts.empty() || faces.empty()) return chunk;
if (verts.empty() || faces.empty()) return mesh;
const size_t num_verts_src = verts.size() / 3;
const size_t num_tris = faces.size() / 3;
@@ -184,8 +184,8 @@ static MeshChunk buildMeshChunk(uint32_t model_id,
std::unordered_map<uint64_t, uint32_t> remap;
remap.reserve(num_verts_src);
chunk.vertices.reserve(num_verts_src * INSTANCED_VERTEX_STRIDE_FLOATS);
chunk.indices.reserve(faces.size());
mesh.vertices.reserve(num_verts_src * INSTANCED_VERTEX_STRIDE_FLOATS);
mesh.indices.reserve(faces.size());
// Track local AABB as we emit vertices.
float local_aabb_min[3] = { std::numeric_limits<float>::max(),
@@ -201,16 +201,16 @@ static MeshChunk buildMeshChunk(uint32_t model_id,
if (it != remap.end()) return it->second;
const uint32_t new_idx = static_cast<uint32_t>(
chunk.vertices.size() / INSTANCED_VERTEX_STRIDE_FLOATS);
mesh.vertices.size() / INSTANCED_VERTEX_STRIDE_FLOATS);
// Subtract in double, narrow to float — preserves precision when
// verts are far from origin and offset cancels the magnitude.
float px = static_cast<float>(verts[orig_idx * 3 + 0] - offset.x());
float py = static_cast<float>(verts[orig_idx * 3 + 1] - offset.y());
float pz = static_cast<float>(verts[orig_idx * 3 + 2] - offset.z());
chunk.vertices.push_back(px);
chunk.vertices.push_back(py);
chunk.vertices.push_back(pz);
mesh.vertices.push_back(px);
mesh.vertices.push_back(py);
mesh.vertices.push_back(pz);
if (px < local_aabb_min[0]) local_aabb_min[0] = px;
if (px > local_aabb_max[0]) local_aabb_max[0] = px;
if (py < local_aabb_min[1]) local_aabb_min[1] = py;
@@ -219,13 +219,13 @@ static MeshChunk buildMeshChunk(uint32_t model_id,
if (pz > local_aabb_max[2]) local_aabb_max[2] = pz;
if (orig_idx * 3 + 2 < normals.size()) {
chunk.vertices.push_back(static_cast<float>(normals[orig_idx * 3 + 0]));
chunk.vertices.push_back(static_cast<float>(normals[orig_idx * 3 + 1]));
chunk.vertices.push_back(static_cast<float>(normals[orig_idx * 3 + 2]));
mesh.vertices.push_back(static_cast<float>(normals[orig_idx * 3 + 0]));
mesh.vertices.push_back(static_cast<float>(normals[orig_idx * 3 + 1]));
mesh.vertices.push_back(static_cast<float>(normals[orig_idx * 3 + 2]));
} else {
chunk.vertices.push_back(0.0f);
chunk.vertices.push_back(1.0f);
chunk.vertices.push_back(0.0f);
mesh.vertices.push_back(0.0f);
mesh.vertices.push_back(1.0f);
mesh.vertices.push_back(0.0f);
}
MaterialInfo m;
@@ -235,7 +235,7 @@ static MeshChunk buildMeshChunk(uint32_t model_id,
uint32_t packed = packRGBA8(m);
float packed_as_float;
std::memcpy(&packed_as_float, &packed, sizeof(float));
chunk.vertices.push_back(packed_as_float);
mesh.vertices.push_back(packed_as_float);
remap.emplace(key, new_idx);
return new_idx;
@@ -243,19 +243,19 @@ static MeshChunk buildMeshChunk(uint32_t model_id,
for (size_t t = 0; t < num_tris; ++t) {
const int mat_id = have_per_tri_material ? material_ids[t] : -1;
chunk.indices.push_back(emit_vertex(static_cast<uint32_t>(faces[t * 3 + 0]), mat_id));
chunk.indices.push_back(emit_vertex(static_cast<uint32_t>(faces[t * 3 + 1]), mat_id));
chunk.indices.push_back(emit_vertex(static_cast<uint32_t>(faces[t * 3 + 2]), mat_id));
mesh.indices.push_back(emit_vertex(static_cast<uint32_t>(faces[t * 3 + 0]), mat_id));
mesh.indices.push_back(emit_vertex(static_cast<uint32_t>(faces[t * 3 + 1]), mat_id));
mesh.indices.push_back(emit_vertex(static_cast<uint32_t>(faces[t * 3 + 2]), mat_id));
}
if (chunk.vertices.empty()) {
if (mesh.vertices.empty()) {
for (int a = 0; a < 3; ++a) local_aabb_min[a] = local_aabb_max[a] = 0.0f;
}
for (int a = 0; a < 3; ++a) {
chunk.local_aabb_min[a] = local_aabb_min[a];
chunk.local_aabb_max[a] = local_aabb_max[a];
mesh.local_aabb_min[a] = local_aabb_min[a];
mesh.local_aabb_max[a] = local_aabb_max[a];
}
return chunk;
return mesh;
}
// Port of ifcopenshell.util.representation.get_prioritised_contexts: rank every
@@ -562,7 +562,6 @@ void GeometryStreamer::run(const std::string& path, int num_threads) {
info.guid = tri_elem->guid();
info.name = tri_elem->name();
info.type = tri_elem->type();
info.parent_id = tri_elem->parent_id();
{
std::lock_guard<std::mutex> lock(elements_mutex_);
pending_elements_.push_back(std::move(info));
@@ -604,19 +603,19 @@ void GeometryStreamer::run(const std::string& path, int num_threads) {
}
}
MeshChunk mesh_chunk =
buildMeshChunk(model_id_, local_mesh_id, tri_elem, offset);
StreamedMesh streamed_mesh =
buildStreamedMesh(model_id_, local_mesh_id, tri_elem, offset);
MeshAabb mesh_aabb;
for (int a = 0; a < 3; ++a) {
mesh_aabb.lmin[a] = mesh_chunk.local_aabb_min[a];
mesh_aabb.lmax[a] = mesh_chunk.local_aabb_max[a];
mesh_aabb.lmin[a] = streamed_mesh.local_aabb_min[a];
mesh_aabb.lmax[a] = streamed_mesh.local_aabb_max[a];
mesh_aabb.offset[a] = offset[a];
}
mesh_aabb.has_offset = (offset.squaredNorm() > 0.0);
if (mesh_aabbs.size() <= local_mesh_id) mesh_aabbs.resize(local_mesh_id + 1);
mesh_aabbs[local_mesh_id] = mesh_aabb;
if (!mesh_chunk.indices.empty()) {
emit meshReady(std::move(mesh_chunk));
if (!streamed_mesh.indices.empty()) {
emit meshReady(std::move(streamed_mesh));
}
}
@@ -635,7 +634,7 @@ void GeometryStreamer::run(const std::string& path, int num_threads) {
mat_d.block<3, 1>(0, 3) += mat_d.block<3, 3>(0, 0) * mesh_rebase_offset;
}
InstanceChunk inst;
StreamedInstance inst;
inst.model_id = model_id_;
inst.local_mesh_id = local_mesh_id;
inst.object_id = object_id;