From e69ad01e700e80fa959dfee08cd556ca0d777ffd Mon Sep 17 00:00:00 2001 From: skylar Date: Sun, 1 Nov 2026 05:43:24 -0800 Subject: Yesod: self-hosted WebXR rooms Start a room in a world and hang out in VR from the headset's browser: A-Frame + Networked-A-Frame over EasyRTC, with a coturn relay that can hide everyone's IP address. Ships with the Campfire, Temple, Cabin, Balcony and Test room worlds. Co-Authored-By: Claude Opus 5.5 --- public/js/components/hand-tilt.js | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 public/js/components/hand-tilt.js (limited to 'public/js/components/hand-tilt.js') diff --git a/public/js/components/hand-tilt.js b/public/js/components/hand-tilt.js new file mode 100644 index 0000000..d874fc8 --- /dev/null +++ b/public/js/components/hand-tilt.js @@ -0,0 +1,37 @@ +/* global AFRAME, THREE */ +// Tips a tracked hand down about its fist. The controller's grip pose points +// noticeably upward, so hands, whatever they hold, and the hands everyone else +// sees all angle up. Turning the pose itself, right after it's read from the +// headset, carries the change to all of them; where the hand is stays put. +(function () { + const X = new THREE.Vector3(1, 0, 0); + + AFRAME.registerComponent('hand-tilt', { + schema: { + degrees: { default: -30 }, // negative tips the fingers down + }, + + init() { + this.tilt = new THREE.Quaternion(); + this.update(); + }, + + update() { + this.tilt.setFromAxisAngle(X, THREE.MathUtils.degToRad(this.data.degrees)); + }, + + // tracked-controls arrives when a controller connects (and again if it's + // swapped), so wrap whichever one is there. + tick() { + const tracked = this.el.components['tracked-controls']; + if (!tracked || tracked.tiltedBy === this) return; + const updatePose = tracked.updatePose; + const tilt = this.tilt; + tracked.updatePose = function () { + updatePose.call(this); + if (this.pose) this.el.object3D.quaternion.multiply(tilt); + }; + tracked.tiltedBy = this; + }, + }); +})(); -- cgit v1.2.3