Skip to content

Commit

Permalink
feat: add basic LOD system using OBBs
Browse files Browse the repository at this point in the history
  • Loading branch information
agviegas committed Feb 29, 2024
1 parent ecf3d62 commit a4faf2f
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 11 deletions.
28 changes: 19 additions & 9 deletions src/fragments/FragmentIfcStreamer/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@
loader.url = "http://dev.api.thatopen.com/storage?fileId=";
let fragments = new OBC.FragmentManager(components);

loader.culler.threshold = 20;

async function loadModel(geometryURL, propertiesURL) {
const rawGeometryData = await fetch(geometryURL);
Expand All @@ -147,14 +146,25 @@
await loader.load(geometryData, true, propertiesData);
}

loader.culler.useLowLod = true;

await loadModel(
"../../../resources/small.ifc-processed.json",
// "../../../resources/small.ifc-processed-properties.json"
);


scene.add(loader.culler.lowLod.get(0).mesh);

// const cam = components.camera.get();
// cam.far = 20000;
// cam.updateProjectionMatrix();


// loader.culler.threshold = 20;
loader.culler.bboxThreshold = 500;
// loader.culler.maxHiddenTime = 1000;
// loader.culler.maxLostTime = 40000;
loader.culler.maxHiddenTime = 1000;
loader.culler.maxLostTime = 40000;

