import { readFile } from "node:fs/promises"; import { performance } from "node:perf_hooks"; import { fileURLToPath } from "node:url"; import { dirname, resolve } from "node:path"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; import { DoubleSide, Raycaster, Vector3 } from "three"; globalThis.self = globalThis; globalThis.createImageBitmap = async () => ({ width: 1, height: 1, close() {}, }); globalThis.ProgressEvent ??= class ProgressEvent { constructor(type, init = {}) { this.type = type; Object.assign(this, init); } }; const here = dirname(fileURLToPath(import.meta.url)); const visualPath = resolve( here, "../src/assets/game/dungeons/wailing-caverns/wailing-caverns-visual.glb", ); const bytes = await readFile(visualPath); const arrayBuffer = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength); const started = performance.now(); const gltf = await new Promise((resolveLoad, rejectLoad) => { new GLTFLoader().parse(arrayBuffer, "", resolveLoad, rejectLoad); }); let meshes = 0; let instancedMeshes = 0; let representedInstances = 0; gltf.scene.traverse((object) => { if (object.isMesh) meshes += 1; if (object.isMesh) { const materials = Array.isArray(object.material) ? object.material : [object.material]; for (const material of materials) material.side = DoubleSide; } if (object.isInstancedMesh) { instancedMeshes += 1; representedInstances += object.count; } }); gltf.scene.updateMatrixWorld(true); const camera = new Vector3(168.4397730700396, -69.7455139484265, 135.3106010044644); const lookAt = new Vector3(162.366, -72.29, 132.353); const raycaster = new Raycaster(camera, lookAt.clone().sub(camera).normalize(), 0, 115); const visibleHits = raycaster.intersectObject(gltf.scene, true).slice(0, 5).map((hit) => ({ distance: hit.distance, object: hit.object.name, point: hit.point.toArray(), materials: (Array.isArray(hit.object.material) ? hit.object.material : [hit.object.material]).map((material) => ({ name: material.name, color: material.color?.getHexString(), opacity: material.opacity, transparent: material.transparent, alphaTest: material.alphaTest, map: material.map?.name ?? null, })), })); console.log(JSON.stringify({ parseMs: Math.round(performance.now() - started), sceneTransform: { position: gltf.scene.position.toArray(), quaternion: gltf.scene.quaternion.toArray(), scale: gltf.scene.scale.toArray(), }, firstChildTransforms: gltf.scene.children.slice(0, 5).map((child) => ({ name: child.name, position: child.position.toArray(), quaternion: child.quaternion.toArray(), scale: child.scale.toArray(), })), sceneChildren: gltf.scene.children.length, meshes, instancedMeshes, representedInstances, visibleHits, }, null, 2));