🚀 Auto-deploy: melhoria no snap e medição AR em 28/05/2026 21:16:09
This commit is contained in:
+68
-15
@@ -26,6 +26,12 @@ import { VisibilityApplier } from '@/components/three/ModelViewer';
|
||||
import { registerModelLocalGroup, unregisterModelLocalGroup } from '@/lib/modelTransforms';
|
||||
import { parseIFCtoThree } from '@/lib/convertIFC';
|
||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
||||
import {
|
||||
xrCalibration,
|
||||
pushXRModelFaceNormal,
|
||||
computeXRCalibrationQuaternion,
|
||||
subscribeXRCalibration,
|
||||
} from '@/components/three/xrCalibrationBus';
|
||||
|
||||
// --- Diagnóstico XR ---
|
||||
console.log('[XR] Inicializando store...');
|
||||
@@ -100,8 +106,15 @@ function XRModel({ sceneModel }: { sceneModel: import('@/stores/useModelStore').
|
||||
}, [sceneModel.url, sceneModel.fileName]);
|
||||
|
||||
const ref = useRef<THREE.Group>(null);
|
||||
const calGroupRef = useRef<THREE.Group>(null);
|
||||
const localFrameRef = useRef<THREE.Group>(null);
|
||||
|
||||
// Escuta mudanças de calibração para re-renderizar no AR
|
||||
const [, setCalTick] = useState(0);
|
||||
useEffect(() => subscribeXRCalibration(() => setCalTick(t => t + 1)), []);
|
||||
|
||||
useEffect(() => {
|
||||
const g = ref.current;
|
||||
const g = localFrameRef.current;
|
||||
if (!g) return;
|
||||
registerModelLocalGroup(sceneModel.id, g);
|
||||
return () => unregisterModelLocalGroup(sceneModel.id, g);
|
||||
@@ -201,24 +214,64 @@ function XRModel({ sceneModel }: { sceneModel: import('@/stores/useModelStore').
|
||||
const scaleRatio = useModelStore((st) => st.scaleRatio);
|
||||
const renderFactor = scaleRatio?.factor ?? 1;
|
||||
|
||||
const calQuatArr = sceneModel.calibrationQuat;
|
||||
const isCalibratingThis = xrCalibration.modelId === sceneModel.id && xrCalibration.step !== 'idle' && xrCalibration.step !== 'done';
|
||||
const calQuat = useMemo(() => {
|
||||
if (isCalibratingThis) return new THREE.Quaternion();
|
||||
if (!calQuatArr) return new THREE.Quaternion();
|
||||
return new THREE.Quaternion(calQuatArr[0], calQuatArr[1], calQuatArr[2], calQuatArr[3]);
|
||||
}, [calQuatArr, isCalibratingThis]);
|
||||
|
||||
if (!sceneModel.visible) return null;
|
||||
if (!scene) return null;
|
||||
|
||||
return (
|
||||
<group scale={[renderFactor, renderFactor, renderFactor]}>
|
||||
<group
|
||||
ref={ref}
|
||||
userData={{ modelId: sceneModel.id }}
|
||||
position={[
|
||||
-modelInfo.center.x + fineTuning.posX,
|
||||
-modelInfo.center.y + fineTuning.posY,
|
||||
-modelInfo.center.z + fineTuning.posZ,
|
||||
]}
|
||||
rotation={[rotXRad, rotYRad, rotZRad]}
|
||||
scale={[s, s, s]}
|
||||
>
|
||||
<primitive object={scene} />
|
||||
<XRLocalModelMeasurements modelId={sceneModel.id} />
|
||||
<group
|
||||
scale={[renderFactor, renderFactor, renderFactor]}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
// Calibração XR: captura normal da face do modelo em espaço de mundo.
|
||||
if (
|
||||
xrCalibration.modelId === sceneModel.id &&
|
||||
(xrCalibration.step === 'await-model-1' || xrCalibration.step === 'await-model-2' || xrCalibration.step === 'await-model-3') &&
|
||||
e.face && e.object
|
||||
) {
|
||||
const n = e.face.normal.clone();
|
||||
const nm = new THREE.Matrix3().getNormalMatrix(e.object.matrixWorld);
|
||||
n.applyMatrix3(nm).normalize();
|
||||
const wq = new THREE.Quaternion();
|
||||
(calGroupRef.current ?? e.object).getWorldQuaternion(wq);
|
||||
pushXRModelFaceNormal(n, wq);
|
||||
|
||||
// Aplica/atualiza calibração se tivermos >= 2 pares
|
||||
if (xrCalibration.pairs.length >= 2) {
|
||||
const q = computeXRCalibrationQuaternion(xrCalibration.pairs);
|
||||
if (q) {
|
||||
useModelStore.getState().setCalibration(sceneModel.id, [q.x, q.y, q.z, q.w]);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}}
|
||||
>
|
||||
{/* Translação */}
|
||||
<group position={[fineTuning.posX, fineTuning.posY, fineTuning.posZ]}>
|
||||
{/* Rotação e escala em volta do centro geométrico */}
|
||||
<group
|
||||
ref={ref}
|
||||
rotation={[rotXRad, rotYRad, rotZRad]}
|
||||
scale={[s, s, s]}
|
||||
>
|
||||
{/* Rotação de calibração */}
|
||||
<group ref={calGroupRef} quaternion={calQuat}>
|
||||
{/* Sistema local do modelo com pivot no centro */}
|
||||
<group ref={localFrameRef} position={[-modelInfo.center.x, -modelInfo.center.y, -modelInfo.center.z]} userData={{ modelId: sceneModel.id }}>
|
||||
<primitive object={scene} />
|
||||
<XRLocalModelMeasurements modelId={sceneModel.id} />
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user