Rotating 3D planet facelift: actually looks like a sphere now (scaled dx); nicer looking slave shield; random code cleanups

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2067 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
avolkov
2005-12-14 01:41:37 +00:00
parent e0f08a9bc2
commit a1c02c4d06
+269 -205
View File
@@ -60,6 +60,9 @@ void arith_frame_blit (FRAME srcFrame, RECT *rsrc, FRAME dstFrame, RECT *rdst, i
void getpixelarray(DWORD *array, FRAME FramePtr, int width, int height); void getpixelarray(DWORD *array, FRAME FramePtr, int width, int height);
#define SHIELD_GLOW_COMP 120
#define SHIELD_REFLECT_COMP 100
#define NUM_BATCH_POINTS 64 #define NUM_BATCH_POINTS 64
#define USE_3D_PLANET 1 #define USE_3D_PLANET 1
#define RADIUS 37 #define RADIUS 37
@@ -67,16 +70,13 @@ void getpixelarray(DWORD *array, FRAME FramePtr, int width, int height);
#define TWORADIUS (RADIUS << 1) #define TWORADIUS (RADIUS << 1)
//RADIUS^2 //RADIUS^2
#define RADIUS_2 (RADIUS * RADIUS) #define RADIUS_2 (RADIUS * RADIUS)
// distance beyond which all pixels are transparent (for aa)
#define RADIUS_THRES ((RADIUS + 1) * (RADIUS + 1))
#define DIAMETER (TWORADIUS + 1) #define DIAMETER (TWORADIUS + 1)
#define DIFFUSE_BITS 24 #define DIFFUSE_BITS 24
#if 0 static inline UBYTE
#define GET_LIGHT(val, dif, sp) \ GET_LIGHT (UBYTE val, DWORD dif, UBYTE sp)
( (UBYTE)min ((sp) + \
( ( ( (DWORD)(val) << DIFFUSE_BITS ) - (DWORD)(val) * (dif) ) >> DIFFUSE_BITS ) \
, 255) )
#endif
UBYTE GET_LIGHT (UBYTE val, DWORD dif, UBYTE sp)
{ {
DWORD i = (DWORD)val << DIFFUSE_BITS; DWORD i = (DWORD)val << DIFFUSE_BITS;
i -= val * dif; i -= val * dif;
@@ -99,14 +99,17 @@ UBYTE GET_LIGHT (UBYTE val, DWORD dif, UBYTE sp)
DWORD light_diff[DIAMETER][DIAMETER]; DWORD light_diff[DIAMETER][DIAMETER];
UBYTE light_spec[DIAMETER][DIAMETER]; UBYTE light_spec[DIAMETER][DIAMETER];
typedef struct typedef struct
{ {
POINT p[4]; POINT p[4];
DWORD m[4]; DWORD m[4];
} MAP3D_POINT; } MAP3D_POINT;
MAP3D_POINT map_rotate[DIAMETER][DIAMETER]; MAP3D_POINT map_rotate[DIAMETER][DIAMETER];
//POINT map_rotate[DIAMETER][DIAMETER];
typedef struct { typedef struct
{
double x, y, z; double x, y, z;
} POINT3; } POINT3;
@@ -263,13 +266,13 @@ RenderPhongMask (POINT loc)
POINT pt; POINT pt;
POINT3 light, view; POINT3 light, view;
double lrad; double lrad;
DWORD step; const DWORD step = 1 << DIFFUSE_BITS;
int y, x; int y, x;
#define LIGHT_INTENS 0.4 #define LIGHT_INTENS 0.3
#define AMBIENT_LIGHT 0.1 #define AMBIENT_LIGHT 0.2
#define MSHI 2 #define MSHI 2
#define LIGHT_Z 1.2 #define LIGHT_Z 1.2
// lrad is the distance from the sun to the planet // lrad is the distance from the sun to the planet
lrad = sqrt (loc.x * loc.x + loc.y * loc.y); lrad = sqrt (loc.x * loc.x + loc.y * loc.y);
// light is the sun's position. the z-coordinate is whatever // light is the sun's position. the z-coordinate is whatever
@@ -285,36 +288,37 @@ RenderPhongMask (POINT loc)
view.x = 0; view.x = 0;
view.y = 0; view.y = 0;
view.z = 1.0; view.z = 1.0;
step = 1 << DIFFUSE_BITS;
for (pt.y = 0, y = -RADIUS; pt.y <= TWORADIUS; ++pt.y, y++) for (pt.y = 0, y = -RADIUS; pt.y <= TWORADIUS; ++pt.y, y++)
{ {
DWORD y_2; DWORD y_2 = y * y;
y_2 = y * y;
for (pt.x = 0, x = -RADIUS; pt.x <= TWORADIUS; ++pt.x, x++) for (pt.x = 0, x = -RADIUS; pt.x <= TWORADIUS; ++pt.x, x++)
{ {
DWORD x_2, rad_2, stepint; DWORD x_2 = x * x;
DWORD rad_2 = x_2 + y_2;
DWORD diff_int;
POINT3 norm, rvec; POINT3 norm, rvec;
double diff, spec = 0.0, fb; double diff, spec = 0.0, fb;
x_2 = x * x;
rad_2 = x_2 + y_2; if (rad_2 < RADIUS_THRES)
if (rad_2 <= RADIUS_2)
{ {
// norm is the sphere's surface normal. // norm is the sphere's surface normal.
norm.x = (double)x; norm.x = (double)x;
norm.y = (double)y; norm.y = (double)y;
norm.z = (sqrt (RADIUS_2 - x_2) * sqrt (RADIUS_2 - y_2)) / norm.z = (sqrt (RADIUS_2 - x_2) * sqrt (RADIUS_2 - y_2)) /
RADIUS; RADIUS;
P3norm(&norm,&norm); P3norm (&norm, &norm);
// diffuse component is norm dot light // diffuse component is norm dot light
diff =P3dot (&norm, &light); diff = P3dot (&norm, &light);
// negative diffuse is bad // negative diffuse is bad
if(diff < 0) if (diff < 0)
diff = 0.0; diff = 0.0;
// specular highlight is the phong equation: // specular highlight is the phong equation:
// (rvec dot view)^MSHI // (rvec dot view)^MSHI
// where rvec = (2*diff)*norm - light (reflection of light // where rvec = (2*diff)*norm - light (reflection of light
// around norm) // around norm)
P3mult (&rvec,&norm,2 * diff); P3mult (&rvec, &norm, 2 * diff);
P3sub (&rvec, &rvec, &light); P3sub (&rvec, &rvec, &light);
fb = P3dot (&rvec, &view); fb = P3dot (&rvec, &view);
if (fb > 0.0) if (fb > 0.0)
@@ -324,24 +328,27 @@ RenderPhongMask (POINT loc)
// adjust for the ambient light // adjust for the ambient light
if (diff < AMBIENT_LIGHT) if (diff < AMBIENT_LIGHT)
diff = AMBIENT_LIGHT; diff = AMBIENT_LIGHT;
// stepint allows us multiply by a ratio without using // Now we antialias the edge of the spere to look nice
if (rad_2 > RADIUS_2)
{
diff *= 1 - (sqrt(rad_2) - RADIUS);
if (diff < 0)
diff = 0;
}
// diff_int allows us multiply by a ratio without using
// floating-point. // floating-point.
// instead of color*diff, we use ((color << 24) - // instead of color*diff, we use ((color << 24) -
// stepint*color) >> 24 // stepint*color) >> 24
stepint = step - (DWORD)(diff * step + 0.5); diff_int = step - (DWORD)(diff * step + 0.5);
// Now we antialias the edge of the spere to look nice
if(rad_2 > (RADIUS - 1) * (RADIUS - 1)) }
{ else
DWORD r; { // outside sphere bounds
r = rad_2 - (RADIUS - 1) * (RADIUS - 1); diff_int = 1 << 31;
stepint += (step >> 7) * (r + 1); }
if (stepint > step)
stepint = step; light_diff[pt.y][pt.x] = diff_int;
} light_spec[pt.y][pt.x] = (UBYTE)(spec * 255);
} else
stepint = 1 << 31;
light_diff[pt.y][pt.x] = (DWORD)stepint;
light_spec[pt.y][pt.x] = (UBYTE)(spec*255);
} }
} }
} }
@@ -349,74 +356,82 @@ RenderPhongMask (POINT loc)
//create_aa_points creates weighted averages for //create_aa_points creates weighted averages for
// 4 points around the 'ideal' point at x,y // 4 points around the 'ideal' point at x,y
// the concept is to compute the weight based on the // the concept is to compute the weight based on the
// distance from the integer location poinnts to the ideal point // distance from the integer location points to the ideal point
static void static void
create_aa_points (MAP3D_POINT *ppt, double x, double y) create_aa_points (MAP3D_POINT *ppt, double x, double y)
{ {
double deltax = 0, deltay = 0, inv_deltax, inv_deltay; double deltax, deltay, inv_deltax, inv_deltay;
COORD nextx, nexty; COORD nextx, nexty;
COUNT i; COUNT i;
double d1, d2, d3, d4, m[4]; double d1, d2, d3, d4, m[4];
if (x < 0)
x = 0;
else if (x >= MAP_HEIGHT)
x = MAP_HEIGHT - 1;
if (y < 0)
y = 0;
else if (y >= MAP_HEIGHT)
y = MAP_HEIGHT - 1;
// get the integer value of this point // get the integer value of this point
ppt->p[0].x = (COORD)(0.5 + x); ppt->p[0].x = (COORD)x;
ppt->p[0].y = (COORD)(0.5 + y); ppt->p[0].y = (COORD)y;
if (ppt->p[0].x >= TWORADIUS) deltax = x - ppt->p[0].x;
ppt->p[0].x = TWORADIUS; deltay = y - ppt->p[0].y;
else if (ppt->p[0].x != 0)
deltax = x - ppt->p[0].x; // if this point doesn't need modificaton, set m[0]=0
if (ppt->p[0].y >= TWORADIUS)
ppt->p[0].y = TWORADIUS;
else if (ppt->p[0].y != 0)
deltay = y - ppt->p[0].y;
//if this point doesn't need modificaton, set m[0]=0
if (deltax == 0 && deltay == 0) if (deltax == 0 && deltay == 0)
ppt->m[0] = 0;
else
{ {
//get the neighbboring points surrounding the 'ideal' poinnt ppt->m[0] = 0;
if (deltax != 0) return;
nextx = ppt->p[0].x + ((deltax > 0) ? 1 : -1);
else
nextx = ppt->p[0].x;
if (deltay != 0)
nexty = ppt->p[0].y + ((deltay > 0) ? 1 : -1);
else
nexty = ppt->p[0].y;
//(x1,y)
ppt->p[1].x = nextx;
ppt->p[1].y = ppt->p[0].y;
//(x,y1)
ppt->p[2].x = ppt->p[0].x;
ppt->p[2].y = nexty;
//(x1y1)
ppt->p[3].x = nextx;
ppt->p[3].y = nexty;
//the square 1x1, so opposite poinnts are at 1-delta
inv_deltax = 1.0 - fabs (deltax);
inv_deltax *= inv_deltax;
inv_deltay = 1.0 - fabs (deltay);
inv_deltay *= inv_deltay;
deltax *= deltax;
deltay *= deltay;
//d1-d4 contain the distances from the poinnts to the ideal point
d1 = sqrt (deltax + deltay);
d2 = sqrt (inv_deltax + deltay);
d3 = sqrt (deltax + inv_deltay);
d4 = sqrt (inv_deltax + inv_deltay);
//compute the weights. the sum(ppt->m[])=65536
m[0] = 1 / (1 + d1 * (1 / d2 + 1 / d3 + 1 / d4));
m[1] = m[0] * d1 / d2;
m[2] = m[0] * d1 / d3;
m[3] = m[0] * d1 / d4;
for (i=0; i<4; i++)
ppt->m[i] = (DWORD)((1 << 16) * m[i] + 0.5);
} }
// get the neighboring points surrounding the 'ideal' point
if (deltax != 0)
nextx = ppt->p[0].x + 1;
else
nextx = ppt->p[0].x;
if (deltay != 0)
nexty = ppt->p[0].y + 1;
else
nexty = ppt->p[0].y;
//(x1,y)
ppt->p[1].x = nextx;
ppt->p[1].y = ppt->p[0].y;
//(x,y1)
ppt->p[2].x = ppt->p[0].x;
ppt->p[2].y = nexty;
//(x1y1)
ppt->p[3].x = nextx;
ppt->p[3].y = nexty;
//the square 1x1, so opposite poinnts are at 1-delta
inv_deltax = 1.0 - fabs (deltax);
inv_deltax *= inv_deltax;
inv_deltay = 1.0 - fabs (deltay);
inv_deltay *= inv_deltay;
deltax *= deltax;
deltay *= deltay;
//d1-d4 contain the distances from the poinnts to the ideal point
d1 = sqrt (deltax + deltay);
d2 = sqrt (inv_deltax + deltay);
d3 = sqrt (deltax + inv_deltay);
d4 = sqrt (inv_deltax + inv_deltay);
//compute the weights. the sum(ppt->m[])=65536
m[0] = 1 / (1 + d1 * (1 / d2 + 1 / d3 + 1 / d4));
m[1] = m[0] * d1 / d2;
m[2] = m[0] * d1 / d3;
m[3] = m[0] * d1 / d4;
for (i = 0; i < 4; i++)
ppt->m[i] = (DWORD)((1 << 16) * m[i] + 0.5);
} }
//get_avg_rgb creates either a red, green, or blue value by //get_avg_rgb creates either a red, green, or blue value by
//computing the weightd averages of the 4 points in p1 //computing the weightd averages of the 4 points in p1
static UBYTE static UBYTE
get_avg_rgb (DWORD p1[4], DWORD mult[4], COUNT offset) { get_avg_rgb (DWORD p1[4], DWORD mult[4], COUNT offset)
{
COUNT i, j; COUNT i, j;
UBYTE c; UBYTE c;
DWORD ci = 0; DWORD ci = 0;
@@ -431,8 +446,9 @@ get_avg_rgb (DWORD p1[4], DWORD mult[4], COUNT offset) {
} }
ci >>= 16; ci >>= 16;
//check for overflow //check for overflow
if ( ci > 255) if (ci > 255)
ci = 255; ci = 255;
return ((UBYTE)ci); return ((UBYTE)ci);
} }
@@ -441,45 +457,63 @@ get_avg_rgb (DWORD p1[4], DWORD mult[4], COUNT offset) {
void void
SetPlanetTilt (int angle) SetPlanetTilt (int angle)
{ {
int x, y, y_2; int x, y;
double multx = (MAP_HEIGHT / M_PI) / RADIUS; const double multx = (MAP_HEIGHT / M_PI);
double multy = (MAP_HEIGHT / M_PI) / RADIUS; const double multy = (MAP_HEIGHT / M_PI);
const double xadj = ((double)MAP_HEIGHT / 2.0);
for (y = -RADIUS; y <= RADIUS; y++) for (y = -RADIUS; y <= RADIUS; y++)
{ {
y_2 = y * y; int y_2 = y * y;
for (x = -RADIUS; x <= RADIUS; x++) for (x = -RADIUS; x <= RADIUS; x++)
{ {
double dx, dy, newx, newy; double dx, dy, newx, newy;
double da, rad, rad2; double da, rad, rad_2;
double xa, ya;
MAP3D_POINT *ppt = &map_rotate[y + RADIUS][x + RADIUS]; MAP3D_POINT *ppt = &map_rotate[y + RADIUS][x + RADIUS];
rad2 = x * x + y_2;
if (rad2 <= RADIUS_2) { rad_2 = x * x + y_2;
rad = sqrt (rad2);
da = atan2 ((double)y, (double)x); if (rad_2 >= RADIUS_THRES)
// compute the planet-tilt { // pixel won't be present
if (angle != 0) {
dx = rad * cos (da + M_DEG2RAD * angle);
dy = rad * sin (da + M_DEG2RAD * angle);
} else {
dx = x;
dy = y;
}
//Map the sphere onto a plane
newx = RADIUS * (multx * acos (-dx / RADIUS));
newy = RADIUS * (multy * acos (-dy / RADIUS));
create_aa_points (ppt, newx, newy);
} else {
ppt->p[0].x = x + RADIUS; ppt->p[0].x = x + RADIUS;
ppt->p[0].y = y + RADIUS; ppt->p[0].y = y + RADIUS;
ppt->m[0] = 0; ppt->m[0] = 0;
continue;
} }
rad = sqrt (rad_2);
// antialiasing goes beyond the actual radius
if (rad >= RADIUS)
rad = (double)RADIUS - 0.1;
da = atan2 ((double)y, (double)x);
// compute the planet-tilt
da += M_DEG2RAD * angle;
dx = rad * cos (da);
dy = rad * sin (da);
// Map the sphere onto a plane
xa = acos (-dx / RADIUS);
ya = acos (-dy / RADIUS);
newx = multx * xa;
newy = multy * ya;
// Adjust for vertical curvature
if (ya <= 0.05 || ya >= 3.1 /* almost PI */)
newx = xadj; // exact centerline
else
newx = xadj + ((newx - xadj) / sin (ya));
create_aa_points (ppt, newx, newy);
} }
} }
} }
//init_zoom_array //init_zoom_array
// evaluate the function 5/6*(1-e^(-x/14)) to get a decelerating zoom // evaluate the function 5/6*(1-e^(-x/14)) to get a decelerating zoom
// on entering planet orbit. This gives is nearly equivalent to what // on entering planet orbit. This gives us nearly equivalent to what
// the 3DO does. // the 3DO does.
#define ZOOM_TIME (1.13) #define ZOOM_TIME (1.13)
#define ZOOM_FACT1 (6.0 / 5) #define ZOOM_FACT1 (6.0 / 5)
@@ -499,83 +533,93 @@ init_zoom_array (COUNT *zoom_arr)
(1 - exp (-(i + 1) / (ZOOM_FACT2 * num_frames)))); (1 - exp (-(i + 1) / (ZOOM_FACT2 * num_frames))));
} }
zoom_arr[i] = base; zoom_arr[i] = base;
return i; return i;
} }
//CreateShieldMask //CreateShieldMask
// The shield is created in two parts. This routine creates the Halo. // The shield is created in two parts. This routine creates the Halo.
// The red tint of the planet is currently applied in RenderLevelMasks // The red tint of the planet is currently applied in RenderLevelMasks
// This was done because the shield lows, and needs to modfy how the planet // This was done because the shield glows and needs to modify how the planet
// gets lit. urrently, the planet area is transparent in the mask made by // gets lit. Currently, the planet area is transparent in the mask made by
// this routine, but a filter can be applied if desired too. // this routine, but a filter can be applied if desired too.
//Outer diameter of HALO // HALO rim size
#define SHIELD_RADIUS (RADIUS + 6) #define SHIELD_HALO 7
#define SHIELD_DIAM ((SHIELD_RADIUS << 1) + 1) #define SHIELD_RADIUS (RADIUS + SHIELD_HALO)
#define SHIELD_RADIUS_2 (SHIELD_RADIUS * SHIELD_RADIUS) #define SHIELD_DIAM ((SHIELD_RADIUS << 1) + 1)
static void CreateShieldMask (void) #define SHIELD_RADIUS_2 (SHIELD_RADIUS * SHIELD_RADIUS)
{ #define SHIELD_RADIUS_THRES ((SHIELD_RADIUS + 1) * (SHIELD_RADIUS + 1))
#define SHIELD_HALO_GLOW (SHIELD_GLOW_COMP + SHIELD_REFLECT_COMP)
#define SHIELD_HALO_GLOW_MIN (SHIELD_HALO_GLOW >> 2)
DWORD rad2, clear, *rgba, *p_rgba, p; static void
UBYTE red_nt; CreateShieldMask (void)
{
DWORD clear, *rgba, *p_rgba;
int x, y; int x, y;
FRAME ShieldFrame; FRAME ShieldFrame;
DWORD aa_delta, aa_delta2;
ShieldFrame = pSolarSysState->Orbit.ShieldFrame; ShieldFrame = pSolarSysState->Orbit.ShieldFrame;
rgba = pSolarSysState->Orbit.ScratchArray; rgba = pSolarSysState->Orbit.ScratchArray;
p_rgba = rgba; p_rgba = rgba;
// This is a non-transparent red for the halo
red_nt = 222;
// This is 100% transparent. // This is 100% transparent.
clear = frame_mapRGBA (ShieldFrame, 0, 0, 0, 0); clear = frame_mapRGBA (ShieldFrame, 0, 0, 0, 0);
aa_delta = SHIELD_RADIUS_2 - (SHIELD_RADIUS - 1) * (SHIELD_RADIUS - 1);
aa_delta2 = (RADIUS + 1) * (RADIUS + 1) - RADIUS_2;
for (y = -SHIELD_RADIUS; y <= SHIELD_RADIUS; y++) for (y = -SHIELD_RADIUS; y <= SHIELD_RADIUS; y++)
{ {
for (x = -SHIELD_RADIUS; x <= SHIELD_RADIUS; x++) for (x = -SHIELD_RADIUS; x <= SHIELD_RADIUS; x++, p_rgba++)
{ {
rad2 = x * x + y * y; int rad_2 = x * x + y * y;
if (rad2 <= SHIELD_RADIUS_2) // This is a non-transparent red for the halo
{ int red = SHIELD_HALO_GLOW;
//Inside the halo int alpha = 255;
if (rad2 <= RADIUS_2) double rad;
// The mask for the planet
p=clear; if (rad_2 >= SHIELD_RADIUS_THRES)
else { // outside all bounds
{ *p_rgba = clear;
// The halo itself continue;
UBYTE red = red_nt; }
if (rad2 < (RADIUS + 1) * (RADIUS + 1)) // Inside the halo
{ if (rad_2 <= RADIUS_2)
DWORD r; { // planet's pixels, ours transparent
r = rad2 - RADIUS_2; *p_rgba = clear;
red = (UBYTE)(red_nt * r / aa_delta2); continue;
} }
else if (rad2 > (RADIUS + 2) * (RADIUS + 2))
{ // The halo itself
DWORD r; rad = sqrt (rad_2);
r = rad2 - ((RADIUS + 1) * (RADIUS + 1));
red = (UBYTE)red - (red * r / (SHIELD_RADIUS_2 -
RADIUS_2 + 1));
}
p = frame_mapRGBA (ShieldFrame, red, 0, 0, 255);
}
}
else
p = clear;
*p_rgba++ = p; if (rad <= RADIUS + 0.8)
{ // pixels common between the shield and planet
// do antialiasing using alpha
alpha = (int) (red * (rad - RADIUS));
red = 255;
}
else
{ // shield pixels
red -= (int) ((red - SHIELD_HALO_GLOW_MIN) * (rad - RADIUS)
/ SHIELD_HALO);
if (red < 0)
red = 0;
}
*p_rgba = frame_mapRGBA (ShieldFrame, red, 0, 0, alpha);
} }
} }
process_rgb_bmp (ShieldFrame, rgba, SHIELD_DIAM, SHIELD_DIAM); process_rgb_bmp (ShieldFrame, rgba, SHIELD_DIAM, SHIELD_DIAM);
SetFrameHot (ShieldFrame, MAKE_HOT_SPOT (SHIELD_RADIUS + 1, SetFrameHot (ShieldFrame, MAKE_HOT_SPOT (SHIELD_RADIUS + 1,
SHIELD_RADIUS + 1)); SHIELD_RADIUS + 1));
{ {
// Applythe shield to the topo data // Apply the shield to the topo data
UBYTE a; UBYTE a;
int blit_type; int blit_type;
FRAME tintFrame = pSolarSysState->Orbit.TintFrame; FRAME tintFrame = pSolarSysState->Orbit.TintFrame;
DWORD p;
#ifdef USE_ALPHA_SHIELD #ifdef USE_ALPHA_SHIELD
a = 200; a = 200;
blit_type = 0; blit_type = 0;
@@ -601,6 +645,7 @@ RenderLevelMasks (int offset)
{ {
POINT pt; POINT pt;
DWORD *rgba, *p_rgba; DWORD *rgba, *p_rgba;
DWORD clear;
int x, y; int x, y;
DWORD p, *pixels; DWORD p, *pixels;
FRAME MaskFrame; FRAME MaskFrame;
@@ -611,66 +656,85 @@ RenderLevelMasks (int offset)
clock_t t1; clock_t t1;
t1 = clock (); t1 = clock ();
#endif #endif
rgba = pSolarSysState->Orbit.ScratchArray; rgba = pSolarSysState->Orbit.ScratchArray;
p_rgba = rgba; p_rgba = rgba;
// Choose the correct Frame to write to // Choose the correct Frame to write to
MaskFrame = SetAbsFrameIndex (pSolarSysState->Orbit.PlanetFrameArray, MaskFrame = SetAbsFrameIndex (pSolarSysState->Orbit.PlanetFrameArray,
(COUNT)(offset + 1)); (COUNT)(offset + 1));
clear = frame_mapRGBA (MaskFrame, 0, 0, 0, 0);
pixels = pSolarSysState->Orbit.lpTopoMap; pixels = pSolarSysState->Orbit.lpTopoMap;
for (pt.y = 0, y = -RADIUS; pt.y <= TWORADIUS; ++pt.y, ++y) for (pt.y = 0, y = -RADIUS; pt.y <= TWORADIUS; ++pt.y, ++y)
{ {
for (pt.x = 0, x = -RADIUS; pt.x <= TWORADIUS; ++pt.x, ++x) for (pt.x = 0, x = -RADIUS; pt.x <= TWORADIUS; ++pt.x, ++x, ++p_rgba)
{ {
UBYTE c[3]; UBYTE c[3];
DWORD diffus; DWORD diffus = light_diff[pt.y][pt.x];
UBYTE spec; UBYTE spec = light_spec[pt.y][pt.x];
COUNT i; int i;
DWORD p1[4]; DWORD p1[4];
MAP3D_POINT *ppt = &map_rotate[pt.y][pt.x]; MAP3D_POINT *ppt = &map_rotate[pt.y][pt.x];
diffus = light_diff[pt.y][pt.x];
spec = light_spec[pt.y][pt.x]; if (diffus >= (1 << DIFFUSE_BITS))
if (diffus < 1 << DIFFUSE_BITS) { // full diffusion
*p_rgba = clear;
continue;
}
if (ppt->m[0] == 0)
{ {
if (ppt->m[0] == 0) p = pixels[PT_TO_ADDR (ppt->p[0].y, ppt->p[0].x) +
{ offset];
p = pixels[PT_TO_ADDR (ppt->p[0].y, ppt->p[0].x) + c[0] = (UBYTE)(p >> 8);
offset]; c[1] = (UBYTE)(p >> 16);
c[0] = (UBYTE)(p >> 8); c[2] = (UBYTE)(p >> 24);
c[1] = (UBYTE)(p >> 16); }
c[2] = (UBYTE)(p >> 24); else
} {
else for (i = 0; i < 4; i++)
{ p1[i] = pixels[PT_TO_ADDR (ppt->p[i].y, ppt->p[i].x)
for (i = 0; i < 4; i++) + offset];
p1[i] = pixels[PT_TO_ADDR (ppt->p[i].y, ppt->p[i].x) for (i = 1; i < 4; i++)
+ offset]; c[i - 1] = get_avg_rgb (p1, ppt->m, i);
for (i = 1; i < 4; i++) }
c[i-1] = get_avg_rgb (p1, ppt->m, i);
} // Apply the lighting model. This also bounds the sphere
// Apply the lighting model. This also bounds the sphere // to make it circular.
// to make it circular. if (pSolarSysState->pOrbitalDesc->data_index & PLANET_SHIELDED)
if (pSolarSysState->pOrbitalDesc->data_index & PLANET_SHIELDED) {
{ int r;
c[2] = GET_LIGHT (255, diffus, spec);
c[1] = GET_LIGHT ((UBYTE)(c[1] >> 1), diffus, spec); // add lite red filter (3/4) component
c[0] = GET_LIGHT ((UBYTE)(c[0] >> 1), diffus, spec); c[1] = (c[1] >> 1) + (c[1] >> 2);
} c[0] = (c[0] >> 1) + (c[0] >> 2);
else
{ c[2] = GET_LIGHT (c[2], diffus, spec);
c[2] = GET_LIGHT (c[2], diffus, spec); c[1] = GET_LIGHT (c[1], diffus, spec);
c[1] = GET_LIGHT (c[1], diffus, spec); c[0] = GET_LIGHT (c[0], diffus, spec);
c[0] = GET_LIGHT (c[0], diffus, spec);
} // The shield is glow + reflect (+ filter for others)
*p_rgba++ = frame_mapRGBA ( r = GET_LIGHT (SHIELD_REFLECT_COMP, diffus, spec);
MaskFrame, c[2], c[1], c[0], (UBYTE)255); r = r + SHIELD_GLOW_COMP + c[2];
if (r > 255)
r = 255;
c[2] = r;
} }
else else
*p_rgba++ = frame_mapRGBA (MaskFrame, 0, 0, 0, 0); {
c[2] = GET_LIGHT (c[2], diffus, spec);
c[1] = GET_LIGHT (c[1], diffus, spec);
c[0] = GET_LIGHT (c[0], diffus, spec);
}
*p_rgba = frame_mapRGBA (MaskFrame, c[2], c[1], c[0], 255);
} }
} }
// Map the rgb bitmap onto the SDL_Surface // Map the rgb bitmap onto the SDL_Surface
process_rgb_bmp (MaskFrame, rgba, DIAMETER, DIAMETER); process_rgb_bmp (MaskFrame, rgba, DIAMETER, DIAMETER);
SetFrameHot (MaskFrame, MAKE_HOT_SPOT (RADIUS + 1, RADIUS + 1)); SetFrameHot (MaskFrame, MAKE_HOT_SPOT (RADIUS + 1, RADIUS + 1));
#if PROFILE #if PROFILE
t += clock() - t1; t += clock() - t1;
if (frames_done == MAP_WIDTH) if (frames_done == MAP_WIDTH)
@@ -1608,7 +1672,7 @@ GeneratePlanetMask (PPLANET_DESC pPlanetDesc, BOOLEAN IsEarth)
RenderPhongMask (loc); RenderPhongMask (loc);
if (pPlanetDesc->data_index & PLANET_SHIELDED) if (pPlanetDesc->data_index & PLANET_SHIELDED)
CreateShieldMask(); CreateShieldMask ();
SetContext (OldContext); SetContext (OldContext);