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.

321 lines
13 KiB

  1. //=========== Copyright � Valve Corporation, All rights reserved. ===========//
  2. //
  3. // Purpose: Mesh types for meshutils library
  4. //
  5. //===========================================================================//
  6. #ifndef MESH_H
  7. #define MESH_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "tier1/utlvector.h"
  12. #include "tier1/utllinkedlist.h"
  13. #include "mathlib/vector.h"
  14. #include "materialsystem/imaterial.h"
  15. #include "rendersystem/irenderdevice.h"
  16. #include "bitvec.h"
  17. class CDmeModel;
  18. class CDmeMesh;
  19. #define VERTEX_ELEMENT_TANGENT_WITH_FLIP VERTEX_ELEMENT_TEXCOORD4D_7
  20. // our usual distance epsilon is 1/32 of an inch
  21. const float ONE_32ND_UNIT = 0.03125f;
  22. // UVChart for unique parameterization
  23. struct UVChart_t
  24. {
  25. Vector4D m_vPlane;
  26. CUtlVector<int> m_TriangleList;
  27. Vector2D m_vMinUV;
  28. Vector2D m_vMaxUV;
  29. int m_nVertexStart;
  30. int m_nVertexCount;
  31. };
  32. // Atlas chart data for atlasing
  33. // TODO: we should probably pull atlasing out into a more visible library
  34. struct AtlasChart_t
  35. {
  36. Vector2D m_vMaxTextureSize;
  37. Vector2D m_vAtlasMin;
  38. Vector2D m_vAtlasMax;
  39. bool m_bAtlased;
  40. };
  41. // the mesh library only supports a single stream, with multiple attributes.
  42. // NOTE: Each attribute must be an array of floats
  43. class CMeshVertexAttribute
  44. {
  45. public:
  46. int m_nOffsetFloats; // Offset is in # of floats
  47. VertexElement_t m_nType;
  48. inline bool IsJointWeight() const // { return !V_stricmp( m_name.Get(), "blendweight" ) || !V_stricmp( m_name.Get(), "blendweights" ); }
  49. {
  50. return m_nType == VERTEX_ELEMENT_BONEWEIGHTS1 || m_nType == VERTEX_ELEMENT_BONEWEIGHTS2 || m_nType == VERTEX_ELEMENT_BONEWEIGHTS3 || m_nType == VERTEX_ELEMENT_BONEWEIGHTS4;
  51. }
  52. inline bool IsJointIndices() const //{ return !V_stricmp( m_name.Get(), "blendindices" ); }
  53. {
  54. return m_nType == VERTEX_ELEMENT_BONEINDEX;
  55. }
  56. inline bool IsClothEnable()const //{ return !V_stricmp( m_name.Get(), "cloth_enable" ); }
  57. {
  58. return false; // needs to be string-based
  59. }
  60. inline bool IsPositionRemap()const //{ return !V_stricmp( m_name.Get(), "dme_position_map" ); }
  61. {
  62. return false; // needs to be string-based
  63. }
  64. };
  65. class CMesh
  66. {
  67. public:
  68. CMesh();
  69. ~CMesh();
  70. // -----------------------------------------------------------------------------------------
  71. // Allocate vertex and index space for a mesh, this memory will automatically be freed in the destructor
  72. void AllocateMesh( int nVertexCount, int nIndexCount, int nVertexStride, CMeshVertexAttribute *pAttributes, int nAtrributeCount );
  73. void AllocateAndCopyMesh( int nInputVertexCount, const float *pInputVerts, int nInputIndexCount, const uint32 *pInputIndices, int nVertexStride, CMeshVertexAttribute *pAttributes, int nAtrributeCount );
  74. void FreeAllMemory();
  75. // -----------------------------------------------------------------------------------------
  76. // If you don't supply the attribute definition it assumes the vertices are just a position vector
  77. // NOTE: VertexStrideFloats is 3 for a normal vector of 3 floats
  78. // External meshes are allocated by external code and not freed in the destructor
  79. void InitExternalMesh( float *pVerts, int nVertexCount, uint32 *pIndices, int nIndexCount, int nVertexStrideFloats = 3, CMeshVertexAttribute *pAttributes = NULL, int nAtrributeCount = 0 );
  80. inline int IndexCount() const
  81. {
  82. return m_nIndexCount;
  83. }
  84. inline int VertexCount() const
  85. {
  86. return m_nVertexCount;
  87. }
  88. inline void SetVertexPosition( int nIndex, const Vector & v )
  89. {
  90. *( Vector * )GetVertex( nIndex ) = v ;
  91. }
  92. struct SkinningDataFields_t
  93. {
  94. SkinningDataFields_t ():m_nBoneWeights( -1 ), m_nBoneIndices( -1 ){}
  95. bool HasSkinningData() const { return m_nBoneIndices >= 0; }
  96. int m_nBoneWeights, m_nBoneIndices;
  97. };
  98. struct ClothDataFields_t
  99. {
  100. ClothDataFields_t() : m_nClothEnable( -1 ), m_nPositionRemap( -1 ) {}
  101. bool HasClothData() const { return m_nClothEnable >= 0 && m_nPositionRemap >= 0; }
  102. int m_nClothEnable, m_nPositionRemap;
  103. };
  104. // accessing a single attribute of a single vertex (attribute may be scalar or an array of T; scalar and array of size 1 are one and the same)
  105. template <typename T>
  106. class CSingleVertexFieldAccessor
  107. {
  108. public:
  109. CSingleVertexFieldAccessor( T*pBase, int nCount ) : m_pBase( pBase ), m_nCount( nCount ) {}
  110. protected:
  111. T *m_pBase;
  112. int m_nCount;
  113. public:
  114. T& operator [] ( int i ) { AssertDbg( i < m_nCount ); return m_pBase[ i ]; }
  115. const T& operator [] ( int i ) const { AssertDbg( i < m_nCount ); return m_pBase[ i ]; }
  116. T& operator *( ){ AssertDbg( m_nCount > 0 ); return *m_pBase; }
  117. const T& operator *( ) const { AssertDbg( m_nCount > 0 ); return *m_pBase; }
  118. T& Tail() { AssertDbg( m_nCount > 0 ); return m_pBase[ m_nCount - 1 ]; }
  119. const T& Tail() const { AssertDbg( m_nCount > 0 ); return m_pBase[ m_nCount - 1 ]; }
  120. int Count()const { return m_nCount; }
  121. };
  122. template <typename T>
  123. class CScalarAttrArray;
  124. // an accessor for a common attribute of all vertices (e.g. blendweights, or position, or normal)
  125. template < typename T >
  126. class CAttrArray
  127. {
  128. protected:
  129. friend class CScalarAttrArray < T > ;
  130. float *m_pBase; // this points to the first vertex field (first vertex + field offset)
  131. int m_nStride; // this is the stride between fields
  132. int m_nElementCount;
  133. int m_nAttrCount;
  134. public:
  135. CAttrArray( float *pBase = NULL, int nStride = 0, int nVertexCount = 0, int nAttrCount = 0 )
  136. : m_pBase( pBase )
  137. , m_nStride( nStride )
  138. , m_nElementCount( nVertexCount )
  139. , m_nAttrCount( nAttrCount )
  140. { }
  141. struct Range_t
  142. {
  143. T m_Min;
  144. T m_Max;
  145. Range_t();
  146. void Append( T val )
  147. {
  148. if ( val < m_Min )
  149. m_Min = val;
  150. if ( val > m_Max )
  151. m_Max = val;
  152. }
  153. };
  154. Range_t GetRange()const
  155. {
  156. Range_t range;
  157. for ( int v = 0; v < m_nElementCount; ++v )
  158. {
  159. const T *pValues = ( const T* )( m_pBase + m_nStride * v );
  160. for ( int na = 0; na < m_nAttrCount; ++na )
  161. {
  162. range.Append( pValues[ na ] );
  163. }
  164. }
  165. return range;
  166. }
  167. public:
  168. // converting to bool to use this in if() to check for NULL
  169. operator bool() const { return m_pBase != NULL; }
  170. CSingleVertexFieldAccessor< T > operator []( int nVertex ) { AssertDbg( nVertex < m_nElementCount ); return CSingleVertexFieldAccessor< T >( ( T* )( m_pBase + m_nStride * nVertex ), m_nAttrCount ); }
  171. CSingleVertexFieldAccessor< const T > operator []( int nVertex ) const { AssertDbg( nVertex < m_nElementCount ); return CSingleVertexFieldAccessor< const T >( ( const T* )( m_pBase + m_nStride * nVertex ), m_nAttrCount ); }
  172. int GetElementCount()const { return m_nElementCount; }
  173. int GetAttrCount()const { return m_nAttrCount; }
  174. };
  175. bool HasSkinningData() const;
  176. SkinningDataFields_t GetSkinningDataFields() const;
  177. ClothDataFields_t GetClothDataFields() const;
  178. float GetVertexJointSumWeight( const SkinningDataFields_t &skinData, int nVertex, const CVarBitVec &jointSet ); // get the weight of this vertex at this joint; 1.0 for vertices rigdly bound to the given bone, 0.0 for vertices not bound to this bone
  179. void AppendMesh( const CMesh &inputMesh );
  180. inline int TriangleCount() const { return m_nIndexCount / 3; }
  181. inline float *GetVertex(int nIndex) { return m_pVerts + (nIndex * m_nVertexStrideFloats); }
  182. inline const float *GetVertex(int nIndex) const { return m_pVerts + (nIndex * m_nVertexStrideFloats); }
  183. inline const Vector &GetVertexPosition(int nIndex) const { return *(Vector *)(m_pVerts + (nIndex * m_nVertexStrideFloats)); }
  184. inline size_t GetVertexSizeInBytes() const { return m_nVertexStrideFloats * sizeof(float); }
  185. inline size_t GetTotalVertexSizeInBytes() const { return GetVertexSizeInBytes() * m_nVertexCount; }
  186. inline size_t GetTotalIndexSizeInBytes() const { return sizeof(uint32) * m_nIndexCount; }
  187. Vector4D PlaneFromTriangle( int nTriangle ) const;
  188. bool CalculateBounds( Vector *pMinOut, Vector *pMaxOut, int nStartVertex = 0, int nVertexCount = 0 ) const;
  189. bool CalculateAdjacency( int *pAdjacencyOut, int nSizeAdjacencyOut ) const;
  190. bool CalculateIndicentFacesForVertices( CUtlLinkedList<int> *pFacesPerVertex, int nFacesPerVertexSize ) const;
  191. bool CalculateInputLayoutFromAttributes( RenderInputLayoutField_t *pOutFields, int *pInOutNumFields ) const;
  192. int FindFirstAttributeOffset( VertexElement_t nType ) const;
  193. void AddAttributes( CMeshVertexAttribute *pAttributes, int nAttributeCount );
  194. void CalculateTangents();
  195. bool CalculateTangentSpaceWorldLengthsPerFace( Vector2D *pLengthsOut, int nLengthsOut, float flMaxWorldPerUV = 256.0f );
  196. bool CalculateFaceCenters( Vector *pCentersOut, int nCentersOut );
  197. int GetAttrSizeFloats( int nAttribute );
  198. float *m_pVerts;
  199. CMeshVertexAttribute *m_pAttributes;
  200. uint32 *m_pIndices;
  201. int m_nVertexCount;
  202. int m_nVertexStrideFloats; // Stride is in # of floats
  203. int m_nAttributeCount;
  204. int m_nIndexCount;
  205. CUtlString m_materialName;
  206. private:
  207. void RestrideVertexBuffer( int nNewStrideFloats );
  208. bool m_bAllocatedMeshData;
  209. };
  210. struct GridVolume_t
  211. {
  212. Vector m_vMinBounds;
  213. Vector m_vMaxBounds;
  214. };
  215. struct IndexRange_t
  216. {
  217. int m_nStartIndex;
  218. int m_nIndexCount;
  219. };
  220. bool ClipMeshToHalfSpace( CMesh *pMeshBack, CMesh *pMeshFront, const CMesh &inputMesh, Vector4D &vClipPlane );
  221. void DuplicateMesh( CMesh *pMeshOut, const CMesh &inputMesh );
  222. bool RationalizeUVsInPlace( CMesh *pMesh );
  223. bool RationalizeUVs( CMesh *pRationalMeshOut, const CMesh &inputMesh );
  224. void DeIndexMesh( CMesh *pMeshOut, const CMesh &inputMesh );
  225. bool ConcatMeshes( CMesh *pMeshOut, CMesh **ppMeshIn, int nInputMeshes,
  226. CMeshVertexAttribute *pAttributeOverride = NULL, int nAttributeOverrideCount = 0, int nStrideOverride = 0 );
  227. bool TessellateOnWrappedUV( CMesh *pMeshOut, const CMesh &inputMesh );
  228. // returns the mesh containing the convex hull of the input mesh
  229. void ConvexHull3D( CMesh *pOutMesh, const CMesh &inputMesh, float flCoplanarEpsilon = ONE_32ND_UNIT );
  230. void FitOBBToMesh( matrix3x4_t *pCenter, Vector *pExtents, const CMesh &inputMesh, float flCoplanarEpsilon = ONE_32ND_UNIT );
  231. // Builds a mesh of the hull defined by an array of planes (pointing out of the solid - plane eq is Ax + By + Cz = D). Optionally, outputs the index of the originating input plane for each triangle in the mesh.
  232. void HullFromPlanes( CMesh *pOutMesh, CUtlVector<uint32> *pTrianglePlaneIndex, const float *pPlanes, int nPlaneCount, int nPlaneStrideFloats, float flCoplanarEpsilon = ONE_32ND_UNIT );
  233. // Same as above but work on a temporary list of planes described as fltx4 (the buffer will be modified in place). No stride needed in this case, ABCD = XYZW
  234. void HullFromPlanes_SIMD( CMesh *pOutMesh, CUtlVector<uint16> *pTrianglePlaneIndex, fltx4 *pPlanes, int nPlaneCount, float flCoplanarEpsilon = ONE_32ND_UNIT );
  235. // TODO: Extreme welds can cause faces to flip/invert. Should we add an option to detect and avoid this?
  236. bool WeldVertices( CMesh *pMeshOut, const CMesh &inputMesh, float *pEpsilons, int nEpsilons );
  237. // This removes any degenerate triangles and puts the vertices in access order
  238. void CleanMesh( CMesh *pMeshOut, const CMesh &inputMesh );
  239. // partitions the mesh into an array of meshes, each with <= nMaxVertex vertices
  240. void SplitMesh( CUtlVector<CMesh> &list, const CMesh &input, int nMaxVertex );
  241. // Create a unique parameterization of the mesh
  242. bool CreateUniqueUVParameterization( CMesh *pMeshOut, const CMesh &inputMesh, float flFaceAngleThreshold, int nAtlasTextureSizeX, int nAtlasTextureSizeY, float flGutterSize );
  243. // Pack a set of charts into an atlas
  244. int PackChartsIntoAtlas( AtlasChart_t *pCharts, int nCharts, int nAtlasTextureSizeX, int nAtlasTextureSizeY, int nAtlasGrow );
  245. // Creates a list of AABBs for a give volume given a target AABB size
  246. void CreateGridCellsForVolume( CUtlVector< GridVolume_t > &outputVolumes, const Vector &vMinBounds, const Vector &vMaxBounds, const Vector &vGridSize );
  247. //--------------------------------------------------------------------------------------
  248. // For a list of AABBs, find all indices in the mesh that belong to each AABB. Then
  249. // coalesce those indices into a single buffer in order of the input AABBs and return a
  250. // list of ranges of the indices in the output mesh that are needed in each input volume
  251. //--------------------------------------------------------------------------------------
  252. void CreatedGriddedIndexRangesFromMesh( CMesh *pOutputMesh, CUtlVector< IndexRange_t > &outputRanges, const CMesh &inputMesh, CUtlVector< GridVolume_t > &inputVolumes );
  253. // Per-vertex ops
  254. void CopyVertex( float *pOut, const float *pIn, int nFloats );
  255. void SubtractVertex( float *pOutput, const float *pLeft, const float *pRight, int nFloats );
  256. void AddVertex( float *pOutput, const float *pLeft, const float *pRight, int nFloats );
  257. void MultiplyVertex( float *pOutput, const float *pLeft, const float* pRight, float nFloats );
  258. void AddVertexInPlace( float *pLeft, const float *pRight, int nFloats );
  259. void MultiplyVertexInPlace( float *pLeft, float flRight, int nFloats );
  260. void LerpVertex( float *pOutput, const float *pLeft, const float *pRight, float flLerp, int nFloats );
  261. void BaryCentricVertices( float *pOutput, float *p0, float *p1, float *p2, float flU, float flV, float flW, int nFloats );
  262. // simple hashing function for edges
  263. inline uint32 VertHashKey( int nV0, int nV1 )
  264. {
  265. uint32 nHash = ((uint32(nV0) >> 16) | (uint32(nV0)<<16)) ^ uint32(nV1);
  266. nHash = ieqsel( nHash, uint32(~0), uint32( 0 ), nHash ); // don't ever return ~0
  267. return nHash;
  268. }
  269. #endif // MESH_H