diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/shared/particlesystemquery.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/shared/particlesystemquery.cpp')
| -rw-r--r-- | mp/src/game/shared/particlesystemquery.cpp | 1242 |
1 files changed, 621 insertions, 621 deletions
diff --git a/mp/src/game/shared/particlesystemquery.cpp b/mp/src/game/shared/particlesystemquery.cpp index f6eeb258..b97a334b 100644 --- a/mp/src/game/shared/particlesystemquery.cpp +++ b/mp/src/game/shared/particlesystemquery.cpp @@ -1,621 +1,621 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: particle system definitions
-//
-//===========================================================================//
-
-#include "cbase.h"
-#include "particles/particles.h"
-#include "baseparticleentity.h"
-#include "entityparticletrail_shared.h"
-#include "collisionutils.h"
-
-#if defined( CLIENT_DLL )
-#include "c_pixel_visibility.h"
-#endif
-
-#ifdef TF_CLIENT_DLL
-#include "tf_shareddefs.h"
-#endif
-
-#ifdef GAME_DLL
-#include "ai_utils.h"
-#endif
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-
-//-----------------------------------------------------------------------------
-// Interface to allow the particle system to call back into the game code
-//-----------------------------------------------------------------------------
-class CParticleSystemQuery : public CBaseAppSystem< IParticleSystemQuery >
-{
-public:
- // Inherited from IParticleSystemQuery
- virtual void GetLightingAtPoint( const Vector& vecOrigin, Color &cTint );
- virtual void TraceLine( const Vector& vecAbsStart,
- const Vector& vecAbsEnd, unsigned int mask,
- const IHandleEntity *ignore,
- int collisionGroup, CBaseTrace *ptr );
-
- virtual bool MovePointInsideControllingObject( CParticleCollection *pParticles,
- void *pObject,
- Vector *pPnt );
- virtual void GetRandomPointsOnControllingObjectHitBox(
- CParticleCollection *pParticles,
- int nControlPointNumber,
- int nNumPtsOut,
- float flBBoxScale,
- int nNumTrysToGetAPointInsideTheModel,
- Vector *pPntsOut,
- Vector vecDirectionalBias,
- Vector *pHitBoxRelativeCoordOut,
- int *pHitBoxIndexOut
- );
-
- virtual int GetCollisionGroupFromName( const char *pszCollisionGroupName );
-
-
- virtual int GetControllingObjectHitBoxInfo(
- CParticleCollection *pParticles,
- int nControlPointNumber,
- int nBufSize, // # of output slots available
- ModelHitBoxInfo_t *pHitBoxOutputBuffer );
-
- virtual bool IsPointInControllingObjectHitBox(
- CParticleCollection *pParticles,
- int nControlPointNumber, Vector vecPos, bool bBBoxOnly );
-
- virtual Vector GetLocalPlayerPos( void );
- virtual void GetLocalPlayerEyeVectors( Vector *pForward, Vector *pRight = NULL, Vector *pUp = NULL );
-
- virtual float GetPixelVisibility( int *pQueryHandle, const Vector &vecOrigin, float flScale );
- virtual void SetUpLightingEnvironment( const Vector& pos );
-};
-
-
-static CParticleSystemQuery s_ParticleSystemQuery;
-IParticleSystemQuery *g_pParticleSystemQuery = &s_ParticleSystemQuery;
-
-
-//-----------------------------------------------------------------------------
-// Exposes the interface (so tools can get at it)
-//-----------------------------------------------------------------------------
-#ifdef CLIENT_DLL
-EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CParticleSystemQuery, IParticleSystemQuery, PARTICLE_SYSTEM_QUERY_INTERFACE_VERSION, s_ParticleSystemQuery );
-#endif
-
-static CThreadFastMutex s_LightMutex;
-static CThreadFastMutex s_BoneMutex;
-
-//-----------------------------------------------------------------------------
-// Inherited from IParticleSystemQuery
-//-----------------------------------------------------------------------------
-void CParticleSystemQuery::GetLightingAtPoint( const Vector& vecOrigin, Color &cTint )
-{
-#ifdef GAME_DLL
-
- // FIXME: Go through to the engine from the server to get these values
- cTint.SetColor( 255, 255, 255, 255 );
-
-#else
-
- if ( engine->IsInGame() )
- {
- s_LightMutex.Lock();
- // Compute our lighting at our position
- Vector totalColor = engine->GetLightForPoint( vecOrigin, true );
- s_LightMutex.Unlock();
-
- // Get our lighting information
- cTint.SetColor( totalColor.x*255, totalColor.y*255, totalColor.z*255, 0 );
- }
- else
- {
- // FIXME: Go through to the engine from the server to get these values
- cTint.SetColor( 255, 255, 255, 255 );
- }
-
-#endif
-}
-
-void CParticleSystemQuery::SetUpLightingEnvironment( const Vector& pos )
-{
-#ifndef GAME_DLL
- if ( !engine->IsInGame() )
- return;
-
- s_LightMutex.Lock();
- modelrender->SetupLighting( pos );
- s_LightMutex.Unlock();
-#endif
-}
-
-void CParticleSystemQuery::TraceLine( const Vector& vecAbsStart,
- const Vector& vecAbsEnd, unsigned int mask,
- const IHandleEntity *ignore,
- int collisionGroup, CBaseTrace *ptr )
-{
- bool bDoTrace = false;
-#ifndef GAME_DLL
- bDoTrace = engine->IsInGame();
-#endif
- if ( bDoTrace )
- {
- trace_t tempTrace;
- UTIL_TraceLine( vecAbsStart, vecAbsEnd, mask, ignore, collisionGroup, &tempTrace );
- memcpy( ptr, &tempTrace, sizeof ( CBaseTrace ) );
- }
- else
- {
- ptr->startsolid = 0;
- ptr->fraction = 1.0;
- }
-
-}
-
-bool CParticleSystemQuery::MovePointInsideControllingObject(
- CParticleCollection *pParticles, void *pObject, Vector *pPnt )
-{
-#ifdef GAME_DLL
- return true;
-#else
- if (! pObject )
- return true; // accept the input point unmodified
-
- Ray_t ray;
- trace_t tr;
- ray.Init( *pPnt, *pPnt );
- enginetrace->ClipRayToEntity( ray, MASK_ALL, (CBaseEntity *) pObject, &tr );
-
- return ( tr.startsolid );
-#endif
-}
-
-static float GetSurfaceCoord( float flRand, float flMinX, float flMaxX )
-{
- return Lerp( flRand, flMinX, flMaxX );
-
-}
-
-
-void CParticleSystemQuery::GetRandomPointsOnControllingObjectHitBox(
- CParticleCollection *pParticles,
- int nControlPointNumber,
- int nNumPtsOut,
- float flBBoxScale,
- int nNumTrysToGetAPointInsideTheModel,
- Vector *pPntsOut,
- Vector vecDirectionalBias,
- Vector *pHitBoxRelativeCoordOut,
- int *pHitBoxIndexOut
- )
-{
-
- bool bSucesss = false;
-
-
-#ifndef GAME_DLL
-
- EHANDLE *phMoveParent = reinterpret_cast<EHANDLE *> ( pParticles->m_ControlPoints[nControlPointNumber].m_pObject );
- CBaseEntity *pMoveParent = NULL;
- if ( phMoveParent )
- {
- pMoveParent = *( phMoveParent );
- }
- 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;
- 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;
- }
- }
- }
- }
- }
-
- if ( pMoveParent->IsBrushModel() )
- {
- Vector vecMin;
- Vector vecMax;
- matrix3x4_t matOrientation;
- Vector VecOrigin;
- pMoveParent->GetRenderBounds( vecMin, vecMax );
- VecOrigin = pMoveParent->GetRenderOrigin();
- matOrientation = pMoveParent->EntityToWorldTransform();
-
-
-
- Vector vecWorldPosition;
- 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
- {
- float flTryU = pParticles->RandomFloat( flRandMin, flRandMax );
- float flTryV = pParticles->RandomFloat( flRandMin, flRandMax );
- float flTryW = pParticles->RandomFloat( flRandMin, flRandMax );
-
- Vector vecLocalPosition;
- vecLocalPosition.x = GetSurfaceCoord( flTryU, vecMin.x, vecMax.x );
- vecLocalPosition.y = GetSurfaceCoord( flTryV, vecMin.y, vecMax.y );
- vecLocalPosition.z = GetSurfaceCoord( flTryW, vecMin.z, vecMax.z );
-
- Vector vecTryWorldPosition;
- VectorTransform( vecLocalPosition, matOrientation, 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 = 0;
- flBestPointGoodness = flPointGoodness;
- }
- } while ( nTryCnt-- );
- *( pPntsOut++ ) = vecWorldPosition;
- if ( pHitBoxRelativeCoordOut )
- ( pHitBoxRelativeCoordOut++ )->Init( u, v, w );
- if ( pHitBoxIndexOut )
- *( pHitBoxIndexOut++ ) = nHitbox;
- }
- }
-
- s_BoneMutex.Unlock();
- }
-#endif
- if (! bSucesss )
- {
- // don't have a model or am in editor or something - fill return with control point
- for( int i=0 ; i < nNumPtsOut; i++)
- {
- pPntsOut[i] = pParticles->m_ControlPoints[nControlPointNumber].m_Position; // fallback if anything goes wrong
-
- if ( pHitBoxIndexOut )
- pHitBoxIndexOut[i] = 0;
-
- if ( pHitBoxRelativeCoordOut )
- pHitBoxRelativeCoordOut[i].Init();
- }
- }
-}
-
-
-int CParticleSystemQuery::GetControllingObjectHitBoxInfo(
- CParticleCollection *pParticles,
- int nControlPointNumber,
- int nBufSize, // # of output slots available
- ModelHitBoxInfo_t *pHitBoxOutputBuffer )
-{
- int nRet = 0;
-
-#ifndef GAME_DLL
- s_BoneMutex.Lock();
-
- EHANDLE *phMoveParent = reinterpret_cast<EHANDLE *> ( pParticles->m_ControlPoints[nControlPointNumber].m_pObject );
- CBaseEntity *pMoveParent = NULL;
- if ( phMoveParent )
- {
- pMoveParent = *( phMoveParent );
- }
-
- 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];
- }
- }
- }
- }
- }
- if ( pMoveParent->IsBrushModel() )
- {
- Vector vecMin;
- Vector vecMax;
- matrix3x4_t matOrientation;
- pMoveParent->GetRenderBounds( vecMin, vecMax );
- matOrientation = pMoveParent->EntityToWorldTransform();
- pHitBoxOutputBuffer[0].m_vecBoxMins = vecMin;
- pHitBoxOutputBuffer[0].m_vecBoxMaxes = vecMax;
- pHitBoxOutputBuffer[0].m_Transform = matOrientation;
- nRet = 1;
- }
- }
- s_BoneMutex.Unlock();
-#endif
- return nRet;
-}
-
-
-
-bool CParticleSystemQuery::IsPointInControllingObjectHitBox(
- CParticleCollection *pParticles,
- int nControlPointNumber, Vector vecPos, bool bBBoxOnly )
-{
- bool bSuccess = false;
-#ifndef GAME_DLL
-
- EHANDLE *phMoveParent = reinterpret_cast<EHANDLE *> ( pParticles->m_ControlPoints[nControlPointNumber].m_pObject );
- CBaseEntity *pMoveParent = NULL;
- if ( phMoveParent )
- {
- pMoveParent = *( phMoveParent );
- }
- if ( pMoveParent )
- {
- s_BoneMutex.Lock();
- C_BaseAnimating *pAnimating = pMoveParent->GetBaseAnimating();
-
- bool bInBBox = false;
- Vector vecBBoxMin;
- Vector vecBBoxMax;
- Vector vecOrigin;
-
- vecBBoxMin = pMoveParent->CollisionProp()->OBBMins();
- vecBBoxMax = pMoveParent->CollisionProp()->OBBMaxs();
-
- matrix3x4_t matOrientation;
- matOrientation = pMoveParent->EntityToWorldTransform();
- Vector vecLocalPos;
- VectorITransform( vecPos, matOrientation, vecLocalPos );
- if ( IsPointInBox( vecLocalPos, vecBBoxMin, vecBBoxMax ) )
- bInBBox = true;
-
- if ( bInBBox && bBBoxOnly )
- bSuccess = true;
- else if ( pAnimating && bInBBox )
- {
- 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 )
- {
- // do a point in solid test
- Ray_t ray;
- trace_t tr;
- ray.Init( vecPos, vecPos );
- enginetrace->ClipRayToEntity( ray, MASK_ALL, pMoveParent, &tr );
- if ( tr.startsolid )
- bSuccess = true;
- }
- }
- }
- }
- else if ( pMoveParent->IsBrushModel() && bInBBox )
- {
- // do a point in solid test
- Ray_t ray;
- trace_t tr;
- ray.Init( vecPos, vecPos );
- enginetrace->ClipRayToEntity( ray, MASK_ALL, pMoveParent, &tr );
- if ( tr.startsolid )
- bSuccess = true;
- }
-
- s_BoneMutex.Unlock();
- }
-#endif
- return bSuccess;
-}
-
-
-struct CollisionGroupNameRecord_t
-{
- const char *m_pszGroupName;
- int m_nGroupID;
-};
-
-
-static CollisionGroupNameRecord_t s_NameMap[]={
- { "NONE", COLLISION_GROUP_NONE },
- { "DEBRIS", COLLISION_GROUP_DEBRIS },
- { "INTERACTIVE", COLLISION_GROUP_INTERACTIVE },
- { "NPC", COLLISION_GROUP_NPC },
- { "ACTOR", COLLISION_GROUP_NPC_ACTOR },
- { "PASSABLE", COLLISION_GROUP_PASSABLE_DOOR },
-#if defined( TF_CLIENT_DLL )
- { "ROCKETS", TFCOLLISION_GROUP_ROCKETS },
-#endif
-};
-
-
-int CParticleSystemQuery::GetCollisionGroupFromName( const char *pszCollisionGroupName )
-{
- for(int i = 0; i < ARRAYSIZE( s_NameMap ); i++ )
- {
- if ( ! stricmp( s_NameMap[i].m_pszGroupName, pszCollisionGroupName ) )
- return s_NameMap[i].m_nGroupID;
- }
- return COLLISION_GROUP_NONE;
-}
-
-Vector CParticleSystemQuery::GetLocalPlayerPos( void )
-{
-#ifdef CLIENT_DLL
- C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
- if ( !pPlayer )
- return vec3_origin;
- return pPlayer->WorldSpaceCenter();
-#else
- CBasePlayer *pPlayer = AI_GetSinglePlayer();
- if ( !pPlayer )
- return vec3_origin;
- return pPlayer->WorldSpaceCenter();
-#endif
-}
-
-void CParticleSystemQuery::GetLocalPlayerEyeVectors( Vector *pForward, Vector *pRight, Vector *pUp )
-{
-#ifdef CLIENT_DLL
- C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
- if ( !pPlayer )
- {
- *pForward = vec3_origin;
- *pRight = vec3_origin;
- *pUp = vec3_origin;
- return;
- }
- pPlayer->EyeVectors( pForward, pRight, pUp );
-#else
- CBasePlayer *pPlayer = AI_GetSinglePlayer();
- if ( !pPlayer )
- {
- *pForward = vec3_origin;
- *pRight = vec3_origin;
- *pUp = vec3_origin;
- return;
- }
- pPlayer->EyeVectors( pForward, pRight, pUp );
-#endif
-}
-
-float CParticleSystemQuery::GetPixelVisibility( int *pQueryHandle, const Vector &vecOrigin, float flScale )
-{
-#ifdef CLIENT_DLL
- pixelvis_queryparams_t params;
- params.Init( vecOrigin, flScale, 1.0 );
- float flVisibility = PixelVisibility_FractionVisible( params, pQueryHandle );
- flVisibility = MAX( 0.0f, flVisibility );
- return flVisibility;
-#else
- return 0.0f;
-#endif
-}
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: particle system definitions +// +//===========================================================================// + +#include "cbase.h" +#include "particles/particles.h" +#include "baseparticleentity.h" +#include "entityparticletrail_shared.h" +#include "collisionutils.h" + +#if defined( CLIENT_DLL ) +#include "c_pixel_visibility.h" +#endif + +#ifdef TF_CLIENT_DLL +#include "tf_shareddefs.h" +#endif + +#ifdef GAME_DLL +#include "ai_utils.h" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +//----------------------------------------------------------------------------- +// Interface to allow the particle system to call back into the game code +//----------------------------------------------------------------------------- +class CParticleSystemQuery : public CBaseAppSystem< IParticleSystemQuery > +{ +public: + // Inherited from IParticleSystemQuery + virtual void GetLightingAtPoint( const Vector& vecOrigin, Color &cTint ); + virtual void TraceLine( const Vector& vecAbsStart, + const Vector& vecAbsEnd, unsigned int mask, + const IHandleEntity *ignore, + int collisionGroup, CBaseTrace *ptr ); + + virtual bool MovePointInsideControllingObject( CParticleCollection *pParticles, + void *pObject, + Vector *pPnt ); + virtual void GetRandomPointsOnControllingObjectHitBox( + CParticleCollection *pParticles, + int nControlPointNumber, + int nNumPtsOut, + float flBBoxScale, + int nNumTrysToGetAPointInsideTheModel, + Vector *pPntsOut, + Vector vecDirectionalBias, + Vector *pHitBoxRelativeCoordOut, + int *pHitBoxIndexOut + ); + + virtual int GetCollisionGroupFromName( const char *pszCollisionGroupName ); + + + virtual int GetControllingObjectHitBoxInfo( + CParticleCollection *pParticles, + int nControlPointNumber, + int nBufSize, // # of output slots available + ModelHitBoxInfo_t *pHitBoxOutputBuffer ); + + virtual bool IsPointInControllingObjectHitBox( + CParticleCollection *pParticles, + int nControlPointNumber, Vector vecPos, bool bBBoxOnly ); + + virtual Vector GetLocalPlayerPos( void ); + virtual void GetLocalPlayerEyeVectors( Vector *pForward, Vector *pRight = NULL, Vector *pUp = NULL ); + + virtual float GetPixelVisibility( int *pQueryHandle, const Vector &vecOrigin, float flScale ); + virtual void SetUpLightingEnvironment( const Vector& pos ); +}; + + +static CParticleSystemQuery s_ParticleSystemQuery; +IParticleSystemQuery *g_pParticleSystemQuery = &s_ParticleSystemQuery; + + +//----------------------------------------------------------------------------- +// Exposes the interface (so tools can get at it) +//----------------------------------------------------------------------------- +#ifdef CLIENT_DLL +EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CParticleSystemQuery, IParticleSystemQuery, PARTICLE_SYSTEM_QUERY_INTERFACE_VERSION, s_ParticleSystemQuery ); +#endif + +static CThreadFastMutex s_LightMutex; +static CThreadFastMutex s_BoneMutex; + +//----------------------------------------------------------------------------- +// Inherited from IParticleSystemQuery +//----------------------------------------------------------------------------- +void CParticleSystemQuery::GetLightingAtPoint( const Vector& vecOrigin, Color &cTint ) +{ +#ifdef GAME_DLL + + // FIXME: Go through to the engine from the server to get these values + cTint.SetColor( 255, 255, 255, 255 ); + +#else + + if ( engine->IsInGame() ) + { + s_LightMutex.Lock(); + // Compute our lighting at our position + Vector totalColor = engine->GetLightForPoint( vecOrigin, true ); + s_LightMutex.Unlock(); + + // Get our lighting information + cTint.SetColor( totalColor.x*255, totalColor.y*255, totalColor.z*255, 0 ); + } + else + { + // FIXME: Go through to the engine from the server to get these values + cTint.SetColor( 255, 255, 255, 255 ); + } + +#endif +} + +void CParticleSystemQuery::SetUpLightingEnvironment( const Vector& pos ) +{ +#ifndef GAME_DLL + if ( !engine->IsInGame() ) + return; + + s_LightMutex.Lock(); + modelrender->SetupLighting( pos ); + s_LightMutex.Unlock(); +#endif +} + +void CParticleSystemQuery::TraceLine( const Vector& vecAbsStart, + const Vector& vecAbsEnd, unsigned int mask, + const IHandleEntity *ignore, + int collisionGroup, CBaseTrace *ptr ) +{ + bool bDoTrace = false; +#ifndef GAME_DLL + bDoTrace = engine->IsInGame(); +#endif + if ( bDoTrace ) + { + trace_t tempTrace; + UTIL_TraceLine( vecAbsStart, vecAbsEnd, mask, ignore, collisionGroup, &tempTrace ); + memcpy( ptr, &tempTrace, sizeof ( CBaseTrace ) ); + } + else + { + ptr->startsolid = 0; + ptr->fraction = 1.0; + } + +} + +bool CParticleSystemQuery::MovePointInsideControllingObject( + CParticleCollection *pParticles, void *pObject, Vector *pPnt ) +{ +#ifdef GAME_DLL + return true; +#else + if (! pObject ) + return true; // accept the input point unmodified + + Ray_t ray; + trace_t tr; + ray.Init( *pPnt, *pPnt ); + enginetrace->ClipRayToEntity( ray, MASK_ALL, (CBaseEntity *) pObject, &tr ); + + return ( tr.startsolid ); +#endif +} + +static float GetSurfaceCoord( float flRand, float flMinX, float flMaxX ) +{ + return Lerp( flRand, flMinX, flMaxX ); + +} + + +void CParticleSystemQuery::GetRandomPointsOnControllingObjectHitBox( + CParticleCollection *pParticles, + int nControlPointNumber, + int nNumPtsOut, + float flBBoxScale, + int nNumTrysToGetAPointInsideTheModel, + Vector *pPntsOut, + Vector vecDirectionalBias, + Vector *pHitBoxRelativeCoordOut, + int *pHitBoxIndexOut + ) +{ + + bool bSucesss = false; + + +#ifndef GAME_DLL + + EHANDLE *phMoveParent = reinterpret_cast<EHANDLE *> ( pParticles->m_ControlPoints[nControlPointNumber].m_pObject ); + CBaseEntity *pMoveParent = NULL; + if ( phMoveParent ) + { + pMoveParent = *( phMoveParent ); + } + 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; + 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; + } + } + } + } + } + + if ( pMoveParent->IsBrushModel() ) + { + Vector vecMin; + Vector vecMax; + matrix3x4_t matOrientation; + Vector VecOrigin; + pMoveParent->GetRenderBounds( vecMin, vecMax ); + VecOrigin = pMoveParent->GetRenderOrigin(); + matOrientation = pMoveParent->EntityToWorldTransform(); + + + + Vector vecWorldPosition; + 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 + { + float flTryU = pParticles->RandomFloat( flRandMin, flRandMax ); + float flTryV = pParticles->RandomFloat( flRandMin, flRandMax ); + float flTryW = pParticles->RandomFloat( flRandMin, flRandMax ); + + Vector vecLocalPosition; + vecLocalPosition.x = GetSurfaceCoord( flTryU, vecMin.x, vecMax.x ); + vecLocalPosition.y = GetSurfaceCoord( flTryV, vecMin.y, vecMax.y ); + vecLocalPosition.z = GetSurfaceCoord( flTryW, vecMin.z, vecMax.z ); + + Vector vecTryWorldPosition; + VectorTransform( vecLocalPosition, matOrientation, 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 = 0; + flBestPointGoodness = flPointGoodness; + } + } while ( nTryCnt-- ); + *( pPntsOut++ ) = vecWorldPosition; + if ( pHitBoxRelativeCoordOut ) + ( pHitBoxRelativeCoordOut++ )->Init( u, v, w ); + if ( pHitBoxIndexOut ) + *( pHitBoxIndexOut++ ) = nHitbox; + } + } + + s_BoneMutex.Unlock(); + } +#endif + if (! bSucesss ) + { + // don't have a model or am in editor or something - fill return with control point + for( int i=0 ; i < nNumPtsOut; i++) + { + pPntsOut[i] = pParticles->m_ControlPoints[nControlPointNumber].m_Position; // fallback if anything goes wrong + + if ( pHitBoxIndexOut ) + pHitBoxIndexOut[i] = 0; + + if ( pHitBoxRelativeCoordOut ) + pHitBoxRelativeCoordOut[i].Init(); + } + } +} + + +int CParticleSystemQuery::GetControllingObjectHitBoxInfo( + CParticleCollection *pParticles, + int nControlPointNumber, + int nBufSize, // # of output slots available + ModelHitBoxInfo_t *pHitBoxOutputBuffer ) +{ + int nRet = 0; + +#ifndef GAME_DLL + s_BoneMutex.Lock(); + + EHANDLE *phMoveParent = reinterpret_cast<EHANDLE *> ( pParticles->m_ControlPoints[nControlPointNumber].m_pObject ); + CBaseEntity *pMoveParent = NULL; + if ( phMoveParent ) + { + pMoveParent = *( phMoveParent ); + } + + 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]; + } + } + } + } + } + if ( pMoveParent->IsBrushModel() ) + { + Vector vecMin; + Vector vecMax; + matrix3x4_t matOrientation; + pMoveParent->GetRenderBounds( vecMin, vecMax ); + matOrientation = pMoveParent->EntityToWorldTransform(); + pHitBoxOutputBuffer[0].m_vecBoxMins = vecMin; + pHitBoxOutputBuffer[0].m_vecBoxMaxes = vecMax; + pHitBoxOutputBuffer[0].m_Transform = matOrientation; + nRet = 1; + } + } + s_BoneMutex.Unlock(); +#endif + return nRet; +} + + + +bool CParticleSystemQuery::IsPointInControllingObjectHitBox( + CParticleCollection *pParticles, + int nControlPointNumber, Vector vecPos, bool bBBoxOnly ) +{ + bool bSuccess = false; +#ifndef GAME_DLL + + EHANDLE *phMoveParent = reinterpret_cast<EHANDLE *> ( pParticles->m_ControlPoints[nControlPointNumber].m_pObject ); + CBaseEntity *pMoveParent = NULL; + if ( phMoveParent ) + { + pMoveParent = *( phMoveParent ); + } + if ( pMoveParent ) + { + s_BoneMutex.Lock(); + C_BaseAnimating *pAnimating = pMoveParent->GetBaseAnimating(); + + bool bInBBox = false; + Vector vecBBoxMin; + Vector vecBBoxMax; + Vector vecOrigin; + + vecBBoxMin = pMoveParent->CollisionProp()->OBBMins(); + vecBBoxMax = pMoveParent->CollisionProp()->OBBMaxs(); + + matrix3x4_t matOrientation; + matOrientation = pMoveParent->EntityToWorldTransform(); + Vector vecLocalPos; + VectorITransform( vecPos, matOrientation, vecLocalPos ); + if ( IsPointInBox( vecLocalPos, vecBBoxMin, vecBBoxMax ) ) + bInBBox = true; + + if ( bInBBox && bBBoxOnly ) + bSuccess = true; + else if ( pAnimating && bInBBox ) + { + 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 ) + { + // do a point in solid test + Ray_t ray; + trace_t tr; + ray.Init( vecPos, vecPos ); + enginetrace->ClipRayToEntity( ray, MASK_ALL, pMoveParent, &tr ); + if ( tr.startsolid ) + bSuccess = true; + } + } + } + } + else if ( pMoveParent->IsBrushModel() && bInBBox ) + { + // do a point in solid test + Ray_t ray; + trace_t tr; + ray.Init( vecPos, vecPos ); + enginetrace->ClipRayToEntity( ray, MASK_ALL, pMoveParent, &tr ); + if ( tr.startsolid ) + bSuccess = true; + } + + s_BoneMutex.Unlock(); + } +#endif + return bSuccess; +} + + +struct CollisionGroupNameRecord_t +{ + const char *m_pszGroupName; + int m_nGroupID; +}; + + +static CollisionGroupNameRecord_t s_NameMap[]={ + { "NONE", COLLISION_GROUP_NONE }, + { "DEBRIS", COLLISION_GROUP_DEBRIS }, + { "INTERACTIVE", COLLISION_GROUP_INTERACTIVE }, + { "NPC", COLLISION_GROUP_NPC }, + { "ACTOR", COLLISION_GROUP_NPC_ACTOR }, + { "PASSABLE", COLLISION_GROUP_PASSABLE_DOOR }, +#if defined( TF_CLIENT_DLL ) + { "ROCKETS", TFCOLLISION_GROUP_ROCKETS }, +#endif +}; + + +int CParticleSystemQuery::GetCollisionGroupFromName( const char *pszCollisionGroupName ) +{ + for(int i = 0; i < ARRAYSIZE( s_NameMap ); i++ ) + { + if ( ! stricmp( s_NameMap[i].m_pszGroupName, pszCollisionGroupName ) ) + return s_NameMap[i].m_nGroupID; + } + return COLLISION_GROUP_NONE; +} + +Vector CParticleSystemQuery::GetLocalPlayerPos( void ) +{ +#ifdef CLIENT_DLL + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if ( !pPlayer ) + return vec3_origin; + return pPlayer->WorldSpaceCenter(); +#else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + if ( !pPlayer ) + return vec3_origin; + return pPlayer->WorldSpaceCenter(); +#endif +} + +void CParticleSystemQuery::GetLocalPlayerEyeVectors( Vector *pForward, Vector *pRight, Vector *pUp ) +{ +#ifdef CLIENT_DLL + C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); + if ( !pPlayer ) + { + *pForward = vec3_origin; + *pRight = vec3_origin; + *pUp = vec3_origin; + return; + } + pPlayer->EyeVectors( pForward, pRight, pUp ); +#else + CBasePlayer *pPlayer = AI_GetSinglePlayer(); + if ( !pPlayer ) + { + *pForward = vec3_origin; + *pRight = vec3_origin; + *pUp = vec3_origin; + return; + } + pPlayer->EyeVectors( pForward, pRight, pUp ); +#endif +} + +float CParticleSystemQuery::GetPixelVisibility( int *pQueryHandle, const Vector &vecOrigin, float flScale ) +{ +#ifdef CLIENT_DLL + pixelvis_queryparams_t params; + params.Init( vecOrigin, flScale, 1.0 ); + float flVisibility = PixelVisibility_FractionVisible( params, pQueryHandle ); + flVisibility = MAX( 0.0f, flVisibility ); + return flVisibility; +#else + return 0.0f; +#endif +} |