Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/game/client/game_controls/basemodel_panel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,11 @@ void CBaseModelPanel::LookAtBounds( const Vector &vecBoundsMin, const Vector &ve
//-----------------------------------------------------------------------------
CBaseModelPanel::particle_data_t::~particle_data_t()
{
if ( m_BMPQueryObj.m_pmatBoneToWorld )
{
delete[] m_BMPQueryObj.m_pmatBoneToWorld;
m_BMPQueryObj.m_pmatBoneToWorld = NULL;
}
if ( m_pParticleSystem )
{
delete m_pParticleSystem;
Expand All @@ -789,6 +794,19 @@ void CBaseModelPanel::particle_data_t::UpdateControlPoints( CStudioHdr *pStudioH
{
if ( m_pParticleSystem )
{
m_BMPQueryObj.m_pStudioHdr = pStudioHdr->GetRenderHdr();
// Save off bone transforms for the particle system query
if ( m_BMPQueryObj.m_numbones != pStudioHdr->numbones() )
{
m_BMPQueryObj.m_numbones = pStudioHdr->numbones();
if ( m_BMPQueryObj.m_pmatBoneToWorld )
{
delete[] m_BMPQueryObj.m_pmatBoneToWorld;
}
m_BMPQueryObj.m_pmatBoneToWorld = new matrix3x4_t[ m_BMPQueryObj.m_numbones ];
}
Q_memcpy( m_BMPQueryObj.m_pmatBoneToWorld, pWorldMatrix, m_BMPQueryObj.m_numbones * sizeof( matrix3x4_t ) );

// Update control points which is updating the position of the particles
matrix3x4_t matAttachToWorld;
Vector vecPosition, vecForward, vecRight, vecUp;
Expand All @@ -803,6 +821,7 @@ void CBaseModelPanel::particle_data_t::UpdateControlPoints( CStudioHdr *pStudioH
MatrixPosition( matAttachToWorld, vecPosition );

m_pParticleSystem->SetControlPointOrientation( i, vecForward, vecRight, vecUp );
m_pParticleSystem->SetControlPointObject( i, &m_BMPQueryObj );
m_pParticleSystem->SetControlPoint( i, vecPosition + vecParticleOffset );
}
}
Expand All @@ -813,6 +832,7 @@ void CBaseModelPanel::particle_data_t::UpdateControlPoints( CStudioHdr *pStudioH
MatrixPosition( matAttachToWorld, vecPosition );

m_pParticleSystem->SetControlPointOrientation( 0, vecForward, vecRight, vecUp );
m_pParticleSystem->SetControlPointObject( 0, &m_BMPQueryObj );
m_pParticleSystem->SetControlPoint( 0, vecPosition + vecParticleOffset );
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/game/client/game_controls/basemodel_panel.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,23 @@

#include "matsys_controls/mdlpanel.h"

//-----------------------------------------------------------------------------
// Particle data we want the particle system query to have.
//-----------------------------------------------------------------------------
struct BMPParticleQueryObject_t
{
const studiohdr_t *m_pStudioHdr;
int m_numbones;
matrix3x4_t *m_pmatBoneToWorld;

BMPParticleQueryObject_t( void )
{
m_pStudioHdr = NULL;
m_numbones = -1;
m_pmatBoneToWorld = NULL;
}
};

//-----------------------------------------------------------------------------
// Resource file data used in posing the model inside of the model panel.
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -248,6 +265,7 @@ class CBaseModelPanel : public CMDLPanel

bool m_bIsUpdateToDate;
CParticleCollection *m_pParticleSystem;
BMPParticleQueryObject_t m_BMPQueryObj;
};
CUtlVector< particle_data_t* > m_particleList;

Expand Down
6 changes: 3 additions & 3 deletions src/game/client/tf/vgui/tf_playermodelpanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1808,11 +1808,11 @@ void CTFPlayerModelPanel::UpdateTauntEffects(
m_aParticleSystems[SYSTEM_TAUNT] = CreateParticleData( strParticleName.String() );
}

matrix3x4_t matAttachToWorld;
SetIdentityMatrix( matAttachToWorld );
Vector vecBonePos;
MatrixPosition( *pWorldMatrix, vecBonePos );

CUtlVector< int > vecAttachments;
m_aParticleSystems[SYSTEM_TAUNT]->UpdateControlPoints( pStudioHdr, &matAttachToWorld, vecAttachments, 0, m_vecPlayerPos );
m_aParticleSystems[SYSTEM_TAUNT]->UpdateControlPoints( pStudioHdr, pWorldMatrix, vecAttachments, 0, m_vecPlayerPos - vecBonePos );
}

//-----------------------------------------------------------------------------
Expand Down
225 changes: 115 additions & 110 deletions src/game/shared/particlesystemquery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "collisionutils.h"

#if defined( CLIENT_DLL )
#include "basemodel_panel.h"
#include "c_pixel_visibility.h"
#endif

Expand Down Expand Up @@ -202,100 +203,96 @@ void CParticleSystemQuery::GetRandomPointsOnControllingObjectHitBox(

#ifndef GAME_DLL

EHANDLE *phMoveParent = reinterpret_cast<EHANDLE *> ( pParticles->m_ControlPoints[nControlPointNumber].m_pObject );
CBaseEntity *pMoveParent = NULL;
if ( phMoveParent )
EHANDLE *phMoveParent = reinterpret_cast< EHANDLE * >( pParticles->m_ControlPoints[ nControlPointNumber ].m_pObject );
CBaseEntity *pMoveParent = phMoveParent ? *( phMoveParent ) : NULL;
BMPParticleQueryObject_t *pBMPQueryObj = !pMoveParent ? reinterpret_cast< BMPParticleQueryObject_t * >( pParticles->m_ControlPoints[ nControlPointNumber ].m_pObject ) : NULL;

float flRandMax = flBBoxScale;
float flRandMin = 1.f - flBBoxScale;
Vector vecBasePos;
pParticles->GetControlPointAtTime( nControlPointNumber, pParticles->m_flCurTime, &vecBasePos );

auto lambdaStudioGetRandomPoints = [ & ]( const studiohdr_t *pStudioHdr, const matrix3x4_t *pmatBoneToWorld, int nHitBoxSet = 0, float flModelScale = 1.f )
{
pMoveParent = *( phMoveParent );
}
mstudiohitboxset_t *pSet = pStudioHdr->pHitboxSet( nHitBoxSet );
if ( pSet )
{
bSucesss = true;

Vector vecWorldPosition( 0.f, 0.f, 0.f );
float u = 0.f, v = 0.f, w = 0.f;
int nHitbox = 0;
int nNumIters = nNumTrysToGetAPointInsideTheModel;
if ( !vecDirectionalBias.IsZero( 0.0001f ) )
nNumIters = MAX( nNumIters, 5 );

for ( int i = 0; i < nNumPtsOut; i++ )
{
int nTryCnt = nNumIters;
float flBestPointGoodness = -1.0e20f;
do
{
int nTryHitbox = pParticles->RandomInt( 0, pSet->numhitboxes - 1 );
mstudiobbox_t *pBox = pSet->pHitbox( nTryHitbox );

float flTryU = pParticles->RandomFloat( flRandMin, flRandMax );
float flTryV = pParticles->RandomFloat( flRandMin, flRandMax );
float flTryW = pParticles->RandomFloat( flRandMin, flRandMax );

Vector vecLocalPosition;
vecLocalPosition.x = GetSurfaceCoord( flTryU, pBox->bbmin.x * flModelScale, pBox->bbmax.x * flModelScale );
vecLocalPosition.y = GetSurfaceCoord( flTryV, pBox->bbmin.y * flModelScale, pBox->bbmax.y * flModelScale );
vecLocalPosition.z = GetSurfaceCoord( flTryW, pBox->bbmin.z * flModelScale, pBox->bbmax.z * flModelScale );

Vector vecTryWorldPosition;
VectorTransform( vecLocalPosition, pmatBoneToWorld[ pBox->bone ], vecTryWorldPosition );

float flPointGoodness = pParticles->RandomFloat( 0.f, 72.f )
+ DotProduct( vecTryWorldPosition - vecBasePos,
vecDirectionalBias );

if ( pMoveParent && nNumTrysToGetAPointInsideTheModel )
{
// do a point in solid test
Ray_t ray;
trace_t tr;
ray.Init( vecTryWorldPosition, vecTryWorldPosition );
enginetrace->ClipRayToEntity( ray, MASK_ALL, pMoveParent, &tr );
if ( tr.startsolid )
flPointGoodness += 1000.f; // got a point inside!
}
if ( flPointGoodness > flBestPointGoodness )
{
u = flTryU;
v = flTryV;
w = flTryW;
vecWorldPosition = vecTryWorldPosition;
nHitbox = nTryHitbox;
flBestPointGoodness = flPointGoodness;
}
} while ( nTryCnt-- );
*( pPntsOut++ ) = vecWorldPosition;
if ( pHitBoxRelativeCoordOut )
( pHitBoxRelativeCoordOut++ )->Init( u, v, w );
if ( pHitBoxIndexOut )
*( pHitBoxIndexOut++ ) = nHitbox;
}
}
};

if ( pMoveParent )
{
float flRandMax = flBBoxScale;
float flRandMin = 1.0 - flBBoxScale;
Vector vecBasePos;
pParticles->GetControlPointAtTime( nControlPointNumber, pParticles->m_flCurTime, &vecBasePos );

s_BoneMutex.Lock();
C_BaseAnimating *pAnimating = pMoveParent->GetBaseAnimating();
if ( pAnimating )
{

matrix3x4_t *hitboxbones[MAXSTUDIOBONES];

if ( pAnimating->HitboxToWorldTransforms( hitboxbones ) )
{

studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );

if ( pStudioHdr )
{
mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() );

if ( set )
{
bSucesss = true;

Vector vecWorldPosition(0, 0, 0);
float u = 0, v = 0, w = 0;
int nHitbox = 0;
int nNumIters = nNumTrysToGetAPointInsideTheModel;
if (! vecDirectionalBias.IsZero( 0.0001 ) )
nNumIters = MAX( nNumIters, 5 );

for( int i=0 ; i < nNumPtsOut; i++)
{
int nTryCnt = nNumIters;
float flBestPointGoodness = -1.0e20;
do
{
int nTryHitbox = pParticles->RandomInt( 0, set->numhitboxes - 1 );
mstudiobbox_t *pBox = set->pHitbox(nTryHitbox);

float flTryU = pParticles->RandomFloat( flRandMin, flRandMax );
float flTryV = pParticles->RandomFloat( flRandMin, flRandMax );
float flTryW = pParticles->RandomFloat( flRandMin, flRandMax );

Vector vecLocalPosition;
vecLocalPosition.x = GetSurfaceCoord( flTryU, pBox->bbmin.x * pAnimating->GetModelScale(), pBox->bbmax.x * pAnimating->GetModelScale() );
vecLocalPosition.y = GetSurfaceCoord( flTryV, pBox->bbmin.y * pAnimating->GetModelScale(), pBox->bbmax.y * pAnimating->GetModelScale() );
vecLocalPosition.z = GetSurfaceCoord( flTryW, pBox->bbmin.z * pAnimating->GetModelScale(), pBox->bbmax.z * pAnimating->GetModelScale() );

Vector vecTryWorldPosition;

VectorTransform( vecLocalPosition, *hitboxbones[pBox->bone], vecTryWorldPosition );


float flPointGoodness = pParticles->RandomFloat( 0, 72 )
+ DotProduct( vecTryWorldPosition - vecBasePos,
vecDirectionalBias );

if ( nNumTrysToGetAPointInsideTheModel )
{
// do a point in solid test
Ray_t ray;
trace_t tr;
ray.Init( vecTryWorldPosition, vecTryWorldPosition );
enginetrace->ClipRayToEntity( ray, MASK_ALL, pMoveParent, &tr );
if ( tr.startsolid )
flPointGoodness += 1000.; // got a point inside!
}
if ( flPointGoodness > flBestPointGoodness )
{
u = flTryU;
v = flTryV;
w = flTryW;
vecWorldPosition = vecTryWorldPosition;
nHitbox = nTryHitbox;
flBestPointGoodness = flPointGoodness;
}
} while ( nTryCnt-- );
*( pPntsOut++ ) = vecWorldPosition;
if ( pHitBoxRelativeCoordOut )
( pHitBoxRelativeCoordOut++ )->Init( u, v, w );
if ( pHitBoxIndexOut )
*( pHitBoxIndexOut++ ) = nHitbox;
}
}
lambdaStudioGetRandomPoints( pStudioHdr, *hitboxbones, pAnimating->GetHitboxSet(), pAnimating->GetModelScale() );
}
}
}
Expand All @@ -310,8 +307,6 @@ void CParticleSystemQuery::GetRandomPointsOnControllingObjectHitBox(
VecOrigin = pMoveParent->GetRenderOrigin();
matOrientation = pMoveParent->EntityToWorldTransform();



Vector vecWorldPosition(0, 0, 0);
float u = 0, v = 0, w = 0;
int nHitbox = 0;
Expand Down Expand Up @@ -371,6 +366,15 @@ void CParticleSystemQuery::GetRandomPointsOnControllingObjectHitBox(

s_BoneMutex.Unlock();
}
else if ( pBMPQueryObj )
{
matrix3x4_t *pmatBoneToWorld = pBMPQueryObj->m_pmatBoneToWorld;
const studiohdr_t *pStudioHdr = pBMPQueryObj->m_pStudioHdr;
if ( pStudioHdr && pmatBoneToWorld )
{
lambdaStudioGetRandomPoints( pStudioHdr, pmatBoneToWorld );
}
}
#endif
if (! bSucesss )
{
Expand Down Expand Up @@ -400,46 +404,38 @@ int CParticleSystemQuery::GetControllingObjectHitBoxInfo(
#ifndef GAME_DLL
s_BoneMutex.Lock();

EHANDLE *phMoveParent = reinterpret_cast<EHANDLE *> ( pParticles->m_ControlPoints[nControlPointNumber].m_pObject );
CBaseEntity *pMoveParent = NULL;
if ( phMoveParent )
EHANDLE *phMoveParent = reinterpret_cast< EHANDLE * >( pParticles->m_ControlPoints[ nControlPointNumber ].m_pObject );
CBaseEntity *pMoveParent = phMoveParent ? *( phMoveParent ) : NULL;
BMPParticleQueryObject_t *pBMPQueryObj = !pMoveParent ? reinterpret_cast< BMPParticleQueryObject_t * >( pParticles->m_ControlPoints[ nControlPointNumber ].m_pObject ) : NULL;

auto lambdaStudioGetHitBoxInfo = [ & ]( const studiohdr_t *pStudioHdr, const matrix3x4_t *pmatBoneToWorld, int nHitBoxSet = 0 )
{
pMoveParent = *( phMoveParent );
}
mstudiohitboxset_t *pSet = pStudioHdr->pHitboxSet( nHitBoxSet );
if ( pSet )
{
nRet = Min( nBufSize, pSet->numhitboxes );
for ( int i = 0; i < nRet; i++ )
{
mstudiobbox_t *pBox = pSet->pHitbox( i );
pHitBoxOutputBuffer[ i ].m_vecBoxMins = pBox->bbmin;
pHitBoxOutputBuffer[ i ].m_vecBoxMaxes = pBox->bbmax;
pHitBoxOutputBuffer[ i ].m_Transform = pmatBoneToWorld[ pBox->bone ];
}
}
};

if ( pMoveParent )
{
C_BaseAnimating *pAnimating = pMoveParent->GetBaseAnimating();
if ( pAnimating )
{
matrix3x4_t *hitboxbones[MAXSTUDIOBONES];

if ( pAnimating->HitboxToWorldTransforms( hitboxbones ) )
{

studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );

if ( pStudioHdr )
{
mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() );

if ( set )
{
nRet = MIN( nBufSize, set->numhitboxes );
for( int i=0 ; i < nRet; i++ )
{
mstudiobbox_t *pBox = set->pHitbox( i );
pHitBoxOutputBuffer[i].m_vecBoxMins.x = pBox->bbmin.x;
pHitBoxOutputBuffer[i].m_vecBoxMins.y = pBox->bbmin.y;
pHitBoxOutputBuffer[i].m_vecBoxMins.z = pBox->bbmin.z;

pHitBoxOutputBuffer[i].m_vecBoxMaxes.x = pBox->bbmax.x;
pHitBoxOutputBuffer[i].m_vecBoxMaxes.y = pBox->bbmax.y;
pHitBoxOutputBuffer[i].m_vecBoxMaxes.z = pBox->bbmax.z;

pHitBoxOutputBuffer[i].m_Transform = *hitboxbones[pBox->bone];
}
}
lambdaStudioGetHitBoxInfo( pStudioHdr, *hitboxbones, pAnimating->GetHitboxSet() );
}
}
}
Expand All @@ -456,6 +452,15 @@ int CParticleSystemQuery::GetControllingObjectHitBoxInfo(
nRet = 1;
}
}
else if ( pBMPQueryObj )
{
matrix3x4_t *pmatBoneToWorld = pBMPQueryObj->m_pmatBoneToWorld;
const studiohdr_t *pStudioHdr = pBMPQueryObj->m_pStudioHdr;
if ( pStudioHdr && pmatBoneToWorld )
{
lambdaStudioGetHitBoxInfo( pStudioHdr, pmatBoneToWorld );
}
}
s_BoneMutex.Unlock();
#endif
return nRet;
Expand Down