Team Fortress 2 Source Code as on 22/4/2020
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

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "stdafx.h"
  9. #include "filesystem_tools.h"
  10. #include "KeyValues.h"
  11. #include "physdll.h"
  12. #include "materialsystem/imesh.h"
  13. #include "utlvector.h"
  14. char g_szAppName[] = "VPhysics perf test";
  15. bool g_bCaptureOnFocus = false;
  16. IPhysics *physics = NULL;
  17. IPhysicsCollision *physcollision = NULL;
  18. IPhysicsSurfaceProps *physprops = NULL;
  19. IMaterial *g_materialFlatshaded = NULL;
  20. IMaterial *g_pWireframeMaterial = NULL;
  21. int gKeys[256];
  22. const objectparams_t g_PhysDefaultObjectParams =
  23. {
  24. NULL,
  25. 1.0f, //mass
  26. 1.0f, // inertia
  27. 0.0f, // damping
  28. 0.0f, // rotdamping
  29. 0.05f, // rotIntertiaLimit
  30. "DEFAULT",
  31. NULL,// game data
  32. 0.f, // volume (leave 0 if you don't have one or call physcollision->CollideVolume() to compute it)
  33. 1.0f, // drag coefficient
  34. true,// enable collisions?
  35. };
  36. void AddSurfacepropFile( const char *pFileName, IPhysicsSurfaceProps *pProps, IFileSystem *pFileSystem )
  37. {
  38. // Load file into memory
  39. FileHandle_t file = pFileSystem->Open( pFileName, "rb" );
  40. if ( file )
  41. {
  42. int len = pFileSystem->Size( file );
  43. // read the file
  44. char *buffer = (char *)stackalloc( len+1 );
  45. pFileSystem->Read( buffer, len, file );
  46. pFileSystem->Close( file );
  47. buffer[len] = 0;
  48. pProps->ParseSurfaceData( pFileName, buffer );
  49. // buffer is on the stack, no need to free
  50. }
  51. }
  52. void PhysParseSurfaceData( IPhysicsSurfaceProps *pProps, IFileSystem *pFileSystem )
  53. {
  54. const char *SURFACEPROP_MANIFEST_FILE = "scripts/surfaceproperties_manifest.txt";
  55. KeyValues *manifest = new KeyValues( SURFACEPROP_MANIFEST_FILE );
  56. if ( manifest->LoadFromFile( pFileSystem, SURFACEPROP_MANIFEST_FILE, "GAME" ) )
  57. {
  58. for ( KeyValues *sub = manifest->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() )
  59. {
  60. if ( !Q_stricmp( sub->GetName(), "file" ) )
  61. {
  62. // Add
  63. AddSurfacepropFile( sub->GetString(), pProps, pFileSystem );
  64. continue;
  65. }
  66. Warning( "surfaceprops::Init: Manifest '%s' with bogus file type '%s', expecting 'file'\n",
  67. SURFACEPROP_MANIFEST_FILE, sub->GetName() );
  68. }
  69. }
  70. else
  71. {
  72. Error( "Unable to load manifest file '%s'\n", SURFACEPROP_MANIFEST_FILE );
  73. }
  74. manifest->deleteThis();
  75. }
  76. struct physics_test_object_t
  77. {
  78. IPhysicsObject *pPhysics;
  79. ICollisionQuery *pModel;
  80. };
  81. struct physicstest_t
  82. {
  83. IPhysicsEnvironment *physenv;
  84. CUtlVector<physics_test_object_t> list;
  85. void Clear()
  86. {
  87. physenv->SetQuickDelete( true );
  88. for ( int i = 0; i < list.Count(); i++ )
  89. {
  90. physcollision->DestroyQueryModel( list[i].pModel );
  91. physenv->DestroyObject( list[i].pPhysics );
  92. }
  93. list.Purge();
  94. physics->DestroyEnvironment( physenv );
  95. }
  96. void InitEnvironment()
  97. {
  98. physenv = physics->CreateEnvironment();
  99. //g_EntityCollisionHash = physics->CreateObjectPairHash();
  100. physenv->EnableDeleteQueue( true );
  101. //physenv->SetCollisionSolver( &g_Collisions );
  102. //physenv->SetCollisionEventHandler( &g_Collisions );
  103. //physenv->SetConstraintEventHandler( g_pConstraintEvents );
  104. //physenv->SetObjectEventHandler( &g_Objects );
  105. physenv->SetSimulationTimestep( DEFAULT_TICK_INTERVAL ); // 15 ms per tick
  106. // HL Game gravity, not real-world gravity
  107. physenv->SetGravity( Vector( 0, 0, -600.0f ) );
  108. physenv->SetAirDensity( 0.5f );
  109. }
  110. int AddObject( IPhysicsObject *pObject )
  111. {
  112. int index = list.AddToTail();
  113. list[index].pPhysics = pObject;
  114. list[index].pModel = physcollision->CreateQueryModel( (CPhysCollide *)pObject->GetCollide() );
  115. return index;
  116. }
  117. void CreateGround( float size )
  118. {
  119. {
  120. CPhysCollide *pCollide = physcollision->BBoxToCollide( Vector(-size,-size,-24), Vector(size,size,0) );
  121. objectparams_t params = g_PhysDefaultObjectParams;
  122. IPhysicsObject *pGround = physenv->CreatePolyObjectStatic( pCollide, physprops->GetSurfaceIndex( "default" ), vec3_origin, vec3_angle, &params );
  123. AddObject( pGround );
  124. }
  125. for ( int i = 0; i < 20; i++ )
  126. {
  127. CPhysCollide *pCollide = physcollision->BBoxToCollide( Vector(-24,-24,-24), Vector(24,24,24) );
  128. objectparams_t params = g_PhysDefaultObjectParams;
  129. params.mass = 150.0f;
  130. IPhysicsObject *pGround = physenv->CreatePolyObject( pCollide, physprops->GetSurfaceIndex( "default" ), Vector(64*(i%4),64 * (i%5),1024), vec3_angle, &params );
  131. AddObject( pGround );
  132. pGround->Wake();
  133. }
  134. }
  135. void Explode( const Vector &origin, float force )
  136. {
  137. for ( int i = 0; i < list.Count(); i++ )
  138. {
  139. if ( !list[i].pPhysics->IsMoveable() )
  140. continue;
  141. Vector pos, dir;
  142. list[i].pPhysics->GetPosition( &pos, NULL );
  143. dir = pos - origin;
  144. dir.z += 10;
  145. VectorNormalize( dir );
  146. list[i].pPhysics->ApplyForceCenter( dir * force );
  147. }
  148. }
  149. void RandomColor( float *color, int key )
  150. {
  151. static bool first = true;
  152. static colorVec colors[256];
  153. if ( first )
  154. {
  155. int r, g, b;
  156. first = false;
  157. for ( int i = 0; i < 256; i++ )
  158. {
  159. do
  160. {
  161. r = rand()&255;
  162. g = rand()&255;
  163. b = rand()&255;
  164. } while ( (r+g+b)<256 );
  165. colors[i].r = r;
  166. colors[i].g = g;
  167. colors[i].b = b;
  168. colors[i].a = 255;
  169. }
  170. }
  171. int index = key & 255;
  172. color[0] = colors[index].r * (1.f / 255.f);
  173. color[1] = colors[index].g * (1.f / 255.f);
  174. color[2] = colors[index].b * (1.f / 255.f);
  175. color[3] = colors[index].a * (1.f / 255.f);
  176. }
  177. void DrawObject( ICollisionQuery *pModel, IMaterial *pMaterial, IPhysicsObject *pObject )
  178. {
  179. matrix3x4_t matrix;
  180. pObject->GetPositionMatrix( &matrix );
  181. CMatRenderContextPtr pRenderContext(g_MaterialSystemApp.m_pMaterialSystem);
  182. pRenderContext->Bind( pMaterial );
  183. int vertIndex = 0;
  184. for ( int i = 0; i < pModel->ConvexCount(); i++ )
  185. {
  186. float color[4];
  187. RandomColor( color, i + (int)pObject );
  188. IMesh* pMatMesh = pRenderContext->GetDynamicMesh( );
  189. CMeshBuilder meshBuilder;
  190. int triCount = pModel->TriangleCount( i );
  191. meshBuilder.Begin( pMatMesh, MATERIAL_TRIANGLES, triCount );
  192. for ( int j = 0; j < triCount; j++ )
  193. {
  194. Vector objectSpaceVerts[3];
  195. pModel->GetTriangleVerts( i, j, objectSpaceVerts );
  196. for ( int k = 0; k < 3; k++ )
  197. {
  198. Vector v;
  199. VectorTransform (objectSpaceVerts[k], matrix, v);
  200. meshBuilder.Position3fv( v.Base() );
  201. meshBuilder.Color4fv( color );
  202. meshBuilder.AdvanceVertex();
  203. }
  204. }
  205. meshBuilder.End( false, true );
  206. }
  207. }
  208. void Draw()
  209. {
  210. for ( int i = 0; i < list.Count(); i++ )
  211. {
  212. DrawObject( list[i].pModel, g_materialFlatshaded, list[i].pPhysics );
  213. }
  214. }
  215. void Simulate( float frametime )
  216. {
  217. physenv->Simulate( frametime );
  218. }
  219. };
  220. physicstest_t staticTest;
  221. void AppInit( void )
  222. {
  223. memset( gKeys, 0, sizeof(gKeys) );
  224. CreateInterfaceFn physicsFactory = GetPhysicsFactory();
  225. if (!(physics = (IPhysics *)physicsFactory( VPHYSICS_INTERFACE_VERSION, NULL )) ||
  226. !(physcollision = (IPhysicsCollision *)physicsFactory( VPHYSICS_COLLISION_INTERFACE_VERSION, NULL )) ||
  227. !(physprops = (IPhysicsSurfaceProps *)physicsFactory( VPHYSICS_SURFACEPROPS_INTERFACE_VERSION, NULL )) )
  228. {
  229. return;
  230. }
  231. PhysParseSurfaceData( physprops, g_pFullFileSystem );
  232. g_materialFlatshaded = g_MaterialSystemApp.m_pMaterialSystem->FindMaterial("debug/debugdrawflatpolygons", TEXTURE_GROUP_OTHER, true);
  233. g_pWireframeMaterial = g_MaterialSystemApp.m_pMaterialSystem->FindMaterial("shadertest/wireframevertexcolor", TEXTURE_GROUP_OTHER);
  234. staticTest.InitEnvironment();
  235. staticTest.CreateGround( 1024 );
  236. }
  237. void FPSControls( float frametime, float mouseDeltaX, float mouseDeltaY, Vector& cameraPosition, QAngle& cameraAngles, float speed )
  238. {
  239. cameraAngles[1] -= mouseDeltaX;
  240. cameraAngles[0] -= mouseDeltaY;
  241. if ( cameraAngles[0] < -85 )
  242. cameraAngles[0] = -85;
  243. if ( cameraAngles[0] > 85 )
  244. cameraAngles[0] = 85;
  245. Vector forward, right, up;
  246. AngleVectors( cameraAngles, &forward, &right, &up );
  247. if ( gKeys[ 'W' ] )
  248. VectorMA( cameraPosition, frametime * speed, forward, cameraPosition );
  249. if ( gKeys[ 'S' ] )
  250. VectorMA( cameraPosition, -frametime * speed, forward, cameraPosition );
  251. if ( gKeys[ 'A' ] )
  252. VectorMA( cameraPosition, -frametime * speed, right, cameraPosition );
  253. if ( gKeys[ 'D' ] )
  254. VectorMA( cameraPosition, frametime * speed, right, cameraPosition );
  255. }
  256. void SetupCamera( Vector& cameraPosition, QAngle& cameraAngles )
  257. {
  258. CMatRenderContextPtr pRenderContext(g_MaterialSystemApp.m_pMaterialSystem);
  259. pRenderContext->MatrixMode( MATERIAL_VIEW );
  260. pRenderContext->LoadIdentity( );
  261. pRenderContext->Rotate( -90, 1, 0, 0 ); // put Z going up
  262. pRenderContext->Rotate( 90, 0, 0, 1 );
  263. pRenderContext->Rotate( -cameraAngles[2], 1, 0, 0); // roll
  264. pRenderContext->Rotate( -cameraAngles[0], 0, 1, 0); // pitch
  265. pRenderContext->Rotate( -cameraAngles[1], 0, 0, 1); // yaw
  266. pRenderContext->Translate( -cameraPosition[0], -cameraPosition[1], -cameraPosition[2] );
  267. }
  268. static Vector cameraPosition = Vector(0,0,128);
  269. static QAngle cameraAngles = vec3_angle;
  270. void AppRender( float frametime, float mouseDeltaX, float mouseDeltaY )
  271. {
  272. FPSControls( frametime, mouseDeltaX, mouseDeltaY, cameraPosition, cameraAngles, 300 );
  273. SetupCamera( cameraPosition, cameraAngles );
  274. staticTest.Simulate( frametime );
  275. staticTest.Draw();
  276. }
  277. void AppExit( void )
  278. {
  279. staticTest.Clear();
  280. //physics->DestroyObjectPairHash( g_EntityCollisionHash );
  281. //g_EntityCollisionHash = NULL;
  282. physics->DestroyAllCollisionSets();
  283. }
  284. void AppKey( int key, int down )
  285. {
  286. gKeys[ key & 255 ] = down;
  287. }
  288. void AppChar( int key )
  289. {
  290. if ( key == ' ' )
  291. {
  292. staticTest.Explode( cameraPosition, 150 * 100 );
  293. }
  294. }