Menu:

¯
RSS  RSS 2.0

Earth

Go get flash player

I wanned to do this ever since I saw André Michelle's Earth. So, I grabbed «atmospherical» texture (with ocean mask) by Tor Øra, cloud map by James Hastings-Trew, and finally did it.

How? Really easy. All you need to know to get your math done is that texture coordiantes are actually lattitude and longitude (this is also known as equi-rectangular projection), so you need to calculate lattitude and longitude instead of source pixel coordinates in code stub I gave you before.

So, let's do the math. Real pros like you and me should not be affraid of math, right?

Go get flash player

Since planets are far far away when we look at them from space, let's ignore effects of perspective. Doing so, we end up with rather simple geometry.

We know that BC = x and AB = FG = y. Given sphere radius R, and using obvious angle equalities ψ = LBEC and φ = LGHF, we find that sin(ψ) = x/BE and sin(φ) = y/FH. Now note that BE² = BD² = AD² - AB² and AD = FH = R, and you're done :) You can compare that with the way Andre did it,

I created a gradient table in flash8 where the x and y values are stored as color-components (red/blue). I switch to 3dmax where I build my model (here a sphere) and map the gradient onto the mesh. The next step is to look, where the original positions of the texture was by comparing the source and the projected bitmap and compose a displacement map of it. I think this is the screwiest workaround I've ever done in flash.

and you will see just how much the math rules (and that he was right about last part).


Map code

All right kids, screw the math, just grab the code below:

import flash.display.BitmapData;
import flash.geom.*;

// BitmapData to hold the map
var R:Number = 129;
var tmp:BitmapData = new BitmapData (R, R);

// color factors
var af = 16777216, rf = 65536, gf = 256, bf = 1;

// this may take a while
for (var x:Number = 0; x < R; x++)
for (var y:Number = 0; y < R; y++) {
    // horizontal radius
    var r:Number = Math.sqrt(R*R - y*y);

    // lattitude & longitude
    var phi:Number = Math.asin( y/R );
    var psi:Number = (x < r) ? Math.asin( x/r ) : Math.PI/2;

    // set source pixel coordinates for (x,y)
    var xS:Number = Math.round(R * psi / (Math.PI/2));
    var yS:Number = Math.round(R * phi / (Math.PI/2));

    // calculate & store displacement in B & G channels
    tmp.setPixel (x, y, bf * (128 + xS - x) + gf * (128 + yS - y));
}

// build complete map using symmetry
var map:BitmapData = new BitmapData (R * 2, R * 2, true, 0);
map.copyPixels(tmp, tmp.rectangle, new Point (R, R));
var m:Matrix = new Matrix (); m.scale(1, -1); m.translate(R, R +2);
map.draw(tmp, m, new ColorTransform (1, -1, 1, 1, 0, 255, 0, 0));
m = new Matrix (); m.scale(-1, 1); m.translate(2*R +2, 0);
map.draw(map, m, new ColorTransform (1, 1, -1, 1, 0, 0, 255, 0));

// show the result: make the screenshot, crop it, and import
_root.attachBitmap (map, _root.getNextHighestDepth ());

Comments