greed/CODE/R_PUBLIC.C
2014-12-12 00:00:00 +00:00

534 lines
14 KiB
C

/***************************************************************************/
/* */
/* */
/* Raven 3D Engine */
/* Copyright (C) 1996 by Softdisk Publishing */
/* */
/* Original Design: */
/* John Carmack of id Software */
/* */
/* Enhancements by: */
/* Robert Morgan of Channel 7............................Main Engine Code */
/* Todd Lewis of Softdisk Publishing......Tools,Utilities,Special Effects */
/* John Bianca of Softdisk Publishing..............Low-level Optimization */
/* Carlos Hasan..........................................Music/Sound Code */
/* */
/* */
/***************************************************************************/
#include <STDLIB.H>
#include <MATH.H>
#include <STRING.H>
#include "d_global.h"
#include "d_disk.h"
#include "r_refdef.h"
#include "protos.h"
#include "d_ints.h"
#include "audio.h"
/**** VARIABLES ****/
int windowHeight = INIT_VIEW_HEIGHT;
int windowWidth = INIT_VIEW_WIDTH;
int windowLeft = 0;
int windowTop = 0;
int windowSize = INIT_VIEW_HEIGHT*INIT_VIEW_WIDTH;
int viewLocation=0xA0000;
fixed_t CENTERX=INIT_VIEW_WIDTH/2;
fixed_t CENTERY=INIT_VIEW_HEIGHT/2;
fixed_t SCALE;
fixed_t ISCALE;
int backtangents[TANANGLES*2];
int autoangle2[MAXAUTO][MAXAUTO];
int scrollmin, scrollmax, bloodcount, metalcount;
extern SoundCard SC;
/**** FUNCTIONS ****/
void r_publicstub2(void);
void RF_PreloadGraphics(void)
{
int i;
int doorlump;
// find the number of lumps of each type
spritelump=CA_GetNamedNum("startsprites");
numsprites=CA_GetNamedNum("endsprites")-spritelump;
walllump=CA_GetNamedNum("startwalls");
numwalls=CA_GetNamedNum("endwalls")-walllump;
flatlump=CA_GetNamedNum("startflats");
numflats=CA_GetNamedNum("endflats")-flatlump;
doorlump=CA_GetNamedNum("door_1");
printf(".");
// load the lumps
for (i=1; i<numsprites; i++)
{
DemandLoadMonster(spritelump+i,1);
// CA_CacheLump(spritelump+i);
if (i%50==0)
{
printf(".");
if (newascii && lastascii==27) return;
}
}
printf(".");
if (!debugmode)
for(i=doorlump;i<numwalls+walllump;i++) CA_CacheLump(i);
else
{
CA_CacheLump(walllump+1);
CA_CacheLump(flatlump+1);
}
printf(".");
}
void RF_InitTargets(void)
{
double at, atf;
int j, angle, x1, y1, i;
fixed_t x, y;
memset(autoangle2,-1,sizeof(autoangle2));
i=0;
do
{
at=atan((double)i/(double)MAXAUTO);
atf=at*(double)ANGLES/(2*PI);
angle=rint(atf);
for(j=0;j<MAXAUTO*2;j++)
{
y=FIXEDMUL(sintable[angle],j<<FRACBITS);
x=FIXEDMUL(costable[angle],j<<FRACBITS);
x1=x>>FRACBITS;
y1=y>>FRACBITS;
if (x1>=MAXAUTO || y1>=MAXAUTO || autoangle2[x1][y1]!=-1) continue;
autoangle2[x1][y1]=angle;
}
i++;
} while (angle<DEGREE45+DEGREE45_2);
for(i=MAXAUTO-1;i>0;i--)
for(j=0;j<MAXAUTO;j++)
if (autoangle2[j][i]==-1) autoangle2[j][i]=autoangle2[j][i-1];
for(i=MAXAUTO-1;i>0;i--)
for(j=0;j<MAXAUTO;j++)
if (autoangle2[j][i]==-1) autoangle2[j][i]=autoangle2[j][i-1];
}
void InitTables(void)
/* Builds tangent tables for -90 degrees to +90 degrees
and pixel angle table */
{
double tang, value, ivalue;
int intval, i;
// tangent values for wall tracing
for (i=0; i<TANANGLES/2; i++)
{
tang=(i+0.5)*PI/(TANANGLES*2);
// tang=i*PI/(TANANGLES*2);
value=tan(tang);
ivalue=1/value;
value=rint(value*FRACUNIT);
ivalue=rint(ivalue*FRACUNIT);
tangents[TANANGLES + i]=-value;
tangents[TANANGLES + TANANGLES - 1 - i]=-ivalue;
tangents[i]=ivalue;
tangents[TANANGLES - 1 - i]=value;
}
// high precision sin / cos for distance calculations
for (i=0; i<TANANGLES; i++)
{
tang=(i+0.5)*PI/(TANANGLES*2);
// tang=i*PI/(TANANGLES*2);
value=sin(tang);
intval=rint(value*FRACUNIT);
sines[i]=intval;
sines[TANANGLES*4 + i]=intval;
sines[TANANGLES*2 - 1 - i]=intval;
sines[TANANGLES*2 + i]=-intval;
sines[TANANGLES*4 - 1 - i]=-intval;
}
cosines=&sines[TANANGLES];
for(i=0;i<TANANGLES*2;i++)
backtangents[i]=((windowWidth/2)*tangents[i])>>FRACBITS;
}
void InitReverseCam(void)
{
int i, intval;
for (i=0;i<65; i++)
{
intval=rint(atan(((double)32-((double)i+1.0))/(double)32)/(double)PI*(double)TANANGLES*(double)2);
pixelangle[i]=intval;
pixelcosine[i]=cosines[intval&(TANANGLES * 4 - 1)];
}
memcpy(campixelangle,pixelangle,sizeof(pixelangle));
memcpy(campixelcosine,pixelcosine,sizeof(pixelcosine));
}
void RF_Startup(void)
{
int i;
double angle;
int lightlump;
lock_region((void near *)RF_GetFloorZ,(char *)r_publicstub2 - (char near *)RF_GetFloorZ);
lock_region(&actionhook,sizeof(actionhook));
lock_region(&actionflag,sizeof(actionflag));
memset(framevalid, 0, sizeof(framevalid));
printf(".");
frameon=0;
// trig tables
for (i=0; i<=ANGLES; i++)
{
angle=(double)(i * PI * 2)/(double)(ANGLES + 1);
sintable[i]=rint(sin(angle)*FRACUNIT);
costable[i]=rint(cos(angle)*FRACUNIT);
}
printf(".");
SetViewSize(windowWidth,windowHeight);
// set up lights
// Allocates a page aligned buffer and load in the light tables
lightlump=CA_GetNamedNum("lights");
numcolormaps=infotable[lightlump].size/256;
colormaps=malloc((size_t)256*(numcolormaps+1));
colormaps=(byte *)(((int)colormaps+255)&~0xff);
CA_ReadLump(lightlump, colormaps);
RF_SetLights((fixed_t)MAXZ);
RF_ClearWorld();
printf(".");
// initialize the translation to no animation
flattranslation=malloc((size_t)(numflats+1)*4);
walltranslation=malloc((size_t)(numwalls+1)*4);
if (!debugmode)
{
for(i=0;i<=numflats;i++) flattranslation[i]=i;
for(i=0;i<=numwalls;i++) walltranslation[i]=i;
}
else
{
for(i=1;i<=numflats;i++) flattranslation[i]=1;
for(i=1;i<=numwalls;i++) walltranslation[i]=1;
flattranslation[0]=0;
walltranslation[0]=0;
}
actionhook=NULL;
actionflag=0;
RF_InitTargets();
InitTables();
printf(".");
InitReverseCam();
InitWalls();
printf(".");
}
void RF_ClearWorld(void)
{
int i;
firstscaleobj.prev=NULL;
firstscaleobj.next=&lastscaleobj;
lastscaleobj.prev=&firstscaleobj;
lastscaleobj.next=NULL;
freescaleobj_p=scaleobjlist;
memset(scaleobjlist,0,sizeof(scaleobjlist));
for(i=0;i<MAXSPRITES-1;i++) scaleobjlist[i].next=&scaleobjlist[i+1];
firstelevobj.prev=NULL;
firstelevobj.next=&lastelevobj;
lastelevobj.prev=&firstelevobj;
lastelevobj.next=NULL;
freeelevobj_p=elevlist;
memset(elevlist,0,sizeof(elevlist));
for(i=0;i<MAXELEVATORS-1;i++) elevlist[i].next=&elevlist[i+1];
numdoors=0;
numspawnareas=0;
bloodcount=0;
metalcount=0;
}
doorobj_t *RF_GetDoor(int tilex, int tiley)
{
doorobj_t *door;
if (numdoors==MAXDOORS) MS_Error("RF_GetDoor: Too many doors placed! (%i,%i)",numdoors,MAXDOORS);
door=&doorlist[numdoors];
numdoors++;
door->tilex=tilex;
door->tiley=tiley;
mapflags[tiley*MAPROWS+tilex] |= FL_DOOR;
return door;
}
scaleobj_t *RF_GetSprite(void)
/* returns a new sprite */
{
scaleobj_t *new;
if (!freescaleobj_p) MS_Error("RF_GetSprite: Out of spots in scaleobjlist!");
new=freescaleobj_p;
freescaleobj_p=freescaleobj_p->next;
memset(new,0,sizeof(scaleobj_t));
new->next=(scaleobj_t *)&lastscaleobj;
new->prev=lastscaleobj.prev;
lastscaleobj.prev=new;
new->prev->next=new;
return new;
}
elevobj_t *RF_GetElevator(void)
/* returns a elevator structure */
{
elevobj_t *new;
if (!freeelevobj_p) MS_Error("RF_GetElevator: Too many elevators placed!");
new=freeelevobj_p;
freeelevobj_p=freeelevobj_p->next;
memset(new,0,sizeof(elevobj_t));
new->next=(elevobj_t *)&lastelevobj;
new->prev=lastelevobj.prev;
lastelevobj.prev=new;
new->prev->next=new;
return new;
}
spawnarea_t *RF_GetSpawnArea(void)
{
if (numspawnareas==MAXSPAWNAREAS) MS_Error("RF_GetSpawnArea: Too many Spawn Areas placed! (%i,%i)",numspawnareas,MAXSPAWNAREAS);
++numspawnareas;
return &spawnareas[numspawnareas-1];
}
void Event(int e,boolean send);
void RF_RemoveSprite(scaleobj_t *spr)
/* removes sprite from doublely linked list of sprites */
{
spr->next->prev=spr->prev;
spr->prev->next=spr->next;
spr->next=freescaleobj_p;
freescaleobj_p=spr;
}
void RF_RemoveElevator(elevobj_t *e)
{
e->next->prev=e->prev;
e->prev->next=e->next;
e->next=freeelevobj_p;
freeelevobj_p=e;
}
fixed_t RF_GetFloorZ(fixed_t x, fixed_t y)
{
fixed_t h1, h2, h3, h4;
int tilex, tiley, mapspot;
int polytype;
fixed_t fx, fy;
fixed_t top, bottom, water;
tilex=x>>(FRACBITS+TILESHIFT);
tiley=y>>(FRACBITS+TILESHIFT);
mapspot=tiley *MAPSIZE+tilex;
polytype=(mapflags[mapspot]&FL_FLOOR)>>FLS_FLOOR;
if (floorpic[mapspot]>=57 && floorpic[mapspot]<=59)
water=-(20<<FRACBITS);
else
water=0;
if (polytype==POLY_FLAT)
return (floorheight[mapspot]<<FRACBITS) + water;
h1=floorheight[mapspot]<<FRACBITS;
h2=floorheight[mapspot+1]<<FRACBITS;
h3=floorheight[mapspot+MAPSIZE]<<FRACBITS;
h4=floorheight[mapspot+MAPSIZE+1]<<FRACBITS;
fx=(x&(TILEUNIT-1))>>6; // range from 0 to fracunit-1
fy=(y&(TILEUNIT-1))>>6;
if (polytype==POLY_SLOPE)
{
if (h1==h2) return h1+FIXEDMUL(h3-h1, fy) + water;
else return h1+FIXEDMUL(h2-h1, fx) + water;
}
// triangulated slopes
// set the outside corner of the triangle that the point is NOT in s
// plane with the other three
if (polytype==POLY_ULTOLR)
{
if (fx>fy) h3=h1-(h2-h1);
else h2=h1+(h1-h3);
}
else
{
if (fx<FRACUNIT-fy) h4=h2+(h2-h1);
else h1=h2-(h4-h2);
}
top=h1+FIXEDMUL(h2-h1, fx);
bottom=h3+FIXEDMUL(h4-h3, fx);
return top+FIXEDMUL(bottom-top, fy) + water;
}
fixed_t RF_GetCeilingZ(fixed_t x, fixed_t y)
/* find how high the ceiling is at x,y */
{
fixed_t h1, h2, h3, h4;
int tilex, tiley, mapspot;
int polytype;
fixed_t fx, fy;
fixed_t top, bottom;
tilex=x>>(FRACBITS+TILESHIFT);
tiley=y>>(FRACBITS+TILESHIFT);
mapspot=tiley *MAPSIZE+tilex;
polytype=(mapflags[mapspot]&FL_CEILING)>>FLS_CEILING;
// flat
if (polytype==POLY_FLAT) return ceilingheight[mapspot]<<FRACBITS;
// constant slopes
if (polytype==POLY_SLOPE)
{
h1=ceilingheight[mapspot]<<FRACBITS;
h2=ceilingheight[mapspot+1]<<FRACBITS;
if (h1==h2)
{
h3=ceilingheight[mapspot+MAPSIZE]<<FRACBITS;
fy=(y&(TILEUNIT-1))>>6;
return h1+FIXEDMUL(h3-h1, fy); // north/south slope
}
else
{
fx=(x&(TILEUNIT-1))>>6;
return h1+FIXEDMUL(h2-h1, fx); // east/west slope
}
}
// triangulated slopes
// set the outside corner of the triangle that the point is NOT in s
// plane with the other three
h1=ceilingheight[mapspot]<<FRACBITS;
h2=ceilingheight[mapspot+1]<<FRACBITS;
h3=ceilingheight[mapspot+MAPSIZE]<<FRACBITS;
h4=ceilingheight[mapspot+MAPSIZE+1]<<FRACBITS;
fx=(x&(TILEUNIT-1))>>6; // range from 0 to fracunit-1
fy=(y&(TILEUNIT-1))>>6;
if (polytype==POLY_ULTOLR)
{
if (fx>fy) h3=h1-(h2-h1);
else h2=h1+(h1-h3);
}
else
{
if (fx<FRACUNIT-fy) h4=h2+(h2-h1);
else h1=h2-(h4-h2);
}
top=h1+FIXEDMUL(h2-h1, fx);
bottom=h3+FIXEDMUL(h4-h3, fx);
return top+FIXEDMUL(bottom-top, fy);
}
void RF_SetActionHook(void (*hook)(void))
{
actionhook=hook;
actionflag=1;
}
void r_publicstub2(void)
{
}
void RF_SetLights(fixed_t blackz)
/* resets the color maps to new lighting values */
{
// linear diminishing, table is actually logrithmic
int i, table;
blackz>>=FRACBITS;
for (i=0;i<=MAXZ>>FRACBITS;i++)
{
table=numcolormaps * i/blackz;
if (table>=numcolormaps) table=numcolormaps-1;
zcolormap[i]=colormaps+table*256;
}
}
void RF_CheckActionFlag(void)
{
if (SC.vrhelmet==0)
TimeUpdate();
if (!actionflag) return;
actionhook();
actionflag=0;
}
void RF_RenderView(fixed_t x, fixed_t y, fixed_t z, int angle)
{
//#ifdef VALIDATE
// if (x<=0 || x>=((MAPSIZE-1)<<(FRACBITS+TILESHIFT)) || y<=0 ||
// y>=((MAPSIZE-1)<<(FRACBITS+TILESHIFT)))
// MS_Error("Invalid RF_RenderView (%p, %p, %p, %i)\n", x, y, z, angle);
//#endif
// viewx=(x&~0xfff) + 0x800;
// viewy=(y&~0xfff) + 0x800;
// viewz=(z&~0xfff) + 0x800;
viewx=x;
viewy=y;
viewz=z;
viewangle=angle&ANGLES;
RF_CheckActionFlag();
SetupFrame();
RF_CheckActionFlag();
FlowView();
RF_CheckActionFlag();
RenderSprites();
DrawSpans();
RF_CheckActionFlag();
}
void SetViewSize(int width, int height)
{
int i;
if (width>MAX_VIEW_WIDTH) width = MAX_VIEW_WIDTH;
if (height>MAX_VIEW_HEIGHT) height = MAX_VIEW_HEIGHT;
windowHeight = height;
windowWidth = width;
windowSize = width*height;
scrollmax=windowHeight+scrollmin;
CENTERX=width/2;
CENTERY=height/2;
SCALE=(width/2)<<FRACBITS;
ISCALE=FRACUNIT/(width/2);
for (i=0;i<height;i++)
viewylookup[i]=viewbuffer+i*width;
// slopes for rows and collumns of screen pixels
// slightly biased to account for the truncation in coordinates
for(i=0;i<=width;i++)
xslope[i]=rint((float)(i+1-CENTERX)/CENTERX*FRACUNIT);
for(i=-MAXSCROLL;i<height+MAXSCROLL;i++)
yslope[i+MAXSCROLL] = rint(-(float)(i-0.5-CENTERY)/CENTERX*FRACUNIT);
for(i=0;i<TANANGLES*2;i++)
backtangents[i]=((width/2)*tangents[i])>>FRACBITS;
hfrac=FIXEDDIV(BACKDROPHEIGHT<<FRACBITS,(windowHeight/2)<<FRACBITS);
afrac=FIXEDDIV(TANANGLES<<FRACBITS,width<<FRACBITS);
}