diff options
author | Simon Howard | 2008-09-04 23:15:36 +0000 |
---|---|---|
committer | Simon Howard | 2008-09-04 23:15:36 +0000 |
commit | 0df2cb80cf03d7259746834220d209b306a8c503 (patch) | |
tree | fdc5037429c91dcbc8207c3e75fc787ef96e207a /src/hexen/r_plane.c | |
parent | 6a294daa7859eaf0250aa4a77484dd11550e5c5e (diff) | |
download | chocolate-doom-0df2cb80cf03d7259746834220d209b306a8c503.tar.gz chocolate-doom-0df2cb80cf03d7259746834220d209b306a8c503.tar.bz2 chocolate-doom-0df2cb80cf03d7259746834220d209b306a8c503.zip |
Add GPLed Heretic/Hexen source.
Subversion-branch: /branches/raven-branch
Subversion-revision: 1195
Diffstat (limited to 'src/hexen/r_plane.c')
-rw-r--r-- | src/hexen/r_plane.c | 559 |
1 files changed, 559 insertions, 0 deletions
diff --git a/src/hexen/r_plane.c b/src/hexen/r_plane.c new file mode 100644 index 00000000..ece108dc --- /dev/null +++ b/src/hexen/r_plane.c @@ -0,0 +1,559 @@ + +//************************************************************************** +//** +//** r_plane.c : Heretic 2 : Raven Software, Corp. +//** +//** $RCSfile: r_plane.c,v $ +//** $Revision: 1.5 $ +//** $Date: 95/07/13 15:17:12 $ +//** $Author: cjr $ +//** +//************************************************************************** + +// HEADER FILES ------------------------------------------------------------ + +#include "h2def.h" +#include "r_local.h" + +// MACROS ------------------------------------------------------------------ + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +extern fixed_t Sky1ScrollDelta; +extern fixed_t Sky2ScrollDelta; + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +int Sky1Texture; +int Sky2Texture; +fixed_t Sky1ColumnOffset; +fixed_t Sky2ColumnOffset; +int skyflatnum; +int skytexturemid; +fixed_t skyiscale; +boolean DoubleSky; +planefunction_t floorfunc, ceilingfunc; + +// Opening +visplane_t visplanes[MAXVISPLANES], *lastvisplane; +visplane_t *floorplane, *ceilingplane; +short openings[MAXOPENINGS], *lastopening; + +// Clip values are the solid pixel bounding the range. +// floorclip start out SCREENHEIGHT +// ceilingclip starts out -1 +short floorclip[SCREENWIDTH]; +short ceilingclip[SCREENWIDTH]; + +// spanstart holds the start of a plane span, initialized to 0 +int spanstart[SCREENHEIGHT]; +int spanstop[SCREENHEIGHT]; + +// Texture mapping +lighttable_t **planezlight; +fixed_t planeheight; +fixed_t yslope[SCREENHEIGHT]; +fixed_t distscale[SCREENWIDTH]; +fixed_t basexscale, baseyscale; +fixed_t cachedheight[SCREENHEIGHT]; +fixed_t cacheddistance[SCREENHEIGHT]; +fixed_t cachedxstep[SCREENHEIGHT]; +fixed_t cachedystep[SCREENHEIGHT]; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// R_InitSky +// +// Called at level load. +// +//========================================================================== + +void R_InitSky(int map) +{ + Sky1Texture = P_GetMapSky1Texture(map); + Sky2Texture = P_GetMapSky2Texture(map); + Sky1ScrollDelta = P_GetMapSky1ScrollDelta(map); + Sky2ScrollDelta = P_GetMapSky2ScrollDelta(map); + Sky1ColumnOffset = 0; + Sky2ColumnOffset = 0; + DoubleSky = P_GetMapDoubleSky(map); +} + +//========================================================================== +// +// R_InitSkyMap +// +// Called whenever the view size changes. +// +//========================================================================== + +void R_InitSkyMap(void) +{ + skyflatnum = R_FlatNumForName("F_SKY"); + skytexturemid = 200*FRACUNIT; + skyiscale = FRACUNIT; +} + +//========================================================================== +// +// R_InitPlanes +// +// Called at game startup. +// +//========================================================================== + +void R_InitPlanes(void) +{ +} + +//========================================================================== +// +// R_MapPlane +// +// Globals used: planeheight, ds_source, basexscale, baseyscale, +// viewx, viewy. +// +//========================================================================== + +void R_MapPlane(int y, int x1, int x2) +{ + angle_t angle; + fixed_t distance, length; + unsigned index; + +#ifdef RANGECHECK + if(x2 < x1 || x1 < 0 || x2 >= viewwidth || (unsigned)y > viewheight) + { + I_Error("R_MapPlane: %i, %i at %i", x1, x2, y); + } +#endif + + if(planeheight != cachedheight[y]) + { + cachedheight[y] = planeheight; + distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); + ds_xstep = cachedxstep[y] = FixedMul(distance, basexscale); + ds_ystep = cachedystep[y] = FixedMul(distance, baseyscale); + } + else + { + distance = cacheddistance[y]; + ds_xstep = cachedxstep[y]; + ds_ystep = cachedystep[y]; + } + + length = FixedMul(distance, distscale[x1]); + angle = (viewangle+xtoviewangle[x1])>>ANGLETOFINESHIFT; + ds_xfrac = viewx+FixedMul(finecosine[angle], length); + ds_yfrac = -viewy-FixedMul(finesine[angle], length); + + if(fixedcolormap) + { + ds_colormap = fixedcolormap; + } + else + { + index = distance >> LIGHTZSHIFT; + if(index >= MAXLIGHTZ ) + { + index = MAXLIGHTZ-1; + } + ds_colormap = planezlight[index]; + } + + ds_y = y; + ds_x1 = x1; + ds_x2 = x2; + + spanfunc(); // High or low detail +} + +//========================================================================== +// +// R_ClearPlanes +// +// Called at the beginning of each frame. +// +//========================================================================== + +void R_ClearPlanes(void) +{ + int i; + angle_t angle; + + // Opening / clipping determination + for(i = 0; i < viewwidth; i++) + { + floorclip[i] = viewheight; + ceilingclip[i] = -1; + } + + lastvisplane = visplanes; + lastopening = openings; + + // Texture calculation + memset(cachedheight, 0, sizeof(cachedheight)); + angle = (viewangle-ANG90)>>ANGLETOFINESHIFT; // left to right mapping + // Scale will be unit scale at SCREENWIDTH/2 distance + basexscale = FixedDiv(finecosine[angle], centerxfrac); + baseyscale = -FixedDiv(finesine[angle], centerxfrac); +} + +//========================================================================== +// +// R_FindPlane +// +//========================================================================== + +visplane_t *R_FindPlane(fixed_t height, int picnum, + int lightlevel, int special) +{ + visplane_t *check; + + if(special < 150) + { // Don't let low specials affect search + special = 0; + } + + if(picnum == skyflatnum) + { // All skies map together + height = 0; + lightlevel = 0; + } + + for(check = visplanes; check < lastvisplane; check++) + { + if(height == check->height + && picnum == check->picnum + && lightlevel == check->lightlevel + && special == check->special) + break; + } + + if(check < lastvisplane) + { + return(check); + } + + if(lastvisplane-visplanes == MAXVISPLANES) + { + I_Error("R_FindPlane: no more visplanes"); + } + + lastvisplane++; + check->height = height; + check->picnum = picnum; + check->lightlevel = lightlevel; + check->special = special; + check->minx = SCREENWIDTH; + check->maxx = -1; + memset(check->top, 0xff, sizeof(check->top)); + return(check); +} + +//========================================================================== +// +// R_CheckPlane +// +//========================================================================== + +visplane_t *R_CheckPlane(visplane_t *pl, int start, int stop) +{ + int intrl, intrh; + int unionl, unionh; + int x; + + if(start < pl->minx) + { + intrl = pl->minx; + unionl = start; + } + else + { + unionl = pl->minx; + intrl = start; + } + if(stop > pl->maxx) + { + intrh = pl->maxx; + unionh = stop; + } + else + { + unionh = pl->maxx; + intrh = stop; + } + + for(x = intrl; x <= intrh; x++) + { + if(pl->top[x] != 0xff) + { + break; + } + } + + if(x > intrh) + { + pl->minx = unionl; + pl->maxx = unionh; + return pl; // use the same visplane + } + + // Make a new visplane + lastvisplane->height = pl->height; + lastvisplane->picnum = pl->picnum; + lastvisplane->lightlevel = pl->lightlevel; + lastvisplane->special = pl->special; + pl = lastvisplane++; + pl->minx = start; + pl->maxx = stop; + memset(pl->top, 0xff, sizeof(pl->top)); + + return pl; +} + +//========================================================================== +// +// R_MakeSpans +// +//========================================================================== + +void R_MakeSpans(int x, int t1, int b1, int t2, int b2) +{ + while(t1 < t2 && t1 <= b1) + { + R_MapPlane(t1, spanstart[t1], x-1); + t1++; + } + while(b1 > b2 && b1 >= t1) + { + R_MapPlane(b1, spanstart[b1], x-1); + b1--; + } + while(t2 < t1 && t2 <= b2) + { + spanstart[t2] = x; + t2++; + } + while(b2 > b1 && b2 >= t2) + { + spanstart[b2] = x; + b2--; + } +} + +//========================================================================== +// +// R_DrawPlanes +// +//========================================================================== + +#define SKYTEXTUREMIDSHIFTED 200 + +void R_DrawPlanes(void) +{ + visplane_t *pl; + int light; + int x, stop; + int angle; + byte *tempSource; + byte *source; + byte *source2; + byte *dest; + int count; + int offset; + int skyTexture; + int offset2; + int skyTexture2; + int scrollOffset; + + extern byte *ylookup[MAXHEIGHT]; + extern int columnofs[MAXWIDTH]; + +#ifdef RANGECHECK + if(ds_p-drawsegs > MAXDRAWSEGS) + { + I_Error("R_DrawPlanes: drawsegs overflow (%i)", ds_p-drawsegs); + } + if(lastvisplane-visplanes > MAXVISPLANES) + { + I_Error("R_DrawPlanes: visplane overflow (%i)", + lastvisplane-visplanes); + } + if(lastopening-openings > MAXOPENINGS) + { + I_Error("R_DrawPlanes: opening overflow (%i)", + lastopening-openings); + } +#endif + + for(pl = visplanes; pl < lastvisplane; pl++) + { + if(pl->minx > pl->maxx) + { + continue; + } + if(pl->picnum == skyflatnum) + { // Sky flat + if(DoubleSky) + { // Render 2 layers, sky 1 in front + offset = Sky1ColumnOffset>>16; + skyTexture = texturetranslation[Sky1Texture]; + offset2 = Sky2ColumnOffset>>16; + skyTexture2 = texturetranslation[Sky2Texture]; + for(x = pl->minx; x <= pl->maxx; x++) + { + dc_yl = pl->top[x]; + dc_yh = pl->bottom[x]; + if(dc_yl <= dc_yh) + { + count = dc_yh-dc_yl; + if(count < 0) + { + return; + } + angle = (viewangle+xtoviewangle[x]) + >>ANGLETOSKYSHIFT; + source = R_GetColumn(skyTexture, angle+offset) + +SKYTEXTUREMIDSHIFTED+(dc_yl-centery); + source2 = R_GetColumn(skyTexture2, angle+offset2) + +SKYTEXTUREMIDSHIFTED+(dc_yl-centery); + dest = ylookup[dc_yl]+columnofs[x]; + do + { + if(*source) + { + *dest = *source++; + source2++; + } + else + { + *dest = *source2++; + source++; + } + dest += SCREENWIDTH; + } while(count--); + } + } + continue; // Next visplane + } + else + { // Render single layer + if(pl->special == 200) + { // Use sky 2 + offset = Sky2ColumnOffset>>16; + skyTexture = texturetranslation[Sky2Texture]; + } + else + { // Use sky 1 + offset = Sky1ColumnOffset>>16; + skyTexture = texturetranslation[Sky1Texture]; + } + for(x = pl->minx; x <= pl->maxx; x++) + { + dc_yl = pl->top[x]; + dc_yh = pl->bottom[x]; + if(dc_yl <= dc_yh) + { + count = dc_yh-dc_yl; + if(count < 0) + { + return; + } + angle = (viewangle+xtoviewangle[x]) + >>ANGLETOSKYSHIFT; + source = R_GetColumn(skyTexture, angle+offset) + +SKYTEXTUREMIDSHIFTED+(dc_yl-centery); + dest = ylookup[dc_yl]+columnofs[x]; + do + { + *dest = *source++; + dest += SCREENWIDTH; + } while(count--); + } + } + continue; // Next visplane + } + } + // Regular flat + tempSource = W_CacheLumpNum(firstflat+ + flattranslation[pl->picnum], PU_STATIC); + scrollOffset = leveltime>>1&63; + switch(pl->special) + { // Handle scrolling flats + case 201: case 202: case 203: // Scroll_North_xxx + ds_source = tempSource+((scrollOffset + <<(pl->special-201)&63)<<6); + break; + case 204: case 205: case 206: // Scroll_East_xxx + ds_source = tempSource+((63-scrollOffset) + <<(pl->special-204)&63); + break; + case 207: case 208: case 209: // Scroll_South_xxx + ds_source = tempSource+(((63-scrollOffset) + <<(pl->special-207)&63)<<6); + break; + case 210: case 211: case 212: // Scroll_West_xxx + ds_source = tempSource+(scrollOffset + <<(pl->special-210)&63); + break; + case 213: case 214: case 215: // Scroll_NorthWest_xxx + ds_source = tempSource+(scrollOffset + <<(pl->special-213)&63)+((scrollOffset + <<(pl->special-213)&63)<<6); + break; + case 216: case 217: case 218: // Scroll_NorthEast_xxx + ds_source = tempSource+((63-scrollOffset) + <<(pl->special-216)&63)+((scrollOffset + <<(pl->special-216)&63)<<6); + break; + case 219: case 220: case 221: // Scroll_SouthEast_xxx + ds_source = tempSource+((63-scrollOffset) + <<(pl->special-219)&63)+(((63-scrollOffset) + <<(pl->special-219)&63)<<6); + break; + case 222: case 223: case 224: // Scroll_SouthWest_xxx + ds_source = tempSource+(scrollOffset + <<(pl->special-222)&63)+(((63-scrollOffset) + <<(pl->special-222)&63)<<6); + break; + default: + ds_source = tempSource; + break; + } + planeheight = abs(pl->height-viewz); + light = (pl->lightlevel >> LIGHTSEGSHIFT)+extralight; + if(light >= LIGHTLEVELS) + { + light = LIGHTLEVELS-1; + } + if(light < 0) + { + light = 0; + } + planezlight = zlight[light]; + + pl->top[pl->maxx+1] = 0xff; + pl->top[pl->minx-1] = 0xff; + + stop = pl->maxx+1; + for(x = pl->minx; x <= stop; x++) + { + R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1], + pl->top[x], pl->bottom[x]); + } + Z_ChangeTag(tempSource, PU_CACHE); + } +} |