source: OGRE/trunk/ogrenew/OgreMain/include/OgreAnimationTrack.h @ 692

Revision 692, 20.5 KB checked in by mattausch, 19 years ago (diff)

adding ogre 1.2 and dependencies

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