Close
Simone Seagle

Simone Seagle

Independent Web and Educational Software Developer

Read More

Search

Play

The Selenographic Phases of the Moon

Tilt or zoom in and out on the animation using mouse scroll or touch gestures. Click here to see it fullscreen.

About the Art

The Selenographic Phases of the Moon, found on a collection from the Public Domain Review, is part of a folio called the Harmonia Macrocosmia. This book from 1660 showcases different models of the universe, from before the Copernican revolution and after as well as constellations. Some people say that it is the most beautiful celestial atlas ever published. The cartographer, Andreas Cellarius, was a Dutch/German Latin School rector. The word "Selenography" means the study of the features of the moon, so frankly the name of this piece is confusing and slightly redundant, especially because it depicts the moon having no features at all.

I worked for two years in the planetarium in the New Mexico Museum of Natural History and Science where I spent plenty of time contemplating (among other things) the phases of the moon and how to teach and understand them. Even though it shows a pre-Copernican revolution version of the solar system, I think this piece shows quite well why the moon looks the way it does throughout the phases. I chose not to animate the Sun along its orbit in this picture for two (basically lazy) reasons - 1, the background was very difficult to Photoshop because of the thin lines that radiate out from the sun that I would ALSO have to animate, and 2, trying to animate moon phases while the sun is also moving made my brain hurt. I personally think the phases of the moon is one of the best points of the heliocentric model of the solar system because otherwise you're seriously running logical circles around yourself to get it to appear properly.

What you see of the rotating moon is actually how the moon looks to us on Earth, instead of this animation being a model of the system itself. If it were a model of the real system, the white side of the moon would, of course, always be facing the sun. What this animation shows is the relative positions of the sun and the moon and the phase they produce as we see them. That's another reason why this animation took me so long - because how it works is not obvious at first glance, but I wanted to stay true to Cellarius's original print. I thought it would be cool to have the earth also rotating, but that couldn't be accomplished with the original art. I found an equirectangular projection of the earth on Wikipedia and then edited it to look like the original art, and for good measure threw in a specular map so that only the ocean is shiny.

The lines on the bottom right show how the Earth-moon-sun system really works because you see the light side always facing the sun, and the lines to the middle indicate the edge of the light from our perspective.

About the Programming

I set out to animate this using pixi.js like I usually do, but I realized before I even started that it wasn't going to work very well and I immediately decided that I would push myself out of my comfort zone and go for 3D. For whatever reason, I feel like my brain tends to work better in 2D than 3D, but the phases of the moon just don't make sense in 2D.

This is my first shot at doing 3D programming, and I started with a course that was part of a bundle I got on MakeUseOf deals for 20 bucks. The course used Babylon.js rather than three.js which seems to be more popular, so that's what I'm using. I'd love to give some sort of rundown on the plusses and minuses of each one, but it's not going to happen this time. So far, for this project, I had zero complaints with Babylon.js and it seemed to be easier than I had expected to use.

Even so, this animation took me about six weeks of work on and off because it took so long to get it the way I wanted it to look. I kept feeling like it needed something, so I kept adding to it. I also kept making mistakes, such as making the moon go around the wrong way and having the phases show up the mirror image of how they were supposed to look.

I also wound up not having this animation use hover or touch over type of events because they don't really quite make sense in 3D, and Babylon doesn't even have those same type of mouse tracking events, anyway. You can tap on meshes, but I didn't see how you could get the world coordinates of the mouse over. Perhaps you can do it and I gave up too soon - I dunno.

Anyway, almost everything in the animation is based on the angular position of the moon. The halo of the moon is supposed to indicate its brightness, so that grows when the moon is full and shrinks when it is new. In order to show the phases as they appear in the print, I roll the moon around the x and y axis. In real life the moon is tidally locked to the earth so it only spins on one axis.

    // Move the moon and its halo around the orbit
    moon.position.x = radius * Math.cos(angle);
    moon.position.z = radius * Math.sin(angle);

    // Roll the moon to display the phases
    // I have to add Math.PI/2 to everything because of how I made the texture.  If you're not familiar with radians, that means 90°.
    moon.rotation.x = Math.abs(angle- Math.PI) + Math.PI/2;
    moon.rotation.y = -angle + Math.PI/2;

    // Scale the halo appropriately
    var haloScale = (1 + Math.cos(angle))/1.5;
    halo.position.x = radius * Math.cos(angle);
    halo.position.z = radius * Math.sin(angle);
    halo.scaling = new BABYLON.Vector3(haloScale, haloScale, haloScale);

It changes the phase labels (which I numbered clockwise instead of counter-clockwise when I made the images by accident, and they're in Latin so I'm not even sure what they say), the highlight in the bottom left showing which phase the moon is in, and changes the color of the active 3D lineset (5 lines demonstrating the phase view) in the bottom right. In order to do this, I multiply the angle by a number and then take the floor and then the mod to get the index of either the lineset or the image I wish to display. I nicknamed it the phase net because that's what it looks like to me.

// Get the index of the current phase image, then tween out the last one and tween in the next one
    var thisPhase = Math.floor((-angle + 9.7)/Math.PI * 4) % 8;
    if (currentPhase != thisPhase) {
        lastPhase = currentPhase;
        currentPhase = thisPhase;
        //console.log(`start phase ${currentPhase} at angle ${angle}`);
        tweenFrame = 0;
    }
    tweenFrame++;

    // Phase net or lineset version of the above
    var phaseNetPhase = Math.floor((angle + 9.7)/Math.PI * 6) % 12;
    for (var i = 0; i < phaseNet.length; i++) {
        if (i == phaseNetPhase) {
            phaseNet[i].lineSet.color = activePhaseColor;
        } else {
            phaseNet[i].lineSet.color = inactivePhaseColor;
        }
    }

    // Move the right phase image into position.  Instead of hiding it and tweening the alpha (because that looks like crap in Babylon! ) I just hide it under the ground.  Fight me.
    var tween = Math.min(1, tweenFrame * 0.03);
    for (var i = 0; i < phaseImages.length; i++) {
        if (i == currentPhase) {
            phaseImages[i].mesh.position.y = 3 * tween - 0.5;
        } else if (i == lastPhase) {
            phaseImages[i].mesh.position.y = 3 - 3 * tween - 0.5;
    }

The cherubs bob up and down slowly by just modulating their y position with a sine function. That always looks good, so this is a good trick to have for all your animation needs.

    for (var i = 0; i < cherubs.length; i++) {
        // I gave all of the cherubs a slightly different offset and animation period so they wouldn't bob up and down together.
        var newY = 0.85 * Math.sin((frame + cherubs[i].offset)/cherubs[i].freq) + 1.7;
        cherubs[i].mesh.position.y =  newY;
    }

There's more to how I laid it out, but this article turned out to be longer than I intended, so I think I'll just quit while I'm ahead. If you have any questions, please reach out! I love talking about this stuff.