/src/ogre/OgreMain/include/OgreAnimationTrack.h
Line | Count | Source |
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 | | private: |
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 | | */ |
71 | | TimeIndex(Real timePos) |
72 | | : mTimePos(timePos) |
73 | | , mKeyIndex(INVALID_KEY_INDEX) |
74 | 0 | { |
75 | 0 | } |
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 | | */ |
82 | | TimeIndex(Real timePos, uint keyIndex) |
83 | | : mTimePos(timePos) |
84 | | , mKeyIndex(keyIndex) |
85 | 0 | { |
86 | 0 | } |
87 | | |
88 | | bool hasKeyIndex(void) const |
89 | 0 | { |
90 | 0 | return mKeyIndex != INVALID_KEY_INDEX; |
91 | 0 | } |
92 | | |
93 | | Real getTimePos(void) const |
94 | 0 | { |
95 | 0 | return mTimePos; |
96 | 0 | } |
97 | | |
98 | | uint getKeyIndex(void) const |
99 | 0 | { |
100 | 0 | return mKeyIndex; |
101 | 0 | } |
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 | | |
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 | | |
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 | | |
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: |
133 | 0 | 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. */ |
147 | 0 | unsigned short getHandle(void) const { return mHandle; } |
148 | | |
149 | | /** Returns the number of keyframes in this animation. */ |
150 | 0 | size_t getNumKeyFrames(void) const { return mKeyFrames.size(); } |
151 | | |
152 | | /** Returns the KeyFrame at the specified index. */ |
153 | 0 | KeyFrame* getKeyFrame(size_t index) const { return mKeyFrames.at(index); } |
154 | | |
155 | | /** Gets the 2 KeyFrame objects which are active at the time given, and the blend value between them. |
156 | | |
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 | | float 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 | | |
181 | | It is better to create KeyFrames in time order. |
182 | | @param timePos The time from which this KeyFrame will apply. |
183 | | */ |
184 | | virtual KeyFrame* createKeyFrame(Real timePos); |
185 | | |
186 | | /** Removes a KeyFrame by it's index. */ |
187 | | virtual void removeKeyFrame(unsigned short index); |
188 | | |
189 | | /** Removes all the KeyFrames from this track. */ |
190 | | void removeAllKeyFrames(void); |
191 | | |
192 | | |
193 | | /** Gets a KeyFrame object which contains the interpolated transforms at the time index specified. |
194 | | |
195 | | The KeyFrame objects held by this class are transformation snapshots at |
196 | | discrete points in time. Normally however, you want to interpolate between these |
197 | | keyframes to produce smooth movement, and this method allows you to do this easily. |
198 | | In animation terminology this is called 'tweening'. |
199 | | @param timeIndex The time (in relation to the whole animation sequence) |
200 | | @param kf Keyframe object to store results |
201 | | */ |
202 | | virtual void getInterpolatedKeyFrame(const TimeIndex& timeIndex, KeyFrame* kf) const = 0; |
203 | | |
204 | | /** Applies an animation track to the designated target. |
205 | | @param timeIndex The time position in the animation to apply. |
206 | | @param weight The influence to give to this track, 1.0 for full influence, less to blend with |
207 | | other animations. |
208 | | @param scale The scale to apply to translations and scalings, useful for |
209 | | adapting an animation to a different size target. |
210 | | */ |
211 | | virtual void apply(const TimeIndex& timeIndex, Real weight = 1.0, Real scale = 1.0f) = 0; |
212 | | |
213 | | /** Internal method used to tell the track that keyframe data has been |
214 | | changed, which may cause it to rebuild some internal data. */ |
215 | 0 | virtual void _keyFrameDataChanged(void) const {} |
216 | | |
217 | | /** Method to determine if this track has any KeyFrames which are |
218 | | doing anything useful - can be used to determine if this track |
219 | | can be optimised out. |
220 | | */ |
221 | 0 | virtual bool hasNonZeroKeyFrames(void) const { return true; } |
222 | | |
223 | | /** Optimise the current track by removing any duplicate keyframes. */ |
224 | 0 | virtual void optimise(void) {} |
225 | | |
226 | | /** Internal method to collect keyframe times, in unique, ordered format. */ |
227 | | virtual void _collectKeyFrameTimes(std::vector<Real>& keyFrameTimes); |
228 | | |
229 | | /** Internal method to build keyframe time index map to translate global lower |
230 | | bound index to local lower bound index. */ |
231 | | virtual void _buildKeyFrameIndexMap(const std::vector<Real>& keyFrameTimes); |
232 | | |
233 | | /** Internal method to re-base the keyframes relative to a given keyframe. */ |
234 | | virtual void _applyBaseKeyFrame(const KeyFrame* base); |
235 | | |
236 | | /** Set a listener for this track. */ |
237 | 0 | virtual void setListener(Listener* l) { mListener = l; } |
238 | | |
239 | | /** Returns the parent Animation object for this track. */ |
240 | 0 | Animation *getParent() const { return mParent; } |
241 | | private: |
242 | | /// Map used to translate global keyframe time lower bound index to local lower bound index |
243 | | typedef std::vector<ushort> KeyFrameIndexMap; |
244 | | KeyFrameIndexMap mKeyFrameIndexMap; |
245 | | |
246 | | /// Create a keyframe implementation - must be overridden |
247 | | virtual KeyFrame* createKeyFrameImpl(Real time) = 0; |
248 | | protected: |
249 | | typedef std::vector<KeyFrame*> KeyFrameList; |
250 | | KeyFrameList mKeyFrames; |
251 | | Animation* mParent; |
252 | | Listener* mListener; |
253 | | unsigned short mHandle; |
254 | | |
255 | | /// Internal method for clone implementation |
256 | | virtual void populateClone(AnimationTrack* clone) const; |
257 | | }; |
258 | | |
259 | | /** Specialised AnimationTrack for dealing with generic animable values. |
260 | | */ |
261 | | class _OgreExport NumericAnimationTrack : public AnimationTrack |
262 | | { |
263 | | public: |
264 | | /// Constructor, associates with an AnimableValue |
265 | | NumericAnimationTrack(Animation* parent, unsigned short handle, |
266 | | const AnimableValuePtr& target); |
267 | | |
268 | | /// @copydoc AnimationTrack::createKeyFrame |
269 | | virtual NumericKeyFrame* createNumericKeyFrame(Real timePos); |
270 | | |
271 | | /// @copydoc AnimationTrack::getInterpolatedKeyFrame |
272 | | void getInterpolatedKeyFrame(const TimeIndex& timeIndex, KeyFrame* kf) const override; |
273 | | |
274 | | /// @copydoc AnimationTrack::apply |
275 | | void apply(const TimeIndex& timeIndex, Real weight = 1.0, Real scale = 1.0f) override; |
276 | | |
277 | | /** Applies an animation track to a given animable value. |
278 | | @param anim The AnimableValue to which to apply the animation |
279 | | @param timeIndex The time position in the animation to apply. |
280 | | @param weight The influence to give to this track, 1.0 for full influence, less to blend with |
281 | | other animations. |
282 | | @param scale The scale to apply to translations and scalings, useful for |
283 | | adapting an animation to a different size target. |
284 | | */ |
285 | | void applyToAnimable(const AnimableValuePtr& anim, const TimeIndex& timeIndex, |
286 | | Real weight = 1.0, Real scale = 1.0f); |
287 | | |
288 | | /** Returns a pointer to the associated animable object (if any). */ |
289 | 0 | const AnimableValuePtr& getAssociatedAnimable(void) const { return mTargetAnim; } |
290 | | |
291 | | /** Sets the associated animable object which will be automatically |
292 | | affected by calls to 'apply'. */ |
293 | 0 | void setAssociatedAnimable(const AnimableValuePtr& val) { mTargetAnim = val; } |
294 | | |
295 | | /** Returns the KeyFrame at the specified index. */ |
296 | | NumericKeyFrame* getNumericKeyFrame(unsigned short index) const; |
297 | | |
298 | | /** Clone this track (internal use only) */ |
299 | | NumericAnimationTrack* _clone(Animation* newParent) const; |
300 | | |
301 | | |
302 | | private: |
303 | | /// Target to animate |
304 | | AnimableValuePtr mTargetAnim; |
305 | | |
306 | | /// @copydoc AnimationTrack::createKeyFrameImpl |
307 | | KeyFrame* createKeyFrameImpl(Real time) override; |
308 | | |
309 | | |
310 | | }; |
311 | | |
312 | | /** Specialised AnimationTrack for dealing with node transforms. |
313 | | */ |
314 | | class _OgreExport NodeAnimationTrack : public AnimationTrack |
315 | | { |
316 | | public: |
317 | | /// Constructor |
318 | | NodeAnimationTrack(Animation* parent, unsigned short handle); |
319 | | /// Constructor, associates with a Node |
320 | | NodeAnimationTrack(Animation* parent, unsigned short handle, |
321 | | Node* targetNode); |
322 | | /// Destructor |
323 | | virtual ~NodeAnimationTrack(); |
324 | | /// @copydoc AnimationTrack::createKeyFrame |
325 | | virtual TransformKeyFrame* createNodeKeyFrame(Real timePos); |
326 | | /** Returns a pointer to the associated Node object (if any). */ |
327 | | virtual Node* getAssociatedNode(void) const; |
328 | | |
329 | | /** Sets the associated Node object which will be automatically affected by calls to 'apply'. */ |
330 | | virtual void setAssociatedNode(Node* node); |
331 | | |
332 | | /** As the 'apply' method but applies to a specified Node instead of associated node. */ |
333 | | virtual void applyToNode(Node* node, const TimeIndex& timeIndex, Real weight = 1.0, |
334 | | Real scale = 1.0f); |
335 | | |
336 | | /** Sets the method of rotation calculation */ |
337 | | virtual void setUseShortestRotationPath(bool useShortestPath); |
338 | | |
339 | | /** Gets the method of rotation calculation */ |
340 | | virtual bool getUseShortestRotationPath() const; |
341 | | |
342 | | /// @copydoc AnimationTrack::getInterpolatedKeyFrame |
343 | | void getInterpolatedKeyFrame(const TimeIndex& timeIndex, KeyFrame* kf) const override; |
344 | | |
345 | | /// @copydoc AnimationTrack::apply |
346 | | void apply(const TimeIndex& timeIndex, Real weight = 1.0, Real scale = 1.0f) override; |
347 | | |
348 | | /// @copydoc AnimationTrack::_keyFrameDataChanged |
349 | | void _keyFrameDataChanged(void) const override; |
350 | | |
351 | | /** Returns the KeyFrame at the specified index. */ |
352 | | virtual TransformKeyFrame* getNodeKeyFrame(unsigned short index) const; |
353 | | |
354 | | |
355 | | /** Method to determine if this track has any KeyFrames which are |
356 | | doing anything useful - can be used to determine if this track |
357 | | can be optimised out. |
358 | | */ |
359 | | bool hasNonZeroKeyFrames(void) const override; |
360 | | |
361 | | /** Optimise the current track by removing any duplicate keyframes. */ |
362 | | void optimise(void) override; |
363 | | |
364 | | /** Clone this track (internal use only) */ |
365 | | NodeAnimationTrack* _clone(Animation* newParent) const; |
366 | | |
367 | | void _applyBaseKeyFrame(const KeyFrame* base) override; |
368 | | |
369 | | private: |
370 | | /// Specialised keyframe creation |
371 | | KeyFrame* createKeyFrameImpl(Real time) override; |
372 | | // Flag indicating we need to rebuild the splines next time |
373 | | virtual void buildInterpolationSplines(void) const; |
374 | | |
375 | | // Struct for store splines, allocate on demand for better memory footprint |
376 | | struct Splines |
377 | | { |
378 | | SimpleSpline positionSpline; |
379 | | SimpleSpline scaleSpline; |
380 | | RotationalSpline rotationSpline; |
381 | | }; |
382 | | |
383 | | mutable bool mSplineBuildNeeded; |
384 | | /// Defines if rotation is done using shortest path |
385 | | mutable bool mUseShortestRotationPath; |
386 | | Node* mTargetNode; |
387 | | // Prebuilt splines, must be mutable since lazy-update in const method |
388 | | mutable Splines* mSplines; |
389 | | }; |
390 | | |
391 | | /** Type of vertex animation. |
392 | | Vertex animation comes in 2 types, morph and pose. The reason |
393 | | for the 2 types is that we have 2 different potential goals - to encapsulate |
394 | | a complete, flowing morph animation with multiple keyframes (a typical animation, |
395 | | but implemented by having snapshots of the vertex data at each keyframe), |
396 | | or to represent a single pose change, for example a facial expression. |
397 | | Whilst both could in fact be implemented using the same system, we choose |
398 | | to separate them since the requirements and limitations of each are quite |
399 | | different. |
400 | | @par |
401 | | Morph animation is a simple approach where we have a whole series of |
402 | | snapshots of vertex data which must be interpolated, e.g. a running |
403 | | animation implemented as morph targets. Because this is based on simple |
404 | | snapshots, it's quite fast to use when animating an entire mesh because |
405 | | it's a simple linear change between keyframes. However, this simplistic |
406 | | approach does not support blending between multiple morph animations. |
407 | | If you need animation blending, you are advised to use skeletal animation |
408 | | for full-mesh animation, and pose animation for animation of subsets of |
409 | | meshes or where skeletal animation doesn't fit - for example facial animation. |
410 | | For animating in a vertex shader, morph animation is quite simple and |
411 | | just requires the 2 vertex buffers (one the original position buffer) |
412 | | of absolute position data, and an interpolation factor. Each track in |
413 | | a morph animation references a unique set of vertex data. |
414 | | @par |
415 | | Pose animation is more complex. Like morph animation each track references |
416 | | a single unique set of vertex data, but unlike morph animation, each |
417 | | keyframe references 1 or more 'poses', each with an influence level. |
418 | | A pose is a series of offsets to the base vertex data, and may be sparse - ie it |
419 | | may not reference every vertex. Because they're offsets, they can be |
420 | | blended - both within a track and between animations. This set of features |
421 | | is very well suited to facial animation. |
422 | | @par |
423 | | For example, let's say you modelled a face (one set of vertex data), and |
424 | | defined a set of poses which represented the various phonetic positions |
425 | | of the face. You could then define an animation called 'SayHello', containing |
426 | | a single track which referenced the face vertex data, and which included |
427 | | a series of keyframes, each of which referenced one or more of the facial |
428 | | positions at different influence levels - the combination of which over |
429 | | time made the face form the shapes required to say the word 'hello'. Since |
430 | | the poses are only stored once, but can be referenced may times in |
431 | | many animations, this is a very powerful way to build up a speech system. |
432 | | @par |
433 | | The downside of pose animation is that it can be more difficult to set up. |
434 | | Also, since it uses more buffers (one for the base data, and one for each |
435 | | active pose), if you're animating in hardware using vertex shaders you need |
436 | | to keep an eye on how many poses you're blending at once. You define a |
437 | | maximum supported number in your vertex program definition, see the |
438 | | includes_pose_animation material script entry. |
439 | | @par |
440 | | So, by partitioning the vertex animation approaches into 2, we keep the |
441 | | simple morph technique easy to use, whilst still allowing all |
442 | | the powerful techniques to be used. Note that morph animation cannot |
443 | | be blended with other types of vertex animation (pose animation or other |
444 | | morph animation); pose animation can be blended with other pose animation |
445 | | though, and both types can be combined with skeletal animation. Also note |
446 | | that all morph animation can be expressed as pose animation, but not vice |
447 | | versa. |
448 | | */ |
449 | | enum VertexAnimationType : uint8 |
450 | | { |
451 | | /// No animation |
452 | | VAT_NONE = 0, |
453 | | /// Morph animation is made up of many interpolated snapshot keyframes |
454 | | VAT_MORPH = 1, |
455 | | /// Pose animation is made up of a single delta pose keyframe |
456 | | VAT_POSE = 2 |
457 | | }; |
458 | | |
459 | | /** Specialised AnimationTrack for dealing with changing vertex position information. |
460 | | @see VertexAnimationType |
461 | | */ |
462 | | class _OgreExport VertexAnimationTrack : public AnimationTrack |
463 | | { |
464 | | public: |
465 | | /** The target animation mode */ |
466 | | enum TargetMode : uint8 |
467 | | { |
468 | | /// Interpolate vertex positions in software |
469 | | TM_SOFTWARE, |
470 | | /** Bind keyframe 1 to position, and keyframe 2 to a texture coordinate |
471 | | for interpolation in hardware */ |
472 | | TM_HARDWARE |
473 | | }; |
474 | | /// Constructor |
475 | | VertexAnimationTrack(Animation* parent, unsigned short handle, VertexAnimationType animType); |
476 | | /// Constructor, associates with target VertexData and temp buffer (for software) |
477 | | VertexAnimationTrack(Animation* parent, unsigned short handle, VertexAnimationType animType, |
478 | | VertexData* targetData, TargetMode target = TM_SOFTWARE); |
479 | | |
480 | | /** Get the type of vertex animation we're performing. */ |
481 | 0 | VertexAnimationType getAnimationType(void) const { return mAnimationType; } |
482 | | |
483 | | /** Whether the vertex animation (if present) includes normals */ |
484 | | bool getVertexAnimationIncludesNormals() const; |
485 | | |
486 | | /// @copydoc AnimationTrack::createKeyFrame |
487 | | virtual VertexMorphKeyFrame* createVertexMorphKeyFrame(Real timePos); |
488 | | |
489 | | /** Creates the single pose KeyFrame and adds it to this animation. |
490 | | */ |
491 | | virtual VertexPoseKeyFrame* createVertexPoseKeyFrame(Real timePos); |
492 | | |
493 | | /** @copydoc AnimationTrack::getInterpolatedKeyFrame |
494 | | */ |
495 | | void getInterpolatedKeyFrame(const TimeIndex& timeIndex, KeyFrame* kf) const override; |
496 | | |
497 | | /// @copydoc AnimationTrack::apply |
498 | | void apply(const TimeIndex& timeIndex, Real weight = 1.0, Real scale = 1.0f) override; |
499 | | |
500 | | /** As the 'apply' method but applies to specified VertexData instead of |
501 | | associated data. */ |
502 | | virtual void applyToVertexData(VertexData* data, |
503 | | const TimeIndex& timeIndex, float weight = 1.0, |
504 | | const PoseList* poseList = 0); |
505 | | |
506 | | |
507 | | /** Returns the morph KeyFrame at the specified index. */ |
508 | | VertexMorphKeyFrame* getVertexMorphKeyFrame(unsigned short index) const; |
509 | | |
510 | | /** Returns the pose KeyFrame at the specified index. */ |
511 | | VertexPoseKeyFrame* getVertexPoseKeyFrame(unsigned short index) const; |
512 | | |
513 | | /** Sets the associated VertexData which this track will update. */ |
514 | 0 | void setAssociatedVertexData(VertexData* data) { mTargetVertexData = data; } |
515 | | /** Gets the associated VertexData which this track will update. */ |
516 | 0 | VertexData* getAssociatedVertexData(void) const { return mTargetVertexData; } |
517 | | |
518 | | /// Set the target mode |
519 | 0 | void setTargetMode(TargetMode m) { mTargetMode = m; } |
520 | | /// Get the target mode |
521 | 0 | TargetMode getTargetMode(void) const { return mTargetMode; } |
522 | | |
523 | | /** Method to determine if this track has any KeyFrames which are |
524 | | doing anything useful - can be used to determine if this track |
525 | | can be optimised out. |
526 | | */ |
527 | | bool hasNonZeroKeyFrames(void) const override; |
528 | | |
529 | | /** Optimise the current track by removing any duplicate keyframes. */ |
530 | | void optimise(void) override; |
531 | | |
532 | | /** Clone this track (internal use only) */ |
533 | | VertexAnimationTrack* _clone(Animation* newParent) const; |
534 | | |
535 | | void _applyBaseKeyFrame(const KeyFrame* base) override; |
536 | | |
537 | | private: |
538 | | /// Animation type |
539 | | VertexAnimationType mAnimationType; |
540 | | /// Mode to apply |
541 | | TargetMode mTargetMode; |
542 | | /// Target to animate |
543 | | VertexData* mTargetVertexData; |
544 | | |
545 | | /// @copydoc AnimationTrack::createKeyFrameImpl |
546 | | KeyFrame* createKeyFrameImpl(Real time) override; |
547 | | |
548 | | /// Utility method for applying pose animation |
549 | | void applyPoseToVertexData(const Pose* pose, VertexData* data, float influence); |
550 | | |
551 | | |
552 | | }; |
553 | | /** @} */ |
554 | | /** @} */ |
555 | | } |
556 | | |
557 | | #include "OgreHeaderSuffix.h" |
558 | | |
559 | | #endif |