Amp-Thread-ID: https://ampcode.com/threads/T-01a02d1c-27fc-7761-9f51-ed97b2dd4e3e Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
146 lines
4.3 KiB
TypeScript
146 lines
4.3 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import { importGltf } from "../src/importers/gltf";
|
|
import { createScene, latestGraph, testCore } from "./scene-helpers";
|
|
|
|
function close(actual: ArrayLike<number>, expected: ArrayLike<number>) {
|
|
assert.equal(actual.length, expected.length);
|
|
for (let index = 0; index < actual.length; index++)
|
|
assert.ok(Math.abs(actual[index] - expected[index]) < 1e-5);
|
|
}
|
|
|
|
test("importGltf hydrates worker output into one batched scene update", async () => {
|
|
const previousWorker = globalThis.Worker;
|
|
const previousImageBitmap = globalThis.ImageBitmap;
|
|
const previousCreateImageBitmap = globalThis.createImageBitmap;
|
|
class MockImageBitmap {
|
|
readonly width = 1;
|
|
readonly height = 1;
|
|
}
|
|
const workerResult = {
|
|
camera: { direction: [0, 0, 1], fov: 1.1 },
|
|
textures: [
|
|
{
|
|
image: new MockImageBitmap(),
|
|
sampler: {
|
|
magFilter: "linear",
|
|
minFilter: "linear",
|
|
mipmapFilter: "linear",
|
|
addressModeU: "repeat",
|
|
addressModeV: "repeat",
|
|
},
|
|
},
|
|
],
|
|
materials: [
|
|
{
|
|
baseColor: [0.2, 0.4, 0.6, 1],
|
|
metallic: 0.3,
|
|
roughness: 0.7,
|
|
flags: 0,
|
|
baseColorTexture: 0,
|
|
metallicRoughnessTexture: -1,
|
|
normalTexture: -1,
|
|
emissiveTexture: -1,
|
|
occlusionTexture: -1,
|
|
transmissionTexture: -1,
|
|
thicknessTexture: -1,
|
|
clearcoatTexture: -1,
|
|
iridescenceTexture: -1,
|
|
iridescenceThicknessTexture: -1,
|
|
anisotropyTexture: -1,
|
|
specularTexture: -1,
|
|
specularColorTexture: -1,
|
|
},
|
|
],
|
|
primitives: [
|
|
{
|
|
positions: new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]),
|
|
normals: new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1]),
|
|
uvs: new Float32Array([0, 0, 1, 0, 0, 1]),
|
|
indices: new Uint32Array([0, 1, 2]),
|
|
material: 0,
|
|
position: [2, 3, 4],
|
|
rotor: [0, 0, 0, 1],
|
|
scale: [1, 1, 1],
|
|
},
|
|
],
|
|
lights: [
|
|
{
|
|
type: "point",
|
|
color: [1, 0.5, 0.25],
|
|
intensity: 6,
|
|
range: 12,
|
|
position: [4, 5, 6],
|
|
},
|
|
],
|
|
};
|
|
class MockWorker {
|
|
#listeners = new Map<string, (event: any) => void>();
|
|
|
|
addEventListener(type: string, listener: (event: any) => void) {
|
|
this.#listeners.set(type, listener);
|
|
}
|
|
|
|
postMessage(message: { request: number }) {
|
|
queueMicrotask(() =>
|
|
this.#listeners.get("message")?.({
|
|
data: { request: message.request, result: workerResult },
|
|
}),
|
|
);
|
|
}
|
|
}
|
|
Object.defineProperties(globalThis, {
|
|
Worker: { configurable: true, value: MockWorker },
|
|
ImageBitmap: { configurable: true, value: MockImageBitmap },
|
|
createImageBitmap: {
|
|
configurable: true,
|
|
value: async () => new MockImageBitmap(),
|
|
},
|
|
});
|
|
|
|
try {
|
|
const scene = await createScene();
|
|
const core = testCore(scene);
|
|
const compiled = core.graphs.length;
|
|
const meshes = await importGltf(scene, "https://example.test/model.glb");
|
|
|
|
assert.equal(meshes.length, 1);
|
|
assert.deepEqual(meshes.camera, workerResult.camera);
|
|
assert.deepEqual(meshes[0].position.toArray(), [2, 3, 4]);
|
|
assert.deepEqual(
|
|
Array.from(scene.geometryData(meshes[0].geometryId, "indices")!),
|
|
[0, 1, 2],
|
|
);
|
|
close(
|
|
scene.array("materials").row(meshes[0].materialId).slice(0, 6),
|
|
[0.2, 0.4, 0.6, 1, 0.3, 0.7],
|
|
);
|
|
assert.equal(
|
|
scene.array("materialTextures").row(meshes[0].materialId)[0],
|
|
1,
|
|
);
|
|
assert.deepEqual(
|
|
Array.from(scene.array("pointLights").row(1)),
|
|
[1, 0.5, 0.25, 6, 12, 1, 0, 0],
|
|
);
|
|
const texture = latestGraph(scene).resources.textures.find(
|
|
(resource: any) => resource.id.startsWith("texture-"),
|
|
);
|
|
assert.equal(texture.format, "rgba8unorm-srgb");
|
|
assert.equal(core.uploadedTextures.length, 1);
|
|
assert.equal(core.graphs.length - compiled, 1);
|
|
} finally {
|
|
for (const [name, previous] of [
|
|
["Worker", previousWorker],
|
|
["ImageBitmap", previousImageBitmap],
|
|
["createImageBitmap", previousCreateImageBitmap],
|
|
] as const)
|
|
if (previous === undefined) delete (globalThis as any)[name];
|
|
else
|
|
Object.defineProperty(globalThis, name, {
|
|
configurable: true,
|
|
value: previous,
|
|
});
|
|
}
|
|
});
|