aboutsummaryrefslogtreecommitdiff
path: root/sp/src/utils/glview/glview.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /sp/src/utils/glview/glview.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'sp/src/utils/glview/glview.cpp')
-rw-r--r--sp/src/utils/glview/glview.cpp2854
1 files changed, 1427 insertions, 1427 deletions
diff --git a/sp/src/utils/glview/glview.cpp b/sp/src/utils/glview/glview.cpp
index d60a6556..d7da07b3 100644
--- a/sp/src/utils/glview/glview.cpp
+++ b/sp/src/utils/glview/glview.cpp
@@ -1,1427 +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 &params )
-{
- 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 &params )
-{
- 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;
-}
-
+//========= 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 &params )
+{
+ 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 &params )
+{
+ 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;
+}
+