feat: apply dark mode contrast corrections to all 3D modules
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user