Skip to content

Commit

Permalink
Cache inject result for NPC's
Browse files Browse the repository at this point in the history
  • Loading branch information
akortunov committed Jan 19, 2019
1 parent 1a3f053 commit 33761cf
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 58 deletions.
47 changes: 0 additions & 47 deletions apps/openmw/mwrender/actoranimation.cpp
Expand Up @@ -115,53 +115,6 @@ std::string ActorAnimation::getHolsteredWeaponBoneName(const MWWorld::ConstPtr&
return boneName;
}

void ActorAnimation::loadBonesFromFile(const std::string &model)
{
const osg::Node* node = mResourceSystem->getSceneManager()->getTemplate(model).get();
osg::ref_ptr<osg::Node> sheathSkeleton (const_cast<osg::Node*>(node)); // const-trickery required because there is no const version of NodeVisitor

SceneUtil::GetExtendedBonesVisitor getBonesVisitor;
sheathSkeleton->accept(getBonesVisitor);
for (auto& nodePair : getBonesVisitor.mFoundBones)
{
osg::Group* sheathParent = getBoneByName(nodePair.second->getName());
if (sheathParent)
{
osg::Node* copy = osg::clone(nodePair.first, osg::CopyOp::DEEP_COPY_ALL);
sheathParent->addChild(copy);
}
}
}

void ActorAnimation::injectCustomBones(const std::string& model)
{
const std::map<std::string, VFS::File*>& index = mResourceSystem->getVFS()->getIndex();

std::string animationPath = model;
if (animationPath.find("meshes") == 0)
{
animationPath.replace(0, 6, "animations");
}
animationPath.replace(animationPath.size()-4, 4, "/");

mResourceSystem->getVFS()->normalizeFilename(animationPath);

std::map<std::string, VFS::File*>::const_iterator found = index.lower_bound(animationPath);
while (found != index.end())
{
const std::string& name = found->first;
if (name.size() >= animationPath.size() && name.substr(0, animationPath.size()) == animationPath)
{
size_t pos = name.find_last_of('.');
if (pos != std::string::npos && name.compare(pos, name.size()-pos, ".nif") == 0)
loadBonesFromFile(name);
}
else
break;
++found;
}
}

// To make sure we do not run morph controllers for weapons, i.e. bows
class EmptyCallback : public osg::NodeCallback
{
Expand Down
1 change: 0 additions & 1 deletion apps/openmw/mwrender/actoranimation.hpp
Expand Up @@ -43,7 +43,6 @@ class ActorAnimation : public Animation, public MWWorld::ContainerStoreListener
bool mWeaponSheathing;
osg::Group* getBoneByName(const std::string& boneName);
virtual void updateHolsteredWeapon(bool showHolsteredWeapons);
virtual void injectCustomBones(const std::string& model);
virtual void updateQuiver();
virtual std::string getHolsteredWeaponBoneName(const MWWorld::ConstPtr& weapon);
virtual PartHolderPtr getWeaponPart(const std::string& model, const std::string& bonename, bool enchantedGlow, osg::Vec4f* glowColor);
Expand Down
90 changes: 86 additions & 4 deletions apps/openmw/mwrender/animation.cpp
Expand Up @@ -1371,8 +1371,66 @@ namespace MWRender
state->second.mLoopingEnabled = enabled;
}

osg::ref_ptr<osg::Node> getModelInstance(Resource::SceneManager* sceneMgr, const std::string& model, bool baseonly)
void loadBonesFromFile(osg::ref_ptr<osg::Node>& baseNode, const std::string &model, Resource::ResourceSystem* resourceSystem)
{
const osg::Node* node = resourceSystem->getSceneManager()->getTemplate(model).get();
osg::ref_ptr<osg::Node> sheathSkeleton (const_cast<osg::Node*>(node)); // const-trickery required because there is no const version of NodeVisitor

SceneUtil::GetExtendedBonesVisitor getBonesVisitor;
sheathSkeleton->accept(getBonesVisitor);
for (auto& nodePair : getBonesVisitor.mFoundBones)
{
SceneUtil::FindByNameVisitor findVisitor (nodePair.second->getName());
baseNode->accept(findVisitor);

osg::Group* sheathParent = findVisitor.mFoundNode;
if (sheathParent)
{
osg::Node* copy = osg::clone(nodePair.first, osg::CopyOp::DEEP_COPY_NODES);
sheathParent->addChild(copy);
}
}
}

