Docs

Import models

Show glTF, FBX, OBJ, STL, PLY, Collada, 3DS, 3MF and USDZ files as Scene Objects, placed, scaled, turned and replaced.

A Scene Object can be drawn by a model file. Its geometry names the file by uri, and the scene gives it a place, a heading and a scale like any other object. The three.js renderer reads ten formats with the loaders three.js ships, and loads each loader only when a scene first uses that format, so a page of glTF never downloads the FBX reader.

models.ts
import { createScene, MODEL_FORMATS, modelFormatOf } from "@klorad/api/world";
import { createThreeRenderer } from "@klorad/engine-three";

const scene = createScene({ coordinateSystem: { origin: { lat: 40.62, lon: 22.95 } } });

// The extension of the address says the format; `format` says it when the address has none.
scene.add({ id: "pump", name: "Pump P1", position: { east: 0, north: 0 }, scale: 0.001, geometry: { kind: "model", uri: "/models/pump.stl" } });
scene.add({ id: "tank", name: "Tank T1", position: { east: 7, north: 5 }, orientation: { heading: 90 }, geometry: { kind: "model", uri: "/files/4f2a", format: "fbx" } });

// One named node of a file, standing at its own origin: one element of a building as its own object.
scene.add({ id: "wall-1", name: "Wall", position: { east: -10, north: 0 }, geometry: { kind: "model", uri: "asset:9c1e", format: "glb", part: "2O2Fr$t4X7Zf8NOew3FLOH" } });

// Replace the file an object shows; it keeps its place, heading and bindings.
scene.update("pump", { geometry: { kind: "model", uri: "/models/pump-v2.glb" }, scale: 1 });

// The formats the renderer reads, and the format a file name says it is.
export const formats = MODEL_FORMATS; // ["gltf", "glb", "fbx", "obj", "stl", "ply", "dae", "3ds", "3mf", "usdz"]
export const pumpFormat = modelFormatOf("Pump.STL"); // "stl"

createThreeRenderer({
  container: document.getElementById("view")!,
  scene,
  // `asset:<id>` names a file your app stores; say where it is fetched from.
  assetUrl: (assetId) => `/api/assets/${assetId}`,
});

Formats

FormatExtensionNotes
glTF.gltf, .glbMaterials, hierarchy and named nodes. The format to prefer.
FBX.fbxMaterials and hierarchy.
OBJ.objGeometry and groups; materials in a separate .mtl are not read.
STL.stlGeometry only, drawn in a plain material. Stands on Z, turned to stand up.
PLY.plyGeometry, with colours by vertex when the file has them. Stands on Z.
Collada.daeMaterials and hierarchy.
3D Studio.3dsMaterials. Stands on Z.
3MF.3mfMaterials. Stands on Z.
USDZ.usdzGeometry and simple materials.

MODEL_FORMATS lists them and modelFormatOf(fileName) names the format of a file by its extension, or null. A model with no format is read by the extension of its address, and as glTF when the address has none. A model stands on its own origin, in metres: give scale when the file was drawn in millimetres (0.001) or centimetres (0.01).

What the renderer does

  • It fetches a file once per page and gives each object its own copy with its own materials, so the glow of one never lights another.
  • part takes one named node of a file and stands it at its own origin, so one file can draw many objects: each element of a building, say.
  • asset:<id> names a file your application stores; the assetUrl option says where it is fetched from. Without it, such a model cannot load and the error goes to onError.
  • Replacing the geometry of an object loads the new file and keeps everything else the object is: its place, its bindings, its readings.

BIM

An IFC file is not read in the browser. Klorad One reads it on the platform's worker, keeps its elements as Scene Objects with their properties and stores their meshes as one glTF binary, each element a named node; each element then draws its own part of that file.

Run it liveSandbox: ModelsA pumping room drawn from glTF, STL, OBJ and PLY files, each placed, scaled and swapped in the scene.

Something wrong or unclear? Tell us.