summaryrefslogtreecommitdiff
path: root/utils/xbox/makephx/makephx.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/xbox/makephx/makephx.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'utils/xbox/makephx/makephx.cpp')
-rw-r--r--utils/xbox/makephx/makephx.cpp359
1 files changed, 359 insertions, 0 deletions
diff --git a/utils/xbox/makephx/makephx.cpp b/utils/xbox/makephx/makephx.cpp
new file mode 100644
index 0000000..8473005
--- /dev/null
+++ b/utils/xbox/makephx/makephx.cpp
@@ -0,0 +1,359 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+#include "stdafx.h"
+#include "physdll.h"
+#include "vphysics/constraints.h"
+#include "tier0/icommandline.h"
+#include "filesystem_tools.h"
+#include "simplify.h"
+#include "keyvalues.h"
+#include "studio.h"
+
+IPhysicsCollision *physcollision = NULL;
+IPhysicsSurfaceProps *physprops = NULL;
+
+int g_TotalOut = 0;
+int g_TotalCompress = 0;
+bool g_bRecursive = false;
+bool g_bQuiet = false;
+
+KeyValues *g_pModelConfig = NULL;
+
+void InitFilesystem( const char *pPath )
+{
+ CmdLib_InitFileSystem( pPath );
+ // This bit of hackery allows us to access files on the harddrive
+ g_pFullFileSystem->AddSearchPath( "", "LOCAL", PATH_ADD_TO_HEAD );
+}
+
+static bool LoadSurfaceProps( const char *pMaterialFilename )
+{
+ if ( !physprops )
+ return false;
+
+ FileHandle_t fp = g_pFileSystem->Open( pMaterialFilename, "rb", TOOLS_READ_PATH_ID );
+ if ( fp == FILESYSTEM_INVALID_HANDLE )
+ return false;
+
+ int len = g_pFileSystem->Size( fp );
+ char *pText = new char[len+1];
+ g_pFileSystem->Read( pText, len, fp );
+ g_pFileSystem->Close( fp );
+
+ pText[len]=0;
+
+ physprops->ParseSurfaceData( pMaterialFilename, pText );
+
+ delete[] pText;
+
+ return true;
+}
+
+void LoadSurfacePropsAll()
+{
+ // already loaded
+ if ( physprops->SurfacePropCount() )
+ return;
+
+ const char *SURFACEPROP_MANIFEST_FILE = "scripts/surfaceproperties_manifest.txt";
+ KeyValues *manifest = new KeyValues( SURFACEPROP_MANIFEST_FILE );
+ if ( manifest->LoadFromFile( g_pFileSystem, SURFACEPROP_MANIFEST_FILE, "GAME" ) )
+ {
+ for ( KeyValues *sub = manifest->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() )
+ {
+ if ( !Q_stricmp( sub->GetName(), "file" ) )
+ {
+ // Add
+ LoadSurfaceProps( sub->GetString() );
+ continue;
+ }
+ }
+ }
+
+ manifest->deleteThis();
+}
+void InitVPhysics()
+{
+ CreateInterfaceFn physicsFactory = GetPhysicsFactory();
+ physcollision = (IPhysicsCollision *)physicsFactory( VPHYSICS_COLLISION_INTERFACE_VERSION, NULL );
+ physprops = (IPhysicsSurfaceProps *)physicsFactory( VPHYSICS_SURFACEPROPS_INTERFACE_VERSION, NULL );
+ LoadSurfacePropsAll();
+}
+
+struct phyfile_t
+{
+ phyheader_t header;
+ vcollide_t collide;
+ int fileSize;
+};
+
+void LoadPHYFile(phyfile_t *pOut, const char *name)
+{
+ memset( pOut, 0, sizeof(*pOut) );
+ FileHandle_t file = g_pFullFileSystem->Open( name, "rb" );
+ if ( !file )
+ return;
+
+ g_pFullFileSystem->Read( &pOut->header, sizeof(pOut->header), file );
+ if ( pOut->header.size != sizeof(pOut->header) || pOut->header.solidCount <= 0 )
+ return;
+
+ pOut->fileSize = g_pFullFileSystem->Size( file );
+
+ char *buf = (char *)_alloca( pOut->fileSize );
+ g_pFullFileSystem->Read( buf, pOut->fileSize, file );
+ g_pFullFileSystem->Close( file );
+
+ physcollision->VCollideLoad( &pOut->collide, pOut->header.solidCount, (const char *)buf, pOut->fileSize );
+}
+
+
+void OverrideDefaultsForModel( const char *keyname, simplifyparams_t &params )
+{
+ KeyValues *pKeys = g_pModelConfig;
+ while ( pKeys )
+ {
+ if ( !Q_stricmp( pKeys->GetName(), keyname ) )
+ {
+ for ( KeyValues *pData = pKeys->GetFirstSubKey(); pData; pData = pData->GetNextKey() )
+ {
+ if ( !Q_stricmp( pData->GetName(), "tolerance" ) )
+ {
+ params.tolerance = pData->GetFloat();
+ if (!g_bQuiet)
+ {
+ Msg("%s: tolerance set to %.2f\n", keyname, params.tolerance );
+ }
+ }
+ else if ( !Q_stricmp( pData->GetName(), "addAABB" ) )
+ {
+ params.addAABBToSimplifiedHull = pData->GetInt() ? true : false;
+ if (!g_bQuiet)
+ {
+ Msg("%s: AABB %s\n", keyname, params.addAABBToSimplifiedHull ? "on" : "off" );
+ }
+ }
+ else if ( !Q_stricmp( pData->GetName(), "singleconvex" ) )
+ {
+ params.forceSingleConvex = pData->GetInt() ? true : false;
+ if (!g_bQuiet)
+ {
+ Msg("%s: Forced to single convex\n", keyname );
+ }
+ }
+ else if ( !Q_stricmp( pData->GetName(), "mergeconvex" ) )
+ {
+ params.mergeConvexTolerance = pData->GetFloat();
+ params.mergeConvexElements = params.mergeConvexTolerance > 0 ? true : false;
+ if (!g_bQuiet)
+ {
+ Msg("%s: Merge convex %.2f\n", keyname, params.mergeConvexTolerance );
+ }
+ }
+ }
+ return;
+ }
+ pKeys = pKeys->GetNextKey();
+ }
+}
+
+bool HasMultipleBones( const char *pFilename )
+{
+ char outName[1024];
+ studiohdr_t hdr;
+ Q_strncpy( outName, pFilename, sizeof(outName) );
+ Q_SetExtension( outName, ".mdl", sizeof(outName) );
+ FileHandle_t fp = g_pFileSystem->Open( outName, "rb", TOOLS_READ_PATH_ID );
+ if ( fp == FILESYSTEM_INVALID_HANDLE )
+ return false;
+
+ g_pFileSystem->Read( &hdr, sizeof(hdr), fp );
+ g_pFileSystem->Close( fp );
+ if ( hdr.numbones > 1 )
+ return true;
+ return false;
+}
+
+void WritePHXFile( const char *pName, const phyfile_t &file )
+{
+ if ( file.header.size != sizeof(file.header) || file.collide.solidCount <= 0 )
+ return;
+
+ CUtlBuffer out;
+
+ char outName[1024];
+ Q_snprintf( outName, sizeof(outName), "%s", pName );
+ Q_SetExtension( outName, ".phx", sizeof(outName) );
+
+ simplifyparams_t params;
+ params.Defaults();
+ params.tolerance = (file.collide.solidCount > 1) ? 4.0f : 2.0f;
+ // single solids constraint to AABB for placement help
+ params.addAABBToSimplifiedHull = (file.collide.solidCount == 1) ? true : false;
+ params.mergeConvexElements = true;
+ params.mergeConvexTolerance = 0.025f;
+ Q_FixSlashes(outName);
+ Q_strlower(outName);
+ char *pSearch = Q_strstr( outName,"models\\" );
+ if ( pSearch )
+ {
+ char keyname[1024];
+ pSearch += strlen("models\\");
+ Q_StripExtension( pSearch, keyname, sizeof(keyname) );
+ OverrideDefaultsForModel( keyname, params );
+ }
+ out.Put( &file.header, sizeof(file.header) );
+ int outSize = 0;
+ bool bStoreSolidNames = file.collide.solidCount > 1 ? true : false;
+ bStoreSolidNames = bStoreSolidNames || HasMultipleBones(outName);
+
+ vcollide_t *pNewCollide = ConvertVCollideToPHX( &file.collide, params, &outSize, false, bStoreSolidNames);
+ g_TotalOut += file.fileSize;
+ for ( int i = 0; i < pNewCollide->solidCount; i++ )
+ {
+ int collideSize = physcollision->CollideSize( pNewCollide->solids[i] );
+ out.PutInt( collideSize );
+ char *pMem = new char[collideSize];
+ physcollision->CollideWrite( pMem, pNewCollide->solids[i] );
+ out.Put( pMem, collideSize );
+ delete[] pMem;
+ }
+
+ if (!g_bQuiet)
+ {
+ Msg("%s Compressed %d (%d text) to %d (%d text)\n", outName, file.fileSize, file.collide.descSize, out.TellPut(), pNewCollide->descSize );
+ }
+ out.Put( pNewCollide->pKeyValues, pNewCollide->descSize );
+ g_TotalCompress += out.TellPut();
+
+#if 0
+ //Msg("OLD:\n-----------------------------------\n%s\n", file.collide.pKeyValues );
+ CPackedPhysicsDescription *pPacked = physcollision->CreatePackedDesc( pNewCollide->pKeyValues, pNewCollide->descSize );
+ Msg("NEW:\n-----------------------------------\n" );
+ for ( int i = 0; i < pPacked->m_solidCount; i++ )
+ {
+ solid_t solid;
+ pPacked->GetSolid( &solid, i );
+ Msg("index %d\n", solid.index );
+ Msg("name %s\n", solid.name );
+ Msg("mass %.2f\n", solid.params.mass );
+ Msg("surfaceprop %s\n", solid.surfaceprop);
+ Msg("damping %.2f\n", solid.params.damping );
+ Msg("rotdamping %.2f\n", solid.params.rotdamping );
+ Msg("drag %.2f\n", solid.params.dragCoefficient );
+ Msg("inertia %.2f\n", solid.params.inertia );
+ Msg("volume %.2f\n", solid.params.volume );
+ }
+#endif
+ DestroyPHX( pNewCollide );
+ if ( !g_pFullFileSystem->WriteFile( outName, NULL, out ) )
+ Warning("Can't write file: %s\n", outName );
+}
+
+void UnloadPHYFile( phyfile_t *pFile )
+{
+ physcollision->VCollideUnload( &pFile->collide );
+ pFile->header.size = 0;
+}
+
+void MakeFilename( char *pDest, int destSize, const char *pPathname, const char *pFilenameExt )
+{
+ Q_strncpy(pDest, pPathname, destSize);
+ Q_AppendSlash(pDest, destSize);
+ Q_strncat(pDest, pFilenameExt, destSize);
+}
+
+void MakeDirname( char *pDest, int destSize, const char *pPathname, const char *pSubdir )
+{
+ MakeFilename(pDest, destSize , pPathname, pSubdir);
+}
+
+int main( int argc, char *argv[] )
+{
+ if ( argc < 2 )
+ {
+ Msg("Usage:\nmakephx [options] <FILESPEC>\ne.g. makephx [-r] *.phy\n");
+ return 0;
+ }
+
+ CommandLine()->CreateCmdLine( argc, argv );
+ g_bRecursive = CommandLine()->FindParm("-r") > 0 ? true : false;
+ g_bQuiet = CommandLine()->FindParm("-quiet") > 0 ? true : false;
+ InitFilesystem( "*.*" );
+ InitVPhysics();
+ // disable automatic packing, we want to do this ourselves.
+ physcollision->SetPackOnLoad( false );
+ MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f, false, false, false, false );
+ InstallSpewFunction();
+
+ g_pModelConfig = new KeyValues("config");
+ g_pModelConfig->LoadFromFile( g_pFullFileSystem, "phx.cfg", "GAME" );
+ g_TotalOut = 0;
+ g_TotalCompress = 0;
+ FileFindHandle_t handle;
+ char fullpath[1024], currentFile[1024], dirName[1024], nameext[256];
+ strcpy( fullpath, argv[argc-1] );
+ strcpy( fullpath, ExpandPath( fullpath ) );
+ strcpy( fullpath, ExpandArg( fullpath ) );
+ Q_strncpy(dirName, fullpath, sizeof(dirName));
+ Q_StripFilename(dirName);
+ Q_strncpy(nameext, fullpath + strlen(dirName)+1, sizeof(nameext));
+ CUtlVector< const char * > directoryList;
+ directoryList.AddToTail( strdup(dirName) );
+ int current = 0;
+ int count = 0;
+ do
+ {
+ if ( g_bRecursive )
+ {
+ MakeFilename( currentFile, sizeof(currentFile), directoryList[current], "*.*" );
+ const char *pFilename = g_pFullFileSystem->FindFirst( currentFile, &handle );
+ while ( pFilename )
+ {
+ if ( pFilename[0] != '.' && g_pFullFileSystem->FindIsDirectory( handle ) )
+ {
+ MakeDirname( currentFile, sizeof(currentFile), directoryList[current], pFilename );
+ directoryList.AddToTail(strdup(currentFile));
+ }
+ pFilename = g_pFullFileSystem->FindNext( handle );
+ }
+ g_pFullFileSystem->FindClose( handle );
+ }
+
+ MakeFilename(currentFile, sizeof(currentFile), directoryList[current], nameext);
+ const char *pFilename = g_pFullFileSystem->FindFirst( currentFile, &handle );
+ while ( pFilename )
+ {
+ phyfile_t phy;
+ MakeFilename(currentFile, sizeof(currentFile), directoryList[current], pFilename);
+ LoadPHYFile( &phy, currentFile );
+ if ( phy.collide.isPacked || phy.collide.solidCount < 1 )
+ {
+ Msg("%s is not a valid PHY file\n", currentFile );
+ }
+ else
+ {
+ WritePHXFile( currentFile, phy );
+ count++;
+ }
+ UnloadPHYFile( &phy );
+ pFilename = g_pFullFileSystem->FindNext( handle );
+ }
+ g_pFullFileSystem->FindClose( handle );
+ current++;
+ } while( current < directoryList.Count() );
+
+ if ( count )
+ {
+ if (!g_bQuiet)
+ {
+ Msg("\n------\nTotal %s, %s\nSaved %s\n", Q_pretifymem( g_TotalOut ), Q_pretifymem( g_TotalCompress ), Q_pretifymem( g_TotalOut - g_TotalCompress ) );
+ Msg("%.2f%% savings\n", ((float)(g_TotalOut-g_TotalCompress) / (float)g_TotalOut) * 100.0f );
+ }
+ }
+ else
+ {
+ Msg("No files found in %s!\n", directoryList[current] );
+ }
+
+ return 0;
+}