disable hdr

This commit is contained in:
Milovann Yanatchkov 2025-11-22 13:00:42 +01:00
parent 85562d5406
commit d610fd0f08
2 changed files with 531 additions and 467 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
viewer/package-lock.json
viewer/web/viewer/render.mjs

View file

@ -1,20 +1,19 @@
// (C) buildingSMART International // (C) buildingSMART International
// published under MIT license // published under MIT license
import { ComposedObject } from './composed-object'; import { ComposedObject } from "./composed-object";
import { IfcxFile } from '../ifcx-core/schema/schema-helper'; import { IfcxFile } from "../ifcx-core/schema/schema-helper";
import { compose3 } from './compose-flattened'; import { compose3 } from "./compose-flattened";
import * as THREE from 'three'; import * as THREE from "three";
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js'; import { RGBELoader } from "three/addons/loaders/RGBELoader.js";
import { PCDLoader } from 'three/addons/loaders/PCDLoader.js'; import { PCDLoader } from "three/addons/loaders/PCDLoader.js";
let controls, renderer, scene, camera; let controls, renderer, scene, camera;
type datastype = [string, IfcxFile][]; type datastype = [string, IfcxFile][];
let datas: datastype = []; let datas: datastype = [];
let autoCamera = true; let autoCamera = true;
let objectMap: { [path: string]: any } = {}; let objectMap: { [path: string]: any } = {};
let domMap: { [path: string]: HTMLElement } = {}; let domMap: { [path: string]: HTMLElement } = {};
let primMap: { [path: string]: ComposedObject } = {}; let primMap: { [path: string]: ComposedObject } = {};
@ -24,7 +23,6 @@ let rootPrim: ComposedObject | null = null;
let selectedObject: any = null; let selectedObject: any = null;
let selectedDom: HTMLElement | null = null; let selectedDom: HTMLElement | null = null;
let raycaster = new THREE.Raycaster(); let raycaster = new THREE.Raycaster();
let mouse = new THREE.Vector2(); let mouse = new THREE.Vector2();
@ -46,21 +44,27 @@ async function init() {
rimLight.position.set(0, 8, -10); rimLight.position.set(0, 8, -10);
scene.add(rimLight); scene.add(rimLight);
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100); camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
100,
);
camera.up.set(0, 0, 1); camera.up.set(0, 0, 1);
camera.position.set(50, 50, 50); camera.position.set(50, 50, 50);
camera.lookAt(0, 0, 0); camera.lookAt(0, 0, 0);
const nd = document.querySelector('.viewport'); const nd = document.querySelector(".viewport");
renderer = new THREE.WebGLRenderer({ renderer = new THREE.WebGLRenderer({
alpha: true, alpha: true,
logarithmicDepthBuffer: true logarithmicDepthBuffer: true,
}); });
// for GLTF PBR rendering, create environment map using PMREMGenerator: // for GLTF PBR rendering, create environment map using PMREMGenerator:
// see https://threejs.org/docs/#api/en/extras/PMREMGenerator // see https://threejs.org/docs/#api/en/extras/PMREMGenerator
/*
const pmremGenerator = new THREE.PMREMGenerator(renderer); const pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader(); pmremGenerator.compileEquirectangularShader();
new RGBELoader() new RGBELoader()
@ -75,6 +79,7 @@ async function init() {
texture.dispose(); texture.dispose();
pmremGenerator.dispose(); pmremGenerator.dispose();
}); });
*/
//@ts-ignore //@ts-ignore
renderer.setSize(nd.offsetWidth, nd.offsetHeight); renderer.setSize(nd.offsetWidth, nd.offsetHeight);
@ -85,24 +90,20 @@ async function init() {
controls.dampingFactor = 0.25; controls.dampingFactor = 0.25;
nd!.appendChild(renderer.domElement); nd!.appendChild(renderer.domElement);
renderer.domElement.addEventListener('click', onCanvasClick); renderer.domElement.addEventListener("click", onCanvasClick);
return scene; return scene;
} }
function HasAttr(node: ComposedObject | undefined, attrName: string) function HasAttr(node: ComposedObject | undefined, attrName: string) {
{
if (!node || !node.attributes) return false; if (!node || !node.attributes) return false;
return !!node.attributes[attrName]; return !!node.attributes[attrName];
} }
function FindChildWithAttr(node: ComposedObject | undefined, attrName: string) function FindChildWithAttr(node: ComposedObject | undefined, attrName: string) {
{
if (!node || !node.children) return undefined; if (!node || !node.children) return undefined;
for (let i = 0; i < node.children.length; i++) for (let i = 0; i < node.children.length; i++) {
{ if (HasAttr(node.children[i], attrName)) {
if (HasAttr(node.children[i], attrName))
{
return node.children[i]; return node.children[i];
} }
} }
@ -132,7 +133,7 @@ function setHighlight(obj: any, highlight: boolean) {
function selectPath(path: string | null) { function selectPath(path: string | null) {
if (!path) { if (!path) {
if (selectedObject) setHighlight(selectedObject, false); if (selectedObject) setHighlight(selectedObject, false);
if (selectedDom) selectedDom.classList.remove('selected'); if (selectedDom) selectedDom.classList.remove("selected");
selectedObject = null; selectedObject = null;
selectedDom = null; selectedDom = null;
return; return;
@ -142,12 +143,12 @@ function selectPath(path: string | null) {
setHighlight(selectedObject, false); setHighlight(selectedObject, false);
} }
if (selectedDom) { if (selectedDom) {
selectedDom.classList.remove('selected'); selectedDom.classList.remove("selected");
} }
selectedObject = objectMap[path] || null; selectedObject = objectMap[path] || null;
selectedDom = domMap[path] || null; selectedDom = domMap[path] || null;
if (selectedObject) setHighlight(selectedObject, true); if (selectedObject) setHighlight(selectedObject, true);
if (selectedDom) selectedDom.classList.add('selected'); if (selectedDom) selectedDom.classList.add("selected");
} }
function onCanvasClick(event) { function onCanvasClick(event) {
@ -167,20 +168,19 @@ function onCanvasClick(event) {
} }
selectPath(path); selectPath(path);
} }
} } else {
else {
selectPath(null); selectPath(null);
} }
} }
function tryCreateMeshGltfMaterial(path: ComposedObject[]) { function tryCreateMeshGltfMaterial(path: ComposedObject[]) {
// check for PBR defined by the gltf::material schema // check for PBR defined by the gltf::material schema
for (let p of path) { for (let p of path) {
if (!p.attributes) { if (!p.attributes) {
continue; continue;
} }
const pbrMetallicRoughness = p.attributes["gltf::material::pbrMetallicRoughness"]; const pbrMetallicRoughness =
p.attributes["gltf::material::pbrMetallicRoughness"];
const normalTexture = p.attributes["gltf::material::normalTexture"]; const normalTexture = p.attributes["gltf::material::normalTexture"];
const occlusionTexture = p.attributes["gltf::material::occlusionTexture"]; const occlusionTexture = p.attributes["gltf::material::occlusionTexture"];
const emissiveTexture = p.attributes["gltf::material::emissiveTexture"]; const emissiveTexture = p.attributes["gltf::material::emissiveTexture"];
@ -188,7 +188,16 @@ function tryCreateMeshGltfMaterial(path: ComposedObject[]) {
const alphaMode = p.attributes["gltf::material::alphaMode"]; const alphaMode = p.attributes["gltf::material::alphaMode"];
const alphaCutoff = p.attributes["gltf::material::alphaCutoff"]; const alphaCutoff = p.attributes["gltf::material::alphaCutoff"];
const doubleSided = p.attributes["gltf::material::doubleSided"]; const doubleSided = p.attributes["gltf::material::doubleSided"];
if (!pbrMetallicRoughness && !normalTexture && !occlusionTexture && !emissiveTexture && !emissiveFactor && !alphaMode && !alphaCutoff && !doubleSided) { if (
!pbrMetallicRoughness &&
!normalTexture &&
!occlusionTexture &&
!emissiveTexture &&
!emissiveFactor &&
!alphaMode &&
!alphaCutoff &&
!doubleSided
) {
// if none of the gltf::material properties are defined, we don't use pbr rendering, but default to the bsi::ifc::presentation definitions // if none of the gltf::material properties are defined, we don't use pbr rendering, but default to the bsi::ifc::presentation definitions
continue; continue;
} }
@ -209,7 +218,11 @@ function tryCreateMeshGltfMaterial(path: ComposedObject[]) {
if (pbrMetallicRoughness) { if (pbrMetallicRoughness) {
let baseColorFactor = pbrMetallicRoughness["baseColorFactor"]; let baseColorFactor = pbrMetallicRoughness["baseColorFactor"];
if (baseColorFactor) { if (baseColorFactor) {
material.color = new THREE.Color(baseColorFactor[0], baseColorFactor[1], baseColorFactor[2]); material.color = new THREE.Color(
baseColorFactor[0],
baseColorFactor[1],
baseColorFactor[2],
);
} }
let metallicFactor = pbrMetallicRoughness["metallicFactor"]; let metallicFactor = pbrMetallicRoughness["metallicFactor"];
@ -222,24 +235,26 @@ function tryCreateMeshGltfMaterial(path: ComposedObject[]) {
material.roughness = roughnessFactor; material.roughness = roughnessFactor;
} }
} }
material.envMap = envMap material.envMap = envMap;
material.needsUpdate = true material.needsUpdate = true;
material.envMapRotation = new THREE.Euler(0.5 * Math.PI, 0, 0); material.envMapRotation = new THREE.Euler(0.5 * Math.PI, 0, 0);
// console.log(material) // console.log(material)
return material; return material;
} }
return undefined return undefined;
} }
function createMaterialFromParent(path: ComposedObject[]) { function createMaterialFromParent(path: ComposedObject[]) {
let material = { let material = {
color: new THREE.Color(0.6, 0.6, 0.6), color: new THREE.Color(0.6, 0.6, 0.6),
transparent: false, transparent: false,
opacity: 1 opacity: 1,
}; };
for (let p of path) { for (let p of path) {
const color = p.attributes ? p.attributes["bsi::ifc::presentation::diffuseColor"] : null; const color = p.attributes
? p.attributes["bsi::ifc::presentation::diffuseColor"]
: null;
if (color) { if (color) {
material.color = new THREE.Color(...color); material.color = new THREE.Color(...color);
const opacity = p.attributes["bsi::ifc::presentation::opacity"]; const opacity = p.attributes["bsi::ifc::presentation::opacity"];
@ -254,7 +269,9 @@ function createMaterialFromParent(path: ComposedObject[]) {
} }
function createCurveFromJson(path: ComposedObject[]) { function createCurveFromJson(path: ComposedObject[]) {
let points = new Float32Array(path[0].attributes["usd::usdgeom::basiscurves::points"].flat()); let points = new Float32Array(
path[0].attributes["usd::usdgeom::basiscurves::points"].flat(),
);
const geometry = new THREE.BufferGeometry(); const geometry = new THREE.BufferGeometry();
geometry.setAttribute("position", new THREE.BufferAttribute(points, 3)); geometry.setAttribute("position", new THREE.BufferAttribute(points, 3));
@ -266,20 +283,23 @@ function createCurveFromJson(path: ComposedObject[]) {
} }
function createMeshFromJson(path: ComposedObject[]) { function createMeshFromJson(path: ComposedObject[]) {
let points = new Float32Array(path[0].attributes["usd::usdgeom::mesh::points"].flat()); let points = new Float32Array(
let indices = new Uint16Array(path[0].attributes["usd::usdgeom::mesh::faceVertexIndices"]); path[0].attributes["usd::usdgeom::mesh::points"].flat(),
);
let indices = new Uint16Array(
path[0].attributes["usd::usdgeom::mesh::faceVertexIndices"],
);
const geometry = new THREE.BufferGeometry(); const geometry = new THREE.BufferGeometry();
geometry.setAttribute("position", new THREE.BufferAttribute(points, 3)); geometry.setAttribute("position", new THREE.BufferAttribute(points, 3));
geometry.setIndex(new THREE.BufferAttribute(indices, 1)); geometry.setIndex(new THREE.BufferAttribute(indices, 1));
geometry.computeVertexNormals(); geometry.computeVertexNormals();
var meshMaterial; var meshMaterial;
let gltfPbrMaterial = tryCreateMeshGltfMaterial(path); let gltfPbrMaterial = tryCreateMeshGltfMaterial(path);
if (gltfPbrMaterial) { if (gltfPbrMaterial) {
meshMaterial = gltfPbrMaterial meshMaterial = gltfPbrMaterial;
// console.log(meshMaterial) // console.log(meshMaterial)
} else { } else {
const m = createMaterialFromParent(path); const m = createMaterialFromParent(path);
@ -305,7 +325,10 @@ function createPointsFromJsonPcdBase64(path: ComposedObject[]) {
return points; return points;
} }
function createPoints(geometry: THREE.BufferGeometry, withColors: boolean): THREE.Points { function createPoints(
geometry: THREE.BufferGeometry,
withColors: boolean,
): THREE.Points {
const material = new THREE.PointsMaterial(); const material = new THREE.PointsMaterial();
material.sizeAttenuation = false; material.sizeAttenuation = false;
material.fog = true; material.fog = true;
@ -321,13 +344,21 @@ function createPoints(geometry: THREE.BufferGeometry, withColors: boolean): THRE
function createPointsFromJsonArray(path: ComposedObject[]) { function createPointsFromJsonArray(path: ComposedObject[]) {
const geometry = new THREE.BufferGeometry(); const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(path[0].attributes["points::array::positions"].flat()); const positions = new Float32Array(
geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3)); path[0].attributes["points::array::positions"].flat(),
);
geometry.setAttribute(
"position",
new THREE.Float32BufferAttribute(positions, 3),
);
const colors = path[0].attributes["points::array::colors"]; const colors = path[0].attributes["points::array::colors"];
if (colors) { if (colors) {
const colors_ = new Float32Array(colors.flat()); const colors_ = new Float32Array(colors.flat());
geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors_, 3)); geometry.setAttribute(
"color",
new THREE.Float32BufferAttribute(colors_, 3),
);
} }
return createPoints(geometry, colors); return createPoints(geometry, colors);
} }
@ -336,8 +367,7 @@ function base64ToArrayBuffer(str): ArrayBuffer | undefined {
let binary; let binary;
try { try {
binary = atob(str); binary = atob(str);
} } catch (e) {
catch(e) {
throw new Error("base64 encoded string is invalid"); throw new Error("base64 encoded string is invalid");
} }
const bytes = new Uint8Array(binary.length); const bytes = new Uint8Array(binary.length);
@ -356,14 +386,20 @@ function createPointsFromJsonPositionBase64(path: ComposedObject[]) {
return null; return null;
} }
const positions = new Float32Array(positions_bytes!); const positions = new Float32Array(positions_bytes!);
geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3)); geometry.setAttribute(
"position",
new THREE.Float32BufferAttribute(positions, 3),
);
const colors_base64 = path[0].attributes["points::base64::colors"]; const colors_base64 = path[0].attributes["points::base64::colors"];
if (colors_base64) { if (colors_base64) {
const colors_bytes = base64ToArrayBuffer(colors_base64); const colors_bytes = base64ToArrayBuffer(colors_base64);
if (colors_bytes) { if (colors_bytes) {
const colors = new Float32Array(colors_bytes!); const colors = new Float32Array(colors_bytes!);
geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3)); geometry.setAttribute(
"color",
new THREE.Float32BufferAttribute(colors, 3),
);
} }
} }
return createPoints(geometry, colors_base64); return createPoints(geometry, colors_base64);
@ -372,31 +408,23 @@ function createPointsFromJsonPositionBase64(path: ComposedObject[]) {
function traverseTree(path: ComposedObject[], parent, pathMapping) { function traverseTree(path: ComposedObject[], parent, pathMapping) {
const node = path[0]; const node = path[0];
let elem: any = new THREE.Group(); let elem: any = new THREE.Group();
if (HasAttr(node, "usd::usdgeom::visibility::visibility")) if (HasAttr(node, "usd::usdgeom::visibility::visibility")) {
{ if (
if (node.attributes["usd::usdgeom::visibility::visibility"] === 'invisible') { node.attributes["usd::usdgeom::visibility::visibility"] === "invisible"
) {
return; return;
} }
} } else if (HasAttr(node, "usd::usdgeom::mesh::points")) {
else if (HasAttr(node, "usd::usdgeom::mesh::points"))
{
elem = createMeshFromJson(path); elem = createMeshFromJson(path);
} } else if (HasAttr(node, "usd::usdgeom::basiscurves::points")) {
else if (HasAttr(node, "usd::usdgeom::basiscurves::points"))
{
elem = createCurveFromJson(path); elem = createCurveFromJson(path);
} }
// point cloud data types: // point cloud data types:
else if (HasAttr(node, "pcd::base64")) else if (HasAttr(node, "pcd::base64")) {
{
elem = createPointsFromJsonPcdBase64(path); elem = createPointsFromJsonPcdBase64(path);
} } else if (HasAttr(node, "points::array::positions")) {
else if (HasAttr(node, "points::array::positions"))
{
elem = createPointsFromJsonArray(path); elem = createPointsFromJsonArray(path);
} } else if (HasAttr(node, "points::base64::positions")) {
else if (HasAttr(node, "points::base64::positions"))
{
elem = createPointsFromJsonPositionBase64(path); elem = createPointsFromJsonPositionBase64(path);
} }
@ -404,15 +432,22 @@ function traverseTree(path: ComposedObject[], parent, pathMapping) {
primMap[node.name] = node; primMap[node.name] = node;
elem.userData.path = node.name; elem.userData.path = node.name;
for (let path of Object.entries(node.attributes || {}).filter(([k, _]) => k.startsWith('__internal_')).map(([_, v]) => v)) { for (let path of Object.entries(node.attributes || {})
(pathMapping[String(path)] = pathMapping[String(path)] || []).push(node.name); .filter(([k, _]) => k.startsWith("__internal_"))
.map(([_, v]) => v)) {
(pathMapping[String(path)] = pathMapping[String(path)] || []).push(
node.name,
);
} }
parent.add(elem); parent.add(elem);
if (path.length > 1) { if (path.length > 1) {
elem.matrixAutoUpdate = false; elem.matrixAutoUpdate = false;
let matrixNode = node.attributes && node.attributes['usd::xformop::transform'] ? node.attributes['usd::xformop::transform'].flat() : null; let matrixNode =
node.attributes && node.attributes["usd::xformop::transform"]
? node.attributes["usd::xformop::transform"].flat()
: null;
if (matrixNode) { if (matrixNode) {
let matrix = new THREE.Matrix4(); let matrix = new THREE.Matrix4();
//@ts-ignore //@ts-ignore
@ -422,22 +457,24 @@ function traverseTree(path: ComposedObject[], parent, pathMapping) {
} }
} }
(node.children || []).forEach(child => traverseTree([child, ...path], elem || parent, pathMapping)); (node.children || []).forEach((child) =>
traverseTree([child, ...path], elem || parent, pathMapping),
);
} }
function encodeHtmlEntities(str) { function encodeHtmlEntities(str) {
const div = document.createElement('div'); const div = document.createElement("div");
div.textContent = str; div.textContent = str;
return div.innerHTML; return div.innerHTML;
}; }
const icons = { const icons = {
'usd::usdgeom::mesh::points': 'deployed_code', "usd::usdgeom::mesh::points": "deployed_code",
'usd::usdgeom::basiscurves::points': 'line_curve', "usd::usdgeom::basiscurves::points": "line_curve",
'usd::usdshade::material::outputs::surface.connect': 'line_style', "usd::usdshade::material::outputs::surface.connect": "line_style",
'pcd::base64': 'grain', "pcd::base64": "grain",
'points::array::positions': 'grain', "points::array::positions": "grain",
'points::base64::positions': 'grain', "points::base64::positions": "grain",
}; };
function handleClick(prim, pathMapping, root) { function handleClick(prim, pathMapping, root) {
@ -446,27 +483,37 @@ function handleClick(prim, pathMapping, root) {
container.innerHTML = ""; container.innerHTML = "";
const table = document.createElement("table"); const table = document.createElement("table");
table.setAttribute("border", "0"); table.setAttribute("border", "0");
const entries = [["name", prim.name], ...Object.entries(prim.attributes).filter(([k, _]) => !k.startsWith('__internal_'))]; const entries = [
["name", prim.name],
...Object.entries(prim.attributes).filter(
([k, _]) => !k.startsWith("__internal_"),
),
];
const format = (value) => { const format = (value) => {
if (Array.isArray(value)) { if (Array.isArray(value)) {
let N = document.createElement('span'); let N = document.createElement("span");
N.appendChild(document.createTextNode('(')); N.appendChild(document.createTextNode("("));
let first = true; let first = true;
for (let n of value.map(format)) { for (let n of value.map(format)) {
if (!first) { if (!first) {
N.appendChild(document.createTextNode(',')); N.appendChild(document.createTextNode(","));
} }
N.appendChild(n); N.appendChild(n);
first = false; first = false;
} }
N.appendChild(document.createTextNode(')')); N.appendChild(document.createTextNode(")"));
return N; return N;
} else if (typeof value === "object") { } else if (typeof value === "object") {
const ks = Object.keys(value); const ks = Object.keys(value);
if (ks.length == 1 && ks[0] === 'ref' && pathMapping[value.ref] && pathMapping[value.ref].length == 1) { if (
let a = document.createElement('a'); ks.length == 1 &&
ks[0] === "ref" &&
pathMapping[value.ref] &&
pathMapping[value.ref].length == 1
) {
let a = document.createElement("a");
let resolvedRefAsPath = pathMapping[value.ref][0]; let resolvedRefAsPath = pathMapping[value.ref][0];
a.setAttribute('href', '#'); a.setAttribute("href", "#");
a.textContent = resolvedRefAsPath; a.textContent = resolvedRefAsPath;
a.onclick = () => { a.onclick = () => {
let prim = null; let prim = null;
@ -476,12 +523,12 @@ function handleClick(prim, pathMapping, root) {
} else { } else {
(n.children || []).forEach(recurse); (n.children || []).forEach(recurse);
} }
} };
recurse(root); recurse(root);
if (prim) { if (prim) {
handleClick(prim, pathMapping, root); handleClick(prim, pathMapping, root);
} }
} };
return a; return a;
} else { } else {
return document.createTextNode(JSON.stringify(value)); return document.createTextNode(JSON.stringify(value));
@ -505,11 +552,17 @@ function handleClick(prim, pathMapping, root) {
} }
function buildDomTree(prim, node, pathMapping, root = null) { function buildDomTree(prim, node, pathMapping, root = null) {
const elem = document.createElement('div'); const elem = document.createElement("div");
let span; let span;
elem.appendChild(document.createTextNode(prim.name ? prim.name.split('/').reverse()[0] : 'root')); elem.appendChild(
elem.appendChild(span = document.createElement('span')); document.createTextNode(
Object.entries(icons).forEach(([k, v]) => span.innerText += (prim.attributes || {})[k] ? v : ' '); prim.name ? prim.name.split("/").reverse()[0] : "root",
),
);
elem.appendChild((span = document.createElement("span")));
Object.entries(icons).forEach(
([k, v]) => (span.innerText += (prim.attributes || {})[k] ? v : " "),
);
span.className = "material-symbols-outlined"; span.className = "material-symbols-outlined";
domMap[prim.name] = elem as HTMLElement; domMap[prim.name] = elem as HTMLElement;
elem.dataset.path = prim.name; elem.dataset.path = prim.name;
@ -519,14 +572,16 @@ function buildDomTree(prim, node, pathMapping, root=null) {
evt.stopPropagation(); evt.stopPropagation();
}; };
node.appendChild(elem); node.appendChild(elem);
(prim.children || []).forEach(p => buildDomTree(p, elem, pathMapping, root || prim)); (prim.children || []).forEach((p) =>
buildDomTree(p, elem, pathMapping, root || prim),
);
} }
export async function composeAndRender() { export async function composeAndRender() {
if (scene) { if (scene) {
// @todo does this actually free up resources? // @todo does this actually free up resources?
// retain only the lights // retain only the lights
scene.children = scene.children.filter(n => n instanceof THREE.Light); scene.children = scene.children.filter((n) => n instanceof THREE.Light);
} }
objectMap = {}; objectMap = {};
@ -535,14 +590,14 @@ export async function composeAndRender() {
currentPathMapping = null; currentPathMapping = null;
rootPrim = null; rootPrim = null;
document.querySelector('.tree')!.innerHTML = ''; document.querySelector(".tree")!.innerHTML = "";
if (datas.length === 0) { if (datas.length === 0) {
return; return;
} }
let tree: null | ComposedObject = null; let tree: null | ComposedObject = null;
let dataArray = datas.map(arr => arr[1]); let dataArray = datas.map((arr) => arr[1]);
tree = await compose3(dataArray as IfcxFile[]); tree = await compose3(dataArray as IfcxFile[]);
if (!tree) { if (!tree) {
@ -551,7 +606,7 @@ export async function composeAndRender() {
} }
if (!scene) { if (!scene) {
await init() await init();
} }
let pathMapping = {}; let pathMapping = {};
@ -563,9 +618,16 @@ export async function composeAndRender() {
const boundingBox = new THREE.Box3(); const boundingBox = new THREE.Box3();
boundingBox.setFromObject(scene); boundingBox.setFromObject(scene);
if (!boundingBox.isEmpty()) { if (!boundingBox.isEmpty()) {
let avg = boundingBox.min.clone().add(boundingBox.max).multiplyScalar(0.5); let avg = boundingBox.min
.clone()
.add(boundingBox.max)
.multiplyScalar(0.5);
let ext = boundingBox.max.clone().sub(boundingBox.min).length(); let ext = boundingBox.max.clone().sub(boundingBox.min).length();
camera.position.copy(avg.clone().add(new THREE.Vector3(1,1,1).normalize().multiplyScalar(ext))); camera.position.copy(
avg
.clone()
.add(new THREE.Vector3(1, 1, 1).normalize().multiplyScalar(ext)),
);
camera.far = ext * 3; camera.far = ext * 3;
camera.updateProjectionMatrix(); camera.updateProjectionMatrix();
controls.target.copy(avg); controls.target.copy(avg);
@ -576,17 +638,17 @@ export async function composeAndRender() {
} }
} }
buildDomTree(tree, document.querySelector('.tree'), pathMapping); buildDomTree(tree, document.querySelector(".tree"), pathMapping);
animate(); animate();
} }
function createLayerDom() { function createLayerDom() {
document.querySelector('.layers div')!.innerHTML = ''; document.querySelector(".layers div")!.innerHTML = "";
datas.forEach(([name, _], index) => { datas.forEach(([name, _], index) => {
const elem = document.createElement('div'); const elem = document.createElement("div");
elem.appendChild(document.createTextNode(name)); elem.appendChild(document.createTextNode(name));
['\u25B3', '\u25BD', '\u00D7'].reverse().forEach((lbl, cmd) => { ["\u25B3", "\u25BD", "\u00D7"].reverse().forEach((lbl, cmd) => {
const btn = document.createElement('span'); const btn = document.createElement("span");
btn.onclick = (evt) => { btn.onclick = (evt) => {
evt.stopPropagation(); evt.stopPropagation();
if (cmd === 2) { if (cmd === 2) {
@ -603,11 +665,11 @@ function createLayerDom() {
// TODO: await this // TODO: await this
composeAndRender(); composeAndRender();
createLayerDom(); createLayerDom();
} };
btn.appendChild(document.createTextNode(lbl)); btn.appendChild(document.createTextNode(lbl));
elem.appendChild(btn); elem.appendChild(btn);
}); });
document.querySelector('.layers div')!.appendChild(elem); document.querySelector(".layers div")!.appendChild(elem);
}); });
} }