FragmentsManager
Copying and pasting? We've got you covered! You can find the full source code of this tutorial here.
๐ Handling BIM models like a bossโ
In this tutorial, you'll learn how to load your BIM models in Fragment format. Fragment is an open source geometry system that we created on top of Three.js to display BIM models fast, while keeping control over the individual items of the model. The idea is simple: a BIM model is a FragmentsGroup, which is (like the name implies) a collection of fragments. A fragment is a set of identical geometries instantiated around the scene.
The IfcLoader component does exactly that! It converts IFC models to Fragments. Check out that tutorial if you are starting out with IFC files. Of course, you can just use the IfcLoader in your app, but loading fragments is more than x10 faster than loading IFC files. Our recommendation is to convert your IFC files to fragments just once, store the fragment somewhere (frontent of backend) and then load the fragments instead of teh IFC models directly.
In this tutorial, we will import:
Three.js
to get some 3D entities for our app.@thatopen/ui
to add some simple and cool UI menus.@thatopen/components
to set up the barebone of our app.Stats.js
(optional) to measure the performance of our app.
import * as THREE from "three";
import Stats from "stats.js";
import * as OBC from "@thatopen/components";
import * as BUI from "@thatopen/ui";
๐ Setting up a simple sceneโ
We will start by creating a simple scene with a camera and a renderer. If you don't know how to set up a scene, you can check the Worlds tutorial.
const container = document.getElementById("container")!;
const components = new OBC.Components();
const worlds = components.get(OBC.Worlds);
const world = worlds.create<
OBC.SimpleScene,
OBC.SimpleCamera,
OBC.SimpleRenderer
>();
world.scene = new OBC.SimpleScene(components);
world.renderer = new OBC.SimpleRenderer(components, container);
world.camera = new OBC.SimpleCamera(components);
components.init();
world.camera.controls.setLookAt(12, 6, 8, 0, 0, -10);
world.scene.setup();
const grids = components.get(OBC.Grids);
grids.create(world);
We'll make the background of the scene transparent so that it looks good in our docs page, but you don't have to do that in your app!
world.scene.three.background = null;
๐งถ Loading a fragments modelโ
Let's begin by getting the FragmentsManager, which is the component to load, export, get and dispose Fragments in your app.๐ญ
const fragments = components.get(OBC.FragmentsManager);
Now we can load a fragment from a file. We will fetch the model data and use the load
method of the FragmentsManager to get the fragment object. Then, we'll add it to the scene of the current world. We will also create an UUID of the model to later get it somewhere else.
let uuid = "";
async function loadFragments() {
if (fragments.groups.size) {
return;
}
const file = await fetch(
"https://thatopen.github.io/engine_components/resources/small.frag",
);
const data = await file.arrayBuffer();
const buffer = new Uint8Array(data);
const group = fragments.load(buffer);
world.scene.three.add(group);
uuid = group.uuid;
}
๐ค Storing Fragmentsโ
Let's see how you can export fragments as a file. First, we'll define a function to download a file:
function download(file: File) {
const link = document.createElement("a");
link.href = URL.createObjectURL(file);
link.download = file.name;
document.body.appendChild(link);
link.click();
link.remove();
}
Fragments Manager can export fragments using the export
method. The method takes the UUID of a fragment as an argument and returns a Blob, which can be used to generate a File and then download it using the function defined just before.โ๏ธ
function exportFragments() {
if (!fragments.groups.size) {
return;
}
const group = fragments.groups.get(uuid);
if (!group) {
return;
}
const data = fragments.export(group);
const blob = new Blob([data]);
const file = new File([blob], "small.frag");
download(file);
}
๐งน Discard Fragment and Clean the Sceneโ
When your user "closes" one or many BIM models, you'll need to discard that FragmetsGroup. You can dispose a specific FragmentsGroup using the disposeGroup
method, or dispose all FragmentsGroups using the dispose
method.
function disposeFragments() {
fragments.dispose();
}