void injectCustomBones(osg::ref_ptr<osg::Node>& node, const std::string& model, Resource::ResourceSystem* resourceSystem)
{
const std::map<std::string, VFS::File*>& index = resourceSystem->getVFS()->getIndex();

std::string animationPath = model;
if (animationPath.find("meshes") == 0)
{
animationPath.replace(0, 6, "animations");
}
animationPath.replace(animationPath.size()-4, 4, "/");

resourceSystem->getVFS()->normalizeFilename(animationPath);

std::map<std::string, VFS::File*>::const_iterator found = index.lower_bound(animationPath);
while (found != index.end())
{
const std::string& name = found->first;
if (name.size() >= animationPath.size() && name.substr(0, animationPath.size()) == animationPath)
{
size_t pos = name.find_last_of('.');
if (pos != std::string::npos && name.compare(pos, name.size()-pos, ".nif") == 0)
loadBonesFromFile(node, name, resourceSystem);
}
else
break;
++found;
}
}

enum InjectType
{
None,
Model,
ModelWithFallback
};

osg::ref_ptr<osg::Node> getModelInstance(Resource::ResourceSystem* resourceSystem, const std::string& model, bool baseonly, InjectType inject)
{
Resource::SceneManager* sceneMgr = resourceSystem->getSceneManager();
if (baseonly)
{
typedef std::map<std::string, osg::ref_ptr<osg::Node> > Cache;
Expand All @@ -1382,6 +1440,12 @@ namespace MWRender
{
osg::ref_ptr<osg::Node> created = sceneMgr->getInstance(model);

if (inject == InjectType::ModelWithFallback)
injectCustomBones(created, "meshes\\xbase_anim.nif", resourceSystem);

if (inject != InjectType::None)
injectCustomBones(created, model, resourceSystem);

SceneUtil::CleanObjectRootVisitor removeDrawableVisitor;
created->accept(removeDrawableVisitor);
removeDrawableVisitor.remove();
Expand All @@ -1394,7 +1458,17 @@ namespace MWRender
return sceneMgr->createInstance(found->second);
}
else
return sceneMgr->createInstance(model);
{
osg::ref_ptr<osg::Node> created = sceneMgr->createInstance(model);

if (inject == InjectType::ModelWithFallback)
injectCustomBones(created, "meshes\\xbase_anim.nif", resourceSystem);

if (inject != InjectType::None)
injectCustomBones(created, model, resourceSystem);

return created;
}
}

void Animation::setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly, bool isCreature)
Expand All @@ -1416,9 +1490,17 @@ namespace MWRender
mAccumRoot = nullptr;
mAccumCtrl = nullptr;

InjectType inject = mUseAdditionalSources && mPtr.getClass().isActor() ? InjectType::Model : InjectType::None;
if (inject != InjectType::None && isCreature)
{
MWWorld::LiveCellRef<ESM::Creature> *ref = mPtr.get<ESM::Creature>();
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
inject = InjectType::ModelWithFallback;
}

if (!forceskeleton)
{
osg::ref_ptr<osg::Node> created = getModelInstance(mResourceSystem->getSceneManager(), model, baseonly);
osg::ref_ptr<osg::Node> created = getModelInstance(mResourceSystem, model, baseonly, inject);
mInsert->addChild(created);
mObjectRoot = created->asGroup();
if (!mObjectRoot)
Expand All @@ -1434,7 +1516,7 @@ namespace MWRender
}
else
{
osg::ref_ptr<osg::Node> created = getModelInstance(mResourceSystem->getSceneManager(), model, baseonly);
osg::ref_ptr<osg::Node> created = getModelInstance(mResourceSystem, model, baseonly, inject);
osg::ref_ptr<SceneUtil::Skeleton> skel = dynamic_cast<SceneUtil::Skeleton*>(created.get());
if (!skel)
{
Expand Down
1 change: 1 addition & 0 deletions apps/openmw/mwrender/animation.hpp
Expand Up @@ -233,6 +233,7 @@ class Animation : public osg::Referenced
// The node expected to accumulate movement during movement animations.
osg::ref_ptr<osg::Node> mAccumRoot;


// The controller animating that node.
osg::ref_ptr<NifOsg::KeyframeController> mAccumCtrl;

Expand Down
3 changes: 0 additions & 3 deletions apps/openmw/mwrender/creatureanimation.cpp
Expand Up @@ -52,9 +52,6 @@ CreatureWeaponAnimation::CreatureWeaponAnimation(const MWWorld::Ptr &ptr, const

if((ref->mBase->mFlags&ESM::Creature::Bipedal))
{
if (mUseAdditionalSources)
injectCustomBones("meshes\\xbase_anim.nif");

addAnimSource("meshes\\xbase_anim.nif", model);
}
addAnimSource(model, model);
Expand Down
3 changes: 0 additions & 3 deletions apps/openmw/mwrender/npcanimation.cpp
Expand Up @@ -471,9 +471,6 @@ void NpcAnimation::updateNpcBase()

setObjectRoot(smodel, true, true, false);

if (mUseAdditionalSources)
injectCustomBones(smodel);

updateParts();

if(!is1stPerson)
Expand Down

0 comments on commit 33761cf

Please sign in to comment.