three-stdlib
Version:
stand-alone library of threejs examples
243 lines (242 loc) • 10.5 kB
JavaScript
"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