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.

1464 lines
42 KiB

  1. //====== Copyright (c) 1996-2009, Valve Corporation, All rights reserved. =====
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. // Valve includes
  7. #include "tier1/utlstack.h"
  8. #include "movieobjects/dmeanimationlist.h"
  9. #include "movieobjects/dmechannel.h"
  10. #include "movieobjects/dmeconnectionoperator.h"
  11. #include "movieobjects/dmelog.h"
  12. #include "mdlobjects/dmebbox.h"
  13. #include "mdlobjects/dmebodygrouplist.h"
  14. #include "mdlobjects/dmebodygroup.h"
  15. #include "mdlobjects/dmecollisionmodel.h"
  16. #include "mdlobjects/dmeeyeball.h"
  17. #include "mdlobjects/dmeeyeballglobals.h"
  18. #include "mdlobjects/dmeik.h"
  19. #include "mdlobjects/dmelodlist.h"
  20. #include "mdlobjects/dmelod.h"
  21. #include "mdlobjects/dmesequencelist.h"
  22. #include "mdlobjects/dmesequence.h"
  23. #include "mdlobjects/dmedefinebonelist.h"
  24. #include "mdlobjects/dmedefinebone.h"
  25. #include "mdlobjects/mpp_utils.h"
  26. //-----------------------------------------------------------------------------
  27. // Returns the matrix & quaternion to reorient
  28. //-----------------------------------------------------------------------------
  29. void GetReorientData( matrix3x4_t &m, Quaternion &q, bool bMakeZUp )
  30. {
  31. if ( bMakeZUp )
  32. {
  33. static const matrix3x4_t mYtoZ(
  34. 1.0f, 0.0f, 0.0f, 0.0f,
  35. 0.0f, 0.0f, -1.0f, 0.0f,
  36. 0.0f, 1.0f, 0.0f, 0.0f );
  37. m = mYtoZ;
  38. }
  39. else
  40. {
  41. static const matrix3x4_t mZtoY(
  42. 1.0f, 0.0f, 0.0f, 0.0f,
  43. 0.0f, 0.0f, 1.0f, 0.0f,
  44. 0.0f, -1.0f, 0.0f, 0.0f );
  45. m = mZtoY;
  46. }
  47. MatrixQuaternion( m, q );
  48. }
  49. //-----------------------------------------------------------------------------
  50. //
  51. //-----------------------------------------------------------------------------
  52. void ReorientDmeAnimation( CDmeDag *pDmeDag, const matrix3x4_t &mOrient, const Quaternion &qOrient )
  53. {
  54. if ( !pDmeDag )
  55. return;
  56. CUtlVector< CDmeChannel * > dmeChannelList;
  57. if ( !FindReferringElements( dmeChannelList, pDmeDag->GetTransform(), g_pDataModel->GetSymbol( "toElement" ) ) || dmeChannelList.Count() < 0 )
  58. return;
  59. const int nDmeChannelCount = dmeChannelList.Count();
  60. for ( int i = 0; i < nDmeChannelCount; ++i )
  61. {
  62. CDmeChannel *pDmeChannel = dmeChannelList[ i ];
  63. if ( !pDmeChannel )
  64. continue;
  65. CDmeLog *pDmeLog = pDmeChannel->GetLog();
  66. if ( !pDmeLog )
  67. continue;
  68. const int nLogLayerCount = pDmeLog->GetNumLayers();
  69. for ( int j = 0; j < nLogLayerCount; ++j )
  70. {
  71. CDmeLogLayer *pDmeLogLayer = pDmeLog->GetLayer( j );
  72. CDmeVector3LogLayer *pDmeVector3LogLayer = CastElement< CDmeVector3LogLayer >( pDmeLogLayer );
  73. if ( pDmeVector3LogLayer )
  74. {
  75. RotatePositionLog( pDmeVector3LogLayer, mOrient );
  76. continue;
  77. }
  78. CDmeQuaternionLogLayer *pDmeQuaternionLogLayer = CastElement< CDmeQuaternionLogLayer >( pDmeLogLayer );
  79. if ( pDmeQuaternionLogLayer )
  80. {
  81. RotateOrientationLog( pDmeQuaternionLogLayer, mOrient, true );
  82. continue;
  83. }
  84. }
  85. }
  86. }
  87. //-----------------------------------------------------------------------------
  88. //
  89. //-----------------------------------------------------------------------------
  90. void ReorientDmeTransform( CDmeTransform *pDmeTransform, const matrix3x4_t &mOrient, const Quaternion &qOrient )
  91. {
  92. if ( !pDmeTransform )
  93. return;
  94. Vector vTmp;
  95. VectorRotate( pDmeTransform->GetPosition(), mOrient, vTmp );
  96. pDmeTransform->SetPosition( vTmp );
  97. Quaternion qTmp;
  98. QuaternionMult( qOrient, pDmeTransform->GetOrientation(), qTmp );
  99. pDmeTransform->SetOrientation( qTmp );
  100. }
  101. //-----------------------------------------------------------------------------
  102. //
  103. //-----------------------------------------------------------------------------
  104. void ReorientDmeDefineBone( CDmeDefineBone *pDmeDefineBone, const matrix3x4_t &mOrient, const Quaternion &qOrient )
  105. {
  106. if ( !pDmeDefineBone )
  107. return;
  108. Vector vTmp;
  109. VectorRotate( pDmeDefineBone->m_Translation, mOrient, vTmp );
  110. pDmeDefineBone->m_Translation = vTmp;
  111. Quaternion qTmp0;
  112. Quaternion qTmp1;
  113. QAngle aTmp;
  114. AngleQuaternion( pDmeDefineBone->m_Rotation, qTmp0 );
  115. QuaternionMult( qOrient, qTmp0, qTmp1 );
  116. QuaternionAngles( qTmp1, aTmp );
  117. pDmeDefineBone->m_Rotation = aTmp;
  118. // Don't touch realign rotation for now
  119. /*
  120. VectorRotate( pDmeDefineBone->m_RealignTranslation, mOrient, vTmp );
  121. pDmeDefineBone->m_RealignTranslation = vTmp;
  122. AngleQuaternion( pDmeDefineBone->m_RealignRotation, qTmp0 );
  123. QuaternionMult( qOrient, qTmp0, qTmp1 );
  124. QuaternionAngles( qTmp1, aTmp );
  125. pDmeDefineBone->m_RealignRotation = aTmp;
  126. */
  127. }
  128. //-----------------------------------------------------------------------------
  129. //
  130. //-----------------------------------------------------------------------------
  131. void ReorientDmeModelChildren( CDmeModel *pDmeModel, const matrix3x4_t &mOrient, const Quaternion &qOrient, CDmeDefineBoneList *pDmeDefineBoneList, bool bDefineBoneDone )
  132. {
  133. if ( !pDmeModel )
  134. return;
  135. CDmeTransformList *pDmeTransformList = pDmeModel->FindBaseState( "bind" );
  136. const int nTransformCount = pDmeTransformList ? pDmeTransformList->GetTransformCount() : 0;
  137. const int nChildCount = pDmeModel->GetChildCount();
  138. for ( int i = 0; i < nChildCount; ++i )
  139. {
  140. CDmeDag *pDmeDag = pDmeModel->GetChild( i );
  141. if ( !pDmeDag )
  142. continue;
  143. ReorientDmeTransform( pDmeDag->GetTransform(), mOrient, qOrient );
  144. // TODO: Separate out DmeDefineBoneList
  145. if ( !bDefineBoneDone && pDmeDefineBoneList )
  146. {
  147. for ( int j = 0; j < pDmeDefineBoneList->m_DefineBones.Count(); ++j )
  148. {
  149. CDmeDefineBone *pDmeDefineBone = pDmeDefineBoneList->m_DefineBones[j];
  150. if ( !pDmeDefineBone )
  151. continue;
  152. if ( Q_strcmp( pDmeDag->GetName(), pDmeDefineBone->GetName() ) )
  153. continue;
  154. ReorientDmeDefineBone( pDmeDefineBone, mOrient, qOrient );
  155. }
  156. }
  157. if ( pDmeTransformList )
  158. {
  159. int nJointIndex = pDmeModel->GetJointIndex( pDmeDag );
  160. if ( nJointIndex >= 0 && nJointIndex < nTransformCount )
  161. {
  162. ReorientDmeTransform( pDmeTransformList->GetTransform( nJointIndex ), mOrient, qOrient );
  163. }
  164. }
  165. ReorientDmeAnimation( pDmeDag, mOrient, qOrient );
  166. }
  167. }
  168. //-----------------------------------------------------------------------------
  169. //
  170. //-----------------------------------------------------------------------------
  171. bool ReorientDmeModel( CDmeModel *pDmeModel, bool bMakeZUp, CDmeDefineBoneList *pDmeDefineBoneList, bool bDefineBoneDone )
  172. {
  173. if ( !pDmeModel )
  174. return false;
  175. if ( bMakeZUp == pDmeModel->IsZUp() )
  176. return true; // Nothing to do
  177. matrix3x4_t m;
  178. Quaternion q;
  179. GetReorientData( m, q, bMakeZUp );
  180. ReorientDmeModelChildren( pDmeModel, m, q, pDmeDefineBoneList, bDefineBoneDone );
  181. pDmeModel->ZUp( true );
  182. return true;
  183. }
  184. //-----------------------------------------------------------------------------
  185. //
  186. //-----------------------------------------------------------------------------
  187. bool ReorientDmeModel( CDmeModel *pDmeModel, bool bMakeZUp )
  188. {
  189. return ReorientDmeModel( pDmeModel, bMakeZUp, NULL, true );
  190. }
  191. //-----------------------------------------------------------------------------
  192. //
  193. //-----------------------------------------------------------------------------
  194. bool ReorientDmxModelFile( CDmElement *pDmElementRoot, bool bMakeZUp )
  195. {
  196. if ( !pDmElementRoot )
  197. return false;
  198. const bool bModel = ReorientDmeModel( pDmElementRoot->GetValueElement< CDmeModel >( "model" ), bMakeZUp );
  199. const bool bSkel = ReorientDmeModel( pDmElementRoot->GetValueElement< CDmeModel >( "skeleton" ), bMakeZUp );
  200. const char *pSrcFile = g_pDataModel->GetFileName( pDmElementRoot->GetFileId() );
  201. if ( pSrcFile && *pSrcFile )
  202. {
  203. char szPath[ MAX_PATH ];
  204. Q_strncpy( szPath, pSrcFile, sizeof( szPath ) );
  205. Q_SetExtension( szPath, "zup", sizeof( szPath ) );
  206. g_pDataModel->SaveToFile( szPath, NULL, "keyvalues2", "model", pDmElementRoot );
  207. }
  208. return bModel || bSkel;
  209. }
  210. //-----------------------------------------------------------------------------
  211. //
  212. //-----------------------------------------------------------------------------
  213. void ReorientIkRuleList( CDmeSequence *pDmeSimpleSequence, const matrix3x4_t &m )
  214. {
  215. if ( !pDmeSimpleSequence )
  216. return;
  217. const int nIkRuleCount = pDmeSimpleSequence->m_eIkRuleList.Count();
  218. if ( nIkRuleCount <= 0 )
  219. return;
  220. for ( int i = 0; i < nIkRuleCount; ++i )
  221. {
  222. CDmeIkRule *pDmeIkRule = pDmeSimpleSequence->m_eIkRuleList[ i ];
  223. if ( !pDmeIkRule )
  224. continue;
  225. CDmeIkAttachmentRule *pDmeIkAttachmentRule = CastElement< CDmeIkAttachmentRule >( pDmeIkRule );
  226. if ( pDmeIkAttachmentRule )
  227. {
  228. if ( pDmeIkAttachmentRule->HasAttribute( "fallbackPosition", AT_VECTOR3 ) )
  229. {
  230. Vector p;
  231. VectorIRotate( pDmeIkAttachmentRule->GetValue< Vector >( "fallbackPosition" ), m, p );
  232. pDmeIkAttachmentRule->SetValue< Vector >( "fallbackPosition", p );
  233. }
  234. }
  235. }
  236. }
  237. //-----------------------------------------------------------------------------
  238. //
  239. //-----------------------------------------------------------------------------
  240. void ReorientSequenceList( CDmeSequenceList *pDmeSequenceList, bool bMakeZUp, const matrix3x4_t &m )
  241. {
  242. if ( !pDmeSequenceList )
  243. return;
  244. const int nSequenceCount = pDmeSequenceList->m_Sequences.Count();
  245. for ( int i = 0; i < nSequenceCount; ++i )
  246. {
  247. CDmeSequence *pDmeSimpleSequence = CastElement< CDmeSequence >( pDmeSequenceList->m_Sequences[i] );
  248. if ( !pDmeSimpleSequence )
  249. continue;
  250. ReorientDmeModel( CastElement< CDmeModel >( pDmeSimpleSequence->m_eSkeleton.GetElement() ), bMakeZUp );
  251. ReorientIkRuleList( pDmeSimpleSequence, m );
  252. }
  253. }
  254. //-----------------------------------------------------------------------------
  255. //
  256. //-----------------------------------------------------------------------------
  257. void ReorientGlobalFlags( CDmElement *pDmeRoot, const matrix3x4_t &m )
  258. {
  259. if ( !pDmeRoot )
  260. return;
  261. CDmeBBox *pDmeBBox = pDmeRoot->GetValueElement< CDmeBBox >( "bbox" );
  262. if ( pDmeBBox )
  263. {
  264. Vector bbmn;
  265. Vector bbmx;
  266. ITransformAABB( m, pDmeBBox->m_vMinBounds, pDmeBBox->m_vMaxBounds, bbmn, bbmx );
  267. pDmeBBox->m_vMinBounds = bbmn;
  268. pDmeBBox->m_vMaxBounds = bbmx;
  269. }
  270. if ( pDmeRoot->HasAttribute( "illuminationPosition", AT_VECTOR3 ) )
  271. {
  272. Vector vIllumPosition;
  273. VectorIRotate( pDmeRoot->GetValue< Vector >( "illuminationPosition" ), m, vIllumPosition );
  274. pDmeRoot->SetValue< Vector >( "illuminationPosition", vIllumPosition );
  275. }
  276. }
  277. //-----------------------------------------------------------------------------
  278. //
  279. //-----------------------------------------------------------------------------
  280. void ReorientEyeballGlobals( CDmeEyeballGlobals *pDmeEyeballGlobals, const matrix3x4_t &m )
  281. {
  282. if ( !pDmeEyeballGlobals )
  283. return;
  284. Vector vEyePosition;
  285. VectorIRotate( pDmeEyeballGlobals->m_vEyePosition.Get(), m, vEyePosition );
  286. }
  287. //-----------------------------------------------------------------------------
  288. //
  289. //-----------------------------------------------------------------------------
  290. void ReorientEyeballs( CDmeLODList *pDmeLODList, const matrix3x4_t &m )
  291. {
  292. if ( !pDmeLODList )
  293. return;
  294. const int nEyeballCount = pDmeLODList->m_EyeballList.Count();
  295. if ( nEyeballCount <= 0 )
  296. return;
  297. for ( int nEyeballIndex = 0; nEyeballIndex < nEyeballCount; ++nEyeballIndex )
  298. {
  299. CDmeEyeball *pDmeEyeball = pDmeLODList->m_EyeballList.Get( nEyeballIndex );
  300. if ( !pDmeEyeball )
  301. continue;
  302. }
  303. }
  304. //-----------------------------------------------------------------------------
  305. //
  306. // Returns true is the rest of the MPP file should be reoriented
  307. // Returns false if the orientation could not be determined or
  308. // it's already oriented correctly
  309. //
  310. //-----------------------------------------------------------------------------
  311. bool ReorientBodyGroupList( CDmeBodyGroupList *pDmeBodyGroupList, CDmeDefineBoneList *pDmeDefineBoneList, bool bMakeZUp, const matrix3x4_t &m )
  312. {
  313. if ( !pDmeBodyGroupList )
  314. return false;
  315. bool bUpAxisSet = false;
  316. bool bZUp = false;
  317. bool bDefineBoneDone = false;
  318. const int nBodyGroupCount = pDmeBodyGroupList->m_BodyGroups.Count();
  319. for ( int i = 0; i < nBodyGroupCount; ++i )
  320. {
  321. CDmeBodyGroup *pDmeBodyGroup = pDmeBodyGroupList->m_BodyGroups[i];
  322. if ( !pDmeBodyGroup )
  323. continue;
  324. const int nBodyPartCount = pDmeBodyGroup->m_BodyParts.Count();
  325. for ( int j = 0; j < nBodyPartCount; ++j )
  326. {
  327. CDmeBodyPart *pDmeBodyPart = pDmeBodyGroup->m_BodyParts[j];
  328. CDmeLODList *pDmeLODList = CastElement< CDmeLODList >( pDmeBodyPart );
  329. if ( !pDmeBodyPart || !pDmeLODList || pDmeBodyPart->LODCount() == 0 )
  330. continue;
  331. const int nLODCount = pDmeLODList->m_LODs.Count();
  332. for ( int k = 0; k < nLODCount; ++k )
  333. {
  334. CDmeLOD *pDmeLOD = pDmeLODList->m_LODs[k];
  335. if ( !pDmeLOD )
  336. continue;
  337. CDmeModel *pDmeModel = pDmeLOD->m_Model.GetElement();
  338. if ( !pDmeModel )
  339. continue;
  340. if ( !bUpAxisSet )
  341. {
  342. bZUp = pDmeModel->IsZUp();
  343. bUpAxisSet = true;
  344. }
  345. else
  346. {
  347. if ( pDmeModel->IsZUp() != bZUp )
  348. {
  349. Warning( "Z Up Mismatch\n" );
  350. }
  351. }
  352. if ( bZUp != bMakeZUp )
  353. {
  354. ReorientDmeModel( pDmeModel, bMakeZUp, pDmeDefineBoneList, bDefineBoneDone );
  355. if ( !bDefineBoneDone )
  356. {
  357. bDefineBoneDone = true;
  358. }
  359. ReorientEyeballs( pDmeLODList, m );
  360. }
  361. }
  362. }
  363. }
  364. return bZUp != bMakeZUp;
  365. }
  366. //-----------------------------------------------------------------------------
  367. //
  368. //-----------------------------------------------------------------------------
  369. void ReorientCollisionModel( CDmeCollisionModel *pDmeCollisionModel, bool bMakeZUp )
  370. {
  371. if ( !pDmeCollisionModel )
  372. return;
  373. ReorientDmeModel( pDmeCollisionModel->GetValueElement< CDmeModel >( "model" ), bMakeZUp );
  374. }
  375. //-----------------------------------------------------------------------------
  376. // Reorients everything in an MPP file
  377. //-----------------------------------------------------------------------------
  378. void ReorientMppFile( CDmElement *pRoot, bool bMakeZUp )
  379. {
  380. matrix3x4_t m;
  381. Quaternion q;
  382. GetReorientData( m, q, bMakeZUp );
  383. if ( ReorientBodyGroupList(
  384. pRoot->GetValueElement< CDmeBodyGroupList >( "bodyGroupList" ),
  385. pRoot->GetValueElement< CDmeDefineBoneList >( "defineBoneList" ),
  386. bMakeZUp, m ) )
  387. {
  388. ReorientGlobalFlags( pRoot, m );
  389. ReorientCollisionModel( pRoot->GetValueElement< CDmeCollisionModel >( "collisionModel" ), bMakeZUp );
  390. ReorientEyeballGlobals( pRoot->GetValueElement< CDmeEyeballGlobals >( "eyeballGlobals" ), m );
  391. ReorientSequenceList( pRoot->GetValueElement< CDmeSequenceList >( "sequenceList" ), bMakeZUp, m );
  392. }
  393. else
  394. {
  395. // Msg( "File Already %s Up\n", bMakeZUp ? "Z" : "Y" );
  396. }
  397. }
  398. //-----------------------------------------------------------------------------
  399. //
  400. //-----------------------------------------------------------------------------
  401. void MppReorient( CDmElement *pRoot, bool bMakeZUp )
  402. {
  403. ReorientMppFile( pRoot, bMakeZUp );
  404. }
  405. //-----------------------------------------------------------------------------
  406. // Get a list of all DmeDag nodes which are the ancestors of the
  407. // specified node. Returns false if this cannot be computed because
  408. // of a cycle or a NULL DmeDag was passed
  409. //
  410. // + hierarchyList[0] // Root
  411. // + hierarchyList[1] // 0 is parent of 1
  412. // + hierarchyList[2] // 1 is parent of 2
  413. // ...
  414. // + hierarchyList[n] == pDmeDag //
  415. //
  416. //-----------------------------------------------------------------------------
  417. bool GetDagHierarchy( CUtlVector< CDmeDag * > &hierarchyList, CDmeDag *pDmeDag )
  418. {
  419. if ( !pDmeDag )
  420. return false;
  421. CUtlRBTree< DmElementHandle_t > visited( DefLessFunc( DmElementHandle_t ) );
  422. hierarchyList.RemoveAll();
  423. for ( ; pDmeDag; pDmeDag = pDmeDag->GetParent() )
  424. {
  425. if ( visited.IsValidIndex( visited.Find( pDmeDag->GetHandle() ) ) )
  426. {
  427. // Found a cycle
  428. return false;
  429. }
  430. visited.Insert( pDmeDag->GetHandle() );
  431. hierarchyList.AddToHead( pDmeDag );
  432. }
  433. return true;
  434. }
  435. //-----------------------------------------------------------------------------
  436. //
  437. //-----------------------------------------------------------------------------
  438. void GetDmeChannelList(
  439. CUtlVector< CDmeChannel * > &PChannelList,
  440. CUtlVector< CDmeChannel * > &OChannelList,
  441. const CUtlVector< CDmeDag * > &dagList )
  442. {
  443. PChannelList.RemoveAll();
  444. for ( int i = 0; i < dagList.Count(); ++i )
  445. {
  446. CUtlVector< CDmeChannel * > dmeChannelList;
  447. bool bPHandled = false;
  448. bool bOHandled = false;
  449. if ( FindReferringElements( dmeChannelList, dagList[i]->GetTransform(), g_pDataModel->GetSymbol( "toElement" ) ) && dmeChannelList.Count() > 0 )
  450. {
  451. for ( int j = 0; j < dmeChannelList.Count(); ++j )
  452. {
  453. CDmeLog *pDmeLog = dmeChannelList[j]->GetLog();
  454. if ( !pDmeLog )
  455. continue;
  456. for ( int k = 0; k < pDmeLog->GetNumLayers(); ++k )
  457. {
  458. CDmeLogLayer *pDmeLogLayer = pDmeLog->GetLayer( k );
  459. CDmeVector3LogLayer *pDmeVector3LogLayer = CastElement< CDmeVector3LogLayer >( pDmeLogLayer );
  460. if ( !bPHandled && pDmeVector3LogLayer )
  461. {
  462. bPHandled = true;
  463. PChannelList.AddToTail( dmeChannelList[j] );
  464. continue;
  465. }
  466. CDmeQuaternionLogLayer *pDmeQuaternionLogLayer = CastElement< CDmeQuaternionLogLayer >( pDmeLogLayer );
  467. if ( !bOHandled && pDmeQuaternionLogLayer )
  468. {
  469. bOHandled = true;
  470. OChannelList.AddToTail( dmeChannelList[j] );
  471. continue;
  472. }
  473. }
  474. }
  475. }
  476. if ( !bPHandled )
  477. {
  478. PChannelList.AddToTail( NULL );
  479. }
  480. if ( !bOHandled )
  481. {
  482. OChannelList.AddToTail( NULL );
  483. }
  484. }
  485. }
  486. //-----------------------------------------------------------------------------
  487. // Computes common data for GetAbsMotion & SetAbsMotion
  488. //-----------------------------------------------------------------------------
  489. bool PrepAndValidateMotionData(
  490. CDmeChannel **pDmeDagPositionChannel,
  491. CDmeChannel **pDmeDagOrientationChannel,
  492. CDmeDag *pDmeDag,
  493. CUtlVector< CDmeDag * > &hierarchyList,
  494. CUtlVector< CDmeChannel * > &PChannelList,
  495. CUtlVector< CDmeChannel * > &OChannelList,
  496. CUtlRBTree< DmeTime_t > &keyTimes )
  497. {
  498. if ( !pDmeDag )
  499. return false;
  500. hierarchyList.RemoveAll();
  501. if ( !GetDagHierarchy( hierarchyList, pDmeDag ) )
  502. return false; // Found a cycle, abort!
  503. PChannelList.RemoveAll();
  504. OChannelList.RemoveAll();
  505. GetDmeChannelList( PChannelList, OChannelList, hierarchyList );
  506. if ( hierarchyList.Count() != PChannelList.Count()
  507. || hierarchyList.Count() != OChannelList.Count() )
  508. return false;
  509. CDmeChannel *pSrcPChannel = PChannelList.Tail();
  510. if ( pDmeDagPositionChannel )
  511. {
  512. *pDmeDagPositionChannel = pSrcPChannel;
  513. }
  514. CDmeLog *pSrcPLog = pSrcPChannel ? pSrcPChannel->GetLog() : NULL;
  515. CDmeChannel *pSrcOChannel = OChannelList.Tail();
  516. if ( pDmeDagOrientationChannel )
  517. {
  518. *pDmeDagOrientationChannel = pSrcOChannel;
  519. }
  520. CDmeLog *pSrcOLog = pSrcOChannel ? pSrcOChannel->GetLog() : NULL;
  521. // Build a list of key times containing all keys from both logs
  522. if ( pSrcPLog )
  523. {
  524. for ( int i = 0; i < pSrcPLog->GetKeyCount(); ++i )
  525. {
  526. keyTimes.InsertIfNotFound( pSrcPLog->GetKeyTime( i ) );
  527. }
  528. }
  529. if ( pSrcOLog )
  530. {
  531. for ( int i = 0; i < pSrcOLog->GetKeyCount(); ++i )
  532. {
  533. keyTimes.InsertIfNotFound( pSrcOLog->GetKeyTime( i ) );
  534. }
  535. }
  536. return true;
  537. }
  538. //-----------------------------------------------------------------------------
  539. // Returns a CDmElement with two attributes:
  540. //
  541. // "positionChannel" - CDmeChannel
  542. // "orientationChannel" - CDmeChannel
  543. //
  544. // These two CDmeChannel's are the worldSpace position and orientation
  545. // of the specified DmeDag node computed over the same time frame as
  546. // the original DmeChannel driving the DmeDag node.
  547. //
  548. // If the DmeDag node isn't animated then two single frame DmeChannels
  549. // are returned with a single sample at DmeTime_t( 0.0 )
  550. //
  551. // NOTE: This should probably take a time frame over which to bake
  552. // and a sample rate and then simply set time and evaluate the
  553. // DmeOperator's in the scene so that rig operator's, etc...
  554. // will work and it doesn't have to be driven by just a DmeChannel
  555. //-----------------------------------------------------------------------------
  556. void GetAbsMotion( CDmeChannel **ppDmePChannel, CDmeChannel **ppDmeOChannel, CDmeDag *pDmeDag )
  557. {
  558. if ( !pDmeDag | !ppDmePChannel || !ppDmeOChannel )
  559. return;
  560. *ppDmePChannel = NULL;
  561. *ppDmeOChannel = NULL;
  562. CUtlVector< CDmeDag * > hierarchyList;
  563. CUtlVector< CDmeChannel * > PChannelList;
  564. CUtlVector< CDmeChannel * > OChannelList;
  565. CUtlRBTree< DmeTime_t > keyTimes( DefLessFunc( DmeTime_t ) );
  566. CDmeChannel *pSrcPChannel = NULL;
  567. CDmeChannel *pSrcOChannel = NULL;
  568. if ( !PrepAndValidateMotionData( &pSrcPChannel, &pSrcOChannel, pDmeDag, hierarchyList, PChannelList, OChannelList, keyTimes ) )
  569. return;
  570. CDmeChannel *pDstPChannel = pSrcPChannel ?
  571. CreateElement< CDmeChannel >( pSrcPChannel->GetName(), pSrcPChannel->GetFileId() ) :
  572. CreateElement< CDmeChannel >( ( CUtlString( pDmeDag->GetName() ) + "_p" ).Get(), pDmeDag->GetFileId() );
  573. *ppDmePChannel = pDstPChannel;
  574. CDmeVector3Log *pDstPLog = pDstPChannel->CreateLog< Vector >();
  575. pDstPLog->SetValueThreshold( 1.0e-6 );
  576. CDmeChannel *pDstOChannel = pSrcOChannel ?
  577. CreateElement< CDmeChannel >( pSrcOChannel->GetName(), pSrcPChannel->GetFileId() ) :
  578. CreateElement< CDmeChannel >( ( CUtlString( pDmeDag->GetName() ) + "_o" ).Get(), pDmeDag->GetFileId() );
  579. *ppDmeOChannel = pDstOChannel;
  580. CDmeQuaternionLog *pDstOLog = pDstOChannel->CreateLog< Quaternion >();
  581. pDstOLog->SetValueThreshold( 1.0e-6 );
  582. matrix3x4_t wm;
  583. matrix3x4_t twm;
  584. matrix3x4_t m;
  585. Vector v;
  586. Quaternion q;
  587. if ( keyTimes.Count() > 0 )
  588. {
  589. // Node is animated, so loop through all of the keys and sample all
  590. // animation curves
  591. // Loop through all logs, get current time, accumulate matrix
  592. for ( CUtlRBTree< DmeTime_t >::IndexType_t i = keyTimes.FirstInorder(); keyTimes.IsValidIndex( i ); i = keyTimes.NextInorder( i ) )
  593. {
  594. const DmeTime_t dmeTime = keyTimes[i];
  595. SetIdentityMatrix( wm );
  596. for ( int j = 0; j < hierarchyList.Count(); ++j )
  597. {
  598. v.Init( 0.0f, 0.0f, 0.0f );
  599. q = quat_identity;
  600. CDmeChannel *pPChannel = PChannelList[j];
  601. if ( pPChannel )
  602. {
  603. pPChannel->GetPlaybackValueAtTime( dmeTime, v );
  604. }
  605. else
  606. {
  607. v = hierarchyList[j]->GetTransform()->GetPosition();
  608. }
  609. CDmeChannel *pOChannel = OChannelList[j];
  610. if ( pOChannel )
  611. {
  612. pOChannel->GetPlaybackValueAtTime( dmeTime, q );
  613. }
  614. else
  615. {
  616. q = hierarchyList[j]->GetTransform()->GetOrientation();
  617. }
  618. QuaternionMatrix( q, v, m );
  619. MatrixCopy( wm, twm );
  620. ConcatTransforms( twm, m, wm );
  621. }
  622. MatrixAngles( wm, q, v );
  623. pDstOLog->SetKey( dmeTime, q );
  624. pDstPLog->SetKey( dmeTime, v );
  625. }
  626. }
  627. else
  628. {
  629. // Node is not animated, so use current value for all nodes...
  630. SetIdentityMatrix( wm );
  631. Vector wt( 0.0f, 0.0f, 0.0f );
  632. for ( int j = 0; j < hierarchyList.Count(); ++j )
  633. {
  634. v.Init( 0.0f, 0.0f, 0.0f );
  635. q = quat_identity;
  636. CDmeTransform *pDmeTransform = hierarchyList[j]->GetTransform();
  637. if ( pDmeTransform )
  638. {
  639. v = hierarchyList[j]->GetTransform()->GetPosition();
  640. q = hierarchyList[j]->GetTransform()->GetOrientation();
  641. }
  642. wt += v;
  643. QuaternionMatrix( q, v, m );
  644. MatrixCopy( wm, twm );
  645. ConcatTransforms( twm, m, wm );
  646. }
  647. MatrixAngles( wm, q, v );
  648. pDstOLog->SetKey( DmeTime_t( 0.0 ), q );
  649. pDstPLog->SetKey( DmeTime_t( 0.0 ), v );
  650. }
  651. }
  652. //-----------------------------------------------------------------------------
  653. //
  654. //-----------------------------------------------------------------------------
  655. bool SetAbsMotion( CDmeDag *pDmeDag, CDmeChannel *pDmePositionChannel, CDmeChannel *pDmeOrientationChannel )
  656. {
  657. CUtlVector< CDmeDag * > hierarchyList;
  658. CUtlVector< CDmeChannel * > PChannelList;
  659. CUtlVector< CDmeChannel * > OChannelList;
  660. CUtlRBTree< DmeTime_t > keyTimes( DefLessFunc( DmeTime_t ) );
  661. CDmeChannel *pDmeDagPChannel = NULL;
  662. CDmeChannel *pDmeDagOChannel = NULL;
  663. if ( !PrepAndValidateMotionData( &pDmeDagPChannel, &pDmeDagOChannel, pDmeDag, hierarchyList, PChannelList, OChannelList, keyTimes ) )
  664. return false;
  665. CDmeVector3Log *pDstPLog = pDmeDagPChannel ? CastElement< CDmeVector3Log >( pDmeDagPChannel->GetLog() ) : NULL;
  666. CDmeQuaternionLog *pDstOLog = pDmeDagOChannel ? CastElement< CDmeQuaternionLog >( pDmeDagOChannel->GetLog() ) : NULL;
  667. matrix3x4_t pwm;
  668. matrix3x4_t ipwm;
  669. matrix3x4_t tpwm;
  670. matrix3x4_t m;
  671. matrix3x4_t wm;
  672. CUtlVector< matrix3x4_t > localMatrices;
  673. Vector v;
  674. Quaternion q;
  675. // Loop through all logs except last one to get parent world matrix at each key time
  676. if ( keyTimes.Count() <= 0 )
  677. {
  678. CDmeLog *pSrcPLog = pDmePositionChannel ? pDmePositionChannel->GetLog() : NULL;
  679. if ( pSrcPLog )
  680. {
  681. for ( int i = 0; i < pSrcPLog->GetKeyCount(); ++i )
  682. {
  683. keyTimes.InsertIfNotFound( pSrcPLog->GetKeyTime( i ) );
  684. }
  685. }
  686. CDmeLog *pSrcOLog = pDmeOrientationChannel ? pDmeOrientationChannel->GetLog() : NULL;
  687. if ( pSrcOLog )
  688. {
  689. for ( int i = 0; i < pSrcOLog->GetKeyCount(); ++i )
  690. {
  691. keyTimes.InsertIfNotFound( pSrcOLog->GetKeyTime( i ) );
  692. }
  693. }
  694. }
  695. if ( keyTimes.Count() <= 0 )
  696. {
  697. keyTimes.Insert( DmeTime_t( 0.0 ) );
  698. }
  699. for ( CUtlRBTree< DmeTime_t >::IndexType_t i = keyTimes.FirstInorder(); keyTimes.IsValidIndex( i ); i = keyTimes.NextInorder( i ) )
  700. {
  701. const DmeTime_t dmeTime = keyTimes[i];
  702. SetIdentityMatrix( pwm );
  703. for ( int j = 0; j < hierarchyList.Count() - 1; ++j )
  704. {
  705. v.Init( 0.0f, 0.0f, 0.0f );
  706. q = quat_identity;
  707. CDmeChannel *pPChannel = PChannelList[j];
  708. if ( pPChannel )
  709. {
  710. pPChannel->GetPlaybackValueAtTime( dmeTime, v );
  711. }
  712. else
  713. {
  714. v = hierarchyList[j]->GetTransform()->GetPosition();
  715. }
  716. CDmeChannel *pOChannel = OChannelList[j];
  717. if ( pOChannel )
  718. {
  719. pOChannel->GetPlaybackValueAtTime( dmeTime, q );
  720. }
  721. else
  722. {
  723. q = hierarchyList[j]->GetTransform()->GetOrientation();
  724. }
  725. QuaternionMatrix( q, v, m );
  726. MatrixCopy( pwm, tpwm );
  727. ConcatTransforms( tpwm, m, pwm );
  728. }
  729. // pwm is the parent world matrix at dmeTime
  730. MatrixInvert( pwm, ipwm );
  731. // wm is the world matrix of dmeDag at dmeTime
  732. pDmePositionChannel->GetPlaybackValueAtTime( dmeTime, v );
  733. pDmeOrientationChannel->GetPlaybackValueAtTime( dmeTime, q );
  734. QuaternionMatrix( q, v, wm );
  735. ConcatTransforms( ipwm, wm, m );
  736. localMatrices.AddToTail( m );
  737. }
  738. Assert( static_cast< int >( keyTimes.Count() ) == localMatrices.Count() );
  739. if ( pDstPLog && pDstOLog )
  740. {
  741. // Destination node is animated
  742. pDstPLog->ClearKeys();
  743. pDstOLog->ClearKeys();
  744. // Now set the key/values in the logs
  745. int nMatIndex = 0;
  746. for ( CUtlRBTree< DmeTime_t >::IndexType_t i = keyTimes.FirstInorder(); keyTimes.IsValidIndex( i ); i = keyTimes.NextInorder( i ), ++nMatIndex )
  747. {
  748. const DmeTime_t dmeTime = keyTimes[i];
  749. MatrixAngles( localMatrices[nMatIndex], q, v );
  750. pDstPLog->SetKey( dmeTime, v );
  751. pDstOLog->SetKey( dmeTime, q );
  752. }
  753. }
  754. else
  755. {
  756. // Destination node is static
  757. hierarchyList.Tail()->GetTransform()->SetTransform( localMatrices[0] );
  758. }
  759. return true;
  760. }
  761. //-----------------------------------------------------------------------------
  762. // Creates a guaranteed unique DmFileId_t
  763. //-----------------------------------------------------------------------------
  764. DmFileId_t CreateUniqueDmFileId()
  765. {
  766. UniqueId_t uniqueId;
  767. CreateUniqueId( &uniqueId );
  768. char buf[64];
  769. UniqueIdToString( uniqueId, buf, ARRAYSIZE( buf ) );
  770. return g_pDataModel->FindOrCreateFileId( buf );
  771. }
  772. //=============================================================================
  773. // MppSequenceIt - MPP File Sequence Iterator
  774. //=============================================================================
  775. //-----------------------------------------------------------------------------
  776. //
  777. //-----------------------------------------------------------------------------
  778. MppSequenceIt::MppSequenceIt( CDmeAssetRoot *pDmeAssetRoot )
  779. : m_nSequenceIndex( -1 )
  780. {
  781. if ( pDmeAssetRoot )
  782. {
  783. CDmeSequenceList *pDmeSequenceList = pDmeAssetRoot->GetValueElement< CDmeSequenceList >( "sequenceList" );
  784. if ( pDmeSequenceList )
  785. {
  786. CUtlVector< CDmeSequenceBase * > sortedSequenceList;
  787. pDmeSequenceList->GetSortedSequenceList( sortedSequenceList );
  788. const int nSortedSequenceCount = sortedSequenceList.Count();
  789. m_hDmeSequenceList.EnsureCapacity( nSortedSequenceCount );
  790. for ( int i = 0; i < nSortedSequenceCount; ++i )
  791. {
  792. CDmeSequence *pDmeSequence = CastElement< CDmeSequence >( sortedSequenceList[i] );
  793. if ( !pDmeSequence )
  794. continue;
  795. m_hDmeSequenceList.AddToTail( pDmeSequence->GetHandle() );
  796. }
  797. }
  798. }
  799. Next();
  800. }
  801. //-----------------------------------------------------------------------------
  802. //
  803. //-----------------------------------------------------------------------------
  804. CDmeSequence *MppSequenceIt::Get() const
  805. {
  806. if ( m_nSequenceIndex < 0 || m_nSequenceIndex >= m_hDmeSequenceList.Count() )
  807. return NULL;
  808. return CastElement< CDmeSequence >( g_pDataModel->GetElement( m_hDmeSequenceList[m_nSequenceIndex] ) );
  809. }
  810. //-----------------------------------------------------------------------------
  811. //
  812. //-----------------------------------------------------------------------------
  813. bool MppSequenceIt::IsDone() const
  814. {
  815. return Get() == NULL;
  816. }
  817. //-----------------------------------------------------------------------------
  818. //
  819. //-----------------------------------------------------------------------------
  820. void MppSequenceIt::Next()
  821. {
  822. for ( int i = m_nSequenceIndex + 1; i < m_hDmeSequenceList.Count(); ++i )
  823. {
  824. CDmeSequence *pDmeSequence = CastElement< CDmeSequence >( g_pDataModel->GetElement( m_hDmeSequenceList[i] ) );
  825. if ( pDmeSequence )
  826. {
  827. m_nSequenceIndex = i;
  828. return;
  829. }
  830. }
  831. m_nSequenceIndex = m_hDmeSequenceList.Count();
  832. }
  833. //-----------------------------------------------------------------------------
  834. //
  835. //-----------------------------------------------------------------------------
  836. void MppSequenceIt::Reset()
  837. {
  838. m_nSequenceIndex = -1;
  839. Next();
  840. }
  841. //-----------------------------------------------------------------------------
  842. // Adds the passed pDmeModel to the skeletonList if it isn't already in the
  843. // list and it isn't NULL
  844. //-----------------------------------------------------------------------------
  845. static void AddUniqueSkeleton( CUtlVector< CDmeModel * > &skeletonList, CDmeModel *pDmeModel )
  846. {
  847. if ( !pDmeModel )
  848. return;
  849. bool bFound = false;
  850. for ( int i = 0; i < skeletonList.Count(); ++i )
  851. {
  852. if ( pDmeModel == skeletonList[i] )
  853. {
  854. bFound = true;
  855. break;
  856. }
  857. }
  858. if ( !bFound )
  859. {
  860. skeletonList.AddToTail( pDmeModel );
  861. }
  862. }
  863. //-----------------------------------------------------------------------------
  864. // Returns a list of all unique skeletons used by animations/sequences under the MPP DmeAssetRoot
  865. //-----------------------------------------------------------------------------
  866. void MppGetAnimationSkeletonList( CUtlVector< CDmeModel * > &skeletonList, CDmeAssetRoot *pDmeAssetRoot )
  867. {
  868. skeletonList.RemoveAll();
  869. for ( MppSequenceIt sIt( pDmeAssetRoot ); !sIt.IsDone(); sIt.Next() )
  870. {
  871. AddUniqueSkeleton( skeletonList, CastElement< CDmeModel >( sIt.Get()->m_eSkeleton.GetElement() ) );
  872. }
  873. }
  874. //-----------------------------------------------------------------------------
  875. // Returns a list of all unique skeletons used by the physics model under the MPP DmeAssetRoot
  876. //-----------------------------------------------------------------------------
  877. void MppGetPhysicsSkeletonList( CUtlVector< CDmeModel * > &skeletonList, CDmeAssetRoot *pDmeAssetRoot )
  878. {
  879. skeletonList.RemoveAll();
  880. if ( !pDmeAssetRoot )
  881. return;
  882. CDmeCollisionModel *pDmeCollisionModel = pDmeAssetRoot->GetValueElement< CDmeCollisionModel >( "collisionModel" );
  883. if ( !pDmeCollisionModel )
  884. return;
  885. const char *const pszAttrs[] = { "skeleton", "model" };
  886. for ( int i = 0; i < 2; ++i )
  887. {
  888. AddUniqueSkeleton( skeletonList, pDmeCollisionModel->GetValueElement< CDmeModel >( pszAttrs[i] ) );
  889. }
  890. }
  891. //-----------------------------------------------------------------------------
  892. // Returns a list of all unique skeletons used by the models under the MPP DmeAssetRoot
  893. //-----------------------------------------------------------------------------
  894. void MppGetModelSkeletonList( CUtlVector< CDmeModel * > &skeletonList, CDmeAssetRoot *pDmeAssetRoot )
  895. {
  896. skeletonList.RemoveAll();
  897. if ( !pDmeAssetRoot )
  898. return;
  899. CDmeBodyGroupList *pDmeBodyGroupList = pDmeAssetRoot->GetValueElement< CDmeBodyGroupList >( "bodyGroupList" );
  900. if ( !pDmeBodyGroupList )
  901. return;
  902. const char *const pszAttrs[] = { "skeleton", "model" };
  903. for ( int i = 0; i < pDmeBodyGroupList->m_BodyGroups.Count(); ++i )
  904. {
  905. CDmeBodyGroup *pDmeBodyGroup = pDmeBodyGroupList->m_BodyGroups[i];
  906. if ( !pDmeBodyGroup )
  907. continue;
  908. for ( int j = 0; j < pDmeBodyGroup->m_BodyParts.Count(); ++j )
  909. {
  910. CDmeLODList *pDmeLODList = CastElement< CDmeLODList >( pDmeBodyGroup->m_BodyParts[j] );
  911. if ( !pDmeLODList )
  912. continue;
  913. for ( int k = 0; k < pDmeLODList->m_LODs.Count(); ++k )
  914. {
  915. CDmeLOD *pDmeLOD = pDmeLODList->m_LODs[k];
  916. if ( !pDmeLOD )
  917. continue;
  918. for ( int i = 0; i < 2; ++i )
  919. {
  920. AddUniqueSkeleton( skeletonList, pDmeLOD->GetValueElement< CDmeModel >( pszAttrs[i] ) );
  921. }
  922. }
  923. }
  924. }
  925. }
  926. //-----------------------------------------------------------------------------
  927. // Returns a list of all unique skeletons under the specified MPP DmeAssetRoot
  928. //-----------------------------------------------------------------------------
  929. void MppGetSkeletonList( CUtlVector< CDmeModel * > &skeletonList, CDmeAssetRoot *pDmeAssetRoot, int nMppSkeletonMask /* = kMppAllSkeletonMask */ )
  930. {
  931. skeletonList.RemoveAll();
  932. if ( !pDmeAssetRoot )
  933. return;
  934. for ( int i = 0; i < 3; ++i )
  935. {
  936. CUtlVector< CDmeModel * > tmpSkeletonList;
  937. switch ( i )
  938. {
  939. case 0:
  940. if ( nMppSkeletonMask & MPP_ANIM_SKELETON_MASK )
  941. {
  942. MppGetAnimationSkeletonList( tmpSkeletonList, pDmeAssetRoot );
  943. }
  944. break;
  945. case 1:
  946. if ( nMppSkeletonMask & MPP_PHYSICS_SKELETON_MASK )
  947. {
  948. MppGetPhysicsSkeletonList( tmpSkeletonList, pDmeAssetRoot );
  949. }
  950. break;
  951. case 2:
  952. if ( nMppSkeletonMask & MPP_MODEL_SKELETON_MASK )
  953. {
  954. MppGetModelSkeletonList( tmpSkeletonList, pDmeAssetRoot );
  955. }
  956. break;
  957. }
  958. for ( int j = 0; j < tmpSkeletonList.Count(); ++j )
  959. {
  960. CDmeModel *pDmeModel = tmpSkeletonList[j];
  961. if ( !pDmeModel )
  962. continue;
  963. bool bFound = false;
  964. for ( int k = 0; k < skeletonList.Count(); ++k )
  965. {
  966. if ( pDmeModel == skeletonList[k] )
  967. {
  968. bFound = true;
  969. break;
  970. }
  971. }
  972. if ( !bFound )
  973. {
  974. skeletonList.AddToTail( pDmeModel );
  975. }
  976. }
  977. }
  978. }
  979. //-----------------------------------------------------------------------------
  980. //
  981. //-----------------------------------------------------------------------------
  982. CDmeTransform *FindMatchingSkeletonTransform( CDmeModel *pDmeModel, CDmeTransform *pDmeTransform )
  983. {
  984. if ( !pDmeModel || !pDmeTransform )
  985. return NULL;
  986. CDmeDag *pDmeDag = NULL;
  987. CDmeDag *pDmeDagChild = NULL;
  988. CDmeTransform *pDmeDagTransform = NULL;
  989. CUtlStack< CDmeDag * > depthFirstDagStack;
  990. depthFirstDagStack.Push( pDmeModel );
  991. while ( depthFirstDagStack.Count() )
  992. {
  993. depthFirstDagStack.Pop( pDmeDag );
  994. if ( !pDmeDag )
  995. continue;
  996. pDmeDagTransform = pDmeDag->GetTransform();
  997. if ( pDmeDagTransform && !Q_stricmp( pDmeTransform->GetName(), pDmeDagTransform->GetName() ) )
  998. return pDmeDagTransform;
  999. for ( int i = pDmeDag->GetChildCount() - 1; i >= 0; --i )
  1000. {
  1001. pDmeDagChild = pDmeDag->GetChild( i );
  1002. if ( !pDmeDagChild )
  1003. continue;
  1004. depthFirstDagStack.Push( pDmeDagChild );
  1005. }
  1006. }
  1007. return NULL;
  1008. }
  1009. //-----------------------------------------------------------------------------
  1010. //
  1011. //-----------------------------------------------------------------------------
  1012. CDmeConnectionOperator *CreateOutgoingConnectionOperator( CDmeTransform *pSrcTransform, CDmAttribute *pSrcAttribute, DmFileId_t nFileId )
  1013. {
  1014. if ( !pSrcTransform || !pSrcAttribute )
  1015. return NULL;
  1016. CUtlString sName( pSrcTransform->GetName() );
  1017. sName += ".";
  1018. sName += pSrcAttribute->GetName();
  1019. CDmeConnectionOperator *pDmeConnectionOperator = CreateElement< CDmeConnectionOperator >( sName.Get(), nFileId );
  1020. if ( !pDmeConnectionOperator )
  1021. return NULL;
  1022. pDmeConnectionOperator->SetInput( pSrcTransform, pSrcAttribute->GetName() );
  1023. return pDmeConnectionOperator;
  1024. }
  1025. //-----------------------------------------------------------------------------
  1026. // Adds the appropriate attribute of the specified DmeTransform as an output
  1027. // of the DmeConnectionOperator if an attribute of the same name as the
  1028. // input operator can be found on the specified DmeTransform
  1029. //-----------------------------------------------------------------------------
  1030. static bool MppConnectDmeTransforms( CDmeConnectionOperator *pDmeConnectionOperator, CDmeTransform *pDstTransform )
  1031. {
  1032. if ( !pDmeConnectionOperator || !pDstTransform )
  1033. return false;
  1034. CDmAttribute *pInputAttribute = pDmeConnectionOperator->GetInputAttribute();
  1035. if ( !pInputAttribute )
  1036. return false;
  1037. CDmeAttributeReference *pDmeAttributeReference = pInputAttribute->GetValueElement< CDmeAttributeReference >();
  1038. if ( !pDmeAttributeReference )
  1039. return false;
  1040. CDmAttribute *pSrcAttribute = pDmeAttributeReference->GetReferencedAttribute();
  1041. if ( !pSrcAttribute )
  1042. return false;
  1043. CDmAttribute *pDstAttribute = pDstTransform->GetAttribute( pSrcAttribute->GetName() );
  1044. if ( !pDstAttribute )
  1045. return false;
  1046. pDmeConnectionOperator->AddOutput( pDstTransform, pDstAttribute->GetName() );
  1047. return true;
  1048. }
  1049. //-----------------------------------------------------------------------------
  1050. // Return true if this DmeTransform has a DmeChannel driving either the
  1051. // position or orientation attributes (or both).
  1052. //-----------------------------------------------------------------------------
  1053. static bool MppIsDmeTransformAnimated( CDmeTransform *pDmeTransform )
  1054. {
  1055. // Assert( 0 );
  1056. return true;
  1057. }
  1058. //-----------------------------------------------------------------------------
  1059. // For each DmeTransform in the source skeleton that has its position or
  1060. // orientation attribute driven by a DmeChannel, create two DmeConnectionOperator
  1061. // elements, one for position and one for orientation and use those attributes
  1062. // as the input to the DmeConnectionOperator. For each skeleton in the
  1063. // dstSkeletonList, if there is a DmeTransform that matches up by a case insensitive
  1064. // name search via a depth first walk, connect the appropriate position or
  1065. // orientation attribute to the outputs of the DmeConnectionOperator.
  1066. // All created DmeConnectionOperators are stored in an attribute on pSrcSkeleton
  1067. // called __MppAnimationDmeConnectionOperators which should already exist
  1068. // and are given the nFileId passed
  1069. //-----------------------------------------------------------------------------
  1070. static void MppConnectSkeletons( CDmeModel *pSrcSkeleton, const CUtlVector< CDmeModel * > &dstSkeletonList, DmFileId_t nFileId )
  1071. {
  1072. if ( !pSrcSkeleton || dstSkeletonList.Count() <= 0 )
  1073. return;
  1074. CDmAttribute *pConnectionOps = pSrcSkeleton->GetAttribute( "__MppAnimationDmeConnectionOperators", AT_ELEMENT_ARRAY );
  1075. if ( !pConnectionOps )
  1076. return;
  1077. CDmrElementArray< CDmeConnectionOperator > connectionOps( pConnectionOps );
  1078. // Do a depth first DmeDag walk of the source skeleton finding DmeTransforms which
  1079. // have connections to DmeOperators... which is tricky because of the way DmeOperators
  1080. // are defined... kind of needs an upfront knowledge of what DmeOperators might be
  1081. // connected and how they are structured for this to function...
  1082. CUtlStack< CDmeDag * > depthFirstStack;
  1083. depthFirstStack.Push( pSrcSkeleton );
  1084. CDmeDag *pDmeDag = NULL;
  1085. while ( depthFirstStack.Count() )
  1086. {
  1087. depthFirstStack.Pop( pDmeDag );
  1088. if ( !pDmeDag )
  1089. continue;
  1090. CDmeTransform *pSrcDmeTransform = pDmeDag->GetTransform();
  1091. if ( pSrcDmeTransform )
  1092. {
  1093. if ( MppIsDmeTransformAnimated( pSrcDmeTransform ) )
  1094. {
  1095. for ( int i = 0; i < 2; ++i )
  1096. {
  1097. CDmAttribute *pSrcAttribute = i == 0 ? pSrcDmeTransform->GetPositionAttribute() : pSrcDmeTransform->GetOrientationAttribute();
  1098. CDmeConnectionOperator *pDmeConnectionOperator = CreateOutgoingConnectionOperator( pSrcDmeTransform, pSrcAttribute, nFileId );
  1099. if ( !pDmeConnectionOperator )
  1100. continue;
  1101. for ( int j = 0; j < dstSkeletonList.Count(); ++j )
  1102. {
  1103. CDmeModel *pDstSkeleton = dstSkeletonList[j];
  1104. if ( pDstSkeleton == pSrcSkeleton )
  1105. continue;
  1106. CDmeTransform *pDstDmeTransform = FindMatchingSkeletonTransform( pDstSkeleton, pSrcDmeTransform );
  1107. if ( !pDstDmeTransform || pSrcDmeTransform == pDstDmeTransform )
  1108. continue;
  1109. MppConnectDmeTransforms( pDmeConnectionOperator, pDstDmeTransform );
  1110. }
  1111. if ( pDmeConnectionOperator->NumOutputAttributes() <= 0 )
  1112. {
  1113. g_pDataModel->DestroyElement( pDmeConnectionOperator->GetHandle() );
  1114. }
  1115. else
  1116. {
  1117. connectionOps.AddToTail( pDmeConnectionOperator );
  1118. }
  1119. }
  1120. }
  1121. }
  1122. for ( int i = pDmeDag->GetChildCount() - 1; i >= 0; --i )
  1123. {
  1124. depthFirstStack.Push( pDmeDag->GetChild( i ) );
  1125. }
  1126. }
  1127. }
  1128. //-----------------------------------------------------------------------------
  1129. //
  1130. //-----------------------------------------------------------------------------
  1131. static void MppDisconnectAnimationSkeleton( CDmeModel *pDmeModel )
  1132. {
  1133. // Assert( 0 );
  1134. }
  1135. //-----------------------------------------------------------------------------
  1136. // Connects all of the non-animation skeletons to each animation skeleton via DmeConnectionOperators
  1137. //-----------------------------------------------------------------------------
  1138. DmFileId_t MppConnectSkeletonsForAnimation( CDmeAssetRoot *pDmeAssetRoot )
  1139. {
  1140. if ( !pDmeAssetRoot )
  1141. return DMFILEID_INVALID;
  1142. CUtlVector< CDmeModel * > animationSkeletonList;
  1143. MppGetSkeletonList( animationSkeletonList, pDmeAssetRoot, MPP_ANIM_SKELETON_MASK );
  1144. CUtlVector< CDmeModel * > skeletonList;
  1145. MppGetSkeletonList( skeletonList, pDmeAssetRoot, MPP_MODEL_SKELETON_MASK | MPP_PHYSICS_SKELETON_MASK );
  1146. if ( animationSkeletonList.Count() <= 0 || skeletonList.Count() <= 0 )
  1147. return DMFILEID_INVALID;
  1148. DmFileId_t nFileId = CreateUniqueDmFileId();
  1149. for ( int i = 0; i < animationSkeletonList.Count(); ++i )
  1150. {
  1151. CDmeModel *pSrcSkeleton = animationSkeletonList[i];
  1152. if ( !pSrcSkeleton )
  1153. continue;
  1154. MppDisconnectAnimationSkeleton( pSrcSkeleton );
  1155. CDmAttribute *pConnectionOps = pSrcSkeleton->AddAttribute( "__MppAnimationDmeConnectionOperators", AT_ELEMENT_ARRAY );
  1156. pConnectionOps->AddFlag( FATTRIB_DONTSAVE );
  1157. CDmrElementArray< CDmeConnectionOperator > connectionOps( pConnectionOps );
  1158. MppConnectSkeletons( pSrcSkeleton, skeletonList, nFileId );
  1159. }
  1160. return nFileId;
  1161. }
  1162. //-----------------------------------------------------------------------------
  1163. // Disconnects all of the non-animation skeletons from each animation skeleton
  1164. // and destroys the elements created by MppConnectSkeletonsForAnimation
  1165. //-----------------------------------------------------------------------------
  1166. void MppDisconnectSkeletonsFromAnimation( CDmeAssetRoot *pDmeAssetRoot )
  1167. {
  1168. }
  1169. //-----------------------------------------------------------------------------
  1170. // Utility to return DmElement id as name:string
  1171. //-----------------------------------------------------------------------------
  1172. CUtlString ComputeDmElementIdStr( const CDmElement *pDmElement )
  1173. {
  1174. if ( !pDmElement )
  1175. return CUtlString( "NULL(Unknown):\"Unknown\"" );
  1176. CUtlString sReturn;
  1177. sReturn = pDmElement->GetTypeString();
  1178. sReturn += "(";
  1179. sReturn = pDmElement->GetName();
  1180. sReturn += "):\"";
  1181. char pszBuf[64];
  1182. UniqueIdToString( pDmElement->GetId(), pszBuf, ARRAYSIZE( pszBuf ) );
  1183. sReturn += pszBuf;
  1184. sReturn += "\"";
  1185. return sReturn;
  1186. }