Initial project import
This commit is contained in:
225
node_modules/three-stdlib/webxr/OculusHandPointerModel.js
generated
vendored
Normal file
225
node_modules/three-stdlib/webxr/OculusHandPointerModel.js
generated
vendored
Normal file
@@ -0,0 +1,225 @@
|
||||
import * as THREE from "three";
|
||||
const PINCH_MAX = 0.05;
|
||||
const PINCH_THRESHOLD = 0.02;
|
||||
const PINCH_MIN = 0.01;
|
||||
const POINTER_ADVANCE_MAX = 0.02;
|
||||
const POINTER_OPACITY_MAX = 1;
|
||||
const POINTER_OPACITY_MIN = 0.4;
|
||||
const POINTER_FRONT_RADIUS = 2e-3;
|
||||
const POINTER_REAR_RADIUS = 0.01;
|
||||
const POINTER_REAR_RADIUS_MIN = 3e-3;
|
||||
const POINTER_LENGTH = 0.035;
|
||||
const POINTER_SEGMENTS = 16;
|
||||
const POINTER_RINGS = 12;
|
||||
const POINTER_HEMISPHERE_ANGLE = 110;
|
||||
const YAXIS = /* @__PURE__ */ new THREE.Vector3(0, 1, 0);
|
||||
const ZAXIS = /* @__PURE__ */ new THREE.Vector3(0, 0, 1);
|
||||
const CURSOR_RADIUS = 0.02;
|
||||
const CURSOR_MAX_DISTANCE = 1.5;
|
||||
class OculusHandPointerModel extends THREE.Object3D {
|
||||
constructor(hand, controller) {
|
||||
super();
|
||||
this.hand = hand;
|
||||
this.controller = controller;
|
||||
this.motionController = null;
|
||||
this.envMap = null;
|
||||
this.mesh = null;
|
||||
this.pointerGeometry = null;
|
||||
this.pointerMesh = null;
|
||||
this.pointerObject = null;
|
||||
this.pinched = false;
|
||||
this.attached = false;
|
||||
this.cursorObject = null;
|
||||
this.raycaster = null;
|
||||
this._onConnected = this._onConnected.bind(this);
|
||||
this._onDisconnected = this._onDisconnected.bind(this);
|
||||
this.hand.addEventListener("connected", this._onConnected);
|
||||
this.hand.addEventListener("disconnected", this._onDisconnected);
|
||||
}
|
||||
_onConnected(event) {
|
||||
const xrInputSource = event.data;
|
||||
if (xrInputSource.hand) {
|
||||
this.visible = true;
|
||||
this.xrInputSource = xrInputSource;
|
||||
this.createPointer();
|
||||
}
|
||||
}
|
||||
_onDisconnected() {
|
||||
var _a, _b;
|
||||
this.visible = false;
|
||||
this.xrInputSource = null;
|
||||
(_a = this.pointerGeometry) == null ? void 0 : _a.dispose();
|
||||
(_b = this.pointerMesh) == null ? void 0 : _b.material.dispose();
|
||||
this.clear();
|
||||
}
|
||||
_drawVerticesRing(vertices, baseVector, ringIndex) {
|
||||
const segmentVector = baseVector.clone();
|
||||
for (var i = 0; i < POINTER_SEGMENTS; i++) {
|
||||
segmentVector.applyAxisAngle(ZAXIS, Math.PI * 2 / POINTER_SEGMENTS);
|
||||
const vid = ringIndex * POINTER_SEGMENTS + i;
|
||||
vertices[3 * vid] = segmentVector.x;
|
||||
vertices[3 * vid + 1] = segmentVector.y;
|
||||
vertices[3 * vid + 2] = segmentVector.z;
|
||||
}
|
||||
}
|
||||
_updatePointerVertices(rearRadius) {
|
||||
const vertices = this.pointerGeometry.attributes.position.array;
|
||||
const frontFaceBase = new THREE.Vector3(POINTER_FRONT_RADIUS, 0, -1 * (POINTER_LENGTH - rearRadius));
|
||||
this._drawVerticesRing(vertices, frontFaceBase, 0);
|
||||
const rearBase = new THREE.Vector3(
|
||||
Math.sin(Math.PI * POINTER_HEMISPHERE_ANGLE / 180) * rearRadius,
|
||||
Math.cos(Math.PI * POINTER_HEMISPHERE_ANGLE / 180) * rearRadius,
|
||||
0
|
||||
);
|
||||
for (var i = 0; i < POINTER_RINGS; i++) {
|
||||
this._drawVerticesRing(vertices, rearBase, i + 1);
|
||||
rearBase.applyAxisAngle(YAXIS, Math.PI * POINTER_HEMISPHERE_ANGLE / 180 / (POINTER_RINGS * -2));
|
||||
}
|
||||
const frontCenterIndex = POINTER_SEGMENTS * (1 + POINTER_RINGS);
|
||||
const rearCenterIndex = POINTER_SEGMENTS * (1 + POINTER_RINGS) + 1;
|
||||
const frontCenter = new THREE.Vector3(0, 0, -1 * (POINTER_LENGTH - rearRadius));
|
||||
vertices[frontCenterIndex * 3] = frontCenter.x;
|
||||
vertices[frontCenterIndex * 3 + 1] = frontCenter.y;
|
||||
vertices[frontCenterIndex * 3 + 2] = frontCenter.z;
|
||||
const rearCenter = new THREE.Vector3(0, 0, rearRadius);
|
||||
vertices[rearCenterIndex * 3] = rearCenter.x;
|
||||
vertices[rearCenterIndex * 3 + 1] = rearCenter.y;
|
||||
vertices[rearCenterIndex * 3 + 2] = rearCenter.z;
|
||||
this.pointerGeometry.setAttribute("position", new THREE.Float32BufferAttribute(vertices, 3));
|
||||
}
|
||||
createPointer() {
|
||||
var i, j;
|
||||
const vertices = new Array(((POINTER_RINGS + 1) * POINTER_SEGMENTS + 2) * 3).fill(0);
|
||||
const indices = [];
|
||||
this.pointerGeometry = new THREE.BufferGeometry();
|
||||
this.pointerGeometry.setAttribute("position", new THREE.Float32BufferAttribute(vertices, 3));
|
||||
this._updatePointerVertices(POINTER_REAR_RADIUS);
|
||||
for (i = 0; i < POINTER_RINGS; i++) {
|
||||
for (j = 0; j < POINTER_SEGMENTS - 1; j++) {
|
||||
indices.push(i * POINTER_SEGMENTS + j, i * POINTER_SEGMENTS + j + 1, (i + 1) * POINTER_SEGMENTS + j);
|
||||
indices.push(i * POINTER_SEGMENTS + j + 1, (i + 1) * POINTER_SEGMENTS + j + 1, (i + 1) * POINTER_SEGMENTS + j);
|
||||
}
|
||||
indices.push((i + 1) * POINTER_SEGMENTS - 1, i * POINTER_SEGMENTS, (i + 2) * POINTER_SEGMENTS - 1);
|
||||
indices.push(i * POINTER_SEGMENTS, (i + 1) * POINTER_SEGMENTS, (i + 2) * POINTER_SEGMENTS - 1);
|
||||
}
|
||||
const frontCenterIndex = POINTER_SEGMENTS * (1 + POINTER_RINGS);
|
||||
const rearCenterIndex = POINTER_SEGMENTS * (1 + POINTER_RINGS) + 1;
|
||||
for (i = 0; i < POINTER_SEGMENTS - 1; i++) {
|
||||
indices.push(frontCenterIndex, i + 1, i);
|
||||
indices.push(rearCenterIndex, i + POINTER_SEGMENTS * POINTER_RINGS, i + POINTER_SEGMENTS * POINTER_RINGS + 1);
|
||||
}
|
||||
indices.push(frontCenterIndex, 0, POINTER_SEGMENTS - 1);
|
||||
indices.push(rearCenterIndex, POINTER_SEGMENTS * (POINTER_RINGS + 1) - 1, POINTER_SEGMENTS * POINTER_RINGS);
|
||||
const material = new THREE.MeshBasicMaterial();
|
||||
material.transparent = true;
|
||||
material.opacity = POINTER_OPACITY_MIN;
|
||||
this.pointerGeometry.setIndex(indices);
|
||||
this.pointerMesh = new THREE.Mesh(this.pointerGeometry, material);
|
||||
this.pointerMesh.position.set(0, 0, -1 * POINTER_REAR_RADIUS);
|
||||
this.pointerObject = new THREE.Object3D();
|
||||
this.pointerObject.add(this.pointerMesh);
|
||||
this.raycaster = new THREE.Raycaster();
|
||||
const cursorGeometry = new THREE.SphereGeometry(CURSOR_RADIUS, 10, 10);
|
||||
const cursorMaterial = new THREE.MeshBasicMaterial();
|
||||
cursorMaterial.transparent = true;
|
||||
cursorMaterial.opacity = POINTER_OPACITY_MIN;
|
||||
this.cursorObject = new THREE.Mesh(cursorGeometry, cursorMaterial);
|
||||
this.pointerObject.add(this.cursorObject);
|
||||
this.add(this.pointerObject);
|
||||
}
|
||||
_updateRaycaster() {
|
||||
if (this.raycaster) {
|
||||
const pointerMatrix = this.pointerObject.matrixWorld;
|
||||
const tempMatrix = new THREE.Matrix4();
|
||||
tempMatrix.identity().extractRotation(pointerMatrix);
|
||||
this.raycaster.ray.origin.setFromMatrixPosition(pointerMatrix);
|
||||
this.raycaster.ray.direction.set(0, 0, -1).applyMatrix4(tempMatrix);
|
||||
}
|
||||
}
|
||||
_updatePointer() {
|
||||
this.pointerObject.visible = this.controller.visible;
|
||||
const indexTip = this.hand.joints["index-finger-tip"];
|
||||
const thumbTip = this.hand.joints["thumb-tip"];
|
||||
const distance = indexTip.position.distanceTo(thumbTip.position);
|
||||
const position = indexTip.position.clone().add(thumbTip.position).multiplyScalar(0.5);
|
||||
this.pointerObject.position.copy(position);
|
||||
this.pointerObject.quaternion.copy(this.controller.quaternion);
|
||||
this.pinched = distance <= PINCH_THRESHOLD;
|
||||
const pinchScale = (distance - PINCH_MIN) / (PINCH_MAX - PINCH_MIN);
|
||||
const focusScale = (distance - PINCH_MIN) / (PINCH_THRESHOLD - PINCH_MIN);
|
||||
if (pinchScale > 1) {
|
||||
this._updatePointerVertices(POINTER_REAR_RADIUS);
|
||||
this.pointerMesh.position.set(0, 0, -1 * POINTER_REAR_RADIUS);
|
||||
this.pointerMesh.material.opacity = POINTER_OPACITY_MIN;
|
||||
} else if (pinchScale > 0) {
|
||||
const rearRadius = (POINTER_REAR_RADIUS - POINTER_REAR_RADIUS_MIN) * pinchScale + POINTER_REAR_RADIUS_MIN;
|
||||
this._updatePointerVertices(rearRadius);
|
||||
if (focusScale < 1) {
|
||||
this.pointerMesh.position.set(0, 0, -1 * rearRadius - (1 - focusScale) * POINTER_ADVANCE_MAX);
|
||||
this.pointerMesh.material.opacity = POINTER_OPACITY_MIN + (1 - focusScale) * (POINTER_OPACITY_MAX - POINTER_OPACITY_MIN);
|
||||
} else {
|
||||
this.pointerMesh.position.set(0, 0, -1 * rearRadius);
|
||||
this.pointerMesh.material.opacity = POINTER_OPACITY_MIN;
|
||||
}
|
||||
} else {
|
||||
this._updatePointerVertices(POINTER_REAR_RADIUS_MIN);
|
||||
this.pointerMesh.position.set(0, 0, -1 * POINTER_REAR_RADIUS_MIN - POINTER_ADVANCE_MAX);
|
||||
this.pointerMesh.material.opacity = POINTER_OPACITY_MAX;
|
||||
}
|
||||
this.cursorObject.material.opacity = this.pointerMesh.material.opacity;
|
||||
}
|
||||
updateMatrixWorld(force) {
|
||||
super.updateMatrixWorld(force);
|
||||
if (this.pointerGeometry) {
|
||||
this._updatePointer();
|
||||
this._updateRaycaster();
|
||||
}
|
||||
}
|
||||
isPinched() {
|
||||
return this.pinched;
|
||||
}
|
||||
setAttached(attached) {
|
||||
this.attached = attached;
|
||||
}
|
||||
isAttached() {
|
||||
return this.attached;
|
||||
}
|
||||
intersectObject(object, recursive = true) {
|
||||
if (this.raycaster) {
|
||||
return this.raycaster.intersectObject(object, recursive);
|
||||
}
|
||||
}
|
||||
intersectObjects(objects, recursive = true) {
|
||||
if (this.raycaster) {
|
||||
return this.raycaster.intersectObjects(objects, recursive);
|
||||
}
|
||||
}
|
||||
checkIntersections(objects, recursive = false) {
|
||||
if (this.raycaster && !this.attached) {
|
||||
const intersections = this.raycaster.intersectObjects(objects, recursive);
|
||||
const direction = new THREE.Vector3(0, 0, -1);
|
||||
if (intersections.length > 0) {
|
||||
const intersection = intersections[0];
|
||||
const distance = intersection.distance;
|
||||
this.cursorObject.position.copy(direction.multiplyScalar(distance));
|
||||
} else {
|
||||
this.cursorObject.position.copy(direction.multiplyScalar(CURSOR_MAX_DISTANCE));
|
||||
}
|
||||
}
|
||||
}
|
||||
setCursor(distance) {
|
||||
const direction = new THREE.Vector3(0, 0, -1);
|
||||
if (this.raycaster && !this.attached) {
|
||||
this.cursorObject.position.copy(direction.multiplyScalar(distance));
|
||||
}
|
||||
}
|
||||
dispose() {
|
||||
this._onDisconnected();
|
||||
this.hand.removeEventListener("connected", this._onConnected);
|
||||
this.hand.removeEventListener("disconnected", this._onDisconnected);
|
||||
}
|
||||
}
|
||||
export {
|
||||
OculusHandPointerModel
|
||||
};
|
||||
//# sourceMappingURL=OculusHandPointerModel.js.map
|
||||
Reference in New Issue
Block a user