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 #include "OgreStableHeaders.h" 29 #include "OgreAnimation.h" 30 #include "OgreKeyFrame.h" 31 #include "OgreEntity.h" 32 #include "OgreSubEntity.h" 33 34 namespace Ogre { 35 36 Animation::InterpolationMode Animation::msDefaultInterpolationMode = Animation::IM_LINEAR; 37 Animation::RotationInterpolationMode 38 Animation::msDefaultRotationInterpolationMode = Animation::RIM_LINEAR; 39 //--------------------------------------------------------------------- Animation(const String & name,Real length)40 Animation::Animation(const String& name, Real length) 41 : mName(name) 42 , mLength(length) 43 , mInterpolationMode(msDefaultInterpolationMode) 44 , mRotationInterpolationMode(msDefaultRotationInterpolationMode) 45 , mKeyFrameTimesDirty(false) 46 , mUseBaseKeyFrame(false) 47 , mBaseKeyFrameTime(0.0f) 48 , mBaseKeyFrameAnimationName(BLANKSTRING) 49 , mContainer(0) 50 { 51 } 52 //--------------------------------------------------------------------- ~Animation()53 Animation::~Animation() 54 { 55 destroyAllTracks(); 56 } 57 //--------------------------------------------------------------------- getLength(void) const58 Real Animation::getLength(void) const 59 { 60 return mLength; 61 } 62 //--------------------------------------------------------------------- setLength(Real len)63 void Animation::setLength(Real len) 64 { 65 mLength = len; 66 } 67 //--------------------------------------------------------------------- createNodeTrack(unsigned short handle)68 NodeAnimationTrack* Animation::createNodeTrack(unsigned short handle) 69 { 70 if (hasNodeTrack(handle)) 71 { 72 OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, 73 "Node track with the specified handle " + 74 StringConverter::toString(handle) + " already exists", 75 "Animation::createNodeTrack"); 76 } 77 78 NodeAnimationTrack* ret = OGRE_NEW NodeAnimationTrack(this, handle); 79 80 mNodeTrackList[handle] = ret; 81 return ret; 82 } 83 //--------------------------------------------------------------------- createNodeTrack(unsigned short handle,Node * node)84 NodeAnimationTrack* Animation::createNodeTrack(unsigned short handle, Node* node) 85 { 86 NodeAnimationTrack* ret = createNodeTrack(handle); 87 88 ret->setAssociatedNode(node); 89 90 return ret; 91 } 92 //--------------------------------------------------------------------- getNumNodeTracks(void) const93 unsigned short Animation::getNumNodeTracks(void) const 94 { 95 return (unsigned short)mNodeTrackList.size(); 96 } 97 //--------------------------------------------------------------------- hasNodeTrack(unsigned short handle) const98 bool Animation::hasNodeTrack(unsigned short handle) const 99 { 100 return (mNodeTrackList.find(handle) != mNodeTrackList.end()); 101 } 102 //--------------------------------------------------------------------- getNodeTrack(unsigned short handle) const103 NodeAnimationTrack* Animation::getNodeTrack(unsigned short handle) const 104 { 105 NodeTrackList::const_iterator i = mNodeTrackList.find(handle); 106 107 if (i == mNodeTrackList.end()) 108 { 109 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 110 "Cannot find node track with the specified handle " + 111 StringConverter::toString(handle), 112 "Animation::getNodeTrack"); 113 } 114 115 return i->second; 116 117 } 118 //--------------------------------------------------------------------- destroyNodeTrack(unsigned short handle)119 void Animation::destroyNodeTrack(unsigned short handle) 120 { 121 NodeTrackList::iterator i = mNodeTrackList.find(handle); 122 123 if (i != mNodeTrackList.end()) 124 { 125 OGRE_DELETE i->second; 126 mNodeTrackList.erase(i); 127 _keyFrameListChanged(); 128 } 129 } 130 //--------------------------------------------------------------------- destroyAllNodeTracks(void)131 void Animation::destroyAllNodeTracks(void) 132 { 133 NodeTrackList::iterator i; 134 for (i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i) 135 { 136 OGRE_DELETE i->second; 137 } 138 mNodeTrackList.clear(); 139 _keyFrameListChanged(); 140 } 141 //--------------------------------------------------------------------- createNumericTrack(unsigned short handle)142 NumericAnimationTrack* Animation::createNumericTrack(unsigned short handle) 143 { 144 if (hasNumericTrack(handle)) 145 { 146 OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, 147 "Numeric track with the specified handle " + 148 StringConverter::toString(handle) + " already exists", 149 "Animation::createNumericTrack"); 150 } 151 152 NumericAnimationTrack* ret = OGRE_NEW NumericAnimationTrack(this, handle); 153 154 mNumericTrackList[handle] = ret; 155 return ret; 156 } 157 //--------------------------------------------------------------------- createNumericTrack(unsigned short handle,const AnimableValuePtr & anim)158 NumericAnimationTrack* Animation::createNumericTrack(unsigned short handle, 159 const AnimableValuePtr& anim) 160 { 161 NumericAnimationTrack* ret = createNumericTrack(handle); 162 163 ret->setAssociatedAnimable(anim); 164 165 return ret; 166 } 167 //--------------------------------------------------------------------- getNumNumericTracks(void) const168 unsigned short Animation::getNumNumericTracks(void) const 169 { 170 return (unsigned short)mNumericTrackList.size(); 171 } 172 //--------------------------------------------------------------------- hasNumericTrack(unsigned short handle) const173 bool Animation::hasNumericTrack(unsigned short handle) const 174 { 175 return (mNumericTrackList.find(handle) != mNumericTrackList.end()); 176 } 177 //--------------------------------------------------------------------- getNumericTrack(unsigned short handle) const178 NumericAnimationTrack* Animation::getNumericTrack(unsigned short handle) const 179 { 180 NumericTrackList::const_iterator i = mNumericTrackList.find(handle); 181 182 if (i == mNumericTrackList.end()) 183 { 184 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 185 "Cannot find numeric track with the specified handle " + 186 StringConverter::toString(handle), 187 "Animation::getNumericTrack"); 188 } 189 190 return i->second; 191 192 } 193 //--------------------------------------------------------------------- destroyNumericTrack(unsigned short handle)194 void Animation::destroyNumericTrack(unsigned short handle) 195 { 196 NumericTrackList::iterator i = mNumericTrackList.find(handle); 197 198 if (i != mNumericTrackList.end()) 199 { 200 OGRE_DELETE i->second; 201 mNumericTrackList.erase(i); 202 _keyFrameListChanged(); 203 } 204 } 205 //--------------------------------------------------------------------- destroyAllNumericTracks(void)206 void Animation::destroyAllNumericTracks(void) 207 { 208 NumericTrackList::iterator i; 209 for (i = mNumericTrackList.begin(); i != mNumericTrackList.end(); ++i) 210 { 211 OGRE_DELETE i->second; 212 } 213 mNumericTrackList.clear(); 214 _keyFrameListChanged(); 215 } 216 //--------------------------------------------------------------------- createVertexTrack(unsigned short handle,VertexAnimationType animType)217 VertexAnimationTrack* Animation::createVertexTrack(unsigned short handle, 218 VertexAnimationType animType) 219 { 220 if (hasVertexTrack(handle)) 221 { 222 OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, 223 "Vertex track with the specified handle " + 224 StringConverter::toString(handle) + " already exists", 225 "Animation::createVertexTrack"); 226 } 227 228 VertexAnimationTrack* ret = OGRE_NEW VertexAnimationTrack(this, handle, animType); 229 230 mVertexTrackList[handle] = ret; 231 return ret; 232 233 } 234 //--------------------------------------------------------------------- createVertexTrack(unsigned short handle,VertexData * data,VertexAnimationType animType)235 VertexAnimationTrack* Animation::createVertexTrack(unsigned short handle, 236 VertexData* data, VertexAnimationType animType) 237 { 238 VertexAnimationTrack* ret = createVertexTrack(handle, animType); 239 240 ret->setAssociatedVertexData(data); 241 242 return ret; 243 } 244 //--------------------------------------------------------------------- getNumVertexTracks(void) const245 unsigned short Animation::getNumVertexTracks(void) const 246 { 247 return (unsigned short)mVertexTrackList.size(); 248 } 249 //--------------------------------------------------------------------- hasVertexTrack(unsigned short handle) const250 bool Animation::hasVertexTrack(unsigned short handle) const 251 { 252 return (mVertexTrackList.find(handle) != mVertexTrackList.end()); 253 } 254 //--------------------------------------------------------------------- getVertexTrack(unsigned short handle) const255 VertexAnimationTrack* Animation::getVertexTrack(unsigned short handle) const 256 { 257 VertexTrackList::const_iterator i = mVertexTrackList.find(handle); 258 259 if (i == mVertexTrackList.end()) 260 { 261 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 262 "Cannot find vertex track with the specified handle " + 263 StringConverter::toString(handle), 264 "Animation::getVertexTrack"); 265 } 266 267 return i->second; 268 269 } 270 //--------------------------------------------------------------------- destroyVertexTrack(unsigned short handle)271 void Animation::destroyVertexTrack(unsigned short handle) 272 { 273 VertexTrackList::iterator i = mVertexTrackList.find(handle); 274 275 if (i != mVertexTrackList.end()) 276 { 277 OGRE_DELETE i->second; 278 mVertexTrackList.erase(i); 279 _keyFrameListChanged(); 280 } 281 } 282 //--------------------------------------------------------------------- destroyAllVertexTracks(void)283 void Animation::destroyAllVertexTracks(void) 284 { 285 VertexTrackList::iterator i; 286 for (i = mVertexTrackList.begin(); i != mVertexTrackList.end(); ++i) 287 { 288 OGRE_DELETE i->second; 289 } 290 mVertexTrackList.clear(); 291 _keyFrameListChanged(); 292 } 293 //--------------------------------------------------------------------- destroyAllTracks(void)294 void Animation::destroyAllTracks(void) 295 { 296 destroyAllNodeTracks(); 297 destroyAllNumericTracks(); 298 destroyAllVertexTracks(); 299 } 300 //--------------------------------------------------------------------- getName(void) const301 const String& Animation::getName(void) const 302 { 303 return mName; 304 } 305 //--------------------------------------------------------------------- apply(Real timePos,Real weight,Real scale)306 void Animation::apply(Real timePos, Real weight, Real scale) 307 { 308 _applyBaseKeyFrame(); 309 310 // Calculate time index for fast keyframe search 311 TimeIndex timeIndex = _getTimeIndex(timePos); 312 313 NodeTrackList::iterator i; 314 for (i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i) 315 { 316 i->second->apply(timeIndex, weight, scale); 317 } 318 NumericTrackList::iterator j; 319 for (j = mNumericTrackList.begin(); j != mNumericTrackList.end(); ++j) 320 { 321 j->second->apply(timeIndex, weight, scale); 322 } 323 VertexTrackList::iterator k; 324 for (k = mVertexTrackList.begin(); k != mVertexTrackList.end(); ++k) 325 { 326 k->second->apply(timeIndex, weight, scale); 327 } 328 329 } 330 //--------------------------------------------------------------------- applyToNode(Node * node,Real timePos,Real weight,Real scale)331 void Animation::applyToNode(Node* node, Real timePos, Real weight, Real scale) 332 { 333 _applyBaseKeyFrame(); 334 335 // Calculate time index for fast keyframe search 336 TimeIndex timeIndex = _getTimeIndex(timePos); 337 338 NodeTrackList::iterator i; 339 for (i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i) 340 { 341 i->second->applyToNode(node, timeIndex, weight, scale); 342 } 343 } 344 //--------------------------------------------------------------------- apply(Skeleton * skel,Real timePos,Real weight,Real scale)345 void Animation::apply(Skeleton* skel, Real timePos, Real weight, 346 Real scale) 347 { 348 _applyBaseKeyFrame(); 349 350 // Calculate time index for fast keyframe search 351 TimeIndex timeIndex = _getTimeIndex(timePos); 352 353 NodeTrackList::iterator i; 354 for (i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i) 355 { 356 // get bone to apply to 357 Bone* b = skel->getBone(i->first); 358 i->second->applyToNode(b, timeIndex, weight, scale); 359 } 360 361 362 } 363 //--------------------------------------------------------------------- apply(Skeleton * skel,Real timePos,float weight,const AnimationState::BoneBlendMask * blendMask,Real scale)364 void Animation::apply(Skeleton* skel, Real timePos, float weight, 365 const AnimationState::BoneBlendMask* blendMask, Real scale) 366 { 367 _applyBaseKeyFrame(); 368 369 // Calculate time index for fast keyframe search 370 TimeIndex timeIndex = _getTimeIndex(timePos); 371 372 NodeTrackList::iterator i; 373 for (i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i) 374 { 375 // get bone to apply to 376 Bone* b = skel->getBone(i->first); 377 i->second->applyToNode(b, timeIndex, (*blendMask)[b->getHandle()] * weight, scale); 378 } 379 } 380 //--------------------------------------------------------------------- apply(Entity * entity,Real timePos,Real weight,bool software,bool hardware)381 void Animation::apply(Entity* entity, Real timePos, Real weight, 382 bool software, bool hardware) 383 { 384 _applyBaseKeyFrame(); 385 386 // Calculate time index for fast keyframe search 387 TimeIndex timeIndex = _getTimeIndex(timePos); 388 389 VertexTrackList::iterator i; 390 for (i = mVertexTrackList.begin(); i != mVertexTrackList.end(); ++i) 391 { 392 unsigned short handle = i->first; 393 VertexAnimationTrack* track = i->second; 394 395 VertexData* swVertexData; 396 VertexData* hwVertexData; 397 if (handle == 0) 398 { 399 // shared vertex data 400 swVertexData = entity->_getSoftwareVertexAnimVertexData(); 401 hwVertexData = entity->_getHardwareVertexAnimVertexData(); 402 entity->_markBuffersUsedForAnimation(); 403 } 404 else 405 { 406 // sub entity vertex data (-1) 407 SubEntity* s = entity->getSubEntity(handle - 1); 408 // Skip this track if subentity is not visible 409 if (!s->isVisible()) 410 continue; 411 swVertexData = s->_getSoftwareVertexAnimVertexData(); 412 hwVertexData = s->_getHardwareVertexAnimVertexData(); 413 s->_markBuffersUsedForAnimation(); 414 } 415 // Apply to both hardware and software, if requested 416 if (software) 417 { 418 track->setTargetMode(VertexAnimationTrack::TM_SOFTWARE); 419 track->applyToVertexData(swVertexData, timeIndex, weight, 420 &(entity->getMesh()->getPoseList())); 421 } 422 if (hardware) 423 { 424 track->setTargetMode(VertexAnimationTrack::TM_HARDWARE); 425 track->applyToVertexData(hwVertexData, timeIndex, weight, 426 &(entity->getMesh()->getPoseList())); 427 } 428 } 429 430 } 431 //--------------------------------------------------------------------- applyToAnimable(const AnimableValuePtr & anim,Real timePos,Real weight,Real scale)432 void Animation::applyToAnimable(const AnimableValuePtr& anim, Real timePos, Real weight, Real scale) 433 { 434 _applyBaseKeyFrame(); 435 436 // Calculate time index for fast keyframe search 437 _getTimeIndex(timePos); 438 439 NumericTrackList::iterator j; 440 for (j = mNumericTrackList.begin(); j != mNumericTrackList.end(); ++j) 441 { 442 j->second->applyToAnimable(anim, timePos, weight, scale); 443 } 444 } 445 //--------------------------------------------------------------------- applyToVertexData(VertexData * data,Real timePos,Real weight)446 void Animation::applyToVertexData(VertexData* data, Real timePos, Real weight) 447 { 448 _applyBaseKeyFrame(); 449 450 // Calculate time index for fast keyframe search 451 TimeIndex timeIndex = _getTimeIndex(timePos); 452 453 VertexTrackList::iterator k; 454 for (k = mVertexTrackList.begin(); k != mVertexTrackList.end(); ++k) 455 { 456 k->second->applyToVertexData(data, timeIndex, weight); 457 } 458 } 459 //--------------------------------------------------------------------- setInterpolationMode(InterpolationMode im)460 void Animation::setInterpolationMode(InterpolationMode im) 461 { 462 mInterpolationMode = im; 463 } 464 //--------------------------------------------------------------------- getInterpolationMode(void) const465 Animation::InterpolationMode Animation::getInterpolationMode(void) const 466 { 467 return mInterpolationMode; 468 } 469 //--------------------------------------------------------------------- setDefaultInterpolationMode(InterpolationMode im)470 void Animation::setDefaultInterpolationMode(InterpolationMode im) 471 { 472 msDefaultInterpolationMode = im; 473 } 474 //--------------------------------------------------------------------- getDefaultInterpolationMode(void)475 Animation::InterpolationMode Animation::getDefaultInterpolationMode(void) 476 { 477 return msDefaultInterpolationMode; 478 } 479 //--------------------------------------------------------------------- _getNodeTrackList(void) const480 const Animation::NodeTrackList& Animation::_getNodeTrackList(void) const 481 { 482 return mNodeTrackList; 483 484 } 485 //--------------------------------------------------------------------- _getNumericTrackList(void) const486 const Animation::NumericTrackList& Animation::_getNumericTrackList(void) const 487 { 488 return mNumericTrackList; 489 } 490 //--------------------------------------------------------------------- _getVertexTrackList(void) const491 const Animation::VertexTrackList& Animation::_getVertexTrackList(void) const 492 { 493 return mVertexTrackList; 494 } 495 //--------------------------------------------------------------------- setRotationInterpolationMode(RotationInterpolationMode im)496 void Animation::setRotationInterpolationMode(RotationInterpolationMode im) 497 { 498 mRotationInterpolationMode = im; 499 } 500 //--------------------------------------------------------------------- getRotationInterpolationMode(void) const501 Animation::RotationInterpolationMode Animation::getRotationInterpolationMode(void) const 502 { 503 return mRotationInterpolationMode; 504 } 505 //--------------------------------------------------------------------- setDefaultRotationInterpolationMode(RotationInterpolationMode im)506 void Animation::setDefaultRotationInterpolationMode(RotationInterpolationMode im) 507 { 508 msDefaultRotationInterpolationMode = im; 509 } 510 //--------------------------------------------------------------------- getDefaultRotationInterpolationMode(void)511 Animation::RotationInterpolationMode Animation::getDefaultRotationInterpolationMode(void) 512 { 513 return msDefaultRotationInterpolationMode; 514 } 515 //--------------------------------------------------------------------- optimise(bool discardIdentityNodeTracks)516 void Animation::optimise(bool discardIdentityNodeTracks) 517 { 518 optimiseNodeTracks(discardIdentityNodeTracks); 519 optimiseVertexTracks(); 520 521 } 522 //----------------------------------------------------------------------- _collectIdentityNodeTracks(TrackHandleList & tracks) const523 void Animation::_collectIdentityNodeTracks(TrackHandleList& tracks) const 524 { 525 NodeTrackList::const_iterator i, iend; 526 iend = mNodeTrackList.end(); 527 for (i = mNodeTrackList.begin(); i != iend; ++i) 528 { 529 const NodeAnimationTrack* track = i->second; 530 if (track->hasNonZeroKeyFrames()) 531 { 532 tracks.erase(i->first); 533 } 534 } 535 } 536 //----------------------------------------------------------------------- _destroyNodeTracks(const TrackHandleList & tracks)537 void Animation::_destroyNodeTracks(const TrackHandleList& tracks) 538 { 539 TrackHandleList::const_iterator t, tend; 540 tend = tracks.end(); 541 for (t = tracks.begin(); t != tend; ++t) 542 { 543 destroyNodeTrack(*t); 544 } 545 } 546 //----------------------------------------------------------------------- optimiseNodeTracks(bool discardIdentityTracks)547 void Animation::optimiseNodeTracks(bool discardIdentityTracks) 548 { 549 // Iterate over the node tracks and identify those with no useful keyframes 550 std::list<unsigned short> tracksToDestroy; 551 NodeTrackList::iterator i; 552 for (i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i) 553 { 554 NodeAnimationTrack* track = i->second; 555 if (discardIdentityTracks && !track->hasNonZeroKeyFrames()) 556 { 557 // mark the entire track for destruction 558 tracksToDestroy.push_back(i->first); 559 } 560 else 561 { 562 track->optimise(); 563 } 564 565 } 566 567 // Now destroy the tracks we marked for death 568 for(std::list<unsigned short>::iterator h = tracksToDestroy.begin(); 569 h != tracksToDestroy.end(); ++h) 570 { 571 destroyNodeTrack(*h); 572 } 573 } 574 //----------------------------------------------------------------------- optimiseVertexTracks(void)575 void Animation::optimiseVertexTracks(void) 576 { 577 // Iterate over the node tracks and identify those with no useful keyframes 578 std::list<unsigned short> tracksToDestroy; 579 VertexTrackList::iterator i; 580 for (i = mVertexTrackList.begin(); i != mVertexTrackList.end(); ++i) 581 { 582 VertexAnimationTrack* track = i->second; 583 if (!track->hasNonZeroKeyFrames()) 584 { 585 // mark the entire track for destruction 586 tracksToDestroy.push_back(i->first); 587 } 588 else 589 { 590 track->optimise(); 591 } 592 593 } 594 595 // Now destroy the tracks we marked for death 596 for(std::list<unsigned short>::iterator h = tracksToDestroy.begin(); 597 h != tracksToDestroy.end(); ++h) 598 { 599 destroyVertexTrack(*h); 600 } 601 602 } 603 //----------------------------------------------------------------------- clone(const String & newName) const604 Animation* Animation::clone(const String& newName) const 605 { 606 Animation* newAnim = OGRE_NEW Animation(newName, mLength); 607 newAnim->mInterpolationMode = mInterpolationMode; 608 newAnim->mRotationInterpolationMode = mRotationInterpolationMode; 609 610 // Clone all tracks 611 for (NodeTrackList::const_iterator i = mNodeTrackList.begin(); 612 i != mNodeTrackList.end(); ++i) 613 { 614 i->second->_clone(newAnim); 615 } 616 for (NumericTrackList::const_iterator i = mNumericTrackList.begin(); 617 i != mNumericTrackList.end(); ++i) 618 { 619 i->second->_clone(newAnim); 620 } 621 for (VertexTrackList::const_iterator i = mVertexTrackList.begin(); 622 i != mVertexTrackList.end(); ++i) 623 { 624 i->second->_clone(newAnim); 625 } 626 627 newAnim->_keyFrameListChanged(); 628 return newAnim; 629 630 } 631 //----------------------------------------------------------------------- _getTimeIndex(Real timePos) const632 TimeIndex Animation::_getTimeIndex(Real timePos) const 633 { 634 // Uncomment following statement for work as previous 635 //return timePos; 636 637 // Build keyframe time list on demand 638 if (mKeyFrameTimesDirty) 639 { 640 buildKeyFrameTimeList(); 641 } 642 643 // Wrap time 644 Real totalAnimationLength = mLength; 645 646 if( timePos > totalAnimationLength && totalAnimationLength > 0.0f ) 647 timePos = std::fmod( timePos, totalAnimationLength ); 648 649 // Search for global index 650 KeyFrameTimeList::iterator it = 651 std::lower_bound(mKeyFrameTimes.begin(), mKeyFrameTimes.end(), timePos); 652 653 return TimeIndex(timePos, static_cast<uint>(std::distance(mKeyFrameTimes.begin(), it))); 654 } 655 //----------------------------------------------------------------------- buildKeyFrameTimeList(void) const656 void Animation::buildKeyFrameTimeList(void) const 657 { 658 NodeTrackList::const_iterator i; 659 NumericTrackList::const_iterator j; 660 VertexTrackList::const_iterator k; 661 662 // Clear old keyframe times 663 mKeyFrameTimes.clear(); 664 665 // Collect all keyframe times from each track 666 for (i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i) 667 { 668 i->second->_collectKeyFrameTimes(mKeyFrameTimes); 669 } 670 for (j = mNumericTrackList.begin(); j != mNumericTrackList.end(); ++j) 671 { 672 j->second->_collectKeyFrameTimes(mKeyFrameTimes); 673 } 674 for (k = mVertexTrackList.begin(); k != mVertexTrackList.end(); ++k) 675 { 676 k->second->_collectKeyFrameTimes(mKeyFrameTimes); 677 } 678 679 // Build global index to local index map for each track 680 for (i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i) 681 { 682 i->second->_buildKeyFrameIndexMap(mKeyFrameTimes); 683 } 684 for (j = mNumericTrackList.begin(); j != mNumericTrackList.end(); ++j) 685 { 686 j->second->_buildKeyFrameIndexMap(mKeyFrameTimes); 687 } 688 for (k = mVertexTrackList.begin(); k != mVertexTrackList.end(); ++k) 689 { 690 k->second->_buildKeyFrameIndexMap(mKeyFrameTimes); 691 } 692 693 // Reset dirty flag 694 mKeyFrameTimesDirty = false; 695 } 696 //----------------------------------------------------------------------- setUseBaseKeyFrame(bool useBaseKeyFrame,Real keyframeTime,const String & baseAnimName)697 void Animation::setUseBaseKeyFrame(bool useBaseKeyFrame, Real keyframeTime, const String& baseAnimName) 698 { 699 if (useBaseKeyFrame != mUseBaseKeyFrame || 700 keyframeTime != mBaseKeyFrameTime || 701 baseAnimName != mBaseKeyFrameAnimationName) 702 { 703 mUseBaseKeyFrame = useBaseKeyFrame; 704 mBaseKeyFrameTime = keyframeTime; 705 mBaseKeyFrameAnimationName = baseAnimName; 706 } 707 } 708 //----------------------------------------------------------------------- getUseBaseKeyFrame() const709 bool Animation::getUseBaseKeyFrame() const 710 { 711 return mUseBaseKeyFrame; 712 } 713 //----------------------------------------------------------------------- getBaseKeyFrameTime() const714 Real Animation::getBaseKeyFrameTime() const 715 { 716 return mBaseKeyFrameTime; 717 } 718 //----------------------------------------------------------------------- getBaseKeyFrameAnimationName() const719 const String& Animation::getBaseKeyFrameAnimationName() const 720 { 721 return mBaseKeyFrameAnimationName; 722 } 723 //----------------------------------------------------------------------- _applyBaseKeyFrame()724 void Animation::_applyBaseKeyFrame() 725 { 726 if (mUseBaseKeyFrame) 727 { 728 Animation* baseAnim = this; 729 if (!mBaseKeyFrameAnimationName.empty() && mContainer) 730 baseAnim = mContainer->getAnimation(mBaseKeyFrameAnimationName); 731 732 if (baseAnim) 733 { 734 for (NodeTrackList::iterator i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i) 735 { 736 NodeAnimationTrack* track = i->second; 737 738 NodeAnimationTrack* baseTrack; 739 if (baseAnim == this) 740 baseTrack = track; 741 else 742 baseTrack = baseAnim->getNodeTrack(track->getHandle()); 743 744 TransformKeyFrame kf(baseTrack, mBaseKeyFrameTime); 745 baseTrack->getInterpolatedKeyFrame(baseAnim->_getTimeIndex(mBaseKeyFrameTime), &kf); 746 track->_applyBaseKeyFrame(&kf); 747 } 748 749 for (VertexTrackList::iterator i = mVertexTrackList.begin(); i != mVertexTrackList.end(); ++i) 750 { 751 VertexAnimationTrack* track = i->second; 752 753 if (track->getAnimationType() == VAT_POSE) 754 { 755 VertexAnimationTrack* baseTrack; 756 if (baseAnim == this) 757 baseTrack = track; 758 else 759 baseTrack = baseAnim->getVertexTrack(track->getHandle()); 760 761 VertexPoseKeyFrame kf(baseTrack, mBaseKeyFrameTime); 762 baseTrack->getInterpolatedKeyFrame(baseAnim->_getTimeIndex(mBaseKeyFrameTime), &kf); 763 track->_applyBaseKeyFrame(&kf); 764 765 } 766 } 767 768 } 769 770 // Re-base has been done, this is a one-way translation 771 mUseBaseKeyFrame = false; 772 } 773 774 } 775 //----------------------------------------------------------------------- _notifyContainer(AnimationContainer * c)776 void Animation::_notifyContainer(AnimationContainer* c) 777 { 778 mContainer = c; 779 } 780 //----------------------------------------------------------------------- getContainer()781 AnimationContainer* Animation::getContainer() 782 { 783 return mContainer; 784 } 785 786 787 } 788 789 790