Home | History | Annotate | Download | only in client
      1 /*
      2 Copyright (C) 1996-1997 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 // r_misc.c
     21 
     22 #include "quakedef.h"
     23 #include "r_local.h"
     24 
     25 
     26 /*
     27 ===============
     28 R_CheckVariables
     29 ===============
     30 */
     31 void R_CheckVariables (void)
     32 {
     33 #if 0
     34 	static float	oldbright;
     35 
     36 	if (r_fullbright.value != oldbright)
     37 	{
     38 		oldbright = r_fullbright.value;
     39 		D_FlushCaches ();	// so all lighting changes
     40 	}
     41 #endif
     42 }
     43 
     44 
     45 /*
     46 ============
     47 Show
     48 
     49 Debugging use
     50 ============
     51 */
     52 void Show (void)
     53 {
     54 	vrect_t	vr;
     55 
     56 	vr.x = vr.y = 0;
     57 	vr.width = vid.width;
     58 	vr.height = vid.height;
     59 	vr.pnext = NULL;
     60 	VID_Update (&vr);
     61 }
     62 
     63 /*
     64 ====================
     65 R_TimeRefresh_f
     66 
     67 For program optimization
     68 ====================
     69 */
     70 void R_TimeRefresh_f (void)
     71 {
     72 	int			i;
     73 	float		start, stop, time;
     74 	int			startangle;
     75 	vrect_t		vr;
     76 
     77 	startangle = r_refdef.viewangles[1];
     78 
     79 	start = Sys_DoubleTime ();
     80 	for (i=0 ; i<128 ; i++)
     81 	{
     82 		r_refdef.viewangles[1] = i/128.0*360.0;
     83 
     84 		VID_LockBuffer ();
     85 
     86 		R_RenderView ();
     87 
     88 		VID_UnlockBuffer ();
     89 
     90 		vr.x = r_refdef.vrect.x;
     91 		vr.y = r_refdef.vrect.y;
     92 		vr.width = r_refdef.vrect.width;
     93 		vr.height = r_refdef.vrect.height;
     94 		vr.pnext = NULL;
     95 		VID_Update (&vr);
     96 	}
     97 	stop = Sys_DoubleTime ();
     98 	time = stop-start;
     99 	Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
    100 
    101 	r_refdef.viewangles[1] = startangle;
    102 }
    103 
    104 /*
    105 ================
    106 R_LineGraph
    107 
    108 Only called by R_DisplayTime
    109 ================
    110 */
    111 void R_LineGraph (int x, int y, int h)
    112 {
    113 	int		i;
    114 	byte	*dest;
    115 	int		s;
    116 	int		color;
    117 
    118 // FIXME: should be disabled on no-buffer adapters, or should be in the driver
    119 
    120 //	x += r_refdef.vrect.x;
    121 //	y += r_refdef.vrect.y;
    122 
    123 	dest = vid.buffer + vid.rowbytes*y + x;
    124 
    125 	s = r_graphheight.value;
    126 
    127 	if (h == 10000)
    128 		color = 0x6f;	// yellow
    129 	else if (h == 9999)
    130 		color = 0x4f;	// red
    131 	else if (h == 9998)
    132 		color = 0xd0;	// blue
    133 	else
    134 		color = 0xff;	// pink
    135 
    136 	if (h>s)
    137 		h = s;
    138 
    139 	for (i=0 ; i<h ; i++, dest -= vid.rowbytes*2)
    140 	{
    141 		dest[0] = color;
    142 //		*(dest-vid.rowbytes) = 0x30;
    143 	}
    144 #if 0
    145 	for ( ; i<s ; i++, dest -= vid.rowbytes*2)
    146 	{
    147 		dest[0] = 0x30;
    148 		*(dest-vid.rowbytes) = 0x30;
    149 	}
    150 #endif
    151 }
    152 
    153 /*
    154 ==============
    155 R_TimeGraph
    156 
    157 Performance monitoring tool
    158 ==============
    159 */
    160 #define	MAX_TIMINGS		100
    161 extern float mouse_x, mouse_y;
    162 int		graphval;
    163 void R_TimeGraph (void)
    164 {
    165 	static	int		timex;
    166 	int		a;
    167 	float	r_time2;
    168 	static byte	r_timings[MAX_TIMINGS];
    169 	int		x;
    170 
    171 	r_time2 = Sys_DoubleTime ();
    172 
    173 	a = (r_time2-r_time1)/0.01;
    174 //a = fabs(mouse_y * 0.05);
    175 //a = (int)((r_refdef.vieworg[2] + 1024)/1)%(int)r_graphheight.value;
    176 //a = (int)((pmove.velocity[2] + 500)/10);
    177 //a = fabs(velocity[0])/20;
    178 //a = ((int)fabs(origin[0])/8)%20;
    179 //a = (cl.idealpitch + 30)/5;
    180 //a = (int)(cl.simangles[YAW] * 64/360) & 63;
    181 a = graphval;
    182 
    183 	r_timings[timex] = a;
    184 	a = timex;
    185 
    186 	if (r_refdef.vrect.width <= MAX_TIMINGS)
    187 		x = r_refdef.vrect.width-1;
    188 	else
    189 		x = r_refdef.vrect.width -
    190 				(r_refdef.vrect.width - MAX_TIMINGS)/2;
    191 	do
    192 	{
    193 		R_LineGraph (x, r_refdef.vrect.height-2, r_timings[a]);
    194 		if (x==0)
    195 			break;		// screen too small to hold entire thing
    196 		x--;
    197 		a--;
    198 		if (a == -1)
    199 			a = MAX_TIMINGS-1;
    200 	} while (a != timex);
    201 
    202 	timex = (timex+1)%MAX_TIMINGS;
    203 }
    204 
    205 /*
    206 ==============
    207 R_NetGraph
    208 ==============
    209 */
    210 void R_NetGraph (void)
    211 {
    212 	int		a, x, y, y2, w, i;
    213 	frame_t	*frame;
    214 	int lost;
    215 	char st[80];
    216 
    217 	if (vid.width - 16 <= NET_TIMINGS)
    218 		w = vid.width - 16;
    219 	else
    220 		w = NET_TIMINGS;
    221 
    222 	x =	-((vid.width - 320)>>1);
    223 	y = vid.height - sb_lines - 24 - (int)r_graphheight.value*2 - 2;
    224 
    225 	M_DrawTextBox (x, y, (w+7)/8, ((int)r_graphheight.value*2+7)/8 + 1);
    226 	y2 = y + 8;
    227 	y = vid.height - sb_lines - 8 - 2;
    228 
    229 	x = 8;
    230 	lost = CL_CalcNet();
    231 	for (a=NET_TIMINGS-w ; a<w ; a++)
    232 	{
    233 		i = (cls.netchan.outgoing_sequence-a) & NET_TIMINGSMASK;
    234 		R_LineGraph (x+w-1-a, y, packet_latency[i]);
    235 	}
    236 	sprintf(st, "%3i%% packet loss", lost);
    237 	Draw_String(8, y2, st);
    238 }
    239 
    240 /*
    241 ==============
    242 R_ZGraph
    243 ==============
    244 */
    245 void R_ZGraph (void)
    246 {
    247 	int		a, x, w, i;
    248 	static	int	height[256];
    249 
    250 	if (r_refdef.vrect.width <= 256)
    251 		w = r_refdef.vrect.width;
    252 	else
    253 		w = 256;
    254 
    255 	height[r_framecount&255] = ((int)r_origin[2]) & 31;
    256 
    257 	x = 0;
    258 	for (a=0 ; a<w ; a++)
    259 	{
    260 		i = (r_framecount-a) & 255;
    261 		R_LineGraph (x+w-1-a, r_refdef.vrect.height-2, height[i]);
    262 	}
    263 }
    264 
    265 /*
    266 =============
    267 R_PrintTimes
    268 =============
    269 */
    270 void R_PrintTimes (void)
    271 {
    272 	float	r_time2;
    273 	float		ms;
    274 
    275 	r_time2 = Sys_DoubleTime ();
    276 
    277 	ms = 1000* (r_time2 - r_time1);
    278 
    279 	Con_Printf ("%5.1f ms %3i/%3i/%3i poly %3i surf\n",
    280 				ms, c_faceclip, r_polycount, r_drawnpolycount, c_surf);
    281 	c_surf = 0;
    282 }
    283 
    284 
    285 /*
    286 =============
    287 R_PrintDSpeeds
    288 =============
    289 */
    290 void R_PrintDSpeeds (void)
    291 {
    292 	float	ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, dv_time;
    293 
    294 	r_time2 = Sys_DoubleTime ();
    295 
    296 	dp_time = (dp_time2 - dp_time1) * 1000;
    297 	rw_time = (rw_time2 - rw_time1) * 1000;
    298 	db_time = (db_time2 - db_time1) * 1000;
    299 	se_time = (se_time2 - se_time1) * 1000;
    300 	de_time = (de_time2 - de_time1) * 1000;
    301 	dv_time = (dv_time2 - dv_time1) * 1000;
    302 	ms = (r_time2 - r_time1) * 1000;
    303 
    304 	Con_Printf ("%3i %4.1fp %3iw %4.1fb %3is %4.1fe %4.1fv\n",
    305 				(int)ms, dp_time, (int)rw_time, db_time, (int)se_time, de_time,
    306 				dv_time);
    307 }
    308 
    309 
    310 /*
    311 =============
    312 R_PrintAliasStats
    313 =============
    314 */
    315 void R_PrintAliasStats (void)
    316 {
    317 	Con_Printf ("%3i polygon model drawn\n", r_amodels_drawn);
    318 }
    319 
    320 
    321 void WarpPalette (void)
    322 {
    323 	int		i,j;
    324 	byte	newpalette[768];
    325 	int		basecolor[3];
    326 
    327 	basecolor[0] = 130;
    328 	basecolor[1] = 80;
    329 	basecolor[2] = 50;
    330 
    331 // pull the colors halfway to bright brown
    332 	for (i=0 ; i<256 ; i++)
    333 	{
    334 		for (j=0 ; j<3 ; j++)
    335 		{
    336 			newpalette[i*3+j] = (host_basepal[i*3+j] + basecolor[j])/2;
    337 		}
    338 	}
    339 
    340 	VID_ShiftPalette (newpalette);
    341 }
    342 
    343 
    344 /*
    345 ===================
    346 R_TransformFrustum
    347 ===================
    348 */
    349 void R_TransformFrustum (void)
    350 {
    351 	int		i;
    352 	vec3_t	v, v2;
    353 
    354 	for (i=0 ; i<4 ; i++)
    355 	{
    356 		v[0] = screenedge[i].normal[2];
    357 		v[1] = -screenedge[i].normal[0];
    358 		v[2] = screenedge[i].normal[1];
    359 
    360 		v2[0] = v[1]*vright[0] + v[2]*vup[0] + v[0]*vpn[0];
    361 		v2[1] = v[1]*vright[1] + v[2]*vup[1] + v[0]*vpn[1];
    362 		v2[2] = v[1]*vright[2] + v[2]*vup[2] + v[0]*vpn[2];
    363 
    364 		VectorCopy (v2, view_clipplanes[i].normal);
    365 
    366 		view_clipplanes[i].dist = DotProduct (modelorg, v2);
    367 	}
    368 }
    369 
    370 
    371 #if !id386
    372 
    373 /*
    374 ================
    375 TransformVector
    376 ================
    377 */
    378 void TransformVector (vec3_t in, vec3_t out)
    379 {
    380 	out[0] = DotProduct(in,vright);
    381 	out[1] = DotProduct(in,vup);
    382 	out[2] = DotProduct(in,vpn);
    383 }
    384 
    385 #endif
    386 
    387 
    388 /*
    389 ================
    390 R_TransformPlane
    391 ================
    392 */
    393 void R_TransformPlane (mplane_t *p, float *normal, float *dist)
    394 {
    395 	float	d;
    396 
    397 	d = DotProduct (r_origin, p->normal);
    398 	*dist = p->dist - d;
    399 // TODO: when we have rotating entities, this will need to use the view matrix
    400 	TransformVector (p->normal, normal);
    401 }
    402 
    403 
    404 /*
    405 ===============
    406 R_SetUpFrustumIndexes
    407 ===============
    408 */
    409 void R_SetUpFrustumIndexes (void)
    410 {
    411 	int		i, j, *pindex;
    412 
    413 	pindex = r_frustum_indexes;
    414 
    415 	for (i=0 ; i<4 ; i++)
    416 	{
    417 		for (j=0 ; j<3 ; j++)
    418 		{
    419 			if (view_clipplanes[i].normal[j] < 0)
    420 			{
    421 				pindex[j] = j;
    422 				pindex[j+3] = j+3;
    423 			}
    424 			else
    425 			{
    426 				pindex[j] = j+3;
    427 				pindex[j+3] = j;
    428 			}
    429 		}
    430 
    431 	// FIXME: do just once at start
    432 		pfrustum_indexes[i] = pindex;
    433 		pindex += 6;
    434 	}
    435 }
    436 
    437 
    438 /*
    439 ===============
    440 R_SetupFrame
    441 ===============
    442 */
    443 void R_SetupFrame (void)
    444 {
    445 	int				edgecount;
    446 	vrect_t			vrect;
    447 	float			w, h;
    448 
    449 // don't allow cheats in multiplayer
    450 r_draworder.value = 0;
    451 r_fullbright.value = 0;
    452 r_ambient.value = 0;
    453 r_drawflat.value = 0;
    454 
    455 	if (r_numsurfs.value)
    456 	{
    457 		if ((surface_p - surfaces) > r_maxsurfsseen)
    458 			r_maxsurfsseen = surface_p - surfaces;
    459 
    460 		Con_Printf ("Used %d of %d surfs; %d max\n", surface_p - surfaces,
    461 				surf_max - surfaces, r_maxsurfsseen);
    462 	}
    463 
    464 	if (r_numedges.value)
    465 	{
    466 		edgecount = edge_p - r_edges;
    467 
    468 		if (edgecount > r_maxedgesseen)
    469 			r_maxedgesseen = edgecount;
    470 
    471 		Con_Printf ("Used %d of %d edges; %d max\n", edgecount,
    472 				r_numallocatededges, r_maxedgesseen);
    473 	}
    474 
    475 	r_refdef.ambientlight = r_ambient.value;
    476 
    477 	if (r_refdef.ambientlight < 0)
    478 		r_refdef.ambientlight = 0;
    479 
    480 //	if (!sv.active)
    481 		r_draworder.value = 0;	// don't let cheaters look behind walls
    482 
    483 	R_CheckVariables ();
    484 
    485 	R_AnimateLight ();
    486 
    487 	r_framecount++;
    488 
    489 	numbtofpolys = 0;
    490 
    491 // debugging
    492 #if 0
    493 r_refdef.vieworg[0]=  80;
    494 r_refdef.vieworg[1]=      64;
    495 r_refdef.vieworg[2]=      40;
    496 r_refdef.viewangles[0]=    0;
    497 r_refdef.viewangles[1]=    46.763641357;
    498 r_refdef.viewangles[2]=    0;
    499 #endif
    500 
    501 // build the transformation matrix for the given view angles
    502 	VectorCopy (r_refdef.vieworg, modelorg);
    503 	VectorCopy (r_refdef.vieworg, r_origin);
    504 
    505 	AngleVectors (r_refdef.viewangles, vpn, vright, vup);
    506 
    507 // current viewleaf
    508 	r_oldviewleaf = r_viewleaf;
    509 	r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
    510 
    511 	r_dowarpold = r_dowarp;
    512 	r_dowarp = r_waterwarp.value && (r_viewleaf->contents <= CONTENTS_WATER);
    513 
    514 	if ((r_dowarp != r_dowarpold) || r_viewchanged)
    515 	{
    516 		if (r_dowarp)
    517 		{
    518 			if ((vid.width <= vid.maxwarpwidth) &&
    519 				(vid.height <= vid.maxwarpheight))
    520 			{
    521 				vrect.x = 0;
    522 				vrect.y = 0;
    523 				vrect.width = vid.width;
    524 				vrect.height = vid.height;
    525 
    526 				R_ViewChanged (&vrect, sb_lines, vid.aspect);
    527 			}
    528 			else
    529 			{
    530 				w = vid.width;
    531 				h = vid.height;
    532 
    533 				if (w > vid.maxwarpwidth)
    534 				{
    535 					h *= (float)vid.maxwarpwidth / w;
    536 					w = vid.maxwarpwidth;
    537 				}
    538 
    539 				if (h > vid.maxwarpheight)
    540 				{
    541 					h = vid.maxwarpheight;
    542 					w *= (float)vid.maxwarpheight / h;
    543 				}
    544 
    545 				vrect.x = 0;
    546 				vrect.y = 0;
    547 				vrect.width = (int)w;
    548 				vrect.height = (int)h;
    549 
    550 				R_ViewChanged (&vrect,
    551 							   (int)((float)sb_lines * (h/(float)vid.height)),
    552 							   vid.aspect * (h / w) *
    553 								 ((float)vid.width / (float)vid.height));
    554 			}
    555 		}
    556 		else
    557 		{
    558 			vrect.x = 0;
    559 			vrect.y = 0;
    560 			vrect.width = vid.width;
    561 			vrect.height = vid.height;
    562 
    563 			R_ViewChanged (&vrect, sb_lines, vid.aspect);
    564 		}
    565 
    566 		r_viewchanged = false;
    567 	}
    568 
    569 // start off with just the four screen edge clip planes
    570 	R_TransformFrustum ();
    571 
    572 // save base values
    573 	VectorCopy (vpn, base_vpn);
    574 	VectorCopy (vright, base_vright);
    575 	VectorCopy (vup, base_vup);
    576 	VectorCopy (modelorg, base_modelorg);
    577 
    578 	R_SetSkyFrame ();
    579 
    580 	R_SetUpFrustumIndexes ();
    581 
    582 	r_cache_thrash = false;
    583 
    584 // clear frame counts
    585 	c_faceclip = 0;
    586 	d_spanpixcount = 0;
    587 	r_polycount = 0;
    588 	r_drawnpolycount = 0;
    589 	r_wholepolycount = 0;
    590 	r_amodels_drawn = 0;
    591 	r_outofsurfaces = 0;
    592 	r_outofedges = 0;
    593 
    594 	D_SetupFrame ();
    595 }
    596 
    597