home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 March / Gamestar_82_2006-03_dvd.iso / DVDStar / Editace / quake4_sdkv10.exe / source / game / anim / Anim.cpp < prev    next >
C/C++ Source or Header  |  2005-11-14  |  28KB  |  1,183 lines

  1.  
  2. #include "../../idlib/precompiled.h"
  3. #pragma hdrstop
  4.  
  5. #include "../Game_local.h"
  6.  
  7. bool idAnimManager::forceExport = false;
  8.  
  9. /***********************************************************************
  10.  
  11.     idMD5Anim
  12.  
  13. ***********************************************************************/
  14.  
  15. /*
  16. ====================
  17. idMD5Anim::idMD5Anim
  18. ====================
  19. */
  20. idMD5Anim::idMD5Anim() {
  21.     ref_count    = 0;
  22.     numFrames    = 0;
  23.     numJoints    = 0;
  24.     frameRate    = 24;
  25.     animLength    = 0;
  26.     totaldelta.Zero();
  27. }
  28.  
  29. /*
  30. ====================
  31. idMD5Anim::idMD5Anim
  32. ====================
  33. */
  34. idMD5Anim::~idMD5Anim() {
  35.     Free();
  36. }
  37.  
  38. /*
  39. ====================
  40. idMD5Anim::Free
  41. ====================
  42. */
  43. void idMD5Anim::Free( void ) {
  44.     numFrames    = 0;
  45.     numJoints    = 0;
  46.     frameRate    = 24;
  47.     animLength    = 0;
  48.     name        = "";
  49.  
  50.     totaldelta.Zero();
  51.  
  52.     jointInfo.Clear();
  53.     bounds.Clear();
  54.     componentFrames.Clear();
  55. }
  56.  
  57. /*
  58. ====================
  59. idMD5Anim::NumFrames
  60. ====================
  61. */
  62. int    idMD5Anim::NumFrames( void ) const {
  63.     return numFrames;
  64. }
  65.  
  66. /*
  67. ====================
  68. idMD5Anim::NumJoints
  69. ====================
  70. */
  71. int    idMD5Anim::NumJoints( void ) const {
  72.     return numJoints;
  73. }
  74.  
  75. /*
  76. ====================
  77. idMD5Anim::Length
  78. ====================
  79. */
  80. int idMD5Anim::Length( void ) const {
  81.     return animLength;
  82. }
  83.  
  84. /*
  85. =====================
  86. idMD5Anim::TotalMovementDelta
  87. =====================
  88. */
  89. const idVec3 &idMD5Anim::TotalMovementDelta( void ) const {
  90.     return totaldelta;
  91. }
  92.  
  93. /*
  94. =====================
  95. idMD5Anim::TotalMovementDelta
  96. =====================
  97. */
  98. const char *idMD5Anim::Name( void ) const {
  99.     return name;
  100. }
  101.  
  102. /*
  103. ====================
  104. idMD5Anim::Reload
  105. ====================
  106. */
  107. bool idMD5Anim::Reload( void ) {
  108.     TIME_THIS_SCOPE( __FUNCLINE__);
  109.     
  110.     idStr filename;
  111.  
  112.     filename = name;
  113.     Free();
  114.  
  115.     return LoadAnim( filename );
  116. }
  117.  
  118. /*
  119. ====================
  120. idMD5Anim::Allocated
  121. ====================
  122. */
  123. size_t idMD5Anim::Allocated( void ) const {
  124.     size_t    size = bounds.Allocated() + jointInfo.Allocated() + componentFrames.Allocated() + name.Allocated();
  125.     return size;
  126. }
  127.  
  128. /*
  129. ====================
  130. idMD5Anim::LoadAnim
  131. ====================
  132. */
  133. bool idMD5Anim::LoadAnim( const char *filename ) {
  134.     int        version;
  135. // RAVEN BEGIN
  136. // jsinger: done this way to minimize amount of code change
  137.     idAutoPtr<Lexer>    lexer( LexerFactory::MakeLexer(LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS | LEXFL_NOSTRINGCONCAT) );
  138.     Lexer &parser(*lexer);
  139. // RAVEN END
  140.     idToken    token;
  141.     int        i, j;
  142.     int        num;
  143.  
  144.     if ( !parser.LoadFile( filename ) ) {
  145.         return false;
  146.     }
  147.  
  148.     Free();
  149.  
  150.     name = filename;
  151.  
  152.     parser.ExpectTokenString( MD5_VERSION_STRING );
  153.     version = parser.ParseInt();
  154.     if ( version != MD5_VERSION ) {
  155.         parser.Error( "Invalid version %d.  Should be version %d\n", version, MD5_VERSION );
  156.     }
  157.  
  158.     // skip the commandline
  159.     parser.ExpectTokenString( "commandline" );
  160.     parser.ReadToken( &token );
  161.  
  162.     // parse num frames
  163.     parser.ExpectTokenString( "numFrames" );
  164.     numFrames = parser.ParseInt();
  165.     if ( numFrames <= 0 ) {
  166.         parser.Error( "Invalid number of frames: %d", numFrames );
  167.     }
  168.  
  169.     // parse num joints
  170.     parser.ExpectTokenString( "numJoints" );
  171.     numJoints = parser.ParseInt();
  172.     if ( numJoints <= 0 ) {
  173.         parser.Error( "Invalid number of joints: %d", numJoints );
  174.     }
  175.  
  176.     // parse frame rate
  177.     parser.ExpectTokenString( "frameRate" );
  178.     frameRate = parser.ParseInt();
  179.     if ( frameRate < 0 ) {
  180.         parser.Error( "Invalid frame rate: %d", frameRate );
  181.     }
  182.  
  183.     // parse number of animated components
  184.     parser.ExpectTokenString( "numAnimatedComponents" );
  185.     numAnimatedComponents = parser.ParseInt();
  186.     if ( ( numAnimatedComponents < 0 ) || ( numAnimatedComponents > numJoints * 6 ) ) {
  187.         parser.Error( "Invalid number of animated components: %d", numAnimatedComponents );
  188.     }
  189.  
  190.     // parse the hierarchy
  191.     jointInfo.SetGranularity( 1 );
  192.     jointInfo.SetNum( numJoints );
  193.     parser.ExpectTokenString( "hierarchy" );
  194.     parser.ExpectTokenString( "{" );
  195.     for( i = 0; i < numJoints; i++ ) {
  196.         parser.ReadToken( &token );
  197. // RAVEN BEGIN
  198. // jsinger: animationLib changed to a pointer
  199.         jointInfo[ i ].nameIndex = animationLib->JointIndex( token );
  200. // RAVEN END
  201.         
  202.         // parse parent num
  203.         jointInfo[ i ].parentNum = parser.ParseInt();
  204.         if ( jointInfo[ i ].parentNum >= i ) {
  205.             parser.Error( "Invalid parent num: %d", jointInfo[ i ].parentNum );
  206.         }
  207.  
  208.         if ( ( i != 0 ) && ( jointInfo[ i ].parentNum < 0 ) ) {
  209.             parser.Error( "Animations may have only one root joint" );
  210.         }
  211.  
  212.         // parse anim bits
  213.         jointInfo[ i ].animBits = parser.ParseInt();
  214.         if ( jointInfo[ i ].animBits & ~63 ) {
  215.             parser.Error( "Invalid anim bits: %d", jointInfo[ i ].animBits );
  216.         }
  217.  
  218.         // parse first component
  219.         jointInfo[ i ].firstComponent = parser.ParseInt();
  220.         if ( ( numAnimatedComponents > 0 ) && ( ( jointInfo[ i ].firstComponent < 0 ) || ( jointInfo[ i ].firstComponent >= numAnimatedComponents ) ) ) {
  221.             parser.Error( "Invalid first component: %d", jointInfo[ i ].firstComponent );
  222.         }
  223.     }
  224.  
  225.     parser.ExpectTokenString( "}" );
  226.  
  227.     // parse bounds
  228.     parser.ExpectTokenString( "bounds" );
  229.     parser.ExpectTokenString( "{" );
  230.     bounds.SetGranularity( 1 );
  231.     bounds.SetNum( numFrames );
  232.     for( i = 0; i < numFrames; i++ ) {
  233.         parser.Parse1DMatrix( 3, bounds[ i ][ 0 ].ToFloatPtr() );
  234.         parser.Parse1DMatrix( 3, bounds[ i ][ 1 ].ToFloatPtr() );
  235.     }
  236.     parser.ExpectTokenString( "}" );
  237.  
  238.     // parse base frame
  239.     baseFrame.SetGranularity( 1 );
  240.     baseFrame.SetNum( numJoints );
  241.     parser.ExpectTokenString( "baseframe" );
  242.     parser.ExpectTokenString( "{" );
  243.     for( i = 0; i < numJoints; i++ ) {
  244.         idCQuat q;
  245.         parser.Parse1DMatrix( 3, baseFrame[ i ].t.ToFloatPtr() );
  246.         parser.Parse1DMatrix( 3, q.ToFloatPtr() );//baseFrame[ i ].q.ToFloatPtr() );
  247.         baseFrame[ i ].q = q.ToQuat();//.w = baseFrame[ i ].q.CalcW();
  248.     }
  249.     parser.ExpectTokenString( "}" );
  250.  
  251.     // parse frames
  252.     componentFrames.SetGranularity( 1 );
  253.     componentFrames.SetNum( numAnimatedComponents * numFrames );
  254.  
  255.     float *componentPtr = componentFrames.Ptr();
  256.     for( i = 0; i < numFrames; i++ ) {
  257.         parser.ExpectTokenString( "frame" );
  258.         num = parser.ParseInt();
  259.         if ( num != i ) {
  260.             parser.Error( "Expected frame number %d", i );
  261.         }
  262.         parser.ExpectTokenString( "{" );
  263.         
  264.         for( j = 0; j < numAnimatedComponents; j++, componentPtr++ ) {
  265.             *componentPtr = parser.ParseFloat();
  266.         }
  267.  
  268.         parser.ExpectTokenString( "}" );
  269.     }
  270.  
  271.     // get total move delta
  272.     if ( !numAnimatedComponents ) {
  273.         totaldelta.Zero();
  274.     } else {
  275.         componentPtr = &componentFrames[ jointInfo[ 0 ].firstComponent ];
  276.         if ( jointInfo[ 0 ].animBits & ANIM_TX ) {
  277.             for( i = 0; i < numFrames; i++ ) {
  278.                 componentPtr[ numAnimatedComponents * i ] -= baseFrame[ 0 ].t.x;
  279.             }
  280.             totaldelta.x = componentPtr[ numAnimatedComponents * ( numFrames - 1 ) ];
  281.             componentPtr++;
  282.         } else {
  283.             totaldelta.x = 0.0f;
  284.         }
  285.         if ( jointInfo[ 0 ].animBits & ANIM_TY ) {
  286.             for( i = 0; i < numFrames; i++ ) {
  287.                 componentPtr[ numAnimatedComponents * i ] -= baseFrame[ 0 ].t.y;
  288.             }
  289.             totaldelta.y = componentPtr[ numAnimatedComponents * ( numFrames - 1 ) ];
  290.             componentPtr++;
  291.         } else {
  292.             totaldelta.y = 0.0f;
  293.         }
  294.         if ( jointInfo[ 0 ].animBits & ANIM_TZ ) {
  295.             for( i = 0; i < numFrames; i++ ) {
  296.                 componentPtr[ numAnimatedComponents * i ] -= baseFrame[ 0 ].t.z;
  297.             }
  298.             totaldelta.z = componentPtr[ numAnimatedComponents * ( numFrames - 1 ) ];
  299.         } else {
  300.             totaldelta.z = 0.0f;
  301.         }
  302.     }
  303.     baseFrame[ 0 ].t.Zero();
  304.  
  305.     // we don't count last frame because it would cause a 1 frame pause at the end
  306.     animLength = ( ( numFrames - 1 ) * 1000 + frameRate - 1 ) / frameRate;
  307.  
  308.     // done
  309.     return true;
  310. }
  311.  
  312. /*
  313. ====================
  314. idMD5Anim::IncreaseRefs
  315. ====================
  316. */
  317. void idMD5Anim::IncreaseRefs( void ) const {
  318.     ref_count++;
  319. }
  320.  
  321. /*
  322. ====================
  323. idMD5Anim::DecreaseRefs
  324. ====================
  325. */
  326. void idMD5Anim::DecreaseRefs( void ) const {
  327.     ref_count--;
  328. }
  329.  
  330. /*
  331. ====================
  332. idMD5Anim::NumRefs
  333. ====================
  334. */
  335. int idMD5Anim::NumRefs( void ) const {
  336.     return ref_count;
  337. }
  338.  
  339. /*
  340. ====================
  341. idMD5Anim::ConvertTimeToFrame
  342. ====================
  343. */
  344. void idMD5Anim::ConvertTimeToFrame( int time, int cyclecount, frameBlend_t &frame ) const {
  345.     int frameTime;
  346.     int frameNum;
  347.  
  348.     if ( numFrames <= 1 ) {
  349.         frame.frame1        = 0;
  350.         frame.frame2        = 0;
  351.         frame.backlerp        = 0.0f;
  352.         frame.frontlerp        = 1.0f;
  353.         frame.cycleCount    = 0;
  354.         return;
  355.     }
  356.  
  357.     if ( time <= 0 ) {
  358.         frame.frame1        = 0;
  359.         frame.frame2        = 1;
  360.         frame.backlerp        = 0.0f;
  361.         frame.frontlerp        = 1.0f;
  362.         frame.cycleCount    = 0;
  363.         return;
  364.     }
  365.     
  366.     frameTime            = time * frameRate;
  367.     frameNum            = frameTime / 1000;
  368.     frame.cycleCount    = frameNum / ( numFrames - 1 );
  369.  
  370.     if ( ( cyclecount > 0 ) && ( frame.cycleCount >= cyclecount ) ) {
  371.         frame.cycleCount    = cyclecount - 1;
  372.         frame.frame1        = numFrames - 1;
  373.         frame.frame2        = frame.frame1;
  374.         frame.backlerp        = 0.0f;
  375.         frame.frontlerp        = 1.0f;
  376.         return;
  377.     }
  378.     
  379.     frame.frame1 = frameNum % ( numFrames - 1 );
  380.     frame.frame2 = frame.frame1 + 1;
  381.     if ( frame.frame2 >= numFrames ) {
  382.         frame.frame2 = 0;
  383.     }
  384.  
  385.     frame.backlerp    = ( frameTime % 1000 ) * 0.001f;
  386.     frame.frontlerp    = 1.0f - frame.backlerp;
  387. }
  388.  
  389. // RAVEN BEGIN
  390. // jscott: added block
  391. /*
  392. ====================
  393. idMD5Anim::ConvertFrameToTime
  394.  
  395. MD5_FRAMERATE is always 24
  396. ====================
  397. */
  398. int idMD5Anim::ConvertFrameToTime( frameBlend_t &frame ) const {
  399.     int        time;
  400.  
  401.     // Adjust the time so the lerping doesn't break the reverse calc
  402.     time = ( ( frame.frame1 % (numFrames - 1)) * 1000 ) / frameRate;
  403.     time += 500 / frameRate;
  404.  
  405.     return( time );
  406. }
  407. // RAVEN END
  408.  
  409. /*
  410. ====================
  411. idMD5Anim::GetOrigin
  412. ====================
  413. */
  414. void idMD5Anim::GetOrigin( idVec3 &offset, int time, int cyclecount ) const {
  415.     frameBlend_t frame;
  416.  
  417.     offset = baseFrame[ 0 ].t;
  418.     if ( !( jointInfo[ 0 ].animBits & ( ANIM_TX | ANIM_TY | ANIM_TZ ) ) ) {
  419.         // just use the baseframe        
  420.         return;
  421.     }
  422.  
  423.     ConvertTimeToFrame( time, cyclecount, frame );
  424.  
  425.     const float *componentPtr1 = &componentFrames[ numAnimatedComponents * frame.frame1 + jointInfo[ 0 ].firstComponent ];
  426.     const float *componentPtr2 = &componentFrames[ numAnimatedComponents * frame.frame2 + jointInfo[ 0 ].firstComponent ];
  427.  
  428.     if ( jointInfo[ 0 ].animBits & ANIM_TX ) {
  429.         offset.x = *componentPtr1 * frame.frontlerp + *componentPtr2 * frame.backlerp;
  430.         componentPtr1++;
  431.         componentPtr2++;
  432.     }
  433.  
  434.     if ( jointInfo[ 0 ].animBits & ANIM_TY ) {
  435.         offset.y = *componentPtr1 * frame.frontlerp + *componentPtr2 * frame.backlerp;
  436.         componentPtr1++;
  437.         componentPtr2++;
  438.     }
  439.  
  440.     if ( jointInfo[ 0 ].animBits & ANIM_TZ ) {
  441.         offset.z = *componentPtr1 * frame.frontlerp + *componentPtr2 * frame.backlerp;
  442.     }
  443.  
  444.     if ( frame.cycleCount ) {
  445.         offset += totaldelta * ( float )frame.cycleCount;
  446.     }
  447. }
  448.  
  449. /*
  450. ====================
  451. idMD5Anim::GetOriginRotation
  452. ====================
  453. */
  454. void idMD5Anim::GetOriginRotation( idQuat &rotation, int time, int cyclecount ) const {
  455.     frameBlend_t    frame;
  456.     int                animBits;
  457.     
  458.     animBits = jointInfo[ 0 ].animBits;
  459.     if ( !( animBits & ( ANIM_QX | ANIM_QY | ANIM_QZ ) ) ) {
  460.         // just use the baseframe        
  461.         rotation = baseFrame[ 0 ].q;
  462.         return;
  463.     }
  464.  
  465.     ConvertTimeToFrame( time, cyclecount, frame );
  466.  
  467.     const float    *jointframe1 = &componentFrames[ numAnimatedComponents * frame.frame1 + jointInfo[ 0 ].firstComponent ];
  468.     const float    *jointframe2 = &componentFrames[ numAnimatedComponents * frame.frame2 + jointInfo[ 0 ].firstComponent ];
  469.  
  470.     if ( animBits & ANIM_TX ) {
  471.         jointframe1++;
  472.         jointframe2++;
  473.     }
  474.  
  475.     if ( animBits & ANIM_TY ) {
  476.         jointframe1++;
  477.         jointframe2++;
  478.     }
  479.  
  480.     if ( animBits & ANIM_TZ ) {
  481.         jointframe1++;
  482.         jointframe2++;
  483.     }
  484.  
  485.     idQuat q1;
  486.     idQuat q2;
  487.  
  488.     switch( animBits & (ANIM_QX|ANIM_QY|ANIM_QZ) ) {
  489.         case ANIM_QX:
  490.             q1.x = jointframe1[0];
  491.             q2.x = jointframe2[0];
  492.             q1.y = baseFrame[ 0 ].q.y;
  493.             q2.y = q1.y;
  494.             q1.z = baseFrame[ 0 ].q.z;
  495.             q2.z = q1.z;
  496.             q1.w = q1.CalcW();
  497.             q2.w = q2.CalcW();
  498.             break;
  499.         case ANIM_QY:
  500.             q1.y = jointframe1[0];
  501.             q2.y = jointframe2[0];
  502.             q1.x = baseFrame[ 0 ].q.x;
  503.             q2.x = q1.x;
  504.             q1.z = baseFrame[ 0 ].q.z;
  505.             q2.z = q1.z;
  506.             q1.w = q1.CalcW();
  507.             q2.w = q2.CalcW();
  508.             break;
  509.         case ANIM_QZ:
  510.             q1.z = jointframe1[0];
  511.             q2.z = jointframe2[0];
  512.             q1.x = baseFrame[ 0 ].q.x;
  513.             q2.x = q1.x;
  514.             q1.y = baseFrame[ 0 ].q.y;
  515.             q2.y = q1.y;
  516.             q1.w = q1.CalcW();
  517.             q2.w = q2.CalcW();
  518.             break;
  519.         case ANIM_QX|ANIM_QY:
  520.             q1.x = jointframe1[0];
  521.             q1.y = jointframe1[1];
  522.             q2.x = jointframe2[0];
  523.             q2.y = jointframe2[1];
  524.             q1.z = baseFrame[ 0 ].q.z;
  525.             q2.z = q1.z;
  526.             q1.w = q1.CalcW();
  527.             q2.w = q2.CalcW();
  528.             break;
  529.         case ANIM_QX|ANIM_QZ:
  530.             q1.x = jointframe1[0];
  531.             q1.z = jointframe1[1];
  532.             q2.x = jointframe2[0];
  533.             q2.z = jointframe2[1];
  534.             q1.y = baseFrame[ 0 ].q.y;
  535.             q2.y = q1.y;
  536.             q1.w = q1.CalcW();
  537.             q2.w = q2.CalcW();
  538.             break;
  539.         case ANIM_QY|ANIM_QZ:
  540.             q1.y = jointframe1[0];
  541.             q1.z = jointframe1[1];
  542.             q2.y = jointframe2[0];
  543.             q2.z = jointframe2[1];
  544.             q1.x = baseFrame[ 0 ].q.x;
  545.             q2.x = q1.x;
  546.             q1.w = q1.CalcW();
  547.             q2.w = q2.CalcW();
  548.             break;
  549.         case ANIM_QX|ANIM_QY|ANIM_QZ:
  550.             q1.x = jointframe1[0];
  551.             q1.y = jointframe1[1];
  552.             q1.z = jointframe1[2];
  553.             q2.x = jointframe2[0];
  554.             q2.y = jointframe2[1];
  555.             q2.z = jointframe2[2];
  556.             q1.w = q1.CalcW();
  557.             q2.w = q2.CalcW();
  558.             break;
  559.     }
  560.  
  561.     rotation.Slerp( q1, q2, frame.backlerp );
  562. }
  563.  
  564. /*
  565. ====================
  566. idMD5Anim::GetBounds
  567. ====================
  568. */
  569. void idMD5Anim::GetBounds( idBounds &bnds, int time, int cyclecount ) const {
  570.     frameBlend_t    frame;
  571.     idVec3            offset;
  572.  
  573.     ConvertTimeToFrame( time, cyclecount, frame );
  574.  
  575.     bnds = bounds[ frame.frame1 ];
  576.     bnds.AddBounds( bounds[ frame.frame2 ] );
  577.  
  578.     // origin position
  579.     offset = baseFrame[ 0 ].t;
  580.     if ( jointInfo[ 0 ].animBits & ( ANIM_TX | ANIM_TY | ANIM_TZ ) ) {
  581.         const float *componentPtr1 = &componentFrames[ numAnimatedComponents * frame.frame1 + jointInfo[ 0 ].firstComponent ];
  582.         const float *componentPtr2 = &componentFrames[ numAnimatedComponents * frame.frame2 + jointInfo[ 0 ].firstComponent ];
  583.  
  584.         if ( jointInfo[ 0 ].animBits & ANIM_TX ) {
  585.             offset.x = *componentPtr1 * frame.frontlerp + *componentPtr2 * frame.backlerp;
  586.             componentPtr1++;
  587.             componentPtr2++;
  588.         }
  589.  
  590.         if ( jointInfo[ 0 ].animBits & ANIM_TY ) {
  591.             offset.y = *componentPtr1 * frame.frontlerp + *componentPtr2 * frame.backlerp;
  592.             componentPtr1++;
  593.             componentPtr2++;
  594.         }
  595.  
  596.         if ( jointInfo[ 0 ].animBits & ANIM_TZ ) {
  597.             offset.z = *componentPtr1 * frame.frontlerp + *componentPtr2 * frame.backlerp;
  598.         }
  599.     }
  600.  
  601.     bnds[ 0 ] -= offset;
  602.     bnds[ 1 ] -= offset;
  603. }
  604.  
  605. /*
  606. ====================
  607. idMD5Anim::GetInterpolatedFrame
  608. ====================
  609. */
  610. void idMD5Anim::GetInterpolatedFrame( const frameBlend_t &frame, idJointQuat *joints, const int *index, int numIndexes ) const {
  611.     int                        i, numLerpJoints;
  612.     const float                *frame1;
  613.     const float                *frame2;
  614.     const float                *jointframe1;
  615.     const float                *jointframe2;
  616.     const jointAnimInfo_t    *infoPtr;
  617.     int                        animBits;
  618.     idJointQuat                *blendJoints;
  619.     idJointQuat                *jointPtr;
  620.     idJointQuat                *blendPtr;
  621.     int                        *lerpIndex;
  622.  
  623.     // copy the baseframe
  624.     SIMDProcessor->Memcpy( joints, baseFrame.Ptr(), baseFrame.Num() * sizeof( baseFrame[ 0 ] ) );
  625.  
  626. #if 0
  627.     if ( !gameLocal.isLastPredictFrame ) {
  628.         return;
  629.     }
  630. #endif
  631.  
  632.     if ( !numAnimatedComponents ) {
  633.         // just use the base frame
  634.         return;
  635.     }
  636.  
  637.     blendJoints = (idJointQuat *)_alloca16( baseFrame.Num() * sizeof( blendPtr[ 0 ] ) );
  638.     lerpIndex = (int *)_alloca16( baseFrame.Num() * sizeof( lerpIndex[ 0 ] ) );
  639.     numLerpJoints = 0;
  640.  
  641.     frame1 = &componentFrames[ frame.frame1 * numAnimatedComponents ];
  642.     frame2 = &componentFrames[ frame.frame2 * numAnimatedComponents ];
  643.  
  644.     for ( i = 0; i < numIndexes; i++ ) {
  645.         int j = index[i];
  646.         jointPtr = &joints[j];
  647.         blendPtr = &blendJoints[j];
  648.         infoPtr = &jointInfo[j];
  649.  
  650.         animBits = infoPtr->animBits;
  651.         if ( animBits ) {
  652.  
  653.             lerpIndex[numLerpJoints++] = j;
  654.  
  655.             jointframe1 = frame1 + infoPtr->firstComponent;
  656.             jointframe2 = frame2 + infoPtr->firstComponent;
  657.  
  658.             switch( animBits & (ANIM_TX|ANIM_TY|ANIM_TZ) ) {
  659.                 case 0:
  660.                     blendPtr->t = jointPtr->t;
  661.                     break;
  662.                 case ANIM_TX:
  663.                     jointPtr->t.x = jointframe1[0];
  664.                     blendPtr->t.x = jointframe2[0];
  665.                     blendPtr->t.y = jointPtr->t.y;
  666.                     blendPtr->t.z = jointPtr->t.z;
  667.                     jointframe1++;
  668.                     jointframe2++;
  669.                     break;
  670.                 case ANIM_TY:
  671.                     jointPtr->t.y = jointframe1[0];
  672.                     blendPtr->t.y = jointframe2[0];
  673.                     blendPtr->t.x = jointPtr->t.x;
  674.                     blendPtr->t.z = jointPtr->t.z;
  675.                     jointframe1++;
  676.                     jointframe2++;
  677.                     break;
  678.                 case ANIM_TZ:
  679.                     jointPtr->t.z = jointframe1[0];
  680.                     blendPtr->t.z = jointframe2[0];
  681.                     blendPtr->t.x = jointPtr->t.x;
  682.                     blendPtr->t.y = jointPtr->t.y;
  683.                     jointframe1++;
  684.                     jointframe2++;
  685.                     break;
  686.                 case ANIM_TX|ANIM_TY:
  687.                     jointPtr->t.x = jointframe1[0];
  688.                     jointPtr->t.y = jointframe1[1];
  689.                     blendPtr->t.x = jointframe2[0];
  690.                     blendPtr->t.y = jointframe2[1];
  691.                     blendPtr->t.z = jointPtr->t.z;
  692.                     jointframe1 += 2;
  693.                     jointframe2 += 2;
  694.                     break;
  695.                 case ANIM_TX|ANIM_TZ:
  696.                     jointPtr->t.x = jointframe1[0];
  697.                     jointPtr->t.z = jointframe1[1];
  698.                     blendPtr->t.x = jointframe2[0];
  699.                     blendPtr->t.z = jointframe2[1];
  700.                     blendPtr->t.y = jointPtr->t.y;
  701.                     jointframe1 += 2;
  702.                     jointframe2 += 2;
  703.                     break;
  704.                 case ANIM_TY|ANIM_TZ:
  705.                     jointPtr->t.y = jointframe1[0];
  706.                     jointPtr->t.z = jointframe1[1];
  707.                     blendPtr->t.y = jointframe2[0];
  708.                     blendPtr->t.z = jointframe2[1];
  709.                     blendPtr->t.x = jointPtr->t.x;
  710.                     jointframe1 += 2;
  711.                     jointframe2 += 2;
  712.                     break;
  713.                 case ANIM_TX|ANIM_TY|ANIM_TZ:
  714.                     jointPtr->t.x = jointframe1[0];
  715.                     jointPtr->t.y = jointframe1[1];
  716.                     jointPtr->t.z = jointframe1[2];
  717.                     blendPtr->t.x = jointframe2[0];
  718.                     blendPtr->t.y = jointframe2[1];
  719.                     blendPtr->t.z = jointframe2[2];
  720.                     jointframe1 += 3;
  721.                     jointframe2 += 3;
  722.                     break;
  723.             }
  724.  
  725.             switch( animBits & (ANIM_QX|ANIM_QY|ANIM_QZ) ) {
  726.                 case 0:
  727.                     blendPtr->q = jointPtr->q;
  728.                     break;
  729.                 case ANIM_QX:
  730.                     jointPtr->q.x = jointframe1[0];
  731.                     blendPtr->q.x = jointframe2[0];
  732.                     blendPtr->q.y = jointPtr->q.y;
  733.                     blendPtr->q.z = jointPtr->q.z;
  734.                     jointPtr->q.w = jointPtr->q.CalcW();
  735.                     blendPtr->q.w = blendPtr->q.CalcW();
  736.                     break;
  737.                 case ANIM_QY:
  738.                     jointPtr->q.y = jointframe1[0];
  739.                     blendPtr->q.y = jointframe2[0];
  740.                     blendPtr->q.x = jointPtr->q.x;
  741.                     blendPtr->q.z = jointPtr->q.z;
  742.                     jointPtr->q.w = jointPtr->q.CalcW();
  743.                     blendPtr->q.w = blendPtr->q.CalcW();
  744.                     break;
  745.                 case ANIM_QZ:
  746.                     jointPtr->q.z = jointframe1[0];
  747.                     blendPtr->q.z = jointframe2[0];
  748.                     blendPtr->q.x = jointPtr->q.x;
  749.                     blendPtr->q.y = jointPtr->q.y;
  750.                     jointPtr->q.w = jointPtr->q.CalcW();
  751.                     blendPtr->q.w = blendPtr->q.CalcW();
  752.                     break;
  753.                 case ANIM_QX|ANIM_QY:
  754.                     jointPtr->q.x = jointframe1[0];
  755.                     jointPtr->q.y = jointframe1[1];
  756.                     blendPtr->q.x = jointframe2[0];
  757.                     blendPtr->q.y = jointframe2[1];
  758.                     blendPtr->q.z = jointPtr->q.z;
  759.                     jointPtr->q.w = jointPtr->q.CalcW();
  760.                     blendPtr->q.w = blendPtr->q.CalcW();
  761.                     break;
  762.                 case ANIM_QX|ANIM_QZ:
  763.                     jointPtr->q.x = jointframe1[0];
  764.                     jointPtr->q.z = jointframe1[1];
  765.                     blendPtr->q.x = jointframe2[0];
  766.                     blendPtr->q.z = jointframe2[1];
  767.                     blendPtr->q.y = jointPtr->q.y;
  768.                     jointPtr->q.w = jointPtr->q.CalcW();
  769.                     blendPtr->q.w = blendPtr->q.CalcW();
  770.                     break;
  771.                 case ANIM_QY|ANIM_QZ:
  772.                     jointPtr->q.y = jointframe1[0];
  773.                     jointPtr->q.z = jointframe1[1];
  774.                     blendPtr->q.y = jointframe2[0];
  775.                     blendPtr->q.z = jointframe2[1];
  776.                     blendPtr->q.x = jointPtr->q.x;
  777.                     jointPtr->q.w = jointPtr->q.CalcW();
  778.                     blendPtr->q.w = blendPtr->q.CalcW();
  779.                     break;
  780.                 case ANIM_QX|ANIM_QY|ANIM_QZ:
  781.                     jointPtr->q.x = jointframe1[0];
  782.                     jointPtr->q.y = jointframe1[1];
  783.                     jointPtr->q.z = jointframe1[2];
  784.                     blendPtr->q.x = jointframe2[0];
  785.                     blendPtr->q.y = jointframe2[1];
  786.                     blendPtr->q.z = jointframe2[2];
  787.                     jointPtr->q.w = jointPtr->q.CalcW();
  788.                     blendPtr->q.w = blendPtr->q.CalcW();
  789.                     break;
  790.             }
  791.         }
  792.     }
  793.  
  794.     SIMDProcessor->BlendJoints( joints, blendJoints, frame.backlerp, lerpIndex, numLerpJoints );
  795.  
  796.     if ( frame.cycleCount ) {
  797.         joints[ 0 ].t += totaldelta * ( float )frame.cycleCount;
  798.     }
  799. }
  800.  
  801. /*
  802. ====================
  803. idMD5Anim::GetSingleFrame
  804. ====================
  805. */
  806. void idMD5Anim::GetSingleFrame( int framenum, idJointQuat *joints, const int *index, int numIndexes ) const {
  807.     int                        i;
  808.     const float                *frame;
  809.     const float                *jointframe;
  810.     int                        animBits;
  811.     idJointQuat                *jointPtr;
  812.     const jointAnimInfo_t    *infoPtr;
  813.  
  814.     // copy the baseframe
  815.     SIMDProcessor->Memcpy( joints, baseFrame.Ptr(), baseFrame.Num() * sizeof( baseFrame[ 0 ] ) );
  816.  
  817.     if ( ( framenum == 0 ) || !numAnimatedComponents ) {
  818.         // just use the base frame
  819.         return;
  820.     }
  821.  
  822.     frame = &componentFrames[ framenum * numAnimatedComponents ];
  823.  
  824.     for ( i = 0; i < numIndexes; i++ ) {
  825.         int j = index[i];
  826.         jointPtr = &joints[j];
  827.         infoPtr = &jointInfo[j];
  828.  
  829.         animBits = infoPtr->animBits;
  830.         if ( animBits ) {
  831.  
  832.             jointframe = frame + infoPtr->firstComponent;
  833.  
  834.             if ( animBits & (ANIM_TX|ANIM_TY|ANIM_TZ) ) {
  835.  
  836.                 if ( animBits & ANIM_TX ) {
  837.                     jointPtr->t.x = *jointframe++;
  838.                 }
  839.  
  840.                 if ( animBits & ANIM_TY ) {
  841.                     jointPtr->t.y = *jointframe++;
  842.                 }
  843.  
  844.                 if ( animBits & ANIM_TZ ) {
  845.                     jointPtr->t.z = *jointframe++;
  846.                 }
  847.             }
  848.  
  849.             if ( animBits & (ANIM_QX|ANIM_QY|ANIM_QZ) ) {
  850.  
  851.                 if ( animBits & ANIM_QX ) {
  852.                     jointPtr->q.x = *jointframe++;
  853.                 }
  854.  
  855.                 if ( animBits & ANIM_QY ) {
  856.                     jointPtr->q.y = *jointframe++;
  857.                 }
  858.  
  859.                 if ( animBits & ANIM_QZ ) {
  860.                     jointPtr->q.z = *jointframe;
  861.                 }
  862.  
  863.                 jointPtr->q.w = jointPtr->q.CalcW();
  864.             }
  865.         }
  866.     }
  867. }
  868.  
  869. /*
  870. ====================
  871. idMD5Anim::CheckModelHierarchy
  872. ====================
  873. */
  874. void idMD5Anim::CheckModelHierarchy( const idRenderModel *model ) const {
  875.     int    i;
  876.     int    jointNum;
  877.     int    parent;
  878.  
  879.     if ( jointInfo.Num() != model->NumJoints() ) {
  880. // RAVEN BEGIN
  881. // scork: reports the actual joint # mismatch as well
  882.         gameLocal.Error( "Model '%s' has different # of joints (%d) than anim '%s' (%d)", model->Name(), model->NumJoints(), name.c_str(), jointInfo.Num() );
  883. // scork: if we don't return here, we get dozens of other warnings generated by mismatching models below, one warning is sufficient...
  884.         if (common->DoingDeclValidation()) {
  885.             return;
  886.         }
  887. // RAVEN END
  888.     }
  889.  
  890.     const idMD5Joint *modelJoints = model->GetJoints();
  891.     for( i = 0; i < jointInfo.Num(); i++ ) {
  892.         jointNum = jointInfo[ i ].nameIndex;
  893. // RAVEN BEGIN
  894. // jsinger: animationLib changed to a pointer
  895.         if ( modelJoints[ i ].name != animationLib->JointName( jointNum ) ) {
  896. // RAVEN END
  897.             gameLocal.Error( "Model '%s''s joint names don't match anim '%s''s", model->Name(), name.c_str() );
  898.         }
  899.         if ( modelJoints[ i ].parent ) {
  900.             parent = modelJoints[ i ].parent - modelJoints;
  901.         } else {
  902.             parent = -1;
  903.         }
  904.         if ( parent != jointInfo[ i ].parentNum ) {
  905.             gameLocal.Error( "Model '%s' has different joint hierarchy than anim '%s'", model->Name(), name.c_str() );
  906.         }
  907.     }
  908. }
  909.  
  910. /***********************************************************************
  911.  
  912.     idAnimManager
  913.  
  914. ***********************************************************************/
  915.  
  916. /*
  917. ====================
  918. idAnimManager::idAnimManager
  919. ====================
  920. */
  921. idAnimManager::idAnimManager() {
  922. // RAVEN BEGIN
  923. // mwhitlock: Dynamic memory consolidation
  924. #if defined(_RV_MEM_SYS_SUPPORT)
  925.     insideLevelLoad=false;
  926. #endif
  927. // RAVEN END
  928. }
  929.  
  930. /*
  931. ====================
  932. idAnimManager::~idAnimManager
  933. ====================
  934. */
  935. idAnimManager::~idAnimManager() {
  936.     Shutdown();
  937. }
  938.  
  939. /*
  940. ====================
  941. idAnimManager::Shutdown
  942. ====================
  943. */
  944. void idAnimManager::Shutdown( void ) {
  945.     animations.DeleteContents();
  946.     jointnames.Clear();
  947.     jointnamesHash.Free();
  948. }
  949.  
  950. // RAVEN BEGIN
  951. // mwhitlock: Dynamic memory consolidation
  952. #if defined(_RV_MEM_SYS_SUPPORT)
  953. /*
  954. ====================
  955. idAnimManager::BeginLevelLoad
  956. ====================
  957. */
  958. void idAnimManager::BeginLevelLoad( void )
  959. {
  960.     insideLevelLoad = true;
  961. }
  962.  
  963. /*
  964. ====================
  965. idAnimManager::EndLevelLoad
  966. ====================
  967. */
  968. void idAnimManager::EndLevelLoad( void )
  969. {
  970.     insideLevelLoad = false;
  971. }
  972. #endif
  973. // RAVEN END
  974.  
  975. /*
  976. ====================
  977. idAnimManager::GetAnim
  978. ====================
  979. */
  980. idMD5Anim *idAnimManager::GetAnim( const char *name ) {
  981.     idMD5Anim **animptrptr;
  982.     idMD5Anim *anim;
  983.  
  984.     // see if it has been asked for before
  985.     animptrptr = NULL;
  986.     if ( animations.Get( name, &animptrptr ) ) {
  987.         anim = *animptrptr;
  988.     } else {
  989.         idStr extension;
  990.         idStr filename = name;
  991.  
  992.         filename.ExtractFileExtension( extension );
  993.         if ( extension != MD5_ANIM_EXT ) {
  994. // RAVEN BEGIN
  995. // nmckenzie: I'm not interested in debugging this blindly again.
  996.             gameLocal.Warning( "Animation '%s' doesn't have the correct extension for an animation file.", filename.c_str() );
  997. // RAVEN END
  998.             return NULL;
  999.         }
  1000.  
  1001. // RAVEN BEGIN
  1002. // mwhitlock: Dynamic memory consolidation
  1003. #if defined(_RV_MEM_SYS_SUPPORT)
  1004.         RV_PUSH_SYS_HEAP_ID(insideLevelLoad?RV_HEAP_ID_LEVEL:RV_HEAP_ID_PERMANENT);
  1005. #endif
  1006. // RAVEN END
  1007.         anim = new idMD5Anim();
  1008. // RAVEN BEGIN
  1009. // mwhitlock: Dynamic memory consolidation
  1010. #if defined(_RV_MEM_SYS_SUPPORT)
  1011.         RV_POP_HEAP();
  1012. #endif
  1013. // RAVEN END
  1014.         if ( !anim->LoadAnim( filename ) ) {
  1015.             gameLocal.Warning( "Couldn't load anim: '%s'", filename.c_str() );
  1016.             delete anim;
  1017.             anim = NULL;
  1018.         }
  1019.         animations.Set( filename, anim );
  1020.     }
  1021.  
  1022.     return anim;
  1023. }
  1024.  
  1025. /*
  1026. ================
  1027. idAnimManager::ReloadAnims
  1028. ================
  1029. */
  1030. void idAnimManager::ReloadAnims( void ) {
  1031.     TIME_THIS_SCOPE( __FUNCLINE__);
  1032.     
  1033.     int            i;
  1034.     idMD5Anim    **animptr;
  1035.  
  1036.     for( i = 0; i < animations.Num(); i++ ) {
  1037.         animptr = animations.GetIndex( i );
  1038.         if ( animptr && *animptr ) {
  1039.             ( *animptr )->Reload();
  1040.         }
  1041.     }
  1042. }
  1043.  
  1044. /*
  1045. ================
  1046. idAnimManager::JointIndex
  1047. ================
  1048. */
  1049. int    idAnimManager::JointIndex( const char *name ) {
  1050.     int i, hash;
  1051.  
  1052.     hash = jointnamesHash.GenerateKey( name );
  1053.     for ( i = jointnamesHash.First( hash ); i != -1; i = jointnamesHash.Next( i ) ) {
  1054.         if ( jointnames[i].Cmp( name ) == 0 ) {
  1055.             return i;
  1056.         }
  1057.     }
  1058.  
  1059.     i = jointnames.Append( name );
  1060.     jointnamesHash.Add( hash, i );
  1061.     return i;
  1062. }
  1063.  
  1064. /*
  1065. ================
  1066. idAnimManager::JointName
  1067. ================
  1068. */
  1069. const char *idAnimManager::JointName( int index ) const {
  1070.     return jointnames[ index ];
  1071. }
  1072.  
  1073. /*
  1074. ================
  1075. idAnimManager::ListAnims
  1076. ================
  1077. */
  1078. void idAnimManager::ListAnims( void ) const {
  1079.     int            i;
  1080.     idMD5Anim    **animptr;
  1081.     idMD5Anim    *anim;
  1082.     size_t        size;
  1083.     size_t        s;
  1084.     size_t        namesize;
  1085.     int            num;
  1086.  
  1087.     num = 0;
  1088.     size = 0;
  1089.     for( i = 0; i < animations.Num(); i++ ) {
  1090.         animptr = animations.GetIndex( i );
  1091.         if ( animptr && *animptr ) {
  1092.             anim = *animptr;
  1093.             s = anim->Size();
  1094.             gameLocal.Printf( "%8d bytes : %2d refs : %s\n", s, anim->NumRefs(), anim->Name() );
  1095.             size += s;
  1096.             num++;
  1097.         }
  1098.     }
  1099.  
  1100.     namesize = jointnames.Size() + jointnamesHash.Size();
  1101.     for( i = 0; i < jointnames.Num(); i++ ) {
  1102.         namesize += jointnames[ i ].Size();
  1103.     }
  1104.  
  1105.     gameLocal.Printf( "\n%d memory used in %d anims\n", size, num );
  1106.     gameLocal.Printf( "%d memory used in %d joint names\n", namesize, jointnames.Num() );
  1107. }
  1108.  
  1109. // RAVEN BEGIN
  1110. /*
  1111. ================
  1112. idAnimManager::PrintMemInfo
  1113. ================
  1114. */
  1115. void idAnimManager::PrintMemInfo( MemInfo *mi ) {
  1116.  
  1117.     int            i;
  1118.     idMD5Anim    **animptr;
  1119.     idMD5Anim    *anim;
  1120.     size_t        size;
  1121.     size_t        namesize;
  1122.     int            num;
  1123.     idFile        *f;
  1124.  
  1125.     f = fileSystem->OpenFileWrite( mi->filebase + "_anim.txt" );
  1126.     if( !f ) {
  1127.         return;
  1128.     }
  1129.  
  1130.     num = 0;
  1131.     size = 0;
  1132.     for( i = 0; i < animations.Num(); i++ ) {
  1133.         animptr = animations.GetIndex( i );
  1134.         if ( animptr && *animptr ) {
  1135.             anim = *animptr;
  1136.             size += anim->Size();
  1137.             num++;
  1138.  
  1139.             f->Printf( "%8d: %s\n", anim->Size(), anim->Name() );
  1140.         }
  1141.     }
  1142.  
  1143.     namesize = jointnames.Size() + jointnamesHash.Size();
  1144.     for( i = 0; i < jointnames.Num(); i++ ) {
  1145.         namesize += jointnames[ i ].Size();
  1146.     }
  1147.  
  1148.     mi->animsAssetsCount = num;
  1149.     mi->animsAssetsTotal = namesize + size;
  1150.  
  1151.     f->Printf( "\nTotal anim bytes allocated: %s (%s items)\n", idStr::FormatNumber( mi->animsAssetsTotal ).c_str(), idStr::FormatNumber( mi->animsAssetsCount ).c_str() );
  1152.     fileSystem->CloseFile( f );
  1153. }
  1154. // RAVEN END
  1155.  
  1156. /*
  1157. ================
  1158. idAnimManager::FlushUnusedAnims
  1159. ================
  1160. */
  1161. void idAnimManager::FlushUnusedAnims( void ) {
  1162.  
  1163.     TIME_THIS_SCOPE( __FUNCLINE__);
  1164.  
  1165.     int                        i;
  1166.     idMD5Anim                **animptr;
  1167.     idList<idMD5Anim *>        removeAnims;
  1168.     
  1169.     for( i = 0; i < animations.Num(); i++ ) {
  1170.         animptr = animations.GetIndex( i );
  1171.         if ( animptr && *animptr ) {
  1172.             if ( ( *animptr )->NumRefs() <= 0 ) {
  1173.                 removeAnims.Append( *animptr );
  1174.             }
  1175.         }
  1176.     }
  1177.  
  1178.     for( i = 0; i < removeAnims.Num(); i++ ) {
  1179.         animations.Remove( removeAnims[ i ]->Name() );
  1180.         delete removeAnims[ i ];
  1181.     }
  1182. }
  1183.