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.

1543 lines
45 KiB

  1. //=========== Copyright � Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Mesh class operations.
  4. //
  5. //===========================================================================//
  6. #include "mesh.h"
  7. #include "tier1/utlbuffer.h"
  8. #include "tier1/utlhash.h"
  9. // simplest mesh type - array of vec3
  10. static CMeshVertexAttribute g_PositionAttribute = {0,VERTEX_ELEMENT_POSITION};
  11. // CMesh - utility mesh class implementation
  12. CMesh::CMesh() :
  13. m_pVerts(NULL), m_pAttributes(NULL), m_pIndices(NULL), m_nVertexCount(0), m_nVertexStrideFloats(0),
  14. m_nAttributeCount(0), m_nIndexCount(0), m_bAllocatedMeshData(false)
  15. {
  16. }
  17. CMesh::~CMesh()
  18. {
  19. FreeAllMemory();
  20. }
  21. // free anything we allocated
  22. void CMesh::FreeAllMemory()
  23. {
  24. if ( m_bAllocatedMeshData )
  25. {
  26. delete[] m_pVerts;
  27. delete[] m_pAttributes;
  28. delete[] m_pIndices;
  29. }
  30. m_pVerts = NULL;
  31. m_pAttributes = NULL;
  32. m_pIndices = NULL;
  33. m_bAllocatedMeshData = false;
  34. m_nAttributeCount = 0;
  35. m_nVertexStrideFloats = 0;
  36. m_nVertexCount = 0;
  37. m_nIndexCount = 0;
  38. }
  39. void CMesh::AllocateMesh( int nVertexCount, int nIndexCount, int nVertexStride, CMeshVertexAttribute *pAttributes, int nAtrributeCount )
  40. {
  41. FreeAllMemory();
  42. if ( !pAttributes )
  43. {
  44. pAttributes = &g_PositionAttribute;
  45. nAtrributeCount = 1;
  46. }
  47. m_nVertexCount = nVertexCount;
  48. m_nVertexStrideFloats = nVertexStride;
  49. m_nIndexCount = nIndexCount;
  50. m_nAttributeCount = nAtrributeCount;
  51. // allocate the mesh data, mark as allocated so it will be freed on destruct
  52. m_bAllocatedMeshData = true;
  53. m_pVerts = new float[nVertexStride * nVertexCount];
  54. m_pIndices = new uint32[nIndexCount];
  55. m_pAttributes = new CMeshVertexAttribute[nAtrributeCount];
  56. for ( int i = 0; i < nAtrributeCount; i++ )
  57. {
  58. m_pAttributes[i] = pAttributes[i];
  59. }
  60. }
  61. void CMesh::AllocateAndCopyMesh( int nInputVertexCount, const float *pInputVerts, int nInputIndexCount, const uint32 *pInputIndices, int nVertexStride, CMeshVertexAttribute *pAttributes, int nAtrributeCount )
  62. {
  63. AllocateMesh( nInputVertexCount, nInputIndexCount, nVertexStride, pAttributes, nAtrributeCount );
  64. V_memcpy( m_pVerts, pInputVerts, GetTotalVertexSizeInBytes() );
  65. V_memcpy( m_pIndices, pInputIndices, GetTotalIndexSizeInBytes() );
  66. }
  67. void CMesh::InitExternalMesh( float *pVerts, int nVertexCount, uint32 *pIndices, int nIndexCount, int nVertexStride, CMeshVertexAttribute *pAttributes, int nAtrributeCount )
  68. {
  69. if ( !pAttributes )
  70. {
  71. pAttributes = &g_PositionAttribute;
  72. nAtrributeCount = 1;
  73. }
  74. FreeAllMemory();
  75. m_bAllocatedMeshData = false;
  76. m_nVertexCount = nVertexCount;
  77. m_nVertexStrideFloats = nVertexStride;
  78. m_nIndexCount = nIndexCount;
  79. m_nAttributeCount = nAtrributeCount;
  80. m_pVerts = pVerts;
  81. m_pIndices = pIndices;
  82. m_pAttributes = pAttributes;
  83. }
  84. void CMesh::AppendMesh( const CMesh &inputMesh )
  85. {
  86. Assert( inputMesh.m_nAttributeCount == m_nAttributeCount );
  87. Assert( inputMesh.m_nVertexStrideFloats == m_nVertexStrideFloats );
  88. // Find total sizes
  89. int nTotalIndices = m_nIndexCount + inputMesh.m_nIndexCount;
  90. int nTotalVertices = m_nVertexCount + inputMesh.m_nVertexCount;
  91. float *pNewVB = new float[ nTotalVertices * m_nVertexStrideFloats ];
  92. uint32 *pNewIB = new uint32[ nTotalIndices ];
  93. Q_memcpy( pNewVB, m_pVerts, m_nVertexCount * m_nVertexStrideFloats * sizeof( float ) );
  94. Q_memcpy( pNewIB, m_pIndices, m_nIndexCount * sizeof( uint32 ) );
  95. int nCurrentIndex = m_nIndexCount;
  96. // copy vertices over
  97. Q_memcpy( pNewVB + m_nVertexCount * m_nVertexStrideFloats,
  98. inputMesh.m_pVerts,
  99. inputMesh.m_nVertexCount * m_nVertexStrideFloats * sizeof( float ) );
  100. for ( int i=0; i<inputMesh.m_nIndexCount; ++i )
  101. {
  102. pNewIB[ nCurrentIndex ] = inputMesh.m_pIndices[ i ] + m_nVertexCount;
  103. nCurrentIndex ++;
  104. }
  105. delete []m_pVerts;
  106. delete []m_pIndices;
  107. m_pVerts = pNewVB;
  108. m_pIndices = pNewIB;
  109. m_nVertexCount = nTotalVertices;
  110. m_nIndexCount = nTotalIndices;
  111. }
  112. bool CMesh::CalculateBounds( Vector *pMinOut, Vector *pMaxOut, int nStartVertex, int nVertexCount ) const
  113. {
  114. Assert( pMinOut && pMaxOut );
  115. Vector vMin( FLT_MAX, FLT_MAX, FLT_MAX );
  116. Vector vMax( -FLT_MAX, -FLT_MAX, -FLT_MAX );
  117. int nPosOffset = FindFirstAttributeOffset( VERTEX_ELEMENT_POSITION );
  118. if ( nPosOffset < 0 )
  119. return false;
  120. float *pPositions = ( m_pVerts + nStartVertex * m_nVertexStrideFloats + nPosOffset );
  121. if ( nVertexCount == 0 )
  122. nVertexCount = m_nVertexCount;
  123. for ( int v=0; v<nVertexCount; ++v )
  124. {
  125. vMin.x = MIN( pPositions[0], vMin.x );
  126. vMin.y = MIN( pPositions[1], vMin.y );
  127. vMin.z = MIN( pPositions[2], vMin.z );
  128. vMax.x = MAX( pPositions[0], vMax.x );
  129. vMax.y = MAX( pPositions[1], vMax.y );
  130. vMax.z = MAX( pPositions[2], vMax.z );
  131. pPositions += m_nVertexStrideFloats;
  132. }
  133. *pMinOut = vMin;
  134. *pMaxOut = vMax;
  135. return true;
  136. }
  137. struct EdgeHash_t
  138. {
  139. inline bool operator==( const EdgeHash_t& src ) const { return src.m_nV0 == m_nV0 && src.m_nV1 == m_nV1; }
  140. int m_nV0;
  141. int m_nV1;
  142. int m_nTri0;
  143. int m_nTri1;
  144. };
  145. // Fills in an adjacency array with the 3 edge adjacent triangles for each triangle in the array.
  146. // The input pAdjacencyOut must be at least 3 * nFaces => ( 3 * m_nIndexCount / 3 ) => m_nIndexCount in size.
  147. // Any boundary edges are given an edge adjacent triangle index of -1.
  148. bool CMesh::CalculateAdjacency( int *pAdjacencyOut, int nSizeAdjacencyOut ) const
  149. {
  150. Assert( pAdjacencyOut );
  151. if ( nSizeAdjacencyOut != m_nIndexCount )
  152. return false;
  153. CUtlScalarHash<EdgeHash_t> edgeHash;
  154. edgeHash.Init( m_nIndexCount * 2 );
  155. int nFaces = m_nIndexCount / 3;
  156. int nIndex = 0;
  157. for ( int f=0; f<nFaces; ++f )
  158. {
  159. for ( int i=0; i<3; ++i )
  160. {
  161. int nV0 = m_pIndices[ nIndex + ( i ) ];
  162. int nV1 = m_pIndices[ nIndex + ( i + 1 ) % 3 ];
  163. if ( nV1 < nV0 )
  164. {
  165. Swap( nV1, nV0 );
  166. }
  167. EdgeHash_t tmp;
  168. tmp.m_nV0 = nV0;
  169. tmp.m_nV1 = nV1;
  170. tmp.m_nTri0 = f;
  171. tmp.m_nTri1 = -1;
  172. uint nHashKey = VertHashKey( nV0, nV1 );
  173. UtlHashFastHandle_t edgeHashIndex = edgeHash.Find( nHashKey, tmp );
  174. if ( edgeHash.InvalidHandle() == edgeHashIndex )
  175. {
  176. edgeHash.Insert( nHashKey, tmp );
  177. }
  178. else
  179. {
  180. EdgeHash_t &edge = edgeHash.Element( edgeHashIndex );
  181. edge.m_nTri1 = f;
  182. }
  183. }
  184. nIndex += 3;
  185. }
  186. // Now that we have an edge datastructure, fill out edge-adjacency
  187. nIndex = 0;
  188. for ( int f=0; f<nFaces; ++f )
  189. {
  190. for ( int i=0; i<3; ++i )
  191. {
  192. int nV0 = m_pIndices[ nIndex + ( i ) ];
  193. int nV1 = m_pIndices[ nIndex + ( i + 1 ) % 3 ];
  194. if ( nV1 < nV0 )
  195. {
  196. Swap( nV1, nV0 );
  197. }
  198. EdgeHash_t tmp;
  199. tmp.m_nV0 = nV0;
  200. tmp.m_nV1 = nV1;
  201. tmp.m_nTri0 = -1;
  202. tmp.m_nTri1 = -1;
  203. uint nHashKey = VertHashKey( nV0, nV1 );
  204. UtlHashFastHandle_t edgeHashIndex = edgeHash.Find( nHashKey, tmp );
  205. Assert( edgeHash.InvalidHandle() != edgeHashIndex );
  206. EdgeHash_t &edge = edgeHash.Element( edgeHashIndex );
  207. if ( edge.m_nTri0 == f )
  208. {
  209. pAdjacencyOut[ nIndex + i ] = edge.m_nTri1;
  210. }
  211. else
  212. {
  213. pAdjacencyOut[ nIndex + i ] = edge.m_nTri0;
  214. }
  215. }
  216. nIndex += 3;
  217. }
  218. return true;
  219. }
  220. // Fills in a list of all faces that contain that particular vertex. The input pFacesPerVertex, must
  221. // contain at least m_nVertexCount elements of type CUtlLinkedList<int>.
  222. bool CMesh::CalculateIndicentFacesForVertices( CUtlLinkedList<int> *pFacesPerVertex, int nFacesPerVertexSize ) const
  223. {
  224. Assert( pFacesPerVertex );
  225. if ( nFacesPerVertexSize != m_nVertexCount )
  226. return false;
  227. int nFaces = m_nIndexCount / 3;
  228. int nIndex = 0;
  229. for ( int f=0; f<nFaces; ++f )
  230. {
  231. int v0 = m_pIndices[ nIndex ]; nIndex++;
  232. int v1 = m_pIndices[ nIndex ]; nIndex++;
  233. int v2 = m_pIndices[ nIndex ]; nIndex++;
  234. pFacesPerVertex[ v0 ].AddToTail( f );
  235. pFacesPerVertex[ v1 ].AddToTail( f );
  236. pFacesPerVertex[ v2 ].AddToTail( f );
  237. }
  238. return true;
  239. }
  240. struct InputDataForVertexElement_t
  241. {
  242. char *m_pSemanticName;
  243. int m_nSemanticIndex;
  244. };
  245. InputDataForVertexElement_t g_pElementData[] =
  246. {
  247. { "POSITION", 0 }, // VERTEX_ELEMENT_POSITION = 0,
  248. { "POSITION", 0 }, // VERTEX_ELEMENT_POSITION4D = 1,
  249. { "NORMAL", 0 }, // VERTEX_ELEMENT_NORMAL = 2,
  250. { "NORMAL", 0 }, // VERTEX_ELEMENT_NORMAL4D = 3,
  251. { "COLOR", 0 }, // VERTEX_ELEMENT_COLOR = 4,
  252. { "SPECULAR", 0 }, // VERTEX_ELEMENT_SPECULAR = 5,
  253. { "TANGENT", 0 }, // VERTEX_ELEMENT_TANGENT_S = 6,
  254. { "BINORMAL", 0 }, // VERTEX_ELEMENT_TANGENT_T = 7,
  255. { "WRINKLE", 0 }, // VERTEX_ELEMENT_WRINKLE = 8,
  256. { "BLENDINDICES", 0 }, // VERTEX_ELEMENT_BONEINDEX = 9,
  257. { "BLENDWEIGHT", 0 }, // VERTEX_ELEMENT_BONEWEIGHTS1 = 10,
  258. { "BLENDWEIGHT", 1 }, // VERTEX_ELEMENT_BONEWEIGHTS2 = 11,
  259. { "BLENDWEIGHT", 2 }, // VERTEX_ELEMENT_BONEWEIGHTS3 = 12,
  260. { "BLENDWEIGHT", 3 }, // VERTEX_ELEMENT_BONEWEIGHTS4 = 13,
  261. { "TEXCOORD", 8 }, // VERTEX_ELEMENT_USERDATA1 = 14,
  262. { "TEXCOORD", 9 }, // VERTEX_ELEMENT_USERDATA2 = 15,
  263. { "TEXCOORD", 10 }, // VERTEX_ELEMENT_USERDATA3 = 16,
  264. { "TEXCOORD", 11 }, // VERTEX_ELEMENT_USERDATA4 = 17,
  265. { "TEXCOORD", 0 }, // VERTEX_ELEMENT_TEXCOORD1D_0 = 18,
  266. { "TEXCOORD", 1 }, // VERTEX_ELEMENT_TEXCOORD1D_1 = 19,
  267. { "TEXCOORD", 2 }, // VERTEX_ELEMENT_TEXCOORD1D_2 = 20,
  268. { "TEXCOORD", 3 }, // VERTEX_ELEMENT_TEXCOORD1D_3 = 21,
  269. { "TEXCOORD", 4 }, // VERTEX_ELEMENT_TEXCOORD1D_4 = 22,
  270. { "TEXCOORD", 5 }, // VERTEX_ELEMENT_TEXCOORD1D_5 = 23,
  271. { "TEXCOORD", 6 }, // VERTEX_ELEMENT_TEXCOORD1D_6 = 24,
  272. { "TEXCOORD", 7 }, // VERTEX_ELEMENT_TEXCOORD1D_7 = 25,
  273. { "TEXCOORD", 0 }, // VERTEX_ELEMENT_TEXCOORD2D_0 = 26,
  274. { "TEXCOORD", 1 }, // VERTEX_ELEMENT_TEXCOORD2D_1 = 27,
  275. { "TEXCOORD", 2 }, // VERTEX_ELEMENT_TEXCOORD2D_2 = 28,
  276. { "TEXCOORD", 3 }, // VERTEX_ELEMENT_TEXCOORD2D_3 = 29,
  277. { "TEXCOORD", 4 }, // VERTEX_ELEMENT_TEXCOORD2D_4 = 30,
  278. { "TEXCOORD", 5 }, // VERTEX_ELEMENT_TEXCOORD2D_5 = 31,
  279. { "TEXCOORD", 6 }, // VERTEX_ELEMENT_TEXCOORD2D_6 = 32,
  280. { "TEXCOORD", 7 }, // VERTEX_ELEMENT_TEXCOORD2D_7 = 33,
  281. { "TEXCOORD", 0 }, // VERTEX_ELEMENT_TEXCOORD3D_0 = 34,
  282. { "TEXCOORD", 1 }, // VERTEX_ELEMENT_TEXCOORD3D_1 = 35,
  283. { "TEXCOORD", 2 }, // VERTEX_ELEMENT_TEXCOORD3D_2 = 36,
  284. { "TEXCOORD", 3 }, // VERTEX_ELEMENT_TEXCOORD3D_3 = 37,
  285. { "TEXCOORD", 4 }, // VERTEX_ELEMENT_TEXCOORD3D_4 = 38,
  286. { "TEXCOORD", 5 }, // VERTEX_ELEMENT_TEXCOORD3D_5 = 39,
  287. { "TEXCOORD", 6 }, // VERTEX_ELEMENT_TEXCOORD3D_6 = 40,
  288. { "TEXCOORD", 7 }, // VERTEX_ELEMENT_TEXCOORD3D_7 = 41,
  289. { "TEXCOORD", 0 }, // VERTEX_ELEMENT_TEXCOORD4D_0 = 42,
  290. { "TEXCOORD", 1 }, // VERTEX_ELEMENT_TEXCOORD4D_1 = 43,
  291. { "TEXCOORD", 2 }, // VERTEX_ELEMENT_TEXCOORD4D_2 = 44,
  292. { "TEXCOORD", 3 }, // VERTEX_ELEMENT_TEXCOORD4D_3 = 45,
  293. { "TEXCOORD", 4 }, // VERTEX_ELEMENT_TEXCOORD4D_4 = 46,
  294. { "TEXCOORD", 5 }, // VERTEX_ELEMENT_TEXCOORD4D_5 = 47,
  295. { "TEXCOORD", 6 }, // VERTEX_ELEMENT_TEXCOORD4D_6 = 48,
  296. { "TEXCOORD", 7 }, // VERTEX_ELEMENT_TEXCOORD4D_7 = 49,
  297. };
  298. ColorFormat_t GetColorFormatForVertexElement( VertexElement_t element )
  299. {
  300. int nBytes = GetVertexElementSize( element, VERTEX_COMPRESSION_NONE );
  301. if ( nBytes % sizeof( float ) != 0 )
  302. {
  303. return COLOR_FORMAT_UNKNOWN;
  304. }
  305. int nFloats = nBytes / sizeof( float );
  306. switch ( nFloats )
  307. {
  308. case 1:
  309. return COLOR_FORMAT_R32_FLOAT;
  310. case 2:
  311. return COLOR_FORMAT_R32G32_FLOAT;
  312. case 3:
  313. return COLOR_FORMAT_R32G32B32_FLOAT;
  314. case 4:
  315. return COLOR_FORMAT_R32G32B32A32_FLOAT;
  316. }
  317. return COLOR_FORMAT_UNKNOWN;
  318. }
  319. bool CMesh::CalculateInputLayoutFromAttributes( RenderInputLayoutField_t *pOutFields, int *pInOutNumFields ) const
  320. {
  321. if ( *pInOutNumFields < m_nAttributeCount )
  322. return false;
  323. for ( int a=0; a<m_nAttributeCount; ++a )
  324. {
  325. InputDataForVertexElement_t elementData = g_pElementData[ m_pAttributes[ a ].m_nType ];
  326. pOutFields[ a ].m_Format = GetColorFormatForVertexElement( m_pAttributes[ a ].m_nType );
  327. pOutFields[ a ].m_nInstanceStepRate = 0;
  328. pOutFields[ a ].m_nOffset = m_pAttributes[ a ].m_nOffsetFloats * sizeof( float );
  329. pOutFields[ a ].m_nSemanticIndex = elementData.m_nSemanticIndex;
  330. pOutFields[ a ].m_nSlot = 0;
  331. pOutFields[ a ].m_nSlotType = RENDER_SLOT_PER_VERTEX;
  332. Q_strncpy( pOutFields[ a ].m_pSemanticName, elementData.m_pSemanticName, RENDER_INPUT_LAYOUT_FIELD_SEMANTIC_NAME_SIZE );
  333. }
  334. *pInOutNumFields = m_nAttributeCount;
  335. return true;
  336. }
  337. int CMesh::FindFirstAttributeOffset( VertexElement_t nType ) const
  338. {
  339. for ( int a=0; a<m_nAttributeCount; ++a )
  340. {
  341. if ( m_pAttributes[ a ].m_nType == nType )
  342. {
  343. return m_pAttributes[ a ].m_nOffsetFloats;
  344. }
  345. }
  346. return -1;
  347. }
  348. void CMesh::RestrideVertexBuffer( int nNewStrideFloats )
  349. {
  350. float *pNewMemory = new float[ nNewStrideFloats * m_nVertexCount ];
  351. int nMinStride = MIN( nNewStrideFloats, m_nVertexStrideFloats ) * sizeof( float );
  352. float *pNewStart = pNewMemory;
  353. for ( int i=0; i<m_nVertexCount; ++i )
  354. {
  355. Q_memcpy( pNewStart, GetVertex( i ), nMinStride );
  356. pNewStart += nNewStrideFloats;
  357. }
  358. delete []m_pVerts;
  359. m_pVerts = pNewMemory;
  360. m_nVertexStrideFloats = nNewStrideFloats;
  361. m_bAllocatedMeshData = true;
  362. }
  363. void CMesh::AddAttributes( CMeshVertexAttribute *pAttributes, int nAttributeCount )
  364. {
  365. Assert( nAttributeCount );
  366. CMeshVertexAttribute *pNewAttributes = new CMeshVertexAttribute[ m_nAttributeCount + nAttributeCount ];
  367. for ( int a=0; a<m_nAttributeCount; ++a )
  368. {
  369. pNewAttributes[ a ] = m_pAttributes[ a ];
  370. }
  371. int nNewStrideFloats = m_nVertexStrideFloats;
  372. for ( int a=0; a<nAttributeCount; ++a )
  373. {
  374. nNewStrideFloats = MAX( pAttributes[ a ].m_nOffsetFloats + GetVertexElementSize( pAttributes[ a ].m_nType, VERTEX_COMPRESSION_NONE ) / (int)sizeof( float ), nNewStrideFloats );
  375. pNewAttributes[ m_nAttributeCount + a ] = pAttributes[ a ];
  376. }
  377. delete []m_pAttributes;
  378. m_pAttributes = pNewAttributes;
  379. m_nAttributeCount += nAttributeCount;
  380. if ( nNewStrideFloats > m_nVertexStrideFloats )
  381. {
  382. RestrideVertexBuffer( nNewStrideFloats );
  383. }
  384. }
  385. typedef CUtlVector<int> CIntVector;
  386. void CMesh::CalculateTangents()
  387. {
  388. int nPositionOffset = FindFirstAttributeOffset( VERTEX_ELEMENT_POSITION );
  389. int nNormalOffset = FindFirstAttributeOffset( VERTEX_ELEMENT_NORMAL );
  390. int nTexOffset = FindFirstAttributeOffset( VERTEX_ELEMENT_TEXCOORD2D_0 );
  391. if ( nTexOffset == -1 )
  392. nTexOffset = FindFirstAttributeOffset( VERTEX_ELEMENT_TEXCOORD3D_0 );
  393. if ( nPositionOffset == -1 || nTexOffset == -1 || nNormalOffset == -1 )
  394. {
  395. Msg( "Need valid position, normal, and texcoord when creating tangent frames!\n" );
  396. return;
  397. }
  398. // Look for a space to store tangents
  399. int nTangentOffset = FindFirstAttributeOffset( VERTEX_ELEMENT_TANGENT_WITH_FLIP );
  400. if ( nTangentOffset == -1 )
  401. {
  402. nTangentOffset = m_nVertexStrideFloats;
  403. // Add a tangent
  404. CMeshVertexAttribute attribute;
  405. attribute.m_nOffsetFloats = m_nVertexStrideFloats;
  406. attribute.m_nType = VERTEX_ELEMENT_TANGENT_WITH_FLIP;
  407. AddAttributes( &attribute, 1 );
  408. }
  409. // Calculate tangent ( pulled from studiomdl ). We've left it this way for now to keep any weirdness from studiomdl that we've come to rely on.
  410. // In the future we should remove the vertToFaceMap and just accumulate tangents inplace in the vertices.
  411. // TODO: fix this function to iterate over quads as well as triangles
  412. int nIndicesPerFace = 3;
  413. int nFaces = m_nIndexCount / nIndicesPerFace;
  414. int nMaxIter = nIndicesPerFace;
  415. CUtlVector<CIntVector> vertToFaceMap;
  416. vertToFaceMap.AddMultipleToTail( m_nVertexCount );
  417. int index = 0;
  418. uint32 *pIndices = m_pIndices;
  419. for( int faceID = 0; faceID < nFaces; faceID++ )
  420. {
  421. for ( int i=0; i<nMaxIter; ++i )
  422. {
  423. vertToFaceMap[ pIndices[ index + i ] ].AddToTail( faceID );
  424. }
  425. index += nIndicesPerFace;
  426. }
  427. CUtlVector<Vector> faceSVect;
  428. CUtlVector<Vector> faceTVect;
  429. faceSVect.AddMultipleToTail( nFaces );
  430. faceTVect.AddMultipleToTail( nFaces );
  431. index = 0;
  432. for ( int f=0; f<nFaces; ++f )
  433. {
  434. Vector vPos[3];
  435. Vector2D vTex[3];
  436. for ( int i=0; i<nMaxIter; ++i )
  437. {
  438. float *pVertex = GetVertex( pIndices[ index + i ] );
  439. vPos[i] = *( ( Vector* )( pVertex + nPositionOffset ) );
  440. vTex[i] = *( ( Vector2D* )( pVertex + nTexOffset ) );
  441. }
  442. CalcTriangleTangentSpace( vPos[0], vPos[1], vPos[2],
  443. vTex[0], vTex[1], vTex[2],
  444. faceSVect[f], faceTVect[f] );
  445. index += nIndicesPerFace;
  446. }
  447. // Calculate an average tangent space for each vertex.
  448. for( int vertID = 0; vertID < m_nVertexCount; vertID++ )
  449. {
  450. float *pVertex = GetVertex( vertID );
  451. const Vector &normal = *( ( Vector* )( pVertex + nNormalOffset ) );
  452. Vector4D &finalSVect = *( ( Vector4D* )( pVertex + nTangentOffset ) );
  453. Vector sVect, tVect;
  454. sVect.Init( 0.0f, 0.0f, 0.0f );
  455. tVect.Init( 0.0f, 0.0f, 0.0f );
  456. for( int faceID = 0; faceID < vertToFaceMap[vertID].Count(); faceID++ )
  457. {
  458. sVect += faceSVect[vertToFaceMap[vertID][faceID]];
  459. tVect += faceTVect[vertToFaceMap[vertID][faceID]];
  460. }
  461. // Make an orthonormal system.
  462. // Need to check if we are left or right handed.
  463. Vector tmpVect;
  464. CrossProduct( sVect, tVect, tmpVect );
  465. bool leftHanded = DotProduct( tmpVect, normal ) < 0.0f;
  466. if( !leftHanded )
  467. {
  468. CrossProduct( normal, sVect, tVect );
  469. CrossProduct( tVect, normal, sVect );
  470. VectorNormalize( sVect );
  471. VectorNormalize( tVect );
  472. finalSVect[0] = sVect[0];
  473. finalSVect[1] = sVect[1];
  474. finalSVect[2] = sVect[2];
  475. finalSVect[3] = 1.0f;
  476. }
  477. else
  478. {
  479. CrossProduct( sVect, normal, tVect );
  480. CrossProduct( normal, tVect, sVect );
  481. VectorNormalize( sVect );
  482. VectorNormalize( tVect );
  483. finalSVect[0] = sVect[0];
  484. finalSVect[1] = sVect[1];
  485. finalSVect[2] = sVect[2];
  486. finalSVect[3] = -1.0f;
  487. }
  488. }
  489. }
  490. //--------------------------------------------------------------------------------------
  491. // Calculates an unnormalized tangent space
  492. //--------------------------------------------------------------------------------------
  493. #define SMALL_FLOAT 1e-12
  494. void CalcTriangleTangentSpaceL( const Vector &p0, const Vector &p1, const Vector &p2,
  495. const Vector2D &t0, const Vector2D &t1, const Vector2D& t2,
  496. Vector &sVect, Vector &tVect )
  497. {
  498. /* Compute the partial derivatives of X, Y, and Z with respect to S and T. */
  499. sVect.Init( 0.0f, 0.0f, 0.0f );
  500. tVect.Init( 0.0f, 0.0f, 0.0f );
  501. // x, s, t
  502. Vector edge01( p1.x - p0.x, t1.x - t0.x, t1.y - t0.y );
  503. Vector edge02( p2.x - p0.x, t2.x - t0.x, t2.y - t0.y );
  504. Vector cross;
  505. CrossProduct( edge01, edge02, cross );
  506. if ( fabs( cross.x ) > SMALL_FLOAT )
  507. {
  508. sVect.x += -cross.y / cross.x;
  509. tVect.x += -cross.z / cross.x;
  510. }
  511. // y, s, t
  512. edge01.Init( p1.y - p0.y, t1.x - t0.x, t1.y - t0.y );
  513. edge02.Init( p2.y - p0.y, t2.x - t0.x, t2.y - t0.y );
  514. CrossProduct( edge01, edge02, cross );
  515. if ( fabs( cross.x ) > SMALL_FLOAT )
  516. {
  517. sVect.y += -cross.y / cross.x;
  518. tVect.y += -cross.z / cross.x;
  519. }
  520. // z, s, t
  521. edge01.Init( p1.z - p0.z, t1.x - t0.x, t1.y - t0.y );
  522. edge02.Init( p2.z - p0.z, t2.x - t0.x, t2.y - t0.y );
  523. CrossProduct( edge01, edge02, cross );
  524. if( fabs( cross.x ) > SMALL_FLOAT )
  525. {
  526. sVect.z += -cross.y / cross.x;
  527. tVect.z += -cross.z / cross.x;
  528. }
  529. }
  530. bool CMesh::CalculateTangentSpaceWorldLengthsPerFace( Vector2D *pLengthsOut, int nLengthsOut, float flMaxWorldPerUV )
  531. {
  532. int nPositionOffset = FindFirstAttributeOffset( VERTEX_ELEMENT_POSITION );
  533. int nTexOffset = FindFirstAttributeOffset( VERTEX_ELEMENT_TEXCOORD2D_0 );
  534. if ( nTexOffset == -1 )
  535. nTexOffset = FindFirstAttributeOffset( VERTEX_ELEMENT_TEXCOORD3D_0 );
  536. if ( nPositionOffset == -1 || nTexOffset == -1 )
  537. {
  538. Msg( "Need valid position and texcoord when creating world space tangent lengths!\n" );
  539. return false;
  540. }
  541. // TODO: fix this to eventually iterate over quads
  542. int nIndicesPerFace = 3;
  543. int nFaces = m_nIndexCount / nIndicesPerFace;
  544. int nMaxIter = nIndicesPerFace;
  545. if ( nLengthsOut < nFaces )
  546. {
  547. return false;
  548. }
  549. // Get the textures
  550. float flMaxUnitsX = flMaxWorldPerUV;
  551. float flMaxUnitsY = flMaxWorldPerUV;
  552. Vector sdir;
  553. Vector tdir;
  554. int index = 0;
  555. uint32 *pIndices = m_pIndices;
  556. for ( int f=0; f<nFaces; ++f )
  557. {
  558. Vector2D vMin( FLT_MAX, FLT_MAX );
  559. // find the min UV
  560. Vector vPos[3];
  561. Vector2D vTex[3];
  562. for ( int i=0; i<nMaxIter; ++i )
  563. {
  564. float *pVertex = GetVertex( pIndices[ index + i ] );
  565. vPos[i] = *( ( Vector* )( pVertex + nPositionOffset ) );
  566. vTex[i] = *( ( Vector2D* )( pVertex + nTexOffset ) );
  567. }
  568. // calc tan-space
  569. CalcTriangleTangentSpaceL( vPos[0], vPos[1], vPos[2],
  570. vTex[0], vTex[1], vTex[2],
  571. sdir, tdir );
  572. pLengthsOut[ f ].x = MIN( flMaxUnitsX, sdir.Length() );
  573. pLengthsOut[ f ].y = MIN( flMaxUnitsY, sdir.Length() );
  574. index += nIndicesPerFace;
  575. }
  576. return true;
  577. }
  578. bool CMesh::CalculateFaceCenters( Vector *pCentersOut, int nCentersOut )
  579. {
  580. int nPositionOffset = FindFirstAttributeOffset( VERTEX_ELEMENT_POSITION );
  581. if ( nPositionOffset == -1 )
  582. {
  583. Msg( "Need valid position to calculate face centers!\n" );
  584. return false;
  585. }
  586. // TODO: fix this to eventually iterate over quads
  587. int nIndicesPerFace = 3;
  588. int nFaces = m_nIndexCount / nIndicesPerFace;
  589. float fIndicesPerFace = (float)nIndicesPerFace;
  590. if ( nCentersOut < nFaces )
  591. {
  592. return false;
  593. }
  594. int index = 0;
  595. uint32 *pIndices = m_pIndices;
  596. for ( int f=0; f<nFaces; ++f )
  597. {
  598. pCentersOut[ f ] = Vector(0,0,0);
  599. for ( int i=0; i<nIndicesPerFace; ++i )
  600. {
  601. float *pVertex = GetVertex( pIndices[ index ] );
  602. Vector &vPos = *( ( Vector* )( pVertex + nPositionOffset ) );
  603. pCentersOut[ f ] += vPos;
  604. index++;
  605. }
  606. pCentersOut[ f ] /= fIndicesPerFace;
  607. }
  608. return true;
  609. }
  610. void DuplicateMesh( CMesh *pMeshOut, const CMesh &inputMesh )
  611. {
  612. Assert( pMeshOut );
  613. pMeshOut->AllocateMesh( inputMesh.m_nVertexCount, inputMesh.m_nIndexCount, inputMesh.m_nVertexStrideFloats, inputMesh.m_pAttributes, inputMesh.m_nAttributeCount );
  614. Q_memcpy( pMeshOut->m_pVerts, inputMesh.m_pVerts, inputMesh.m_nVertexCount * inputMesh.m_nVertexStrideFloats * sizeof( float ) );
  615. Q_memcpy( pMeshOut->m_pIndices, inputMesh.m_pIndices, inputMesh.m_nIndexCount * sizeof( uint32 ) );
  616. pMeshOut->m_materialName = inputMesh.m_materialName;
  617. }
  618. // Shifts the UVs of an entire triangle to the origin defined by the smallest set of UV coordinates.
  619. // The mesh must be de-indexed to do this. This ensures our UVs are as close to the origin as possible.
  620. bool RationalizeUVsInPlace( CMesh *pMesh )
  621. {
  622. // We need to have texcoords to rationalize
  623. int nTexcoordOffset = pMesh->FindFirstAttributeOffset( VERTEX_ELEMENT_TEXCOORD2D_0 );
  624. if ( nTexcoordOffset < 0 )
  625. {
  626. nTexcoordOffset = pMesh->FindFirstAttributeOffset( VERTEX_ELEMENT_TEXCOORD3D_0 );
  627. }
  628. if ( nTexcoordOffset < 0 )
  629. {
  630. return false;
  631. }
  632. if ( pMesh->m_nVertexCount != pMesh->m_nIndexCount )
  633. return false;
  634. int nFaces = pMesh->m_nIndexCount / 3;
  635. float *pVertices = pMesh->m_pVerts;
  636. for ( int f=0; f<nFaces; ++f )
  637. {
  638. Vector2D vMin(FLT_MAX,FLT_MAX);
  639. // find the min UV
  640. float *pTriVerts = pVertices;
  641. for ( int i=0; i<3; ++i )
  642. {
  643. float flU = pVertices[ nTexcoordOffset ];
  644. float flV = pVertices[ nTexcoordOffset + 1 ];
  645. vMin.x = MIN( vMin.x, flU );
  646. vMin.y = MIN( vMin.y, flV );
  647. pVertices += pMesh->m_nVertexStrideFloats;
  648. }
  649. // clamp to the nearest whole rep
  650. Vector2D vMinFloor;
  651. vMinFloor.x = floor( vMin.x );
  652. vMinFloor.y = floor( vMin.y );
  653. // rationalize UVs across the face
  654. for ( int i=0; i<3; ++i )
  655. {
  656. pTriVerts[ nTexcoordOffset ] -= vMinFloor.x;
  657. pTriVerts[ nTexcoordOffset + 1 ] -= vMinFloor.y;
  658. pTriVerts += pMesh->m_nVertexStrideFloats;
  659. }
  660. }
  661. return true;
  662. }
  663. // Shifts the UVs of an entire triangle to the origin defined by the smallest set of UV coordinates.
  664. // The mesh must be de-indexed to do this. This ensures our UVs are as close to the origin as possible.
  665. bool RationalizeUVs( CMesh *pRationalMeshOut, const CMesh &inputMesh )
  666. {
  667. // We need our mesh de-indexed to rationalize UVs since we'll be shifting
  668. // UVs on a per-triangle basis
  669. if ( inputMesh.m_nVertexCount != inputMesh.m_nIndexCount )
  670. {
  671. DeIndexMesh( pRationalMeshOut, inputMesh );
  672. }
  673. else
  674. {
  675. pRationalMeshOut->AllocateMesh( inputMesh.m_nIndexCount, inputMesh.m_nIndexCount, inputMesh.m_nVertexStrideFloats, inputMesh.m_pAttributes, inputMesh.m_nAttributeCount );
  676. }
  677. return RationalizeUVsInPlace( pRationalMeshOut );
  678. }
  679. // Removes the need for an index buffer by storing redundant vertices
  680. // back into the vertex buffer.
  681. void DeIndexMesh( CMesh *pMeshOut, const CMesh &inputMesh )
  682. {
  683. Assert( pMeshOut );
  684. pMeshOut->AllocateMesh( inputMesh.m_nIndexCount, inputMesh.m_nIndexCount, inputMesh.m_nVertexStrideFloats, inputMesh.m_pAttributes, inputMesh.m_nAttributeCount );
  685. float *pOutVerts = pMeshOut->m_pVerts;
  686. for ( int i=0; i<inputMesh.m_nIndexCount; ++i )
  687. {
  688. CopyVertex( pOutVerts, inputMesh.GetVertex( inputMesh.m_pIndices[ i ] ), inputMesh.m_nVertexStrideFloats );
  689. pOutVerts += inputMesh.m_nVertexStrideFloats;
  690. pMeshOut->m_pIndices[ i ] = i;
  691. }
  692. }
  693. // Combines two compatibles meshes into one. The two meshes must have the same vertex stride.
  694. bool ConcatMeshes( CMesh *pMeshOut, CMesh **ppMeshIn, int nInputMeshes,
  695. CMeshVertexAttribute *pAttributeOverride, int nAttributeOverrideCount, int nStrideOverride )
  696. {
  697. Assert( pMeshOut && ppMeshIn && nInputMeshes > 1 );
  698. // Find total sizes
  699. int nTotalIndices = 0;
  700. int nTotalVertices = 0;
  701. int nAttributes = 0;
  702. int nStrideFloats = 0;
  703. CMeshVertexAttribute *pAttributes = NULL;
  704. for ( int m=0; m<nInputMeshes; ++m )
  705. {
  706. CMesh *pMesh = ppMeshIn[m];
  707. nTotalIndices += pMesh->m_nIndexCount;
  708. nTotalVertices += pMesh->m_nVertexCount;
  709. if ( m == 0 )
  710. {
  711. nAttributes = pMesh->m_nAttributeCount;
  712. nStrideFloats = pMesh->m_nVertexStrideFloats;
  713. pAttributes = pMesh->m_pAttributes;
  714. }
  715. else if ( nStrideOverride == 0 )
  716. {
  717. if ( nStrideFloats != pMesh->m_nVertexStrideFloats )
  718. {
  719. Warning( "Trying to concatenate differently strided meshes!\n" );
  720. return false;
  721. }
  722. }
  723. }
  724. if ( pAttributeOverride && nAttributeOverrideCount > 0 )
  725. {
  726. pAttributes = pAttributeOverride;
  727. nAttributes = nAttributeOverrideCount;
  728. }
  729. if ( nStrideOverride > 0 )
  730. {
  731. nStrideFloats = nStrideOverride;
  732. }
  733. pMeshOut->AllocateMesh( nTotalVertices, nTotalIndices, nStrideFloats, pAttributes, nAttributes );
  734. int nCurrentVertex = 0;
  735. int nCurrentIndex = 0;
  736. for ( int m=0; m<nInputMeshes; ++m )
  737. {
  738. CMesh *pMesh = ppMeshIn[m];
  739. for ( int v=0; v<pMesh->m_nVertexCount; ++v )
  740. {
  741. CopyVertex( pMeshOut->GetVertex( nCurrentVertex + v ), pMesh->GetVertex( v ), nStrideFloats );
  742. }
  743. for ( int i=0; i<pMesh->m_nIndexCount; ++i )
  744. {
  745. pMeshOut->m_pIndices[ nCurrentIndex ] = pMesh->m_pIndices[ i ] + nCurrentVertex;
  746. nCurrentIndex ++;
  747. }
  748. nCurrentVertex += pMesh->m_nVertexCount;
  749. }
  750. return true;
  751. }
  752. // Recursively tessellates a triangle if it's UV ranges are greater than 1
  753. void TessellateTriangle( CUtlBuffer *pOutTriangles, const float **ppVertsIn, int nTexcoordOffset, int nVertexStride )
  754. {
  755. // Find the longest and second longest edges
  756. float flLongestUV = -1;
  757. float flSecondLongestUV = -1;
  758. int nLongestEdge = -1;
  759. int nSecondLongestEdge = -1;
  760. for ( int e=0; e<3; ++e )
  761. {
  762. int eNext = ( e + 1 ) % 3;
  763. float flUDelta = fabs( ppVertsIn[ eNext ][ nTexcoordOffset ] - ppVertsIn[ e ][ nTexcoordOffset ] );
  764. float flVDelta = fabs( ppVertsIn[ eNext ][ nTexcoordOffset + 1 ] - ppVertsIn[ e ][ nTexcoordOffset + 1 ] );
  765. if ( flUDelta > flLongestUV )
  766. {
  767. flSecondLongestUV = flLongestUV;
  768. nSecondLongestEdge = nLongestEdge;
  769. flLongestUV = flUDelta;
  770. nLongestEdge = e;
  771. }
  772. else if ( flUDelta > flSecondLongestUV )
  773. {
  774. flSecondLongestUV = flUDelta;
  775. nSecondLongestEdge = e;
  776. }
  777. if ( flVDelta > flLongestUV )
  778. {
  779. flSecondLongestUV = flLongestUV;
  780. nSecondLongestEdge = nLongestEdge;
  781. flLongestUV = flVDelta;
  782. nLongestEdge = e;
  783. }
  784. else if( flVDelta > flSecondLongestUV )
  785. {
  786. flSecondLongestUV = flVDelta;
  787. nSecondLongestEdge = e;
  788. }
  789. }
  790. Assert( nLongestEdge > -1 && nSecondLongestEdge > -1 );
  791. static const int pCornerTable[3][3] =
  792. {
  793. -1, // 0, 0
  794. 1, // 0, 1
  795. 0, // 0, 2
  796. 1, // 1, 0
  797. -1, // 1, 1
  798. 2, // 1, 2
  799. 0, // 2, 0
  800. 2, // 2, 1
  801. -1, // 2, 2
  802. };
  803. if ( flLongestUV > 1.0f )
  804. {
  805. // Subdivide in half
  806. float *pEdgeVertex0 = new float[ nVertexStride ];
  807. float *pEdgeVertex1 = new float[ nVertexStride ];
  808. // Find the vertex that is the corner of the two longest edges
  809. int nCornerVertex = pCornerTable[ nLongestEdge ][ nSecondLongestEdge ];
  810. Assert( nCornerVertex > -1 );
  811. int nCornerPlus1 = ( nCornerVertex + 1 ) % 3;
  812. int nCornerPlus2 = ( nCornerVertex + 2 ) % 3;
  813. // Cut the two longest edges in half
  814. LerpVertex( pEdgeVertex0, ppVertsIn[ nCornerVertex ], ppVertsIn[ nCornerPlus1 ], 0.5f, nVertexStride );
  815. LerpVertex( pEdgeVertex1, ppVertsIn[ nCornerPlus2 ], ppVertsIn[ nCornerVertex ], 0.5f, nVertexStride );
  816. // Test the 3 children
  817. const float *pVerts0[3] = { ppVertsIn[ nCornerVertex ], pEdgeVertex0, pEdgeVertex1 };
  818. TessellateTriangle( pOutTriangles, pVerts0, nTexcoordOffset, nVertexStride );
  819. const float *pVerts1[3] = { pEdgeVertex0, ppVertsIn[ nCornerPlus1 ], ppVertsIn[ nCornerPlus2 ] };
  820. TessellateTriangle( pOutTriangles, pVerts1, nTexcoordOffset, nVertexStride );
  821. const float *pVerts2[3] = { pEdgeVertex0, ppVertsIn[ nCornerPlus2 ], pEdgeVertex1 };
  822. TessellateTriangle( pOutTriangles, pVerts2, nTexcoordOffset, nVertexStride );
  823. delete []pEdgeVertex0;
  824. delete []pEdgeVertex1;
  825. }
  826. else
  827. {
  828. // This triangle is OK
  829. pOutTriangles->Put( ppVertsIn[ 0 ], nVertexStride * sizeof( float ) );
  830. pOutTriangles->Put( ppVertsIn[ 1 ], nVertexStride * sizeof( float ) );
  831. pOutTriangles->Put( ppVertsIn[ 2 ], nVertexStride * sizeof( float ) );
  832. }
  833. }
  834. // Subdivide triangles when their UV coordinates exceed the [0..1] range
  835. bool TessellateOnWrappedUV( CMesh *pMeshOut, const CMesh &inputMesh )
  836. {
  837. // We need to have texcoords to rationalize
  838. int nTexcoordOffset = inputMesh.FindFirstAttributeOffset( VERTEX_ELEMENT_TEXCOORD2D_0 );
  839. if ( nTexcoordOffset < 0 )
  840. {
  841. nTexcoordOffset = inputMesh.FindFirstAttributeOffset( VERTEX_ELEMENT_TEXCOORD3D_0 );
  842. }
  843. if ( nTexcoordOffset < 0 )
  844. {
  845. return false;
  846. }
  847. // Tessellate the triangles
  848. CUtlBuffer triangleBuffer;
  849. for ( int i=0; i<inputMesh.m_nIndexCount; i += 3 )
  850. {
  851. const float *pVerts[3];
  852. pVerts[ 0 ] = inputMesh.GetVertex( inputMesh.m_pIndices[ i ] );
  853. pVerts[ 1 ] = inputMesh.GetVertex( inputMesh.m_pIndices[ i + 1 ] );
  854. pVerts[ 2 ] = inputMesh.GetVertex( inputMesh.m_pIndices[ i + 2 ] );
  855. TessellateTriangle( &triangleBuffer, pVerts, nTexcoordOffset, inputMesh.m_nVertexStrideFloats );
  856. }
  857. int nNewVertices = triangleBuffer.TellPut() / ( inputMesh.m_nVertexStrideFloats * sizeof( float ) );
  858. pMeshOut->AllocateMesh( nNewVertices, nNewVertices, inputMesh.m_nVertexStrideFloats, inputMesh.m_pAttributes, inputMesh.m_nAttributeCount );
  859. Q_memcpy( pMeshOut->m_pVerts, triangleBuffer.Base(), triangleBuffer.TellPut() );
  860. for ( int i=0; i<nNewVertices; ++i )
  861. {
  862. pMeshOut->m_pIndices[ i ] = i;
  863. }
  864. return RationalizeUVsInPlace( pMeshOut );
  865. }
  866. bool VertexMatches( const float *pV0, const float *pV1, const float *pEpsilons, int nEpsilons )
  867. {
  868. for ( int i = 0; i < nEpsilons; ++i )
  869. {
  870. float flDelta = pV0[i] - pV1[i];
  871. if ( fabs( flDelta ) > pEpsilons[ i ] )
  872. return false;
  873. }
  874. return true;
  875. }
  876. class CVertexKDNode
  877. {
  878. public:
  879. uint32 m_nChildren[2];
  880. int32 m_nAxis;
  881. float m_flSplit;
  882. inline bool IsLeaf() const { return m_nAxis == 0xFF ? true : false; }
  883. inline void InitAsSplit( float flSplit, int nAxis, int nCount )
  884. {
  885. m_nAxis = nAxis;
  886. m_flSplit = flSplit;
  887. m_nChildren[0] = uint32(~0);
  888. m_nChildren[1] = uint32(~0);
  889. }
  890. inline int GetLeafVertCount() const { Assert(IsLeaf()); return m_nChildren[1]; }
  891. inline int GetLeafVertStart() const { Assert(IsLeaf()); return m_nChildren[0]; }
  892. void InitAsLeaf( int nStart, int nCount )
  893. {
  894. m_nAxis = 0xFF;
  895. m_flSplit = 0;
  896. m_nChildren[0] = nStart;
  897. m_nChildren[1] = nCount;
  898. }
  899. };
  900. class CVertexKDTree
  901. {
  902. public:
  903. CVertexKDTree() {}
  904. void BuildMidpoint( const float *pVerts, int nVertexCount, int nVertexStrideFloats );
  905. void FindVertsInBox( CUtlVectorFixedGrowable<const float *, 64> &list, const Vector &mins, const Vector &maxs, int nStartNode = 0 );
  906. private:
  907. int FindMidpointIndex( int nStart, int nCount, int nAxis, float flSplit );
  908. void ComputeBounds( Vector *pMins, Vector *pMaxs, int nStart, int nCount );
  909. int BuildNode( int nStart, int nCount ); // recursive
  910. CUtlVector<CVertexKDNode> m_tree;
  911. CUtlVector<const float *> m_vertexList;
  912. };
  913. int CVertexKDTree::FindMidpointIndex( int nStart, int nCount, int nAxis, float flSplit )
  914. {
  915. // partition the verts in this run on the axis with the greatest extent
  916. const float **pBase = m_vertexList.Base() + nStart;
  917. int nMid = nCount/2;
  918. int nEnd = nCount;
  919. for ( int i = nMid; i < nEnd; i++ )
  920. {
  921. if ( pBase[i][nAxis] < flSplit )
  922. {
  923. const float *pSwap = pBase[nMid];
  924. pBase[nMid] = pBase[i];
  925. pBase[i] = pSwap;
  926. nMid++;
  927. }
  928. }
  929. for ( int i = nMid-1; i >= 0; i-- )
  930. {
  931. if ( pBase[i][nAxis] >= flSplit )
  932. {
  933. const float *pSwap = pBase[nMid-1];
  934. pBase[nMid-1] = pBase[i];
  935. pBase[i] = pSwap;
  936. nMid--;
  937. }
  938. }
  939. return nMid + nStart;
  940. }
  941. void CVertexKDTree::FindVertsInBox( CUtlVectorFixedGrowable<const float *, 64> &list, const Vector &mins, const Vector &maxs, int nStartNode )
  942. {
  943. const CVertexKDNode &node = m_tree[nStartNode];
  944. if ( node.IsLeaf() )
  945. {
  946. int nVertCount = node.GetLeafVertCount();
  947. int nVertStart = node.GetLeafVertStart();
  948. // check each vert at this leaf
  949. for ( int i = 0; i < nVertCount; i++ )
  950. {
  951. const float *pVert = m_vertexList[nVertStart + i];
  952. // is point in box, add to tail
  953. if ( pVert[0] >= mins.x && pVert[0] <= maxs.x && pVert[1] >= mins.y && pVert[1] <= maxs.y && pVert[2] >= mins.z && pVert[2] <= maxs.z )
  954. {
  955. list.AddToTail( pVert );
  956. }
  957. }
  958. }
  959. else
  960. {
  961. // recurse to the sides of the tree that contain the box
  962. int nAxis = node.m_nAxis;
  963. if ( mins[nAxis] <= node.m_flSplit )
  964. {
  965. FindVertsInBox( list, mins, maxs, node.m_nChildren[0] );
  966. }
  967. if ( maxs[nAxis] >= node.m_flSplit )
  968. {
  969. FindVertsInBox( list, mins, maxs, node.m_nChildren[1] );
  970. }
  971. }
  972. }
  973. void CVertexKDTree::ComputeBounds( Vector *pMins, Vector *pMaxs, int nStart, int nCount )
  974. {
  975. Vector mins = *(Vector *)m_vertexList[nStart];
  976. Vector maxs = mins;
  977. for ( int i = 1; i < nCount; i++ )
  978. {
  979. mins.x = MIN(mins.x, m_vertexList[i+nStart][0]);
  980. maxs.x = MAX(maxs.x, m_vertexList[i+nStart][0]);
  981. mins.y = MIN(mins.y, m_vertexList[i+nStart][1]);
  982. maxs.y = MAX(maxs.y, m_vertexList[i+nStart][1]);
  983. mins.z = MIN(mins.z, m_vertexList[i+nStart][2]);
  984. maxs.z = MAX(maxs.z, m_vertexList[i+nStart][2]);
  985. }
  986. if ( pMins )
  987. {
  988. *pMins = mins;
  989. }
  990. if ( pMaxs )
  991. {
  992. *pMaxs = maxs;
  993. }
  994. }
  995. inline int GreatestAxis( const Vector &v )
  996. {
  997. if ( v.x >= v.y )
  998. {
  999. return v.x > v.z ? 0 : 2;
  1000. }
  1001. return v.y > v.z ? 1 : 2;
  1002. }
  1003. int CVertexKDTree::BuildNode( int nStart, int nCount )
  1004. {
  1005. if ( nCount > 8 )
  1006. {
  1007. Vector mins, maxs;
  1008. ComputeBounds( &mins, &maxs, nStart, nCount );
  1009. int nAxis = GreatestAxis( maxs - mins );
  1010. float flSplit = 0.5f * (maxs[nAxis] + mins[nAxis]);
  1011. int nSplit = FindMidpointIndex( nStart, nCount, nAxis, flSplit );
  1012. int nLeftCount = nSplit - nStart;
  1013. int nRightCount = (nStart + nCount) - nSplit;
  1014. if ( nLeftCount != 0 && nRightCount != 0 )
  1015. {
  1016. int nIndex = m_tree.AddToTail();
  1017. int nLeft = BuildNode( nStart, nLeftCount );
  1018. int nRight = BuildNode( nSplit, nRightCount );
  1019. m_tree[nIndex].InitAsSplit( flSplit, nAxis, nCount );
  1020. m_tree[nIndex].m_nChildren[0] = nLeft;
  1021. m_tree[nIndex].m_nChildren[1] = nRight;
  1022. return nIndex;
  1023. }
  1024. }
  1025. int nIndex = m_tree.AddToTail();
  1026. m_tree[nIndex].InitAsLeaf( nStart, nCount );
  1027. return nIndex;
  1028. }
  1029. void CVertexKDTree::BuildMidpoint( const float *pVerts, int nVertexCount, int nVertexStrideFloats )
  1030. {
  1031. m_vertexList.SetCount( nVertexCount );
  1032. for ( int i = 0; i < nVertexCount; i++ )
  1033. {
  1034. m_vertexList[i] = pVerts + i * nVertexStrideFloats;
  1035. }
  1036. BuildNode( 0, nVertexCount );
  1037. }
  1038. // TODO: Extreme welds can cause faces to flip/invert. Should we add an option to detect and avoid this?
  1039. bool WeldVertices( CMesh *pMeshOut, const CMesh &inputMesh, float *pEpsilons, int nEpsilons )
  1040. {
  1041. // Must have epsilons for at least the first three position components
  1042. if ( nEpsilons != inputMesh.m_nVertexStrideFloats )
  1043. return false;
  1044. CVertexKDTree searchTree;
  1045. searchTree.BuildMidpoint( inputMesh.m_pVerts, inputMesh.m_nVertexCount, inputMesh.m_nVertexStrideFloats );
  1046. CUtlVector< const float* > inOrderVertices;
  1047. CUtlVector<uint32> remapTable;
  1048. const uint32 nEmptyValue = uint32(~0);
  1049. remapTable.SetCount( inputMesh.m_nVertexCount );
  1050. remapTable.FillWithValue( nEmptyValue );
  1051. Vector mins, maxs;
  1052. CUtlVectorFixedGrowable<const float *, 64> list;
  1053. for ( int i = 0; i < inputMesh.m_nVertexCount; i++ )
  1054. {
  1055. // skip if already welded this vertex
  1056. if ( remapTable[i] != nEmptyValue )
  1057. continue;
  1058. // build weld box around vert
  1059. const float *pVertex = inputMesh.GetVertex(i);
  1060. mins.x = pVertex[0] - pEpsilons[0];
  1061. mins.y = pVertex[1] - pEpsilons[1];
  1062. mins.z = pVertex[2] - pEpsilons[2];
  1063. maxs.x = pVertex[0] + pEpsilons[0];
  1064. maxs.y = pVertex[1] + pEpsilons[1];
  1065. maxs.z = pVertex[2] + pEpsilons[2];
  1066. list.RemoveAll();
  1067. searchTree.FindVertsInBox( list, mins, maxs );
  1068. for ( int j = 0; j < list.Count(); j++ )
  1069. {
  1070. const float *pCheck = list[j];
  1071. // only check lower indexed vertices, the opposite check will happen in future iterations
  1072. if ( pCheck >= pVertex )
  1073. continue;
  1074. int nMatchIndex = (list[j] - inputMesh.m_pVerts) / inputMesh.m_nVertexStrideFloats;
  1075. Assert(remapTable[nMatchIndex] != nEmptyValue);
  1076. // match the output vert instead of the input - this vert may have been welded to some other vert
  1077. pCheck = inOrderVertices[remapTable[nMatchIndex]];
  1078. if ( VertexMatches( pVertex, pCheck, pEpsilons, inputMesh.m_nVertexStrideFloats ) )
  1079. {
  1080. remapTable[i] = remapTable[nMatchIndex];
  1081. break;
  1082. }
  1083. }
  1084. if ( remapTable[i] == nEmptyValue )
  1085. {
  1086. int nVertexIndex = inOrderVertices.AddToTail( pVertex );
  1087. remapTable[i] = nVertexIndex;
  1088. }
  1089. }
  1090. // allocate enough for all new verts
  1091. int nNewVerts = inOrderVertices.Count();
  1092. pMeshOut->AllocateMesh( nNewVerts, inputMesh.m_nIndexCount, inputMesh.m_nVertexStrideFloats, inputMesh.m_pAttributes, inputMesh.m_nAttributeCount );
  1093. // copy the welded verts out
  1094. for ( int v=0; v<nNewVerts; ++v )
  1095. {
  1096. CopyVertex( pMeshOut->GetVertex( v ), inOrderVertices[ v ], inputMesh.m_nVertexStrideFloats );
  1097. }
  1098. // now remap the indices
  1099. for ( int i=0; i<inputMesh.m_nIndexCount; ++i )
  1100. {
  1101. pMeshOut->m_pIndices[ i ] = remapTable[ inputMesh.m_pIndices[ i ] ];
  1102. Assert( pMeshOut->m_pIndices[i] < (uint32)nNewVerts );
  1103. }
  1104. return true;
  1105. }
  1106. void CleanMesh( CMesh *pMeshOut, const CMesh &inputMesh )
  1107. {
  1108. CUtlVector<uint32> indexMap;
  1109. indexMap.SetCount( inputMesh.m_nVertexCount );
  1110. const uint32 nUnusedIndex = ~0UL;
  1111. for ( int i = 0; i < inputMesh.m_nVertexCount; i++ )
  1112. {
  1113. indexMap[i] = nUnusedIndex;
  1114. }
  1115. // build a compact map of vertices
  1116. uint32 nVertexOut = 0;
  1117. int nIndexOut = 0;
  1118. for ( int i = 0; i < inputMesh.m_nIndexCount; i += 3 )
  1119. {
  1120. // skip degenerate triangles
  1121. int nV0 = inputMesh.m_pIndices[i+0];
  1122. int nV1 = inputMesh.m_pIndices[i+1];
  1123. int nV2 = inputMesh.m_pIndices[i+2];
  1124. if ( nV0 == nV1 || nV1 == nV2 || nV0 == nV2 )
  1125. continue;
  1126. if ( indexMap[nV0] == nUnusedIndex )
  1127. {
  1128. indexMap[nV0] = nVertexOut++;
  1129. }
  1130. if ( indexMap[nV1] == nUnusedIndex )
  1131. {
  1132. indexMap[nV1] = nVertexOut++;
  1133. }
  1134. if ( indexMap[nV2] == nUnusedIndex )
  1135. {
  1136. indexMap[nV2] = nVertexOut++;
  1137. }
  1138. nIndexOut += 3;
  1139. }
  1140. // allocate the cleaned mesh now that we know its size
  1141. pMeshOut->AllocateMesh( nVertexOut, nIndexOut, inputMesh.m_nVertexStrideFloats, inputMesh.m_pAttributes, inputMesh.m_nAttributeCount );
  1142. nIndexOut = 0;
  1143. for ( int i = 0; i < inputMesh.m_nIndexCount; i += 3 )
  1144. {
  1145. // skip degenerate triangles (again)
  1146. int nV0 = inputMesh.m_pIndices[i+0];
  1147. int nV1 = inputMesh.m_pIndices[i+1];
  1148. int nV2 = inputMesh.m_pIndices[i+2];
  1149. if ( nV0 == nV1 || nV1 == nV2 || nV0 == nV2 )
  1150. continue;
  1151. // copy and remap the indices
  1152. pMeshOut->m_pIndices[ nIndexOut++ ] = indexMap[ nV0 ];
  1153. pMeshOut->m_pIndices[ nIndexOut++ ] = indexMap[ nV1 ];
  1154. pMeshOut->m_pIndices[ nIndexOut++ ] = indexMap[ nV2 ];
  1155. }
  1156. Assert( nIndexOut == pMeshOut->m_nIndexCount );
  1157. // copy out the vertices in order by use
  1158. for ( int v = 0; v < inputMesh.m_nVertexCount; ++v )
  1159. {
  1160. if ( indexMap[v] == nUnusedIndex )
  1161. continue;
  1162. uint32 nVOut = indexMap[v];
  1163. CopyVertex( pMeshOut->GetVertex( nVOut ), inputMesh.GetVertex(v), inputMesh.m_nVertexStrideFloats );
  1164. }
  1165. }
  1166. // partitions the mesh into an array of meshes, each with <= nMaxVertex vertices
  1167. void SplitMesh( CUtlVector<CMesh> &list, const CMesh &input, int nMaxVertex )
  1168. {
  1169. const uint32 nUnusedIndex = uint32(~0);
  1170. CUtlVector<uint32> indexMap;
  1171. indexMap.SetCount( input.m_nVertexCount );
  1172. for ( int i = 0; i < input.m_nVertexCount; i++ )
  1173. {
  1174. indexMap[i] = nUnusedIndex;
  1175. }
  1176. CUtlVectorFixedGrowable<int, 32> indexCount;
  1177. CUtlVectorFixedGrowable<int, 32> vertexCount;
  1178. const uint32 *pIndex = input.m_pIndices;
  1179. const int nCount = input.m_nIndexCount;
  1180. int nIndex = 0;
  1181. int nIndexOut = 0;
  1182. int nVertexOut = 0;
  1183. // count how many you need
  1184. while ( nIndex < nCount )
  1185. {
  1186. if ( indexMap[pIndex[nIndex]] == nUnusedIndex )
  1187. {
  1188. indexMap[pIndex[nIndex]] = nVertexOut;
  1189. nVertexOut++;
  1190. if ( nVertexOut >= nMaxVertex )
  1191. {
  1192. nIndexOut -= (nIndex%3);
  1193. nIndex -= (nIndex%3);
  1194. indexCount.AddToTail(nIndexOut);
  1195. vertexCount.AddToTail(nVertexOut);
  1196. for ( int i = 0; i < input.m_nVertexCount; i++ )
  1197. {
  1198. indexMap[i] = nUnusedIndex;
  1199. }
  1200. nVertexOut = 0;
  1201. nIndexOut = 0;
  1202. continue;
  1203. }
  1204. }
  1205. nIndexOut++;
  1206. nIndex++;
  1207. }
  1208. if ( nVertexOut > 0 && nIndexOut > 0 )
  1209. {
  1210. indexCount.AddToTail( nIndexOut );
  1211. vertexCount.AddToTail( nVertexOut );
  1212. }
  1213. // now allocate the actual meshes and populate them
  1214. nIndex = 0;
  1215. int nMeshCount = indexCount.Count();
  1216. list.SetCount( nMeshCount );
  1217. for ( int nMesh = 0; nMesh < nMeshCount; nMesh++ )
  1218. {
  1219. list[nMesh].AllocateMesh( vertexCount[nMesh], indexCount[nMesh], input.m_nVertexStrideFloats, input.m_pAttributes, input.m_nAttributeCount );
  1220. int nIndexCount = indexCount[nMesh];
  1221. nVertexOut = 0;
  1222. Assert( (nIndexCount%3) == 0 );
  1223. Assert( (nIndex%3) == 0 );
  1224. for ( int i = 0; i < input.m_nVertexCount; i++ )
  1225. {
  1226. indexMap[i] = nUnusedIndex;
  1227. }
  1228. for ( int j = 0; j < nIndexCount; j++ )
  1229. {
  1230. int nV0 = pIndex[nIndex];
  1231. if ( indexMap[nV0] == nUnusedIndex )
  1232. {
  1233. CopyVertex( list[nMesh].GetVertex(nVertexOut), input.GetVertex(nV0), input.m_nVertexStrideFloats );
  1234. indexMap[nV0] = nVertexOut;
  1235. nVertexOut++;
  1236. Assert( nVertexOut <= vertexCount[nMesh] );
  1237. }
  1238. list[nMesh].m_pIndices[j] = indexMap[nV0];
  1239. nIndex++;
  1240. }
  1241. }
  1242. }
  1243. bool CMesh::HasSkinningData()const
  1244. {
  1245. return GetSkinningDataFields().HasSkinningData();
  1246. }
  1247. // Find and return joint weight and joint indices attributes in a convenient struct
  1248. CMesh::SkinningDataFields_t CMesh::GetSkinningDataFields()const
  1249. {
  1250. SkinningDataFields_t dataFields;
  1251. for ( int a = 0; a < m_nAttributeCount; ++a )
  1252. {
  1253. if ( m_pAttributes[ a ].IsJointWeight() )
  1254. {
  1255. if ( dataFields.m_nBoneWeights < 0 /*|| m_pAttributes[ a ].m_nSemanticIndex < m_pAttributes[ dataFields.m_nBoneWeights ].m_nSemanticIndex*/ )
  1256. {
  1257. dataFields.m_nBoneWeights = a;
  1258. }
  1259. }
  1260. if ( m_pAttributes[ a ].IsJointIndices() )
  1261. {
  1262. if ( dataFields.m_nBoneIndices < 0 /*|| m_pAttributes[ a ].m_nSemanticIndex < m_pAttributes[ dataFields.m_nBoneIndices ].m_nSemanticIndex*/ )
  1263. {
  1264. dataFields.m_nBoneIndices = a;
  1265. }
  1266. }
  1267. }
  1268. // we must have either both or none or indices but not just weights by themselves
  1269. Assert( ( dataFields.m_nBoneWeights < 0 ) || ( dataFields.m_nBoneIndices >= 0 ) );
  1270. return dataFields;
  1271. }
  1272. CMesh::ClothDataFields_t CMesh::GetClothDataFields() const
  1273. {
  1274. ClothDataFields_t dataFields;
  1275. for ( int a = 0; a < m_nAttributeCount; ++a )
  1276. {
  1277. if ( m_pAttributes[ a ].IsClothEnable() )
  1278. {
  1279. dataFields.m_nClothEnable = a;
  1280. }
  1281. if ( m_pAttributes[ a ].IsPositionRemap() )
  1282. {
  1283. dataFields.m_nPositionRemap = a;
  1284. }
  1285. }
  1286. return dataFields;
  1287. }
  1288. int CMesh::GetAttrSizeFloats( int nAttribute )
  1289. {
  1290. if ( nAttribute < 0 || nAttribute >= m_nAttributeCount )
  1291. return 0;
  1292. if ( nAttribute + 1 >= m_nAttributeCount )
  1293. return m_nVertexStrideFloats - m_pAttributes[ nAttribute ].m_nOffsetFloats;
  1294. return m_pAttributes[ nAttribute + 1 ].m_nOffsetFloats - m_pAttributes[ nAttribute ].m_nOffsetFloats;
  1295. }
  1296. float CMesh::GetVertexJointSumWeight( const SkinningDataFields_t &skinData, int nVertex, const CVarBitVec &jointSet )
  1297. {
  1298. if ( skinData.m_nBoneIndices < 0 )
  1299. {
  1300. return 0.0f; // this isn't a skinned mesh
  1301. }
  1302. const CMeshVertexAttribute &attrIndices = m_pAttributes[ skinData.m_nBoneIndices ];
  1303. int nWeightAttrSize= Min( GetAttrSizeFloats( skinData.m_nBoneIndices ), GetAttrSizeFloats( skinData.m_nBoneWeights ) );
  1304. if ( nWeightAttrSize > 1 )
  1305. {
  1306. Assert( uint( skinData.m_nBoneWeights ) < uint( m_nAttributeCount ) );
  1307. const CMeshVertexAttribute &attrWeights = m_pAttributes[ skinData.m_nBoneWeights ];
  1308. //Assert( attrIndices.m_nSizeFloats == attrWeights.m_nSizeFloats );
  1309. float flSumWeight = 0.0f;
  1310. for ( int nWeightIndex = 0; nWeightIndex < nWeightAttrSize; ++nWeightIndex )
  1311. {
  1312. const float *pVertex = GetVertex( nVertex );
  1313. int nAssignedJoint = *( int* )( pVertex + attrIndices.m_nOffsetFloats + nWeightIndex );
  1314. if ( jointSet.IsBitSet( nAssignedJoint ) )
  1315. {
  1316. float flAssignedWeight = pVertex[ attrWeights.m_nOffsetFloats + nWeightIndex ];
  1317. flSumWeight += flAssignedWeight;
  1318. }
  1319. }
  1320. return flSumWeight; // didn't find the joint
  1321. }
  1322. else
  1323. {
  1324. // there's just one weight
  1325. int nAssignedJoint = *( int* )( GetVertex( nVertex ) + attrIndices.m_nOffsetFloats );
  1326. return jointSet.IsBitSet( nAssignedJoint ) ? 1.0f : 0.0f;
  1327. }
  1328. }