2
0
Эх сурвалжийг харах

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

Alexander Gessler 13 жил өмнө
parent
commit
cdb7caffbd

+ 71 - 5
code/FBXConverter.cpp

@@ -61,6 +61,8 @@ namespace FBX {
 
 
 #define MAGIC_NODE_TAG "_$AssimpFbx$"
+#define MAGIC_NULL_TAG "_$AssimpFbxNull$"
+
 #define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
 
 	// 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 
 					// preserve the name - people might have scripts etc. that rely
 					// on specific node names.
-					bool has_name = false;
+					aiNode* name_carrier = NULL;
 					BOOST_FOREACH(aiNode* prenode, nodes_chain) {
 						if ( !strcmp(prenode->mName.C_Str(), original_name.c_str()) ) {
-							has_name = true;
+							name_carrier = prenode;
 							break;
 						}
 					}
 
-					if(!has_name) {
+					if(!name_carrier) {
 						nodes_chain.push_back(new aiNode(original_name));
+						name_carrier = nodes_chain.back();
 					}
 
 					// link all nodes in a row
@@ -247,6 +250,14 @@ private:
 						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_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)
 	{
 		// strip Model:: prefix, avoiding ambiguities (i.e. don't strip if 
@@ -1636,7 +1695,9 @@ private:
 				}
 			}
 			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);
@@ -1646,7 +1707,9 @@ private:
 			}
 		}
 		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;
 	NodeNameMap node_names;
 
+	typedef std::map<std::string, std::string> NameNameMap;
+	NameNameMap renamed_nodes;
+
 	double anim_fps;
 
 	aiScene* const out;

+ 6 - 0
code/FBXDocument.h

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

+ 16 - 0
code/FBXModel.cpp

@@ -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
 } //!Assimp