Viewing CityJSON using CityJSONLoader


How to load a CityJSON model directly into 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 CityJSON using CityJSONLoader


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 CityJSON using CityJSONLoader</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 SDK from a bundle built for these examples.

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

2. Create a helper that sets up the Scene , Data, Viewer, and WebGLRenderer used by this demo.

import {DemoHelper} from "../../js/DemoHelper.js";
const demoHelper = new DemoHelper({});
demoHelper.init().then(({
                          scene,
                          data,
                          viewer,
                          view,
                          renderer
                        }) => {

3. Create a CityJSONLoader to load CityJSON files

  const cityJSONLoader = new xeokit.formats.cityjson.CityJSONLoader();

4. Configure the View 's World-space coordinate axis to make the +Z axis "up. This is actually the default, but we show it here for clarity

  view.camera.worldAxis = [
    1, 0, 0, // Right +X
    0, 0, 1, // Up +Z
    0, -1, 0  // Forward -Y
  ];

5. Arrange the View's Camera within our +Z "up" coordinate system

  view.camera.eye = [11.50, 16.32, 15.12];
  view.camera.look = [9.01, 9.65, 11.22];
  view.camera.up = [-0.16, -0.45, 0.87];
  view.camera.zoom(-15)

6. Create a SceneModel to hold our model's geometry and materials

  const sceneModelResult = scene.createModel({
    id: "demoModel",

7. coordinateSystem: { // Model's local CityJSON-standard coordinate system basis: [ 1, 0, 0, // Right +X 0, 0, 1, // Up +Z 0, -1, 0 // Forward -Y ], origin: [0, 0, 0], units: "meters" }

  });
  if (!sceneModelResult.ok) {
    return;
  }
  const sceneModel = sceneModelResult.value;

8. Create a DataModel to hold semantic data for our model

  const dataModelResult = data.createModel({
    id: "demoModel"
  });
  if (!dataModelResult.ok) {
    return;
  }
  const dataModel = dataModelResult.value;

9. Use CityJSONLoader to load an IFC model from a dotbim file into our SceneModel and DataModel

  fetch("../../models/LoD3_Railway/cityjson/model.json").then(response => {
    response
      .json()
      .then(fileData => {
        cityJSONLoader.load({
          fileData,
          sceneModel,
          dataModel
        }).then(() => {

10. The Scene and SceneModel will now 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.

          demoHelper.finished();
        }).catch(message => {
          console.error(`Error loading CityJSON: ${message}`);
        });
      });
  });
});