Files
healer-man/scripts/probe-three-loader.mjs
2026-08-14 15:56:39 -04:00

85 lines
2.8 KiB
JavaScript

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));