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"
@@ -1315,3 +1319,127 @@ bool UTIL_HasLoadedAnyMap()
13151319
13161320 return g_pFullFileSystem->FileExists ( szFilename, " MOD" );
13171321}
1322+
1323+ struct CPhysEntry
1324+ {
1325+ int references = 1 ;
1326+ int modelIndex = 0 ;
1327+ float scale = 1 .0f ;
1328+ };
1329+
1330+ std::unordered_map<CPhysCollide*, CPhysEntry> g_pScaledReferences;
1331+ std::unordered_map<int , std::unordered_map<float , CPhysCollide*>*> g_pScaledCollidables;
1332+ CPhysCollide *UTIL_GetScaledPhysCollide ( int modelIndex, float scale ) // Based off UTIL_CreateScaledPhysObject
1333+ {
1334+ VPROF ( " UTIL_GetScaledPhysCollide" , VPROF_BUDGETGROUP_PHYSICS );
1335+
1336+ if (scale == 1 .0f )
1337+ return NULL ;
1338+
1339+ std::unordered_map<float , CPhysCollide*>* scaledCollidables = nullptr ;
1340+ auto iModel = g_pScaledCollidables.find ( modelIndex );
1341+ if ( iModel != g_pScaledCollidables.end () )
1342+ {
1343+ std::unordered_map<float , CPhysCollide*>* collidables = iModel->second ;
1344+ auto iCollidable = collidables->find ( scale );
1345+ if ( iCollidable != collidables->end () )
1346+ {
1347+ auto it = g_pScaledReferences.find ( iCollidable->second );
1348+ if ( it != g_pScaledReferences.end () )
1349+ {
1350+ ++it->second .references ;
1351+ } else {
1352+ DevWarning ( " UTIL_GetScaledPhysCollide: Failed to find reference counter!\n " );
1353+ }
1354+
1355+ return iCollidable->second ;
1356+ } else {
1357+ scaledCollidables = collidables;
1358+ }
1359+ } else {
1360+ scaledCollidables = new std::unordered_map<float , CPhysCollide*>;
1361+ g_pScaledCollidables[modelIndex] = scaledCollidables;
1362+ }
1363+
1364+ ICollisionQuery *pQuery = physcollision->CreateQueryModel ( modelinfo->GetVCollide ( modelIndex )->solids [0 ] );
1365+ if ( pQuery == NULL )
1366+ {
1367+ Warning ( " UTIL_GetScaledPhysCollide: Failed to created scaled CPhysCollide for model %s!\n " , modelinfo->GetModelName ( modelinfo->GetModel ( modelIndex ) ) );
1368+ return NULL ;
1369+ }
1370+
1371+ const int nNumConvex = pQuery->ConvexCount ();
1372+ CPhysPolysoup *pPolySoups = physcollision->PolysoupCreate ();
1373+
1374+ for ( int i = 0 ; i < nNumConvex; ++i )
1375+ {
1376+ int nNumTris = pQuery->TriangleCount ( i );
1377+ int nNumVerts = nNumTris * 3 ;
1378+
1379+ Vector *pVerts = (Vector *) stackalloc ( sizeof (Vector) * nNumVerts );
1380+ for ( int j = 0 ; j < nNumTris; ++j )
1381+ {
1382+ int p = j*3 ;
1383+ pQuery->GetTriangleVerts ( i, j, pVerts+p );
1384+ *(pVerts+p) *= scale;
1385+ *(pVerts+p+1 ) *= scale;
1386+ *(pVerts+p+2 ) *= scale;
1387+ }
1388+
1389+ for ( int j = 0 ; j < nNumVerts; j += 3 )
1390+ {
1391+ physcollision->PolysoupAddTriangle ( pPolySoups, pVerts[j], pVerts[j + 1 ], pVerts[j + 2 ], 0 );
1392+ }
1393+ }
1394+
1395+ physcollision->DestroyQueryModel ( pQuery );
1396+
1397+ CPhysCollide* physCollide = physcollision->ConvertPolysoupToCollide ( pPolySoups, true );
1398+ physcollision->PolysoupDestroy ( pPolySoups );
1399+ if ( physCollide == NULL )
1400+ {
1401+ Warning ( " UTIL_GetScaledPhysCollide: Failed to created scaled CPhysCollide for model %s %f!\n " , modelinfo->GetModelName ( modelinfo->GetModel ( modelIndex ) ), scale );
1402+ return NULL ;
1403+ }
1404+
1405+ (*scaledCollidables)[scale] = physCollide;
1406+
1407+ CPhysEntry entry;
1408+ entry.modelIndex = modelIndex;
1409+ entry.scale = scale;
1410+ g_pScaledReferences[physCollide] = entry;
1411+
1412+ return physCollide;
1413+ }
1414+
1415+ void UTIL_RemoveScaledPhysCollide ( CPhysCollide *physCollide )
1416+ {
1417+ VPROF ( " UTIL_RemoveScaledPhysCollide" , VPROF_BUDGETGROUP_PHYSICS );
1418+
1419+ auto it = g_pScaledReferences.find ( physCollide );
1420+ if ( it != g_pScaledReferences.end () )
1421+ {
1422+ --it->second .references ;
1423+ if (it->second .references > 0 )
1424+ return ;
1425+ } else {
1426+ DevWarning ( " UTIL_GetScaledPhysCollide: Failed to find reference counter!\n " );
1427+ }
1428+
1429+ auto iModel = g_pScaledCollidables.find ( it->second .modelIndex );
1430+ if ( iModel == g_pScaledCollidables.end () )
1431+ return ;
1432+
1433+ std::unordered_map<float , CPhysCollide*> scaledCollibales = *iModel->second ;
1434+ auto iEntry = scaledCollibales.find ( it->second .scale );
1435+ if ( iEntry == scaledCollibales.end () )
1436+ return ;
1437+
1438+ scaledCollibales.erase ( iEntry->first );
1439+ physcollision->DestroyCollide ( physCollide );
1440+
1441+ if ( scaledCollibales.size () == 0 )
1442+ g_pScaledCollidables.erase ( iModel );
1443+
1444+ DevMsg ( " UTIL_RemoveScaledPhysCollide: Freed model %s\n " , modelinfo->GetModelName (modelinfo->GetModel (it->second .modelIndex )) );
1445+ }
0 commit comments