FragmentsModels
Copying and pasting? We've got you covered! You can find the full source code of this tutorial here.
Loading Fragment Models 🔼
Before diving into the world of Fragments, the first step is to load your Fragment Models. This is a crucial step to unlock the full potential of working with Fragments. Let's explore how to do it effectively.
🖖 Importing our Libraries
First things first, let's install all necessary dependencies to make this example work:
import * as THREE from "three";
import * as OBC from "@thatopen/components";
import * as BUI from "@thatopen/ui";
import Stats from "stats.js";
// You have to import * as FRAGS from "@thatopen/fragments"
import * as FRAGS from "..";
🌎 Setting up a Simple Scene
To get started, let's set up a basic ThreeJS scene. This will serve as the foundation for our application and allow us to visualize the 3D models effectively:
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.scene.setup();
world.scene.three.background = null;
const container = document.getElementById("container")!;
world.renderer = new OBC.SimpleRenderer(components, container);
world.camera = new OBC.SimpleCamera(components);
world.camera.controls.setLookAt(58, 22, -25, 13, 0, 4.2); // convenient position for the model we will load
components.init();
const grids = components.get(OBC.Grids);
grids.create(world);
Not necessarily! While @thatopen/components simplifies the process of setting up a scene, you can always use plain ThreeJS to create your own custom scene setup. It's entirely up to your preference and project requirements! 😉
🛠️ Setting Up Fragments
Now, let's configure the Fragments library core. This will allow us to load models effortlessly and start manipulating them with ease:
// You have to copy `/node_modules/@thatopen/fragments/dist/Worker/worker.mjs` to your project directory
// and provide the relative path in `workerUrl`
// We use here the internal route of the worker in the library for simplicity purposes
const workerUrl = "https://thatopen.github.io/engine_fragment/resources/worker.mjs";
const fragments = new FRAGS.FragmentsModels(workerUrl);
world.camera.controls.addEventListener("rest", () => fragments.update(true));
// Once a model is available in the list, we can tell what camera to use
// in order to perform the culling and LOD operations.
// Also, we add the model to the 3D scene.
fragments.models.list.onItemSet.add(({ value: model }) => {
model.useCamera(world.camera.three);
world.scene.three.add(model.object);
// At the end, you tell fragments to update so the model can be seen given
// the initial camera position
fragments.update(true);
});
📂 Loading Fragments Models
With the core setup complete, it's time to load a Fragments model into our scene. Fragments are optimized for fast loading and rendering, making them ideal for large-scale 3D models.
You can use the sample Fragment files available in our repository for testing. If you have an IFC model you'd like to convert to Fragments, check out the IfcImporter tutorial for detailed instructions.
To make things more convenient, let's create a helper function that will load the Fragments Model from a given URL:
const loadFragmentFile = async (url: string, id: string) => {
const file = await fetch(url);
const buffer = await file.arrayBuffer();
await fragments.load(buffer, { modelId: id });
};
At any point, you can retrieve the binary data of a loaded model for exporting. This is particularly useful when models are loaded automatically from a remote source, but you want to provide an option to download the data locally for further use:
const getBinaryData = async (id: string) => {
const model = fragments.models.list.get(id);
if (!model) return null;
const buffer = await model.getBuffer(false);
return { name: model.modelId, buffer };
};
Now that all Fragments Models are loaded with unique IDs, let's create a helper function to retrieve these IDs. This will make it easier to manage models, such as loading, disposing, or performing other operations on them.
const getModelsIds = () => {
const models = fragments.models.list.values();
const ids = [...models].map((model) => model.modelId);
return ids;
};