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.

237 lines
10 KiB

  1. //============ Copyright (c) Valve Corporation, All rights reserved. ============
  2. //
  3. // Utility functions for BSP and map file math operations.
  4. //
  5. //===============================================================================
  6. #ifndef VBSPMATHUTIL_H
  7. #define VBSPMATHUTIL_H
  8. #if defined( COMPILER_MSVC )
  9. #pragma once
  10. #endif
  11. #include "utlvector.h"
  12. #include "mathlib/vector.h"
  13. #include "worldsize.h"
  14. #include "bspfile.h"
  15. DECLARE_LOGGING_CHANNEL( LOG_VBSP2 );
  16. //-----------------------------------------------------------------------------
  17. // A threshold used to determine whether coordinates of two normals are equal.
  18. //-----------------------------------------------------------------------------
  19. static const float c_flNormalEpsilon = 0.00001f;
  20. //-----------------------------------------------------------------------------
  21. // A threshold used to determine whether the distance value of two planes
  22. // are equal. Also used for rounding coordinates to the nearest integer.
  23. //-----------------------------------------------------------------------------
  24. static const float c_flDistanceEpsilon = 0.01f;
  25. //-----------------------------------------------------------------------------
  26. // Threshold used to determine whether something is entirely on one side
  27. // of a plane or another.
  28. //-----------------------------------------------------------------------------
  29. static const float c_flPlaneSideEpsilon = 0.1f;
  30. //-----------------------------------------------------------------------------
  31. // Threshold used to determine whether points should be snapped to each other.
  32. //-----------------------------------------------------------------------------
  33. static const float c_flWeldVertexEpsilon = 0.1f;
  34. //-----------------------------------------------------------------------------
  35. // Threshold used when clipping to determine whether a point is on a plane
  36. // or on a particular side.
  37. //-----------------------------------------------------------------------------
  38. static const float c_flPlaneClipEpsilon = 0.01f;
  39. //-----------------------------------------------------------------------------
  40. // Polygons with more points than this are not handled properly by
  41. // the system.
  42. //-----------------------------------------------------------------------------
  43. static const int MAX_POINTS_ON_POLYGON = 64;
  44. //-----------------------------------------------------------------------------
  45. // Represents a plane.
  46. // Unlike a standard plane equation, a point P is defined to be on a plane if
  47. // P * m_vNormal - m_flDistance == 0.
  48. // A point P is defined to be in the positive half-space if
  49. // P * m_vNormal - m_flDistance > 0.
  50. // (In a standard plane equation that minus sign is a plus sign)
  51. //-----------------------------------------------------------------------------
  52. struct Plane_t
  53. {
  54. Vector m_vNormal;
  55. float m_flDistance;
  56. // A value in the range [0,5] which indicates the axis alignment,
  57. // e.g. PLANE_X, PLANE_Y, PLANE_Z, PLANE_ANYX, PLANE_ANYY, PLANE_ANYZ
  58. int m_Type;
  59. };
  60. //-----------------------------------------------------------------------------
  61. // Flags indicating on which side of a plane something lies.
  62. //-----------------------------------------------------------------------------
  63. enum PlaneSide_t
  64. {
  65. PLANE_SIDE_INVALID = 0,
  66. PLANE_SIDE_FRONT = 1,
  67. PLANE_SIDE_BACK = 2,
  68. PLANE_SIDE_BOTH = PLANE_SIDE_FRONT | PLANE_SIDE_BACK,
  69. // "Facing" means that the point or face is directly on the plane;
  70. // this may be combined with front or back to take into account
  71. // direction.
  72. PLANE_SIDE_FACING = 4,
  73. };
  74. //-----------------------------------------------------------------------------
  75. // Returns which side of a plane a bounding box is on.
  76. //-----------------------------------------------------------------------------
  77. PlaneSide_t GetPlaneSide( const Vector &vMin, const Vector &vMax, Plane_t *pPlane );
  78. //-----------------------------------------------------------------------------
  79. // Snaps the plane to be axis-aligned if it is within an epsilon of axial.
  80. //-----------------------------------------------------------------------------
  81. bool SnapVector( Vector &vNormal );
  82. //-----------------------------------------------------------------------------
  83. // Snaps the plane to be axis-aligned if it is within an epsilon of axial.
  84. // Recalculates dist if the vNormal was snapped. Rounds dist to integer
  85. // if it is within an epsilon of integer.
  86. //
  87. // vNormal - Plane vNormal vector (assumed to be unit length).
  88. // flDistance - Plane constant.
  89. // v0, v1, v2 - Three points on the plane.
  90. //-----------------------------------------------------------------------------
  91. void SnapPlane( Vector &vNormal, vec_t &flDistance, const Vector &v0, const Vector &v1, const Vector &v2 );
  92. //-----------------------------------------------------------------------------
  93. // Returns true if one plane representation is equal to the other,
  94. // within an epsilon threshold.
  95. //-----------------------------------------------------------------------------
  96. bool PlaneEqual( Plane_t *pPlane, const Vector &vNormal, float flDistance );
  97. //-----------------------------------------------------------------------------
  98. // Returns a value classifying the plane based on its axis alignment,
  99. // e.g. PLANE_X, PLANE_Y, PLANE_Z, PLANE_ANYX, PLANE_ANYY, PLANE_ANYZ
  100. //-----------------------------------------------------------------------------
  101. int GetPlaneTypeFromNormal( const Vector &vNormal );
  102. //-----------------------------------------------------------------------------
  103. // Compute a normal for a triangle, given three points.
  104. // The points are clockwise when looking at the triangle from the normal side.
  105. //-----------------------------------------------------------------------------
  106. Vector TriangleNormal( const Vector &v0, const Vector &v1, const Vector &v2 );
  107. //-----------------------------------------------------------------------------
  108. // A polygon used to represent faces on maps, BSPs, etc.
  109. // This class is copyable.
  110. //-----------------------------------------------------------------------------
  111. class Polygon_t
  112. {
  113. public:
  114. CCopyableUtlVector< Vector > m_Points;
  115. };
  116. //-----------------------------------------------------------------------------
  117. // Computes whether a given polygon is tiny, relative to an epsilon threshold
  118. //-----------------------------------------------------------------------------
  119. bool IsPolygonTiny( Polygon_t *pPolygon );
  120. //-----------------------------------------------------------------------------
  121. // Checks all points in a polygon against the min and max coordinates.
  122. //-----------------------------------------------------------------------------
  123. bool IsPolygonHuge( Polygon_t *pPolygon );
  124. //-----------------------------------------------------------------------------
  125. // Computes the area of a polygon
  126. //-----------------------------------------------------------------------------
  127. float ComputePolygonArea( const Polygon_t &polygon );
  128. //-----------------------------------------------------------------------------
  129. // Creates a large polygon with extremal coordinates that lies on the plane
  130. //-----------------------------------------------------------------------------
  131. void CreatePolygonFromPlane( const Vector &vNormal, float flDistance, Polygon_t *pPolygon );
  132. //-----------------------------------------------------------------------------
  133. // Clips a polygon against a plane, creating* either:
  134. // 1) One new, identical polygon (pOn), if the polygon is coincident
  135. // with the plane.
  136. // 2) One new, identical polygon (either pFront or pBack) if the polygon
  137. // is entirely on one side of the plane.
  138. // 3) Two new, different polygons (pFront and pBack) if the polygon is
  139. // clipped by the plane
  140. //
  141. // If pOn is NULL, the "on" case is ignored and treated as either front
  142. // or back appropriately.
  143. //
  144. // *The passed-in polygons (pOn, pFront, pBack) have their point arrays
  145. // cleared at the start of the function. They are considered to be
  146. // "created" upon exit if their point array has a non-zero point count.
  147. //-----------------------------------------------------------------------------
  148. void ChopPolygon( const Polygon_t &polygon, const Vector &vNormal, float flDistance, Polygon_t *pOn, Polygon_t *pFront, Polygon_t *pBack );
  149. //-----------------------------------------------------------------------------
  150. // Clips a polygon against a plane. If the polygon is completely clipped,
  151. // pPolygon->m_Points will be empty ( Count() == 0 ).
  152. //-----------------------------------------------------------------------------
  153. void ChopPolygonInPlace( Polygon_t *pPolygon, const Vector &vNormal, float flDistance );
  154. //-----------------------------------------------------------------------------
  155. // A plane which can be stored efficiently in a hash table for fast lookup.
  156. //-----------------------------------------------------------------------------
  157. struct HashedPlane_t : public Plane_t
  158. {
  159. int m_nNextPlaneIndex;
  160. };
  161. // Make sure this is a power of 2, code depends on it.
  162. static const int PLANE_HASH_TABLE_SIZE = 1024;
  163. //-----------------------------------------------------------------------------
  164. // A class to hash and pool planes.
  165. //-----------------------------------------------------------------------------
  166. class CPlaneHash
  167. {
  168. public:
  169. CPlaneHash();
  170. int FindPlaneIndex( const Vector &vNormal, float flDistance );
  171. int FindPlaneIndex( Vector vPoints[3] );
  172. CCopyableUtlVector< HashedPlane_t > m_Planes;
  173. private:
  174. HashedPlane_t *AllocateNewPlane();
  175. // Hash table consisting of indices into the m_Planes array
  176. int m_HashTable[PLANE_HASH_TABLE_SIZE];
  177. };
  178. //-----------------------------------------------------------------------------
  179. // A class to hash, weld, and pool vertices.
  180. //-----------------------------------------------------------------------------
  181. class CVertexHash
  182. {
  183. public:
  184. CVertexHash();
  185. CUtlVector< Vector > &GetVertices() { return m_Vertices; }
  186. const CUtlVector< Vector > &GetVertices() const { return m_Vertices; }
  187. void Purge();
  188. // If bAlwaysAdd is true, this will skip the hash check and always add a new vertex
  189. // (useful if vertex indices must be kept consistent and duplicates might exist)
  190. int FindVertexIndex( const Vector &vertex, bool bAlwaysAdd = false );
  191. private:
  192. static const int m_nHashBitShift = 8;
  193. static const int m_nHashLength = COORD_EXTENT >> m_nHashBitShift;
  194. // Hash along the X and Y axes by grouping vertices into hash buckets
  195. // which are NxN square columns of space.
  196. // ~64 KB
  197. int m_nVertexHash[m_nHashLength * m_nHashLength];
  198. CUtlVector< int > m_VertexHashChain;
  199. CUtlVector< Vector > m_Vertices;
  200. };
  201. #endif // VBSPMATHUTIL_H