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/client/particle_collision.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/client/particle_collision.cpp')
| -rw-r--r-- | mp/src/game/client/particle_collision.cpp | 752 |
1 files changed, 376 insertions, 376 deletions
diff --git a/mp/src/game/client/particle_collision.cpp b/mp/src/game/client/particle_collision.cpp index 0f956f13..5da0ac14 100644 --- a/mp/src/game/client/particle_collision.cpp +++ b/mp/src/game/client/particle_collision.cpp @@ -1,376 +1,376 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Local fast collision system for particles
-//
-// $NoKeywords: $
-//=============================================================================//
-#include "cbase.h"
-#include "particle_collision.h"
-#include "engine/ivdebugoverlay.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-#ifdef _XBOX
-#define __DEBUG_PARTICLE_COLLISION_RETEST 0
-#else
-#define __DEBUG_PARTICLE_COLLISION_RETEST 1
-#endif // _XBOX
-
-#define __DEBUG_PARTICLE_COLLISION_OVERLAY 0
-#define __DEBUG_PARTICLE_COLLISION_OVERLAY_LIFETIME 0.1f
-
-#define NUM_DISCREET_STEPS 8.0f
-#define NUM_SIMULATION_SECONDS 2.0f
-
-#define COLLISION_EPSILON 0.01f
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-CBaseSimpleCollision::CBaseSimpleCollision( void )
-{
- ClearActivePlanes();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : &origin -
-// radius -
-//-----------------------------------------------------------------------------
-void CBaseSimpleCollision::Setup( const Vector &origin, float speed, float gravity )
-{
- TestForPlane( origin, Vector( 1, 0, 0 ), speed, gravity );
- TestForPlane( origin, Vector( -1, 0, 0 ), speed, gravity );
- TestForPlane( origin, Vector( 0, 1, 0 ), speed, gravity );
- TestForPlane( origin, Vector( 0, -1, 0 ), speed, gravity );
- TestForPlane( origin, Vector( 0, 0, 1 ), speed, gravity );
- TestForPlane( origin, Vector( 0, 0, -1 ), speed, gravity );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Trace line for super-simplified traces
-// Input : &start - start position
-// &end - end position
-// *pTrace - trace structure to fill
-// coarse - tests again with a real trace unless coarse is set
-//-----------------------------------------------------------------------------
-void CBaseSimpleCollision::TraceLine( const Vector &start, const Vector &end, trace_t *pTrace, bool coarse )
-{
- //Iterate over all active planes
- for ( int i = 0; i < m_nActivePlanes; i++ )
- {
- //Must be a valid plane
- if ( m_collisionPlanes[i].m_Dist == -1.0f )
- continue;
-
- //Get our information about the relation to this plane
- float dot1 = m_collisionPlanes[i].DistTo(start);
- float dot2 = m_collisionPlanes[i].DistTo(end);
-
- //Don't consider particles on the backside of planes
- if ( dot1 < -COLLISION_EPSILON )
- continue;
-
- //Must be crossing the plane's boundary
- if ( ( dot1 > COLLISION_EPSILON ) == ( dot2 > COLLISION_EPSILON ) )
- continue;
-
- //Find the intersection point
- float t = dot1 / (dot1 - dot2);
- Vector vIntersection = start + (end - start) * t;
-
- //Fake the collision info
- pTrace->endpos = vIntersection;
- pTrace->fraction = t - COLLISION_EPSILON;
- pTrace->plane.normal = m_collisionPlanes[i].m_Normal;
- pTrace->plane.dist = m_collisionPlanes[i].m_Dist;
-
- //If we need an exact trace, test again on a successful hit
- if ( ( coarse == false ) && ( pTrace->fraction < 1.0f ) )
- {
- UTIL_TraceLine( start, end, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, pTrace );
- }
-
- #if __DEBUG_PARTICLE_COLLISION_OVERLAY
- debugoverlay->AddBoxOverlay( vIntersection, Vector(-1,-1,-1), Vector(1,1,1), QAngle(0,0,0), 0, 255, 0, 16, __DEBUG_PARTICLE_COLLISION_OVERLAY_LIFETIME );
- #endif //__DEBUG_PARTICLE_COLLISION_OVERLAY
-
- //Done
- return;
- }
-
- //Fell through, so clear all the fields
- pTrace->plane.normal[0] = 0.0f;
- pTrace->plane.normal[1] = 0.0f;
- pTrace->plane.normal[2] = 0.0f;
- pTrace->plane.dist = 0.0f;
- pTrace->fraction = 1.0f;
- pTrace->allsolid = false;
- pTrace->startsolid = false;
- pTrace->m_pEnt = NULL;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Tests the planes against all others for validity
-// Input : *plane - plane to test
-//-----------------------------------------------------------------------------
-void CBaseSimpleCollision::ConsiderPlane( cplane_t *plane )
-{
- //Test against all other active planes
- for ( int i = 0; i < m_nActivePlanes; i++ )
- {
- if ( m_collisionPlanes[i].m_Dist != -1.0f )
- {
- //Test for coplanar
- if ( ( m_collisionPlanes[i].m_Normal == plane->normal ) && ( m_collisionPlanes[i].m_Dist == plane->dist ) )
- return;
- }
- }
-
- //Don't overrun
- if ( m_nActivePlanes >= MAX_COLLISION_PLANES )
- return;
-
- //Take it
- m_collisionPlanes[m_nActivePlanes].m_Dist = plane->dist;
- m_collisionPlanes[m_nActivePlanes].m_Normal = plane->normal;
- m_nActivePlanes++;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Runs a simulation of the average particle's movement, looking for collisions along the way
-// Input : &start - start of the simulation
-// &dir - direction of travel
-// speed - speed of the particle
-// gravity - gravity being used
-//-----------------------------------------------------------------------------
-void CBaseSimpleCollision::TestForPlane( const Vector &start, const Vector &dir, float speed, float gravity )
-{
- trace_t tr;
- Vector testStart, testEnd;
-
- testStart = start;
-
- //Setup our step increments
- float dStepTime = (NUM_SIMULATION_SECONDS/NUM_DISCREET_STEPS);
- Vector vStepIncr = dir * ( speed * dStepTime );
- float flGravIncr = gravity*dStepTime;
-
- //Simulate collsions in discreet steps
- for ( int i = 1; i <= NUM_DISCREET_STEPS; i++ )
- {
- testEnd = testStart + vStepIncr;
- testEnd[2] -= flGravIncr * (0.5f*(dStepTime*i)*(dStepTime*i) );
-
- //Trace the line
- UTIL_TraceLine( testStart, testEnd, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr );
-
- //See if we found one
- if ( tr.fraction != 1.0f )
- {
- #if __DEBUG_PARTICLE_COLLISION_OVERLAY
- debugoverlay->AddLineOverlay( testStart, tr.endpos, 255, 0, 0, true, __DEBUG_PARTICLE_COLLISION_OVERLAY_LIFETIME );
-
- QAngle angles;
-
- VectorAngles( tr.plane.normal,angles );
- angles[PITCH] += 90;
-
- debugoverlay->AddBoxOverlay( tr.endpos, Vector(-64,-64,0), Vector(64,64,0), angles, 255, 0, 0, 16, __DEBUG_PARTICLE_COLLISION_OVERLAY_LIFETIME );
- #endif //__DEBUG_PARTICLE_COLLISION_OVERLAY
-
- //Test the plane against a set of criteria
- ConsiderPlane( &tr.plane );
-
- return;
- }
-
- //We missed
- #if __DEBUG_PARTICLE_COLLISION_OVERLAY
- debugoverlay->AddLineOverlay( testStart, tr.endpos, 0, 128.0f+(128.0f*((float)i/(float)NUM_DISCREET_STEPS)), 0, true, __DEBUG_PARTICLE_COLLISION_OVERLAY_LIFETIME );
- #endif //__DEBUG_PARTICLE_COLLISION_OVERLAY
-
- //Save that position for the next round
- testStart = testEnd;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CBaseSimpleCollision::ClearActivePlanes( void )
-{
- for ( int i = 0; i < MAX_COLLISION_PLANES; i++ )
- {
- m_collisionPlanes[i].m_Dist = -1.0f;
- m_collisionPlanes[i].m_Normal.Init();
- }
-
- m_nActivePlanes = 0;
-}
-
-//
-// CParticleCollision
-//
-
-//-----------------------------------------------------------------------------
-// Constructor
-//-----------------------------------------------------------------------------
-CParticleCollision::CParticleCollision( void )
-{
- m_flGravity = 800.0f;
- m_flCollisionDampen = 0.5f;
- m_flAngularCollisionDampen = 0.25f;
-
- ClearActivePlanes();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Test for surrounding collision surfaces for quick collision testing for the particle system
-// Input : &origin - starting position
-// *dir - direction of movement (if NULL, will do a point emission test in four directions)
-// angularSpread - looseness of the spread
-// minSpeed - minimum speed
-// maxSpeed - maximum speed
-// gravity - particle gravity for the sytem
-// dampen - dampening amount on collisions
-//-----------------------------------------------------------------------------
-void CParticleCollision::Setup( const Vector &origin, const Vector *dir, float angularSpread, float minSpeed, float maxSpeed, float gravity, float dampen )
-{
- //Take the information for this simulation
- m_flGravity = gravity;
- m_flCollisionDampen = dampen;
- m_nActivePlanes = 0;
-
- //We take a rough estimation of the spray
- float speedAvg = (minSpeed+maxSpeed)*0.5f;
-
- //Point or directed?
- if ( dir == NULL )
- {
- //Test all around
- TestForPlane( origin, Vector( 1, 0, 0 ), speedAvg, gravity );
- TestForPlane( origin, Vector( -1, 0, 0 ), speedAvg, gravity );
- TestForPlane( origin, Vector( 0, 1, 0 ), speedAvg, gravity );
- TestForPlane( origin, Vector( 0, -1, 0 ), speedAvg, gravity );
- TestForPlane( origin, Vector( 0, 0, 1 ), speedAvg, gravity );
- TestForPlane( origin, Vector( 0, 0, -1 ), speedAvg, gravity );
- }
- else
- {
- Vector vSkewDir, vRight;
- QAngle vAngles;
-
- //FIXME: Quicker conversion?
- //FIXME: We need to factor in the angular spread instead
- VectorAngles( *dir, vAngles );
- AngleVectors( vAngles, NULL, &vRight, NULL );
-
- //Test straight
- TestForPlane( origin, *dir, speedAvg, gravity );
-
- vSkewDir = vRight;
-
- //Test right
- TestForPlane( origin, vSkewDir, speedAvg, gravity );
-
- vSkewDir *= -1.0f;
-
- //Test left
- TestForPlane( origin, vSkewDir, speedAvg, gravity );
-
- #if __DEBUG_PARTICLE_COLLISION_OVERLAY
- DevMsg( 1, "CParticleCollision: Found %d active plane(s)\n", m_nActivePlanes );
- #endif //__DEBUG_PARTICLE_COLLISION_OVERLAY
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Simulate movement, with collision
-// Input : &origin - position of the particle
-// &velocity - velocity of the particle
-// &rollDelta - roll delta of the particle
-// timeDelta - time step
-//-----------------------------------------------------------------------------
-bool CParticleCollision::MoveParticle( Vector &origin, Vector &velocity, float *rollDelta, float timeDelta, trace_t *pTrace )
-{
- //Don't bother with non-moving particles
- if ( velocity == vec3_origin )
- return false;
-
- //Factor in gravity
- velocity[2] -= m_flGravity * timeDelta;
-
- //Move
- Vector testPosition = ( origin + ( velocity * timeDelta ) );
-
- //Only collide if we have active planes
- if ( m_nActivePlanes > 0 )
- {
- //Collide
- TraceLine( origin, testPosition, pTrace );
-
- //See if we hit something
- if ( pTrace->fraction != 1.0f )
- {
- #if __DEBUG_PARTICLE_COLLISION_RETEST
- //Retest the collision with a true trace line to avoid errant collisions
- UTIL_TraceLine( origin, testPosition, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, pTrace );
- #endif //__DEBUG_RETEST_COLLISION
-
- //Did we hit anything?
- if ( pTrace->fraction != 1.0f )
- {
- //See if we've settled
- if ( ( pTrace->plane.normal[2] >= 0.5f ) && ( fabs( velocity[2] ) <= 48.0f ) )
- {
- //Leave the particle at the collision point
- origin += velocity * ( (pTrace->fraction-COLLISION_EPSILON) * timeDelta );
-
- //Stop the particle
- velocity = vec3_origin;
-
- if ( rollDelta != NULL )
- {
- *rollDelta = 0.0f;
- }
-
- return false;
- }
- else
- {
- //Move the particle to the collision point
- origin += velocity * ( (pTrace->fraction-COLLISION_EPSILON) * timeDelta );
-
- //Find the reflection vector
- float proj = velocity.Dot( pTrace->plane.normal );
- velocity += pTrace->plane.normal * (-proj*2.0f);
-
- //Apply dampening
- velocity *= random->RandomFloat( (m_flCollisionDampen-0.1f), (m_flCollisionDampen+0.1f) );
-
- //Dampen the roll of the particles
- if ( rollDelta != NULL )
- {
- (*rollDelta) *= -0.25f;
- }
-
- return true;
- }
- }
- else
- {
- #if __DEBUG_PARTICLE_COLLISION_OVERLAY
- //Display a false hit
- debugoverlay->AddBoxOverlay( pTrace->endpos, Vector(-1,-1,-1), Vector(1,1,1), QAngle(0,0,0), 255, 0, 0, 16, __DEBUG_PARTICLE_COLLISION_OVERLAY_LIFETIME );
- #endif //__DEBUG_PARTICLE_COLLISION_OVERLAY
- }
- }
- }
-
- //Simple move, no collision
- origin = testPosition;
-
- return false;
-}
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Local fast collision system for particles +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "particle_collision.h" +#include "engine/ivdebugoverlay.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#ifdef _XBOX +#define __DEBUG_PARTICLE_COLLISION_RETEST 0 +#else +#define __DEBUG_PARTICLE_COLLISION_RETEST 1 +#endif // _XBOX + +#define __DEBUG_PARTICLE_COLLISION_OVERLAY 0 +#define __DEBUG_PARTICLE_COLLISION_OVERLAY_LIFETIME 0.1f + +#define NUM_DISCREET_STEPS 8.0f +#define NUM_SIMULATION_SECONDS 2.0f + +#define COLLISION_EPSILON 0.01f + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CBaseSimpleCollision::CBaseSimpleCollision( void ) +{ + ClearActivePlanes(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &origin - +// radius - +//----------------------------------------------------------------------------- +void CBaseSimpleCollision::Setup( const Vector &origin, float speed, float gravity ) +{ + TestForPlane( origin, Vector( 1, 0, 0 ), speed, gravity ); + TestForPlane( origin, Vector( -1, 0, 0 ), speed, gravity ); + TestForPlane( origin, Vector( 0, 1, 0 ), speed, gravity ); + TestForPlane( origin, Vector( 0, -1, 0 ), speed, gravity ); + TestForPlane( origin, Vector( 0, 0, 1 ), speed, gravity ); + TestForPlane( origin, Vector( 0, 0, -1 ), speed, gravity ); +} + +//----------------------------------------------------------------------------- +// Purpose: Trace line for super-simplified traces +// Input : &start - start position +// &end - end position +// *pTrace - trace structure to fill +// coarse - tests again with a real trace unless coarse is set +//----------------------------------------------------------------------------- +void CBaseSimpleCollision::TraceLine( const Vector &start, const Vector &end, trace_t *pTrace, bool coarse ) +{ + //Iterate over all active planes + for ( int i = 0; i < m_nActivePlanes; i++ ) + { + //Must be a valid plane + if ( m_collisionPlanes[i].m_Dist == -1.0f ) + continue; + + //Get our information about the relation to this plane + float dot1 = m_collisionPlanes[i].DistTo(start); + float dot2 = m_collisionPlanes[i].DistTo(end); + + //Don't consider particles on the backside of planes + if ( dot1 < -COLLISION_EPSILON ) + continue; + + //Must be crossing the plane's boundary + if ( ( dot1 > COLLISION_EPSILON ) == ( dot2 > COLLISION_EPSILON ) ) + continue; + + //Find the intersection point + float t = dot1 / (dot1 - dot2); + Vector vIntersection = start + (end - start) * t; + + //Fake the collision info + pTrace->endpos = vIntersection; + pTrace->fraction = t - COLLISION_EPSILON; + pTrace->plane.normal = m_collisionPlanes[i].m_Normal; + pTrace->plane.dist = m_collisionPlanes[i].m_Dist; + + //If we need an exact trace, test again on a successful hit + if ( ( coarse == false ) && ( pTrace->fraction < 1.0f ) ) + { + UTIL_TraceLine( start, end, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, pTrace ); + } + + #if __DEBUG_PARTICLE_COLLISION_OVERLAY + debugoverlay->AddBoxOverlay( vIntersection, Vector(-1,-1,-1), Vector(1,1,1), QAngle(0,0,0), 0, 255, 0, 16, __DEBUG_PARTICLE_COLLISION_OVERLAY_LIFETIME ); + #endif //__DEBUG_PARTICLE_COLLISION_OVERLAY + + //Done + return; + } + + //Fell through, so clear all the fields + pTrace->plane.normal[0] = 0.0f; + pTrace->plane.normal[1] = 0.0f; + pTrace->plane.normal[2] = 0.0f; + pTrace->plane.dist = 0.0f; + pTrace->fraction = 1.0f; + pTrace->allsolid = false; + pTrace->startsolid = false; + pTrace->m_pEnt = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Tests the planes against all others for validity +// Input : *plane - plane to test +//----------------------------------------------------------------------------- +void CBaseSimpleCollision::ConsiderPlane( cplane_t *plane ) +{ + //Test against all other active planes + for ( int i = 0; i < m_nActivePlanes; i++ ) + { + if ( m_collisionPlanes[i].m_Dist != -1.0f ) + { + //Test for coplanar + if ( ( m_collisionPlanes[i].m_Normal == plane->normal ) && ( m_collisionPlanes[i].m_Dist == plane->dist ) ) + return; + } + } + + //Don't overrun + if ( m_nActivePlanes >= MAX_COLLISION_PLANES ) + return; + + //Take it + m_collisionPlanes[m_nActivePlanes].m_Dist = plane->dist; + m_collisionPlanes[m_nActivePlanes].m_Normal = plane->normal; + m_nActivePlanes++; +} + +//----------------------------------------------------------------------------- +// Purpose: Runs a simulation of the average particle's movement, looking for collisions along the way +// Input : &start - start of the simulation +// &dir - direction of travel +// speed - speed of the particle +// gravity - gravity being used +//----------------------------------------------------------------------------- +void CBaseSimpleCollision::TestForPlane( const Vector &start, const Vector &dir, float speed, float gravity ) +{ + trace_t tr; + Vector testStart, testEnd; + + testStart = start; + + //Setup our step increments + float dStepTime = (NUM_SIMULATION_SECONDS/NUM_DISCREET_STEPS); + Vector vStepIncr = dir * ( speed * dStepTime ); + float flGravIncr = gravity*dStepTime; + + //Simulate collsions in discreet steps + for ( int i = 1; i <= NUM_DISCREET_STEPS; i++ ) + { + testEnd = testStart + vStepIncr; + testEnd[2] -= flGravIncr * (0.5f*(dStepTime*i)*(dStepTime*i) ); + + //Trace the line + UTIL_TraceLine( testStart, testEnd, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); + + //See if we found one + if ( tr.fraction != 1.0f ) + { + #if __DEBUG_PARTICLE_COLLISION_OVERLAY + debugoverlay->AddLineOverlay( testStart, tr.endpos, 255, 0, 0, true, __DEBUG_PARTICLE_COLLISION_OVERLAY_LIFETIME ); + + QAngle angles; + + VectorAngles( tr.plane.normal,angles ); + angles[PITCH] += 90; + + debugoverlay->AddBoxOverlay( tr.endpos, Vector(-64,-64,0), Vector(64,64,0), angles, 255, 0, 0, 16, __DEBUG_PARTICLE_COLLISION_OVERLAY_LIFETIME ); + #endif //__DEBUG_PARTICLE_COLLISION_OVERLAY + + //Test the plane against a set of criteria + ConsiderPlane( &tr.plane ); + + return; + } + + //We missed + #if __DEBUG_PARTICLE_COLLISION_OVERLAY + debugoverlay->AddLineOverlay( testStart, tr.endpos, 0, 128.0f+(128.0f*((float)i/(float)NUM_DISCREET_STEPS)), 0, true, __DEBUG_PARTICLE_COLLISION_OVERLAY_LIFETIME ); + #endif //__DEBUG_PARTICLE_COLLISION_OVERLAY + + //Save that position for the next round + testStart = testEnd; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseSimpleCollision::ClearActivePlanes( void ) +{ + for ( int i = 0; i < MAX_COLLISION_PLANES; i++ ) + { + m_collisionPlanes[i].m_Dist = -1.0f; + m_collisionPlanes[i].m_Normal.Init(); + } + + m_nActivePlanes = 0; +} + +// +// CParticleCollision +// + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +CParticleCollision::CParticleCollision( void ) +{ + m_flGravity = 800.0f; + m_flCollisionDampen = 0.5f; + m_flAngularCollisionDampen = 0.25f; + + ClearActivePlanes(); +} + +//----------------------------------------------------------------------------- +// Purpose: Test for surrounding collision surfaces for quick collision testing for the particle system +// Input : &origin - starting position +// *dir - direction of movement (if NULL, will do a point emission test in four directions) +// angularSpread - looseness of the spread +// minSpeed - minimum speed +// maxSpeed - maximum speed +// gravity - particle gravity for the sytem +// dampen - dampening amount on collisions +//----------------------------------------------------------------------------- +void CParticleCollision::Setup( const Vector &origin, const Vector *dir, float angularSpread, float minSpeed, float maxSpeed, float gravity, float dampen ) +{ + //Take the information for this simulation + m_flGravity = gravity; + m_flCollisionDampen = dampen; + m_nActivePlanes = 0; + + //We take a rough estimation of the spray + float speedAvg = (minSpeed+maxSpeed)*0.5f; + + //Point or directed? + if ( dir == NULL ) + { + //Test all around + TestForPlane( origin, Vector( 1, 0, 0 ), speedAvg, gravity ); + TestForPlane( origin, Vector( -1, 0, 0 ), speedAvg, gravity ); + TestForPlane( origin, Vector( 0, 1, 0 ), speedAvg, gravity ); + TestForPlane( origin, Vector( 0, -1, 0 ), speedAvg, gravity ); + TestForPlane( origin, Vector( 0, 0, 1 ), speedAvg, gravity ); + TestForPlane( origin, Vector( 0, 0, -1 ), speedAvg, gravity ); + } + else + { + Vector vSkewDir, vRight; + QAngle vAngles; + + //FIXME: Quicker conversion? + //FIXME: We need to factor in the angular spread instead + VectorAngles( *dir, vAngles ); + AngleVectors( vAngles, NULL, &vRight, NULL ); + + //Test straight + TestForPlane( origin, *dir, speedAvg, gravity ); + + vSkewDir = vRight; + + //Test right + TestForPlane( origin, vSkewDir, speedAvg, gravity ); + + vSkewDir *= -1.0f; + + //Test left + TestForPlane( origin, vSkewDir, speedAvg, gravity ); + + #if __DEBUG_PARTICLE_COLLISION_OVERLAY + DevMsg( 1, "CParticleCollision: Found %d active plane(s)\n", m_nActivePlanes ); + #endif //__DEBUG_PARTICLE_COLLISION_OVERLAY + } +} + +//----------------------------------------------------------------------------- +// Purpose: Simulate movement, with collision +// Input : &origin - position of the particle +// &velocity - velocity of the particle +// &rollDelta - roll delta of the particle +// timeDelta - time step +//----------------------------------------------------------------------------- +bool CParticleCollision::MoveParticle( Vector &origin, Vector &velocity, float *rollDelta, float timeDelta, trace_t *pTrace ) +{ + //Don't bother with non-moving particles + if ( velocity == vec3_origin ) + return false; + + //Factor in gravity + velocity[2] -= m_flGravity * timeDelta; + + //Move + Vector testPosition = ( origin + ( velocity * timeDelta ) ); + + //Only collide if we have active planes + if ( m_nActivePlanes > 0 ) + { + //Collide + TraceLine( origin, testPosition, pTrace ); + + //See if we hit something + if ( pTrace->fraction != 1.0f ) + { + #if __DEBUG_PARTICLE_COLLISION_RETEST + //Retest the collision with a true trace line to avoid errant collisions + UTIL_TraceLine( origin, testPosition, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, pTrace ); + #endif //__DEBUG_RETEST_COLLISION + + //Did we hit anything? + if ( pTrace->fraction != 1.0f ) + { + //See if we've settled + if ( ( pTrace->plane.normal[2] >= 0.5f ) && ( fabs( velocity[2] ) <= 48.0f ) ) + { + //Leave the particle at the collision point + origin += velocity * ( (pTrace->fraction-COLLISION_EPSILON) * timeDelta ); + + //Stop the particle + velocity = vec3_origin; + + if ( rollDelta != NULL ) + { + *rollDelta = 0.0f; + } + + return false; + } + else + { + //Move the particle to the collision point + origin += velocity * ( (pTrace->fraction-COLLISION_EPSILON) * timeDelta ); + + //Find the reflection vector + float proj = velocity.Dot( pTrace->plane.normal ); + velocity += pTrace->plane.normal * (-proj*2.0f); + + //Apply dampening + velocity *= random->RandomFloat( (m_flCollisionDampen-0.1f), (m_flCollisionDampen+0.1f) ); + + //Dampen the roll of the particles + if ( rollDelta != NULL ) + { + (*rollDelta) *= -0.25f; + } + + return true; + } + } + else + { + #if __DEBUG_PARTICLE_COLLISION_OVERLAY + //Display a false hit + debugoverlay->AddBoxOverlay( pTrace->endpos, Vector(-1,-1,-1), Vector(1,1,1), QAngle(0,0,0), 255, 0, 0, 16, __DEBUG_PARTICLE_COLLISION_OVERLAY_LIFETIME ); + #endif //__DEBUG_PARTICLE_COLLISION_OVERLAY + } + } + } + + //Simple move, no collision + origin = testPosition; + + return false; +} |