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.

461 lines
16 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef DISPCOLL_COMMON_H
  8. #define DISPCOLL_COMMON_H
  9. #pragma once
  10. #include "trace.h"
  11. #include "builddisp.h"
  12. #include "bitvec.h"
  13. #ifdef ENGINE_DLL
  14. #include "../engine/zone.h"
  15. #endif
  16. #ifdef ENGINE_DLL
  17. template<typename T>
  18. class CDispVector : public CUtlVector<T, CHunkMemory<T> >
  19. {
  20. };
  21. #else
  22. template<typename T>
  23. class CDispVector : public CUtlVector<T, CUtlMemoryAligned<T,16> >
  24. {
  25. };
  26. #define HUNK_ALLOC_CREDIT_( _x_ )
  27. #endif
  28. FORWARD_DECLARE_HANDLE( memhandle_t );
  29. #define DISPCOLL_TREETRI_SIZE MAX_DISPTRIS
  30. #define DISPCOLL_DIST_EPSILON 0.03125f
  31. #define DISPCOLL_ROOTNODE_INDEX 0
  32. #define DISPCOLL_INVALID_TRI -1
  33. #define DISPCOLL_INVALID_FRAC -99999.9f
  34. #define DISPCOLL_NORMAL_UNDEF 0xffff
  35. extern double g_flDispCollSweepTimer;
  36. extern double g_flDispCollIntersectTimer;
  37. extern double g_flDispCollInCallTimer;
  38. struct RayDispOutput_t
  39. {
  40. short ndxVerts[4]; // 3 verts and a pad
  41. float u, v; // the u, v paramters (edgeU = v1 - v0, edgeV = v2 - v0)
  42. float dist; // intersection distance
  43. };
  44. // Assumptions:
  45. // Max patch is 17x17, therefore 9 bits needed to represent a triangle index
  46. //
  47. //=============================================================================
  48. // Displacement Collision Triangle
  49. class CDispCollTri
  50. {
  51. struct index_t
  52. {
  53. union
  54. {
  55. struct
  56. {
  57. unsigned short uiVert:9;
  58. unsigned short uiMin:2;
  59. unsigned short uiMax:2;
  60. } m_Index;
  61. unsigned short m_IndexDummy;
  62. };
  63. };
  64. index_t m_TriData[3];
  65. public:
  66. unsigned short m_ucSignBits:3; // Plane test.
  67. unsigned short m_ucPlaneType:3; // Axial test?
  68. unsigned short m_uiFlags:7; // Uses 7-bits - maybe look into merging it with something?
  69. Vector m_vecNormal; // Triangle normal (plane normal).
  70. float m_flDist; // Triangle plane dist.
  71. // Creation.
  72. CDispCollTri();
  73. void Init( void );
  74. void CalcPlane( CDispVector<Vector> &m_aVerts );
  75. void FindMinMax( CDispVector<Vector> &m_aVerts );
  76. // Triangle data.
  77. inline void SetVert( int iPos, int iVert ) { Assert( ( iPos >= 0 ) && ( iPos < 3 ) ); Assert( ( iVert >= 0 ) && ( iVert < ( 1 << 9 ) ) ); m_TriData[iPos].m_Index.uiVert = iVert; }
  78. inline int GetVert( int iPos ) const { Assert( ( iPos >= 0 ) && ( iPos < 3 ) ); return m_TriData[iPos].m_Index.uiVert; }
  79. inline void SetMin( int iAxis, int iMin ) { Assert( ( iAxis >= 0 ) && ( iAxis < 3 ) ); Assert( ( iMin >= 0 ) && ( iMin < 3 ) ); m_TriData[iAxis].m_Index.uiMin = iMin; }
  80. inline int GetMin( int iAxis ) const { Assert( ( iAxis >= 0 ) && ( iAxis < 3 ) ); return m_TriData[iAxis].m_Index.uiMin; }
  81. inline void SetMax( int iAxis, int iMax ) { Assert( ( iAxis >= 0 ) && ( iAxis < 3 ) ); Assert( ( iMax >= 0 ) && ( iMax < 3 ) ); m_TriData[iAxis].m_Index.uiMax = iMax; }
  82. inline int GetMax( int iAxis ) const { Assert( ( iAxis >= 0 ) && ( iAxis < 3 ) ); return m_TriData[iAxis].m_Index.uiMax; }
  83. };
  84. //=============================================================================
  85. // Helper
  86. class CDispCollHelper
  87. {
  88. public:
  89. float m_flStartFrac;
  90. float m_flEndFrac;
  91. Vector m_vecImpactNormal;
  92. float m_flImpactDist;
  93. };
  94. //=============================================================================
  95. // Cache
  96. #pragma pack(1)
  97. class CDispCollTriCache
  98. {
  99. public:
  100. unsigned short m_iCrossX[3];
  101. unsigned short m_iCrossY[3];
  102. unsigned short m_iCrossZ[3];
  103. };
  104. #pragma pack()
  105. #include "mathlib/ssemath.h"
  106. class CDispCollNode
  107. {
  108. public:
  109. FourVectors m_mins;
  110. FourVectors m_maxs;
  111. };
  112. class CDispCollLeaf
  113. {
  114. public:
  115. short m_tris[2];
  116. };
  117. // a power 4 displacement can have 341 nodes, pad out to 344 for 16-byte alignment
  118. const int MAX_DISP_AABB_NODES = 341;
  119. const int MAX_AABB_LIST = 344;
  120. struct rayleaflist_t
  121. {
  122. FourVectors rayStart;
  123. FourVectors rayExtents;
  124. FourVectors invDelta;
  125. int nodeList[MAX_AABB_LIST];
  126. int maxIndex;
  127. };
  128. //=============================================================================
  129. //
  130. // Displacement Collision Tree Data
  131. //
  132. class CDispCollTree
  133. {
  134. public:
  135. // Creation/Destruction.
  136. CDispCollTree();
  137. ~CDispCollTree();
  138. virtual bool Create( CCoreDispInfo *pDisp );
  139. // Raycasts.
  140. // NOTE: These assume you've precalculated invDelta as well as culled to the bounds of this disp
  141. bool AABBTree_Ray( const Ray_t &ray, const Vector &invDelta, CBaseTrace *pTrace, bool bSide = true );
  142. bool AABBTree_Ray( const Ray_t &ray, const Vector &invDelta, RayDispOutput_t &output );
  143. // NOTE: Lower perf helper function, should not be used in the game runtime
  144. bool AABBTree_Ray( const Ray_t &ray, RayDispOutput_t &output );
  145. // Hull Sweeps.
  146. // NOTE: These assume you've precalculated invDelta as well as culled to the bounds of this disp
  147. bool AABBTree_SweepAABB( const Ray_t &ray, const Vector &invDelta, CBaseTrace *pTrace );
  148. // Hull Intersection.
  149. bool AABBTree_IntersectAABB( const Vector &absMins, const Vector &absMaxs );
  150. // Point/Box vs. Bounds.
  151. bool PointInBounds( Vector const &vecBoxCenter, Vector const &vecBoxMin, Vector const &vecBoxMax, bool bPoint );
  152. // Utility.
  153. inline void SetPower( int power ) { m_nPower = power; }
  154. inline int GetPower( void ) { return m_nPower; }
  155. inline int GetFlags( void ) { return m_nFlags; }
  156. inline void SetFlags( int nFlags ) { m_nFlags = nFlags; }
  157. inline bool CheckFlags( int nFlags ) { return ( ( nFlags & GetFlags() ) != 0 ) ? true : false; }
  158. inline int GetTexinfoFlags( void ) { return m_nTexinfoFlags; }
  159. inline void SetTexinfoFlags( int nFlags ) { m_nTexinfoFlags = nFlags; }
  160. inline int GetWidth( void ) { return ( ( 1 << m_nPower ) + 1 ); }
  161. inline int GetHeight( void ) { return ( ( 1 << m_nPower ) + 1 ); }
  162. inline int GetSize( void ) { return ( ( 1 << m_nPower ) + 1 ) * ( ( 1 << m_nPower ) + 1 ); }
  163. inline int GetTriSize( void ) { return ( ( 1 << m_nPower ) * ( 1 << m_nPower ) * 2 ); }
  164. // inline void SetTriFlags( short iTri, unsigned short nFlags ) { m_aTris[iTri].m_uiFlags = nFlags; }
  165. inline void GetStabDirection( Vector &vecDir ) { vecDir = m_vecStabDir; }
  166. inline void GetBounds( Vector &vecBoxMin, Vector &vecBoxMax ) { vecBoxMin = m_mins; vecBoxMax = m_maxs; }
  167. inline int GetContents( void ) { return m_nContents; }
  168. inline void SetSurfaceProps( int iProp, short nSurfProp ) { Assert( ( iProp >= 0 ) && ( iProp < 4 ) ); m_nSurfaceProps[iProp] = nSurfProp; }
  169. inline short GetSurfaceProps( int iProp ) { return m_nSurfaceProps[iProp]; }
  170. inline unsigned int GetMemorySize( void ) { return m_nSize; }
  171. inline unsigned int GetCacheMemorySize( void ) { return ( m_aTrisCache.Count() * sizeof(CDispCollTriCache) + m_aEdgePlanes.Count() * sizeof(Vector) ); }
  172. inline bool IsCached( void ) { return m_aTrisCache.Count() == m_aTris.Count(); }
  173. void GetVirtualMeshList( struct virtualmeshlist_t *pList );
  174. int AABBTree_GetTrisInSphere( const Vector &center, float radius, unsigned short *pIndexOut, int indexMax );
  175. public:
  176. inline int Nodes_GetChild( int iNode, int nDirection );
  177. inline int Nodes_CalcCount( int nPower );
  178. inline int Nodes_GetParent( int iNode );
  179. inline int Nodes_GetLevel( int iNode );
  180. inline int Nodes_GetIndexFromComponents( int x, int y );
  181. void LockCache();
  182. void UnlockCache();
  183. void Cache( void );
  184. void Uncache() { m_aTrisCache.Purge(); m_aEdgePlanes.Purge(); }
  185. #ifdef ENGINE_DLL
  186. // Data manager methods
  187. static size_t EstimatedSize( CDispCollTree *pTree )
  188. {
  189. return pTree->GetCacheMemorySize();
  190. }
  191. static CDispCollTree *CreateResource( CDispCollTree *pTree )
  192. {
  193. // Created ahead of time
  194. return pTree;
  195. }
  196. bool GetData()
  197. {
  198. return IsCached();
  199. }
  200. size_t Size()
  201. {
  202. return GetCacheMemorySize();
  203. }
  204. void DestroyResource()
  205. {
  206. Uncache();
  207. m_hCache = NULL;
  208. }
  209. #endif
  210. protected:
  211. bool AABBTree_Create( CCoreDispInfo *pDisp );
  212. void AABBTree_CopyDispData( CCoreDispInfo *pDisp );
  213. void AABBTree_CreateLeafs( void );
  214. void AABBTree_GenerateBoxes_r( int nodeIndex, Vector *pMins, Vector *pMaxs );
  215. void AABBTree_CalcBounds( void );
  216. int AABBTree_BuildTreeTrisInSphere_r( const Vector &center, float radius, int iNode, unsigned short *pIndexOut, unsigned short indexMax );
  217. void AABBTree_TreeTrisRayTest( const Ray_t &ray, const Vector &vecInvDelta, int iNode, CBaseTrace *pTrace, bool bSide, CDispCollTri **pImpactTri );
  218. void AABBTree_TreeTrisRayBarycentricTest( const Ray_t &ray, const Vector &vecInvDelta, int iNode, RayDispOutput_t &output, CDispCollTri **pImpactTri );
  219. int FORCEINLINE BuildRayLeafList( int iNode, rayleaflist_t &list );
  220. struct AABBTree_TreeTrisSweepTest_Args_t
  221. {
  222. AABBTree_TreeTrisSweepTest_Args_t( const Ray_t &ray, const Vector &vecInvDelta, const Vector &rayDir, CBaseTrace *pTrace )
  223. : ray( ray ), vecInvDelta( vecInvDelta ), rayDir( rayDir ), pTrace( pTrace ) {}
  224. const Ray_t &ray;
  225. const Vector &vecInvDelta;
  226. const Vector &rayDir;
  227. CBaseTrace *pTrace;
  228. };
  229. protected:
  230. void SweepAABBTriIntersect( const Ray_t &ray, const Vector &rayDir, int iTri, CDispCollTri *pTri, CBaseTrace *pTrace );
  231. void Cache_Create( CDispCollTri *pTri, int iTri ); // Testing!
  232. bool Cache_EdgeCrossAxisX( const Vector &vecEdge, const Vector &vecOnEdge, const Vector &vecOffEdge, CDispCollTri *pTri, unsigned short &iPlane );
  233. bool Cache_EdgeCrossAxisY( const Vector &vecEdge, const Vector &vecOnEdge, const Vector &vecOffEdge, CDispCollTri *pTri, unsigned short &iPlane );
  234. bool Cache_EdgeCrossAxisZ( const Vector &vecEdge, const Vector &vecOnEdge, const Vector &vecOffEdge, CDispCollTri *pTri, unsigned short &iPlane );
  235. inline bool FacePlane( const Ray_t &ray, const Vector &rayDir, CDispCollTri *pTri, CDispCollHelper *pHelper );
  236. bool FORCEINLINE AxisPlanesXYZ( const Ray_t &ray, CDispCollTri *pTri, CDispCollHelper *pHelper );
  237. inline bool EdgeCrossAxisX( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper );
  238. inline bool EdgeCrossAxisY( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper );
  239. inline bool EdgeCrossAxisZ( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper );
  240. bool ResolveRayPlaneIntersect( float flStart, float flEnd, const Vector &vecNormal, float flDist, CDispCollHelper *pHelper );
  241. template <int AXIS> bool FORCEINLINE TestOneAxisPlaneMin( const Ray_t &ray, CDispCollTri *pTri );
  242. template <int AXIS> bool FORCEINLINE TestOneAxisPlaneMax( const Ray_t &ray, CDispCollTri *pTri );
  243. template <int AXIS> bool EdgeCrossAxis( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper );
  244. // Utility
  245. inline void CalcClosestBoxPoint( const Vector &vecPlaneNormal, const Vector &vecBoxStart, const Vector &vecBoxExtents, Vector &vecBoxPoint );
  246. inline void CalcClosestExtents( const Vector &vecPlaneNormal, const Vector &vecBoxExtents, Vector &vecBoxPoint );
  247. int AddPlane( const Vector &vecNormal );
  248. bool FORCEINLINE IsLeafNode(int iNode);
  249. public:
  250. Vector m_mins; // Bounding box of the displacement surface and base face
  251. int m_iCounter;
  252. Vector m_maxs; // Bounding box of the displacement surface and base face
  253. protected:
  254. int m_nContents; // The displacement surface "contents" (solid, etc...)
  255. #ifdef ENGINE_DLL
  256. memhandle_t m_hCache;
  257. #endif
  258. int m_nPower; // Size of the displacement ( 2^power + 1 )
  259. uint16 m_nFlags;
  260. uint16 m_nTexinfoFlags;
  261. Vector m_vecSurfPoints[4]; // Base surface points.
  262. // Collision data.
  263. Vector m_vecStabDir; // Direction to stab for this displacement surface (is the base face normal)
  264. short m_nSurfaceProps[4]; // Surface properties (save off from texdata for impact responses)
  265. protected:
  266. CDispVector<Vector> m_aVerts; // Displacement verts.
  267. CDispVector<CDispCollTri> m_aTris; // Displacement triangles.
  268. CDispVector<CDispCollNode> m_nodes; // Nodes.
  269. CDispVector<CDispCollLeaf> m_leaves; // Leaves.
  270. // Cache
  271. CUtlVector<CDispCollTriCache> m_aTrisCache;
  272. CUtlVector<Vector> m_aEdgePlanes;
  273. CDispCollHelper m_Helper;
  274. unsigned int m_nSize;
  275. };
  276. FORCEINLINE bool CDispCollTree::IsLeafNode(int iNode)
  277. {
  278. return iNode >= m_nodes.Count() ? true : false;
  279. }
  280. //-----------------------------------------------------------------------------
  281. // Purpose: get the child node index given the current node index and direction
  282. // of the child (1 of 4)
  283. // Input: iNode - current node index
  284. // nDirection - direction of the child ( [0...3] - SW, SE, NW, NE )
  285. // Output: int - the index of the child node
  286. //-----------------------------------------------------------------------------
  287. inline int CDispCollTree::Nodes_GetChild( int iNode, int nDirection )
  288. {
  289. // node range [0...m_NodeCount)
  290. Assert( iNode >= 0 );
  291. Assert( iNode < m_nodes.Count() );
  292. // ( node index * 4 ) + ( direction + 1 )
  293. return ( ( iNode << 2 ) + ( nDirection + 1 ) );
  294. }
  295. //-----------------------------------------------------------------------------
  296. // Purpose:
  297. //-----------------------------------------------------------------------------
  298. inline int CDispCollTree::Nodes_CalcCount( int nPower )
  299. {
  300. Assert( nPower >= 1 );
  301. Assert( nPower <= 4 );
  302. return ( ( 1 << ( ( nPower + 1 ) << 1 ) ) / 3 );
  303. }
  304. //-----------------------------------------------------------------------------
  305. // Purpose: get the parent node index given the current node
  306. // Input: iNode - current node index
  307. // Output: int - the index of the parent node
  308. //-----------------------------------------------------------------------------
  309. inline int CDispCollTree::Nodes_GetParent( int iNode )
  310. {
  311. // node range [0...m_NodeCount)
  312. Assert( iNode >= 0 );
  313. Assert( iNode < m_nodes.Count() );
  314. // ( node index - 1 ) / 4
  315. return ( ( iNode - 1 ) >> 2 );
  316. }
  317. //-----------------------------------------------------------------------------
  318. // Purpose:
  319. // TODO: should make this a function - not a hardcoded set of statements!!!
  320. //-----------------------------------------------------------------------------
  321. inline int CDispCollTree::Nodes_GetLevel( int iNode )
  322. {
  323. // node range [0...m_NodeCount)
  324. Assert( iNode >= 0 );
  325. Assert( iNode < m_nodes.Count() );
  326. // level = 2^n + 1
  327. if ( iNode == 0 ) { return 1; }
  328. if ( iNode < 5 ) { return 2; }
  329. if ( iNode < 21 ) { return 3; }
  330. if ( iNode < 85 ) { return 4; }
  331. if ( iNode < 341 ) { return 5; }
  332. return -1;
  333. }
  334. //-----------------------------------------------------------------------------
  335. // Purpose:
  336. //-----------------------------------------------------------------------------
  337. inline int CDispCollTree::Nodes_GetIndexFromComponents( int x, int y )
  338. {
  339. int nIndex = 0;
  340. // Interleave bits from the x and y values to create the index
  341. int iShift;
  342. for( iShift = 0; x != 0; iShift += 2, x >>= 1 )
  343. {
  344. nIndex |= ( x & 1 ) << iShift;
  345. }
  346. for( iShift = 1; y != 0; iShift += 2, y >>= 1 )
  347. {
  348. nIndex |= ( y & 1 ) << iShift;
  349. }
  350. return nIndex;
  351. }
  352. //-----------------------------------------------------------------------------
  353. // Purpose:
  354. //-----------------------------------------------------------------------------
  355. inline void CDispCollTree::CalcClosestBoxPoint( const Vector &vecPlaneNormal, const Vector &vecBoxStart,
  356. const Vector &vecBoxExtents, Vector &vecBoxPoint )
  357. {
  358. vecBoxPoint = vecBoxStart;
  359. ( vecPlaneNormal[0] < 0.0f ) ? vecBoxPoint[0] += vecBoxExtents[0] : vecBoxPoint[0] -= vecBoxExtents[0];
  360. ( vecPlaneNormal[1] < 0.0f ) ? vecBoxPoint[1] += vecBoxExtents[1] : vecBoxPoint[1] -= vecBoxExtents[1];
  361. ( vecPlaneNormal[2] < 0.0f ) ? vecBoxPoint[2] += vecBoxExtents[2] : vecBoxPoint[2] -= vecBoxExtents[2];
  362. }
  363. //-----------------------------------------------------------------------------
  364. // Purpose:
  365. //-----------------------------------------------------------------------------
  366. inline void CDispCollTree::CalcClosestExtents( const Vector &vecPlaneNormal, const Vector &vecBoxExtents,
  367. Vector &vecBoxPoint )
  368. {
  369. ( vecPlaneNormal[0] < 0.0f ) ? vecBoxPoint[0] = vecBoxExtents[0] : vecBoxPoint[0] = -vecBoxExtents[0];
  370. ( vecPlaneNormal[1] < 0.0f ) ? vecBoxPoint[1] = vecBoxExtents[1] : vecBoxPoint[1] = -vecBoxExtents[1];
  371. ( vecPlaneNormal[2] < 0.0f ) ? vecBoxPoint[2] = vecBoxExtents[2] : vecBoxPoint[2] = -vecBoxExtents[2];
  372. }
  373. //=============================================================================
  374. // Global Helper Functions
  375. CDispCollTree *DispCollTrees_Alloc( int count );
  376. void DispCollTrees_Free( CDispCollTree *pTrees );
  377. #endif // DISPCOLL_COMMON_H