Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreAnimation.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 21.7 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreStableHeaders.h"
30#include "OgreAnimation.h"
31#include "OgreKeyFrame.h"
32#include "OgreException.h"
33#include "OgreSkeleton.h"
34#include "OgreBone.h"
35#include "OgreEntity.h"
36#include "OgreSubEntity.h"
37#include "OgreMesh.h"
38#include "OgreSubMesh.h"
39#include "OgreStringConverter.h"
40
41namespace Ogre {
42
43    Animation::InterpolationMode Animation::msDefaultInterpolationMode = Animation::IM_LINEAR;
44    Animation::RotationInterpolationMode
45        Animation::msDefaultRotationInterpolationMode = Animation::RIM_LINEAR;
46    //---------------------------------------------------------------------
47    Animation::Animation(const String& name, Real length)
48        : mName(name)
49        , mLength(length)
50        , mInterpolationMode(msDefaultInterpolationMode)
51        , mRotationInterpolationMode(msDefaultRotationInterpolationMode)
52        , mKeyFrameTimesDirty(false)
53    {
54    }
55    //---------------------------------------------------------------------
56    Animation::~Animation()
57    {
58        destroyAllTracks();
59    }
60    //---------------------------------------------------------------------
61    Real Animation::getLength(void) const
62    {
63        return mLength;
64    }
65    //---------------------------------------------------------------------
66    NodeAnimationTrack* Animation::createNodeTrack(unsigned short handle)
67    {
68        if (hasNodeTrack(handle))
69        {
70            OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, 
71                "Node track with the specified handle " +
72                StringConverter::toString(handle) + " already exists",
73                "Animation::createNodeTrack");
74        }
75
76        NodeAnimationTrack* ret = new NodeAnimationTrack(this, handle);
77
78        mNodeTrackList[handle] = ret;
79        return ret;
80    }
81    //---------------------------------------------------------------------
82    NodeAnimationTrack* Animation::createNodeTrack(unsigned short handle, Node* node)
83    {
84        NodeAnimationTrack* ret = createNodeTrack(handle);
85
86        ret->setAssociatedNode(node);
87
88        return ret;
89    }
90    //---------------------------------------------------------------------
91    unsigned short Animation::getNumNodeTracks(void) const
92    {
93        return (unsigned short)mNodeTrackList.size();
94    }
95        //---------------------------------------------------------------------
96        bool Animation::hasNodeTrack(unsigned short handle) const
97        {
98                return (mNodeTrackList.find(handle) != mNodeTrackList.end());
99        }
100    //---------------------------------------------------------------------
101    NodeAnimationTrack* Animation::getNodeTrack(unsigned short handle) const
102    {
103        NodeTrackList::const_iterator i = mNodeTrackList.find(handle);
104
105        if (i == mNodeTrackList.end())
106        {
107            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
108                "Cannot find node track with the specified handle " +
109                StringConverter::toString(handle),
110                "Animation::getNodeTrack");
111        }
112
113        return i->second;
114
115    }
116    //---------------------------------------------------------------------
117    void Animation::destroyNodeTrack(unsigned short handle)
118    {
119        NodeTrackList::iterator i = mNodeTrackList.find(handle);
120
121                if (i != mNodeTrackList.end())
122                {
123                        delete i->second;
124                        mNodeTrackList.erase(i);
125            _keyFrameListChanged();
126                }
127    }
128    //---------------------------------------------------------------------
129    void Animation::destroyAllNodeTracks(void)
130    {
131        NodeTrackList::iterator i;
132        for (i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i)
133        {
134            delete i->second;
135        }
136        mNodeTrackList.clear();
137        _keyFrameListChanged();
138    }
139        //---------------------------------------------------------------------
140        NumericAnimationTrack* Animation::createNumericTrack(unsigned short handle)
141        {
142        if (hasNumericTrack(handle))
143        {
144            OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, 
145                "Numeric track with the specified handle " +
146                StringConverter::toString(handle) + " already exists",
147                "Animation::createNumericTrack");
148        }
149
150                NumericAnimationTrack* ret = new NumericAnimationTrack(this, handle);
151
152                mNumericTrackList[handle] = ret;
153                return ret;
154        }
155        //---------------------------------------------------------------------
156        NumericAnimationTrack* Animation::createNumericTrack(unsigned short handle, 
157                const AnimableValuePtr& anim)
158        {
159                NumericAnimationTrack* ret = createNumericTrack(handle);
160
161                ret->setAssociatedAnimable(anim);
162
163                return ret;
164        }
165        //---------------------------------------------------------------------
166        unsigned short Animation::getNumNumericTracks(void) const
167        {
168                return (unsigned short)mNumericTrackList.size();
169        }
170        //---------------------------------------------------------------------
171        bool Animation::hasNumericTrack(unsigned short handle) const
172        {
173                return (mNumericTrackList.find(handle) != mNumericTrackList.end());
174        }
175        //---------------------------------------------------------------------
176        NumericAnimationTrack* Animation::getNumericTrack(unsigned short handle) const
177        {
178                NumericTrackList::const_iterator i = mNumericTrackList.find(handle);
179
180                if (i == mNumericTrackList.end())
181                {
182                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
183                                "Cannot find numeric track with the specified handle " +
184                StringConverter::toString(handle),
185                                "Animation::getNumericTrack");
186                }
187
188                return i->second;
189
190        }
191        //---------------------------------------------------------------------
192        void Animation::destroyNumericTrack(unsigned short handle)
193        {
194                NumericTrackList::iterator i = mNumericTrackList.find(handle);
195
196                if (i != mNumericTrackList.end())
197                {
198                        delete i->second;
199                        mNumericTrackList.erase(i);
200            _keyFrameListChanged();
201                }
202        }
203        //---------------------------------------------------------------------
204        void Animation::destroyAllNumericTracks(void)
205        {
206                NumericTrackList::iterator i;
207                for (i = mNumericTrackList.begin(); i != mNumericTrackList.end(); ++i)
208                {
209                        delete i->second;
210                }
211                mNumericTrackList.clear();
212        _keyFrameListChanged();
213        }
214        //---------------------------------------------------------------------
215        VertexAnimationTrack* Animation::createVertexTrack(unsigned short handle, 
216                VertexAnimationType animType)
217        {
218        if (hasVertexTrack(handle))
219        {
220            OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, 
221                "Vertex track with the specified handle " +
222                StringConverter::toString(handle) + " already exists",
223                "Animation::createVertexTrack");
224        }
225
226                VertexAnimationTrack* ret = new VertexAnimationTrack(this, handle, animType);
227
228                mVertexTrackList[handle] = ret;
229                return ret;
230
231        }
232        //---------------------------------------------------------------------
233        VertexAnimationTrack* Animation::createVertexTrack(unsigned short handle, 
234                VertexData* data, VertexAnimationType animType)
235        {
236                VertexAnimationTrack* ret = createVertexTrack(handle, animType);
237
238                ret->setAssociatedVertexData(data);
239
240                return ret;
241        }
242        //---------------------------------------------------------------------
243        unsigned short Animation::getNumVertexTracks(void) const
244        {
245                return (unsigned short)mVertexTrackList.size();
246        }
247        //---------------------------------------------------------------------
248        bool Animation::hasVertexTrack(unsigned short handle) const
249        {
250                return (mVertexTrackList.find(handle) != mVertexTrackList.end());
251        }
252        //---------------------------------------------------------------------
253        VertexAnimationTrack* Animation::getVertexTrack(unsigned short handle) const
254        {
255                VertexTrackList::const_iterator i = mVertexTrackList.find(handle);
256
257                if (i == mVertexTrackList.end())
258                {
259                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
260                                "Cannot find vertex track with the specified handle " +
261                StringConverter::toString(handle),
262                                "Animation::getVertexTrack");
263                }
264
265                return i->second;
266
267        }
268        //---------------------------------------------------------------------
269        void Animation::destroyVertexTrack(unsigned short handle)
270        {
271                VertexTrackList::iterator i = mVertexTrackList.find(handle);
272
273                if (i != mVertexTrackList.end())
274                {
275                        delete i->second;
276                        mVertexTrackList.erase(i);
277            _keyFrameListChanged();
278                }
279        }
280        //---------------------------------------------------------------------
281        void Animation::destroyAllVertexTracks(void)
282        {
283                VertexTrackList::iterator i;
284                for (i = mVertexTrackList.begin(); i != mVertexTrackList.end(); ++i)
285                {
286                        delete i->second;
287                }
288                mVertexTrackList.clear();
289        _keyFrameListChanged();
290        }
291        //---------------------------------------------------------------------
292        void Animation::destroyAllTracks(void)
293        {
294                destroyAllNodeTracks();
295                destroyAllNumericTracks();
296                destroyAllVertexTracks();
297        }
298    //---------------------------------------------------------------------
299    const String& Animation::getName(void) const
300    {
301        return mName;
302    }
303    //---------------------------------------------------------------------
304        void Animation::apply(Real timePos, Real weight, Real scale)
305    {
306        // Calculate time index for fast keyframe search
307        TimeIndex timeIndex = _getTimeIndex(timePos);
308
309        NodeTrackList::iterator i;
310        for (i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i)
311        {
312            i->second->apply(timeIndex, weight, scale);
313        }
314                NumericTrackList::iterator j;
315                for (j = mNumericTrackList.begin(); j != mNumericTrackList.end(); ++j)
316                {
317                        j->second->apply(timeIndex, weight, scale);
318                }
319                VertexTrackList::iterator k;
320                for (k = mVertexTrackList.begin(); k != mVertexTrackList.end(); ++k)
321                {
322                        k->second->apply(timeIndex, weight, scale);
323                }
324
325    }
326    //---------------------------------------------------------------------
327    void Animation::apply(Skeleton* skel, Real timePos, Real weight, 
328                Real scale)
329    {
330        // Calculate time index for fast keyframe search
331        TimeIndex timeIndex = _getTimeIndex(timePos);
332
333        NodeTrackList::iterator i;
334        for (i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i)
335        {
336            // get bone to apply to
337            Bone* b = skel->getBone(i->first);
338            i->second->applyToNode(b, timeIndex, weight, scale);
339        }
340
341
342    }
343        //---------------------------------------------------------------------
344        void Animation::apply(Entity* entity, Real timePos, Real weight, 
345                bool software, bool hardware)
346        {
347        // Calculate time index for fast keyframe search
348        TimeIndex timeIndex = _getTimeIndex(timePos);
349
350                VertexTrackList::iterator i;
351                for (i = mVertexTrackList.begin(); i != mVertexTrackList.end(); ++i)
352                {
353                        unsigned short handle = i->first;
354                        VertexAnimationTrack* track = i->second;
355
356                        VertexData* swVertexData;
357                        VertexData* hwVertexData;
358                        VertexData* origVertexData;
359                        bool firstAnim = false;
360                        if (handle == 0)
361                        {
362                                // shared vertex data
363                                firstAnim = !entity->_getBuffersMarkedForAnimation();
364                                swVertexData = entity->_getSoftwareVertexAnimVertexData();
365                                hwVertexData = entity->_getHardwareVertexAnimVertexData();
366                                origVertexData = entity->getMesh()->sharedVertexData;
367                                entity->_markBuffersUsedForAnimation();
368                        }
369                        else
370                        {
371                                // sub entity vertex data (-1)
372                                SubEntity* s = entity->getSubEntity(handle - 1);
373                                // Skip this track if subentity is not visible
374                                if (!s->isVisible())
375                                        continue;
376                                firstAnim = !s->_getBuffersMarkedForAnimation();
377                                swVertexData = s->_getSoftwareVertexAnimVertexData();
378                                hwVertexData = s->_getHardwareVertexAnimVertexData();
379                                origVertexData = s->getSubMesh()->vertexData;
380                                s->_markBuffersUsedForAnimation();
381                        }
382                        // Apply to both hardware and software, if requested
383                        if (software)
384                        {
385                                if (firstAnim && track->getAnimationType() == VAT_POSE)
386                                {
387                                        // First time through for a piece of pose animated vertex data
388                                        // We need to copy the original position values to the temp accumulator
389                                        const VertexElement* origelem = 
390                                                origVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
391                                        const VertexElement* destelem = 
392                                                swVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
393                                        HardwareVertexBufferSharedPtr origBuffer = 
394                                                origVertexData->vertexBufferBinding->getBuffer(origelem->getSource());
395                                        HardwareVertexBufferSharedPtr destBuffer = 
396                                                swVertexData->vertexBufferBinding->getBuffer(destelem->getSource());
397                                        destBuffer->copyData(*origBuffer.get(), 0, 0, destBuffer->getSizeInBytes(), true);
398                                }
399                                track->setTargetMode(VertexAnimationTrack::TM_SOFTWARE);
400                                track->applyToVertexData(swVertexData, timeIndex, weight, 
401                                        &(entity->getMesh()->getPoseList()));
402                        }
403                        if (hardware)
404                        {
405                                track->setTargetMode(VertexAnimationTrack::TM_HARDWARE);
406                                track->applyToVertexData(hwVertexData, timeIndex, weight, 
407                                        &(entity->getMesh()->getPoseList()));
408                        }
409                }
410
411        }
412    //---------------------------------------------------------------------
413    void Animation::setInterpolationMode(InterpolationMode im)
414    {
415        mInterpolationMode = im;
416    }
417    //---------------------------------------------------------------------
418    Animation::InterpolationMode Animation::getInterpolationMode(void) const
419    {
420        return mInterpolationMode;
421    }
422    //---------------------------------------------------------------------
423    void Animation::setDefaultInterpolationMode(InterpolationMode im)
424    {
425        msDefaultInterpolationMode = im;
426    }
427    //---------------------------------------------------------------------
428    Animation::InterpolationMode Animation::getDefaultInterpolationMode(void)
429    {
430        return msDefaultInterpolationMode;
431    }
432    //---------------------------------------------------------------------
433    const Animation::NodeTrackList& Animation::_getNodeTrackList(void) const
434    {
435        return mNodeTrackList;
436
437    }
438        //---------------------------------------------------------------------
439        const Animation::NumericTrackList& Animation::_getNumericTrackList(void) const
440        {
441                return mNumericTrackList;
442        }
443    //---------------------------------------------------------------------
444    const Animation::VertexTrackList& Animation::_getVertexTrackList(void) const
445    {
446        return mVertexTrackList;
447    }
448    //---------------------------------------------------------------------
449    void Animation::setRotationInterpolationMode(RotationInterpolationMode im)
450    {
451        mRotationInterpolationMode = im;
452    }
453    //---------------------------------------------------------------------
454    Animation::RotationInterpolationMode Animation::getRotationInterpolationMode(void) const
455    {
456        return mRotationInterpolationMode;
457    }
458    //---------------------------------------------------------------------
459    void Animation::setDefaultRotationInterpolationMode(RotationInterpolationMode im)
460    {
461        msDefaultRotationInterpolationMode = im;
462    }
463    //---------------------------------------------------------------------
464    Animation::RotationInterpolationMode Animation::getDefaultRotationInterpolationMode(void)
465    {
466        return msDefaultRotationInterpolationMode;
467    }
468    //---------------------------------------------------------------------
469        void Animation::optimise(bool discardIdentityNodeTracks)
470        {
471                optimiseNodeTracks(discardIdentityNodeTracks);
472                optimiseVertexTracks();
473               
474        }
475        //-----------------------------------------------------------------------
476    void Animation::_collectIdentityNodeTracks(TrackHandleList& tracks) const
477    {
478                NodeTrackList::const_iterator i, iend;
479        iend = mNodeTrackList.end();
480                for (i = mNodeTrackList.begin(); i != iend; ++i)
481                {
482                        const NodeAnimationTrack* track = i->second;
483                        if (track->hasNonZeroKeyFrames())
484                        {
485                tracks.erase(i->first);
486            }
487                }
488    }
489        //-----------------------------------------------------------------------
490    void Animation::_destroyNodeTracks(const TrackHandleList& tracks)
491    {
492        TrackHandleList::const_iterator t, tend;
493        tend = tracks.end();
494                for (t = tracks.begin(); t != tend; ++t)
495                {
496                        destroyNodeTrack(*t);
497                }
498    }
499        //-----------------------------------------------------------------------
500        void Animation::optimiseNodeTracks(bool discardIdentityTracks)
501        {
502                // Iterate over the node tracks and identify those with no useful keyframes
503                std::list<unsigned short> tracksToDestroy;
504                NodeTrackList::iterator i;
505                for (i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i)
506                {
507                        NodeAnimationTrack* track = i->second;
508                        if (discardIdentityTracks && !track->hasNonZeroKeyFrames())
509                        {
510                                // mark the entire track for destruction
511                                tracksToDestroy.push_back(i->first);
512                        }
513                        else
514                        {
515                                track->optimise();
516                        }
517
518                }
519
520                // Now destroy the tracks we marked for death
521                for(std::list<unsigned short>::iterator h = tracksToDestroy.begin();
522                        h != tracksToDestroy.end(); ++h)
523                {
524                        destroyNodeTrack(*h);
525                }
526        }
527        //-----------------------------------------------------------------------
528        void Animation::optimiseVertexTracks(void)
529        {
530                // Iterate over the node tracks and identify those with no useful keyframes
531                std::list<unsigned short> tracksToDestroy;
532                VertexTrackList::iterator i;
533                for (i = mVertexTrackList.begin(); i != mVertexTrackList.end(); ++i)
534                {
535                        VertexAnimationTrack* track = i->second;
536                        if (!track->hasNonZeroKeyFrames())
537                        {
538                                // mark the entire track for destruction
539                                tracksToDestroy.push_back(i->first);
540                        }
541                        else
542                        {
543                                track->optimise();
544                        }
545
546                }
547
548                // Now destroy the tracks we marked for death
549                for(std::list<unsigned short>::iterator h = tracksToDestroy.begin();
550                        h != tracksToDestroy.end(); ++h)
551                {
552                        destroyVertexTrack(*h);
553                }
554
555        }
556        //-----------------------------------------------------------------------
557        Animation* Animation::clone(const String& newName) const
558        {
559                Animation* newAnim = new Animation(newName, mLength);
560        newAnim->mInterpolationMode = mInterpolationMode;
561        newAnim->mRotationInterpolationMode = mRotationInterpolationMode;
562               
563                // Clone all tracks
564                for (NodeTrackList::const_iterator i = mNodeTrackList.begin();
565                        i != mNodeTrackList.end(); ++i)
566                {
567                        newAnim->mNodeTrackList[i->second->getHandle()] = i->second->_clone(newAnim);
568                }
569                for (NumericTrackList::const_iterator i = mNumericTrackList.begin();
570                        i != mNumericTrackList.end(); ++i)
571                {
572                        newAnim->mNumericTrackList[i->second->getHandle()] = i->second->_clone(newAnim);
573                }
574                for (VertexTrackList::const_iterator i = mVertexTrackList.begin();
575                        i != mVertexTrackList.end(); ++i)
576                {
577                        newAnim->mVertexTrackList[i->second->getHandle()] = i->second->_clone(newAnim);
578                }
579
580        newAnim->_keyFrameListChanged();
581                return newAnim;
582
583        }
584    //-----------------------------------------------------------------------
585    TimeIndex Animation::_getTimeIndex(Real timePos) const
586    {
587        // Uncomment following statement for work as previous
588        //return timePos;
589
590        // Build keyframe time list on demand
591        if (mKeyFrameTimesDirty)
592        {
593            buildKeyFrameTimeList();
594        }
595
596        // Wrap time
597        Real totalAnimationLength = mLength;
598
599        while (timePos > totalAnimationLength && totalAnimationLength > 0.0f)
600        {
601            timePos -= totalAnimationLength;
602        }
603
604        // Search for global index
605        KeyFrameTimeList::iterator it =
606            std::lower_bound(mKeyFrameTimes.begin(), mKeyFrameTimes.end(), timePos);
607
608        return TimeIndex(timePos, std::distance(mKeyFrameTimes.begin(), it));
609    }
610    //-----------------------------------------------------------------------
611    void Animation::buildKeyFrameTimeList(void) const
612    {
613        NodeTrackList::const_iterator i;
614                NumericTrackList::const_iterator j;
615                VertexTrackList::const_iterator k;
616
617        // Clear old keyframe times
618        mKeyFrameTimes.clear();
619
620        // Collect all keyframe times from each track
621        for (i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i)
622        {
623            i->second->_collectKeyFrameTimes(mKeyFrameTimes);
624        }
625                for (j = mNumericTrackList.begin(); j != mNumericTrackList.end(); ++j)
626                {
627            j->second->_collectKeyFrameTimes(mKeyFrameTimes);
628                }
629                for (k = mVertexTrackList.begin(); k != mVertexTrackList.end(); ++k)
630                {
631            k->second->_collectKeyFrameTimes(mKeyFrameTimes);
632                }
633
634        // Build global index to local index map for each track
635        for (i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i)
636        {
637            i->second->_buildKeyFrameIndexMap(mKeyFrameTimes);
638        }
639                for (j = mNumericTrackList.begin(); j != mNumericTrackList.end(); ++j)
640                {
641            j->second->_buildKeyFrameIndexMap(mKeyFrameTimes);
642                }
643                for (k = mVertexTrackList.begin(); k != mVertexTrackList.end(); ++k)
644                {
645            k->second->_buildKeyFrameIndexMap(mKeyFrameTimes);
646                }
647
648        // Reset dirty flag
649        mKeyFrameTimesDirty = false;
650    }
651
652}
653
654
Note: See TracBrowser for help on using the repository browser.