useHitTest
Provides a hit test result on each frame during an immersive-ar session.
Hit testing lets you position virtual items in a real-world view.
<script> import { useHitTest } from '@threlte/xr'
let ref
useHitTest((hitMatrix, hit) => { if (!ref) return
if (hit) { ref.visible = true ref.matrix.copy(hitMatrix) } else { ref.visible = false } })</script>
<T.Mesh bind:ref> <T.SphereGeometry args={[0.1]}> <T.MeshBasicMaterial /></T.Mesh>This hook can optionally specify one of three origins from which to cast the hit test ray: viewer (the default), leftInput or rightInput.
useHitTest( (hitMatrix, hit) => { // Perform a hit test from the left controller or hand. }, { source: 'leftInput' })In the following example, hit testing is set up from both controllers and hands.
<script lang="ts"> import { Canvas } from '@threlte/core' import { ARButton } from '@threlte/xr' import Scene from './Scene.svelte'</script>
<div> <Canvas> <Scene /> </Canvas> <ARButton /></div>
<style> div { height: 100%; }</style><script lang="ts"> import * as THREE from 'three' import { T } from '@threlte/core' import { XR, Controller, Hand, useHitTest } from '@threlte/xr'
const geometry = new THREE.CylinderGeometry(0.1, 0.1, 0.2, 32).translate(0, 0.1, 0)
let meshes = $state<THREE.Mesh[]>([]) let cursors = $state({ left: undefined! as THREE.Mesh, right: undefined! as THREE.Mesh })
const hands = ['left', 'right'] as const type Hands = (typeof hands)[number]
const handleSelect = (hand: Hands) => () => { if (!cursors[hand].visible) return
const material = new THREE.MeshPhongMaterial({ color: 0xffffff * Math.random() }) const mesh = new THREE.Mesh(geometry, material) cursors[hand].matrix.decompose(mesh.position, mesh.quaternion, mesh.scale) mesh.scale.y = Math.random() * 2 + 1 meshes.push(mesh) }
const handleHitTest = (hand: Hands) => (hitMatrix: THREE.Matrix4, hit: XRHitTestResult | undefined) => { if (!cursors[hand]) return
if (hit) { cursors[hand].visible = true cursors[hand].matrix.copy(hitMatrix) } else { cursors[hand].visible = false } }
useHitTest(handleHitTest('left'), { source: 'leftInput' }) useHitTest(handleHitTest('right'), { source: 'rightInput' })</script>
<XR> {#each hands as hand} <Controller {hand} onselect={handleSelect(hand)} /> <Hand {hand} onpinchend={handleSelect(hand)} /> {/each}</XR>
<T.Mesh bind:ref={cursors.left} matrixAutoUpdate={false}> <T.RingGeometry args={[0.15, 0.2, 32]} oncreate={(ref) => { ref.rotateX(-Math.PI / 2) }} /> <T.MeshBasicMaterial /></T.Mesh>
<T.Mesh bind:ref={cursors.right} matrixAutoUpdate={false}> <T.RingGeometry args={[0.15, 0.2, 32]} oncreate={(ref) => { ref.rotateX(-Math.PI / 2) }} /> <T.MeshBasicMaterial /></T.Mesh>
<T.HemisphereLight args={[0xffffff, 0xbbbbff, 1]} position={[0.5, 1, 0.25]}/>
<T.AmbientLight intensity={0.5} />
{#each meshes as mesh, index (index)} <T is={mesh} />{/each}Signature
Section titled “Signature”useHitTest((hitMatrix: THREE.Matrix4, hit: XRHitTestResult | undefined) => {})