<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3D Solar System Simulation</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div id="info">
        Solar System Simulation<br>
        Drag to rotate, Scroll to zoom, Right-drag to pan.
    </div>
    <div id="container"></div>

    <!-- Include Three.js Library -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <!-- Include OrbitControls Add-on -->
    <script src="https://unpkg.com/three@0.128.0/examples/js/controls/OrbitControls.js"></script>


    <!-- Your simulation script -->
    <script src="script.js"></script>
</body>
</html>
body {
    margin: 0;
    font-family: Arial, sans-serif;
    background-color: #000000; /* Black space background */
    color: #eee;
    overflow: hidden; /* Prevent scrollbars from canvas */
}

#container {
    width: 100vw;
    height: 100vh;
    display: block;
}

#info {
    position: absolute;
    top: 10px;
    left: 10px;
    padding: 10px;
    background-color: rgba(0, 0, 0, 0.5);
    border-radius: 5px;
    z-index: 100; /* Ensure it's on top */
    color: #fff;
    text-align: center;
    width: auto;
}
// Basic check for Three.js and OrbitControls
if (typeof THREE === 'undefined' || typeof THREE.OrbitControls === 'undefined') {
    alert('Error: Three.js or OrbitControls library not loaded!');
} else {
    // --- Scene Setup ---
    const scene = new THREE.Scene();

    // --- Camera Setup ---
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
    camera.position.z = 50; // Start further back
    camera.position.y = 20; // Start slightly above the plane

    // --- Renderer Setup ---
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(window.devicePixelRatio); // Adjust for device resolution
    document.getElementById('container').appendChild(renderer.domElement);

    // --- Orbit Controls ---
    const controls = new THREE.OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true; // Smooths out the controls
    controls.dampingFactor = 0.05;
    controls.screenSpacePanning = false; // Keep panning relative to world origin
    controls.minDistance = 5;
    controls.maxDistance = 1000;

    // --- Lighting ---
    // Sun Light - Acts as the primary light source
    const pointLight = new THREE.PointLight(0xffffff, 1.5, 2000); // Strong white light
    scene.add(pointLight); // PointLight is automatically placed at (0,0,0)

    // Ambient light for faint overall illumination
    const ambientLight = new THREE.AmbientLight(0xffffff, 0.1); // Faint white light
    scene.add(ambientLight);

    // --- Sun Object ---
    const sunGeometry = new THREE.SphereGeometry(5, 32, 32); // Larger sphere for Sun
    // MeshBasicMaterial ignores lights, good for self-luminous objects
    const sunMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00, wireframe: false });
    const sunMesh = new THREE.Mesh(sunGeometry, sunMaterial);
    scene.add(sunMesh);

    // --- Planet Data (Artistic Scale & Simplified Speeds) ---
    const planetsData = [
        { name: 'Mercury', radius: 0.5, color: 0xaaaaaa, orbitRadius: 10, speed: 0.040 },
        { name: 'Venus', radius: 0.9, color: 0xffe4b5, orbitRadius: 15, speed: 0.025 },
        { name: 'Earth', radius: 1.0, color: 0x4682b4, orbitRadius: 22, speed: 0.015 },
        { name: 'Mars', radius: 0.7, color: 0xff4500, orbitRadius: 30, speed: 0.010 },
        { name: 'Jupiter', radius: 3.5, color: 0xffa500, orbitRadius: 50, speed: 0.005 },
        { name: 'Saturn', radius: 3.0, color: 0xf4a460, orbitRadius: 75, speed: 0.003, hasRing: true },
        { name: 'Uranus', radius: 2.0, color: 0xadd8e6, orbitRadius: 100, speed: 0.002 },
        { name: 'Neptune', radius: 1.9, color: 0x0000ff, orbitRadius: 130, speed: 0.001 }
    ];

    const planetMeshes = []; // To store planet meshes for potential interaction later
    const planetPivots = []; // To store pivot points for easy rotation

    // --- Create Planets and Orbits ---
    planetsData.forEach(data => {
        // Planet Mesh
        const geometry = new THREE.SphereGeometry(data.radius, 16, 16);
        // Use MeshStandardMaterial so planets react to light
        const material = new THREE.MeshStandardMaterial({ color: data.color, roughness: 0.8, metalness: 0.1 });
        const planetMesh = new THREE.Mesh(geometry, material);
        planetMesh.position.x = data.orbitRadius; // Position planet along the x-axis initially

        // Saturn's Ring
        if (data.hasRing) {
            const ringGeometry = new THREE.RingGeometry(data.radius * 1.3, data.radius * 2, 32);
             // Make ring slightly transparent and double-sided
            const ringMaterial = new THREE.MeshBasicMaterial({ color: 0xaaaaaa, side: THREE.DoubleSide, transparent: true, opacity: 0.6 });
            const ringMesh = new THREE.Mesh(ringGeometry, ringMaterial);
            ringMesh.rotation.x = Math.PI / 2; // Rotate ring to be horizontal
            planetMesh.add(ringMesh); // Add ring as a child of Saturn mesh
        }

        // Orbit Path Visualization
        const orbitPathGeometry = new THREE.BufferGeometry();
        const points = [];
        const segments = 128;
        for (let i = 0; i <= segments; i++) {
            const theta = (i / segments) * Math.PI * 2;
            points.push(new THREE.Vector3(Math.cos(theta) * data.orbitRadius, 0, Math.sin(theta) * data.orbitRadius));
        }
        orbitPathGeometry.setFromPoints(points);
        const orbitPathMaterial = new THREE.LineBasicMaterial({ color: 0x444444 }); // Dim grey orbits
        const orbitLine = new THREE.Line(orbitPathGeometry, orbitPathMaterial);

        // Pivot Point for Rotation
        // Create an Object3D to act as the center of rotation for this planet
        const pivot = new THREE.Object3D();
        pivot.add(planetMesh); // Add the planet mesh to the pivot
        scene.add(pivot);      // Add the pivot to the main scene
        scene.add(orbitLine);  // Add the orbit line visualization to the scene

        // Store for animation
        planetMeshes.push(planetMesh);
        planetPivots.push({ pivot: pivot, speed: data.speed });
    });


    // --- Window Resize Handling ---
    window.addEventListener('resize', () => {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    });

    // --- Animation Loop ---
    const clock = new THREE.Clock(); // For delta time (smoother animation)

    function animate() {
        requestAnimationFrame(animate); // Loop animation

        const delta = clock.getDelta(); // Time since last frame

        // Update planet rotations around the Sun
        planetPivots.forEach(item => {
            item.pivot.rotation.y += item.speed * delta * 10; // Multiply speed by delta and a factor
        });

        // Optional: Add self-rotation to planets (axial spin)
        planetMeshes.forEach(mesh => {
             mesh.rotation.y += 0.05 * delta * 10; // Example: simple same-speed spin
        });


        // Update controls (needed for damping)
        controls.update();

        // Render the scene
        renderer.render(scene, camera);
    }

    // --- Start Animation ---
    animate();
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.