Spaces:
Sleeping
Sleeping
| import { Vector3 } from '../../math/Vector3.js'; | |
| import { Group } from '../../objects/Group.js'; | |
| const _moveEvent = { type: 'move' }; | |
| class WebXRController { | |
| constructor() { | |
| this._targetRay = null; | |
| this._grip = null; | |
| this._hand = null; | |
| } | |
| getHandSpace() { | |
| if (this._hand === null) { | |
| this._hand = new Group(); | |
| this._hand.matrixAutoUpdate = false; | |
| this._hand.visible = false; | |
| this._hand.joints = {}; | |
| this._hand.inputState = { pinching: false }; | |
| } | |
| return this._hand; | |
| } | |
| getTargetRaySpace() { | |
| if (this._targetRay === null) { | |
| this._targetRay = new Group(); | |
| this._targetRay.matrixAutoUpdate = false; | |
| this._targetRay.visible = false; | |
| this._targetRay.hasLinearVelocity = false; | |
| this._targetRay.linearVelocity = new Vector3(); | |
| this._targetRay.hasAngularVelocity = false; | |
| this._targetRay.angularVelocity = new Vector3(); | |
| } | |
| return this._targetRay; | |
| } | |
| getGripSpace() { | |
| if (this._grip === null) { | |
| this._grip = new Group(); | |
| this._grip.matrixAutoUpdate = false; | |
| this._grip.visible = false; | |
| this._grip.hasLinearVelocity = false; | |
| this._grip.linearVelocity = new Vector3(); | |
| this._grip.hasAngularVelocity = false; | |
| this._grip.angularVelocity = new Vector3(); | |
| } | |
| return this._grip; | |
| } | |
| dispatchEvent(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(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(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 && frame.session.visibilityState !== 'visible-blurred') { | |
| 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 (inputPose.linearVelocity) { | |
| targetRay.hasLinearVelocity = true; | |
| targetRay.linearVelocity.copy(inputPose.linearVelocity); | |
| } else { | |
| targetRay.hasLinearVelocity = false; | |
| } | |
| if (inputPose.angularVelocity) { | |
| targetRay.hasAngularVelocity = true; | |
| targetRay.angularVelocity.copy(inputPose.angularVelocity); | |
| } else { | |
| targetRay.hasAngularVelocity = false; | |
| } | |
| this.dispatchEvent(_moveEvent); | |
| } | |
| } | |
| if (hand && inputSource.hand) { | |
| handPose = true; | |
| for (const inputjoint of inputSource.hand.values()) { | |
| // Update the joints groups with the XRJoint poses | |
| const jointPose = frame.getJointPose(inputjoint, referenceSpace); | |
| if (hand.joints[inputjoint.jointName] === undefined) { | |
| // The transform of this joint will be updated with the joint pose on each frame | |
| const joint = new Group(); | |
| joint.matrixAutoUpdate = false; | |
| joint.visible = false; | |
| hand.joints[inputjoint.jointName] = joint; | |
| // ?? | |
| hand.add(joint); | |
| } | |
| const joint = hand.joints[inputjoint.jointName]; | |
| 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 pinchz | |
| const indexTip = hand.joints['index-finger-tip']; | |
| const thumbTip = hand.joints['thumb-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 (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 (gripPose.linearVelocity) { | |
| grip.hasLinearVelocity = true; | |
| grip.linearVelocity.copy(gripPose.linearVelocity); | |
| } else { | |
| grip.hasLinearVelocity = false; | |
| } | |
| if (gripPose.angularVelocity) { | |
| grip.hasAngularVelocity = true; | |
| grip.angularVelocity.copy(gripPose.angularVelocity); | |
| } else { | |
| grip.hasAngularVelocity = false; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| 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 }; | |