diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/utils/glview/glview.cpp | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/utils/glview/glview.cpp')
| -rw-r--r-- | mp/src/utils/glview/glview.cpp | 1427 |
1 files changed, 1427 insertions, 0 deletions
diff --git a/mp/src/utils/glview/glview.cpp b/mp/src/utils/glview/glview.cpp new file mode 100644 index 00000000..d60a6556 --- /dev/null +++ b/mp/src/utils/glview/glview.cpp @@ -0,0 +1,1427 @@ +//========= 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;
+}
+
|