Counter Strike : Global Offensive Source Code

505 lines
17 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef COLLISIONPROPERTY_H
  8. #define COLLISIONPROPERTY_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #include "networkvar.h"
  13. #include "engine/ICollideable.h"
  14. #include "mathlib/vector.h"
  15. #include "ispatialpartition.h"
  16. //-----------------------------------------------------------------------------
  17. // Forward declarations
  18. //-----------------------------------------------------------------------------
  19. class CBaseEntity;
  20. class IHandleEntity;
  21. class QAngle;
  22. class Vector;
  23. struct Ray_t;
  24. class IPhysicsObject;
  25. //-----------------------------------------------------------------------------
  26. // Force spatial partition updates (to avoid threading problems caused by lazy update)
  27. //-----------------------------------------------------------------------------
  28. void UpdateDirtySpatialPartitionEntities();
  29. //-----------------------------------------------------------------------------
  30. // Specifies how to compute the surrounding box
  31. //-----------------------------------------------------------------------------
  32. enum SurroundingBoundsType_t
  33. {
  34. USE_OBB_COLLISION_BOUNDS = 0,
  35. USE_BEST_COLLISION_BOUNDS, // Always use the best bounds (most expensive)
  36. USE_HITBOXES,
  37. USE_SPECIFIED_BOUNDS,
  38. USE_GAME_CODE,
  39. USE_ROTATION_EXPANDED_BOUNDS,
  40. USE_COLLISION_BOUNDS_NEVER_VPHYSICS,
  41. USE_ROTATION_EXPANDED_SEQUENCE_BOUNDS,
  42. SURROUNDING_TYPE_BIT_COUNT = 3
  43. };
  44. //-----------------------------------------------------------------------------
  45. // Encapsulates collision representation for an entity
  46. //-----------------------------------------------------------------------------
  47. class CCollisionProperty : public ICollideable
  48. {
  49. DECLARE_CLASS_NOBASE( CCollisionProperty );
  50. DECLARE_EMBEDDED_NETWORKVAR();
  51. DECLARE_PREDICTABLE();
  52. #ifdef GAME_DLL
  53. DECLARE_DATADESC();
  54. #endif
  55. public:
  56. CCollisionProperty();
  57. ~CCollisionProperty();
  58. void Init( CBaseEntity *pEntity );
  59. // Methods of ICollideable
  60. virtual IHandleEntity *GetEntityHandle();
  61. virtual const Vector& OBBMins( ) const;
  62. virtual const Vector& OBBMaxs( ) const;
  63. virtual void WorldSpaceTriggerBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) const;
  64. virtual bool TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr );
  65. virtual bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr );
  66. virtual int GetCollisionModelIndex();
  67. virtual const model_t* GetCollisionModel();
  68. virtual const Vector& GetCollisionOrigin() const;
  69. virtual const QAngle& GetCollisionAngles() const;
  70. virtual const matrix3x4_t& CollisionToWorldTransform() const;
  71. virtual SolidType_t GetSolid() const;
  72. virtual int GetSolidFlags() const;
  73. virtual IClientUnknown* GetIClientUnknown();
  74. virtual int GetCollisionGroup() const;
  75. virtual void WorldSpaceSurroundingBounds( Vector *pVecMins, Vector *pVecMaxs );
  76. virtual uint GetRequiredTriggerFlags() const;
  77. virtual const matrix3x4_t *GetRootParentToWorldTransform() const;
  78. virtual IPhysicsObject *GetVPhysicsObject() const;
  79. public:
  80. // Spatial partition management
  81. void CreatePartitionHandle();
  82. void DestroyPartitionHandle();
  83. SpatialPartitionHandle_t GetPartitionHandle() const;
  84. // Marks the spatial partition dirty
  85. void MarkPartitionHandleDirty();
  86. // Sets the collision bounds + the size (OBB)
  87. void SetCollisionBounds( const Vector& mins, const Vector &maxs );
  88. // Sets special trigger bounds. The bloat amount indicates how much bigger the
  89. // trigger bounds should be beyond the bounds set in SetCollisionBounds
  90. // This method will also set the FSOLID flag FSOLID_USE_TRIGGER_BOUNDS
  91. void UseTriggerBounds( bool bEnable, float flBloat = 0.0f );
  92. // Sets the method by which the surrounding collision bounds is set
  93. // You must pass in values for mins + maxs if you select the USE_SPECIFIED_BOUNDS type.
  94. void SetSurroundingBoundsType( SurroundingBoundsType_t type, const Vector *pMins = NULL, const Vector *pMaxs = NULL );
  95. SurroundingBoundsType_t GetSurroundingBoundsType() const;
  96. // Sets the solid type (which type of collision representation)
  97. void SetSolid( SolidType_t val );
  98. // Methods related to size. The OBB here is measured in CollisionSpace
  99. // (specified by GetCollisionToWorld)
  100. const Vector& OBBSize( ) const;
  101. // Returns a radius (or the square of the radius) of a sphere
  102. // *centered at the world space center* bounding the collision representation
  103. // of the entity. NOTE: The world space center *may* move when the entity rotates.
  104. float BoundingRadius() const;
  105. float BoundingRadius2D() const;
  106. // Returns the center of the OBB in collision space
  107. const Vector & OBBCenter( ) const;
  108. // center point of entity measured in world space
  109. // NOTE: This point *may* move when the entity moves depending on
  110. // which solid type is being used.
  111. const Vector & WorldSpaceCenter( ) const;
  112. // Methods related to solid flags
  113. void ClearSolidFlags( void );
  114. void RemoveSolidFlags( int flags );
  115. void AddSolidFlags( int flags );
  116. bool IsSolidFlagSet( int flagMask ) const;
  117. void SetSolidFlags( int flags );
  118. bool IsSolid() const;
  119. // Updates the spatial partition
  120. void UpdatePartition( );
  121. // Are the bounds defined in entity space?
  122. bool IsBoundsDefinedInEntitySpace() const;
  123. // Transforms a point in OBB space to world space
  124. const Vector & CollisionToWorldSpace( const Vector &in, Vector *pResult ) const;
  125. // Transforms a point in world space to OBB space
  126. const Vector & WorldToCollisionSpace( const Vector &in, Vector *pResult ) const;
  127. // Transforms a direction in world space to OBB space
  128. const Vector & WorldDirectionToCollisionSpace( const Vector &in, Vector *pResult ) const;
  129. // Selects a random point in the bounds given the normalized 0-1 bounds
  130. void RandomPointInBounds( const Vector &vecNormalizedMins, const Vector &vecNormalizedMaxs, Vector *pPoint) const;
  131. // Is a worldspace point within the bounds of the OBB?
  132. bool IsPointInBounds( const Vector &vecWorldPt ) const;
  133. // Computes a bounding box in world space surrounding the collision bounds
  134. void WorldSpaceAABB( Vector *pWorldMins, Vector *pWorldMaxs ) const;
  135. // Computes a "normalized" point (range 0,0,0 - 1,1,1) in collision space
  136. // Useful for things like getting a point 75% of the way along z on the OBB, for example
  137. const Vector & NormalizedToCollisionSpace( const Vector &in, Vector *pResult ) const;
  138. // Computes a "normalized" point (range 0,0,0 - 1,1,1) in world space
  139. const Vector & NormalizedToWorldSpace( const Vector &in, Vector *pResult ) const;
  140. // Transforms a point in world space to normalized space
  141. const Vector & WorldToNormalizedSpace( const Vector &in, Vector *pResult ) const;
  142. // Transforms a point in collision space to normalized space
  143. const Vector & CollisionToNormalizedSpace( const Vector &in, Vector *pResult ) const;
  144. // Computes the nearest point in the OBB to a point specified in world space
  145. void CalcNearestPoint( const Vector &vecWorldPt, Vector *pVecNearestWorldPt ) const;
  146. // Computes the distance from a point in world space to the OBB
  147. float CalcDistanceFromPoint( const Vector &vecWorldPt ) const;
  148. float CalcSqrDistanceFromPoint( const Vector &vecWorldPt ) const;
  149. // Does a rotation make us need to recompute the surrounding box?
  150. bool DoesRotationInvalidateSurroundingBox( ) const;
  151. // Does VPhysicsUpdate make us need to recompute the surrounding box?
  152. bool DoesVPhysicsInvalidateSurroundingBox( ) const;
  153. // Does a sequence change make us need to recompute the surrounding box?
  154. bool DoesSequenceChangeInvalidateSurroundingBox( ) const;
  155. // Marks the entity has having a dirty surrounding box
  156. void MarkSurroundingBoundsDirty();
  157. // Compute the largest dot product of the OBB and the specified direction vector
  158. float ComputeSupportMap( const Vector &vecDirection ) const;
  159. private:
  160. // Transforms an AABB measured in collision space to a box that surrounds it in world space
  161. void CollisionAABBToWorldAABB( const Vector &entityMins, const Vector &entityMaxs, Vector *pWorldMins, Vector *pWorldMaxs ) const;
  162. // Expand trigger bounds..
  163. void ComputeVPhysicsSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
  164. // Expand trigger bounds..
  165. bool ComputeHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
  166. bool ComputeEntitySpaceHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
  167. // Computes the surrounding collision bounds based on the current sequence box
  168. void ComputeOBBBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
  169. // Computes the surrounding collision bounds from the current sequence box
  170. void ComputeRotationExpandedSequenceBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
  171. // Computes the surrounding collision bounds based on whatever algorithm we want...
  172. void ComputeCollisionSurroundingBox( bool bUseVPhysics, Vector *pVecWorldMins, Vector *pVecWorldMaxs );
  173. // Computes the surrounding collision bounds from the OBB (not vphysics)
  174. void ComputeRotationExpandedBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
  175. // Computes the surrounding collision bounds based on whatever algorithm we want...
  176. void ComputeSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
  177. // Check for untouch
  178. void CheckForUntouch();
  179. // Updates the spatial partition
  180. void UpdateServerPartitionMask( );
  181. uint ComputeServerPartitionMask( );
  182. inline const Vector& GetCollisionOrigin_Inline() const;
  183. // Outer
  184. CBaseEntity *GetOuter();
  185. const CBaseEntity *GetOuter() const;
  186. private:
  187. CBaseEntity *m_pOuter;
  188. // BEGIN PREDICTION DATA COMPACTION (these fields are together to allow for faster copying in prediction system)
  189. CNetworkVector( m_vecMins );
  190. CNetworkVector( m_vecMaxs );
  191. CNetworkVar( unsigned short, m_usSolidFlags );
  192. // One of the SOLID_ defines. Use GetSolid/SetSolid.
  193. CNetworkVar( unsigned char, m_nSolidType );
  194. CNetworkVar( unsigned char , m_triggerBloat );
  195. // END PREDICTION DATA COMPACTION
  196. float m_flRadius;
  197. // Spatial partition
  198. SpatialPartitionHandle_t m_Partition;
  199. CNetworkVar( unsigned char, m_nSurroundType );
  200. // SUCKY: We didn't use to have to store this previously
  201. // but storing it here means that we can network it + avoid a ton of
  202. // client-side mismatch problems
  203. CNetworkVector( m_vecSpecifiedSurroundingMins );
  204. CNetworkVector( m_vecSpecifiedSurroundingMaxs );
  205. // Cached off world-aligned surrounding bounds
  206. #if 0
  207. short m_surroundingMins[3];
  208. short m_surroundingMaxs[3];
  209. #else
  210. Vector m_vecSurroundingMins;
  211. Vector m_vecSurroundingMaxs;
  212. #endif
  213. // pointer to the entity's physics object (vphysics.dll)
  214. //IPhysicsObject *m_pPhysicsObject;
  215. friend class CBaseEntity;
  216. };
  217. //-----------------------------------------------------------------------------
  218. // For networking this bad boy
  219. //-----------------------------------------------------------------------------
  220. #ifdef CLIENT_DLL
  221. EXTERN_RECV_TABLE( DT_CollisionProperty );
  222. #else
  223. EXTERN_SEND_TABLE( DT_CollisionProperty );
  224. #endif
  225. //-----------------------------------------------------------------------------
  226. // Inline methods
  227. //-----------------------------------------------------------------------------
  228. inline CBaseEntity *CCollisionProperty::GetOuter()
  229. {
  230. return m_pOuter;
  231. }
  232. inline const CBaseEntity *CCollisionProperty::GetOuter() const
  233. {
  234. return m_pOuter;
  235. }
  236. //-----------------------------------------------------------------------------
  237. // Spatial partition
  238. //-----------------------------------------------------------------------------
  239. inline SpatialPartitionHandle_t CCollisionProperty::GetPartitionHandle() const
  240. {
  241. return m_Partition;
  242. }
  243. inline SurroundingBoundsType_t CCollisionProperty::GetSurroundingBoundsType() const
  244. {
  245. return (SurroundingBoundsType_t)m_nSurroundType.Get();
  246. }
  247. //-----------------------------------------------------------------------------
  248. // Methods related to size
  249. //-----------------------------------------------------------------------------
  250. inline const Vector& CCollisionProperty::OBBSize( ) const
  251. {
  252. // NOTE: Could precache this, but it's not used that often..
  253. Vector &temp = AllocTempVector();
  254. VectorSubtract( m_vecMaxs, m_vecMins, temp );
  255. return temp;
  256. }
  257. //-----------------------------------------------------------------------------
  258. // Bounding radius size
  259. //-----------------------------------------------------------------------------
  260. inline float CCollisionProperty::BoundingRadius() const
  261. {
  262. return m_flRadius;
  263. }
  264. //-----------------------------------------------------------------------------
  265. // Methods relating to solid flags
  266. //-----------------------------------------------------------------------------
  267. inline bool CCollisionProperty::IsBoundsDefinedInEntitySpace() const
  268. {
  269. return (( m_usSolidFlags & FSOLID_FORCE_WORLD_ALIGNED ) == 0 ) &&
  270. ( m_nSolidType != SOLID_BBOX ) && ( m_nSolidType != SOLID_NONE );
  271. }
  272. inline void CCollisionProperty::ClearSolidFlags( void )
  273. {
  274. SetSolidFlags( 0 );
  275. }
  276. inline void CCollisionProperty::RemoveSolidFlags( int flags )
  277. {
  278. SetSolidFlags( m_usSolidFlags & ~flags );
  279. }
  280. inline void CCollisionProperty::AddSolidFlags( int flags )
  281. {
  282. SetSolidFlags( m_usSolidFlags | flags );
  283. }
  284. inline int CCollisionProperty::GetSolidFlags( void ) const
  285. {
  286. return m_usSolidFlags;
  287. }
  288. inline bool CCollisionProperty::IsSolidFlagSet( int flagMask ) const
  289. {
  290. return (m_usSolidFlags & flagMask) != 0;
  291. }
  292. inline bool CCollisionProperty::IsSolid() const
  293. {
  294. return ::IsSolid( (SolidType_t)(unsigned char)m_nSolidType, m_usSolidFlags );
  295. }
  296. //-----------------------------------------------------------------------------
  297. // Returns the center in OBB space
  298. //-----------------------------------------------------------------------------
  299. inline const Vector& CCollisionProperty::OBBCenter( ) const
  300. {
  301. Vector &vecResult = AllocTempVector();
  302. VectorLerp( m_vecMins, m_vecMaxs, 0.5f, vecResult );
  303. return vecResult;
  304. }
  305. //-----------------------------------------------------------------------------
  306. // center point of entity
  307. //-----------------------------------------------------------------------------
  308. inline const Vector &CCollisionProperty::WorldSpaceCenter( ) const
  309. {
  310. Vector &vecResult = AllocTempVector();
  311. CollisionToWorldSpace( OBBCenter(), &vecResult );
  312. return vecResult;
  313. }
  314. //-----------------------------------------------------------------------------
  315. // Transforms a point in OBB space to world space
  316. //-----------------------------------------------------------------------------
  317. inline const Vector &CCollisionProperty::CollisionToWorldSpace( const Vector &in, Vector *pResult ) const
  318. {
  319. // Makes sure we don't re-use the same temp twice
  320. if ( !IsBoundsDefinedInEntitySpace() || ( GetCollisionAngles() == vec3_angle ) )
  321. {
  322. VectorAdd( in, GetCollisionOrigin(), *pResult );
  323. }
  324. else
  325. {
  326. VectorTransform( in, CollisionToWorldTransform(), *pResult );
  327. }
  328. return *pResult;
  329. }
  330. //-----------------------------------------------------------------------------
  331. // Transforms a point in world space to OBB space
  332. //-----------------------------------------------------------------------------
  333. inline const Vector &CCollisionProperty::WorldToCollisionSpace( const Vector &in, Vector *pResult ) const
  334. {
  335. if ( !IsBoundsDefinedInEntitySpace() || ( GetCollisionAngles() == vec3_angle ) )
  336. {
  337. VectorSubtract( in, GetCollisionOrigin(), *pResult );
  338. }
  339. else
  340. {
  341. VectorITransform( in, CollisionToWorldTransform(), *pResult );
  342. }
  343. return *pResult;
  344. }
  345. //-----------------------------------------------------------------------------
  346. // Transforms a direction in world space to OBB space
  347. //-----------------------------------------------------------------------------
  348. inline const Vector & CCollisionProperty::WorldDirectionToCollisionSpace( const Vector &in, Vector *pResult ) const
  349. {
  350. if ( !IsBoundsDefinedInEntitySpace() || ( GetCollisionAngles() == vec3_angle ) )
  351. {
  352. *pResult = in;
  353. }
  354. else
  355. {
  356. VectorIRotate( in, CollisionToWorldTransform(), *pResult );
  357. }
  358. return *pResult;
  359. }
  360. //-----------------------------------------------------------------------------
  361. // Computes a bounding box in world space surrounding the collision bounds
  362. //-----------------------------------------------------------------------------
  363. inline void CCollisionProperty::WorldSpaceAABB( Vector *pWorldMins, Vector *pWorldMaxs ) const
  364. {
  365. CollisionAABBToWorldAABB( m_vecMins, m_vecMaxs, pWorldMins, pWorldMaxs );
  366. }
  367. //-----------------------------------------------------------------------------
  368. // Does a rotation make us need to recompute the surrounding box?
  369. //-----------------------------------------------------------------------------
  370. inline bool CCollisionProperty::DoesSequenceChangeInvalidateSurroundingBox( ) const
  371. {
  372. return ( m_nSurroundType == USE_ROTATION_EXPANDED_SEQUENCE_BOUNDS );
  373. }
  374. //-----------------------------------------------------------------------------
  375. // Does a rotation make us need to recompute the surrounding box?
  376. //-----------------------------------------------------------------------------
  377. inline bool CCollisionProperty::DoesRotationInvalidateSurroundingBox( ) const
  378. {
  379. if ( IsSolidFlagSet(FSOLID_ROOT_PARENT_ALIGNED) )
  380. return true;
  381. switch ( m_nSurroundType )
  382. {
  383. case USE_COLLISION_BOUNDS_NEVER_VPHYSICS:
  384. case USE_OBB_COLLISION_BOUNDS:
  385. case USE_BEST_COLLISION_BOUNDS:
  386. return IsBoundsDefinedInEntitySpace();
  387. // In the case of game code, we don't really know, so we have to assume it does
  388. case USE_HITBOXES:
  389. case USE_GAME_CODE:
  390. return true;
  391. case USE_ROTATION_EXPANDED_BOUNDS:
  392. case USE_SPECIFIED_BOUNDS:
  393. case USE_ROTATION_EXPANDED_SEQUENCE_BOUNDS:
  394. return false;
  395. default:
  396. Assert(0);
  397. return true;
  398. }
  399. }
  400. #endif // COLLISIONPROPERTY_H