3D planet is now antialiased, from PhracturedBlue

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@336 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
gewlitys
2002-12-05 02:38:57 +00:00
parent 86f74ceaf3
commit 19a7ee3820
+142 -34
View File
@@ -64,7 +64,13 @@ DWORD **getpixelarray(FRAME FramePtr,int width, int height);
#endif
DWORD phong[DIAMETER][DIAMETER];
POINT map_rotate[DIAMETER][DIAMETER];
typedef struct
{
POINT p[4];
DWORD m[4];
} MAP3D_POINT;
MAP3D_POINT map_rotate[DIAMETER][DIAMETER];
//POINT map_rotate[DIAMETER][DIAMETER];
void
RenderTopography (BOOLEAN Reconstruct)
@@ -109,7 +115,7 @@ RenderTopography (BOOLEAN Reconstruct)
pBatch = &BatchArray[0];
for (i = 0; i < NUM_BATCH_POINTS; ++i, ++pBatch)
{
SetPrimNextLink (pBatch, i + 1);
SetPrimNextLink (pBatch, (COUNT)(i + 1));
SetPrimType (pBatch, POINT_PRIM);
}
SetPrimNextLink (&pBatch[-1], END_OF_LIST);
@@ -196,7 +202,7 @@ RenderPhongMask (POINT loc)
POINT pt,light;
double lrad;
int lmag;
int step;
DWORD step;
double lmag2;
#define LIGHT_MULT 0.8
@@ -247,6 +253,99 @@ RenderPhongMask (POINT loc)
}
}
}
//create_aa_points creates weighted averages for
// 4 points around the 'ideal' point at x,y
// the concept is to compute the weight based on the
// distance from the integer location poinnts to the ideal point
void create_aa_points(MAP3D_POINT *ppt, double x, double y)
{
double deltax=0,deltay=0,inv_deltax,inv_deltay;
COORD nextx,nexty;
COUNT i;
double d1,d2,d3,d4,m[4];
// get the integer value of this point
ppt->p[0].x=(COORD)(0.5+x);
ppt->p[0].y=(COORD)(0.5+y);
if(ppt->p[0].x > TWORADIUS) {
ppt->p[0].x=TWORADIUS;
} else if(ppt->p[0].x != 0) {
deltax=x-ppt->p[0].x;
}
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) {
ppt->m[0]=0;
} else {
//get the neighbboring points surrounding the 'ideal' poinnt
if(deltax!=0) {
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_avg_rgb creates either a red, green, or blue value by
//computing the weightd averages of the 4 points in p1
UBYTE get_avg_rgb(DWORD p1[4],DWORD mult[4],COUNT offset) {
COUNT i,j;
UBYTE c;
DWORD ci;
i=offset<<3;
ci=0;
//sum(mult[])==65536
//c is the red/green/blue value of this pixel
for(j=0;j<4;j++)
{
c=(UBYTE)(p1[j] >> i);
ci+=c*mult[j];
}
ci=ci>>16;
//check for overflow
if (ci> 255)
ci=255;
return((UBYTE)ci);
}
// SetPlanetTilt creates 'map_rotate' to map the topo data
// for a tilted planet. It also does the sphere->plane mapping
void
@@ -261,9 +360,9 @@ SetPlanetTilt (int angle)
y_2=y*y;
for(x=-RADIUS;x<=RADIUS;x++)
{
double dx, dy;
double dx, dy, newx, newy;
double da,rad,rad2;
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=sqrt(rad2);
@@ -277,15 +376,13 @@ SetPlanetTilt (int angle)
dy=y;
}
//Map the sphere onto a plane
ppt->x=(int)(0.5+RADIUS*(multx*acos(-dx/RADIUS)));
if(ppt->x > TWORADIUS)
ppt->x=TWORADIUS;
ppt->y=(int)(0.5+RADIUS*(multy*acos(-dy/RADIUS)));
if(ppt->y > TWORADIUS)
ppt->y=TWORADIUS;
newx=RADIUS*(multx*acos(-dx/RADIUS));
newy=RADIUS*(multy*acos(-dy/RADIUS));
create_aa_points(ppt,newx,newy);
} else {
ppt->x=x+RADIUS;
ppt->y=y+RADIUS;
ppt->p[0].x=x+RADIUS;
ppt->p[0].y=y+RADIUS;
ppt->m[0]=0;
}
}
}
@@ -304,7 +401,8 @@ SetPlanetTilt (int angle)
#define SHIELD_RADIUS_2 SHIELD_RADIUS*SHIELD_RADIUS
void CreateShieldMask()
{
DWORD rad2,red,red_nt,clear,**rgba,p;
DWORD rad2,clear,**rgba,p;
UBYTE red_nt;
int x,y;
FRAME ShieldFrame;
DWORD aa_delta,aa_delta2;
@@ -313,8 +411,6 @@ void CreateShieldMask()
CreateDrawable (WANT_PIXMAP, SHIELD_DIAM, SHIELD_DIAM, 1)
);
rgba=(DWORD **)malloc(sizeof(DWORD *)*(SHIELD_DIAM));
// This is a 'transparent' red for the planet mask.
red=frame_mapRGBA (ShieldFrame,255,0,0,200);
// This is a non-transparent red for the halo
red_nt=180;
// This is 100% transparent.
@@ -335,16 +431,16 @@ void CreateShieldMask()
p=frame_mapRGBA(ShieldFrame,0,0,0,255);
} else {
// The halo itself
DWORD red=red_nt;
UBYTE red=red_nt;
if(rad2>(SHIELD_RADIUS-1)*(SHIELD_RADIUS-1))
{
DWORD r;
r=rad2-(SHIELD_RADIUS-1)*(SHIELD_RADIUS-1);
red=red_nt-red_nt*r/aa_delta;
red=red_nt-(UBYTE)(red_nt*r/aa_delta);
} else if (rad2 < (RADIUS+3)*(RADIUS+3)) {
DWORD r;
r = rad2 - (RADIUS+2)*(RADIUS+2);
red = red_nt*r/aa_delta2;
red = (UBYTE)(red_nt*r/aa_delta2);
}
p=frame_mapRGBA (ShieldFrame,red,0,0,255);
@@ -394,28 +490,40 @@ RenderLevelMasks (int offset)
rgba[pt.y]=malloc(sizeof(DWORD)*(DIAMETER));
for (pt.x = 0, x=-RADIUS; pt.x <= TWORADIUS; ++pt.x,++x)
{
int c1,c2,c3;
UBYTE c[3];
int ph;
COUNT i;
DWORD p1[4];
MAP3D_POINT *ppt=&map_rotate[pt.y][pt.x];
rgba[pt.y][pt.x]=0;
ph=phong[pt.y][pt.x];
p=pixels[map_rotate[pt.y][pt.x].y][map_rotate[pt.y][pt.x].x+offset];
c1=(p&0xff000000)>>24;
c2=(p&0x00ff0000)>>16;
c3=(p&0x0000ff00)>>8;
if(ph < 1<<PHONG_BITS) {
if(ppt->m[0]==0) {
p=pixels[ppt->p[0].y][ppt->p[0].x+offset];
c[0]=(UBYTE)(p>>8);
c[1]=(UBYTE)(p>>16);
c[2]=(UBYTE)(p>>24);
} else {
for(i=0;i<4;i++) {
p1[i]=pixels[ppt->p[i].y][ppt->p[i].x+offset];
}
for(i=1;i<4;i++) {
c[i-1]=get_avg_rgb(p1,ppt->m,i);
}
}
// fixed planet surfaces being too dark
// ctab shifts were previously >> 3 .. -Mika
// Apply the lightinng model. This also bounds the sphere to make it circular
if(ph < 1<<PHONG_BITS) {
if(pSolarSysState->ShieldFrame) {
c1=GET_PHONG(255,ph);
c2=GET_PHONG(c2>>1,ph);
c3=GET_PHONG(c3>>1,ph);
c[2]=GET_PHONG(255,ph);
c[1]=GET_PHONG(c[1]>>1,ph);
c[0]=GET_PHONG(c[0]>>1,ph);
} else {
c1=GET_PHONG(c1,ph);
c2=GET_PHONG(c2,ph);
c3=GET_PHONG(c3,ph);
c[2]=GET_PHONG(c[2],ph);
c[1]=GET_PHONG(c[1],ph);
c[0]=GET_PHONG(c[0],ph);
}
rgba[pt.y][pt.x]=frame_mapRGBA (MaskFrame,(UBYTE)c1,(UBYTE)c2,(UBYTE)c3,(UBYTE)255);
rgba[pt.y][pt.x]=frame_mapRGBA (MaskFrame,c[2],c[1],c[0],(UBYTE)255);
} else {
rgba[pt.y][pt.x]=frame_mapRGBA (MaskFrame,0,0,0,0);
}
@@ -899,7 +1007,7 @@ MakeGasGiant (COUNT num_bands, PSBYTE DepthArray, PRECT pRect, SIZE
& (((1 << RANGE_SHIFT) * NUM_BAND_COLORS) - 1);
}
MakeStorms (4 + ((COUNT)Random () & 3) + 1, DepthArray);
MakeStorms ((COUNT)(4 + ((COUNT)Random () & 3) + 1), DepthArray);
DitherMap (DepthArray);
}
@@ -1136,7 +1244,7 @@ GeneratePlanetMask (PPLANET_DESC pPlanetDesc, BOOLEAN IsEarth)
SeedRandom (old_seed);
SetPlanetMusic (pPlanetDesc->data_index & ~PLANET_SHIELDED);
SetPlanetMusic ((UBYTE)(pPlanetDesc->data_index & ~PLANET_SHIELDED));
}
int