feat(viewer3d): solido translucido atenuado para pecas nao apontadas e remocao de aramado
This commit is contained in:
@@ -50,7 +50,6 @@ export const ModelViewer3D: React.FC<ModelViewer3DProps> = ({
|
|||||||
const [opacity, setOpacity] = useState<number>(100);
|
const [opacity, setOpacity] = useState<number>(100);
|
||||||
const [showGrid, setShowGrid] = useState<boolean>(true);
|
const [showGrid, setShowGrid] = useState<boolean>(true);
|
||||||
const [isOrthographic, setIsOrthographic] = useState<boolean>(false);
|
const [isOrthographic, setIsOrthographic] = useState<boolean>(false);
|
||||||
const [isWireframe, setIsWireframe] = useState<boolean>(false);
|
|
||||||
const [colorMode, setColorMode] = useState<'description' | 'production'>('production');
|
const [colorMode, setColorMode] = useState<'description' | 'production'>('production');
|
||||||
const [selectedProcess, setSelectedProcess] = useState<string>('all');
|
const [selectedProcess, setSelectedProcess] = useState<string>('all');
|
||||||
|
|
||||||
@@ -429,50 +428,32 @@ export const ModelViewer3D: React.FC<ModelViewer3DProps> = ({
|
|||||||
else isPointedInThisProcess = Boolean(procPointedMap[targetProcKey] > 0 || procsDone.includes(targetProcKey));
|
else isPointedInThisProcess = Boolean(procPointedMap[targetProcKey] > 0 || procsDone.includes(targetProcKey));
|
||||||
|
|
||||||
if (isPointedInThisProcess) {
|
if (isPointedInThisProcess) {
|
||||||
// SÓLIDO COM A COR DO PROCESSO SELECIONADO
|
// SÓLIDO COM A COR DO PROCESSO SELECIONADO (OPACO 100%)
|
||||||
mesh.material = new THREE.MeshStandardMaterial({
|
mesh.material = new THREE.MeshStandardMaterial({
|
||||||
color: new THREE.Color(targetColorHex),
|
color: new THREE.Color(targetColorHex),
|
||||||
metalness: 0.35,
|
metalness: 0.35,
|
||||||
roughness: 0.45,
|
roughness: 0.45,
|
||||||
transparent: opacity < 100,
|
transparent: opacity < 100,
|
||||||
opacity: opacity / 100,
|
opacity: opacity / 100,
|
||||||
|
depthWrite: true,
|
||||||
side: THREE.DoubleSide,
|
side: THREE.DoubleSide,
|
||||||
});
|
});
|
||||||
if (mesh.userData.edgesLine) {
|
if (mesh.userData.edgesLine) {
|
||||||
mesh.userData.edgesLine.visible = false;
|
mesh.userData.edgesLine.visible = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ARAMADO FANTASMA CINZA CLARO ULTRA-SUAVE (5% de opacidade)
|
// SÓLIDO TRANSLÚCIDO ATENUADO (Ghost Solid volumétrico a 8% - sem linhas de aramado)
|
||||||
if (!mesh.userData.edgesLine) {
|
mesh.material = new THREE.MeshStandardMaterial({
|
||||||
const edgesGeo = new THREE.EdgesGeometry(mesh.geometry, 24);
|
color: new THREE.Color('#94a3b8'), // Cinza industrial translúcido
|
||||||
const lineMat = new THREE.LineBasicMaterial({
|
metalness: 0.1,
|
||||||
color: 0x94a3b8, // Cinza claro industrial
|
roughness: 0.8,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
opacity: 0.05, // 5% de opacidade
|
opacity: 0.08, // 8% de opacidade volumétrica suave
|
||||||
});
|
depthWrite: false,
|
||||||
const edgesLine = new THREE.LineSegments(edgesGeo, lineMat);
|
side: THREE.DoubleSide,
|
||||||
mesh.userData.edgesLine = edgesLine;
|
});
|
||||||
mesh.add(edgesLine);
|
if (mesh.userData.edgesLine) {
|
||||||
} else {
|
mesh.userData.edgesLine.visible = false;
|
||||||
if (mesh.userData.edgesLine.material) {
|
|
||||||
mesh.userData.edgesLine.material.color.set(0x94a3b8);
|
|
||||||
mesh.userData.edgesLine.material.transparent = true;
|
|
||||||
mesh.userData.edgesLine.material.opacity = 0.05;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mesh.userData.edgesLine.visible = true;
|
|
||||||
|
|
||||||
// Mantém material ativo para Raycaster mas 100% translúcido visualmente
|
|
||||||
if (Array.isArray(mesh.material)) {
|
|
||||||
mesh.material.forEach((m) => {
|
|
||||||
m.visible = true;
|
|
||||||
m.transparent = true;
|
|
||||||
m.opacity = 0.001;
|
|
||||||
});
|
|
||||||
} else if (mesh.material) {
|
|
||||||
mesh.material.visible = true;
|
|
||||||
mesh.material.transparent = true;
|
|
||||||
mesh.material.opacity = 0.001;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -502,6 +483,7 @@ export const ModelViewer3D: React.FC<ModelViewer3DProps> = ({
|
|||||||
roughness: 0.45,
|
roughness: 0.45,
|
||||||
transparent: opacity < 100,
|
transparent: opacity < 100,
|
||||||
opacity: opacity / 100,
|
opacity: opacity / 100,
|
||||||
|
depthWrite: true,
|
||||||
side: THREE.DoubleSide,
|
side: THREE.DoubleSide,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -509,37 +491,19 @@ export const ModelViewer3D: React.FC<ModelViewer3DProps> = ({
|
|||||||
mesh.userData.edgesLine.visible = false;
|
mesh.userData.edgesLine.visible = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// A PEÇA NÃO TEM NENHUM APONTAMENTO: ARAMADO FANTASMA CINZA CLARO A 5% (ATENUADA)
|
// A PEÇA NÃO TEM NENHUM APONTAMENTO: SÓLIDO TRANSLÚCIDO ATENUADO (Ghost Solid a 8%)
|
||||||
if (!mesh.userData.edgesLine) {
|
mesh.material = new THREE.MeshStandardMaterial({
|
||||||
const edgesGeo = new THREE.EdgesGeometry(mesh.geometry, 24);
|
color: new THREE.Color('#94a3b8'),
|
||||||
const lineMat = new THREE.LineBasicMaterial({
|
metalness: 0.1,
|
||||||
color: 0x94a3b8,
|
roughness: 0.8,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
opacity: 0.05,
|
opacity: 0.08,
|
||||||
});
|
depthWrite: false,
|
||||||
const edgesLine = new THREE.LineSegments(edgesGeo, lineMat);
|
side: THREE.DoubleSide,
|
||||||
mesh.userData.edgesLine = edgesLine;
|
});
|
||||||
mesh.add(edgesLine);
|
|
||||||
} else {
|
|
||||||
if (mesh.userData.edgesLine.material) {
|
|
||||||
mesh.userData.edgesLine.material.color.set(0x94a3b8);
|
|
||||||
mesh.userData.edgesLine.material.transparent = true;
|
|
||||||
mesh.userData.edgesLine.material.opacity = 0.05;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mesh.userData.edgesLine.visible = true;
|
|
||||||
|
|
||||||
// Material ativo para Raycaster mas translúcido
|
if (mesh.userData.edgesLine) {
|
||||||
if (Array.isArray(mesh.material)) {
|
mesh.userData.edgesLine.visible = false;
|
||||||
mesh.material.forEach((m) => {
|
|
||||||
m.visible = true;
|
|
||||||
m.transparent = true;
|
|
||||||
m.opacity = 0.001;
|
|
||||||
});
|
|
||||||
} else if (mesh.material) {
|
|
||||||
mesh.material.visible = true;
|
|
||||||
mesh.material.transparent = true;
|
|
||||||
mesh.material.opacity = 0.001;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -550,6 +514,7 @@ export const ModelViewer3D: React.FC<ModelViewer3DProps> = ({
|
|||||||
roughness: 0.65,
|
roughness: 0.65,
|
||||||
transparent: opacity < 100,
|
transparent: opacity < 100,
|
||||||
opacity: opacity / 100,
|
opacity: opacity / 100,
|
||||||
|
depthWrite: true,
|
||||||
side: THREE.DoubleSide,
|
side: THREE.DoubleSide,
|
||||||
});
|
});
|
||||||
if (mesh.userData.edgesLine) {
|
if (mesh.userData.edgesLine) {
|
||||||
@@ -557,33 +522,6 @@ export const ModelViewer3D: React.FC<ModelViewer3DProps> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Controle de Aramado Geral (Botão Sólido / Aramado)
|
|
||||||
if (isWireframe) {
|
|
||||||
if (!mesh.userData.edgesLine) {
|
|
||||||
const edgesGeo = new THREE.EdgesGeometry(mesh.geometry, 24);
|
|
||||||
const lineMat = new THREE.LineBasicMaterial({
|
|
||||||
color: 0x94a3b8, // Cinza claro industrial idêntico às peças não apontadas
|
|
||||||
transparent: true,
|
|
||||||
opacity: 0.85,
|
|
||||||
});
|
|
||||||
const edgesLine = new THREE.LineSegments(edgesGeo, lineMat);
|
|
||||||
mesh.userData.edgesLine = edgesLine;
|
|
||||||
mesh.add(edgesLine);
|
|
||||||
} else {
|
|
||||||
if (mesh.userData.edgesLine.material) {
|
|
||||||
mesh.userData.edgesLine.material.color.set(0x94a3b8);
|
|
||||||
mesh.userData.edgesLine.material.opacity = 0.85;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mesh.userData.edgesLine.visible = true;
|
|
||||||
|
|
||||||
if (Array.isArray(mesh.material)) {
|
|
||||||
mesh.material.forEach((m) => { m.visible = false; });
|
|
||||||
} else if (mesh.material) {
|
|
||||||
mesh.material.visible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -605,7 +543,7 @@ export const ModelViewer3D: React.FC<ModelViewer3DProps> = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [modelData, colorMode, productionData, selectedPhase, selectedOF, opacity, isWireframe, selectedProcess]);
|
}, [modelData, colorMode, productionData, selectedPhase, selectedOF, opacity, selectedProcess]);
|
||||||
|
|
||||||
// Camera Toggle (Ortogonal / Perspectiva)
|
// Camera Toggle (Ortogonal / Perspectiva)
|
||||||
const handleToggleCamera = useCallback(() => {
|
const handleToggleCamera = useCallback(() => {
|
||||||
@@ -815,8 +753,6 @@ export const ModelViewer3D: React.FC<ModelViewer3DProps> = ({
|
|||||||
}}
|
}}
|
||||||
isOrthographic={isOrthographic}
|
isOrthographic={isOrthographic}
|
||||||
onToggleCamera={handleToggleCamera}
|
onToggleCamera={handleToggleCamera}
|
||||||
isWireframe={isWireframe}
|
|
||||||
onToggleWireframe={() => setIsWireframe(!isWireframe)}
|
|
||||||
colorMode={colorMode}
|
colorMode={colorMode}
|
||||||
onColorModeChange={setColorMode}
|
onColorModeChange={setColorMode}
|
||||||
selectedProcess={selectedProcess}
|
selectedProcess={selectedProcess}
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ interface Viewer3DSidebarProps {
|
|||||||
onToggleGrid: () => void;
|
onToggleGrid: () => void;
|
||||||
isOrthographic: boolean;
|
isOrthographic: boolean;
|
||||||
onToggleCamera: () => void;
|
onToggleCamera: () => void;
|
||||||
isWireframe: boolean;
|
|
||||||
onToggleWireframe: () => void;
|
|
||||||
colorMode: 'description' | 'production';
|
colorMode: 'description' | 'production';
|
||||||
onColorModeChange: (mode: 'description' | 'production') => void;
|
onColorModeChange: (mode: 'description' | 'production') => void;
|
||||||
selectedProcess?: string;
|
selectedProcess?: string;
|
||||||
@@ -52,8 +50,6 @@ export const Viewer3DSidebar: React.FC<Viewer3DSidebarProps> = ({
|
|||||||
onToggleGrid,
|
onToggleGrid,
|
||||||
isOrthographic,
|
isOrthographic,
|
||||||
onToggleCamera,
|
onToggleCamera,
|
||||||
isWireframe,
|
|
||||||
onToggleWireframe,
|
|
||||||
colorMode,
|
colorMode,
|
||||||
onColorModeChange,
|
onColorModeChange,
|
||||||
selectedProcess = 'all',
|
selectedProcess = 'all',
|
||||||
@@ -166,37 +162,24 @@ export const Viewer3DSidebar: React.FC<Viewer3DSidebarProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Grupo 3: Visibilidade & Grade */}
|
{/* Grupo 3: Ambiente & Grade */}
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
<label className="text-[11px] font-bold uppercase tracking-wider text-slate-600 dark:text-slate-400 flex items-center gap-1.5">
|
<label className="text-[11px] font-bold uppercase tracking-wider text-slate-600 dark:text-slate-400 flex items-center gap-1.5">
|
||||||
<GridIcon className="w-3.5 h-3.5 text-cyan-600 dark:text-cyan-400" />
|
<GridIcon className="w-3.5 h-3.5 text-cyan-600 dark:text-cyan-400" />
|
||||||
Ambiente & Estrutura
|
Ambiente & Piso
|
||||||
</label>
|
</label>
|
||||||
<div className="grid grid-cols-2 gap-1.5">
|
<div>
|
||||||
{/* Toggle Grid */}
|
{/* Toggle Grid */}
|
||||||
<button
|
<button
|
||||||
onClick={onToggleGrid}
|
onClick={onToggleGrid}
|
||||||
className={`flex items-center justify-center gap-1.5 px-2.5 py-2 rounded-xl text-xs font-semibold border transition-all ${
|
className={`w-full flex items-center justify-center gap-2 py-2 rounded-xl text-xs font-semibold border transition-all ${
|
||||||
showGrid
|
showGrid
|
||||||
? 'bg-cyan-50 dark:bg-cyan-950/40 text-cyan-800 dark:text-cyan-300 border-cyan-300 dark:border-cyan-800 shadow-sm'
|
? 'bg-cyan-50 dark:bg-cyan-950/40 text-cyan-800 dark:text-cyan-300 border-cyan-300 dark:border-cyan-800 shadow-sm'
|
||||||
: 'bg-white dark:bg-slate-900 text-slate-700 dark:text-slate-400 border-slate-200 dark:border-slate-800 hover:border-slate-300'
|
: 'bg-white dark:bg-slate-900 text-slate-700 dark:text-slate-400 border-slate-200 dark:border-slate-800 hover:border-slate-300'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<GridIcon className="w-3.5 h-3.5" />
|
<GridIcon className="w-3.5 h-3.5" />
|
||||||
<span>Grid: {showGrid ? 'LIGADO' : 'DESL'}</span>
|
<span>Grade de Piso: {showGrid ? 'LIGADO' : 'DESL'}</span>
|
||||||
</button>
|
|
||||||
|
|
||||||
{/* Sólido / Aramado */}
|
|
||||||
<button
|
|
||||||
onClick={onToggleWireframe}
|
|
||||||
className={`flex items-center justify-center gap-1.5 px-2.5 py-2 rounded-xl text-xs font-semibold border transition-all ${
|
|
||||||
isWireframe
|
|
||||||
? 'bg-slate-100 dark:bg-slate-800 text-slate-900 dark:text-slate-100 border-slate-300 dark:border-slate-700 shadow-sm'
|
|
||||||
: 'bg-white dark:bg-slate-900 text-slate-700 dark:text-slate-400 border-slate-200 dark:border-slate-800 hover:border-slate-300'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{isWireframe ? <Layers className="w-3.5 h-3.5 text-slate-600 dark:text-slate-300" /> : <Box className="w-3.5 h-3.5" />}
|
|
||||||
<span>{isWireframe ? 'Aramado' : 'Sólido'}</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user