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)
|
, 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue