Browse Source

VR interaction with items

master
Cailean Finn 2 weeks ago
parent
commit
0d8101125d
  1. 92
      js/Player.js

92
js/Player.js

@ -214,10 +214,13 @@ export class Player {
controller.add(debugSphere);
const lineGeometry = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 0, -1)]);
const line = new THREE.Line(lineGeometry);
line.scale.z = 5;
const lineMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 }); // White color for the ray
const line = new THREE.Line(lineGeometry, lineMaterial);
line.name = 'controller-ray'; // Give the line a name to find it later
line.scale.z = this.maxInteractionDistance;
controller.add(line);
controller.addEventListener('selectstart', () => this._OnVRSelectStart(i));
controller.addEventListener('selectend', () => this._OnVRSelectEnd(i));
controller.addEventListener('squeezestart', () => this._OnVRSqueezeStart(i));
@ -232,6 +235,7 @@ export class Player {
if (this.currentIntItem && !this.attachedItem) {
this.attachedItem = this.currentIntItem;
this.attachedItem.isActive = true;
console.log("Attaced Item to (VR) ", this.attachedItem.name);
} else {
this.isDrawing = true;
}
@ -246,9 +250,13 @@ export class Player {
_OnVRSelectEnd(controllerIndex) {
// Right controller
console.log(`Select End: ${controllerIndex}`);
if (controllerIndex === 0) {
this.isDrawing = false;
if (controllerIndex === 0 && this.attachedItem) {
this.attachedItem.isActive = false;
this.attachedItem._removeContentDisplay();
this.attachedItem = null;
console.log("Dettached item from player (VR)");
}
// Left controller
if (controllerIndex === 1) {
this.teleporting = false;
@ -276,36 +284,36 @@ export class Player {
}
_handleVRJoystick() {
// Get the gamepad for the left controller (index 1 in your setup)
const gamepad = this.vrGamepads[1];
// You no longer need to check this.vrControllers[1] since the gamepad is null if disconnected.
if (!gamepad) return;
// The axes array for a thumbstick is often at index 2 (X) and 3 (Y) for the primary stick.
// If the left stick is the primary for movement/teleport, these are the typical indices.
// Always check for undefined or use a safe index, just in case.
const joystickVertical = gamepad.axes[3];
if (joystickVertical !== undefined) {
// joystickVertical is -1 (forward) to 1 (backward). We want forward to be max distance.
// We'll map the [-1, 1] range to our [min, max] distance factor range.
// --- Left Controller (Teleport Distance) ---
const leftGamepad = this.vrGamepads[1];
if (leftGamepad) {
const joystickVertical = leftGamepad.axes[3];
// 1. Convert [-1, 1] to [0, 1] (Mapping: -1 -> 1, 0 -> 0.5, 1 -> 0)
// Since Y is typically -1 forward, using (-Y + 1) / 2 makes full forward (Y=-1) equal to 1.
const normalizedValue = (-joystickVertical + 1) / 2;
// 2. Linearly interpolate between min and max factors
this.teleportDistanceFactor = this.minTeleportDistanceFactor + normalizedValue * (this.maxTeleportDistanceFactor - this.minTeleportDistanceFactor);
// Optional: Apply a small deadzone to prevent accidental changes when the stick is centered
const deadzone = 0.05;
if (Math.abs(joystickVertical) < deadzone) {
// If centered, reset to the default factor (e.g., the midpoint of your min/max range)
this.teleportDistanceFactor = (this.minTeleportDistanceFactor + this.maxTeleportDistanceFactor) / 2;
if (joystickVertical !== undefined) {
const normalizedValue = (-joystickVertical + 1) / 2;
this.teleportDistanceFactor = this.minTeleportDistanceFactor + normalizedValue * (this.maxTeleportDistanceFactor - this.minTeleportDistanceFactor);
const deadzone = 0.05;
if (Math.abs(joystickVertical) < deadzone) {
this.teleportDistanceFactor = (this.minTeleportDistanceFactor + this.maxTeleportDistanceFactor) / 2;
}
}
}
// console.log(`Normalized: ${normalizedValue.toFixed(2)}, Factor: ${this.teleportDistanceFactor.toFixed(2)}`);
// --- Right Controller (Content Interaction) ---
const rightGamepad = this.vrGamepads[0];
if (rightGamepad && this.attachedItem && this.attachedItem.content) {
const joystickVertical = rightGamepad.axes[3]; // Y-axis of the thumbstick
const deadzone = 0.5; // Use a larger deadzone to prevent accidental scrolling
if (joystickVertical < -deadzone) { // Pushed Up
if (typeof this.attachedItem.content.scrollUp === 'function') {
this.attachedItem.content.scrollUp();
}
} else if (joystickVertical > deadzone) { // Pushed Down
if (typeof this.attachedItem.content.scrollDown === 'function') {
this.attachedItem.content.scrollDown();
}
}
}
}
@ -453,14 +461,13 @@ export class Player {
_checkForInteractableItems() {
const ray = new THREE.Raycaster();
let isVR = this.vrControllers[0] && this.vrControllers[0].visible;
let isVR = this.renderer.xr.isPresenting && this.vrControllers[0] && this.vrControllers[0].visible;
if (isVR) {
// Use right controller for interaction ray
const controller = this.vrControllers[0];
const controllerMatrix = controller.matrixWorld;
ray.ray.origin.setFromMatrixPosition(controllerMatrix);
ray.ray.direction.set(0, 0, -1).applyMatrix4(new THREE.Matrix4().extractRotation(controllerMatrix));
controller.getWorldPosition(ray.ray.origin);
ray.ray.direction.set(0, 0, -1).applyQuaternion(controller.getWorldQuaternion(new THREE.Quaternion()));
} else {
// Use camera for desktop interaction ray
ray.setFromCamera({ x: 0, y: 0 }, this.camera);
@ -472,6 +479,12 @@ export class Player {
const intersects = ray.intersectObjects(itemObj, true);
// Update ray visualization
const controllerRay = this.vrControllers[0]?.getObjectByName('controller-ray');
if (controllerRay) {
controllerRay.visible = isVR;
}
if (intersects.length > 0) {
let intersectedObject = intersects[0].object;
@ -483,7 +496,7 @@ export class Player {
// Find the item that corresponds to this root object
const foundItem = nearbyItems.find(item => item.object === rootObject);
if (foundItem) {
if (this.currentIntItem !== foundItem) {
// Optional: Add some visual feedback for the newly highlighted item
@ -563,14 +576,15 @@ export class Player {
}
if (this.enableInput) {
if (this.attachedItem) {
if (this.attachedItem && !this.renderer.xr.isPresenting) { // Only lock camera for desktop
this._lockCameraForAttachedItem();
} else if (!this.renderer.xr.isPresenting) { // Only update movement if not in VR
this._updatePlayerMovement(delta);
}
this._checkForInteractableItems();
}
}
this._checkForInteractableItems();
this.input.mouseDelta.x = 0;
this.input.mouseDelta.y = 0;
}

Loading…
Cancel
Save