1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "sys/platform.h"
30 #include "renderer/simplex.h"	// line font definition
31 #include "renderer/VertexCache.h"
32 #include "renderer/Cinematic.h"
33 #include "renderer/RenderWorld_local.h"
34 
35 #include "renderer/tr_local.h"
36 
37 #define MAX_DEBUG_LINES			16384
38 
39 typedef struct debugLine_s {
40 	idVec4		rgb;
41 	idVec3		start;
42 	idVec3		end;
43 	bool		depthTest;
44 	int			lifeTime;
45 } debugLine_t;
46 
47 debugLine_t		rb_debugLines[ MAX_DEBUG_LINES ];
48 int				rb_numDebugLines = 0;
49 int				rb_debugLineTime = 0;
50 
51 #define MAX_DEBUG_TEXT			512
52 
53 typedef struct debugText_s {
54 	idStr		text;
55 	idVec3		origin;
56 	float		scale;
57 	idVec4		color;
58 	idMat3		viewAxis;
59 	int			align;
60 	int			lifeTime;
61 	bool		depthTest;
62 } debugText_t;
63 
64 debugText_t		rb_debugText[ MAX_DEBUG_TEXT ];
65 int				rb_numDebugText = 0;
66 int				rb_debugTextTime = 0;
67 
68 #define MAX_DEBUG_POLYGONS		8192
69 
70 typedef struct debugPolygon_s {
71 	idVec4		rgb;
72 	idWinding	winding;
73 	bool		depthTest;
74 	int			lifeTime;
75 } debugPolygon_t;
76 
77 debugPolygon_t	rb_debugPolygons[ MAX_DEBUG_POLYGONS ];
78 int				rb_numDebugPolygons = 0;
79 int				rb_debugPolygonTime = 0;
80 
81 static void RB_DrawText( const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align );
82 
83 /*
84 ================
85 RB_DrawBounds
86 ================
87 */
RB_DrawBounds(const idBounds & bounds)88 void RB_DrawBounds( const idBounds &bounds ) {
89 	if ( bounds.IsCleared() ) {
90 		return;
91 	}
92 
93 	qglBegin( GL_LINE_LOOP );
94 	qglVertex3f( bounds[0][0], bounds[0][1], bounds[0][2] );
95 	qglVertex3f( bounds[0][0], bounds[1][1], bounds[0][2] );
96 	qglVertex3f( bounds[1][0], bounds[1][1], bounds[0][2] );
97 	qglVertex3f( bounds[1][0], bounds[0][1], bounds[0][2] );
98 	qglEnd();
99 	qglBegin( GL_LINE_LOOP );
100 	qglVertex3f( bounds[0][0], bounds[0][1], bounds[1][2] );
101 	qglVertex3f( bounds[0][0], bounds[1][1], bounds[1][2] );
102 	qglVertex3f( bounds[1][0], bounds[1][1], bounds[1][2] );
103 	qglVertex3f( bounds[1][0], bounds[0][1], bounds[1][2] );
104 	qglEnd();
105 
106 	qglBegin( GL_LINES );
107 	qglVertex3f( bounds[0][0], bounds[0][1], bounds[0][2] );
108 	qglVertex3f( bounds[0][0], bounds[0][1], bounds[1][2] );
109 
110 	qglVertex3f( bounds[0][0], bounds[1][1], bounds[0][2] );
111 	qglVertex3f( bounds[0][0], bounds[1][1], bounds[1][2] );
112 
113 	qglVertex3f( bounds[1][0], bounds[0][1], bounds[0][2] );
114 	qglVertex3f( bounds[1][0], bounds[0][1], bounds[1][2] );
115 
116 	qglVertex3f( bounds[1][0], bounds[1][1], bounds[0][2] );
117 	qglVertex3f( bounds[1][0], bounds[1][1], bounds[1][2] );
118 	qglEnd();
119 }
120 
121 
122 /*
123 ================
124 RB_SimpleSurfaceSetup
125 ================
126 */
RB_SimpleSurfaceSetup(const drawSurf_t * drawSurf)127 void RB_SimpleSurfaceSetup( const drawSurf_t *drawSurf ) {
128 	// change the matrix if needed
129 	if ( drawSurf->space != backEnd.currentSpace ) {
130 		qglLoadMatrixf( drawSurf->space->modelViewMatrix );
131 		backEnd.currentSpace = drawSurf->space;
132 	}
133 
134 	// change the scissor if needed
135 	if ( r_useScissor.GetBool() && !backEnd.currentScissor.Equals( drawSurf->scissorRect ) ) {
136 		backEnd.currentScissor = drawSurf->scissorRect;
137 		qglScissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1,
138 			backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1,
139 			backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1,
140 			backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 );
141 	}
142 }
143 
144 /*
145 ================
146 RB_SimpleWorldSetup
147 ================
148 */
RB_SimpleWorldSetup(void)149 void RB_SimpleWorldSetup( void ) {
150 	backEnd.currentSpace = &backEnd.viewDef->worldSpace;
151 	qglLoadMatrixf( backEnd.viewDef->worldSpace.modelViewMatrix );
152 
153 	backEnd.currentScissor = backEnd.viewDef->scissor;
154 	qglScissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1,
155 		backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1,
156 		backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1,
157 		backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 );
158 }
159 
160 /*
161 =================
162 RB_PolygonClear
163 
164 This will cover the entire screen with normal rasterization.
165 Texturing is disabled, but the existing glColor, glDepthMask,
166 glColorMask, and the enabled state of depth buffering and
167 stenciling will matter.
168 =================
169 */
RB_PolygonClear(void)170 void RB_PolygonClear( void ) {
171 	qglPushMatrix();
172 	qglPushAttrib( GL_ALL_ATTRIB_BITS  );
173 	qglLoadIdentity();
174 	qglDisable( GL_TEXTURE_2D );
175 	qglDisable( GL_DEPTH_TEST );
176 	qglDisable( GL_CULL_FACE );
177 	qglDisable( GL_SCISSOR_TEST );
178 	qglBegin( GL_POLYGON );
179 	qglVertex3f( -20, -20, -10 );
180 	qglVertex3f( 20, -20, -10 );
181 	qglVertex3f( 20, 20, -10 );
182 	qglVertex3f( -20, 20, -10 );
183 	qglEnd();
184 	qglPopAttrib();
185 	qglPopMatrix();
186 }
187 
188 /*
189 ====================
190 RB_ShowDestinationAlpha
191 ====================
192 */
RB_ShowDestinationAlpha(void)193 void RB_ShowDestinationAlpha( void ) {
194 	GL_State( GLS_SRCBLEND_DST_ALPHA | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS );
195 	qglColor3f( 1, 1, 1 );
196 	RB_PolygonClear();
197 }
198 
199 /*
200 ===================
201 RB_ScanStencilBuffer
202 
203 Debugging tool to see what values are in the stencil buffer
204 ===================
205 */
RB_ScanStencilBuffer(void)206 void RB_ScanStencilBuffer( void ) {
207 	int		counts[256];
208 	int		i;
209 	byte	*stencilReadback;
210 
211 	memset( counts, 0, sizeof( counts ) );
212 
213 	stencilReadback = (byte *)R_StaticAlloc( glConfig.vidWidth * glConfig.vidHeight );
214 	qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback );
215 
216 	for ( i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++ ) {
217 		counts[ stencilReadback[i] ]++;
218 	}
219 
220 	R_StaticFree( stencilReadback );
221 
222 	// print some stats (not supposed to do from back end in SMP...)
223 	common->Printf( "stencil values:\n" );
224 	for ( i = 0 ; i < 255 ; i++ ) {
225 		if ( counts[i] ) {
226 			common->Printf( "%i: %i\n", i, counts[i] );
227 		}
228 	}
229 }
230 
231 
232 /*
233 ===================
234 RB_CountStencilBuffer
235 
236 Print an overdraw count based on stencil index values
237 ===================
238 */
RB_CountStencilBuffer(void)239 void RB_CountStencilBuffer( void ) {
240 	int		count;
241 	int		i;
242 	byte	*stencilReadback;
243 
244 
245 	stencilReadback = (byte *)R_StaticAlloc( glConfig.vidWidth * glConfig.vidHeight );
246 	qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback );
247 
248 	count = 0;
249 	for ( i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++ ) {
250 		count += stencilReadback[i];
251 	}
252 
253 	R_StaticFree( stencilReadback );
254 
255 	// print some stats (not supposed to do from back end in SMP...)
256 	common->Printf( "overdraw: %5.1f\n", (float)count/(glConfig.vidWidth * glConfig.vidHeight)  );
257 }
258 
259 /*
260 ===================
261 R_ColorByStencilBuffer
262 
263 Sets the screen colors based on the contents of the
264 stencil buffer.  Stencil of 0 = black, 1 = red, 2 = green,
265 3 = blue, ..., 7+ = white
266 ===================
267 */
R_ColorByStencilBuffer(void)268 static void R_ColorByStencilBuffer( void ) {
269 	int		i;
270 	static float	colors[8][3] = {
271 		{0,0,0},
272 		{1,0,0},
273 		{0,1,0},
274 		{0,0,1},
275 		{0,1,1},
276 		{1,0,1},
277 		{1,1,0},
278 		{1,1,1},
279 	};
280 
281 	// clear color buffer to white (>6 passes)
282 	qglClearColor( 1, 1, 1, 1 );
283 	qglDisable( GL_SCISSOR_TEST );
284 	qglClear( GL_COLOR_BUFFER_BIT );
285 
286 	// now draw color for each stencil value
287 	qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
288 	for ( i = 0 ; i < 6 ; i++ ) {
289 		qglColor3fv( colors[i] );
290 		qglStencilFunc( GL_EQUAL, i, 255 );
291 		RB_PolygonClear();
292 	}
293 
294 	qglStencilFunc( GL_ALWAYS, 0, 255 );
295 }
296 
297 //======================================================================
298 
299 /*
300 ==================
301 RB_ShowOverdraw
302 ==================
303 */
RB_ShowOverdraw(void)304 void RB_ShowOverdraw( void ) {
305 	const idMaterial *	material;
306 	int					i;
307 	drawSurf_t * *		drawSurfs;
308 	const drawSurf_t *	surf;
309 	int					numDrawSurfs;
310 	viewLight_t *		vLight;
311 
312 	if ( r_showOverDraw.GetInteger() == 0 ) {
313 		return;
314 	}
315 
316 	material = declManager->FindMaterial( "textures/common/overdrawtest", false );
317 	if ( material == NULL ) {
318 		return;
319 	}
320 
321 	drawSurfs = backEnd.viewDef->drawSurfs;
322 	numDrawSurfs = backEnd.viewDef->numDrawSurfs;
323 
324 	int interactions = 0;
325 	for ( vLight = backEnd.viewDef->viewLights; vLight; vLight = vLight->next ) {
326 		for ( surf = vLight->localInteractions; surf; surf = surf->nextOnLight ) {
327 			interactions++;
328 		}
329 		for ( surf = vLight->globalInteractions; surf; surf = surf->nextOnLight ) {
330 			interactions++;
331 		}
332 	}
333 
334 	drawSurf_t **newDrawSurfs = (drawSurf_t **)R_FrameAlloc( numDrawSurfs + interactions * sizeof( newDrawSurfs[0] ) );
335 
336 	for ( i = 0; i < numDrawSurfs; i++ ) {
337 		surf = drawSurfs[i];
338 		if ( surf->material ) {
339 			const_cast<drawSurf_t *>(surf)->material = material;
340 		}
341 		newDrawSurfs[i] = const_cast<drawSurf_t *>(surf);
342 	}
343 
344 	for ( vLight = backEnd.viewDef->viewLights; vLight; vLight = vLight->next ) {
345 		for ( surf = vLight->localInteractions; surf; surf = surf->nextOnLight ) {
346 			const_cast<drawSurf_t *>(surf)->material = material;
347 			newDrawSurfs[i++] = const_cast<drawSurf_t *>(surf);
348 		}
349 		for ( surf = vLight->globalInteractions; surf; surf = surf->nextOnLight ) {
350 			const_cast<drawSurf_t *>(surf)->material = material;
351 			newDrawSurfs[i++] = const_cast<drawSurf_t *>(surf);
352 		}
353 		vLight->localInteractions = NULL;
354 		vLight->globalInteractions = NULL;
355 	}
356 
357 	switch( r_showOverDraw.GetInteger() ) {
358 		case 1: // geometry overdraw
359 			const_cast<viewDef_t *>(backEnd.viewDef)->drawSurfs = newDrawSurfs;
360 			const_cast<viewDef_t *>(backEnd.viewDef)->numDrawSurfs = numDrawSurfs;
361 			break;
362 		case 2: // light interaction overdraw
363 			const_cast<viewDef_t *>(backEnd.viewDef)->drawSurfs = &newDrawSurfs[numDrawSurfs];
364 			const_cast<viewDef_t *>(backEnd.viewDef)->numDrawSurfs = interactions;
365 			break;
366 		case 3: // geometry + light interaction overdraw
367 			const_cast<viewDef_t *>(backEnd.viewDef)->drawSurfs = newDrawSurfs;
368 			const_cast<viewDef_t *>(backEnd.viewDef)->numDrawSurfs += interactions;
369 			break;
370 	}
371 }
372 
373 /*
374 ===================
375 RB_ShowIntensity
376 
377 Debugging tool to see how much dynamic range a scene is using.
378 The greatest of the rgb values at each pixel will be used, with
379 the resulting color shading from red at 0 to green at 128 to blue at 255
380 ===================
381 */
RB_ShowIntensity(void)382 void RB_ShowIntensity( void ) {
383 	byte	*colorReadback;
384 	int		i, j, c;
385 
386 	if ( !r_showIntensity.GetBool() ) {
387 		return;
388 	}
389 
390 	colorReadback = (byte *)R_StaticAlloc( glConfig.vidWidth * glConfig.vidHeight * 4 );
391 	qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGBA, GL_UNSIGNED_BYTE, colorReadback );
392 
393 	c = glConfig.vidWidth * glConfig.vidHeight * 4;
394 	for ( i = 0; i < c ; i+=4 ) {
395 		j = colorReadback[i];
396 		if ( colorReadback[i+1] > j ) {
397 			j = colorReadback[i+1];
398 		}
399 		if ( colorReadback[i+2] > j ) {
400 			j = colorReadback[i+2];
401 		}
402 		if ( j < 128 ) {
403 			colorReadback[i+0] = 2*(128-j);
404 			colorReadback[i+1] = 2*j;
405 			colorReadback[i+2] = 0;
406 		} else {
407 			colorReadback[i+0] = 0;
408 			colorReadback[i+1] = 2*(255-j);
409 			colorReadback[i+2] = 2*(j-128);
410 		}
411 	}
412 
413 	// draw it back to the screen
414 	qglLoadIdentity();
415 	qglMatrixMode( GL_PROJECTION );
416 	GL_State( GLS_DEPTHFUNC_ALWAYS );
417 	qglPushMatrix();
418 	qglLoadIdentity();
419 	qglOrtho( 0, 1, 0, 1, -1, 1 );
420 	qglRasterPos2f( 0, 0 );
421 	qglPopMatrix();
422 	qglColor3f( 1, 1, 1 );
423 	globalImages->BindNull();
424 	qglMatrixMode( GL_MODELVIEW );
425 
426 	qglDrawPixels( glConfig.vidWidth, glConfig.vidHeight, GL_RGBA , GL_UNSIGNED_BYTE, colorReadback );
427 
428 	R_StaticFree( colorReadback );
429 }
430 
431 
432 /*
433 ===================
434 RB_ShowDepthBuffer
435 
436 Draw the depth buffer as colors
437 ===================
438 */
RB_ShowDepthBuffer(void)439 void RB_ShowDepthBuffer( void ) {
440 	void	*depthReadback;
441 
442 	if ( !r_showDepth.GetBool() ) {
443 		return;
444 	}
445 
446 	qglPushMatrix();
447 	qglLoadIdentity();
448 	qglMatrixMode( GL_PROJECTION );
449 	qglPushMatrix();
450 	qglLoadIdentity();
451 	qglOrtho( 0, 1, 0, 1, -1, 1 );
452 	qglRasterPos2f( 0, 0 );
453 	qglPopMatrix();
454 	qglMatrixMode( GL_MODELVIEW );
455 	qglPopMatrix();
456 
457 	GL_State( GLS_DEPTHFUNC_ALWAYS );
458 	qglColor3f( 1, 1, 1 );
459 	globalImages->BindNull();
460 
461 	depthReadback = R_StaticAlloc( glConfig.vidWidth * glConfig.vidHeight*4 );
462 	memset( depthReadback, 0, glConfig.vidWidth * glConfig.vidHeight*4 );
463 
464 	qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_DEPTH_COMPONENT , GL_FLOAT, depthReadback );
465 
466 #if 0
467 	for ( i = 0 ; i < glConfig.vidWidth * glConfig.vidHeight ; i++ ) {
468 		((byte *)depthReadback)[i*4] =
469 		((byte *)depthReadback)[i*4+1] =
470 		((byte *)depthReadback)[i*4+2] = 255 * ((float *)depthReadback)[i];
471 		((byte *)depthReadback)[i*4+3] = 1;
472 	}
473 #endif
474 
475 	qglDrawPixels( glConfig.vidWidth, glConfig.vidHeight, GL_RGBA , GL_UNSIGNED_BYTE, depthReadback );
476 	R_StaticFree( depthReadback );
477 }
478 
479 /*
480 =================
481 RB_ShowLightCount
482 
483 This is a debugging tool that will draw each surface with a color
484 based on how many lights are effecting it
485 =================
486 */
RB_ShowLightCount(void)487 void RB_ShowLightCount( void ) {
488 	int		i;
489 	const drawSurf_t	*surf;
490 	const viewLight_t	*vLight;
491 
492 	if ( !r_showLightCount.GetBool() ) {
493 		return;
494 	}
495 
496 	GL_State( GLS_DEPTHFUNC_EQUAL );
497 
498 	RB_SimpleWorldSetup();
499 	qglClearStencil( 0 );
500 	qglClear( GL_STENCIL_BUFFER_BIT );
501 
502 	qglEnable( GL_STENCIL_TEST );
503 
504 	// optionally count everything through walls
505 	if ( r_showLightCount.GetInteger() >= 2 ) {
506 		qglStencilOp( GL_KEEP, GL_INCR, GL_INCR );
507 	} else {
508 		qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
509 	}
510 
511 	qglStencilFunc( GL_ALWAYS, 1, 255 );
512 
513 	globalImages->defaultImage->Bind();
514 
515 	for ( vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
516 		for ( i = 0 ; i < 2 ; i++ ) {
517 			for ( surf = i ? vLight->localInteractions: vLight->globalInteractions; surf; surf = (drawSurf_t *)surf->nextOnLight ) {
518 				RB_SimpleSurfaceSetup( surf );
519 				if ( !surf->geo->ambientCache ) {
520 					continue;
521 				}
522 
523 				const idDrawVert	*ac = (idDrawVert *)vertexCache.Position( surf->geo->ambientCache );
524 				qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), &ac->xyz );
525 				RB_DrawElementsWithCounters( surf->geo );
526 			}
527 		}
528 	}
529 
530 	// display the results
531 	R_ColorByStencilBuffer();
532 
533 	if ( r_showLightCount.GetInteger() > 2 ) {
534 		RB_CountStencilBuffer();
535 	}
536 }
537 
538 
539 /*
540 =================
541 RB_ShowSilhouette
542 
543 Blacks out all edges, then adds color for each edge that a shadow
544 plane extends from, allowing you to see doubled edges
545 =================
546 */
RB_ShowSilhouette(void)547 void RB_ShowSilhouette( void ) {
548 	int		i;
549 	const drawSurf_t	*surf;
550 	const viewLight_t	*vLight;
551 
552 	if ( !r_showSilhouette.GetBool() ) {
553 		return;
554 	}
555 
556 	//
557 	// clear all triangle edges to black
558 	//
559 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
560 	globalImages->BindNull();
561 	qglDisable( GL_TEXTURE_2D );
562 	qglDisable( GL_STENCIL_TEST );
563 
564 	qglColor3f( 0, 0, 0 );
565 
566 	GL_State( GLS_POLYMODE_LINE );
567 
568 	GL_Cull( CT_TWO_SIDED );
569 	qglDisable( GL_DEPTH_TEST );
570 
571 	RB_RenderDrawSurfListWithFunction( backEnd.viewDef->drawSurfs, backEnd.viewDef->numDrawSurfs,
572 		RB_T_RenderTriangleSurface );
573 
574 
575 	//
576 	// now blend in edges that cast silhouettes
577 	//
578 	RB_SimpleWorldSetup();
579 	qglColor3f( 0.5, 0, 0 );
580 	GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
581 
582 	for ( vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
583 		for ( i = 0 ; i < 2 ; i++ ) {
584 			for ( surf = i ? vLight->localShadows : vLight->globalShadows
585 				; surf ; surf = (drawSurf_t *)surf->nextOnLight ) {
586 				RB_SimpleSurfaceSetup( surf );
587 
588 				const srfTriangles_t	*tri = surf->geo;
589 
590 				qglVertexPointer( 3, GL_FLOAT, sizeof( shadowCache_t ), vertexCache.Position( tri->shadowCache ) );
591 				qglBegin( GL_LINES );
592 
593 				for ( int j = 0 ; j < tri->numIndexes ; j+=3 ) {
594 					int		i1 = tri->indexes[j+0];
595 					int		i2 = tri->indexes[j+1];
596 					int		i3 = tri->indexes[j+2];
597 
598 					if ( (i1 & 1) + (i2 & 1) + (i3 & 1) == 1 ) {
599 						if ( (i1 & 1) + (i2 & 1) == 0 ) {
600 							qglArrayElement( i1 );
601 							qglArrayElement( i2 );
602 						} else if ( (i1 & 1 ) + (i3 & 1) == 0 ) {
603 							qglArrayElement( i1 );
604 							qglArrayElement( i3 );
605 						}
606 					}
607 				}
608 				qglEnd();
609 
610 			}
611 		}
612 	}
613 
614 	qglEnable( GL_DEPTH_TEST );
615 
616 	GL_State( GLS_DEFAULT );
617 	qglColor3f( 1,1,1 );
618 	GL_Cull( CT_FRONT_SIDED );
619 }
620 
621 
622 
623 /*
624 =================
625 RB_ShowShadowCount
626 
627 This is a debugging tool that will draw only the shadow volumes
628 and count up the total fill usage
629 =================
630 */
RB_ShowShadowCount(void)631 static void RB_ShowShadowCount( void ) {
632 	int		i;
633 	const drawSurf_t	*surf;
634 	const viewLight_t	*vLight;
635 
636 	if ( !r_showShadowCount.GetBool() ) {
637 		return;
638 	}
639 
640 	GL_State( GLS_DEFAULT );
641 
642 	qglClearStencil( 0 );
643 	qglClear( GL_STENCIL_BUFFER_BIT );
644 
645 	qglEnable( GL_STENCIL_TEST );
646 
647 	qglStencilOp( GL_KEEP, GL_INCR, GL_INCR );
648 
649 	qglStencilFunc( GL_ALWAYS, 1, 255 );
650 
651 	globalImages->defaultImage->Bind();
652 
653 	// draw both sides
654 	GL_Cull( CT_TWO_SIDED );
655 
656 	for ( vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
657 		for ( i = 0 ; i < 2 ; i++ ) {
658 			for ( surf = i ? vLight->localShadows : vLight->globalShadows
659 				; surf ; surf = (drawSurf_t *)surf->nextOnLight ) {
660 				RB_SimpleSurfaceSetup( surf );
661 				const srfTriangles_t	*tri = surf->geo;
662 				if ( !tri->shadowCache ) {
663 					continue;
664 				}
665 
666 				if ( r_showShadowCount.GetInteger() == 3 ) {
667 					// only show turboshadows
668 					if ( tri->numShadowIndexesNoCaps != tri->numIndexes ) {
669 						continue;
670 					}
671 				}
672 				if ( r_showShadowCount.GetInteger() == 4 ) {
673 					// only show static shadows
674 					if ( tri->numShadowIndexesNoCaps == tri->numIndexes ) {
675 						continue;
676 					}
677 				}
678 
679 				shadowCache_t *cache = (shadowCache_t *)vertexCache.Position( tri->shadowCache );
680 				qglVertexPointer( 4, GL_FLOAT, sizeof( *cache ), &cache->xyz );
681 				RB_DrawElementsWithCounters( tri );
682 			}
683 		}
684 	}
685 
686 	// display the results
687 	R_ColorByStencilBuffer();
688 
689 	if ( r_showShadowCount.GetInteger() == 2 ) {
690 		common->Printf( "all shadows " );
691 	} else if ( r_showShadowCount.GetInteger() == 3 ) {
692 		common->Printf( "turboShadows " );
693 	} else if ( r_showShadowCount.GetInteger() == 4 ) {
694 		common->Printf( "static shadows " );
695 	}
696 
697 	if ( r_showShadowCount.GetInteger() >= 2 ) {
698 		RB_CountStencilBuffer();
699 	}
700 
701 	GL_Cull( CT_FRONT_SIDED );
702 }
703 
704 
705 /*
706 ===============
707 RB_T_RenderTriangleSurfaceAsLines
708 
709 ===============
710 */
RB_T_RenderTriangleSurfaceAsLines(const drawSurf_t * surf)711 void RB_T_RenderTriangleSurfaceAsLines( const drawSurf_t *surf ) {
712 	const srfTriangles_t *tri = surf->geo;
713 
714 	if ( !tri->verts ) {
715 		return;
716 	}
717 
718 	qglBegin( GL_LINES );
719 	for ( int i = 0 ; i < tri->numIndexes ; i+= 3 ) {
720 		for ( int j = 0 ; j < 3 ; j++ ) {
721 			int k = ( j + 1 ) % 3;
722 			qglVertex3fv( tri->verts[ tri->silIndexes[i+j] ].xyz.ToFloatPtr() );
723 			qglVertex3fv( tri->verts[ tri->silIndexes[i+k] ].xyz.ToFloatPtr() );
724 		}
725 	}
726 	qglEnd();
727 }
728 
729 
730 /*
731 =====================
732 RB_ShowTris
733 
734 Debugging tool
735 =====================
736 */
RB_ShowTris(drawSurf_t ** drawSurfs,int numDrawSurfs)737 static void RB_ShowTris( drawSurf_t **drawSurfs, int numDrawSurfs ) {
738 	idVec3 end;
739 
740 	if ( !r_showTris.GetInteger() ) {
741 		return;
742 	}
743 
744 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
745 	globalImages->BindNull();
746 	qglDisable( GL_TEXTURE_2D );
747 	qglDisable( GL_STENCIL_TEST );
748 
749 	qglColor3f( 1, 1, 1 );
750 
751 
752 	GL_State( GLS_POLYMODE_LINE );
753 
754 	switch ( r_showTris.GetInteger() ) {
755 	case 1:	// only draw visible ones
756 		qglPolygonOffset( -1, -2 );
757 		qglEnable( GL_POLYGON_OFFSET_LINE );
758 		break;
759 	default:
760 	case 2:	// draw all front facing
761 		GL_Cull( CT_FRONT_SIDED );
762 		qglDisable( GL_DEPTH_TEST );
763 		break;
764 	case 3: // draw all
765 		GL_Cull( CT_TWO_SIDED );
766 		qglDisable( GL_DEPTH_TEST );
767 		break;
768 	}
769 
770 	RB_RenderDrawSurfListWithFunction( drawSurfs, numDrawSurfs, RB_T_RenderTriangleSurface );
771 
772 	qglEnable( GL_DEPTH_TEST );
773 	qglDisable( GL_POLYGON_OFFSET_LINE );
774 
775 	qglDepthRange( 0, 1 );
776 	GL_State( GLS_DEFAULT );
777 	GL_Cull( CT_FRONT_SIDED );
778 }
779 
780 
781 /*
782 =====================
783 RB_ShowSurfaceInfo
784 
785 Debugging tool
786 =====================
787 */
RB_ShowSurfaceInfo(drawSurf_t ** drawSurfs,int numDrawSurfs)788 static void RB_ShowSurfaceInfo( drawSurf_t **drawSurfs, int numDrawSurfs ) {
789 	modelTrace_t mt;
790 	idVec3 start, end;
791 
792 	if ( !r_showSurfaceInfo.GetBool() ) {
793 		return;
794 	}
795 
796 	// start far enough away that we don't hit the player model
797 	start = tr.primaryView->renderView.vieworg + tr.primaryView->renderView.viewaxis[0] * 16;
798 	end = start + tr.primaryView->renderView.viewaxis[0] * 1000.0f;
799 	if ( !tr.primaryWorld->Trace( mt, start, end, 0.0f, false ) ) {
800 		return;
801 	}
802 
803 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
804 	globalImages->BindNull();
805 	qglDisable( GL_TEXTURE_2D );
806 	qglDisable( GL_STENCIL_TEST );
807 
808 	qglColor3f( 1, 1, 1 );
809 
810 	GL_State( GLS_POLYMODE_LINE );
811 
812 	qglPolygonOffset( -1, -2 );
813 	qglEnable( GL_POLYGON_OFFSET_LINE );
814 
815 	float	matrix[16];
816 
817 	// transform the object verts into global space
818 	R_AxisToModelMatrix( mt.entity->axis, mt.entity->origin, matrix );
819 
820 	tr.primaryWorld->DrawText( mt.entity->hModel->Name(), mt.point + tr.primaryView->renderView.viewaxis[2] * 12,
821 		0.35f, colorRed, tr.primaryView->renderView.viewaxis );
822 	tr.primaryWorld->DrawText( mt.material->GetName(), mt.point,
823 		0.35f, colorBlue, tr.primaryView->renderView.viewaxis );
824 
825 	qglEnable( GL_DEPTH_TEST );
826 	qglDisable( GL_POLYGON_OFFSET_LINE );
827 
828 	qglDepthRange( 0, 1 );
829 	GL_State( GLS_DEFAULT );
830 	GL_Cull( CT_FRONT_SIDED );
831 }
832 
833 
834 /*
835 =====================
836 RB_ShowViewEntitys
837 
838 Debugging tool
839 =====================
840 */
RB_ShowViewEntitys(viewEntity_t * vModels)841 static void RB_ShowViewEntitys( viewEntity_t *vModels ) {
842 	if ( !r_showViewEntitys.GetBool() ) {
843 		return;
844 	}
845 	if ( r_showViewEntitys.GetInteger() == 2 ) {
846 		common->Printf( "view entities: " );
847 		for ( ; vModels ; vModels = vModels->next ) {
848 			common->Printf( "%i ", vModels->entityDef->index );
849 		}
850 		common->Printf( "\n" );
851 		return;
852 	}
853 
854 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
855 	globalImages->BindNull();
856 	qglDisable( GL_TEXTURE_2D );
857 	qglDisable( GL_STENCIL_TEST );
858 
859 	qglColor3f( 1, 1, 1 );
860 
861 
862 	GL_State( GLS_POLYMODE_LINE );
863 
864 	GL_Cull( CT_TWO_SIDED );
865 	qglDisable( GL_DEPTH_TEST );
866 	qglDisable( GL_SCISSOR_TEST );
867 
868 	for ( ; vModels ; vModels = vModels->next ) {
869 		idBounds	b;
870 
871 		qglLoadMatrixf( vModels->modelViewMatrix );
872 
873 		if ( !vModels->entityDef ) {
874 			continue;
875 		}
876 
877 		// draw the reference bounds in yellow
878 		qglColor3f( 1, 1, 0 );
879 		RB_DrawBounds( vModels->entityDef->referenceBounds );
880 
881 
882 		// draw the model bounds in white
883 		qglColor3f( 1, 1, 1 );
884 
885 		idRenderModel *model = R_EntityDefDynamicModel( vModels->entityDef );
886 		if ( !model ) {
887 			continue;	// particles won't instantiate without a current view
888 		}
889 		b = model->Bounds( &vModels->entityDef->parms );
890 		RB_DrawBounds( b );
891 	}
892 
893 	qglEnable( GL_DEPTH_TEST );
894 	qglDisable( GL_POLYGON_OFFSET_LINE );
895 
896 	qglDepthRange( 0, 1 );
897 	GL_State( GLS_DEFAULT );
898 	GL_Cull( CT_FRONT_SIDED );
899 }
900 
901 /*
902 =====================
903 RB_ShowTexturePolarity
904 
905 Shade triangle red if they have a positive texture area
906 green if they have a negative texture area, or blue if degenerate area
907 =====================
908 */
RB_ShowTexturePolarity(drawSurf_t ** drawSurfs,int numDrawSurfs)909 static void RB_ShowTexturePolarity( drawSurf_t **drawSurfs, int numDrawSurfs ) {
910 	int		i, j;
911 	drawSurf_t	*drawSurf;
912 	const srfTriangles_t	*tri;
913 
914 	if ( !r_showTexturePolarity.GetBool() ) {
915 		return;
916 	}
917 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
918 	globalImages->BindNull();
919 	qglDisable( GL_STENCIL_TEST );
920 
921 	GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
922 
923 	qglColor3f( 1, 1, 1 );
924 
925 	for ( i = 0 ; i < numDrawSurfs ; i++ ) {
926 		drawSurf = drawSurfs[i];
927 		tri = drawSurf->geo;
928 		if ( !tri->verts ) {
929 			continue;
930 		}
931 
932 		RB_SimpleSurfaceSetup( drawSurf );
933 
934 		qglBegin( GL_TRIANGLES );
935 		for ( j = 0 ; j < tri->numIndexes ; j+=3 ) {
936 			idDrawVert	*a, *b, *c;
937 			float		d0[5], d1[5];
938 			float		area;
939 
940 			a = tri->verts + tri->indexes[j];
941 			b = tri->verts + tri->indexes[j+1];
942 			c = tri->verts + tri->indexes[j+2];
943 
944 			// VectorSubtract( b->xyz, a->xyz, d0 );
945 			d0[3] = b->st[0] - a->st[0];
946 			d0[4] = b->st[1] - a->st[1];
947 			// VectorSubtract( c->xyz, a->xyz, d1 );
948 			d1[3] = c->st[0] - a->st[0];
949 			d1[4] = c->st[1] - a->st[1];
950 
951 			area = d0[3] * d1[4] - d0[4] * d1[3];
952 
953 			if ( idMath::Fabs( area ) < 0.0001 ) {
954 				qglColor4f( 0, 0, 1, 0.5 );
955 			} else  if ( area < 0 ) {
956 				qglColor4f( 1, 0, 0, 0.5 );
957 			} else {
958 				qglColor4f( 0, 1, 0, 0.5 );
959 			}
960 			qglVertex3fv( a->xyz.ToFloatPtr() );
961 			qglVertex3fv( b->xyz.ToFloatPtr() );
962 			qglVertex3fv( c->xyz.ToFloatPtr() );
963 		}
964 		qglEnd();
965 	}
966 
967 	GL_State( GLS_DEFAULT );
968 }
969 
970 
971 /*
972 =====================
973 RB_ShowUnsmoothedTangents
974 
975 Shade materials that are using unsmoothed tangents
976 =====================
977 */
RB_ShowUnsmoothedTangents(drawSurf_t ** drawSurfs,int numDrawSurfs)978 static void RB_ShowUnsmoothedTangents( drawSurf_t **drawSurfs, int numDrawSurfs ) {
979 	int		i, j;
980 	drawSurf_t	*drawSurf;
981 	const srfTriangles_t	*tri;
982 
983 	if ( !r_showUnsmoothedTangents.GetBool() ) {
984 		return;
985 	}
986 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
987 	globalImages->BindNull();
988 	qglDisable( GL_STENCIL_TEST );
989 
990 	GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
991 
992 	qglColor4f( 0, 1, 0, 0.5 );
993 
994 	for ( i = 0 ; i < numDrawSurfs ; i++ ) {
995 		drawSurf = drawSurfs[i];
996 
997 		if ( !drawSurf->material->UseUnsmoothedTangents() ) {
998 			continue;
999 		}
1000 
1001 		RB_SimpleSurfaceSetup( drawSurf );
1002 
1003 		tri = drawSurf->geo;
1004 		qglBegin( GL_TRIANGLES );
1005 		for ( j = 0 ; j < tri->numIndexes ; j+=3 ) {
1006 			idDrawVert	*a, *b, *c;
1007 
1008 			a = tri->verts + tri->indexes[j];
1009 			b = tri->verts + tri->indexes[j+1];
1010 			c = tri->verts + tri->indexes[j+2];
1011 
1012 			qglVertex3fv( a->xyz.ToFloatPtr() );
1013 			qglVertex3fv( b->xyz.ToFloatPtr() );
1014 			qglVertex3fv( c->xyz.ToFloatPtr() );
1015 		}
1016 		qglEnd();
1017 	}
1018 
1019 	GL_State( GLS_DEFAULT );
1020 }
1021 
1022 
1023 /*
1024 =====================
1025 RB_ShowTangentSpace
1026 
1027 Shade a triangle by the RGB colors of its tangent space
1028 1 = tangents[0]
1029 2 = tangents[1]
1030 3 = normal
1031 =====================
1032 */
RB_ShowTangentSpace(drawSurf_t ** drawSurfs,int numDrawSurfs)1033 static void RB_ShowTangentSpace( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1034 	int		i, j;
1035 	drawSurf_t	*drawSurf;
1036 	const srfTriangles_t	*tri;
1037 
1038 	if ( !r_showTangentSpace.GetInteger() ) {
1039 		return;
1040 	}
1041 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1042 	globalImages->BindNull();
1043 	qglDisable( GL_STENCIL_TEST );
1044 
1045 	GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
1046 
1047 	for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1048 		drawSurf = drawSurfs[i];
1049 
1050 		RB_SimpleSurfaceSetup( drawSurf );
1051 
1052 		tri = drawSurf->geo;
1053 		if ( !tri->verts ) {
1054 			continue;
1055 		}
1056 		qglBegin( GL_TRIANGLES );
1057 		for ( j = 0 ; j < tri->numIndexes ; j++ ) {
1058 			const idDrawVert *v;
1059 
1060 			v = &tri->verts[tri->indexes[j]];
1061 
1062 			if ( r_showTangentSpace.GetInteger() == 1 ) {
1063 				qglColor4f( 0.5 + 0.5 * v->tangents[0][0],  0.5 + 0.5 * v->tangents[0][1],
1064 					0.5 + 0.5 * v->tangents[0][2], 0.5 );
1065 			} else if ( r_showTangentSpace.GetInteger() == 2 ) {
1066 				qglColor4f( 0.5 + 0.5 * v->tangents[1][0],  0.5 + 0.5 * v->tangents[1][1],
1067 					0.5 + 0.5 * v->tangents[1][2], 0.5 );
1068 			} else {
1069 				qglColor4f( 0.5 + 0.5 * v->normal[0],  0.5 + 0.5 * v->normal[1],
1070 					0.5 + 0.5 * v->normal[2], 0.5 );
1071 			}
1072 			qglVertex3fv( v->xyz.ToFloatPtr() );
1073 		}
1074 		qglEnd();
1075 	}
1076 
1077 	GL_State( GLS_DEFAULT );
1078 }
1079 
1080 /*
1081 =====================
1082 RB_ShowVertexColor
1083 
1084 Draw each triangle with the solid vertex colors
1085 =====================
1086 */
RB_ShowVertexColor(drawSurf_t ** drawSurfs,int numDrawSurfs)1087 static void RB_ShowVertexColor( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1088 	int		i, j;
1089 	drawSurf_t	*drawSurf;
1090 	const srfTriangles_t	*tri;
1091 
1092 	if ( !r_showVertexColor.GetBool() ) {
1093 		return;
1094 	}
1095 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1096 	globalImages->BindNull();
1097 	qglDisable( GL_STENCIL_TEST );
1098 
1099 	GL_State( GLS_DEPTHFUNC_LESS );
1100 
1101 	for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1102 		drawSurf = drawSurfs[i];
1103 
1104 		RB_SimpleSurfaceSetup( drawSurf );
1105 
1106 		tri = drawSurf->geo;
1107 		if ( !tri->verts ) {
1108 			continue;
1109 		}
1110 		qglBegin( GL_TRIANGLES );
1111 		for ( j = 0 ; j < tri->numIndexes ; j++ ) {
1112 			const idDrawVert *v;
1113 
1114 			v = &tri->verts[tri->indexes[j]];
1115 			qglColor4ubv( v->color );
1116 			qglVertex3fv( v->xyz.ToFloatPtr() );
1117 		}
1118 		qglEnd();
1119 	}
1120 
1121 	GL_State( GLS_DEFAULT );
1122 }
1123 
1124 
1125 /*
1126 =====================
1127 RB_ShowNormals
1128 
1129 Debugging tool
1130 =====================
1131 */
RB_ShowNormals(drawSurf_t ** drawSurfs,int numDrawSurfs)1132 static void RB_ShowNormals( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1133 	int			i, j;
1134 	drawSurf_t	*drawSurf;
1135 	idVec3		end;
1136 	const srfTriangles_t	*tri;
1137 	float		size;
1138 	bool		showNumbers;
1139 	idVec3		pos;
1140 
1141 	if ( r_showNormals.GetFloat() == 0.0f ) {
1142 		return;
1143 	}
1144 
1145 	GL_State( GLS_POLYMODE_LINE );
1146 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1147 
1148 	globalImages->BindNull();
1149 	qglDisable( GL_STENCIL_TEST );
1150 	if ( !r_debugLineDepthTest.GetBool() ) {
1151 		qglDisable( GL_DEPTH_TEST );
1152 	} else {
1153 		qglEnable( GL_DEPTH_TEST );
1154 	}
1155 
1156 	size = r_showNormals.GetFloat();
1157 	if ( size < 0.0f ) {
1158 		size = -size;
1159 		showNumbers = true;
1160 	} else {
1161 		showNumbers = false;
1162 	}
1163 
1164 	for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1165 		drawSurf = drawSurfs[i];
1166 
1167 		RB_SimpleSurfaceSetup( drawSurf );
1168 
1169 		tri = drawSurf->geo;
1170 		if ( !tri->verts ) {
1171 			continue;
1172 		}
1173 
1174 		qglBegin( GL_LINES );
1175 		for ( j = 0 ; j < tri->numVerts ; j++ ) {
1176 			qglColor3f( 0, 0, 1 );
1177 			qglVertex3fv( tri->verts[j].xyz.ToFloatPtr() );
1178 			VectorMA( tri->verts[j].xyz, size, tri->verts[j].normal, end );
1179 			qglVertex3fv( end.ToFloatPtr() );
1180 
1181 			qglColor3f( 1, 0, 0 );
1182 			qglVertex3fv( tri->verts[j].xyz.ToFloatPtr() );
1183 			VectorMA( tri->verts[j].xyz, size, tri->verts[j].tangents[0], end );
1184 			qglVertex3fv( end.ToFloatPtr() );
1185 
1186 			qglColor3f( 0, 1, 0 );
1187 			qglVertex3fv( tri->verts[j].xyz.ToFloatPtr() );
1188 			VectorMA( tri->verts[j].xyz, size, tri->verts[j].tangents[1], end );
1189 			qglVertex3fv( end.ToFloatPtr() );
1190 		}
1191 		qglEnd();
1192 	}
1193 
1194 	if ( showNumbers ) {
1195 		RB_SimpleWorldSetup();
1196 		for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1197 			drawSurf = drawSurfs[i];
1198 			tri = drawSurf->geo;
1199 			if ( !tri->verts ) {
1200 				continue;
1201 			}
1202 
1203 			for ( j = 0 ; j < tri->numVerts ; j++ ) {
1204 				R_LocalPointToGlobal( drawSurf->space->modelMatrix, tri->verts[j].xyz + tri->verts[j].tangents[0] + tri->verts[j].normal * 0.2f, pos );
1205 				RB_DrawText( va( "%d", j ), pos, 0.01f, colorWhite, backEnd.viewDef->renderView.viewaxis, 1 );
1206 			}
1207 
1208 			for ( j = 0 ; j < tri->numIndexes; j += 3 ) {
1209 				R_LocalPointToGlobal( drawSurf->space->modelMatrix, ( tri->verts[ tri->indexes[ j + 0 ] ].xyz + tri->verts[ tri->indexes[ j + 1 ] ].xyz + tri->verts[ tri->indexes[ j + 2 ] ].xyz ) * ( 1.0f / 3.0f ) + tri->verts[ tri->indexes[ j + 0 ] ].normal * 0.2f, pos );
1210 				RB_DrawText( va( "%d", j / 3 ), pos, 0.01f, colorCyan, backEnd.viewDef->renderView.viewaxis, 1 );
1211 			}
1212 		}
1213 	}
1214 
1215 	qglEnable( GL_STENCIL_TEST );
1216 }
1217 
1218 
1219 /*
1220 =====================
1221 RB_ShowNormals
1222 
1223 Debugging tool
1224 =====================
1225 */
1226 #if 0
1227 static void RB_AltShowNormals( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1228 	int			i, j, k;
1229 	drawSurf_t	*drawSurf;
1230 	idVec3		end;
1231 	const srfTriangles_t	*tri;
1232 
1233 	if ( r_showNormals.GetFloat() == 0.0f ) {
1234 		return;
1235 	}
1236 
1237 	GL_State( GLS_DEFAULT );
1238 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1239 
1240 	globalImages->BindNull();
1241 	qglDisable( GL_STENCIL_TEST );
1242 	qglDisable( GL_DEPTH_TEST );
1243 
1244 	for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1245 		drawSurf = drawSurfs[i];
1246 
1247 		RB_SimpleSurfaceSetup( drawSurf );
1248 
1249 		tri = drawSurf->geo;
1250 		qglBegin( GL_LINES );
1251 		for ( j = 0 ; j < tri->numIndexes ; j += 3 ) {
1252 			const idDrawVert *v[3];
1253 			idVec3		mid;
1254 
1255 			v[0] = &tri->verts[tri->indexes[j+0]];
1256 			v[1] = &tri->verts[tri->indexes[j+1]];
1257 			v[2] = &tri->verts[tri->indexes[j+2]];
1258 
1259 			// make the midpoint slightly above the triangle
1260 			mid = ( v[0]->xyz + v[1]->xyz + v[2]->xyz ) * ( 1.0f / 3.0f );
1261 			mid += 0.1f * tri->facePlanes[ j / 3 ].Normal();
1262 
1263 			for ( k = 0 ; k < 3 ; k++ ) {
1264 				idVec3	pos;
1265 
1266 				pos = ( mid + v[k]->xyz * 3.0f ) * 0.25f;
1267 
1268 				qglColor3f( 0, 0, 1 );
1269 				qglVertex3fv( pos.ToFloatPtr() );
1270 				VectorMA( pos, r_showNormals.GetFloat(), v[k]->normal, end );
1271 				qglVertex3fv( end.ToFloatPtr() );
1272 
1273 				qglColor3f( 1, 0, 0 );
1274 				qglVertex3fv( pos.ToFloatPtr() );
1275 				VectorMA( pos, r_showNormals.GetFloat(), v[k]->tangents[0], end );
1276 				qglVertex3fv( end.ToFloatPtr() );
1277 
1278 				qglColor3f( 0, 1, 0 );
1279 				qglVertex3fv( pos.ToFloatPtr() );
1280 				VectorMA( pos, r_showNormals.GetFloat(), v[k]->tangents[1], end );
1281 				qglVertex3fv( end.ToFloatPtr() );
1282 
1283 				qglColor3f( 1, 1, 1 );
1284 				qglVertex3fv( pos.ToFloatPtr() );
1285 				qglVertex3fv( v[k]->xyz.ToFloatPtr() );
1286 			}
1287 		}
1288 		qglEnd();
1289 	}
1290 
1291 	qglEnable( GL_DEPTH_TEST );
1292 	qglEnable( GL_STENCIL_TEST );
1293 }
1294 #endif
1295 
1296 
1297 
1298 /*
1299 =====================
1300 RB_ShowTextureVectors
1301 
1302 Draw texture vectors in the center of each triangle
1303 =====================
1304 */
RB_ShowTextureVectors(drawSurf_t ** drawSurfs,int numDrawSurfs)1305 static void RB_ShowTextureVectors( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1306 	int			i, j;
1307 	drawSurf_t	*drawSurf;
1308 	const srfTriangles_t	*tri;
1309 
1310 	if ( r_showTextureVectors.GetFloat() == 0.0f ) {
1311 		return;
1312 	}
1313 
1314 	GL_State( GLS_DEPTHFUNC_LESS );
1315 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1316 
1317 	globalImages->BindNull();
1318 
1319 	for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1320 		drawSurf = drawSurfs[i];
1321 
1322 		tri = drawSurf->geo;
1323 
1324 		if ( !tri->verts ) {
1325 			continue;
1326 		}
1327 		if ( !tri->facePlanes ) {
1328 			continue;
1329 		}
1330 		RB_SimpleSurfaceSetup( drawSurf );
1331 
1332 		// draw non-shared edges in yellow
1333 		qglBegin( GL_LINES );
1334 
1335 		for ( j = 0 ; j < tri->numIndexes ; j+= 3 ) {
1336 			const idDrawVert *a, *b, *c;
1337 			float	area, inva;
1338 			idVec3	temp;
1339 			float		d0[5], d1[5];
1340 			idVec3		mid;
1341 			idVec3		tangents[2];
1342 
1343 			a = &tri->verts[tri->indexes[j+0]];
1344 			b = &tri->verts[tri->indexes[j+1]];
1345 			c = &tri->verts[tri->indexes[j+2]];
1346 
1347 			// make the midpoint slightly above the triangle
1348 			mid = ( a->xyz + b->xyz + c->xyz ) * ( 1.0f / 3.0f );
1349 			mid += 0.1f * tri->facePlanes[ j / 3 ].Normal();
1350 
1351 			// calculate the texture vectors
1352 			VectorSubtract( b->xyz, a->xyz, d0 );
1353 			d0[3] = b->st[0] - a->st[0];
1354 			d0[4] = b->st[1] - a->st[1];
1355 			VectorSubtract( c->xyz, a->xyz, d1 );
1356 			d1[3] = c->st[0] - a->st[0];
1357 			d1[4] = c->st[1] - a->st[1];
1358 
1359 			area = d0[3] * d1[4] - d0[4] * d1[3];
1360 			if ( area == 0 ) {
1361 				continue;
1362 			}
1363 			inva = 1.0 / area;
1364 
1365 			temp[0] = (d0[0] * d1[4] - d0[4] * d1[0]) * inva;
1366 			temp[1] = (d0[1] * d1[4] - d0[4] * d1[1]) * inva;
1367 			temp[2] = (d0[2] * d1[4] - d0[4] * d1[2]) * inva;
1368 			temp.Normalize();
1369 			tangents[0] = temp;
1370 
1371 			temp[0] = (d0[3] * d1[0] - d0[0] * d1[3]) * inva;
1372 			temp[1] = (d0[3] * d1[1] - d0[1] * d1[3]) * inva;
1373 			temp[2] = (d0[3] * d1[2] - d0[2] * d1[3]) * inva;
1374 			temp.Normalize();
1375 			tangents[1] = temp;
1376 
1377 			// draw the tangents
1378 			tangents[0] = mid + tangents[0] * r_showTextureVectors.GetFloat();
1379 			tangents[1] = mid + tangents[1] * r_showTextureVectors.GetFloat();
1380 
1381 			qglColor3f( 1, 0, 0 );
1382 			qglVertex3fv( mid.ToFloatPtr() );
1383 			qglVertex3fv( tangents[0].ToFloatPtr() );
1384 
1385 			qglColor3f( 0, 1, 0 );
1386 			qglVertex3fv( mid.ToFloatPtr() );
1387 			qglVertex3fv( tangents[1].ToFloatPtr() );
1388 		}
1389 
1390 		qglEnd();
1391 	}
1392 }
1393 
1394 /*
1395 =====================
1396 RB_ShowDominantTris
1397 
1398 Draw lines from each vertex to the dominant triangle center
1399 =====================
1400 */
RB_ShowDominantTris(drawSurf_t ** drawSurfs,int numDrawSurfs)1401 static void RB_ShowDominantTris( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1402 	int			i, j;
1403 	drawSurf_t	*drawSurf;
1404 	const srfTriangles_t	*tri;
1405 
1406 	if ( !r_showDominantTri.GetBool() ) {
1407 		return;
1408 	}
1409 
1410 	GL_State( GLS_DEPTHFUNC_LESS );
1411 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1412 
1413 	qglPolygonOffset( -1, -2 );
1414 	qglEnable( GL_POLYGON_OFFSET_LINE );
1415 
1416 	globalImages->BindNull();
1417 
1418 	for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1419 		drawSurf = drawSurfs[i];
1420 
1421 		tri = drawSurf->geo;
1422 
1423 		if ( !tri->verts ) {
1424 			continue;
1425 		}
1426 		if ( !tri->dominantTris ) {
1427 			continue;
1428 		}
1429 		RB_SimpleSurfaceSetup( drawSurf );
1430 
1431 		qglColor3f( 1, 1, 0 );
1432 		qglBegin( GL_LINES );
1433 
1434 		for ( j = 0 ; j < tri->numVerts ; j++ ) {
1435 			const idDrawVert *a, *b, *c;
1436 			idVec3		mid;
1437 
1438 			// find the midpoint of the dominant tri
1439 
1440 			a = &tri->verts[j];
1441 			b = &tri->verts[tri->dominantTris[j].v2];
1442 			c = &tri->verts[tri->dominantTris[j].v3];
1443 
1444 			mid = ( a->xyz + b->xyz + c->xyz ) * ( 1.0f / 3.0f );
1445 
1446 			qglVertex3fv( mid.ToFloatPtr() );
1447 			qglVertex3fv( a->xyz.ToFloatPtr() );
1448 		}
1449 
1450 		qglEnd();
1451 	}
1452 	qglDisable( GL_POLYGON_OFFSET_LINE );
1453 }
1454 
1455 /*
1456 =====================
1457 RB_ShowEdges
1458 
1459 Debugging tool
1460 =====================
1461 */
RB_ShowEdges(drawSurf_t ** drawSurfs,int numDrawSurfs)1462 static void RB_ShowEdges( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1463 	int			i, j, k, m, n, o;
1464 	drawSurf_t	*drawSurf;
1465 	const srfTriangles_t	*tri;
1466 	const silEdge_t			*edge;
1467 	int			danglePlane;
1468 
1469 	if ( !r_showEdges.GetBool() ) {
1470 		return;
1471 	}
1472 
1473 	GL_State( GLS_DEFAULT );
1474 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1475 
1476 	globalImages->BindNull();
1477 	qglDisable( GL_DEPTH_TEST );
1478 
1479 	for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1480 		drawSurf = drawSurfs[i];
1481 
1482 		tri = drawSurf->geo;
1483 
1484 		idDrawVert *ac = (idDrawVert *)tri->verts;
1485 		if ( !ac ) {
1486 			continue;
1487 		}
1488 
1489 		RB_SimpleSurfaceSetup( drawSurf );
1490 
1491 		// draw non-shared edges in yellow
1492 		qglColor3f( 1, 1, 0 );
1493 		qglBegin( GL_LINES );
1494 
1495 		for ( j = 0 ; j < tri->numIndexes ; j+= 3 ) {
1496 			for ( k = 0 ; k < 3 ; k++ ) {
1497 				int		l, i1, i2;
1498 				l = ( k == 2 ) ? 0 : k + 1;
1499 				i1 = tri->indexes[j+k];
1500 				i2 = tri->indexes[j+l];
1501 
1502 				// if these are used backwards, the edge is shared
1503 				for ( m = 0 ; m < tri->numIndexes ; m += 3 ) {
1504 					for ( n = 0 ; n < 3 ; n++ ) {
1505 						o = ( n == 2 ) ? 0 : n + 1;
1506 						if ( tri->indexes[m+n] == i2 && tri->indexes[m+o] == i1 ) {
1507 							break;
1508 						}
1509 					}
1510 					if ( n != 3 ) {
1511 						break;
1512 					}
1513 				}
1514 
1515 				// if we didn't find a backwards listing, draw it in yellow
1516 				if ( m == tri->numIndexes ) {
1517 					qglVertex3fv( ac[ i1 ].xyz.ToFloatPtr() );
1518 					qglVertex3fv( ac[ i2 ].xyz.ToFloatPtr() );
1519 				}
1520 
1521 			}
1522 		}
1523 
1524 		qglEnd();
1525 
1526 		// draw dangling sil edges in red
1527 		if ( !tri->silEdges ) {
1528 			continue;
1529 		}
1530 
1531 		// the plane number after all real planes
1532 		// is the dangling edge
1533 		danglePlane = tri->numIndexes / 3;
1534 
1535 		qglColor3f( 1, 0, 0 );
1536 
1537 		qglBegin( GL_LINES );
1538 		for ( j = 0 ; j < tri->numSilEdges ; j++ ) {
1539 			edge = tri->silEdges + j;
1540 
1541 			if ( edge->p1 != danglePlane && edge->p2 != danglePlane ) {
1542 				continue;
1543 			}
1544 
1545 			qglVertex3fv( ac[ edge->v1 ].xyz.ToFloatPtr() );
1546 			qglVertex3fv( ac[ edge->v2 ].xyz.ToFloatPtr() );
1547 		}
1548 		qglEnd();
1549 	}
1550 
1551 	qglEnable( GL_DEPTH_TEST );
1552 }
1553 
1554 /*
1555 ==============
1556 RB_ShowLights
1557 
1558 Visualize all light volumes used in the current scene
1559 r_showLights 1	: just print volumes numbers, highlighting ones covering the view
1560 r_showLights 2	: also draw planes of each volume
1561 r_showLights 3	: also draw edges of each volume
1562 ==============
1563 */
RB_ShowLights(void)1564 void RB_ShowLights( void ) {
1565 	const idRenderLightLocal	*light;
1566 	int					count;
1567 	srfTriangles_t		*tri;
1568 	viewLight_t			*vLight;
1569 
1570 	if ( !r_showLights.GetInteger() ) {
1571 		return;
1572 	}
1573 
1574 	// all volumes are expressed in world coordinates
1575 	RB_SimpleWorldSetup();
1576 
1577 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1578 	globalImages->BindNull();
1579 	qglDisable( GL_STENCIL_TEST );
1580 
1581 
1582 	GL_Cull( CT_TWO_SIDED );
1583 	qglDisable( GL_DEPTH_TEST );
1584 
1585 
1586 	common->Printf( "volumes: " );	// FIXME: not in back end!
1587 
1588 	count = 0;
1589 	for ( vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
1590 		light = vLight->lightDef;
1591 		count++;
1592 
1593 		tri = light->frustumTris;
1594 
1595 		// depth buffered planes
1596 		if ( r_showLights.GetInteger() >= 2 ) {
1597 			GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHMASK );
1598 			qglColor4f( 0, 0, 1, 0.25 );
1599 			qglEnable( GL_DEPTH_TEST );
1600 			RB_RenderTriangleSurface( tri );
1601 		}
1602 
1603 		// non-hidden lines
1604 		if ( r_showLights.GetInteger() >= 3 ) {
1605 			GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK  );
1606 			qglDisable( GL_DEPTH_TEST );
1607 			qglColor3f( 1, 1, 1 );
1608 			RB_RenderTriangleSurface( tri );
1609 		}
1610 
1611 		int index;
1612 
1613 		index = backEnd.viewDef->renderWorld->lightDefs.FindIndex( vLight->lightDef );
1614 		if ( vLight->viewInsideLight ) {
1615 			// view is in this volume
1616 			common->Printf( "[%i] ", index );
1617 		} else {
1618 			common->Printf( "%i ", index );
1619 		}
1620 	}
1621 
1622 	qglEnable( GL_DEPTH_TEST );
1623 	qglDisable( GL_POLYGON_OFFSET_LINE );
1624 
1625 	qglDepthRange( 0, 1 );
1626 	GL_State( GLS_DEFAULT );
1627 	GL_Cull( CT_FRONT_SIDED );
1628 
1629 	common->Printf( " = %i total\n", count );
1630 }
1631 
1632 /*
1633 =====================
1634 RB_ShowPortals
1635 
1636 Debugging tool, won't work correctly with SMP or when mirrors are present
1637 =====================
1638 */
RB_ShowPortals(void)1639 void RB_ShowPortals( void ) {
1640 	if ( !r_showPortals.GetBool() ) {
1641 		return;
1642 	}
1643 
1644 	// all portals are expressed in world coordinates
1645 	RB_SimpleWorldSetup();
1646 
1647 	globalImages->BindNull();
1648 	qglDisable( GL_DEPTH_TEST );
1649 
1650 	GL_State( GLS_DEFAULT );
1651 
1652 	((idRenderWorldLocal *)backEnd.viewDef->renderWorld)->ShowPortals();
1653 
1654 	qglEnable( GL_DEPTH_TEST );
1655 }
1656 
1657 /*
1658 ================
1659 RB_ClearDebugText
1660 ================
1661 */
RB_ClearDebugText(int time)1662 void RB_ClearDebugText( int time ) {
1663 	int			i;
1664 	int			num;
1665 	debugText_t	*text;
1666 
1667 	rb_debugTextTime = time;
1668 
1669 	if ( !time ) {
1670 		// free up our strings
1671 		text = rb_debugText;
1672 		for ( i = 0 ; i < MAX_DEBUG_TEXT; i++, text++ ) {
1673 			text->text.Clear();
1674 		}
1675 		rb_numDebugText = 0;
1676 		return;
1677 	}
1678 
1679 	// copy any text that still needs to be drawn
1680 	num	= 0;
1681 	text = rb_debugText;
1682 	for ( i = 0 ; i < rb_numDebugText; i++, text++ ) {
1683 		if ( text->lifeTime > time ) {
1684 			if ( num != i ) {
1685 				rb_debugText[ num ] = *text;
1686 			}
1687 			num++;
1688 		}
1689 	}
1690 	rb_numDebugText = num;
1691 }
1692 
1693 /*
1694 ================
1695 RB_AddDebugText
1696 ================
1697 */
RB_AddDebugText(const char * text,const idVec3 & origin,float scale,const idVec4 & color,const idMat3 & viewAxis,const int align,const int lifetime,const bool depthTest)1698 void RB_AddDebugText( const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align, const int lifetime, const bool depthTest ) {
1699 	debugText_t *debugText;
1700 
1701 	if ( rb_numDebugText < MAX_DEBUG_TEXT ) {
1702 		debugText = &rb_debugText[ rb_numDebugText++ ];
1703 		debugText->text			= text;
1704 		debugText->origin		= origin;
1705 		debugText->scale		= scale;
1706 		debugText->color		= color;
1707 		debugText->viewAxis		= viewAxis;
1708 		debugText->align		= align;
1709 		debugText->lifeTime		= rb_debugTextTime + lifetime;
1710 		debugText->depthTest	= depthTest;
1711 	}
1712 }
1713 
1714 /*
1715 ================
1716 RB_DrawTextLength
1717 
1718   returns the length of the given text
1719 ================
1720 */
RB_DrawTextLength(const char * text,float scale,int len)1721 float RB_DrawTextLength( const char *text, float scale, int len ) {
1722 	int i, num, index, charIndex;
1723 	float spacing, textLen = 0.0f;
1724 
1725 	if ( text && *text ) {
1726 		if ( !len ) {
1727 			len = strlen(text);
1728 		}
1729 		for ( i = 0; i < len; i++ ) {
1730 			charIndex = text[i] - 32;
1731 			if ( charIndex < 0 || charIndex > NUM_SIMPLEX_CHARS ) {
1732 				continue;
1733 			}
1734 			num = simplex[charIndex][0] * 2;
1735 			spacing = simplex[charIndex][1];
1736 			index = 2;
1737 
1738 			while( index - 2 < num ) {
1739 				if ( simplex[charIndex][index] < 0) {
1740 					index++;
1741 					continue;
1742 				}
1743 				index += 2;
1744 				if ( simplex[charIndex][index] < 0) {
1745 					index++;
1746 					continue;
1747 				}
1748 			}
1749 			textLen += spacing * scale;
1750 		}
1751 	}
1752 	return textLen;
1753 }
1754 
1755 /*
1756 ================
1757 RB_DrawText
1758 
1759   oriented on the viewaxis
1760   align can be 0-left, 1-center (default), 2-right
1761 ================
1762 */
RB_DrawText(const char * text,const idVec3 & origin,float scale,const idVec4 & color,const idMat3 & viewAxis,const int align)1763 static void RB_DrawText( const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align ) {
1764 	int i, j, len, num, index, charIndex, line;
1765 	float textLen = 0.0f, spacing;
1766 	idVec3 org, p1, p2;
1767 
1768 	if ( text && *text ) {
1769 		qglBegin( GL_LINES );
1770 		qglColor3fv( color.ToFloatPtr() );
1771 
1772 		if ( text[0] == '\n' ) {
1773 			line = 1;
1774 		} else {
1775 			line = 0;
1776 		}
1777 
1778 		org.Zero();
1779 		len = strlen( text );
1780 		for ( i = 0; i < len; i++ ) {
1781 
1782 			if ( i == 0 || text[i] == '\n' ) {
1783 				org = origin - viewAxis[2] * ( line * 36.0f * scale );
1784 				if ( align != 0 ) {
1785 					for ( j = 1; i+j <= len; j++ ) {
1786 						if ( i+j == len || text[i+j] == '\n' ) {
1787 							textLen = RB_DrawTextLength( text+i, scale, j );
1788 							break;
1789 						}
1790 					}
1791 					if ( align == 2 ) {
1792 						// right
1793 						org += viewAxis[1] * textLen;
1794 					} else {
1795 						// center
1796 						org += viewAxis[1] * ( textLen * 0.5f );
1797 					}
1798 				}
1799 				line++;
1800 			}
1801 
1802 			charIndex = text[i] - 32;
1803 			if ( charIndex < 0 || charIndex > NUM_SIMPLEX_CHARS ) {
1804 				continue;
1805 			}
1806 			num = simplex[charIndex][0] * 2;
1807 			spacing = simplex[charIndex][1];
1808 			index = 2;
1809 
1810 			while( index - 2 < num ) {
1811 				if ( simplex[charIndex][index] < 0) {
1812 					index++;
1813 					continue;
1814 				}
1815 				p1 = org + scale * simplex[charIndex][index] * -viewAxis[1] + scale * simplex[charIndex][index+1] * viewAxis[2];
1816 				index += 2;
1817 				if ( simplex[charIndex][index] < 0) {
1818 					index++;
1819 					continue;
1820 				}
1821 				p2 = org + scale * simplex[charIndex][index] * -viewAxis[1] + scale * simplex[charIndex][index+1] * viewAxis[2];
1822 
1823 				qglVertex3fv( p1.ToFloatPtr() );
1824 				qglVertex3fv( p2.ToFloatPtr() );
1825 			}
1826 			org -= viewAxis[1] * ( spacing * scale );
1827 		}
1828 
1829 		qglEnd();
1830 	}
1831 }
1832 
1833 /*
1834 ================
1835 RB_ShowDebugText
1836 ================
1837 */
RB_ShowDebugText(void)1838 void RB_ShowDebugText( void ) {
1839 	int			i;
1840 	int			width;
1841 	debugText_t	*text;
1842 
1843 	if ( !rb_numDebugText ) {
1844 		return;
1845 	}
1846 
1847 	// all lines are expressed in world coordinates
1848 	RB_SimpleWorldSetup();
1849 
1850 	globalImages->BindNull();
1851 
1852 	width = r_debugLineWidth.GetInteger();
1853 	if ( width < 1 ) {
1854 		width = 1;
1855 	} else if ( width > 10 ) {
1856 		width = 10;
1857 	}
1858 
1859 	// draw lines
1860 	GL_State( GLS_POLYMODE_LINE );
1861 	qglLineWidth( width );
1862 
1863 	if ( !r_debugLineDepthTest.GetBool() ) {
1864 		qglDisable( GL_DEPTH_TEST );
1865 	}
1866 
1867 	text = rb_debugText;
1868 	for ( i = 0 ; i < rb_numDebugText; i++, text++ ) {
1869 		if ( !text->depthTest ) {
1870 			RB_DrawText( text->text, text->origin, text->scale, text->color, text->viewAxis, text->align );
1871 		}
1872 	}
1873 
1874 	if ( !r_debugLineDepthTest.GetBool() ) {
1875 		qglEnable( GL_DEPTH_TEST );
1876 	}
1877 
1878 	text = rb_debugText;
1879 	for ( i = 0 ; i < rb_numDebugText; i++, text++ ) {
1880 		if ( text->depthTest ) {
1881 			RB_DrawText( text->text, text->origin, text->scale, text->color, text->viewAxis, text->align );
1882 		}
1883 	}
1884 
1885 	qglLineWidth( 1 );
1886 	GL_State( GLS_DEFAULT );
1887 }
1888 
1889 /*
1890 ================
1891 RB_ClearDebugLines
1892 ================
1893 */
RB_ClearDebugLines(int time)1894 void RB_ClearDebugLines( int time ) {
1895 	int			i;
1896 	int			num;
1897 	debugLine_t	*line;
1898 
1899 	rb_debugLineTime = time;
1900 
1901 	if ( !time ) {
1902 		rb_numDebugLines = 0;
1903 		return;
1904 	}
1905 
1906 	// copy any lines that still need to be drawn
1907 	num	= 0;
1908 	line = rb_debugLines;
1909 	for ( i = 0 ; i < rb_numDebugLines; i++, line++ ) {
1910 		if ( line->lifeTime > time ) {
1911 			if ( num != i ) {
1912 				rb_debugLines[ num ] = *line;
1913 			}
1914 			num++;
1915 		}
1916 	}
1917 	rb_numDebugLines = num;
1918 }
1919 
1920 /*
1921 ================
1922 RB_AddDebugLine
1923 ================
1924 */
RB_AddDebugLine(const idVec4 & color,const idVec3 & start,const idVec3 & end,const int lifeTime,const bool depthTest)1925 void RB_AddDebugLine( const idVec4 &color, const idVec3 &start, const idVec3 &end, const int lifeTime, const bool depthTest ) {
1926 	debugLine_t *line;
1927 
1928 	if ( rb_numDebugLines < MAX_DEBUG_LINES ) {
1929 		line = &rb_debugLines[ rb_numDebugLines++ ];
1930 		line->rgb		= color;
1931 		line->start		= start;
1932 		line->end		= end;
1933 		line->depthTest = depthTest;
1934 		line->lifeTime	= rb_debugLineTime + lifeTime;
1935 	}
1936 }
1937 
1938 /*
1939 ================
1940 RB_ShowDebugLines
1941 ================
1942 */
RB_ShowDebugLines(void)1943 void RB_ShowDebugLines( void ) {
1944 	int			i;
1945 	int			width;
1946 	debugLine_t	*line;
1947 
1948 	if ( !rb_numDebugLines ) {
1949 		return;
1950 	}
1951 
1952 	// all lines are expressed in world coordinates
1953 	RB_SimpleWorldSetup();
1954 
1955 	globalImages->BindNull();
1956 
1957 	width = r_debugLineWidth.GetInteger();
1958 	if ( width < 1 ) {
1959 		width = 1;
1960 	} else if ( width > 10 ) {
1961 		width = 10;
1962 	}
1963 
1964 	// draw lines
1965 	GL_State( GLS_POLYMODE_LINE );//| GLS_DEPTHMASK ); //| GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
1966 	qglLineWidth( width );
1967 
1968 	if ( !r_debugLineDepthTest.GetBool() ) {
1969 		qglDisable( GL_DEPTH_TEST );
1970 	}
1971 
1972 	qglBegin( GL_LINES );
1973 
1974 	line = rb_debugLines;
1975 	for ( i = 0 ; i < rb_numDebugLines; i++, line++ ) {
1976 		if ( !line->depthTest ) {
1977 			qglColor3fv( line->rgb.ToFloatPtr() );
1978 			qglVertex3fv( line->start.ToFloatPtr() );
1979 			qglVertex3fv( line->end.ToFloatPtr() );
1980 		}
1981 	}
1982 	qglEnd();
1983 
1984 	if ( !r_debugLineDepthTest.GetBool() ) {
1985 		qglEnable( GL_DEPTH_TEST );
1986 	}
1987 
1988 	qglBegin( GL_LINES );
1989 
1990 	line = rb_debugLines;
1991 	for ( i = 0 ; i < rb_numDebugLines; i++, line++ ) {
1992 		if ( line->depthTest ) {
1993 			qglColor4fv( line->rgb.ToFloatPtr() );
1994 			qglVertex3fv( line->start.ToFloatPtr() );
1995 			qglVertex3fv( line->end.ToFloatPtr() );
1996 		}
1997 	}
1998 
1999 	qglEnd();
2000 
2001 	qglLineWidth( 1 );
2002 	GL_State( GLS_DEFAULT );
2003 }
2004 
2005 /*
2006 ================
2007 RB_ClearDebugPolygons
2008 ================
2009 */
RB_ClearDebugPolygons(int time)2010 void RB_ClearDebugPolygons( int time ) {
2011 	int				i;
2012 	int				num;
2013 	debugPolygon_t	*poly;
2014 
2015 	rb_debugPolygonTime = time;
2016 
2017 	if ( !time ) {
2018 		rb_numDebugPolygons = 0;
2019 		return;
2020 	}
2021 
2022 	// copy any polygons that still need to be drawn
2023 	num	= 0;
2024 
2025 	poly = rb_debugPolygons;
2026 	for ( i = 0 ; i < rb_numDebugPolygons; i++, poly++ ) {
2027 		if ( poly->lifeTime > time ) {
2028 			if ( num != i ) {
2029 				rb_debugPolygons[ num ] = *poly;
2030 			}
2031 			num++;
2032 		}
2033 	}
2034 	rb_numDebugPolygons = num;
2035 }
2036 
2037 /*
2038 ================
2039 RB_AddDebugPolygon
2040 ================
2041 */
RB_AddDebugPolygon(const idVec4 & color,const idWinding & winding,const int lifeTime,const bool depthTest)2042 void RB_AddDebugPolygon( const idVec4 &color, const idWinding &winding, const int lifeTime, const bool depthTest ) {
2043 	debugPolygon_t *poly;
2044 
2045 	if ( rb_numDebugPolygons < MAX_DEBUG_POLYGONS ) {
2046 		poly = &rb_debugPolygons[ rb_numDebugPolygons++ ];
2047 		poly->rgb		= color;
2048 		poly->winding	= winding;
2049 		poly->depthTest = depthTest;
2050 		poly->lifeTime	= rb_debugPolygonTime + lifeTime;
2051 	}
2052 }
2053 
2054 /*
2055 ================
2056 RB_ShowDebugPolygons
2057 ================
2058 */
RB_ShowDebugPolygons(void)2059 void RB_ShowDebugPolygons( void ) {
2060 	int				i, j;
2061 	debugPolygon_t	*poly;
2062 
2063 	if ( !rb_numDebugPolygons ) {
2064 		return;
2065 	}
2066 
2067 	// all lines are expressed in world coordinates
2068 	RB_SimpleWorldSetup();
2069 
2070 	globalImages->BindNull();
2071 
2072 	qglDisable( GL_TEXTURE_2D );
2073 	qglDisable( GL_STENCIL_TEST );
2074 
2075 	qglEnable( GL_DEPTH_TEST );
2076 
2077 	if ( r_debugPolygonFilled.GetBool() ) {
2078 		GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHMASK );
2079 		qglPolygonOffset( -1, -2 );
2080 		qglEnable( GL_POLYGON_OFFSET_FILL );
2081 	} else {
2082 		GL_State( GLS_POLYMODE_LINE );
2083 		qglPolygonOffset( -1, -2 );
2084 		qglEnable( GL_POLYGON_OFFSET_LINE );
2085 	}
2086 
2087 	poly = rb_debugPolygons;
2088 	for ( i = 0 ; i < rb_numDebugPolygons; i++, poly++ ) {
2089 //		if ( !poly->depthTest ) {
2090 
2091 			qglColor4fv( poly->rgb.ToFloatPtr() );
2092 
2093 			qglBegin( GL_POLYGON );
2094 
2095 			for ( j = 0; j < poly->winding.GetNumPoints(); j++) {
2096 				qglVertex3fv( poly->winding[j].ToFloatPtr() );
2097 			}
2098 
2099 			qglEnd();
2100 //		}
2101 	}
2102 
2103 	GL_State( GLS_DEFAULT );
2104 
2105 	if ( r_debugPolygonFilled.GetBool() ) {
2106 		qglDisable( GL_POLYGON_OFFSET_FILL );
2107 	} else {
2108 		qglDisable( GL_POLYGON_OFFSET_LINE );
2109 	}
2110 
2111 	qglDepthRange( 0, 1 );
2112 	GL_State( GLS_DEFAULT );
2113 }
2114 
2115 /*
2116 ================
2117 RB_TestGamma
2118 ================
2119 */
2120 #define	G_WIDTH		512
2121 #define	G_HEIGHT	512
2122 #define	BAR_HEIGHT	64
2123 
RB_TestGamma(void)2124 void RB_TestGamma( void ) {
2125 	byte	image[G_HEIGHT][G_WIDTH][4];
2126 	int		i, j;
2127 	int		c, comp;
2128 	int		v, dither;
2129 	int		mask, y;
2130 
2131 	if ( r_testGamma.GetInteger() <= 0 ) {
2132 		return;
2133 	}
2134 
2135 	v = r_testGamma.GetInteger();
2136 	if ( v <= 1 || v >= 196 ) {
2137 		v = 128;
2138 	}
2139 
2140 	memset( image, 0, sizeof( image ) );
2141 
2142 	for ( mask = 0 ; mask < 8 ; mask++ ) {
2143 		y = mask * BAR_HEIGHT;
2144 		for ( c = 0 ; c < 4 ; c++ ) {
2145 			v = c * 64 + 32;
2146 			// solid color
2147 			for ( i = 0 ; i < BAR_HEIGHT/2 ; i++ ) {
2148 				for ( j = 0 ; j < G_WIDTH/4 ; j++ ) {
2149 					for ( comp = 0 ; comp < 3 ; comp++ ) {
2150 						if ( mask & ( 1 << comp ) ) {
2151 							image[y+i][c*G_WIDTH/4+j][comp] = v;
2152 						}
2153 					}
2154 				}
2155 				// dithered color
2156 				for ( j = 0 ; j < G_WIDTH/4 ; j++ ) {
2157 					if ( ( i ^ j ) & 1 ) {
2158 						dither = c * 64;
2159 					} else {
2160 						dither = c * 64 + 63;
2161 					}
2162 					for ( comp = 0 ; comp < 3 ; comp++ ) {
2163 						if ( mask & ( 1 << comp ) ) {
2164 							image[y+BAR_HEIGHT/2+i][c*G_WIDTH/4+j][comp] = dither;
2165 						}
2166 					}
2167 				}
2168 			}
2169 		}
2170 	}
2171 
2172 	// draw geometrically increasing steps in the bottom row
2173 	y = 0 * BAR_HEIGHT;
2174 	float	scale = 1;
2175 	for ( c = 0 ; c < 4 ; c++ ) {
2176 		v = (int)(64 * scale);
2177 		if ( v < 0 ) {
2178 			v = 0;
2179 		} else if ( v > 255 ) {
2180 			v = 255;
2181 		}
2182 		scale = scale * 1.5;
2183 		for ( i = 0 ; i < BAR_HEIGHT ; i++ ) {
2184 			for ( j = 0 ; j < G_WIDTH/4 ; j++ ) {
2185 				image[y+i][c*G_WIDTH/4+j][0] = v;
2186 				image[y+i][c*G_WIDTH/4+j][1] = v;
2187 				image[y+i][c*G_WIDTH/4+j][2] = v;
2188 			}
2189 		}
2190 	}
2191 
2192 
2193 	qglLoadIdentity();
2194 
2195 	qglMatrixMode( GL_PROJECTION );
2196 	GL_State( GLS_DEPTHFUNC_ALWAYS );
2197 	qglColor3f( 1, 1, 1 );
2198 	qglPushMatrix();
2199 	qglLoadIdentity();
2200 	qglDisable( GL_TEXTURE_2D );
2201 	qglOrtho( 0, 1, 0, 1, -1, 1 );
2202 	qglRasterPos2f( 0.01f, 0.01f );
2203 	qglDrawPixels( G_WIDTH, G_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, image );
2204 	qglPopMatrix();
2205 	qglEnable( GL_TEXTURE_2D );
2206 	qglMatrixMode( GL_MODELVIEW );
2207 }
2208 
2209 
2210 /*
2211 ==================
2212 RB_TestGammaBias
2213 ==================
2214 */
RB_TestGammaBias(void)2215 static void RB_TestGammaBias( void ) {
2216 	byte	image[G_HEIGHT][G_WIDTH][4];
2217 
2218 	if ( r_testGammaBias.GetInteger() <= 0 ) {
2219 		return;
2220 	}
2221 
2222 	int y = 0;
2223 	for ( int bias = -40 ; bias < 40 ; bias+=10, y += BAR_HEIGHT ) {
2224 		float	scale = 1;
2225 		for ( int c = 0 ; c < 4 ; c++ ) {
2226 			int v = (int)(64 * scale + bias);
2227 			scale = scale * 1.5;
2228 			if ( v < 0 ) {
2229 				v = 0;
2230 			} else if ( v > 255 ) {
2231 				v = 255;
2232 			}
2233 			for ( int i = 0 ; i < BAR_HEIGHT ; i++ ) {
2234 				for ( int j = 0 ; j < G_WIDTH/4 ; j++ ) {
2235 					image[y+i][c*G_WIDTH/4+j][0] = v;
2236 					image[y+i][c*G_WIDTH/4+j][1] = v;
2237 					image[y+i][c*G_WIDTH/4+j][2] = v;
2238 				}
2239 			}
2240 		}
2241 	}
2242 
2243 
2244 	qglLoadIdentity();
2245 	qglMatrixMode( GL_PROJECTION );
2246 	GL_State( GLS_DEPTHFUNC_ALWAYS );
2247 	qglColor3f( 1, 1, 1 );
2248 	qglPushMatrix();
2249 	qglLoadIdentity();
2250 	qglDisable( GL_TEXTURE_2D );
2251 	qglOrtho( 0, 1, 0, 1, -1, 1 );
2252 	qglRasterPos2f( 0.01f, 0.01f );
2253 	qglDrawPixels( G_WIDTH, G_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, image );
2254 	qglPopMatrix();
2255 	qglEnable( GL_TEXTURE_2D );
2256 	qglMatrixMode( GL_MODELVIEW );
2257 }
2258 
2259 /*
2260 ================
2261 RB_TestImage
2262 
2263 Display a single image over most of the screen
2264 ================
2265 */
RB_TestImage(void)2266 void RB_TestImage( void ) {
2267 	idImage	*image;
2268 	int		max;
2269 	float	w, h;
2270 
2271 	image = tr.testImage;
2272 	if ( !image ) {
2273 		return;
2274 	}
2275 
2276 	if ( tr.testVideo ) {
2277 		cinData_t	cin;
2278 
2279 		cin = tr.testVideo->ImageForTime( (int)(1000 * ( backEnd.viewDef->floatTime - tr.testVideoStartTime ) ) );
2280 		if ( cin.image ) {
2281 			image->UploadScratch( cin.image, cin.imageWidth, cin.imageHeight );
2282 		} else {
2283 			tr.testImage = NULL;
2284 			return;
2285 		}
2286 		w = 0.25;
2287 		h = 0.25;
2288 	} else {
2289 		max = image->uploadWidth > image->uploadHeight ? image->uploadWidth : image->uploadHeight;
2290 
2291 		w = 0.25 * image->uploadWidth / max;
2292 		h = 0.25 * image->uploadHeight / max;
2293 
2294 		w *= (float)glConfig.vidHeight / glConfig.vidWidth;
2295 	}
2296 
2297 	qglLoadIdentity();
2298 
2299 	qglMatrixMode( GL_PROJECTION );
2300 	GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
2301 	qglColor3f( 1, 1, 1 );
2302 	qglPushMatrix();
2303 	qglLoadIdentity();
2304 	qglOrtho( 0, 1, 0, 1, -1, 1 );
2305 
2306 	tr.testImage->Bind();
2307 	qglBegin( GL_QUADS );
2308 
2309 	qglTexCoord2f( 0, 1 );
2310 	qglVertex2f( 0.5 - w, 0 );
2311 
2312 	qglTexCoord2f( 0, 0 );
2313 	qglVertex2f( 0.5 - w, h*2 );
2314 
2315 	qglTexCoord2f( 1, 0 );
2316 	qglVertex2f( 0.5 + w, h*2 );
2317 
2318 	qglTexCoord2f( 1, 1 );
2319 	qglVertex2f( 0.5 + w, 0 );
2320 
2321 	qglEnd();
2322 
2323 	qglPopMatrix();
2324 	qglMatrixMode( GL_MODELVIEW );
2325 }
2326 
2327 /*
2328 =================
2329 RB_RenderDebugTools
2330 =================
2331 */
RB_RenderDebugTools(drawSurf_t ** drawSurfs,int numDrawSurfs)2332 void RB_RenderDebugTools( drawSurf_t **drawSurfs, int numDrawSurfs ) {
2333 	// don't do anything if this was a 2D rendering
2334 	if ( !backEnd.viewDef->viewEntitys ) {
2335 		return;
2336 	}
2337 
2338 	GL_State( GLS_DEFAULT );
2339 	backEnd.currentScissor = backEnd.viewDef->scissor;
2340 	qglScissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1,
2341 		backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1,
2342 		backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1,
2343 		backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 );
2344 
2345 
2346 	RB_ShowLightCount();
2347 	RB_ShowShadowCount();
2348 	RB_ShowTexturePolarity( drawSurfs, numDrawSurfs );
2349 	RB_ShowTangentSpace( drawSurfs, numDrawSurfs );
2350 	RB_ShowVertexColor( drawSurfs, numDrawSurfs );
2351 	RB_ShowTris( drawSurfs, numDrawSurfs );
2352 	RB_ShowUnsmoothedTangents( drawSurfs, numDrawSurfs );
2353 	RB_ShowSurfaceInfo( drawSurfs, numDrawSurfs );
2354 	RB_ShowEdges( drawSurfs, numDrawSurfs );
2355 	RB_ShowNormals( drawSurfs, numDrawSurfs );
2356 	RB_ShowViewEntitys( backEnd.viewDef->viewEntitys );
2357 	RB_ShowLights();
2358 	RB_ShowTextureVectors( drawSurfs, numDrawSurfs );
2359 	RB_ShowDominantTris( drawSurfs, numDrawSurfs );
2360 	if ( r_testGamma.GetInteger() > 0 ) {	// test here so stack check isn't so damn slow on debug builds
2361 		RB_TestGamma();
2362 	}
2363 	if ( r_testGammaBias.GetInteger() > 0 ) {
2364 		RB_TestGammaBias();
2365 	}
2366 	RB_TestImage();
2367 	RB_ShowPortals();
2368 	RB_ShowSilhouette();
2369 	RB_ShowDepthBuffer();
2370 	RB_ShowIntensity();
2371 	RB_ShowDebugLines();
2372 	RB_ShowDebugText();
2373 	RB_ShowDebugPolygons();
2374 	RB_ShowTrace( drawSurfs, numDrawSurfs );
2375 }
2376 
2377 /*
2378 =================
2379 RB_ShutdownDebugTools
2380 =================
2381 */
RB_ShutdownDebugTools(void)2382 void RB_ShutdownDebugTools( void ) {
2383 	for ( int i = 0; i < MAX_DEBUG_POLYGONS; i++ ) {
2384 		rb_debugPolygons[i].winding.Clear();
2385 	}
2386 }
2387