Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>3D Solar System with NEOs</title> | |
<style> | |
body { margin: 0; overflow: hidden; } | |
canvas { width: 100%; height: 100%; } | |
</style> | |
</head> | |
<body> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js"></script> | |
<script> | |
// Scene setup | |
const scene = new THREE.Scene(); | |
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); | |
const renderer = new THREE.WebGLRenderer(); | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
document.body.appendChild(renderer.domElement); | |
// Orbit controls for camera movement | |
const controls = new THREE.OrbitControls(camera, renderer.domElement); | |
camera.position.set(0, 20, 100); | |
controls.update(); | |
// Lights | |
const ambientLight = new THREE.AmbientLight(0x404040); | |
scene.add(ambientLight); | |
const pointLight = new THREE.PointLight(0xffffff); | |
pointLight.position.set(0, 100, 100); | |
scene.add(pointLight); | |
// Sun | |
const sunGeometry = new THREE.SphereGeometry(5, 32, 32); | |
const sunMaterial = new THREE.MeshBasicMaterial({ color: 0xffcc00 }); | |
const sun = new THREE.Mesh(sunGeometry, sunMaterial); | |
scene.add(sun); | |
// Planets | |
const planets = [ | |
{ name: 'Mercury', distance: 10, scale: 0.2 }, | |
{ name: 'Venus', distance: 15, scale: 0.4 }, | |
{ name: 'Earth', distance: 20, scale: 0.5 }, | |
{ name: 'Mars', distance: 25, scale: 0.3 }, | |
{ name: 'Jupiter', distance: 35, scale: 2 }, | |
{ name: 'Saturn', distance: 45, scale: 1.5 }, | |
{ name: 'Uranus', distance: 55, scale: 1 }, | |
{ name: 'Neptune', distance: 65, scale: 1 } | |
]; | |
planets.forEach(planet => { | |
const geometry = new THREE.SphereGeometry(planet.scale, 32, 32); | |
const material = new THREE.MeshPhongMaterial({ color: Math.random() * 0xffffff }); | |
const mesh = new THREE.Mesh(geometry, material); | |
mesh.position.x = planet.distance; | |
scene.add(mesh); | |
}); | |
// NEOs (fictional for now, will update with real data) | |
let neos = []; | |
for (let i = 0; i < 10; i++) { | |
const geometry = new THREE.SphereGeometry(0.1, 32, 32); | |
const material = new THREE.MeshBasicMaterial({ color: 0xcccccc }); | |
const neo = new THREE.Mesh(geometry, material); | |
neo.position.set(Math.random() * 30 - 15, Math.random() * 10 - 5, Math.random() * 30 - 15); | |
scene.add(neo); | |
neos.push(neo); | |
} | |
// Animation | |
function animate() { | |
requestAnimationFrame(animate); | |
planets.forEach((planet, index) => { | |
const planetMesh = scene.children[3 + index]; | |
planetMesh.position.x = Math.cos(Date.now() * 0.001 * (index + 1)) * planet.distance; | |
planetMesh.position.z = Math.sin(Date.now() * 0.001 * (index + 1)) * planet.distance; | |
}); | |
neos.forEach(neo => { | |
neo.position.x += Math.sin(Date.now() * 0.001) * 0.1; | |
neo.position.z += Math.cos(Date.now() * 0.001) * 0.1; | |
}); | |
controls.update(); | |
renderer.render(scene, camera); | |
} | |
animate(); | |
// Fetching NEO data from NASA API | |
function fetchNEOData() { | |
fetch('https://api.nasa.gov/neo/rest/v1/feed?start_date=2025-02-18&end_date=2025-02-19&api_key=DEMO_KEY') | |
.then(response => response.json()) | |
.then(data => { | |
// Update NEOs with real data | |
const neoData = data.near_earth_objects['2025-02-18']; | |
if (neoData) { | |
neos.forEach((neo, index) => { | |
if (index < neoData.length) { | |
const obj = neoData[index]; | |
// Note: This is a very simplistic representation. Real trajectory calculation would require more complex physics. | |
neo.position.set( | |
obj.close_approach_data[0].miss_distance.astronomical * 100 - 50, | |
obj.close_approach_data[0].miss_distance.astronomical * 50, | |
obj.close_approach_data[0].miss_distance.astronomical * 100 - 50 | |
); | |
} | |
}); | |
} | |
}).catch(error => console.error('Error fetching NEO data:', error)); | |
} | |
// Update NEO data periodically | |
fetchNEOData(); // Initial fetch | |
setInterval(fetchNEOData, 3600000); // Update every hour | |
</script> | |
</body> | |
</html> |