mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-29 03:26:38 +00:00 
			
		
		
		
	Update the object position as the animation moves
This commit is contained in:
		
							parent
							
								
									7ba09ff025
								
							
						
					
					
						commit
						5b3a20ef69
					
				
					 3 changed files with 77 additions and 11 deletions
				
			
		|  | @ -7,6 +7,9 @@ | ||||||
| #include <OgreSubMesh.h> | #include <OgreSubMesh.h> | ||||||
| #include <OgreSceneManager.h> | #include <OgreSceneManager.h> | ||||||
| 
 | 
 | ||||||
|  | #include "../mwbase/environment.hpp" | ||||||
|  | #include "../mwbase/world.hpp" | ||||||
|  | 
 | ||||||
| namespace MWRender | namespace MWRender | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
|  | @ -16,8 +19,14 @@ Animation::Animation(const MWWorld::Ptr &ptr) | ||||||
|     , mTime(0.0f) |     , mTime(0.0f) | ||||||
|     , mAnimState(NULL) |     , mAnimState(NULL) | ||||||
|     , mSkipFrame(false) |     , mSkipFrame(false) | ||||||
|  |     , mAccumRoot(NULL) | ||||||
|     , mNonAccumRoot(NULL) |     , mNonAccumRoot(NULL) | ||||||
|  |     , mLastPosition(0.0f) | ||||||
| { | { | ||||||
|  |     mCurGroup.mStart = mCurGroup.mLoopStart = 0.0f; | ||||||
|  |     mCurGroup.mLoopStop = mCurGroup.mStop = 0.0f; | ||||||
|  |     mNextGroup.mStart = mNextGroup.mLoopStart = 0.0f; | ||||||
|  |     mNextGroup.mLoopStop = mNextGroup.mStop = 0.0f; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Animation::~Animation() | Animation::~Animation() | ||||||
|  | @ -52,9 +61,10 @@ void Animation::createEntityList(Ogre::SceneNode *node, const std::string &model | ||||||
|                 mAnimState = state; |                 mAnimState = state; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         Ogre::SkeletonInstance *skelinst = mEntityList.mSkelBase->getSkeleton(); | ||||||
|         // Would be nice if Ogre::SkeletonInstance allowed access to the 'master' Ogre::SkeletonPtr.
 |         // Would be nice if Ogre::SkeletonInstance allowed access to the 'master' Ogre::SkeletonPtr.
 | ||||||
|         Ogre::SkeletonManager &skelMgr = Ogre::SkeletonManager::getSingleton(); |         Ogre::SkeletonManager &skelMgr = Ogre::SkeletonManager::getSingleton(); | ||||||
|         Ogre::SkeletonPtr skel = skelMgr.getByName(mEntityList.mSkelBase->getSkeleton()->getName()); |         Ogre::SkeletonPtr skel = skelMgr.getByName(skelinst->getName()); | ||||||
|         Ogre::Skeleton::BoneIterator iter = skel->getBoneIterator(); |         Ogre::Skeleton::BoneIterator iter = skel->getBoneIterator(); | ||||||
|         while(iter.hasMoreElements()) |         while(iter.hasMoreElements()) | ||||||
|         { |         { | ||||||
|  | @ -63,7 +73,10 @@ void Animation::createEntityList(Ogre::SceneNode *node, const std::string &model | ||||||
|             if(!data.isEmpty()) |             if(!data.isEmpty()) | ||||||
|             { |             { | ||||||
|                 mTextKeys = Ogre::any_cast<NifOgre::TextKeyMap>(data); |                 mTextKeys = Ogre::any_cast<NifOgre::TextKeyMap>(data); | ||||||
|                 mNonAccumRoot = mEntityList.mSkelBase->getSkeleton()->getBone(bone->getHandle()); |                 mAccumRoot = skelinst->getRootBone(); | ||||||
|  |                 mAccumRoot->setManuallyControlled(true); | ||||||
|  |                 mNonAccumRoot = skelinst->getBone(bone->getHandle()); | ||||||
|  |                 mLastPosition = mNonAccumRoot->getPosition(); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -71,6 +84,43 @@ void Animation::createEntityList(Ogre::SceneNode *node, const std::string &model | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | void Animation::updatePosition(float time) | ||||||
|  | { | ||||||
|  |     mAnimState->setTimePosition(time); | ||||||
|  |     if(mNonAccumRoot) | ||||||
|  |     { | ||||||
|  |         /* Update the animation and get the non-accumulation root's difference from the
 | ||||||
|  |          * last update. */ | ||||||
|  |         mEntityList.mSkelBase->getSkeleton()->setAnimationState(*mAnimState->getParent()); | ||||||
|  |         Ogre::Vector3 posdiff = mNonAccumRoot->getPosition() - mLastPosition; | ||||||
|  | 
 | ||||||
|  |         /* Translate the accumulation root back to compensate for the move. */ | ||||||
|  |         mAccumRoot->translate(-posdiff); | ||||||
|  |         mLastPosition += posdiff; | ||||||
|  | 
 | ||||||
|  |         /* Finally, move the object based on how much the non-accumulation root moved. */ | ||||||
|  |         Ogre::Vector3 newpos(mPtr.getRefData().getPosition().pos); | ||||||
|  |         newpos += mInsert->getOrientation() * posdiff; | ||||||
|  | 
 | ||||||
|  |         MWBase::World *world = MWBase::Environment::get().getWorld(); | ||||||
|  |         world->moveObject(mPtr, newpos.x, newpos.y, newpos.z); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Animation::resetPosition(float time) | ||||||
|  | { | ||||||
|  |     mAnimState->setTimePosition(time); | ||||||
|  |     if(mNonAccumRoot) | ||||||
|  |     { | ||||||
|  |         mEntityList.mSkelBase->getSkeleton()->setAnimationState(*mAnimState->getParent()); | ||||||
|  |         mLastPosition = mNonAccumRoot->getPosition(); | ||||||
|  |         /* FIXME: This should be set to -mLastPosition, but without proper collision the
 | ||||||
|  |          * model gets placed halfway into the ground. */ | ||||||
|  |         mAccumRoot->setPosition(0.0f, 0.0f, 0.0f); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| struct checklow { | struct checklow { | ||||||
|     bool operator()(const char &a, const char &b) const |     bool operator()(const char &a, const char &b) const | ||||||
|     { |     { | ||||||
|  | @ -145,6 +195,7 @@ void Animation::playGroup(std::string groupname, int mode, int loops) | ||||||
|         mCurGroup = times; |         mCurGroup = times; | ||||||
|         mNextGroup = GroupTimes(); |         mNextGroup = GroupTimes(); | ||||||
|         mTime = ((mode==2) ? mCurGroup.mLoopStart : mCurGroup.mStart); |         mTime = ((mode==2) ? mCurGroup.mLoopStart : mCurGroup.mStart); | ||||||
|  |         resetPosition(mTime); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -155,29 +206,36 @@ void Animation::skipAnim() | ||||||
| 
 | 
 | ||||||
| void Animation::runAnimation(float timepassed) | void Animation::runAnimation(float timepassed) | ||||||
| { | { | ||||||
|     if(mCurGroup.mLoops > 0 && !mSkipFrame) |     if(mAnimState && !mSkipFrame) | ||||||
|     { |     { | ||||||
|         mTime += timepassed; |         mTime += timepassed; | ||||||
|  |     recheck: | ||||||
|         if(mTime >= mCurGroup.mLoopStop) |         if(mTime >= mCurGroup.mLoopStop) | ||||||
|         { |         { | ||||||
|             if(mCurGroup.mLoops > 1) |             if(mCurGroup.mLoops > 1) | ||||||
|             { |             { | ||||||
|                 mCurGroup.mLoops--; |                 mCurGroup.mLoops--; | ||||||
|  |                 updatePosition(mCurGroup.mLoopStop); | ||||||
|                 mTime = mTime - mCurGroup.mLoopStop + mCurGroup.mLoopStart; |                 mTime = mTime - mCurGroup.mLoopStop + mCurGroup.mLoopStart; | ||||||
|  |                 resetPosition(mCurGroup.mLoopStart); | ||||||
|  |                 goto recheck; | ||||||
|             } |             } | ||||||
|             else if(mTime >= mCurGroup.mStop) |             else if(mTime >= mCurGroup.mStop) | ||||||
|             { |             { | ||||||
|                 if(mNextGroup.mLoops > 0) |                 if(mNextGroup.mLoops > 0) | ||||||
|  |                 { | ||||||
|  |                     updatePosition(mCurGroup.mStop); | ||||||
|                     mTime = mTime - mCurGroup.mStop + mNextGroup.mStart; |                     mTime = mTime - mCurGroup.mStop + mNextGroup.mStart; | ||||||
|                 else |                     resetPosition(mNextGroup.mStart); | ||||||
|                     mTime = mCurGroup.mStop; |                     mCurGroup = mNextGroup; | ||||||
|                 mCurGroup = mNextGroup; |                     mNextGroup = GroupTimes(); | ||||||
|                 mNextGroup = GroupTimes(); |                     goto recheck; | ||||||
|  |                 } | ||||||
|  |                 mTime = mCurGroup.mStop; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if(mAnimState) |         updatePosition(mTime); | ||||||
|             mAnimState->setTimePosition(mTime); |  | ||||||
|     } |     } | ||||||
|     mSkipFrame = false; |     mSkipFrame = false; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -37,7 +37,16 @@ protected: | ||||||
| 
 | 
 | ||||||
|     NifOgre::EntityList mEntityList; |     NifOgre::EntityList mEntityList; | ||||||
|     NifOgre::TextKeyMap mTextKeys; |     NifOgre::TextKeyMap mTextKeys; | ||||||
|     Ogre::Node *mNonAccumRoot; |     Ogre::Bone *mAccumRoot; | ||||||
|  |     Ogre::Bone *mNonAccumRoot; | ||||||
|  |     Ogre::Vector3 mLastPosition; | ||||||
|  | 
 | ||||||
|  |     /* Updates the animation to the specified time, and moves the mPtr object
 | ||||||
|  |      * based on the change since the last update or reset. */ | ||||||
|  |     void updatePosition(float time); | ||||||
|  |     /* Updates the animation to the specified time, without moving the mPtr
 | ||||||
|  |      * object. */ | ||||||
|  |     void resetPosition(float time); | ||||||
| 
 | 
 | ||||||
|     bool findGroupTimes(const std::string &groupname, GroupTimes *times); |     bool findGroupTimes(const std::string &groupname, GroupTimes *times); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -138,7 +138,6 @@ namespace MWRender | ||||||
|         mSelectionBuffer = new OEngine::Render::SelectionBuffer(mCamera, 512, 1024, RV_PlayerPreview); |         mSelectionBuffer = new OEngine::Render::SelectionBuffer(mCamera, 512, 1024, RV_PlayerPreview); | ||||||
| 
 | 
 | ||||||
|         mAnimation->playGroup ("inventoryhandtohand", 0, 1); |         mAnimation->playGroup ("inventoryhandtohand", 0, 1); | ||||||
|         mAnimation->runAnimation (0); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // --------------------------------------------------------------------------------------------------
 |     // --------------------------------------------------------------------------------------------------
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue