meshBounds
A raycast function that will first check for collision with the object’s bounding sphere, then it will check against the object’s bounding box but only if the bounding box has been previously computed. You can use this function if you want to trade pointer precision for an increase in performance.
Basic Usage
Section titled “Basic Usage”meshBounds can simply be passed to an object’s
raycast
prop.
<script> import { meshBounds } from '@threlte/extras'</script>
<T.Mesh raycast={meshBounds}> <T.BoxGeometry /></T.Mesh>If your meshes or models aren’t very complex in terms of geometry, meshBounds won’t provide much
of a performance boost.
<script lang="ts"> import Scene from './Scene.svelte' import { Canvas } from '@threlte/core' import { Checkbox, Pane } from 'svelte-tweakpane-ui'
let showBounds = $state(false)</script>
<Pane title="meshBounds" position="fixed"> <Checkbox bind:value={showBounds} label="show bounds" /></Pane>
<div> <Canvas> <Scene {showBounds} /> </Canvas></div>
<style> div { height: 100%; }</style><script lang="ts"> import type { Vector3Tuple } from 'three' import { OrbitControls } from '@threlte/extras' import { T } from '@threlte/core' import { interactivity, meshBounds } from '@threlte/extras'
let { showBounds = false }: { showBounds?: boolean } = $props()
interactivity()
const positions: Vector3Tuple[] = [ [0, 1, 0], [1, -1, 0], [-1, -1, 0] ]
class BoundsItem { wireframe = $state(true) position: Vector3Tuple
constructor(position: Vector3Tuple) { this.position = position } }
const boundsItems = positions.map((position) => { return new BoundsItem(position) })
const size = 1 // half of the box's diagonal === radius of the bounding sphere const radius = 0.5 * size * Math.sqrt(3)</script>
<T.AmbientLight />
<T.PerspectiveCamera makeDefault position.z={5}> <OrbitControls /></T.PerspectiveCamera>
{#each boundsItems as boundsItem} <T.Mesh raycast={meshBounds} onpointerenter={() => { boundsItem.wireframe = false }} onpointerleave={() => { boundsItem.wireframe = true }} position={boundsItem.position} > <T.BoxGeometry args={[size, size, size]} /> <T.MeshStandardMaterial color="hotpink" wireframe={boundsItem.wireframe} /> </T.Mesh>{/each}
<T.Group visible={showBounds}> {#each positions as position} <T.Mesh {position}> <T.SphereGeometry args={[radius]} /> <T.MeshStandardMaterial transparent opacity={0.25} /> </T.Mesh> {/each}</T.Group>Creating a plugin
Section titled “Creating a plugin”Instead of manually applying the meshBounds raycast function to each mesh, you
can use a Threlte plugin to automatically
apply the meshBounds raycast function to all meshes in your scene.
<script> import { T, injectPlugin, isInstanceOf } from '@threlte/core' import { meshBounds } from '@threlte/extras'
injectPlugin('mesh-bounds-plugin', (args) => { if (isInstanceOf(args.ref, 'Mesh')) { args.ref.raycast = meshBounds } })</script>
<!-- No need to manually apply the meshBounds raycast function --><T.Mesh> <T.MeshBasicMaterial color="hotpink" /> <T.BoxGeometry /></T.Mesh>To selectively apply the meshBounds raycast function to only certain meshes,
you can listen to a prop (e.g. raycastMeshBounds) and conditionally apply the
function.
<script> import { T, injectPlugin, isInstanceOf } from '@threlte/core' import { meshBounds } from '@threlte/extras' import { onDestroy } from 'svelte'
injectPlugin('mesh-bounds-plugin', (args) => { if (!isInstanceOf(args.ref, 'Mesh')) return
const originalRaycast = args.ref.raycast
$effect(() => { if (!!args.props.raycastMeshBounds) { args.ref.raycast = meshBounds } else { args.ref.raycast = originalRaycast } })
onDestroy(() => { args.ref.raycast = originalRaycast })
return { pluginProps: ['raycastMeshBounds'] } })</script>
<!-- Regular raycasting --><T.Mesh> <T.MeshBasicMaterial color="hotpink" /> <T.BoxGeometry /></T.Mesh>
<!-- meshBounds raycasting --><T.Mesh raycastMeshBounds> <T.MeshBasicMaterial color="hotpink" /> <T.BoxGeometry /></T.Mesh>