From 3e9b0a333cea79ba76b684bdb83b086c89028432 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 18 Jan 2013 14:25:32 -0800 Subject: [PATCH] Allow specifying the accumulation for animations Animations that move a character may do so either visually or physically. An axis' accumuluation value specifies whether the movement is visual (0) or physical (1). Idle animations, for instance, typically don't physically move a character, while death animations may physically move them along the X and Y planes, but not along Z (the vertical movement is purely visual). --- apps/openmw/mwmechanics/character.cpp | 15 ++++----------- apps/openmw/mwrender/animation.cpp | 9 ++++++++- apps/openmw/mwrender/animation.hpp | 6 ++++++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 96221cbb8d..f5b6301a2b 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -41,17 +41,7 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim } mAnimation->setController(this); - switch(mState) - { - case CharState_Idle: - mCurrentGroup = "idle"; - mAnimation->play(mCurrentGroup, "start"); - break; - case CharState_Dead: - mCurrentGroup = "death1"; - mAnimation->play(mCurrentGroup, "stop"); - break; - } + setState(mState); } CharacterController::CharacterController(const CharacterController &rhs) @@ -138,6 +128,7 @@ void CharacterController::playGroup(const std::string &groupname, int mode, int while(count-- > 0) mAnimQueue.push_back(groupname); mCurrentGroup = groupname; + mAnimation->setAccumulation(Ogre::Vector3::ZERO); mAnimation->play(mCurrentGroup, ((mode==2) ? "loop start" : "start")); } else if(mode == 0) @@ -166,10 +157,12 @@ void CharacterController::setState(CharacterState state) { case CharState_Idle: mCurrentGroup = "idle"; + mAnimation->setAccumulation(Ogre::Vector3::ZERO); mAnimation->play(mCurrentGroup, "start"); break; case CharState_Dead: mCurrentGroup = "death1"; + mAnimation->setAccumulation(Ogre::Vector3(1.0f, 1.0f, 0.0f)); mAnimation->play(mCurrentGroup, "start"); break; } diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 1a464f5d84..b6c712522b 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -21,6 +21,7 @@ Animation::Animation(const MWWorld::Ptr &ptr) , mInsert(NULL) , mAccumRoot(NULL) , mNonAccumRoot(NULL) + , mAccumulate(Ogre::Vector3::ZERO) , mStartPosition(0.0f) , mLastPosition(0.0f) , mCurrentKeys(NULL) @@ -118,6 +119,12 @@ void Animation::setController(MWMechanics::CharacterController *controller) } +void Animation::setAccumulation(const Ogre::Vector3 &accum) +{ + mAccumulate = accum; +} + + void Animation::updatePosition(float time) { mAnimState->setTimePosition(time); @@ -127,7 +134,7 @@ void Animation::updatePosition(float time) /* 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; + Ogre::Vector3 posdiff = (mNonAccumRoot->getPosition() - mLastPosition) * mAccumulate; /* Translate the accumulation root back to compensate for the move. */ mAccumRoot->translate(-posdiff); diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 726d0cf388..32d51775a5 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -24,6 +24,7 @@ protected: std::map mTextKeys; Ogre::Bone *mAccumRoot; Ogre::Bone *mNonAccumRoot; + Ogre::Vector3 mAccumulate; Ogre::Vector3 mStartPosition; Ogre::Vector3 mLastPosition; @@ -49,6 +50,11 @@ public: void setController(MWMechanics::CharacterController *controller); std::vector getAnimationNames(); + // Specifies the axis' to accumulate on. Non-accumulated axis will just + // move visually, but not affect the actual movement. Each x/y/z value + // should be on the scale of 0 to 1. + void setAccumulation(const Ogre::Vector3 &accum); + void play(const std::string &groupname, const std::string &start); virtual void runAnimation(float timepassed); };