Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
openaec-foundation avatar

Threejs Impl Ifc Viewer

  • 18 installs
  • 11 repo stars
  • Updated July 8, 2026
  • openaec-foundation/three.js-claude-skill-package

Helps with ai & agent building tasks.

About

threejs-impl-ifc-viewer is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.

  • threejs-impl-ifc-viewer
  • AI & Agent Building
  • AI-coding skill

Threejs Impl Ifc Viewer by the numbers

  • 18 all-time installs (skills.sh)
  • +2 installs in the week ending Aug 4, 2026 (Skillselion tracking)
  • Ranked #10,736 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/openaec-foundation/three.js-claude-skill-package --skill threejs-impl-ifc-viewer

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs18
repo stars11
Last updatedJuly 8, 2026
Repositoryopenaec-foundation/three.js-claude-skill-package

What it does

Helps with ai & agent building tasks.

Files

SKILL.mdMarkdownGitHub ↗

threejs-impl-ifc-viewer

Quick Reference

Library Comparison

LibraryLicenseLevelStatusUse Case
web-ifcMITLow-level WASM parserActive (v0.77+)Custom pipelines, full control
@thatopen/componentsMIT (v3.x)High-level BIM toolkitActive (v3.3.2+)Full BIM viewers, rapid prototyping
@thatopen/components-frontMITBrowser-specific extensionsActiveUI, advanced visualization
web-ifc-threeDeprecated bridgeDEADNEVER use
openbim-components (v1)Deprecated toolkitDEADNEVER use

Package Installation

# Low-level approach (MIT, full control)
npm install web-ifc three

# High-level approach (MIT, batteries-included)
npm install @thatopen/components @thatopen/components-front web-ifc three

Critical Warnings

LICENSE HISTORY WARNING: The @thatopen packages (v3.x) are licensed under MIT. However, older IFC.js ecosystem packages (openbim-components v1, IFC.js v0.x) used AGPL-3.0. ALWAYS verify the license of the exact package version you install. If using any package with AGPL-3.0, your entire application MUST be open-sourced under AGPL-3.0 or a compatible license.

NEVER use web-ifc-three -- it is deprecated and unmaintained. Use web-ifc directly or @thatopen/components instead.

NEVER use openbim-components (v1) -- it is deprecated. Use @thatopen/components (v3.x) instead.

NEVER load entire IFC geometry at once for files >50MB -- ALWAYS stream or load geometry on demand. WASM memory is limited and cannot be reclaimed without page reload.

NEVER forget to call ifcApi.CloseModel(modelID) after processing -- WASM memory leaks are permanent until page reload.

ALWAYS call components.dispose() when unmounting a @thatopen viewer -- failure to do so leaks GPU memory, Three.js objects, and event listeners.

ALWAYS initialize IfcAPI asynchronously -- await ifcApi.Init() MUST complete before any model operations.

---

Approach 1: web-ifc (Low-Level WASM Parser)

When to Use

  • You need full control over geometry extraction and rendering
  • You are building a custom rendering pipeline
  • You want MIT-licensed code only
  • You need to extract IFC properties without rendering geometry

WASM Setup

import * as WebIFC from 'web-ifc';

const ifcApi = new WebIFC.IfcAPI();
ifcApi.SetWasmPath('./');  // MUST point to directory containing web-ifc.wasm
await ifcApi.Init();       // ALWAYS await before any operations

WASM file requirement: The web-ifc.wasm file MUST be served from a location accessible by the browser. Copy it from node_modules/web-ifc/ to your public/static directory. Bundlers like Vite require explicit configuration to serve WASM files.

IfcAPI Core Methods

MethodSignatureDescription
Init()() => Promise<void>Initialize WASM module
SetWasmPath(path)(string) => voidSet directory containing .wasm file
OpenModel(data, settings?)(Uint8Array, object?) => numberLoad IFC data, returns modelID
CloseModel(modelID)(number) => voidRelease model memory
GetGeometry(modelID, expressID)(number, number) => objectGet geometry for element
GetFlatMesh(modelID, expressID)(number, number) => FlatMeshGet flattened mesh data
GetPlacedGeometry(modelID, pg)(number, PlacedGeometry) => MeshDataGet positioned geometry with transform
GetLine(modelID, expressID, flatten?)(number, number, boolean?) => objectRead single IFC entity by expressID
GetAllLines(modelID)(number) => number[]Get all express IDs in model
GetLineIDsWithType(modelID, type)(number, number) => number[]Get IDs by IFC type constant
GetAllTypesOfModel(modelID)(number) => TypeInfo[]List all entity types in model

