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.
342 lines
9.4 KiB
342 lines
9.4 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
// |
|
//=============================================================================// |
|
#include "stdafx.h" |
|
#include "filesystem_tools.h" |
|
#include "KeyValues.h" |
|
#include "physdll.h" |
|
#include "materialsystem/imesh.h" |
|
#include "utlvector.h" |
|
|
|
char g_szAppName[] = "VPhysics perf test"; |
|
bool g_bCaptureOnFocus = false; |
|
|
|
IPhysics *physics = NULL; |
|
IPhysicsCollision *physcollision = NULL; |
|
IPhysicsSurfaceProps *physprops = NULL; |
|
IMaterial *g_materialFlatshaded = NULL; |
|
IMaterial *g_pWireframeMaterial = NULL; |
|
int gKeys[256]; |
|
|
|
const objectparams_t g_PhysDefaultObjectParams = |
|
{ |
|
NULL, |
|
1.0f, //mass |
|
1.0f, // inertia |
|
0.0f, // damping |
|
0.0f, // rotdamping |
|
0.05f, // rotIntertiaLimit |
|
"DEFAULT", |
|
NULL,// game data |
|
0.f, // volume (leave 0 if you don't have one or call physcollision->CollideVolume() to compute it) |
|
1.0f, // drag coefficient |
|
true,// enable collisions? |
|
}; |
|
|
|
|
|
void AddSurfacepropFile( const char *pFileName, IPhysicsSurfaceProps *pProps, IFileSystem *pFileSystem ) |
|
{ |
|
// Load file into memory |
|
FileHandle_t file = pFileSystem->Open( pFileName, "rb" ); |
|
|
|
if ( file ) |
|
{ |
|
int len = pFileSystem->Size( file ); |
|
|
|
// read the file |
|
char *buffer = (char *)stackalloc( len+1 ); |
|
pFileSystem->Read( buffer, len, file ); |
|
pFileSystem->Close( file ); |
|
buffer[len] = 0; |
|
pProps->ParseSurfaceData( pFileName, buffer ); |
|
// buffer is on the stack, no need to free |
|
} |
|
} |
|
|
|
void PhysParseSurfaceData( IPhysicsSurfaceProps *pProps, IFileSystem *pFileSystem ) |
|
{ |
|
const char *SURFACEPROP_MANIFEST_FILE = "scripts/surfaceproperties_manifest.txt"; |
|
KeyValues *manifest = new KeyValues( SURFACEPROP_MANIFEST_FILE ); |
|
if ( manifest->LoadFromFile( pFileSystem, SURFACEPROP_MANIFEST_FILE, "GAME" ) ) |
|
{ |
|
for ( KeyValues *sub = manifest->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() ) |
|
{ |
|
if ( !Q_stricmp( sub->GetName(), "file" ) ) |
|
{ |
|
// Add |
|
AddSurfacepropFile( sub->GetString(), pProps, pFileSystem ); |
|
continue; |
|
} |
|
|
|
Warning( "surfaceprops::Init: Manifest '%s' with bogus file type '%s', expecting 'file'\n", |
|
SURFACEPROP_MANIFEST_FILE, sub->GetName() ); |
|
} |
|
} |
|
else |
|
{ |
|
Error( "Unable to load manifest file '%s'\n", SURFACEPROP_MANIFEST_FILE ); |
|
} |
|
|
|
manifest->deleteThis(); |
|
} |
|
|
|
struct physics_test_object_t |
|
{ |
|
IPhysicsObject *pPhysics; |
|
ICollisionQuery *pModel; |
|
}; |
|
|
|
struct physicstest_t |
|
{ |
|
IPhysicsEnvironment *physenv; |
|
CUtlVector<physics_test_object_t> list; |
|
|
|
void Clear() |
|
{ |
|
physenv->SetQuickDelete( true ); |
|
for ( int i = 0; i < list.Count(); i++ ) |
|
{ |
|
physcollision->DestroyQueryModel( list[i].pModel ); |
|
physenv->DestroyObject( list[i].pPhysics ); |
|
} |
|
list.Purge(); |
|
physics->DestroyEnvironment( physenv ); |
|
} |
|
void InitEnvironment() |
|
{ |
|
physenv = physics->CreateEnvironment(); |
|
//g_EntityCollisionHash = physics->CreateObjectPairHash(); |
|
physenv->EnableDeleteQueue( true ); |
|
|
|
//physenv->SetCollisionSolver( &g_Collisions ); |
|
//physenv->SetCollisionEventHandler( &g_Collisions ); |
|
//physenv->SetConstraintEventHandler( g_pConstraintEvents ); |
|
//physenv->SetObjectEventHandler( &g_Objects ); |
|
|
|
physenv->SetSimulationTimestep( DEFAULT_TICK_INTERVAL ); // 15 ms per tick |
|
// HL Game gravity, not real-world gravity |
|
physenv->SetGravity( Vector( 0, 0, -600.0f ) ); |
|
physenv->SetAirDensity( 0.5f ); |
|
} |
|
|
|
int AddObject( IPhysicsObject *pObject ) |
|
{ |
|
int index = list.AddToTail(); |
|
list[index].pPhysics = pObject; |
|
list[index].pModel = physcollision->CreateQueryModel( (CPhysCollide *)pObject->GetCollide() ); |
|
return index; |
|
} |
|
|
|
void CreateGround( float size ) |
|
{ |
|
{ |
|
CPhysCollide *pCollide = physcollision->BBoxToCollide( Vector(-size,-size,-24), Vector(size,size,0) ); |
|
objectparams_t params = g_PhysDefaultObjectParams; |
|
IPhysicsObject *pGround = physenv->CreatePolyObjectStatic( pCollide, physprops->GetSurfaceIndex( "default" ), vec3_origin, vec3_angle, ¶ms ); |
|
AddObject( pGround ); |
|
} |
|
|
|
for ( int i = 0; i < 20; i++ ) |
|
{ |
|
CPhysCollide *pCollide = physcollision->BBoxToCollide( Vector(-24,-24,-24), Vector(24,24,24) ); |
|
objectparams_t params = g_PhysDefaultObjectParams; |
|
params.mass = 150.0f; |
|
IPhysicsObject *pGround = physenv->CreatePolyObject( pCollide, physprops->GetSurfaceIndex( "default" ), Vector(64*(i%4),64 * (i%5),1024), vec3_angle, ¶ms ); |
|
AddObject( pGround ); |
|
pGround->Wake(); |
|
} |
|
} |
|
|
|
void Explode( const Vector &origin, float force ) |
|
{ |
|
for ( int i = 0; i < list.Count(); i++ ) |
|
{ |
|
if ( !list[i].pPhysics->IsMoveable() ) |
|
continue; |
|
|
|
Vector pos, dir; |
|
list[i].pPhysics->GetPosition( &pos, NULL ); |
|
dir = pos - origin; |
|
dir.z += 10; |
|
VectorNormalize( dir ); |
|
list[i].pPhysics->ApplyForceCenter( dir * force ); |
|
} |
|
} |
|
void RandomColor( float *color, int key ) |
|
{ |
|
static bool first = true; |
|
static colorVec colors[256]; |
|
|
|
if ( first ) |
|
{ |
|
int r, g, b; |
|
first = false; |
|
for ( int i = 0; i < 256; i++ ) |
|
{ |
|
do |
|
{ |
|
r = rand()&255; |
|
g = rand()&255; |
|
b = rand()&255; |
|
} while ( (r+g+b)<256 ); |
|
colors[i].r = r; |
|
colors[i].g = g; |
|
colors[i].b = b; |
|
colors[i].a = 255; |
|
} |
|
} |
|
|
|
int index = key & 255; |
|
color[0] = colors[index].r * (1.f / 255.f); |
|
color[1] = colors[index].g * (1.f / 255.f); |
|
color[2] = colors[index].b * (1.f / 255.f); |
|
color[3] = colors[index].a * (1.f / 255.f); |
|
} |
|
|
|
void DrawObject( ICollisionQuery *pModel, IMaterial *pMaterial, IPhysicsObject *pObject ) |
|
{ |
|
matrix3x4_t matrix; |
|
pObject->GetPositionMatrix( &matrix ); |
|
CMatRenderContextPtr pRenderContext(g_MaterialSystemApp.m_pMaterialSystem); |
|
pRenderContext->Bind( pMaterial ); |
|
|
|
int vertIndex = 0; |
|
for ( int i = 0; i < pModel->ConvexCount(); i++ ) |
|
{ |
|
float color[4]; |
|
RandomColor( color, i + (int)pObject ); |
|
IMesh* pMatMesh = pRenderContext->GetDynamicMesh( ); |
|
CMeshBuilder meshBuilder; |
|
int triCount = pModel->TriangleCount( i ); |
|
meshBuilder.Begin( pMatMesh, MATERIAL_TRIANGLES, triCount ); |
|
|
|
for ( int j = 0; j < triCount; j++ ) |
|
{ |
|
Vector objectSpaceVerts[3]; |
|
pModel->GetTriangleVerts( i, j, objectSpaceVerts ); |
|
|
|
for ( int k = 0; k < 3; k++ ) |
|
{ |
|
Vector v; |
|
|
|
VectorTransform (objectSpaceVerts[k], matrix, v); |
|
meshBuilder.Position3fv( v.Base() ); |
|
meshBuilder.Color4fv( color ); |
|
meshBuilder.AdvanceVertex(); |
|
} |
|
} |
|
meshBuilder.End( false, true ); |
|
} |
|
} |
|
|
|
void Draw() |
|
{ |
|
for ( int i = 0; i < list.Count(); i++ ) |
|
{ |
|
DrawObject( list[i].pModel, g_materialFlatshaded, list[i].pPhysics ); |
|
} |
|
} |
|
void Simulate( float frametime ) |
|
{ |
|
physenv->Simulate( frametime ); |
|
} |
|
}; |
|
|
|
physicstest_t staticTest; |
|
|
|
void AppInit( void ) |
|
{ |
|
memset( gKeys, 0, sizeof(gKeys) ); |
|
CreateInterfaceFn physicsFactory = GetPhysicsFactory(); |
|
if (!(physics = (IPhysics *)physicsFactory( VPHYSICS_INTERFACE_VERSION, NULL )) || |
|
!(physcollision = (IPhysicsCollision *)physicsFactory( VPHYSICS_COLLISION_INTERFACE_VERSION, NULL )) || |
|
!(physprops = (IPhysicsSurfaceProps *)physicsFactory( VPHYSICS_SURFACEPROPS_INTERFACE_VERSION, NULL )) ) |
|
{ |
|
return; |
|
} |
|
|
|
PhysParseSurfaceData( physprops, g_pFullFileSystem ); |
|
g_materialFlatshaded = g_MaterialSystemApp.m_pMaterialSystem->FindMaterial("debug/debugdrawflatpolygons", TEXTURE_GROUP_OTHER, true); |
|
g_pWireframeMaterial = g_MaterialSystemApp.m_pMaterialSystem->FindMaterial("shadertest/wireframevertexcolor", TEXTURE_GROUP_OTHER); |
|
staticTest.InitEnvironment(); |
|
staticTest.CreateGround( 1024 ); |
|
} |
|
|
|
void FPSControls( float frametime, float mouseDeltaX, float mouseDeltaY, Vector& cameraPosition, QAngle& cameraAngles, float speed ) |
|
{ |
|
cameraAngles[1] -= mouseDeltaX; |
|
cameraAngles[0] -= mouseDeltaY; |
|
|
|
if ( cameraAngles[0] < -85 ) |
|
cameraAngles[0] = -85; |
|
if ( cameraAngles[0] > 85 ) |
|
cameraAngles[0] = 85; |
|
|
|
Vector forward, right, up; |
|
AngleVectors( cameraAngles, &forward, &right, &up ); |
|
|
|
if ( gKeys[ 'W' ] ) |
|
VectorMA( cameraPosition, frametime * speed, forward, cameraPosition ); |
|
if ( gKeys[ 'S' ] ) |
|
VectorMA( cameraPosition, -frametime * speed, forward, cameraPosition ); |
|
if ( gKeys[ 'A' ] ) |
|
VectorMA( cameraPosition, -frametime * speed, right, cameraPosition ); |
|
if ( gKeys[ 'D' ] ) |
|
VectorMA( cameraPosition, frametime * speed, right, cameraPosition ); |
|
} |
|
|
|
|
|
void SetupCamera( Vector& cameraPosition, QAngle& cameraAngles ) |
|
{ |
|
CMatRenderContextPtr pRenderContext(g_MaterialSystemApp.m_pMaterialSystem); |
|
pRenderContext->MatrixMode( MATERIAL_VIEW ); |
|
pRenderContext->LoadIdentity( ); |
|
pRenderContext->Rotate( -90, 1, 0, 0 ); // put Z going up |
|
pRenderContext->Rotate( 90, 0, 0, 1 ); |
|
|
|
pRenderContext->Rotate( -cameraAngles[2], 1, 0, 0); // roll |
|
pRenderContext->Rotate( -cameraAngles[0], 0, 1, 0); // pitch |
|
pRenderContext->Rotate( -cameraAngles[1], 0, 0, 1); // yaw |
|
|
|
pRenderContext->Translate( -cameraPosition[0], -cameraPosition[1], -cameraPosition[2] ); |
|
} |
|
|
|
static Vector cameraPosition = Vector(0,0,128); |
|
static QAngle cameraAngles = vec3_angle; |
|
|
|
void AppRender( float frametime, float mouseDeltaX, float mouseDeltaY ) |
|
{ |
|
FPSControls( frametime, mouseDeltaX, mouseDeltaY, cameraPosition, cameraAngles, 300 ); |
|
SetupCamera( cameraPosition, cameraAngles ); |
|
|
|
staticTest.Simulate( frametime ); |
|
staticTest.Draw(); |
|
} |
|
|
|
void AppExit( void ) |
|
{ |
|
staticTest.Clear(); |
|
|
|
//physics->DestroyObjectPairHash( g_EntityCollisionHash ); |
|
//g_EntityCollisionHash = NULL; |
|
physics->DestroyAllCollisionSets(); |
|
} |
|
|
|
void AppKey( int key, int down ) |
|
{ |
|
gKeys[ key & 255 ] = down; |
|
} |
|
|
|
|
|
void AppChar( int key ) |
|
{ |
|
if ( key == ' ' ) |
|
{ |
|
staticTest.Explode( cameraPosition, 150 * 100 ); |
|
} |
|
} |
|
|
|
|