From 512ff3687adf306fae3d0dc85d2019909eb77d35 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 23 Apr 2013 20:42:54 -0700 Subject: [PATCH] Don't create Ogre animations for skeletons --- components/nifogre/ogrenifloader.cpp | 28 +++- components/nifogre/skeleton.cpp | 220 ++------------------------- components/nifogre/skeleton.hpp | 4 +- 3 files changed, 37 insertions(+), 215 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 95ba439d1b..e451326fee 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -676,6 +676,32 @@ class NIFObjectLoader } + static TextKeyMap extractTextKeys(const Nif::NiTextKeyExtraData *tk) + { + TextKeyMap textkeys; + for(size_t i = 0;i < tk->list.size();i++) + { + const std::string &str = tk->list[i].text; + std::string::size_type pos = 0; + while(pos < str.length()) + { + if(::isspace(str[pos])) + { + pos++; + continue; + } + + std::string::size_type nextpos = std::min(str.find('\r', pos), str.find('\n', pos)); + std::string result = str.substr(pos, nextpos-pos); + textkeys.insert(std::make_pair(tk->list[i].time, Misc::StringUtils::toLower(result))); + + pos = nextpos; + } + } + return textkeys; + } + + static void createObjects(const std::string &name, const std::string &group, Ogre::SceneManager *sceneMgr, const Nif::Node *node, ObjectList &objectlist, int flags, int animflags, int partflags) @@ -704,7 +730,7 @@ class NIFObjectLoader const Nif::NiTextKeyExtraData *tk = static_cast(e.getPtr()); int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, node->recIndex); - objectlist.mTextKeys[trgtid] = NIFSkeletonLoader::extractTextKeys(tk); + objectlist.mTextKeys[trgtid] = extractTextKeys(tk); } else if(e->recType == Nif::RC_NiStringExtraData) { diff --git a/components/nifogre/skeleton.cpp b/components/nifogre/skeleton.cpp index 1306d037c2..3aec920fc4 100644 --- a/components/nifogre/skeleton.cpp +++ b/components/nifogre/skeleton.cpp @@ -11,142 +11,7 @@ namespace NifOgre { -void NIFSkeletonLoader::buildAnimation(Ogre::Skeleton *skel, const std::string &name, const std::vector &ctrls, const std::vector &targets, float startTime, float stopTime) -{ - Ogre::Animation *anim = skel->createAnimation(name, stopTime); - - for(size_t i = 0;i < ctrls.size();i++) - { - const Nif::NiKeyframeController *kfc = ctrls[i]; - if(kfc->data.empty()) - continue; - const Nif::NiKeyframeData *kf = kfc->data.getPtr(); - - /* Get the keyframes and make sure they're sorted first to last */ - const Nif::QuaternionKeyList &quatkeys = kf->mRotations; - const Nif::Vector3KeyList &trankeys = kf->mTranslations; - const Nif::FloatKeyList &scalekeys = kf->mScales; - - Nif::QuaternionKeyList::VecType::const_iterator quatiter = quatkeys.mKeys.begin(); - Nif::Vector3KeyList::VecType::const_iterator traniter = trankeys.mKeys.begin(); - Nif::FloatKeyList::VecType::const_iterator scaleiter = scalekeys.mKeys.begin(); - - Ogre::Bone *bone = skel->getBone(targets[i]); - // NOTE: For some reason, Ogre doesn't like the node track ID being different from - // the bone ID - Ogre::NodeAnimationTrack *nodetrack = anim->hasNodeTrack(bone->getHandle()) ? - anim->getNodeTrack(bone->getHandle()) : - anim->createNodeTrack(bone->getHandle(), bone); - - Ogre::Quaternion lastquat, curquat; - Ogre::Vector3 lasttrans(0.0f), curtrans(0.0f); - Ogre::Vector3 lastscale(1.0f), curscale(1.0f); - if(quatiter != quatkeys.mKeys.end()) - lastquat = curquat = quatiter->mValue; - if(traniter != trankeys.mKeys.end()) - lasttrans = curtrans = traniter->mValue; - if(scaleiter != scalekeys.mKeys.end()) - lastscale = curscale = Ogre::Vector3(scaleiter->mValue); - - bool didlast = false; - while(!didlast) - { - float curtime = std::numeric_limits::max(); - - //Get latest time - if(quatiter != quatkeys.mKeys.end()) - curtime = std::min(curtime, quatiter->mTime); - if(traniter != trankeys.mKeys.end()) - curtime = std::min(curtime, traniter->mTime); - if(scaleiter != scalekeys.mKeys.end()) - curtime = std::min(curtime, scaleiter->mTime); - - curtime = std::max(curtime, startTime); - if(curtime >= stopTime) - { - didlast = true; - curtime = stopTime; - } - - // Get the latest quaternions, translations, and scales for the - // current time - while(quatiter != quatkeys.mKeys.end() && curtime >= quatiter->mTime) - { - lastquat = curquat; - if(++quatiter != quatkeys.mKeys.end()) - curquat = quatiter->mValue; - } - while(traniter != trankeys.mKeys.end() && curtime >= traniter->mTime) - { - lasttrans = curtrans; - if(++traniter != trankeys.mKeys.end()) - curtrans = traniter->mValue; - } - while(scaleiter != scalekeys.mKeys.end() && curtime >= scaleiter->mTime) - { - lastscale = curscale; - if(++scaleiter != scalekeys.mKeys.end()) - curscale = Ogre::Vector3(scaleiter->mValue); - } - - Ogre::TransformKeyFrame *kframe; - kframe = nodetrack->createNodeKeyFrame(curtime); - if(quatiter == quatkeys.mKeys.end() || quatiter == quatkeys.mKeys.begin()) - kframe->setRotation(curquat); - else - { - Nif::QuaternionKeyList::VecType::const_iterator last = quatiter-1; - float diff = (curtime-last->mTime) / (quatiter->mTime-last->mTime); - kframe->setRotation(Ogre::Quaternion::nlerp(diff, lastquat, curquat)); - } - if(traniter == trankeys.mKeys.end() || traniter == trankeys.mKeys.begin()) - kframe->setTranslate(curtrans); - else - { - Nif::Vector3KeyList::VecType::const_iterator last = traniter-1; - float diff = (curtime-last->mTime) / (traniter->mTime-last->mTime); - kframe->setTranslate(lasttrans + ((curtrans-lasttrans)*diff)); - } - if(scaleiter == scalekeys.mKeys.end() || scaleiter == scalekeys.mKeys.begin()) - kframe->setScale(curscale); - else - { - Nif::FloatKeyList::VecType::const_iterator last = scaleiter-1; - float diff = (curtime-last->mTime) / (scaleiter->mTime-last->mTime); - kframe->setScale(lastscale + ((curscale-lastscale)*diff)); - } - } - } - anim->optimise(); -} - - -TextKeyMap NIFSkeletonLoader::extractTextKeys(const Nif::NiTextKeyExtraData *tk) -{ - TextKeyMap textkeys; - for(size_t i = 0;i < tk->list.size();i++) - { - const std::string &str = tk->list[i].text; - std::string::size_type pos = 0; - while(pos < str.length()) - { - if(::isspace(str[pos])) - { - pos++; - continue; - } - - std::string::size_type nextpos = std::min(str.find('\r', pos), str.find('\n', pos)); - std::string result = str.substr(pos, nextpos-pos); - textkeys.insert(std::make_pair(tk->list[i].time, Misc::StringUtils::toLower(result))); - - pos = nextpos; - } - } - return textkeys; -} - -void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animroot, TextKeyMap &textkeys, std::vector &ctrls, Ogre::Bone *parent) +void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *parent) { Ogre::Bone *bone; if(!skel->hasBone(node->name)) @@ -175,29 +40,16 @@ void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Nif::ControllerPtr ctrl = node->controller; while(!ctrl.empty()) { - if(ctrl->recType == Nif::RC_NiKeyframeController) - ctrls.push_back(static_cast(ctrl.getPtr())); - else if(!(ctrl->recType == Nif::RC_NiParticleSystemController || - ctrl->recType == Nif::RC_NiVisController || - ctrl->recType == Nif::RC_NiUVController || - ctrl->recType == Nif::RC_NiGeomMorpherController - )) + if(!(ctrl->recType == Nif::RC_NiParticleSystemController || + ctrl->recType == Nif::RC_NiVisController || + ctrl->recType == Nif::RC_NiUVController || + ctrl->recType == Nif::RC_NiKeyframeController || + ctrl->recType == Nif::RC_NiGeomMorpherController + )) warn("Unhandled "+ctrl->recName+" from node "+node->name+" in "+skel->getName()); ctrl = ctrl->next; } - Nif::ExtraPtr e = node->extra; - while(!e.empty()) - { - if(e->recType == Nif::RC_NiTextKeyExtraData && !animroot) - { - const Nif::NiTextKeyExtraData *tk = static_cast(e.getPtr()); - textkeys = extractTextKeys(tk); - animroot = bone; - } - e = e->extra; - } - const Nif::NiNode *ninode = dynamic_cast(node); if(ninode) { @@ -205,7 +57,7 @@ void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node, for(size_t i = 0;i < children.length();i++) { if(!children[i].empty()) - buildBones(skel, children[i].getPtr(), animroot, textkeys, ctrls, bone); + buildBones(skel, children[i].getPtr(), bone); } } } @@ -218,68 +70,14 @@ void NIFSkeletonLoader::loadResource(Ogre::Resource *resource) Nif::NIFFile::ptr nif(Nif::NIFFile::create(skel->getName())); const Nif::Node *node = static_cast(nif->getRoot(0)); - std::vector ctrls; - Ogre::Bone *animroot = NULL; - TextKeyMap textkeys; try { - buildBones(skel, node, animroot, textkeys, ctrls); + buildBones(skel, node); } catch(std::exception &e) { std::cerr<< "Exception while loading "<getName() < targets; - // TODO: If ctrls.size() == 0, check for a .kf file sharing the name of the .nif file - if(ctrls.size() == 0) // No animations? Then we're done. - return; - - float maxtime = 0.0f; - for(size_t i = 0;i < ctrls.size();i++) - { - const Nif::NiKeyframeController *ctrl = ctrls[i]; - maxtime = std::max(maxtime, ctrl->timeStop); - Nif::Named *target = dynamic_cast(ctrl->target.getPtr()); - if(target != NULL) - targets.push_back(target->name); - } - - if(targets.size() != ctrls.size()) - { - warn("Target size mismatch ("+Ogre::StringConverter::toString(targets.size())+" targets, "+ - Ogre::StringConverter::toString(ctrls.size())+" controllers)"); - return; - } - - std::string currentgroup; - TextKeyMap::const_iterator keyiter = textkeys.begin(); - for(keyiter = textkeys.begin();keyiter != textkeys.end();keyiter++) - { - std::string::size_type sep = keyiter->second.find(':'); - if((sep == currentgroup.length() && keyiter->second.compare(0, sep, currentgroup) == 0) || - (sep == sizeof("soundgen")-1 && keyiter->second.compare(0, sep, "soundgen") == 0) || - (sep == sizeof("sound")-1 && keyiter->second.compare(0, sep, "sound") == 0)) - continue; - currentgroup = keyiter->second.substr(0, sep); - - if(skel->hasAnimation(currentgroup)) - continue; - - TextKeyMap::const_iterator lastkeyiter = textkeys.end(); - while((--lastkeyiter)->first > keyiter->first) - { - if(lastkeyiter->second.find(':') == currentgroup.length() && - lastkeyiter->second.compare(0, currentgroup.length(), currentgroup) == 0) - break; - } - - buildAnimation(skel, currentgroup, ctrls, targets, keyiter->first, lastkeyiter->first); - } } diff --git a/components/nifogre/skeleton.hpp b/components/nifogre/skeleton.hpp index e71dcfb158..38cfe14e3d 100644 --- a/components/nifogre/skeleton.hpp +++ b/components/nifogre/skeleton.hpp @@ -36,8 +36,7 @@ class NIFSkeletonLoader : public Ogre::ManualResourceLoader abort(); } - static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const std::vector &ctrls, const std::vector &targets, float startTime, float stopTime); - void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animroot, TextKeyMap &textkeys, std::vector &ctrls, Ogre::Bone *parent=NULL); + void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *parent=NULL); // Lookup to retrieve an Ogre bone handle for a given Nif record index std::map mNifToOgreHandleMap; @@ -46,7 +45,6 @@ class NIFSkeletonLoader : public Ogre::ManualResourceLoader static LoaderMap sLoaders; public: - static TextKeyMap extractTextKeys(const Nif::NiTextKeyExtraData *tk); void loadResource(Ogre::Resource *resource); static Ogre::SkeletonPtr createSkeleton(const std::string &name, const std::string &group, const Nif::Node *node);