doom

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

r_main.c (8827B)


      1 #include <stdlib.h>
      2 #include <math.h>
      3 
      4 #include "doomdef.h"
      5 #include "d_net.h"
      6 #include "m_bbox.h"
      7 #include "r_local.h"
      8 
      9 #define FIELDOFVIEW		2048
     10 #define DISTMAP		2
     11 
     12 extern lighttable_t**	walllights;
     13 extern int	detailLevel;
     14 extern int	screenblocks;
     15 
     16 int			viewangleoffset;
     17 int			validcount = 1;
     18 lighttable_t*		fixedcolormap;
     19 int			centerx;
     20 int			centery;
     21 fixed_t			centerxfrac;
     22 fixed_t			centeryfrac;
     23 fixed_t			projection;
     24 int			framecount;
     25 int			sscount;
     26 int			linecount;
     27 int			loopcount;
     28 fixed_t			viewx;
     29 fixed_t			viewy;
     30 fixed_t			viewz;
     31 angle_t			viewangle;
     32 fixed_t			viewcos;
     33 fixed_t			viewsin;
     34 player_t*		viewplayer;
     35 int			detailshift;
     36 angle_t			clipangle;
     37 int			viewangletox[FINEANGLES/2];
     38 angle_t			xtoviewangle[SCREENWIDTH+1];
     39 fixed_t*		finecosine = &finesine[FINEANGLES/4];
     40 lighttable_t*		scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
     41 lighttable_t*		scalelightfixed[MAXLIGHTSCALE];
     42 lighttable_t*		zlight[LIGHTLEVELS][MAXLIGHTZ];
     43 int			extralight;
     44 boolean		setsizeneeded;
     45 int		setblocks;
     46 int		setdetail;
     47 int skyflatnum;
     48 int skytexture;
     49 int skytexturemid;
     50 
     51 void (*colfunc) ();
     52 void (*basecolfunc) ();
     53 void (*fuzzcolfunc) ();
     54 void (*transcolfunc) ();
     55 void (*spanfunc) ();
     56 
     57 void
     58 R_AddPointToBox(int x, int y, fixed_t* box)
     59 {
     60 	if (x< box[BOXLEFT]) box[BOXLEFT] = x;
     61 	if (x> box[BOXRIGHT]) box[BOXRIGHT] = x;
     62 	if (y< box[BOXBOTTOM]) box[BOXBOTTOM] = y;
     63 	if (y> box[BOXTOP]) box[BOXTOP] = y;
     64 }
     65 int
     66 R_PointOnSide(fixed_t x, fixed_t y, node_t* node)
     67 {
     68 	fixed_t	dx, dy, left, right;
     69 
     70 	if (!node->dx) {
     71 		if (x <= node->x)
     72 			return node->dy > 0;
     73 		return node->dy < 0;
     74 	}
     75 	if (!node->dy) {
     76 		if (y <= node->y)
     77 			return node->dx < 0;
     78 		return node->dx > 0;
     79 	}
     80 	dx = (x - node->x);
     81 	dy = (y - node->y);
     82 	if ((node->dy ^ node->dx ^ dx ^ dy)&0x80000000) {
     83 		if ((node->dy ^ dx) & 0x80000000)
     84 			return 1;
     85 		return 0;
     86 	}
     87 	left = FixedMul(node->dy>>FRACBITS , dx);
     88 	right = FixedMul(dy , node->dx>>FRACBITS);
     89 	if (right < left) 
     90 		return 0;
     91 	return 1;
     92 }
     93 
     94 int
     95 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t* line)
     96 {
     97 	fixed_t	lx, ly, ldx, ldy, dx, dy, left, right;
     98 
     99 	lx = line->v1->x;
    100 	ly = line->v1->y;
    101 	ldx = line->v2->x - lx;
    102 	ldy = line->v2->y - ly;
    103 	if (!ldx) {
    104 		if (x <= lx)
    105 			return ldy > 0;
    106 		return ldy < 0;
    107 	}
    108 	if (!ldy) {
    109 		if (y <= ly)
    110 			return ldx < 0;
    111 		return ldx > 0;
    112 	}
    113 	dx = (x - lx);
    114 	dy = (y - ly);
    115 	if ((ldy ^ ldx ^ dx ^ dy)&0x80000000) {
    116 		if ((ldy ^ dx) & 0x80000000) 
    117 			return 1;
    118 		return 0;
    119 	}
    120 	left = FixedMul(ldy>>FRACBITS , dx);
    121 	right = FixedMul(dy , ldx>>FRACBITS);
    122 	if (right < left)
    123 		return 0;
    124 	return 1;
    125 }
    126 
    127 angle_t
    128 R_PointToAngle(fixed_t x, fixed_t y)
    129 {
    130 	x -= viewx;
    131 	y -= viewy;
    132 	if ((!x) && (!y))
    133 		return 0;
    134 	if (x>= 0) {
    135 		if (y>= 0) {
    136 			if (x>y)
    137 				return tantoangle[ SlopeDiv(y,x)];
    138 			else return ANG90-1-tantoangle[ SlopeDiv(x,y)];
    139 		}
    140 		else {
    141 			y = -y;
    142 			if (x>y)
    143 				return -tantoangle[SlopeDiv(y,x)];
    144 			else  return ANG270+tantoangle[ SlopeDiv(x,y)];
    145 		}
    146 	} else {
    147 		x = -x;
    148 		if (y>= 0) {
    149 			if (x > y)
    150 				return ANG180-1-tantoangle[ SlopeDiv(y,x)];
    151 			else return ANG90+ tantoangle[ SlopeDiv(x,y)];
    152 		} else {
    153 			y = -y;
    154 			if (x > y)
    155 				return ANG180+tantoangle[ SlopeDiv(y,x)];
    156 			else return ANG270-1-tantoangle[ SlopeDiv(x,y)];
    157 		}
    158 	}
    159 	return 0;
    160 }
    161 
    162 angle_t
    163 R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
    164 {
    165 	viewx = x1;
    166 	viewy = y1;
    167 	return R_PointToAngle(x2, y2);
    168 }
    169 
    170 fixed_t
    171 R_PointToDist(fixed_t x, fixed_t y)
    172 {
    173 	fixed_t	dx, dy, temp, dist;
    174 	int		angle;
    175 
    176 	dx = abs(x - viewx);
    177 	dy = abs(y - viewy);
    178 	if (dy > dx) {
    179 		temp = dx;
    180 		dx = dy;
    181 		dy = temp;
    182 	}
    183 	angle = (tantoangle[ FixedDiv(dy,dx)>>DBITS ]+ANG90) >> ANGLETOFINESHIFT;
    184 	dist = FixedDiv (dx, finesine[angle] );
    185 	return dist;
    186 }
    187 
    188 fixed_t
    189 R_ScaleFromGlobalAngle(angle_t visangle)
    190 {
    191 	fixed_t		scale, num;
    192 	int			anglea, angleb, sinea, sineb, den;
    193 	anglea = ANG90 + (visangle-viewangle);
    194 	angleb = ANG90 + (visangle-rw_normalangle);
    195 	sinea = finesine[anglea>>ANGLETOFINESHIFT];
    196 	sineb = finesine[angleb>>ANGLETOFINESHIFT];
    197 	num = FixedMul(projection,sineb)<<detailshift;
    198 	den = FixedMul(rw_distance,sinea);
    199 	if (den > num>>16) {
    200 		scale = FixedDiv(num, den);
    201 		if (scale > 64*FRACUNIT) scale = 64*FRACUNIT;
    202 		if (scale < 256) scale = 256;
    203 	}
    204 	else scale = 64*FRACUNIT;
    205 	return scale;
    206 }
    207 
    208 void
    209 R_InitTextureMapping()
    210 {
    211 	fixed_t		focallength;
    212 	int			i, x, t;
    213 
    214 	focallength = FixedDiv(centerxfrac, finetangent[FINEANGLES/4+FIELDOFVIEW/2]);
    215 	for (i = 0; i < FINEANGLES/2; ++i) {
    216 		if (finetangent[i] > FRACUNIT * 2)
    217 			t = -1;
    218 		else if
    219 			(finetangent[i] < -FRACUNIT*2) t = viewwidth+1;
    220 		else {
    221 			t = FixedMul (finetangent[i], focallength);
    222 			t = (centerxfrac - t+FRACUNIT-1)>>FRACBITS;
    223 			if (t < -1)
    224 				t = -1;
    225 			if (t>viewwidth+1)
    226 				t = viewwidth+1;
    227 		}
    228 		viewangletox[i] = t;
    229 	}
    230 	for (x = 0; x <= viewwidth; ++x) {
    231 		i = 0;
    232 		while (viewangletox[i]>x)
    233 			++i;
    234 		xtoviewangle[x] = (i<<ANGLETOFINESHIFT)-ANG90;
    235 	}
    236 	for (i = 0; i < FINEANGLES/2; ++i) {
    237 		t = centerx - FixedMul(finetangent[i], focallength);;
    238 		if (viewangletox[i] == -1)
    239 			viewangletox[i] = 0;
    240 		if (viewangletox[i] == viewwidth+1)
    241 			viewangletox[i]  = viewwidth;
    242 	}
    243 	clipangle = xtoviewangle[0];
    244 }
    245 
    246 void
    247 R_InitLightTables()
    248 {
    249 	int		i, j, level, startmap, scale;
    250 
    251 	for (i = 0; i < LIGHTLEVELS; ++i) {
    252 		startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
    253 		for (j = 0; j < MAXLIGHTZ; ++j) {
    254 			scale = FixedDiv ((SCREENWIDTH/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
    255 			scale >>= LIGHTSCALESHIFT;
    256 			level = startmap - scale/DISTMAP;
    257 			if (level < 0)
    258 				level = 0;
    259 			if (level >= NUMCOLORMAPS)
    260 				level = NUMCOLORMAPS-1;
    261 			zlight[i][j] = colormaps + level*256;
    262 		}
    263 	}
    264 }
    265 
    266 void
    267 R_SetViewSize(int blocks, int detail)
    268 {
    269 	setsizeneeded = true;
    270 	setblocks = blocks;
    271 	setdetail = detail;
    272 }
    273 
    274 void
    275 R_ExecuteSetViewSize()
    276 {
    277 	fixed_t	cosadj, dy;
    278 	int		i, j, level, startmap;
    279 
    280 	setsizeneeded = false;
    281 	if (setblocks == 11) {
    282 		scaledviewwidth = SCREENWIDTH;
    283 		viewheight = SCREENHEIGHT;
    284 	} else {
    285 		scaledviewwidth = setblocks * 32;
    286 		viewheight = (setblocks * 168/10) & ~7;
    287 	}
    288 	detailshift = setdetail;
    289 	viewwidth = scaledviewwidth>>detailshift;
    290 	centery = viewheight/2;
    291 	centerx = viewwidth/2;
    292 	centerxfrac = centerx<<FRACBITS;
    293 	centeryfrac = centery<<FRACBITS;
    294 	projection = centerxfrac;
    295 	if (!detailshift) {
    296 		colfunc = basecolfunc = R_DrawColumn;
    297 		fuzzcolfunc = R_DrawFuzzColumn;
    298 		transcolfunc = R_DrawTranslatedColumn;
    299 		spanfunc = R_DrawSpan;
    300 	} else {
    301 		colfunc = basecolfunc = R_DrawColumnLow;
    302 		fuzzcolfunc = R_DrawFuzzColumn;
    303 		transcolfunc = R_DrawTranslatedColumn;
    304 		spanfunc = R_DrawSpanLow;
    305 	}
    306 	R_InitBuffer(scaledviewwidth, viewheight);
    307 	R_InitTextureMapping();
    308 	pspritescale = FRACUNIT*viewwidth/SCREENWIDTH;
    309 	pspriteiscale = FRACUNIT*SCREENWIDTH/viewwidth;
    310 	for (i = 0; i < viewwidth; ++i)
    311 		screenheightarray[i] = viewheight;
    312 	for (i = 0; i < viewheight; ++i) {
    313 		dy = ((i-viewheight/2)<<FRACBITS)+FRACUNIT/2;
    314 		dy = abs(dy);
    315 		yslope[i] = FixedDiv ( (viewwidth<<detailshift)/2*FRACUNIT, dy);
    316 	}
    317 	for (i = 0; i < viewwidth; ++i) {
    318 		cosadj = abs(finecosine[xtoviewangle[i]>>ANGLETOFINESHIFT]);
    319 		distscale[i] = FixedDiv (FRACUNIT,cosadj);
    320 	}
    321 	for (i = 0; i < LIGHTLEVELS; ++i) {
    322 		startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
    323 		for (j = 0; j <MAXLIGHTSCALE; ++j) {
    324 			level = startmap - j*SCREENWIDTH/(viewwidth<<detailshift)/DISTMAP;
    325 			if (level < 0)
    326 				level = 0;
    327 			if (level >= NUMCOLORMAPS)
    328 				level = NUMCOLORMAPS-1;
    329 			scalelight[i][j] = colormaps + level*256;
    330 		}
    331 	}
    332 }
    333 
    334 void
    335 R_Init()
    336 {
    337 	R_InitData();
    338 	R_SetViewSize(screenblocks, detailLevel);
    339 	R_InitPlanes();
    340 	R_InitLightTables();
    341 	skytexturemid = 100 * FRACUNIT;
    342 	R_InitTranslationTables();
    343 	framecount = 0;
    344 }
    345 
    346 subsector_t*
    347 R_PointInSubsector(fixed_t x, fixed_t y)
    348 {
    349 	node_t*	node;
    350 	int		side, nodenum;
    351 
    352 	if (!numnodes)
    353 		return subsectors;
    354 	nodenum = numnodes-1;
    355 	while (!(nodenum & NF_SUBSECTOR)) {
    356 		node = &nodes[nodenum];
    357 		side = R_PointOnSide (x, y, node);
    358 		nodenum = node->children[side];
    359 	}
    360 	return &subsectors[nodenum & ~NF_SUBSECTOR];
    361 }
    362 
    363 void
    364 R_SetupFrame(player_t* player)
    365 {
    366 	int i;
    367 
    368 	viewplayer = player;
    369 	viewx = player->mo->x;
    370 	viewy = player->mo->y;
    371 	viewangle = player->mo->angle + viewangleoffset;
    372 	extralight = player->extralight;
    373 	viewz = player->viewz;
    374 	viewsin = finesine[viewangle>>ANGLETOFINESHIFT];
    375 	viewcos = finecosine[viewangle>>ANGLETOFINESHIFT];
    376 	sscount = 0;
    377 	if (player->fixedcolormap) {
    378 		fixedcolormap = colormaps + player->fixedcolormap*256*sizeof(lighttable_t);
    379 		walllights = scalelightfixed;
    380 		for (i = 0; i < MAXLIGHTSCALE; ++i)
    381 			scalelightfixed[i] = fixedcolormap;
    382 	} else {
    383 		fixedcolormap = 0;
    384 	}
    385 	++framecount;
    386 	++validcount;
    387 }
    388 
    389 void
    390 R_RenderPlayerView(player_t* player)
    391 {
    392 	R_SetupFrame(player);
    393 	R_ClearClipSegs();
    394 	R_ClearDrawSegs();
    395 	R_ClearPlanes();
    396 	R_ClearSprites();
    397 	NetUpdate();
    398 	R_RenderBSPNode(numnodes-1);
    399 	NetUpdate();
    400 	R_DrawPlanes();
    401 	NetUpdate();
    402 	R_DrawMasked();
    403 	NetUpdate();
    404 }