178 lines
5.3 KiB
JavaScript
178 lines
5.3 KiB
JavaScript
import * as THREE from 'three';
|
||
|
||
// Scene
|
||
const scene = new THREE.Scene();
|
||
|
||
// Camera
|
||
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
|
||
camera.position.set(0, 25, 45);
|
||
camera.lookAt(scene.position);
|
||
|
||
// Renderer
|
||
const renderer = new THREE.WebGLRenderer();
|
||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||
document.body.appendChild(renderer.domElement);
|
||
|
||
// Lighting
|
||
const pointLight = new THREE.PointLight(0xffffff, 5, 3000); // Increased intensity and distance
|
||
scene.add(pointLight);
|
||
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); // Increased ambient light
|
||
scene.add(ambientLight);
|
||
|
||
|
||
// Texture Loader
|
||
const textureLoader = new THREE.TextureLoader();
|
||
|
||
// Stars
|
||
const starVertices = [];
|
||
for (let i = 0; i < 10000; i++) {
|
||
const x = (Math.random() - 0.5) * 2000;
|
||
const y = (Math.random() - 0.5) * 2000;
|
||
const z = (Math.random() - 0.5) * 2000;
|
||
starVertices.push(x, y, z);
|
||
}
|
||
|
||
const starGeometry = new THREE.BufferGeometry();
|
||
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
|
||
|
||
const starMaterial = new THREE.PointsMaterial({
|
||
color: 0xffffff,
|
||
size: 0.7
|
||
});
|
||
|
||
const stars = new THREE.Points(starGeometry, starMaterial);
|
||
scene.add(stars);
|
||
|
||
// --- Sun ---
|
||
const sunTexture = textureLoader.load('assets/textures/sun.jpg');
|
||
const sunMaterial = new THREE.MeshBasicMaterial({ map: sunTexture });
|
||
const sun = new THREE.Mesh(new THREE.SphereGeometry(5, 32, 32), sunMaterial);
|
||
scene.add(sun);
|
||
|
||
// --- Planets & Orbits ---
|
||
const segments = 128;
|
||
const orbitMaterial = new THREE.LineBasicMaterial({ color: 0xffffff, opacity: 0.5, transparent: true });
|
||
|
||
function createPlanet(radius, textureFile, distance, orbitSpeed) {
|
||
const texture = textureLoader.load(`assets/textures/${textureFile}`);
|
||
const geometry = new THREE.SphereGeometry(radius, 32, 32);
|
||
const material = new THREE.MeshStandardMaterial({ map: texture });
|
||
const planet = new THREE.Mesh(geometry, material);
|
||
|
||
const pivot = new THREE.Object3D();
|
||
sun.add(pivot);
|
||
pivot.add(planet);
|
||
planet.position.x = distance;
|
||
|
||
const orbitGeometry = new THREE.BufferGeometry().setFromPoints(
|
||
new THREE.Path().absarc(0, 0, distance, 0, Math.PI * 2, false).getSpacedPoints(segments)
|
||
);
|
||
const orbit = new THREE.Line(orbitGeometry, orbitMaterial);
|
||
orbit.rotation.x = Math.PI / 2;
|
||
scene.add(orbit);
|
||
|
||
return { planet, pivot, orbitSpeed };
|
||
}
|
||
|
||
const mercuryData = createPlanet(0.4, 'mercury.jpg', 7, 0.04);
|
||
const venusData = createPlanet(0.9, 'venus.jpg', 11, 0.015);
|
||
const earthData = createPlanet(1, 'earth.jpg', 15, 0.01);
|
||
const marsData = createPlanet(0.7, 'mars.jpg', 20, 0.008);
|
||
|
||
const planets = [mercuryData, venusData, earthData, marsData];
|
||
|
||
// Planet Data
|
||
const planetData = {
|
||
[earthData.planet.uuid]: {
|
||
name: 'Earth',
|
||
mass: '5.97 × 10^24 kg',
|
||
radius: '6,371 km',
|
||
orbital_speed: '29.78 km/s',
|
||
},
|
||
[mercuryData.planet.uuid]: {
|
||
name: 'Mercury',
|
||
mass: '3.285 × 10^23 kg',
|
||
radius: '2,439.7 km',
|
||
orbital_speed: '47.36 km/s',
|
||
},
|
||
[venusData.planet.uuid]: {
|
||
name: 'Venus',
|
||
mass: '4.867 × 10^24 kg',
|
||
radius: '6,051.8 km',
|
||
orbital_speed: '35.02 km/s',
|
||
},
|
||
[marsData.planet.uuid]: {
|
||
name: 'Mars',
|
||
mass: '6.39 × 10^23 kg',
|
||
radius: '3,389.5 km',
|
||
orbital_speed: '24.07 km/s',
|
||
}
|
||
};
|
||
|
||
// Stats Panel
|
||
const statsInfo = document.getElementById('stats-info');
|
||
const statsButtons = document.getElementById('stats-buttons');
|
||
|
||
function updateStats(planetUUID) {
|
||
const data = planetData[planetUUID];
|
||
if (data) {
|
||
statsInfo.innerHTML = `
|
||
<h3>${data.name}</h3>
|
||
<p>Mass: ${data.mass}</p>
|
||
<p>Radius: ${data.radius}</p>
|
||
<p>Orbital Speed: ${data.orbital_speed}</p>
|
||
`;
|
||
}
|
||
}
|
||
|
||
statsButtons.addEventListener('click', (event) => {
|
||
if (event.target.tagName === 'BUTTON') {
|
||
const planetName = event.target.dataset.planet;
|
||
let planetUUID;
|
||
|
||
statsButtons.querySelectorAll('button').forEach(btn => btn.classList.remove('active'));
|
||
event.target.classList.add('active');
|
||
|
||
if (planetName === 'earth') {
|
||
planetUUID = earthData.planet.uuid;
|
||
} else if (planetName === 'mercury') {
|
||
planetUUID = mercuryData.planet.uuid;
|
||
} else if (planetName === 'venus') {
|
||
planetUUID = venusData.planet.uuid;
|
||
} else if (planetName === 'mars') {
|
||
planetUUID = marsData.planet.uuid;
|
||
}
|
||
|
||
if (planetUUID) {
|
||
updateStats(planetUUID);
|
||
}
|
||
}
|
||
});
|
||
|
||
// Display Earth's stats by default and set button to active
|
||
updateStats(earthData.planet.uuid);
|
||
statsButtons.querySelector('button[data-planet="earth"]').classList.add('active');
|
||
|
||
|
||
// Animation loop
|
||
function animate() {
|
||
requestAnimationFrame(animate);
|
||
|
||
// Rotation
|
||
sun.rotation.y += 0.001;
|
||
planets.forEach(p => {
|
||
p.pivot.rotation.y += p.orbitSpeed;
|
||
p.planet.rotation.y += 0.01; // Add self-rotation
|
||
});
|
||
|
||
renderer.render(scene, camera);
|
||
}
|
||
|
||
animate();
|
||
|
||
// Handle window resize
|
||
window.addEventListener('resize', () => {
|
||
camera.aspect = window.innerWidth / window.innerHeight;
|
||
camera.updateProjectionMatrix();
|
||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||
}); |