doom

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

r_segs.c (12546B)


      1 #include <stdlib.h>
      2 
      3 #include "i_system.h"
      4 #include "doomdef.h"
      5 #include "doomstat.h"
      6 #include "r_local.h"
      7 #include "r_things.h"
      8 
      9 boolean		segtextured;	
     10 boolean		markfloor;	
     11 boolean		markceiling;
     12 boolean		maskedtexture;
     13 int			   toptexture;
     14 int			   bottomtexture;
     15 int			   midtexture;
     16 angle_t		rw_normalangle;
     17 int			rw_angle1;	
     18 int			rw_x;
     19 int			rw_stopx;
     20 angle_t		rw_centerangle;
     21 fixed_t		rw_offset;
     22 fixed_t		rw_distance;
     23 fixed_t		rw_scale;
     24 fixed_t		rw_scalestep;
     25 fixed_t		rw_midtexturemid;
     26 fixed_t		rw_toptexturemid;
     27 fixed_t		rw_bottomtexturemid;
     28 int			worldtop;
     29 int			worldbottom;
     30 int			worldhigh;
     31 int			worldlow;
     32 fixed_t		pixhigh;
     33 fixed_t		pixlow;
     34 fixed_t		pixhighstep;
     35 fixed_t		pixlowstep;
     36 fixed_t		topfrac;
     37 fixed_t		topstep;
     38 fixed_t		bottomfrac;
     39 fixed_t		bottomstep;
     40 lighttable_t** walllights;
     41 short*		 maskedtexturecol;
     42 
     43 void
     44 R_RenderMaskedSegRange(drawseg_t* ds, int x1, int x2)
     45 {
     46 	column_t* col;
     47 	uint	  index;
     48 	int       lightnum, texnum;
     49 	
     50 	curline = ds->curline;
     51 	frontsector = curline->frontsector;
     52 	backsector = curline->backsector;
     53 	texnum = texturetranslation[curline->sidedef->midtexture];
     54 	lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
     55 	if (curline->v1->y == curline->v2->y)
     56 		--lightnum;
     57 	if (curline->v1->x == curline->v2->x)
     58 		++lightnum;
     59 	if (lightnum < 0)		
     60 		walllights = scalelight[0];
     61 	else if (lightnum >= LIGHTLEVELS)
     62 		walllights = scalelight[LIGHTLEVELS-1];
     63 	else
     64 		walllights = scalelight[lightnum];
     65 	maskedtexturecol = ds->maskedtexturecol;
     66 	rw_scalestep = ds->scalestep;		
     67 	spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
     68 	mfloorclip = ds->sprbottomclip;
     69 	mceilingclip = ds->sprtopclip;
     70 	if (curline->linedef->flags & ML_DONTPEGBOTTOM) {
     71 		dc_texturemid =
     72 			frontsector->floorheight > backsector->floorheight
     73 			? frontsector->floorheight
     74 			: backsector->floorheight;
     75 		dc_texturemid = dc_texturemid + textureheight_g[texnum] - viewz;
     76 	} else {
     77 		dc_texturemid =
     78 			frontsector->ceilingheight<backsector->ceilingheight
     79 			? frontsector->ceilingheight
     80 			: backsector->ceilingheight;
     81 		dc_texturemid = dc_texturemid - viewz;
     82 	}
     83 	dc_texturemid += curline->sidedef->rowoffset;
     84 	if (fixedcolormap)
     85 		dc_colormap = fixedcolormap;
     86 	for (dc_x = x1; dc_x <= x2; ++dc_x) {
     87 		if (maskedtexturecol[dc_x] != SHRT_MAX) {
     88 			if (!fixedcolormap) {
     89 				index = spryscale >> LIGHTSCALESHIFT;
     90 				if (index >=  MAXLIGHTSCALE )
     91 					index = MAXLIGHTSCALE-1;
     92 				dc_colormap = walllights[index];
     93 			}
     94 			sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
     95 			dc_iscale = 0xffffffffu / (unsigned)spryscale;
     96 			col = (column_t*)((byte*)R_GetColumn(texnum,maskedtexturecol[dc_x]) -3);
     97 			R_DrawMaskedColumn(col);
     98 			maskedtexturecol[dc_x] = SHRT_MAX;
     99 		}
    100 		spryscale += rw_scalestep;
    101 	}
    102 }
    103 
    104 #define HEIGHTBITS 12
    105 #define HEIGHTUNIT (1<<HEIGHTBITS)
    106 
    107 void
    108 R_RenderSegLoop()
    109 {
    110 	angle_t angle;
    111 	fixed_t texturecolumn;
    112 	uint	index;
    113 	int	 yl, yh, mid, top, bottom;
    114 	
    115 	texturecolumn = 0;
    116 	for (; rw_x < rw_stopx; ++rw_x) {
    117 	yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;
    118 	if (yl < ceilingclip[rw_x]+1)
    119 		yl = ceilingclip[rw_x]+1;
    120 	if (markceiling) {
    121 		top = ceilingclip[rw_x] + 1;
    122 		bottom = yl - 1;
    123 		if (bottom >= floorclip[rw_x])
    124 			bottom = floorclip[rw_x]-1;
    125 		if (top <= bottom) {
    126 			ceilingplane->top[rw_x] = top;
    127 			ceilingplane->bottom[rw_x] = bottom;
    128 		}
    129 	}
    130 	yh = bottomfrac>>HEIGHTBITS;
    131 	if (yh >= floorclip[rw_x])
    132 		yh = floorclip[rw_x]-1;
    133 	if (markfloor) {
    134 		top = yh + 1;
    135 		bottom = floorclip[rw_x] - 1;
    136 		if (top <= ceilingclip[rw_x])
    137 		top = ceilingclip[rw_x] + 1;
    138 		if (top <= bottom) {
    139 			floorplane->top[rw_x] = top;
    140 			floorplane->bottom[rw_x] = bottom;
    141 		}
    142 	}
    143 	if (segtextured) {
    144 		angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
    145 		texturecolumn = rw_offset - FixedMul(finetangent[angle], rw_distance);
    146 		texturecolumn >>= FRACBITS;
    147 		index = rw_scale>>LIGHTSCALESHIFT;
    148 		if (index >=  MAXLIGHTSCALE)
    149 			index = MAXLIGHTSCALE-1;
    150 		dc_colormap = walllights[index];
    151 		dc_x = rw_x;
    152 		dc_iscale = 0xffffffffu / (unsigned)rw_scale;
    153 	}
    154 	if (midtexture) {
    155 		dc_yl = yl;
    156 		dc_yh = yh;
    157 		dc_texturemid = rw_midtexturemid;
    158 		dc_source = R_GetColumn(midtexture,texturecolumn);
    159 		colfunc ();
    160 		ceilingclip[rw_x] = viewheight;
    161 		floorclip[rw_x] = -1;
    162 	} else {
    163 		if (toptexture) {
    164 			mid = pixhigh>>HEIGHTBITS;
    165 			pixhigh += pixhighstep;
    166 			if (mid >= floorclip[rw_x])
    167 				mid = floorclip[rw_x]-1;
    168 			if (mid >= yl) {
    169 				dc_yl = yl;
    170 				dc_yh = mid;
    171 				dc_texturemid = rw_toptexturemid;
    172 				dc_source = R_GetColumn(toptexture, texturecolumn);
    173 				colfunc();
    174 				ceilingclip[rw_x] = mid;
    175 			} else
    176 				ceilingclip[rw_x] = yl-1;
    177 		} else {
    178 			if (markceiling)
    179 				ceilingclip[rw_x] = yl-1;
    180 		}
    181 		if (bottomtexture) {
    182 			mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
    183 			pixlow += pixlowstep;
    184 			if (mid <= ceilingclip[rw_x])
    185 				mid = ceilingclip[rw_x]+1;
    186 			if (mid <= yh) {
    187 				dc_yl = mid;
    188 				dc_yh = yh;
    189 				dc_texturemid = rw_bottomtexturemid;
    190 				dc_source = R_GetColumn(bottomtexture,
    191 				texturecolumn);
    192 				colfunc();
    193 				floorclip[rw_x] = mid;
    194 			} else
    195 				floorclip[rw_x] = yh+1;
    196 		} else {
    197 			if (markfloor)
    198 				floorclip[rw_x] = yh+1;
    199 		}
    200 		if (maskedtexture)
    201 			maskedtexturecol[rw_x] = texturecolumn;
    202 	}
    203 	rw_scale += rw_scalestep;
    204 	topfrac += topstep;
    205 	bottomfrac += bottomstep;
    206 	}
    207 }
    208 
    209 void
    210 R_StoreWallRange(int start, int stop)
    211 {
    212 	fixed_t		hyp, sineval, vtop;
    213 	angle_t		distangle, offsetangle;
    214 	int			lightnum;
    215 	
    216 	if (ds_p == &drawsegs[MAXDRAWSEGS])
    217 		return;		
    218 #ifdef RANGECHECK
    219 	if (start >=viewwidth || start > stop)
    220 		I_Error("Bad R_RenderWallRange: %i to %i", start , stop);
    221 #endif
    222 	sidedef = curline->sidedef;
    223 	linedef = curline->linedef;
    224 	linedef->flags |= ML_MAPPED;
    225 	rw_normalangle = curline->angle + ANG90;
    226 	offsetangle = abs(rw_normalangle-rw_angle1);
    227 	if (offsetangle > ANG90)
    228 		offsetangle = ANG90;
    229 	distangle = ANG90 - offsetangle;
    230 	hyp = R_PointToDist (curline->v1->x, curline->v1->y);
    231 	sineval = finesine[distangle>>ANGLETOFINESHIFT];
    232 	rw_distance = FixedMul (hyp, sineval);
    233 	ds_p->x1 = rw_x = start;
    234 	ds_p->x2 = stop;
    235 	ds_p->curline = curline;
    236 	rw_stopx = stop+1;
    237 	ds_p->scale1 = rw_scale = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[start]);
    238 	if (stop > start) {
    239 	ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]);
    240 	ds_p->scalestep = rw_scalestep = 
    241 		(ds_p->scale2 - rw_scale) / (stop-start);
    242 	}
    243 	else
    244 	{
    245 	
    246 #if 0
    247 	if (rw_distance < FRACUNIT/2)
    248 	{
    249 		fixed_t		trx,try;
    250 		fixed_t		gxt,gyt;
    251 
    252 		trx = curline->v1->x - viewx;
    253 		try = curline->v1->y - viewy;
    254 			
    255 		gxt = FixedMul(trx,viewcos); 
    256 		gyt = -FixedMul(try,viewsin); 
    257 		ds_p->scale1 = FixedDiv(projection, gxt-gyt)<<detailshift;
    258 	}
    259 #endif
    260 	ds_p->scale2 = ds_p->scale1;
    261 	}
    262 	
    263 	
    264 	
    265 	worldtop = frontsector->ceilingheight - viewz;
    266 	worldbottom = frontsector->floorheight - viewz;
    267 	
    268 	midtexture = toptexture = bottomtexture = maskedtexture = 0;
    269 	ds_p->maskedtexturecol = NULL;
    270 	
    271 	if (!backsector)
    272 	{
    273 	
    274 	midtexture = texturetranslation[sidedef->midtexture];
    275 	
    276 	markfloor = markceiling = true;
    277 	if (linedef->flags & ML_DONTPEGBOTTOM)
    278 	{
    279 		vtop = frontsector->floorheight +
    280 		textureheight_g[sidedef->midtexture];
    281 		
    282 		rw_midtexturemid = vtop - viewz;	
    283 	}
    284 	else
    285 	{
    286 		
    287 		rw_midtexturemid = worldtop;
    288 	}
    289 	rw_midtexturemid += sidedef->rowoffset;
    290 
    291 	ds_p->silhouette = SIL_BOTH;
    292 	ds_p->sprtopclip = screenheightarray;
    293 	ds_p->sprbottomclip = negonearray;
    294 	ds_p->bsilheight = INT_MAX;
    295 	ds_p->tsilheight = INT_MIN;
    296 	}
    297 	else
    298 	{
    299 	
    300 	ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
    301 	ds_p->silhouette = 0;
    302 	
    303 	if (frontsector->floorheight > backsector->floorheight)
    304 	{
    305 		ds_p->silhouette = SIL_BOTTOM;
    306 		ds_p->bsilheight = frontsector->floorheight;
    307 	}
    308 	else if (backsector->floorheight > viewz)
    309 	{
    310 		ds_p->silhouette = SIL_BOTTOM;
    311 		ds_p->bsilheight = INT_MAX;
    312 		
    313 	}
    314 	
    315 	if (frontsector->ceilingheight < backsector->ceilingheight)
    316 	{
    317 		ds_p->silhouette |= SIL_TOP;
    318 		ds_p->tsilheight = frontsector->ceilingheight;
    319 	}
    320 	else if (backsector->ceilingheight < viewz)
    321 	{
    322 		ds_p->silhouette |= SIL_TOP;
    323 		ds_p->tsilheight = INT_MIN;
    324 		
    325 	}
    326 		
    327 	if (backsector->ceilingheight <= frontsector->floorheight)
    328 	{
    329 		ds_p->sprbottomclip = negonearray;
    330 		ds_p->bsilheight = INT_MAX;
    331 		ds_p->silhouette |= SIL_BOTTOM;
    332 	}
    333 	
    334 	if (backsector->floorheight >= frontsector->ceilingheight)
    335 	{
    336 		ds_p->sprtopclip = screenheightarray;
    337 		ds_p->tsilheight = INT_MIN;
    338 		ds_p->silhouette |= SIL_TOP;
    339 	}
    340 	
    341 	worldhigh = backsector->ceilingheight - viewz;
    342 	worldlow = backsector->floorheight - viewz;
    343 		
    344 	
    345 	if (frontsector->ceilingpic == skyflatnum 
    346 		&& backsector->ceilingpic == skyflatnum)
    347 	{
    348 		worldtop = worldhigh;
    349 	}
    350 	
    351 			
    352 	if (worldlow != worldbottom 
    353 		|| backsector->floorpic != frontsector->floorpic
    354 		|| backsector->lightlevel != frontsector->lightlevel)
    355 	{
    356 		markfloor = true;
    357 	}
    358 	else
    359 	{
    360 		
    361 		markfloor = false;
    362 	}
    363 	
    364 			
    365 	if (worldhigh != worldtop 
    366 		|| backsector->ceilingpic != frontsector->ceilingpic
    367 		|| backsector->lightlevel != frontsector->lightlevel)
    368 	{
    369 		markceiling = true;
    370 	}
    371 	else
    372 	{
    373 		
    374 		markceiling = false;
    375 	}
    376 	
    377 	if (backsector->ceilingheight <= frontsector->floorheight
    378 		|| backsector->floorheight >= frontsector->ceilingheight)
    379 	{
    380 		
    381 		markceiling = markfloor = true;
    382 	}
    383 	
    384 
    385 	if (worldhigh < worldtop)
    386 	{
    387 		
    388 		toptexture = texturetranslation[sidedef->toptexture];
    389 		if (linedef->flags & ML_DONTPEGTOP)
    390 		{
    391 		
    392 		rw_toptexturemid = worldtop;
    393 		}
    394 		else
    395 		{
    396 		vtop =
    397 			backsector->ceilingheight
    398 			+ textureheight_g[sidedef->toptexture];
    399 		
    400 		
    401 		rw_toptexturemid = vtop - viewz;	
    402 		}
    403 	}
    404 	if (worldlow > worldbottom)
    405 	{
    406 		
    407 		bottomtexture = texturetranslation[sidedef->bottomtexture];
    408 
    409 		if (linedef->flags & ML_DONTPEGBOTTOM )
    410 		{
    411 		
    412 		
    413 		rw_bottomtexturemid = worldtop;
    414 		}
    415 		else	
    416 		rw_bottomtexturemid = worldlow;
    417 	}
    418 	rw_toptexturemid += sidedef->rowoffset;
    419 	rw_bottomtexturemid += sidedef->rowoffset;
    420 	
    421 	
    422 	if (sidedef->midtexture)
    423 	{
    424 		
    425 		maskedtexture = true;
    426 		ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x;
    427 		lastopening += rw_stopx - rw_x;
    428 	}
    429 	}
    430 	
    431 	
    432 	segtextured = midtexture | toptexture | bottomtexture | maskedtexture;
    433 
    434 	if (segtextured)
    435 	{
    436 	offsetangle = rw_normalangle-rw_angle1;
    437 	
    438 	if (offsetangle > ANG180)
    439 		offsetangle = -offsetangle;
    440 
    441 	if (offsetangle > ANG90)
    442 		offsetangle = ANG90;
    443 
    444 	sineval = finesine[offsetangle >>ANGLETOFINESHIFT];
    445 	rw_offset = FixedMul (hyp, sineval);
    446 
    447 	if (rw_normalangle-rw_angle1 < ANG180)
    448 		rw_offset = -rw_offset;
    449 
    450 	rw_offset += sidedef->textureoffset + curline->offset;
    451 	rw_centerangle = ANG90 + viewangle - rw_normalangle;
    452 	
    453 	
    454 	
    455 	
    456 	
    457 	if (!fixedcolormap)
    458 	{
    459 		lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight;
    460 
    461 		if (curline->v1->y == curline->v2->y)
    462 		lightnum--;
    463 		else if (curline->v1->x == curline->v2->x)
    464 		lightnum++;
    465 
    466 		if (lightnum < 0)		
    467 		walllights = scalelight[0];
    468 		else if (lightnum >= LIGHTLEVELS)
    469 		walllights = scalelight[LIGHTLEVELS-1];
    470 		else
    471 		walllights = scalelight[lightnum];
    472 	}
    473 	}
    474 	
    475 	
    476 	
    477 	
    478 	
    479   
    480 	if (frontsector->floorheight >= viewz)
    481 	{
    482 	
    483 	markfloor = false;
    484 	}
    485 	
    486 	if (frontsector->ceilingheight <= viewz 
    487 	&& frontsector->ceilingpic != skyflatnum)
    488 	{
    489 	
    490 	markceiling = false;
    491 	}
    492 
    493 	
    494 	
    495 	worldtop >>= 4;
    496 	worldbottom >>= 4;
    497 	
    498 	topstep = -FixedMul (rw_scalestep, worldtop);
    499 	topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale);
    500 
    501 	bottomstep = -FixedMul (rw_scalestep,worldbottom);
    502 	bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale);
    503 	
    504 	if (backsector)
    505 	{	
    506 	worldhigh >>= 4;
    507 	worldlow >>= 4;
    508 
    509 	if (worldhigh < worldtop)
    510 	{
    511 		pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
    512 		pixhighstep = -FixedMul (rw_scalestep,worldhigh);
    513 	}
    514 	
    515 	if (worldlow > worldbottom)
    516 	{
    517 		pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
    518 		pixlowstep = -FixedMul (rw_scalestep,worldlow);
    519 	}
    520 	}
    521 	
    522 	
    523 	if (markceiling)
    524 	ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1);
    525 	
    526 	if (markfloor)
    527 	floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1);
    528 
    529 	R_RenderSegLoop ();
    530 
    531 	
    532 	
    533 	if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture)
    534 	 && !ds_p->sprtopclip)
    535 	{
    536 	memcpy (lastopening, ceilingclip+start, 2*(rw_stopx-start));
    537 	ds_p->sprtopclip = lastopening - start;
    538 	lastopening += rw_stopx - start;
    539 	}
    540 	
    541 	if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture)
    542 	 && !ds_p->sprbottomclip)
    543 	{
    544 	memcpy (lastopening, floorclip+start, 2*(rw_stopx-start));
    545 	ds_p->sprbottomclip = lastopening - start;
    546 	lastopening += rw_stopx - start;	
    547 	}
    548 
    549 	if (maskedtexture && !(ds_p->silhouette&SIL_TOP))
    550 	{
    551 	ds_p->silhouette |= SIL_TOP;
    552 	ds_p->tsilheight = INT_MIN;
    553 	}
    554 	if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM))
    555 	{
    556 	ds_p->silhouette |= SIL_BOTTOM;
    557 	ds_p->bsilheight = INT_MAX;
    558 	}
    559 	ds_p++;
    560 }
    561