Geometry Extraction Pattern

const modelID = ifcApi.OpenModel(ifcData); // ifcData: Uint8Array

const wallIDs = ifcApi.GetLineIDsWithType(modelID, WebIFC.IFCWALL);
for (const wallID of wallIDs) {
  const flatMesh = ifcApi.GetFlatMesh(modelID, wallID);
  for (const pg of flatMesh.geometries) {
    const meshData = ifcApi.GetPlacedGeometry(modelID, pg);
    // meshData.vertexData: Float32Array (interleaved position + normal, 6 floats per vertex)
    // meshData.indexData: Uint32Array (triangle indices)
    // pg.flatTransformation: Float64Array (4x4 column-major matrix)
    // pg.color: { x: r, y: g, z: b, w: alpha } (0-1 range)
  }
}

ifcApi.CloseModel(modelID); // ALWAYS release when done

Converting web-ifc Geometry to Three.js

import * as THREE from 'three';

function ifcMeshToThree(meshData, placedGeometry) {
  const { vertexData, indexData } = meshData;

  // vertexData is interleaved: [px, py, pz, nx, ny, nz, px, py, pz, nx, ny, nz, ...]
  const posFloats = new Float32Array(vertexData.length / 2);
  const normFloats = new Float32Array(vertexData.length / 2);
  for (let i = 0; i < vertexData.length; i += 6) {
    const j = i / 2;
    posFloats[j]     = vertexData[i];
    posFloats[j + 1] = vertexData[i + 1];
    posFloats[j + 2] = vertexData[i + 2];
    normFloats[j]     = vertexData[i + 3];
    normFloats[j + 1] = vertexData[i + 4];
    normFloats[j + 2] = vertexData[i + 5];
  }

  const geometry = new THREE.BufferGeometry();
  geometry.setAttribute('position', new THREE.BufferAttribute(posFloats, 3));
  geometry.setAttribute('normal', new THREE.BufferAttribute(normFloats, 3));
  geometry.setIndex(new THREE.BufferAttribute(indexData, 1));

  const { x: r, y: g, z: b, w: a } = placedGeometry.color;
  const material = new THREE.MeshPhongMaterial({
    color: new THREE.Color(r, g, b),
    opacity: a,
    transparent: a < 1,
    side: THREE.DoubleSide,
  });

  const mesh = new THREE.Mesh(geometry, material);

  // Apply the 4x4 transform matrix (column-major)
  const mat = new THREE.Matrix4();
  mat.fromArray(placedGeometry.flatTransformation);
  mesh.applyMatrix4(mat);

  return mesh;
}

IFC Property Extraction

// Read a specific entity
const wall = ifcApi.GetLine(modelID, wallExpressID, true); // flatten=true resolves references
console.log(wall.Name?.value);       // "Basic Wall:Generic - 200mm"
console.log(wall.GlobalId?.value);   // IFC GUID

// Get all property sets for an element
const relDefines = ifcApi.GetLineIDsWithType(modelID, WebIFC.IFCRELDEFINESBYPROPERTIES);
for (const relID of relDefines) {
  const rel = ifcApi.GetLine(modelID, relID, false);
  // Check if this relation references our element
  // rel.RelatedObjects contains expressIDs of related elements
  // rel.RelatingPropertyDefinition points to the property set
}

IFC Type Constants

ConstantIFC Entity
WebIFC.IFCWALLWalls
WebIFC.IFCWALLSTANDARDCASEStandard walls
WebIFC.IFCSLABSlabs / floors
WebIFC.IFCCOLUMNColumns
WebIFC.IFCBEAMBeams
WebIFC.IFCDOORDoors
WebIFC.IFCWINDOWWindows
WebIFC.IFCROOFRoofs
WebIFC.IFCSTAIRStairs
WebIFC.IFCSPACESpaces / rooms
WebIFC.IFCSITESite
WebIFC.IFCBUILDINGBuilding
WebIFC.IFCBUILDINGSTOREYStorey / floor level
WebIFC.IFCPROJECTProject root
WebIFC.IFCRELDEFINESBYPROPERTIESProperty set relations
WebIFC.IFCPROPERTYSETProperty sets
WebIFC.IFCPROPERTYSINGLEVALUEIndividual property values

---

Approach 2: @thatopen/components (High-Level BIM Toolkit)

