File size: 3,506 Bytes
d2226ad
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import * as THREE from "three";
import { useMemo } from "react";
import { Text, Billboard } from "@react-three/drei";

const PLANET_STYLES = {
  Sun: { color: "#ffaa00", size: 15.0, label: "Sun" },
  Mercury: { color: "#ff0000", size: 3.0, label: "Mercury" },
  Venus: { color: "#e3bb76", size: 4.5, label: "Venus" },
  Moon: { color: "#999999", size: 6.0, label: "Moon" },
  Mars: { color: "#9C2E35", size: 4.0, label: "Mars" },
  Jupiter: { color: "#B45C3D", size: 8.0, label: "Jupiter" },
  Saturn: { color: "#eddbad", size: 7.0, label: "Saturn" },
  Uranus: { color: "#BBE1E4", size: 6.0, label: "Uranus" },
  Neptune: { color: "#7CB7BB", size: 6.0, label: "Neptune" },

  // Dwarf Planets
  Pluto: { color: "#d1c5b4", size: 2.5, label: "Pluto" },
  Ceres: { color: "#aaaaaa", size: 2.0, label: "Ceres" },
  Eris: { color: "#eeeeee", size: 2.0, label: "Eris" },
  Haumea: { color: "#999999", size: 2.0, label: "Haumea" },
  Makemake: { color: "#cc9966", size: 2.0, label: "Makemake" },
};

export function Planets({ data, visible, showLabels }) {
  const glowTexture = useMemo(() => {
    const canvas = document.createElement("canvas");
    canvas.width = 64;
    canvas.height = 64;
    const context = canvas.getContext("2d");
    const gradient = context.createRadialGradient(32, 32, 0, 32, 32, 32);
    gradient.addColorStop(0, "rgba(255, 255, 255, 1)");
    gradient.addColorStop(0.4, "rgba(255, 255, 255, 0.5)");
    gradient.addColorStop(1, "rgba(255, 255, 255, 0)");
    context.fillStyle = gradient;
    context.fillRect(0, 0, 64, 64);
    return new THREE.CanvasTexture(canvas);
  }, []);

  const planetObjects = useMemo(() => {
    if (!data) return [];
    const objects = [];
    const radius = 90;
    data.names.forEach((name, i) => {
      const alt = data.altitude[i];
      const az = data.azimuth[i];
      const phi = (90 - alt) * (Math.PI / 180);
      const theta = az * (Math.PI / 180);
      const x = radius * Math.sin(phi) * Math.sin(theta);
      const y = radius * Math.cos(phi);
      const z = -radius * Math.sin(phi) * Math.cos(theta);

      const style = PLANET_STYLES[name] || { color: "white", size: 3 };
      objects.push({ name, position: [x, y, z], ...style });
    });
    return objects;
  }, [data]);

  return (
    <group visible={visible}>
      {planetObjects.map((planet) => (
        <group key={planet.name} position={planet.position}>
          <mesh>
            <sphereGeometry args={[planet.size * 0.1, 16, 16]} />
            <meshBasicMaterial color={planet.color} />
          </mesh>

          <sprite scale={[planet.size, planet.size, 1]} renderOrder={1}>
            <spriteMaterial
              map={glowTexture}
              color={planet.color}
              transparent={true}
              opacity={0.8}
              depthWrite={false}
              blending={THREE.AdditiveBlending}
            />
          </sprite>

          {showLabels && (
            <Billboard>
              <Text
                position={[0, -planet.size * 0.6, 0]}
                fontSize={2.5}
                color={planet.color}
                anchorX="center"
                anchorY="top"
                renderOrder={10}
                depthTest={false}
                depthWrite={false}
              >
                {planet.name === "Moon" || planet.name === "Sun"
                  ? planet.label
                  : planet.name}
              </Text>
            </Billboard>
          )}
        </group>
      ))}
    </group>
  );
}