diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /sp/src/game/shared/collisionproperty.h | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'sp/src/game/shared/collisionproperty.h')
| -rw-r--r-- | sp/src/game/shared/collisionproperty.h | 503 |
1 files changed, 503 insertions, 0 deletions
diff --git a/sp/src/game/shared/collisionproperty.h b/sp/src/game/shared/collisionproperty.h new file mode 100644 index 00000000..124073a3 --- /dev/null +++ b/sp/src/game/shared/collisionproperty.h @@ -0,0 +1,503 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef COLLISIONPROPERTY_H
+#define COLLISIONPROPERTY_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "networkvar.h"
+#include "engine/ICollideable.h"
+#include "mathlib/vector.h"
+#include "ispatialpartition.h"
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+class CBaseEntity;
+class IHandleEntity;
+class QAngle;
+class Vector;
+struct Ray_t;
+class IPhysicsObject;
+
+
+//-----------------------------------------------------------------------------
+// Force spatial partition updates (to avoid threading problems caused by lazy update)
+//-----------------------------------------------------------------------------
+void UpdateDirtySpatialPartitionEntities();
+
+
+//-----------------------------------------------------------------------------
+// Specifies how to compute the surrounding box
+//-----------------------------------------------------------------------------
+enum SurroundingBoundsType_t
+{
+ USE_OBB_COLLISION_BOUNDS = 0,
+ USE_BEST_COLLISION_BOUNDS, // Always use the best bounds (most expensive)
+ USE_HITBOXES,
+ USE_SPECIFIED_BOUNDS,
+ USE_GAME_CODE,
+ USE_ROTATION_EXPANDED_BOUNDS,
+ USE_COLLISION_BOUNDS_NEVER_VPHYSICS,
+
+ SURROUNDING_TYPE_BIT_COUNT = 3
+};
+
+
+//-----------------------------------------------------------------------------
+// Encapsulates collision representation for an entity
+//-----------------------------------------------------------------------------
+class CCollisionProperty : public ICollideable
+{
+ DECLARE_CLASS_NOBASE( CCollisionProperty );
+ DECLARE_EMBEDDED_NETWORKVAR();
+ DECLARE_PREDICTABLE();
+
+#ifdef GAME_DLL
+ DECLARE_DATADESC();
+#endif
+
+public:
+ CCollisionProperty();
+ ~CCollisionProperty();
+
+ void Init( CBaseEntity *pEntity );
+
+ // Methods of ICollideable
+ virtual IHandleEntity *GetEntityHandle();
+ virtual const Vector& OBBMinsPreScaled() const { return m_vecMinsPreScaled.Get(); }
+ virtual const Vector& OBBMaxsPreScaled() const { return m_vecMaxsPreScaled.Get(); }
+ virtual const Vector& OBBMins() const { return m_vecMins.Get(); }
+ virtual const Vector& OBBMaxs() const { return m_vecMaxs.Get(); }
+ virtual void WorldSpaceTriggerBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) const;
+ virtual bool TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr );
+ virtual bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr );
+ virtual int GetCollisionModelIndex();
+ virtual const model_t* GetCollisionModel();
+ virtual const Vector& GetCollisionOrigin() const;
+ virtual const QAngle& GetCollisionAngles() const;
+ virtual const matrix3x4_t& CollisionToWorldTransform() const;
+ virtual SolidType_t GetSolid() const;
+ virtual int GetSolidFlags() const;
+ virtual IClientUnknown* GetIClientUnknown();
+ virtual int GetCollisionGroup() const;
+ virtual void WorldSpaceSurroundingBounds( Vector *pVecMins, Vector *pVecMaxs );
+ virtual bool ShouldTouchTrigger( int triggerSolidFlags ) const;
+ virtual const matrix3x4_t *GetRootParentToWorldTransform() const;
+
+public:
+ // Spatial partition management
+ void CreatePartitionHandle();
+ void DestroyPartitionHandle();
+ unsigned short GetPartitionHandle() const;
+
+ // Marks the spatial partition dirty
+ void MarkPartitionHandleDirty();
+
+ // Sets the collision bounds + the size (OBB)
+ void SetCollisionBounds( const Vector& mins, const Vector &maxs );
+
+ // Rebuilds the scaled bounds from the pre-scaled bounds after a model's scale has changed
+ void RefreshScaledCollisionBounds( void );
+
+ // Sets special trigger bounds. The bloat amount indicates how much bigger the
+ // trigger bounds should be beyond the bounds set in SetCollisionBounds
+ // This method will also set the FSOLID flag FSOLID_USE_TRIGGER_BOUNDS
+ void UseTriggerBounds( bool bEnable, float flBloat = 0.0f );
+
+ // Sets the method by which the surrounding collision bounds is set
+ // You must pass in values for mins + maxs if you select the USE_SPECIFIED_BOUNDS type.
+ void SetSurroundingBoundsType( SurroundingBoundsType_t type, const Vector *pMins = NULL, const Vector *pMaxs = NULL );
+
+ // Sets the solid type (which type of collision representation)
+ void SetSolid( SolidType_t val );
+
+ // Methods related to size. The OBB here is measured in CollisionSpace
+ // (specified by GetCollisionToWorld)
+ const Vector& OBBSize( ) const;
+
+ // Returns a radius (or the square of the radius) of a sphere
+ // *centered at the world space center* bounding the collision representation
+ // of the entity. NOTE: The world space center *may* move when the entity rotates.
+ float BoundingRadius() const;
+ float BoundingRadius2D() const;
+
+ // Returns the center of the OBB in collision space
+ const Vector & OBBCenter( ) const;
+
+ // center point of entity measured in world space
+ // NOTE: This point *may* move when the entity moves depending on
+ // which solid type is being used.
+ const Vector & WorldSpaceCenter( ) const;
+
+ // Methods related to solid flags
+ void ClearSolidFlags( void );
+ void RemoveSolidFlags( int flags );
+ void AddSolidFlags( int flags );
+ bool IsSolidFlagSet( int flagMask ) const;
+ void SetSolidFlags( int flags );
+ bool IsSolid() const;
+
+ // Updates the spatial partition
+ void UpdatePartition( );
+
+ // Are the bounds defined in entity space?
+ bool IsBoundsDefinedInEntitySpace() const;
+
+ // Transforms a point in OBB space to world space
+ const Vector & CollisionToWorldSpace( const Vector &in, Vector *pResult ) const;
+
+ // Transforms a point in world space to OBB space
+ const Vector & WorldToCollisionSpace( const Vector &in, Vector *pResult ) const;
+
+ // Transforms a direction in world space to OBB space
+ const Vector & WorldDirectionToCollisionSpace( const Vector &in, Vector *pResult ) const;
+
+ // Selects a random point in the bounds given the normalized 0-1 bounds
+ void RandomPointInBounds( const Vector &vecNormalizedMins, const Vector &vecNormalizedMaxs, Vector *pPoint) const;
+
+ // Is a worldspace point within the bounds of the OBB?
+ bool IsPointInBounds( const Vector &vecWorldPt ) const;
+
+ // Computes a bounding box in world space surrounding the collision bounds
+ void WorldSpaceAABB( Vector *pWorldMins, Vector *pWorldMaxs ) const;
+
+ // Get the collision space mins directly
+ const Vector & CollisionSpaceMins( void ) const;
+
+ // Get the collision space maxs directly
+ const Vector & CollisionSpaceMaxs( void ) const;
+
+ // Computes a "normalized" point (range 0,0,0 - 1,1,1) in collision space
+ // Useful for things like getting a point 75% of the way along z on the OBB, for example
+ const Vector & NormalizedToCollisionSpace( const Vector &in, Vector *pResult ) const;
+
+ // Computes a "normalized" point (range 0,0,0 - 1,1,1) in world space
+ const Vector & NormalizedToWorldSpace( const Vector &in, Vector *pResult ) const;
+
+ // Transforms a point in world space to normalized space
+ const Vector & WorldToNormalizedSpace( const Vector &in, Vector *pResult ) const;
+
+ // Transforms a point in collision space to normalized space
+ const Vector & CollisionToNormalizedSpace( const Vector &in, Vector *pResult ) const;
+
+ // Computes the nearest point in the OBB to a point specified in world space
+ void CalcNearestPoint( const Vector &vecWorldPt, Vector *pVecNearestWorldPt ) const;
+
+ // Computes the distance from a point in world space to the OBB
+ float CalcDistanceFromPoint( const Vector &vecWorldPt ) const;
+
+ // Does a rotation make us need to recompute the surrounding box?
+ bool DoesRotationInvalidateSurroundingBox( ) const;
+
+ // Does VPhysicsUpdate make us need to recompute the surrounding box?
+ bool DoesVPhysicsInvalidateSurroundingBox( ) const;
+
+ // Marks the entity has having a dirty surrounding box
+ void MarkSurroundingBoundsDirty();
+
+ // Compute the largest dot product of the OBB and the specified direction vector
+ float ComputeSupportMap( const Vector &vecDirection ) const;
+
+private:
+ // Transforms an AABB measured in collision space to a box that surrounds it in world space
+ void CollisionAABBToWorldAABB( const Vector &entityMins, const Vector &entityMaxs, Vector *pWorldMins, Vector *pWorldMaxs ) const;
+
+ // Expand trigger bounds..
+ void ComputeVPhysicsSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
+
+ // Expand trigger bounds..
+ bool ComputeHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
+ bool ComputeEntitySpaceHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
+
+ // Computes the surrounding collision bounds based on whatever algorithm we want...
+ void ComputeCollisionSurroundingBox( bool bUseVPhysics, Vector *pVecWorldMins, Vector *pVecWorldMaxs );
+
+ // Computes the surrounding collision bounds from the the OBB (not vphysics)
+ void ComputeRotationExpandedBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
+
+ // Computes the surrounding collision bounds based on whatever algorithm we want...
+ void ComputeSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
+
+ // Check for untouch
+ void CheckForUntouch();
+
+ // Updates the spatial partition
+ void UpdateServerPartitionMask( );
+
+ // Outer
+ CBaseEntity *GetOuter();
+ const CBaseEntity *GetOuter() const;
+
+private:
+ CBaseEntity *m_pOuter;
+
+ CNetworkVector( m_vecMinsPreScaled );
+ CNetworkVector( m_vecMaxsPreScaled );
+ CNetworkVector( m_vecMins );
+ CNetworkVector( m_vecMaxs );
+ float m_flRadius;
+
+ CNetworkVar( unsigned short, m_usSolidFlags );
+
+ // Spatial partition
+ SpatialPartitionHandle_t m_Partition;
+ CNetworkVar( unsigned char, m_nSurroundType );
+
+ // One of the SOLID_ defines. Use GetSolid/SetSolid.
+ CNetworkVar( unsigned char, m_nSolidType );
+ CNetworkVar( unsigned char , m_triggerBloat );
+
+ // SUCKY: We didn't use to have to store this previously
+ // but storing it here means that we can network it + avoid a ton of
+ // client-side mismatch problems
+ CNetworkVector( m_vecSpecifiedSurroundingMinsPreScaled );
+ CNetworkVector( m_vecSpecifiedSurroundingMaxsPreScaled );
+ CNetworkVector( m_vecSpecifiedSurroundingMins );
+ CNetworkVector( m_vecSpecifiedSurroundingMaxs );
+
+ // Cached off world-aligned surrounding bounds
+#if 0
+ short m_surroundingMins[3];
+ short m_surroundingMaxs[3];
+#else
+ Vector m_vecSurroundingMins;
+ Vector m_vecSurroundingMaxs;
+#endif
+
+ // pointer to the entity's physics object (vphysics.dll)
+ //IPhysicsObject *m_pPhysicsObject;
+
+ friend class CBaseEntity;
+};
+
+
+//-----------------------------------------------------------------------------
+// For networking this bad boy
+//-----------------------------------------------------------------------------
+#ifdef CLIENT_DLL
+EXTERN_RECV_TABLE( DT_CollisionProperty );
+#else
+EXTERN_SEND_TABLE( DT_CollisionProperty );
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Inline methods
+//-----------------------------------------------------------------------------
+inline CBaseEntity *CCollisionProperty::GetOuter()
+{
+ return m_pOuter;
+}
+
+inline const CBaseEntity *CCollisionProperty::GetOuter() const
+{
+ return m_pOuter;
+}
+
+
+//-----------------------------------------------------------------------------
+// Spatial partition
+//-----------------------------------------------------------------------------
+inline unsigned short CCollisionProperty::GetPartitionHandle() const
+{
+ return m_Partition;
+}
+
+
+//-----------------------------------------------------------------------------
+// Methods related to size
+//-----------------------------------------------------------------------------
+inline const Vector& CCollisionProperty::OBBSize( ) const
+{
+ // NOTE: Could precache this, but it's not used that often..
+ Vector &temp = AllocTempVector();
+ VectorSubtract( m_vecMaxs, m_vecMins, temp );
+ return temp;
+}
+
+
+//-----------------------------------------------------------------------------
+// Bounding radius size
+//-----------------------------------------------------------------------------
+inline float CCollisionProperty::BoundingRadius() const
+{
+ return m_flRadius;
+}
+
+
+//-----------------------------------------------------------------------------
+// Methods relating to solid flags
+//-----------------------------------------------------------------------------
+inline bool CCollisionProperty::IsBoundsDefinedInEntitySpace() const
+{
+ return (( m_usSolidFlags & FSOLID_FORCE_WORLD_ALIGNED ) == 0 ) &&
+ ( m_nSolidType != SOLID_BBOX ) && ( m_nSolidType != SOLID_NONE );
+}
+
+inline void CCollisionProperty::ClearSolidFlags( void )
+{
+ SetSolidFlags( 0 );
+}
+
+inline void CCollisionProperty::RemoveSolidFlags( int flags )
+{
+ SetSolidFlags( m_usSolidFlags & ~flags );
+}
+
+inline void CCollisionProperty::AddSolidFlags( int flags )
+{
+ SetSolidFlags( m_usSolidFlags | flags );
+}
+
+inline int CCollisionProperty::GetSolidFlags( void ) const
+{
+ return m_usSolidFlags;
+}
+
+inline bool CCollisionProperty::IsSolidFlagSet( int flagMask ) const
+{
+ return (m_usSolidFlags & flagMask) != 0;
+}
+
+inline bool CCollisionProperty::IsSolid() const
+{
+ return ::IsSolid( (SolidType_t)(unsigned char)m_nSolidType, m_usSolidFlags );
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the center in OBB space
+//-----------------------------------------------------------------------------
+inline const Vector& CCollisionProperty::OBBCenter( ) const
+{
+ Vector &vecResult = AllocTempVector();
+ VectorLerp( m_vecMins, m_vecMaxs, 0.5f, vecResult );
+ return vecResult;
+}
+
+
+//-----------------------------------------------------------------------------
+// center point of entity
+//-----------------------------------------------------------------------------
+inline const Vector &CCollisionProperty::WorldSpaceCenter( ) const
+{
+ Vector &vecResult = AllocTempVector();
+ CollisionToWorldSpace( OBBCenter(), &vecResult );
+ return vecResult;
+}
+
+
+//-----------------------------------------------------------------------------
+// Transforms a point in OBB space to world space
+//-----------------------------------------------------------------------------
+inline const Vector &CCollisionProperty::CollisionToWorldSpace( const Vector &in, Vector *pResult ) const
+{
+ // Makes sure we don't re-use the same temp twice
+ if ( !IsBoundsDefinedInEntitySpace() || ( GetCollisionAngles() == vec3_angle ) )
+ {
+ VectorAdd( in, GetCollisionOrigin(), *pResult );
+ }
+ else
+ {
+ VectorTransform( in, CollisionToWorldTransform(), *pResult );
+ }
+ return *pResult;
+}
+
+
+//-----------------------------------------------------------------------------
+// Transforms a point in world space to OBB space
+//-----------------------------------------------------------------------------
+inline const Vector &CCollisionProperty::WorldToCollisionSpace( const Vector &in, Vector *pResult ) const
+{
+ if ( !IsBoundsDefinedInEntitySpace() || ( GetCollisionAngles() == vec3_angle ) )
+ {
+ VectorSubtract( in, GetCollisionOrigin(), *pResult );
+ }
+ else
+ {
+ VectorITransform( in, CollisionToWorldTransform(), *pResult );
+ }
+ return *pResult;
+}
+
+
+//-----------------------------------------------------------------------------
+// Transforms a direction in world space to OBB space
+//-----------------------------------------------------------------------------
+inline const Vector & CCollisionProperty::WorldDirectionToCollisionSpace( const Vector &in, Vector *pResult ) const
+{
+ if ( !IsBoundsDefinedInEntitySpace() || ( GetCollisionAngles() == vec3_angle ) )
+ {
+ *pResult = in;
+ }
+ else
+ {
+ VectorIRotate( in, CollisionToWorldTransform(), *pResult );
+ }
+ return *pResult;
+}
+
+
+//-----------------------------------------------------------------------------
+// Computes a bounding box in world space surrounding the collision bounds
+//-----------------------------------------------------------------------------
+inline void CCollisionProperty::WorldSpaceAABB( Vector *pWorldMins, Vector *pWorldMaxs ) const
+{
+ CollisionAABBToWorldAABB( m_vecMins, m_vecMaxs, pWorldMins, pWorldMaxs );
+}
+
+
+// Get the collision space mins directly
+inline const Vector & CCollisionProperty::CollisionSpaceMins( void ) const
+{
+ return m_vecMins;
+}
+
+// Get the collision space maxs directly
+inline const Vector & CCollisionProperty::CollisionSpaceMaxs( void ) const
+{
+ return m_vecMaxs;
+}
+
+
+//-----------------------------------------------------------------------------
+// Does a rotation make us need to recompute the surrounding box?
+//-----------------------------------------------------------------------------
+inline bool CCollisionProperty::DoesRotationInvalidateSurroundingBox( ) const
+{
+ if ( IsSolidFlagSet(FSOLID_ROOT_PARENT_ALIGNED) )
+ return true;
+
+ switch ( m_nSurroundType )
+ {
+ case USE_COLLISION_BOUNDS_NEVER_VPHYSICS:
+ case USE_OBB_COLLISION_BOUNDS:
+ case USE_BEST_COLLISION_BOUNDS:
+ return IsBoundsDefinedInEntitySpace();
+
+ // In the case of game code, we don't really know, so we have to assume it does
+ case USE_HITBOXES:
+ case USE_GAME_CODE:
+ return true;
+
+ case USE_ROTATION_EXPANDED_BOUNDS:
+ case USE_SPECIFIED_BOUNDS:
+ return false;
+
+ default:
+ Assert(0);
+ return true;
+ }
+}
+
+
+#endif // COLLISIONPROPERTY_H
|