Viewing .BIM using ModelConverter and IFCLoader


Use the ModelConverter class to convert a model from dotbim (.bim) format to IFC, then use IFCLoader to view the IFC in a xeokit web viewer.
Click on the preview below to run the example. Scroll down to learn how it's made.


Click to load
Placeholder image

Viewing .BIM using ModelConverter and IFCLoader


HTML


Listed below is the HTML for this example.


<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Viewing .BIM using ModelConverter and IFCLoader</title>
    <style>
        body {
            background-color: white;
            overflow: hidden;
            margin: 0;
            user-select: none;
        }

        #demoCanvas {
            width: 100%;
            height: 100%;
            position: absolute;
            background: white;
            border: 0;
        }
    </style>
</head>
<body>
<canvas id="demoCanvas"></canvas>
</body>
<script type="module" src="./index.js"></script>
</html>


JavaScript


Listed below is the JavaScript for this example, which we'll break down into steps.

1. Import the xeokit SDK bundle built specifically for the example environment

import * as xeokit from "../../js/xeokit-demo-bundle.js";
import {DemoHelper} from "../../js/DemoHelper.js";

2. Create a ModelConverter instance configured to convert our .BIM file into IFC. We configure the ModelConverter with a DotBIMLoader to load BIM files and an IFCExporter to export IFC format. We'll also configure the ModelConveter with a single pipeline, "dotbim2ifc", which connects our loader and exporters together into a pipeline.

const modelConverter = new xeokit.modelconverter.ModelConverter({
  loaders: {
    "dotbim": new xeokit.dotbim.DotBIMLoader()
  },
  exporters: {
    "ifc": new xeokit.ifc.IFCExporter()
  },
  pipelines: {
    "dotbim2ifc": {
      inputs: {
        "dotbim": {
          loader: "dotbim",
          options: {}
        }
      },
      outputs: {
        "ifc": {
          exporter: "ifc",
          version: "1.0",
          options: {}
        }
      }
    }
  }
});

3. Create a Scene to manage geometry, materials, and scene structure

const scene = new xeokit.scene.Scene();

4. Create a Data instance to manage semantic information (like IFC metadata)

const data = new xeokit.data.Data();

5. Initialize a WebGLRenderer to use the browser’s WebGL API for 3D rendering

const renderer = new xeokit.webglrenderer.WebGLRenderer({});

6. Create a Viewer to visualize the Scene using the WebGLRenderer

const viewer = new xeokit.viewer.Viewer({
  id: "demoViewer",
  scene,
  renderer
});

7. Create a single View within the Viewer, linked to an HTML canvas

const view = viewer.createView({
  id: "demoView",
  elementId: "demoCanvas"
});

8. Configure the coordinate system for the View's Camera Setting +Z as "up", +X as "right", and -Y as "forward"

view.camera.worldAxis = [
  1, 0, 0, // +X
  0, 0, 1, // +Z (up)
  0, -1, 0 // -Y (forward)
];

9. Position the Camera in the scene with eye, look, and up vectors

view.camera.eye = [11.276311451067942, 16.914467176601914, 7.399026975905038];
view.camera.look = [0, 0, 0];
view.camera.up = [-0.18971864040782152, -0.28457796061173224, 0.9396926209223285];

10. Add interactive controls for navigating the View using mouse, keyboard, and touch

new xeokit.cameracontrol.CameraControl(view, {});

11. Create a SceneModel to store the geometry and material data for the model

const sceneModel = scene.createModel({
  id: "demoModel"
});

12. Create a DataModel to hold the semantic metadata for the model

const dataModel = data.createModel({
  id: "demoModel"
});

13. Create an IFCLoader to load the IFC into our Viewer's Scene

const ifcLoader = new xeokit.ifc.IFCLoader();

14. Ignore the DemoHelper—used only to signal example completion

const demoHelper = new DemoHelper({});
demoHelper.init()
  .then(() => {

15. Fetch the .BIM file containing the source model

    fetch("../../models/BlenderHouse/dotbim/model.bim").then(response => {
      response
        .json()
        .then(fileData => {

16. Convert the .BIM file into IFC (geometry) and DataModelParams (semantics) using the ModelConverter

          modelConverter.convert({
            pipeline: "dotbim2ifc",
            inputs: {
              dotbim: {
                fileData
              }
            }
          }).then(result => {
            function stringToArrayBuffer(str) {
              const encoder = new TextEncoder();
              return encoder.encode(str).buffer;
            }

17. Load the IFC geometry into the SceneModel

            ifcLoader.load({
              fileData: result.outputs.ifc.fileData,
              sceneModel,
              dataModel
            }).then(() => {

18. Build the SceneModel and DataModel, to finalize the model structure. The Scene and SceneModel will then contain a SceneObject for each displayable object in our model. The Data and DataModel will contain a DataObject for each IFC element in the model. Each SceneObject will have a corresponding DataObject with the same ID, to attach semantic meaning. The View will contain a ViewObject corresponding to each SceneObject, through which the appearance of the object can be controlled in the View.

              dataModel.build();
              sceneModel.build();
              demoHelper.finished();
            }).catch(message => {
              console.error(`Error loading IFC: ${message}`);
            });
          }).catch(message => {
            console.error(`Error converting .BIM to IFC: ${message}`);
          });
        });
    });
  });