Coverage Report

Created: 2025-07-11 06:36

/src/ogre/OgreMain/include/OgreAnimation.h
Line
Count
Source (jump to first uncovered line)
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 __Animation_H__
30
#define __Animation_H__
31
32
#include "OgrePrerequisites.h"
33
#include "OgreIteratorWrapper.h"
34
#include "OgreAnimationTrack.h"
35
#include "OgreAnimationState.h"
36
#include "OgreHeaderPrefix.h"
37
38
namespace Ogre {
39
    /** \addtogroup Core
40
    *  @{
41
    */
42
43
    /** \addtogroup Animation
44
    *  @{
45
    */
46
47
    class Animation;
48
    
49
    /** An animation container interface, which allows generic access to sibling animations.
50
51
        Because Animation instances can be held by different kinds of classes, and
52
        there are sometimes instances when you need to reference other Animation 
53
        instances within the same container, this class allows generic access to
54
        named animations within that container, whatever it may be.
55
    */
56
    class _OgreExport AnimationContainer
57
    {
58
    public:
59
        typedef std::map<String, Animation*> AnimationList;
60
61
0
        virtual ~AnimationContainer() {}
62
63
        /** Gets the number of animations in this container. */
64
        virtual unsigned short getNumAnimations(void) const = 0;
65
        
66
        /** Retrieve an animation by index.  */
67
        virtual Animation* getAnimation(unsigned short index) const = 0;
68
        
69
        /** Looks up an Animation object previously created with createAnimation.
70
        @note Throws an exception if the named instance does not exist
71
        @param name The name of the animation.
72
        */
73
        virtual Animation* getAnimation(const String& name) const = 0;
74
        
75
        /** Create a new animation with a given length owned by this container
76
        @param name The name of the animation, must be unique within this container.
77
        @param length The length of the animation in seconds
78
        */
79
        virtual Animation* createAnimation(const String& name, Real length) = 0;
80
        
81
        /** Returns whether this object contains the named animation. */
82
        virtual bool hasAnimation(const String& name) const = 0;
83
        
84
        /** Remove & destroy an Animation from this container. */
85
        virtual void removeAnimation(const String& name) = 0;
86
        
87
    };
88
    /** An animation sequence. 
89
90
        This class defines the interface for a sequence of animation, whether that
91
        be animation of a mesh, a path along a spline, or possibly more than one
92
        type of animation in one. An animation is made up of many 'tracks', which are
93
        the more specific types of animation.
94
    @par
95
        You should not create these animations directly. They will be created via a parent
96
        object which owns the animation, e.g. Skeleton.
97
    */
98
    class _OgreExport Animation : public AnimationAlloc
99
    {
100
101
    public:
102
        /** The types of animation interpolation available. */
103
        enum InterpolationMode : uint8
104
        {
105
            /** Values are interpolated along straight lines. */
106
            IM_LINEAR,
107
            /** Values are interpolated along a spline, resulting in smoother changes in direction. */
108
            IM_SPLINE
109
        };
110
111
        /** The types of rotational interpolation available. */
112
        enum RotationInterpolationMode : uint8
113
        {
114
            /** Values are interpolated linearly. This is faster but does not 
115
                necessarily give a completely accurate result.
116
            */
117
            RIM_LINEAR,
118
            /** Values are interpolated spherically. This is more accurate but
119
                has a higher cost.
120
            */
121
            RIM_SPHERICAL
122
        };
123
        /** You should not use this constructor directly, use the parent object such as Skeleton instead.
124
        @param name The name of the animation, should be unique within it's parent (e.g. Skeleton)
125
        @param length The length of the animation in seconds.
126
        */
127
        Animation(const String& name, Real length);
128
        virtual ~Animation();
129
130
        /** Gets the name of this animation. */
131
        const String& getName(void) const;
132
133
        /** Gets the total length of the animation. */
134
        Real getLength(void) const;
135
136
        /** Sets the length of the animation. 
137
        @note Changing the length of an animation may invalidate existing AnimationState
138
            instances which will need to be recreated. 
139
        */
140
        void setLength(Real len);
141
142
        /** Creates a NodeAnimationTrack for animating a Node.
143
        @param handle Handle to give the track, used for accessing the track later. 
144
            Must be unique within this Animation.
145
        */
146
        NodeAnimationTrack* createNodeTrack(unsigned short handle);
147
148
        /** Creates a VertexAnimationTrack for animating vertex position data.
149
        @param handle Handle to give the track, used for accessing the track later. 
150
            Must be unique within this Animation, and is used to identify the target. For example
151
            when applied to a Mesh, the handle must reference the index of the geometry being 
152
            modified; 0 for the shared geometry, and 1+ for SubMesh geometry with the same index-1.
153
        @param animType Either morph or pose animation, 
154
        */
155
        VertexAnimationTrack* createVertexTrack(unsigned short handle, VertexAnimationType animType);
156
157
        /** Creates a new AnimationTrack automatically associated with a Node. 
158
159
            This method creates a standard AnimationTrack, but also associates it with a
160
            target Node which will receive all keyframe effects.
161
        @param handle Numeric handle to give the track, used for accessing the track later. 
162
            Must be unique within this Animation.
163
        @param node A pointer to the Node object which will be affected by this track
164
        */
165
        NodeAnimationTrack* createNodeTrack(unsigned short handle, Node* node);
166
167
        /** Creates a NumericAnimationTrack and associates it with an animable. 
168
        @param handle Handle to give the track, used for accessing the track later. 
169
        @param anim Animable object link
170
            Must be unique within this Animation.
171
        */
172
        NumericAnimationTrack* createNumericTrack(unsigned short handle, 
173
            const AnimableValuePtr& anim);
174
175
        /** Creates a VertexAnimationTrack and associates it with VertexData. 
176
        @param handle Handle to give the track, used for accessing the track later. 
177
        @param data VertexData object link
178
        @param animType The animation type 
179
            Must be unique within this Animation.
180
        */
181
        VertexAnimationTrack* createVertexTrack(unsigned short handle, 
182
            VertexData* data, VertexAnimationType animType);
183
184
        /** Gets the number of NodeAnimationTrack objects contained in this animation. */
185
        unsigned short getNumNodeTracks(void) const;
186
187
        /** Gets a node track by it's handle. */
188
        NodeAnimationTrack* getNodeTrack(unsigned short handle) const;
189
190
        /** Does a track exist with the given handle? */
191
        bool hasNodeTrack(unsigned short handle) const;
192
193
        /** Gets the number of NumericAnimationTrack objects contained in this animation. */
194
        unsigned short getNumNumericTracks(void) const;
195
196
        /** Gets a numeric track by it's handle. */
197
        NumericAnimationTrack* getNumericTrack(unsigned short handle) const;
198
199
        /** Does a track exist with the given handle? */
200
        bool hasNumericTrack(unsigned short handle) const;
201
202
        /** Gets the number of VertexAnimationTrack objects contained in this animation. */
203
        unsigned short getNumVertexTracks(void) const;
204
205
        /** Gets a Vertex track by it's handle. */
206
        VertexAnimationTrack* getVertexTrack(unsigned short handle) const;
207
208
        /** Does a track exist with the given handle? */
209
        bool hasVertexTrack(unsigned short handle) const;
210
        
211
        /** Destroys the node track with the given handle. */
212
        void destroyNodeTrack(unsigned short handle);
213
214
        /** Destroys the numeric track with the given handle. */
215
        void destroyNumericTrack(unsigned short handle);
216
217
        /** Destroys the Vertex track with the given handle. */
218
        void destroyVertexTrack(unsigned short handle);
219
220
        /** Removes and destroys all tracks making up this animation. */
221
        void destroyAllTracks(void);
222
223
        /** Removes and destroys all tracks making up this animation. */
224
        void destroyAllNodeTracks(void);
225
        /** Removes and destroys all tracks making up this animation. */
226
        void destroyAllNumericTracks(void);
227
        /** Removes and destroys all tracks making up this animation. */
228
        void destroyAllVertexTracks(void);
229
230
        /** Applies an animation given a specific time point and weight.
231
232
            Where you have associated animation tracks with objects, you can easily apply
233
            an animation to those objects by calling this method.
234
        @param timePos The time position in the animation to apply.
235
        @param weight The influence to give to this track, 1.0 for full influence, less to blend with
236
          other animations.
237
        @param scale The scale to apply to translations and scalings, useful for 
238
            adapting an animation to a different size target.
239
        */
240
        void apply(Real timePos, Real weight = 1.0, Real scale = 1.0f);
241
242
        /** Applies all node tracks given a specific time point and weight to the specified node.
243
244
            It does not consider the actual node tracks are attached to.
245
            As such, it resembles the apply method for a given skeleton (see below).
246
        @param node
247
        @param timePos The time position in the animation to apply.
248
        @param weight The influence to give to this track, 1.0 for full influence, less to blend with
249
          other animations.
250
        @param scale The scale to apply to translations and scalings, useful for 
251
            adapting an animation to a different size target.
252
        */
253
        void applyToNode(Node* node, Real timePos, Real weight = 1.0, Real scale = 1.0f);
254
255
        /** Applies all node tracks given a specific time point and weight to a given skeleton.
256
257
            Where you have associated animation tracks with Node objects, you can easily apply
258
            an animation to those nodes by calling this method.
259
        @param skeleton
260
        @param timePos The time position in the animation to apply.
261
        @param weight The influence to give to this track, 1.0 for full influence, less to blend with
262
            other animations.
263
        @param scale The scale to apply to translations and scalings, useful for 
264
            adapting an animation to a different size target.
265
        */
266
        void apply(Skeleton* skeleton, Real timePos, Real weight = 1.0, Real scale = 1.0f);
267
268
        /** Applies all node tracks given a specific time point and weight to a given skeleton.
269
270
            Where you have associated animation tracks with Node objects, you can easily apply
271
            an animation to those nodes by calling this method.
272
        @param skeleton
273
        @param timePos The time position in the animation to apply.
274
        @param weight The influence to give to this track, 1.0 for full influence, less to blend with
275
            other animations.
276
        @param blendMask The influence array defining additional per bone weights. These will
277
            be modulated with the weight factor.
278
        @param scale The scale to apply to translations and scalings, useful for 
279
            adapting an animation to a different size target.
280
        */
281
        void apply(Skeleton* skeleton, Real timePos, float weight,
282
          const AnimationState::BoneBlendMask* blendMask, Real scale);
283
284
        /** Applies all vertex tracks given a specific time point and weight to a given entity.
285
        @param entity The Entity to which this animation should be applied
286
        @param timePos The time position in the animation to apply.
287
        @param weight The weight at which the animation should be applied 
288
            (only affects pose animation)
289
        @param software Whether to populate the software morph vertex data
290
        @param hardware Whether to populate the hardware morph vertex data
291
        */
292
        void apply(Entity* entity, Real timePos, Real weight, bool software, 
293
            bool hardware);
294
295
        /** Applies all numeric tracks given a specific time point and weight to the specified animable value.
296
297
            It does not applies to actual attached animable values but rather uses all tracks for a single animable value.
298
        @param anim
299
        @param timePos The time position in the animation to apply.
300
        @param weight The influence to give to this track, 1.0 for full influence, less to blend with
301
          other animations.
302
        @param scale The scale to apply to translations and scalings, useful for 
303
            adapting an animation to a different size target.
304
        */
305
        void applyToAnimable(const AnimableValuePtr& anim, Real timePos, Real weight = 1.0, Real scale = 1.0f);
306
307
        /** Applies all vertex tracks given a specific time point and weight to the specified vertex data.
308
309
            It does not apply to the actual attached vertex data but rather uses all tracks for a given vertex data.
310
        @param data
311
        @param timePos The time position in the animation to apply.
312
        @param weight The influence to give to this track, 1.0 for full influence, less to blend with
313
          other animations.
314
        */
315
        void applyToVertexData(VertexData* data, Real timePos, float weight = 1.0);
316
317
        /** Tells the animation how to interpolate between keyframes.
318
319
            By default, animations normally interpolate linearly between keyframes. This is
320
            fast, but when animations include quick changes in direction it can look a little
321
            unnatural because directions change instantly at keyframes. An alternative is to
322
            tell the animation to interpolate along a spline, which is more expensive in terms
323
            of calculation time, but looks smoother because major changes in direction are 
324
            distributed around the keyframes rather than just at the keyframe.
325
        @par
326
            You can also change the default animation behaviour by calling 
327
            Animation::setDefaultInterpolationMode.
328
        */
329
        void setInterpolationMode(InterpolationMode im);
330
331
        /** Gets the current interpolation mode of this animation. 
332
333
            See setInterpolationMode for more info.
334
        */
335
        InterpolationMode getInterpolationMode(void) const;
336
        /** Tells the animation how to interpolate rotations.
337
338
            By default, animations interpolate linearly between rotations. This
339
            is fast but not necessarily completely accurate. If you want more 
340
            accurate interpolation, use spherical interpolation, but be aware 
341
            that it will incur a higher cost.
342
        @par
343
            You can also change the default rotation behaviour by calling 
344
            Animation::setDefaultRotationInterpolationMode.
345
        */
346
        void setRotationInterpolationMode(RotationInterpolationMode im);
347
348
        /** Gets the current rotation interpolation mode of this animation. 
349
350
            See setRotationInterpolationMode for more info.
351
        */
352
        RotationInterpolationMode getRotationInterpolationMode(void) const;
353
354
        // Methods for setting the defaults
355
        /** Sets the default animation interpolation mode. 
356
357
            Every animation created after this option is set will have the new interpolation
358
            mode specified. You can also change the mode per animation by calling the 
359
            setInterpolationMode method on the instance in question.
360
        */
361
        static void setDefaultInterpolationMode(InterpolationMode im);
362
363
        /** Gets the default interpolation mode for all animations. */
364
        static InterpolationMode getDefaultInterpolationMode(void);
365
366
        /** Sets the default rotation interpolation mode. 
367
368
            Every animation created after this option is set will have the new interpolation
369
            mode specified. You can also change the mode per animation by calling the 
370
            setInterpolationMode method on the instance in question.
371
        */
372
        static void setDefaultRotationInterpolationMode(RotationInterpolationMode im);
373
374
        /** Gets the default rotation interpolation mode for all animations. */
375
        static RotationInterpolationMode getDefaultRotationInterpolationMode(void);
376
377
        typedef std::map<unsigned short, NodeAnimationTrack*> NodeTrackList;
378
        typedef ConstMapIterator<NodeTrackList> NodeTrackIterator;
379
380
        typedef std::map<unsigned short, NumericAnimationTrack*> NumericTrackList;
381
        typedef ConstMapIterator<NumericTrackList> NumericTrackIterator;
382
383
        typedef std::map<unsigned short, VertexAnimationTrack*> VertexTrackList;
384
        typedef ConstMapIterator<VertexTrackList> VertexTrackIterator;
385
386
        /// Fast access to NON-UPDATEABLE node track list
387
        const NodeTrackList& _getNodeTrackList(void) const;
388
389
        /// @deprecated use _getNodeTrackList
390
        OGRE_DEPRECATED NodeTrackIterator getNodeTrackIterator(void) const
391
0
        { return NodeTrackIterator(mNodeTrackList.begin(), mNodeTrackList.end()); }
392
        
393
        /// Fast access to NON-UPDATEABLE numeric track list
394
        const NumericTrackList& _getNumericTrackList(void) const;
395
396
        /// @deprecated use _getNumericTrackList
397
        OGRE_DEPRECATED NumericTrackIterator getNumericTrackIterator(void) const
398
0
        { return NumericTrackIterator(mNumericTrackList.begin(), mNumericTrackList.end()); }
399
400
        /// Fast access to NON-UPDATEABLE Vertex track list
401
        const VertexTrackList& _getVertexTrackList(void) const;
402
403
        /// @deprecated use _getVertexTrackList
404
        OGRE_DEPRECATED VertexTrackIterator getVertexTrackIterator(void) const
405
0
        { return VertexTrackIterator(mVertexTrackList.begin(), mVertexTrackList.end()); }
406
407
        /** Optimise an animation by removing unnecessary tracks and keyframes.
408
409
            When you export an animation, it is possible that certain tracks
410
            have been keyframed but actually don't include anything useful - the
411
            keyframes include no transformation. These tracks can be completely
412
            eliminated from the animation and thus speed up the animation. 
413
            In addition, if several keyframes in a row have the same value, 
414
            then they are just adding overhead and can be removed.
415
        @note
416
            Since track-less and identity track has difference behavior for
417
            accumulate animation blending if corresponding track presenting at
418
            other animation that is non-identity, and in normally this method
419
            didn't known about the situation of other animation, it can't deciding
420
            whether or not discards identity tracks. So there have a parameter
421
            allow you choose what you want, in case you aren't sure how to do that,
422
            you should use Skeleton::optimiseAllAnimations instead.
423
        @param
424
            discardIdentityNodeTracks If true, discard identity node tracks.
425
        */
426
        void optimise(bool discardIdentityNodeTracks = true);
427
428
        /// A list of track handles
429
        typedef std::set<ushort> TrackHandleList;
430
431
        /** Internal method for collecting identity node tracks.
432
433
            This method remove non-identity node tracks form the track handle list.
434
        @param
435
            tracks A list of track handle of non-identity node tracks, where this
436
            method will remove non-identity node track handles.
437
        */
438
        void _collectIdentityNodeTracks(TrackHandleList& tracks) const;
439
440
        /** Internal method for destroy given node tracks.
441
        */
442
        void _destroyNodeTracks(const TrackHandleList& tracks);
443
444
        /** Clone this animation.
445
        @note
446
            The pointer returned from this method is the only one recorded, 
447
            thus it is up to the caller to arrange for the deletion of this
448
            object.
449
        */
450
        Animation* clone(const String& newName) const OGRE_NODISCARD;
451
        
452
        /** Internal method used to tell the animation that keyframe list has been
453
            changed, which may cause it to rebuild some internal data */
454
0
        void _keyFrameListChanged(void) { mKeyFrameTimesDirty = true; }
455
456
        /** Internal method used to convert time position to time index object.
457
        @note
458
            The time index returns by this function are associated with state of
459
            the animation object, if the animation object altered (e.g. create/remove
460
            keyframe or track), all related time index will invalidated.
461
        @param timePos The time position.
462
        @return The time index object which contains wrapped time position (in
463
            relation to the whole animation sequence) and lower bound index of
464
            global keyframe time list.
465
        */
466
        TimeIndex _getTimeIndex(Real timePos) const;
467
        
468
        /** Sets a base keyframe which for the skeletal / pose keyframes 
469
            in this animation. 
470
471
            Skeletal and pose animation keyframes are expressed as deltas from a 
472
            given base state. By default, that is the binding setup of the skeleton, 
473
            or the object space mesh positions for pose animation. However, sometimes
474
            it is useful for animators to create animations with a different starting
475
            pose, because that's more convenient, and the animation is designed to
476
            simply be added to the existing animation state and not globally averaged
477
            with other animations (this is always the case with pose animations, but
478
            is activated for skeletal animations via ANIMBLEND_CUMULATIVE).
479
        @par
480
            In order for this to work, the keyframes need to be 're-based' against
481
            this new starting state, for example by treating the first keyframe as
482
            the reference point (and therefore representing no change). This can 
483
            be achieved by applying the inverse of this reference keyframe against
484
            all other keyframes. Since this fundamentally changes the animation, 
485
            this method just marks the animation as requiring this rebase, which 
486
            is performed at the next @ref Animation::apply call. This is to allow the
487
            Animation to be re-saved with this flag set, but without having altered
488
            the keyframes yet, so no data is lost unintentionally. If you wish to
489
            save the animation after the adjustment has taken place, you can
490
            use @ref _applyBaseKeyFrame
491
        @param useBaseKeyFrame Whether a base keyframe should be used
492
        @param keyframeTime The time corresponding to the base keyframe, if any
493
        @param baseAnimName Optionally a different base animation (must contain the same tracks)
494
        */
495
        void setUseBaseKeyFrame(bool useBaseKeyFrame, Real keyframeTime = 0.0f, const String& baseAnimName = BLANKSTRING);
496
        /** Whether a base keyframe is being used for this Animation. */
497
        bool getUseBaseKeyFrame() const;
498
        /** If a base keyframe is being used, the time of that keyframe. */
499
        Real getBaseKeyFrameTime() const;
500
        /** If a base keyframe is being used, the Animation that provides that keyframe. */
501
        const String& getBaseKeyFrameAnimationName() const;
502
        
503
        /// Internal method to adjust keyframes relative to a base keyframe (see @ref setUseBaseKeyFrame)
504
        void _applyBaseKeyFrame();
505
        
506
        void _notifyContainer(AnimationContainer* c);
507
        /** Retrieve the container of this animation. */
508
        AnimationContainer* getContainer();
509
        
510
    private:
511
        /// Node tracks, indexed by handle
512
        NodeTrackList mNodeTrackList;
513
        /// Numeric tracks, indexed by handle
514
        NumericTrackList mNumericTrackList;
515
        /// Vertex tracks, indexed by handle
516
        VertexTrackList mVertexTrackList;
517
        String mName;
518
519
        Real mLength;
520
        
521
        InterpolationMode mInterpolationMode;
522
        RotationInterpolationMode mRotationInterpolationMode;
523
524
        /// Dirty flag indicate that keyframe time list need to rebuild
525
        mutable bool mKeyFrameTimesDirty;
526
        bool mUseBaseKeyFrame;
527
528
        static InterpolationMode msDefaultInterpolationMode;
529
        static RotationInterpolationMode msDefaultRotationInterpolationMode;
530
531
        /// Global keyframe time list used to search global keyframe index.
532
        typedef std::vector<Real> KeyFrameTimeList;
533
        mutable KeyFrameTimeList mKeyFrameTimes;
534
        Real mBaseKeyFrameTime;
535
        String mBaseKeyFrameAnimationName;
536
        AnimationContainer* mContainer;
537
538
        void optimiseNodeTracks(bool discardIdentityTracks);
539
        void optimiseVertexTracks(void);
540
541
        /// Internal method to build global keyframe time list
542
        void buildKeyFrameTimeList(void) const;
543
    };
544
545
    /** @} */
546
    /** @} */
547
} // namespace Ogre
548
549
#include "OgreHeaderSuffix.h"
550
551
#endif // __Animation_H__
552