Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1489 lines
45 KiB

  1. //====== Copyright � 1996-2004, Valve Corporation, All rights reserved. =======
  2. //
  3. // Dme version of a skeletal model (gets compiled into a MDL)
  4. //
  5. //=============================================================================
  6. #include "movieobjects/dmemodel.h"
  7. #include "movieobjects_interfaces.h"
  8. #include "datamodel/dmelementfactoryhelper.h"
  9. #include "datacache/imdlcache.h"
  10. #include "materialsystem/imaterialsystem.h"
  11. #include "tier2/tier2.h"
  12. #include "studio.h"
  13. #include "materialsystem/imaterialsystemhardwareconfig.h"
  14. #include "movieobjects/dmemesh.h"
  15. #include "movieobjects/dmechannel.h"
  16. #include "movieobjects/dmelog.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. //-----------------------------------------------------------------------------
  20. // Expose this class to the scene database
  21. //-----------------------------------------------------------------------------
  22. IMPLEMENT_ELEMENT_FACTORY( DmeModel, CDmeModel );
  23. //-----------------------------------------------------------------------------
  24. // Stack of DmeModels currently being rendered. Used to set up render state
  25. //-----------------------------------------------------------------------------
  26. CUtlStack< CDmeModel * > CDmeModel::s_ModelStack;
  27. static CUtlVector< matrix3x4_t > s_PoseToWorld;
  28. //-----------------------------------------------------------------------------
  29. // Purpose:
  30. //-----------------------------------------------------------------------------
  31. void CDmeModel::OnConstruction()
  32. {
  33. m_JointList.Init( this, "jointList" );
  34. m_BaseStates.Init( this, "baseStates" );
  35. m_UpAxis.InitAndSet( this, "upAxis", "Y" );
  36. m_eAxisSystem.InitAndCreate( this, "axisSystem" ); // Defaults to Y up
  37. }
  38. void CDmeModel::OnDestruction()
  39. {
  40. }
  41. //-----------------------------------------------------------------------------
  42. // Add joint
  43. //-----------------------------------------------------------------------------
  44. int CDmeModel::AddJoint( CDmeDag *pJoint )
  45. {
  46. const int nIndex = GetJointIndex( pJoint );
  47. if ( nIndex >= 0 )
  48. return nIndex;
  49. return m_JointList.AddToTail( pJoint );
  50. }
  51. //-----------------------------------------------------------------------------
  52. // Add joint
  53. //-----------------------------------------------------------------------------
  54. CDmeJoint *CDmeModel::AddJoint( const char *pJointName, CDmeDag *pParent )
  55. {
  56. CDmeJoint *pJoint = CreateElement< CDmeJoint >( pJointName, GetFileId() );
  57. CDmeTransform *pTransform = pJoint->GetTransform();
  58. pTransform->SetName( pJointName );
  59. if ( !pParent )
  60. {
  61. pParent = this;
  62. }
  63. pParent->AddChild( pJoint );
  64. m_JointList.AddToTail( pJoint );
  65. return pJoint;
  66. }
  67. //-----------------------------------------------------------------------------
  68. // Returns the number of joint transforms we know about
  69. //-----------------------------------------------------------------------------
  70. int CDmeModel::GetJointCount() const
  71. {
  72. return m_JointList.Count();
  73. }
  74. //-----------------------------------------------------------------------------
  75. // Determines joint transform index given a joint transform
  76. //-----------------------------------------------------------------------------
  77. int CDmeModel::GetJointIndex( CDmeDag *pJoint ) const
  78. {
  79. const int nJointCount = m_JointList.Count();
  80. for ( int i = 0; i < nJointCount; ++i )
  81. {
  82. if ( pJoint == m_JointList[ i ] )
  83. {
  84. return i;
  85. }
  86. }
  87. return -1;
  88. }
  89. //-----------------------------------------------------------------------------
  90. // Determines joint transform index given a joint name
  91. //-----------------------------------------------------------------------------
  92. int CDmeModel::GetJointIndex( const char *pJointName ) const
  93. {
  94. const int nJointCount = m_JointList.Count();
  95. for ( int i = 0; i < nJointCount; ++i )
  96. {
  97. if ( !V_strcmp( pJointName, m_JointList[ i ]->GetName() ) )
  98. {
  99. return i;
  100. }
  101. }
  102. return -1;
  103. }
  104. //-----------------------------------------------------------------------------
  105. // Determines joint transform index given a joint name hash
  106. //-----------------------------------------------------------------------------
  107. int CDmeModel::GetJointIndex( CUtlStringToken nJointNameHash ) const
  108. {
  109. const int nJointCount = m_JointList.Count();
  110. for ( int i = 0; i < nJointCount; ++i )
  111. {
  112. if ( MakeStringToken( m_JointList[ i ]->GetName() ) == nJointNameHash )
  113. {
  114. return i;
  115. }
  116. }
  117. return -1;
  118. }
  119. //-----------------------------------------------------------------------------
  120. // Returns the DmeDag for the specified joint index
  121. //-----------------------------------------------------------------------------
  122. CDmeDag *CDmeModel::GetJoint( int nIndex )
  123. {
  124. return m_JointList[ nIndex ];
  125. }
  126. const CDmeDag *CDmeModel::GetJoint( int nIndex ) const
  127. {
  128. return m_JointList[ nIndex ];
  129. }
  130. //-----------------------------------------------------------------------------
  131. // Determines joint transform index given a joint name
  132. //-----------------------------------------------------------------------------
  133. CDmeTransform *CDmeModel::GetJointTransform( int nIndex )
  134. {
  135. return m_JointList[ nIndex ]->GetTransform();
  136. }
  137. const CDmeTransform *CDmeModel::GetJointTransform( int nIndex ) const
  138. {
  139. return m_JointList[ nIndex ]->GetTransform();
  140. }
  141. //-----------------------------------------------------------------------------
  142. // Finds a base state by name, returns NULL if not found
  143. //-----------------------------------------------------------------------------
  144. CDmeTransformList *CDmeModel::FindBaseState( const char *pBaseStateName )
  145. {
  146. int nCount = m_BaseStates.Count();
  147. for ( int i = 0; i < nCount; ++i )
  148. {
  149. if ( !V_stricmp( m_BaseStates[i]->GetName(), pBaseStateName ) )
  150. return m_BaseStates[i];
  151. }
  152. return NULL;
  153. }
  154. //-----------------------------------------------------------------------------
  155. // Captures the current joint transforms into a base state
  156. //-----------------------------------------------------------------------------
  157. void CDmeModel::CaptureJointsToBaseState( const char *pBaseStateName )
  158. {
  159. CDmeTransformList *pTransformList = FindBaseState( pBaseStateName );
  160. if ( !pTransformList )
  161. {
  162. pTransformList = CreateElement<CDmeTransformList>( pBaseStateName, GetFileId() );
  163. m_BaseStates.AddToTail( pTransformList );
  164. }
  165. // Make the transform list have the correct number of elements
  166. const int nJointCount = m_JointList.Count();
  167. const int nCurrentCount = pTransformList->GetTransformCount();
  168. if ( nJointCount > nCurrentCount )
  169. {
  170. for ( int i = nCurrentCount; i < nJointCount; ++i )
  171. {
  172. CDmeTransform *pTransform = CreateElement<CDmeTransform>( m_JointList[i]->GetName(), pTransformList->GetFileId() );
  173. pTransformList->m_Transforms.AddToTail( pTransform );
  174. }
  175. }
  176. else if ( nJointCount < nCurrentCount )
  177. {
  178. pTransformList->m_Transforms.RemoveMultiple( nJointCount, nCurrentCount - nJointCount );
  179. }
  180. // Copy the state over
  181. for ( int i = 0; i < nJointCount; ++i )
  182. {
  183. matrix3x4_t mat;
  184. CDmeDag *pDmeDag = m_JointList[i];
  185. if ( !pDmeDag )
  186. {
  187. char szTmpBuf0[ 38 ];
  188. UniqueIdToString( GetId(), szTmpBuf0, ARRAYSIZE( szTmpBuf0 ) );
  189. Warning( "DmeModel::CaptureJointsToBaseState( %s ): DmeModel %s[%s].jointList[ %d ] is NULL\n", pBaseStateName, GetName(), szTmpBuf0, i );
  190. continue;
  191. }
  192. CDmeTransform *pDmeTransform = pDmeDag->GetTransform();
  193. if ( !pDmeTransform )
  194. {
  195. char szTmpBuf0[ 38 ];
  196. UniqueIdToString( GetId(), szTmpBuf0, ARRAYSIZE( szTmpBuf0 ) );
  197. char szTmpBuf1[ 38 ];
  198. UniqueIdToString( pDmeDag->GetId(), szTmpBuf1, ARRAYSIZE( szTmpBuf1 ) );
  199. Warning( "DmeModel::CaptureJointsToBaseState( %s ) - DmeModel %s[%s].jointList[ %d ].transform ( %s[%s].transform ) is NULL\n", pBaseStateName, GetName(), szTmpBuf0, i, pDmeDag->GetName(), szTmpBuf1 );
  200. continue;
  201. }
  202. pDmeTransform->GetTransform( mat );
  203. pTransformList->SetTransform( i, mat );
  204. }
  205. }
  206. //-----------------------------------------------------------------------------
  207. // Sets the joint transforms to the values in the specified base state, if it exists
  208. //-----------------------------------------------------------------------------
  209. void CDmeModel::PushBaseStateToJoints( const char *pBaseStateName )
  210. {
  211. CDmeTransformList *pTransformList = FindBaseState( pBaseStateName );
  212. if ( !pTransformList )
  213. return;
  214. for ( int ii = 0; ii < pTransformList->GetTransformCount(); ++ii )
  215. {
  216. CDmeTransform *pSrcDmeTransform = pTransformList->GetTransform( ii );
  217. CDmeDag *pDmeJoint = GetJoint( ii );
  218. if ( !pSrcDmeTransform || !pDmeJoint )
  219. continue;
  220. CDmeTransform *pDstDmeTransform = pDmeJoint->GetTransform();
  221. if ( !pDstDmeTransform )
  222. continue;
  223. pDstDmeTransform->SetPosition( pSrcDmeTransform->GetPosition() );
  224. pDstDmeTransform->SetOrientation( pSrcDmeTransform->GetOrientation() );
  225. }
  226. }
  227. //-----------------------------------------------------------------------------
  228. // Loads up joint transforms for this model
  229. //-----------------------------------------------------------------------------
  230. void CDmeModel::LoadJointTransform( CDmeDag *pJoint, CDmeTransformList *pBindPose, const matrix3x4_t &parentToWorld, const matrix3x4_t &parentToBindPose, bool bSetHardwareState )
  231. {
  232. // Determines joint transform index; no index, no traversing lower in the hierarchy
  233. const int nJointIndex = GetJointIndex( pJoint );
  234. if ( nJointIndex < 0 )
  235. return;
  236. // FIXME: Sucky search here necessary to find bone matrix index
  237. matrix3x4_t jointToWorld, jointToParent;
  238. pJoint->GetTransform()->GetTransform( jointToParent );
  239. ConcatTransforms( parentToWorld, jointToParent, jointToWorld );
  240. matrix3x4_t bindJointToParent, bindPoseToJoint, bindPoseToWorld, jointToBindPose;
  241. if ( pBindPose )
  242. {
  243. if ( nJointIndex >= pBindPose->GetTransformCount() )
  244. {
  245. Warning( "Model is in an invalid state! There are different numbers of bones in the bind pose and joint transform list!\n" );
  246. return;
  247. }
  248. pBindPose->GetTransform( nJointIndex )->GetTransform( bindJointToParent );
  249. }
  250. else
  251. {
  252. MatrixCopy( jointToParent, bindJointToParent );
  253. }
  254. ConcatTransforms( parentToBindPose, bindJointToParent, jointToBindPose );
  255. MatrixInvert( jointToBindPose, bindPoseToJoint );
  256. ConcatTransforms( jointToWorld, bindPoseToJoint, bindPoseToWorld );
  257. if ( bSetHardwareState )
  258. {
  259. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  260. pRenderContext->LoadBoneMatrix( nJointIndex, bindPoseToWorld );
  261. }
  262. MatrixCopy( bindPoseToWorld, s_PoseToWorld[ nJointIndex ] );
  263. int nChildCount = pJoint->GetChildCount();
  264. for ( int i = 0; i < nChildCount; ++i )
  265. {
  266. CDmeDag *pChildJoint = pJoint->GetChild(i);
  267. if ( !pChildJoint )
  268. continue;
  269. LoadJointTransform( pChildJoint, pBindPose, jointToWorld, jointToBindPose, bSetHardwareState );
  270. }
  271. }
  272. //-----------------------------------------------------------------------------
  273. // Sets up the render state for the model
  274. //-----------------------------------------------------------------------------
  275. CDmeModel::SetupBoneRetval_t CDmeModel::SetupBoneMatrixState( const matrix3x4_t& shapeToWorld, bool bForceSoftwareSkin )
  276. {
  277. const int nJointCount = m_JointList.Count();
  278. if ( nJointCount <= 0 )
  279. return NO_SKIN_DATA;
  280. int nBoneBatchCount = g_pMaterialSystemHardwareConfig->MaxVertexShaderBlendMatrices();
  281. bool bSetHardwareState = ( nJointCount <= nBoneBatchCount ) && !bForceSoftwareSkin;
  282. s_PoseToWorld.EnsureCount( nJointCount );
  283. // Finds a base state by name, returns NULL if not found
  284. CDmeTransformList *pBindPose = FindBaseState( "bind" );
  285. matrix3x4_t parentToBindPose;
  286. SetIdentityMatrix( parentToBindPose );
  287. int nChildCount = GetChildCount();
  288. for ( int i = 0; i < nChildCount; ++i )
  289. {
  290. CDmeDag *pChildJoint = GetChild(i);
  291. if ( !pChildJoint )
  292. continue;
  293. LoadJointTransform( pChildJoint, pBindPose, shapeToWorld, parentToBindPose, bSetHardwareState );
  294. }
  295. return bSetHardwareState ? BONES_SET_UP : TOO_MANY_BONES;
  296. }
  297. matrix3x4_t *CDmeModel::SetupModelRenderState( const matrix3x4_t& shapeToWorld, bool bHasSkinningData, bool bForceSoftwareSkin )
  298. {
  299. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  300. if ( bHasSkinningData && ( s_ModelStack.Count() > 0 ) )
  301. {
  302. SetupBoneRetval_t retVal = s_ModelStack.Top()->SetupBoneMatrixState( shapeToWorld, bForceSoftwareSkin );
  303. if ( retVal == TOO_MANY_BONES )
  304. {
  305. pRenderContext->MatrixMode( MATERIAL_MODEL );
  306. pRenderContext->LoadIdentity( );
  307. return s_PoseToWorld.Base();
  308. }
  309. if ( retVal != NO_SKIN_DATA )
  310. return NULL;
  311. }
  312. if ( bForceSoftwareSkin )
  313. {
  314. pRenderContext->MatrixMode( MATERIAL_MODEL );
  315. pRenderContext->LoadIdentity( );
  316. s_PoseToWorld.EnsureCount( 1 );
  317. MatrixCopy( shapeToWorld, s_PoseToWorld[0] );
  318. return s_PoseToWorld.Base();
  319. }
  320. pRenderContext->MatrixMode( MATERIAL_MODEL );
  321. pRenderContext->LoadMatrix( shapeToWorld );
  322. return NULL;
  323. }
  324. void CDmeModel::CleanupModelRenderState()
  325. {
  326. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  327. pRenderContext->MatrixMode( MATERIAL_MODEL );
  328. pRenderContext->LoadIdentity();
  329. }
  330. //-----------------------------------------------------------------------------
  331. // Recursively render the Dag hierarchy
  332. //-----------------------------------------------------------------------------
  333. void CDmeModel::Draw( CDmeDrawSettings *pDrawSettings /* = NULL */ )
  334. {
  335. s_ModelStack.Push( this );
  336. BaseClass::Draw( pDrawSettings );
  337. s_ModelStack.Pop( );
  338. }
  339. //-----------------------------------------------------------------------------
  340. // Set if Z is the up axis of the model
  341. //-----------------------------------------------------------------------------
  342. void CDmeModel::ZUp( bool bZUp )
  343. {
  344. if ( bZUp )
  345. {
  346. // Z up is technically ambiguous, but only Maya created SMD Z Up files, everything else assumes Z up is Valve engine Z up
  347. SetAxisSystem( CDmeAxisSystem::AS_VALVE_ENGINE );
  348. }
  349. else
  350. {
  351. SetAxisSystem( CDmeAxisSystem::AS_MAYA_YUP );
  352. }
  353. }
  354. //-----------------------------------------------------------------------------
  355. // Returns the matrix that moves DmeModel data to engine space
  356. //-----------------------------------------------------------------------------
  357. void CDmeModel::GetModelToEngineMat( matrix3x4_t &modelToEngineMat )
  358. {
  359. CDmeDag::DmeToEngineMatrix( modelToEngineMat, IsZUp() );
  360. }
  361. //-----------------------------------------------------------------------------
  362. // Returns the matrix that moves engine data to DmeModel space
  363. //-----------------------------------------------------------------------------
  364. void CDmeModel::GetEngineToModelMat( matrix3x4_t &engineToModelMat )
  365. {
  366. CDmeDag::EngineToDmeMatrix( engineToModelMat, IsZUp() );
  367. }
  368. //-----------------------------------------------------------------------------
  369. // Returns true if the data under the DmeModel is AS_VALVE_ENGINE_SPACE ( Up: Z, Fwd: X, Left: Y )
  370. // Returns false otherwise, NOTE: false doesn't imply any other axis system, examine m_eAxisSystem to see
  371. //-----------------------------------------------------------------------------
  372. bool CDmeModel::IsZUp() const
  373. {
  374. Assert( m_eAxisSystem.GetElement() );
  375. if ( m_eAxisSystem.GetElement()->IsEqual( CDmeAxisSystem::AS_VALVE_ENGINE ) )
  376. return true;
  377. if ( m_eAxisSystem.GetElement()->IsEqual( CDmeAxisSystem::AS_MAYA_YUP ) )
  378. return false;
  379. AssertMsg( false, "CDmeModel::IsZUp() called, but axis system is neither AS_VALVE_ENGINE or AS_MAYA_YUP, cannot represent via true/false, ambiguous state" );
  380. return false;
  381. }
  382. //-----------------------------------------------------------------------------
  383. // Replace all instances of a material with a different material
  384. //-----------------------------------------------------------------------------
  385. void CDmeModel::ReplaceMaterial( CDmeDag *pDag, const char *pOldMaterialName, const char *pNewMaterialName )
  386. {
  387. if ( !pDag )
  388. return;
  389. CDmeMesh *pMesh = CastElement< CDmeMesh >( pDag->GetShape() );
  390. if ( pMesh )
  391. {
  392. pMesh->ReplaceMaterial( pOldMaterialName, pNewMaterialName );
  393. }
  394. int nCount = pDag->GetChildCount();
  395. for ( int i = 0; i < nCount; ++i )
  396. {
  397. CDmeDag *pChild = pDag->GetChild( i );
  398. ReplaceMaterial( pChild, pOldMaterialName, pNewMaterialName );
  399. }
  400. }
  401. void CDmeModel::ReplaceMaterial( const char *pOldMaterialName, const char *pNewMaterialName )
  402. {
  403. ReplaceMaterial( this, pOldMaterialName, pNewMaterialName );
  404. }
  405. //-----------------------------------------------------------------------------
  406. // Gets the joint with the specified name
  407. //-----------------------------------------------------------------------------
  408. CDmeDag *CDmeModel::GetJoint( const char *pJointName )
  409. {
  410. CDmeDag *pJoint = NULL;
  411. const int nJointCount = m_JointList.Count();
  412. for ( int i = 0; i < nJointCount; ++i )
  413. {
  414. pJoint = m_JointList[ i ];
  415. if ( !pJoint )
  416. continue;
  417. if ( !V_stricmp( pJointName, pJoint->GetName() ) )
  418. return pJoint;
  419. }
  420. return NULL;
  421. }
  422. //-----------------------------------------------------------------------------
  423. //
  424. //-----------------------------------------------------------------------------
  425. void CDmeModel::ReskinMeshes( const int *pJointTransformIndexRemap )
  426. {
  427. ReskinMeshes( this, pJointTransformIndexRemap );
  428. }
  429. //-----------------------------------------------------------------------------
  430. // Reskin meshes based on bone collapse
  431. //-----------------------------------------------------------------------------
  432. void CDmeModel::ReskinMeshes( CDmeDag *pDag, const int *pJointTransformIndexRemap )
  433. {
  434. if ( !pDag )
  435. return;
  436. CDmeMesh *pMesh = CastElement< CDmeMesh >( pDag->GetShape() );
  437. if ( pMesh )
  438. {
  439. pMesh->Reskin( pJointTransformIndexRemap );
  440. }
  441. int nCount = pDag->GetChildCount();
  442. for ( int i = 0; i < nCount; ++i )
  443. {
  444. CDmeDag *pChild = pDag->GetChild( i );
  445. ReskinMeshes( pChild, pJointTransformIndexRemap );
  446. }
  447. }
  448. //-----------------------------------------------------------------------------
  449. // Remove joints
  450. //-----------------------------------------------------------------------------
  451. void CDmeModel::RemoveJoints( int nNewJointCount, const int *pInvJointRemap )
  452. {
  453. const int nOldJointTransformCount = m_JointList.Count();
  454. const int nSizeInBytes = nNewJointCount * sizeof(CDmeTransform*);
  455. CDmeDag **ppJoints = (CDmeDag**)stackalloc( nSizeInBytes );
  456. for ( int i = 0; i < nNewJointCount; ++i )
  457. {
  458. ppJoints[i] = m_JointList[ pInvJointRemap[i] ];
  459. }
  460. m_JointList.RemoveAll();
  461. for ( int i = 0; i < nNewJointCount; ++i )
  462. {
  463. m_JointList.AddToTail( ppJoints[i] );
  464. }
  465. CUtlVectorFixedGrowable< CDmeTransform*, 256 > transforms;
  466. const int nCount = m_BaseStates.Count();
  467. for ( int i = 0; i < nCount; ++i )
  468. {
  469. CDmeTransformList *pList = m_BaseStates[i];
  470. int nTransformCount = pList->GetTransformCount();
  471. transforms.SetCount( nTransformCount );
  472. int nStateJointCount = nNewJointCount;
  473. for ( int j = 0; j < nNewJointCount; ++j )
  474. {
  475. transforms[j] = pList->GetTransform( pInvJointRemap[j] );
  476. }
  477. for ( int j = nOldJointTransformCount; j < nTransformCount; ++j )
  478. {
  479. transforms[ nStateJointCount++ ] = pList->GetTransform( j );
  480. }
  481. pList->m_Transforms.RemoveAll();
  482. for ( int j = 0; j < nStateJointCount; ++j )
  483. {
  484. pList->m_Transforms.AddToTail( transforms[ j ] );
  485. }
  486. }
  487. }
  488. //-----------------------------------------------------------------------------
  489. // Updates all base states by adding missing joints
  490. //-----------------------------------------------------------------------------
  491. void CDmeModel::UpdateBaseStates()
  492. {
  493. const int nJointCount = m_JointList.Count();
  494. for ( int i = 0; i < m_BaseStates.Count(); ++i )
  495. {
  496. CDmeTransformList *pTransformList = m_BaseStates[i];
  497. if ( !pTransformList )
  498. continue;
  499. // Make the transform list have the correct number of elements
  500. const int nCurrentCount = pTransformList->GetTransformCount();
  501. if ( nJointCount < nCurrentCount )
  502. {
  503. pTransformList->m_Transforms.RemoveMultiple( nJointCount, nCurrentCount - nJointCount );
  504. return;
  505. }
  506. else if ( nJointCount == nCurrentCount )
  507. {
  508. return;
  509. }
  510. Assert( nJointCount > nCurrentCount );
  511. for ( int i = nCurrentCount; i < nJointCount; ++i )
  512. {
  513. CDmeTransform *pTransform = CreateElement<CDmeTransform>( m_JointList[i]->GetName(), pTransformList->GetFileId() );
  514. pTransformList->m_Transforms.AddToTail( pTransform );
  515. matrix3x4_t mat;
  516. CDmeDag *pDmeDag = m_JointList[i];
  517. if ( !pDmeDag )
  518. continue;
  519. CDmeTransform *pDmeTransform = pDmeDag->GetTransform();
  520. if ( !pDmeTransform )
  521. continue;
  522. pDmeTransform->GetTransform( mat );
  523. pTransformList->SetTransform( i, mat );
  524. }
  525. }
  526. }
  527. //-----------------------------------------------------------------------------
  528. // Removes all children from this joint, moving shapes to be
  529. //-----------------------------------------------------------------------------
  530. void CDmeModel::RemoveAllChildren( CDmeDag *pDag, CDmeDag *pSubtreeRoot, const matrix3x4_t &jointToSubtreeRoot )
  531. {
  532. if ( !pDag )
  533. return;
  534. CDmeTransform *pDagTransform = pDag->GetTransform();
  535. matrix3x4_t curToSubtreeRoot, dagToParent;
  536. pDagTransform->GetTransform( dagToParent );
  537. ConcatTransforms( jointToSubtreeRoot, dagToParent, curToSubtreeRoot );
  538. if ( !CastElement< CDmeJoint >( pDag ) )
  539. {
  540. pSubtreeRoot->AddChild( pDag );
  541. pDagTransform->SetTransform( curToSubtreeRoot );
  542. }
  543. int nCount = pDag->GetChildCount();
  544. for ( int i = 0; i < nCount; ++i )
  545. {
  546. RemoveAllChildren( pDag->GetChild(i), pSubtreeRoot, curToSubtreeRoot );
  547. }
  548. pDag->RemoveAllChildren();
  549. }
  550. void CDmeModel::RemoveAllChildren( CDmeDag *pSubtreeRoot )
  551. {
  552. matrix3x4_t root;
  553. SetIdentityMatrix( root );
  554. int nCount = pSubtreeRoot->GetChildCount();
  555. for ( int i = 0; i < nCount; ++i )
  556. {
  557. CDmeDag *pChild = pSubtreeRoot->GetChild(i);
  558. if ( !CastElement< CDmeJoint >( pChild ) )
  559. continue;
  560. RemoveAllChildren( pChild, pSubtreeRoot, root );
  561. }
  562. // Regetting the child count, as it has changed from the RemoveAllChildren calls
  563. nCount = pSubtreeRoot->GetChildCount();
  564. for ( int i = nCount; --i >= 0; )
  565. {
  566. if ( !CastElement< CDmeJoint >( pSubtreeRoot->GetChild(i) ) )
  567. continue;
  568. pSubtreeRoot->RemoveChild( i );
  569. }
  570. }
  571. //-----------------------------------------------------------------------------
  572. // Collapses all joints below the specified joint name, reskinning any meshes
  573. // referring to collapsed joints to use the specified joint instead
  574. //-----------------------------------------------------------------------------
  575. void CDmeModel::CollapseJoints( const char *pJointName )
  576. {
  577. CDmeDag *pJoint = GetJoint( pJointName );
  578. if ( !pJoint )
  579. return;
  580. // Determine which joints must be collapsed
  581. CDmeDag *pParent;
  582. const int nCount = m_JointList.Count();
  583. bool *pIsCollapsed = (bool*)stackalloc( nCount * sizeof(bool) );
  584. for ( int i = 0; i < nCount; ++i )
  585. {
  586. CDmeDag *pTestJoint = m_JointList[ i ];
  587. if ( !pTestJoint )
  588. continue;
  589. pIsCollapsed[i] = ( pJoint->FindChild( pParent, pTestJoint ) >= 0 );
  590. }
  591. // Build remap indices
  592. int nNewJointCount = 0;
  593. int nCollapseJointIndex = 0;
  594. int* pJointRemap = (int*)stackalloc( nCount * sizeof(int) );
  595. int* pInvJointRemap = (int*)stackalloc( nCount * sizeof(int) );
  596. for ( int i = 0; i < nCount; ++i )
  597. {
  598. if ( pIsCollapsed[i] )
  599. {
  600. pJointRemap[i] = -1;
  601. continue;
  602. }
  603. if ( pJoint == m_JointList[i] )
  604. {
  605. nCollapseJointIndex = nNewJointCount;
  606. }
  607. pInvJointRemap[nNewJointCount] = i;
  608. pJointRemap[i] = nNewJointCount++;
  609. }
  610. for ( int i = 0; i < nCount; ++i )
  611. {
  612. if ( pJointRemap[i] < 0 )
  613. {
  614. pJointRemap[i] = nCollapseJointIndex;
  615. }
  616. }
  617. // Reskin meshes
  618. ReskinMeshes( this, pJointRemap );
  619. // Fixup joint transform + base state lists
  620. RemoveJoints( nNewJointCount, pInvJointRemap );
  621. // Remove all children from this node
  622. RemoveAllChildren( pJoint );
  623. stackfree( pIsCollapsed );
  624. stackfree( pJointRemap );
  625. stackfree( pInvJointRemap );
  626. }
  627. //-----------------------------------------------------------------------------
  628. // Returns the matrix & quaternion to reorient
  629. //-----------------------------------------------------------------------------
  630. void CDmeModel::GetReorientData( matrix3x4_t &m, Quaternion &q, bool bMakeZUp )
  631. {
  632. // YUP_ACTIVE: FIXME
  633. if ( bMakeZUp )
  634. {
  635. static const matrix3x4_t mYtoZ(
  636. 0.0f, 0.0f, 1.0f, 0.0f,
  637. 1.0f, 0.0f, 0.0f, 0.0f,
  638. 0.0f, 1.0f, 0.0f, 0.0f );
  639. m = mYtoZ;
  640. matrix3x4a_t mA;
  641. CDmeAxisSystem::GetConversionMatrix( mA, CDmeAxisSystem::AS_MAYA_YUP, CDmeAxisSystem::AS_VALVE_ENGINE );
  642. Assert( MatricesAreEqual( mYtoZ, mA ) );
  643. }
  644. else
  645. {
  646. static const matrix3x4_t mZtoY(
  647. 0.0f, 1.0f, 0.0f, 0.0f,
  648. 0.0f, 0.0f, 1.0f, 0.0f,
  649. 1.0f, 0.0f, 0.0f, 0.0f );
  650. m = mZtoY;
  651. matrix3x4a_t mA;
  652. CDmeAxisSystem::GetConversionMatrix( mA, CDmeAxisSystem::AS_VALVE_ENGINE, CDmeAxisSystem::AS_MAYA_YUP );
  653. Assert( MatricesAreEqual( mZtoY, mA, 1.0e-4 ) );
  654. }
  655. MatrixQuaternion( m, q );
  656. }
  657. //-----------------------------------------------------------------------------
  658. //
  659. //-----------------------------------------------------------------------------
  660. void CDmeModel::ReorientDmeAnimation( CDmeDag *pDmeDag, const matrix3x4_t &mOrient, const Quaternion &qOrient )
  661. {
  662. if ( !pDmeDag )
  663. return;
  664. CUtlVector< CDmeChannel * > dmeChannelList;
  665. if ( !FindReferringElements( dmeChannelList, pDmeDag->GetTransform(), g_pDataModel->GetSymbol( "toElement" ) ) || dmeChannelList.Count() < 0 )
  666. return;
  667. const int nDmeChannelCount = dmeChannelList.Count();
  668. for ( int i = 0; i < nDmeChannelCount; ++i )
  669. {
  670. CDmeChannel *pDmeChannel = dmeChannelList[ i ];
  671. if ( !pDmeChannel )
  672. continue;
  673. CDmeLog *pDmeLog = pDmeChannel->GetLog();
  674. if ( !pDmeLog )
  675. continue;
  676. const int nLogLayerCount = pDmeLog->GetNumLayers();
  677. for ( int j = 0; j < nLogLayerCount; ++j )
  678. {
  679. CDmeLogLayer *pDmeLogLayer = pDmeLog->GetLayer( j );
  680. CDmeVector3LogLayer *pDmeVector3LogLayer = CastElement< CDmeVector3LogLayer >( pDmeLogLayer );
  681. if ( pDmeVector3LogLayer )
  682. {
  683. RotatePositionLog( pDmeVector3LogLayer, mOrient );
  684. continue;
  685. }
  686. CDmeQuaternionLogLayer *pDmeQuaternionLogLayer = CastElement< CDmeQuaternionLogLayer >( pDmeLogLayer );
  687. if ( pDmeQuaternionLogLayer )
  688. {
  689. RotateOrientationLog( pDmeQuaternionLogLayer, mOrient, true );
  690. continue;
  691. }
  692. }
  693. }
  694. }
  695. //-----------------------------------------------------------------------------
  696. //
  697. //-----------------------------------------------------------------------------
  698. void CDmeModel::ReorientDmeTransform( CDmeTransform *pDmeTransform, const matrix3x4_t &mOrient, const Quaternion &qOrient )
  699. {
  700. if ( !pDmeTransform )
  701. return;
  702. Vector vTmp;
  703. VectorRotate( pDmeTransform->GetPosition(), mOrient, vTmp );
  704. pDmeTransform->SetPosition( vTmp );
  705. Quaternion qTmp;
  706. QuaternionMult( qOrient, pDmeTransform->GetOrientation(), qTmp );
  707. pDmeTransform->SetOrientation( qTmp );
  708. }
  709. //-----------------------------------------------------------------------------
  710. // Changes the orientation of the vertices and normals of a CDmeMesh using
  711. // the given transform.
  712. //-----------------------------------------------------------------------------
  713. void CDmeModel::ReorientDmeMesh( CDmeMesh *pDmeMesh, matrix3x4_t absMat )
  714. {
  715. CDisableUndoScopeGuard();
  716. CDmeVertexData *pDmeVertexData = pDmeMesh->GetBindBaseState();
  717. FieldIndex_t nFieldPosIndex = pDmeVertexData->FindFieldIndex( CDmeVertexDataBase::FIELD_POSITION );
  718. FieldIndex_t nFieldNormIndex = pDmeVertexData->FindFieldIndex( CDmeVertexDataBase::FIELD_NORMAL );
  719. if ( nFieldPosIndex >= 0 && nFieldNormIndex > 0 )
  720. {
  721. CDmAttribute *pDmPositionAttr = pDmeVertexData->GetVertexData( nFieldPosIndex );
  722. CDmAttribute *pDmNormalAttr = pDmeVertexData->GetVertexData( nFieldNormIndex );
  723. CDmrArray< Vector > positions( pDmPositionAttr );
  724. CDmrArray< Vector > normals( pDmNormalAttr );
  725. CUtlVector<Vector> newPositions;
  726. matrix3x4_t normalMat;
  727. MatrixInverseTranspose( absMat, normalMat );
  728. for ( int i = 0; i < positions.Count(); ++i )
  729. {
  730. Vector newPosition;
  731. VectorTransform( positions[i], absMat, newPosition );
  732. positions.Set( i, newPosition );
  733. }
  734. for ( int i = 0; i < normals.Count(); ++i )
  735. {
  736. Vector normalizedNormal;
  737. Vector newNormal;
  738. VectorCopy( normals[i], normalizedNormal );
  739. VectorNormalize( normalizedNormal );
  740. VectorRotate( normalizedNormal, normalMat, newNormal );
  741. normals.Set( i, newNormal );
  742. }
  743. }
  744. }
  745. //-----------------------------------------------------------------------------
  746. //
  747. //-----------------------------------------------------------------------------
  748. void CDmeModel::ReorientDmeModelChildren( CDmeModel *pDmeModel, const matrix3x4_t &mOrient, const Quaternion &qOrient )
  749. {
  750. if ( !pDmeModel )
  751. return;
  752. CDmeTransformList *pDmeTransformList = pDmeModel->FindBaseState( "bind" );
  753. const int nTransformCount = pDmeTransformList ? pDmeTransformList->GetTransformCount() : 0;
  754. const int nChildCount = pDmeModel->GetChildCount();
  755. for ( int i = 0; i < nChildCount; ++i )
  756. {
  757. CDmeDag *pDmeDag = pDmeModel->GetChild( i );
  758. if ( !pDmeDag )
  759. continue;
  760. ReorientDmeTransform( pDmeDag->GetTransform(), mOrient, qOrient );
  761. if ( pDmeTransformList )
  762. {
  763. int nJointIndex = pDmeModel->GetJointIndex( pDmeDag );
  764. if ( nJointIndex >= 0 && nJointIndex < nTransformCount )
  765. {
  766. ReorientDmeTransform( pDmeTransformList->GetTransform( nJointIndex ), mOrient, qOrient );
  767. }
  768. }
  769. ReorientDmeAnimation( pDmeDag, mOrient, qOrient );
  770. }
  771. }
  772. //-----------------------------------------------------------------------------
  773. // Changes the orientation of a given CDmeDag's mesh data and those of any
  774. // children the CDmeDag has.
  775. //-----------------------------------------------------------------------------
  776. void CDmeModel::ReorientChildDmeMeshes_R( CDmeDag *pDmeDag )
  777. {
  778. // Reorient the Dag's shape
  779. CDmeMesh *pDmeMesh = CastElement< CDmeMesh >( pDmeDag->GetShape() );
  780. if ( pDmeMesh )
  781. {
  782. matrix3x4_t absMat;
  783. pDmeDag->GetAbsTransform( absMat );
  784. ReorientDmeMesh( pDmeMesh, absMat );
  785. }
  786. // Recurse all child CDmeDags and
  787. const int nChildCount = pDmeDag->GetChildCount();
  788. for ( int i = 0; i < nChildCount; ++i )
  789. {
  790. ReorientChildDmeMeshes_R( pDmeDag->GetChild( i ) );
  791. }
  792. }
  793. //-----------------------------------------------------------------------------
  794. // Walks through the immediate children of this DmeModel and bakes the world
  795. // space transform of any DmeMesh into its vertices and then sets the transform
  796. // of that mesh to the identity. Currently only called by hammer import and
  797. // hammer <-> modo in modo via ReorientToEngineSpace & ReorientToDCCToolSpace
  798. // dmeutils to convert DmeMesh to CMesh uses ReorientToValveEngineSpace
  799. // which does not call FreezeChildMeshes. FreezeChildMeshes is also not a
  800. // complete implementation as it doesn't take into account deltas on meshes
  801. //-----------------------------------------------------------------------------
  802. void CDmeModel::FreezeChildMeshes()
  803. {
  804. const int nChildCount = GetChildCount();
  805. for ( int i = 0; i < nChildCount; ++i )
  806. {
  807. CDmeDag *pDmeDag = GetChild( i );
  808. if ( !pDmeDag )
  809. continue;
  810. ReorientChildDmeMeshes_R( pDmeDag );
  811. // Zero out the rotation since ReorientChildDmeMeshes_R bakes it into the mesh
  812. CDmeTransform *pTransform = pDmeDag->GetTransform();
  813. if ( pTransform )
  814. {
  815. Quaternion qZero;
  816. qZero.Init();
  817. pTransform->SetOrientation( qZero );
  818. }
  819. }
  820. }
  821. //-----------------------------------------------------------------------------
  822. //
  823. //-----------------------------------------------------------------------------
  824. bool CDmeModel::SetAxisSystem( CDmeAxisSystem::PredefinedAxisSystem ePredefAxisSystem )
  825. {
  826. if ( !m_eAxisSystem.GetElement() )
  827. return false;
  828. return m_eAxisSystem.GetElement()->Init( ePredefAxisSystem );
  829. }
  830. //-----------------------------------------------------------------------------
  831. //
  832. //-----------------------------------------------------------------------------
  833. bool CDmeModel::SetAxisSystem(
  834. CDmeAxisSystem::Axis_t eUpAxis,
  835. CDmeAxisSystem::ForwardParity_t eForwardParity,
  836. CDmeAxisSystem::CoordSys_t eCoordSys /* = CDmeAxisSystem::AS_RIGHT_HANDED */ )
  837. {
  838. if ( !m_eAxisSystem.GetElement() )
  839. return false;
  840. return m_eAxisSystem.GetElement()->Init( eUpAxis, eForwardParity, eCoordSys );
  841. }
  842. //-----------------------------------------------------------------------------
  843. // This expects the app has handled undo
  844. //-----------------------------------------------------------------------------
  845. bool CDmeModel::ConvertToAxisSystem( CDmeAxisSystem::PredefinedAxisSystem eToPredefinedAxisSystem )
  846. {
  847. if ( !m_eAxisSystem.GetElement() )
  848. return false;
  849. CDmeAxisSystem::Axis_t eToUpAxis;
  850. CDmeAxisSystem::ForwardParity_t eToForwardParity;
  851. CDmeAxisSystem::CoordSys_t eToCoordSys;
  852. if ( !CDmeAxisSystem::GetPredefinedAxisSystem( eToUpAxis, eToForwardParity, eToCoordSys, eToPredefinedAxisSystem ) )
  853. return false;
  854. return ConvertToAxisSystem( eToUpAxis, eToForwardParity, eToCoordSys );
  855. }
  856. //-----------------------------------------------------------------------------
  857. // This expects the app has handled undo
  858. //-----------------------------------------------------------------------------
  859. bool CDmeModel::ConvertToAxisSystem(
  860. CDmeAxisSystem::Axis_t eToUpAxis,
  861. CDmeAxisSystem::ForwardParity_t eToForwardParity,
  862. CDmeAxisSystem::CoordSys_t eToCoordSys /* = CDmeAxisSystem::AS_RIGHT_HANDED */ )
  863. {
  864. if ( !m_eAxisSystem.GetElement() )
  865. return false;
  866. if ( !CDmeAxisSystem::IsValid( eToUpAxis, eToForwardParity, eToCoordSys ) )
  867. return false;
  868. const CDmeAxisSystem *pFromDmeAxisSystem = m_eAxisSystem.GetElement();
  869. Assert( pFromDmeAxisSystem->IsValid() );
  870. const CDmeAxisSystem::Axis_t eFromUpAxis = pFromDmeAxisSystem->GetUpAxis();
  871. const CDmeAxisSystem::ForwardParity_t eFromForwardParity = pFromDmeAxisSystem->GetForwardParity();
  872. const CDmeAxisSystem::CoordSys_t eFromCoordSys = pFromDmeAxisSystem->GetCoordSys();
  873. Assert( CDmeAxisSystem::IsValid( eToUpAxis, eToForwardParity, eToCoordSys ) );
  874. if ( eFromUpAxis == eToUpAxis &&
  875. eFromForwardParity == eToForwardParity &&
  876. eFromCoordSys == eToCoordSys )
  877. {
  878. // No change needed
  879. return true;
  880. }
  881. matrix3x4a_t mConversion = g_MatrixIdentity;
  882. CDmeAxisSystem::GetConversionMatrix( mConversion, eFromUpAxis, eFromForwardParity, eFromCoordSys, eToUpAxis, eToForwardParity, eToCoordSys );
  883. const Quaternion qConversion = MatrixQuaternion( mConversion );
  884. ReorientDmeModelChildren( this, mConversion, qConversion );
  885. m_UpAxis.Set( "axisSystem" );
  886. return SetAxisSystem( eToUpAxis, eToForwardParity, eToCoordSys );
  887. }
  888. //-----------------------------------------------------------------------------
  889. //
  890. //-----------------------------------------------------------------------------
  891. bool CDmeModel::GetConversionMatrix( matrix3x4a_t &mConversion, CDmeAxisSystem::PredefinedAxisSystem eToPredefinedAxisSystem )
  892. {
  893. const CDmeAxisSystem *pFromDmeAxisSystem = m_eAxisSystem.GetElement();
  894. Assert( pFromDmeAxisSystem->IsValid() );
  895. const CDmeAxisSystem::Axis_t eFromUpAxis = pFromDmeAxisSystem->GetUpAxis();
  896. const CDmeAxisSystem::ForwardParity_t eFromForwardParity = pFromDmeAxisSystem->GetForwardParity();
  897. const CDmeAxisSystem::CoordSys_t eFromCoordSys = pFromDmeAxisSystem->GetCoordSys();
  898. CDmeAxisSystem::Axis_t eToUpAxis;
  899. CDmeAxisSystem::ForwardParity_t eToForwardParity;
  900. CDmeAxisSystem::CoordSys_t eToCoordSys;
  901. if ( !CDmeAxisSystem::GetPredefinedAxisSystem( eToUpAxis, eToForwardParity, eToCoordSys, eToPredefinedAxisSystem ) )
  902. return false;
  903. CDmeAxisSystem::GetConversionMatrix( mConversion, eFromUpAxis, eFromForwardParity, eFromCoordSys, eToUpAxis, eToForwardParity, eToCoordSys );
  904. return true;
  905. }
  906. //-----------------------------------------------------------------------------
  907. //
  908. //-----------------------------------------------------------------------------
  909. void CDmeModel::TransformScene(
  910. const Vector &vScale /*= Vector( 1.0f, 1.0f, 1.0f )*/,
  911. const Vector &vTranslate /*= vec3_origin*/,
  912. const DegreeEuler &eRotation /*= DegreeEuler( 0.0f, 0.0f, 0.0f )*/,
  913. float flEps /*= 1.0e-4 */ )
  914. {
  915. if ( !VectorsAreEqual( vScale, Vector( 1.0f, 1.0f, 1.0f ), flEps ) )
  916. {
  917. ScaleScene( vScale );
  918. }
  919. if ( !VectorsAreEqual( vTranslate, vec3_origin, flEps ) || !DegreeEulersAreEqual( eRotation, DegreeEuler( 0.0f, 0.0f, 0.0f ), flEps ) )
  920. {
  921. matrix3x4a_t mTransform;
  922. AngleMatrix( RadianEuler( eRotation ), vTranslate, mTransform );
  923. matrix3x4a_t mIdentity;
  924. SetIdentityMatrix( mIdentity );
  925. matrix3x4a_t mDag;
  926. CDmeTransform *pDmeModelTransform = GetTransform();
  927. pDmeModelTransform->GetTransform( mDag );
  928. if ( MatricesAreEqual( mDag, mIdentity, flEps ) )
  929. {
  930. // DmeModel is just a group, leave it alone, put transform on all children
  931. const int nChildCount = GetChildCount();
  932. for ( int i = 0; i < nChildCount; ++i )
  933. {
  934. CDmeDag *pDmeDagChild = GetChild( i );
  935. CDmeTransform *pDmeTransform = pDmeDagChild->GetTransform();
  936. pDmeTransform->GetTransform( mDag );
  937. pDmeTransform->SetTransform( ConcatTransforms( mTransform, mDag ) );
  938. }
  939. }
  940. else
  941. {
  942. // DmeModel has transformation data of its own... put transform on it
  943. pDmeModelTransform->SetTransform( ConcatTransforms( mTransform, mDag ) );
  944. }
  945. }
  946. CaptureJointsToBaseState( "bind" );
  947. }
  948. //-----------------------------------------------------------------------------
  949. //
  950. //-----------------------------------------------------------------------------
  951. void CDmeModel::ScaleScene( const Vector &vScale )
  952. {
  953. CUtlStack< CDmeDag * > depthFirstStack;
  954. depthFirstStack.Push( this );
  955. while ( depthFirstStack.Count() > 0 )
  956. {
  957. CDmeDag *pDmeDag = depthFirstStack.Top();
  958. depthFirstStack.Pop();
  959. if ( !pDmeDag )
  960. continue;
  961. const int nChildCount = pDmeDag->GetChildCount();
  962. for ( int i = nChildCount + 1; i >= 0; --i )
  963. {
  964. depthFirstStack.Push( pDmeDag->GetChild( i ) );
  965. }
  966. CDmeTransform *pDmeTransform = pDmeDag->GetTransform();
  967. Vector vLocalPos = pDmeTransform->GetPosition();
  968. vLocalPos.x *= vScale.x;
  969. vLocalPos.y *= vScale.y;
  970. vLocalPos.z *= vScale.z;
  971. pDmeTransform->SetPosition( vLocalPos );
  972. matrix3x4a_t mScale;
  973. SetScaleMatrix( vScale, mScale );
  974. matrix3x4a_t mScaleInvTranspose;
  975. MatrixInverseTranspose( mScale, mScaleInvTranspose );
  976. CDmeMesh *pDmeMesh = CastElement< CDmeMesh >( pDmeDag->GetShape() );
  977. if ( pDmeMesh )
  978. {
  979. CUtlVector< CDmeVertexDataBase * > vertexDataList;
  980. const int nStateCount = pDmeMesh->BaseStateCount();
  981. for ( int i = 0; i < nStateCount; ++i )
  982. {
  983. CDmeVertexDataBase *pDmeVertexData = pDmeMesh->GetBaseState( i );
  984. if ( pDmeVertexData )
  985. {
  986. vertexDataList.AddToTail( pDmeVertexData );
  987. }
  988. }
  989. // TODO: See if delta data needs to be scaled differently, positions shouldn't but normals might
  990. const int nDeltaStateCount = pDmeMesh->DeltaStateCount();
  991. for ( int i = 0; i < nDeltaStateCount; ++i )
  992. {
  993. CDmeVertexDataBase *pDmeVertexData = pDmeMesh->GetDeltaState( i );
  994. if ( pDmeVertexData )
  995. {
  996. vertexDataList.AddToTail( pDmeVertexData );
  997. }
  998. }
  999. const int nVertexDataCount = vertexDataList.Count();
  1000. for ( int i = 0; i < nVertexDataCount; ++i )
  1001. {
  1002. CDmeVertexDataBase *pDmeVertexData = vertexDataList[i];
  1003. const FieldIndex_t nPosFieldIndex = pDmeVertexData->FindFieldIndex( CDmeVertexDataBase::FIELD_POSITION );
  1004. if ( nPosFieldIndex >= 0 )
  1005. {
  1006. CDmrArray< Vector > vertexData = pDmeVertexData->GetVertexData( nPosFieldIndex );
  1007. const int nDataCount = vertexData.Count();
  1008. for ( int j = 0; j < nDataCount; ++j )
  1009. {
  1010. vertexData.Set( j, VectorTransform( vertexData.Get( j ), mScale ) );
  1011. }
  1012. }
  1013. const FieldIndex_t nNormalFieldIndex = pDmeVertexData->FindFieldIndex( CDmeVertexDataBase::FIELD_NORMAL );
  1014. if ( nPosFieldIndex >= 0 )
  1015. {
  1016. CDmrArray< Vector > vertexData = pDmeVertexData->GetVertexData( nNormalFieldIndex );
  1017. const int nDataCount = vertexData.Count();
  1018. for ( int j = 0; j < nDataCount; ++j )
  1019. {
  1020. vertexData.Set( j, VectorTransform( vertexData.Get( j ), mScaleInvTranspose ).Normalized() );
  1021. }
  1022. }
  1023. }
  1024. }
  1025. }
  1026. }
  1027. #if 0
  1028. //-----------------------------------------------------------------------------
  1029. // temp function for validation of code changes, used by CompareDmeDag_R
  1030. //-----------------------------------------------------------------------------
  1031. static bool CompareDmeMeshes( CDmeMesh *pDmeMeshA, CDmeMesh *pDmeMeshB )
  1032. {
  1033. if ( !pDmeMeshA && !pDmeMeshB )
  1034. return true;
  1035. if ( !pDmeMeshA || !pDmeMeshB )
  1036. return false;
  1037. pDmeMeshA->Resolve();
  1038. pDmeMeshB->Resolve();
  1039. if ( pDmeMeshA->BaseStateCount() != pDmeMeshB->BaseStateCount() )
  1040. {
  1041. AssertMsg( 0, "DmeMesh BaseStateCount mismatch: %s:%d vs %s:%d\n", pDmeMeshA->GetName(), pDmeMeshA->BaseStateCount(), pDmeMeshB->GetName(), pDmeMeshB->BaseStateCount() );
  1042. return false;
  1043. }
  1044. CDmeVertexData *pDmeVertexDataA = pDmeMeshA->GetBindBaseState();
  1045. CDmeVertexData *pDmeVertexDataB = pDmeMeshB->GetBindBaseState();
  1046. if ( !pDmeVertexDataA && !pDmeVertexDataB )
  1047. return true; // No vertex data in bind base state... not really a good state but they are the same
  1048. if ( !pDmeVertexDataA || !pDmeVertexDataB )
  1049. {
  1050. AssertMsg( 0, "DmeMesh one NULL BindBaseState: %s:0x%p vs %s:0x%p\n", pDmeMeshA->GetName(), pDmeVertexDataA, pDmeMeshB->GetName(), pDmeVertexDataB );
  1051. return false;
  1052. }
  1053. pDmeVertexDataA->Resolve();
  1054. pDmeVertexDataB->Resolve();
  1055. const CUtlVector< Vector > &posDataA = pDmeVertexDataA->GetPositionData();
  1056. const CUtlVector< Vector > &posDataB = pDmeVertexDataB->GetPositionData();
  1057. if ( posDataA.Count() != posDataB.Count() )
  1058. {
  1059. AssertMsg( 0, "DmeMesh posData count mismatch: %s:%d vs %s:%d\n", pDmeMeshA->GetName(), posDataA.Count(), pDmeMeshB->GetName(), posDataB.Count() );
  1060. return false;
  1061. }
  1062. for ( int i = 0; i < posDataA.Count(); ++i )
  1063. {
  1064. if ( !VectorsAreEqual( posDataA[i], posDataB[i] ) )
  1065. {
  1066. AssertMsg( 0, "DmeMesh posData vector mismatch: %d %s:< %6.2f %6.2f %6.2f > vs %s:< %6.2f %6.2f %6.2f >\n",
  1067. i,
  1068. pDmeMeshA->GetName(),
  1069. posDataA[i].x,
  1070. posDataA[i].y,
  1071. posDataA[i].z,
  1072. pDmeMeshB->GetName(),
  1073. posDataB[i].x,
  1074. posDataB[i].y,
  1075. posDataB[i].z );
  1076. return false;
  1077. }
  1078. }
  1079. const CUtlVector< Vector > &normalDataA = pDmeVertexDataA->GetNormalData();
  1080. const CUtlVector< Vector > &normalDataB = pDmeVertexDataB->GetNormalData();
  1081. if ( normalDataA.Count() != normalDataB.Count() )
  1082. {
  1083. AssertMsg( 0, "DmeMesh normalData count mismatch: %s:%d vs %s:%d\n", pDmeMeshA->GetName(), normalDataA.Count(), pDmeMeshB->GetName(), normalDataB.Count() );
  1084. return false;
  1085. }
  1086. for ( int i = 0; i < normalDataA.Count(); ++i )
  1087. {
  1088. if ( !VectorsAreEqual( normalDataA[i], normalDataB[i] ) )
  1089. {
  1090. AssertMsg( 0, "DmeMesh normalData vector mismatch: %d %s:< %6.2f %6.2f %6.2f > vs %s:< %6.2f %6.2f %6.2f >\n",
  1091. i,
  1092. pDmeMeshA->GetName(),
  1093. normalDataA[i].x,
  1094. normalDataA[i].y,
  1095. normalDataA[i].z,
  1096. pDmeMeshB->GetName(),
  1097. normalDataB[i].x,
  1098. normalDataB[i].y,
  1099. normalDataB[i].z );
  1100. return false;
  1101. }
  1102. }
  1103. return true;
  1104. }
  1105. //-----------------------------------------------------------------------------
  1106. // temp function for validation of code changes, used by CompareDmeDag_R
  1107. //-----------------------------------------------------------------------------
  1108. static bool CompareDmeDag_R( CDmeDag *pDmeDagA, CDmeDag *pDmeDagB )
  1109. {
  1110. // Both NULL, Ok
  1111. if ( !pDmeDagA && !pDmeDagB )
  1112. return true;
  1113. // Only one NULL, bad
  1114. if ( !pDmeDagA || !pDmeDagB )
  1115. {
  1116. AssertMsg( 0, "One Dag NULL, the other isn't: 0x%p vs 0x%p\n", pDmeDagA, pDmeDagB );
  1117. return false;
  1118. }
  1119. // Names don't match, bad
  1120. if ( V_strcmp( pDmeDagA->GetName(), pDmeDagB->GetName() ) )
  1121. {
  1122. AssertMsg( 0, "Shape name mismatch: %s vs %s\n", pDmeDagA->GetName(), pDmeDagB->GetName() );
  1123. return false;
  1124. }
  1125. // Transforms don't match, bad
  1126. CDmeTransform *pDmeTransformA = pDmeDagA->GetTransform();
  1127. CDmeTransform *pDmeTransformB = pDmeDagB->GetTransform();
  1128. if ( pDmeTransformA && pDmeTransformB )
  1129. {
  1130. matrix3x4a_t mA;
  1131. pDmeTransformA->GetTransform( mA );
  1132. matrix3x4a_t mB;
  1133. pDmeTransformB->GetTransform( mB );
  1134. if ( !MatricesAreEqual( mA, mB ) )
  1135. {
  1136. AssertMsg( 0, "Matrix mismatch" );
  1137. return false;
  1138. }
  1139. }
  1140. else if ( pDmeTransformA || pDmeTransformB )
  1141. {
  1142. AssertMsg( 0, "One DmeTransform NULL, the other isn't: %s 0x%p vs %s 0x%p \n", pDmeDagA->GetName(), pDmeTransformA, pDmeDagB->GetName(), pDmeTransformB );
  1143. return false;
  1144. }
  1145. // Compare shapes, if they exist
  1146. CDmeShape *pDmeShapeA = pDmeDagA->GetShape();
  1147. CDmeShape *pDmeShapeB = pDmeDagB->GetShape();
  1148. if ( pDmeShapeA && pDmeShapeB )
  1149. {
  1150. if ( pDmeShapeA->GetType() != pDmeShapeB->GetType() )
  1151. {
  1152. AssertMsg( 0, "Shape type mismatch: %s vs %s\n", pDmeShapeA->GetTypeString(), pDmeShapeB->GetTypeString() );
  1153. return false;
  1154. }
  1155. if ( pDmeShapeA->IsA( CDmeMesh::GetStaticTypeSymbol() ) )
  1156. {
  1157. if ( !CompareDmeMeshes( CastElement< CDmeMesh >( pDmeShapeA ), CastElement< CDmeMesh >( pDmeShapeB ) ) )
  1158. {
  1159. AssertMsg( 0, "Mesh Mismatch: %s vs %s\n", pDmeShapeA->GetName(), pDmeShapeB->GetName() );
  1160. return false;
  1161. }
  1162. }
  1163. }
  1164. else if ( pDmeShapeA || pDmeShapeB )
  1165. {
  1166. AssertMsg( 0, "One Shape NULL, the other isn't: 0x%p vs 0x%p\n", pDmeShapeA, pDmeShapeB );
  1167. return false;
  1168. }
  1169. // Child count don't match, bad
  1170. const int nChildCountA = pDmeDagA->GetChildCount();
  1171. const int nChildCountB = pDmeDagB->GetChildCount();
  1172. if ( nChildCountA != nChildCountB )
  1173. return false;
  1174. // Compare their children
  1175. for ( int i = 0; i < nChildCountA; ++i )
  1176. {
  1177. if ( !CompareDmeDag_R( pDmeDagA->GetChild( i ), pDmeDagB->GetChild( i ) ) )
  1178. return false;
  1179. }
  1180. return true;
  1181. }
  1182. //-----------------------------------------------------------------------------
  1183. // temp function for validation of code changes, used by CompareDmeDag_R
  1184. //-----------------------------------------------------------------------------
  1185. static void ResolveDmeDagHierarchy_R( CDmeDag *pDmeDag )
  1186. {
  1187. if ( !pDmeDag )
  1188. return;
  1189. pDmeDag->Resolve();
  1190. CDmeShape *pDmeShape = pDmeDag->GetShape();
  1191. if ( pDmeShape )
  1192. {
  1193. pDmeShape->Resolve();
  1194. CDmeMesh *pDmeMesh = CastElement< CDmeMesh >( pDmeShape );
  1195. if ( pDmeMesh )
  1196. {
  1197. pDmeMesh->Resolve();
  1198. for ( int i = 0; i < pDmeMesh->BaseStateCount(); ++i )
  1199. {
  1200. CDmeVertexData *pDmeVertexData = pDmeMesh->GetBaseState( i );
  1201. if ( pDmeVertexData )
  1202. {
  1203. pDmeVertexData->Resolve();
  1204. }
  1205. }
  1206. }
  1207. }
  1208. for ( int i = 0; i < pDmeDag->GetChildCount(); ++i )
  1209. {
  1210. ResolveDmeDagHierarchy_R( pDmeDag->GetChild( i ) );
  1211. }
  1212. }
  1213. #endif // 0