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