"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const THREE = require("three"); function _interopNamespaceDefault(e) { const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } }); if (e) { for (const k in e) { if (k !== "default") { const d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: () => e[k] }); } } } n.default = e; return Object.freeze(n); } const THREE__namespace = /* @__PURE__ */ _interopNamespaceDefault(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__namespace.Vector3(0, 1, 0); const ZAXIS = /* @__PURE__ */ new THREE__namespace.Vector3(0, 0, 1); const CURSOR_RADIUS = 0.02; const CURSOR_MAX_DISTANCE = 1.5; class OculusHandPointerModel extends THREE__namespace.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__namespace.Vector3(POINTER_FRONT_RADIUS, 0, -1 * (POINTER_LENGTH - rearRadius)); this._drawVerticesRing(vertices, frontFaceBase, 0); const rearBase = new THREE__namespace.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__namespace.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__namespace.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__namespace.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__namespace.BufferGeometry(); this.pointerGeometry.setAttribute("position", new THREE__namespace.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__namespace.MeshBasicMaterial(); material.transparent = true; material.opacity = POINTER_OPACITY_MIN; this.pointerGeometry.setIndex(indices); this.pointerMesh = new THREE__namespace.Mesh(this.pointerGeometry, material); this.pointerMesh.position.set(0, 0, -1 * POINTER_REAR_RADIUS); this.pointerObject = new THREE__namespace.Object3D(); this.pointerObject.add(this.pointerMesh); this.raycaster = new THREE__namespace.Raycaster(); const cursorGeometry = new THREE__namespace.SphereGeometry(CURSOR_RADIUS, 10, 10); const cursorMaterial = new THREE__namespace.MeshBasicMaterial(); cursorMaterial.transparent = true; cursorMaterial.opacity = POINTER_OPACITY_MIN; this.cursorObject = new THREE__namespace.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__namespace.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__namespace.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__namespace.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); } } exports.OculusHandPointerModel = OculusHandPointerModel; //# sourceMappingURL=OculusHandPointerModel.cjs.map