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:
parent
f69a8259e1
commit
261ea1fe5e
3 changed files with 124 additions and 5 deletions
|
@ -37,6 +37,7 @@ Animation::Animation(const MWWorld::Ptr &ptr)
|
|||
, mNonAccumRoot(NULL)
|
||||
, mAccumulate(Ogre::Vector3::ZERO)
|
||||
, mLastPosition(0.0f)
|
||||
, mCurrentControllers(NULL)
|
||||
, mCurrentKeys(NULL)
|
||||
, mCurrentAnim(NULL)
|
||||
, mCurrentTime(0.0f)
|
||||
|
@ -68,6 +69,7 @@ void Animation::setAnimationSources(const std::vector<std::string> &names)
|
|||
return;
|
||||
Ogre::SceneManager *sceneMgr = mInsert->getCreator();
|
||||
|
||||
mCurrentControllers = &mObjectList.mControllers;
|
||||
mCurrentAnim = NULL;
|
||||
mCurrentKeys = NULL;
|
||||
mAnimVelocity = 0.0f;
|
||||
|
@ -78,6 +80,7 @@ void Animation::setAnimationSources(const std::vector<std::string> &names)
|
|||
destroyObjectList(sceneMgr, mAnimationSources[i]);
|
||||
mAnimationSources.clear();
|
||||
|
||||
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > ctrlval(OGRE_NEW AnimationValue(this));
|
||||
Ogre::SkeletonInstance *skelinst = mObjectList.mSkelBase->getSkeleton();
|
||||
std::vector<std::string>::const_iterator 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();
|
||||
continue;
|
||||
}
|
||||
const NifOgre::ObjectList &objects = mAnimationSources.back();
|
||||
NifOgre::ObjectList &objects = mAnimationSources.back();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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::Skeleton::BoneIterator boneiter = skel->getBoneIterator();
|
||||
while(boneiter.hasMoreElements())
|
||||
|
@ -167,6 +176,7 @@ void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model
|
|||
if(mObjectList.mControllers[i].getSource().isNull())
|
||||
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 {
|
||||
bool found = false;
|
||||
/* 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))
|
||||
{
|
||||
mCurrentAnim = iter->mSkelBase->getSkeleton()->getAnimation(groupname);
|
||||
mCurrentKeys = &mTextKeys[groupname];
|
||||
mCurrentControllers = &iter->mControllers;
|
||||
mAnimVelocity = 0.0f;
|
||||
|
||||
if(mNonAccumRoot)
|
||||
|
@ -495,8 +506,8 @@ Ogre::Vector3 Animation::runAnimation(float timepassed)
|
|||
if(!handleEvent(time, evt))
|
||||
break;
|
||||
}
|
||||
for(size_t i = 0;i < mObjectList.mControllers.size();i++)
|
||||
mObjectList.mControllers[i].update();
|
||||
for(size_t i = 0;i < mCurrentControllers->size();i++)
|
||||
(*mCurrentControllers)[i].update();
|
||||
|
||||
return movement;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ protected:
|
|||
|
||||
std::vector<NifOgre::ObjectList> mAnimationSources;
|
||||
|
||||
std::vector<Ogre::Controller<Ogre::Real> > *mCurrentControllers;
|
||||
NifOgre::TextKeyMap *mCurrentKeys;
|
||||
NifOgre::TextKeyMap::const_iterator mNextKey;
|
||||
Ogre::Animation *mCurrentAnim;
|
||||
|
|
|
@ -169,6 +169,101 @@ public:
|
|||
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
|
||||
{
|
||||
public:
|
||||
|
@ -1546,6 +1641,18 @@ class NIFObjectLoader : Ogre::ManualResourceLoader
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue