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.

658 lines
17 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef CMODEL_PRIVATE_H
  8. #define CMODEL_PRIVATE_H
  9. #pragma once
  10. #include "qlimits.h"
  11. #include "bitvec.h"
  12. #include "bspfile.h"
  13. #include "utlbuffer.h"
  14. #include "filesystem.h"
  15. #include "filesystem_engine.h"
  16. #include "dispcoll_common.h"
  17. class CDispCollTree;
  18. class CCollisionBSPData;
  19. struct cbrush_t;
  20. #define MAX_CHECK_COUNT_DEPTH 2
  21. struct TraceVisits_t
  22. {
  23. CVarBitVec m_Brushes;
  24. CVarBitVec m_Disps;
  25. };
  26. typedef uint32 TraceCounter_t;
  27. typedef CUtlVector<TraceCounter_t> CTraceCounterVec;
  28. struct TraceInfo_t
  29. {
  30. TraceInfo_t()
  31. {
  32. memset( this, 0, offsetof( TraceInfo_t, m_BrushCounters ) );
  33. m_nCheckDepth = -1;
  34. }
  35. Vector m_start;
  36. Vector m_end;
  37. Vector m_mins;
  38. Vector m_maxs;
  39. Vector m_extents;
  40. Vector m_delta;
  41. Vector m_invDelta;
  42. trace_t m_trace;
  43. trace_t m_stabTrace;
  44. int m_contents;
  45. bool m_ispoint;
  46. bool m_isswept;
  47. // BSP Data
  48. CCollisionBSPData *m_pBSPData;
  49. // Displacement Data
  50. Vector m_DispStabDir; // the direction to stab in
  51. int m_bDispHit; // hit displacement surface last
  52. bool m_bCheckPrimary;
  53. int m_nCheckDepth;
  54. TraceCounter_t m_Count[MAX_CHECK_COUNT_DEPTH];
  55. CTraceCounterVec m_BrushCounters[MAX_CHECK_COUNT_DEPTH];
  56. CTraceCounterVec m_DispCounters[MAX_CHECK_COUNT_DEPTH];
  57. TraceCounter_t GetCount() { return m_Count[m_nCheckDepth]; }
  58. TraceCounter_t *GetBrushCounters() { return m_BrushCounters[m_nCheckDepth].Base(); }
  59. TraceCounter_t *GetDispCounters() { return m_DispCounters[m_nCheckDepth].Base(); }
  60. bool Visit( cbrush_t *pBrush, int ndxBrush );
  61. bool Visit( int dispIndex );
  62. bool Visit( cbrush_t *pBrush, int ndxBrush, TraceCounter_t cachedCount, TraceCounter_t *pCachedCounters );
  63. bool Visit( int dispIndex, TraceCounter_t cachedCount, TraceCounter_t *pCachedCounters );
  64. };
  65. class CBspDebugLog;
  66. struct OcclusionTestResults_t;
  67. struct COcclusionInfo
  68. {
  69. COcclusionInfo()
  70. {
  71. V_memset( m_nBrushesChecked, 0, sizeof( m_nBrushesChecked ) );
  72. m_nBrushesChecked[ 0 ]/*[ 0 ] = m_nBrushesChecked[ 0 ][ 1 ] */= 0xFFFF; // the only associative line that can conceivably contain 0 is the line 0; set it to invalid value, effectively making it empty
  73. }
  74. bool PrepareCheckBrush( uint16 nBrush )
  75. {
  76. const uint nMask = ARRAYSIZE( m_nBrushesChecked ) - 1;
  77. uint16 * pLine = &m_nBrushesChecked[ nBrush & nMask ];
  78. if ( pLine[ 0 ] == nBrush /*|| pLine[ 1 ] == nBrush*/ )
  79. {
  80. s_nAssocArrayHits++;
  81. return false; // we already saw this brush
  82. }
  83. if ( ( pLine[ 0 ] & nMask ) == ( nBrush & nMask ) )
  84. ++s_nAssocArrayCollisions; // this entry was valid, we have to overwrite it with another entry
  85. //pLine[ 1 ] = pLine[ 0 ];
  86. ++s_nAssocArrayMisses;
  87. pLine[ 0 ] = nBrush;
  88. return true; // ok, maybe we saw this brush and maybe we didn't, we don't know for sure, but we didn't see it recently
  89. }
  90. fltx4 m_StartXnXYnY; // {p0+X0,p0-X0,p0+Y0,p0-Y0}
  91. fltx4 m_EndXnXYnY;// {p1+X1,p1-X1,p1+Y1,p1-Y1}
  92. fltx4 m_StartEndZnZ; // {p0+Z0,p0-Z0,p1+Z1,p1-Z1}
  93. FORCEINLINE fltx4 GetStartX()const { return ShuffleXYXY( m_StartXnXYnY ); } // {p0+X0, p0-X0,p0+X0,p0-X0}
  94. FORCEINLINE fltx4 GetStartY()const { return ShuffleZZWW( m_StartXnXYnY ); } // {p1+Y1, p1+Y1,p1-Y1,p1-Y1}
  95. FORCEINLINE fltx4 GetEndX()const { return ShuffleXYXY( m_EndXnXYnY ); } // {p0+X0, p0-X0,p0+X0,p0-X0}
  96. FORCEINLINE fltx4 GetEndY()const { return ShuffleZZWW( m_EndXnXYnY ); } // {p1+Y1, p1+Y1,p1-Y1,p1-Y1}
  97. FORCEINLINE fltx4 GetStartZ0()const { return SplatXSIMD( m_StartEndZnZ ); }
  98. FORCEINLINE fltx4 GetStartZ1()const { return SplatYSIMD( m_StartEndZnZ ); }
  99. FORCEINLINE fltx4 GetEndZ0()const { return SplatZSIMD( m_StartEndZnZ ); }
  100. FORCEINLINE fltx4 GetEndZ1()const { return SplatWSIMD( m_StartEndZnZ ); }
  101. uint16 m_nBrushesChecked[ 64 ]/*[ 2 ]*/; // associative array of brushes that have already been checked
  102. VectorAligned m_traceMins;
  103. VectorAligned m_traceMaxs;
  104. VectorAligned m_delta;
  105. VectorAligned m_deltaPos;
  106. static uint64 s_nAssocArrayCollisions;
  107. static uint64 s_nAssocArrayHits;
  108. static uint64 s_nAssocArrayMisses;
  109. Vector m_start;
  110. Vector m_end;
  111. Vector m_extents;
  112. Vector m_uvwExtents;
  113. Vector m_uvwMins;
  114. Vector m_uvwMaxs;
  115. Vector m_deltaSigns;
  116. // Vector m_minsPos;
  117. // Vector m_maxsPos;
  118. int m_contents;
  119. // BSP Data
  120. CCollisionBSPData *m_pBSPData;
  121. CBspDebugLog *m_pDebugLog;
  122. OcclusionTestResults_t *m_pResults;
  123. };
  124. extern TraceInfo_t g_PrimaryTraceInfo;
  125. #define NEVER_UPDATED -99999
  126. //=============================================================================
  127. //
  128. // Local CModel Structures (cmodel.cpp and cmodel_disp.cpp)
  129. //
  130. struct cbrushside_t
  131. {
  132. cplane_t *plane;
  133. unsigned short surfaceIndex;
  134. byte bBevel; // is the side a bevel plane?
  135. byte bThin; // is a thin brush side?
  136. };
  137. #define NUMSIDES_BOXBRUSH 0xFFFF
  138. struct cbrush_t
  139. {
  140. int contents;
  141. unsigned short numsides;
  142. unsigned short firstbrushside;
  143. inline int GetBox() const { return firstbrushside; }
  144. inline void SetBox( int boxID )
  145. {
  146. numsides = NUMSIDES_BOXBRUSH;
  147. firstbrushside = boxID;
  148. }
  149. inline bool IsBox() const { return numsides == NUMSIDES_BOXBRUSH ? true : false; }
  150. };
  151. // 48-bytes, aligned to 16-byte boundary
  152. // this is a brush that is an AABB. It's encoded this way instead of with 6 brushsides
  153. struct cboxbrush_t
  154. {
  155. VectorAligned mins;
  156. VectorAligned maxs;
  157. unsigned short surfaceIndex[6];
  158. unsigned short thinMask;
  159. unsigned short pad;
  160. };
  161. struct cleaf_t
  162. {
  163. int contents;
  164. short cluster;
  165. short area : 9;
  166. short flags : 7;
  167. unsigned short firstleafbrush;
  168. unsigned short numleafbrushes;
  169. unsigned short dispListStart;
  170. unsigned short dispCount;
  171. };
  172. struct carea_t
  173. {
  174. int numareaportals;
  175. int firstareaportal;
  176. int floodnum; // if two areas have equal floodnums, they are connected
  177. int floodvalid;
  178. };
  179. struct cnode_t
  180. {
  181. cplane_t *plane;
  182. int children[2]; // negative numbers are leafs
  183. };
  184. // global collision checkcount
  185. TraceInfo_t *BeginTrace();
  186. void PushTraceVisits( TraceInfo_t *pTraceInfo );
  187. void PopTraceVisits( TraceInfo_t *pTraceInfo );
  188. void EndTrace( TraceInfo_t *&pTraceInfo );
  189. //-----------------------------------------------------------------------------
  190. // We keep running into overflow errors here. This is to avoid that problem
  191. //-----------------------------------------------------------------------------
  192. template <class T>
  193. class CRangeValidatedArray
  194. {
  195. public:
  196. void Attach( int nCount, T* pData );
  197. void Detach();
  198. T &operator[]( int i );
  199. const T &operator[]( int i ) const;
  200. T *Base();
  201. private:
  202. T *m_pArray;
  203. #ifdef DBGFLAG_ASSERT
  204. int m_nCount;
  205. #endif
  206. };
  207. template <class T>
  208. inline T &CRangeValidatedArray<T>::operator[]( int i )
  209. {
  210. Assert( (i >= 0) && (i < m_nCount) );
  211. return m_pArray[i];
  212. }
  213. template <class T>
  214. inline const T &CRangeValidatedArray<T>::operator[]( int i ) const
  215. {
  216. Assert( (i >= 0) && (i < m_nCount) );
  217. return m_pArray[i];
  218. }
  219. template <class T>
  220. inline void CRangeValidatedArray<T>::Attach( int nCount, T* pData )
  221. {
  222. m_pArray = pData;
  223. #ifdef DBGFLAG_ASSERT
  224. m_nCount = nCount;
  225. #endif
  226. }
  227. template <class T>
  228. inline void CRangeValidatedArray<T>::Detach()
  229. {
  230. m_pArray = NULL;
  231. #ifdef DBGFLAG_ASSERT
  232. m_nCount = 0;
  233. #endif
  234. }
  235. template <class T>
  236. inline T *CRangeValidatedArray<T>::Base()
  237. {
  238. return m_pArray;
  239. }
  240. //-----------------------------------------------------------------------------
  241. // A dumpable version of RangeValidatedArray
  242. //-----------------------------------------------------------------------------
  243. #include "tier0/memdbgon.h"
  244. template <class T>
  245. class CDiscardableArray
  246. {
  247. public:
  248. CDiscardableArray()
  249. {
  250. m_nCount = 0;
  251. m_nOffset = -1;
  252. memset( m_pFilename, 0, sizeof( m_pFilename ) );
  253. }
  254. ~CDiscardableArray()
  255. {
  256. }
  257. void Init( char* pFilename, int nOffset, int nCount, void *pData = NULL )
  258. {
  259. if ( m_buf.TellPut() )
  260. {
  261. Discard();
  262. }
  263. m_nCount = nCount;
  264. V_strcpy_safe( m_pFilename, pFilename );
  265. m_nOffset = nOffset;
  266. // can preload as required
  267. if ( pData )
  268. {
  269. m_buf.Put( pData, nCount );
  270. }
  271. }
  272. // Either get or load the array as needed:
  273. T* Get()
  274. {
  275. if ( !m_buf.TellPut() )
  276. {
  277. MEM_ALLOC_CREDIT();
  278. if ( !g_pFileSystem->ReadFile( m_pFilename, NULL, m_buf, sizeof(T) * m_nCount, m_nOffset ) )
  279. {
  280. return NULL;
  281. }
  282. }
  283. return (T *)m_buf.PeekGet();
  284. }
  285. void Discard()
  286. {
  287. m_buf.Purge();
  288. }
  289. protected:
  290. int m_nCount;
  291. CUtlBuffer m_buf;
  292. char m_pFilename[256];
  293. int m_nOffset;
  294. };
  295. #include "tier0/memdbgoff.h"
  296. const int SURFACE_INDEX_INVALID = 0xFFFF;
  297. //=============================================================================
  298. //
  299. // Collision BSP Data Class
  300. //
  301. class CCollisionBSPData
  302. {
  303. public:
  304. // This is sort of a hack, but it was a little too painful to do this any other way
  305. // The goal of this dude is to allow us to override the tree with some
  306. // other tree (or a subtree)
  307. cnode_t* map_rootnode;
  308. char mapPathName[MAX_QPATH];
  309. static csurface_t nullsurface;
  310. int numbrushsides;
  311. CRangeValidatedArray<cbrushside_t> map_brushsides;
  312. int numboxbrushes;
  313. CRangeValidatedArray<cboxbrush_t> map_boxbrushes;
  314. int numplanes;
  315. CRangeValidatedArray<cplane_t> map_planes;
  316. int numnodes;
  317. CRangeValidatedArray<cnode_t> map_nodes;
  318. int numleafs; // allow leaf funcs to be called without a map
  319. CRangeValidatedArray<cleaf_t> map_leafs;
  320. int emptyleaf, solidleaf;
  321. int numleafbrushes;
  322. CRangeValidatedArray<unsigned short> map_leafbrushes;
  323. int numcmodels;
  324. CRangeValidatedArray<cmodel_t> map_cmodels;
  325. int numbrushes;
  326. CRangeValidatedArray<cbrush_t> map_brushes;
  327. int numdisplist;
  328. CRangeValidatedArray<unsigned short> map_dispList;
  329. // this points to the whole block of memory for vis data, but it is used to
  330. // reference the header at the top of the block.
  331. int numvisibility;
  332. dvis_t *map_vis;
  333. int numentitychars;
  334. CDiscardableArray<char> map_entitystring;
  335. int numareas;
  336. CRangeValidatedArray<carea_t> map_areas;
  337. int numareaportals;
  338. CRangeValidatedArray<dareaportal_t> map_areaportals;
  339. int numclusters;
  340. char *map_nullname;
  341. int numtextures;
  342. char *map_texturenames;
  343. CRangeValidatedArray<csurface_t> map_surfaces;
  344. int floodvalid;
  345. int numportalopen;
  346. CRangeValidatedArray<bool> portalopen;
  347. int allcontents;
  348. csurface_t *GetSurfaceAtIndex( unsigned short surfaceIndex );
  349. };
  350. //=============================================================================
  351. //
  352. // physics collision
  353. //
  354. class IPhysicsSurfaceProps;
  355. class IPhysicsCollision;
  356. extern IPhysicsSurfaceProps *physprops;
  357. extern IPhysicsCollision *physcollision;
  358. //=============================================================================
  359. //
  360. // This might eventually become a class/interface when we want multiple instances
  361. // etc.......for now....
  362. //
  363. extern csurface_t nullsurface;
  364. extern bool bStartSolidDisp;
  365. bool CollisionBSPData_Init( CCollisionBSPData *pBSPData );
  366. void CollisionBSPData_Destroy( CCollisionBSPData *pBSPData );
  367. void CollisionBSPData_LinkPhysics( void );
  368. void CollisionBSPData_PreLoad( CCollisionBSPData *pBSPData );
  369. bool CollisionBSPData_Load( const char *pPathName, CCollisionBSPData *pBSPData, texinfo_t *pTexinfo, int texInfoCount );
  370. void CollisionBSPData_PostLoad( void );
  371. //-----------------------------------------------------------------------------
  372. // Returns the collision tree associated with the ith displacement
  373. //-----------------------------------------------------------------------------
  374. CDispCollTree* CollisionBSPData_GetCollisionTree( int i );
  375. //-----------------------------------------------------------------------------
  376. //-----------------------------------------------------------------------------
  377. inline CCollisionBSPData *GetCollisionBSPData( void /*int ndxBSP*/ )
  378. {
  379. extern CCollisionBSPData g_BSPData; // the global collision bsp
  380. return &g_BSPData;
  381. }
  382. //=============================================================================
  383. //
  384. // Collision Model Counts
  385. //
  386. #ifdef COUNT_COLLISIONS
  387. class CCollisionCounts
  388. {
  389. public:
  390. int m_PointContents;
  391. int m_Traces;
  392. int m_BrushTraces;
  393. int m_DispTraces;
  394. int m_Stabs;
  395. };
  396. void CollisionCounts_Init( CCollisionCounts *pCounts );
  397. extern CCollisionCounts g_CollisionCounts;
  398. #endif
  399. //=============================================================================
  400. //
  401. // Older Code That Should Live Here!!!!
  402. // a shared file should contain all the CDispCollTree stuff
  403. //
  404. //=============================================================================
  405. //
  406. // Displacement Collision Functions and Data
  407. //
  408. // UNDONE: Find a way to overlap the counter/contents bits with mins.w/maxs.w without hosing performance
  409. struct alignedbbox_t
  410. {
  411. VectorAligned mins;
  412. VectorAligned maxs;
  413. int dispCounter;
  414. int dispContents;
  415. int pad[2];
  416. void SetCounter(int counter)
  417. {
  418. dispCounter = counter;
  419. }
  420. int GetCounter()
  421. {
  422. return dispCounter;
  423. }
  424. void SetContents(int contents)
  425. {
  426. dispContents = contents;
  427. }
  428. int GetContents()
  429. {
  430. return dispContents;
  431. }
  432. void Init( const Vector &minsIn, const Vector &maxsIn, int counterIn, int contentsIn )
  433. {
  434. mins = minsIn;
  435. SetCounter(counterIn);
  436. maxs = maxsIn;
  437. SetContents(contentsIn);
  438. }
  439. };
  440. #define TLD_DEF_BRUSH_MAX 64
  441. #define TLD_DEF_DISP_MAX 32
  442. #define TLD_DEF_ENTITY_MAX 64
  443. class ICollideable;
  444. class IHandleEntity;
  445. class IEngineTrace;
  446. struct collideable_handleentity_t
  447. {
  448. IHandleEntity *pEntity;
  449. ICollideable *pCollideable;
  450. };
  451. class CTraceListData : public IPartitionEnumerator, public ITraceListData
  452. {
  453. public:
  454. CTraceListData()
  455. {
  456. m_pEngineTrace = NULL;
  457. m_bFoundNonSolidLeaf = false;
  458. m_mins.Init();
  459. m_maxs.Init();
  460. }
  461. ~CTraceListData() {}
  462. void Reset()
  463. {
  464. m_brushList.RemoveAll();
  465. m_dispList.RemoveAll();
  466. m_entityList.RemoveAll();
  467. m_staticPropList.RemoveAll();
  468. m_mins.Init();
  469. m_maxs.Init();
  470. m_pEngineTrace = NULL;
  471. m_bFoundNonSolidLeaf = false;
  472. }
  473. bool IsEmpty() { return m_pEngineTrace == NULL ? true : false; }
  474. // For entities...
  475. IterationRetval_t EnumElement( IHandleEntity *pHandleEntity );
  476. bool CanTraceRay( const Ray_t &ray );
  477. public:
  478. CUtlVectorFixedGrowable<unsigned short, TLD_DEF_BRUSH_MAX> m_brushList;
  479. CUtlVectorFixedGrowable<unsigned short, TLD_DEF_DISP_MAX> m_dispList;
  480. CUtlVectorFixedGrowable<collideable_handleentity_t, TLD_DEF_ENTITY_MAX> m_entityList;
  481. CUtlVectorFixedGrowable<collideable_handleentity_t, TLD_DEF_ENTITY_MAX> m_staticPropList;
  482. Vector m_mins;
  483. Vector m_maxs;
  484. class CEngineTrace *m_pEngineTrace;
  485. bool m_bFoundNonSolidLeaf;
  486. };
  487. extern int g_DispCollTreeCount;
  488. extern CDispCollTree *g_pDispCollTrees;
  489. extern alignedbbox_t *g_pDispBounds;
  490. extern csurface_t dispSurf;
  491. // memory allocation/de-allocation
  492. void DispCollTrees_FreeLeafList( CCollisionBSPData *pBSPData );
  493. // setup
  494. void CM_DispTreeLeafnum( CCollisionBSPData *pBSPData );
  495. // collision
  496. void CM_TestInDispTree( TraceInfo_t *pTraceInfo, const unsigned short *pDispList, int dispListCount, const Vector &traceStart,
  497. const Vector &boxMin, const Vector &boxMax, int collisionMask, trace_t *pTrace );
  498. template <bool IS_POINT>
  499. void FASTCALL CM_TraceToDispTree( TraceInfo_t *pTraceInfo, CDispCollTree *pDispTree, float startFrac, float endFrac );
  500. void CM_PostTraceToDispTree( TraceInfo_t *pTraceInfo );
  501. //=============================================================================
  502. //
  503. // profiling purposes only -- remove when done!!!
  504. //
  505. void CM_TestBoxInBrush ( const Vector& mins, const Vector& maxs, const Vector& p1,
  506. trace_t *trace, cbrush_t *brush, BOOL bDispSurf );
  507. void FASTCALL CM_TestBoxInBrush( TraceInfo_t *pTraceInfo, const cbrush_t *brush );
  508. void FASTCALL CM_RecursiveHullCheck ( TraceInfo_t *pTraceInfo, int num, const float p1f, const float p2f );
  509. bool FASTCALL CM_RecursiveOcclusionPass( COcclusionInfo &oi, int num, const float p1f, const float p2f, const Vector& p1, const Vector& p2 );
  510. void CM_GetTraceDataForBSP( const Vector &mins, const Vector &maxs, CTraceListData &traceData );
  511. //=============================================================================
  512. inline bool TraceInfo_t::Visit( cbrush_t *pBrush, int ndxBrush, TraceCounter_t cachedCount, TraceCounter_t *pCachedCounters )
  513. {
  514. TraceCounter_t * RESTRICT pCounter = pCachedCounters + ndxBrush;
  515. if ( *pCounter == cachedCount )
  516. {
  517. return false;
  518. }
  519. *pCounter = cachedCount;
  520. return true;
  521. }
  522. FORCEINLINE bool TraceInfo_t::Visit( int dispCounter, TraceCounter_t cachedCount, TraceCounter_t *pCachedCounters )
  523. {
  524. TraceCounter_t * RESTRICT pCounter = pCachedCounters + dispCounter;
  525. if ( *pCounter == cachedCount )
  526. {
  527. return false;
  528. }
  529. *pCounter = cachedCount;
  530. return true;
  531. }
  532. FORCEINLINE bool TraceInfo_t::Visit( cbrush_t *pBrush, int ndxBrush )
  533. {
  534. return Visit( pBrush, ndxBrush, GetCount(), GetBrushCounters() );
  535. }
  536. FORCEINLINE bool TraceInfo_t::Visit( int dispIndex )
  537. {
  538. return Visit( dispIndex, GetCount(), GetDispCounters() );
  539. }
  540. #endif // CMODEL_PRIVATE_H