Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

536 lines
22 KiB

//========= Copyright © Valve Corporation, All rights reserved. ============//
//
// A port of CRnSoftbody
// Note: mathlib is tentative place for this code. We will probably move it to a separate lib or dll or vphysics.dll
//
#ifndef MATHLIB_SOFTBODY_HDR
#define MATHLIB_SOFTBODY_HDR
#include "rubikon/param_types.h"
#include "rubikon/debugname.h"
#include "rubikon/intersection.h"
// #include "rnmath.h"
// #include "geometry.h"
// #include "mass.h"
// #include "graphedge.h"
// #include "collisionfilter.h"
// #include "rnserialize.h"
// #include "legacyobject.h"
#include "tier1/utlbuffer.h"
#include "mathlib/femodel.h"
#include "tier1/hierarchicalbitvec.h"
#include "rubikon/serializehelpers.h"
class CRnSoftbodyDesc;
class CSoftbodyEnvironment;
class CRnBody;
class CRnJoint;
struct PhysSoftbodyDesc_t;
class CJob ;
class CSoftbody;
class CFeModel;
struct FilterTransformsParams_t;
struct SetNodePositionsParams_t;
class CFeModelReplaceContext;
class IVDebugOverlay;
class IMesh;
struct FilterTransformsParams_t
{
matrix3x4a_t *pOutputWorldTransforms;
const int16 *pCtrlToBone;
const uint32 *pValidTransforms;
VectorAligned *pNodePos;
bool flMatrixScale; // Scale to convey in matrices; 1.0 will not scale anything (appropriate for Hammer conventions). 0.0 means use the model scale (appropriate for game conventions)
};
struct SetNodePositionsParams_t
{
SetNodePositionsParams_t()
{
nFrame = 1;
}
const VectorAligned *pPos;
int nCount;
Vector vAbsOrigin;
QAngle vAbsAngles;
int nFrame;
};
class CParticleGlue
{
public:
float m_flStickiness;
float m_flWeight1; // 0: only use parent [0], >0 : blend from [0] to [1]
uint16 m_nParentNode[ 2 ]; // this is actual node index; we're mostly parented to static nodes
public:
CParticleGlue(){}
CParticleGlue( uint nParentNode, float flStickiness )
{
m_flStickiness = flStickiness;
m_flWeight1 = 0;
m_nParentNode[ 0 ] = m_nParentNode[ 1 ] = nParentNode;
}
};
class ALIGN16 CSoftbody
{
public:
CSoftbody( void );
CSoftbody( CSoftbodyEnvironment *pWorld, const CFeModel *pFeModel );
~CSoftbody();
void Shutdown( );
void Init( int numModelBones = 0);
void Init( CSoftbodyEnvironment *pWorld, const CFeModel *pFeModel, int numModelBones );
void InitFeModel( int numModelBones = 0 );
void InitDefaults( );
void Integrate( float flTimeStep );
void IntegrateWind( VectorAligned *pPos, float flTimeStep );
void RawSimulate( int nIterations, float flTimeStep );
void ValidatingSimulate( int nIterations, float flTimeStep );
void AddAnimationAttraction( float flTimeStep );
void Predict( float flTimeStep );
void Post( );
void Collide();
void CollideWithWorldInternal();
void CollideWithRigidsInternal();
// void CollideTaperedCapsule( uint16 nCollisionMask, const VectorAligned &vCenter0, float flRadius0, const VectorAligned &vCenter1, float flRadius1, const Vector &vAxis, float flDist );
// void CollideTaperedCapsule( uint16 nCollisionMask, const VectorAligned &vCenter0, float flRadius0, const VectorAligned &vCenter1, float flRadius1 );
// @begin_publish
uint Step( int nIterations, float flTimeStep );
uint Step( float flTimeStep );
uint GetStateHash()const;
void TouchAnimatedTransforms();
void SetAnimatedTransform( int nParticle, const matrix3x4a_t &transform );
void SetAnimatedTransforms( const matrix3x4a_t *pSimulationWorldTransforms );
void SetAnimatedTransformsNoScale( const matrix3x4a_t *pSimulationWorldTransforms );
matrix3x4a_t* GetParticleTransforms( const VectorAligned *pInputNodePos = NULL, uint nFlags = 0 );
const VectorAligned* GetNodePositions( int nFrame = 1 ) const { return nFrame ? m_pPos1 : m_pPos0; }
VectorAligned* GetNodePositions( int nFrame = 1 ) { return nFrame ? m_pPos1 : m_pPos0; }
void SetNodePositions( const Vector *pPos, int nCount, int nFrame = 1 );
void SetNodePositions( SetNodePositionsParams_t &params );
uint GetNodeCount() const { return m_nNodeCount; }
uint GetCtrlCount() const { return m_nParticleCount; }
Vector GetNodeVelocity( uint nNode ) const { return ( m_pPos1[ nNode ] - m_pPos0[ nNode ] ) / m_flLastTimestep; }
Vector GetCtrlVelocity( uint nCtrl ) const;
matrix3x4a_t* GetAnimatedTransforms( ) { return m_pParticles; }
const matrix3x4a_t* GetAnimatedTransforms() const { return m_pParticles; }
matrix3x4a_t* GetSimulatedTransforms() { return m_pParticles + m_nParticleCount; }
const matrix3x4a_t* GetSimulatedTransforms() const { return m_pParticles + m_nParticleCount; }
const CFeModel *GetFeModel()const { return m_pFeModel; }
CFeModel *GetFeModel( ){ return m_pFeModel; }
CSoftbodyEnvironment *GetEnvironment( ) const { return m_pEnvironment; }
int GetParticleCount( ) const { return m_nParticleCount; }
void SetDebugNameV( const char* pNameFormat, va_list args ) { m_DebugName.SetV( pNameFormat, args );}
const char *GetDebugName() const { return m_DebugName.Get(); }
void AppendDebugInfo( CUtlString &line );
void Draw( const RnDebugDrawOptions_t &options, IVDebugOverlay* pDebugOverlay );
void Draw( const RnDebugDrawOptions_t &options, IMesh *pDynamicMesh );
void SetPose() { SetPose( m_pFeModel->m_pInitPose ); }
void SetPose( const CTransform *pPose );
void SetPose( const CTransform &tm ) { SetPose( tm, m_pFeModel->m_pInitPose ); }
void SetPose( const CTransform &tm, const CTransform *pPose );
void SetPoseFromBones( const int16 *pCtrlToBone, const matrix3x4a_t *pBones, float flScale = 1.0f );
void SetCtrl( int nParticle, const CTransform &tm );
void SetDebugSelection( int nSelection );
void SetSimFlags( uint nNewSimFlags );
void AddSimFlags( uint nAddSimFlags ) { SetSimFlags( m_nSimFlags | nAddSimFlags ); }
void ClearSimFlags( uint nClearSimFlags ) { SetSimFlags( m_nSimFlags & ~nClearSimFlags ); }
void SetAnimSpace( PhysicsSoftbodyAnimSpace_t nAnimSpace ) { m_nAnimSpace = nAnimSpace; }
PhysicsSoftbodyAnimSpace_t GetAnimSpace()const { return m_nAnimSpace; }
uint GetSimFlags()const { return m_nSimFlags; }
int CastCone( const Vector &vStart, const Vector &vDir, float flConePitch );
uint GetContactCount( )const { return 0; }
void SetOverPredict( float flOverPredict ) { m_flOverPredict = flOverPredict; }
float GetOverPredict( ) const { return m_flOverPredict; }
void ResetVelocities( );
void SetThreadStretch( float flBendUnderRelax ) { m_flThreadStretch = flBendUnderRelax; }
float GetThreadStretch( )const { return m_flThreadStretch; }
void SetSurfaceStretch( float flStretchUnderRelax ) { m_flSurfaceStretch = flStretchUnderRelax; }
float GetSurfaceStretch( )const { return m_flSurfaceStretch; }
void SetStepUnderRelax( float flStepUnderRelax ) { m_flStepUnderRelax = flStepUnderRelax; }
float GetStepUnderRelax( void ) const { return m_flStepUnderRelax; }
AABB_t BuildBounds( )const;
void FilterTransforms( const FilterTransformsParams_t &params );
void FilterTransforms( matrix3x4a_t *pModelBones );
void SetGravityScale( float flScale ) { m_flGravityScale = flScale; }
void EnableGravity( bool bEnableGravity ) { m_bGravityDisabled = !bEnableGravity; }
void EnableGravity( ) { m_bGravityDisabled = false; }
void DisableGravity( ) { m_bGravityDisabled = true; }
bool IsGravityEnabled( ) const { return !m_bGravityDisabled; }
bool IsGravityDisabled( ) const { return m_bGravityDisabled; }
bool IsFtlPassEnabled( ) const { return m_bEnableFtlPass; }
void EnableFtlPass( bool bEnable ) { m_bEnableFtlPass = bEnable; }
float GetGravityScale( void ) const{ return m_flGravityScale; }
Vector GetEffectiveGravity( void ) const;
float GetEffectiveGravityScale( void ) const;
void EnableAnimationAttraction( bool bEnable ) { m_bEnableAnimationAttraction = bEnable; }
bool IsAnimationAttractionEnabled( )const { return m_bEnableAnimationAttraction; }
void EnableFollowNode( bool bEnable ) { m_bEnableFollowNodes = bEnable; }
bool IsFollowNodeEnabled( ) const { return m_bEnableFollowNodes; }
void EnableSprings( bool bEnable ){ m_bEnableSprings = bEnable; }
bool AreSpringsEnabled( )const { return m_bEnableSprings; }
void EnableInclusiveCollisionSpheres( bool bEnable ) { m_bEnableInclusiveCollisionSpheres = bEnable; }
bool AreInclusiveCollisionSpheresEnabled( ) const { return m_bEnableInclusiveCollisionSpheres; }
void EnableExclusiveCollisionSpheres( bool bEnable ) { m_bEnableExclusiveCollisionSpheres = bEnable; }
bool AreExclusiveCollisionSpheresEnabled( ) const { return m_bEnableExclusiveCollisionSpheres; }
void EnableCollisionPlanes( bool bEnable ) { m_bEnableCollisionPlanes = bEnable; }
bool AreCollisionPlanesEnabled( ) const { return m_bEnableCollisionPlanes; }
void EnableGroundCollision( bool bEnable ) { m_bEnableGroundCollision = bEnable; }
bool IsGroundCollisionEnabled( ) const { return m_bEnableGroundCollision; }
void EnableGroundTrace( bool bEnable ) { m_bEnableGroundTrace = bEnable; }
bool IsGroundTraceEnabled( ) const { return m_bEnableGroundTrace; }
float GetTimeStep( void )const { return m_flLastTimestep; }
void SetModelScale( float flModelScale ) { m_flModelScale = flModelScale; }
float GetModelScale( )const { return m_flModelScale; }
void SetVelocityDamping( float flDamping ) { m_flVelocityDamping = flDamping; } // 1.0f - full damping; 0.0 - no damping (default)
float GetVelocityDamping( )const { return m_flVelocityDamping; }
void SetUserData( uint nIndex, void *pData );
void* GetUserData( uint nIndex );
//void SetOrigin( const Vector &vAbsOrigin );
void InitializeTransforms( const int16 *pCtrlToBone, const matrix3x4a_t *pSimulationWorldTransforms );
void SetAbsAngles( const QAngle &vNewAngles, bool bTeleport );
const QAngle GetAbsAngles() const { return m_vSimAngles; }
void SetAbsOrigin( const Vector &vNewOrigin, bool bTeleport );
const Vector GetAbsOrigin()const { return m_vSimOrigin; }
float GetEnergy( PhysicsSoftbodyEnergyTypeEnum_t nEnergy )const;
float GetElasticEnergy( )const;
float GetPotentialEnergy( )const;
float GetKinematicEnergy( )const;
void SetDampingMultiplier( float flMul ) { m_flDampingMultiplier = flMul; }
float GetDampingMultiplier( )const { return m_flDampingMultiplier; }
void SetGroundZ( float flGroundZ ) { m_vGround.Init( m_vSimOrigin.x, m_vSimOrigin.y, flGroundZ ); }
float GetGroundZ( )const { return m_vGround.z; }
bool IsDormant( )const;
void GoDormant( );
bool AdvanceSleepCounter();
void GoWakeup( );
bool IsActive()const;
bool BeforeFilterTransforms( );
void SetDebugDrawTreeBeginLevel( int nLevel ) { m_nDebugDrawTreeBeginLevel = nLevel; }
int GetDebugDrawTreeBeginLevel() { return m_nDebugDrawTreeBeginLevel; }
void SetDebugDrawTreeEndLevel( int nLevel ) { m_nDebugDrawTreeEndLevel = nLevel; }
int GetDebugDrawTreeEndLevel() { return m_nDebugDrawTreeEndLevel; }
void SetDebugDrawTreeFlags( uint nFlags ) { m_nDebugDrawTreeFlags = nFlags; }
uint GetDebugDrawTreeFlags(){ return m_nDebugDrawTreeFlags; }
void EnableDebugDraw( bool bEnable ){ m_bDebugDraw = bEnable; }
void EnableDebugRendering( bool bEnable );
float GetVelAirDrag() const { return m_flVelAirDrag; }
void SetVelAirDrag( float flVelAirDrag ){ m_flVelAirDrag = flVelAirDrag; }
float GetExpAirDrag() const { return m_flExpAirDrag; }
void SetExpAirDrag( float flExpAirDrag ){ m_flExpAirDrag = flExpAirDrag; }
float GetVelQuadAirDrag() const { return m_flVelQuadAirDrag; }
void SetVelQuadAirDrag( float flVelQuadAirDrag ){ m_flVelQuadAirDrag = flVelQuadAirDrag; }
float GetExpQuadAirDrag() const { return m_flExpQuadAirDrag; }
void SetExpQuadAirDrag( float flExpQuadAirDrag ){ m_flExpQuadAirDrag = flExpQuadAirDrag; }
float GetVelRodAirDrag() const { return m_flVelRodAirDrag; }
void SetVelRodAirDrag( float flVelRodAirDrag ){ m_flVelRodAirDrag = flVelRodAirDrag; }
float GetExpRodAirDrag() const { return m_flExpRodAirDrag; }
void SetExpRodAirDrag( float flExpRodAirDrag ){ m_flExpRodAirDrag = flExpRodAirDrag; }
float GetQuadVelocitySmoothRate()const { return m_flQuadVelocitySmoothRate; }
void SetQuadVelocitySmoothRate( float flRate ){ m_flQuadVelocitySmoothRate = flRate; }
float GetRodVelocitySmoothRate()const { return m_flRodVelocitySmoothRate; }
void SetRodVelocitySmoothRate( float flRate ){ m_flRodVelocitySmoothRate = flRate; }
uint16 GetQuadVelocitySmoothIterations()const { return m_nQuadVelocitySmoothIterations; }
void SetQuadVelocitySmoothIterations( uint16 nIterations ){ m_nQuadVelocitySmoothIterations = nIterations; }
uint16 GetRodVelocitySmoothIterations()const { return m_nRodVelocitySmoothIterations; }
void SetRodVelocitySmoothIterations( uint16 nIterations ){ m_nRodVelocitySmoothIterations = nIterations; }
const RnCollisionAttr_t &GetCollisionAttributes() const { return m_CollisionAttributes; }
void SetCollisionAttributes( const RnCollisionAttr_t &attr );
int GetIndexInWorld() const { return m_nIndexInWorld; }
void ReplaceFeModel( CFeModelReplaceContext &context );
matrix3x4_t GetDifferenceTransform( const Vector &vAltOrigin, const QAngle &vAltAngles );
void ComputeInterpolatedNodePositions( float flFactor, VectorAligned *pPosOut );
void SetInstanceSettings( void *pSettings );
void SetFrozen( bool bFrozen ) { m_bFrozen = true; }
bool IsFrozen()const { return m_bFrozen; }
void SetVolumetricSolveAmount( float flVolumetricSolveAmount ) { m_flVolumetricSolveAmount = flVolumetricSolveAmount; }
float GetVolumetricSolveAmount()const { return m_flVolumetricSolveAmount; }
void ParseParticleState( CUtlBuffer &buf, float flTimeStep );
CUtlString PrintParticleState( )const;
int16 *GetModelBoneToCtrl() { return m_pModelBoneToCtrl; }
void BindModelBoneToCtrl( int nModelBone, int nCtrl );
//bool SetupCtrl( uint nCtrl, matrix3x4a_t &writeBone );
// @end_publish
void DebugDump( );
void UpdateCtrlOffsets( bool bOverridePose );
uint ComputeVirtualCtrls( CVarBitVec &virtualNodes );
matrix3x4a_t &GetAnim( int i ) { return GetAnimatedTransforms()[ i ]; }
const matrix3x4a_t &GetAnim( int i ) const { return GetAnimatedTransforms()[ i ]; }
matrix3x4a_t &GetSim( int i ) { return GetSimulatedTransforms()[ i ]; }
const matrix3x4a_t &GetSim( int i ) const { return GetSimulatedTransforms()[ i ]; }
uint ShouldUsePreconditioner()const { return m_nSimFlags & ( SOFTBODY_SIM_DIAGONAL_PRECONDITIONER | SOFTBODY_SIM_TRIDIAGONAL_PRECONDITIONER | SOFTBODY_SIM_RELAXATION_PRECONDITIONER ); }
class CWorldIndexPred
{
public:
static int GetIndex( const CSoftbody *pBody ) { return pBody->m_nIndexInWorld; }
static void SetIndex( CSoftbody *pBody, int nIndex ) { pBody->m_nIndexInWorld = nIndex; }
};
friend class CWorldIndexPred;
uint GetParticleArrayCount( ) const { return m_nParticleCount * 2; }
void Validate();
void DebugPreStep( float flTimeStep );
void DebugPostStep();
class CConstraintIterator
{
public:
CConstraintIterator( CSoftbody *pSoftbody );
~CConstraintIterator( );
void Iterate( int nIterations );
protected:
CSoftbody *m_pSoftbody;
CSoftbodyEnvironment *m_pEnvironment;
CUtlVectorFixedGrowable< VectorAligned, 128 > m_PosBeforeCorrect; // the biggest hero in source1 is Medusa, with 104 nodes (52 useful, 52 virtual)
};
friend class CConstraintIterator;
void GlueNode( uint nDynNode, uint nParentNode, float flStickiness );
void GlueNode( uint nDynNode, uint nParentNode0, uint nParentNode1, float flStickiness, float flWeight1 );
void GlueNode( uint nDynNode, const CParticleGlue &glue, float flReplacementStickiness );
void DebugTraceMove( const char *pMsg );
protected:
void Integrate_S1( float flTimeStep );
void ResolveStretch_S1( float flTimeStep );
void ResolveAnimAttraction_S1( float flTimeStep );
protected:
friend class CRnSoftbodyChangeGuard;
CRnDebugName m_DebugName;
CSoftbodyEnvironment *m_pEnvironment;
RnCollisionAttr_t m_CollisionAttributes;
CFeModel *m_pFeModel; // Finite Element Model
float m_flThreadStretch; // positive: underrelax; negative: overrelax
float m_flSurfaceStretch;
float m_flStepUnderRelax;
float m_flOverPredict; // 0 : normal integration; positive: overpredict, correct, step back
float m_flGravityScale;
uint m_nNodeCount; // actual simulated node count (includes static and dynamic nodes: even though static nodes are not simulated, we need their coordinates to simulate the other nodes connected to them)
uint m_nParticleCount; // Ctrl count
float m_flModelScale;
float m_flVelocityDamping;
float m_flDampingMultiplier;
float m_flClothScale;
Vector m_vGround;
Vector m_vSimOrigin;
QAngle m_vSimAngles;
matrix3x4a_t *m_pParticles SERIALIZE_ARRAY_SIZE( GetParticleArrayCount() );
VectorAligned *m_pPos0 SERIALIZE_ARRAY_SIZE( m_nNodeCount );
VectorAligned *m_pPos1 SERIALIZE_ARRAY_SIZE( m_nNodeCount );
FeAabb_t *m_pAabb SERIALIZE_ARRAY_SIZE( m_pFeModel->GetDynamicNodeCount() - 1 );
int16 *m_pModelBoneToCtrl;
int16 *m_pCtrlToModelBone;
CHierarchicalBitVector m_StickyBuffer; // sticky particles
CParticleGlue *m_pParticleGlue SERIALIZE_ARRAY_SIZE( m_pFeModel->GetDynamicNodeCount() );
enum StateEnum_t
{
STATE_ACTIVE, // actively simulating, taking in transforms, filtering out transforms
STATE_DORMANT,// not simulating, not taking in transforms, not filtering anything
STATE_WAKEUP, // StateCounter == 0 : not simulating, readying to take in transforms, not filtering anything, not copying transforms
// StateCounter > 0 : not simulating, taking in transforms, not filtering anything, copying transforms
STEPS_INVISIBLE_BEFORE_DORMANT = 12,
FRAMES_INVISIBLE_BEFORE_DORMANT = 3
};
uint32 m_nSimFlags;
uint32 m_nStepsSimulated;
int8 m_nDebugDrawTreeEndLevel;
int8 m_nDebugDrawTreeBeginLevel;
uint8 m_nDebugDrawTreeFlags;
// STATE_ACTIVE: how many steps we've taken without having FilterTransforms called once
// STATE_DORMANT: doesn't matter
// STATE_WAKEUP: how many times we've set animated transforms (need 2 to switch to ACTIVE state)
uint8 m_nStateCounter;
float m_flLastTimestep;
float m_flVelAirDrag;
float m_flExpAirDrag;
float m_flVelQuadAirDrag;
float m_flExpQuadAirDrag;
float m_flVelRodAirDrag;
float m_flExpRodAirDrag;
float m_flQuadVelocitySmoothRate;
float m_flRodVelocitySmoothRate;
float m_flVolumetricSolveAmount;
uint16 m_nQuadVelocitySmoothIterations;
uint16 m_nRodVelocitySmoothIterations;
int m_nIndexInWorld;
int m_nDebugSelection;
Vector m_vRopeOffset; // <sergiy> a horrible S1 cloth rope hack I'm faithfully replicating so that dota cloth looks exactly the same
uintp m_pUserData[ 2 ] ;
StateEnum_t m_nActivityState;
//uint m_nDebugNode;
uint8 m_nEnableWorldShapeCollision : 4;
PhysicsSoftbodyAnimSpace_t m_nAnimSpace : 2;
bool m_bAnimTransformChanged : 1; // True means that the animation transforms, that the game sets from outside, have changed and need to be propagated into the simulation
bool m_bSimTransformsOutdated : 1; // True means that the sim transforms, that the game queries from outside, are out of date and need to be copied from the simulation (and their rotations computed)
bool m_bGravityDisabled : 1;
bool m_bEnableAnimationAttraction : 1;
bool m_bEnableFollowNodes : 1;
bool m_bEnableSprings : 1;
bool m_bEnableInclusiveCollisionSpheres : 1;
bool m_bEnableExclusiveCollisionSpheres : 1;
bool m_bEnableCollisionPlanes : 1;
bool m_bEnableGroundCollision : 1;
bool m_bEnableGroundTrace : 1;
bool m_bEnableFtlPass : 1;
bool m_bFrozen : 1;
bool m_bDebugDraw : 1;
bool m_bEnableSimd : 1;
/*
bool m_bTeleportOnNextSetAbsOrigin : 1;
bool m_bTeleportOnNextSetAbsAngles : 1;
*/
friend class CTaperedCapsuleColliderFunctor;
friend class CGluePredictFunctor;
friend class CSphereColliderFunctor;
} ALIGN16_POST;
inline void CSoftbody::GlueNode( uint nDynNode, uint nParentNode, float flStickiness )
{
Assert( nDynNode < m_pFeModel->GetDynamicNodeCount() );
m_StickyBuffer.Set( nDynNode );
CParticleGlue &glue = m_pParticleGlue[ nDynNode ];
glue.m_flStickiness = flStickiness;
glue.m_flWeight1 = 0;
glue.m_nParentNode[ 0 ] = nParentNode;
glue.m_nParentNode[ 1 ] = nParentNode;
}
inline void CSoftbody::GlueNode( uint nDynNode, uint nParentNode0, uint nParentNode1, float flStickiness, float flWeight1 )
{
Assert( nDynNode < m_pFeModel->GetDynamicNodeCount() );
m_StickyBuffer.Set( nDynNode );
CParticleGlue &glue = m_pParticleGlue[ nDynNode ];
glue.m_flStickiness = flStickiness;
glue.m_flWeight1 = flWeight1;
glue.m_nParentNode[ 0 ] = nParentNode0;
glue.m_nParentNode[ 1 ] = nParentNode1;
}
inline void CSoftbody::GlueNode( uint nDynNode, const CParticleGlue &glueBase, float flReplacementStickiness )
{
m_StickyBuffer.Set( nDynNode );
CParticleGlue &glueNode = m_pParticleGlue[ nDynNode ];
glueNode.m_flStickiness = flReplacementStickiness;
glueNode.m_flWeight1 = glueBase.m_flWeight1; // 0: only use parent [0], >0 : blend from [0] to [1]
glueNode.m_nParentNode[ 0 ] = glueBase.m_nParentNode[ 0 ];
glueNode.m_nParentNode[ 1 ] = glueBase.m_nParentNode[ 1 ];
}
class CSphereColliderFunctor
{
public:
VectorAligned m_Sphere;
VectorAligned *m_pDynPos1;
const float *m_pNodeCollisionRadii;
CSoftbody *m_pSoftbody;
float m_flStickiness;
uint16 m_nParentNode; // needed for gluing particle to this node
public:
CSphereColliderFunctor(){}
CSphereColliderFunctor( CSoftbody *pSoftbody, const Vector &vSphereCenter, float flSphereRadius, float flStickiness, uint16 nParentNode )
{
m_flStickiness = flStickiness;
m_nParentNode = nParentNode;
m_pSoftbody = pSoftbody;
m_Sphere = vSphereCenter;
m_Sphere.w = flSphereRadius;
const CFeModel *pFeModel = pSoftbody->GetFeModel();
m_pDynPos1 = pSoftbody->m_pPos1 + pFeModel->m_nStaticNodes;
m_pNodeCollisionRadii = pFeModel->m_pNodeCollisionRadii;
}
void Collide( uint16 nCollisionMask );
};
class CTaperedCapsuleColliderFunctor
{
public:
VectorAligned m_vSphereCenter0;
VectorAligned m_vSphereCenter1;
VectorAligned *m_pDynPos1;
const float *m_pNodeCollisionRadii;
CSoftbody *m_pSoftbody;
float m_flStickiness;
uint16 m_nParentNode[ 2 ];
float m_flSlope;
Vector m_vAxisX;
float m_flDist;
public:
CTaperedCapsuleColliderFunctor(){}
CTaperedCapsuleColliderFunctor( CSoftbody *pSoftbody, const Vector &vSphereCenter0, float flSphereRadius0, const Vector &vSphereCenter1, float flSphereRadius1, float flStickiness, uint16 nParentNodes0, uint16 nParentNodes1 )
{
m_pSoftbody = pSoftbody;
m_vSphereCenter0 = vSphereCenter0;
m_vSphereCenter0.w = flSphereRadius0;
m_vSphereCenter1 = vSphereCenter1;
m_vSphereCenter1.w = flSphereRadius1;
m_flStickiness = flStickiness;
m_nParentNode[ 0 ] = nParentNodes0;
m_nParentNode[ 1 ] = nParentNodes1;
const CFeModel *pFeModel = pSoftbody->GetFeModel();
m_pDynPos1 = pSoftbody->m_pPos1 + pFeModel->m_nStaticNodes;
m_pNodeCollisionRadii = pFeModel->m_pNodeCollisionRadii;
m_vAxisX = ( vSphereCenter1 - vSphereCenter0 ) ;
m_flDist = m_vAxisX.Length();
m_vAxisX /= m_flDist;
m_flSlope = ( flSphereRadius1 - flSphereRadius0 ) / m_flDist;
}
void Collide( uint16 nCollisionMask );
};
#endif