Skip to content

Viewing BIM Models Offline

xeolabs edited this page Feb 4, 2019 · 56 revisions

See also:

Introduction

In this tutorial we'll use xeokit's GLTFLoaderPlugin to load BIM models with IFC metadata from the file system.

This gives us theadvantage of not having to store our models in the cloud, which may be useful if privacy and data ownership are concerns.

We'll provide our model as a glTF file containing geometry for each element, along with a JSON file containing IFC metadata for each element.

xeokit agnostic of how these files are generated, since that can be done by any proprietary pipeline, but for the purpose of demonstrating xeokit, I used a set of open source tools to generate them from IFC STEP files, which I'll describe at the end of this tutorial.

Contents

Example

Click the image below for a live demo.

Loading a Model

We load our IFC model from two files:

  • a JSON file containing metadata about each IFC element, and
  • a glTF file containing objects with IDs matching the elements in the IFC JSON.

The code snippets below show how it's done. We'll create a Viewer, to which we'll add a GLTFLoaderPlugin, with which we'll load our model:

import {Viewer} from "./../src/viewer/Viewer.js";
import {GLTFLoaderPlugin} from "./../src/viewer/plugins/GLTFLoaderPlugin/GLTFLoaderPlugin.js";

// Create a Viewer
const viewer = new Viewer({
    canvasId: "myCanvas"
});

// Add a GLTFLoaderPlugin
const gltfLoader = new GLTFLoaderPlugin(viewer);

// Load glTF and metadata
const model = gltfLoader.load({
    id: "myModel",
    src:          "./models/OTCConferenceCenter.gltf",
    metaModelSrc: "./models/OTCConferenceCenter.json"
});

// Fit camera to model when loaded
model.on("loaded", function() {
    viewer.cameraFlight.jumpTo(model);
});

Accessing Objects

After loading, the GLTFLoaderPlugin has created Entities to represent our model and its objects, which we can find by ID.

Through the Entity's, we can control the objects, updating their visibilities, enabling effects, querying boundaries, and so on.

We can find our model and object Entities like this:

const theModel = viewer.scene.models["myModel"];
const anObject = viewer.scene.objects["3NI6Sp$yf87eKCx0T$FWj3"];

Let's update the state of our model and one of its objects:

// Controlling model visibility
theModel.visibility = false;
theModel.visibility = true;

// Controlling object visibility
theObject.visibility = false;
theObject.visibility = true;

// Highlight an object
theObject.highlighted = true;

// Get an object's axis-aligned World-space boundary
const boundary = theObject.aabb;

// Fly camera to an object
viewer.cameraFlight.flyTo(theObject);

Getting Metadata

The plugin has also created a MetaModel that provides IFC metadata for our model, along with with a MetaObject for each object.

We can get IFC metadata for the model and its objects like this:

// Get matadata on our model
const metaModel = viewer.metaScene.metaModels["myModel"];

// Get metadata on an object
const metaObject = metaModel.metaObjects["3NI6Sp$yf87eKCx0T$FWj3"];

const name = metaObject.name; // "stelkozijn",
const type = metaObject.type; // "IfcWindow",
const parent = metaObject.parent; // "2SWZMQPyD9pfT9q87pgXa1"

Setting Initial States for IFC Types

When loading metadata, GLTFLoaderPlugin will also by default apply certain initial states to objects whose types match known standard IFC types. For example, setting "IfcSpace" types invisible and unpickable, setting "IfcWindow" types blue and transparent, etc.

GLTFLoaderPlugin has a default map of these states, but we can override that as needed to apply our own states. In the example below, our map is the same as the default, except that we'll set "IfcWall" types purple.

Click the image below for a live demo.

// Define our own custom initial states for objects

 const myObjectDefaults = {
    IfcSpace: {
        colorize: [0.137255, 0.403922, 0.870588],
        pickable: false,
        visible: false,
        opacity: 0.5
    },
    IfcRoof: {
        colorize: [0.837255, 0.203922, 0.270588]
    },
    IfcSlab: {
        colorize: [0.837255, 0.603922, 0.670588]
    },
    IfcWall: {
        colorize: [ 0.537255, 0.537255, 0.837255]
    },

    //...

    DEFAULT: { // All other types get this color
        colorize: [0.5, 0.5, 0.5]
    }
};

// Use our custom initial default states for object Entities

const model = gltfLoader.load({
    id: "myModel",
    src: "./models/gltf/duplex/scene.gltf",
    metaModelSrc: "./metaModels/duplex/metaModel.json",

    objectDefaults: myObjectDefaults
});

Masking what IFC Types are Loaded

We can optionally load only those objects that have the specified IFC types. In the example below, we'll load only the objects that represent walls, in order to create a plan view.

Click the image below for a live demo.

const model = gltfLoader.load({
    id: "myModel",
     src: "./models/gltf/OTCConferenceCenter/scene.gltf",
     metaModelSrc: "./metaModels/OTCConferenceCenter/metaModel.json",
     includeTypes: ["IfcWallStandardCase"]
});

We can also optionally load only those objects that do not have the specified IFC types. In the example below, we'll load only the objects that do not represent empty spaces.

const model = gltfLoader.load({
    id: "myModel",
     src: "./models/gltf/OTCConferenceCenter/scene.gltf",
     metaModelSrc: "./metaModels/OTCConferenceCenter/metaModel.json",
     excludeTypes: ["IfcSpace"]
});

Creating the Files

Potentially, we can generate our glTF and JSON files via some sort of custom automated server-side pipeline.

However, for the purpose of demonstrating xeokit, I used open source CLI tools to convert the IFC into glTF, and my own node.js-based client for BIMServer to generate the JSON metadata. Read more about that in Creating Files for Offline BIM.

Clone this wiki locally