Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogre_src_v1-9-0/OgreMain/include/OgreAnimationTrack.h @ 148

Last change on this file since 148 was 148, checked in by patricwi, 6 years ago

Added new dependencies for ogre1.9 and cegui0.8

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