Team Fortress 2 Source Code as on 22/4/2020
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.

528 lines
13 KiB

  1. //========= Copyright 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. extern TraceInfo_t g_PrimaryTraceInfo;
  66. #define NEVER_UPDATED -99999
  67. //=============================================================================
  68. //
  69. // Local CModel Structures (cmodel.cpp and cmodel_disp.cpp)
  70. //
  71. struct cbrushside_t
  72. {
  73. cplane_t *plane;
  74. unsigned short surfaceIndex;
  75. unsigned short bBevel; // is the side a bevel plane?
  76. };
  77. #define NUMSIDES_BOXBRUSH 0xFFFF
  78. struct cbrush_t
  79. {
  80. int contents;
  81. unsigned short numsides;
  82. unsigned short firstbrushside;
  83. inline int GetBox() const { return firstbrushside; }
  84. inline void SetBox( int boxID )
  85. {
  86. numsides = NUMSIDES_BOXBRUSH;
  87. firstbrushside = boxID;
  88. }
  89. inline bool IsBox() const { return numsides == NUMSIDES_BOXBRUSH ? true : false; }
  90. };
  91. // 48-bytes, aligned to 16-byte boundary
  92. // this is a brush that is an AABB. It's encoded this way instead of with 6 brushsides
  93. struct cboxbrush_t
  94. {
  95. VectorAligned mins;
  96. VectorAligned maxs;
  97. unsigned short surfaceIndex[6];
  98. unsigned short pad2[2];
  99. };
  100. struct cleaf_t
  101. {
  102. int contents;
  103. short cluster;
  104. short area : 9;
  105. short flags : 7;
  106. unsigned short firstleafbrush;
  107. unsigned short numleafbrushes;
  108. unsigned short dispListStart;
  109. unsigned short dispCount;
  110. };
  111. struct carea_t
  112. {
  113. int numareaportals;
  114. int firstareaportal;
  115. int floodnum; // if two areas have equal floodnums, they are connected
  116. int floodvalid;
  117. };
  118. struct cnode_t
  119. {
  120. cplane_t *plane;
  121. int children[2]; // negative numbers are leafs
  122. };
  123. // global collision checkcount
  124. TraceInfo_t *BeginTrace();
  125. void PushTraceVisits( TraceInfo_t *pTraceInfo );
  126. void PopTraceVisits( TraceInfo_t *pTraceInfo );
  127. void EndTrace( TraceInfo_t *&pTraceInfo );
  128. //-----------------------------------------------------------------------------
  129. // We keep running into overflow errors here. This is to avoid that problem
  130. //-----------------------------------------------------------------------------
  131. template <class T>
  132. class CRangeValidatedArray
  133. {
  134. public:
  135. void Attach( int nCount, T* pData );
  136. void Detach();
  137. T &operator[]( int i );
  138. const T &operator[]( int i ) const;
  139. T *Base();
  140. private:
  141. T *m_pArray;
  142. #ifdef DBGFLAG_ASSERT
  143. int m_nCount;
  144. #endif
  145. };
  146. template <class T>
  147. inline T &CRangeValidatedArray<T>::operator[]( int i )
  148. {
  149. Assert( (i >= 0) && (i < m_nCount) );
  150. return m_pArray[i];
  151. }
  152. template <class T>
  153. inline const T &CRangeValidatedArray<T>::operator[]( int i ) const
  154. {
  155. Assert( (i >= 0) && (i < m_nCount) );
  156. return m_pArray[i];
  157. }
  158. template <class T>
  159. inline void CRangeValidatedArray<T>::Attach( int nCount, T* pData )
  160. {
  161. m_pArray = pData;
  162. #ifdef DBGFLAG_ASSERT
  163. m_nCount = nCount;
  164. #endif
  165. }
  166. template <class T>
  167. inline void CRangeValidatedArray<T>::Detach()
  168. {
  169. m_pArray = NULL;
  170. #ifdef DBGFLAG_ASSERT
  171. m_nCount = 0;
  172. #endif
  173. }
  174. template <class T>
  175. inline T *CRangeValidatedArray<T>::Base()
  176. {
  177. return m_pArray;
  178. }
  179. //-----------------------------------------------------------------------------
  180. // A dumpable version of RangeValidatedArray
  181. //-----------------------------------------------------------------------------
  182. #include "tier0/memdbgon.h"
  183. template <class T>
  184. class CDiscardableArray
  185. {
  186. public:
  187. CDiscardableArray()
  188. {
  189. m_nCount = 0;
  190. m_nOffset = -1;
  191. memset( m_pFilename, 0, sizeof( m_pFilename ) );
  192. }
  193. ~CDiscardableArray()
  194. {
  195. }
  196. void Init( char* pFilename, int nOffset, int nCount, void *pData = NULL )
  197. {
  198. if ( m_buf.TellPut() )
  199. {
  200. m_buf.Purge();
  201. }
  202. m_nCount = nCount;
  203. V_strcpy_safe( m_pFilename, pFilename );
  204. m_nOffset = nOffset;
  205. // can preload as required
  206. if ( pData )
  207. {
  208. m_buf.Put( pData, nCount );
  209. }
  210. }
  211. // Either get or load the array as needed:
  212. T* Get()
  213. {
  214. if ( !m_buf.TellPut() )
  215. {
  216. MEM_ALLOC_CREDIT();
  217. if ( !g_pFileSystem->ReadFile( m_pFilename, NULL, m_buf, sizeof(T) * m_nCount, m_nOffset ) )
  218. {
  219. return NULL;
  220. }
  221. }
  222. return (T *)m_buf.PeekGet();
  223. }
  224. void Discard()
  225. {
  226. // TODO(johns): Neutered -- Tear this class out. This can no longer be discarded with transparently compressed
  227. // BSPs. This is on the range of 500k of memory, and is probably overly complex for the savings in
  228. // the current era.
  229. DevMsg("TODO: Refusing to discard %u bytes\n", sizeof(T) * m_nCount);
  230. // m_buf.Purge();
  231. }
  232. protected:
  233. int m_nCount;
  234. CUtlBuffer m_buf;
  235. char m_pFilename[256];
  236. int m_nOffset;
  237. };
  238. #include "tier0/memdbgoff.h"
  239. const int SURFACE_INDEX_INVALID = 0xFFFF;
  240. //=============================================================================
  241. //
  242. // Collision BSP Data Class
  243. //
  244. class CCollisionBSPData
  245. {
  246. public:
  247. // This is sort of a hack, but it was a little too painful to do this any other way
  248. // The goal of this dude is to allow us to override the tree with some
  249. // other tree (or a subtree)
  250. cnode_t* map_rootnode;
  251. char map_name[MAX_QPATH];
  252. static csurface_t nullsurface;
  253. int numbrushsides;
  254. CRangeValidatedArray<cbrushside_t> map_brushsides;
  255. int numboxbrushes;
  256. CRangeValidatedArray<cboxbrush_t> map_boxbrushes;
  257. int numplanes;
  258. CRangeValidatedArray<cplane_t> map_planes;
  259. int numnodes;
  260. CRangeValidatedArray<cnode_t> map_nodes;
  261. int numleafs; // allow leaf funcs to be called without a map
  262. CRangeValidatedArray<cleaf_t> map_leafs;
  263. int emptyleaf, solidleaf;
  264. int numleafbrushes;
  265. CRangeValidatedArray<unsigned short> map_leafbrushes;
  266. int numcmodels;
  267. CRangeValidatedArray<cmodel_t> map_cmodels;
  268. int numbrushes;
  269. CRangeValidatedArray<cbrush_t> map_brushes;
  270. int numdisplist;
  271. CRangeValidatedArray<unsigned short> map_dispList;
  272. // this points to the whole block of memory for vis data, but it is used to
  273. // reference the header at the top of the block.
  274. int numvisibility;
  275. dvis_t *map_vis;
  276. int numentitychars;
  277. CDiscardableArray<char> map_entitystring;
  278. int numareas;
  279. CRangeValidatedArray<carea_t> map_areas;
  280. int numareaportals;
  281. CRangeValidatedArray<dareaportal_t> map_areaportals;
  282. int numclusters;
  283. char *map_nullname;
  284. int numtextures;
  285. char *map_texturenames;
  286. CRangeValidatedArray<csurface_t> map_surfaces;
  287. int floodvalid;
  288. int numportalopen;
  289. CRangeValidatedArray<bool> portalopen;
  290. csurface_t *GetSurfaceAtIndex( unsigned short surfaceIndex );
  291. };
  292. //=============================================================================
  293. //
  294. // physics collision
  295. //
  296. class IPhysicsSurfaceProps;
  297. class IPhysicsCollision;
  298. extern IPhysicsSurfaceProps *physprop;
  299. extern IPhysicsCollision *physcollision;
  300. //=============================================================================
  301. //
  302. // This might eventually become a class/interface when we want multiple instances
  303. // etc.......for now....
  304. //
  305. extern csurface_t nullsurface;
  306. extern bool bStartSolidDisp;
  307. bool CollisionBSPData_Init( CCollisionBSPData *pBSPData );
  308. void CollisionBSPData_Destroy( CCollisionBSPData *pBSPData );
  309. void CollisionBSPData_LinkPhysics( void );
  310. void CollisionBSPData_PreLoad( CCollisionBSPData *pBSPData );
  311. bool CollisionBSPData_Load( const char *pName, CCollisionBSPData *pBSPData );
  312. void CollisionBSPData_PostLoad( void );
  313. //-----------------------------------------------------------------------------
  314. // Returns the collision tree associated with the ith displacement
  315. //-----------------------------------------------------------------------------
  316. CDispCollTree* CollisionBSPData_GetCollisionTree( int i );
  317. //-----------------------------------------------------------------------------
  318. //-----------------------------------------------------------------------------
  319. inline CCollisionBSPData *GetCollisionBSPData( void /*int ndxBSP*/ )
  320. {
  321. extern CCollisionBSPData g_BSPData; // the global collision bsp
  322. return &g_BSPData;
  323. }
  324. //=============================================================================
  325. //
  326. // Collision Model Counts
  327. //
  328. #ifdef COUNT_COLLISIONS
  329. class CCollisionCounts
  330. {
  331. public:
  332. int m_PointContents;
  333. int m_Traces;
  334. int m_BrushTraces;
  335. int m_DispTraces;
  336. int m_Stabs;
  337. };
  338. void CollisionCounts_Init( CCollisionCounts *pCounts );
  339. extern CCollisionCounts g_CollisionCounts;
  340. #endif
  341. //=============================================================================
  342. //
  343. // Older Code That Should Live Here!!!!
  344. // a shared file should contain all the CDispCollTree stuff
  345. //
  346. //=============================================================================
  347. //
  348. // Displacement Collision Functions and Data
  349. //
  350. // UNDONE: Find a way to overlap the counter/contents bits with mins.w/maxs.w without hosing performance
  351. struct alignedbbox_t
  352. {
  353. VectorAligned mins;
  354. VectorAligned maxs;
  355. int dispCounter;
  356. int dispContents;
  357. int pad[2];
  358. void SetCounter(int counter)
  359. {
  360. dispCounter = counter;
  361. }
  362. int GetCounter()
  363. {
  364. return dispCounter;
  365. }
  366. void SetContents(int contents)
  367. {
  368. dispContents = contents;
  369. }
  370. int GetContents()
  371. {
  372. return dispContents;
  373. }
  374. void Init( const Vector &minsIn, const Vector &maxsIn, int counterIn, int contentsIn )
  375. {
  376. mins = minsIn;
  377. SetCounter(counterIn);
  378. maxs = maxsIn;
  379. SetContents(contentsIn);
  380. }
  381. };
  382. extern int g_DispCollTreeCount;
  383. extern CDispCollTree *g_pDispCollTrees;
  384. extern alignedbbox_t *g_pDispBounds;
  385. extern csurface_t dispSurf;
  386. // memory allocation/de-allocation
  387. void DispCollTrees_FreeLeafList( CCollisionBSPData *pBSPData );
  388. // setup
  389. void CM_DispTreeLeafnum( CCollisionBSPData *pBSPData );
  390. // collision
  391. void CM_TestInDispTree( TraceInfo_t *pTraceInfo, cleaf_t *pLeaf, Vector const &traceStart,
  392. Vector const &boxMin, Vector const &boxMax, int collisionMask, trace_t *pTrace );
  393. template <bool IS_POINT>
  394. void FASTCALL CM_TraceToDispTree( TraceInfo_t *pTraceInfo, CDispCollTree *pDispTree, float startFrac, float endFrac );
  395. void CM_PostTraceToDispTree( TraceInfo_t *pTraceInfo );
  396. //=============================================================================
  397. //
  398. // profiling purposes only -- remove when done!!!
  399. //
  400. void CM_TestBoxInBrush ( const Vector& mins, const Vector& maxs, const Vector& p1,
  401. trace_t *trace, cbrush_t *brush, BOOL bDispSurf );
  402. void FASTCALL CM_RecursiveHullCheck ( TraceInfo_t *pTraceInfo, int num, const float p1f, const float p2f );
  403. //=============================================================================
  404. inline bool TraceInfo_t::Visit( cbrush_t *pBrush, int ndxBrush, TraceCounter_t cachedCount, TraceCounter_t *pCachedCounters )
  405. {
  406. TraceCounter_t * RESTRICT pCounter = pCachedCounters + ndxBrush;
  407. if ( *pCounter == cachedCount )
  408. {
  409. return false;
  410. }
  411. *pCounter = cachedCount;
  412. return true;
  413. }
  414. FORCEINLINE bool TraceInfo_t::Visit( int dispCounter, TraceCounter_t cachedCount, TraceCounter_t *pCachedCounters )
  415. {
  416. TraceCounter_t * RESTRICT pCounter = pCachedCounters + dispCounter;
  417. if ( *pCounter == cachedCount )
  418. {
  419. return false;
  420. }
  421. *pCounter = cachedCount;
  422. return true;
  423. }
  424. FORCEINLINE bool TraceInfo_t::Visit( cbrush_t *pBrush, int ndxBrush )
  425. {
  426. return Visit( pBrush, ndxBrush, GetCount(), GetBrushCounters() );
  427. }
  428. FORCEINLINE bool TraceInfo_t::Visit( int dispIndex )
  429. {
  430. return Visit( dispIndex, GetCount(), GetDispCounters() );
  431. }
  432. #endif // CMODEL_PRIVATE_H