components.camera.controls.addEventListener("controlend", () => {
loader.culler.needsUpdate = true;
Expand Down Expand Up @@ -450,12 +460,12 @@
// }
// );

// loader.culler.renderDebugFrame = true;
// const debugFrame = loader.culler.get().domElement;
// document.body.appendChild(debugFrame);
// debugFrame.style.position = 'fixed';
// debugFrame.style.left = '0';
// debugFrame.style.bottom = '0';
loader.culler.renderDebugFrame = true;
const debugFrame = loader.culler.get().domElement;
document.body.appendChild(debugFrame);
debugFrame.style.position = 'fixed';
debugFrame.style.left = '0';
debugFrame.style.bottom = '0';


// Set up stats
Expand Down
64 changes: 62 additions & 2 deletions src/fragments/FragmentIfcStreamer/src/geometry-culler-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ export class GeometryCullerRenderer extends CullerRenderer {

boxes = new Map<number, FRAGS.Fragment>();

useLowLod = false;

lowLod = new Map<number, FRAGS.Fragment>();

private _geometry: THREE.BufferGeometry;

private _material = new THREE.MeshBasicMaterial({
Expand All @@ -40,6 +44,8 @@ export class GeometryCullerRenderer extends CullerRenderer {
opacity: 1,
});

private _lodMaterial = new THREE.MeshLambertMaterial();

readonly onViewUpdated = new Event<{
toLoad: { [modelID: string]: Map<number, Set<number>> };
toRemove: { [modelID: string]: Set<number> };
Expand Down Expand Up @@ -129,16 +135,27 @@ export class GeometryCullerRenderer extends CullerRenderer {
this.boxes.set(modelIndex, bboxes);
this.scene.add(bboxes.mesh);

if (this.useLowLod) {
const lowLod = new FRAGS.Fragment(this._geometry, this._lodMaterial, 10);
this.lowLod.set(modelIndex, lowLod);
}

const fragmentsGroup = new THREE.Group();
this.scene.add(fragmentsGroup);
this._geometriesGroups.set(modelIndex, fragmentsGroup);

const items = new Map<number, FRAGS.Item>();
const items = new Map<
number,
FRAGS.Item & { geometryColors: THREE.Color[] }
>();

for (const asset of assets) {
// if (asset.id !== 664833) continue;
for (const geometryData of asset.geometries) {
const { geometryID, transformation } = geometryData;
const { geometryID, transformation, color } = geometryData;

const geometryColor = new THREE.Color();
geometryColor.setRGB(color[0], color[1], color[2], "srgb");

const instanceID = this.getInstanceID(asset.id, geometryID);

Expand Down Expand Up @@ -187,12 +204,14 @@ export class GeometryCullerRenderer extends CullerRenderer {
throw new Error("Malformed item!");
}
item.colors.push(threeColor);
item.geometryColors.push(geometryColor);
item.transforms.push(instanceMatrix);
} else {
// This geometry exists only once in this asset (for now)
items.set(instanceID, {
id: instanceID,
colors: [threeColor],
geometryColors: [geometryColor],
transforms: [instanceMatrix],
});
}
Expand All @@ -217,6 +236,14 @@ export class GeometryCullerRenderer extends CullerRenderer {
const itemsArray = Array.from(items.values());
bboxes.add(itemsArray);

if (this.useLowLod) {
for (const item of itemsArray) {
item.colors = item.geometryColors;
}
const lowLod = this.lowLod.get(modelIndex) as FRAGS.Fragment;
lowLod.add(itemsArray);
}

THREE.ColorManagement.enabled = colorEnabled;

// const { geometry, material, count, instanceMatrix, instanceColor } = [
Expand Down Expand Up @@ -411,6 +438,9 @@ export class GeometryCullerRenderer extends CullerRenderer {
const now = performance.now();
let viewWasUpdated = false;

const lodsToShow = new Set<CullerBoundingBox>();
const lodsToHide = new Set<CullerBoundingBox>();

let bboxAmount = 0;
for (const [color, number] of colors) {
if (number < this.threshold) {
Expand Down Expand Up @@ -454,6 +484,9 @@ export class GeometryCullerRenderer extends CullerRenderer {
toShow[modelID].add(geometry.geometryID);
this._foundGeometries.add(color);
viewWasUpdated = true;
if (this.useLowLod) {
lodsToHide.add(geometry);
}
} else if (isFound && !exists) {
// New geometry found
if (!toLoad[modelID]) {
Expand All @@ -469,12 +502,19 @@ export class GeometryCullerRenderer extends CullerRenderer {
set.add(geometry.geometryID);
this._foundGeometries.add(color);
viewWasUpdated = true;

if (this.useLowLod) {
lodsToHide.add(geometry);
}
} else if (!isFound && exists) {
// Geometry is hardly seen, so it can be considered lost
if (bboxAmount < this.bboxThreshold) {
// When too many bounding boxes on sight
// don't hide / destroy geometry to prevent flickering
this.handleLostGeometries(now, color, geometry, toRemove, toHide);
if (this.useLowLod) {
lodsToShow.add(geometry);
}
viewWasUpdated = true;
}
}
Expand All @@ -489,6 +529,9 @@ export class GeometryCullerRenderer extends CullerRenderer {
throw new Error("Geometry not found!");
}
this.handleLostGeometries(now, color, geometry, toRemove, toHide);
if (this.useLowLod) {
lodsToShow.add(geometry);
}
viewWasUpdated = true;
}
}
Expand All @@ -497,6 +540,15 @@ export class GeometryCullerRenderer extends CullerRenderer {
await this.onViewUpdated.trigger({ toLoad, toRemove, toHide, toShow });
}

if (this.useLowLod) {
for (const geometry of lodsToShow) {
this.setLodVisibility(true, geometry);
}
for (const geometry of lodsToHide) {
this.setLodVisibility(false, geometry);
}
}

if (bboxAmount > this.bboxThreshold) {
this.needsUpdate = true;
}
Expand Down Expand Up @@ -530,6 +582,14 @@ export class GeometryCullerRenderer extends CullerRenderer {
}
}

private setLodVisibility(visible: boolean, geometry: CullerBoundingBox) {
const lod = this.lowLod.get(geometry.modelIndex) as FRAGS.Fragment;
for (const assetID of geometry.assetIDs) {
const instanceID = this.getInstanceID(assetID, geometry.geometryID);
lod.setVisibility(visible, [instanceID]);
}
}

private createModelIndex(modelID: string) {
if (this._modelIDIndex.has(modelID)) {
throw new Error("Can't load the same model twice!");
Expand Down
2 changes: 2 additions & 0 deletions src/navigation/EdgesClipper/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@
scene.add(cube2);
components.meshes.add(cube2);



/*MD
:::info Storing Components
Expand Down

0 comments on commit a4faf2f

Please sign in to comment.