• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
R_CheckVariables(void)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 */
Show(void)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 */
R_TimeRefresh_f(void)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 */
R_LineGraph(int x,int y,int h)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;
R_TimeGraph(void)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 */
R_NetGraph(void)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 */
R_ZGraph(void)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 */
R_PrintTimes(void)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 */
R_PrintDSpeeds(void)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 */
R_PrintAliasStats(void)315 void R_PrintAliasStats (void)
316 {
317 	Con_Printf ("%3i polygon model drawn\n", r_amodels_drawn);
318 }
319 
320 
WarpPalette(void)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 */
R_TransformFrustum(void)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 */
TransformVector(vec3_t in,vec3_t out)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 */
R_TransformPlane(mplane_t * p,float * normal,float * dist)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 */
R_SetUpFrustumIndexes(void)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 */
R_SetupFrame(void)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