Files
spark/examples/multiple-viewpoints/index.html
T
Diego Marcos 3332f609a9 Initial commit
2025-05-24 00:14:53 -07:00

95 lines
3.3 KiB
HTML

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<title>Forge • Multiple Viewpoints</title>
<style> body {margin: 0;} </style>
</head>
<body>
<script type="importmap">
{
"imports": {
"three": "/examples/js/vendor/three/build/three.module.js",
"@forge-gfx/forge": "/dist/forge.module.js"
}
}
</script>
<script type="module">
import * as THREE from "three";
import { ForgeRenderer, ForgeViewpoint, SplatMesh } from "@forge-gfx/forge";
import { getAssetFileURL } from "/examples/js/get-asset-url.js";
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement)
// Explicitly create a ForgeRenderer in the scene to spawn new viewpoints
const forge = new ForgeRenderer({ renderer });
const splatURL = await getAssetFileURL("butterfly.spz");
const butterfly = new SplatMesh({ url: splatURL});
butterfly.quaternion.set(1, 0, 0, 0);
butterfly.position.set(0, 0, -1);
scene.add(butterfly);
function createViewpoint(origin, screenPos) {
// Create a textured rectangle at the near plane to show the viewpoint
const width = 320;
const height = 240;
const screen = new THREE.Mesh(
new THREE.PlaneGeometry(0.5 * camera.near, 0.5 * camera.near * height / width),
new THREE.MeshBasicMaterial({ map: ForgeViewpoint.EMPTY_TEXTURE }),
);
screen.position.set(screenPos.x, screenPos.y, -1).multiplyScalar(camera.near);
scene.add(screen);
const viewCamera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
viewCamera.position.copy(origin);
viewCamera.lookAt(butterfly.position);
// Create a cone to show the viewpoint camera
const cone = new THREE.Mesh(
new THREE.ConeGeometry(0.1, 0.1, 32),
new THREE.MeshNormalMaterial(),
);
cone.position.copy(viewCamera.position);
cone.quaternion.copy(viewCamera.quaternion);
cone.rotateX(Math.PI / 2);
scene.add(cone);
// Spawn a new viewpoint that auto-updates its sort order, double
// buffered in case the texture is used recursively in the scene
const viewpoint = forge.newViewpoint({
autoUpdate: true,
camera: viewCamera,
target: { width, height, doubleBuffer: true },
onTextureUpdated: (texture) => {
// Update the view screen with the rendered viewpoint
screen.material.map = texture;
},
});
return viewpoint;
}
const viewpoints = [
createViewpoint(new THREE.Vector3(0, 0.5, -1), new THREE.Vector2(-0.5, 0.5)),
createViewpoint(new THREE.Vector3(0.5, -0.5, -1), new THREE.Vector2(-0.5, -0.5)),
];
renderer.setAnimationLoop(function animate(time) {
scene.background.set(0x000000);
renderer.render(scene, camera);
butterfly.rotation.y += 0.01;
// Adjust the background for visibility and render the viewpoints
scene.background.set(0x000040);
for (const viewpoint of viewpoints) {
viewpoint.renderTarget({ scene, camera: viewpoint.camera });
}
});
</script>
</body>
</html>