When to Use

  • You need a full-featured BIM viewer quickly
  • You want built-in fragment optimization for large models
  • You need element highlighting, section planes, or floor plans
  • MIT license (v3.x) is acceptable for your project

Architecture Setup

import * as OBC from '@thatopen/components';

const components = new OBC.Components();
const worlds = components.get(OBC.Worlds);
const world = worlds.create();

// Scene
world.scene = new OBC.SimpleScene(components);
world.scene.setup(); // Adds default lights and grid

// Camera
world.camera = new OBC.SimpleCamera(components);
world.camera.controls.setLookAt(10, 10, 10, 0, 0, 0);

// Renderer (container is an HTMLDivElement)
world.renderer = new OBC.SimpleRenderer(components, container);

// ALWAYS call init after setup
components.init();

Loading IFC Files

const ifcLoader = components.get(OBC.IfcLoader);
await ifcLoader.setup(); // Downloads and initializes WASM

// Load from file input
const file = event.target.files[0];
const data = new Uint8Array(await file.arrayBuffer());
const model = await ifcLoader.load(data);

// model is added to the active world automatically
// model contains Three.js Group with fragment meshes

Key Components

ComponentAccess PatternPurpose
OBC.Componentsnew OBC.Components()Central manager for all subsystems
OBC.Worldscomponents.get(OBC.Worlds)Multi-world environment management
OBC.SimpleSceneConstructorThree.js scene wrapper with defaults
OBC.SimpleCameraConstructorCamera with built-in orbit controls
OBC.SimpleRendererConstructorWebGL renderer bound to DOM element
OBC.IfcLoadercomponents.get(OBC.IfcLoader)IFC file loading and fragment conversion
OBC.FragmentsManagercomponents.get(OBC.FragmentsManager)Efficient batched geometry management
OBC.Highlightercomponents.get(OBC.Highlighter)Element selection and highlighting
OBC.Clippercomponents.get(OBC.Clipper)Section plane tools
OBC.Planscomponents.get(OBC.Plans)Floor plan generation

Fragment System

The fragment system converts IFC geometry into batched draw calls. This is critical for performance with large BIM models (10,000+ elements).

  • Each IFC type gets batched into a single fragment mesh
  • Fragments share materials where possible, minimizing state changes
  • Individual elements can still be picked, highlighted, and hidden by expressID
  • ALWAYS use fragments for models with >1,000 elements

Cleanup

// ALWAYS dispose when unmounting the viewer
components.dispose();
// This releases: Three.js scene, renderer, geometries, materials, textures,
// WASM memory, event listeners, and all component state

---

IFC Spatial Tree

IFC files follow a hierarchical spatial structure:

IFCPROJECT
  └── IFCSITE
        └── IFCBUILDING
              ├── IFCBUILDINGSTOREY (Level 0)
              │     ├── IFCWALL
              │     ├── IFCSLAB
              │     └── IFCSPACE
              └── IFCBUILDINGSTOREY (Level 1)
                    ├── IFCWALL
                    ├── IFCCOLUMN
                    └── IFCDOOR

Spatial containment is defined by IFCRELCONTAINEDINSPATIALSTRUCTURE and IFCRELAGGREGATES relationships. ALWAYS traverse these relationships to build a navigable tree -- do NOT assume flat element lists represent the building structure.

---

Memory Management for Large IFC Files

File SizeStrategy
<10MBLoad entirely, render all geometry at once
10-50MBLoad entirely, use fragment batching
50-200MBStream geometry by storey or type, dispose unused
>200MBServer-side preprocessing into fragments, load on demand

Rules

  • ALWAYS monitor WASM heap usage -- web-ifc allocates in WASM linear memory which has a hard cap
  • ALWAYS dispose geometry that is not currently visible (off-screen storeys, hidden types)
  • NEVER keep duplicate geometry in both WASM and JavaScript heap
  • ALWAYS use BufferGeometry (never legacy Geometry)
  • ALWAYS call geometry.dispose() and material.dispose() when removing meshes from scene

---

Reference Links

  • references/methods.md -- Complete API signatures for web-ifc and @thatopen/components
  • references/examples.md -- Working code examples for IFC loading and viewing
  • references/anti-patterns.md -- What NOT to do when working with IFC in Three.js

Official Sources

  • https://github.com/IFCjs/web-ifc
  • https://github.com/ThatOpen/engine_components
  • https://docs.thatopen.com/
  • https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.