Skip to main content

Crate openbim_ifcx_geometry

Crate openbim_ifcx_geometry 

Source
Expand description

Renderer-neutral geometry and viewer helpers for IFC5 / IFCX.

The crate decodes the geometry and presentation attributes of ifcx_alpha nodes into typed values. It never depends on a renderer or GPU API (see docs/adr/0002).

ModuleAttributeResult
transformusd::xformopTransform, composed with world_from_parent
meshusd::usdgeom::meshTriangleMesh
curvesusd::usdgeom::basiscurvesCurveGeometry
pointspoints::array, points::base64, pcd::base64PointCloud
presentationusd::usdgeom::visibility, bsi::ifc::presentation::*, gltf::materialNodePresentation, resolved over ancestors by is_visible, resolve_basic_material, and resolve_mesh_material
sceneall of the above, over a composed treeRenderScene: instances with node path, world matrix, shared f32 buffers, materials, bounds
glba RenderScenebinary glTF 2.0 bytes, to_glb

Each decoder takes the attribute’s serde_json::Value as stored in openbim_ifcx::IfcxNode::attributes and returns a DecodeError for malformed values instead of panicking. PointCloud::from_attributes and NodePresentation::from_attributes pick their attributes from anything implementing Attributes. Coordinates stay f64; see math.

RenderScene::from_composition walks a composed node tree once and returns the flat scene a viewer draws, with each shared geometry stored once and instanced. to_glb writes that scene as a binary glTF 2.0 file; the ifcx2glb example converts IFCX files from the command line.

use openbim_ifcx::IfcxFile;
use openbim_ifcx_geometry::{mesh, transform, Transform, TriangleMesh};

let file = IfcxFile::from_json_str(r#"{
    "header": {"id": "demo", "ifcxVersion": "ifcx_alpha", "dataVersion": "1.0.0",
               "author": "someone", "timestamp": "2026-10-03"},
    "imports": [], "schemas": {},
    "data": [{"path": "slab", "attributes": {
        "usd::xformop": {"transform": [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,3,1]]},
        "usd::usdgeom::mesh": {"points": [[0,0,0],[1,0,0],[0,1,0]],
                               "faceVertexIndices": [0,1,2]}
    }}]
}"#)?;
let attributes = file.data[0].attributes.as_ref().unwrap();
let local = Transform::from_attribute(&attributes[transform::ATTRIBUTE])?;
let mesh = TriangleMesh::from_attribute(&attributes[mesh::ATTRIBUTE])?;
let world: Vec<_> = mesh.positions.iter().map(|&p| local.transform_point(p)).collect();
assert_eq!(world[1], [1.0, 0.0, 3.0]);

Point clouds and presentation:

use openbim_ifcx_geometry::{is_visible, resolve_basic_material, NodePresentation, PointCloud};
use serde_json::json;

let node = json!({
    "points::array": {"positions": [[0, 0, 0], [1, 0, 0]]},
    "bsi::ifc::presentation::diffuseColor": [1, 0, 0],
});
let attributes = node.as_object().unwrap();

let cloud = PointCloud::from_attributes(attributes)?.unwrap();
assert_eq!(cloud.positions, [[0.0, 0.0, 0.0], [1.0, 0.0, 0.0]]);

let own = NodePresentation::from_attributes(attributes)?;
assert!(is_visible(true, own.visibility));
assert_eq!(resolve_basic_material([&own]).color, [1.0, 0.0, 0.0]);

A render scene from a composed file:

use openbim_ifcx::{compose, flatten_owned, IfcxFile};
use openbim_ifcx_geometry::{GeometryKind, RenderScene, SceneOptions};

let file = IfcxFile::from_json_str(r#"{
    "header": {"id": "demo", "ifcxVersion": "ifcx_alpha", "dataVersion": "1.0.0",
               "author": "someone", "timestamp": "2026-10-03"},
    "imports": [], "schemas": {},
    "data": [
        {"path": "storey", "children": {"Slab": "slab"}, "attributes": {
            "usd::xformop": {"transform": [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,3,1]]},
            "bsi::ifc::presentation::diffuseColor": [0.8, 0.2, 0.2]}},
        {"path": "slab", "attributes": {"usd::usdgeom::mesh": {
            "points": [[0,0,0],[1,0,0],[0,1,0]], "faceVertexIndices": [0,1,2]}}}
    ]
}"#)?;
let composition = compose(&flatten_owned(file.data))?;
let scene = RenderScene::from_composition(&composition, &SceneOptions::default());
let slab = &scene.instances[0];
assert_eq!(slab.path, "storey/Slab");
assert_eq!(slab.geometry.kind(), GeometryKind::Mesh);
assert_eq!(slab.world.translation(), [0.0, 0.0, 3.0]);
assert!(scene.warnings.is_empty());

Re-exports§

pub use curves::CurveGeometry;
pub use curves::Polyline;
pub use curves::UnsupportedCurve;
pub use error::DecodeError;
pub use glb::to_glb;
pub use glb::GlbError;
pub use glb::GlbOptions;
pub use math::Vec3;
pub use mesh::TriangleMesh;
pub use points::PointCloud;
pub use presentation::is_visible;
pub use presentation::resolve_basic_material;
pub use presentation::resolve_mesh_material;
pub use presentation::AlphaMode;
pub use presentation::BasicMaterial;
pub use presentation::GltfMaterial;
pub use presentation::Material;
pub use presentation::NodePresentation;
pub use presentation::NormalTexture;
pub use presentation::OcclusionTexture;
pub use presentation::Visibility;
pub use scene::Bounds;
pub use scene::GeometryKind;
pub use scene::GeometryRef;
pub use scene::Instance;
pub use scene::LineBuffer;
pub use scene::MeshBuffer;
pub use scene::Origin;
pub use scene::PointBuffer;
pub use scene::RenderScene;
pub use scene::SceneOptions;
pub use scene::SceneWarning;
pub use scene::SceneWarningKind;
pub use transform::world_from_parent;
pub use transform::Transform;

Modules§

curves
Polylines from usd::usdgeom::basiscurves.
error
The error shared by every attribute decoder in this crate.
glb
Binary glTF 2.0 (GLB) export of a RenderScene.
math
Small vector helpers shared by the decoders.
mesh
Indexed triangle meshes from usd::usdgeom::mesh.
points
Point clouds from points::array, points::base64, and pcd::base64 (ifcx_alpha).
presentation
Visibility, colour, opacity, and glTF PBR materials (ifcx_alpha).
scene
A flat, renderer-neutral render scene over a composed node tree.
transform
Local and world transforms from usd::xformop.

Traits§

Attributes
A node’s attributes keyed by namespaced attribute id, as in a file’s schemas (for example points::array or gltf::material).