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.

3932 lines
111 KiB

  1. //====== Copyright � 1996-2006, Valve Corporation, All rights reserved. =======
  2. //
  3. // Functions which do things to a DmeMesh
  4. //
  5. //=============================================================================
  6. // Valve includes
  7. #include "dmeutils/dmmeshutils.h"
  8. #include "movieobjects/dmeanimationset.h"
  9. #include "movieobjects/dmecombinationoperator.h"
  10. #include "movieobjects/dmemodel.h"
  11. #include "movieobjects/dmedag.h"
  12. #include "movieobjects/dmemesh.h"
  13. #include "movieobjects/dmefaceset.h"
  14. #include "movieobjects/dmematerial.h"
  15. #include "movieobjects/dmevertexdata.h"
  16. #include "tier1/utlstack.h"
  17. #include "tier2/p4helpers.h"
  18. #include "tier1/utlstring.h"
  19. #include "tier1/utlstringmap.h"
  20. #include "tier1/utlbuffer.h"
  21. #include "tier1/fmtstr.h"
  22. #include "filesystem.h"
  23. // memdbgon must be the last include file in a .cpp file!!!
  24. #include "tier0/memdbgon.h"
  25. //-----------------------------------------------------------------------------
  26. //
  27. //-----------------------------------------------------------------------------
  28. DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_MESHUTILS, "MeshUtils" );
  29. #ifndef LOG_COLOR_RED
  30. #define LOG_COLOR_RED Color( 255, 0, 0, 255 )
  31. #endif // #ifndef LOG_COLOR_RED
  32. #ifndef LOG_COLOR_YELLOW
  33. #define LOG_COLOR_YELLOW Color( 255, 255, 0, 255 )
  34. #endif // #ifndef LOG_COLOR_YELLOW
  35. //-----------------------------------------------------------------------------
  36. //
  37. //-----------------------------------------------------------------------------
  38. bool CDmMeshUtils::RemoveLargeAxisAlignedPlanarFaces( CDmeMesh *pMesh )
  39. {
  40. CDmeVertexData *pBase( pMesh->FindBaseState( "bind" ) );
  41. if ( !pBase )
  42. return false;
  43. const int posIndex = pBase->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  44. if ( posIndex < 0 )
  45. return false;
  46. const CUtlVector< Vector > &posData( CDmrArrayConst< Vector >( pBase->GetVertexData( posIndex ) ).Get() );
  47. if ( posData.Count() <= 0 )
  48. return false;
  49. const CUtlVector< int > &posIndices( CDmrArrayConst< int >( pBase->GetIndexData( posIndex ) ).Get() );
  50. if ( posIndices.Count() <= 0 )
  51. return false;
  52. bool bMeshChanged = false;
  53. CUtlVector< int > emptyFaceSets;
  54. int faceStartIndex = 0;
  55. int faceCurrentIndex = 0;
  56. int faceVertexCount = 0;
  57. bool bPlanarX = true;
  58. bool bPlanarY = true;
  59. bool bPlanarZ = true;
  60. Vector p;
  61. CUtlVector< int > removeStart;
  62. CUtlVector< int > removeCount;
  63. const int nFaceSets = pMesh->FaceSetCount();
  64. for ( int i = 0; i < nFaceSets; ++i )
  65. {
  66. CDmeFaceSet *pFaceSet = pMesh->GetFaceSet( i );
  67. const int nFaceIndices = pFaceSet->NumIndices();
  68. if ( nFaceIndices <= 0 )
  69. continue;
  70. faceStartIndex = 0;
  71. faceCurrentIndex = pFaceSet->GetIndex( 0 );
  72. if ( faceCurrentIndex < 0 )
  73. continue;
  74. faceVertexCount = 0;
  75. bPlanarX = true;
  76. bPlanarY = true;
  77. bPlanarZ = true;
  78. removeStart.RemoveAll();
  79. removeCount.RemoveAll();
  80. p = posData[ posIndices[ faceCurrentIndex ] ];
  81. for ( int j = 1; j < nFaceIndices; ++j )
  82. {
  83. faceCurrentIndex = pFaceSet->GetIndex( j );
  84. if ( faceCurrentIndex < 0 )
  85. {
  86. // End of a face
  87. if ( faceVertexCount > 4 && ( bPlanarX || bPlanarY || bPlanarZ ) )
  88. {
  89. removeStart.AddToTail( faceStartIndex );
  90. removeCount.AddToTail( j - faceStartIndex + 1 );
  91. }
  92. faceStartIndex = j + 1;
  93. if ( faceStartIndex < nFaceIndices )
  94. {
  95. p = posData[ posIndices[ pFaceSet->GetIndex( faceStartIndex ) ] ];
  96. }
  97. faceVertexCount = 0;
  98. bPlanarX = true;
  99. bPlanarY = true;
  100. bPlanarZ = true;
  101. continue;
  102. }
  103. Assert( faceCurrentIndex < posIndices.Count() );
  104. Assert( posIndices[ faceCurrentIndex ] < posData.Count() );
  105. const Vector &vPos = posData[ posIndices[ faceCurrentIndex ] ];
  106. if ( vPos.x != p.x )
  107. bPlanarX = false;
  108. if ( vPos.y != p.y )
  109. bPlanarY = false;
  110. if ( vPos.z != p.z )
  111. bPlanarZ = false;
  112. ++faceVertexCount;
  113. }
  114. Assert( removeStart.Count() == removeCount.Count() );
  115. for ( int j = removeStart.Count() - 1; j >= 0; --j )
  116. {
  117. pFaceSet->RemoveMultiple( removeStart[ j ], removeCount[ j ] );
  118. bMeshChanged = true;
  119. }
  120. if ( pFaceSet->GetIndexCount() == 0 )
  121. {
  122. emptyFaceSets.AddToTail( i );
  123. }
  124. }
  125. for ( int i = emptyFaceSets.Count() - 1; i >= 0; --i )
  126. {
  127. pMesh->RemoveFaceSet( emptyFaceSets[ i ] );
  128. bMeshChanged = true;
  129. }
  130. if ( bMeshChanged )
  131. {
  132. PurgeUnusedData( pMesh );
  133. return true;
  134. }
  135. return false;
  136. }
  137. //-----------------------------------------------------------------------------
  138. //
  139. //-----------------------------------------------------------------------------
  140. bool CDmMeshUtils::RemoveFacesWithMaterial( CDmeMesh *pMesh, const char *pMaterialName )
  141. {
  142. bool bMeshChanged = false;
  143. CUtlVector< int > emptyFaceSets;
  144. const int nFaceSets = pMesh->FaceSetCount();
  145. for ( int i = 0; i < nFaceSets; ++i )
  146. {
  147. CDmeFaceSet *pFaceSet = pMesh->GetFaceSet( i );
  148. if ( !Q_strcmp( pFaceSet->GetMaterial()->GetMaterialName(), pMaterialName ) )
  149. {
  150. emptyFaceSets.AddToTail( i );
  151. bMeshChanged = true;
  152. }
  153. }
  154. for ( int i = emptyFaceSets.Count() - 1; i >= 0; --i )
  155. {
  156. pMesh->RemoveFaceSet( emptyFaceSets[ i ] );
  157. bMeshChanged = true;
  158. }
  159. if ( bMeshChanged )
  160. {
  161. PurgeUnusedData( pMesh );
  162. return true;
  163. }
  164. return false;
  165. }
  166. //-----------------------------------------------------------------------------
  167. //
  168. //-----------------------------------------------------------------------------
  169. bool CDmMeshUtils::RemoveFacesWithMoreThanNVerts( CDmeMesh *pMesh, const int nVertexCount )
  170. {
  171. CDmeVertexData *pBase( pMesh->FindBaseState( "bind" ) );
  172. if ( !pBase )
  173. return false;
  174. bool bMeshChanged = false;
  175. CUtlVector< int > emptyFaceSets;
  176. int faceStartIndex = 0;
  177. int faceCurrentIndex = 0;
  178. int faceVertexCount = 0;
  179. CUtlVector< int > removeStart;
  180. CUtlVector< int > removeCount;
  181. const int nFaceSets = pMesh->FaceSetCount();
  182. for ( int i = 0; i < nFaceSets; ++i )
  183. {
  184. CDmeFaceSet *pFaceSet = pMesh->GetFaceSet( i );
  185. const int nFaceIndices = pFaceSet->NumIndices();
  186. if ( nFaceIndices <= 0 )
  187. continue;
  188. faceStartIndex = 0;
  189. faceCurrentIndex = pFaceSet->GetIndex( 0 );
  190. if ( faceCurrentIndex < 0 )
  191. continue;
  192. faceVertexCount = 0;
  193. removeStart.RemoveAll();
  194. removeCount.RemoveAll();
  195. for ( int j = 1; j < nFaceIndices; ++j )
  196. {
  197. faceCurrentIndex = pFaceSet->GetIndex( j );
  198. if ( faceCurrentIndex < 0 )
  199. {
  200. // End of a face
  201. if ( faceVertexCount > nVertexCount )
  202. {
  203. removeStart.AddToTail( faceStartIndex );
  204. removeCount.AddToTail( j - faceStartIndex + 1 );
  205. }
  206. faceStartIndex = j + 1;
  207. faceVertexCount = 0;
  208. continue;
  209. }
  210. ++faceVertexCount;
  211. }
  212. Assert( removeStart.Count() == removeCount.Count() );
  213. for ( int j = removeStart.Count() - 1; j >= 0; --j )
  214. {
  215. pFaceSet->RemoveMultiple( removeStart[ j ], removeCount[ j ] );
  216. bMeshChanged = true;
  217. }
  218. if ( pFaceSet->GetIndexCount() == 0 )
  219. {
  220. emptyFaceSets.AddToTail( i );
  221. }
  222. }
  223. for ( int i = emptyFaceSets.Count() - 1; i >= 0; --i )
  224. {
  225. pMesh->RemoveFaceSet( emptyFaceSets[ i ] );
  226. bMeshChanged = true;
  227. }
  228. if ( bMeshChanged )
  229. {
  230. PurgeUnusedData( pMesh );
  231. return true;
  232. }
  233. // Nothing remove
  234. return false;
  235. }
  236. //-----------------------------------------------------------------------------
  237. // Figures out which vertexIndices are missing
  238. // Returned list will be in sorted order
  239. //-----------------------------------------------------------------------------
  240. void ComputeVertexIndexMap( CDmeMesh *pMesh, int nMaxVertexCount, CUtlVector< int > &vertexIndexMap )
  241. {
  242. bool *pVertexFound = reinterpret_cast< bool * >( alloca( nMaxVertexCount * sizeof( bool ) ) );
  243. memset( pVertexFound, 0, nMaxVertexCount * sizeof( bool ) );
  244. // Loop through all the face sets to find out the highest vertex index
  245. const int nFaceSetCount = pMesh->FaceSetCount();
  246. for ( int i = 0; i < nFaceSetCount; ++i )
  247. {
  248. const CDmeFaceSet *pFaceSet = pMesh->GetFaceSet( i );
  249. const int nFaceSetIndices = pFaceSet->NumIndices();
  250. for ( int j = 0; j < nFaceSetIndices; ++j )
  251. {
  252. const int &nIndex = pFaceSet->GetIndex( j );
  253. if ( nIndex >= 0 )
  254. {
  255. Assert( nIndex < nMaxVertexCount );
  256. pVertexFound[ nIndex ] = true;
  257. }
  258. }
  259. }
  260. int nMissingCount = 0;
  261. for ( int i = 0; i < nMaxVertexCount; ++i )
  262. {
  263. if ( !pVertexFound[ i ] )
  264. {
  265. ++nMissingCount;
  266. }
  267. }
  268. vertexIndexMap.SetSize( nMaxVertexCount );
  269. for ( int i = 0; i < nMaxVertexCount; ++i )
  270. {
  271. vertexIndexMap[ i ] = i;
  272. }
  273. for ( int i = nMaxVertexCount - 1; i >= 0; --i )
  274. {
  275. if ( !pVertexFound[ i ] )
  276. {
  277. vertexIndexMap.Remove( i );
  278. }
  279. }
  280. // Build up the reverse map
  281. int *pReverseVertexIndexMap = reinterpret_cast< int * >( alloca( nMaxVertexCount * sizeof( int ) ) );
  282. for ( int i = 0; i < nFaceSetCount; ++i )
  283. {
  284. pReverseVertexIndexMap[ i ] = -1;
  285. }
  286. for ( int i = vertexIndexMap.Count() - 1; i >= 0; --i )
  287. {
  288. pReverseVertexIndexMap[ vertexIndexMap[ i ] ] = i;
  289. }
  290. // Fix up the face set indices to compensate for the ones which are going to be removed
  291. for ( int i = 0; i < nFaceSetCount; ++i )
  292. {
  293. CDmeFaceSet *pFaceSet = pMesh->GetFaceSet( i );
  294. const int nFaceSetIndices = pFaceSet->NumIndices();
  295. for ( int j = 0; j < nFaceSetIndices; ++j )
  296. {
  297. const int &nIndex = pFaceSet->GetIndex( j );
  298. if ( nIndex >= 0 )
  299. {
  300. Assert( pReverseVertexIndexMap[ nIndex ] >= 0 );
  301. pFaceSet->SetIndex( j, pReverseVertexIndexMap[ nIndex ] );
  302. }
  303. }
  304. }
  305. }
  306. //-----------------------------------------------------------------------------
  307. // Returns the highest vertex index used by the face sets of the mesh + 1
  308. //-----------------------------------------------------------------------------
  309. int GetMaxVertexCount( const CDmeMesh *pMesh )
  310. {
  311. int nMaxVertexIndex = 0;
  312. // Loop through all the face sets to find out the highest vertex index
  313. const int nFaceSetCount = pMesh->FaceSetCount();
  314. for ( int i = 0; i < nFaceSetCount; ++i )
  315. {
  316. const CDmeFaceSet *pFaceSet = pMesh->GetFaceSet( i );
  317. const int nFaceSetIndices = pFaceSet->NumIndices();
  318. for ( int j = 0; j < nFaceSetIndices; ++j )
  319. {
  320. const int &nIndex = pFaceSet->GetIndex( j );
  321. if ( nIndex > nMaxVertexIndex )
  322. {
  323. nMaxVertexIndex = nIndex;
  324. }
  325. }
  326. }
  327. return nMaxVertexIndex + 1;
  328. }
  329. //-----------------------------------------------------------------------------
  330. //
  331. //-----------------------------------------------------------------------------
  332. template < class T_t >
  333. void RemapData(
  334. CDmrArray< T_t > data,
  335. const CUtlVector< int > &newToOldMap )
  336. {
  337. const int nNewToOldMapCount = newToOldMap.Count();
  338. T_t *pNewData = reinterpret_cast< T_t * >( alloca( nNewToOldMapCount * sizeof( T_t ) ) );
  339. for ( int i = 0; i < nNewToOldMapCount; ++i )
  340. {
  341. pNewData[ i ] = data.Get( newToOldMap[ i ] );
  342. }
  343. data.RemoveMultiple( nNewToOldMapCount, data.Count() - nNewToOldMapCount );
  344. data.SetMultiple( 0, nNewToOldMapCount, pNewData );
  345. }
  346. //-----------------------------------------------------------------------------
  347. // Computes the map of new data indices to old data indices
  348. //-----------------------------------------------------------------------------
  349. void RemoveUnusedData(
  350. CDmeMesh *pMesh,
  351. CDmeVertexData *pVertexData,
  352. bool bBind,
  353. const char *pFieldName,
  354. int *pIndices,
  355. int nIndicesCount,
  356. CDmrGenericArray &data )
  357. {
  358. const int nDataCount = data.Count();
  359. bool *pDataIndexFound = reinterpret_cast< bool * >( alloca( nDataCount * sizeof( bool ) ) );
  360. memset( pDataIndexFound, 0, nDataCount * sizeof( bool ) );
  361. // Figure out which data is used
  362. for ( int i = 0; i < nIndicesCount; ++i )
  363. {
  364. Assert( pIndices[ i ] >= 0 && pIndices[ i ] < nDataCount );
  365. pDataIndexFound[ pIndices[ i ] ] = true;
  366. }
  367. int nMissingCount = 0;
  368. for ( int i = 0; i < nDataCount; ++i )
  369. {
  370. if ( !pDataIndexFound[ i ] )
  371. {
  372. ++nMissingCount;
  373. }
  374. }
  375. // Compute the New to Old data map
  376. CUtlVector< int > newToOldDataMap;
  377. newToOldDataMap.SetSize( nDataCount );
  378. for ( int i = 0; i < nDataCount; ++i )
  379. {
  380. newToOldDataMap[ i ] = i;
  381. }
  382. for ( int i = nDataCount - 1; i >= 0; --i )
  383. {
  384. if ( !pDataIndexFound[ i ] )
  385. {
  386. newToOldDataMap.Remove( i );
  387. }
  388. }
  389. // Fix up the data
  390. CDmAttribute *pDataAttr = data.GetAttribute();
  391. const DmAttributeType_t dataAttrType = pDataAttr->GetType();
  392. switch ( dataAttrType )
  393. {
  394. case AT_FLOAT_ARRAY:
  395. RemapData( CDmrArray< float >( pDataAttr ), newToOldDataMap );
  396. break;
  397. case AT_VECTOR2_ARRAY:
  398. RemapData( CDmrArray< Vector2D >( pDataAttr ), newToOldDataMap );
  399. break;
  400. case AT_VECTOR3_ARRAY:
  401. RemapData( CDmrArray< Vector >( pDataAttr ), newToOldDataMap );
  402. break;
  403. case AT_VECTOR4_ARRAY:
  404. RemapData( CDmrArray< Vector4D >( pDataAttr ), newToOldDataMap );
  405. break;
  406. case AT_QUATERNION_ARRAY:
  407. RemapData( CDmrArray< Quaternion >( pDataAttr ), newToOldDataMap );
  408. break;
  409. case AT_COLOR_ARRAY:
  410. RemapData( CDmrArray< Color >( pDataAttr ), newToOldDataMap );
  411. break;
  412. default:
  413. Assert( 0 );
  414. break;
  415. }
  416. // Compute Old To New Data Map
  417. int *pOldToNewDataMap = reinterpret_cast< int * >( alloca( nDataCount * sizeof( int ) ) );
  418. for ( int i = 0; i < nDataCount; ++i )
  419. {
  420. pOldToNewDataMap[ i ] = -1;
  421. }
  422. for ( int i = newToOldDataMap.Count() - 1; i >= 0; --i )
  423. {
  424. pOldToNewDataMap[ newToOldDataMap[ i ] ] = i;
  425. }
  426. // Fix up the indices
  427. for ( int i = 0; i < nIndicesCount; ++i )
  428. {
  429. pIndices[ i ] = pOldToNewDataMap[ pIndices[ i ] ];
  430. }
  431. // TODO: Fix up "jointWeight & "jointIndices" if this is "position"
  432. if ( !Q_strcmp( pFieldName, "position" ) )
  433. {
  434. const int nFields = pVertexData->FieldCount();
  435. for ( int i = 0; i < nFields; ++i )
  436. {
  437. }
  438. }
  439. // If this is the bind state then fix up any delta states
  440. if ( !bBind )
  441. return;
  442. // Fix up any Delta states
  443. const int nDeltaStateCount = pMesh->DeltaStateCount();
  444. for ( int i = 0; i < nDeltaStateCount; ++i )
  445. {
  446. CDmeVertexDeltaData *pDelta = pMesh->GetDeltaState( i );
  447. const int nDeltaFieldCount = pDelta->FieldCount();
  448. for ( int j = 0; j < nDeltaFieldCount; ++j )
  449. {
  450. if ( !Q_strcmp( pFieldName, pDelta->FieldName( j ) ) )
  451. {
  452. CDmrArray< int > deltaIndices = pDelta->GetIndexData( j );
  453. CDmrGenericArray deltaData = pDelta->GetVertexData( j );
  454. Assert( deltaIndices.Count() == deltaData.Count() );
  455. for ( int k = deltaIndices.Count() - 1; k >= 0; --k )
  456. {
  457. const int oldIndex = deltaIndices.Get( k );
  458. const int &newIndex = pOldToNewDataMap[ oldIndex ];
  459. if ( newIndex < 0 )
  460. {
  461. deltaIndices.Remove( k );
  462. deltaData.Remove( k );
  463. }
  464. else if ( newIndex != oldIndex )
  465. {
  466. deltaIndices.Set( k, newIndex );
  467. }
  468. }
  469. }
  470. }
  471. }
  472. }
  473. //-----------------------------------------------------------------------------
  474. //
  475. //-----------------------------------------------------------------------------
  476. void RemoveUnusedVerticesFromBaseState(
  477. CDmeMesh *pMesh,
  478. CDmeVertexData *pVertexData,
  479. const CUtlVector< int > &newToOldIndexMap )
  480. {
  481. const int nNewToOldIndexMapCount = newToOldIndexMap.Count();
  482. int *pNewVertexIndices = reinterpret_cast< int * >( alloca( nNewToOldIndexMapCount * sizeof( int ) ) );
  483. // See if this is the bind state for the mesh
  484. const bool bBind = !Q_strcmp( pVertexData->GetName(), "bind" );
  485. const int nFieldCount = pVertexData->FieldCount();
  486. for ( int i = 0; i < nFieldCount; ++i )
  487. {
  488. const char *pFieldName = pVertexData->FieldName( i );
  489. // TODO: Checking by name is lame... should be a lookup to map fieldIndex to a standard field index
  490. if ( !Q_strcmp( pFieldName, "jointWeights" ) || !Q_strcmp( pFieldName, "jointIndices" ) )
  491. {
  492. // TODO: Handle when positions are Remapped
  493. continue;
  494. }
  495. CDmrArray< int > indices = pVertexData->GetIndexData( i );
  496. // Create the new index array accounting for missing indices
  497. for ( int j = 0; j < nNewToOldIndexMapCount; ++j )
  498. {
  499. Assert( newToOldIndexMap[ j ] < indices.Count() );
  500. pNewVertexIndices[ j ] = indices.Get( newToOldIndexMap[ j ] );
  501. }
  502. CDmrGenericArray data = pVertexData->GetVertexData( i );
  503. // This will also update pNewVertexIndices
  504. RemoveUnusedData( pMesh, pVertexData, bBind, pFieldName, pNewVertexIndices, nNewToOldIndexMapCount, CDmrGenericArray( pVertexData->GetVertexData( i ) ) );
  505. // Shrink the indices array
  506. indices.RemoveMultiple( nNewToOldIndexMapCount, indices.Count() - nNewToOldIndexMapCount );
  507. // Set the new index values
  508. indices.SetMultiple( 0, nNewToOldIndexMapCount, pNewVertexIndices );
  509. }
  510. // Update the vertex count
  511. pVertexData->Resolve();
  512. }
  513. //-----------------------------------------------------------------------------
  514. // Removes unused data from the mesh
  515. // Unused means a 'vertex' that isn't referred to by any face
  516. // Once all unused vertices are removed, unused data is removed from each
  517. // bit of data
  518. // TODO: Also loop through each field of data, see which ones are no longer
  519. // being referred to and then purge the data as well
  520. // Would also have to purge delta data at the same time
  521. // Would also have to purge joints at the same time (for position)
  522. //-----------------------------------------------------------------------------
  523. bool CDmMeshUtils::PurgeUnusedData( CDmeMesh *pMesh )
  524. {
  525. // Get the maximum vertex index of the mesh
  526. const int nMaxVertexCount = GetMaxVertexCount( pMesh );
  527. // Now find any missing indices
  528. CUtlVector< int > vertexIndexMap;
  529. ComputeVertexIndexMap( pMesh, nMaxVertexCount, vertexIndexMap );
  530. // Remove the redundant vertices from all base states
  531. for ( int i = pMesh->BaseStateCount() - 1; i >= 0; --i )
  532. {
  533. RemoveUnusedVerticesFromBaseState( pMesh, pMesh->GetBaseState( i ), vertexIndexMap );
  534. }
  535. return true;
  536. }
  537. //-----------------------------------------------------------------------------
  538. //
  539. //-----------------------------------------------------------------------------
  540. bool CDmMeshUtils::Mirror( CDmeMesh *pMesh, int axis /*= kXAxis */ )
  541. {
  542. CDmeVertexData *pBase( pMesh->FindBaseState( "bind" ) );
  543. if ( !pBase )
  544. return false;
  545. CUtlVector< int > mirrorMap;
  546. if ( !MirrorVertices( pMesh, pBase, axis, mirrorMap ) )
  547. return false;
  548. int vertexIndex;
  549. int faceStart = 0;
  550. CUtlVector< int > newFaceIndices;
  551. const int nFaceSets = pMesh->FaceSetCount();
  552. for ( int i = 0; i < nFaceSets; ++i )
  553. {
  554. CDmeFaceSet *pSrcFaceSet = pMesh->GetFaceSet( i );
  555. const int nFaceSetIndices = pSrcFaceSet->NumIndices();
  556. if ( nFaceSetIndices <= 0 )
  557. continue;
  558. CDmeFaceSet *pDstFaceSet = pSrcFaceSet;
  559. // See if a new face set needs to be created
  560. CDmeMaterial *pSrcMaterial = pSrcFaceSet->GetMaterial();
  561. const char *pSrcMaterialName = pSrcMaterial->GetMaterialName();
  562. const int nNameLen = Q_strlen( pSrcMaterialName );
  563. if ( nNameLen >= 2 )
  564. {
  565. CUtlString materialName;
  566. if ( !Q_stricmp( pSrcMaterialName + nNameLen - 2, "_l" ) )
  567. {
  568. materialName = pSrcMaterialName;
  569. materialName.SetLength( nNameLen - 2 );
  570. materialName += "_r";
  571. }
  572. else if ( !Q_stricmp( pSrcMaterialName + nNameLen - 2, "_r" ) )
  573. {
  574. materialName = pSrcMaterialName;
  575. materialName.SetLength( nNameLen - 2 );
  576. materialName += "_l";
  577. }
  578. else if ( nNameLen >= 5 && !Q_stricmp( pSrcMaterialName + nNameLen - 5, "_left" ) )
  579. {
  580. materialName = pSrcMaterialName;
  581. materialName.SetLength( nNameLen - 5 );
  582. materialName += "_right";
  583. }
  584. else if ( nNameLen >= 6 && !Q_stricmp( pSrcMaterialName + nNameLen - 6, "_right" ) )
  585. {
  586. materialName = pSrcMaterialName;
  587. materialName.SetLength( nNameLen - 6 );
  588. materialName += "_left";
  589. }
  590. if ( materialName.Length() )
  591. {
  592. pDstFaceSet = CreateElement< CDmeFaceSet >( materialName, pMesh->GetFileId() );
  593. CDmeMaterial *pDstMaterial = CreateElement< CDmeMaterial >( materialName, pDstFaceSet->GetFileId() );
  594. pDstMaterial->SetMaterial( materialName );
  595. pDstFaceSet->SetMaterial( pDstMaterial );
  596. pMesh->AddFaceSet( pDstFaceSet );
  597. }
  598. }
  599. faceStart = 0;
  600. for ( int j = 0; j < nFaceSetIndices; ++j )
  601. {
  602. vertexIndex = pSrcFaceSet->GetIndex( j );
  603. if ( vertexIndex < 0 )
  604. {
  605. newFaceIndices.RemoveAll();
  606. for ( int k = j - 1; k >= faceStart; --k )
  607. {
  608. newFaceIndices.AddToTail( mirrorMap[ pSrcFaceSet->GetIndex( k ) ] );
  609. }
  610. newFaceIndices.AddToTail( -1 );
  611. const int oldNumIndices = pDstFaceSet->NumIndices();
  612. pDstFaceSet->AddIndices( newFaceIndices.Count() );
  613. pDstFaceSet->SetIndices( oldNumIndices, newFaceIndices.Count(), newFaceIndices.Base() );
  614. // End of face
  615. faceStart = j + 1;
  616. continue;
  617. }
  618. }
  619. }
  620. return true;
  621. }
  622. //-----------------------------------------------------------------------------
  623. // Initializes the CUtlVector to a linear ramp where utlVector[ i ] == i
  624. //-----------------------------------------------------------------------------
  625. template < typename T_t >
  626. void RampInit( CUtlVector< T_t > &utlVector, const int nCount )
  627. {
  628. utlVector.SetCount( nCount );
  629. for ( int i = 0; i < nCount; ++i )
  630. {
  631. utlVector[ i ] = i;
  632. }
  633. }
  634. //-----------------------------------------------------------------------------
  635. // Build Data Mirror Map
  636. // Returns a pointer to the memory holding the indices for the map or NULL
  637. //-----------------------------------------------------------------------------
  638. const int *CDmMeshUtils::BuildDataMirrorMap( CDmeVertexData *pBase, int axis, CDmeVertexData::StandardFields_t standardField, CUtlVector< int > &dataMirrorMap )
  639. {
  640. const FieldIndex_t fieldIndex = pBase->FindFieldIndex( standardField );
  641. if ( fieldIndex < 0 )
  642. return NULL;
  643. const CUtlVector< int > &indices( CDmrArrayConst< int >( pBase->GetIndexData( fieldIndex ) ).Get() );
  644. CDmAttribute *pData = pBase->GetVertexData( fieldIndex );
  645. if ( standardField == CDmeVertexData::FIELD_POSITION || standardField == CDmeVertexData::FIELD_NORMAL )
  646. {
  647. const Vector mirrorOrigin( 0.0f, 0.0f, 0.0f );
  648. const float mirrorAxisVal = mirrorOrigin[ axis ];
  649. CDmrArray< Vector > data( pBase->GetVertexData( fieldIndex ) );
  650. Vector v;
  651. const int nDataCount = data.Count();
  652. dataMirrorMap.SetCount( nDataCount );
  653. int nMirrorDataCount = nDataCount;
  654. for ( int i = 0; i < nDataCount; ++i )
  655. {
  656. if ( fabs( data[ i ][ axis ] - mirrorAxisVal ) > FLT_EPSILON * 1000.0f )
  657. {
  658. dataMirrorMap[ i ] = nMirrorDataCount++;
  659. }
  660. else
  661. {
  662. dataMirrorMap[ i ] = i;
  663. v = data[ i ];
  664. v[ axis ] = mirrorOrigin[ axis ];
  665. data.Set( i, v );
  666. }
  667. }
  668. }
  669. else if ( standardField == CDmeVertexData::FIELD_TEXCOORD )
  670. {
  671. const Vector2D mirrorOrigin( 0.5f, 0.5f );
  672. const float mirrorAxisVal = mirrorOrigin[ axis % 2 ];
  673. const CUtlVector< Vector2D > &data( CDmrArrayConst< Vector2D >( pBase->GetVertexData( fieldIndex ) ).Get() );
  674. const int nDataCount = data.Count();
  675. dataMirrorMap.SetCount( nDataCount );
  676. int nMirrorDataCount = nDataCount;
  677. for ( int i = 0; i < nDataCount; ++i )
  678. {
  679. if ( fabs( data[ i ][ axis ] - mirrorAxisVal ) > FLT_EPSILON * 1000.0f )
  680. {
  681. dataMirrorMap[ i ] = nMirrorDataCount++;
  682. }
  683. else
  684. {
  685. dataMirrorMap[ i ] = i;
  686. }
  687. }
  688. }
  689. else
  690. {
  691. RampInit( dataMirrorMap, CDmrGenericArrayConst( pData ).Count() );
  692. }
  693. return indices.Base();
  694. }
  695. //-----------------------------------------------------------------------------
  696. // y = mirrorMap[ x ] means that if y < 0 then original position x is not
  697. // mirrored. Otherwise y is the index into the vertex indices of the mirrored
  698. // version of vertex
  699. //-----------------------------------------------------------------------------
  700. bool CDmMeshUtils::MirrorVertices( CDmeMesh *pMesh, CDmeVertexData *pBase, int axis, CUtlVector< int > &mirrorMap )
  701. {
  702. mirrorMap.RemoveAll();
  703. if ( !pMesh || !pBase || axis < kXAxis || axis > kZAxis )
  704. return false;
  705. const int posIndex = pBase->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  706. if ( posIndex < 0 )
  707. return false;
  708. const CUtlVector< int > &posIndices( CDmrArrayConst< int >( pBase->GetIndexData( posIndex ) ).Get() );
  709. const int nIndices = posIndices.Count();
  710. Assert( nIndices == pBase->VertexCount() );
  711. CUtlVector< int > posMirrorMap;
  712. if ( !BuildDataMirrorMap( pBase, axis, CDmeVertexData::FIELD_POSITION, posMirrorMap ) )
  713. return false;
  714. CUtlVector< int > normalMirrorMap;
  715. const int *pNormalIndices = BuildDataMirrorMap( pBase, axis, CDmeVertexData::FIELD_NORMAL, normalMirrorMap );
  716. CUtlVector< int > uvMirrorMap;
  717. const int *pUVIndices = BuildDataMirrorMap( pBase, axis, CDmeVertexData::FIELD_TEXCOORD, uvMirrorMap );
  718. RampInit( mirrorMap, nIndices );
  719. int mirrorCount = 0;
  720. {
  721. bool mirror;
  722. Vector tmpVec;
  723. Vector2D tmpVec2D;
  724. for ( int i = 0; i < nIndices; ++i )
  725. {
  726. mirror = false;
  727. if ( posMirrorMap[ posIndices[ i ] ] != posIndices[ i ] )
  728. {
  729. mirror = true;
  730. }
  731. if ( pNormalIndices && normalMirrorMap[ pNormalIndices[ i ] ] != pNormalIndices[ i ] )
  732. {
  733. mirror = true;
  734. }
  735. if ( pUVIndices && uvMirrorMap[ pUVIndices[ i ] ] != pUVIndices[ i ] )
  736. {
  737. mirror = true;
  738. }
  739. if ( mirror )
  740. {
  741. mirrorMap[ i ] = nIndices + mirrorCount;
  742. ++mirrorCount;
  743. }
  744. }
  745. }
  746. const int nBaseState = pMesh->BaseStateCount();
  747. for ( int i = 0; i < nBaseState; ++i )
  748. {
  749. CDmeVertexData *pBase = pMesh->GetBaseState( i );
  750. const int nVertexCount = pBase->VertexCount();
  751. MirrorVertices( pBase, axis, nVertexCount, mirrorCount, mirrorMap, posMirrorMap, normalMirrorMap, uvMirrorMap );
  752. }
  753. const int nDeltaState = pMesh->DeltaStateCount();
  754. for ( int i = 0; i < nDeltaState; ++i )
  755. {
  756. CDmeVertexDeltaData *pDelta = pMesh->GetDeltaState( i );
  757. MirrorDelta( pDelta, axis, posMirrorMap, normalMirrorMap, uvMirrorMap );
  758. }
  759. return true;
  760. }
  761. //-----------------------------------------------------------------------------
  762. //
  763. //-----------------------------------------------------------------------------
  764. inline void MirrorData( Vector &d, const int &axis )
  765. {
  766. d[ axis ] *= -1.0f;
  767. }
  768. //-----------------------------------------------------------------------------
  769. //
  770. //-----------------------------------------------------------------------------
  771. inline void MirrorData( Vector2D &d, const int &axis )
  772. {
  773. d[ axis ] = ( d[ axis ] - 0.5f ) * -1.0f + 0.5f;
  774. }
  775. //-----------------------------------------------------------------------------
  776. // Mirror 3D things like positions & normals
  777. //-----------------------------------------------------------------------------
  778. template < class T_t >
  779. void MirrorVertexData(
  780. CDmeVertexData *pBase,
  781. FieldIndex_t fieldIndex,
  782. int axis,
  783. int nOrigVertexCount,
  784. int nMirrorCount,
  785. const CDmrArrayConst< T_t > &origData,
  786. const CUtlVector< int > &origIndices,
  787. const CUtlVector< int > &mirrorMap,
  788. const CUtlVector< int > &dataMirrorMap )
  789. {
  790. if ( nMirrorCount <= 0 )
  791. return;
  792. Assert( origIndices.Count() == nOrigVertexCount + nMirrorCount );
  793. Assert( mirrorMap.Count() == nOrigVertexCount );
  794. Assert( dataMirrorMap.Count() == origData.Count() );
  795. const int nData = origData.Count();
  796. T_t *pMirrorData = reinterpret_cast< T_t * >( alloca( nMirrorCount * sizeof( T_t ) ) );
  797. int *pMirrorIndices = reinterpret_cast< int * >( alloca( nMirrorCount * sizeof( int ) ) );
  798. T_t mirrorData;
  799. int nMirrorIndex = 0;
  800. int nMirrorDataCount = -1;
  801. for ( int i = 0; i < nOrigVertexCount; ++i )
  802. {
  803. if ( mirrorMap[ i ] != i )
  804. {
  805. // Vertex must be mirrored
  806. if ( dataMirrorMap[ origIndices[ i ] ] != origIndices[ i ] )
  807. {
  808. // Data referred to by vertex i must be mirror (this may be done a redundant number of times)
  809. const T_t &origData( origData[ origIndices[ i ] ] );
  810. mirrorData = origData;
  811. MirrorData( mirrorData, axis );
  812. pMirrorData[ dataMirrorMap[ origIndices[ i ] ] - nData ] = mirrorData;
  813. if ( ( dataMirrorMap[ origIndices[ i ] ] - nData ) > nMirrorDataCount )
  814. {
  815. nMirrorDataCount = dataMirrorMap[ origIndices[ i ] ] - nData;
  816. }
  817. pMirrorIndices[ nMirrorIndex ] = dataMirrorMap[ origIndices[ i ] ];
  818. }
  819. else
  820. {
  821. // The data does not need to be mirrored
  822. pMirrorIndices[ nMirrorIndex ] = origIndices[ i ];
  823. }
  824. ++nMirrorIndex;
  825. }
  826. else
  827. {
  828. Assert( dataMirrorMap[ origIndices[ i ] ] == origIndices[ i ] );
  829. }
  830. }
  831. ++nMirrorDataCount;
  832. Assert( nMirrorCount == nMirrorIndex );
  833. Assert( nMirrorDataCount <= nMirrorCount );
  834. const DmAttributeType_t dmAttributeType = ArrayTypeToValueType( origData.GetAttribute()->GetType() );
  835. pBase->AddVertexData( fieldIndex, nMirrorDataCount );
  836. pBase->SetVertexData( fieldIndex, nData, nMirrorDataCount, dmAttributeType, pMirrorData );
  837. pBase->SetVertexIndices( fieldIndex, nOrigVertexCount, nMirrorCount, pMirrorIndices );
  838. }
  839. //-----------------------------------------------------------------------------
  840. //
  841. //-----------------------------------------------------------------------------
  842. bool CDmMeshUtils::MirrorVertices(
  843. CDmeVertexData *pBase,
  844. int axis,
  845. int nOldVertexCount,
  846. int nMirrorCount,
  847. const CUtlVector< int > &mirrorMap,
  848. const CUtlVector< int > &posMirrorMap,
  849. const CUtlVector< int > &normalMirrorMap,
  850. const CUtlVector< int > &uvMirrorMap )
  851. {
  852. if ( !pBase || axis < kXAxis || axis > kZAxis )
  853. return false;
  854. pBase->AddVertexIndices( nMirrorCount );
  855. const int posFieldIndex = pBase->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  856. const int normalFieldIndex = pBase->FindFieldIndex( CDmeVertexData::FIELD_NORMAL );
  857. const int uvFieldIndex = pBase->FindFieldIndex( CDmeVertexData::FIELD_TEXCOORD );
  858. const int nFields = pBase->FieldCount();
  859. for ( int i = 0; i < nFields; ++i )
  860. {
  861. CDmAttribute *pBaseData( pBase->GetVertexData( i ) );
  862. const CUtlVector< int > &baseIndices( pBase->GetVertexIndexData( i ) );
  863. Assert( baseIndices.Count() == nOldVertexCount + nMirrorCount );
  864. Assert( mirrorMap.Count() == nOldVertexCount );
  865. switch ( pBaseData->GetType() )
  866. {
  867. case AT_VECTOR2_ARRAY:
  868. if ( i == uvFieldIndex )
  869. {
  870. MirrorVertexData( pBase, i, axis % 2, nOldVertexCount, nMirrorCount, CDmrArrayConst< Vector2D >( pBaseData ), baseIndices, mirrorMap, uvMirrorMap );
  871. continue;
  872. }
  873. break;
  874. case AT_VECTOR3_ARRAY:
  875. if ( i == posFieldIndex )
  876. {
  877. MirrorVertexData( pBase, i, axis, nOldVertexCount, nMirrorCount, CDmrArrayConst< Vector >( pBaseData ), baseIndices, mirrorMap, posMirrorMap );
  878. continue;
  879. }
  880. else if ( i == normalFieldIndex )
  881. {
  882. MirrorVertexData( pBase, i, axis, nOldVertexCount, nMirrorCount, CDmrArrayConst< Vector >( pBaseData ), baseIndices, mirrorMap, normalMirrorMap );
  883. continue;
  884. }
  885. break;
  886. default:
  887. break;
  888. }
  889. MirrorVertices( pBase, i, nOldVertexCount, nMirrorCount, baseIndices, mirrorMap );
  890. }
  891. return true;
  892. }
  893. //-----------------------------------------------------------------------------
  894. // This does the default case of mirroring which is no mirroring at all!
  895. // No data is changed, the extra indices are added to the index
  896. //-----------------------------------------------------------------------------
  897. void CDmMeshUtils::MirrorVertices(
  898. CDmeVertexData *pBase,
  899. FieldIndex_t fieldIndex,
  900. int nOldVertexCount,
  901. int nMirrorCount,
  902. const CUtlVector< int > &baseIndices,
  903. const CUtlVector< int > &mirrorMap )
  904. {
  905. if ( nMirrorCount <= 0 )
  906. return;
  907. Assert( baseIndices.Count() == nOldVertexCount + nMirrorCount );
  908. Assert( mirrorMap.Count() == nOldVertexCount );
  909. int *pIndices = reinterpret_cast< int * >( alloca( nMirrorCount * sizeof( int ) ) );
  910. {
  911. int pIndex = 0;
  912. for ( int i = 0; i < nOldVertexCount; ++i )
  913. {
  914. if ( mirrorMap[ i ] != i )
  915. {
  916. pIndices[ pIndex ] = baseIndices[ mirrorMap[ i ] - nOldVertexCount ];
  917. ++pIndex;
  918. }
  919. }
  920. Assert( pIndex == nMirrorCount );
  921. }
  922. pBase->SetVertexIndices( fieldIndex, nOldVertexCount, nMirrorCount, pIndices );
  923. }
  924. //-----------------------------------------------------------------------------
  925. //
  926. //-----------------------------------------------------------------------------
  927. template < class T_t >
  928. void MirrorDeltaData(
  929. CDmeVertexDeltaData *pDelta,
  930. FieldIndex_t fieldIndex,
  931. int axis,
  932. const CDmrArrayConst< T_t > &origData,
  933. const CUtlVector< int > &origIndices,
  934. const CUtlVector< int > &dataMap )
  935. {
  936. Assert( origData.Count() == origIndices.Count() );
  937. const int nOrigDataCount = origData.Count();
  938. T_t *pMirrorData = reinterpret_cast< T_t * >( alloca( nOrigDataCount * sizeof( T_t ) ) );
  939. int *pMirrorIndices = reinterpret_cast< int * >( alloca( nOrigDataCount * sizeof( int ) ) );
  940. int nMirrorDataCount = 0;
  941. for ( int i = 0; i < nOrigDataCount; ++i )
  942. {
  943. if ( dataMap[ origIndices[ i ] ] != origIndices[ i ] )
  944. {
  945. pMirrorData[ nMirrorDataCount ] = origData[ i ];
  946. MirrorData( pMirrorData[ nMirrorDataCount ], axis );
  947. pMirrorIndices[ nMirrorDataCount ] = dataMap[ origIndices[ i ] ];
  948. ++nMirrorDataCount;
  949. }
  950. }
  951. const DmAttributeType_t dmAttributeType = ArrayTypeToValueType( origData.GetAttribute()->GetType() );
  952. pDelta->AddVertexData( fieldIndex, nMirrorDataCount );
  953. pDelta->SetVertexData( fieldIndex, nOrigDataCount, nMirrorDataCount, dmAttributeType, pMirrorData );
  954. pDelta->SetVertexIndices( fieldIndex, nOrigDataCount, nMirrorDataCount, pMirrorIndices );
  955. }
  956. //-----------------------------------------------------------------------------
  957. //
  958. //-----------------------------------------------------------------------------
  959. bool CDmMeshUtils::MirrorDelta(
  960. CDmeVertexDeltaData *pDelta,
  961. int axis,
  962. const CUtlVector< int > &posMirrorMap,
  963. const CUtlVector< int > &normalMirrorMap,
  964. const CUtlVector< int > &uvMirrorMap )
  965. {
  966. if ( !pDelta || axis < kXAxis || axis > kZAxis )
  967. return false;
  968. const int posFieldIndex = pDelta->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  969. const int normalFieldIndex = pDelta->FindFieldIndex( CDmeVertexData::FIELD_NORMAL );
  970. const int uvFieldIndex = pDelta->FindFieldIndex( CDmeVertexData::FIELD_TEXCOORD );
  971. const int nFields = pDelta->FieldCount();
  972. for ( int i = 0; i < nFields; ++i )
  973. {
  974. CDmAttribute *pDeltaData( pDelta->GetVertexData( i ) );
  975. const CUtlVector< int > &deltaIndices( pDelta->GetVertexIndexData( i ) );
  976. switch ( pDeltaData->GetType() )
  977. {
  978. case AT_VECTOR2_ARRAY:
  979. if ( i == uvFieldIndex )
  980. {
  981. MirrorDeltaData( pDelta, i, axis % 2, CDmrArrayConst< Vector2D >( pDeltaData ), deltaIndices, uvMirrorMap );
  982. continue;
  983. }
  984. break;
  985. case AT_VECTOR3_ARRAY:
  986. if ( i == posFieldIndex )
  987. {
  988. MirrorDeltaData( pDelta, i, axis, CDmrArrayConst< Vector >( pDeltaData ), deltaIndices, posMirrorMap );
  989. continue;
  990. }
  991. else if ( i == normalFieldIndex )
  992. {
  993. MirrorDeltaData( pDelta, i, axis, CDmrArrayConst< Vector >( pDeltaData ), deltaIndices, normalMirrorMap );
  994. continue;
  995. }
  996. break;
  997. default:
  998. break;
  999. }
  1000. }
  1001. return true;
  1002. }
  1003. //-----------------------------------------------------------------------------
  1004. // Finds all materials bound to the mesh and replaces ones which match the
  1005. // source name with the destination name
  1006. //-----------------------------------------------------------------------------
  1007. bool CDmMeshUtils::RemapMaterial( CDmeMesh *pMesh, const CUtlString &src, const CUtlString &dst )
  1008. {
  1009. bool retVal = false;
  1010. char srcName[ MAX_PATH ];
  1011. char matName[ MAX_PATH ];
  1012. char dstName[ MAX_PATH ];
  1013. Q_StripExtension( src.Get(), srcName, sizeof( srcName ) );
  1014. Q_FixSlashes( srcName, '/' );
  1015. Q_strncpy( dstName, dst.Get(), sizeof( dstName ) );
  1016. Q_FixSlashes( dstName, '/' );
  1017. const int nFaceSets = pMesh->FaceSetCount();
  1018. for ( int i = 0; i < nFaceSets; ++i )
  1019. {
  1020. CDmeFaceSet *pFaceSet = pMesh->GetFaceSet( i );
  1021. if ( !pFaceSet )
  1022. continue;
  1023. CDmeMaterial *pMaterial = pFaceSet->GetMaterial();
  1024. if ( !pMaterial )
  1025. continue;
  1026. const char *pMaterialName = pMaterial->GetMaterialName();
  1027. Q_StripExtension( pMaterialName, matName, sizeof( matName ) );
  1028. Q_FixSlashes( matName, '/' );
  1029. // TODO: Regular expressions or at least glob style matching would be cool
  1030. if ( !Q_stricmp( srcName, matName ) )
  1031. {
  1032. pMaterial->SetMaterial( dstName );
  1033. pMaterial->SetName( dstName );
  1034. retVal = true;
  1035. }
  1036. }
  1037. return retVal;
  1038. }
  1039. //-----------------------------------------------------------------------------
  1040. // Replaces the nth material found with the specified material name
  1041. //-----------------------------------------------------------------------------
  1042. bool CDmMeshUtils::RemapMaterial( CDmeMesh *pMesh, const int nMaterialIndex, const CUtlString &dst )
  1043. {
  1044. const int nFaceSets = pMesh->FaceSetCount();
  1045. if ( nMaterialIndex >= nFaceSets )
  1046. return false;
  1047. CDmeFaceSet *pFaceSet = pMesh->GetFaceSet( nMaterialIndex );
  1048. if ( !pFaceSet )
  1049. return false;
  1050. CDmeMaterial *pMaterial = pFaceSet->GetMaterial();
  1051. if ( !pMaterial )
  1052. return false;
  1053. pMaterial->SetMaterial( dst );
  1054. pMaterial->SetName( dst );
  1055. return true;
  1056. }
  1057. //-----------------------------------------------------------------------------
  1058. // Finds the "socket" on which to base the mesh merge
  1059. // This is defined as the vertices along the two meshes
  1060. // Returns the index into srcBorderEdgesList of the edge list that is found
  1061. // -1 if not found
  1062. //-----------------------------------------------------------------------------
  1063. int CDmMeshUtils::FindMergeSocket(
  1064. const CUtlVector< CUtlVector< CDmMeshComp::CEdge * > > &srcBorderEdgesList,
  1065. CDmeMesh *pDstMesh )
  1066. {
  1067. CDmMeshComp dstComp( pDstMesh );
  1068. const CUtlVector< CDmMeshComp::CEdge * > &edgeList = dstComp.m_edges;
  1069. for ( int i = srcBorderEdgesList.Count() - 1; i >= 0; --i )
  1070. {
  1071. const CUtlVector< CDmMeshComp::CEdge * > &srcBorderEdges = srcBorderEdgesList[ i ];
  1072. int nEdgeMatch = 0;
  1073. for ( int j = 0; j != edgeList.Count(); j++ )
  1074. {
  1075. const CDmMeshComp::CEdge &e = *edgeList[ j ];
  1076. for ( int k = srcBorderEdges.Count() - 1; k >= 0; --k )
  1077. {
  1078. if ( e == *srcBorderEdges[ k ] )
  1079. {
  1080. ++nEdgeMatch;
  1081. break;
  1082. }
  1083. }
  1084. }
  1085. if ( nEdgeMatch == srcBorderEdges.Count() )
  1086. {
  1087. return i;
  1088. }
  1089. }
  1090. return -1;
  1091. }
  1092. //-----------------------------------------------------------------------------
  1093. // Merge by finding the two meshes in the scene which are joined at a socket
  1094. // A socket being defined as a group of border edges that match exactly
  1095. // between two meshes
  1096. //-----------------------------------------------------------------------------
  1097. bool CDmMeshUtils::Merge( CDmeMesh *pSrcMesh, CDmElement *pRoot )
  1098. {
  1099. CDmMeshComp srcComp( pSrcMesh );
  1100. CUtlVector< CUtlVector< CDmMeshComp::CEdge * > > srcBorderEdgesList;
  1101. if ( srcComp.GetBorderEdges( srcBorderEdgesList ) == 0 )
  1102. return false;
  1103. CDmeMesh *pDstMesh = NULL;
  1104. // Find each mesh under pRoot
  1105. CDmeDag *pModel = pRoot->GetValueElement< CDmeDag >( "model" );
  1106. if ( !pModel )
  1107. return false;
  1108. CUtlStack< CDmeDag * > traverseStack;
  1109. traverseStack.Push( pModel );
  1110. CDmeDag *pDag;
  1111. CDmeMesh *pMesh;
  1112. Vector srcCenter;
  1113. float srcRadius;
  1114. Vector dstCenter;
  1115. float dstRadius;
  1116. float sqDist = FLT_MAX;
  1117. pSrcMesh->GetBoundingSphere( srcCenter, srcRadius );
  1118. int nEdgeListIndex = -1;
  1119. while ( traverseStack.Count() )
  1120. {
  1121. traverseStack.Pop( pDag );
  1122. if ( !pDag )
  1123. continue;
  1124. // Push all children onto stack in reverse order
  1125. for ( int nChildIndex = pDag->GetChildCount() - 1; nChildIndex >= 0; --nChildIndex )
  1126. {
  1127. traverseStack.Push( pDag->GetChild( nChildIndex ) );
  1128. }
  1129. // See if there's a mesh associated with this dag
  1130. pMesh = CastElement< CDmeMesh >( pDag->GetShape() );
  1131. if ( !pMesh )
  1132. continue;
  1133. int eli = FindMergeSocket( srcBorderEdgesList, pMesh );
  1134. if ( eli < 0 )
  1135. continue;
  1136. pMesh->GetBoundingSphere( dstCenter, dstRadius );
  1137. dstRadius = dstCenter.DistToSqr( srcCenter );
  1138. if ( dstRadius < sqDist )
  1139. {
  1140. sqDist = dstRadius;
  1141. pDstMesh = pMesh;
  1142. nEdgeListIndex = eli;
  1143. }
  1144. }
  1145. if ( pDstMesh )
  1146. {
  1147. return Merge( srcComp, srcBorderEdgesList[ nEdgeListIndex ], pDstMesh );
  1148. }
  1149. Msg( "Error: Merge() - No Merge Socket Found - i.e. A Set Of Border Edges On The Source Model That Are Found On The Merge Model" );
  1150. return false;
  1151. }
  1152. //-----------------------------------------------------------------------------
  1153. //
  1154. //-----------------------------------------------------------------------------
  1155. template < class T_t >
  1156. void AppendData(
  1157. const CDmrArrayConst< T_t > &srcData,
  1158. CDmrArray< T_t > &dstData,
  1159. const matrix3x4_t *pMat = NULL )
  1160. {
  1161. const int nSrcCount = srcData.Count();
  1162. const int nDstCount = dstData.Count();
  1163. dstData.AddMultipleToTail( nSrcCount );
  1164. dstData.SetMultiple( nDstCount, nSrcCount, srcData.Base() );
  1165. }
  1166. //-----------------------------------------------------------------------------
  1167. //
  1168. //-----------------------------------------------------------------------------
  1169. template <>
  1170. void AppendData(
  1171. const CDmrArrayConst< Vector > &srcData,
  1172. CDmrArray< Vector > &dstData,
  1173. const matrix3x4_t *pMat )
  1174. {
  1175. const int nSrcCount = srcData.Count();
  1176. const int nDstCount = dstData.Count();
  1177. dstData.AddMultipleToTail( nSrcCount );
  1178. if ( pMat )
  1179. {
  1180. Vector v;
  1181. for ( int i = 0; i < nSrcCount; ++i )
  1182. {
  1183. v = srcData.Get( i );
  1184. VectorTransform( srcData.Get( i ), *pMat, v );
  1185. dstData.Set( nDstCount + i, v );
  1186. }
  1187. }
  1188. else
  1189. {
  1190. dstData.SetMultiple( nDstCount, nSrcCount, srcData.Base() );
  1191. }
  1192. }
  1193. //-----------------------------------------------------------------------------
  1194. //
  1195. //-----------------------------------------------------------------------------
  1196. static void MergeJointData(
  1197. CDmeVertexData *pDstBase,
  1198. CDmeVertexData *pSrcBase,
  1199. const CUtlMap< int, int > &jointMap )
  1200. {
  1201. if ( !pSrcBase || !pDstBase )
  1202. return;
  1203. const int nSrcPositionIndex = pSrcBase->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  1204. const int nSrcJointWeightsIndex = pSrcBase->FindFieldIndex( CDmeVertexData::FIELD_JOINT_WEIGHTS );
  1205. const int nSrcJointIndicesIndex = pSrcBase->FindFieldIndex( CDmeVertexData::FIELD_JOINT_INDICES );
  1206. const int nDstJointWeightsIndex = pDstBase->FindFieldIndex( CDmeVertexData::FIELD_JOINT_WEIGHTS );
  1207. const int nDstJointIndicesIndex = pDstBase->FindFieldIndex( CDmeVertexData::FIELD_JOINT_INDICES );
  1208. if ( nSrcPositionIndex < 0 || nSrcJointWeightsIndex < 0 || nSrcJointIndicesIndex < 0 || nDstJointWeightsIndex < 0 || nDstJointIndicesIndex < 0 )
  1209. return;
  1210. const int nSrcJointCount = pSrcBase->JointCount();
  1211. const int nDstJointCount = pDstBase->JointCount();
  1212. if ( nSrcJointCount <= 0 || nDstJointCount <= 0 )
  1213. return;
  1214. const int nSrcPosCount = CDmrGenericArray( pSrcBase->GetVertexData( nSrcPositionIndex ) ).Count();
  1215. const CDmrArrayConst< float > srcWeights( pSrcBase->GetVertexData( nSrcJointWeightsIndex ) );
  1216. const CDmrArrayConst< int > srcIndices( pSrcBase->GetVertexData( nSrcJointIndicesIndex ) );
  1217. CDmrArray< float > dstWeights( pDstBase->GetVertexData( nDstJointWeightsIndex ) );
  1218. CDmrArray< int > dstIndices( pDstBase->GetVertexData( nDstJointIndicesIndex ) );
  1219. int nDstIndex = dstWeights.Count();
  1220. int nSrcIndex = 0;
  1221. dstWeights.AddMultipleToTail( nSrcPosCount * nDstJointCount );
  1222. dstIndices.AddMultipleToTail( nSrcPosCount * nDstJointCount );
  1223. while ( nDstIndex < dstWeights.Count() )
  1224. {
  1225. float flTotalWeight = 0.0f;
  1226. for ( int i = 0; i < nDstJointCount; ++i )
  1227. {
  1228. if ( i < nSrcJointCount )
  1229. {
  1230. Assert( nSrcIndex < srcWeights.Count() );
  1231. const CUtlMap< int, int >::IndexType_t nJointMapIndex = jointMap.Find( srcIndices[ nSrcIndex ] );
  1232. if ( jointMap.IsValidIndex( nJointMapIndex ) )
  1233. {
  1234. dstWeights.Set( nDstIndex, srcWeights[ nSrcIndex ] );
  1235. dstIndices.Set( nDstIndex, jointMap.Element( nJointMapIndex ) );
  1236. flTotalWeight += dstWeights[ nDstIndex ];
  1237. }
  1238. else
  1239. {
  1240. Warning( "Can't Joint Index %d On Src Isn't Mapped To Dst\n", srcIndices[ nSrcIndex ] );
  1241. dstWeights.Set( nDstIndex, 0.0f );
  1242. dstIndices.Set( nDstIndex, -1 );
  1243. }
  1244. ++nSrcIndex;
  1245. }
  1246. else
  1247. {
  1248. dstWeights.Set( nDstIndex, 0.0f );
  1249. dstIndices.Set( nDstIndex, -1 );
  1250. }
  1251. ++nDstIndex;
  1252. }
  1253. // Renormalize if weight didn't equal 1
  1254. if ( flTotalWeight > 0.0f && FloatMakePositive( flTotalWeight - 1.0f ) > FLT_EPSILON * 100.0 )
  1255. {
  1256. for ( int i = nDstIndex - nDstJointCount; i < nDstIndex; ++i )
  1257. {
  1258. dstWeights.Set( i, dstWeights.Element( i ) / flTotalWeight );
  1259. }
  1260. }
  1261. }
  1262. }
  1263. //-----------------------------------------------------------------------------
  1264. // Merge data from a base state on one DmeMesh into another DmeMesh
  1265. // Preserve positions and normals by transforming them with the
  1266. // positionMatrix & normalMatrix
  1267. //
  1268. // Return the number of new vertices in the mesh
  1269. //-----------------------------------------------------------------------------
  1270. int MergeBaseState(
  1271. CDmeVertexData *pSrcBase,
  1272. CDmeVertexData *pDstBase,
  1273. const matrix3x4_t &pMat,
  1274. const matrix3x4_t &nMat,
  1275. int nSkinningJointIndex,
  1276. int &nPositionOffset,
  1277. int &nNormalOffset,
  1278. int &nWrinkleOffset,
  1279. CUtlMap< int, int > *pSkinMap /* = NULL */ )
  1280. {
  1281. int nRetVal = -1;
  1282. const int nSrcPositionIndex = pSrcBase->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  1283. const int nSrcNormalIndex = pSrcBase->FindFieldIndex( CDmeVertexData::FIELD_NORMAL );
  1284. const int nSrcWrinkleIndex = pSrcBase->FindFieldIndex( CDmeVertexData::FIELD_WRINKLE );
  1285. const int nSrcJointWeightsIndex = pSrcBase->FindFieldIndex( CDmeVertexData::FIELD_JOINT_WEIGHTS );
  1286. const int nSrcJointIndicesIndex = pSrcBase->FindFieldIndex( CDmeVertexData::FIELD_JOINT_INDICES );
  1287. const int nDstJointWeightsIndex = pDstBase->FindFieldIndex( CDmeVertexData::FIELD_JOINT_WEIGHTS );
  1288. const int nDstJointIndicesIndex = pDstBase->FindFieldIndex( CDmeVertexData::FIELD_JOINT_INDICES );
  1289. // Handle skinning the new mesh data to a single joint if the destination mesh
  1290. // is already skinned. If the destination mesh is skinned but there is no
  1291. // specific joint specified to skin to, the first joint is used and a warning issued
  1292. if ( nDstJointWeightsIndex >= 0 && nDstJointIndicesIndex >= 0 )
  1293. {
  1294. if ( pSkinMap && nSrcJointWeightsIndex >= 0 && nSrcJointIndicesIndex >= 0 )
  1295. {
  1296. MergeJointData( pDstBase, pSrcBase, *pSkinMap );
  1297. }
  1298. else
  1299. {
  1300. if ( nSkinningJointIndex < 0 )
  1301. {
  1302. Msg( "Warning: Destination mesh is skinned but no valid joint specified to skin to, using first joint\n" );
  1303. nSkinningJointIndex = 0;
  1304. }
  1305. const int nJointCount = pDstBase->JointCount();
  1306. CDmrGenericArray srcPos( pSrcBase->GetVertexData( nSrcPositionIndex ) );
  1307. const int nSrcPosCount = srcPos.Count();
  1308. CDmrArray< float > dstWeights( pDstBase->GetVertexData( nDstJointWeightsIndex ) );
  1309. CDmrArray< int > dstIndices( pDstBase->GetVertexData( nDstJointIndicesIndex ) );
  1310. const int nDstCount = dstWeights.Count();
  1311. Assert( nDstCount == dstIndices.Count() );
  1312. dstWeights.AddMultipleToTail( nSrcPosCount * nJointCount );
  1313. dstIndices.AddMultipleToTail( nSrcPosCount * nJointCount );
  1314. // Since there can be more than 1 joint per vertex, specify 1
  1315. // for the first joint and 0 for the rest but use the same joint
  1316. const int nEnd = nDstCount + nSrcPosCount * nJointCount;
  1317. for ( int i = nDstCount; i < nEnd; i += nJointCount )
  1318. {
  1319. dstWeights.Set( i, 1.0f );
  1320. dstIndices.Set( i, nSkinningJointIndex );
  1321. }
  1322. for ( int i = 1; i < nJointCount; ++i )
  1323. {
  1324. for ( int j = nDstCount + i; j < nEnd; j += nJointCount )
  1325. {
  1326. dstWeights.Set( j, 0.0f );
  1327. dstIndices.Set( j, nSkinningJointIndex );
  1328. }
  1329. }
  1330. }
  1331. }
  1332. // Handling merging all fields that match
  1333. int nIndexPadCount = -1;
  1334. for ( int i = 0; i < pSrcBase->FieldCount(); ++i )
  1335. {
  1336. bool bMerged = false;
  1337. for ( int j = 0; j < pDstBase->FieldCount(); ++j )
  1338. {
  1339. if ( V_strcmp( pSrcBase->FieldName( i ), pDstBase->FieldName( j ) ) )
  1340. continue;
  1341. bMerged = true;
  1342. if ( i == nSrcJointWeightsIndex || i == nSrcJointIndicesIndex )
  1343. continue;
  1344. CDmAttribute *pSrcData = pSrcBase->GetVertexData( i );
  1345. CDmAttribute *pDstData = pDstBase->GetVertexData( j );
  1346. const int nOffset = CDmrGenericArray( pDstData ).Count();
  1347. switch ( pSrcData->GetType() )
  1348. {
  1349. case AT_FLOAT_ARRAY:
  1350. AppendData( CDmrArrayConst< float >( pSrcData ), CDmrArray< float >( pDstData ) );
  1351. break;
  1352. case AT_VECTOR2_ARRAY:
  1353. AppendData( CDmrArrayConst< Vector2D >( pSrcData ), CDmrArray< Vector2D >( pDstData ) );
  1354. break;
  1355. case AT_VECTOR3_ARRAY:
  1356. if ( i == nSrcPositionIndex )
  1357. {
  1358. AppendData( CDmrArrayConst< Vector >( pSrcData ), CDmrArray< Vector >( pDstData ), &pMat );
  1359. }
  1360. else if ( i == nSrcNormalIndex )
  1361. {
  1362. AppendData( CDmrArrayConst< Vector >( pSrcData ), CDmrArray< Vector >( pDstData ), &nMat );
  1363. }
  1364. else
  1365. {
  1366. AppendData( CDmrArrayConst< Vector >( pSrcData ), CDmrArray< Vector >( pDstData ) );
  1367. }
  1368. break;
  1369. case AT_VECTOR4_ARRAY:
  1370. AppendData( CDmrArrayConst< Vector4D >( pSrcData ), CDmrArray< Vector4D >( pDstData ) );
  1371. break;
  1372. case AT_QUATERNION_ARRAY:
  1373. AppendData( CDmrArrayConst< Quaternion >( pSrcData ), CDmrArray< Quaternion >( pDstData ) );
  1374. break;
  1375. case AT_COLOR_ARRAY:
  1376. AppendData( CDmrArrayConst< Color >( pSrcData ), CDmrArray< Color >( pDstData ) );
  1377. break;
  1378. default:
  1379. Assert( 0 );
  1380. break;
  1381. }
  1382. CDmrArray< int > srcIndices( pSrcBase->GetIndexData( i ) );
  1383. CDmrArray< int > dstIndices( pDstBase->GetIndexData( j ) );
  1384. const int nSrcIndexCount = srcIndices.Count();
  1385. const int nDstIndexCount = dstIndices.Count();
  1386. if ( nRetVal < 0 )
  1387. {
  1388. nRetVal = nDstIndexCount;
  1389. }
  1390. Assert( nRetVal == nDstIndexCount );
  1391. dstIndices.AddMultipleToTail( nSrcIndexCount );
  1392. if ( nIndexPadCount < 0 )
  1393. {
  1394. nIndexPadCount = nSrcIndexCount;
  1395. }
  1396. Assert( nIndexPadCount == nSrcIndexCount );
  1397. for ( int k = 0; k < nSrcIndexCount; ++k )
  1398. {
  1399. dstIndices.Set( nDstIndexCount + k, srcIndices.Get( k ) + nOffset );
  1400. }
  1401. if ( i == nSrcPositionIndex )
  1402. {
  1403. nPositionOffset = nOffset;
  1404. }
  1405. else if ( i == nSrcNormalIndex )
  1406. {
  1407. nNormalOffset = nOffset;
  1408. }
  1409. else if ( i == nSrcWrinkleIndex )
  1410. {
  1411. nWrinkleOffset = nOffset;
  1412. }
  1413. }
  1414. if ( !bMerged )
  1415. {
  1416. Msg( "Warning: Not merging base data %s\n", pSrcBase->FieldName( i ) );
  1417. }
  1418. }
  1419. const int nDstSpeedIndex = pDstBase->FindFieldIndex( CDmeVertexData::FIELD_MORPH_SPEED );
  1420. // Handle all fields on the destination mesh that weren't on the source mesh
  1421. for ( int i = 0; i < pDstBase->FieldCount(); ++i )
  1422. {
  1423. bool bFound = false;
  1424. if ( i == nDstJointWeightsIndex || i == nDstJointIndicesIndex )
  1425. continue;
  1426. for ( int j = 0; j < pSrcBase->FieldCount(); ++j )
  1427. {
  1428. if ( Q_strcmp( pDstBase->FieldName( i ), pSrcBase->FieldName( j ) ) )
  1429. continue;
  1430. bFound = true;
  1431. break;
  1432. }
  1433. if ( !bFound )
  1434. {
  1435. int nDstIndex = -1;
  1436. if ( i == nDstSpeedIndex )
  1437. {
  1438. // Pad data with a 1
  1439. nDstIndex = CDmrArray< float >( pDstBase->GetVertexData( i ) ).AddToTail( 1.0f );
  1440. }
  1441. else
  1442. {
  1443. // Pad data with a 0
  1444. nDstIndex = CDmrGenericArray( pDstBase->GetVertexData( i ) ).AddToTail();
  1445. }
  1446. // Pad data indices with index to that extra data value
  1447. CDmrArray< int > dstIndices( pDstBase->GetIndexData( i ) );
  1448. const int nStart = dstIndices.Count();
  1449. const int nEnd = dstIndices.Count() + nIndexPadCount;
  1450. dstIndices.AddMultipleToTail( nIndexPadCount );
  1451. for ( int k = nStart; k < nEnd; ++k )
  1452. {
  1453. dstIndices.Set( k, nDstIndex );
  1454. }
  1455. }
  1456. }
  1457. pDstBase->Resolve();
  1458. return nRetVal;
  1459. }
  1460. //-----------------------------------------------------------------------------
  1461. //
  1462. //-----------------------------------------------------------------------------
  1463. void MergeDeltaState( CDmeMesh *pDmeMesh, CDmeVertexDeltaData *pSrcDelta, CDmeVertexDeltaData *pDstDelta, int &nPositionOffset, int &nNormalOffset, int &nWrinkleOffset )
  1464. {
  1465. if ( !pDstDelta )
  1466. {
  1467. // No destination delta... copy it
  1468. pDstDelta = pDmeMesh->FindOrCreateDeltaState( pSrcDelta->GetName() );
  1469. if ( !pDstDelta )
  1470. return;
  1471. }
  1472. for ( int i = 0; i < pSrcDelta->FieldCount(); ++i )
  1473. {
  1474. bool bFound = false;
  1475. for ( int j = 0; j < pDstDelta->FieldCount(); ++j )
  1476. {
  1477. if ( Q_strcmp( pSrcDelta->FieldName( i ), pDstDelta->FieldName( j ) ) )
  1478. continue;
  1479. bFound = true;
  1480. break;
  1481. }
  1482. if ( !bFound )
  1483. {
  1484. // Make an empty one, data will be added below
  1485. CDmAttribute *pSrcData = pSrcDelta->GetVertexData( i );
  1486. pDstDelta->CreateField( pSrcDelta->FieldName( i ), pSrcData->GetType() );
  1487. }
  1488. }
  1489. const int nSrcPositionIndex = pSrcDelta->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  1490. const int nSrcNormalIndex = pSrcDelta->FindFieldIndex( CDmeVertexData::FIELD_NORMAL );
  1491. const int nSrcWrinkleIndex = pSrcDelta->FindFieldIndex( CDmeVertexData::FIELD_WRINKLE );
  1492. for ( int i = 0; i < pSrcDelta->FieldCount(); ++i )
  1493. {
  1494. int nOffset = 0;
  1495. if ( i == nSrcPositionIndex )
  1496. {
  1497. nOffset = nPositionOffset;
  1498. }
  1499. else if ( i == nSrcNormalIndex )
  1500. {
  1501. nOffset = nNormalOffset;
  1502. }
  1503. else if ( i == nSrcWrinkleIndex )
  1504. {
  1505. nOffset = nWrinkleOffset;
  1506. }
  1507. if ( nOffset < 0 )
  1508. {
  1509. nOffset = 0;
  1510. }
  1511. for ( int j = 0; j < pDstDelta->FieldCount(); ++j )
  1512. {
  1513. if ( Q_strcmp( pSrcDelta->FieldName( i ), pDstDelta->FieldName( j ) ) )
  1514. continue;
  1515. CDmAttribute *pSrcData = pSrcDelta->GetVertexData( i );
  1516. CDmAttribute *pDstData = pDstDelta->GetVertexData( j );
  1517. switch ( pSrcData->GetType() )
  1518. {
  1519. case AT_FLOAT_ARRAY:
  1520. AppendData( CDmrArrayConst< float >( pSrcData ), CDmrArray< float >( pDstData ) );
  1521. break;
  1522. case AT_VECTOR2_ARRAY:
  1523. AppendData( CDmrArrayConst< Vector2D >( pSrcData ), CDmrArray< Vector2D >( pDstData ) );
  1524. break;
  1525. case AT_VECTOR3_ARRAY:
  1526. AppendData( CDmrArrayConst< Vector >( pSrcData ), CDmrArray< Vector >( pDstData ) );
  1527. break;
  1528. case AT_VECTOR4_ARRAY:
  1529. AppendData( CDmrArrayConst< Vector4D >( pSrcData ), CDmrArray< Vector4D >( pDstData ) );
  1530. break;
  1531. case AT_QUATERNION_ARRAY:
  1532. AppendData( CDmrArrayConst< Quaternion >( pSrcData ), CDmrArray< Quaternion >( pDstData ) );
  1533. break;
  1534. case AT_COLOR_ARRAY:
  1535. AppendData( CDmrArrayConst< Color >( pSrcData ), CDmrArray< Color >( pDstData ) );
  1536. break;
  1537. default:
  1538. Assert( 0 );
  1539. break;
  1540. }
  1541. CDmrArray< int > srcIndices( pSrcDelta->GetIndexData( i ) );
  1542. CDmrArray< int > dstIndices( pDstDelta->GetIndexData( j ) );
  1543. const int nSrcIndexCount = srcIndices.Count();
  1544. const int nDstIndexCount = dstIndices.Count();
  1545. dstIndices.AddMultipleToTail( nSrcIndexCount );
  1546. for ( int k = 0; k < nSrcIndexCount; ++k )
  1547. {
  1548. dstIndices.Set( nDstIndexCount + k, srcIndices.Get( k ) + nOffset );
  1549. }
  1550. break;
  1551. }
  1552. }
  1553. // TODO: Centralize all of the '_' for corrector business...
  1554. const char *pszDeltaName = pDstDelta->GetName();
  1555. if ( strchr( pszDeltaName, '_' ) )
  1556. return; // No controls for deltas with '_''s
  1557. if ( !pDmeMesh )
  1558. return;
  1559. CDmeCombinationOperator *pDmeCombo = FindReferringElement< CDmeCombinationOperator >( pDmeMesh, "targets" );
  1560. if ( !pDmeCombo )
  1561. return;
  1562. if ( pDmeCombo->HasRawControl( pszDeltaName ) )
  1563. return;
  1564. pDmeCombo->FindOrCreateControl( pDstDelta->GetName(), false, true );
  1565. }
  1566. //-----------------------------------------------------------------------------
  1567. //
  1568. //-----------------------------------------------------------------------------
  1569. bool CDmMeshUtils::Merge( CDmeMesh *pSrcMesh, CDmeMesh *pDstMesh, int nSkinningJointIndex, CUtlMap< int, int > *pJointMap /* = NULL */ )
  1570. {
  1571. if ( !pSrcMesh || !pDstMesh )
  1572. return false;
  1573. CDmeDag *pSrcDag = FindReferringElement< CDmeDag >( pSrcMesh, "shape", true );
  1574. CDmeDag *pDstDag = FindReferringElement< CDmeDag >( pDstMesh, "shape", true );
  1575. if ( !pSrcDag || !pDstDag )
  1576. return false;
  1577. matrix3x4_t nMat;
  1578. pSrcDag->GetAbsTransform( nMat );
  1579. matrix3x4_t pMat;
  1580. pDstDag->GetAbsTransform( pMat );
  1581. matrix3x4_t dMatInv;
  1582. MatrixInvert( pMat, dMatInv );
  1583. MatrixMultiply( dMatInv, nMat, pMat );
  1584. MatrixInverseTranspose( pMat, nMat );
  1585. int nPositionOffset = -1;
  1586. int nNormalOffset = -1;
  1587. int nWrinkleOffset = -1;
  1588. int nVertexOffset = -1;
  1589. for ( int i = 0; i < pSrcMesh->BaseStateCount(); ++i )
  1590. {
  1591. CDmeVertexData *pSrcBase = pSrcMesh->GetBaseState( i );
  1592. bool bMerged = false;
  1593. for ( int j = 0; j < pDstMesh->BaseStateCount(); ++j )
  1594. {
  1595. CDmeVertexData *pDstBase = pDstMesh->GetBaseState( j );
  1596. if ( Q_strcmp( pSrcBase->GetName(), pDstBase->GetName() ) )
  1597. continue;
  1598. bMerged = true;
  1599. const int nTmpVertexOffset = MergeBaseState( pSrcBase, pDstBase, pMat, nMat, nSkinningJointIndex, nPositionOffset, nNormalOffset, nWrinkleOffset, pJointMap );
  1600. if ( nVertexOffset < 0 )
  1601. {
  1602. nVertexOffset = nTmpVertexOffset;
  1603. }
  1604. Assert( nVertexOffset == nTmpVertexOffset );
  1605. }
  1606. if ( !bMerged )
  1607. {
  1608. Msg( "Error: Merge( %s, %s ) - Can't Find Base State %s On %s\n", pSrcMesh->GetName(), pDstMesh->GetName(), pSrcBase->GetName(), pDstMesh->GetName() );
  1609. }
  1610. }
  1611. // Merge Face Sets
  1612. int nFaceSetIndex;
  1613. for ( int i = 0; i < pSrcMesh->FaceSetCount(); ++i )
  1614. {
  1615. CDmeFaceSet *pFaceSet = pSrcMesh->GetFaceSet( i )->Copy();
  1616. pFaceSet->SetFileId( pDstMesh->GetFileId(), TD_DEEP );
  1617. const int nFaceSetIndexCount = pFaceSet->NumIndices();
  1618. for ( int j = 0; j < nFaceSetIndexCount; ++j )
  1619. {
  1620. nFaceSetIndex = pFaceSet->GetIndex( j );
  1621. if ( nFaceSetIndex >= 0 )
  1622. {
  1623. pFaceSet->SetIndex( j, nFaceSetIndex + nVertexOffset );
  1624. }
  1625. }
  1626. pDstMesh->AddFaceSet( pFaceSet );
  1627. }
  1628. // Merge Deltas
  1629. for ( int i = 0; i < pSrcMesh->DeltaStateCount(); ++i )
  1630. {
  1631. CDmeVertexDeltaData *pSrcDelta = pSrcMesh->GetDeltaState( i );
  1632. CDmeVertexDeltaData *pDstDelta = pDstMesh->FindDeltaState( pSrcDelta->GetName() );
  1633. MergeDeltaState( pDstMesh, pSrcDelta, pDstDelta, nPositionOffset, nNormalOffset, nWrinkleOffset );
  1634. }
  1635. return true;
  1636. }
  1637. //-----------------------------------------------------------------------------
  1638. //
  1639. //-----------------------------------------------------------------------------
  1640. struct VertexWeightMap_s
  1641. {
  1642. struct VertexWeight_s
  1643. {
  1644. int m_vertexDataIndex; // Index into the CDmeVertexData data (only used for joint weights & indices)
  1645. const CUtlVector< int > *m_pVertexIndices; // Index into the CDmeVertexData vertex indices
  1646. float m_vertexWeight;
  1647. };
  1648. int m_nVertexWeights;
  1649. VertexWeight_s m_vertexWeights[ 5 ];
  1650. };
  1651. //-----------------------------------------------------------------------------
  1652. //
  1653. //-----------------------------------------------------------------------------
  1654. bool CopyJointWeights(
  1655. CDmeVertexData *pSrcData,
  1656. CDmeVertexData *pDstData,
  1657. const CUtlVector< VertexWeightMap_s > &vertexWeightMap )
  1658. {
  1659. const int nJointCount = pSrcData->GetValue< int >( "jointCount" );
  1660. const FieldIndex_t nSrcJointWeightsField = pSrcData->FindFieldIndex( CDmeVertexData::FIELD_JOINT_WEIGHTS );
  1661. const FieldIndex_t nSrcJointIndicesField = pSrcData->FindFieldIndex( CDmeVertexData::FIELD_JOINT_INDICES );
  1662. if ( nJointCount <= 0 || nSrcJointWeightsField < 0 || nSrcJointIndicesField < 0 )
  1663. return false;
  1664. const CUtlVector< float > &srcJointWeights = CDmrArrayConst< float >( pSrcData->GetVertexData( nSrcJointWeightsField ) ).Get();
  1665. const float *const pSrcJointWeights = srcJointWeights.Base();
  1666. const CUtlVector< int > &srcJointIndices = CDmrArrayConst< int >( pSrcData->GetVertexData( nSrcJointIndicesField ) ).Get();
  1667. const int *const pSrcJointIndices = srcJointIndices.Base();
  1668. FieldIndex_t nDstJointWeightsField;
  1669. FieldIndex_t nDstJointIndicesField;
  1670. pDstData->CreateJointWeightsAndIndices( nJointCount, &nDstJointWeightsField, &nDstJointIndicesField );
  1671. const int nDstCount = vertexWeightMap.Count();
  1672. float *pDstJointWeights = reinterpret_cast< float * >( alloca( nDstCount * nJointCount * sizeof( float ) ) );
  1673. memset( pDstJointWeights, 0, nDstCount * nJointCount );
  1674. int *pDstJointIndices = reinterpret_cast< int * >( alloca( nDstCount * nJointCount * sizeof( int ) ) );
  1675. memset( pDstJointIndices, 0, nDstCount * nJointCount );
  1676. for ( int i = 0; i < nDstCount; ++i )
  1677. {
  1678. const VertexWeightMap_s &vertexWeight = vertexWeightMap[ i ];
  1679. const int nVertexWeights = vertexWeight.m_nVertexWeights;
  1680. if ( nVertexWeights > 0 )
  1681. {
  1682. // TODO: Find the best weights to use! For now, use the first one
  1683. int nMatchIndex = vertexWeight.m_vertexWeights[ 0 ].m_vertexDataIndex;
  1684. memcpy( pDstJointWeights + i * nJointCount, pSrcJointWeights + nMatchIndex * nJointCount, nJointCount * sizeof( float ) );
  1685. memcpy( pDstJointIndices + i * nJointCount, pSrcJointIndices + nMatchIndex * nJointCount, nJointCount * sizeof( int ) );
  1686. }
  1687. }
  1688. pDstData->AddVertexData( nDstJointIndicesField, nDstCount * nJointCount );
  1689. pDstData->SetVertexData( nDstJointIndicesField, 0, nDstCount * nJointCount, AT_INT, pDstJointIndices );
  1690. pDstData->AddVertexData( nDstJointWeightsField, nDstCount * nJointCount );
  1691. pDstData->SetVertexData( nDstJointWeightsField, 0, nDstCount * nJointCount, AT_FLOAT, pDstJointWeights );
  1692. return true;
  1693. }
  1694. //-----------------------------------------------------------------------------
  1695. // Replaces the DstMesh with the SrcMesh
  1696. //-----------------------------------------------------------------------------
  1697. CDmeMesh *ReplaceMesh(
  1698. CDmeMesh *pSrcMesh,
  1699. CDmeMesh *pDstMesh )
  1700. {
  1701. if ( !pSrcMesh || !pDstMesh )
  1702. return NULL;
  1703. CDmeDag *pSrcDag = pSrcMesh->GetParent();
  1704. CDmeDag *pDstDag = pDstMesh->GetParent();
  1705. if ( !pSrcDag || !pDstDag )
  1706. return NULL;
  1707. // Fix up the transform
  1708. matrix3x4_t inclusiveMat;
  1709. matrix3x4_t localMat;
  1710. pDstDag->GetShapeToWorldTransform( inclusiveMat );
  1711. pDstDag->GetTransform()->GetTransform( localMat );
  1712. matrix3x4_t inverseMat;
  1713. MatrixInvert( localMat, inverseMat );
  1714. matrix3x4_t exclusiveMat;
  1715. MatrixMultiply( inclusiveMat, inverseMat, exclusiveMat );
  1716. MatrixInvert( exclusiveMat, inverseMat );
  1717. pSrcDag->GetShapeToWorldTransform( inclusiveMat );
  1718. MatrixMultiply( inverseMat, inclusiveMat, localMat );
  1719. pDstDag->GetTransform()->SetTransform( localMat );
  1720. // Duplicate the mesh
  1721. CDmeMesh *pNewMesh = pSrcMesh->Copy();
  1722. pNewMesh->SetFileId( pDstMesh->GetFileId(), TD_DEEP );
  1723. // A bit of cleanup
  1724. pNewMesh->RemoveAttribute( "selection" );
  1725. pNewMesh->SetCurrentBaseState( "bind" );
  1726. pNewMesh->DeleteBaseState( "__dmxEdit_work" );
  1727. // Replace the DstMesh with the SrcMesh
  1728. pDstDag->SetShape( pNewMesh );
  1729. // Replace the combination operators, if applicable
  1730. CDmeCombinationOperator *pSrcComboOp = FindReferringElement< CDmeCombinationOperator >( pSrcMesh, "targets" );
  1731. if ( pSrcComboOp )
  1732. {
  1733. CDmeCombinationOperator *pDstComboOp = FindReferringElement< CDmeCombinationOperator >( pDstMesh, "targets" );
  1734. CDmElement *pDstRoot = NULL;
  1735. if ( pDstComboOp )
  1736. {
  1737. // Find the root the easy way
  1738. pDstRoot = FindReferringElement< CDmElement >( pDstComboOp, "combinationOperator" );
  1739. // Delete the old busted combination operator
  1740. g_pDataModel->DestroyElement( pDstComboOp->GetHandle() );
  1741. }
  1742. else
  1743. {
  1744. // Find the root the hard way
  1745. CDmeDag *pDmeDag = pDstDag;
  1746. for ( ;; )
  1747. {
  1748. // Walk backwards via "children" attribute
  1749. CDmeDag *pNextDag = FindReferringElement< CDmeDag >( pDmeDag, "children" );
  1750. if ( pNextDag )
  1751. {
  1752. pDmeDag = pNextDag;
  1753. }
  1754. else
  1755. {
  1756. // Can't find anyone referring to this via "children" so, hopefully it's the DmeModel referred to by "model"
  1757. pDstRoot = FindReferringElement< CDmElement >( pDmeDag, "model" );
  1758. break;
  1759. }
  1760. }
  1761. }
  1762. if ( pDstRoot )
  1763. {
  1764. // Install the shiny new combination operator
  1765. CDmeCombinationOperator *pNewComboOp = pSrcComboOp->Copy();
  1766. pNewComboOp->SetFileId( pDstRoot->GetFileId(), TD_DEEP );
  1767. pDstRoot->SetValue( "combinationOperator", pNewComboOp );
  1768. pNewComboOp->RemoveAllTargets();
  1769. pNewComboOp->AddTarget( pNewMesh );
  1770. pNewComboOp->GenerateWrinkleDeltas( false );
  1771. }
  1772. }
  1773. return pNewMesh;
  1774. }
  1775. //-----------------------------------------------------------------------------
  1776. //
  1777. //-----------------------------------------------------------------------------
  1778. template < class T_t >
  1779. void CopyFieldData(
  1780. const CDmrArrayConst< T_t > &srcData,
  1781. const CUtlVector< int > &srcIndices,
  1782. CDmeVertexData *pDstVertexData,
  1783. FieldIndex_t dstFieldIndex,
  1784. const CUtlVector< VertexWeightMap_s > &vertexWeightMap )
  1785. {
  1786. const int nDstData = vertexWeightMap.Count();
  1787. T_t sum;
  1788. T_t *pDstData = reinterpret_cast< T_t * >( alloca( nDstData * sizeof( T_t ) ) );
  1789. for ( int i = 0; i < nDstData; ++i )
  1790. {
  1791. CDmAttributeInfo< T_t >::SetDefaultValue( pDstData[ i ] );
  1792. const VertexWeightMap_s &vertexWeight = vertexWeightMap[ i ];
  1793. for ( int j = 0; j < vertexWeight.m_nVertexWeights; ++j )
  1794. {
  1795. const VertexWeightMap_s::VertexWeight_s &vWeight = vertexWeight.m_vertexWeights[ j ];
  1796. CDmAttributeInfo< T_t >::SetDefaultValue( sum );
  1797. const CUtlVector< int > &vertexList = *vWeight.m_pVertexIndices;
  1798. for ( int k = 0; k < vertexList.Count(); ++k )
  1799. {
  1800. sum += srcData[ srcIndices[ vertexList[ k ] ] ];
  1801. }
  1802. sum /= static_cast< float >( vertexList.Count() );
  1803. pDstData[ i ] += sum * vWeight.m_vertexWeight;
  1804. }
  1805. }
  1806. const DmAttributeType_t dmAttributeType = ArrayTypeToValueType( srcData.GetAttribute()->GetType() );
  1807. CDmrArray< T_t > dstData( pDstVertexData->GetVertexData( dstFieldIndex ) );
  1808. dstData.EnsureCount( nDstData );
  1809. pDstVertexData->SetVertexData( dstFieldIndex, 0, nDstData, dmAttributeType, pDstData );
  1810. }
  1811. //-----------------------------------------------------------------------------
  1812. //
  1813. //-----------------------------------------------------------------------------
  1814. bool CopyField(
  1815. CDmeVertexData::StandardFields_t field,
  1816. CDmeVertexData *pSrcData,
  1817. CDmeVertexData *pDstData,
  1818. const CUtlVector< VertexWeightMap_s > &vertexWeightMap )
  1819. {
  1820. FieldIndex_t srcFieldIndex = pSrcData->FindFieldIndex( field );
  1821. if ( srcFieldIndex < 0 )
  1822. return false;
  1823. FieldIndex_t dstFieldIndex = pDstData->CreateField( field );
  1824. if ( dstFieldIndex < 0 )
  1825. return false;
  1826. CDmAttribute *pSrcVertexData = pSrcData->GetVertexData( srcFieldIndex );
  1827. const CUtlVector< int > &srcIndices = pSrcData->GetVertexIndexData( srcFieldIndex );
  1828. // Everything on dst has to be indexed the same as position
  1829. const CUtlVector< int > &dstPosIndices = pDstData->GetVertexIndexData( CDmeVertexData::FIELD_POSITION );
  1830. CDmrArray< int > dstIndices( pDstData->GetIndexData( dstFieldIndex ) );
  1831. dstIndices.EnsureCount( dstPosIndices.Count() );
  1832. pDstData->SetVertexIndices( dstFieldIndex, 0, dstPosIndices.Count(), dstPosIndices.Base() );
  1833. switch ( pSrcVertexData->GetType() )
  1834. {
  1835. case AT_FLOAT_ARRAY:
  1836. CopyFieldData( CDmrArrayConst< float >( pSrcVertexData ), srcIndices, pDstData, dstFieldIndex, vertexWeightMap );
  1837. break;
  1838. case AT_VECTOR2_ARRAY:
  1839. CopyFieldData( CDmrArrayConst< Vector2D >( pSrcVertexData ), srcIndices, pDstData, dstFieldIndex, vertexWeightMap );
  1840. break;
  1841. case AT_VECTOR3_ARRAY:
  1842. CopyFieldData( CDmrArrayConst< Vector >( pSrcVertexData ), srcIndices, pDstData, dstFieldIndex, vertexWeightMap );
  1843. break;
  1844. default:
  1845. break;
  1846. }
  1847. return true;
  1848. }
  1849. //-----------------------------------------------------------------------------
  1850. //
  1851. //-----------------------------------------------------------------------------
  1852. inline bool IsEqual( const float &flA, const float &flB, float flTolerance )
  1853. {
  1854. return ( FloatMakePositive( flA - flB ) <= flTolerance );
  1855. }
  1856. //-----------------------------------------------------------------------------
  1857. //
  1858. //-----------------------------------------------------------------------------
  1859. inline bool IsEqual( const Vector &vA, const Vector &vB, float flTolerance )
  1860. {
  1861. return VectorsAreEqual( vA, vB, flTolerance );
  1862. }
  1863. //-----------------------------------------------------------------------------
  1864. //
  1865. //-----------------------------------------------------------------------------
  1866. inline bool IsEqual( const Vector2D &vA, const Vector2D &vB, float flTolerance )
  1867. {
  1868. if ( FloatMakePositive( vA.x - vB.x ) > flTolerance )
  1869. return false;
  1870. return ( FloatMakePositive( vA.y - vB.y ) <= flTolerance );
  1871. }
  1872. //-----------------------------------------------------------------------------
  1873. //
  1874. //-----------------------------------------------------------------------------
  1875. template < class T >
  1876. bool MergeField(
  1877. CDmeVertexData *pDstVertexData,
  1878. FieldIndex_t nDstFieldIndex,
  1879. CDmAttribute *pDstAttr,
  1880. CDmeVertexData *pSrcVertexData,
  1881. FieldIndex_t nSrcFieldIndex,
  1882. CDmAttribute *pSrcAttr,
  1883. int nIndexOffset,
  1884. float flTolerance )
  1885. {
  1886. CUtlMap< int, int > srcToDstMap( CDefOps< int >::LessFunc );
  1887. if ( !pDstVertexData || !pDstAttr || !pSrcAttr )
  1888. return false;
  1889. const CDmrArrayConst< T > dstData( pDstAttr );
  1890. const CDmrArrayConst< T > srcData( pSrcAttr );
  1891. if ( dstData.Count() <= 0 || srcData.Count() <= 0 )
  1892. return false;
  1893. CUtlVector< T > newDstData;
  1894. for ( int i = 0; i < srcData.Count(); ++i )
  1895. {
  1896. int nDstIndex = -1;
  1897. const T &srcVal = srcData[i];
  1898. for ( int j = 0; j < dstData.Count(); ++j )
  1899. {
  1900. const T &dstVal = dstData[j];
  1901. if ( IsEqual( srcVal, dstVal, flTolerance ) )
  1902. {
  1903. nDstIndex = j;
  1904. break;
  1905. }
  1906. }
  1907. if ( nDstIndex < 0 )
  1908. {
  1909. nDstIndex = dstData.Count() + newDstData.AddToTail( srcVal );
  1910. }
  1911. Assert( nDstIndex >= 0 );
  1912. srcToDstMap.InsertOrReplace( i, nDstIndex );
  1913. }
  1914. CUtlVector< int > newIndices;
  1915. const CUtlVector< int > &srcIndexData = pSrcVertexData->GetVertexIndexData( nSrcFieldIndex );
  1916. Assert( srcIndexData.Count() > 0 );
  1917. for ( int i = 0; i < srcIndexData.Count(); ++i )
  1918. {
  1919. const CUtlMap< int, int >::IndexType_t nFindIndex = srcToDstMap.Find( srcIndexData[i] );
  1920. Assert( srcToDstMap.IsValidIndex( nFindIndex ) );
  1921. newIndices.AddToTail( srcToDstMap.Element( nFindIndex ) );
  1922. }
  1923. Assert( pDstVertexData->VertexCount() == nIndexOffset + newIndices.Count() );
  1924. pDstVertexData->SetVertexIndices( nDstFieldIndex, nIndexOffset, newIndices.Count(), newIndices.Base() );
  1925. if ( newDstData.Count() > 0 )
  1926. {
  1927. const int nStart = dstData.Count();
  1928. pDstVertexData->AddVertexData( nDstFieldIndex, newDstData.Count() );
  1929. pDstVertexData->SetVertexData( nDstFieldIndex, nStart, newDstData.Count(), ArrayTypeToValueType( pDstAttr->GetType() ), newDstData.Base() );
  1930. }
  1931. return true;
  1932. }
  1933. //-----------------------------------------------------------------------------
  1934. //
  1935. //-----------------------------------------------------------------------------
  1936. bool CDmMeshUtils::Merge(
  1937. CDmMeshComp &srcComp,
  1938. const CUtlVector< CDmMeshComp::CEdge * > &edgeList,
  1939. CDmeMesh *pDstMesh )
  1940. {
  1941. CDmeMesh *pSrcMesh = srcComp.m_pMesh;
  1942. if ( !pSrcMesh || !pDstMesh )
  1943. return false;
  1944. CDmeVertexData *pSrcData = pSrcMesh->FindBaseState( "bind" );
  1945. CDmeVertexData *pDstData = pDstMesh->FindBaseState( "bind" );
  1946. if ( !pSrcData || !pDstData )
  1947. return false;
  1948. const CUtlVector< Vector > &srcPosData = pSrcData->GetPositionData();
  1949. const int nSrcCount = srcPosData.Count();
  1950. const CUtlVector< Vector > &dstPosData = pDstData->GetPositionData();
  1951. const int nDstCount = dstPosData.Count();
  1952. if ( nSrcCount <= 0 || nDstCount <= 0 )
  1953. return false;
  1954. CUtlVector< VertexWeightMap_s > vertexWeightMap;
  1955. vertexWeightMap.SetSize( nSrcCount );
  1956. for ( int i = 0; i < nSrcCount; ++i )
  1957. {
  1958. int nClosestIndex = -1;
  1959. float closest = FLT_MAX;
  1960. VertexWeightMap_s &vertexWeight = vertexWeightMap[ i ];
  1961. vertexWeight.m_nVertexWeights = 0;
  1962. const Vector &vSrc = srcPosData[ i ];
  1963. for ( int j = 0; j < nDstCount; ++j )
  1964. {
  1965. const Vector &vDst = dstPosData[ j ];
  1966. if ( vSrc.DistToSqr( vDst ) < FLT_EPSILON * 10.0f )
  1967. {
  1968. vertexWeight.m_nVertexWeights = 1;
  1969. vertexWeight.m_vertexWeights[ 0 ].m_vertexDataIndex = j;
  1970. vertexWeight.m_vertexWeights[ 0 ].m_vertexWeight = 1.0f;
  1971. vertexWeight.m_vertexWeights[ 0 ].m_pVertexIndices = &pDstData->FindVertexIndicesFromDataIndex( CDmeVertexData::FIELD_POSITION, j );
  1972. break;
  1973. }
  1974. float distance = vSrc.DistToSqr( vDst );
  1975. if ( distance < closest )
  1976. {
  1977. closest = distance;
  1978. nClosestIndex = j;
  1979. }
  1980. }
  1981. if ( vertexWeight.m_nVertexWeights == 0 )
  1982. {
  1983. Warning( "Warning: Merge() - No Match For Src Vertex: %f %f %f, Using Closest: %f %f %f\n",
  1984. vSrc.x, vSrc.y, vSrc.z,
  1985. dstPosData[ nClosestIndex ].x, dstPosData[ nClosestIndex ].y, dstPosData[ nClosestIndex ].z );
  1986. // TODO: Loop through and find up to n closest vertices by position
  1987. vertexWeight.m_nVertexWeights = 1;
  1988. vertexWeight.m_vertexWeights[ 0 ].m_vertexDataIndex = nClosestIndex;
  1989. vertexWeight.m_vertexWeights[ 0 ].m_vertexWeight = 1.0f;
  1990. vertexWeight.m_vertexWeights[ 0 ].m_pVertexIndices = &pDstData->FindVertexIndicesFromDataIndex( CDmeVertexData::FIELD_POSITION, nClosestIndex );
  1991. // Assert( vertexWeight.m_nVertexWeights );
  1992. // return false;
  1993. }
  1994. }
  1995. CDmeMesh *pNewMesh = ReplaceMesh( pSrcMesh, pDstMesh );
  1996. if ( !pNewMesh )
  1997. {
  1998. Error( "Error: Merge() - Couldn't Replace Mesh %s With %s\n", pDstMesh->GetName(), pSrcMesh->GetName() );
  1999. return false;
  2000. }
  2001. CDmeVertexData *pNewData = pNewMesh->FindBaseState( "bind" );
  2002. if ( pNewData )
  2003. {
  2004. CopyJointWeights( pDstData, pNewData, vertexWeightMap );
  2005. CopyField( CDmeVertexData::FIELD_BALANCE, pDstData, pNewData, vertexWeightMap );
  2006. CopyField( CDmeVertexData::FIELD_MORPH_SPEED, pDstData, pNewData, vertexWeightMap );
  2007. if ( pNewData->FindFieldIndex( CDmeVertexData::FIELD_MORPH_SPEED ) >= 0 )
  2008. {
  2009. CDmeCombinationOperator *pComboOp( FindReferringElement< CDmeCombinationOperator >( pNewMesh, "targets" ) );
  2010. if ( pComboOp )
  2011. {
  2012. pComboOp->UsingLaggedData( true );
  2013. }
  2014. }
  2015. }
  2016. // Destroy the old busted mesh
  2017. g_pDataModel->DestroyElement( pDstMesh->GetHandle() );
  2018. return true;
  2019. }
  2020. //-----------------------------------------------------------------------------
  2021. //
  2022. //-----------------------------------------------------------------------------
  2023. bool CDmMeshUtils::NewMerge(
  2024. CDmeMesh *pDstMesh,
  2025. CDmeMesh *pSrcMesh,
  2026. const CUtlVector< CDmMeshComp::CEdge * > &edgeList,
  2027. float flTolerance,
  2028. float flTexCoordTolerance )
  2029. {
  2030. if ( !pSrcMesh || !pDstMesh )
  2031. return false;
  2032. CDmeVertexData *pSrcData = pSrcMesh->FindBaseState( "bind" );
  2033. CDmeVertexData *pDstData = pDstMesh->FindBaseState( "bind" );
  2034. if ( !pSrcData || !pDstData )
  2035. return false;
  2036. int nDstIndexCount = pDstData->VertexCount();
  2037. int nDstIndexOffset = nDstIndexCount;
  2038. if ( nDstIndexCount <= 0 )
  2039. return false;
  2040. // Merge or add face sets
  2041. for ( int i = 0; i < pSrcMesh->FaceSetCount(); ++i )
  2042. {
  2043. CDmeFaceSet *pSrcFaceSet = pSrcMesh->GetFaceSet( i );
  2044. if ( !pSrcFaceSet )
  2045. continue;
  2046. const int nSrcIndexCount = pSrcFaceSet->GetIndexCount();
  2047. if ( nSrcIndexCount <= 0 )
  2048. continue;
  2049. CDmeMaterial *pSrcMat = pSrcFaceSet->GetMaterial();
  2050. const char *pszSrcMatName = pSrcMat ? pSrcMat->GetMaterialName() : NULL;
  2051. bool bCopy = true;
  2052. if ( pszSrcMatName )
  2053. {
  2054. for ( int j = 0; j < pDstMesh->FaceSetCount(); ++j )
  2055. {
  2056. CDmeFaceSet *pDstFaceSet = pDstMesh->GetFaceSet( j );
  2057. if ( !pDstFaceSet )
  2058. continue;
  2059. CDmeMaterial *pDstMat = pDstFaceSet->GetMaterial();
  2060. if ( !pDstMat )
  2061. continue;
  2062. if ( !V_strcmp( pDstMat->GetMaterialName(), pszSrcMatName ) )
  2063. {
  2064. bCopy = false;
  2065. // Merge
  2066. pDstData->AddVertexIndices( nSrcIndexCount );
  2067. for ( int k = 0; k < pSrcFaceSet->NumIndices(); ++k )
  2068. {
  2069. const int nFaceSetIndex = pSrcFaceSet->GetIndex( k );
  2070. const int nToSetIndex = pDstFaceSet->NumIndices();
  2071. pDstFaceSet->AddIndices( 1 );
  2072. if ( nFaceSetIndex < 0 )
  2073. {
  2074. pDstFaceSet->SetIndex( nToSetIndex, -1 );
  2075. }
  2076. else
  2077. {
  2078. pDstFaceSet->SetIndex( nToSetIndex, nFaceSetIndex + nDstIndexCount );
  2079. }
  2080. }
  2081. nDstIndexCount += nSrcIndexCount;
  2082. break;
  2083. }
  2084. }
  2085. }
  2086. if ( bCopy )
  2087. {
  2088. CDmeFaceSet *pDmeFaceSet = pSrcMesh->GetFaceSet( i )->Copy();
  2089. pDmeFaceSet->SetFileId( pDstMesh->GetFileId(), TD_DEEP );
  2090. pDstData->AddVertexIndices( nSrcIndexCount );
  2091. for ( int j = 0; j < pDmeFaceSet->NumIndices(); ++j )
  2092. {
  2093. int nFaceSetIndex = pDmeFaceSet->GetIndex( j );
  2094. if ( nFaceSetIndex >= 0 )
  2095. {
  2096. pDmeFaceSet->SetIndex( j, nFaceSetIndex + nDstIndexCount );
  2097. }
  2098. }
  2099. nDstIndexCount += nSrcIndexCount;
  2100. pDstMesh->AddFaceSet( pDmeFaceSet );
  2101. }
  2102. }
  2103. for ( int nSrcFieldIndex = 0; nSrcFieldIndex < pSrcData->FieldCount(); ++nSrcFieldIndex )
  2104. {
  2105. CDmAttribute *pSrcAttr = pSrcData->GetVertexData( nSrcFieldIndex );
  2106. const char *pszSrcFieldName = pSrcData->FieldName( nSrcFieldIndex );
  2107. if ( !pSrcAttr || !pszSrcFieldName || V_strlen( pszSrcFieldName ) <= 0 )
  2108. continue;
  2109. const FieldIndex_t nDstFieldIndex = pDstData->FindFieldIndex( pszSrcFieldName );
  2110. if ( nDstFieldIndex < 0 )
  2111. {
  2112. Log_Error( LOG_MESHUTILS, LOG_COLOR_RED, "ERROR: Merge( \"%s\", \"%s\" ): Cannot Find Field \"%s\" On Dst Mesh: \"%s\"\n",
  2113. pDstMesh->GetName(), pSrcMesh->GetName(), pszSrcFieldName, pDstMesh->GetName() );
  2114. continue;
  2115. }
  2116. CDmAttribute *pDstAttr = pDstData->GetVertexData( nDstFieldIndex );
  2117. if ( !pDstAttr )
  2118. {
  2119. Log_Error( LOG_MESHUTILS, LOG_COLOR_RED, "ERROR: Merge( \"%s\", \"%s\" ): Cannot Find Field \"%s\" On Dst Mesh: \"%s\"\n",
  2120. pDstMesh->GetName(), pSrcMesh->GetName(), pszSrcFieldName, pDstMesh->GetName() ); continue;
  2121. }
  2122. if ( pSrcAttr->GetType() != pDstAttr->GetType() )
  2123. {
  2124. Log_Error( LOG_MESHUTILS, LOG_COLOR_RED, "ERROR: Merge( \"%s\", \"%s\" ): Field \"%s\" Type Mismatch: Src %s vs Dst %s\n",
  2125. pDstMesh->GetName(), pSrcMesh->GetName(), pszSrcFieldName, pSrcAttr->GetTypeString(), pDstAttr->GetTypeString() );
  2126. continue;
  2127. }
  2128. bool bOk = false;
  2129. const DmAttributeType_t nAttrType = pSrcAttr->GetType();
  2130. if ( nAttrType == AT_FLOAT_ARRAY )
  2131. {
  2132. bOk = MergeField< float >( pDstData, nDstFieldIndex, pDstAttr, pSrcData, nSrcFieldIndex, pSrcAttr, nDstIndexOffset, flTolerance );
  2133. }
  2134. else if ( nAttrType == AT_VECTOR2_ARRAY )
  2135. {
  2136. bOk = MergeField< Vector2D >( pDstData, nDstFieldIndex, pDstAttr, pSrcData, nSrcFieldIndex, pSrcAttr, nDstIndexOffset, flTexCoordTolerance );
  2137. }
  2138. else if ( nAttrType == AT_VECTOR3_ARRAY )
  2139. {
  2140. bOk = MergeField< Vector >( pDstData, nDstFieldIndex, pDstAttr, pSrcData, nSrcFieldIndex, pSrcAttr, nDstIndexOffset, flTolerance );
  2141. }
  2142. if ( !bOk )
  2143. {
  2144. Log_Warning( LOG_MESHUTILS, LOG_COLOR_YELLOW, "WARNING: Merge( \"%s\", \"%s\" ): Field \"%s\" Not Merged\n",
  2145. pDstMesh->GetName(), pSrcMesh->GetName(), pszSrcFieldName );
  2146. }
  2147. }
  2148. pDstData->Resolve();
  2149. pDstMesh->Resolve();
  2150. return true;
  2151. }
  2152. //-----------------------------------------------------------------------------
  2153. // Returns a guaranteed unique DmFileId_t
  2154. //-----------------------------------------------------------------------------
  2155. DmFileId_t CreateUniqueFileId()
  2156. {
  2157. DmFileId_t fileId = DMFILEID_INVALID;
  2158. UniqueId_t uniqueId;
  2159. char fileIdBuf[ MAX_PATH ];
  2160. do
  2161. {
  2162. CreateUniqueId( &uniqueId );
  2163. UniqueIdToString( uniqueId, fileIdBuf, sizeof( fileIdBuf ) );
  2164. fileId = g_pDataModel->GetFileId( fileIdBuf );
  2165. } while( fileId != DMFILEID_INVALID );
  2166. return g_pDataModel->FindOrCreateFileId( fileIdBuf );
  2167. }
  2168. //-----------------------------------------------------------------------------
  2169. //
  2170. //-----------------------------------------------------------------------------
  2171. bool CreateExpressionFile( const char *pExpressionFile, const CUtlVector< CUtlString > *pPurgeAllButThese, CDmeCombinationOperator *pComboOp, CDmePresetGroup *pPresetGroup )
  2172. {
  2173. if ( !pPresetGroup )
  2174. return false;
  2175. Assert( pExpressionFile && pComboOp );
  2176. const int nControlCount = pComboOp->GetControlCount();
  2177. const CDmaElementArray< CDmePreset > &presets = pPresetGroup->GetPresets();
  2178. const int nPresetsCount = presets.Count();
  2179. if ( nControlCount <= 0 || nPresetsCount <= 0 )
  2180. return false;
  2181. char expName[ MAX_PATH ];
  2182. Q_FileBase( pExpressionFile, expName, sizeof( expName ) );
  2183. CDmePresetGroup *pDstPresetGroup = CreateElement< CDmePresetGroup >( expName, CreateUniqueFileId() );
  2184. if ( !pDstPresetGroup )
  2185. return false;
  2186. for ( int i = 0; i < nPresetsCount; ++i )
  2187. {
  2188. CDmePreset *pPreset = presets[ i ];
  2189. Assert( !pPreset->IsAnimated() ); // deal with this after GDC
  2190. if ( pPreset->IsAnimated() )
  2191. continue;
  2192. const char *pPresetName = pPreset->GetName();
  2193. CDmePreset *pDstPreset = pDstPresetGroup->FindOrAddPreset( pPresetName );
  2194. const CDmaElementArray< CDmElement > &controlValues = pPreset->GetControlValues();
  2195. const int nControlValueCount = controlValues.Count();
  2196. for ( int j = 0; j < nControlCount; ++j )
  2197. {
  2198. // Figure out if this preset is used
  2199. bool bFound = false; // Used for two things
  2200. const char *pControlName = pComboOp->GetControlName( j );
  2201. if ( pPurgeAllButThese )
  2202. {
  2203. for ( int k = 0; k < pPurgeAllButThese->Count(); ++k )
  2204. {
  2205. if ( !Q_strcmp( pControlName, pPurgeAllButThese->Element( k ).Get() ) )
  2206. {
  2207. bFound = true;
  2208. break;
  2209. }
  2210. }
  2211. }
  2212. if ( !bFound && pPresetGroup->FindPreset( pControlName ) )
  2213. bFound = true;
  2214. if ( !bFound )
  2215. continue;
  2216. CDmElement *pDstControlValue = NULL;
  2217. const bool bStereo = pComboOp->IsStereoControl( j );
  2218. const bool bMulti = pComboOp->IsMultiControl( j );
  2219. if ( !Q_strcmp( pControlName, pPresetName ) )
  2220. {
  2221. pDstControlValue = pDstPreset->FindOrAddControlValue( pControlName );
  2222. // These shouldn't really happen because these are presets which were made
  2223. // into deltas so they are never stereo nor multi-controls
  2224. if ( bStereo )
  2225. {
  2226. pDstControlValue->SetValue( "leftValue", 1.0f );
  2227. pDstControlValue->SetValue( "rightValue", 1.0f );
  2228. }
  2229. else
  2230. {
  2231. pDstControlValue->SetValue( "value", 1.0f );
  2232. }
  2233. if ( bMulti )
  2234. {
  2235. CFmtStr multiControlName( "%s_multi", pControlName );
  2236. CDmElement *pDstMultiControlValue = pDstPreset->FindOrAddControlValue( multiControlName );
  2237. pDstMultiControlValue->SetValue( "value", 0.5f );
  2238. }
  2239. continue;
  2240. }
  2241. for ( int k = 0; k < nControlValueCount; ++k )
  2242. {
  2243. CDmElement *pControlPreset = controlValues[ k ];
  2244. if ( !pControlPreset )
  2245. continue;
  2246. if ( !Q_strcmp( pControlName, pControlPreset->GetName() ) )
  2247. {
  2248. pDstControlValue = pDstPreset->FindOrAddControlValue( pControlName );
  2249. if ( bStereo )
  2250. {
  2251. pDstControlValue->SetValue( "leftValue", pControlPreset->GetValue( "leftValue", 0.0f ) );
  2252. pDstControlValue->SetValue( "rightValue", pControlPreset->GetValue( "rightValue", 0.0f ) );
  2253. }
  2254. else
  2255. {
  2256. pDstControlValue->SetValue( "value", pControlPreset->GetValue( "value", 0.0f ) );
  2257. }
  2258. if ( bMulti )
  2259. {
  2260. CFmtStr multiControlName( "%s_multi", pControlName );
  2261. CDmElement *pMultiControlPreset = pPreset->FindControlValue( multiControlName );
  2262. CDmElement *pDstMultiControlValue = pDstPreset->FindOrAddControlValue( multiControlName );
  2263. pDstMultiControlValue->SetValue( "value", pMultiControlPreset ? pMultiControlPreset->GetValue( "value", 0.5f ) : 0.5f );
  2264. }
  2265. break;
  2266. }
  2267. }
  2268. if ( !pDstControlValue )
  2269. {
  2270. pDstControlValue = pDstPreset->FindOrAddControlValue( pControlName );
  2271. if ( bStereo )
  2272. {
  2273. float flValue = pComboOp->GetControlDefaultValue( j );
  2274. pDstControlValue->SetValue( "leftValue", flValue );
  2275. pDstControlValue->SetValue( "rightValue", flValue );
  2276. }
  2277. else
  2278. {
  2279. pDstControlValue->SetValue( "value", pComboOp->GetControlDefaultValue( j ) );
  2280. }
  2281. if ( bMulti )
  2282. {
  2283. CFmtStr multiControlName( "%s_multi", pControlName );
  2284. CDmElement *pDstMultiControlValue = pDstPreset->FindOrAddControlValue( multiControlName );
  2285. pDstMultiControlValue->SetValue( "value", 0.5f );
  2286. }
  2287. }
  2288. }
  2289. }
  2290. char buf[ MAX_PATH ];
  2291. char buf1[ MAX_PATH ];
  2292. Q_strncpy( buf, pExpressionFile, sizeof( buf ) );
  2293. Q_SetExtension( buf, ".txt", sizeof( buf ) );
  2294. Q_ExtractFilePath( buf, buf1, sizeof( buf1 ) );
  2295. Q_FixSlashes( buf1 );
  2296. g_pFullFileSystem->CreateDirHierarchy( buf1 );
  2297. if ( !g_p4factory->AccessFile( buf )->Edit() )
  2298. {
  2299. g_p4factory->AccessFile( buf )->Add();
  2300. }
  2301. pDstPresetGroup->ExportToTXT( buf, NULL, pComboOp );
  2302. Q_SetExtension( buf, ".vfe", sizeof( buf ) );
  2303. Q_ExtractFilePath( buf, buf1, sizeof( buf1 ) );
  2304. Q_FixSlashes( buf1 );
  2305. g_pFullFileSystem->CreateDirHierarchy( buf1 );
  2306. if ( !g_p4factory->AccessFile( buf )->Edit() )
  2307. {
  2308. g_p4factory->AccessFile( buf )->Add();
  2309. }
  2310. pDstPresetGroup->ExportToVFE( buf, NULL, pComboOp );
  2311. g_pDataModel->UnloadFile( pDstPresetGroup->GetFileId() );
  2312. return true;
  2313. }
  2314. //-----------------------------------------------------------------------------
  2315. //
  2316. //-----------------------------------------------------------------------------
  2317. bool CDmMeshUtils::CreateDeltasFromPresets(
  2318. CDmeMesh *pMesh,
  2319. CDmeVertexData *pPassedDst,
  2320. const CUtlStringMap< CUtlString > &presetExpressionMap,
  2321. bool bPurge,
  2322. const CUtlVector< CUtlString > *pPurgeAllButThese /*= NULL */ )
  2323. {
  2324. if ( !pMesh )
  2325. return false;
  2326. CDisableUndoScopeGuard sgDisableUndo;
  2327. CUtlStringMap< CDmePreset * > presetMap;
  2328. CUtlStringMap< CUtlString > conflictingNames;
  2329. CDmeVertexData *pDst = pPassedDst ? pPassedDst : pMesh->GetCurrentBaseState();
  2330. CDmeVertexData *pBind = pMesh->FindBaseState( "bind" );
  2331. if ( !pDst || !pBind || pDst == pBind )
  2332. return false;
  2333. CDmeCombinationOperator *pComboOp = FindReferringElement< CDmeCombinationOperator >( pMesh, "targets" );
  2334. if ( !pComboOp )
  2335. return false;
  2336. const bool bSavedUsingLagged = pComboOp->IsUsingLaggedData();
  2337. CUtlVector< CDmePresetGroup * > presetGroups;
  2338. for ( int i = 0; i < presetExpressionMap.GetNumStrings(); ++i )
  2339. {
  2340. const char *pPresetFilename = presetExpressionMap.String( i );
  2341. // Load the preset file
  2342. CDmElement *pRoot = NULL;
  2343. g_p4factory->AccessFile( pPresetFilename )->Add();
  2344. g_pDataModel->RestoreFromFile( pPresetFilename, NULL, NULL, &pRoot );
  2345. CDmePresetGroup *pPresetGroup = CastElement< CDmePresetGroup >( pRoot );
  2346. presetGroups.AddToTail( pPresetGroup );
  2347. if ( !pPresetGroup )
  2348. continue;
  2349. CreateDeltasFromPresetGroup( pPresetGroup, pComboOp, pPurgeAllButThese, pMesh, pDst, conflictingNames, presetMap );
  2350. }
  2351. if ( bPurge )
  2352. {
  2353. PurgeUnreferencedDeltas( pMesh, presetMap, pPurgeAllButThese, pComboOp );
  2354. }
  2355. for ( int i = 0; i < presetMap.GetNumStrings(); ++i )
  2356. {
  2357. const char *pPresetName = presetMap[ i ]->GetName();
  2358. const int nControlIndex = pComboOp->FindControlIndex( pPresetName );
  2359. if ( nControlIndex < 0 )
  2360. {
  2361. pComboOp->FindOrCreateControl( pPresetName, false, true );
  2362. }
  2363. else
  2364. {
  2365. bool bFound = false;
  2366. if ( bPurge )
  2367. {
  2368. pComboOp->RemoveAllRawControls( nControlIndex );
  2369. }
  2370. else
  2371. {
  2372. const int nRawControls = pComboOp->GetRawControlCount( nControlIndex );
  2373. for ( int j = 0; j < nRawControls; ++j )
  2374. {
  2375. if ( !Q_strcmp( pComboOp->GetRawControlName( nControlIndex, j ), pPresetName ) )
  2376. {
  2377. bFound = true;
  2378. break;
  2379. }
  2380. }
  2381. }
  2382. if ( !bFound )
  2383. {
  2384. pComboOp->AddRawControl( nControlIndex, pPresetName );
  2385. }
  2386. }
  2387. }
  2388. pComboOp->UsingLaggedData( bSavedUsingLagged );
  2389. pComboOp->SetToDefault();
  2390. for ( int i = 0; i < presetExpressionMap.GetNumStrings(); ++i )
  2391. {
  2392. const CUtlString &expressionFile = presetExpressionMap[ i ];
  2393. if ( expressionFile.IsEmpty() )
  2394. continue;
  2395. CreateExpressionFile( expressionFile.Get(), pPurgeAllButThese, pComboOp, presetGroups[ i ] );
  2396. }
  2397. for ( int i = 0; i < presetGroups.Count(); ++i )
  2398. {
  2399. CDmePresetGroup *pPresetGroup = presetGroups[ i ];
  2400. if ( !pPresetGroup )
  2401. continue;
  2402. g_pDataModel->UnloadFile( pPresetGroup->GetFileId() );
  2403. }
  2404. return true;
  2405. }
  2406. //-----------------------------------------------------------------------------
  2407. // Removes any deltas from the specified mesh which are not referred to by
  2408. // any rule of the combination operator driving the mesh
  2409. //-----------------------------------------------------------------------------
  2410. bool CDmMeshUtils::PurgeUnusedDeltas( CDmeMesh *pMesh )
  2411. {
  2412. // Disable for now
  2413. // This code will delete all corrective delta states, i.e. deltas named A_B
  2414. return true;
  2415. if ( !pMesh )
  2416. return false;
  2417. CDmeCombinationOperator *pCombo = FindReferringElement< CDmeCombinationOperator >( pMesh, "targets" );
  2418. if ( !pCombo )
  2419. return false;
  2420. const int nControlCount = pCombo->GetControlCount();
  2421. CUtlVector< CDmeMesh::DeltaComputation_t > compList;
  2422. pMesh->ComputeDependentDeltaStateList( compList );
  2423. const int nDeltaCount = compList.Count();
  2424. Assert( nDeltaCount == pMesh->DeltaStateCount() );
  2425. CUtlVector< bool > deltasToKeep;
  2426. deltasToKeep.EnsureCount( nDeltaCount );
  2427. memset( deltasToKeep.Base(), 0, sizeof( bool ) * nDeltaCount );
  2428. for ( int i = 0; i < nControlCount; ++i )
  2429. {
  2430. const int nRawControlCount = pCombo->GetRawControlCount( i );
  2431. for ( int j = 0; j < nRawControlCount; ++j )
  2432. {
  2433. const int nDeltaIndex = pMesh->FindDeltaStateIndex( pCombo->GetRawControlName( i, j ) );
  2434. const CDmeMesh::DeltaComputation_t &deltaComp = compList[ nDeltaIndex ];
  2435. deltasToKeep[ deltaComp.m_nDeltaIndex ] = true;
  2436. for ( int k = 0; k < deltaComp.m_DependentDeltas.Count(); ++k )
  2437. {
  2438. deltasToKeep[ deltaComp.m_DependentDeltas[ k ] ] = true;
  2439. }
  2440. }
  2441. }
  2442. return true;
  2443. }
  2444. //-----------------------------------------------------------------------------
  2445. //
  2446. //-----------------------------------------------------------------------------
  2447. bool CDmMeshUtils::CreateWrinkleDeltaFromBaseState(
  2448. CDmeVertexDeltaData *pDelta,
  2449. float flScale /* = 1.0f */,
  2450. WrinkleOp wrinkleOp /* = kReplace */,
  2451. CDmeMesh *pPassedMesh /* = NULL */,
  2452. CDmeVertexData *pPassedBind /* = NULL */,
  2453. CDmeVertexData *pPassedCurrent /* = NULL */,
  2454. bool bUseNormalForSign /* = false */ )
  2455. {
  2456. CDmeVertexData *pBind = pPassedBind ? pPassedBind : pPassedMesh ? pPassedMesh->GetBindBaseState() : NULL;
  2457. CDmeVertexData *pCurr = pPassedCurrent ? pPassedCurrent : pPassedMesh ? pPassedMesh->GetCurrentBaseState() : NULL;
  2458. const CDmeMesh *pMesh = pPassedMesh ? pPassedMesh : pBind ? FindReferringElement< CDmeMesh >( pBind, "baseStates" ) : NULL;
  2459. const CDmeMesh *pBindMesh = pBind ? FindReferringElement< CDmeMesh >( pBind, "baseStates" ) : NULL;
  2460. const CDmeMesh *pCurrMesh = pCurr ? FindReferringElement< CDmeMesh >( pCurr, "baseStates", false ) : NULL;
  2461. const CDmeMesh *pDeltaMesh = pDelta ? FindReferringElement< CDmeMesh >( pDelta, "deltaStates" ) : NULL;
  2462. if ( !pDelta || !pBind || !pCurr || pBind == pCurr || !pMesh || pMesh != pBindMesh || pMesh != pCurrMesh || pMesh != pDeltaMesh )
  2463. {
  2464. return false;
  2465. }
  2466. const FieldIndex_t nBindPosIndex = pBind->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  2467. const FieldIndex_t nBindTexIndex = pBind->FindFieldIndex( CDmeVertexData::FIELD_TEXCOORD );
  2468. const FieldIndex_t nCurrPosIndex = pCurr->FindFieldIndex( CDmeVertexData::FIELD_POSITION );
  2469. if ( nBindPosIndex < 0 || nBindTexIndex < 0 || nCurrPosIndex < 0 )
  2470. return false;
  2471. const CUtlVector< Vector > &bindPos = CDmrArrayConst< Vector >( pBind->GetVertexData( nBindPosIndex ) ).Get();
  2472. const CUtlVector< Vector > &currPos = CDmrArrayConst< Vector >( pCurr->GetVertexData( nCurrPosIndex ) ).Get();
  2473. const CUtlVector< int > &baseTexCoordIndices = pBind->GetVertexIndexData( nBindTexIndex );
  2474. const int nPosCount = bindPos.Count();
  2475. if ( nPosCount != currPos.Count() )
  2476. return false;
  2477. const CDmrArrayConst< Vector2D > texData( pBind->GetVertexData( nBindTexIndex ) );
  2478. const int nBaseTexCoordCount = texData.Count();
  2479. FieldIndex_t nWrinkleIndex = pDelta->FindFieldIndex( CDmeVertexDeltaData::FIELD_WRINKLE );
  2480. if ( nWrinkleIndex < 0 )
  2481. {
  2482. nWrinkleIndex = pDelta->CreateField( CDmeVertexDeltaData::FIELD_WRINKLE );
  2483. }
  2484. float *pOldWrinkleData = NULL;
  2485. if ( wrinkleOp == kAdd )
  2486. {
  2487. // Copy the old wrinkle data
  2488. CDmAttribute *pWrinkleDeltaAttr = pDelta->GetVertexData( nWrinkleIndex );
  2489. if ( pWrinkleDeltaAttr )
  2490. {
  2491. CDmrArrayConst< float > wrinkleDeltaArray( pWrinkleDeltaAttr );
  2492. if ( wrinkleDeltaArray.Count() )
  2493. {
  2494. const CUtlVector< int > &wrinkleDeltaIndices = pDelta->GetVertexIndexData( nWrinkleIndex );
  2495. Assert( wrinkleDeltaIndices.Count() == wrinkleDeltaArray.Count() );
  2496. pOldWrinkleData = reinterpret_cast< float * >( alloca( nBaseTexCoordCount * sizeof( float ) ) );
  2497. memset( pOldWrinkleData, 0, nBaseTexCoordCount * sizeof( float ) );
  2498. int nWrinkleIndex;
  2499. for ( int i = 0; i < wrinkleDeltaIndices.Count(); ++i )
  2500. {
  2501. nWrinkleIndex = wrinkleDeltaIndices[ i ];
  2502. if ( i < nPosCount )
  2503. {
  2504. *( pOldWrinkleData + nWrinkleIndex ) = wrinkleDeltaArray[ i ];
  2505. }
  2506. }
  2507. }
  2508. }
  2509. }
  2510. pDelta->RemoveAllVertexData( nWrinkleIndex );
  2511. if ( flScale == 0.0f && wrinkleOp != kAdd )
  2512. return true;
  2513. float flMaxDeflection = 0.0f;
  2514. int *pWrinkleIndices = reinterpret_cast< int * >( alloca( nPosCount * sizeof( int ) ) );
  2515. float *pWrinkleDelta = reinterpret_cast< float * >( alloca( nPosCount * sizeof( float ) ) );
  2516. int nWrinkleCount = 0;
  2517. float flDelta;
  2518. Vector v;
  2519. const int *pNormalIndices = NULL;
  2520. const Vector *pNormals = NULL;
  2521. if ( bUseNormalForSign )
  2522. {
  2523. const CUtlVector<int> &normalIndices = pBind->GetVertexIndexData( CDmeVertexData::FIELD_NORMAL );
  2524. const CUtlVector< Vector > &normals = pBind->GetNormalData();
  2525. if ( normalIndices.Count() > 0 && normals.Count() > 0 )
  2526. {
  2527. pNormalIndices = normalIndices.Base();
  2528. pNormals = normals.Base();
  2529. }
  2530. else
  2531. {
  2532. Warning( "ComputeNormalWrinkle called but no normals on Mesh: %s\n", pDeltaMesh->GetName() );
  2533. bUseNormalForSign = false;
  2534. }
  2535. }
  2536. if ( pOldWrinkleData || bUseNormalForSign )
  2537. {
  2538. for ( int i = 0; i < nPosCount; ++i )
  2539. {
  2540. v = bindPos[ i ] - currPos[ i ];
  2541. // Figure out the texture indices for this position index
  2542. const CUtlVector< int > &baseVerts = pBind->FindVertexIndicesFromDataIndex( CDmeVertexData::FIELD_POSITION, i );
  2543. for ( int j = 0; j < baseVerts.Count(); ++j )
  2544. {
  2545. // See if we have a delta for this texcoord...
  2546. const int nTexCoordIndex = baseTexCoordIndices[ baseVerts[ j ] ];
  2547. if ( ( pOldWrinkleData && fabs( pOldWrinkleData[ nTexCoordIndex ] ) > 0.0001 ) || fabs( v.x ) >= ( 1 / 4096.0f ) || fabs( v.y ) >= ( 1 / 4096.0f ) || fabs( v.z ) >= ( 1 / 4096.0f ) )
  2548. {
  2549. flDelta = v.NormalizeInPlace();
  2550. if ( flDelta > flMaxDeflection )
  2551. {
  2552. flMaxDeflection = flDelta;
  2553. }
  2554. if ( bUseNormalForSign )
  2555. {
  2556. Vector vNormal = pNormals[ pNormalIndices[ baseVerts[ j ] ] ];
  2557. vNormal.NormalizeInPlace();
  2558. if ( DotProduct( v, vNormal ) < 0 )
  2559. {
  2560. flDelta = -flDelta;
  2561. }
  2562. }
  2563. pWrinkleDelta[ nWrinkleCount ] = flDelta;
  2564. pWrinkleIndices[ nWrinkleCount ] = i;
  2565. ++nWrinkleCount;
  2566. break;
  2567. }
  2568. }
  2569. }
  2570. }
  2571. else
  2572. {
  2573. for ( int i = 0; i < nPosCount; ++i )
  2574. {
  2575. v = bindPos[ i ] - currPos[ i ];
  2576. if ( fabs( v.x ) >= ( 1 / 4096.0f ) || fabs( v.y ) >= ( 1 / 4096.0f ) || fabs( v.z ) >= ( 1 / 4096.0f ) )
  2577. {
  2578. flDelta = v.Length();
  2579. if ( flDelta > flMaxDeflection )
  2580. {
  2581. flMaxDeflection = flDelta;
  2582. }
  2583. pWrinkleDelta[ nWrinkleCount ] = flDelta;
  2584. pWrinkleIndices[ nWrinkleCount ] = i;
  2585. ++nWrinkleCount;
  2586. }
  2587. }
  2588. }
  2589. if ( flMaxDeflection == 0.0f )
  2590. return true;
  2591. const double scaledInverseMaxDeflection = static_cast< double >( flScale ) / static_cast< double >( flMaxDeflection );
  2592. const int nBufSize = ( ( nBaseTexCoordCount + 7 ) >> 3 );
  2593. unsigned char * const pUsedBits = reinterpret_cast< unsigned char* >( alloca( nBufSize * sizeof( unsigned char ) ) );
  2594. memset( pUsedBits, 0, nBufSize );
  2595. for ( int i = 0; i < nWrinkleCount; ++i )
  2596. {
  2597. float flWrinkleDelta = static_cast< float >( static_cast< double >( pWrinkleDelta[ i ] ) * scaledInverseMaxDeflection );
  2598. Assert( fabs( flWrinkleDelta ) <= fabs( flScale ) );
  2599. // NOTE: This will produce bad behavior in cases where two positions share the
  2600. // same texcoord, which shouldn't theoretically happen.
  2601. const CUtlVector< int > &baseVerts = pBind->FindVertexIndicesFromDataIndex( CDmeVertexData::FIELD_POSITION, pWrinkleIndices[ i ] );
  2602. const int nBaseVertCount = baseVerts.Count();
  2603. for ( int j = 0; j < nBaseVertCount; ++j )
  2604. {
  2605. // See if we have a delta for this texcoord...
  2606. int nTexCoordIndex = baseTexCoordIndices[ baseVerts[j] ];
  2607. if ( pUsedBits[ nTexCoordIndex >> 3 ] & ( 1 << ( nTexCoordIndex & 0x7 ) ) )
  2608. continue;
  2609. pUsedBits[ nTexCoordIndex >> 3 ] |= 1 << ( nTexCoordIndex & 0x7 );
  2610. if ( pOldWrinkleData )
  2611. {
  2612. flWrinkleDelta += pOldWrinkleData[ nTexCoordIndex ];
  2613. }
  2614. int nDeltaIndex = pDelta->AddVertexData( nWrinkleIndex, 1 );
  2615. pDelta->SetVertexIndices( nWrinkleIndex, nDeltaIndex, 1, &nTexCoordIndex );
  2616. pDelta->SetVertexData( nWrinkleIndex, nDeltaIndex, 1, AT_FLOAT, &flWrinkleDelta );
  2617. }
  2618. }
  2619. return true;
  2620. }
  2621. //-----------------------------------------------------------------------------
  2622. //
  2623. //-----------------------------------------------------------------------------
  2624. CDmMeshFaceIt::CDmMeshFaceIt( const CDmeMesh *pMesh, const CDmeVertexData *pVertexData /* = NULL */ )
  2625. {
  2626. Reset( pMesh, pVertexData );
  2627. }
  2628. //-----------------------------------------------------------------------------
  2629. //
  2630. //-----------------------------------------------------------------------------
  2631. bool CDmMeshFaceIt::Reset( const CDmeMesh *pMesh, const CDmeVertexData *pVertexData /* = NULL */ )
  2632. {
  2633. m_nFaceIndex = 0;
  2634. if ( pMesh )
  2635. {
  2636. m_pMesh = pMesh;
  2637. m_pVertexData = pVertexData ? pVertexData : m_pVertexData ? m_pVertexData : m_pMesh->GetCurrentBaseState();
  2638. m_nFaceSetCount = 0;
  2639. m_nFaceSetIndex = 0;
  2640. m_pFaceSet = NULL;
  2641. m_nFaceSetIndexCount = 0;
  2642. m_nFaceSetIndexIndex = 0;
  2643. m_nFaceCount = 0;
  2644. // Get number of face sets in current mesh
  2645. m_nFaceSetCount = m_pMesh->FaceSetCount();
  2646. if ( m_nFaceSetCount <= 0 )
  2647. return false;
  2648. // Get number of faces in current mesh
  2649. for ( m_nFaceSetIndex = 0; m_nFaceSetIndex < m_nFaceSetCount; ++m_nFaceSetIndex )
  2650. {
  2651. const CDmeFaceSet *pFaceSet = m_pMesh->GetFaceSet( m_nFaceSetIndex );
  2652. m_nFaceCount += pFaceSet->GetFaceCount();
  2653. }
  2654. }
  2655. else if ( !m_pMesh )
  2656. {
  2657. return false;
  2658. }
  2659. // Set indices to point to first index of first face of first face set, accounting for
  2660. // NULL face sets and NULL faces
  2661. for ( m_nFaceSetIndex = 0; m_nFaceSetIndex < m_nFaceSetCount; ++m_nFaceSetIndex )
  2662. {
  2663. if ( SetFaceSet() )
  2664. return true;
  2665. }
  2666. // All face sets were empty or full of nothing but -1's
  2667. Assert( m_nFaceSetIndex == m_nFaceSetCount );
  2668. Assert( m_nFaceCount == 0 );
  2669. m_pFaceSet = NULL;
  2670. m_nFaceSetIndexCount = 0;
  2671. m_nFaceSetIndexIndex = 0;
  2672. return true;
  2673. }
  2674. //-----------------------------------------------------------------------------
  2675. //
  2676. //-----------------------------------------------------------------------------
  2677. int CDmMeshFaceIt::Count() const
  2678. {
  2679. return m_nFaceCount;
  2680. }
  2681. //-----------------------------------------------------------------------------
  2682. //
  2683. //-----------------------------------------------------------------------------
  2684. int CDmMeshFaceIt::VertexCount() const
  2685. {
  2686. if ( IsDone() )
  2687. return 0;
  2688. return m_pFaceSet->GetNextPolygonVertexCount( m_nFaceSetIndexIndex );
  2689. }
  2690. //-----------------------------------------------------------------------------
  2691. //
  2692. //-----------------------------------------------------------------------------
  2693. bool CDmMeshFaceIt::IsDone() const
  2694. {
  2695. if ( m_nFaceIndex < m_nFaceCount )
  2696. {
  2697. Assert( m_nFaceSetIndex < m_nFaceSetCount );
  2698. Assert( m_nFaceSetIndexIndex < m_nFaceSetIndexCount );
  2699. }
  2700. else
  2701. {
  2702. Assert( m_nFaceSetIndex >= m_nFaceSetCount );
  2703. Assert( m_nFaceSetIndexIndex >= m_nFaceSetIndexCount );
  2704. }
  2705. return m_nFaceIndex >= m_nFaceCount;
  2706. }
  2707. //-----------------------------------------------------------------------------
  2708. //
  2709. //-----------------------------------------------------------------------------
  2710. bool CDmMeshFaceIt::Next()
  2711. {
  2712. // Set indices to point to first index of first face of first face set, accounting for
  2713. // NULL face sets and NULL faces
  2714. while ( m_nFaceSetIndex < m_nFaceSetCount )
  2715. {
  2716. // Skip to next -1 face delimiter
  2717. while ( m_nFaceSetIndexIndex < m_nFaceSetIndexCount )
  2718. {
  2719. if ( m_pFaceSet->GetIndex( m_nFaceSetIndexIndex ) >= 0 )
  2720. break;
  2721. ++m_nFaceSetIndexIndex;
  2722. }
  2723. // Skip to next face index
  2724. while ( m_nFaceSetIndexIndex < m_nFaceSetIndexCount )
  2725. {
  2726. if ( m_pFaceSet->GetIndex( m_nFaceSetIndexIndex ) < 0 )
  2727. break;
  2728. ++m_nFaceSetIndexIndex;
  2729. }
  2730. if ( m_nFaceSetIndexIndex < m_nFaceSetIndexCount )
  2731. {
  2732. ++m_nFaceIndex;
  2733. Assert( m_nFaceIndex < m_nFaceCount );
  2734. return true;
  2735. }
  2736. // Must increment the face set
  2737. ++m_nFaceSetIndex;
  2738. SetFaceSet();
  2739. }
  2740. // At the end of the iteration
  2741. Assert( IsDone() );
  2742. return false;
  2743. }
  2744. //-----------------------------------------------------------------------------
  2745. //
  2746. //-----------------------------------------------------------------------------
  2747. bool CDmMeshFaceIt::SetFaceSet()
  2748. {
  2749. if ( !m_pMesh )
  2750. {
  2751. m_pFaceSet = NULL;
  2752. m_nFaceSetIndexCount = 0;
  2753. m_nFaceSetIndexIndex = 0;
  2754. return false;
  2755. }
  2756. if ( m_nFaceSetIndex >= m_nFaceSetCount )
  2757. {
  2758. m_pFaceSet = NULL;
  2759. m_nFaceSetIndexCount = 0;
  2760. m_nFaceSetIndexIndex = 0;
  2761. return false;
  2762. }
  2763. m_pFaceSet = m_pMesh->GetFaceSet( m_nFaceSetIndex );
  2764. m_nFaceSetIndexCount = m_pFaceSet->NumIndices();
  2765. m_nFaceSetIndexIndex = 0;
  2766. // Skip to the first valid face index
  2767. for ( m_nFaceSetIndexIndex = 0; m_nFaceSetIndexIndex < m_nFaceSetIndexCount; ++m_nFaceSetIndexIndex )
  2768. {
  2769. if ( m_pFaceSet->GetIndex( m_nFaceSetIndex ) >= 0 )
  2770. return true;
  2771. }
  2772. return false;
  2773. }
  2774. //-----------------------------------------------------------------------------
  2775. //
  2776. //-----------------------------------------------------------------------------
  2777. bool CDmMeshFaceIt::GetVertexIndices( int *pIndices, int nIndices ) const
  2778. {
  2779. if ( IsDone() || nIndices != VertexCount() )
  2780. {
  2781. memset( pIndices, 0, nIndices * sizeof( int ) );
  2782. return false;
  2783. }
  2784. int vertexIndex;
  2785. for ( int i = m_nFaceSetIndexIndex; i < m_nFaceSetIndexCount; ++i )
  2786. {
  2787. vertexIndex = m_pFaceSet->GetIndex( i );
  2788. if ( vertexIndex < 0 )
  2789. {
  2790. Assert( i == m_nFaceSetIndexIndex + VertexCount() );
  2791. return true;
  2792. }
  2793. Assert( i < m_nFaceSetIndexIndex + VertexCount() );
  2794. *pIndices = vertexIndex;
  2795. ++pIndices;
  2796. }
  2797. return true;
  2798. }
  2799. //-----------------------------------------------------------------------------
  2800. //
  2801. //-----------------------------------------------------------------------------
  2802. bool CDmMeshFaceIt::GetVertexIndices( CUtlVector< int > &vertexIndices ) const
  2803. {
  2804. vertexIndices.SetCount( VertexCount() );
  2805. if ( IsDone() )
  2806. {
  2807. memset( vertexIndices.Base(), 0, vertexIndices.Count() * sizeof( int ) );
  2808. return false;
  2809. }
  2810. return GetVertexIndices( vertexIndices.Base(), vertexIndices.Count() );
  2811. }
  2812. //-----------------------------------------------------------------------------
  2813. //
  2814. //-----------------------------------------------------------------------------
  2815. int CDmMeshFaceIt::GetVertexIndex( int nFaceRelativeVertexIndex ) const
  2816. {
  2817. if ( IsDone() )
  2818. return -1;
  2819. const int nVertexCount = VertexCount();
  2820. if ( nVertexCount <= 0 || nFaceRelativeVertexIndex < 0 || nFaceRelativeVertexIndex >= nVertexCount )
  2821. return -1;
  2822. int *pVertexIndices = reinterpret_cast< int * >( alloca( nVertexCount * sizeof( int ) ) );
  2823. if ( !GetVertexIndices( pVertexIndices, nVertexCount ) )
  2824. return -1;
  2825. return pVertexIndices[ nFaceRelativeVertexIndex ];
  2826. }
  2827. //-----------------------------------------------------------------------------
  2828. //
  2829. //-----------------------------------------------------------------------------
  2830. void CDmMeshUtils::CreateDeltasFromPresetGroup(
  2831. CDmePresetGroup *pPresetGroup,
  2832. CDmeCombinationOperator * pComboOp,
  2833. const CUtlVector< CUtlString > *pPurgeAllButThese,
  2834. CDmeMesh *pMesh,
  2835. CDmeVertexData *pDst,
  2836. CUtlStringMap< CUtlString > &conflictingNames,
  2837. CUtlStringMap< CDmePreset * > &presetMap )
  2838. {
  2839. const CDmaElementArray< CDmePreset > &presets = pPresetGroup->GetPresets();
  2840. const int nPresetsCount = presets.Count();
  2841. if ( nPresetsCount <= 0 )
  2842. return;
  2843. for ( int i = 0; i < nPresetsCount; ++i )
  2844. {
  2845. pComboOp->SetToBase();
  2846. CDmePreset *pPreset = presets[ i ];
  2847. Assert( !pPreset->IsAnimated() ); // deal with this after GDC
  2848. if ( pPreset->IsAnimated() )
  2849. continue;
  2850. CDmaElementArray< CDmElement > &controlValues = pPreset->GetControlValues();
  2851. const int nControlValues = controlValues.Count();
  2852. for ( int j = 0; j < nControlValues; ++j )
  2853. {
  2854. CDmElement *pControlPreset = controlValues[ j ];
  2855. bool bIsMulti;
  2856. const ControlIndex_t nControlIndex = FindComboOpControlIndexForAnimSetControl( pComboOp, pControlPreset->GetName(), &bIsMulti );
  2857. if ( nControlIndex < 0 )
  2858. continue;
  2859. bool bSkip = false;
  2860. if ( pPurgeAllButThese )
  2861. {
  2862. for ( int k = 0; k < pPurgeAllButThese->Count(); ++k )
  2863. {
  2864. if ( !Q_strcmp( pControlPreset->GetName(), pPurgeAllButThese->Element( k ).Get() ) )
  2865. {
  2866. bSkip = true;
  2867. }
  2868. }
  2869. }
  2870. if ( bSkip )
  2871. continue;
  2872. if ( pComboOp->IsStereoControl( nControlIndex ) )
  2873. {
  2874. pComboOp->SetControlValue(
  2875. nControlIndex,
  2876. pControlPreset->GetValue<float>( "leftValue", 0.0f ),
  2877. pControlPreset->GetValue<float>( "rightValue", 0.0f ) );
  2878. }
  2879. else
  2880. {
  2881. pComboOp->SetControlValue(
  2882. nControlIndex,
  2883. pControlPreset->GetValue< float >( "value", 0.0 ) );
  2884. }
  2885. if ( bIsMulti )
  2886. {
  2887. pComboOp->SetMultiControlLevel(
  2888. nControlIndex,
  2889. pControlPreset->GetValue< float >( "value", 0.5 ) );
  2890. }
  2891. }
  2892. // Pass the control data from the DmeCombinationOperator into the mesh
  2893. pComboOp->Resolve();
  2894. pComboOp->Operate();
  2895. pMesh->Resolve();
  2896. pMesh->SetBaseStateToDeltas( pDst );
  2897. CUtlString presetName = pPreset->GetName();
  2898. // Look for any conflicting pre-existing names
  2899. for ( int presetSuffix = 1; pComboOp->FindControlIndex( presetName ) >= 0 || pMesh->FindDeltaState( presetName ) != NULL || conflictingNames.Defined( presetName ) || presetMap.Defined( presetName ); ++presetSuffix )
  2900. {
  2901. presetName = pPreset->GetName();
  2902. presetName += presetSuffix;
  2903. }
  2904. if ( Q_strcmp( pPreset->GetName(), presetName ) )
  2905. {
  2906. // Had to rename preset... save name for later renaming back
  2907. conflictingNames[ presetName ] = pPreset->GetName();
  2908. }
  2909. presetMap[ presetName ] = pPreset;
  2910. pMesh->ModifyOrCreateDeltaStateFromBaseState( presetName, pDst, true );
  2911. }
  2912. }
  2913. //-----------------------------------------------------------------------------
  2914. //
  2915. //-----------------------------------------------------------------------------
  2916. void CDmMeshUtils::PurgeUnreferencedDeltas( CDmeMesh *pMesh, CUtlStringMap< CDmePreset * > &presetMap, const CUtlVector< CUtlString > *pPurgeAllButThese, CDmeCombinationOperator *pComboOp )
  2917. {
  2918. // Loop because deleting changes indexing
  2919. bool bDeleted = false;
  2920. do
  2921. {
  2922. bDeleted = false;
  2923. for ( int i = 0; i < pMesh->DeltaStateCount(); ++i )
  2924. {
  2925. const char *pDeltaStateName = pMesh->GetDeltaState( i )->GetName();
  2926. if ( presetMap.Defined( pDeltaStateName ) )
  2927. continue;
  2928. bool bDelete = true;
  2929. if ( pPurgeAllButThese )
  2930. {
  2931. for ( int j = 0; j < pPurgeAllButThese->Count(); ++j )
  2932. {
  2933. if ( !Q_strcmp( pDeltaStateName, pPurgeAllButThese->Element( j ).Get() ) )
  2934. {
  2935. bDelete = false;
  2936. break;
  2937. }
  2938. const ControlIndex_t nControlIndex = pComboOp->FindControlIndex( pPurgeAllButThese->Element( j ) );
  2939. if ( nControlIndex < 0 )
  2940. continue;
  2941. for ( int k = 0; k < pComboOp->GetRawControlCount( nControlIndex ); ++k )
  2942. {
  2943. if ( !Q_strcmp( pDeltaStateName, pComboOp->GetRawControlName( nControlIndex, k ) ) )
  2944. {
  2945. bDelete = false;
  2946. break;
  2947. }
  2948. }
  2949. }
  2950. }
  2951. if ( bDelete )
  2952. {
  2953. pMesh->DeleteDeltaState( pDeltaStateName );
  2954. bDeleted = true;
  2955. break;
  2956. }
  2957. }
  2958. } while( bDeleted );
  2959. // Loop because deleting changes indexing
  2960. do
  2961. {
  2962. bDeleted = false;
  2963. for ( int i = 0; i < pComboOp->GetControlCount(); ++i )
  2964. {
  2965. const char *pControlName = pComboOp->GetControlName( i );
  2966. if ( presetMap.Defined( pControlName ) )
  2967. continue;
  2968. bool bDelete = true;
  2969. if ( pPurgeAllButThese )
  2970. {
  2971. for ( int j = 0; j < pPurgeAllButThese->Count(); ++j )
  2972. {
  2973. if ( !Q_strcmp( pControlName, pPurgeAllButThese->Element( j ) ) )
  2974. {
  2975. bDelete = false;
  2976. break;
  2977. }
  2978. }
  2979. }
  2980. if ( bDelete )
  2981. {
  2982. pComboOp->RemoveControl( pControlName );
  2983. bDeleted = true;
  2984. break;
  2985. }
  2986. }
  2987. } while( bDeleted );
  2988. // Rename any that can be renamed... which should be all of them
  2989. for ( int i = 0; i < presetMap.GetNumStrings(); ++i )
  2990. {
  2991. const char *pPresetName = presetMap.String( i );
  2992. CDmePreset *pPreset = presetMap[ i ];
  2993. if ( Q_strcmp( pPreset->GetName(), pPresetName ) )
  2994. {
  2995. const ControlIndex_t nOrigIndex = pComboOp->FindControlIndex( pPreset->GetName() );
  2996. const ControlIndex_t nRenamedIndex = pComboOp->FindControlIndex( pPresetName );
  2997. CDmeVertexDeltaData *pOrigDelta = pMesh->FindDeltaState( pPreset->GetName() );
  2998. CDmeVertexDeltaData *pRenamedDelta = pMesh->FindDeltaState( pPresetName );
  2999. if ( nOrigIndex < 0 && nRenamedIndex >= 0 && pOrigDelta == NULL && pRenamedDelta != NULL )
  3000. {
  3001. pComboOp->RemoveControl( pPresetName );
  3002. pRenamedDelta->SetName( pPreset->GetName() );
  3003. }
  3004. }
  3005. }
  3006. }
  3007. //-----------------------------------------------------------------------------
  3008. // Returns the first DmeModel which is an ancestor of the specified DmeMesh
  3009. //-----------------------------------------------------------------------------
  3010. CDmeModel *CDmMeshUtils::GetDmeModelFromMesh( CDmeMesh *pDmeMesh )
  3011. {
  3012. if ( !pDmeMesh )
  3013. return NULL;
  3014. CUtlStack< CDmeDag * > parentWalk;
  3015. CDmeDag *pDmeDag;
  3016. for ( int i = pDmeMesh->GetParentCount() - 1; i >= 0; --i )
  3017. {
  3018. pDmeDag = pDmeMesh->GetParent( i );
  3019. if ( !pDmeDag )
  3020. continue;
  3021. parentWalk.Push( pDmeDag );
  3022. }
  3023. while ( parentWalk.Count() )
  3024. {
  3025. parentWalk.Pop( pDmeDag );
  3026. if ( !pDmeDag )
  3027. continue;
  3028. if ( CastElement< CDmeModel >( pDmeDag ) )
  3029. return CastElement< CDmeModel >( pDmeDag );
  3030. parentWalk.Push( pDmeDag->GetParent() );
  3031. }
  3032. return NULL;
  3033. }
  3034. //-----------------------------------------------------------------------------
  3035. // Does a depth first walk of the DmeDag hierarchy specified until a DmeDag with the
  3036. // requested name is found, returns that dag if found, NULL if not found or on error
  3037. //-----------------------------------------------------------------------------
  3038. CDmeDag *CDmMeshUtils::FindDagByNameInHierarchy( CDmeDag *pSearchDag, const char *pszSearchName )
  3039. {
  3040. if ( !pSearchDag || !pszSearchName || V_strlen( pszSearchName ) <= 0 )
  3041. return NULL;
  3042. CUtlStack< CDmeDag * > depthFirstStack;
  3043. depthFirstStack.Push( pSearchDag );
  3044. CDmeDag *pDmeDag;
  3045. while ( depthFirstStack.Count() > 0 )
  3046. {
  3047. depthFirstStack.Pop( pDmeDag );
  3048. if ( !pDmeDag )
  3049. continue;
  3050. if ( !V_strcmp( pDmeDag->GetName(), pszSearchName ) )
  3051. return pDmeDag;
  3052. for ( int i = pDmeDag->GetChildCount() - 1; i >= 0; --i )
  3053. {
  3054. depthFirstStack.Push( pDmeDag->GetChild( i ) );
  3055. }
  3056. }
  3057. return NULL;
  3058. }
  3059. //-----------------------------------------------------------------------------
  3060. // Adds the joint to the specified model by finding the common ancestor
  3061. // Duplicates the required hierarchy of the source joint
  3062. //-----------------------------------------------------------------------------
  3063. CDmeDag *CDmMeshUtils::AddJointToModel( CDmeModel *pDstModel, CDmeDag *pSrcJoint )
  3064. {
  3065. if ( !pDstModel || !pSrcJoint || CastElement< CDmeModel >( pSrcJoint ) )
  3066. return NULL;
  3067. // See if the dag is already part of the DmeModel
  3068. if ( pDstModel->GetJointIndex( pSrcJoint ) >= 0 )
  3069. return pSrcJoint;
  3070. // Find it by name in the DmeModel hierarchy
  3071. CDmeDag *pDstDag = FindDagByNameInHierarchy( pDstModel, pSrcJoint->GetName() );
  3072. if ( pDstDag )
  3073. {
  3074. // Same named joint was already in hierarchy just not in model
  3075. // TODO: Warn if joint is not equal to pSrcJoint
  3076. pDstModel->AddJoint( pDstDag );
  3077. // TODO: This is a big hammer, make 'AddJoint' add the base state for just the added joint
  3078. pDstModel->CaptureJointsToBaseState( "bind" );
  3079. pDstModel->Resolve();
  3080. return pDstDag;
  3081. }
  3082. // Walk backwards until we find an ancestor of pSrcJoint that exists in the DstModel
  3083. // or until we get to the DmeModel ancestor of the pSrcJoint
  3084. CDmeDag *pDstParent = pDstModel;
  3085. CUtlStack< CDmeDag * > dupeList;
  3086. dupeList.Push( pSrcJoint );
  3087. for ( CDmeDag *pSrcParent = pSrcJoint->GetParent(); pSrcParent; pSrcParent = pSrcParent->GetParent() )
  3088. {
  3089. // If we've gotten to a CDmeModel then leave the pDstParent as the pDstModel
  3090. if ( CastElement< CDmeModel >( pSrcParent ) )
  3091. break;
  3092. CDmeDag *pTmpDag = FindDagByNameInHierarchy( pDstModel, pSrcParent->GetName() );
  3093. if ( pTmpDag )
  3094. {
  3095. pDstParent = pTmpDag;
  3096. break;
  3097. }
  3098. dupeList.Push( pSrcParent );
  3099. }
  3100. CDmeDag *pSrcDag = NULL;
  3101. matrix3x4a_t mAbs;
  3102. while ( dupeList.Count() )
  3103. {
  3104. dupeList.Pop( pSrcDag );
  3105. if ( !pSrcDag )
  3106. {
  3107. Error( "NULL DmeDag in AddJoint\n" );
  3108. break;
  3109. }
  3110. CDmeDag *pDstDag = pDstModel->AddJoint( pSrcDag->GetName(), pDstParent );
  3111. if ( !pDstDag )
  3112. {
  3113. Error( "Couldn't AddJoint( %s )\n", pSrcDag->GetName() );
  3114. break;
  3115. }
  3116. // Only settings the Abs transform... not copyting any other dynamic attributes
  3117. pSrcDag->GetAbsTransform( mAbs );
  3118. pDstDag->SetAbsTransform( mAbs );
  3119. pDstParent = pDstDag;
  3120. }
  3121. pDstModel->CaptureJointsToBaseState( "bind" );
  3122. return pDstParent;
  3123. }
  3124. //-----------------------------------------------------------------------------
  3125. //
  3126. //-----------------------------------------------------------------------------
  3127. bool CDmMeshUtils::MergeMeshAndSkeleton( CDmeMesh *pDstMesh, CDmeMesh *pSrcMesh )
  3128. {
  3129. if ( !pDstMesh || !pSrcMesh )
  3130. return false;
  3131. CDmeModel *pDstModel = GetDmeModelFromMesh( pDstMesh );
  3132. CDmeModel *pSrcModel = GetDmeModelFromMesh( pSrcMesh );
  3133. CDmeVertexData *pSrcBind = pSrcMesh->GetBindBaseState();
  3134. if ( !pDstModel || !pSrcModel || !pSrcBind || !pSrcBind->HasSkinningData() )
  3135. return false;
  3136. CUtlMap< int, int > jointRemap( CDefOps< int >::LessFunc );
  3137. const FieldIndex_t nSrcJointIndex = pSrcBind->FindFieldIndex( CDmeVertexData::FIELD_JOINT_INDICES );
  3138. if ( nSrcJointIndex < 0 )
  3139. {
  3140. Warning( "No Joints!\n" );
  3141. return false;
  3142. }
  3143. const CDmrArrayConst< int > srcJointIndices = pSrcBind->GetVertexData( nSrcJointIndex );
  3144. for ( int i = 0; i < srcJointIndices.Count(); ++i )
  3145. {
  3146. const int nSrcIndex = srcJointIndices[i];
  3147. if ( jointRemap.IsValidIndex( jointRemap.Find( nSrcIndex ) ) )
  3148. continue;
  3149. CDmeDag *pSrcJoint = pSrcModel->GetJoint( nSrcIndex );
  3150. if ( !pSrcJoint )
  3151. continue;
  3152. CDmeDag *pDstJoint = pDstModel->GetJoint( pSrcJoint->GetName() );
  3153. if ( !pDstJoint )
  3154. {
  3155. pDstJoint = AddJointToModel( pDstModel, pSrcJoint );
  3156. }
  3157. if ( pDstJoint )
  3158. {
  3159. const int nDstIndex = pDstModel->GetJointIndex( pDstJoint );
  3160. Assert( nDstIndex >= 0 );
  3161. jointRemap.InsertOrReplace( nSrcIndex, nDstIndex );
  3162. continue;
  3163. }
  3164. else
  3165. {
  3166. Error( "Can't Add Joint: %s\n", pSrcJoint->GetName() );
  3167. return false;
  3168. }
  3169. }
  3170. Merge( pSrcMesh, pDstMesh, -1, &jointRemap );
  3171. // If there are any other base states on the mesh, just copy the bind base state overtop
  3172. CDmeVertexData *pBindState = pDstMesh->GetBindBaseState();
  3173. if ( pBindState )
  3174. {
  3175. const int nBaseStateCount = pDstMesh->BaseStateCount();
  3176. for ( int i = 0; i < nBaseStateCount; ++i )
  3177. {
  3178. CDmeVertexData *pBaseState = pDstMesh->GetBaseState( i );
  3179. if ( pBindState != pBaseState )
  3180. {
  3181. pBindState->CopyTo( pBaseState );
  3182. }
  3183. }
  3184. }
  3185. return true;
  3186. }