OptionalappearanceCanonical item triangle order, stamped at WASM extraction before streaming. Rebuilt topology must discard this metadata. The repeated indices reference survives structured clone and detects replacement without hashing geometry.
OptionalcornerIndices?: Uint32Array<ArrayBufferLike>Current triangle corner -> canonical triangle corner. Absent means identity.
Identity fence for the current geometry topology.
Original canonical final geometry, before streaming fragments.
Apparent rendering colour: IfcSurfaceStyleRendering.DiffuseColour when authored, otherwise the SurfaceColour. Matches what most IFC viewers display and what the GLB exporter uses by default.
OptionalentityPer-vertex entity IDs for color-merged batches (desktop fast path).
When present the renderer writes these instead of repeating expressId
for every vertex, so picking/selection resolves to the correct individual
entity even though many entities share a single GPU batch.
OptionalgeometryWhole-entity world bounding box from the SAME hashing pass as
MeshData.geometryHash (MeshCollection.geometryAabbValues),
populated only when geometry hashing is enabled
(GeometryProcessor.enableGeometryHashes()). Like the hash, all submeshes
of one entity carry the same box — it spans the entity, not this submesh.
ABSOLUTE world, unlike positions: the RTC offset and the per-element
MeshData.origin are already folded in, so two revisions that chose
different RTC offsets report the same box. Do NOT add origin to it.
Absent when the pass produced no box for the entity (the wasm side writes
six NaNs there; the extractor drops them rather than passing a
NaN-bearing object on), when hashing is off, or on a wasm build predating
the getter. Consumed by the model-diff / compare feature to tell a move
from a reshape (#1891); renderers ignore it.
OptionalgeometryGeometry provenance for rendering and the viewer's Model/Types view switch:
Absent/undefined is treated as 0 (occurrence).
Downstream filter: if ((mesh.geometryClass ?? 0) === 2) continue;
OptionalgeometryRTC-invariant per-entity geometry fingerprint from the WASM mesh pass,
populated only when geometry hashing is enabled
(GeometryProcessor.enableGeometryHashes()). All submeshes of one entity
share the same value (it is the whole-entity hash). Consumed by the
model-diff / compare feature (issue #924); renderers ignore it.
OptionalgeometryThe IfcRepresentationItem this mesh came from, so a host can drill from
a rendered piece to its entity (#2985). ALWAYS a representation item;
materialId carries the other case and the two are NEVER both set.
Absent where identity is merged away (single-mesh fallback, cached
IfcMappedItem, GPU instancing) (#3199).
OptionalgeometryWhole-entity enclosed volume in CUBIC METRES, from the SAME hashing pass
as MeshData.geometryHash (MeshCollection.geometryVolumeValues,
#1993). Like the hash and the box, all submeshes of one entity carry the
identical value — it is the volume of the entity, not of this submesh, so
summing it across submeshes would multiply it.
Present only when the meshed geometry was PROVABLY a single closed,
orientable, single-component solid (measured coverage on a real corpus:
71.4%, 24,073 of 33,701 elements). Absent means the kernel could not prove
a volume — an open shell, a material-layered wall, a multi-item assembly —
and NEVER that the volume is zero or that it differs. The wasm side writes
NaN there; the extractor drops it rather than passing a NaN-bearing
number on.
It is the volume of what was actually meshed, AFTER opening cuts, so it is
not an IFC BaseQuantities GrossVolume and must not be compared with
one. Consumed by the model-diff split/merge detector (#1891); renderers
ignore it.
OptionalifcTriangle indices (3 per face).
NOTE: Winding order is UNRELIABLE (meshes are double-sided by design).
Do not use winding for front/back-face determination or normal-based
culling. Use depth testing or abs(dot(normal, viewDir)) for shading.
OptionallocalLocal (pre-placement, object-space) AABB — positions bounds as they
were BEFORE the element's IfcLocalPlacement was baked in (issue #1474).
Absent when not captured (e.g. an instancing template, or a mesh built
outside the standard element pipeline). Unrelated to origin, which is
a world-space translation captured AFTER placement, purely for f32
precision — don't conflate the two.
OptionallocalThe resolved IfcLocalPlacement chain applied to this mesh (issue
#1474): row-major 4x4, 16 numbers, WebGL Y-up axis convention — but its
translation is the placement's PRE-RTC absolute origin, not the frame
positions render in (mesh_world.rs assigns this before subtracting
the model's RTC offset). Do NOT shift it when RTC changes. Absent when
not captured. All of one entity's MeshData pieces share the same
value (one placement per element).
OptionalmaterialIFC-authored metallic/roughness (#5582): IfcSurfaceStyleRendering's
SpecularColour / SpecularHighlight / ReflectanceMethod, mapped in
Rust (ifc_lite_processing::style::extract_surface_style_specular).
Either field, or the whole object, is absent when the file authored no
evidence for it — the renderer's packMeshMaterial then keeps its own
default (a matte dielectric, or glass roughness when the authored colour
is translucent).
OptionalmaterialThe IfcMaterial layer this mesh slices. DISJOINT from geometryItemId,
which used to carry it — so following that field for a layered wall landed
on the wrong entity. geometryClass === 3 cannot substitute (#3199).
Same id space as expressId: a federated viewer session re-homes it
alongside expressId and geometryItemId (applyFederationOffsetToMesh
in apps/viewer/src/hooks/useIfcLoader.ts), so a value read off this
field is always safe to resolve the same way as expressId (#3525).
OptionalmodelOptionaloccurrenceStable key for CPU caches that must distinguish occurrences sharing one
expressId. GPU-instanced occurrences are materialized on demand as one
MeshData per occurrence, all stamped with the same expressId but holding
different world-space positions (issue #1405). Caches keyed on expressId
alone (e.g. the measure-snap geometry cache) would collide across them and
serve the first occurrence's geometry for every later one. When present,
such caches must key on this instead. Absent for flat meshes (one MeshData
per expressId), where expressId is already a sufficient key.
OptionaloriginPer-element local-frame origin (WebGL Y-up, metres): world position of
vertex i = origin + positions[3i..3i+3]. Present when the wasm pipeline
emits a per-element frame (building-scale f32 precision); absent/[0,0,0]
means positions are already absolute world coords (legacy / native /
caches predating local frame). The renderer reconstructs world via a
per-batch model-matrix translate.
OptionalshadingSurfaceColour, populated by the WASM extractor only when the file
authored a distinct DiffuseColour (so shadingColor !== color).
Consumed by the GLB exporter's "Shading" colour-source option.
For basic rendering, use color (matches most IFC viewers).
For physically-accurate rendering, prefer shadingColor ?? color.
OptionaltextureDecoded surface texture (IfcBlobTexture / IfcPixelTexture), present only
for textured meshes (#961). Decoded to RGBA8 entirely in Rust; the
renderer uploads rgba verbatim to a GPU texture.
OptionaltextureThe decoded image for textureRef, attached on the MAIN thread by the
viewer after resolving textureRef.url against the .ifcZIP sibling
images (#1781). One ImageBitmap instance is shared by every mesh with the
same textureRef.textureId; the renderer uploads it to ONE GPU texture
per id. Never set by the worker.
OptionaltextureExternal image texture reference (IfcImageTexture, #1781): the image
ships OUTSIDE the model (a sibling file inside the .ifcZIP), so the
pipeline carries the reference and the viewer resolves + decodes it once
per textureId, sharing the GPU texture across every mesh that samples
it. Mutually exclusive with texture. uvs are present alongside.
OptionaluvsPer-vertex texture coordinates (u, v pairs, 1:1 with positions), present only for textured meshes (issue #961).
Mesh data for a single geometric representation of an IFC element.
An element may produce MULTIPLE MeshData entries (one per material, CSG part, or representation item). Group by
expressIdfor per-element operations such as DOM grouping, picking, or depth sorting. The number of meshes per element depends on the IFC file's geometric complexity.