You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1427 lines
33 KiB
1427 lines
33 KiB
//========= 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[256]; |
|
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; |
|
} |
|
|
|
|