assets.ts
examples/spark/js/assets.ts · raw · open the example · all examples · site home
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
// The assets of the Spark examples (Spark's examples/assets.json). Every
// host sends access-control-allow-origin: *, so pages load them directly.
// ?assets=<base> loads them from a local copy instead: <base>/<name>.
import * as THREE from "three";
const SPARK = "https://sparkjs.dev/assets";
const FORGE = "https://storage.googleapis.com/forge-dev-public";
const ASSETS: Record<string, string> = {
"arrow.glb": `${SPARK}/models/arrow.glb`,
"dali-env.glb": `${SPARK}/models/dali-env.glb`,
"dali-table.glb": `${SPARK}/models/dali-table.glb`,
"rubberduck.glb": `${SPARK}/models/rubberduck.glb`,
"table.glb": `${SPARK}/models/table.glb`,
"butterfly.png": `${SPARK}/images/butterfly.png`,
"heart.png": `${SPARK}/images/heart.png`,
"sky.jpeg": `${SPARK}/images/sky.jpeg`,
"star.png": `${SPARK}/images/star.png`,
"butterfly.spz": `${SPARK}/splats/butterfly.spz`,
"butterfly-ai.spz": `${SPARK}/splats/butterfly-ai.spz`,
"butterfly-wings-closed.spz": `${SPARK}/splats/butterfly-wings-closed.spz`,
"cat.spz": `${SPARK}/splats/cat.spz`,
"dessert.spz": `${SPARK}/splats/dessert.spz`,
"distant-igloo.spz": `${SPARK}/splats/distant-igloo.spz`,
"fireplace.spz": `${SPARK}/splats/fireplace.spz`,
"fly.spz": `${SPARK}/splats/fly.spz`,
"forge.spz": `${SPARK}/splats/forge.spz`,
"furry-logo-pedestal.spz": `${SPARK}/splats/furry-logo-pedestal.spz`,
"penguin.spz": `${SPARK}/splats/penguin.spz`,
"robot-head.spz": `${SPARK}/splats/robot-head.spz`,
"snow-street.spz": `${SPARK}/splats/snow-street.spz`,
"valley.spz": `${SPARK}/splats/valley.spz`,
"woobles.spz": `${SPARK}/splats/woobles.spz`,
"branzino-amarin.spz": `${SPARK}/splats/food/branzino-amarin.spz`,
"burger-from-amboy.spz": `${SPARK}/splats/food/burger-from-amboy.spz`,
"clams-and-caviar-by-ikoyi.spz": `${SPARK}/splats/food/clams-and-caviar-by-ikoyi.spz`,
"coral-caviar.spz": `${SPARK}/splats/food/coral-caviar.spz`,
"double-double-from-InNOut.spz": `${SPARK}/splats/food/double-Double-from-InNOut.spz`,
"gyro.spz": `${SPARK}/splats/food/gyro.spz`,
"iberico-sandwich-by-reserve.spz": `${SPARK}/splats/food/iberico-sandwich-by-reserve.spz`,
"pad-thai.spz": `${SPARK}/splats/food/pad-thai.spz`,
"primerib-tamos.spz": `${SPARK}/splats/food/primerib-tamos.spz`,
"steaksandwich-mels.spz": `${SPARK}/splats/food/steaksandwich-mels.spz`,
"tomahawk-niku.spz": `${SPARK}/splats/food/tomahawk-niku.spz`,
"greyscale-bedroom.spz": `${FORGE}/marble-scenes/greyscale-room.spz`,
"painted-bedroom.spz": `${FORGE}/painted_bedroom.spz`,
"cozy-cottage-lod.spz": `${FORGE}/asundqui/cozy-xr/cozy_cottage-lod.spz`,
};
const localBase = new URLSearchParams(location.search).get("assets");
// The URL of one of the examples' assets
export function asset(name: string) {
if (!ASSETS[name]) {
throw new Error(`Unknown asset ${name}`);
}
return localBase ? `${localBase.replace(/\/$/, "")}/${name}` : ASSETS[name];
}
type GlbMaterial = THREE.Material & { color?: THREE.Color; map?: THREE.Texture | null };
// A GLB asset's scene. `unlit` swaps its materials for unlit ones (Spark's
// loadDelitGLB); "env" also turns them inside out with a linear texture, for
// environment spheres.
export async function loadGlb(name: string, { unlit }: { unlit?: boolean | "env" } = {}) {
const { GLTFLoader } = await import("three/addons/loaders/GLTFLoader.js");
const { scene } = await new GLTFLoader().loadAsync(asset(name));
if (!unlit) {
return scene;
}
scene.traverse((object) => {
const mesh = object as THREE.Mesh<THREE.BufferGeometry, GlbMaterial>;
if (!mesh.isMesh) {
return;
}
const material = new THREE.MeshBasicMaterial({ map: mesh.material.map ?? null });
if (mesh.material.color) {
material.color.copy(mesh.material.color);
}
if (unlit === "env") {
material.side = THREE.BackSide;
if (material.map) {
material.map.colorSpace = THREE.LinearSRGBColorSpace;
material.map.needsUpdate = true;
}
}
mesh.material = material;
});
return scene;
}