forked from teamnwah/openmw-tes3coop
Avoid creating bones for NiTriShape nodes
The offset specified for them can be just as easilly handled by the tag point they get connected to, and as such it's just needless extra nodes.
This commit is contained in:
parent
648e3331f5
commit
14d814d1d3
2 changed files with 51 additions and 23 deletions
|
@ -169,6 +169,8 @@ static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const
|
||||||
for(size_t i = 0;i < ctrls.size();i++)
|
for(size_t i = 0;i < ctrls.size();i++)
|
||||||
{
|
{
|
||||||
Nif::NiKeyframeController *kfc = ctrls[i];
|
Nif::NiKeyframeController *kfc = ctrls[i];
|
||||||
|
if(kfc->data.empty())
|
||||||
|
continue;
|
||||||
Nif::NiKeyframeData *kf = kfc->data.getPtr();
|
Nif::NiKeyframeData *kf = kfc->data.getPtr();
|
||||||
|
|
||||||
/* Get the keyframes and make sure they're sorted first to last */
|
/* Get the keyframes and make sure they're sorted first to last */
|
||||||
|
@ -183,7 +185,9 @@ static void buildAnimation(Ogre::Skeleton *skel, const std::string &name, const
|
||||||
Ogre::Bone *bone = skel->getBone(targets[i]);
|
Ogre::Bone *bone = skel->getBone(targets[i]);
|
||||||
// NOTE: For some reason, Ogre doesn't like the node track ID being different from
|
// NOTE: For some reason, Ogre doesn't like the node track ID being different from
|
||||||
// the bone ID
|
// the bone ID
|
||||||
Ogre::NodeAnimationTrack *nodetrack = anim->createNodeTrack(bone->getHandle(), bone);
|
Ogre::NodeAnimationTrack *nodetrack = anim->hasNodeTrack(bone->getHandle()) ?
|
||||||
|
anim->getNodeTrack(bone->getHandle()) :
|
||||||
|
anim->createNodeTrack(bone->getHandle(), bone);
|
||||||
const Ogre::Quaternion &startquat = bone->getInitialOrientation();
|
const Ogre::Quaternion &startquat = bone->getInitialOrientation();
|
||||||
const Ogre::Vector3 &starttrans = bone->getInitialPosition();
|
const Ogre::Vector3 &starttrans = bone->getInitialPosition();
|
||||||
const Ogre::Vector3 &startscale = bone->getInitialScale();
|
const Ogre::Vector3 &startscale = bone->getInitialScale();
|
||||||
|
@ -299,6 +303,9 @@ static TextKeyMap extractTextKeys(const Nif::NiTextKeyExtraData *tk)
|
||||||
|
|
||||||
void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, std::vector<Nif::NiKeyframeController*> &ctrls, Ogre::Bone *parent=NULL)
|
void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, std::vector<Nif::NiKeyframeController*> &ctrls, Ogre::Bone *parent=NULL)
|
||||||
{
|
{
|
||||||
|
if(node->recType == Nif::RC_NiTriShape)
|
||||||
|
return;
|
||||||
|
|
||||||
Ogre::Bone *bone;
|
Ogre::Bone *bone;
|
||||||
if(!skel->hasBone(node->name))
|
if(!skel->hasBone(node->name))
|
||||||
bone = skel->createBone(node->name);
|
bone = skel->createBone(node->name);
|
||||||
|
@ -403,6 +410,9 @@ void loadResource(Ogre::Resource *resource)
|
||||||
|
|
||||||
bool createSkeleton(const std::string &name, const std::string &group, const Nif::Node *node)
|
bool createSkeleton(const std::string &name, const std::string &group, const Nif::Node *node)
|
||||||
{
|
{
|
||||||
|
if(node->recType == Nif::RC_NiTriShape)
|
||||||
|
return false;
|
||||||
|
|
||||||
if(node->boneTrafo != NULL)
|
if(node->boneTrafo != NULL)
|
||||||
{
|
{
|
||||||
Ogre::SkeletonManager &skelMgr = Ogre::SkeletonManager::getSingleton();
|
Ogre::SkeletonManager &skelMgr = Ogre::SkeletonManager::getSingleton();
|
||||||
|
@ -733,7 +743,6 @@ class NIFMeshLoader : Ogre::ManualResourceLoader
|
||||||
// Get the skeleton resource, so vertices can be transformed into the bones' initial state.
|
// Get the skeleton resource, so vertices can be transformed into the bones' initial state.
|
||||||
Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr();
|
Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr();
|
||||||
skel = skelMgr->getByName(mSkelName);
|
skel = skelMgr->getByName(mSkelName);
|
||||||
skel->touch();
|
|
||||||
|
|
||||||
// Convert vertices and normals to bone space from bind position. It would be
|
// Convert vertices and normals to bone space from bind position. It would be
|
||||||
// better to transform the bones into bind position, but there doesn't seem to
|
// better to transform the bones into bind position, but there doesn't seem to
|
||||||
|
@ -967,7 +976,7 @@ public:
|
||||||
findTriShape(mesh, node);
|
findTriShape(mesh, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createMeshes(const Nif::Node *node, MeshPairList &meshes, int flags=0)
|
void createMeshes(const Nif::Node *node, MeshInfoList &meshes, int flags=0)
|
||||||
{
|
{
|
||||||
flags |= node->flags;
|
flags |= node->flags;
|
||||||
|
|
||||||
|
@ -1026,7 +1035,8 @@ public:
|
||||||
mesh->setAutoBuildEdgeLists(false);
|
mesh->setAutoBuildEdgeLists(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
meshes.push_back(std::make_pair(mesh->getName(), shape->name));
|
meshes.push_back(MeshInfo(mesh->getName(), (shape->parent ? shape->parent->name : shape->name),
|
||||||
|
shape->trafo.pos, shape->trafo.rotation, shape->trafo.scale));
|
||||||
}
|
}
|
||||||
else if(node->recType != Nif::RC_NiNode && node->recType != Nif::RC_RootCollisionNode &&
|
else if(node->recType != Nif::RC_NiNode && node->recType != Nif::RC_RootCollisionNode &&
|
||||||
node->recType != Nif::RC_NiRotatingParticles)
|
node->recType != Nif::RC_NiRotatingParticles)
|
||||||
|
@ -1047,16 +1057,16 @@ public:
|
||||||
NIFMeshLoader::LoaderMap NIFMeshLoader::sLoaders;
|
NIFMeshLoader::LoaderMap NIFMeshLoader::sLoaders;
|
||||||
|
|
||||||
|
|
||||||
typedef std::map<std::string,MeshPairList> MeshPairMap;
|
typedef std::map<std::string,MeshInfoList> MeshInfoMap;
|
||||||
static MeshPairMap sMeshPairMap;
|
static MeshInfoMap sMeshInfoMap;
|
||||||
|
|
||||||
MeshPairList NIFLoader::load(const std::string &name, const std::string &skelName, const std::string &group)
|
MeshInfoList NIFLoader::load(const std::string &name, const std::string &skelName, const std::string &group)
|
||||||
{
|
{
|
||||||
MeshPairMap::const_iterator meshiter = sMeshPairMap.find(name+"@skel="+skelName);
|
MeshInfoMap::const_iterator meshiter = sMeshInfoMap.find(name+"@skel="+skelName);
|
||||||
if(meshiter != sMeshPairMap.end())
|
if(meshiter != sMeshInfoMap.end())
|
||||||
return meshiter->second;
|
return meshiter->second;
|
||||||
|
|
||||||
MeshPairList &meshes = sMeshPairMap[name+"@skel="+skelName];
|
MeshInfoList &meshes = sMeshInfoMap[name+"@skel="+skelName];
|
||||||
Nif::NIFFile nif(name);
|
Nif::NIFFile nif(name);
|
||||||
if (nif.numRecords() < 1)
|
if (nif.numRecords() < 1)
|
||||||
{
|
{
|
||||||
|
@ -1090,14 +1100,14 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parentNode, std::string na
|
||||||
EntityList entitylist;
|
EntityList entitylist;
|
||||||
|
|
||||||
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
|
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
|
||||||
MeshPairList meshes = load(name, name, group);
|
MeshInfoList meshes = load(name, name, group);
|
||||||
if(meshes.size() == 0)
|
if(meshes.size() == 0)
|
||||||
return entitylist;
|
return entitylist;
|
||||||
|
|
||||||
Ogre::SceneManager *sceneMgr = parentNode->getCreator();
|
Ogre::SceneManager *sceneMgr = parentNode->getCreator();
|
||||||
for(size_t i = 0;i < meshes.size();i++)
|
for(size_t i = 0;i < meshes.size();i++)
|
||||||
{
|
{
|
||||||
entitylist.mEntities.push_back(sceneMgr->createEntity(meshes[i].first));
|
entitylist.mEntities.push_back(sceneMgr->createEntity(meshes[i].mMeshName));
|
||||||
Ogre::Entity *entity = entitylist.mEntities.back();
|
Ogre::Entity *entity = entitylist.mEntities.back();
|
||||||
if(!entitylist.mSkelBase && entity->hasSkeleton())
|
if(!entitylist.mSkelBase && entity->hasSkeleton())
|
||||||
entitylist.mSkelBase = entity;
|
entitylist.mSkelBase = entity;
|
||||||
|
@ -1115,7 +1125,12 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parentNode, std::string na
|
||||||
parentNode->attachObject(entity);
|
parentNode->attachObject(entity);
|
||||||
}
|
}
|
||||||
else if(entity != entitylist.mSkelBase)
|
else if(entity != entitylist.mSkelBase)
|
||||||
entitylist.mSkelBase->attachObjectToBone(meshes[i].second, entity);
|
{
|
||||||
|
Ogre::TagPoint *tag = entitylist.mSkelBase->attachObjectToBone(meshes[i].mTargetNode, entity);
|
||||||
|
tag->setPosition(meshes[i].mPos);
|
||||||
|
tag->setOrientation(meshes[i].mRot);
|
||||||
|
tag->setScale(Ogre::Vector3(meshes[i].mScale));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1134,22 +1149,22 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo
|
||||||
EntityList entitylist;
|
EntityList entitylist;
|
||||||
|
|
||||||
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
|
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
|
||||||
MeshPairList meshes = load(name, parent->getMesh()->getSkeletonName(), group);
|
MeshInfoList meshes = load(name, parent->getMesh()->getSkeletonName(), group);
|
||||||
if(meshes.size() == 0)
|
if(meshes.size() == 0)
|
||||||
return entitylist;
|
return entitylist;
|
||||||
|
|
||||||
Ogre::SceneManager *sceneMgr = parentNode->getCreator();
|
Ogre::SceneManager *sceneMgr = parentNode->getCreator();
|
||||||
std::string filter = "tri "+bonename;
|
std::string filter = bonename;
|
||||||
std::transform(filter.begin()+4, filter.end(), filter.begin()+4, ::tolower);
|
std::transform(filter.begin(), filter.end(), filter.begin(), ::tolower);
|
||||||
for(size_t i = 0;i < meshes.size();i++)
|
for(size_t i = 0;i < meshes.size();i++)
|
||||||
{
|
{
|
||||||
Ogre::Entity *ent = sceneMgr->createEntity(meshes[i].first);
|
Ogre::Entity *ent = sceneMgr->createEntity(meshes[i].mMeshName);
|
||||||
if(ent->hasSkeleton())
|
if(ent->hasSkeleton())
|
||||||
{
|
{
|
||||||
std::transform(meshes[i].second.begin(), meshes[i].second.end(), meshes[i].second.begin(), ::tolower);
|
std::transform(meshes[i].mTargetNode.begin(), meshes[i].mTargetNode.end(),
|
||||||
|
meshes[i].mTargetNode.begin(), ::tolower);
|
||||||
|
|
||||||
if(meshes[i].second.length() < filter.length() ||
|
if(meshes[i].mMeshName.find("@shape=tri "+filter) == std::string::npos)
|
||||||
meshes[i].second.compare(0, filter.length(), filter) != 0)
|
|
||||||
{
|
{
|
||||||
sceneMgr->destroyEntity(ent);
|
sceneMgr->destroyEntity(ent);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -53,8 +53,21 @@ struct EntityList {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/** This holds a list of mesh names along with the names of their parent nodes */
|
/* This holds a list of mesh names, the names of their parent nodes, and the offset
|
||||||
typedef std::vector< std::pair<std::string,std::string> > MeshPairList;
|
* from their parent nodes. */
|
||||||
|
struct MeshInfo {
|
||||||
|
std::string mMeshName;
|
||||||
|
std::string mTargetNode;
|
||||||
|
Ogre::Vector3 mPos;
|
||||||
|
Ogre::Matrix3 mRot;
|
||||||
|
float mScale;
|
||||||
|
|
||||||
|
MeshInfo(const std::string &name, const std::string &target,
|
||||||
|
const Ogre::Vector3 &pos, const Ogre::Matrix3 &rot, float scale)
|
||||||
|
: mMeshName(name), mTargetNode(target), mPos(pos), mRot(rot), mScale(scale)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
typedef std::vector<MeshInfo> MeshInfoList;
|
||||||
|
|
||||||
/** Manual resource loader for NIF meshes. This is the main class
|
/** Manual resource loader for NIF meshes. This is the main class
|
||||||
responsible for translating the internal NIF mesh structure into
|
responsible for translating the internal NIF mesh structure into
|
||||||
|
@ -70,7 +83,7 @@ typedef std::vector< std::pair<std::string,std::string> > MeshPairList;
|
||||||
*/
|
*/
|
||||||
class NIFLoader
|
class NIFLoader
|
||||||
{
|
{
|
||||||
static MeshPairList load(const std::string &name, const std::string &skelName, const std::string &group);
|
static MeshInfoList load(const std::string &name, const std::string &skelName, const std::string &group);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static EntityList createEntities(Ogre::Entity *parent, const std::string &bonename,
|
static EntityList createEntities(Ogre::Entity *parent, const std::string &bonename,
|
||||||
|
|
Loading…
Reference in a new issue