disable hdr
This commit is contained in:
parent
85562d5406
commit
d610fd0f08
2 changed files with 531 additions and 467 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
viewer/package-lock.json
|
||||||
|
viewer/web/viewer/render.mjs
|
||||||
|
|
@ -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));
|
||||||
|
|
@ -504,12 +551,18 @@ 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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue