🚀 Auto-deploy: melhoria no snap e medição AR em 24/05/2026 13:56:02
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useRef, useMemo, useState, useCallback } from 'react';
|
||||
import { useFrame, useThree } from '@react-three/fiber';
|
||||
import { Grid, Billboard } from '@react-three/drei';
|
||||
import { Grid, Billboard, Sky } from '@react-three/drei';
|
||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
||||
import * as THREE from 'three';
|
||||
import { useModelStore, type SceneModel } from '@/stores/useModelStore';
|
||||
@@ -141,20 +141,39 @@ export function XRModel({ sceneModel }: { sceneModel: SceneModel }) {
|
||||
const s = fineTuning.scale ?? 1;
|
||||
const scaleRatio = useModelStore((st) => st.scaleRatio);
|
||||
const renderFactor = scaleRatio?.factor ?? 1;
|
||||
const xrScaleMode = useModelStore((st) => st.xrScaleMode);
|
||||
const isTabletop = xrScaleMode === 'tabletop';
|
||||
|
||||
if (!sceneModel.visible) return null;
|
||||
if (!scene) return null;
|
||||
|
||||
// Escala final: se for tabletop, escala de maquete proporcional ao tamanho do objeto
|
||||
const maxDim = Math.max(modelInfo.size.x, modelInfo.size.y, modelInfo.size.z);
|
||||
const finalScaleFactor = isTabletop
|
||||
? (maxDim > 0 ? 0.5 / maxDim : 0.05)
|
||||
: renderFactor;
|
||||
|
||||
// Posição local: no tabletop, eleva-se o modelo para que sua base coincida com Y=0 da origem do pai (topo da mesa)
|
||||
const localPos: [number, number, number] = isTabletop
|
||||
? [
|
||||
-modelInfo.center.x + fineTuning.posX,
|
||||
(-modelInfo.center.y + (modelInfo.size.y / 2)) + fineTuning.posY,
|
||||
-modelInfo.center.z + fineTuning.posZ,
|
||||
]
|
||||
: [
|
||||
-modelInfo.center.x + fineTuning.posX,
|
||||
-modelInfo.center.y + fineTuning.posY,
|
||||
-modelInfo.center.z + fineTuning.posZ,
|
||||
];
|
||||
|
||||
const parentPos: [number, number, number] = isTabletop ? [0, 0.85, 0] : [0, 0, 0];
|
||||
|
||||
return (
|
||||
<group scale={[renderFactor, renderFactor, renderFactor]}>
|
||||
<group scale={[finalScaleFactor, finalScaleFactor, finalScaleFactor]} position={parentPos}>
|
||||
<group
|
||||
ref={ref}
|
||||
userData={{ modelId: sceneModel.id }}
|
||||
position={[
|
||||
-modelInfo.center.x + fineTuning.posX,
|
||||
-modelInfo.center.y + fineTuning.posY,
|
||||
-modelInfo.center.z + fineTuning.posZ,
|
||||
]}
|
||||
position={localPos}
|
||||
rotation={[rotXRad, rotYRad, rotZRad]}
|
||||
scale={[s, s, s]}
|
||||
>
|
||||
@@ -541,3 +560,58 @@ export function XRGridAutoFollower() {
|
||||
}, [models, scene]);
|
||||
return null;
|
||||
}
|
||||
|
||||
export function XREnvironmentSelector() {
|
||||
const xrEnvironment = useModelStore((s) => s.xrEnvironment);
|
||||
|
||||
if (xrEnvironment === 'passthrough') return null;
|
||||
|
||||
return (
|
||||
<group>
|
||||
{/* Luzes adicionais para ambientes imersivos virtuais */}
|
||||
<ambientLight intensity={0.5} />
|
||||
<directionalLight position={[5, 10, 5]} intensity={1.0} castShadow />
|
||||
|
||||
{/* Cenário Escritório */}
|
||||
{xrEnvironment === 'office' && (
|
||||
<group>
|
||||
{/* Carpete do escritório */}
|
||||
<mesh rotation={[-Math.PI / 2, 0, 0]} receiveShadow>
|
||||
<planeGeometry args={[50, 50]} />
|
||||
<meshStandardMaterial color="#263238" roughness={0.95} />
|
||||
</mesh>
|
||||
|
||||
{/* Tampo da Mesa */}
|
||||
<mesh position={[0, 0.825, 0]} receiveShadow castShadow>
|
||||
<cylinderGeometry args={[0.7, 0.7, 0.05, 32]} />
|
||||
<meshStandardMaterial color="#3e2723" roughness={0.6} metalness={0.1} />
|
||||
</mesh>
|
||||
|
||||
{/* Perna da Mesa */}
|
||||
<mesh position={[0, 0.4, 0]} castShadow>
|
||||
<cylinderGeometry args={[0.08, 0.08, 0.8, 16]} />
|
||||
<meshStandardMaterial color="#333333" roughness={0.4} metalness={0.8} />
|
||||
</mesh>
|
||||
|
||||
{/* Base da perna */}
|
||||
<mesh position={[0, 0.01, 0]} castShadow>
|
||||
<cylinderGeometry args={[0.3, 0.3, 0.02, 24]} />
|
||||
<meshStandardMaterial color="#222222" roughness={0.3} metalness={0.8} />
|
||||
</mesh>
|
||||
</group>
|
||||
)}
|
||||
|
||||
{/* Cenário Campo Aberto */}
|
||||
{xrEnvironment === 'field' && (
|
||||
<group>
|
||||
<Sky distance={450000} sunPosition={[10, 5, 10]} inclination={0} azimuth={0.25} />
|
||||
{/* Chão de grama */}
|
||||
<mesh rotation={[-Math.PI / 2, 0, 0]} receiveShadow>
|
||||
<planeGeometry args={[1000, 1000]} />
|
||||
<meshStandardMaterial color="#1b5e20" roughness={0.9} />
|
||||
</mesh>
|
||||
</group>
|
||||
)}
|
||||
</group>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user