DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

r_plane.cpp (9208B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
     25 
     26 ===========================================================================
     27 */
     28 
     29 #include "Precompiled.h"
     30 #include "globaldata.h"
     31 
     32 #include <stdlib.h>
     33 
     34 #include "i_system.h"
     35 #include "z_zone.h"
     36 #include "w_wad.h"
     37 
     38 #include "doomdef.h"
     39 #include "doomstat.h"
     40 
     41 #include "r_local.h"
     42 #include "r_sky.h"
     43 
     44 
     45 
     46 
     47 //
     48 // opening
     49 //
     50 
     51 // Here comes the obnoxious "visplane".
     52 
     53 
     54 
     55 //
     56 // Clip values are the solid pixel bounding the range.
     57 //  ::g->floorclip starts out SCREENHEIGHT
     58 //  ::g->ceilingclip starts out -1
     59 //
     60 
     61 //
     62 // ::g->spanstart holds the start of a plane span
     63 // initialized to 0 at start
     64 //
     65 
     66 //
     67 // texture mapping
     68 //
     69 
     70 
     71 
     72 
     73 
     74 //
     75 // R_InitPlanes
     76 // Only at game startup.
     77 //
     78 void R_InitPlanes (void)
     79 {
     80   // Doh!
     81 }
     82 
     83 
     84 //
     85 // R_MapPlane
     86 //
     87 // Uses global vars:
     88 //  ::g->planeheight
     89 //  ::g->ds_source
     90 //  ::g->basexscale
     91 //  ::g->baseyscale
     92 //  ::g->viewx
     93 //  ::g->viewy
     94 //
     95 // BASIC PRIMITIVE
     96 //
     97 void
     98 R_MapPlane
     99 ( int		y,
    100   int		x1,
    101   int		x2 )
    102 {
    103     angle_t	angle;
    104     fixed_t	distance;
    105     fixed_t	length;
    106     unsigned	index;
    107 	
    108 //#ifdef RANGECHECK
    109     if ( x2 < x1 || x1<0 || x2>=::g->viewwidth || y>::g->viewheight )
    110     {
    111 		//I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y);
    112 		return;
    113     }
    114 //#endif
    115 
    116     if (::g->planeheight != ::g->cachedheight[y])
    117     {
    118 	::g->cachedheight[y] = ::g->planeheight;
    119 	distance = ::g->cacheddistance[y] = FixedMul (::g->planeheight, ::g->yslope[y]);
    120 	::g->ds_xstep = ::g->cachedxstep[y] = FixedMul (distance,::g->basexscale);
    121 	::g->ds_ystep = ::g->cachedystep[y] = FixedMul (distance,::g->baseyscale);
    122     }
    123     else
    124     {
    125 	distance = ::g->cacheddistance[y];
    126 	::g->ds_xstep = ::g->cachedxstep[y];
    127 	::g->ds_ystep = ::g->cachedystep[y];
    128     }
    129 	
    130 	extern angle_t GetViewAngle();
    131     length = FixedMul (distance,::g->distscale[x1]);
    132     angle = (GetViewAngle() + ::g->xtoviewangle[x1])>>ANGLETOFINESHIFT;
    133 	extern fixed_t GetViewX(); extern fixed_t GetViewY();
    134     ::g->ds_xfrac = GetViewX() + FixedMul(finecosine[angle], length);
    135     ::g->ds_yfrac = -GetViewY() - FixedMul(finesine[angle], length);
    136 
    137     if (::g->fixedcolormap)
    138 	::g->ds_colormap = ::g->fixedcolormap;
    139     else
    140     {
    141 	index = distance >> LIGHTZSHIFT;
    142 	
    143 	if (index >= MAXLIGHTZ )
    144 	    index = MAXLIGHTZ-1;
    145 
    146 	::g->ds_colormap = ::g->planezlight[index];
    147     }
    148 	
    149     ::g->ds_y = y;
    150     ::g->ds_x1 = x1;
    151     ::g->ds_x2 = x2;
    152 
    153     // high or low detail
    154     spanfunc (
    155 		::g->ds_xfrac,
    156 		::g->ds_yfrac,
    157 		::g->ds_y,
    158 		::g->ds_x1,
    159 		::g->ds_x2,
    160 		::g->ds_xstep,
    161 		::g->ds_ystep,
    162 		::g->ds_colormap,
    163 		::g->ds_source );	
    164 }
    165 
    166 
    167 //
    168 // R_ClearPlanes
    169 // At begining of frame.
    170 //
    171 void R_ClearPlanes (void)
    172 {
    173     int		i;
    174     angle_t	angle;
    175     
    176     // opening / clipping determination
    177     for (i=0 ; i < ::g->viewwidth ; i++)
    178     {
    179 	::g->floorclip[i] = ::g->viewheight;
    180 	::g->ceilingclip[i] = -1;
    181     }
    182 
    183 	::g->lastvisplane = ::g->visplanes;
    184     ::g->lastopening = ::g->openings;
    185 
    186     // texture calculation
    187     memset (::g->cachedheight, 0, sizeof(::g->cachedheight));
    188 
    189     // left to right mapping
    190 	extern angle_t GetViewAngle();
    191     angle = (GetViewAngle()-ANG90)>>ANGLETOFINESHIFT;
    192 	
    193     // scale will be unit scale at SCREENWIDTH/2 distance
    194     ::g->basexscale = FixedDiv (finecosine[angle],::g->centerxfrac);
    195     ::g->baseyscale = -FixedDiv (finesine[angle],::g->centerxfrac);
    196 }
    197 
    198 
    199 
    200 
    201 //
    202 // R_FindPlane
    203 //
    204 visplane_t* R_FindPlane( fixed_t height, int picnum, int lightlevel ) {
    205     visplane_t*	check;
    206 	
    207     if (picnum == ::g->skyflatnum) {
    208 		height = 0;			// all skys map together
    209 		lightlevel = 0;
    210 	}
    211 	
    212 	for (check=::g->visplanes; check < ::g->lastvisplane; check++) {
    213 		if (height == check->height && picnum == check->picnum && lightlevel == check->lightlevel) {
    214 			break;
    215 		}
    216 	}
    217 
    218 	if (check < ::g->lastvisplane)
    219 		return check;
    220 		
    221     //if (::g->lastvisplane - ::g->visplanes == MAXVISPLANES)
    222 		//I_Error ("R_FindPlane: no more visplanes");
    223 	if ( ::g->lastvisplane - ::g->visplanes == MAXVISPLANES ) {
    224 		check = ::g->visplanes;
    225 		return check;
    226 	}
    227 		
    228     ::g->lastvisplane++;
    229 
    230     check->height = height;
    231     check->picnum = picnum;
    232     check->lightlevel = lightlevel;
    233     check->minx = SCREENWIDTH;
    234     check->maxx = -1;
    235 
    236     memset(check->top,0xff,sizeof(check->top));
    237 
    238     return check;
    239 }
    240 
    241 
    242 //
    243 // R_CheckPlane
    244 //
    245 visplane_t*
    246 R_CheckPlane
    247 ( visplane_t*	pl,
    248   int		start,
    249   int		stop )
    250 {
    251     int		intrl;
    252     int		intrh;
    253     int		unionl;
    254     int		unionh;
    255     int		x;
    256 	
    257 	if (start < pl->minx)
    258 	{
    259 		intrl = pl->minx;
    260 		unionl = start;
    261 	}
    262 	else
    263 	{
    264 		unionl = pl->minx;
    265 		intrl = start;
    266 	}
    267 
    268 	if (stop > pl->maxx)
    269 	{
    270 		intrh = pl->maxx;
    271 		unionh = stop;
    272 	}
    273 	else
    274 	{
    275 		unionh = pl->maxx;
    276 		intrh = stop;
    277 	}
    278 
    279 	for (x=intrl ; x<= intrh ; x++)
    280 		if (pl->top[x] != 0xffff)
    281 			break;
    282 
    283 	if (x > intrh)
    284 	{
    285 		pl->minx = unionl;
    286 		pl->maxx = unionh;
    287 
    288 		// use the same one
    289 		return pl;		
    290 	}
    291 	
    292 	if ( ::g->lastvisplane - ::g->visplanes == MAXVISPLANES ) {
    293 		return pl;
    294 	}
    295 
    296     // make a new visplane
    297     ::g->lastvisplane->height = pl->height;
    298     ::g->lastvisplane->picnum = pl->picnum;
    299     ::g->lastvisplane->lightlevel = pl->lightlevel;
    300     
    301     pl = ::g->lastvisplane++;
    302     pl->minx = start;
    303     pl->maxx = stop;
    304 
    305     memset(pl->top,0xff,sizeof(pl->top));
    306 		
    307     return pl;
    308 }
    309 
    310 
    311 //
    312 // R_MakeSpans
    313 //
    314 void
    315 R_MakeSpans
    316 ( int		x,
    317   int		t1,
    318   int		b1,
    319   int		t2,
    320   int		b2 )
    321 {
    322     while (t1 < t2 && t1<=b1)
    323     {
    324 	R_MapPlane (t1,::g->spanstart[t1],x-1);
    325 	t1++;
    326     }
    327     while (b1 > b2 && b1>=t1)
    328     {
    329 	R_MapPlane (b1,::g->spanstart[b1],x-1);
    330 	b1--;
    331     }
    332 	
    333     while (t2 < t1 && t2<=b2)
    334     {
    335 	::g->spanstart[t2] = x;
    336 	t2++;
    337     }
    338     while (b2 > b1 && b2>=t2)
    339     {
    340 	::g->spanstart[b2] = x;
    341 	b2--;
    342     }
    343 }
    344 
    345 
    346 
    347 //
    348 // R_DrawPlanes
    349 // At the end of each frame.
    350 //
    351 void R_DrawPlanes (void)
    352 {
    353     visplane_t*		pl;
    354     int			light;
    355     int			x;
    356     int			stop;
    357     int			angle;
    358 				
    359 #ifdef RANGECHECK
    360     if (::g->ds_p - ::g->drawsegs > MAXDRAWSEGS)
    361 	I_Error ("R_DrawPlanes: ::g->drawsegs overflow (%i)",
    362 		 ::g->ds_p - ::g->drawsegs);
    363     
    364     if (::g->lastvisplane - ::g->visplanes > MAXVISPLANES)
    365 	I_Error ("R_DrawPlanes: visplane overflow (%i)",
    366 		 ::g->lastvisplane - ::g->visplanes);
    367     
    368     if (::g->lastopening - ::g->openings > MAXOPENINGS)
    369 	I_Error ("R_DrawPlanes: opening overflow (%i)",
    370 		 ::g->lastopening - ::g->openings);
    371 #endif
    372 
    373     for (pl = ::g->visplanes ; pl < ::g->lastvisplane ; pl++)
    374     {
    375 	if (pl->minx > pl->maxx)
    376 	    continue;
    377 
    378 	
    379 	// sky flat
    380 	if (pl->picnum == ::g->skyflatnum)
    381 	{
    382 	    ::g->dc_iscale = ::g->pspriteiscale>>::g->detailshift;
    383 	    
    384 	    // Sky is allways drawn full bright,
    385 	    //  i.e. ::g->colormaps[0] is used.
    386 	    // Because of this hack, sky is not affected
    387 	    //  by INVUL inverse mapping.
    388 	    ::g->dc_colormap = ::g->colormaps;
    389 	    ::g->dc_texturemid = ::g->skytexturemid;
    390 	    for (x=pl->minx ; x <= pl->maxx ; x++)
    391 	    {
    392 		::g->dc_yl = pl->top[x];
    393 		::g->dc_yh = pl->bottom[x];
    394 
    395 		if (::g->dc_yl <= ::g->dc_yh)
    396 		{
    397 			extern angle_t GetViewAngle();
    398 		    angle = (GetViewAngle() + ::g->xtoviewangle[x])>>ANGLETOSKYSHIFT;
    399 		    ::g->dc_x = x;
    400 		    ::g->dc_source = R_GetColumn(::g->skytexture, angle);
    401 		    colfunc ( ::g->dc_colormap, ::g->dc_source );
    402 		}
    403 	    }
    404 	    continue;
    405 	}
    406 	
    407 	// regular flat
    408 	::g->ds_source = (byte*)W_CacheLumpNum(::g->firstflat +
    409 				   ::g->flattranslation[pl->picnum],
    410 				   PU_CACHE_SHARED);
    411 	
    412 	::g->planeheight = abs(pl->height-::g->viewz);
    413 	light = (pl->lightlevel >> LIGHTSEGSHIFT)+::g->extralight;
    414 
    415 	if (light >= LIGHTLEVELS)
    416 	    light = LIGHTLEVELS-1;
    417 
    418 	if (light < 0)
    419 	    light = 0;
    420 
    421 	::g->planezlight = ::g->zlight[light];
    422 
    423 	pl->top[pl->maxx+1] = 0xffff;
    424 	pl->top[pl->minx-1] = 0xffff;
    425 		
    426 	stop = pl->maxx + 1;
    427 
    428 	for (x=pl->minx ; x<= stop ; x++)
    429 	{
    430 	    R_MakeSpans(x,pl->top[x-1],
    431 			pl->bottom[x-1],
    432 			pl->top[x],
    433 			pl->bottom[x]);
    434 	}
    435     }
    436 }
    437