Skip to content

Commit

Permalink
[client] Fix SetModelScale having no clientside collisions
Browse files Browse the repository at this point in the history
  • Loading branch information
RaphaelIT7 committed Dec 7, 2024
1 parent ee09a8e commit 9772c4d
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 1 deletion.
36 changes: 35 additions & 1 deletion game/client/c_baseanimating.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,12 @@ C_BaseAnimating::~C_BaseAnimating()
m_pAttachedTo->RemoveBoneAttachment( this );
m_pAttachedTo = NULL;
}

if ( m_pScaledCollidable )
{
UTIL_RemoveScaledPhysCollide( m_pScaledCollidable );
m_pScaledCollidable = NULL;
}
}

bool C_BaseAnimating::UsesPowerOfTwoFrameBufferTexture( void )
Expand Down Expand Up @@ -5157,9 +5163,18 @@ void C_BaseAnimating::Simulate()
}
}


bool C_BaseAnimating::TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr )
{
if ( GetModelScale() != 1.0f )
{
if ( m_pScaledCollidable != NULL )
{
physcollision->TraceBox( ray, m_pScaledCollidable, GetAbsOrigin(), GetAbsAngles(), &tr );

return tr.DidHit();
}
}

if ( ray.m_IsRay && IsSolidFlagSet( FSOLID_CUSTOMRAYTEST ))
{
if (!TestHitboxes( ray, fContentsMask, tr ))
Expand Down Expand Up @@ -6706,3 +6721,22 @@ void C_BaseAnimating::MoveBoneAttachments( C_BaseAnimating* attachTarget )
}
}
}

//-----------------------------------------------------------------------------
// Purpose: Update Collisions. (Same way it's done serverside. We only update it when Activate is called)
//-----------------------------------------------------------------------------
void C_BaseAnimating::Activate()
{
if ( GetModelScale() != 1.0f )
{
if ( m_pScaledCollidable )
{
UTIL_RemoveScaledPhysCollide( m_pScaledCollidable );
m_pScaledCollidable = NULL;
}

m_pScaledCollidable = UTIL_GetScaledPhysCollide( GetModelIndex(), GetModelScale() );
}

BaseClass::Activate();
}
4 changes: 4 additions & 0 deletions game/client/c_baseanimating.h
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ class C_BaseAnimating : public C_BaseEntity, private IModelLoadCallback

virtual bool IsViewModel() const;
void UpdateOnRemove( void ) override;
virtual void Activate( void );

protected:
// View models scale their attachment positions to account for FOV. To get the unmodified
Expand Down Expand Up @@ -640,6 +641,9 @@ class C_BaseAnimating : public C_BaseEntity, private IModelLoadCallback
mutable MDLHandle_t m_hStudioHdr;
CThreadFastMutex m_StudioHdrInitLock;
bool m_bHasAttachedParticles;

private:
CPhysCollide *m_pScaledCollidable;
};

enum
Expand Down
3 changes: 3 additions & 0 deletions game/client/c_baseentity.h
Original file line number Diff line number Diff line change
Expand Up @@ -1710,6 +1710,9 @@ class C_BaseEntity : public IClientEntity

private:
bool m_bOldShouldDraw;

public:
virtual void OnModelChange( int oldModelIndex, int newModelIndex ) {};
};

EXTERN_RECV_TABLE(DT_BaseEntity);
Expand Down
128 changes: 128 additions & 0 deletions game/client/cdll_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
#include "view.h"
#include "ixboxsystem.h"
#include "inputsystem/iinputsystem.h"
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <vprof.h>

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
Expand Down Expand Up @@ -1315,3 +1319,127 @@ bool UTIL_HasLoadedAnyMap()

return g_pFullFileSystem->FileExists( szFilename, "MOD" );
}

struct CPhysEntry
{
int references = 1;
int modelIndex = 0;
float scale = 1.0f;
};

