From 44b041392937c914a0cf64955b5366cf97075f5b Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Fri, 12 Sep 2025 19:20:56 +0000 Subject: [PATCH] Revert to version 79dd707 --- assets/css/custom.css | 103 ++------ assets/js/main.js | 564 +++++++++++++++++++++++------------------- index.php | 42 +--- 3 files changed, 341 insertions(+), 368 deletions(-) diff --git a/assets/css/custom.css b/assets/css/custom.css index 5073798..5961183 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -3,21 +3,6 @@ body { overflow: hidden; background-color: #000; } - -#date-container { - position: absolute; - top: 20px; - left: 50%; - transform: translateX(-50%); - color: white; - background-color: rgba(0, 0, 0, 0.5); - padding: 10px 20px; - border-radius: 5px; - font-family: sans-serif; - font-size: 1.2em; - z-index: 10; -} - canvas { display: block; } @@ -57,78 +42,40 @@ canvas { border-color: #007bff; } -#time-controls { +#controls-container { position: absolute; bottom: 20px; - left: 20px; - background-color: rgba(0,0,0,0.5); - padding: 10px; - border-radius: 5px; - z-index: 10; - color: white; - font-family: sans-serif; -} - -#time-controls button { - background-color: #333; - color: white; - border: 1px solid #555; - padding: 5px 10px; - cursor: pointer; - border-radius: 3px; - margin: 0 5px; -} - -#time-controls button:hover { - background-color: #555; -} - -#time-controls span { - margin-left: 10px; - font-size: 0.9em; - vertical-align: middle; -} - -.planet-label { - position: absolute; - color: white; - font-family: sans-serif; - font-size: 12px; - text-shadow: 1px 1px 2px black; - pointer-events: none; /* So they don't interfere with mouse controls */ - z-index: 11; -} - -#controls-top-left { - position: absolute; - top: 20px; - right: 20px; - display: flex; - flex-direction: column; - gap: 10px; - z-index: 10; -} - -#scale-container, #focus-container { - color: white; + left: 50%; + transform: translateX(-50%); background-color: rgba(0, 0, 0, 0.5); padding: 10px; border-radius: 5px; - font-family: sans-serif; + z-index: 10; } -#scale-container label { - margin-right: 5px; -} - -#focus-container label { - margin-right: 5px; -} - -#focus-container select { +#controls-container button { background-color: #333; color: white; border: 1px solid #555; + padding: 10px 20px; + cursor: pointer; border-radius: 3px; - padding: 5px; +} + +#controls-container button:hover { + background-color: #555; +} + +#time-container { + position: absolute; + top: 20px; + left: 50%; + transform: translateX(-50%); + color: white; + background-color: rgba(0, 0, 0, 0.5); + padding: 10px 20px; + border-radius: 5px; + font-family: monospace; + font-size: 1.2em; + z-index: 10; } \ No newline at end of file diff --git a/assets/js/main.js b/assets/js/main.js index fb7210c..e5eb124 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -1,328 +1,383 @@ import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; -// --- SCENE, CAMERA, RENDERER, CONTROLS --- +// Scene const scene = new THREE.Scene(); -const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 50000); + +// Camera +const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(0, 25, 45); camera.lookAt(scene.position); -const renderer = new THREE.WebGLRenderer({ antialias: true }); +// Renderer +const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); +// Controls const controls = new OrbitControls(camera, renderer.domElement); -controls.enableDamping = true; +controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled controls.dampingFactor = 0.05; controls.screenSpacePanning = false; -controls.minDistance = 1; -controls.maxDistance = 20000; +controls.minDistance = 10; +controls.maxDistance = 500; -// --- LIGHTING --- -const pointLight = new THREE.PointLight(0xffffff, 5, 60000); +// Lighting +const pointLight = new THREE.PointLight(0xffffff, 5, 3000); // Increased intensity and distance scene.add(pointLight); -const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); +const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); // Increased ambient light scene.add(ambientLight); -// --- TEXTURES & ASSETS --- + +// Texture Loader const textureLoader = new THREE.TextureLoader(); -// --- STARS BACKGROUND --- +// Stars const starVertices = []; -for (let i = 0; i < 15000; i++) { - const x = (Math.random() - 0.5) * 25000; - const y = (Math.random() - 0.5) * 25000; - const z = (Math.random() - 0.5) * 25000; +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: 1.5 }); + +const starMaterial = new THREE.PointsMaterial({ + color: 0xffffff, + size: 0.7 +}); + const stars = new THREE.Points(starGeometry, starMaterial); scene.add(stars); -// --- SCALE CONSTANTS --- -const SCALES = { - artistic: { - sunSize: 5, - planetScale: 1, - orbitScale: 1, - moonOrbitScale: 1, - }, - realistic: { - sunSize: 0.5, - planetScale: 0.01, - orbitScale: 100, - moonOrbitScale: 0.1, - } -}; -let currentScale = 'artistic'; - -// --- CELESTIAL BODY DATA & CREATION --- -const celestialBodies = []; - -// --- SUN --- +// --- Sun --- const sunTexture = textureLoader.load('assets/textures/sun.jpg'); const sunMaterial = new THREE.MeshBasicMaterial({ map: sunTexture }); -const sun = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 32), sunMaterial); -sun.name = 'Sun'; +const sun = new THREE.Mesh(new THREE.SphereGeometry(5, 32, 32), sunMaterial); scene.add(sun); -celestialBodies.push({ name: 'Sun', object: sun, data: { radius: 696340 } }); // Real radius in km -function createPlanet(name, textureFile, data) { +// --- Planets & Orbits --- +const segments = 128; +const orbitMaterial = new THREE.LineBasicMaterial({ color: 0xffffff, opacity: 0.5, transparent: true }); + +function createPlanet(radius, textureFile, distance, orbitalPeriodDays) { const texture = textureLoader.load(`assets/textures/${textureFile}?v=${Date.now()}`); - const geometry = new THREE.SphereGeometry(data.radius, 32, 32); - const material = new THREE.MeshBasicMaterial({ map: texture }); + const geometry = new THREE.SphereGeometry(radius, 32, 32); + const material = new THREE.MeshBasicMaterial({ map: texture }); // Reverted const planet = new THREE.Mesh(geometry, material); - planet.name = name; - + const pivot = new THREE.Object3D(); sun.add(pivot); pivot.add(planet); + planet.position.x = distance; - const planetObj = { - name, - object: planet, - pivot, - data, - }; - celestialBodies.push(planetObj); - return planetObj; + // Trail setup + const trailPoints = []; + const trailGeometry = new THREE.BufferGeometry(); + const trailMaterial = new THREE.LineBasicMaterial({ color: 0xffffff, opacity: 0.5, transparent: true }); + const trail = new THREE.Line(trailGeometry, trailMaterial); + scene.add(trail); + + return { planet, pivot, orbitalPeriodDays, trail, trailPoints }; } -function createMoon(name, color, data, parentPlanetObject) { - const geometry = new THREE.SphereGeometry(data.radius, 32, 32); - const material = new THREE.MeshBasicMaterial({ color }); - const moon = new THREE.Mesh(geometry, material); - moon.name = name; +const mercuryData = createPlanet(0.4, 'mercury.jpg', 7, 88); +const venusData = createPlanet(0.9, 'venus.jpg', 11, 225); +const earthData = createPlanet(1, 'earth.jpg', 15, 365); +const marsData = createPlanet(0.7, 'mars.jpg', 20, 687); +const jupiterData = createPlanet(3, 'jupiter.jpg', 30, 4333); +const saturnData = createPlanet(2.5, 'saturn.jpg', 40, 10759); +const uranusData = createPlanet(2, 'uranus.jpg', 50, 30687); +const neptuneData = createPlanet(1.9, 'neptune.jpg', 60, 60190); - const pivot = new THREE.Object3D(); - parentPlanetObject.add(pivot); - pivot.add(moon); +// --- Saturn's Rings --- +const ringGeometry = new THREE.RingGeometry(3.5, 5, 64); +const ringMaterial = new THREE.MeshBasicMaterial({ + color: 0xffffff, + side: THREE.DoubleSide, + transparent: true, + opacity: 0.6 +}); +const ring = new THREE.Mesh(ringGeometry, ringMaterial); +ring.rotation.x = -Math.PI / 2.5; // Tilt the rings +saturnData.planet.add(ring); - const moonObj = { - name, - object: moon, - pivot, - data, - parent: parentPlanetObject - }; - celestialBodies.push(moonObj); - return moonObj; +// --- Moon --- +const moonGeometry = new THREE.SphereGeometry(0.25, 32, 32); +const moonMaterial = new THREE.MeshBasicMaterial({ color: 0x888888 }); +const moon = new THREE.Mesh(moonGeometry, moonMaterial); + +const moonPivot = new THREE.Object3D(); +earthData.planet.add(moonPivot); +moonPivot.add(moon); +moon.position.x = 2; + +// --- Asteroid Belt --- +const asteroidCount = 1500; +const asteroidGeometry = new THREE.SphereGeometry(0.05, 8, 8); // A small sphere for asteroids +const asteroidMaterial = new THREE.MeshStandardMaterial({ color: 0x999999, roughness: 0.9 }); +const asteroidMesh = new THREE.InstancedMesh(asteroidGeometry, asteroidMaterial, asteroidCount); + +const beltMinRadius = 23; +const beltMaxRadius = 28; +const beltHeight = 1.5; // Vertical thickness + +const dummy = new THREE.Object3D(); +const asteroidData = []; + +for (let i = 0; i < asteroidCount; i++) { + const radius = Math.random() * (beltMaxRadius - beltMinRadius) + beltMinRadius; + const angle = Math.random() * Math.PI * 2; + const y = (Math.random() - 0.5) * beltHeight; + const orbitSpeed = (Math.random() * 0.002 + 0.0005); // Slower than Mars, faster than Jupiter + const rotationSpeed = Math.random() * 0.05; + + asteroidData.push({ radius, angle, y, orbitSpeed, rotationSpeed }); + + dummy.position.set( + Math.cos(angle) * radius, + y, + Math.sin(angle) * radius + ); + dummy.updateMatrix(); + asteroidMesh.setMatrixAt(i, dummy.matrix); } -function createRings(innerRadius, outerRadius, color, opacity, tilt) { - const ringGeometry = new THREE.RingGeometry(innerRadius, outerRadius, 64); - const ringMaterial = new THREE.MeshBasicMaterial({ - color: color, - side: THREE.DoubleSide, - transparent: true, - opacity: opacity - }); - const ring = new THREE.Mesh(ringGeometry, ringMaterial); - ring.rotation.x = tilt; - return ring; -} +scene.add(asteroidMesh); -const celestialData = { - mercury: { radius: 0.4, distance: 7, period: 88 }, - venus: { radius: 0.9, distance: 11, period: 225 }, - earth: { radius: 1, distance: 15, period: 365 }, - mars: { radius: 0.7, distance: 20, period: 687 }, - jupiter: { radius: 3, distance: 30, period: 4333 }, - saturn: { radius: 2.5, distance: 40, period: 10759 }, - uranus: { radius: 2, distance: 50, period: 30687 }, - neptune: { radius: 1.9, distance: 60, period: 60190 }, - moon: { radius: 0.25, distance: 2, period: 27.3 }, - io: { radius: 0.2, distance: 3.5, period: 1.769 }, - europa: { radius: 0.2, distance: 4.0, period: 3.551 }, - ganymede: { radius: 0.3, distance: 4.5, period: 7.155 }, - callisto: { radius: 0.3, distance: 5.0, period: 16.689 }, - titan: { radius: 0.4, distance: 6.0, period: 15.95 }, - triton: { radius: 0.35, distance: 4.0, period: 5.88 }, + +const planets = [mercuryData, venusData, earthData, marsData, jupiterData, saturnData, uranusData, neptuneData]; + +// 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', + }, + [jupiterData.planet.uuid]: { + name: 'Jupiter', + mass: '1.898 × 10^27 kg', + radius: '69,911 km', + orbital_speed: '13.07 km/s', + }, + [saturnData.planet.uuid]: { + name: 'Saturn', + mass: '5.683 × 10^26 kg', + radius: '58,232 km', + orbital_speed: '9.69 km/s', + }, + [uranusData.planet.uuid]: { + name: 'Uranus', + mass: '8.681 × 10^25 kg', + radius: '25,362 km', + orbital_speed: '6.81 km/s', + }, + [neptuneData.planet.uuid]: { + name: 'Neptune', + mass: '1.024 × 10^26 kg', + radius: '24,622 km', + orbital_speed: '5.43 km/s', + } }; -// --- INSTANTIATE BODIES --- -const mercury = createPlanet('Mercury', 'mercury.jpg', celestialData.mercury); -const venus = createPlanet('Venus', 'venus.jpg', celestialData.venus); -const earth = createPlanet('Earth', 'earth.jpg', celestialData.earth); -const mars = createPlanet('Mars', 'mars.jpg', celestialData.mars); -const jupiter = createPlanet('Jupiter', 'jupiter.jpg', celestialData.jupiter); -const saturn = createPlanet('Saturn', 'saturn.jpg', celestialData.saturn); -const uranus = createPlanet('Uranus', 'uranus.jpg', celestialData.uranus); -const neptune = createPlanet('Neptune', 'neptune.jpg', celestialData.neptune); +// --- Selection Outline --- +let outlineMesh; +const outlineMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00, side: THREE.BackSide }); +const outlineScale = 1.15; -createMoon('Moon', 0x888888, celestialData.moon, earth.object); -createMoon('Io', 0xffff00, celestialData.io, jupiter.object); -createMoon('Europa', 0xffa500, celestialData.europa, jupiter.object); -createMoon('Ganymede', 0x00ff00, celestialData.ganymede, jupiter.object); -createMoon('Callisto', 0x0000ff, celestialData.callisto, jupiter.object); -createMoon('Titan', 0xFFAC1C, celestialData.titan, saturn.object); -createMoon('Triton', 0xADD8E6, celestialData.triton, neptune.object); +function setOutline(object) { + if (outlineMesh && outlineMesh.parent) { + outlineMesh.parent.remove(outlineMesh); + } -// --- RINGS --- -saturn.object.add(createRings(3.5, 5, 0xffffff, 0.6, -Math.PI / 2.5)); -jupiter.object.add(createRings(3.5, 4.5, 0x8c7853, 0.4, -Math.PI / 2)); -uranus.object.add(createRings(2.5, 3.5, 0xadd8e6, 0.3, -Math.PI / 2)); -neptune.object.add(createRings(2.4, 3, 0xadd8e6, 0.2, -Math.PI / 2.5)); - -// --- UI & CONTROLS --- -const scaleToggle = document.getElementById('scale-toggle'); -const focusSelect = document.getElementById('focus-select'); -const dateDisplay = document.getElementById('date-container'); -const slowDownButton = document.getElementById('slow-down'); -const pauseToggleButton = document.getElementById('pause-toggle'); -const speedUpButton = document.getElementById('speed-up'); -const speedDisplay = document.getElementById('speed-display'); - -// Populate Focus Dropdown -celestialBodies.forEach(body => { - const option = document.createElement('option'); - option.value = body.name; - option.textContent = body.name; - focusSelect.appendChild(option); -}); - -function focusOnObject(name) { - const body = celestialBodies.find(b => b.name === name); - if (!body) return; - - const target = new THREE.Vector3(); - body.object.getWorldPosition(target); - controls.target.copy(target); - - const size = body.object.geometry.parameters.radius * body.object.scale.x; - const offset = size * 5; - - const cameraPosition = new THREE.Vector3(target.x + offset, target.y + offset / 2, target.z + offset); - camera.position.copy(cameraPosition); - controls.update(); + outlineMesh = new THREE.Mesh(object.geometry, outlineMaterial); + outlineMesh.scale.set(outlineScale, outlineScale, outlineScale); + object.add(outlineMesh); } -focusSelect.addEventListener('change', (event) => { - focusOnObject(event.target.value); -}); -scaleToggle.addEventListener('change', (event) => { - const scale = event.target.checked ? 'realistic' : 'artistic'; - updateScale(scale); -}); +// Stats Panel +const statsInfo = document.getElementById('stats-info'); +const statsButtons = document.getElementById('stats-buttons'); -// --- TIME CONTROLS --- -let simulationSpeed = 1; // Represents days per second -let isPaused = false; -let currentDate = new Date(); - -function updateSpeedDisplay() { - speedDisplay.textContent = `Speed: ${simulationSpeed}x`; +function updateStats(planetUUID) { + const data = planetData[planetUUID]; + if (data) { + statsInfo.innerHTML = ` +

${data.name}

+

Mass: ${data.mass}

+

Radius: ${data.radius}

+

Orbital Speed: ${data.orbital_speed}

+ `; + } } -pauseToggleButton.addEventListener('click', () => { - isPaused = !isPaused; - pauseToggleButton.textContent = isPaused ? 'Resume' : 'Pause'; -}); +statsButtons.addEventListener('click', (event) => { + if (event.target.tagName === 'BUTTON') { + const planetName = event.target.dataset.planet; + let planetObject, planetUUID; -slowDownButton.addEventListener('click', () => { - simulationSpeed /= 2; - updateSpeedDisplay(); -}); + statsButtons.querySelectorAll('button').forEach(btn => btn.classList.remove('active')); + event.target.classList.add('active'); -speedUpButton.addEventListener('click', () => { - simulationSpeed *= 2; - updateSpeedDisplay(); -}); + if (planetName === 'earth') { + planetObject = earthData.planet; + planetUUID = earthData.planet.uuid; + } else if (planetName === 'mercury') { + planetObject = mercuryData.planet; + planetUUID = mercuryData.planet.uuid; + } else if (planetName === 'venus') { + planetObject = venusData.planet; + planetUUID = venusData.planet.uuid; + } else if (planetName === 'mars') { + planetObject = marsData.planet; + planetUUID = marsData.planet.uuid; + } else if (planetName === 'jupiter') { + planetObject = jupiterData.planet; + planetUUID = jupiterData.planet.uuid; + } else if (planetName === 'saturn') { + planetObject = saturnData.planet; + planetUUID = saturnData.planet.uuid; + } else if (planetName === 'uranus') { + planetObject = uranusData.planet; + planetUUID = uranusData.planet.uuid; + } else if (planetName === 'neptune') { + planetObject = neptuneData.planet; + planetUUID = neptuneData.planet.uuid; + } - -// --- SCALE UPDATE LOGIC --- -function updateScale(scaleType) { - currentScale = scaleType; - const scaleConfig = SCALES[scaleType]; - - sun.scale.setScalar(scaleConfig.sunSize); - - celestialBodies.forEach(body => { - if (body.name === 'Sun') return; - - const { object, pivot, data } = body; - object.scale.setScalar(scaleConfig.planetScale); - - if (pivot) { - if (body.parent) { - object.position.x = data.distance * scaleConfig.moonOrbitScale; - } else { - object.position.x = data.distance * scaleConfig.orbitScale; + if (planetUUID) { + updateStats(planetUUID); + if (planetObject) { + setOutline(planetObject); } } - }); - - if (scaleType === 'realistic') { - controls.maxDistance = 400000; - controls.minDistance = 0.01; - } else { - controls.maxDistance = 1000; - controls.minDistance = 1; } - focusOnObject(focusSelect.value); +}); + +// Display Earth's stats by default and set button to active +updateStats(earthData.planet.uuid); +statsButtons.querySelector('button[data-planet="earth"]').classList.add('active'); +setOutline(earthData.planet); // Initial outline for Earth + + +// --- Controls Logic --- +let isPaused = false; +const pauseButton = document.getElementById('pause-button'); +const speedToggleButton = document.getElementById('speed-toggle-button'); + +pauseButton.addEventListener('click', () => { + isPaused = !isPaused; + pauseButton.textContent = isPaused ? 'Play' : 'Pause'; +}); + +const speeds = [1, 100, 500, 1000, 10000]; +let currentSpeedIndex = 0; +let timeScale = speeds[currentSpeedIndex]; // Start with 1x speed + +speedToggleButton.addEventListener('click', () => { + currentSpeedIndex = (currentSpeedIndex + 1) % speeds.length; + timeScale = speeds[currentSpeedIndex]; + speedToggleButton.textContent = 'Speed: ' + timeScale + 'x'; +}); + + +// --- Time & Simulation --- +const clock = new THREE.Clock(); +const timeContainer = document.getElementById('time-container'); +let simulationTime = new Date(); +const TIME_SPEED_FACTOR = 60; // 1 real second = 1 simulation minute at 1x +const MS_IN_A_DAY = 24 * 60 * 60 * 1000; +const MOON_ORBIT_DAYS = 27.3; + + +function updateTimeDisplay() { + const hours = String(simulationTime.getHours()).padStart(2, '0'); + const minutes = String(simulationTime.getMinutes()).padStart(2, '0'); + const seconds = String(simulationTime.getSeconds()).padStart(2, '0'); + const day = String(simulationTime.getDate()).padStart(2, '0'); + const month = String(simulationTime.getMonth() + 1).padStart(2, '0'); // Month is 0-indexed + const year = simulationTime.getFullYear(); + timeContainer.textContent = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; } -// Initial setup -updateScale('artistic'); -updateSpeedDisplay(); - -// --- LABELS --- -const labels = celestialBodies.map(body => ({ - object: body.object, - element: document.getElementById(`label-${body.name.toLowerCase()}`), -})).filter(label => label.element); - -// --- ANIMATION LOOP --- -const clock = new THREE.Clock(); -let simulationTime = 0; -const ORBIT_SPEED_FACTOR = 0.1; // Slows down overall orbit speed - +// Animation loop function animate() { requestAnimationFrame(animate); - const deltaTime = clock.getDelta(); + + // Get time delta for frame-rate independent animation + let delta = clock.getDelta(); + // Clamp the delta to a maximum value to prevent large jumps, e.g., on the first frame or after tab refocus. + delta = Math.min(delta, 0.1); + + // Update controls + controls.update(); if (!isPaused) { - const timePassed = deltaTime * simulationSpeed; - simulationTime += timePassed; - // Advance current date by days - currentDate.setDate(currentDate.getDate() + timePassed); + // Advance simulation time using milliseconds for precision + const incrementMs = delta * 1000 * timeScale * TIME_SPEED_FACTOR; + simulationTime.setTime(simulationTime.getTime() + incrementMs); + + // Sun's self-rotation (can be slower and independent of timeScale) + sun.rotation.y += 0.005 * delta; + + const maxTrailPoints = 200; + const worldPosition = new THREE.Vector3(); + + planets.forEach(p => { + const orbitalPeriodMs = p.orbitalPeriodDays * MS_IN_A_DAY; + const angleIncrement = (incrementMs / orbitalPeriodMs) * (2 * Math.PI); + p.pivot.rotation.y += angleIncrement; + + // Planet's self-rotation (can also be constant) + p.planet.rotation.y += 0.05 * delta; + + // Update trail + p.planet.getWorldPosition(worldPosition); + p.trailPoints.push(worldPosition.clone()); + + if (p.trailPoints.length > maxTrailPoints) { + p.trailPoints.shift(); + } + + p.trail.geometry.setFromPoints(p.trailPoints); + }); + + // Moon's orbit (also scaled by timeScale) + const moonOrbitalPeriodMs = MOON_ORBIT_DAYS * MS_IN_A_DAY; + const moonAngleIncrement = (incrementMs / moonOrbitalPeriodMs) * (2 * Math.PI); + moonPivot.rotation.y += moonAngleIncrement; } - - // Update Date Display - dateDisplay.textContent = currentDate.toDateString(); - sun.rotation.y += 0.0005 * simulationSpeed * deltaTime; + // Update time display every frame + updateTimeDisplay(); - celestialBodies.forEach(body => { - if (!body.pivot || !body.data.period) return; - - const angle = (simulationTime * ORBIT_SPEED_FACTOR) / body.data.period * (2 * Math.PI); - body.pivot.rotation.y = angle; - - body.object.rotation.y += 0.05 * deltaTime * simulationSpeed; - }); - - // Update labels - labels.forEach(labelData => { - const { object, element } = labelData; - if (!element) return; - const vector = new THREE.Vector3(); - object.getWorldPosition(vector); - vector.project(camera); - - const x = (vector.x * 0.5 + 0.5) * window.innerWidth; - const y = (vector.y * -0.5 + 0.5) * window.innerHeight; - - element.style.transform = `translate(-50%, -50%) translate(${x}px, ${y}px)`; - }); - - controls.update(); renderer.render(scene, camera); } + animate(); // Handle window resize @@ -331,3 +386,6 @@ window.addEventListener('resize', () => { camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); + +// Initial call to set time +updateTimeDisplay(); diff --git a/index.php b/index.php index a94a96e..d1ecee0 100644 --- a/index.php +++ b/index.php @@ -7,27 +7,7 @@ -
-
-
- - -
-
- - -
-
- -
- - - - Speed: 1x -
- +
@@ -41,7 +21,10 @@
- +
+ + +
-
Sun
-
Mercury
-
Venus
-
Earth
-
Mars
-
Jupiter
-
Saturn
-
Uranus
-
Neptune
-
Io
-
Europa
-
Ganymede
-
Callisto
-
Titan
-
Triton
\ No newline at end of file