Yesterday, I was able to pick back up with Three.js by coding up a simulation of the Moon travelling around the Earth. I eased myself back in by copying a simulation of the Earth passing Mars in their respective orbits. The result was a working solution, but perhaps not the best solution. Today I hope to see if I can do better.
In the Mars simulation, I positioned both Earth and Mars with absolute X & Y coordinates, with the Sun at (0,0). I accomplished this with simple sines and cosines primarily because I needed those absolute coordinates to calculate the orientation of the Earth camera pointing at Mars. Also, I like tormenting kids with trig in 3D Game Programming for Kids.
Anyhow, for the Moon simulator, I repeated the absolute X & Y coordinates for the Moon, though I offset them by the Earth's position to give the appearance of orbiting. It worked, but that's not an effective 3D programming technique. The proper way to do this is create a new earth-centric frame of reference for the Moon. In Three.js, this is done by creating an empty
Object3D
object and adding it to the Earth: var moon_orbit = new THREE.Object3D();
earth.add(moon_orbit);
I then add the Moon to this frame of reference and move the Moon 100 units away from the center of this new frame of reference: moon_orbit.add(moon);
moon.position.set(0, 100, 0);
The order of those two operations does not matter in Three.js, but it is easier to follow as shown.It occurs to me that I can stick the earth-cam-looking-at-the-moon into this same frame of reference. When this frame of reference turns to give the Moon the semblance of an orbit, the camera will turn right along with it:
moon_orbit.add(earth_cam);
earth_cam.rotation.set(Math.PI/2, 0, 0);
Rotating this frame of reference is pretty simple. In my animate()
function, I update the rotation around the Z axis (pointing out of the screen) a tiny bit on each call: function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
if (pause) return;
time = time + speed;
var e_angle = time * 0.001;
earth.position.set(350* Math.cos(e_angle), 350* Math.sin(e_angle), 0);
var m_angle = time * 0.01;
moon_orbit.rotation.set(0, 0, m_angle);
}
That is a darn sight easier to read than the sine and cosine for the Earth. It also much improves on setting the X & Y coordinates as I was doing yesterday: // Ew.
moon.position.set(
100* Math.cos(m_angle) + earth.position.x,
100* Math.sin(m_angle) + earth.position.y,
0
);
Most importantly, this is another example that I can use to teach kids about frame of reference in the book.Obviously, I can improve upon the Earth's orbit as well, but I may leave it as-is in the book to make the transition to or from the Mars simulator easier. That or I could leave it as a challenge for the more industrious readers.
The end result code and simulation are available in editable format. Once the code is hidden, the controls are: C (or Space) to toggle the camera, P to pause, and 1, 2, or 3 to change the speed of the simulation.
This stuff is starting to come back to me. I make pick up with an entirely new game tomorrow. Or I may add planet and satellite rotation to the mix.
Day #633
example?
ReplyDelete