2828#include " view.h"
2929#include " ixboxsystem.h"
3030#include " inputsystem/iinputsystem.h"
31+ #include < unordered_map>
32+ #include < unordered_set>
33+ #include < vector>
34+ #include < vprof.h>
3135
3236// memdbgon must be the last include file in a .cpp file!!!
3337#include " tier0/memdbgon.h"
@@ -1289,3 +1293,127 @@ bool UTIL_HasLoadedAnyMap()
12891293
12901294 return g_pFullFileSystem->FileExists ( szFilename, " MOD" );
12911295}
1296+
1297+ struct CPhysEntry
1298+ {
1299+ int references = 1 ;
1300+ int modelIndex = 0 ;
1301+ float scale = 1 .0f ;
1302+ };
1303+
1304+ std::unordered_map<CPhysCollide*, CPhysEntry> g_pScaledReferences;
1305+ std::unordered_map<int , std::unordered_map<float , CPhysCollide*>*> g_pScaledCollidables;
1306+ CPhysCollide *UTIL_GetScaledPhysCollide ( int modelIndex, float scale ) // Based off UTIL_CreateScaledPhysObject
1307+ {
1308+ VPROF ( " UTIL_GetScaledPhysCollide" , VPROF_BUDGETGROUP_PHYSICS );
1309+
1310+ if (scale == 1 .0f )
1311+ return NULL ;
1312+
1313+ std::unordered_map<float , CPhysCollide*>* scaledCollidables = nullptr ;
1314+ auto iModel = g_pScaledCollidables.find ( modelIndex );
1315+ if ( iModel != g_pScaledCollidables.end () )
1316+ {
1317+ std::unordered_map<float , CPhysCollide*>* collidables = iModel->second ;
1318+ auto iCollidable = collidables->find ( scale );
1319+ if ( iCollidable != collidables->end () )
1320+ {
1321+ auto it = g_pScaledReferences.find ( iCollidable->second );
1322+ if ( it != g_pScaledReferences.end () )
1323+ {
1324+ ++it->second .references ;
1325+ } else {
1326+ DevWarning ( " UTIL_GetScaledPhysCollide: Failed to find reference counter!\n " );
1327+ }
1328+
1329+ return iCollidable->second ;
1330+ } else {
1331+ scaledCollidables = collidables;
1332+ }
1333+ } else {
1334+ scaledCollidables = new std::unordered_map<float , CPhysCollide*>;
1335+ g_pScaledCollidables[modelIndex] = scaledCollidables;
1336+ }
1337+
1338+ ICollisionQuery *pQuery = physcollision->CreateQueryModel ( modelinfo->GetVCollide ( modelIndex )->solids [0 ] );
1339+ if ( pQuery == NULL )
1340+ {
1341+ Warning ( " UTIL_GetScaledPhysCollide: Failed to created scaled CPhysCollide for model %s!\n " , modelinfo->GetModelName ( modelinfo->GetModel ( modelIndex ) ) );
1342+ return NULL ;
1343+ }
1344+
1345+ const int nNumConvex = pQuery->ConvexCount ();
1346+ CPhysPolysoup *pPolySoups = physcollision->PolysoupCreate ();
1347+
1348+ for ( int i = 0 ; i < nNumConvex; ++i )
1349+ {
1350+ int nNumTris = pQuery->TriangleCount ( i );
1351+ int nNumVerts = nNumTris * 3 ;
1352+
1353+ Vector *pVerts = (Vector *) stackalloc ( sizeof (Vector) * nNumVerts );
1354+ for ( int j = 0 ; j < nNumTris; ++j )
1355+ {
1356+ int p = j*3 ;
1357+ pQuery->GetTriangleVerts ( i, j, pVerts+p );
1358+ *(pVerts+p) *= scale;
1359+ *(pVerts+p+1 ) *= scale;
1360+ *(pVerts+p+2 ) *= scale;
1361+ }
1362+
1363+ for ( int j = 0 ; j < nNumVerts; j += 3 )
1364+ {
1365+ physcollision->PolysoupAddTriangle ( pPolySoups, pVerts[j], pVerts[j + 1 ], pVerts[j + 2 ], 0 );
1366+ }
1367+ }
1368+
1369+ physcollision->DestroyQueryModel ( pQuery );
1370+
1371+ CPhysCollide* physCollide = physcollision->ConvertPolysoupToCollide ( pPolySoups, true );
1372+ physcollision->PolysoupDestroy ( pPolySoups );
1373+ if ( physCollide == NULL )
1374+ {
1375+ Warning ( " UTIL_GetScaledPhysCollide: Failed to created scaled CPhysCollide for model %s %f!\n " , modelinfo->GetModelName ( modelinfo->GetModel ( modelIndex ) ), scale );
1376+ return NULL ;
1377+ }
1378+
1379+ (*scaledCollidables)[scale] = physCollide;
1380+
1381+ CPhysEntry entry;
1382+ entry.modelIndex = modelIndex;
1383+ entry.scale = scale;
1384+ g_pScaledReferences[physCollide] = entry;
1385+
1386+ return physCollide;
1387+ }
1388+
1389+ void UTIL_RemoveScaledPhysCollide ( CPhysCollide *physCollide )
1390+ {
1391+ VPROF ( " UTIL_RemoveScaledPhysCollide" , VPROF_BUDGETGROUP_PHYSICS );
1392+
1393+ auto it = g_pScaledReferences.find ( physCollide );
1394+ if ( it != g_pScaledReferences.end () )
1395+ {
1396+ --it->second .references ;
1397+ if (it->second .references > 0 )
1398+ return ;
1399+ } else {
1400+ DevWarning ( " UTIL_GetScaledPhysCollide: Failed to find reference counter!\n " );
1401+ }
1402+
1403+ auto iModel = g_pScaledCollidables.find ( it->second .modelIndex );
1404+ if ( iModel == g_pScaledCollidables.end () )
1405+ return ;
1406+
1407+ std::unordered_map<float , CPhysCollide*> scaledCollibales = *iModel->second ;
1408+ auto iEntry = scaledCollibales.find ( it->second .scale );
1409+ if ( iEntry == scaledCollibales.end () )
1410+ return ;
1411+
1412+ scaledCollibales.erase ( iEntry->first );
1413+ physcollision->DestroyCollide ( physCollide );
1414+
1415+ if ( scaledCollibales.size () == 0 )
1416+ g_pScaledCollidables.erase ( iModel );
1417+
1418+ DevMsg ( " UTIL_RemoveScaledPhysCollide: Freed model %s\n " , modelinfo->GetModelName (modelinfo->GetModel (it->second .modelIndex )) );
1419+ }
0 commit comments