From 6b0cc52c19f91414096ca633d2b2a7a9fd1c583d Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 11:44:46 +0000 Subject: [PATCH] Changes Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com> --- src/components/three/XRHudInWorld.tsx | 55 +++++++++++++++++++-------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/src/components/three/XRHudInWorld.tsx b/src/components/three/XRHudInWorld.tsx index 51a7890..9f4a33e 100644 --- a/src/components/three/XRHudInWorld.tsx +++ b/src/components/three/XRHudInWorld.tsx @@ -86,24 +86,47 @@ export function XRHudInWorld(props: XRHudInWorldProps) { // • If unpinned → continuously follow head with damping. // • On (re)anchor request → snap target once and stop. if (panelRef.current && open) { - const fwd = new THREE.Vector3(0, -0.05, -0.7).applyQuaternion(camera.quaternion); - const wantPos = new THREE.Vector3().copy(camera.position).add(fwd); - const euler = new THREE.Euler().setFromQuaternion(camera.quaternion, 'YXZ'); - const wantQuat = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, euler.y, 0, 'YXZ')); + // Drag mode → panel rigidly follows right controller using captured offset. + if (dragging) { + const ctrlObj = rightCtrl?.object; + if (ctrlObj) { + ctrlObj.updateMatrixWorld(); + const cPos = new THREE.Vector3().setFromMatrixPosition(ctrlObj.matrixWorld); + const cQuat = new THREE.Quaternion().setFromRotationMatrix(ctrlObj.matrixWorld); + if (!dragInitialized.current) { + // Capture current panel pose relative to controller + const invQ = cQuat.clone().invert(); + dragOffsetPos.current + .copy(panelRef.current.position).sub(cPos).applyQuaternion(invQ); + dragOffsetQuat.current.copy(invQ).multiply(panelRef.current.quaternion); + dragInitialized.current = true; + } + const newPos = dragOffsetPos.current.clone().applyQuaternion(cQuat).add(cPos); + const newQuat = cQuat.clone().multiply(dragOffsetQuat.current); + panelRef.current.position.copy(newPos); + panelRef.current.quaternion.copy(newQuat); + } + } else { + if (dragInitialized.current) dragInitialized.current = false; + const fwd = new THREE.Vector3(0, -0.05, -0.7).applyQuaternion(camera.quaternion); + const wantPos = new THREE.Vector3().copy(camera.position).add(fwd); + const euler = new THREE.Euler().setFromQuaternion(camera.quaternion, 'YXZ'); + const wantQuat = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, euler.y, 0, 'YXZ')); - if (reanchorRequested.current) { - targetPos.current.copy(wantPos); - targetQuat.current.copy(wantQuat); - panelRef.current.position.copy(wantPos); - panelRef.current.quaternion.copy(wantQuat); - reanchorRequested.current = false; - } else if (!pinned) { - targetPos.current.copy(wantPos); - targetQuat.current.copy(wantQuat); - panelRef.current.position.lerp(targetPos.current, 0.12); - panelRef.current.quaternion.slerp(targetQuat.current, 0.18); + if (reanchorRequested.current) { + targetPos.current.copy(wantPos); + targetQuat.current.copy(wantQuat); + panelRef.current.position.copy(wantPos); + panelRef.current.quaternion.copy(wantQuat); + reanchorRequested.current = false; + } else if (!pinned) { + targetPos.current.copy(wantPos); + targetQuat.current.copy(wantQuat); + panelRef.current.position.lerp(targetPos.current, 0.12); + panelRef.current.quaternion.slerp(targetQuat.current, 0.18); + } + // pinned + already anchored → leave panel where it is. } - // pinned + already anchored → leave panel where it is. } // Wrist toggle follows left controller