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.

262 lines
8.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef DISP_COMMON_H
  8. #define DISP_COMMON_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #include "disp_vertindex.h"
  13. #include "bspfile.h"
  14. #include "utlvector.h"
  15. class CPowerInfo;
  16. class CCoreDispInfo;
  17. // ----------------------------------------------------------------------------- //
  18. // Classes.
  19. // ----------------------------------------------------------------------------- //
  20. // This class provides a set of utility functions for displacements that work in the tools and the engine.
  21. abstract_class CDispUtilsHelper
  22. {
  23. // Derived classes must implement these.
  24. public:
  25. virtual const CPowerInfo* GetPowerInfo() const = 0;
  26. virtual CDispNeighbor* GetEdgeNeighbor( int index ) = 0;
  27. virtual CDispCornerNeighbors* GetCornerNeighbors( int index ) = 0;
  28. virtual CDispUtilsHelper* GetDispUtilsByIndex( int index ) = 0;
  29. // Helper functions.
  30. public:
  31. int GetPower() const;
  32. int GetSideLength() const;
  33. const CVertIndex& GetCornerPointIndex( int iCorner ) const;
  34. int VertIndexToInt( const CVertIndex &i ) const;
  35. CVertIndex GetEdgeMidPoint( int iEdge ) const;
  36. };
  37. // Use this to walk along two neighboring displacements and touch all the
  38. // common vertices.
  39. class CDispSubEdgeIterator
  40. {
  41. public:
  42. CDispSubEdgeIterator();
  43. // Normally, this will iterate all shared verts along the edge except the corners.
  44. // If you want the corners to be touched too, then pass in bTouchCorners=true.
  45. void Start( CDispUtilsHelper *pDisp, int iEdge, int iSub, bool bTouchCorners = false );
  46. bool Next();
  47. const CVertIndex& GetVertIndex() const { return m_Index; } // Get the vert index for the displacement in pUtils.
  48. const CVertIndex& GetNBVertIndex() const { return m_NBIndex; } // Get the neighbor's vert index.
  49. CDispUtilsHelper* GetNeighbor() const { return m_pNeighbor; }
  50. // Returns true if you're on the last vert (ie: the next Next() call will return false).ssssss
  51. bool IsLastVert() const;
  52. private:
  53. CDispUtilsHelper *m_pNeighbor; // The neighbor to the edge we were setup on.
  54. CVertIndex m_Index;
  55. CVertIndex m_Inc;
  56. CVertIndex m_NBIndex;
  57. CVertIndex m_NBInc;
  58. int m_End;
  59. int m_FreeDim;
  60. };
  61. // Use this to walk along the edge of a displacement, touching the points in common
  62. // between the two neighbors. Note: this won't hit the corner points of any of the displacements.
  63. // (As a result, it won't hit the midpoint of pDisps's edge if there are 2 neighbors).
  64. class CDispEdgeIterator
  65. {
  66. public:
  67. CDispEdgeIterator( CDispUtilsHelper *pDisp, int iEdge );
  68. // Seek to the next point on the edge.
  69. bool Next();
  70. const CVertIndex& GetVertIndex() const { return m_It.GetVertIndex(); } // Get the vert index for the displacement in pUtils.
  71. const CVertIndex& GetNBVertIndex() const { return m_It.GetNBVertIndex(); } // Get the neighbor's vert index.
  72. // What is the current neighbor?
  73. CDispUtilsHelper* GetCurrentNeighbor() const { return m_It.GetNeighbor(); }
  74. private:
  75. CDispUtilsHelper *m_pDisp;
  76. int m_iEdge;
  77. int m_iCurSub;
  78. CDispSubEdgeIterator m_It;
  79. };
  80. // Use this to walk all the corners and edge verts in the displacement.
  81. // It walks the edges in the order of the NEIGHBOREDGE_ defines.
  82. // Iterate like this:
  83. // CDispCircumferenceIterator iterator( pDisp->GetSideLength() );
  84. // while ( iterator.Next() )
  85. // ...
  86. class CDispCircumferenceIterator
  87. {
  88. public:
  89. CDispCircumferenceIterator( int sideLength );
  90. // Seek to the next point. Returns false when there are no more points.
  91. bool Next();
  92. const CVertIndex& GetVertIndex() const { return m_VertIndex; }
  93. private:
  94. int m_SideLengthM1;
  95. int m_iCurEdge;
  96. CVertIndex m_VertIndex;
  97. };
  98. // These store info about how to scale and shift coordinates between neighbors
  99. // of different relations (in g_ShiftInfos).
  100. class CShiftInfo
  101. {
  102. public:
  103. int m_MidPointScale;
  104. int m_PowerShiftAdd;
  105. bool m_bValid;
  106. };
  107. class CDispBox
  108. {
  109. public:
  110. Vector m_Min, m_Max;
  111. };
  112. // ----------------------------------------------------------------------------- //
  113. // Globals.
  114. // ----------------------------------------------------------------------------- //
  115. extern int g_EdgeDims[4]; // This tells which dimension (0 or 1) is locked on an edge for each NEIGHBOREDGE_ enum.
  116. extern CShiftInfo g_ShiftInfos[3][3]; // See CShiftInfo.
  117. extern int g_EdgeSideLenMul[4];// Multiply these by the side length to get the index of the edge.
  118. // ----------------------------------------------------------------------------- //
  119. // Helper functions.
  120. // ----------------------------------------------------------------------------- //
  121. // Reference implementation to generate triangle indices for a displacement.
  122. int DispCommon_GetNumTriIndices( int power );
  123. void DispCommon_GenerateTriIndices( int power, unsigned short *indices );
  124. // Returns a NEIGHBOREDGE_ value for the edge that the index is on.
  125. // Returns -1 if the index is not on a side.
  126. // If the point is on a corner, the edges are tested in the order of the NEIGHBOREDGE_ defines.
  127. int GetEdgeIndexFromPoint( CVertIndex const &index, int iPower );
  128. // Returns a CORNER_ value for the corner the point is on, or -1 if it's not on a corner.
  129. int GetEdgeIndexFromPoint( CVertIndex const &index, int iPower );
  130. // This returns the neighbor's power, possibly +1 or -1.
  131. //
  132. // It will add one if the neighbor takes up half of your edge (ie: if it took up your
  133. // whole edge, its resolution would be twice what it really is).
  134. //
  135. // It will subtract one if you take up half of its edge (ie: you only touch half of its verts).
  136. //
  137. // Returns -1 if the edge connection is invalid.
  138. int GetNeighborEdgePower( CDispUtilsHelper *pDisp, int iEdge, int iSub );
  139. // This function sets you up so you can walk along an edge that joins two neighbors.
  140. // Add myInc to myIndex and nbInc to nbIndex until myIndex[iFreeDim] >= myEnd.
  141. //
  142. // Returns the neighbor displacement, or NULL if the specified sub neighbor isn't valid.
  143. CDispUtilsHelper* SetupEdgeIncrements(
  144. CDispUtilsHelper *pDisp,
  145. int iEdge,
  146. int iSub,
  147. CVertIndex &myIndex,
  148. CVertIndex &myInc,
  149. CVertIndex &nbIndex,
  150. CVertIndex &nbInc,
  151. int &myEnd,
  152. int &iFreeDim );
  153. // Figure out which sub neighbor nodeIndex touches.
  154. // Returns -1 if there is no valid sub neighbor at the specified index.
  155. int GetSubNeighborIndex(
  156. CDispUtilsHelper *pDisp,
  157. int iEdge,
  158. CVertIndex const &nodeIndex
  159. );
  160. // Given a vert index and the CSubNeighbor the vert lies on, this
  161. // transforms the specified vert into the neighbor's space.
  162. //
  163. // Note: for corner verts, there may be multiple neighbors touching the same vert, so the
  164. // result you get depends on the edge you specify in iEdge (ie: if you specify the same
  165. // node index but a different edge, you may get a different neighbor).
  166. //
  167. // Note: This only returns a point if the point at nodeIndex actually touches a neighbor point.
  168. // An example where this might be unexpected is if pDisp is power 4 and its neighbor on iEdge
  169. // is power 3, and nodeIndex points at a vert in between two of its neighbor's verts.
  170. // In that case, even though there is a neighbor displacement, nodeIndex doesn't touch
  171. // any points on it, so NULL is returned.
  172. CDispUtilsHelper* TransformIntoSubNeighbor(
  173. CDispUtilsHelper *pDisp,
  174. int iEdge,
  175. int iSub,
  176. CVertIndex const &nodeIndex,
  177. CVertIndex &out
  178. );
  179. // Transform pDisp's node at nodeIndex into its neighboring connection.
  180. // Returns the neighbor displacement and sets out to the index in the neighbor.
  181. //
  182. // Note: for corner verts, there may be multiple neighbors touching the same vert, so the
  183. // result you get depends on the edge you specify in iEdge (ie: if you specify the same
  184. // node index but a different edge, you may get a different neighbor).
  185. //
  186. // Note: This only returns a point if the point at nodeIndex actually touches a neighbor point.
  187. // An example where this might surprise you is if pDisp is power 4 and its neighbor on iEdge
  188. // is power 3, and nodeIndex points at a vert in between two of its neighbor's verts.
  189. // In that case, even though there is a neighbor displacement, nodeIndex doesn't touch
  190. // any points on it, so NULL is returned.
  191. CDispUtilsHelper* TransformIntoNeighbor(
  192. CDispUtilsHelper *pDisp,
  193. int iEdge,
  194. CVertIndex const &nodeIndex,
  195. CVertIndex &out );
  196. // Returns true if the specified point has one or more neighbors.
  197. bool DoesPointHaveAnyNeighbors(
  198. CDispUtilsHelper *pDisp,
  199. const CVertIndex &index );
  200. void FindNeighboringDispSurfs( CCoreDispInfo **ppListBase, int nListSize );
  201. void SetupAllowedVerts( CCoreDispInfo **ppListBase, int nListSize );
  202. void GetDispBox( CCoreDispInfo *pDisp, CDispBox &box );
  203. // ----------------------------------------------------------------------------- //
  204. // Inlines.
  205. // ----------------------------------------------------------------------------- //
  206. #include "disp_powerinfo.h"
  207. #endif // DISP_COMMON_H