mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-04-01 20:06:41 +00:00
Use accurate bone lookups for attaching objects
NIFs don't requires nodes to have unique names, which means looking up a bone by name may get the wrong one. Instead, use a NifIndex:BoneHandle map to make sure we can get the proper bone from a given Nif::Node.
This commit is contained in:
parent
95730cc127
commit
e0da265972
1 changed files with 29 additions and 7 deletions
|
@ -380,7 +380,6 @@ static TextKeyMap extractTextKeys(const Nif::NiTextKeyExtraData *tk)
|
||||||
return textkeys;
|
return textkeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animroot, TextKeyMap &textkeys, std::vector<Nif::NiKeyframeController const*> &ctrls, Ogre::Bone *parent=NULL)
|
void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animroot, TextKeyMap &textkeys, std::vector<Nif::NiKeyframeController const*> &ctrls, Ogre::Bone *parent=NULL)
|
||||||
{
|
{
|
||||||
Ogre::Bone *bone;
|
Ogre::Bone *bone;
|
||||||
|
@ -389,6 +388,7 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animro
|
||||||
else
|
else
|
||||||
bone = skel->createBone();
|
bone = skel->createBone();
|
||||||
if(parent) parent->addChild(bone);
|
if(parent) parent->addChild(bone);
|
||||||
|
mNifToOgreHandleMap[node->recIndex] = bone->getHandle();
|
||||||
|
|
||||||
bone->setOrientation(node->trafo.rotation);
|
bone->setOrientation(node->trafo.rotation);
|
||||||
bone->setPosition(node->trafo.pos);
|
bone->setPosition(node->trafo.pos);
|
||||||
|
@ -439,6 +439,8 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lookup to retrieve an Ogre bone handle for a given Nif record index
|
||||||
|
std::map<int,int> mNifToOgreHandleMap;
|
||||||
|
|
||||||
typedef std::map<std::string,NIFSkeletonLoader> LoaderMap;
|
typedef std::map<std::string,NIFSkeletonLoader> LoaderMap;
|
||||||
static LoaderMap sLoaders;
|
static LoaderMap sLoaders;
|
||||||
|
@ -569,6 +571,20 @@ static Ogre::SkeletonPtr createSkeleton(const std::string &name, const std::stri
|
||||||
return skelMgr.create(name, group, true, &sLoaders[name]);
|
return skelMgr.create(name, group, true, &sLoaders[name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Looks up an Ogre Bone handle ID from a NIF's record index. Should only be
|
||||||
|
// used when the bone name is insufficient as this is a relatively slow lookup
|
||||||
|
static int lookupOgreBoneHandle(const std::string &nifname, int idx)
|
||||||
|
{
|
||||||
|
LoaderMap::const_iterator loader = sLoaders.find(nifname);
|
||||||
|
if(loader != sLoaders.end())
|
||||||
|
{
|
||||||
|
std::map<int,int>::const_iterator entry = loader->second.mNifToOgreHandleMap.find(idx);
|
||||||
|
if(entry != loader->second.mNifToOgreHandleMap.end())
|
||||||
|
return entry->second;
|
||||||
|
}
|
||||||
|
throw std::runtime_error("Invalid NIF record lookup ("+nifname+", index "+Ogre::StringConverter::toString(idx)+")");
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
NIFSkeletonLoader::LoaderMap NIFSkeletonLoader::sLoaders;
|
NIFSkeletonLoader::LoaderMap NIFSkeletonLoader::sLoaders;
|
||||||
|
|
||||||
|
@ -1285,7 +1301,11 @@ class NIFMeshLoader : Ogre::ManualResourceLoader
|
||||||
|
|
||||||
createParticleEmitterAffectors(partsys, partctrl);
|
createParticleEmitterAffectors(partsys, partctrl);
|
||||||
if(!partctrl->emitter.empty() && !partsys->isAttached())
|
if(!partctrl->emitter.empty() && !partsys->isAttached())
|
||||||
entitybase->attachObjectToBone(partctrl->emitter->name, partsys);
|
{
|
||||||
|
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, partctrl->emitter->recIndex);
|
||||||
|
Ogre::Bone *trgtbone = entitybase->getSkeleton()->getBone(trgtid);
|
||||||
|
entitybase->attachObjectToBone(trgtbone->getName(), partsys);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ctrl = ctrl->next;
|
ctrl = ctrl->next;
|
||||||
}
|
}
|
||||||
|
@ -1362,10 +1382,8 @@ class NIFMeshLoader : Ogre::ManualResourceLoader
|
||||||
{
|
{
|
||||||
const Nif::NiVisController *vis = static_cast<const Nif::NiVisController*>(ctrl.getPtr());
|
const Nif::NiVisController *vis = static_cast<const Nif::NiVisController*>(ctrl.getPtr());
|
||||||
|
|
||||||
const Nif::Named *target = dynamic_cast<const Nif::Named*>(ctrl->target.getPtr());
|
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, ctrl->target->recIndex);
|
||||||
if(!target) target = node;
|
Ogre::Bone *trgtbone = entities.mSkelBase->getSkeleton()->getBone(trgtid);
|
||||||
|
|
||||||
Ogre::Bone *trgtbone = entities.mSkelBase->getSkeleton()->getBone(target->name);
|
|
||||||
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > srcval; /* Filled in later */
|
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > srcval; /* Filled in later */
|
||||||
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > dstval(OGRE_NEW VisController::Value(trgtbone));
|
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > dstval(OGRE_NEW VisController::Value(trgtbone));
|
||||||
Ogre::SharedPtr<Ogre::ControllerFunction<Ogre::Real> > func(OGRE_NEW VisController::Function(vis->data.getPtr()));
|
Ogre::SharedPtr<Ogre::ControllerFunction<Ogre::Real> > func(OGRE_NEW VisController::Function(vis->data.getPtr()));
|
||||||
|
@ -1405,7 +1423,11 @@ class NIFMeshLoader : Ogre::ManualResourceLoader
|
||||||
if(entity->hasSkeleton())
|
if(entity->hasSkeleton())
|
||||||
entity->shareSkeletonInstanceWith(entities.mSkelBase);
|
entity->shareSkeletonInstanceWith(entities.mSkelBase);
|
||||||
else
|
else
|
||||||
entities.mSkelBase->attachObjectToBone(shape->name, entity);
|
{
|
||||||
|
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(mName, shape->recIndex);
|
||||||
|
Ogre::Bone *trgtbone = entities.mSkelBase->getSkeleton()->getBone(trgtid);
|
||||||
|
entities.mSkelBase->attachObjectToBone(trgtbone->getName(), entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue