Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

# OgreAnimationTrack.cpp

Go to the documentation of this file.

    00001 /*
    00002 -----------------------------------------------------------------------------
    00003 This source file is part of OGRE
    00004     (Object-oriented Graphics Rendering Engine)
    00005 For the latest info, see http://www.ogre3d.org/
    00006
    00007 Copyright © 2000-2002 The OGRE Team
    00008 Also see acknowledgements in Readme.html
    00009
    00010 This program is free software; you can redistribute it and/or modify it under
    00011 the terms of the GNU Lesser General Public License as published by the Free Software
    00012 Foundation; either version 2 of the License, or (at your option) any later
    00013 version.
    00014
    00015 This program is distributed in the hope that it will be useful, but WITHOUT
    00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
    00018
    00019 You should have received a copy of the GNU Lesser General Public License along with
    00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
    00022 http://www.gnu.org/copyleft/lesser.txt.
    00023 -----------------------------------------------------------------------------
    00024 */
    00025 #include "OgreStableHeaders.h"
    00026 #include "OgreAnimationTrack.h"
    00027 #include "OgreAnimation.h"
    00028 #include "OgreKeyFrame.h"
    00029 #include "OgreNode.h"
    00030 #include "OgreLogManager.h"
    00031
    00032 // Debug
    00033 #include "OgreRenderWindow.h"
    00034 #include "OgreRoot.h"
    00035 Ogre::RenderWindow* mMainWindow = 0;
    00036 // End Debug
    00037
    00038 namespace Ogre {
    00039
    00040     //---------------------------------------------------------------------
    00041     AnimationTrack::AnimationTrack(Animation* parent) : mParent(parent)
    00042     {
    00043         mTargetNode = 0;
    00044         mMaxKeyFrameTime = -1;
    00045         mSplineBuildNeeded = false;
    00046         mUseShortestRotationPath = true ;
    00047     }
    00048     //---------------------------------------------------------------------
    00049     AnimationTrack::AnimationTrack(Animation* parent, Node* targetNode)
    00050         : mParent(parent), mTargetNode(targetNode)
    00051     {
    00052         mMaxKeyFrameTime = -1;
    00053         mSplineBuildNeeded = false;
    00054         mUseShortestRotationPath = true ;
    00055     }
    00056     //---------------------------------------------------------------------
    00057     AnimationTrack::~AnimationTrack()
    00058     {
    00059         removeAllKeyFrames();
    00060     }
    00061     //---------------------------------------------------------------------
    00062     unsigned short AnimationTrack::getNumKeyFrames(void) const
    00063     {
    00064         return (unsigned short)mKeyFrames.size();
    00065     }
    00066     //---------------------------------------------------------------------
    00067     KeyFrame* AnimationTrack::getKeyFrame(unsigned short index) const
    00068     {
    00069         // If you hit this assert, then the keyframe index is out of bounds
    00070         assert( index < (ushort)mKeyFrames.size() );
    00071
    00072         return mKeyFrames[index];
    00073     }
    00074     //---------------------------------------------------------------------
    00075     Real AnimationTrack::getKeyFramesAtTime(Real timePos, KeyFrame** keyFrame1, KeyFrame** keyFrame2,
    00076             unsigned short* firstKeyIndex) const
    00077     {
    00078         short firstIndex = -1;
    00079         Real totalAnimationLength = mParent->getLength();
    00080
    00081         // Wrap time
    00082         while (timePos > totalAnimationLength)
    00083         {
    00084             timePos -= totalAnimationLength;
    00085         }
    00086
    00087         KeyFrameList::const_iterator i = mKeyFrames.begin();
    00088         // Find last keyframe before or on current time
    00089         while (i != mKeyFrames.end() && (*i)->getTime() <= timePos)
    00090         {
    00091             *keyFrame1 = *i++;
    00092             ++firstIndex;
    00093         }
    00094
    00095         // Trap case where there is no key before this time (problem with animation config)
    00096         // In this case use the first key anyway and pretend it's time index 0
    00097         if (firstIndex == -1)
    00098         {
    00099             *keyFrame1 = *i;
    00100             ++firstIndex;
    00101         }
    00102
    00103         // Fill index of the first key
    00104         if (firstKeyIndex != NULL)
    00105         {
    00106             *firstKeyIndex = firstIndex;
    00107         }
    00108
    00109         // Parametric time
    00110         // t1 = time of previous keyframe
    00111         // t2 = time of next keyframe
    00112         Real t1, t2;
    00113         // Find first keyframe after the time
    00114         // If no next keyframe, wrap back to first
    00115         if (i == mKeyFrames.end())
    00116         {
    00117             *keyFrame2 = mKeyFrames[0];
    00118             t2 = totalAnimationLength;
    00119         }
    00120         else
    00121         {
    00122             *keyFrame2 = *i;
    00123             t2 = (*keyFrame2)->getTime();
    00124         }
    00125
    00126         t1 = (*keyFrame1)->getTime();
    00127
    00128         if (t1 == t2)
    00129         {
    00130             // Same KeyFrame (only one)
    00131             return 0.0;
    00132         }
    00133         else
    00134         {
    00135             return (timePos - t1) / (t2 - t1);
    00136         }
    00137     }
    00138     //---------------------------------------------------------------------
    00139     KeyFrame* AnimationTrack::createKeyFrame(Real timePos)
    00140     {
    00141         KeyFrame* kf = new KeyFrame(this, timePos);
    00142
    00143         // Insert at correct location
    00144         if (timePos > mMaxKeyFrameTime || (timePos == 0 && mKeyFrames.empty()))
    00145         {
    00146             // Quick insert at end
    00147             mKeyFrames.push_back(kf);
    00148             mMaxKeyFrameTime = timePos;
    00149         }
    00150         else
    00151         {
    00152             // Search
    00153             KeyFrameList::iterator i = mKeyFrames.begin();
    00154             while ((*i)->getTime() < timePos && i != mKeyFrames.end())
    00155             {
    00156                 ++i;
    00157             }
    00158             mKeyFrames.insert(i, kf);
    00159         }
    00160
    00161         _keyFrameDataChanged();
    00162
    00163         return kf;
    00164
    00165     }
    00166     //---------------------------------------------------------------------
    00167     void AnimationTrack::removeKeyFrame(unsigned short index)
    00168     {
    00169         // If you hit this assert, then the keyframe index is out of bounds
    00170         assert( index < (ushort)mKeyFrames.size() );
    00171
    00172         KeyFrameList::iterator i = mKeyFrames.begin();
    00173
    00174         i += index;
    00175
    00176         delete *i;
    00177
    00178         mKeyFrames.erase(i);
    00179
    00180         _keyFrameDataChanged();
    00181
    00182
    00183     }
    00184     //---------------------------------------------------------------------
    00185     void AnimationTrack::removeAllKeyFrames(void)
    00186     {
    00187         KeyFrameList::iterator i = mKeyFrames.begin();
    00188
    00189         for (; i != mKeyFrames.end(); ++i)
    00190         {
    00191             delete *i;
    00192         }
    00193
    00194         _keyFrameDataChanged();
    00195
    00196         mKeyFrames.clear();
    00197
    00198     }
    00199     //---------------------------------------------------------------------
    00200     KeyFrame AnimationTrack::getInterpolatedKeyFrame(Real timeIndex) const
    00201     {
    00202         // Return value (note unattached)
    00203         KeyFrame kret(0, timeIndex);
    00204
    00205         // Keyframe pointers
    00206         KeyFrame *k1, *k2;
    00207         unsigned short firstKeyIndex;
    00208
    00209         Real t = this->getKeyFramesAtTime(timeIndex, &k1, &k2, &firstKeyIndex);
    00210
    00211         if (t == 0.0)
    00212         {
    00213             // Just use k1
    00214             kret.setRotation(k1->getRotation());
    00215             kret.setTranslate(k1->getTranslate());
    00216             kret.setScale(k1->getScale());
    00217         }
    00218         else
    00219         {
    00220             // Interpolate by t
    00221             Animation::InterpolationMode im = mParent->getInterpolationMode();
    00222             Animation::RotationInterpolationMode rim =
    00223                 mParent->getRotationInterpolationMode();
    00224             Vector3 base;
    00225             switch(im)
    00226             {
    00227             case Animation::IM_LINEAR:
    00228                 // Interpolate linearly
    00229                 // Rotation
    00230                 // Interpolate to nearest rotation if mUseShortestRotationPath set
    00231                 if (rim == Animation::RIM_LINEAR)
    00232                 {
    00233                     kret.setRotation( Quaternion::nlerp(t, k1->getRotation(),
    00234                         k2->getRotation(), mUseShortestRotationPath) );
    00235                 }
    00236                 else //if (rim == Animation::RIM_SPHERICAL)
    00237                 {
    00238                     kret.setRotation( Quaternion::Slerp(t, k1->getRotation(),
    00239                         k2->getRotation(), mUseShortestRotationPath) );
    00240                 }
    00241
    00242                 // Translation
    00243                 base = k1->getTranslate();
    00244                 kret.setTranslate( base + ((k2->getTranslate() - base) * t) );
    00245
    00246                 // Scale
    00247                 base = k1->getScale();
    00248                 kret.setScale( base + ((k2->getScale() - base) * t) );
    00249                 break;
    00250
    00251             case Animation::IM_SPLINE:
    00252                 // Spline interpolation
    00253
    00254                 // Build splines if required
    00255                 if (mSplineBuildNeeded)
    00256                 {
    00257                     buildInterpolationSplines();
    00258                 }
    00259
    00260                 // Rotation, take mUseShortestRotationPath into account
    00261                 kret.setRotation( mRotationSpline.interpolate(firstKeyIndex, t,
    00262                     mUseShortestRotationPath) );
    00263
    00264                 // Translation
    00265                 kret.setTranslate( mPositionSpline.interpolate(firstKeyIndex, t) );
    00266
    00267                 // Scale
    00268                 kret.setScale( mScaleSpline.interpolate(firstKeyIndex, t) );
    00269
    00270                 break;
    00271             }
    00272
    00273         }
    00274
    00275         return kret;
    00276
    00277     }
    00278     //---------------------------------------------------------------------
    00279     void AnimationTrack::apply(Real timePos, Real weight, bool accumulate)
    00280     {
    00281         applyToNode(mTargetNode, timePos, weight, accumulate);
    00282
    00283     }
    00284     //---------------------------------------------------------------------
    00285     Node* AnimationTrack::getAssociatedNode(void) const
    00286     {
    00287         return mTargetNode;
    00288     }
    00289     //---------------------------------------------------------------------
    00290     void AnimationTrack::setAssociatedNode(Node* node)
    00291     {
    00292         mTargetNode = node;
    00293     }
    00294     //---------------------------------------------------------------------
    00295     void AnimationTrack::applyToNode(Node* node, Real timePos, Real weight, bool accumulate)
    00296     {
    00297         KeyFrame kf = this->getInterpolatedKeyFrame(timePos);
    00298         if (accumulate)
    00299         {
    00300             // add to existing. Weights are not relative, but treated as absolute multipliers for the animation
    00301             Vector3 translate = kf.getTranslate() * weight;
    00302             node->translate(translate);
    00303
    00304             // interpolate between no-rotation and full rotation, to point 'weight', so 0 = no rotate, 1 = full
    00305             Quaternion rotate;
    00306             Animation::RotationInterpolationMode rim =
    00307                 mParent->getRotationInterpolationMode();
    00308             if (rim == Animation::RIM_LINEAR)
    00309             {
    00310                 rotate = Quaternion::nlerp(weight, Quaternion::IDENTITY, kf.getRotation());
    00311             }
    00312             else //if (rim == Animation::RIM_SPHERICAL)
    00313             {
    00314                 rotate = Quaternion::Slerp(weight, Quaternion::IDENTITY, kf.getRotation());
    00315             }
    00316             node->rotate(rotate);
    00317
    00318             Vector3 scale = kf.getScale();
    00319             // Not sure how to modify scale for cumulative anims... leave it alone
    00320             //scale = ((Vector3::UNIT_SCALE - kf.getScale()) * weight) + Vector3::UNIT_SCALE;
    00321             node->scale(scale);
    00322         }
    00323         else
    00324         {
    00325             // apply using weighted transform method
    00326             node->_weightedTransform(weight, kf.getTranslate(), kf.getRotation(),
    00327                 kf.getScale());
    00328         }
    00329
    00330         /*
    00331         // DEBUG
    00332         if (!mMainWindow)
    00333         {
    00334             mMainWindow = Root::getSingleton().getRenderWindow("OGRE Render Window");
    00335         }
    00336         String msg = "Time: ";
    00337         msg << timePos;
    00338         mMainWindow->setDebugText(msg);
    00339         */
    00340
    00341         //node->rotate(kf.getRotation() * weight);
    00342         //node->translate(kf.getTranslate() * weight);
    00343
    00344
    00345
    00346
    00347     }
    00348     //---------------------------------------------------------------------
    00349     void AnimationTrack::buildInterpolationSplines(void) const
    00350     {
    00351         // Don't calc automatically, do it on request at the end
    00352         mPositionSpline.setAutoCalculate(false);
    00353         mRotationSpline.setAutoCalculate(false);
    00354         mScaleSpline.setAutoCalculate(false);
    00355
    00356         mPositionSpline.clear();
    00357         mRotationSpline.clear();
    00358         mScaleSpline.clear();
    00359
    00360         KeyFrameList::const_iterator i, iend;
    00361         iend = mKeyFrames.end(); // precall to avoid overhead
    00362         for (i = mKeyFrames.begin(); i != iend; ++i)
    00363         {
    00364             mPositionSpline.addPoint((*i)->getTranslate());
    00365             mRotationSpline.addPoint((*i)->getRotation());
    00366             mScaleSpline.addPoint((*i)->getScale());
    00367         }
    00368
    00369         mPositionSpline.recalcTangents();
    00370         mRotationSpline.recalcTangents();
    00371         mScaleSpline.recalcTangents();
    00372
    00373
    00374         mSplineBuildNeeded = false;
    00375     }
    00376
    00377     //---------------------------------------------------------------------
    00378     void AnimationTrack::setUseShortestRotationPath(bool useShortestPath)
    00379     {
    00380         mUseShortestRotationPath = useShortestPath ;
    00381     }
    00382
    00383     //---------------------------------------------------------------------
    00384     bool AnimationTrack::getUseShortestRotationPath() const
    00385     {
    00386         return mUseShortestRotationPath ;
    00387     }
    00388     //---------------------------------------------------------------------
    00389     void AnimationTrack::_keyFrameDataChanged(void) const
    00390     {
    00391         mSplineBuildNeeded = true;
    00392     }
    00393
    00394 }
    00395

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:14 2004