<HUD>
Renders a heads-up-display (HUD). Each HUD creates a new scene rendered on top of the main scene with a separate Threlte context and camera.
The HUD component creates a partially new Threlte context, specifically a new scene and camera.
Everything else in useThrelte is preserved and reused.
<script lang="ts"> import { Canvas } from '@threlte/core' import Scene from './Scene.svelte'</script>
<div> <Canvas> <Scene /> </Canvas></div>
<style> div { height: 100%; }</style><script lang="ts"> import { T, useTask } from '@threlte/core' import { interactivity, useCursor, useViewport } from '@threlte/extras' import { Mesh, Quaternion } from 'three'
interface Props { quaternion: Quaternion onselect: (arg: string) => void }
let { quaternion, onselect }: Props = $props()
const viewport = useViewport()
let meshes: [Mesh, Mesh, Mesh] = [null!, null!, null!]
const boxCursor = useCursor('pointer') const torusCursor = useCursor('pointer') const torusKnotCursor = useCursor('pointer')
interactivity()
useTask( () => { for (const mesh of meshes) { mesh.quaternion.copy(quaternion) } }, { autoInvalidate: false } )
const boxHovering = boxCursor.hovering const torusHovering = torusCursor.hovering const torusKnotHovering = torusKnotCursor.hovering</script>
<T.OrthographicCamera makeDefault zoom={80} position={[0, 0, 10]}/><T.AmbientLight intensity={Math.PI / 2} />
<T.PointLight position={[10, 10, 10]} decay={0} intensity={Math.PI * 2}/>
<T.Mesh bind:ref={meshes[0]} position={[$viewport.width / 2 - 1, $viewport.height / 2 - 1, 0]} onpointerenter={boxCursor.onPointerEnter} onpointerleave={boxCursor.onPointerLeave} onclick={() => onselect('box')} scale={$boxHovering ? 1.1 : 1}> <T.BoxGeometry args={[0.5, 0.5, 0.5]} /> <T.MeshToonMaterial color={$boxHovering ? 'hotpink' : 'gray'} /></T.Mesh>
<T.Mesh bind:ref={meshes[1]} position={[$viewport.width / 2 - 2, $viewport.height / 2 - 1, 0]} onpointerenter={torusCursor.onPointerEnter} onpointerleave={torusCursor.onPointerLeave} onclick={() => onselect('torus')} scale={$torusHovering ? 1.1 : 1}> <T.TorusGeometry args={[0.25, 0.1]} /> <T.MeshToonMaterial color={$torusHovering ? 'hotpink' : 'gray'} /></T.Mesh>
<T.Mesh bind:ref={meshes[2]} position={[$viewport.width / 2 - 3, $viewport.height / 2 - 1, 0]} onpointerover={torusKnotCursor.onPointerEnter} onpointerleave={torusKnotCursor.onPointerLeave} onclick={() => onselect('torusknot')} scale={$torusKnotHovering ? 1.1 : 1}> <T.TorusKnotGeometry args={[0.215, 0.08, 256]} /> <T.MeshToonMaterial color={$torusKnotHovering ? 'hotpink' : 'gray'} /></T.Mesh><script lang="ts"> import { T, useTask, useThrelte } from '@threlte/core' import { Float, OrbitControls, HUD } from '@threlte/extras' import { Quaternion } from 'three' import HudScene from './HudScene.svelte'
let selected = $state('box') let rotation = $state(0)
const quaternion = new Quaternion() const { camera } = useThrelte()
useTask( (delta) => { rotation += delta
// Spin mesh to the inverse of the default cameras matrix quaternion.copy(camera.current.quaternion).invert() }, { autoInvalidate: false } )</script>
<T.PerspectiveCamera position={[11, 5, 11]} makeDefault fov={30}> <OrbitControls enableZoom={false} /></T.PerspectiveCamera>
<T.DirectionalLight position={[0, 10, 10]} />
<T.AmbientLight intensity={0.6} />
<T.GridHelper args={[5]} />
<HUD> <HudScene {quaternion} onselect={(arg) => { selected = arg }} /></HUD>
<Float speed={8} rotation.y={rotation}> {#if selected === 'box'} <T.Mesh position.y={0.8} scale={2} > <T.BoxGeometry args={[0.5, 0.5, 0.5]} /> <T.MeshToonMaterial color="turquoise" /> </T.Mesh> {:else if selected === 'torus'} <T.Mesh position.y={0.8} scale={1.8} > <T.TorusGeometry args={[0.25, 0.1]} /> <T.MeshToonMaterial color="turquoise" /> </T.Mesh> {:else if selected === 'torusknot'} <T.Mesh position.y={0.8} scale={1.8} > <T.TorusKnotGeometry args={[0.215, 0.08, 256]} /> <T.MeshToonMaterial color="turquoise" /> </T.Mesh> {/if}</Float>Because creating a <HUD> is somewhat similar to creating a <Canvas>, it is recommended to use the same best practices and
place all objects you want in the HUD within a new Scene component:
<script> import Scene from './Scene.svelte'</script>
<HUD> <Scene /></HUD><script> import { T } from '@threlte/core'</script>
<T.PerspectiveCamera makeDefault position={[0, 0, 0]} oncreate={(ref) => ref.lookAt(0, 0, 0)}/>
<T.AmbientLight />
<T.Mesh> <T.BoxGeometry /> <T.MeshStandardMaterial /></T.Mesh>