/* R_planes.c */ #include "doomdef.h" #include "r_local.h" planefunction_t floorfunc, ceilingfunc; extern int weirdaspect; /* * sky mapping */ int skyflatnum; int skytexture; int skytexturemid; fixed_t skyiscale; /* * opening */ visplane_t visplanes[MAXVISPLANES], *lastvisplane; visplane_t *floorplane, *ceilingplane; short *openings, *lastopening; /* * clip values are the solid pixel bounding the range * floorclip starts out screenheight * ceilingclip starts out -1 */ short *floorclip; short *ceilingclip; /* * spanstart holds the start of a plane span * initialized to 0 at start */ int *spanstart; int *spanstop; /* * texture mapping */ lighttable_t **planezlight; fixed_t planeheight; fixed_t *yslope; fixed_t *distscale; fixed_t basexscale, baseyscale; fixed_t *cachedheight; fixed_t *cacheddistance; fixed_t *cachedxstep; fixed_t *cachedystep; void resinit_r_plane_c(void) { /* called before anything else */ int i; for (i=0; i=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 = = At begining of frame ==================== */ void R_ClearPlanes (void) { int i; angle_t angle; /* * opening / clipping determination */ for (i=0 ; i>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(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)); */ memset(check->top, 0xff, screenwidth*sizeof(unsigned short)); 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++) /* ANDRE !!! or if (pl->top[x] != 0xffff) ? */ if (pl->top[x] != 0xff) break; if (x > intrh) { pl->minx = unionl; pl->maxx = unionh; return pl; /* use the same one */ } /* 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)); */ memset(pl->top, 0xff, screenwidth*sizeof(unsigned short)); 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 = = At the end of each frame ================ */ void R_DrawPlanes (void) { visplane_t *pl; int light; int x, stop; int angle; byte *tempSource; byte *dest; int count; fixed_t frac, fracstep; extern byte *ylookup[MAXSCREENHEIGHT]; extern int columnofs[MAXSCREENWIDTH]; #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; /* * sky flat */ if (pl->picnum == skyflatnum) {/* if ((screenwidth>320) || (screenheight>200)) { dc_iscale = FixedDiv(FRACUNIT, pspriteyscale); } else*/ dc_iscale = skyiscale; if (!weirdaspect) dc_iscale = FixedMul(dc_iscale, (fixed_t)((200.0/240.0) * (double)FRACUNIT)); dc_colormap = colormaps; /* sky is allways drawn full bright */ dc_texturemid = skytexturemid; for (x=pl->minx ; x <= pl->maxx ; x++) { dc_yl = pl->top[x]; dc_yh = pl->bottom[x]; if (dc_yl <= dc_yh) { angle = (viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; dc_x = x; dc_source = R_GetColumn(skytexture, angle); if ((screenwidth>320) || (screenheight>200)) { /* Is this correct ? */ /* R_DrawSkyColumn(); */ colfunc(); } else { count = dc_yh - dc_yl; if (count < 0) return; #ifdef RANGECHECK if ((unsigned)dc_x >= screenwidth || dc_yl < 0 || dc_yh >= screenheight) I_Error ("R_DrawSpecColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); #endif dest = ylookup[dc_yl] + columnofs[dc_x]; fracstep = 1; frac = (dc_texturemid>>FRACBITS) + (dc_yl-centery); do { *dest = dc_source[frac]; dest += screenwidth; frac += fracstep; } while (count--); } } } continue; } /* * regular flat */ tempSource = W_CacheLumpNum(firstflat + flattranslation[pl->picnum], PU_STATIC); switch(pl->special) { case 25: case 26: case 27: case 28: case 29: /* Scroll_North */ ds_source = tempSource; break; case 20: case 21: case 22: case 23: case 24: /* Scroll_East */ ds_source = tempSource+((63-((leveltime>>1)&63))<< (pl->special-20)&63); /* ds_source = tempSource+((leveltime>>1)&63); */ break; case 30: case 31: case 32: case 33: case 34: /* Scroll_South */ ds_source = tempSource; break; case 35: case 36: case 37: case 38: case 39: /* Scroll_West */ ds_source = tempSource; break; case 4: /* Scroll_EastLavaDamage */ ds_source = tempSource+(((63-((leveltime>>1)&63))<<3)&63); break; default: ds_source = tempSource; } 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] = 0xffff; pl->top[pl->minx-1] = 0xffff; 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); } }