three
Version:
JavaScript 3D library
252 lines (145 loc) • 4.6 kB
JavaScript
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 };