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:
+269
-205
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user