Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-05-09 13:38:57 +00:00
parent eba810b22e
commit 0aa31ed6ad
+35 -9
View File
@@ -12,6 +12,7 @@ import { generateMarkerDownloadURL } from '@/lib/trackingMarker';
import { XRHud } from '@/components/XRHud'; import { XRHud } from '@/components/XRHud';
import { findNearestVertex } from '@/components/three/SmartMeasure'; import { findNearestVertex } from '@/components/three/SmartMeasure';
import { XRHitTestPlacement } from '@/components/three/XRHitTestPlacement'; import { XRHitTestPlacement } from '@/components/three/XRHitTestPlacement';
import { XRGrabbable } from '@/components/three/XRGrabbable';
// --- Diagnóstico XR --- // --- Diagnóstico XR ---
console.log('[XR] Inicializando store...'); console.log('[XR] Inicializando store...');
@@ -111,6 +112,7 @@ function XRModel({ url }: { url: string }) {
const rotXRad = (fineTuning.rotX * Math.PI) / 180; const rotXRad = (fineTuning.rotX * Math.PI) / 180;
const rotYRad = (fineTuning.rotY * Math.PI) / 180; const rotYRad = (fineTuning.rotY * Math.PI) / 180;
const rotZRad = (fineTuning.rotZ * Math.PI) / 180; const rotZRad = (fineTuning.rotZ * Math.PI) / 180;
const s = fineTuning.scale ?? 1;
return ( return (
<group <group
@@ -121,6 +123,7 @@ function XRModel({ url }: { url: string }) {
-modelInfo.center.z + fineTuning.posZ, -modelInfo.center.z + fineTuning.posZ,
]} ]}
rotation={[rotXRad, rotYRad, rotZRad]} rotation={[rotXRad, rotYRad, rotZRad]}
scale={[s, s, s]}
> >
<primitive object={scene} /> <primitive object={scene} />
</group> </group>
@@ -128,6 +131,9 @@ function XRModel({ url }: { url: string }) {
} }
// ─── ControllerFineTuning ────────────────────────────── // ─── ControllerFineTuning ──────────────────────────────
// Joystick for slow numeric adjustments. Disabled while any grip is held
// (grab takes priority). Trigger pressure modulates speed: light = fine,
// strong = fast. Standard VR mapping: left=lateral/forward, right=rotY/height.
function ControllerFineTuning({ freeMove }: { freeMove: boolean }) { function ControllerFineTuning({ freeMove }: { freeMove: boolean }) {
const { setFineTuning } = useModelStore(); const { setFineTuning } = useModelStore();
const session = useXR((s) => s.session); const session = useXR((s) => s.session);
@@ -139,37 +145,57 @@ function ControllerFineTuning({ freeMove }: { freeMove: boolean }) {
let leftAxes: number[] | null = null; let leftAxes: number[] | null = null;
let rightAxes: number[] | null = null; let rightAxes: number[] | null = null;
let leftTrig = 0;
let rightTrig = 0;
let gripHeld = false; let gripHeld = false;
let anyGripHeld = false;
for (const source of inputSources) { for (const source of inputSources) {
const gp = source.gamepad; const gp = source.gamepad;
if (!gp) continue; if (!gp) continue;
const gripButton = gp.buttons[2]; const gripBtn = gp.buttons[2];
if (gripButton && gripButton.pressed) gripHeld = true; const trigBtn = gp.buttons[1];
const gripVal = gripBtn ? (gripBtn.value || (gripBtn.pressed ? 1 : 0)) : 0;
if (gripBtn?.pressed) gripHeld = true;
if (gripVal > 0.3) anyGripHeld = true; // matches grab hysteresis OFF
const trigVal = trigBtn ? (trigBtn.value || (trigBtn.pressed ? 1 : 0)) : 0;
if (source.handedness === 'left' && gp.axes.length >= 4) { if (source.handedness === 'left' && gp.axes.length >= 4) {
leftAxes = [gp.axes[2], gp.axes[3]]; leftAxes = [gp.axes[2], gp.axes[3]];
leftTrig = trigVal;
} }
if (source.handedness === 'right' && gp.axes.length >= 4) { if (source.handedness === 'right' && gp.axes.length >= 4) {
rightAxes = [gp.axes[2], gp.axes[3]]; rightAxes = [gp.axes[2], gp.axes[3]];
rightTrig = trigVal;
} }
} }
// In freeMove mode, joystick always moves. Otherwise requires grip. // Grab takes priority — joystick is disabled while grabbing
if (anyGripHeld) return;
// In freeMove mode, joystick always moves. Otherwise requires grip — but
// grip is reserved for grab now, so freeMove=false essentially disables.
if (!freeMove && !gripHeld) return; if (!freeMove && !gripHeld) return;
const posStep = 0.001; const baseStep = 0.001;
const rotStep = 0.1; const baseRot = 0.1;
const deadzone = 0.15; const deadzone = 0.15;
// Trigger modulation: 0 → 0.3×, 1 → 3×
const speedL = 0.3 + leftTrig * 2.7;
const speedR = 0.3 + rightTrig * 2.7;
// Quadratic acceleration on thumbstick value
const curve = (v: number) => Math.sign(v) * v * v;
const modelStore = useModelStore.getState(); const modelStore = useModelStore.getState();
const ft = { ...modelStore.fineTuning }; const ft = { ...modelStore.fineTuning };
if (leftAxes) { if (leftAxes) {
if (Math.abs(leftAxes[0]) > deadzone) ft.posX += leftAxes[0] * posStep; // Left: X (horizontal) / Z forward-back (vertical, up = forward = -Z)
if (Math.abs(leftAxes[1]) > deadzone) ft.posY -= leftAxes[1] * posStep; if (Math.abs(leftAxes[0]) > deadzone) ft.posX += curve(leftAxes[0]) * baseStep * speedL;
if (Math.abs(leftAxes[1]) > deadzone) ft.posZ += curve(leftAxes[1]) * baseStep * speedL;
} }
if (rightAxes) { if (rightAxes) {
if (Math.abs(rightAxes[1]) > deadzone) ft.posZ += rightAxes[1] * posStep; // Right: rotY (horizontal) / Y height (vertical, up = up)
if (Math.abs(rightAxes[0]) > deadzone) ft.rotY += rightAxes[0] * rotStep; if (Math.abs(rightAxes[0]) > deadzone) ft.rotY += curve(rightAxes[0]) * baseRot * speedR;
if (Math.abs(rightAxes[1]) > deadzone) ft.posY -= curve(rightAxes[1]) * baseStep * speedR;
} }
setFineTuning(ft); setFineTuning(ft);