std::unordered_map<CPhysCollide*, CPhysEntry> g_pScaledReferences;
std::unordered_map<int, std::unordered_map<float, CPhysCollide*>*> g_pScaledCollidables;
CPhysCollide *UTIL_GetScaledPhysCollide( int modelIndex, float scale ) // Based off UTIL_CreateScaledPhysObject
{
VPROF( "UTIL_GetScaledPhysCollide", VPROF_BUDGETGROUP_PHYSICS );

if (scale == 1.0f)
return NULL;

std::unordered_map<float, CPhysCollide*>* scaledCollidables = nullptr;
auto iModel = g_pScaledCollidables.find( modelIndex );
if ( iModel != g_pScaledCollidables.end() )
{
std::unordered_map<float, CPhysCollide*>* collidables = iModel->second;
auto iCollidable = collidables->find( scale );
if ( iCollidable != collidables->end() )
{
auto it = g_pScaledReferences.find( iCollidable->second );
if ( it != g_pScaledReferences.end() )
{
++it->second.references;
} else {
DevWarning( "UTIL_GetScaledPhysCollide: Failed to find reference counter!\n" );
}

return iCollidable->second;
} else {
scaledCollidables = collidables;
}
} else {
scaledCollidables = new std::unordered_map<float, CPhysCollide*>;
g_pScaledCollidables[modelIndex] = scaledCollidables;
}

ICollisionQuery *pQuery = physcollision->CreateQueryModel( modelinfo->GetVCollide( modelIndex )->solids[0] );
if ( pQuery == NULL )
{
Warning( "UTIL_GetScaledPhysCollide: Failed to created scaled CPhysCollide for model %s!\n", modelinfo->GetModelName( modelinfo->GetModel( modelIndex ) ) );
return NULL;
}

const int nNumConvex = pQuery->ConvexCount();
CPhysPolysoup *pPolySoups = physcollision->PolysoupCreate();

for ( int i = 0; i < nNumConvex; ++i )
{
int nNumTris = pQuery->TriangleCount( i );
int nNumVerts = nNumTris * 3;

Vector *pVerts = (Vector *) stackalloc( sizeof(Vector) * nNumVerts );
for ( int j = 0; j < nNumTris; ++j )
{
int p = j*3;
pQuery->GetTriangleVerts( i, j, pVerts+p );
*(pVerts+p) *= scale;
*(pVerts+p+1) *= scale;
*(pVerts+p+2) *= scale;
}

for ( int j = 0; j < nNumVerts; j += 3 )
{
physcollision->PolysoupAddTriangle( pPolySoups, pVerts[j], pVerts[j + 1], pVerts[j + 2], 0 );
}
}

physcollision->DestroyQueryModel( pQuery );

CPhysCollide* physCollide = physcollision->ConvertPolysoupToCollide( pPolySoups, true );
physcollision->PolysoupDestroy( pPolySoups );
if ( physCollide == NULL )
{
Warning( "UTIL_GetScaledPhysCollide: Failed to created scaled CPhysCollide for model %s %f!\n", modelinfo->GetModelName( modelinfo->GetModel( modelIndex ) ), scale );
return NULL;
}

(*scaledCollidables)[scale] = physCollide;

CPhysEntry entry;
entry.modelIndex = modelIndex;
entry.scale = scale;
g_pScaledReferences[physCollide] = entry;

return physCollide;
}

void UTIL_RemoveScaledPhysCollide( CPhysCollide *physCollide )
{
VPROF( "UTIL_RemoveScaledPhysCollide", VPROF_BUDGETGROUP_PHYSICS );

auto it = g_pScaledReferences.find( physCollide );
if ( it != g_pScaledReferences.end() )
{
--it->second.references;
if (it->second.references > 0)
return;
} else {
DevWarning( "UTIL_GetScaledPhysCollide: Failed to find reference counter!\n" );
}

auto iModel = g_pScaledCollidables.find( it->second.modelIndex );
if ( iModel == g_pScaledCollidables.end() )
return;

std::unordered_map<float, CPhysCollide*> scaledCollibales = *iModel->second;
auto iEntry = scaledCollibales.find( it->second.scale );
if ( iEntry == scaledCollibales.end() )
return;

scaledCollibales.erase( iEntry->first );
physcollision->DestroyCollide( physCollide );

if ( scaledCollibales.size() == 0 )
g_pScaledCollidables.erase( iModel );

DevMsg( "UTIL_RemoveScaledPhysCollide: Freed model %s\n", modelinfo->GetModelName(modelinfo->GetModel(it->second.modelIndex)) );
}
10 changes: 10 additions & 0 deletions game/client/cdll_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class IClientEntity;
class CHudTexture;
class CGameTrace;
class C_BaseEntity;
class C_BaseAnimating;
class CPhysCollide;

struct Ray_t;
struct client_textmessage_t;
Expand Down Expand Up @@ -184,4 +186,12 @@ int UTIL_GetMapKeyCount( const char *pszCustomKey );
// Returns true if the user has loaded any maps, false otherwise.
bool UTIL_HasLoadedAnyMap();

// SetModelScale being clientside broken fix
// Returns the given CPhysCollide for the given model index and scale. If not found it will create it.
CPhysCollide* UTIL_GetScaledPhysCollide( int modelIndex, float scale );

// Frees the given CPhysCollide if the internal reference count reaches 0.
// NOTE: Only supports CPhysCollide created by UTIL_GetScaledPhysCollide!
void UTIL_RemoveScaledPhysCollide( CPhysCollide *physCollide );

#endif // !UTIL_H

0 comments on commit 9772c4d

Please sign in to comment.