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