1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-19 22:23:51 +00:00

Implement a KeyframeController

This commit is contained in:
Chris Robinson 2013-04-07 14:56:23 -07:00
parent f69a8259e1
commit 261ea1fe5e
3 changed files with 124 additions and 5 deletions

View file

@ -37,6 +37,7 @@ Animation::Animation(const MWWorld::Ptr &ptr)
, mNonAccumRoot(NULL) , mNonAccumRoot(NULL)
, mAccumulate(Ogre::Vector3::ZERO) , mAccumulate(Ogre::Vector3::ZERO)
, mLastPosition(0.0f) , mLastPosition(0.0f)
, mCurrentControllers(NULL)
, mCurrentKeys(NULL) , mCurrentKeys(NULL)
, mCurrentAnim(NULL) , mCurrentAnim(NULL)
, mCurrentTime(0.0f) , mCurrentTime(0.0f)
@ -68,6 +69,7 @@ void Animation::setAnimationSources(const std::vector<std::string> &names)
return; return;
Ogre::SceneManager *sceneMgr = mInsert->getCreator(); Ogre::SceneManager *sceneMgr = mInsert->getCreator();
mCurrentControllers = &mObjectList.mControllers;
mCurrentAnim = NULL; mCurrentAnim = NULL;
mCurrentKeys = NULL; mCurrentKeys = NULL;
mAnimVelocity = 0.0f; mAnimVelocity = 0.0f;
@ -78,6 +80,7 @@ void Animation::setAnimationSources(const std::vector<std::string> &names)
destroyObjectList(sceneMgr, mAnimationSources[i]); destroyObjectList(sceneMgr, mAnimationSources[i]);
mAnimationSources.clear(); mAnimationSources.clear();
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > ctrlval(OGRE_NEW AnimationValue(this));
Ogre::SkeletonInstance *skelinst = mObjectList.mSkelBase->getSkeleton(); Ogre::SkeletonInstance *skelinst = mObjectList.mSkelBase->getSkeleton();
std::vector<std::string>::const_iterator nameiter; std::vector<std::string>::const_iterator nameiter;
for(nameiter = names.begin();nameiter != names.end();nameiter++) for(nameiter = names.begin();nameiter != names.end();nameiter++)
@ -90,7 +93,7 @@ void Animation::setAnimationSources(const std::vector<std::string> &names)
mAnimationSources.pop_back(); mAnimationSources.pop_back();
continue; continue;
} }
const NifOgre::ObjectList &objects = mAnimationSources.back(); NifOgre::ObjectList &objects = mAnimationSources.back();
for(size_t i = 0;i < objects.mControllers.size();i++) for(size_t i = 0;i < objects.mControllers.size();i++)
{ {
@ -104,7 +107,13 @@ void Animation::setAnimationSources(const std::vector<std::string> &names)
dstval->setNode(bone); dstval->setNode(bone);
} }
Ogre::Entity *ent = mAnimationSources.back().mSkelBase; for(size_t i = 0;i < objects.mControllers.size();i++)
{
if(objects.mControllers[i].getSource().isNull())
objects.mControllers[i].setSource(ctrlval);
}
Ogre::Entity *ent = objects.mSkelBase;
Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(ent->getSkeleton()->getName()); Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(ent->getSkeleton()->getName());
Ogre::Skeleton::BoneIterator boneiter = skel->getBoneIterator(); Ogre::Skeleton::BoneIterator boneiter = skel->getBoneIterator();
while(boneiter.hasMoreElements()) while(boneiter.hasMoreElements())
@ -167,6 +176,7 @@ void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model
if(mObjectList.mControllers[i].getSource().isNull()) if(mObjectList.mControllers[i].getSource().isNull())
mObjectList.mControllers[i].setSource(ctrlval); mObjectList.mControllers[i].setSource(ctrlval);
} }
mCurrentControllers = &mObjectList.mControllers;
} }
@ -441,12 +451,13 @@ void Animation::play(const std::string &groupname, const std::string &start, con
try { try {
bool found = false; bool found = false;
/* Look in reverse; last-inserted source has priority. */ /* Look in reverse; last-inserted source has priority. */
for(std::vector<NifOgre::ObjectList>::const_reverse_iterator iter(mAnimationSources.rbegin());iter != mAnimationSources.rend();iter++) for(std::vector<NifOgre::ObjectList>::reverse_iterator iter(mAnimationSources.rbegin());iter != mAnimationSources.rend();iter++)
{ {
if(iter->mSkelBase->hasAnimationState(groupname)) if(iter->mSkelBase->hasAnimationState(groupname))
{ {
mCurrentAnim = iter->mSkelBase->getSkeleton()->getAnimation(groupname); mCurrentAnim = iter->mSkelBase->getSkeleton()->getAnimation(groupname);
mCurrentKeys = &mTextKeys[groupname]; mCurrentKeys = &mTextKeys[groupname];
mCurrentControllers = &iter->mControllers;
mAnimVelocity = 0.0f; mAnimVelocity = 0.0f;
if(mNonAccumRoot) if(mNonAccumRoot)
@ -495,8 +506,8 @@ Ogre::Vector3 Animation::runAnimation(float timepassed)
if(!handleEvent(time, evt)) if(!handleEvent(time, evt))
break; break;
} }
for(size_t i = 0;i < mObjectList.mControllers.size();i++) for(size_t i = 0;i < mCurrentControllers->size();i++)
mObjectList.mControllers[i].update(); (*mCurrentControllers)[i].update();
return movement; return movement;
} }

View file

@ -49,6 +49,7 @@ protected:
std::vector<NifOgre::ObjectList> mAnimationSources; std::vector<NifOgre::ObjectList> mAnimationSources;
std::vector<Ogre::Controller<Ogre::Real> > *mCurrentControllers;
NifOgre::TextKeyMap *mCurrentKeys; NifOgre::TextKeyMap *mCurrentKeys;
NifOgre::TextKeyMap::const_iterator mNextKey; NifOgre::TextKeyMap::const_iterator mNextKey;
Ogre::Animation *mCurrentAnim; Ogre::Animation *mCurrentAnim;

View file

@ -169,6 +169,101 @@ public:
typedef DefaultFunction Function; typedef DefaultFunction Function;
}; };
class KeyframeController
{
public:
class Value : public NodeTargetValue<Ogre::Real>
{
private:
Nif::QuaternionKeyList mRotations;
Nif::Vector3KeyList mTranslations;
Nif::FloatKeyList mScales;
public:
Value(Ogre::Node *target, const Nif::NiKeyframeData *data)
: NodeTargetValue<Ogre::Real>(target)
, mRotations(data->mRotations)
, mTranslations(data->mTranslations)
, mScales(data->mScales)
{ }
virtual Ogre::Real getValue() const
{
// Should not be called
return 0.0f;
}
virtual void setValue(Ogre::Real time)
{
if(mRotations.mKeys.size() > 0)
{
if(time <= mRotations.mKeys.front().mTime)
mNode->setOrientation(mRotations.mKeys.front().mValue);
else if(time >= mRotations.mKeys.back().mTime)
mNode->setOrientation(mRotations.mKeys.back().mValue);
else
{
Nif::QuaternionKeyList::VecType::const_iterator iter(mRotations.mKeys.begin()+1);
for(;iter != mRotations.mKeys.end();iter++)
{
if(iter->mTime < time)
continue;
Nif::QuaternionKeyList::VecType::const_iterator last(iter-1);
float a = (time-last->mTime) / (iter->mTime-last->mTime);
mNode->setOrientation(Ogre::Quaternion::nlerp(a, last->mValue, iter->mValue));
break;
}
}
}
if(mTranslations.mKeys.size() > 0)
{
if(time <= mTranslations.mKeys.front().mTime)
mNode->setPosition(mTranslations.mKeys.front().mValue);
else if(time >= mTranslations.mKeys.back().mTime)
mNode->setPosition(mTranslations.mKeys.back().mValue);
else
{
Nif::Vector3KeyList::VecType::const_iterator iter(mTranslations.mKeys.begin()+1);
for(;iter != mTranslations.mKeys.end();iter++)
{
if(iter->mTime < time)
continue;
Nif::Vector3KeyList::VecType::const_iterator last(iter-1);
float a = (time-last->mTime) / (iter->mTime-last->mTime);
mNode->setPosition(last->mValue + ((iter->mValue - last->mValue)*a));
break;
}
}
}
if(mScales.mKeys.size() > 0)
{
if(time <= mScales.mKeys.front().mTime)
mNode->setScale(Ogre::Vector3(mScales.mKeys.front().mValue));
else if(time >= mScales.mKeys.back().mTime)
mNode->setScale(Ogre::Vector3(mScales.mKeys.back().mValue));
else
{
Nif::FloatKeyList::VecType::const_iterator iter(mScales.mKeys.begin()+1);
for(;iter != mScales.mKeys.end();iter++)
{
if(iter->mTime < time)
continue;
Nif::FloatKeyList::VecType::const_iterator last(iter-1);
float a = (time-last->mTime) / (iter->mTime-last->mTime);
mNode->setScale(Ogre::Vector3(last->mValue + ((iter->mValue - last->mValue)*a)));
break;
}
}
}
}
};
typedef DefaultFunction Function;
};
class UVController class UVController
{ {
public: public:
@ -1546,6 +1641,18 @@ class NIFObjectLoader : Ogre::ManualResourceLoader
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func)); objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
} }
else if(ctrl->recType == Nif::RC_NiKeyframeController)
{
const Nif::NiKeyframeController *key = static_cast<const Nif::NiKeyframeController*>(ctrl.getPtr());
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, ctrl->target->recIndex);
Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid);
Ogre::ControllerValueRealPtr srcval; /* Filled in later */
Ogre::ControllerValueRealPtr dstval(OGRE_NEW KeyframeController::Value(trgtbone, key->data.getPtr()));
Ogre::ControllerFunctionRealPtr func(OGRE_NEW KeyframeController::Function(key, false));
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
ctrl = ctrl->next; ctrl = ctrl->next;
} }