UNPKG

three

Version:

JavaScript 3D library

252 lines (145 loc) 4.6 kB
import { Group } from '../../objects/Group.js'; function WebXRController() { this._targetRay = null; this._grip = null; this._hand = null; } Object.assign( WebXRController.prototype, { constructor: WebXRController, getHandSpace: function () { if ( this._hand === null ) { this._hand = new Group(); this._hand.matrixAutoUpdate = false; this._hand.visible = false; this._hand.joints = []; this._hand.inputState = { pinching: false }; if ( window.XRHand ) { for ( let i = 0; i <= window.XRHand.LITTLE_PHALANX_TIP; i ++ ) { // The transform of this joint will be updated with the joint pose on each frame let joint = new Group(); joint.matrixAutoUpdate = false; joint.visible = false; this._hand.joints.push( joint ); // ?? this._hand.add( joint ); } } } return this._hand; }, getTargetRaySpace: function () { if ( this._targetRay === null ) { this._targetRay = new Group(); this._targetRay.matrixAutoUpdate = false; this._targetRay.visible = false; } return this._targetRay; }, getGripSpace: function () { if ( this._grip === null ) { this._grip = new Group(); this._grip.matrixAutoUpdate = false; this._grip.visible = false; } return this._grip; }, dispatchEvent: function ( event ) { if ( this._targetRay !== null ) { this._targetRay.dispatchEvent( event ); } if ( this._grip !== null ) { this._grip.dispatchEvent( event ); } if ( this._hand !== null ) { this._hand.dispatchEvent( event ); } return this; }, disconnect: function ( inputSource ) { this.dispatchEvent( { type: 'disconnected', data: inputSource } ); if ( this._targetRay !== null ) { this._targetRay.visible = false; } if ( this._grip !== null ) { this._grip.visible = false; } if ( this._hand !== null ) { this._hand.visible = false; } return this; }, update: function ( inputSource, frame, referenceSpace ) { let inputPose = null; let gripPose = null; let handPose = null; const targetRay = this._targetRay; const grip = this._grip; const hand = this._hand; if ( inputSource ) { if ( inputSource.hand ) { handPose = true; for ( let i = 0; i <= window.XRHand.LITTLE_PHALANX_TIP; i ++ ) { if ( inputSource.hand[ i ] ) { // Update the joints groups with the XRJoint poses let jointPose = frame.getJointPose( inputSource.hand[ i ], referenceSpace ); const joint = hand.joints[ i ]; if ( jointPose !== null ) { joint.matrix.fromArray( jointPose.transform.matrix ); joint.matrix.decompose( joint.position, joint.rotation, joint.scale ); joint.jointRadius = jointPose.radius; } joint.visible = jointPose !== null; // Custom events // Check pinch const indexTip = hand.joints[ window.XRHand.INDEX_PHALANX_TIP ]; const thumbTip = hand.joints[ window.XRHand.THUMB_PHALANX_TIP ]; const distance = indexTip.position.distanceTo( thumbTip.position ); const distanceToPinch = 0.02; const threshold = 0.005; if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) { hand.inputState.pinching = false; this.dispatchEvent( { type: "pinchend", handedness: inputSource.handedness, target: this } ); } else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) { hand.inputState.pinching = true; this.dispatchEvent( { type: "pinchstart", handedness: inputSource.handedness, target: this } ); } } } } else { if ( targetRay !== null ) { inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace ); if ( inputPose !== null ) { targetRay.matrix.fromArray( inputPose.transform.matrix ); targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale ); } } if ( grip !== null && inputSource.gripSpace ) { gripPose = frame.getPose( inputSource.gripSpace, referenceSpace ); if ( gripPose !== null ) { grip.matrix.fromArray( gripPose.transform.matrix ); grip.matrix.decompose( grip.position, grip.rotation, grip.scale ); } } } } if ( targetRay !== null ) { targetRay.visible = ( inputPose !== null ); } if ( grip !== null ) { grip.visible = ( gripPose !== null ); } if ( hand !== null ) { hand.visible = ( handPose !== null ); } return this; } } ); export { WebXRController };