Tuesday, October 2, 2012

Three.js Planets

‹prev | My Chain | next›

I just can't help myself. One of my favorite things to do with 3D is make astronomical simulations. I find the topic fun and 3D suits it. So I return to my retrograde motion simulator, but this time with Three.js.

For the Sun, I create an ambient light throughout the scene. This ambient light will give the Sun its color, which I specify with the ambient attribute for the Phong material that will play the role of the Sun's surface:
  var ambient = new THREE.AmbientLight(0xffffff); 
  scene.add(ambient);
  
  var surface = new THREE.MeshPhongMaterial({ambient: 0xFFD700});
  var star = new THREE.SphereGeometry(50, 10, 10);
  var sun = new THREE.Mesh(star, surface);
  scene.add(sun);
  
  var sunlight = new THREE.PointLight(0xffffff, 5, 1000);
  sun.add(sunlight)
That works to give the Sun a nice yellow, but to make it behave as a light source for the rest of the Solar System, I add a point light to the sun, making it fairly bright and extending well out into space (1000).

To get the Phong materials to work, I need to use the WebGL renderer instead of the canvas renderer that I default most of my work to (for greater compatibility). I suppose in Gaming JavaScript that I will have to start with MeshBasicMaterial, which ought to be fine for the Sun. Not so much for planets.

Anyhow, with that, I have my Sun:


Next up, I add my planets:
var surface = new THREE.MeshPhongMaterial({ambient: 0x000000, color: 0x0000cd});
  var planet = new THREE.SphereGeometry(20);
  var earth = new THREE.Mesh(planet, surface);
  earth.position.set(250, 0, 0);
  scene.add(earth);
Since I am using Phong materials, I get a nice dark-side of the Earth effect:


When I do the same for Mars, however, I notice that it is looking... stretched:


At first, I think that I will be forced to switch to an orthographic camera to deal with this. That is not necessarily a bad thing as it probably makes a little more sense for astronomy simulations. After all, the vast distances that are usually involved make "perspective" a quaint concept. But in this case, I don't have to introduce the difference between cameras. I had been setting the field of view for the camera to a rather wide 75°:
  var camera = new THREE.PerspectiveCamera(75, aspect_ratio, 1, 10000);
  camera.position.z = 500;
  scene.add(camera);
Cutting that down (and moving back a bit), does the trick:


I still may switch to the orthographic camera, but at least now I am not forced to.

Last up, is movement of the planets. Back when I was first doing these simulations, I would add the planet to a frame of reference and rotate the frame of reference. This time, however, I stick with simple geometry:
  clock = new THREE.Clock();

  function animate() {
    requestAnimationFrame(animate);
    
    var t = clock.getElapsedTime();
    
    var e_angle = 3 * t * 0.1;
    earth.position.set(250* Math.cos(e_angle), 250* Math.sin(e_angle), 0);

    // Now, show what the camera sees on the screen:
    renderer.render(scene, camera);
  }
  
  animate();
If memory serves, knowing the X-Y position in scene coordinate space will come in handy.

And that does the trick:


That is a good stopping point for tonight. Up tomorrow, I will add cameras on the two planets to witness retrograde motion. And maybe some background stars.

Editable source code

Day #527

No comments:

Post a Comment