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?
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,
and you will see just how much the math rules (and that he was right about last part).
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 ());