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.

290 lines
11 KiB

//=================================================================================================
//
// A physics object
//
//=================================================================================================
#pragma once
class IPredictedPhysicsObject;
class IJoltObjectDestroyedListener;
class JoltPhysicsShadowController;
class JoltPhysicsFluidController;
class JoltPhysicsEnvironment;
class JoltPhysicsObject;
#if defined( GAME_CSGO_OR_NEWER )
using IPhysicsObjectInterface = IPredictedPhysicsObject;
#else
using IPhysicsObjectInterface = IPhysicsObject;
#endif
class JoltPhysicsObject final : public IPhysicsObjectInterface
{
public:
JoltPhysicsObject( JPH::Body *pBody, JoltPhysicsEnvironment *pEnvironment, bool bStatic, int nMaterialIndex, const objectparams_t *pParams );
JoltPhysicsObject( JPH::Body *pBody, JoltPhysicsEnvironment *pEnvironment, void *pGameData, JPH::StateRecorder &recorder );
~JoltPhysicsObject() override;
bool IsStatic() const override;
bool IsAsleep() const override;
bool IsTrigger() const override;
bool IsFluid() const override;
bool IsHinged() const override;
bool IsCollisionEnabled() const override;
bool IsGravityEnabled() const override;
bool IsDragEnabled() const override;
bool IsMotionEnabled() const override;
bool IsMoveable() const override; // legacy: IsMotionEnabled() && !IsStatic()
bool IsAttachedToConstraint( bool bExternalOnly ) const override;
void EnableCollisions( bool enable ) override;
void EnableGravity( bool enable ) override;
void EnableDrag( bool enable ) override;
void EnableMotion( bool enable ) override;
void SetGameData( void *pGameData ) override;
void * GetGameData() const override;
void SetGameFlags( unsigned short userFlags ) override;
unsigned short GetGameFlags() const override;
void SetGameIndex( unsigned short gameIndex ) override;
unsigned short GetGameIndex() const override;
void SetCallbackFlags( unsigned short callbackflags ) override;
unsigned short GetCallbackFlags() const override;
void Wake() override;
void Sleep() override;
void RecheckCollisionFilter() override;
void RecheckContactPoints( bool bSearchForNewContacts ) override_portal2;
void RecheckContactPoints() override_not_portal2 { RecheckContactPoints( false ); }
void SetMass( float mass ) override;
float GetMass() const override;
float GetInvMass() const override;
Vector GetInertia() const override;
Vector GetInvInertia() const override;
void SetInertia( const Vector &inertia ) override;
void SetDamping( const float *speed, const float *rot ) override;
void GetDamping( float *speed, float *rot ) const override;
void SetDragCoefficient( float *pDrag, float *pAngularDrag ) override;
void SetBuoyancyRatio( float ratio ) override;
int GetMaterialIndex() const override;
void SetMaterialIndex( int materialIndex ) override;
unsigned int GetContents() const override;
void SetContents( unsigned int contents ) override;
float GetSphereRadius() const override;
void SetSphereRadius( float radius ) override_asw;
float GetEnergy() const override;
Vector GetMassCenterLocalSpace() const override;
void SetPosition( const Vector &worldPosition, const QAngle &angles, bool isTeleport ) override;
void SetPositionMatrix( const matrix3x4_t &matrix, bool isTeleport ) override;
void GetPosition( Vector *worldPosition, QAngle *angles ) const override;
void GetPositionMatrix( matrix3x4_t *positionMatrix ) const override;
void SetVelocity( const Vector *velocity, const AngularImpulse *angularVelocity ) override;
void SetVelocityInstantaneous( const Vector *velocity, const AngularImpulse *angularVelocity ) override;
void GetVelocity( Vector *velocity, AngularImpulse *angularVelocity ) const override;
void AddVelocity( const Vector *velocity, const AngularImpulse *angularVelocity ) override;
void GetVelocityAtPoint( const Vector &worldPosition, Vector *pVelocity ) const override;
void GetImplicitVelocity( Vector *velocity, AngularImpulse *angularVelocity ) const override;
void LocalToWorld( Vector *worldPosition, const Vector &localPosition ) const override;
void WorldToLocal( Vector *localPosition, const Vector &worldPosition ) const override;
void LocalToWorldVector( Vector *worldVector, const Vector &localVector ) const override;
void WorldToLocalVector( Vector *localVector, const Vector &worldVector ) const override;
void ApplyForceCenter( const Vector &forceVector ) override;
void ApplyForceOffset( const Vector &forceVector, const Vector &worldPosition ) override;
void ApplyTorqueCenter( const AngularImpulse &torque ) override;
void CalculateForceOffset( const Vector &forceVector, const Vector &worldPosition, Vector *centerForce, AngularImpulse *centerTorque ) const override;
void CalculateVelocityOffset( const Vector &forceVector, const Vector &worldPosition, Vector *centerVelocity, AngularImpulse *centerAngularVelocity ) const override;
float CalculateLinearDrag( const Vector &unitDirection ) const override;
float CalculateAngularDrag( const Vector &objectSpaceRotationAxis ) const override;
bool GetContactPoint( Vector *contactPoint, IPhysicsObject **contactObject ) const override;
void SetShadow( float maxSpeed, float maxAngularSpeed, bool allowPhysicsMovement, bool allowPhysicsRotation ) override;
void UpdateShadow( const Vector &targetPosition, const QAngle &targetAngles, bool tempDisableGravity, float timeOffset ) override;
int GetShadowPosition( Vector *position, QAngle *angles ) const override;
IPhysicsShadowController * GetShadowController() const override;
void RemoveShadowController() override;
float ComputeShadowControl( const hlshadowcontrol_params_t &params, float secondsToArrival, float dt ) override;
const CPhysCollide * GetCollide() const override;
const char * GetName() const override;
void BecomeTrigger() override;
void RemoveTrigger() override;
void BecomeHinged( int localAxis ) override;
void RemoveHinged() override;
IPhysicsFrictionSnapshot *CreateFrictionSnapshot() override;
void DestroyFrictionSnapshot( IPhysicsFrictionSnapshot *pSnapshot ) override;
void OutputDebugInfo() const override;
#if OBJECT_WELDING
void WeldToObject( IPhysicsObject *pParent ) override;
void RemoveWeld( IPhysicsObject *pOther ) override;
void RemoveAllWelds() override;
#endif
void SetUseAlternateGravity( bool bSet ) override_asw;
void SetCollisionHints( uint32 collisionHints ) override_asw;
uint32 GetCollisionHints() const override_asw;
IPredictedPhysicsObject * GetPredictedInterface() const override_csgo;
void SyncWith( IPhysicsObject *pOther ) override_csgo;
void SetErrorDelta_Position( const Vector& vPosition ) override_csgo {}
void SetErrorDelta_Velocity( const Vector& vVelocity ) override_csgo {}
public:
JoltPhysicsEnvironment *GetEnvironment() { return m_pEnvironment; }
JPH::BodyID GetBodyID() { return m_pBody->GetID(); }
JPH::Body *GetBody() { return m_pBody; }
void UpdateEnvironment( JoltPhysicsEnvironment *pEnvironment );
void AddDestroyedListener( IJoltObjectDestroyedListener *pListener );
void RemoveDestroyedListener( IJoltObjectDestroyedListener *pListener );
// Grabs the position, adds addPos and teleports the object
void AddToPosition( JPH::Vec3Arg addPos );
// Only sets the position, and nothing else.
void SetPosition( const Vector &worldPosition );
// Adds to the velocity (Source space)
void AddVelocity( const Vector &worldPosition );
Vector GetVelocity();
void CalculateBuoyancy();
float GetMaterialDensity() const;
float GetBuoyancyRatio() const;
float GetVolume() const { return m_flVolume; }
bool IsControlledByGame() const;
void AddCallbackFlags( uint16 flags ) { m_callbackFlags |= flags; }
void RemoveCallbackFlags( uint16 flags ) { m_callbackFlags &= ~flags; }
void SaveObjectState( JPH::StateRecorder &recorder );
void RestoreObjectState( JPH::StateRecorder &recorder );
unsigned short GetGameMaterial() const
{
return m_GameMaterial;
}
bool GetGameMaterialAllowsSounds() const
{
return m_GameMaterial != 'X';
}
JoltPhysicsFluidController *GetFluidController()
{
return m_pFluidController;
}
void SetFluidController( JoltPhysicsFluidController *pFluidController )
{
m_pFluidController = pFluidController;
}
// Fakes a linear velocity so we can have correct before/after velocity
// when going between PreCollision and PostCollision callbacks.
JPH::Vec3 FakeJoltLinearVelocity( JPH::Vec3Arg fakeVelocity )
{
if ( m_pBody->IsStatic() )
return JPH::Vec3::sZero();
JPH::Vec3 oldVel = m_pBody->GetLinearVelocity();
m_pBody->SetLinearVelocity( fakeVelocity );
return oldVel;
}
void RestoreJoltLinearVelocity( JPH::Vec3Arg realVelocity )
{
if ( m_pBody->IsStatic() )
return;
m_pBody->SetLinearVelocity( realVelocity );
}
private:
void UpdateMaterialProperties();
void UpdateLayer();
// Josh:
// Always put m_pGameData first. Some games that will
// remain un-named offset by the vtable to get to this
// instead of calling GetGameData().
void *m_pGameData = nullptr;
uint16 m_gameFlags = 0;
uint16 m_gameIndex = 0;
uint16 m_callbackFlags = CALLBACK_GLOBAL_COLLISION|CALLBACK_GLOBAL_FRICTION|CALLBACK_FLUID_TOUCH|CALLBACK_GLOBAL_TOUCH|CALLBACK_GLOBAL_COLLIDE_STATIC|CALLBACK_DO_FLUID_SIMULATION;
uint32 m_collisionHints = 0;
bool m_bStatic = false;
bool m_bPinned = false;
int m_materialIndex = 0;
uint m_contents = CONTENTS_SOLID;
// Need this as Jolt gets very unhappy about reading motion
// properties of static objects.
float m_flCachedMass = 0.0f;
float m_flCachedInvMass = 0.0f;
bool m_bCachedCollisionEnabled = true;
float m_flMaterialDensity = 1.0f; // Material density in Jolt space.
float m_flBuoyancyRatio = 0.0f;
float m_flVolume = 0.0f;
unsigned short m_GameMaterial = 0;
CUtlVector< IJoltObjectDestroyedListener * > m_destroyedListeners;
// Shadow variables
JoltPhysicsShadowController *m_pShadowController = nullptr;
JoltPhysicsFluidController *m_pFluidController = nullptr;
bool m_bShadowTemporarilyDisableGravity = false;
JPH::Body *m_pBody = nullptr; // Underlying Jolt body
JoltPhysicsEnvironment *m_pEnvironment = nullptr; // Physics environment this body belongs to
JPH::PhysicsSystem *m_pPhysicsSystem = nullptr; // Physics system this body belongs to
};
// Josh: This doesn't handle mass change and is kind of a hack and sliightly wrong.
// Would be nice to just specify spring constant directly in Jolt.
inline float GetInvEffectiveMass( JoltPhysicsObject *pObject0, JoltPhysicsObject *pObject1 )
{
return ( pObject0->IsStatic() ? 0.0f : pObject0->GetInvMass() ) + ( pObject1->IsStatic() ? 0.0f : pObject1->GetInvMass() );
}
inline float GetSpringFrequency( float flConstant, JoltPhysicsObject *pObject0, JoltPhysicsObject *pObject1 )
{
return sqrt( flConstant * GetInvEffectiveMass( pObject0, pObject1 ) ) / ( 2.0f * M_PI_F );
}