feat: apply dark mode contrast corrections to all 3D modules

This commit is contained in:
2026-07-10 16:34:03 +00:00
parent bcca3738d0
commit 9d01915704
8 changed files with 158 additions and 66 deletions
+22 -15
View File
@@ -3,6 +3,7 @@ import { OrbitControls, Grid, Environment, Text } from '@react-three/drei';
import * as THREE from 'three';
import SceneCanvas from '../SceneCanvas';
import FallbackDiagram from '../FallbackDiagram';
import { useCanvasTheme } from '@/lib/theme';
export interface Dome3DInput {
diameter: number;
@@ -14,16 +15,19 @@ export interface Dome3DInput {
cpeLateral: number;
}
function domeColor(cpe: number, cpi: number): THREE.Color {
function domeColor(cpe: number, cpi: number, isDark: boolean): THREE.Color {
const p = cpe - cpi;
const intensity = Math.min(1, Math.abs(p) / 1.5);
const l = isDark ? (65 - intensity * 15) : (60 - intensity * 25);
if (p > 0) {
return new THREE.Color(`hsl(${215 - intensity * 10}, ${70 + intensity * 25}%, ${Math.max(35, 60 - intensity * 25)}%)`);
return new THREE.Color(`hsl(${215 - intensity * 10}, ${70 + intensity * 25}%, ${Math.max(35, l)}%)`);
}
return new THREE.Color(`hsl(0, ${70 + intensity * 25}%, ${Math.max(40, 60 - intensity * 20)}%)`);
return new THREE.Color(`hsl(0, ${70 + intensity * 25}%, ${Math.max(40, l + 5)}%)`);
}
function DomeModel({ diameter, rise, wallHeight, cpi, cpeBarlavento, cpeTopo, cpeLateral }: Dome3DInput) {
const theme = useCanvasTheme();
const isDark = theme === 'dark';
const radius = diameter / 2;
const segments = 64;
@@ -31,12 +35,6 @@ function DomeModel({ diameter, rise, wallHeight, cpi, cpeBarlavento, cpeTopo, cp
const domeGeoms = useMemo(() => {
const arr: { startTheta: number; endTheta: number; color: THREE.Color }[] = [];
// Divide a circunferência completa (360°) em 6 zonas (simétricas)
// 0° a 60°: Barlavento
// 60° a 120°: Topo
// 120° a 180°: Lateral
// 180° a 240°: Lateral (espelhado)
// 240° a 300°: Topo (espelhado)
// 300° a 360°: Barlavento (espelhado)
const zones = [
{ fromDeg: 0, toDeg: 60, cpe: cpeBarlavento },
{ fromDeg: 60, toDeg: 120, cpe: cpeTopo },
@@ -49,11 +47,11 @@ function DomeModel({ diameter, rise, wallHeight, cpi, cpeBarlavento, cpeTopo, cp
arr.push({
startTheta: (z.fromDeg * Math.PI) / 180,
endTheta: (z.toDeg * Math.PI) / 180,
color: domeColor(z.cpe, cpi),
color: domeColor(z.cpe, cpi, isDark),
});
}
return arr;
}, [cpeBarlavento, cpeTopo, cpeLateral, cpi]);
}, [cpeBarlavento, cpeTopo, cpeLateral, cpi, isDark]);
// Raio da esfera da calota esférica baseada na flecha (rise) e raio da base (radius)
const rSphere = useMemo(() => {
@@ -71,11 +69,11 @@ function DomeModel({ diameter, rise, wallHeight, cpi, cpeBarlavento, cpeTopo, cp
{/* Detalhes de anéis metálicos nas bordas */}
<mesh position={[0, 0.01, 0]} rotation={[-Math.PI / 2, 0, 0]}>
<ringGeometry args={[radius - 0.03, radius + 0.03, segments]} />
<meshStandardMaterial color="#2d3748" roughness={0.5} />
<meshStandardMaterial color={isDark ? "#475569" : "#2d3748"} roughness={0.5} />
</mesh>
<mesh position={[0, wallHeight, 0]} rotation={[-Math.PI / 2, 0, 0]}>
<ringGeometry args={[radius - 0.03, radius + 0.03, segments]} />
<meshStandardMaterial color="#2d3748" roughness={0.5} />
<meshStandardMaterial color={isDark ? "#475569" : "#2d3748"} roughness={0.5} />
</mesh>
{/* Cúpula de cobertura (Spherical Cap) segmentada */}
@@ -156,7 +154,7 @@ function DomeModel({ diameter, rise, wallHeight, cpi, cpeBarlavento, cpeTopo, cp
<Text
position={[0, wallHeight + rise + 0.8, 0]}
fontSize={Math.max(0.3, Math.min(0.6, diameter / 12))}
color="#1a202c"
color={isDark ? "#cbd5e1" : "#1a202c"}
anchorX="center"
anchorY="bottom"
>
@@ -167,6 +165,9 @@ function DomeModel({ diameter, rise, wallHeight, cpi, cpeBarlavento, cpeTopo, cp
}
export default function Dome3DViewer(props: Dome3DInput) {
const theme = useCanvasTheme();
const isDark = theme === 'dark';
const fallback = (
<FallbackDiagram
type="dome"
@@ -197,7 +198,13 @@ export default function Dome3DViewer(props: Dome3DInput) {
shadow-camera-bottom={-maxDim}
/>
<DomeModel {...props} />
<Grid infiniteGrid fadeDistance={maxDim * 5} sectionColor="#94a3b8" cellColor="#cbd5e1" position={[0, -0.01, 0]} />
<Grid
infiniteGrid
fadeDistance={maxDim * 5}
sectionColor={isDark ? "#475569" : "#94a3b8"}
cellColor={isDark ? "#1e293b" : "#cbd5e1"}
position={[0, -0.01, 0]}
/>
<OrbitControls makeDefault minPolarAngle={0} maxPolarAngle={Math.PI / 2 - 0.05} />
<Environment preset="city" />
</SceneCanvas>