/***************************************************************************/ /* */ /* */ /* 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 #include #include "d_global.h" #include "r_refdef.h" #include "d_disk.h" #include "d_video.h" #include "d_misc.h" /**** VARIABLES ****/ fixed_t tangents[TANANGLES *2]; fixed_t sines[TANANGLES *5]; fixed_t *cosines; // point 1/4 phase into sines int pixelangle[MAX_VIEW_WIDTH+1]; fixed_t pixelcosine[MAX_VIEW_WIDTH+1]; fixed_t wallz[MAX_VIEW_WIDTH]; // pointx byte *tpwalls_dest[MAXPEND]; byte *tpwalls_colormap[MAXPEND]; int tpwalls_count[MAXPEND]; int transparentposts; int wallpixelangle[MAX_VIEW_WIDTH+1]; fixed_t wallpixelcosine[MAX_VIEW_WIDTH+1]; int campixelangle[MAX_VIEW_WIDTH+1]; fixed_t campixelcosine[MAX_VIEW_WIDTH+1]; /**** FUNCTIONS ****/ void InitWalls(void) { int intval, i; // calculate the angle deltas for each view post // VIEWWIDTH view posts covers TANANGLES angles // traces go through the RIGHT EDGE of the pixel to follow the direction for (i=0;ipx to p2->px-1 with wall picture wall p1/p2 are projected and Z clipped, but unclipped to the view window */ { int baseangle; byte **postindex; // start of the 64 entry texture table for t fixed_t distance; // horizontal / vertical dist to wall segmen fixed_t pointz; // transformed distance to wall post fixed_t anglecos; fixed_t textureadjust; // the amount the texture p1ane is shifted fixed_t ceiling; // top of the wall fixed_t floor; // bottom of the wall fixed_t top, bottom; // precise y coordinates for post fixed_t scale; int topy, bottomy; // pixel y coordinates for post fixed_t fracadjust; // the amount to prestep for the top pixel int angle; // the ray angle that strikes the current po int texture; // 0-63 post number int x; // collumn and ranges int light; short *wall; unsigned span; span_t *span_p; int rotateright, rotateleft, transparent, rotateup, rotatedown, invisible; walltype=walltranslation[walltype]; // global animation wall=lumpmain[walllump+walltype]; // to get wall height postindex=wallposts+((walltype-1)<<6); // 64 pointers to texture start baseangle=viewfineangle; transparent=wallflags & F_TRANSPARENT; floor=floorheight[mapspot]; ceiling=ceilingheight[mapspot]; switch (side) { case 0: // south facing wall distance=viewy-(tiley<ceiling) ceiling=ceilingheight[mapspot+1]; } break; case 1: // west facing wall distance=((tilex+1)<ceiling) ceiling=ceilingheight[mapspot+MAPCOLS+1]; } break; case 2: // north facing wall distance=((tiley+1)<ceiling) ceiling=ceilingheight[mapspot+MAPCOLS+1]; } break; case 3: // east facing wall distance=viewx-(tilex<ceiling) ceiling=ceilingheight[mapspot+MAPCOLS]; } } // the floor and ceiling height is the max of the points ceiling=(ceiling<=5 && wallshadow<=8) { if (wallcycle==wallshadow-5) sp_colormap=colormaps; else { light=(pointz>>FRACBITS)+maplight; if (light>MAXZLIGHT) light=MAXZLIGHT; else if (light<0) light=0; sp_colormap=zcolormap[light]; } } rotateleft=wallflags & F_LEFT; rotateright=wallflags & F_RIGHT; rotateup=wallflags & F_UP; rotatedown=wallflags & F_DOWN; invisible=wallflags & F_DAMAGE; // step through the individual posts for (x=x1; x<=x2; x++) { // first do the z clipping angle=baseangle+pixelangle[x]; angle&=TANANGLES *2-1; anglecos=cosines[(angle-TANANGLES)&(TANANGLES *4-1)]; pointz=FIXEDDIV(distance, anglecos); pointz=FIXEDMUL(pointz, pixelcosine[x]); if (pointz>MAXZ) return; if (pointz>FRACBITS)+maplight; if (light>MAXZLIGHT) light=MAXZLIGHT; else if (light<0) light=0; sp_colormap=zcolormap[light]; } else if (wallshadow==9) { light=(pointz>>FRACBITS)+maplight+wallflicker4; if (light>MAXZLIGHT) light=MAXZLIGHT; else if (light<0) light=0; sp_colormap=zcolormap[light]; } // calculate the texture post along the wall that was hit texture=(textureadjust+FIXEDMUL(distance,tangents[angle]))>>FRACBITS; if (rotateright) texture-=wallrotate; else if (rotateleft) texture+=wallrotate; else if (x==x1 && x!=0) texture=0; // fix the incorrect looping problem texture&=63; sp_source=postindex[texture]; if (!transparent) wallz[x]=pointz; // calculate the size and scale of the post sp_fracstep=FIXEDMUL(pointz,ISCALE); scale=sp_fracstep; if (scale<1000) continue; top=FIXEDDIV(ceiling,scale)+FRACUNIT; topy=CENTERY - (top>>FRACBITS); fracadjust=top & (FRACUNIT-1); sp_frac=FIXEDMUL(fracadjust,sp_fracstep); if (rotatedown) sp_frac+=FRACUNIT*(63-wallrotate); else if (rotateup) sp_frac+=FRACUNIT*wallrotate; if (topy=sp_loopvalue) sp_frac-=sp_loopvalue; topy=scrollmin; } bottom=FIXEDDIV(floor,scale)+FRACUNIT*2; bottomy=bottom>=((CENTERY+scrollmin)<>FRACBITS); if (bottomy=scrollmax || topy==bottomy) continue; sp_count=bottomy-topy+1; sp_dest=viewylookup[bottomy-scrollmin]+x; if (transparent) { span=(pointz<spantype=sp_inviswall; else span_p->spantype=sp_transparentwall; span_p->picture=sp_source; span_p->y=sp_frac; // store info in span structure span_p->yh=sp_fracstep; span_p->x2=transparentposts; // post index span_p->light=(*wall*4); numspans++; tpwalls_dest[transparentposts]=sp_dest; tpwalls_colormap[transparentposts]=sp_colormap; tpwalls_count[transparentposts]=sp_count; transparentposts++; #ifdef VALIDATE if (transparentposts>=MAXPEND) MS_Error("Too many Pending Posts! (%i>=%i)",transparentposts,MAXPEND); if (numspans>=MAXSPANS) MS_Error("MAXSPANS exceeded, Walls (%i>=%i)",numspans,MAXSPANS); #endif } else ScalePost(); } } void DrawSteps(int x1, int x2) { int baseangle; byte **postindex1,**postindex2; // start of the 64 entry texture table for t fixed_t distance; // horizontal / vertical dist to wall segmen fixed_t pointz; // transformed distance to wall post fixed_t anglecos; fixed_t textureadjust; // the amount the texture p1ane is shifted fixed_t ceiling1, ceiling2; // top of the wall fixed_t floor1,floor2; // bottom of the wall fixed_t top, bottom; // precise y coordinates for post fixed_t scale; fixed_t cclip1; int topy, bottomy; // pixel y coordinates for post fixed_t fracadjust; // the amount to prestep for the top pixel int angle; // the ray angle that strikes the current po int texture, texture2; // 0-63 post number int x; // collumn and ranges int light; short *wall1, *wall2; unsigned span; span_t *span_p; int walltype1, walltype2, c, rotateright1, rotateright2; int rotateleft1, rotateleft2, tm; int rotateup1, rotateup2, rotatedown1, rotatedown2; boolean floor, ceiling; floor=false; ceiling=false; if (mapflags[mapspot]&FL_FLOOR) goto ceilingstep; baseangle=viewfineangle; switch (side) { case 0: // south facing wall distance=viewy-(tiley<=ceilingheight[mapspot]) walltype=1; // clip beyond this tile floor=true; walltype1=floordef[tm]; rotateright1=floordefflags[tm] & F_RIGHT; rotateleft1=floordefflags[tm] & F_LEFT; rotateup1=floordefflags[tm] & F_UP; rotatedown1=floordefflags[tm] & F_DOWN; cclip1=ceiling1; ceiling1=(ceiling1<=floor2) walltype=1; ceiling=true; ceiling2=(ceiling2<MAXZ || pointz>FRACBITS)+maplight; if (light>MAXZLIGHT) light=MAXZLIGHT; else if (light<0) light=0; sp_colormap=zcolormap[light]; } else if (wallshadow>=5 && wallshadow<=8) { if (wallcycle==wallshadow-5) sp_colormap=colormaps; else { light=(pointz>>FRACBITS)+maplight; if (light>MAXZLIGHT) light=MAXZLIGHT; else if (light<0) light=0; sp_colormap=zcolormap[light]; } } else if (wallshadow==9) { light=(pointz>>FRACBITS)+maplight+wallflicker4; if (light>MAXZLIGHT) light=MAXZLIGHT; else if (light<0) light=0; sp_colormap=zcolormap[light]; } texture=(textureadjust+FIXEDMUL(distance,tangents[angle]))>>FRACBITS; scale=FIXEDMUL(pointz,ISCALE); if (scale<1000) continue; sp_fracstep=scale; /*=======================================*/ if (floor) { texture2=texture; if (rotateright1) texture2-=wallrotate; else if (rotateleft1) texture2+=wallrotate; else if (x==x1 && x!=0) texture2=0; // fix the incorrect looping problem texture2&=63; sp_source=postindex1[texture2]; top=FIXEDDIV(ceiling1,scale); topy=CENTERY - (top>>FRACBITS); fracadjust=top & (FRACUNIT-1); sp_frac=FIXEDMUL(fracadjust,sp_fracstep); if (topy=sp_loopvalue) sp_frac-=sp_loopvalue; topy=scrollmin; } if (rotatedown1) sp_frac+=FRACUNIT*(63-wallrotate); else if (rotateup1) sp_frac+=FRACUNIT*wallrotate; bottom=FIXEDDIV(floor1,scale)+FRACUNIT; bottomy=bottom>=((CENTERY+scrollmin)<>FRACBITS); if ((bottomy=scrollmax)) goto contceiling; sp_count=bottomy-topy+1; sp_dest=viewylookup[bottomy-scrollmin]+x; span=(pointz<spantype=sp_step; span_p->picture=sp_source; span_p->y=sp_frac; // store info in span structure span_p->yh=sp_fracstep; span_p->x2=transparentposts; // post index span_p->light=(*wall1 * 4); numspans++; tpwalls_dest[transparentposts]=sp_dest; tpwalls_colormap[transparentposts]=sp_colormap; tpwalls_count[transparentposts]=sp_count; transparentposts++; #ifdef VALIDATE if (transparentposts>=MAXPEND) MS_Error("Too many Pending Posts! (%i>=%i)",transparentposts,MAXPEND); if (numspans>=MAXSPANS) MS_Error("MAXSPANS exceeded, FloorDefs (%i>=%i)",numspans,MAXSPANS); #endif } contceiling: /*=======================================*/ if (ceiling) { texture2=texture; if (rotateright2) texture2-=wallrotate; else if (rotateleft2) texture2+=wallrotate; else if (x==x1 && x!=0) texture2=0; // fix the incorrect looping problem texture2&=63; sp_source=postindex2[texture2]; top=FIXEDDIV(ceiling2,scale)+FRACUNIT; topy=CENTERY - (top>>FRACBITS); fracadjust=top & (FRACUNIT-1); sp_frac=FIXEDMUL(fracadjust,sp_fracstep); if (topy=sp_loopvalue) sp_frac-=sp_loopvalue; topy=scrollmin; } if (rotatedown2) sp_frac+=FRACUNIT*(63-wallrotate); else if (rotateup2) sp_frac+=FRACUNIT*wallrotate; bottom=FIXEDDIV(floor2,scale)+FRACUNIT; bottomy=bottom>=((CENTERY+scrollmin)<>FRACBITS); if (bottomy=scrollmax) continue; sp_count=bottomy-topy+1; sp_dest=viewylookup[bottomy-scrollmin]+x; span=(pointz<spantype=sp_step; span_p->picture=sp_source; span_p->y=sp_frac; // store info in span structure span_p->yh=sp_fracstep; span_p->x2=transparentposts; // post index span_p->light=(*wall2 * 4); // loop value numspans++; tpwalls_dest[transparentposts]=sp_dest; tpwalls_colormap[transparentposts]=sp_colormap; tpwalls_count[transparentposts]=sp_count; transparentposts++; #ifdef VALIDATE if (transparentposts>=MAXPEND) MS_Error("Too many Pending Posts! (%i>=%i)",transparentposts,MAXPEND); if (numspans>=MAXSPANS) MS_Error("MAXSPANS exceeded, CeilingDefs (%i>=%i)",numspans,MAXSPANS); #endif } } if (floor) { if (walltype) c=WALL_COLOR; else c=STEP_COLOR; switch(side) { case 0: player.northmap[mapspot]=c; break; case 1: player.westmap[mapspot+1]=c; break; case 2: player.northmap[mapspot+MAPCOLS]=c; break; case 3: player.westmap[mapspot]=c; } } }