doom

a minimalistic implementation of doom
git clone git://ssnf.xyz/doom
Log | Files | Refs

r_plane.c (6029B)


      1 #include <stdlib.h>
      2 
      3 #include "i_system.h"
      4 #include "z_zone.h"
      5 #include "w_wad.h"
      6 #include "doomdef.h"
      7 #include "doomstat.h"
      8 #include "r_local.h"
      9 
     10 planefunction_t		floorfunc;
     11 planefunction_t		ceilingfunc;
     12 #define MAXVISPLANES	128
     13 visplane_t		visplanes[MAXVISPLANES];
     14 visplane_t*		lastvisplane;
     15 visplane_t*		floorplane;
     16 visplane_t*		ceilingplane;
     17 #define MAXOPENINGS	SCREENWIDTH*64
     18 short			openings[MAXOPENINGS];
     19 short*			lastopening;
     20 short			floorclip[SCREENWIDTH];
     21 short			ceilingclip[SCREENWIDTH];
     22 int			spanstart[SCREENHEIGHT];
     23 int			spanstop[SCREENHEIGHT];
     24 lighttable_t**		planezlight;
     25 fixed_t			planeheight;
     26 fixed_t			yslope[SCREENHEIGHT];
     27 fixed_t			distscale[SCREENWIDTH];
     28 fixed_t			basexscale;
     29 fixed_t			baseyscale;
     30 fixed_t			cachedheight[SCREENHEIGHT];
     31 fixed_t			cacheddistance[SCREENHEIGHT];
     32 fixed_t			cachedxstep[SCREENHEIGHT];
     33 fixed_t			cachedystep[SCREENHEIGHT];
     34 
     35 void
     36 R_InitPlanes()
     37 {
     38 }
     39 
     40 void
     41 R_MapPlane(int y, int x1, int x2)
     42 {
     43     angle_t angle;
     44     fixed_t distance, length;
     45     uint index;
     46 	
     47     if (planeheight != cachedheight[y]) {
     48 		cachedheight[y] = planeheight;
     49 		distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]);
     50 		ds_xstep = cachedxstep[y] = FixedMul (distance,basexscale);
     51 		ds_ystep = cachedystep[y] = FixedMul (distance,baseyscale);
     52     } else {
     53 		distance = cacheddistance[y];
     54 		ds_xstep = cachedxstep[y];
     55 		ds_ystep = cachedystep[y];
     56     }
     57     length = FixedMul (distance,distscale[x1]);
     58     angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT;
     59     ds_xfrac = viewx + FixedMul(finecosine[angle], length);
     60     ds_yfrac = -viewy - FixedMul(finesine[angle], length);
     61     if (fixedcolormap) {
     62 		ds_colormap = fixedcolormap;
     63 	} else {
     64 		index = distance >> LIGHTZSHIFT;
     65 		if (index >= MAXLIGHTZ )
     66 			index = MAXLIGHTZ-1;
     67 		ds_colormap = planezlight[index];
     68     }
     69     ds_y = y;
     70     ds_x1 = x1;
     71     ds_x2 = x2;
     72     spanfunc();	
     73 }
     74 
     75 void
     76 R_ClearPlanes (void)
     77 {
     78     int		i;
     79     angle_t	angle;
     80     
     81     
     82     for (i=0 ; i<viewwidth ; i++)
     83     {
     84 	floorclip[i] = viewheight;
     85 	ceilingclip[i] = -1;
     86     }
     87 
     88     lastvisplane = visplanes;
     89     lastopening = openings;
     90     
     91     
     92     memset (cachedheight, 0, sizeof(cachedheight));
     93 
     94     
     95     angle = (viewangle-ANG90)>>ANGLETOFINESHIFT;
     96 	
     97     
     98     basexscale = FixedDiv (finecosine[angle],centerxfrac);
     99     baseyscale = -FixedDiv (finesine[angle],centerxfrac);
    100 }
    101 
    102 
    103 
    104 
    105 
    106 
    107 
    108 visplane_t*
    109 R_FindPlane
    110 ( fixed_t	height,
    111   int		picnum,
    112   int		lightlevel )
    113 {
    114     visplane_t*	check;
    115 	
    116     if (picnum == skyflatnum)
    117     {
    118 	height = 0;			
    119 	lightlevel = 0;
    120     }
    121 	
    122     for (check=visplanes; check<lastvisplane; check++)
    123     {
    124 	if (height == check->height
    125 	    && picnum == check->picnum
    126 	    && lightlevel == check->lightlevel)
    127 	{
    128 	    break;
    129 	}
    130     }
    131     
    132 			
    133     if (check < lastvisplane)
    134 	return check;
    135 		
    136     if (lastvisplane - visplanes == MAXVISPLANES)
    137 	I_Error ("R_FindPlane: no more visplanes");
    138 		
    139     lastvisplane++;
    140 
    141     check->height = height;
    142     check->picnum = picnum;
    143     check->lightlevel = lightlevel;
    144     check->minx = SCREENWIDTH;
    145     check->maxx = -1;
    146     
    147     memset (check->top,0xff,sizeof(check->top));
    148 		
    149     return check;
    150 }
    151 
    152 
    153 
    154 
    155 
    156 visplane_t*
    157 R_CheckPlane
    158 ( visplane_t*	pl,
    159   int		start,
    160   int		stop )
    161 {
    162     int		intrl;
    163     int		intrh;
    164     int		unionl;
    165     int		unionh;
    166     int		x;
    167 	
    168     if (start < pl->minx)
    169     {
    170 	intrl = pl->minx;
    171 	unionl = start;
    172     }
    173     else
    174     {
    175 	unionl = pl->minx;
    176 	intrl = start;
    177     }
    178 	
    179     if (stop > pl->maxx)
    180     {
    181 	intrh = pl->maxx;
    182 	unionh = stop;
    183     }
    184     else
    185     {
    186 	unionh = pl->maxx;
    187 	intrh = stop;
    188     }
    189 
    190     for (x=intrl ; x<= intrh ; x++)
    191 	if (pl->top[x] != 0xff)
    192 	    break;
    193 
    194     if (x > intrh)
    195     {
    196 	pl->minx = unionl;
    197 	pl->maxx = unionh;
    198 
    199 	
    200 	return pl;		
    201     }
    202 	
    203     
    204     lastvisplane->height = pl->height;
    205     lastvisplane->picnum = pl->picnum;
    206     lastvisplane->lightlevel = pl->lightlevel;
    207     
    208     pl = lastvisplane++;
    209     pl->minx = start;
    210     pl->maxx = stop;
    211 
    212     memset (pl->top,0xff,sizeof(pl->top));
    213 		
    214     return pl;
    215 }
    216 
    217 
    218 
    219 
    220 
    221 void
    222 R_MakeSpans
    223 ( int		x,
    224   int		t1,
    225   int		b1,
    226   int		t2,
    227   int		b2 )
    228 {
    229     while (t1 < t2 && t1<=b1)
    230     {
    231 	R_MapPlane (t1,spanstart[t1],x-1);
    232 	t1++;
    233     }
    234     while (b1 > b2 && b1>=t1)
    235     {
    236 	R_MapPlane (b1,spanstart[b1],x-1);
    237 	b1--;
    238     }
    239 	
    240     while (t2 < t1 && t2<=b2)
    241     {
    242 	spanstart[t2] = x;
    243 	t2++;
    244     }
    245     while (b2 > b1 && b2>=t2)
    246     {
    247 	spanstart[b2] = x;
    248 	b2--;
    249     }
    250 }
    251 
    252 
    253 
    254 
    255 
    256 
    257 
    258 void R_DrawPlanes (void)
    259 {
    260     visplane_t*		pl;
    261     int			light;
    262     int			x;
    263     int			stop;
    264     int			angle;
    265 				
    266 #ifdef RANGECHECK
    267     if (ds_p - drawsegs > MAXDRAWSEGS)
    268 	I_Error ("R_DrawPlanes: drawsegs overflow (%i)",
    269 		 ds_p - drawsegs);
    270     
    271     if (lastvisplane - visplanes > MAXVISPLANES)
    272 	I_Error ("R_DrawPlanes: visplane overflow (%i)",
    273 		 lastvisplane - visplanes);
    274     
    275     if (lastopening - openings > MAXOPENINGS)
    276 	I_Error ("R_DrawPlanes: opening overflow (%i)",
    277 		 lastopening - openings);
    278 #endif
    279 
    280     for (pl = visplanes ; pl < lastvisplane ; pl++)
    281     {
    282 	if (pl->minx > pl->maxx)
    283 	    continue;
    284 
    285 	
    286 	
    287 	if (pl->picnum == skyflatnum)
    288 	{
    289 	    dc_iscale = pspriteiscale>>detailshift;
    290 	    
    291 	    
    292 	    
    293 	    
    294 	    
    295 	    dc_colormap = colormaps;
    296 	    dc_texturemid = skytexturemid;
    297 	    for (x=pl->minx ; x <= pl->maxx ; x++)
    298 	    {
    299 		dc_yl = pl->top[x];
    300 		dc_yh = pl->bottom[x];
    301 
    302 		if (dc_yl <= dc_yh)
    303 		{
    304 		    angle = (viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT;
    305 		    dc_x = x;
    306 		    dc_source = R_GetColumn(skytexture, angle);
    307 		    colfunc ();
    308 		}
    309 	    }
    310 	    continue;
    311 	}
    312 	
    313 	
    314 	ds_source = W_CacheLumpNum(firstflat +
    315 				   flattranslation[pl->picnum],
    316 				   PU_STATIC);
    317 	
    318 	planeheight = abs(pl->height-viewz);
    319 	light = (pl->lightlevel >> LIGHTSEGSHIFT)+extralight;
    320 
    321 	if (light >= LIGHTLEVELS)
    322 	    light = LIGHTLEVELS-1;
    323 
    324 	if (light < 0)
    325 	    light = 0;
    326 
    327 	planezlight = zlight[light];
    328 
    329 	pl->top[pl->maxx+1] = 0xff;
    330 	pl->top[pl->minx-1] = 0xff;
    331 		
    332 	stop = pl->maxx + 1;
    333 
    334 	for (x=pl->minx ; x<= stop ; x++)
    335 	{
    336 	    R_MakeSpans(x,pl->top[x-1],
    337 			pl->bottom[x-1],
    338 			pl->top[x],
    339 			pl->bottom[x]);
    340 	}
    341 	
    342 	Z_ChangeTag (ds_source, PU_CACHE);
    343     }
    344 }