diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/xbox/makephx/makephx.cpp | |
| download | archived-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.cpp | 359 |
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 ¶ms ) +{ + 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; +} |