author Yannick Deubel (https://github.com/yandeu)
 *  copyright license https import * as THREE from 'three' ; import { VRButton } from 'three/examples/jsm/webxr/VRButton' ; import { XRControllerModelFactory } from 'three/examples/jsm/webxr/XRControllerModelFactory' ; export default class WebXR { cameraGroup : THREE . Group ; controllerModelFactory = new XRControllerModelFactory ( ) ; constructor ( private _renderer , private _scene , private _camera ) { this . cameraGroup = new THREE . Group ( ) ; this . cameraGroup . add ( _camera ) ; _scene . add ( this . cameraGroup ) ; _renderer . xr . enabled = true ; const vrButton = VRButton . createButton ( _renderer ) ; vrButton . style . cssText += 'background: rgba(0, 0, 0, 0.8); ' ; document . body . appendChild ( vrButton ) ; } public get isPresenting ( ) { return ! ! this . _renderer ?. xr ?. isPresenting ; } public getController ( id ) { const controller = this . _renderer . xr . getController ( id ) ; this . cameraGroup . add ( controller ) ; return controller ; } public getControllerGrip ( id ) { const controllerGrip = this . _renderer . xr . getControllerGrip ( id ) ; const model = this . controllerModelFactory . createControllerModel ( controllerGrip ) ; controllerGrip . add ( model ) ; this . cameraGroup . add ( controllerGrip ) ; return controllerGrip ; } public getControllerRay ( data ) { const { targetRayMode } = data ; if ( targetRayMode === 'tracked-pointer' ) { const geometry = new THREE . BufferGeometry ( ) ; geometry . setAttribute ( 'position' , new THREE . Float32BufferAttribute ( [ 0 , 0 , 0 , 0 , 0 , - 1 ] , 3 ) ) ; geometry . setAttribute ( 'color' , new THREE . Float32BufferAttribute ( [ 1 , 0 , 0 , 1 , 1 , 1 ] , 3 ) ) ; const material = new THREE . LineBasicMaterial ( { vertexColors : true } ) ; return new THREE . Line ( geometry , material ) ; } if ( targetRayMode === 'gaze' ) { const geometry = new THREE . RingBufferGeometry ( 0.02 , 0.04 , 32 ) . translate ( 0 , 0 , - 1 ) ; const material = new THREE . MeshBasicMaterial ( { color : 'red' , opacity : 0.5 , transparent : true } ) ; return new THREE . Mesh ( geometry , material ) ; } return ; } public get camera ( ) { return this . WebXRCamera ; } private get WebXRCamera ( ) { return { group : this . cameraGroup , position : this . cameraGroup ?. position , rotation : this . isPresenting ? this . _renderer . xr . getCamera ( this . _camera ) . rotation : undefined , getWorldDirection : ( target ) => this . isPresenting ? this . _renderer . xr . getCamera ( this . _camera ) . getWorldDirection ( target ) : undefined } ; } }