Advertisement
jarekmor

Solar 3D

Feb 2nd, 2025
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.   <meta charset="UTF-8">
  5.   <title>3D Solar System</title>
  6.   <style>
  7.     body { margin: 0; overflow: hidden; }
  8.     #ui {
  9.       position: absolute;
  10.       top: 10px;
  11.       left: 10px;
  12.       background: rgba(255, 255, 255, 0.8);
  13.       padding: 10px;
  14.       font-family: sans-serif;
  15.       z-index: 10;
  16.       border-radius: 4px;
  17.     }
  18.     #ui label {
  19.       margin-right: 5px;
  20.     }
  21.     #ui > div {
  22.       margin-bottom: 10px;
  23.     }
  24.   </style>
  25. </head>
  26. <body>
  27.   <!-- UI controls -->
  28.   <div id="ui">
  29.     <div>
  30.       <label for="scaleSlider">Simulation Scale:</label>
  31.       <input id="scaleSlider" type="range" min="0.5" max="2" step="0.01" value="1">
  32.       <span id="scaleValue">1</span>
  33.     </div>
  34.     <div>
  35.       <label for="rotationSpeedSlider">Self-Rotation Speed:</label>
  36.       <input id="rotationSpeedSlider" type="range" min="0" max="0.1" step="0.001" value="0.02">
  37.       <span id="rotationSpeedValue">0.02</span>
  38.     </div>
  39.     <div>
  40.       <label for="orbitalSpeedSlider">Orbital Speed:</label>
  41.       <input id="orbitalSpeedSlider" type="range" min="0" max="0.1" step="0.001" value="0.04">
  42.       <span id="orbitalSpeedValue">0.04</span>
  43.     </div>
  44.     <div>
  45.       <label for="zoomSlider">Zoom:</label>
  46.       <input id="zoomSlider" type="range" min="50" max="300" step="1" value="150">
  47.       <span id="zoomValue">150</span>
  48.     </div>
  49.   </div>
  50.  
  51.   <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
  52.   <script>
  53.     // Create scene, camera, and renderer
  54.     const scene = new THREE.Scene();
  55.     const camera = new THREE.PerspectiveCamera(
  56.       75, window.innerWidth / window.innerHeight, 0.1, 2000
  57.     );
  58.     const renderer = new THREE.WebGLRenderer({ antialias: true });
  59.     renderer.setSize(window.innerWidth, window.innerHeight);
  60.     document.body.appendChild(renderer.domElement);
  61.  
  62.     // Create a group for the entire solar system (for scaling)
  63.     const solarSystem = new THREE.Group();
  64.     scene.add(solarSystem);
  65.  
  66.     // Add ambient light
  67.     const ambientLight = new THREE.AmbientLight(0x404040);
  68.     scene.add(ambientLight);
  69.  
  70.     // Add background stars
  71.     function addStars() {
  72.       const starsGeometry = new THREE.BufferGeometry();
  73.       const starsCount = 10000;
  74.       const positions = new Float32Array(starsCount * 3);
  75.       for (let i = 0; i < starsCount; i++) {
  76.         const x = (Math.random() - 0.5) * 2000;
  77.         const y = (Math.random() - 0.5) * 2000;
  78.         const z = (Math.random() - 0.5) * 2000;
  79.         positions[i * 3] = x;
  80.         positions[i * 3 + 1] = y;
  81.         positions[i * 3 + 2] = z;
  82.       }
  83.       starsGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
  84.       const starsMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 1 });
  85.       const starField = new THREE.Points(starsGeometry, starsMaterial);
  86.       scene.add(starField);
  87.     }
  88.     addStars();
  89.  
  90.     // Helper function to create a text sprite for labels
  91.     function createTextSprite(message, parameters = {}) {
  92.       const fontface = parameters.fontface || 'Arial';
  93.       const fontsize = parameters.fontsize || 48;
  94.       const borderThickness = parameters.borderThickness || 4;
  95.       const borderColor = parameters.borderColor || { r: 0, g: 0, b: 0, a: 1.0 };
  96.       const backgroundColor = parameters.backgroundColor || { r: 255, g: 255, b: 255, a: 1.0 };
  97.  
  98.       const canvas = document.createElement('canvas');
  99.       const context = canvas.getContext('2d');
  100.       context.font = fontsize + "px " + fontface;
  101.       const metrics = context.measureText(message);
  102.       const textWidth = metrics.width;
  103.       canvas.width = textWidth + borderThickness * 2;
  104.       canvas.height = fontsize + borderThickness * 2;
  105.       context.font = fontsize + "px " + fontface;
  106.  
  107.       // Draw background and border
  108.       context.fillStyle = `rgba(${backgroundColor.r}, ${backgroundColor.g}, ${backgroundColor.b}, ${backgroundColor.a})`;
  109.       context.strokeStyle = `rgba(${borderColor.r}, ${borderColor.g}, ${borderColor.b}, ${borderColor.a})`;
  110.       context.lineWidth = borderThickness;
  111.       context.fillRect(0, 0, canvas.width, canvas.height);
  112.       context.strokeRect(0, 0, canvas.width, canvas.height);
  113.      
  114.       // Draw text
  115.       context.fillStyle = 'rgba(0, 0, 0, 1.0)';
  116.       context.textAlign = "center";
  117.       context.textBaseline = "middle";
  118.       context.fillText(message, canvas.width / 2, canvas.height / 2);
  119.  
  120.       const texture = new THREE.CanvasTexture(canvas);
  121.       texture.needsUpdate = true;
  122.       const spriteMaterial = new THREE.SpriteMaterial({ map: texture });
  123.       const sprite = new THREE.Sprite(spriteMaterial);
  124.       sprite.scale.set(canvas.width * 0.02, canvas.height * 0.02, 1);
  125.       return sprite;
  126.     }
  127.  
  128.     // Create the Sun (central light source) with higher resolution geometry
  129.     const sunGeometry = new THREE.SphereGeometry(5, 64, 64);
  130.     const sunMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });
  131.     const sun = new THREE.Mesh(sunGeometry, sunMaterial);
  132.     solarSystem.add(sun);
  133.  
  134.     // Add a point light inside the Sun
  135.     const sunLight = new THREE.PointLight(0xffffff, 1.5, 1000);
  136.     sun.add(sunLight);
  137.  
  138.     // Add Sun label
  139.     const sunLabel = createTextSprite("Sun", { fontsize: 48 });
  140.     sunLabel.position.set(0, 6.5, 0);
  141.     sun.add(sunLabel);
  142.  
  143.     // Planetary data (all eight planets; values scaled for visualization)
  144.     const planets = [
  145.       { name: 'Mercury', radius: 0.4,  distance: 10, speed: 0.08,  color: 0x808080 },
  146.       { name: 'Venus',   radius: 0.9,  distance: 15, speed: 0.06,  color: 0xffa500 },
  147.       { name: 'Earth',   radius: 1,    distance: 20, speed: 0.04,  color: 0x0000ff },
  148.       { name: 'Mars',    radius: 0.5,  distance: 25, speed: 0.03,  color: 0xff0000 },
  149.       { name: 'Jupiter', radius: 2.5,  distance: 35, speed: 0.02,  color: 0xffd700 },
  150.       { name: 'Saturn',  radius: 2,    distance: 45, speed: 0.014, color: 0xffd700 },
  151.       { name: 'Uranus',  radius: 1.5,  distance: 55, speed: 0.01,  color: 0x00ffff },
  152.       { name: 'Neptune', radius: 1.5,  distance: 65, speed: 0.008, color: 0x00008b },
  153.     ];
  154.  
  155.     // Array to hold planet objects for animation
  156.     const planetMeshes = [];
  157.  
  158.     // Create planets, orbits, and labels with higher resolution geometry
  159.     planets.forEach((planet, index) => {
  160.       const geometry = new THREE.SphereGeometry(planet.radius, 64, 64);
  161.       const material = new THREE.MeshPhongMaterial({ color: planet.color });
  162.       const mesh = new THREE.Mesh(geometry, material);
  163.       const angle = Math.random() * Math.PI * 2;
  164.       mesh.position.set(
  165.         Math.cos(angle) * planet.distance,
  166.         0,
  167.         Math.sin(angle) * planet.distance
  168.       );
  169.  
  170.       // Create orbit path
  171.       const orbitGeometry = new THREE.BufferGeometry();
  172.       const orbitPoints = [];
  173.       const segments = 128;
  174.       for (let i = 0; i <= segments; i++) {
  175.         const a = (i / segments) * Math.PI * 2;
  176.         orbitPoints.push(new THREE.Vector3(
  177.           Math.cos(a) * planet.distance,
  178.           0,
  179.           Math.sin(a) * planet.distance
  180.         ));
  181.       }
  182.       orbitGeometry.setFromPoints(orbitPoints);
  183.       const orbitLine = new THREE.Line(
  184.         orbitGeometry,
  185.         new THREE.LineBasicMaterial({ color: 0x444444 })
  186.       );
  187.       solarSystem.add(orbitLine);
  188.  
  189.       // Add planet label
  190.       const label = createTextSprite(planet.name, { fontsize: 48 });
  191.       label.position.set(0, planet.radius + 1, 0);
  192.       mesh.add(label);
  193.  
  194.       // Optional inclination for a 3D effect.
  195.       mesh.rotation.x = (Math.PI / 180) * (index * 5);
  196.  
  197.       solarSystem.add(mesh);
  198.  
  199.       planetMeshes.push({
  200.         ...planet,
  201.         mesh,
  202.         angle
  203.       });
  204.     });
  205.  
  206.     // Position the camera and set initial zoom (z value)
  207.     camera.position.set(0, 50, 150);
  208.     camera.lookAt(0, 0, 0);
  209.  
  210.     // Mouse-drag rotation controls for the camera.
  211.     let mouseDown = false;
  212.     let mouseX = 0;
  213.     let mouseY = 0;
  214.     document.addEventListener('mousedown', (e) => {
  215.       mouseDown = true;
  216.       mouseX = e.clientX;
  217.       mouseY = e.clientY;
  218.     });
  219.     document.addEventListener('mouseup', () => {
  220.       mouseDown = false;
  221.     });
  222.     document.addEventListener('mousemove', (e) => {
  223.       if (mouseDown) {
  224.         const deltaX = e.clientX - mouseX;
  225.         const deltaY = e.clientY - mouseY;
  226.         camera.position.x += deltaX * 0.1;
  227.         camera.position.y -= deltaY * 0.1;
  228.         mouseX = e.clientX;
  229.         mouseY = e.clientY;
  230.       }
  231.     });
  232.  
  233.     // UI Sliders for simulation scale, self-rotation speed, orbital speed, and zoom.
  234.     const scaleSlider = document.getElementById('scaleSlider');
  235.     const scaleValue = document.getElementById('scaleValue');
  236.     scaleSlider.addEventListener('input', () => {
  237.       const scale = parseFloat(scaleSlider.value);
  238.       solarSystem.scale.set(scale, scale, scale);
  239.       scaleValue.textContent = scale;
  240.     });
  241.  
  242.     const rotationSpeedSlider = document.getElementById('rotationSpeedSlider');
  243.     const rotationSpeedValue = document.getElementById('rotationSpeedValue');
  244.     let rotationSpeed = parseFloat(rotationSpeedSlider.value);
  245.     rotationSpeedSlider.addEventListener('input', () => {
  246.       rotationSpeed = parseFloat(rotationSpeedSlider.value);
  247.       rotationSpeedValue.textContent = rotationSpeed;
  248.     });
  249.  
  250.     const orbitalSpeedSlider = document.getElementById('orbitalSpeedSlider');
  251.     const orbitalSpeedValue = document.getElementById('orbitalSpeedValue');
  252.     let orbitalSpeed = parseFloat(orbitalSpeedSlider.value);
  253.     orbitalSpeedSlider.addEventListener('input', () => {
  254.       orbitalSpeed = parseFloat(orbitalSpeedSlider.value);
  255.       orbitalSpeedValue.textContent = orbitalSpeed;
  256.     });
  257.  
  258.     const zoomSlider = document.getElementById('zoomSlider');
  259.     const zoomValue = document.getElementById('zoomValue');
  260.     zoomSlider.addEventListener('input', () => {
  261.       const zoom = parseFloat(zoomSlider.value);
  262.       camera.position.z = zoom;
  263.       zoomValue.textContent = zoom;
  264.     });
  265.  
  266.     // Animation loop
  267.     function animate() {
  268.       requestAnimationFrame(animate);
  269.  
  270.       // Update each planet's orbit and self-rotation.
  271.       planetMeshes.forEach(planet => {
  272.         planet.angle += planet.speed * orbitalSpeed;
  273.         planet.mesh.position.x = Math.cos(planet.angle) * planet.distance;
  274.         planet.mesh.position.z = Math.sin(planet.angle) * planet.distance;
  275.         planet.mesh.rotation.y += rotationSpeed;
  276.       });
  277.  
  278.       // Rotate the Sun using self-rotation speed (a fraction of orbital speed)
  279.       sun.rotation.y += rotationSpeed * 0.1;
  280.  
  281.       // Ensure all label sprites face the camera.
  282.       solarSystem.traverse(child => {
  283.         if (child instanceof THREE.Sprite) {
  284.           child.lookAt(camera.position);
  285.         }
  286.       });
  287.  
  288.       camera.lookAt(0, 0, 0);
  289.       renderer.render(scene, camera);
  290.     }
  291.  
  292.     window.addEventListener('resize', () => {
  293.       camera.aspect = window.innerWidth / window.innerHeight;
  294.       camera.updateProjectionMatrix();
  295.       renderer.setSize(window.innerWidth, window.innerHeight);
  296.     });
  297.  
  298.     animate();
  299.   </script>
  300. </body>
  301. </html>
  302.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement