1428 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1428 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //========= Copyright Valve Corporation, All rights reserved. ============//
 | |
| //
 | |
| // Purpose: 
 | |
| //
 | |
| // $NoKeywords: $
 | |
| //
 | |
| //=============================================================================//
 | |
| #include "glos.h"
 | |
| #include <gl/gl.h>
 | |
| #if _MSC_VER < 1600
 | |
| #include <gl/glaux.h>
 | |
| #endif
 | |
| #include <gl/glu.h>
 | |
| #include <stdarg.h>
 | |
| #include <string.h>
 | |
| #include <stdio.h>
 | |
| #include <math.h>
 | |
| #include "cmdlib.h"
 | |
| #include "mathlib/mathlib.h"
 | |
| #include "cmodel.h"
 | |
| #include "tier1/strtools.h"
 | |
| #include "physdll.h"
 | |
| #include "phyfile.h"
 | |
| #include "vphysics_interface.h"
 | |
| #include "tier0/icommandline.h"
 | |
| #include "tier0/vprof.h"
 | |
| 
 | |
| HDC		camdc;
 | |
| HGLRC	baseRC;
 | |
| HWND	camerawindow;
 | |
| HANDLE	main_instance;
 | |
| 
 | |
| /*	YWB:  3/13/98
 | |
| 	You run the program like normal with any file.  If you want to read portals for the
 | |
| 	file type, you type:  glview -portal filename.gl0 (or whatever).  glview will then
 | |
| 	try to read in the .prt file filename.prt.
 | |
| 
 | |
| 	The portals are shown as white lines superimposed over your image.  You can toggle the 
 | |
| 	view between showing portals or not by hitting the '2' key.  The '1' key toggles 
 | |
| 	world polygons.
 | |
| 
 | |
| 	The 'b' key toggles blending modes.
 | |
| 
 | |
| 	If you don't want to depth buffer the portals, hit 'p'.
 | |
| 
 | |
|     The command line parsing is inelegant but functional.
 | |
| 
 | |
|     I sped up the KB movement and turn speed, too.
 | |
|  */
 | |
| 
 | |
| // Vars added by YWB
 | |
| Vector g_Center;               // Center of all read points, so camera is in a sensible place
 | |
| int g_nTotalPoints	   = 0;    // Total points read, for calculating center
 | |
| int g_UseBlending      = 0;	   // Toggle to use blending mode or not
 | |
| BOOL g_bReadPortals    = 0;	   // Did we read in a portal file?
 | |
| BOOL g_bNoDepthPortals = 0;    // Do we zbuffer the lines of the portals?
 | |
| int g_nPortalHighlight = -1;	// The leaf we're viewing
 | |
| int g_nLeafHighlight = -1;	// The leaf we're viewing
 | |
| BOOL g_bShowList1      = 1;	   // Show regular polygons?
 | |
| BOOL g_bShowList2      = 1;	   // Show portals?
 | |
| BOOL g_bShowLines      = 0;    // Show outlines of faces
 | |
| BOOL g_Active = TRUE;
 | |
| BOOL g_Update = TRUE;
 | |
| BOOL g_bDisp = FALSE;
 | |
| IPhysicsCollision *physcollision = NULL;
 | |
| // -----------
 | |
| static int g_Keys[255];
 | |
| void AppKeyDown( int key );
 | |
| void AppKeyUp( int key );
 | |
| 
 | |
| 
 | |
| BOOL ReadDisplacementFile( const char *filename );
 | |
| void DrawDisplacementData( void );
 | |
| 
 | |
| #define BENCHMARK_PHY 0
 | |
| 
 | |
| /*
 | |
| =================
 | |
| Error
 | |
| 
 | |
| For abnormal program terminations
 | |
| =================
 | |
| */
 | |
| void Error (char *error, ...)
 | |
| {
 | |
| 	va_list argptr;
 | |
| 	char	text[1024];
 | |
| 
 | |
| 	va_start (argptr,error);
 | |
| 	vsprintf (text, error,argptr);
 | |
| 	va_end (argptr);
 | |
| 
 | |
|     MessageBox(NULL, text, "Error", 0 /* MB_OK */ );
 | |
| 
 | |
| 	exit (1);
 | |
| }
 | |
| 
 | |
| float	origin[3] = {32, 32, 48};
 | |
| float	angles[3];
 | |
| float	forward[3], right[3], vup[3], vpn[3], vright[3];
 | |
| float	width = 1024;
 | |
| float	height = 768;
 | |
| 
 | |
| float g_flMovementSpeed	= 320.f;		// Units / second (run speed of HL)
 | |
| #define	SPEED_TURN	90		// Degrees / second
 | |
| 
 | |
| #define	VK_COMMA		188
 | |
| #define	VK_PERIOD		190
 | |
| 
 | |
| 
 | |
| void KeyDown (int key)
 | |
| {
 | |
| 	switch (key)
 | |
| 	{
 | |
| 	case VK_ESCAPE:
 | |
| 		g_Active = FALSE;
 | |
| 		break;
 | |
| 
 | |
| 	case VK_F1:
 | |
| 		glEnable (GL_CULL_FACE);
 | |
| 		glCullFace (GL_FRONT);
 | |
| 		break;
 | |
| 	case 'B':
 | |
| 		g_UseBlending ^= 1;
 | |
| 		if (g_UseBlending)
 | |
| 			glEnable(GL_BLEND);// YWB TESTING
 | |
| 		else
 | |
| 			glDisable(GL_BLEND);
 | |
| 		break;
 | |
| 
 | |
| 	case '1':
 | |
| 		g_bShowList1 ^= 1;
 | |
| 		break;
 | |
| 	case '2':
 | |
| 		g_bShowList2 ^= 1;
 | |
| 		break;
 | |
| 	case 'P':
 | |
| 		g_bNoDepthPortals ^= 1;
 | |
| 		break;
 | |
| 	case 'L':
 | |
| 		g_bShowLines ^= 1;
 | |
| 		break;
 | |
| 	}
 | |
| 	g_Update = TRUE;
 | |
| }
 | |
| 
 | |
| static BOOL g_Capture = FALSE;
 | |
| 
 | |
| #define	MOUSE_SENSITIVITY			0.2f
 | |
| #define MOUSE_SENSITIVITY_X			(MOUSE_SENSITIVITY*1)
 | |
| #define MOUSE_SENSITIVITY_Y			(MOUSE_SENSITIVITY*1)
 | |
| 
 | |
| void Cam_MouseMoved( void )
 | |
| {
 | |
| 	if ( g_Capture )
 | |
| 	{
 | |
| 		RECT rect;
 | |
| 		int centerx, centery;
 | |
| 		float deltax, deltay;
 | |
| 		POINT cursorPoint;
 | |
| 
 | |
| 		GetWindowRect( camerawindow, &rect );
 | |
| 		
 | |
| 		if ( rect.top < 0)
 | |
| 			rect.top = 0;
 | |
| 		if ( rect.left < 0)
 | |
| 			rect.left = 0;
 | |
| 
 | |
| 		centerx = ( rect.left + rect.right ) / 2;
 | |
| 		centery = ( rect.top + rect.bottom ) / 2;
 | |
| 
 | |
| 		GetCursorPos( &cursorPoint );
 | |
| 		SetCursorPos( centerx, centery );
 | |
| 
 | |
| 		deltax = (cursorPoint.x - centerx) * MOUSE_SENSITIVITY_X;
 | |
| 		deltay = (cursorPoint.y - centery) * MOUSE_SENSITIVITY_Y;
 | |
| 
 | |
| 		angles[1] -= deltax;
 | |
| 		angles[0] -= deltay;
 | |
| 
 | |
| 		g_Update = TRUE;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int Test_Key( int key )
 | |
| {
 | |
| 	int r = (g_Keys[ key ] != 0);
 | |
| 
 | |
| 	g_Keys[ key ] &= 0x01; // clear out debounce bit
 | |
| 
 | |
| 	if (r)
 | |
| 		g_Update = TRUE;
 | |
| 
 | |
| 	return r;
 | |
| }
 | |
| 
 | |
| // UNDONE: Probably should change the controls to match the game - but I don't know who relies on them
 | |
| // as of now.
 | |
| void Cam_Update( float frametime )
 | |
| {
 | |
| 	if ( Test_Key( 'W' ) )
 | |
| 	{
 | |
| 		VectorMA (origin, g_flMovementSpeed*frametime, vpn, origin);
 | |
| 	}
 | |
| 	if ( Test_Key( 'S' ) )
 | |
| 	{
 | |
| 		VectorMA (origin, -g_flMovementSpeed*frametime, vpn, origin);
 | |
| 	}
 | |
| 	if ( Test_Key( 'A' ) )
 | |
| 	{
 | |
| 		VectorMA (origin, -g_flMovementSpeed*frametime, vright, origin);
 | |
| 	}
 | |
| 	if ( Test_Key( 'D' ) )
 | |
| 	{
 | |
| 		VectorMA (origin, g_flMovementSpeed*frametime, vright, origin);
 | |
| 	}
 | |
| 
 | |
| 	if ( Test_Key( VK_UP ) )
 | |
| 	{
 | |
| 		VectorMA (origin, g_flMovementSpeed*frametime, forward, origin);
 | |
| 	}
 | |
| 	if ( Test_Key( VK_DOWN ) )
 | |
| 	{
 | |
| 		VectorMA (origin, -g_flMovementSpeed*frametime, forward, origin);
 | |
| 	}
 | |
| 
 | |
| 	if ( Test_Key( VK_LEFT ) )
 | |
| 	{
 | |
| 		angles[1] += SPEED_TURN * frametime;
 | |
| 	}
 | |
| 	if ( Test_Key( VK_RIGHT ) )
 | |
| 	{
 | |
| 		angles[1] -= SPEED_TURN * frametime;
 | |
| 	}
 | |
| 	if ( Test_Key( 'F' ) )
 | |
| 	{
 | |
| 		origin[2] += g_flMovementSpeed*frametime;
 | |
| 	}
 | |
| 	if ( Test_Key( 'C' ) )
 | |
| 	{
 | |
| 		origin[2] -= g_flMovementSpeed*frametime;
 | |
| 	}
 | |
| 	if ( Test_Key( VK_INSERT ) )
 | |
| 	{
 | |
| 		angles[0] += SPEED_TURN * frametime;
 | |
| 		if (angles[0] > 85)
 | |
| 			angles[0] = 85;
 | |
| 	}
 | |
| 	if ( Test_Key( VK_DELETE ) )
 | |
| 	{
 | |
| 		angles[0] -= SPEED_TURN * frametime;
 | |
| 		if (angles[0] < -85)
 | |
| 			angles[0] = -85;
 | |
| 	}
 | |
| 	Cam_MouseMoved();
 | |
| }
 | |
| 
 | |
| void Cam_BuildMatrix (void)
 | |
| {
 | |
| 	float	xa, ya;
 | |
| 	float	matrix[4][4];
 | |
| 	int		i;
 | |
| 
 | |
| 	xa = angles[0]/180*M_PI;
 | |
| 	ya = angles[1]/180*M_PI;
 | |
| 
 | |
| 	// the movement matrix is kept 2d ?? do we want this?
 | |
| 
 | |
|     forward[0] = cos(ya);
 | |
|     forward[1] = sin(ya);
 | |
|     right[0] = forward[1];
 | |
|     right[1] = -forward[0];
 | |
| 
 | |
| 	glGetFloatv (GL_PROJECTION_MATRIX, &matrix[0][0]);
 | |
| 
 | |
| 	for (i=0 ; i<3 ; i++)
 | |
| 	{
 | |
| 		vright[i] = matrix[i][0];
 | |
| 		vup[i] = matrix[i][1];
 | |
| 		vpn[i] = matrix[i][2];
 | |
| 	}
 | |
| 
 | |
| 	VectorNormalize (vright);
 | |
| 	VectorNormalize (vup);
 | |
| 	VectorNormalize (vpn);
 | |
| }
 | |
| 
 | |
| void Draw (void)
 | |
| {
 | |
| 	float	screenaspect;
 | |
| 	float	yfov;
 | |
| 
 | |
| 	//glClearColor (0.5, 0.5, 0.5, 0);
 | |
| 	glClearColor(0.0, 0.0, 0.0, 0);  // Black Clearing YWB
 | |
| 	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 | |
| 
 | |
| 	//
 | |
| 	// set up viewpoint
 | |
| 	//
 | |
| 	glMatrixMode(GL_PROJECTION);
 | |
|     glLoadIdentity ();
 | |
| 
 | |
|     screenaspect = (float)width/height;
 | |
| 	yfov = 2*atan((float)height/width)*180/M_PI;
 | |
|     gluPerspective (yfov,  screenaspect,  6,  20000);
 | |
| 
 | |
|     glRotatef (-90,  1, 0, 0);	    // put Z going up
 | |
|     glRotatef (90,  0, 0, 1);	    // put Z going up
 | |
|     glRotatef (angles[0],  0, 1, 0);
 | |
|     glRotatef (-angles[1],  0, 0, 1);
 | |
|     glTranslatef (-origin[0],  -origin[1],  -origin[2]);
 | |
| 
 | |
| 	Cam_BuildMatrix ();
 | |
| 
 | |
| 	//
 | |
| 	// set drawing parms
 | |
| 	//
 | |
| 	glShadeModel (GL_SMOOTH);
 | |
| 
 | |
| 	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
 | |
| 	glFrontFace(GL_CW);  // YWB   Carmack goes backward
 | |
| 	glCullFace(GL_BACK); // Cull backfaces (qcsg used to spit out two sides, doesn't for -glview now)
 | |
| 	glEnable(GL_CULL_FACE); // Enable face culling, just in case...
 | |
| 	glDisable(GL_TEXTURE_2D);
 | |
| 
 | |
| 	// Blending function if enabled..
 | |
| 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 | |
| 
 | |
| 	if (g_UseBlending)
 | |
| 	{
 | |
| 		glEnable(GL_BLEND);// YWB TESTING
 | |
| 		glDisable(GL_DEPTH_TEST);
 | |
| 		glDisable(GL_CULL_FACE); // Enable face culling, just in case...
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		glDisable(GL_BLEND);
 | |
| 		glEnable(GL_DEPTH_TEST);
 | |
| 	}
 | |
| 	glDepthFunc (GL_LEQUAL);
 | |
| 
 | |
| 	if( g_bDisp )
 | |
| 	{
 | |
| 		DrawDisplacementData();
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		//
 | |
| 		// draw the list
 | |
| 		//
 | |
| 		if (g_bShowList1)
 | |
| 			glCallList (1);
 | |
| 		
 | |
| 		if (g_bReadPortals)
 | |
| 		{
 | |
| 			if (g_bNoDepthPortals)
 | |
| 				glDisable(GL_DEPTH_TEST);
 | |
| 			glDisable(GL_CULL_FACE); // Disable face culling
 | |
| 			if (g_bShowList2)
 | |
| 				glCallList(2);
 | |
| 		};
 | |
| 		
 | |
| 		if (g_bShowLines)
 | |
| 			glCallList(3);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void ReadPolyFileType(const char *name, int nList, BOOL drawLines)
 | |
| {
 | |
| 	FILE	*f;
 | |
| 	int		i, j, numverts;
 | |
| 	float	v[8];
 | |
| 	int		c;
 | |
| 	int		r;
 | |
| 	float divisor;
 | |
| 
 | |
| 	f = fopen (name, "rt");
 | |
| 	if (!f)
 | |
| 		Error ("Couldn't open %s", name);
 | |
| 
 | |
| 	if (g_bReadPortals)
 | |
| 		divisor = 2.0f;
 | |
| 	else 
 | |
| 		divisor = 1.0f;
 | |
| 
 | |
| 	c = 0;
 | |
| 	glNewList (nList, GL_COMPILE);
 | |
| 	
 | |
| 	for (i = 0; i < 3; i++)  // Find the center point so we can put the viewer there by default
 | |
| 		g_Center[i] = 0.0f;
 | |
| 
 | |
| 	if (drawLines)           // Slight hilite
 | |
| 		glLineWidth(1.5);
 | |
| 
 | |
| 	while (1)
 | |
| 	{
 | |
| 		r = fscanf( f, "%i\n", &numverts);
 | |
| 		if (!r || r == EOF)
 | |
| 			break;
 | |
| 
 | |
| 		if ( c > 65534*8)
 | |
| 			break;
 | |
| 
 | |
| 		if (drawLines || numverts == 2)
 | |
| 			glBegin(GL_LINE_LOOP);
 | |
| 		else
 | |
| 			glBegin (GL_POLYGON);
 | |
| 
 | |
| 		for (i=0 ; i<numverts ; i++)
 | |
| 		{
 | |
| 			r = fscanf( f, "%f %f %f %f %f %f\n", &v[0], &v[1],
 | |
| 				&v[2], &v[3], &v[4], &v[5]);
 | |
| 
 | |
| 			/*
 | |
| 			if (!(fabs( v[0] ) < 32768.0&& fabs( v[1] ) < 32768.0 && fabs( v[2] ) < 32768.0 ) )
 | |
| 				Error( "Out of range data\n");
 | |
| 			*/
 | |
| 
 | |
| 			/*
 | |
| 			if (v[3] <= 0.1 && v[4] <= 0.1 && v[5] <= 0.1 )
 | |
| 				continue;
 | |
| 			*/
 | |
| 
 | |
| 			if (drawLines)  // YELLOW OUTLINES
 | |
| 				glColor4f(1.0, 1.0, 0.0, 0.5);
 | |
| 			else
 | |
| 			{
 | |
| 				if (g_bReadPortals)  // Gray scale it, leave portals blue
 | |
| 				{
 | |
| 					if (fabs(fabs(v[5]) - 1.0f) < 0.01)   // Is this a detail brush (color 0,0,1 blue)
 | |
| 					{
 | |
| 						glColor4f (v[3],v[4],v[5],0.5);   
 | |
| 					}	
 | |
| 					else                                  // Normal brush, gray scale it...
 | |
| 					{
 | |
| 						v[3] += v[4] + v[5];
 | |
| 						v[3]/= 3.0f;
 | |
| 						glColor4f (v[3]/divisor, v[3]/divisor, v[3]/divisor, 0.6);   
 | |
| 					}
 | |
| 				}
 | |
| 				else 
 | |
| 				{
 | |
| 					v[3] = pow( v[3], (float)(1.0 / 2.2) );
 | |
| 					v[4] = pow( v[4], (float)(1.0 / 2.2) );
 | |
| 					v[5] = pow( v[5], (float)(1.0 / 2.2) );
 | |
| 
 | |
| 					glColor4f (v[3]/divisor, v[4]/divisor, 	v[5]/divisor, 0.6);   // divisor is one, bright colors
 | |
| 				};
 | |
| 			};
 | |
| 			glVertex3f (v[0], v[1], v[2]);
 | |
| 
 | |
| 			for (j = 0; j < 3; j++)
 | |
| 			{
 | |
| 				g_Center[j] += v[j];
 | |
| 			}
 | |
| 	
 | |
| 			g_nTotalPoints++;
 | |
| 		}
 | |
| 		glEnd ();
 | |
| 		c++;
 | |
| 	}
 | |
| 
 | |
| 	if (f)
 | |
| 		fclose(f);
 | |
| 
 | |
| 	glEndList ();
 | |
| 
 | |
| 	if (g_nTotalPoints > 0)  // Avoid division by zero
 | |
| 	{
 | |
| 		for (i = 0; i < 3; i++)
 | |
| 		{
 | |
| 			g_Center[i] = g_Center[i]/(float)g_nTotalPoints; // Calculate center...
 | |
| 			origin[i] = g_Center[i];
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| #if BENCHMARK_PHY
 | |
| #define NUM_COLLISION_TESTS 2500
 | |
| #include "gametrace.h"
 | |
| #include "fmtstr.h"
 | |
| 
 | |
| 
 | |
| struct testlist_t
 | |
| {
 | |
| 	Vector start;
 | |
| 	Vector end;
 | |
| 	Vector normal;
 | |
| 	bool hit;
 | |
| };
 | |
| 
 | |
| const float baselineTotal = 120.16f;
 | |
| const float baselineRay = 28.25f;
 | |
| const float baselineBox = 91.91f;
 | |
| #define IMPROVEMENT_FACTOR(x,baseline) (baseline/(x))
 | |
| #define IMPROVEMENT_PERCENT(x,baseline) (((baseline-(x)) / baseline) * 100.0f)
 | |
| 
 | |
| testlist_t g_Traces[NUM_COLLISION_TESTS];
 | |
| void Benchmark_PHY( const CPhysCollide *pCollide )
 | |
| {
 | |
| 	int i;
 | |
| 	Msg( "Testing collision system\n" );
 | |
| 	Vector start = vec3_origin;
 | |
| 	static Vector *targets = NULL;
 | |
| 	static bool first = true;
 | |
| 	static float test[2] = {1,1};
 | |
| 	if ( first )
 | |
| 	{
 | |
| 		float radius = 0;
 | |
| 		float theta = 0;
 | |
| 		float phi = 0;
 | |
| 		for ( int i = 0; i < NUM_COLLISION_TESTS; i++ )
 | |
| 		{
 | |
| 			radius += NUM_COLLISION_TESTS * 123.123f;
 | |
| 			radius = fabs(fmod(radius, 128));
 | |
| 			theta += NUM_COLLISION_TESTS * 0.76f;
 | |
| 			theta = fabs(fmod(theta, DEG2RAD(360)));
 | |
| 			phi += NUM_COLLISION_TESTS * 0.16666666f;
 | |
| 			phi = fabs(fmod(phi, DEG2RAD(180)));
 | |
| 
 | |
| 			float st, ct, sp, cp;
 | |
| 			SinCos( theta, &st, &ct );
 | |
| 			SinCos( phi, &sp, &cp );
 | |
| 			st = sin(theta);
 | |
| 			ct = cos(theta);
 | |
| 			sp = sin(phi);
 | |
| 			cp = cos(phi);
 | |
| 
 | |
| 			g_Traces[i].start.x = radius * ct * sp;
 | |
| 			g_Traces[i].start.y = radius * st * sp;
 | |
| 			g_Traces[i].start.z = radius * cp;
 | |
| 		}
 | |
| 		first = false;
 | |
| 	}
 | |
| 
 | |
| 	float duration = 0;
 | |
| 	Vector size[2];
 | |
| 	size[0].Init(0,0,0);
 | |
| 	size[1].Init(16,16,16);
 | |
| 	unsigned int dots = 0;
 | |
| 
 | |
| #if VPROF_LEVEL > 0 
 | |
| 	g_VProfCurrentProfile.Reset();
 | |
| 	g_VProfCurrentProfile.ResetPeaks();
 | |
| 	g_VProfCurrentProfile.Start();
 | |
| #endif
 | |
| 	unsigned int hitCount = 0;
 | |
| 	double startTime = Plat_FloatTime();
 | |
| 	trace_t tr;
 | |
| 	for ( i = 0; i < NUM_COLLISION_TESTS; i++ )
 | |
| 	{
 | |
| 		physcollision->TraceBox( g_Traces[i].start, start, -size[0], size[0], pCollide, vec3_origin, vec3_angle, &tr );
 | |
| 		if ( tr.DidHit() )
 | |
| 		{
 | |
| 			g_Traces[i].end = tr.endpos;
 | |
| 			g_Traces[i].normal = tr.plane.normal;
 | |
| 			g_Traces[i].hit = true;
 | |
| 			hitCount++;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			g_Traces[i].hit = false;
 | |
| 		}
 | |
| 	}
 | |
| 	for ( i = 0; i < NUM_COLLISION_TESTS; i++ )
 | |
| 	{
 | |
| 		physcollision->TraceBox( g_Traces[i].start, start, -size[1], size[1], pCollide, vec3_origin, vec3_angle, &tr );
 | |
| 	}
 | |
| 	duration = Plat_FloatTime() - startTime;
 | |
| 	{
 | |
| 	unsigned int msSupp = physcollision->ReadStat( 100 );
 | |
| 	unsigned int msGJK = physcollision->ReadStat( 101 );
 | |
| 	unsigned int msMesh = physcollision->ReadStat( 102 );
 | |
| 	CFmtStr str("%d ms total %d ms gjk %d mesh solve\n", msSupp, msGJK, msMesh );
 | |
| 	OutputDebugStr( str.Access() );
 | |
| 	}
 | |
| 
 | |
| #if VPROF_LEVEL > 0 
 | |
| 	g_VProfCurrentProfile.MarkFrame();
 | |
| 	g_VProfCurrentProfile.Stop();
 | |
| 	g_VProfCurrentProfile.Reset();
 | |
| 	g_VProfCurrentProfile.ResetPeaks();
 | |
| 	g_VProfCurrentProfile.Start();
 | |
| #endif
 | |
| 	hitCount = 0;
 | |
| 	startTime = Plat_FloatTime();
 | |
| 	for ( i = 0; i < NUM_COLLISION_TESTS; i++ )
 | |
| 	{
 | |
| 		physcollision->TraceBox( g_Traces[i].start, start, -size[0], size[0], pCollide, vec3_origin, vec3_angle, &tr );
 | |
| 		if ( tr.DidHit() )
 | |
| 		{
 | |
| 			g_Traces[i].end = tr.endpos;
 | |
| 			g_Traces[i].normal = tr.plane.normal;
 | |
| 			g_Traces[i].hit = true;
 | |
| 			hitCount++;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			g_Traces[i].hit = false;
 | |
| 		}
 | |
| #if VPROF_LEVEL > 0 
 | |
| 		g_VProfCurrentProfile.MarkFrame();
 | |
| #endif
 | |
| 	}
 | |
| 	double midTime = Plat_FloatTime();
 | |
| 	for ( i = 0; i < NUM_COLLISION_TESTS; i++ )
 | |
| 	{
 | |
| 		physcollision->TraceBox( g_Traces[i].start, start, -size[1], size[1], pCollide, vec3_origin, vec3_angle, &tr );
 | |
| #if VPROF_LEVEL > 0 
 | |
| 		g_VProfCurrentProfile.MarkFrame();
 | |
| #endif
 | |
| 	}
 | |
| 	double endTime = Plat_FloatTime();
 | |
| 	duration = endTime - startTime;
 | |
| 	{
 | |
| 	CFmtStr str("%d collisions in %.2f ms [%.2f X] %d hits\n", NUM_COLLISION_TESTS, duration*1000, IMPROVEMENT_FACTOR(duration*1000.0f, baselineTotal), hitCount );
 | |
| 	OutputDebugStr( str.Access() );
 | |
| 	}
 | |
| 	{
 | |
| 		float rayTime = (midTime - startTime) * 1000.0f;
 | |
| 		float boxTime = (endTime - midTime)*1000.0f;
 | |
| 		CFmtStr str("%.2f ms rays [%.2f X] %.2f ms boxes [%.2f X]\n", rayTime, IMPROVEMENT_FACTOR(rayTime, baselineRay), boxTime, IMPROVEMENT_FACTOR(boxTime, baselineBox));
 | |
| 		OutputDebugStr( str.Access() );
 | |
| 	}
 | |
| 
 | |
| 	{
 | |
| 	unsigned int msSupp = physcollision->ReadStat( 100 );
 | |
| 	unsigned int msGJK = physcollision->ReadStat( 101 );
 | |
| 	unsigned int msMesh = physcollision->ReadStat( 102 );
 | |
| 	CFmtStr str("%d ms total %d ms gjk %d mesh solve\n", msSupp, msGJK, msMesh );
 | |
| 	OutputDebugStr( str.Access() );
 | |
| 	}
 | |
| #if VPROF_LEVEL > 0 
 | |
| 	g_VProfCurrentProfile.Stop();
 | |
| 	g_VProfCurrentProfile.OutputReport( VPRT_FULL & ~VPRT_HIERARCHY, NULL );
 | |
| #endif
 | |
| 
 | |
| 	// draw the traces in yellow
 | |
| 	glColor3f( 1.0f, 1.0f, 0.0f );
 | |
| 	glBegin( GL_LINES );
 | |
| 	for ( int i = 0; i < NUM_COLLISION_TESTS; i++ )
 | |
| 	{
 | |
| 		if ( !g_Traces[i].hit )
 | |
| 			continue;
 | |
| 		glVertex3fv( g_Traces[i].end.Base() );
 | |
| 		Vector tmp = g_Traces[i].end + g_Traces[i].normal * 10.0f;
 | |
| 		glVertex3fv( tmp.Base() );
 | |
| 	}
 | |
| 	glEnd();
 | |
| }
 | |
| #endif
 | |
| 
 | |
| struct phyviewparams_t
 | |
| { 
 | |
| 	Vector mins;
 | |
| 	Vector maxs;
 | |
| 	Vector offset;
 | |
| 	QAngle angles;
 | |
| 	int outputType;
 | |
| 	
 | |
| 	void Defaults()
 | |
| 	{
 | |
| 		ClearBounds(mins, maxs);
 | |
| 		offset.Init();
 | |
| 		outputType = GL_POLYGON;
 | |
| 		angles.Init();
 | |
| 	}
 | |
| };
 | |
| 
 | |
| 
 | |
| void AddVCollideToList( phyheader_t &header, vcollide_t &collide, phyviewparams_t ¶ms )
 | |
| {
 | |
| 	matrix3x4_t xform;
 | |
| 	AngleMatrix( params.angles, params.offset, xform );
 | |
| 	ClearBounds( params.mins, params.maxs );
 | |
| 	for ( int i = 0; i < header.solidCount; i++ )
 | |
| 	{
 | |
| 		ICollisionQuery *pQuery = physcollision->CreateQueryModel( collide.solids[i] );
 | |
| 		for ( int j = 0; j < pQuery->ConvexCount(); j++ )
 | |
| 		{
 | |
| 			for ( int k = 0; k < pQuery->TriangleCount(j); k++ )
 | |
| 			{
 | |
| 				Vector verts[3];
 | |
| 				pQuery->GetTriangleVerts( j, k, verts );
 | |
| 				Vector v0,v1,v2;
 | |
| 				VectorTransform( verts[0], xform, v0 );
 | |
| 				VectorTransform( verts[1], xform, v1 );
 | |
| 				VectorTransform( verts[2], xform, v2 );
 | |
| 				AddPointToBounds( v0, params.mins, params.maxs );
 | |
| 				AddPointToBounds( v1, params.mins, params.maxs );
 | |
| 				AddPointToBounds( v2, params.mins, params.maxs );
 | |
| 
 | |
| 				glBegin(params.outputType);
 | |
| 				glColor3ub( 255, 0, 0 );
 | |
| 				glVertex3fv( v0.Base() );
 | |
| 				glColor3ub( 0, 255, 0 );
 | |
| 				glVertex3fv( v1.Base() );
 | |
| 				glColor3ub( 0, 0, 255 );
 | |
| 				glVertex3fv( v2.Base() );
 | |
| 				glEnd();
 | |
| 			}
 | |
| 		}
 | |
| 		physcollision->DestroyQueryModel( pQuery );
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void GL_DrawLine( const Vector &start, const Vector &dir, float length, int r, int g, int b )
 | |
| {
 | |
| 	Vector end = start + (dir*length);
 | |
| 	glBegin( GL_LINES );
 | |
| 	glColor3ub(r,g,b);
 | |
| 	glVertex3fv( start.Base() );
 | |
| 	glVertex3fv( end.Base() );
 | |
| 	glEnd();
 | |
| }
 | |
| 
 | |
| void GL_DrawBox( Vector origin, float size, int r, int g, int b )
 | |
| {
 | |
| 	Vector mins = origin - Vector(size,size,size);
 | |
| 	Vector maxs = origin + Vector(size,size,size);
 | |
| 	const float *v[2] = {mins.Base(), maxs.Base()};
 | |
| 
 | |
| 	Vector start, end;
 | |
| 	{
 | |
| 		for ( int i = 0; i < 3; i++ )
 | |
| 		{
 | |
| 			int a0 = i;
 | |
| 			int a1 = (i+1)%3;
 | |
| 			int a2 = (i+2)%3;
 | |
| 			for ( int j = 0; j < 2; j++ )
 | |
| 			{
 | |
| 				for ( int k = 0; k < 2; k++ )
 | |
| 				{
 | |
| 					start[a0] = v[0][a0];
 | |
| 					end[a0] = v[1][a0];
 | |
| 					start[a1] = v[j][a1];
 | |
| 					end[a1] = v[j][a1];
 | |
| 					start[a2] = v[k][a2];
 | |
| 					end[a2] = v[k][a2];
 | |
| 					GL_DrawLine( start, end-start, 1, r, g, b );
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	for ( int axis = 0; axis < 3; axis++ )
 | |
| 	{
 | |
| 		int a0 = axis;
 | |
| 		int a1 = (axis+1)%3;
 | |
| 		int a2 = (axis+2)%3;
 | |
| 		start[a0] = v[0][a0];
 | |
| 		end[a0] = v[1][a0];
 | |
| 		start[a1] = 0.5f *(v[0][a1]+v[1][a1]);
 | |
| 		end[a1] = 0.5f *(v[0][a1]+v[1][a1]);
 | |
| 		start[a2] = 0.5f *(v[0][a2]+v[1][a2]);
 | |
| 		end[a2] = 0.5f *(v[0][a2]+v[1][a2]);
 | |
| 		GL_DrawLine( start, end-start, 1, r, g, b );
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| void ReadPHYFile(const char *name, phyviewparams_t ¶ms )
 | |
| {
 | |
| 	FILE *fp = fopen (name, "rb");
 | |
| 	if (!fp)
 | |
| 		Error ("Couldn't open %s", name);
 | |
| 
 | |
| 	phyheader_t header;
 | |
| 	
 | |
| 	fread( &header, sizeof(header), 1, fp );
 | |
| 	if ( header.size != sizeof(header) || header.solidCount <= 0 )
 | |
| 		return;
 | |
| 
 | |
| 	int pos = ftell( fp );
 | |
| 	fseek( fp, 0, SEEK_END );
 | |
| 	int fileSize = ftell(fp) - pos;
 | |
| 	fseek( fp, pos, SEEK_SET );
 | |
| 
 | |
| 	char *buf = (char *)_alloca( fileSize );
 | |
| 	fread( buf, fileSize, 1, fp );
 | |
| 	fclose( fp );
 | |
| 
 | |
| 	vcollide_t collide;
 | |
| 	physcollision->VCollideLoad( &collide, header.solidCount, (const char *)buf, fileSize );
 | |
| #if 0
 | |
| 	Vector start0( -3859.1199, -2050.8674, 64.031250 );
 | |
| 	Vector end0(-3859.2246, -2051.2817, 64.031250 );
 | |
| 	Vector modelPosition(-3840,-2068.0000, 82.889099);
 | |
| 	QAngle modelAngles(0,90,0);
 | |
| 
 | |
| 	{
 | |
| 		Ray_t ray;
 | |
| 		ray.Init( start0, end0, Vector(-16,-16,0), Vector(16,16,72));
 | |
| 		trace_t tr;
 | |
| 		physcollision->TraceBox( ray, collide.solids[0], modelPosition, modelAngles, &tr );
 | |
| 		Assert(!tr.startsolid);
 | |
| 		if ( tr.DidHit() )
 | |
| 		{
 | |
| 			Ray_t ray2;
 | |
| 			ray2.Init( tr.endpos, tr.endpos, Vector(-16,-16,0), Vector(16,16,72));
 | |
| 			trace_t tr2;
 | |
| 			physcollision->TraceBox( ray2, collide.solids[0], modelPosition, modelAngles, &tr2 );
 | |
|  			Assert(!tr2.startsolid);
 | |
| 		}
 | |
| 	}
 | |
| #endif
 | |
| #if BENCHMARK_PHY
 | |
| 	Benchmark_PHY( collide.solids[0] );
 | |
| #endif
 | |
| 	AddVCollideToList( header, collide, params );
 | |
| }
 | |
| 
 | |
| void ReadPolyFile (const char *name)
 | |
| {
 | |
| 	char ext[4];
 | |
| 	Q_ExtractFileExtension( name, ext, 4 );
 | |
| 
 | |
| 	bool isPHY = !Q_stricmp( ext, "phy" );
 | |
| 	if ( isPHY )
 | |
| 	{
 | |
| 		CreateInterfaceFn physicsFactory = GetPhysicsFactory();
 | |
| 		physcollision = (IPhysicsCollision *)physicsFactory( VPHYSICS_COLLISION_INTERFACE_VERSION, NULL );
 | |
| 		if ( physcollision )
 | |
| 		{
 | |
| 			phyviewparams_t params;
 | |
| 			params.Defaults();
 | |
| 			glNewList (1, GL_COMPILE);
 | |
| 			ReadPHYFile( name, params );
 | |
| 			Vector tmp = (params.mins + params.maxs) * 0.5;
 | |
| 			tmp.CopyToArray(origin);
 | |
| 			glEndList ();
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		// Read in polys...
 | |
| 		ReadPolyFileType(name, 1, false);
 | |
| 
 | |
| 		// Make list 3 just the lines... so we can draw outlines
 | |
| 		ReadPolyFileType(name, 3, true);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void ReadPortalFile (char *name)
 | |
| {
 | |
| 	FILE	*f;
 | |
| 	int		i, numverts;
 | |
| 	float	v[8];
 | |
| 	int		c;
 | |
| 	int		r;
 | |
| 
 | |
| 	// For Portal type reading...
 | |
| 	char szDummy[80];
 | |
| 	int nNumLeafs;
 | |
| 	int nNumPortals;
 | |
| 	int nLeafIndex[2];
 | |
| 
 | |
| 	f = fopen (name, "r");
 | |
| 	if (!f)
 | |
| 		Error ("Couldn't open %s", name);
 | |
| 
 | |
| 	c = 0;
 | |
| 	
 | |
| 	glNewList (2, GL_COMPILE);
 | |
| 
 | |
| 	// Read in header
 | |
| 	fscanf(f, "%79s\n", szDummy);
 | |
| 	fscanf(f, "%i\n", &nNumLeafs);
 | |
| 	fscanf(f, "%i\n", &nNumPortals);
 | |
| 
 | |
| 	glLineWidth(1.5);
 | |
| 
 | |
| 	while (1)
 | |
| 	{
 | |
| 		r = fscanf(f, "%i %i %i ", &numverts, &nLeafIndex[0], &nLeafIndex[1]);
 | |
| 		if (!r || r == EOF)
 | |
| 			break;
 | |
| 
 | |
| 		glBegin(GL_LINE_LOOP);
 | |
| 		for (i=0 ; i<numverts ; i++)
 | |
| 		{
 | |
| 			r = fscanf (f, "(%f %f %f )\n", &v[0], &v[1],
 | |
| 				&v[2]);
 | |
| 			if (!r || (r != 3) || r == EOF)
 | |
| 				break;
 | |
| 
 | |
| 			if ( c == g_nPortalHighlight || nLeafIndex[0] == g_nLeafHighlight || nLeafIndex[1] == g_nLeafHighlight )
 | |
| 			{
 | |
| 				glColor4f (1.0, 0.0, 0.0, 1.0);   
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				glColor4f (1.0f, 1.0f, 1.0f, 1.0f);   // WHITE portals
 | |
| 			}
 | |
| 			glVertex3f (v[0], v[1], v[2]);
 | |
| 		}
 | |
| 
 | |
| 		glEnd ();
 | |
| 		c++;
 | |
| 	}
 | |
| 
 | |
| 	if (f)
 | |
| 		fclose(f);
 | |
| 
 | |
| 	glEndList ();
 | |
| }
 | |
| 
 | |
| #define MAX_DISP_COUNT	4096
 | |
| static Vector dispPoints[MAX_DISP_COUNT];
 | |
| static Vector dispNormals[MAX_DISP_COUNT];
 | |
| static int dispPointCount = 0;
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| //-----------------------------------------------------------------------------
 | |
| BOOL ReadDisplacementFile( const char *filename )
 | |
| {
 | |
| 	FILE	*pFile;
 | |
| 	int		fileCount;
 | |
| 
 | |
| 	//
 | |
| 	// open the file
 | |
| 	//
 | |
| 	pFile = fopen( filename, "r" );
 | |
| 	if( !pFile )
 | |
| 		Error( "Couldn't open %s", filename );
 | |
| 
 | |
| 	//
 | |
| 	// read data in file
 | |
| 	//
 | |
| 	while( 1 )
 | |
| 	{
 | |
| 		// overflow test
 | |
| 		if( dispPointCount >= MAX_DISP_COUNT )
 | |
| 			break;
 | |
| 
 | |
| 		fileCount = fscanf( pFile, "%f %f %f %f %f %f",
 | |
| 			                &dispPoints[dispPointCount][0], &dispPoints[dispPointCount][1], &dispPoints[dispPointCount][2],
 | |
| 							&dispNormals[dispPointCount][0], &dispNormals[dispPointCount][1], &dispNormals[dispPointCount][2] );
 | |
| 		dispPointCount++;
 | |
| 
 | |
| 		// end of file check
 | |
| 		if( !fileCount || ( fileCount == EOF ) )
 | |
| 			break;
 | |
| 	}
 | |
| 
 | |
| 	fclose( pFile );
 | |
| 
 | |
| 	return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| //-----------------------------------------------------------------------------
 | |
| void DrawDisplacementData( void )
 | |
| {
 | |
| 	int		i, j;
 | |
| 	int		width, halfCount;
 | |
| 
 | |
| 	GLUquadricObj *pObject = gluNewQuadric();
 | |
| 
 | |
| 	glEnable( GL_DEPTH_TEST );
 | |
| 
 | |
| 	for( i = 0; i < dispPointCount; i++ )
 | |
| 	{
 | |
| 		// draw a sphere where the point is (in red)
 | |
| 		glColor3f( 1.0f, 0.0f, 0.0f );
 | |
| 		glPushMatrix();
 | |
| 		glTranslatef( dispPoints[i][0], dispPoints[i][1], dispPoints[i][2] );
 | |
| 		gluSphere( pObject, 5, 5, 5 );
 | |
| 		glPopMatrix();
 | |
| 
 | |
| 		// draw the normal (in yellow)
 | |
| 		glColor3f( 1.0f, 1.0f, 0.0f );
 | |
| 		glBegin( GL_LINES );
 | |
| 		glVertex3f( dispPoints[i][0], dispPoints[i][1], dispPoints[i][2] );
 | |
| 		glVertex3f( dispPoints[i][0] + ( dispNormals[i][0] * 50.0f ), dispPoints[i][1] + ( dispNormals[i][1] * 50.0f ), dispPoints[i][2] + ( dispNormals[i][2] * 50.0f ) );
 | |
| 		glEnd();
 | |
| 	}
 | |
| 
 | |
| 	halfCount = dispPointCount / 2;
 | |
| 
 | |
| 	width = sqrt( (float)halfCount );
 | |
| 
 | |
| 	glDisable( GL_CULL_FACE );
 | |
| 
 | |
| 	glColor3f( 0.0f, 0.0f, 1.0f );
 | |
| 	for( i = 0; i < width - 1; i++ )
 | |
| 	{
 | |
| 		for( j = 0; j < width - 1; j++ )
 | |
| 		{
 | |
| 			glBegin( GL_POLYGON );
 | |
| 			glVertex3f( dispPoints[i*width+j][0], dispPoints[i*width+j][1], dispPoints[i*width+j][2] );
 | |
| 			glVertex3f( dispPoints[(i+1)*width+j][0], dispPoints[(i+1)*width+j][1], dispPoints[(i+1)*width+j][2] );
 | |
| 			glVertex3f( dispPoints[(i+1)*width+(j+1)][0], dispPoints[(i+1)*width+(j+1)][1], dispPoints[(i+1)*width+(j+1)][2] );
 | |
| 			glVertex3f( dispPoints[i*width+(j+1)][0], dispPoints[i*width+(j+1)][1], dispPoints[i*width+(j+1)][2] );
 | |
| 			glEnd();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| #if 0
 | |
| 	for( i = 0; i < width - 1; i++ )
 | |
| 	{
 | |
| 		for( j = 0; j < width - 1; j++ )
 | |
| 		{
 | |
| 			glBegin( GL_POLYGON );
 | |
| 			glVertex3f( dispPoints[halfCount+(i*width+j)][0], dispPoints[halfCount+(i*width+j)][1], dispPoints[halfCount+(i*width+j)][2] );
 | |
| 			glVertex3f( dispPoints[halfCount+((i+1)*width+j)][0], dispPoints[halfCount+(i+1)*width+j][1], dispPoints[halfCount+((i+1)*width+j)][2] );
 | |
| 			glVertex3f( dispPoints[halfCount+((i+1)*width+(j+1))][0], dispPoints[halfCount+(i+1)*width+(j+1)][1], dispPoints[halfCount+((i+1)*width+(j+1))][2] );
 | |
| 			glVertex3f( dispPoints[halfCount+(i*width+(j+1))][0], dispPoints[halfCount+(i*width+(j+1))][1], dispPoints[halfCount+(i*width+(j+1))][2] );
 | |
| 			glEnd();
 | |
| 		}
 | |
| 	}
 | |
| #endif
 | |
| 
 | |
| 	glColor3f( 0.0f, 1.0f, 0.0f );
 | |
| 	for( i = 0; i < width - 1; i++ )
 | |
| 	{
 | |
| 		for( j = 0; j < width - 1; j++ )
 | |
| 		{
 | |
| 			glBegin( GL_POLYGON );
 | |
| 			glVertex3f( dispPoints[i*width+j][0] + ( dispNormals[i*width+j][0] * 150.0f ), 
 | |
| 				        dispPoints[i*width+j][1] + ( dispNormals[i*width+j][1] * 150.0f ), 
 | |
| 						dispPoints[i*width+j][2] + ( dispNormals[i*width+j][2] * 150.0f ) );
 | |
| 
 | |
| 			glVertex3f( dispPoints[(i+1)*width+j][0] + ( dispNormals[(i+1)*width+j][0] * 150.0f ), 
 | |
| 				        dispPoints[(i+1)*width+j][1] + ( dispNormals[(i+1)*width+j][1] * 150.0f ), 
 | |
| 						dispPoints[(i+1)*width+j][2] + ( dispNormals[(i+1)*width+j][2] * 150.0f ) );
 | |
| 
 | |
| 			glVertex3f( dispPoints[(i+1)*width+(j+1)][0] + ( dispNormals[(i+1)*width+(j+1)][0] * 150.0f ), 
 | |
| 				        dispPoints[(i+1)*width+(j+1)][1] + ( dispNormals[(i+1)*width+(j+1)][1] * 150.0f ), 
 | |
| 						dispPoints[(i+1)*width+(j+1)][2] + ( dispNormals[(i+1)*width+(j+1)][2] * 150.0f ) );
 | |
| 
 | |
| 			glVertex3f( dispPoints[i*width+(j+1)][0] + ( dispNormals[i*width+(j+1)][0] * 150.0f ), 
 | |
| 				        dispPoints[i*width+(j+1)][1] + ( dispNormals[i*width+(j+1)][1] * 150.0f ), 
 | |
| 						dispPoints[i*width+(j+1)][2] + ( dispNormals[i*width+(j+1)][2] * 150.0f ) );
 | |
| 			glEnd();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	glDisable( GL_DEPTH_TEST );
 | |
| 
 | |
| 	glColor3f( 0.0f, 0.0f, 1.0f );
 | |
| 	for( i = 0; i < width - 1; i++ )
 | |
| 	{
 | |
| 		for( j = 0; j < width - 1; j++ )
 | |
| 		{
 | |
| 			glBegin( GL_LINE_LOOP );
 | |
| 			glVertex3f( dispPoints[i*width+j][0] + ( dispNormals[i*width+j][0] * 150.0f ), 
 | |
| 				        dispPoints[i*width+j][1] + ( dispNormals[i*width+j][1] * 150.0f ), 
 | |
| 						dispPoints[i*width+j][2] + ( dispNormals[i*width+j][2] * 150.0f ) );
 | |
| 
 | |
| 			glVertex3f( dispPoints[(i+1)*width+j][0] + ( dispNormals[(i+1)*width+j][0] * 150.0f ), 
 | |
| 				        dispPoints[(i+1)*width+j][1] + ( dispNormals[(i+1)*width+j][1] * 150.0f ), 
 | |
| 						dispPoints[(i+1)*width+j][2] + ( dispNormals[(i+1)*width+j][2] * 150.0f ) );
 | |
| 
 | |
| 			glVertex3f( dispPoints[(i+1)*width+(j+1)][0] + ( dispNormals[(i+1)*width+(j+1)][0] * 150.0f ), 
 | |
| 				        dispPoints[(i+1)*width+(j+1)][1] + ( dispNormals[(i+1)*width+(j+1)][1] * 150.0f ), 
 | |
| 						dispPoints[(i+1)*width+(j+1)][2] + ( dispNormals[(i+1)*width+(j+1)][2] * 150.0f ) );
 | |
| 
 | |
| 			glVertex3f( dispPoints[i*width+(j+1)][0] + ( dispNormals[i*width+(j+1)][0] * 150.0f ), 
 | |
| 				        dispPoints[i*width+(j+1)][1] + ( dispNormals[i*width+(j+1)][1] * 150.0f ), 
 | |
| 						dispPoints[i*width+(j+1)][2] + ( dispNormals[i*width+(j+1)][2] * 150.0f ) );
 | |
| 			glEnd();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	gluDeleteQuadric( pObject );
 | |
| }
 | |
| 
 | |
| 
 | |
| //=====================================================================
 | |
| 
 | |
| BOOL bSetupPixelFormat(HDC hDC)
 | |
| {
 | |
|     static PIXELFORMATDESCRIPTOR pfd = {
 | |
| 	sizeof(PIXELFORMATDESCRIPTOR),	// size of this pfd
 | |
| 	1,				// version number
 | |
| 	PFD_DRAW_TO_WINDOW |		// support window
 | |
| 	  PFD_SUPPORT_OPENGL |		// support OpenGL
 | |
| 	  PFD_DOUBLEBUFFER,		// double buffered
 | |
| 	PFD_TYPE_RGBA,			// RGBA type
 | |
| 	24,				// 24-bit color depth
 | |
| 	0, 0, 0, 0, 0, 0,		// color bits ignored
 | |
| 	0,				// no alpha buffer
 | |
| 	0,				// shift bit ignored
 | |
| 	0,				// no accumulation buffer
 | |
| 	0, 0, 0, 0, 			// accum bits ignored
 | |
| 	32,				// 32-bit z-buffer	
 | |
| 	0,				// no stencil buffer
 | |
| 	0,				// no auxiliary buffer
 | |
| 	PFD_MAIN_PLANE,			// main layer
 | |
| 	0,				// reserved
 | |
| 	0, 0, 0				// layer masks ignored
 | |
|     };
 | |
| 
 | |
|     int pixelformat = 0;
 | |
| 
 | |
|     if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 )
 | |
|         Error ("ChoosePixelFormat failed");
 | |
| 
 | |
|     if (!SetPixelFormat(hDC, pixelformat, &pfd))
 | |
|         Error ("SetPixelFormat failed");
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| /*
 | |
| ============
 | |
| CameraWndProc
 | |
| ============
 | |
| */
 | |
| LONG WINAPI WCam_WndProc (
 | |
|     HWND    hWnd,
 | |
|     UINT    uMsg,
 | |
|     WPARAM  wParam,
 | |
|     LPARAM  lParam)
 | |
| {
 | |
|     LONG    lRet = 1;
 | |
|     RECT	rect;
 | |
| 
 | |
|     GetClientRect(hWnd, &rect);
 | |
| 
 | |
|     switch (uMsg)
 | |
|     {
 | |
| 	case WM_CREATE:
 | |
| 		{
 | |
|             camdc = GetDC(hWnd);
 | |
| 	    	bSetupPixelFormat(camdc);
 | |
| 
 | |
|             baseRC = wglCreateContext( camdc );
 | |
| 			if (!baseRC)
 | |
| 				Error ("wglCreateContext failed");
 | |
|             if (!wglMakeCurrent( camdc, baseRC ))
 | |
| 				Error ("wglMakeCurrent failed");
 | |
| 			glCullFace(GL_FRONT);
 | |
| 			glEnable(GL_CULL_FACE);
 | |
| 		}
 | |
| 		break;
 | |
| 	case WM_PAINT:
 | |
|         { 
 | |
| 		    PAINTSTRUCT	ps;
 | |
| 
 | |
| 		    BeginPaint(hWnd, &ps);
 | |
|             if (!wglMakeCurrent( camdc, baseRC ))
 | |
| 				Error ("wglMakeCurrent failed");
 | |
| 			Draw ();
 | |
| 			SwapBuffers(camdc);
 | |
| 		    EndPaint(hWnd, &ps);
 | |
|         }
 | |
| 		break;
 | |
| 	
 | |
| 		case WM_KEYDOWN:
 | |
| 			KeyDown (wParam);
 | |
| 			AppKeyDown( wParam );
 | |
| 			break;
 | |
| 			
 | |
| 		case WM_KEYUP:
 | |
| 			AppKeyUp( wParam );
 | |
| 			break;
 | |
| 
 | |
| 		case WM_MBUTTONDOWN:
 | |
| 		case WM_RBUTTONDOWN:
 | |
| 		case WM_LBUTTONDOWN:
 | |
| 			SetCapture (camerawindow);
 | |
| 			ShowCursor( FALSE );
 | |
| 			g_Capture = TRUE;
 | |
| 			break;
 | |
| 
 | |
| 		case WM_MBUTTONUP:
 | |
| 		case WM_RBUTTONUP:
 | |
| 		case WM_LBUTTONUP:
 | |
| 			if (! (wParam & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
 | |
| 			{
 | |
| 				g_Capture = FALSE;
 | |
| 				ReleaseCapture ();
 | |
| 				ShowCursor( TRUE );
 | |
| 			}
 | |
| 			break;
 | |
| 
 | |
|     	case WM_SIZE:
 | |
| 			InvalidateRect(camerawindow, NULL, false);
 | |
|             break;
 | |
| 		case WM_NCCALCSIZE:// don't let windows copy pixels
 | |
| 			lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
 | |
| 			return WVR_REDRAW;
 | |
|    	    case WM_CLOSE:
 | |
|             /* call destroy window to cleanup and go away */
 | |
|             DestroyWindow (hWnd);
 | |
|         break;
 | |
| 
 | |
|    	    case WM_DESTROY:
 | |
|         {
 | |
|     	    HGLRC hRC;
 | |
|     	    HDC	  hDC;
 | |
| 
 | |
|                 /* release and free the device context and rendering context */
 | |
|     	    hRC = wglGetCurrentContext();
 | |
|     	    hDC = wglGetCurrentDC();
 | |
| 
 | |
|     	    wglMakeCurrent(NULL, NULL);
 | |
| 
 | |
|     	    if (hRC)
 | |
|     	    	wglDeleteContext(hRC);
 | |
|     	    if (hDC)
 | |
|     	        ReleaseDC(hWnd, hDC);
 | |
| 
 | |
|                 PostQuitMessage (0);
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|     	default:
 | |
|             /* pass all unhandled messages to DefWindowProc */
 | |
|             lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     /* return 1 if handled message, 0 if not */
 | |
|     return lRet;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
| ==============
 | |
| WCam_Register
 | |
| ==============
 | |
| */
 | |
| void WCam_Register (HINSTANCE hInstance)
 | |
| {
 | |
|     WNDCLASS   wc;
 | |
| 
 | |
|     /* Register the camera class */
 | |
| 	memset (&wc, 0, sizeof(wc));
 | |
| 
 | |
|     wc.style         = 0;
 | |
|     wc.lpfnWndProc   = (WNDPROC)WCam_WndProc;
 | |
|     wc.cbClsExtra    = 0;
 | |
|     wc.cbWndExtra    = 0;
 | |
|     wc.hInstance     = hInstance;
 | |
|     wc.hIcon         = 0;
 | |
|     wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
 | |
|     wc.hbrBackground = NULL;
 | |
|     wc.lpszMenuName  = 0;
 | |
|     wc.lpszClassName = "camera";
 | |
| 
 | |
|     if (!RegisterClass (&wc) )
 | |
|         Error ("WCam_Register: failed");
 | |
| }
 | |
| 
 | |
| 
 | |
| void WCam_Create (HINSTANCE hInstance)
 | |
| {
 | |
| 	// Center it
 | |
| 	int nScx, nScy;
 | |
| 	int w, h;
 | |
| 	int x, y;
 | |
| 
 | |
| 	WCam_Register (hInstance);
 | |
| 
 | |
| 	w = ::width;
 | |
| 	h = ::height;
 | |
| 
 | |
| 	nScx = GetSystemMetrics(SM_CXSCREEN);
 | |
| 	nScy = GetSystemMetrics(SM_CYSCREEN);
 | |
| 
 | |
| 
 | |
| 	x = (nScx - w)/2;
 | |
| 	y = (nScy - h)/2;
 | |
| 
 | |
| 	camerawindow = CreateWindow ("camera" ,
 | |
| 		"Camera View",
 | |
| 		WS_OVERLAPPED |
 | |
| 		WS_CAPTION |
 | |
| 		WS_SYSMENU |
 | |
| 		WS_THICKFRAME |
 | |
| 		WS_MAXIMIZEBOX |
 | |
| 		WS_CLIPSIBLINGS |
 | |
| 		WS_CLIPCHILDREN,
 | |
| 
 | |
| 		x,
 | |
| 		y,
 | |
| 		w,
 | |
| 		h,	// size
 | |
| 
 | |
| 		NULL,	// parent window
 | |
| 		0,		// no menu
 | |
| 		hInstance,
 | |
| 		0);
 | |
| 	if (!camerawindow)
 | |
| 		Error ("Couldn't create camerawindow");
 | |
| 
 | |
|     ShowWindow (camerawindow, SW_SHOWDEFAULT);
 | |
| }
 | |
| 
 | |
| 
 | |
| void AppKeyDown( int key )
 | |
| {
 | |
| 	key &= 0xFF;
 | |
| 
 | |
| 	g_Keys[key] = 0x03; // add debounce bit
 | |
| }
 | |
| 
 | |
| void AppKeyUp( int key )
 | |
| {
 | |
| 	key &= 0xFF;
 | |
| 
 | |
| 	g_Keys[key] &= 0x02;
 | |
| }
 | |
| 
 | |
| void AppRender( void )
 | |
| {
 | |
| 	static double lastTime = 0;
 | |
| 	double time = timeGetTime() * 0.001f;
 | |
| 	double frametime = time - lastTime;
 | |
| 
 | |
| 	// clamp too large frames (like first frame)
 | |
| 	if ( frametime > 0.2 )
 | |
| 		frametime = 0.2;
 | |
| 	lastTime = time;
 | |
| 
 | |
|     if (!wglMakeCurrent( camdc, baseRC ))
 | |
| 		Error ("wglMakeCurrent failed");
 | |
| 
 | |
| 	Cam_Update( frametime );
 | |
| 
 | |
| 	if (g_Update)
 | |
| 	{
 | |
| 		Draw ();
 | |
| 		SwapBuffers(camdc);
 | |
| 		g_Update = FALSE;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		Sleep( 1.0 );
 | |
| 	}
 | |
| }
 | |
| 
 | |
| SpewRetval_t Sys_SpewFunc( SpewType_t type, const char *pMsg )
 | |
| {
 | |
| 	OutputDebugString( pMsg );
 | |
| 	if( type == SPEW_ASSERT )
 | |
| 		return SPEW_DEBUGGER;
 | |
| 	else if( type == SPEW_ERROR )
 | |
| 		return SPEW_ABORT;
 | |
| 	else
 | |
| 		return SPEW_CONTINUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
| ==================
 | |
| WinMain
 | |
| 
 | |
| ==================
 | |
| */
 | |
| int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance
 | |
| 					,LPSTR lpCmdLine, int nCmdShow)
 | |
| {
 | |
| 	CommandLine()->CreateCmdLine( Plat_GetCommandLine() );
 | |
| 
 | |
| 	MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
 | |
|     MSG        msg;
 | |
| 
 | |
| 	if (!lpCmdLine || !lpCmdLine[0])
 | |
| 		Error ("No file specified");
 | |
| 
 | |
| 	main_instance = hInstance;
 | |
| 
 | |
| 	WCam_Create (hInstance);
 | |
| 
 | |
| 	// Last argument is the file name
 | |
| 	const char *pFileName = CommandLine()->GetParm( CommandLine()->ParmCount() - 1 );
 | |
| 	CmdLib_InitFileSystem( pFileName );
 | |
| 
 | |
| 	if ( CommandLine()->CheckParm( "-portal") )
 | |
| 	{
 | |
| 		g_bReadPortals = 1;
 | |
| 		g_nPortalHighlight = CommandLine()->ParmValue( "-portalhighlight", -1 );
 | |
| 		g_nLeafHighlight = CommandLine()->ParmValue( "-leafhighlight", -1 );
 | |
| 	}
 | |
| 	g_flMovementSpeed = CommandLine()->ParmValue( "-speed", 320 );
 | |
| 
 | |
| 	if( CommandLine()->CheckParm( "-disp") )
 | |
| 	{
 | |
| 		ReadDisplacementFile( pFileName );
 | |
| 		g_bDisp = TRUE;
 | |
| 	}
 | |
| 	SpewOutputFunc( Sys_SpewFunc );
 | |
| 
 | |
| 	// Any chunk of original left is the filename.
 | |
| 	if (pFileName && pFileName[0] && !g_bDisp )
 | |
| 	{
 | |
| 		ReadPolyFile( pFileName );
 | |
| 	}
 | |
| 
 | |
| 	if (g_bReadPortals)
 | |
| 	{
 | |
| 		// Copy file again and this time look for the . from .gl? so we can concatenate .prt
 | |
| 		// and open the portal file.
 | |
| 		char szTempCmd[MAX_PATH];
 | |
| 		strcpy(szTempCmd, pFileName);
 | |
| 		char *pTmp = szTempCmd;
 | |
| 		while (pTmp && *pTmp && *pTmp != '.')
 | |
| 		{
 | |
| 			pTmp++;
 | |
| 		}
 | |
| 
 | |
| 		*pTmp = '\0';
 | |
| 		strcat(szTempCmd, ".prt");
 | |
| 
 | |
| 		ReadPortalFile(szTempCmd);
 | |
| 	};
 | |
| 
 | |
|     /* main window message loop */
 | |
| 	while (g_Active)
 | |
| 	{
 | |
|         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
 | |
| 		{
 | |
|             TranslateMessage (&msg);
 | |
|             DispatchMessage (&msg);
 | |
| 		}
 | |
| 		AppRender();
 | |
| 	}
 | |
| 
 | |
|     /* return success of application */
 | |
|     return TRUE;
 | |
| }
 | |
| 
 |