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.

215 lines
6.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. #include "cmdlib.h"
  3. #include "mathlib/mathlib.h"
  4. #include "tier1/strtools.h"
  5. #include "physdll.h"
  6. #include "phyfile.h"
  7. #include "phxfile.h"
  8. #include "utlvector.h"
  9. #include "utlbuffer.h"
  10. #include "vphysics_interface.h"
  11. #include "vcollide_parse.h"
  12. #include "vphysics/constraints.h"
  13. #include "tier0/icommandline.h"
  14. #include "filesystem_tools.h"
  15. #include "simplify.h"
  16. #include "mathlib/compressed_vector.h"
  17. #include "keyvalues.h"
  18. IPhysicsCollision *physcollision = NULL;
  19. IPhysicsSurfaceProps *physprops = NULL;
  20. int g_TotalOut = 0;
  21. int g_TotalCompress = 0;
  22. void InitFilesystem( const char *pPath )
  23. {
  24. CmdLib_InitFileSystem( pPath );
  25. //FileSystem_Init( ".", 0, FS_INIT_COMPATIBILITY_MODE );
  26. // This bit of hackery allows us to access files on the harddrive
  27. g_pFullFileSystem->AddSearchPath( "", "LOCAL", PATH_ADD_TO_HEAD );
  28. }
  29. static bool LoadSurfaceProps( const char *pMaterialFilename )
  30. {
  31. if ( !physprops )
  32. return false;
  33. // already loaded
  34. if ( physprops->SurfacePropCount() )
  35. return false;
  36. FileHandle_t fp = g_pFileSystem->Open( pMaterialFilename, "rb", TOOLS_READ_PATH_ID );
  37. if ( fp == FILESYSTEM_INVALID_HANDLE )
  38. return false;
  39. int len = g_pFileSystem->Size( fp );
  40. char *pText = new char[len+1];
  41. g_pFileSystem->Read( pText, len, fp );
  42. g_pFileSystem->Close( fp );
  43. pText[len]=0;
  44. physprops->ParseSurfaceData( pMaterialFilename, pText );
  45. delete[] pText;
  46. return true;
  47. }
  48. void LoadSurfacePropsAll()
  49. {
  50. const char *SURFACEPROP_MANIFEST_FILE = "scripts/surfaceproperties_manifest.txt";
  51. KeyValues *manifest = new KeyValues( SURFACEPROP_MANIFEST_FILE );
  52. if ( manifest->LoadFromFile( g_pFileSystem, SURFACEPROP_MANIFEST_FILE, "GAME" ) )
  53. {
  54. for ( KeyValues *sub = manifest->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() )
  55. {
  56. if ( !Q_stricmp( sub->GetName(), "file" ) )
  57. {
  58. // Add
  59. LoadSurfaceProps( sub->GetString() );
  60. continue;
  61. }
  62. }
  63. }
  64. manifest->deleteThis();
  65. }
  66. void InitVPhysics()
  67. {
  68. CreateInterfaceFn physicsFactory = GetPhysicsFactory();
  69. physcollision = (IPhysicsCollision *)physicsFactory( VPHYSICS_COLLISION_INTERFACE_VERSION, NULL );
  70. physprops = (IPhysicsSurfaceProps *)physicsFactory( VPHYSICS_SURFACEPROPS_INTERFACE_VERSION, NULL );
  71. LoadSurfacePropsAll();
  72. }
  73. struct phyfile_t
  74. {
  75. phyheader_t header;
  76. vcollide_t collide;
  77. int fileSize;
  78. };
  79. void LoadPHYFile(phyfile_t *pOut, const char *name)
  80. {
  81. memset( pOut, 0, sizeof(*pOut) );
  82. FileHandle_t file = g_pFullFileSystem->Open( name, "rb" );
  83. if ( !file )
  84. return;
  85. g_pFullFileSystem->Read( &pOut->header, sizeof(pOut->header), file );
  86. if ( pOut->header.size != sizeof(pOut->header) || pOut->header.solidCount <= 0 )
  87. return;
  88. pOut->fileSize = g_pFullFileSystem->Size( file );
  89. char *buf = (char *)_alloca( pOut->fileSize );
  90. g_pFullFileSystem->Read( buf, pOut->fileSize, file );
  91. g_pFullFileSystem->Close( file );
  92. physcollision->VCollideLoad( &pOut->collide, pOut->header.solidCount, (const char *)buf, pOut->fileSize );
  93. }
  94. void WritePHXFile( const char *pName, const phyfile_t &file )
  95. {
  96. if ( file.header.size != sizeof(file.header) || file.collide.solidCount <= 0 )
  97. return;
  98. CUtlBuffer out;
  99. char outName[1024];
  100. Q_snprintf( outName, sizeof(outName), "%s", pName );
  101. Q_SetExtension( outName, ".phx", sizeof(outName) );
  102. out.Put( &file.header, sizeof(file.header) );
  103. int outSize = 0;
  104. float tolerance = (file.collide.solidCount > 1) ? 3.0f : 7.0f;
  105. vcollide_t *pNewCollide = ConvertVCollideToPHX( &file.collide, tolerance, &outSize, false );
  106. g_TotalOut += file.fileSize;
  107. for ( int i = 0; i < pNewCollide->solidCount; i++ )
  108. {
  109. int collideSize = physcollision->CollideSize( pNewCollide->solids[i] );
  110. out.PutInt( collideSize );
  111. char *pMem = new char[collideSize];
  112. physcollision->CollideWrite( pMem, pNewCollide->solids[i] );
  113. out.Put( pMem, collideSize );
  114. delete[] pMem;
  115. }
  116. Msg("%s Compressed %d (%d text) to %d (%d text)\n", outName, file.fileSize, file.collide.descSize, out.TellPut(), pNewCollide->descSize );
  117. out.Put( pNewCollide->pKeyValues, pNewCollide->descSize );
  118. g_TotalCompress += out.TellPut();
  119. Msg("OLD:\n-----------------------------------\n%s\n", file.collide.pKeyValues );
  120. CPackedPhysicsDescription *pPacked = physcollision->CreatePackedDesc( pNewCollide->pKeyValues, pNewCollide->descSize );
  121. Msg("NEW:\n-----------------------------------\n" );
  122. for ( int i = 0; i < pPacked->m_solidCount; i++ )
  123. {
  124. solid_t solid;
  125. pPacked->GetSolid( &solid, i );
  126. Msg("index %d\n", solid.index );
  127. Msg("name %s\n", solid.name );
  128. Msg("mass %.2f\n", solid.params.mass );
  129. Msg("surfaceprop %s\n", solid.surfaceprop);
  130. Msg("damping %.2f\n", solid.params.damping );
  131. Msg("rotdamping %.2f\n", solid.params.rotdamping );
  132. Msg("drag %.2f\n", solid.params.dragCoefficient );
  133. Msg("inertia %.2f\n", solid.params.inertia );
  134. Msg("volume %.2f\n", solid.params.volume );
  135. }
  136. if ( !g_pFullFileSystem->WriteFile( outName, NULL, out ) )
  137. Error("Error writing %s\n", outName );
  138. }
  139. void UnloadPHYFile( phyfile_t *pFile )
  140. {
  141. physcollision->VCollideUnload( &pFile->collide );
  142. pFile->header.size = 0;
  143. }
  144. int main( int argc, char *argv[] )
  145. {
  146. CommandLine()->CreateCmdLine( argc, argv );
  147. InstallSpewFunction();
  148. InitFilesystem( argv[argc-1] );
  149. InitVPhysics();
  150. MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f, false, false, false, false );
  151. g_TotalOut = 0;
  152. g_TotalCompress = 0;
  153. FileFindHandle_t handle;
  154. char fullpath[1024], filebase[1024];
  155. strcpy( fullpath, argv[argc-1] );
  156. strcpy( fullpath, ExpandPath( fullpath ) );
  157. strcpy( fullpath, ExpandArg( fullpath ) );
  158. Q_FileBase(fullpath, filebase, sizeof(filebase));
  159. const char *pFilename = g_pFullFileSystem->FindFirst( argv[argc-1], &handle );
  160. while ( pFilename )
  161. {
  162. #if 0
  163. if ( g_pFullFileSystem->FindIsDirectory( handle ) )
  164. {
  165. }
  166. #endif
  167. g_pFullFileSystem->RelativePathToFullPath( pFilename, NULL, filebase, sizeof( filebase ) );
  168. phyfile_t phy;
  169. strcpy( filebase, ExpandPath( filebase ) );
  170. strcpy( filebase, ExpandArg( filebase ) );
  171. LoadPHYFile( &phy, filebase );
  172. WritePHXFile( filebase, phy );
  173. UnloadPHYFile( &phy );
  174. pFilename = g_pFullFileSystem->FindNext( handle );
  175. }
  176. g_pFullFileSystem->FindClose( handle );
  177. Msg("Total %s, %s\nSaved %s\n", Q_pretifymem( g_TotalOut ), Q_pretifymem( g_TotalCompress ), Q_pretifymem( g_TotalOut - g_TotalCompress ) );
  178. Msg("%.2f%% savings\n", ((float)(g_TotalOut-g_TotalCompress) / (float)g_TotalOut) * 100.0f );
  179. return 0;
  180. }