Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3313 lines
93 KiB

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