Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/include/OgreAnimationTrack.h @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 23.6 KB
RevLine 
[1]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
30#ifndef __AnimationTrack_H__
31#define __AnimationTrack_H__
32
33#include "OgrePrerequisites.h"
34#include "OgreSimpleSpline.h"
35#include "OgreRotationalSpline.h"
36#include "OgreKeyFrame.h"
37#include "OgreAnimable.h"
38#include "OgrePose.h"
39
40namespace Ogre
41{
42    /** Time index object used to search keyframe at the given position.
43    */
44    class _OgreExport TimeIndex
45    {
46    protected:
47        /** The time position (in relation to the whole animation sequence)
48        */
49        Real mTimePos;
50        /** The global keyframe index (in relation to the whole animation sequence)
51            that used to convert to local keyframe index, or INVALID_KEY_INDEX which
52            means global keyframe index unavailable, and then slight slow method will
53            used to search local keyframe index.
54        */
55        uint mKeyIndex;
56
57        /** Indicate it's an invalid global keyframe index.
58        */
59        static const uint INVALID_KEY_INDEX = (uint)-1;
60
61    public:
62        /** Construct time index object by the given time position.
63        */
64        TimeIndex(Real timePos)
65            : mTimePos(timePos)
66            , mKeyIndex(INVALID_KEY_INDEX)
67        {
68        }
69
70        /** Construct time index object by the given time position and
71            global keyframe index.
72        @note In normally, you don't need to use this constructor directly, use
73            Animation::_getTimeIndex instead.
74        */
75        TimeIndex(Real timePos, uint keyIndex)
76            : mTimePos(timePos)
77            , mKeyIndex(keyIndex)
78        {
79        }
80
81        bool hasKeyIndex(void) const
82        {
83            return mKeyIndex != INVALID_KEY_INDEX;
84        }
85
86        Real getTimePos(void) const
87        {
88            return mTimePos;
89        }
90
91        uint getKeyIndex(void) const
92        {
93            return mKeyIndex;
94        }
95    };
96
97    /** A 'track' in an animation sequence, ie a sequence of keyframes which affect a
98        certain type of animable object.
99    @remarks
100        This class is intended as a base for more complete classes which will actually
101        animate specific types of object, e.g. a bone in a skeleton to affect
102        skeletal animation. An animation will likely include multiple tracks each of which
103        can be made up of many KeyFrame instances. Note that the use of tracks allows each animable
104        object to have it's own number of keyframes, i.e. you do not have to have the
105        maximum number of keyframes for all animable objects just to cope with the most
106        animated one.
107    @remarks
108        Since the most common animable object is a Node, there are options in this class for associating
109        the track with a Node which will receive keyframe updates automatically when the 'apply' method
110        is called.
111        @remarks
112                By default rotation is done using shortest-path algorithm.
113                It is possible to change this behaviour using
114                setUseShortestRotationPath() method.
115    */
116    class _OgreExport AnimationTrack
117    {
118    public:
119        /// Constructor
120        AnimationTrack(Animation* parent, unsigned short handle);
121
122        virtual ~AnimationTrack();
123
124                /** Get the handle associated with this track. */
125                unsigned short getHandle(void) const { return mHandle; }
126
127        /** Returns the number of keyframes in this animation. */
128        virtual unsigned short getNumKeyFrames(void) const;
129
130        /** Returns the KeyFrame at the specified index. */
131        virtual KeyFrame* getKeyFrame(unsigned short index) const;
132
133        /** Gets the 2 KeyFrame objects which are active at the time given, and the blend value between them.
134        @remarks
135            At any point in time  in an animation, there are either 1 or 2 keyframes which are 'active',
136            1 if the time index is exactly on a keyframe, 2 at all other times i.e. the keyframe before
137            and the keyframe after.
138        @par
139            This method returns those keyframes given a time index, and also returns a parametric
140            value indicating the value of 't' representing where the time index falls between them.
141            E.g. if it returns 0, the time index is exactly on keyFrame1, if it returns 0.5 it is
142            half way between keyFrame1 and keyFrame2 etc.
143        @param timeIndex The time index.
144        @param keyFrame1 Pointer to a KeyFrame pointer which will receive the pointer to the
145            keyframe just before or at this time index.
146        @param keyFrame2 Pointer to a KeyFrame pointer which will receive the pointer to the
147            keyframe just after this time index.
148        @param firstKeyIndex Pointer to an unsigned short which, if supplied, will receive the
149            index of the 'from' keyframe incase the caller needs it.
150        @returns Parametric value indicating how far along the gap between the 2 keyframes the timeIndex
151            value is, e.g. 0.0 for exactly at 1, 0.25 for a quarter etc. By definition the range of this
152            value is:  0.0 <= returnValue < 1.0 .
153        */
154        virtual Real getKeyFramesAtTime(const TimeIndex& timeIndex, KeyFrame** keyFrame1, KeyFrame** keyFrame2,
155            unsigned short* firstKeyIndex = 0) const;
156
157        /** Creates a new KeyFrame and adds it to this animation at the given time index.
158        @remarks
159            It is better to create KeyFrames in time order. Creating them out of order can result
160            in expensive reordering processing. Note that a KeyFrame at time index 0.0 is always created
161            for you, so you don't need to create this one, just access it using getKeyFrame(0);
162                @note this method will always create a keyframe even if the track already has a keyframe
163                        at the given time position.
164        @param timePos The time from which this KeyFrame will apply.
165        */
166        virtual KeyFrame* createKeyFrame(Real timePos);
167
168        /** Removes a KeyFrame by it's index. */
169        virtual void removeKeyFrame(unsigned short index);
170
171        /** Removes all the KeyFrames from this track. */
172        virtual void removeAllKeyFrames(void);
173
174
175        /** Gets a KeyFrame object which contains the interpolated transforms at the time index specified.
176        @remarks
177            The KeyFrame objects held by this class are transformation snapshots at
178            discrete points in time. Normally however, you want to interpolate between these
179            keyframes to produce smooth movement, and this method allows you to do this easily.
180            In animation terminology this is called 'tweening'.
181        @param timeIndex The time (in relation to the whole animation sequence)
182        @param kf Keyframe object to store results
183        */
184        virtual void getInterpolatedKeyFrame(const TimeIndex& timeIndex, KeyFrame* kf) const = 0;
185
186        /** Applies an animation track to the designated target.
187        @param timeIndex The time position in the animation to apply.
188        @param weight The influence to give to this track, 1.0 for full influence, less to blend with
189          other animations.
190            @param scale The scale to apply to translations and scalings, useful for
191                        adapting an animation to a different size target.
192        */
193        virtual void apply(const TimeIndex& timeIndex, Real weight = 1.0, Real scale = 1.0f) = 0;
194
195        /** Internal method used to tell the track that keyframe data has been
196            changed, which may cause it to rebuild some internal data. */
197                virtual void _keyFrameDataChanged(void) const {}
198
199                /** Method to determine if this track has any KeyFrames which are
200                doing anything useful - can be used to determine if this track
201                can be optimised out.
202                */
203                virtual bool hasNonZeroKeyFrames(void) const { return true; }
204
205                /** Optimise the current track by removing any duplicate keyframes. */
206                virtual void optimise(void) {}
207
208        /** Internal method to collect keyframe times, in unique, ordered format. */
209        virtual void _collectKeyFrameTimes(std::vector<Real>& keyFrameTimes);
210
211        /** Internal method to build keyframe time index map to translate global lower
212            bound index to local lower bound index. */
213        virtual void _buildKeyFrameIndexMap(const std::vector<Real>& keyFrameTimes);
214
215    protected:
216        typedef std::vector<KeyFrame*> KeyFrameList;
217        KeyFrameList mKeyFrames;
218        Animation* mParent;
219                unsigned short mHandle;
220
221        /// Map used to translate global keyframe time lower bound index to local lower bound index
222        typedef std::vector<ushort> KeyFrameIndexMap;
223        KeyFrameIndexMap mKeyFrameIndexMap;
224
225                /// Create a keyframe implementation - must be overridden
226                virtual KeyFrame* createKeyFrameImpl(Real time) = 0;
227
228                /// Internal method for clone implementation
229                virtual void populateClone(AnimationTrack* clone) const;
230               
231
232
233    };
234
235        /** Specialised AnimationTrack for dealing with generic animable values.
236        */
237        class _OgreExport NumericAnimationTrack : public AnimationTrack
238        {
239        public:
240                /// Constructor
241                NumericAnimationTrack(Animation* parent, unsigned short handle);
242                /// Constructor, associates with an AnimableValue
243                NumericAnimationTrack(Animation* parent, unsigned short handle, 
244                        AnimableValuePtr& target);
245
246        /** Creates a new KeyFrame and adds it to this animation at the given time index.
247        @remarks
248            It is better to create KeyFrames in time order. Creating them out of order can result
249            in expensive reordering processing. Note that a KeyFrame at time index 0.0 is always created
250            for you, so you don't need to create this one, just access it using getKeyFrame(0);
251        @param timePos The time from which this KeyFrame will apply.
252        */
253        virtual NumericKeyFrame* createNumericKeyFrame(Real timePos);
254
255                /// @copydoc AnimationTrack::getInterpolatedKeyFrame
256        virtual void getInterpolatedKeyFrame(const TimeIndex& timeIndex, KeyFrame* kf) const;
257
258                /// @copydoc AnimationTrack::apply
259                virtual void apply(const TimeIndex& timeIndex, Real weight = 1.0, Real scale = 1.0f);
260
261        /** Applies an animation track to a given animable value.
262                @param anim The AnimableValue to which to apply the animation
263        @param timeIndex The time position in the animation to apply.
264        @param weight The influence to give to this track, 1.0 for full influence, less to blend with
265          other animations.
266            @param scale The scale to apply to translations and scalings, useful for
267                        adapting an animation to a different size target.
268        */
269                void applyToAnimable(const AnimableValuePtr& anim, const TimeIndex& timeIndex, 
270                        Real weight = 1.0, Real scale = 1.0f);
271
272                /** Returns a pointer to the associated animable object (if any). */
273                virtual const AnimableValuePtr& getAssociatedAnimable(void) const;
274
275                /** Sets the associated animable object which will be automatically
276                        affected by calls to 'apply'. */
277                virtual void setAssociatedAnimable(const AnimableValuePtr& val);
278
279                /** Returns the KeyFrame at the specified index. */
280                NumericKeyFrame* getNumericKeyFrame(unsigned short index) const;
281
282                /** Clone this track (internal use only) */
283                NumericAnimationTrack* _clone(Animation* newParent) const;
284
285
286        protected:
287                /// Target to animate
288                AnimableValuePtr mTargetAnim;
289
290                /// @copydoc AnimationTrack::createKeyFrameImpl
291                KeyFrame* createKeyFrameImpl(Real time);
292
293
294        };
295
296        /** Specialised AnimationTrack for dealing with node transforms.
297        */
298        class _OgreExport NodeAnimationTrack : public AnimationTrack
299        {
300        public:
301                /// Constructor
302                NodeAnimationTrack(Animation* parent, unsigned short handle);
303                /// Constructor, associates with a Node
304                NodeAnimationTrack(Animation* parent, unsigned short handle, 
305                        Node* targetNode);
306        /// Destructor
307        virtual ~NodeAnimationTrack();
308        /** Creates a new KeyFrame and adds it to this animation at the given time index.
309        @remarks
310            It is better to create KeyFrames in time order. Creating them out of order can result
311            in expensive reordering processing. Note that a KeyFrame at time index 0.0 is always created
312            for you, so you don't need to create this one, just access it using getKeyFrame(0);
313        @param timePos The time from which this KeyFrame will apply.
314        */
315        virtual TransformKeyFrame* createNodeKeyFrame(Real timePos);
316                /** Returns a pointer to the associated Node object (if any). */
317                virtual Node* getAssociatedNode(void) const;
318
319                /** Sets the associated Node object which will be automatically affected by calls to 'apply'. */
320                virtual void setAssociatedNode(Node* node);
321
322                /** As the 'apply' method but applies to a specified Node instead of associated node. */
323                virtual void applyToNode(Node* node, const TimeIndex& timeIndex, Real weight = 1.0, 
324                        Real scale = 1.0f);
325
326                /** Sets the method of rotation calculation */
327                virtual void setUseShortestRotationPath(bool useShortestPath);
328
329                /** Gets the method of rotation calculation */
330                virtual bool getUseShortestRotationPath() const;
331
332                /// @copydoc AnimationTrack::getInterpolatedKeyFrame
333        virtual void getInterpolatedKeyFrame(const TimeIndex& timeIndex, KeyFrame* kf) const;
334
335                /// @copydoc AnimationTrack::apply
336                virtual void apply(const TimeIndex& timeIndex, Real weight = 1.0, Real scale = 1.0f);
337
338                /// @copydoc AnimationTrack::_keyFrameDataChanged
339                void _keyFrameDataChanged(void) const;
340
341                /** Returns the KeyFrame at the specified index. */
342                virtual TransformKeyFrame* getNodeKeyFrame(unsigned short index) const;
343
344
345                /** Method to determine if this track has any KeyFrames which are
346                        doing anything useful - can be used to determine if this track
347                        can be optimised out.
348                */
349                virtual bool hasNonZeroKeyFrames(void) const;
350
351                /** Optimise the current track by removing any duplicate keyframes. */
352                virtual void optimise(void);
353
354                /** Clone this track (internal use only) */
355                NodeAnimationTrack* _clone(Animation* newParent) const;
356               
357        protected:
358                /// Specialised keyframe creation
359                KeyFrame* createKeyFrameImpl(Real time);
360                // Flag indicating we need to rebuild the splines next time
361                virtual void buildInterpolationSplines(void) const;
362
363        // Struct for store splines, allocate on demand for better memory footprint
364        struct Splines
365        {
366                    SimpleSpline positionSpline;
367                    SimpleSpline scaleSpline;
368                    RotationalSpline rotationSpline;
369        };
370
371                Node* mTargetNode;
372                // Prebuilt splines, must be mutable since lazy-update in const method
373                mutable Splines* mSplines;
374                mutable bool mSplineBuildNeeded;
375                /// Defines if rotation is done using shortest path
376                mutable bool mUseShortestRotationPath ;
377
378
379        };
380
381        /** Type of vertex animation.
382                Vertex animation comes in 2 types, morph and pose. The reason
383                for the 2 types is that we have 2 different potential goals - to encapsulate
384                a complete, flowing morph animation with multiple keyframes (a typical animation,
385                but implemented by having snapshots of the vertex data at each keyframe),
386                or to represent a single pose change, for example a facial expression.
387                Whilst both could in fact be implemented using the same system, we choose
388                to separate them since the requirements and limitations of each are quite
389                different.
390        @par
391                Morph animation is a simple approach where we have a whole series of
392                snapshots of vertex data which must be interpolated, e.g. a running
393                animation implemented as morph targets. Because this is based on simple
394                snapshots, it's quite fast to use when animating an entire mesh because
395                it's a simple linear change between keyframes. However, this simplistic
396                approach does not support blending between multiple morph animations.
397                If you need animation blending, you are advised to use skeletal animation
398                for full-mesh animation, and pose animation for animation of subsets of
399                meshes or where skeletal animation doesn't fit - for example facial animation.
400                For animating in a vertex shader, morph animation is quite simple and
401                just requires the 2 vertex buffers (one the original position buffer)
402                of absolute position data, and an interpolation factor. Each track in
403                a morph animation refrences a unique set of vertex data.
404        @par
405                Pose animation is more complex. Like morph animation each track references
406                a single unique set of vertex data, but unlike morph animation, each
407                keyframe references 1 or more 'poses', each with an influence level.
408                A pose is a series of offsets to the base vertex data, and may be sparse - ie it
409                may not reference every vertex. Because they're offsets, they can be
410                blended - both within a track and between animations. This set of features
411                is very well suited to facial animation.
412        @par
413                For example, let's say you modelled a face (one set of vertex data), and
414                defined a set of poses which represented the various phonetic positions
415                of the face. You could then define an animation called 'SayHello', containing
416                a single track which referenced the face vertex data, and which included
417                a series of keyframes, each of which referenced one or more of the facial
418                positions at different influence levels - the combination of which over
419                time made the face form the shapes required to say the word 'hello'. Since
420                the poses are only stored once, but can be referenced may times in
421                many animations, this is a very powerful way to build up a speech system.
422        @par
423                The downside of pose animation is that it can be more difficult to set up.
424                Also, since it uses more buffers (one for the base data, and one for each
425                active pose), if you're animating in hardware using vertex shaders you need
426                to keep an eye on how many poses you're blending at once. You define a
427                maximum supported number in your vertex program definition, see the
428                includes_pose_animation material script entry.
429        @par
430                So, by partitioning the vertex animation approaches into 2, we keep the
431                simple morph technique easy to use, whilst still allowing all
432                the powerful techniques to be used. Note that morph animation cannot
433                be blended with other types of vertex animation (pose animation or other
434                morph animation); pose animation can be blended with other pose animation
435                though, and both types can be combined with skeletal animation. Also note
436                that all morph animation can be expressed as pose animation, but not vice
437                versa.
438        */
439        enum VertexAnimationType
440        {
441                /// No animation
442                VAT_NONE = 0,
443                /// Morph animation is made up of many interpolated snapshot keyframes
444                VAT_MORPH = 1,
445                /// Pose animation is made up of a single delta pose keyframe
446                VAT_POSE = 2
447        };
448
449        /** Specialised AnimationTrack for dealing with changing vertex position information.
450        @see VertexAnimationType
451        */
452        class _OgreExport VertexAnimationTrack : public AnimationTrack
453        {
454        public:
455                /** The target animation mode */
456                enum TargetMode
457                {
458                        /// Interpolate vertex positions in software
459                        TM_SOFTWARE, 
460                        /** Bind keyframe 1 to position, and keyframe 2 to a texture coordinate
461                                for interpolation in hardware */
462                        TM_HARDWARE
463                };
464                /// Constructor
465                VertexAnimationTrack(Animation* parent, unsigned short handle, VertexAnimationType animType);
466                /// Constructor, associates with target VertexData and temp buffer (for software)
467                VertexAnimationTrack(Animation* parent, unsigned short handle, VertexAnimationType animType, 
468                        VertexData* targetData, TargetMode target = TM_SOFTWARE);
469
470                /** Get the type of vertex animation we're performing. */
471                VertexAnimationType getAnimationType(void) const { return mAnimationType; }
472
473                /** Creates a new morph KeyFrame and adds it to this animation at the given time index.
474                @remarks
475                It is better to create KeyFrames in time order. Creating them out of order can result
476                in expensive reordering processing. Note that a KeyFrame at time index 0.0 is always created
477                for you, so you don't need to create this one, just access it using getKeyFrame(0);
478                @param timePos The time from which this KeyFrame will apply.
479                */
480                virtual VertexMorphKeyFrame* createVertexMorphKeyFrame(Real timePos);
481
482                /** Creates the single pose KeyFrame and adds it to this animation.
483                */
484                virtual VertexPoseKeyFrame* createVertexPoseKeyFrame(Real timePos);
485
486                /** This method in fact does nothing, since interpolation is not performed
487                        inside the keyframes for this type of track.
488                */
489        virtual void getInterpolatedKeyFrame(const TimeIndex& timeIndex, KeyFrame* kf) const {}
490
491                /// @copydoc AnimationTrack::apply
492                virtual void apply(const TimeIndex& timeIndex, Real weight = 1.0, Real scale = 1.0f);
493
494                /** As the 'apply' method but applies to specified VertexData instead of
495                        associated data. */
496                virtual void applyToVertexData(VertexData* data, 
497                        const TimeIndex& timeIndex, Real weight = 1.0, 
498                        const PoseList* poseList = 0);
499
500
501                /** Returns the morph KeyFrame at the specified index. */
502                VertexMorphKeyFrame* getVertexMorphKeyFrame(unsigned short index) const;
503
504                /** Returns the pose KeyFrame at the specified index. */
505                VertexPoseKeyFrame* getVertexPoseKeyFrame(unsigned short index) const;
506
507                /** Sets the associated VertexData which this track will update. */
508                void setAssociatedVertexData(VertexData* data) { mTargetVertexData = data; }
509                /** Gets the associated VertexData which this track will update. */
510                VertexData* getAssociatedVertexData(void) const { return mTargetVertexData; }
511
512                /// Set the target mode
513                void setTargetMode(TargetMode m) { mTargetMode = m; }
514                /// Get the target mode
515                TargetMode getTargetMode(void) const { return mTargetMode; }
516
517                /** Method to determine if this track has any KeyFrames which are
518                doing anything useful - can be used to determine if this track
519                can be optimised out.
520                */
521                virtual bool hasNonZeroKeyFrames(void) const;
522
523                /** Optimise the current track by removing any duplicate keyframes. */
524                virtual void optimise(void);
525
526                /** Clone this track (internal use only) */
527                VertexAnimationTrack* _clone(Animation* newParent) const;
528
529        protected:
530                /// Animation type
531                VertexAnimationType mAnimationType;
532                /// Target to animate
533                VertexData* mTargetVertexData;
534                /// Mode to apply
535                TargetMode mTargetMode;
536
537                /// @copydoc AnimationTrack::createKeyFrameImpl
538                KeyFrame* createKeyFrameImpl(Real time);
539
540                /// Utility method for applying pose animation
541                void applyPoseToVertexData(const Pose* pose, VertexData* data, Real influence);
542
543
544        };
545
546
547}
548
549#endif
Note: See TracBrowser for help on using the repository browser.