Add interactive tutorial playgrounds
Embed editable split-view examples throughout the guide, restore the full LFS-backed Sponza demo, batch glTF hydration, honor hierarchical transforms, and report transformed BVH picks with a live FPS counter. Amp-Thread-ID: https://ampcode.com/threads/T-01a01380-b478-77d0-84a0-102880a5c5ae Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
@@ -4,11 +4,17 @@ import { PBRMaterial } from "../materials/PBRMaterial";
|
||||
|
||||
let worker: Worker | undefined;
|
||||
let nextRequest = 1;
|
||||
const pending = new Map<number, { resolve: (value: any) => void; reject: (error: Error) => void }>();
|
||||
const pending = new Map<
|
||||
number,
|
||||
{ resolve: (value: any) => void; reject: (error: Error) => void }
|
||||
>();
|
||||
|
||||
function importer() {
|
||||
if (worker) return worker;
|
||||
worker = new Worker(new URL("./worker.ts", import.meta.url), { type: "module", name: "yawn-importer" });
|
||||
worker = new Worker(new URL("./worker.ts", import.meta.url), {
|
||||
type: "module",
|
||||
name: "yawn-importer",
|
||||
});
|
||||
worker.addEventListener("message", ({ data }) => {
|
||||
const request = pending.get(data.request);
|
||||
if (!request) return;
|
||||
@@ -17,7 +23,8 @@ function importer() {
|
||||
else request.resolve(data.result);
|
||||
});
|
||||
worker.addEventListener("error", () => {
|
||||
for (const request of pending.values()) request.reject(new Error("IMPORT_WORKER_ERROR"));
|
||||
for (const request of pending.values())
|
||||
request.reject(new Error("IMPORT_WORKER_ERROR"));
|
||||
pending.clear();
|
||||
});
|
||||
return worker;
|
||||
@@ -31,26 +38,33 @@ export async function importGltf(scene: Scene, url: string | URL) {
|
||||
pending.set(request, { resolve, reject });
|
||||
importer().postMessage({ request, url: String(url) });
|
||||
});
|
||||
const materials = result.materials.map((options: any) => new PBRMaterial(scene, options));
|
||||
await Promise.all(materials.map((material: PBRMaterial) => material.ready));
|
||||
const meshes: Mesh[] = [];
|
||||
for (const primitive of result.primitives) {
|
||||
const mesh = new Mesh(scene, {
|
||||
position: primitive.position,
|
||||
quaternion: primitive.quaternion,
|
||||
scale: primitive.scale,
|
||||
material: materials[primitive.material],
|
||||
vertexData: {
|
||||
positions: primitive.positions,
|
||||
indices: primitive.indices,
|
||||
...(primitive.normals ? { normals: primitive.normals } : {}),
|
||||
...(primitive.tangents ? { tangents: primitive.tangents } : {}),
|
||||
...(primitive.uvs ? { uvs: primitive.uvs } : {}),
|
||||
...(primitive.colors ? { colors: primitive.colors } : {}),
|
||||
},
|
||||
});
|
||||
await mesh.ready;
|
||||
meshes.push(mesh);
|
||||
}
|
||||
return meshes;
|
||||
await scene.reserve({
|
||||
nodes: result.primitives.length,
|
||||
materials: result.materials.length,
|
||||
});
|
||||
return scene.batchGraphUpdates(async () => {
|
||||
const materials = result.materials.map(
|
||||
(options: any) => new PBRMaterial(scene, options),
|
||||
);
|
||||
await Promise.all(materials.map((material: PBRMaterial) => material.ready));
|
||||
const meshes: Mesh[] = result.primitives.map(
|
||||
(primitive: any) =>
|
||||
new Mesh(scene, {
|
||||
position: primitive.position,
|
||||
quaternion: primitive.quaternion,
|
||||
scale: primitive.scale,
|
||||
material: materials[primitive.material],
|
||||
vertexData: {
|
||||
positions: primitive.positions,
|
||||
indices: primitive.indices,
|
||||
...(primitive.normals ? { normals: primitive.normals } : {}),
|
||||
...(primitive.tangents ? { tangents: primitive.tangents } : {}),
|
||||
...(primitive.uvs ? { uvs: primitive.uvs } : {}),
|
||||
...(primitive.colors ? { colors: primitive.colors } : {}),
|
||||
},
|
||||
}),
|
||||
);
|
||||
await Promise.all(meshes.map((mesh) => mesh.ready));
|
||||
return meshes;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user