Speed up finding of attachment node by using the cached nodeMap

pull/140/head
scrawl 7 years ago
parent a76d693627
commit 767eba941f

@ -1,5 +1,9 @@
#include "creatureanimation.hpp"
#include <iostream>
#include <osg/MatrixTransform>
#include <components/esm/loadcrea.hpp>
#include <components/resource/resourcesystem.hpp>
@ -9,6 +13,8 @@
#include <components/sceneutil/positionattitudetransform.hpp>
#include <components/sceneutil/skeleton.hpp>
#include <components/misc/stringops.hpp>
#include "../mwbase/world.hpp"
#include "../mwworld/class.hpp"
@ -107,39 +113,51 @@ void CreatureWeaponAnimation::updatePart(PartHolderPtr& scene, int slot)
else
bonename = "Shield Bone";
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->getInstance(item.getClass().getModel(item));
osg::ref_ptr<osg::Node> attached = SceneUtil::attach(node, mObjectRoot, bonename, bonename);
mResourceSystem->getSceneManager()->notifyAttached(attached);
scene.reset(new PartHolder(attached));
if (!item.getClass().getEnchantment(item).empty())
addGlow(attached, getEnchantmentColor(item));
// Crossbows start out with a bolt attached
// FIXME: code duplicated from NpcAnimation
if (slot == MWWorld::InventoryStore::Slot_CarriedRight &&
item.getTypeName() == typeid(ESM::Weapon).name() &&
item.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow)
try
{
MWWorld::ContainerStoreIterator ammo = inv.getSlot(MWWorld::InventoryStore::Slot_Ammunition);
if (ammo != inv.end() && ammo->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::Bolt)
attachArrow();
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->getInstance(item.getClass().getModel(item));
const NodeMap& nodeMap = getNodeMap();
NodeMap::const_iterator found = getNodeMap().find(Misc::StringUtils::lowerCase(bonename));
if (found == nodeMap.end())
throw std::runtime_error("Can't find attachment node " + bonename);
osg::ref_ptr<osg::Node> attached = SceneUtil::attach(node, mObjectRoot, bonename, found->second.get());
mResourceSystem->getSceneManager()->notifyAttached(attached);
scene.reset(new PartHolder(attached));
if (!item.getClass().getEnchantment(item).empty())
addGlow(attached, getEnchantmentColor(item));
// Crossbows start out with a bolt attached
// FIXME: code duplicated from NpcAnimation
if (slot == MWWorld::InventoryStore::Slot_CarriedRight &&
item.getTypeName() == typeid(ESM::Weapon).name() &&
item.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow)
{
MWWorld::ContainerStoreIterator ammo = inv.getSlot(MWWorld::InventoryStore::Slot_Ammunition);
if (ammo != inv.end() && ammo->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::Bolt)
attachArrow();
else
mAmmunition.reset();
}
else
mAmmunition.reset();
}
else
mAmmunition.reset();
boost::shared_ptr<SceneUtil::ControllerSource> source;
boost::shared_ptr<SceneUtil::ControllerSource> source;
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
source = mWeaponAnimationTime;
else
source.reset(new NullAnimationTime);
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
source = mWeaponAnimationTime;
else
source.reset(new NullAnimationTime);
SceneUtil::AssignControllerSourcesVisitor assignVisitor(source);
attached->accept(assignVisitor);
SceneUtil::AssignControllerSourcesVisitor assignVisitor(source);
attached->accept(assignVisitor);
}
catch (std::exception& e)
{
std::cerr << "Error adding creature part: " << e.what() << std::endl;
}
}
void CreatureWeaponAnimation::attachArrow()

@ -667,10 +667,18 @@ void NpcAnimation::updateParts()
attachArrow();
}
PartHolderPtr NpcAnimation::insertBoundedPart(const std::string& model, const std::string& bonename, const std::string& bonefilter, bool enchantedGlow, osg::Vec4f* glowColor)
{
osg::ref_ptr<osg::Node> instance = mResourceSystem->getSceneManager()->getInstance(model);
osg::ref_ptr<osg::Node> attached = SceneUtil::attach(instance, mObjectRoot, bonefilter, bonename);
const NodeMap& nodeMap = getNodeMap();
NodeMap::const_iterator found = nodeMap.find(Misc::StringUtils::lowerCase(bonename));
if (found == nodeMap.end())
throw std::runtime_error("Can't find attachment node " + bonename);
osg::ref_ptr<osg::Node> attached = SceneUtil::attach(instance, mObjectRoot, bonefilter, found->second);
mResourceSystem->getSceneManager()->notifyAttached(attached);
if (enchantedGlow)
addGlow(attached, *glowColor);

@ -63,7 +63,7 @@ namespace SceneUtil
std::string mFilter2;
};
osg::ref_ptr<osg::Node> attach(osg::ref_ptr<osg::Node> toAttach, osg::Node *master, const std::string &filter, const std::string &attachNode)
osg::ref_ptr<osg::Node> attach(osg::ref_ptr<osg::Node> toAttach, osg::Node *master, const std::string &filter, osg::Group* attachNode)
{
if (dynamic_cast<SceneUtil::Skeleton*>(toAttach.get()))
{
@ -88,11 +88,6 @@ namespace SceneUtil
}
else
{
FindByNameVisitor find(attachNode);
master->accept(find);
if (!find.mFoundNode)
throw std::runtime_error(std::string("Can't find attachment node ") + attachNode);
FindByNameVisitor findBoneOffset("BoneOffset");
toAttach->accept(findBoneOffset);
@ -110,7 +105,7 @@ namespace SceneUtil
trans->setAttitude(osg::Quat(osg::DegreesToRadians(-90.f), osg::Vec3f(1,0,0)));
}
if (attachNode.find("Left") != std::string::npos)
if (attachNode->getName().find("Left") != std::string::npos)
{
if (!trans)
trans = new osg::PositionAttitudeTransform;
@ -132,13 +127,13 @@ namespace SceneUtil
if (trans)
{
find.mFoundNode->addChild(trans);
attachNode->addChild(trans);
trans->addChild(toAttach);
return trans;
}
else
{
find.mFoundNode->addChild(toAttach);
attachNode->addChild(toAttach);
return toAttach;
}
}

@ -8,6 +8,7 @@
namespace osg
{
class Node;
class Group;
}
namespace SceneUtil
@ -18,7 +19,7 @@ namespace SceneUtil
/// Otherwise, just attach all of the toAttach scenegraph to the attachment node on the master scenegraph, with no filtering.
/// @note The master scene graph is expected to include a skeleton.
/// @return A newly created node that is directly attached to the master scene graph
osg::ref_ptr<osg::Node> attach(osg::ref_ptr<osg::Node> toAttach, osg::Node* master, const std::string& filter, const std::string& attachNode);
osg::ref_ptr<osg::Node> attach(osg::ref_ptr<osg::Node> toAttach, osg::Node* master, const std::string& filter, osg::Group* attachNode);
}

Loading…
Cancel
Save