- fbx: add special output node name tag to mark fbx null nodes.

pull/14/head
Alexander Gessler 2012-08-25 22:24:08 +02:00
parent eed3cebc18
commit cdb7caffbd
3 changed files with 93 additions and 5 deletions

View File

@ -61,6 +61,8 @@ namespace FBX {
#define MAGIC_NODE_TAG "_$AssimpFbx$" #define MAGIC_NODE_TAG "_$AssimpFbx$"
#define MAGIC_NULL_TAG "_$AssimpFbxNull$"
#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L #define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
// XXX vc9's debugger won't step into anonymous namespaces // XXX vc9's debugger won't step into anonymous namespaces
@ -204,16 +206,17 @@ private:
// is supposed to have. If there is none, add another node to // is supposed to have. If there is none, add another node to
// preserve the name - people might have scripts etc. that rely // preserve the name - people might have scripts etc. that rely
// on specific node names. // on specific node names.
bool has_name = false; aiNode* name_carrier = NULL;
BOOST_FOREACH(aiNode* prenode, nodes_chain) { BOOST_FOREACH(aiNode* prenode, nodes_chain) {
if ( !strcmp(prenode->mName.C_Str(), original_name.c_str()) ) { if ( !strcmp(prenode->mName.C_Str(), original_name.c_str()) ) {
has_name = true; name_carrier = prenode;
break; break;
} }
} }
if(!has_name) { if(!name_carrier) {
nodes_chain.push_back(new aiNode(original_name)); nodes_chain.push_back(new aiNode(original_name));
name_carrier = nodes_chain.back();
} }
// link all nodes in a row // link all nodes in a row
@ -247,6 +250,14 @@ private:
ConvertCameras(*model); ConvertCameras(*model);
} }
// preserve the info that a node was marked as Null node
// in the original file.
if(model->IsNull()) {
const std::string& new_name = original_name + MAGIC_NULL_TAG;
RenameNode(original_name, new_name);
name_carrier->mName.Set( new_name.c_str() );
}
nodes.push_back(nodes_chain.front()); nodes.push_back(nodes_chain.front());
nodes_chain.clear(); nodes_chain.clear();
} }
@ -1620,6 +1631,54 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// rename a node already partially converted. fixed_name is a string previously returned by
// FixNodeName, new_name specifies the string FixNodeName should return on all further invocations
// which would previously have returned the old value.
//
// this also updates names in node animations, cameras and light sources and is thus slow.
//
// NOTE: the caller is responsible for ensuring that the new name is unique and does
// not collide with any other identifiers. The best way to ensure this is to only
// append to the old name, which is guaranteed to match these requirements.
void RenameNode(const std::string& fixed_name, const std::string& new_name)
{
ai_assert(node_names.find(fixed_name) != node_names.end());
ai_assert(node_names.find(new_name) == node_names.end());
renamed_nodes[fixed_name] = new_name;
const aiString fn(fixed_name);
BOOST_FOREACH(aiCamera* cam, cameras) {
if (cam->mName == fn) {
cam->mName.Set(new_name);
break;
}
}
BOOST_FOREACH(aiLight* light, lights) {
if (light->mName == fn) {
light->mName.Set(new_name);
break;
}
}
BOOST_FOREACH(aiAnimation* anim, animations) {
for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
aiNodeAnim* const na = anim->mChannels[i];
if (na->mNodeName == fn) {
na->mNodeName.Set(new_name);
break;
}
}
}
}
// ------------------------------------------------------------------------------------------------
// takes a fbx node name and returns the identifier to be used in the assimp output scene.
// the function is guaranteed to provide consistent results over multiple invocations
// UNLESS RenameNode() is called for a particular node name.
std::string FixNodeName(const std::string& name) std::string FixNodeName(const std::string& name)
{ {
// strip Model:: prefix, avoiding ambiguities (i.e. don't strip if // strip Model:: prefix, avoiding ambiguities (i.e. don't strip if
@ -1636,7 +1695,9 @@ private:
} }
} }
node_names[temp] = true; node_names[temp] = true;
return temp;
const NameNameMap::const_iterator rit = renamed_nodes.find(temp);
return rit == renamed_nodes.end() ? temp : (*rit).second;
} }
const NodeNameMap::const_iterator it = node_names.find(name); const NodeNameMap::const_iterator it = node_names.find(name);
@ -1646,7 +1707,9 @@ private:
} }
} }
node_names[name] = false; node_names[name] = false;
return name;
const NameNameMap::const_iterator rit = renamed_nodes.find(name);
return rit == renamed_nodes.end() ? name : (*rit).second;
} }
@ -2631,6 +2694,9 @@ private:
typedef std::map<std::string, bool> NodeNameMap; typedef std::map<std::string, bool> NodeNameMap;
NodeNameMap node_names; NodeNameMap node_names;
typedef std::map<std::string, std::string> NameNameMap;
NameNameMap renamed_nodes;
double anim_fps; double anim_fps;
aiScene* const out; aiScene* const out;

View File

@ -485,6 +485,12 @@ public:
return attributes; return attributes;
} }
public:
/** convenience method to check if the node has a Null node marker */
bool IsNull() const;
private: private:
void ResolveLinks(const Element& element, const Document& doc); void ResolveLinks(const Element& element, const Document& doc);

View File

@ -134,6 +134,22 @@ void Model::ResolveLinks(const Element& element, const Document& doc)
} }
// ------------------------------------------------------------------------------------------------
bool Model::IsNull() const
{
const std::vector<const NodeAttribute*>& attrs = GetAttributes();
BOOST_FOREACH(const NodeAttribute* att, attrs) {
const Null* null_tag = dynamic_cast<const Null*>(att);
if(null_tag) {
return true;
}
}
return false;
}
} //!FBX } //!FBX
} //!Assimp } //!Assimp