PhracturedBlue's 3D planet implementation

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@279 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
gewlitys
2002-12-01 20:07:56 +00:00
parent 354af5dd92
commit f6776ea8ef
6 changed files with 611 additions and 204 deletions
@@ -25,6 +25,7 @@
#include "sdl_common.h" #include "sdl_common.h"
#include "primitives.h" #include "primitives.h"
#include "rotozoom.h"
typedef struct anidata typedef struct anidata
{ {
@@ -129,6 +130,97 @@ process_font (FRAMEPTR FramePtr, SDL_Surface *img[], int cel_ct)
SetFrameBounds (FramePtr, img[cel_ct]->w, img[cel_ct]->h); SetFrameBounds (FramePtr, img[cel_ct]->w, img[cel_ct]->h);
} }
//stretch_frame
// create a new frame of size neww x newh, and blit a scaled version FramePtr into it
// destroy the old frame if 'destroy' is 1
FRAMEPTR stretch_frame (FRAMEPTR FramePtr, int neww, int newh,int destroy)
{
FRAMEPTR NewFrame;
SDL_Surface *src,*dst;
NewFrame = CaptureDrawable (
CreateDrawable (WANT_PIXMAP, (SIZE)neww, (SIZE)newh, 1)
);
src = ((TFB_Image *)((BYTE *)(FramePtr) + FramePtr->DataOffs))->NormalImg;
dst = ((TFB_Image *)((BYTE *)(NewFrame) + NewFrame->DataOffs))->NormalImg;
SDL_LockSurface (src);
zoomSurfaceRGBA(src, dst, 0);
SDL_UnlockSurface (src);
if(destroy) {
DestroyDrawable (ReleaseDrawable (FramePtr));
}
return(NewFrame);
}
void process_rgb_bmp (FRAMEPTR FramePtr, Uint32 **rgba, int maxx, int maxy)
{
int hx, hy;
int x,y;
SDL_Surface *img;
PutPixelFn putpix;
// TYPE_SET (FramePtr->TypeIndexAndFlags, WANT_PIXMAP << FTYPE_SHIFT);
// INDEX_SET (FramePtr->TypeIndexAndFlags, 1);
hx = hy = 0;
// convert 32-bit png font to indexed
img = ((TFB_Image *)((BYTE *)(FramePtr) + FramePtr->DataOffs))->NormalImg;
SDL_LockSurface (img);
putpix = putpixel_for (img);
for (y = 0; y < maxy; ++y)
{
for (x = 0; x < maxx; ++x)
{
putpix (img, x, y, rgba[y][x]);
}
}
SDL_UnlockSurface (img);
}
// Generate an array of all pixels in FramePtr
// The pixel format is :
// bits 25-32 : red
// bits 17-24 : green
// bits 9-16 : blue
// bits 1-8 : alpha
Uint32 **getpixelarray(FRAMEPTR FramePtr,int width, int height)
{
Uint8 r,g,b,a;
Uint32 p, **map;
SDL_Surface *img;
GetPixelFn getpix;
int x,y;
img = ((TFB_Image *)((BYTE *)(FramePtr) + FramePtr->DataOffs))->NormalImg;
SDL_LockSurface (img);
getpix = getpixel_for (img);
map=(Uint32 **)malloc(sizeof(Uint32 *)*(height+1));
for (y=0;y<height;y++) {
map[y]=(Uint32 *)calloc(width,sizeof(Uint32));
if(y>=img->h) {
continue;
}
for(x=0;x<img->w;x++) {
p=getpix(img,x,y);
SDL_GetRGBA(p,img->format,&r,&g,&b,&a);
map[y][x]=r<<24 | g<<16 | b<<8 | a;
}
}
SDL_UnlockSurface (img);
map[y]=NULL;
return(map);
}
// Generate a pixel (in the correct format to be applied to FramePtr) from the
// r,g,b,a values supplied
Uint32 frame_mapRGBA (FRAMEPTR FramePtr,Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
SDL_Surface *img= ((TFB_Image *)((BYTE *)(FramePtr) + FramePtr->DataOffs))->NormalImg;
return(SDL_MapRGBA(img->format,r,g,b,a));
}
MEM_HANDLE MEM_HANDLE
_GetCelData (FILE *fp, DWORD length) _GetCelData (FILE *fp, DWORD length)
{ {
@@ -42,6 +42,15 @@ typedef struct tColorY {
/* ---- Prototypes */ /* ---- Prototypes */
/*
zoomSurfaceRGBA()
Zoom the src surface into dst. The zoom amount is determined
by the dimensions of src and dst
*/
int zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int smooth);
/* /*
rotozoomSurface() rotozoomSurface()
+87 -15
View File
@@ -24,13 +24,15 @@
//#include "BlockFile.h" //#include "BlockFile.h"
#include "starcon.h" #include "starcon.h"
#include "libs/graphics/gfx_common.h" #include "libs/graphics/gfx_common.h"
#include "libs/graphics/drawable.h"
#define PLANET_SPIN 0
#define PLANET_SPIN_DEBUG 1
//Added by Chris //Added by Chris
//End Added by Chris //End Added by Chris
//#define KDEBUG //#define KDEBUG
#define SCALE_ROTATE //#define SCALE_ROTATE
//#define SCREEN_WIDTH 320 //#define SCREEN_WIDTH 320
@@ -109,6 +111,7 @@ typedef struct
CCB plCCB[NUM_CELS]; CCB plCCB[NUM_CELS];
CCB *last_zoom_ccb; CCB *last_zoom_ccb;
UBYTE zoom_batch; UBYTE zoom_batch;
#ifdef SCALE_ROTATE #ifdef SCALE_ROTATE
@@ -118,7 +121,7 @@ typedef struct
CCB *pcirc_ccb, *pblur_ccb; CCB *pcirc_ccb, *pblur_ccb;
} PLANET_STUFF; } PLANET_STUFF;
static PLANET_STUFF *planet_stuff; static PLANET_STUFF *planet_stuff=NULL;
#define x0 (planet_stuff->x0) #define x0 (planet_stuff->x0)
#define x1 (planet_stuff->x1) #define x1 (planet_stuff->x1)
@@ -208,7 +211,12 @@ static PLANET_STUFF *planet_stuff;
#define pcirc_ccb (planet_stuff->pcirc_ccb) #define pcirc_ccb (planet_stuff->pcirc_ccb)
#define pblur_ccb (planet_stuff->pblur_ccb) #define pblur_ccb (planet_stuff->pblur_ccb)
#if 0 #if PLANET_SPIN
void add_cel(CCB* cel) {}
void add_cels(CCB* first, CCB* last) {}
void myMapCel(CCB* myCCB, POINT Points[4]) {}
void OpenMathFolio(void) {}
static void static void
build_steps () build_steps ()
{ {
@@ -237,7 +245,7 @@ build_steps ()
ystep[i] = 1; ystep[i] = 1;
#if 0 #if PLANET_SPIN_DEBUG
y = 0; y = 0;
for (i = 0; y < (HEIGHT >> 1); i++) for (i = 0; y < (HEIGHT >> 1); i++)
{ {
@@ -285,7 +293,7 @@ build_tables (int da)
y1[i] >>= 1; y1[i] >>= 1;
y += h; y += h;
#if 0 #if PLANET_SPIN_DEBUG
fprintf (stderr, "%ld: %ld ", i, y); fprintf (stderr, "%ld: %ld ", i, y);
fprintf (stderr, "%ld,%ld -- ", x0[i] >> 16, y0[i] >> 16); fprintf (stderr, "%ld,%ld -- ", x0[i] >> 16, y0[i] >> 16);
fprintf (stderr, "%ld,%ld\n", x1[i] >> 16, y1[i] >> 16); fprintf (stderr, "%ld,%ld\n", x1[i] >> 16, y1[i] >> 16);
@@ -430,18 +438,23 @@ init_rotate_cels ()
--i; --i;
} }
} }
#if 0 #if PLANET_SPIN_DEBUG
fprintf (stderr, "using %d cels for rotate\n", cur_ccb - plCCB); fprintf (stderr, "using %d cels for rotate\n", cur_ccb - plCCB);
#endif #endif
} }
#endif #endif
//SetPlantTilt has moved to plangen.c
#if PLANET_SPIN
void void
SetPlanetTilt (int da) SetPlanetTilt (int da)
{ {
#if 0
int w, i; int w, i;
int j;
j=MAX_PULSE_RED;
if(planet_stuff==NULL) {
planet_stuff=(PLANET_STUFF *)calloc(sizeof(PLANET_STUFF),1);
}
shield_pulse = MAX_PULSE_RED; shield_pulse = MAX_PULSE_RED;
for (i = 0, cur_ccb = plCCB; i < NUM_ROTATE_CELS; i++, cur_ccb++) for (i = 0, cur_ccb = plCCB; i < NUM_ROTATE_CELS; i++, cur_ccb++)
{ {
@@ -482,14 +495,74 @@ SetPlanetTilt (int da)
cur_ccb->ccb_NextPtr = cur_ccb + 1; cur_ccb->ccb_NextPtr = cur_ccb + 1;
} }
} }
#endif
} }
#endif
extern FRAME stretch_frame (FRAME FramePtr, int neww, int newh,int destroy);
extern void RenderLevelMasks(int,int);
// RotatePlanet
// This will take care of zooming into a planet on orbit, generating the planet frames
// And applying the shield.
//The initial size of the planet when zooming. MUST BE ODD
#define PLANET_INIT_ZOOM_SIZE 9
// The speed to zoom in.
#define PLANET_ZOOM_SPEED 2
int int
RotatePlanet (int x, int dx, int dy) RotatePlanet (int x, int da, int dx, int dy, int zoom)
{ {
#if 1 #if !PLANET_SPIN
return (0); STAMP s;
FRAME pFrame[2];
COUNT i,num_frames;
static COUNT scale_amt=PLANET_INIT_ZOOM_SIZE;
// If thiis frame hasn' been generted, generate it
if(!pSolarSysState->isPFADefined[x]) {
RenderLevelMasks(x,da);
pSolarSysState->isPFADefined[x]=1;
}
num_frames=(pSolarSysState->ShieldFrame==0) ? 1 : 2;
pFrame[0]=pSolarSysState->PlanetFrameArray[x];
if(num_frames==2) {
pFrame[1]=pSolarSysState->ShieldFrame;
}
if (zoom) {
// we're zooming in, take care of scalinng the frames
for(i=0;i<num_frames;i++) {
COUNT frameh,this_scale;
if(pSolarSysState->ScaleFrame[i]) {
DestroyDrawable (ReleaseDrawable (pSolarSysState->ScaleFrame[i]));
}
frameh=GetFrameHeight(pFrame[i]);
this_scale=frameh*scale_amt/MAP_HEIGHT;
if(! (this_scale & 0x01)) {
this_scale++;
}
pSolarSysState->ScaleFrame[i] = stretch_frame(pFrame[i],this_scale,this_scale,0);
SetFrameHot (pSolarSysState->ScaleFrame[i], MAKE_HOT_SPOT ((this_scale>>1)+1,(this_scale>>1)+1));
pFrame[i]=pSolarSysState->ScaleFrame[i];
}
scale_amt+=PLANET_ZOOM_SPEED;
//Translate the planet so it comes from the bottom right corner
if(scale_amt > MAP_HEIGHT)
{
scale_amt=MAP_HEIGHT;
}
dx+=dx*(MAP_HEIGHT-scale_amt)/MAP_HEIGHT;
dy+=dy*(MAP_HEIGHT-scale_amt)/MAP_HEIGHT;
if(scale_amt==MAP_HEIGHT) {
scale_amt=PLANET_INIT_ZOOM_SIZE;
zoom=0;
}
}
s.origin.x = dx;
s.origin.y = dy;
for(i=0;i<num_frames;i++) {
s.frame=pFrame[i];
DrawStamp (&s);
}
return(zoom);
// }
#else #else
int i, y; int i, y;
int incr; int incr;
@@ -677,7 +750,6 @@ DrawPlanet (int x, int y, int dy, unsigned int rgb)
{ {
#if 1 #if 1
STAMP s; STAMP s;
s.origin.x = x; s.origin.x = x;
s.origin.y = y; s.origin.y = y;
s.frame = pSolarSysState->TopoFrame; s.frame = pSolarSysState->TopoFrame;
@@ -735,7 +807,7 @@ DrawPlanet (int x, int y, int dy, unsigned int rgb)
else else
tint_ccb[i].ccb_YPos = my << 16; tint_ccb[i].ccb_YPos = my << 16;
tint_ccb[i].ccb_XPos = x << 16; tint_ccb[i].ccb_XPos = x << 16;
*((unsigned int *)tint_ccb[i].ccb_SourcePtr) = rgb | (rgb << 16) | 0x80008000; *((Uint32 *)tint_ccb[i].ccb_SourcePtr) = rgb | (rgb << 16) | 0x80008000;
add_cel (&tint_ccb[i]); add_cel (&tint_ccb[i]);
} }
} }
+21
View File
@@ -213,6 +213,27 @@ FreePlanet (void)
pSolarSysState->TopoFrame = 0; pSolarSysState->TopoFrame = 0;
DestroyColorMap (ReleaseColorMap (pSolarSysState->OrbitalCMap)); DestroyColorMap (ReleaseColorMap (pSolarSysState->OrbitalCMap));
pSolarSysState->OrbitalCMap = 0; pSolarSysState->OrbitalCMap = 0;
for(i=0;i<255;i++) {
DestroyDrawable (ReleaseDrawable (pSolarSysState->PlanetFrameArray[i]));
}
for(i=0;i<2;i++) {
if(pSolarSysState->ScaleFrame[i]) {
DestroyDrawable (ReleaseDrawable (pSolarSysState->ScaleFrame[i]));
pSolarSysState->ScaleFrame[i]=0;
}
}
if(pSolarSysState->ShieldFrame != 0) {
DestroyDrawable (ReleaseDrawable (pSolarSysState->ShieldFrame));
pSolarSysState->ShieldFrame=0;
}
if(pSolarSysState->lpTopoMap!=NULL) {
for(i=0;pSolarSysState->lpTopoMap[i]!=NULL;i++) {
free(pSolarSysState->lpTopoMap[i]);
}
free(pSolarSysState->lpTopoMap);
}
free(pSolarSysState->PlanetFrameArray);
free(pSolarSysState->isPFADefined);
DestroyContext (ReleaseContext (TaskContext)); DestroyContext (ReleaseContext (TaskContext));
TaskContext = 0; TaskContext = 0;
+6
View File
@@ -20,6 +20,7 @@
#define _PLANETS_H #define _PLANETS_H
#define END_INTERPLANETARY START_INTERPLANETARY #define END_INTERPLANETARY START_INTERPLANETARY
typedef unsigned int Uint32;
enum enum
{ {
@@ -163,6 +164,11 @@ typedef struct solarsys_state
PLAN_GEN_FUNC GenFunc; PLAN_GEN_FUNC GenFunc;
FRAME PlanetSideFrame[6]; FRAME PlanetSideFrame[6];
FRAME *PlanetFrameArray;
FRAME ScaleFrame[2];
FRAME ShieldFrame;
BYTE *isPFADefined;
Uint32 **lpTopoMap;
} SOLARSYS_STATE; } SOLARSYS_STATE;
typedef SOLARSYS_STATE *PSOLARSYS_STATE; typedef SOLARSYS_STATE *PSOLARSYS_STATE;
+320 -113
View File
@@ -17,6 +17,11 @@
*/ */
#include "starcon.h" #include "starcon.h"
#include <math.h>
#include <time.h>
#define PROFILE 1
#define ROTATION_TIME 12
extern void DeltaTopography (COUNT num_iterations, PSBYTE DepthArray, extern void DeltaTopography (COUNT num_iterations, PSBYTE DepthArray,
PRECT pRect, SIZE depth_delta); PRECT pRect, SIZE depth_delta);
@@ -27,9 +32,39 @@ void SetPlanetTilt (int da);
void RepairBackRect (PRECT pRect); void RepairBackRect (PRECT pRect);
int RotatePlanet (int x, int dx, int dy); int RotatePlanet (int x, int angle, int dx, int dy,int zoom);
Uint32 frame_mapRGBA (FRAME FramePtr,UBYTE r, UBYTE g, UBYTE b, UBYTE a);
void process_rgb_bmp (FRAME FramePtr, Uint32 **rgba, int maxx, int maxy);
FRAME stretch_frame (FRAME FramePtr, int neww, int newh,int destroy);
Uint32 **getpixelarray(FRAME FramePtr,int width, int height);
#define NUM_BATCH_POINTS 64 #define NUM_BATCH_POINTS 64
#define USE_3D_PLANET 1
#define RADIUS 37
//2*RADIUS
#define TWORADIUS (RADIUS << 1)
//RADIUS^2
#define RADIUS_2 (RADIUS * RADIUS)
#define DIAMETER (TWORADIUS + 1)
#define PHONG_BITS 24
#define GET_PHONG(val, ph) ((((val)<<PHONG_BITS)-((val)*ph))>>PHONG_BITS)
#ifndef M_TWOPI
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define M_TWOPI (M_PI * 2.0)
#endif
#ifndef M_DEG2RAD
#define M_DEG2RAD (M_TWOPI / 360.0)
#endif
Uint32 phong[DIAMETER][DIAMETER];
POINT map_rotate[DIAMETER][DIAMETER];
void void
RenderTopography (BOOLEAN Reconstruct) RenderTopography (BOOLEAN Reconstruct)
@@ -153,107 +188,236 @@ RenderTopography (BOOLEAN Reconstruct)
SetContext (OldContext); SetContext (OldContext);
} }
#if 0 // RenderPhongMask builds a shadow map for the rotating planet
// loc indicates the planets position relavtive to the sun
static void static void
RenderLevelMasks (void) RenderPhongMask (POINT loc)
{ {
COUNT i, num_frames; POINT pt,light;
BYTE AlgoType; double lrad;
SIZE base, d; int lmag;
POINT pt; int step;
PLANDATAPTR PlanDataPtr; double lmag2;
PRIMITIVE BatchArray[NUM_BATCH_POINTS];
register PPRIMITIVE pBatch;
PBYTE lpDst;
PSIZE level_tab;
FRAME DupFrame, MaskFrame;
pBatch = &BatchArray[0]; #define LIGHT_MULT 0.8
for (i = 0; i < NUM_BATCH_POINTS; ++i, ++pBatch) #define AMBIENT_LIGHT 0.05
#define LIGHT_RADIUS 1.6
light.x=(int)(LIGHT_MULT*RADIUS*cos(atan2(-(double)loc.y,-(double)loc.x)));
light.y=(int)(LIGHT_MULT*RADIUS*sin(atan2(-(double)loc.y,-(double)loc.x)));
// light.x=(int)(RADIUS*0.8);
// light.y=(int)(-RADIUS*0.6);
// fprintf(stderr,"light: (%d,%d)->(%d,%d)\n",loc.x,loc.y,light.x,light.y);
lmag=(int)(LIGHT_RADIUS*RADIUS);
lmag2=pow(lmag,2);
step=1<<PHONG_BITS;
for (pt.y = 0; pt.y <= TWORADIUS; ++pt.y)
{ {
SetPrimNextLink (pBatch, i + 1); for (pt.x = 0; pt.x <= TWORADIUS; ++pt.x)
SetPrimType (pBatch, POINT_PRIM); {
int x,y,rad;
Uint32 stepint;
double lrad2;
double intens;
x=pt.x-RADIUS;
y=pt.y-RADIUS;
rad=x*x+y*y;
if(rad<RADIUS_2) {
lrad=((x-light.x)*(x-light.x)+(y-light.y)*(y-light.y));
lrad2=pow(lrad,1);
if (lrad2 >= lmag2) {
intens=AMBIENT_LIGHT;
} else {
intens=1*cos((3.1416/2)*(double)lrad2/(double)lmag2);
if(intens<AMBIENT_LIGHT) {intens=AMBIENT_LIGHT;}
}
stepint=step- (Uint32)(intens*step+0.5);
} else {
stepint=step;
}
phong[pt.y][pt.x]=(int)stepint;
}
}
}
// SetPlanetTilt creates 'map_rotate' to map the topo data
// for a tilted planet. It also does the sphere->plane mapping
void
SetPlanetTilt (int angle)
{
int x,y,y_2;
double multx,multy;
multx=(MAP_HEIGHT/M_PI)/RADIUS;
multy=(MAP_HEIGHT/M_PI)/RADIUS;
for(y=-RADIUS;y<=RADIUS;y++)
{
y_2=y*y;
for(x=-RADIUS;x<=RADIUS;x++)
{
double dx, dy;
double da,rad,rad2;
POINT *ppt=&map_rotate[y+RADIUS][x+RADIUS];
rad2=x*x+y_2;
if(rad2<=RADIUS_2) {
rad=sqrt(rad2);
da=atan2((double)y,(double)x);
// compute the planet-tilt
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
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;
} else {
ppt->x=x+RADIUS;
ppt->y=y+RADIUS;
}
}
}
} }
SetPrimNextLink (&pBatch[-1], END_OF_LIST);
PlanDataPtr = &PlanData[ //CreateShieldMask
pSolarSysState->pOrbitalDesc->data_index & ~PLANET_SHIELDED // The shield is created in two parts. This routine creates the Halo.
]; // The red tint of the planet is currently applied in RenderLevelMasks
base = PlanDataPtr->base_elevation; // This was done because the shield lows, and needs to modfy how the planet
AlgoType = PLANALGO (PlanDataPtr->Type); // gets lit. urrently, the planet area is transparent in the mask made by
// this routine, but a filter can be applied if desired too.
MaskFrame = pSolarSysState->PlanetFrameArray[1]; //Outer diameter of HALO
DupFrame = CaptureDrawable ( #define SHIELD_RADIUS (RADIUS+5)
CreateDrawable (WANT_MASK, #define SHIELD_DIAM ((SHIELD_RADIUS<<1)+1)
(MAP_WIDTH >> 1) - 1, #define SHIELD_RADIUS_2 SHIELD_RADIUS*SHIELD_RADIUS
MAP_HEIGHT, void CreateShieldMask()
1) {
Uint32 rad2,red,red_nt,clear,**rgba,p;
int x,y;
FRAME ShieldFrame;
ShieldFrame = CaptureDrawable (
CreateDrawable (WANT_PIXMAP, SHIELD_DIAM, SHIELD_DIAM, 1)
); );
rgba=(Uint32 **)malloc(sizeof(Uint32 *)*(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=frame_mapRGBA (ShieldFrame,180,0,0,255);
// This is 100% transparent.
clear=frame_mapRGBA (ShieldFrame,0,0,0,0);
for(y=-SHIELD_RADIUS;y<=SHIELD_RADIUS;y++) {
rgba[y+SHIELD_RADIUS]=(Uint32 *)calloc((SHIELD_DIAM),sizeof(Uint32));
for(x=-SHIELD_RADIUS;x<=SHIELD_RADIUS;x++) {
rad2=x*x+y*y;
if(rad2<=SHIELD_RADIUS_2) {
//Inside the halo
if(rad2<=RADIUS_2) {
// The mask for the planet
p=clear;
} else if(rad2<=(RADIUS_2+4*RADIUS+4)) {
// The space between the halo and the planet
p=clear;
} else {
// The halo itself
p=red_nt;
}
} else {
p=clear;
}
level_tab = (PSIZE)((XLAT_DESCPTR)pSolarSysState->XlatPtr)->level_tab; rgba[y+SHIELD_RADIUS][x+SHIELD_RADIUS]=p;
num_frames = GetFrameCount (MaskFrame); }
while (num_frames--) }
process_rgb_bmp(ShieldFrame,rgba,SHIELD_DIAM,SHIELD_DIAM);
SetFrameHot (ShieldFrame, MAKE_HOT_SPOT (SHIELD_RADIUS+1,SHIELD_RADIUS+1));
for (y=-SHIELD_RADIUS; y <= SHIELD_RADIUS; ++y)
{ {
MaskFrame = DecFrameIndex (MaskFrame); free(rgba[y+SHIELD_RADIUS]);
}
free(rgba);
pSolarSysState->ShieldFrame=ShieldFrame;
}
SetContextDrawState (DEST_MASK | DRAW_SUBTRACTIVE); // RenderLevelMasks builds a frame for the rotating planet view
SetContextFGFrame (DupFrame); // offset is effectively the angle of rotation around the planet's axis
ClearDrawable (); // We use the SDL routines to directly write to the SDL_Surface to improve performance
SetContextFGFrame (MaskFrame); void
SetContextDrawState (DEST_MASK | DRAW_ADDITIVE); RenderLevelMasks (int offset)
SetContextClipping (FALSE);
pBatch = &BatchArray[i = NUM_BATCH_POINTS];
lpDst = pSolarSysState->lpTopoData;
for (pt.y = 0; pt.y < MAP_HEIGHT; ++pt.y)
{ {
for (pt.x = 0; pt.x < MAP_WIDTH; ++pt.x) POINT pt;
{ Uint32 **rgba;
d = *lpDst++; int x,y;
if (d >= level_tab[num_frames] Uint32 p,**pixels;
&& (num_frames == 2 FRAME MaskFrame;
|| d < level_tab[num_frames + 1]))
{
--pBatch;
pBatch->Object.Point.x = pt.x;
pBatch->Object.Point.y = pt.y;
if (--i)
continue;
DrawBatch (BatchArray, 0, 0); #if PROFILE
pBatch = &BatchArray[i = NUM_BATCH_POINTS]; static clock_t t=0;
static int frames_done=1;
clock_t t1;
t1=clock();
#endif
rgba=malloc(sizeof(Uint32 *)*(DIAMETER));
// Choose the correct Frame to wrte to
MaskFrame = pSolarSysState->PlanetFrameArray[offset];
pixels=pSolarSysState->lpTopoMap;
for (pt.y = 0, y=-RADIUS; pt.y <= TWORADIUS; ++pt.y,++y)
{
rgba[pt.y]=malloc(sizeof(Uint32)*(DIAMETER));
for (pt.x = 0, x=-RADIUS; pt.x <= TWORADIUS; ++pt.x,++x)
{
int c1,c2,c3;
int ph;
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;
// 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);
} else {
c1=GET_PHONG(c1,ph);
c2=GET_PHONG(c2,ph);
c3=GET_PHONG(c3,ph);
}
rgba[pt.y][pt.x]=frame_mapRGBA (MaskFrame,(UBYTE)c1,(UBYTE)c2,(UBYTE)c3,(UBYTE)255);
} else {
rgba[pt.y][pt.x]=frame_mapRGBA (MaskFrame,0,0,0,0);
} }
} }
} }
// Map the rgb bitmap onto the SDL_Surface
if (i < NUM_BATCH_POINTS) process_rgb_bmp(pSolarSysState->PlanetFrameArray[offset],rgba,DIAMETER,DIAMETER);
SetFrameHot (MaskFrame, MAKE_HOT_SPOT (RADIUS+1,RADIUS+1));
for (pt.y = 0, y=-RADIUS; pt.y <= TWORADIUS; ++pt.y,++y)
{ {
DrawBatch (BatchArray, i, 0); free(rgba[pt.y]);
} }
free(rgba);
SetContextClipping (TRUE); #if PROFILE
if(frames_done==MAP_WIDTH) {
{ t+=clock()-t1;
STAMP s; fprintf(stderr,"frames/sec: %d/%d(msec)=%f\n",frames_done,t,frames_done/((double)t/CLOCKS_PER_SEC));
frames_done=1;
SetContextFGFrame (DupFrame); t=clock()-t1;
s.origin.x = 0; } else {
s.origin.y = 0; t+=clock()-t1;
s.frame = MaskFrame; frames_done++;
DrawStamp (&s);
SetContextFGFrame (MaskFrame);
s.origin.x = MAP_WIDTH;
s.origin.y = 0;
s.frame = DupFrame;
DrawStamp (&s);
}
}
DestroyDrawable (ReleaseDrawable (DupFrame));
} }
#endif #endif
}
#ifdef NOTYET #ifdef NOTYET
static void static void
@@ -320,14 +484,14 @@ DitherMap (PSBYTE DepthArray)
DWORD rand_val; DWORD rand_val;
rand_val = Random (); rand_val = Random ();
*lpDst++ += (1 << (RANGE_SHIFT - 4)) *lpDst++ += (SBYTE) ((1 << (RANGE_SHIFT - 4))
- (LOBYTE (LOWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1)); - (LOBYTE (LOWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1)));
*lpDst++ += (1 << (RANGE_SHIFT - 4)) *lpDst++ += (SBYTE) ((1 << (RANGE_SHIFT - 4))
- (HIBYTE (LOWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1)); - (HIBYTE (LOWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1)));
*lpDst++ += (1 << (RANGE_SHIFT - 4)) *lpDst++ += (SBYTE) ((1 << (RANGE_SHIFT - 4))
- (LOBYTE (HIWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1)); - (LOBYTE (HIWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1)));
*lpDst++ += (1 << (RANGE_SHIFT - 4)) *lpDst++ += (SBYTE) ((1 << (RANGE_SHIFT - 4))
- (HIBYTE (HIWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1)); - (HIBYTE (HIWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1)));
} while (--i); } while (--i);
} }
@@ -776,17 +940,23 @@ GeneratePlanetMask (PPLANET_DESC pPlanetDesc, BOOLEAN IsEarth)
RECT r; RECT r;
DWORD old_seed; DWORD old_seed;
PLANDATAPTR PlanDataPtr; PLANDATAPTR PlanDataPtr;
COUNT i;
old_seed = SeedRandom (pPlanetDesc->rand_seed);
if(pSolarSysState->hTopoData!=0) {
fprintf(stderr,"hTopoData wasn't reset!!!\n");
}
if (IsEarth) if (IsEarth)
{ {
//Earth uses a pixmap for the topography
pSolarSysState->TopoFrame = CaptureDrawable ( pSolarSysState->TopoFrame = CaptureDrawable (
LoadGraphic (EARTH_MASK_ANIM) LoadGraphic (EARTH_MASK_ANIM)
); );
return; pSolarSysState->TopoFrame = stretch_frame(pSolarSysState->TopoFrame,MAP_WIDTH,MAP_HEIGHT,1);
}
old_seed = SeedRandom (pPlanetDesc->rand_seed); } else {
pSolarSysState->lpTopoMap=NULL;
PlanDataPtr = &PlanData[ PlanDataPtr = &PlanData[
pPlanetDesc->data_index & ~PLANET_SHIELDED pPlanetDesc->data_index & ~PLANET_SHIELDED
]; ];
@@ -800,8 +970,6 @@ GeneratePlanetMask (PPLANET_DESC pPlanetDesc, BOOLEAN IsEarth)
} }
if (pSolarSysState->lpTopoData) if (pSolarSysState->lpTopoData)
{ {
COUNT i;
memset (pSolarSysState->lpTopoData, 0, MAP_WIDTH * MAP_HEIGHT); memset (pSolarSysState->lpTopoData, 0, MAP_WIDTH * MAP_HEIGHT);
switch (PLANALGO (PlanDataPtr->Type)) switch (PLANALGO (PlanDataPtr->Type))
{ {
@@ -860,22 +1028,27 @@ GeneratePlanetMask (PPLANET_DESC pPlanetDesc, BOOLEAN IsEarth)
ValidateMap (pSolarSysState->lpTopoData); ValidateMap (pSolarSysState->lpTopoData);
break; break;
} }
} else {
return;
}
}
{ {
CONTEXT OldContext; CONTEXT OldContext;
OldContext = SetContext (TaskContext); OldContext = SetContext (TaskContext);
pSolarSysState->isPFADefined=(BYTE *)calloc(255,sizeof(BYTE));
#if 0 pSolarSysState->PlanetFrameArray=malloc(255*sizeof(FRAME));
pSolarSysState->PlanetFrameArray[1] = CaptureDrawable ( for(i=0;i<255;i++) {
CreateDrawable (WANT_MASK, pSolarSysState->PlanetFrameArray[i] = CaptureDrawable (
MAP_WIDTH + ((MAP_WIDTH >> 1) - 1), CreateDrawable (WANT_PIXMAP, DIAMETER, DIAMETER, 1)
MAP_HEIGHT,
3)
); );
#endif }
pSolarSysState->ScaleFrame[0]=0;
pSolarSysState->ScaleFrame[1]=0;
if(! IsEarth) {
pSolarSysState->TopoFrame = CaptureDrawable ( pSolarSysState->TopoFrame = CaptureDrawable (
CreateDrawable (WANT_PIXMAP, MAP_WIDTH, MAP_HEIGHT, 1) CreateDrawable (WANT_PIXMAP, (SIZE)MAP_WIDTH, (SIZE)MAP_HEIGHT, 1)
); );
pSolarSysState->OrbitalCMap = CaptureColorMap ( pSolarSysState->OrbitalCMap = CaptureColorMap (
LoadColorMap (PlanDataPtr->CMapInstance) LoadColorMap (PlanDataPtr->CMapInstance)
@@ -899,15 +1072,44 @@ GeneratePlanetMask (PPLANET_DESC pPlanetDesc, BOOLEAN IsEarth)
pSolarSysState->XlatRef = SetAbsStringTableIndex (pSolarSysState->XlatRef, 1); pSolarSysState->XlatRef = SetAbsStringTableIndex (pSolarSysState->XlatRef, 1);
} }
pSolarSysState->XlatPtr = GetStringAddress (pSolarSysState->XlatRef); pSolarSysState->XlatPtr = GetStringAddress (pSolarSysState->XlatRef);
RenderTopography (FALSE); RenderTopography (FALSE);
#if 0
RenderLevelMasks (); }
#endif {
// Generate a pixel array fromthe Topography map.
// We use this instead of lpTopoData because it needs to be WAP_WIDTH+MAP_HEIGHT wide
// and we need this method for Earth anyway. It may be more efficient to build it
// from lpTopoData instead of the FRAMPTR though
COUNT x,y;
x=MAP_WIDTH+MAP_HEIGHT;
y=MAP_HEIGHT;
pSolarSysState->lpTopoMap=getpixelarray(pSolarSysState->TopoFrame,x,y);
// Extend the width from MAP_WIDTH to MAP_WIDTH+MAP_HEIGHT
for(y=0;y<MAP_HEIGHT;y++) {
for(x=0;x<MAP_HEIGHT;x++) {
pSolarSysState->lpTopoMap[y][x+MAP_WIDTH]=pSolarSysState->lpTopoMap[y][x];
}
}
}
{
POINT loc;
if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->SunDesc[0])
{
// This is a planet. Get its location
loc=pSolarSysState->pOrbitalDesc->location;
} else {
// This is a moon. Get its planet's location
loc=pSolarSysState->pOrbitalDesc->pPrevDesc->location;
}
RenderPhongMask(loc);
}
if (pPlanetDesc->data_index & PLANET_SHIELDED) {
fprintf(stderr,"Found shield\n");
CreateShieldMask();
}
SetContext (OldContext); SetContext (OldContext);
} }
}
SeedRandom (old_seed); SeedRandom (old_seed);
@@ -921,6 +1123,8 @@ rotate_planet_task(void *data)
DWORD TimeIn; DWORD TimeIn;
PSOLARSYS_STATE pSS; PSOLARSYS_STATE pSS;
BOOLEAN repair, zooming; BOOLEAN repair, zooming;
int angle=0;
Task task = (Task) data; Task task = (Task) data;
repair = FALSE; repair = FALSE;
@@ -930,7 +1134,9 @@ rotate_planet_task(void *data)
while (((PSOLARSYS_STATE volatile)pSS)->MenuState.Initialized < 2 && !Task_ReadState (task, TASK_EXIT)) while (((PSOLARSYS_STATE volatile)pSS)->MenuState.Initialized < 2 && !Task_ReadState (task, TASK_EXIT))
TaskSwitch (); TaskSwitch ();
SetPlanetTilt ((pSS->SysInfo.PlanetInfo.AxialTilt << 8) / 360); // SetPlanetTilt ((pSS->SysInfo.PlanetInfo.AxialTilt << 8) / 360);
SetPlanetTilt (pSS->SysInfo.PlanetInfo.AxialTilt);
// angle=pSS->SysInfo.PlanetInfo.AxialTilt;
i = 1 - ((pSS->SysInfo.PlanetInfo.AxialTilt & 1) << 1); i = 1 - ((pSS->SysInfo.PlanetInfo.AxialTilt & 1) << 1);
TimeIn = GetTimeCounter (); TimeIn = GetTimeCounter ();
@@ -964,7 +1170,7 @@ rotate_planet_task(void *data)
r.extent.height = SIS_SCREEN_HEIGHT - MAP_HEIGHT; r.extent.height = SIS_SCREEN_HEIGHT - MAP_HEIGHT;
RepairBackRect (&r); RepairBackRect (&r);
} }
repair = RotatePlanet (x, SIS_SCREEN_WIDTH >> 1, (148 - SIS_ORG_Y) >> 1); repair = RotatePlanet (x, angle, SIS_SCREEN_WIDTH >> 1, (148 - SIS_ORG_Y) >> 1,zooming);
UnbatchGraphics (); UnbatchGraphics ();
SetContext (OldContext); SetContext (OldContext);
@@ -977,7 +1183,8 @@ rotate_planet_task(void *data)
} }
ClearSemaphore (GraphicsSem); ClearSemaphore (GraphicsSem);
SleepThreadUntil (TimeIn + (ONE_SECOND * 5 / MAP_WIDTH)); SleepThreadUntil (TimeIn + (ONE_SECOND * ROTATION_TIME) / (MAP_WIDTH));
// SleepThreadUntil (TimeIn + (ONE_SECOND * 5 / (MAP_WIDTH-32)));
TimeIn = GetTimeCounter (); TimeIn = GetTimeCounter ();
} while (--view_index && !Task_ReadState (task, TASK_EXIT)); } while (--view_index && !Task_ReadState (task, TASK_EXIT));
} }