[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [48653] branches/soc-2012-bratwurst/extern /assimp: - fbx: merge https://github.com/acgessler/ assimp-gsoc2012-fbx - fbx importer now reads materials, textures, models, node hierarchy and resolves fbx object links between these.

Alexander Gessler alexander.gessler at gmx.net
Thu Jul 5 17:23:39 CEST 2012


Revision: 48653
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=48653
Author:   aramis_acg
Date:     2012-07-05 15:23:39 +0000 (Thu, 05 Jul 2012)
Log Message:
-----------
- fbx: merge https://github.com/acgessler/assimp-gsoc2012-fbx - fbx importer now reads materials, textures, models, node hierarchy and resolves fbx object links between these. Conversion code now handles multi-material meshes, also support multiple UV channels. Lots of bugfixes. See git commit log for a full changelist.

Modified Paths:
--------------
    branches/soc-2012-bratwurst/extern/assimp/CMakeLists.txt
    branches/soc-2012-bratwurst/extern/assimp/code/FBXConverter.cpp
    branches/soc-2012-bratwurst/extern/assimp/code/FBXDocument.cpp
    branches/soc-2012-bratwurst/extern/assimp/code/FBXDocument.h
    branches/soc-2012-bratwurst/extern/assimp/code/FBXImportSettings.h
    branches/soc-2012-bratwurst/extern/assimp/code/FBXUtil.cpp

Added Paths:
-----------
    branches/soc-2012-bratwurst/extern/assimp/code/FBXDocumentUtil.h
    branches/soc-2012-bratwurst/extern/assimp/code/FBXMaterial.cpp
    branches/soc-2012-bratwurst/extern/assimp/code/FBXMeshGeometry.cpp
    branches/soc-2012-bratwurst/extern/assimp/code/FBXModel.cpp
    branches/soc-2012-bratwurst/extern/assimp/code/FBXProperties.cpp
    branches/soc-2012-bratwurst/extern/assimp/code/FBXProperties.h

Modified: branches/soc-2012-bratwurst/extern/assimp/CMakeLists.txt
===================================================================
--- branches/soc-2012-bratwurst/extern/assimp/CMakeLists.txt	2012-07-05 15:09:16 UTC (rev 48652)
+++ branches/soc-2012-bratwurst/extern/assimp/CMakeLists.txt	2012-07-05 15:23:39 UTC (rev 48653)
@@ -297,6 +297,12 @@
 	code/FBXTokenizer.h
 	code/FBXUtil.cpp
 	code/FBXUtil.h
+	code/FBXDocumentUtil.h
+	code/FBXMaterial.cpp
+	code/FBXMeshGeometry.cpp
+	code/FBXModel.cpp
+	code/FBXProperties.cpp
+	code/FBXProperties.h
 )
 
 
@@ -523,6 +529,7 @@
 
 add_definitions(-DASSIMP_BUILD_NO_COLLADA_IMPORTER)
 add_definitions(-DASSIMP_BUILD_NO_BLEND_IMPORTER)
+add_definitions(-Icode/BoostWorkaround/)
 
 blender_add_lib(extern_assimp "${SRC}" "${INC}" "$(INC_SYS)")
 

Modified: branches/soc-2012-bratwurst/extern/assimp/code/FBXConverter.cpp
===================================================================
--- branches/soc-2012-bratwurst/extern/assimp/code/FBXConverter.cpp	2012-07-05 15:09:16 UTC (rev 48652)
+++ branches/soc-2012-bratwurst/extern/assimp/code/FBXConverter.cpp	2012-07-05 15:23:39 UTC (rev 48653)
@@ -38,8 +38,8 @@
 ----------------------------------------------------------------------
 */
 
-/** @file  FBXDocument.cpp
- *  @brief Implementation of the FBX DOM classes
+/** @file  FBXConverter.cpp
+ *  @brief Implementation of the FBX DOM -> aiScene converter
  */
 #include "AssimpPCH.h"
 
@@ -49,11 +49,17 @@
 #include "FBXConverter.h"
 #include "FBXDocument.h"
 #include "FBXUtil.h"
+#include "FBXProperties.h"
+#include "FBXImporter.h"
 
 namespace Assimp {
 namespace FBX {
-namespace {
 
+	using namespace Util;
+
+	// XXX vc9's debugger won't step into anonymous namespaces
+//namespace {
+
 /** Dummy class to encapsulate the conversion process */
 class Converter
 {
@@ -64,19 +70,25 @@
 		: out(out) 
 		, doc(doc)
 	{
-		//ConvertRootNode();
+		ConvertRootNode();
 
-		// hack to process all meshes
-		BOOST_FOREACH(const ObjectMap::value_type& v,doc.Objects()) {
+		if(doc.Settings().readAllMaterials) {
+			// unfortunately this means we have to evaluate all objects
+			BOOST_FOREACH(const ObjectMap::value_type& v,doc.Objects()) {
 
-			const Object* ob = v.second->Get();
-			if(!ob) {
-				continue;
+				const Object* ob = v.second->Get();
+				if(!ob) {
+					continue;
+				}
+
+				const Material* mat = dynamic_cast<const Material*>(ob);
+				if(mat) {
+
+					if (materials_converted.find(mat) == materials_converted.end()) {
+						ConvertMaterial(*mat);
+					}
+				}
 			}
-			const MeshGeometry* geo = dynamic_cast<const MeshGeometry*>(ob);
-			if(geo) {
-				ConvertMesh(*geo);
-			}
 		}
 
 		// dummy root node
@@ -94,6 +106,7 @@
 	~Converter()
 	{
 		std::for_each(meshes.begin(),meshes.end(),Util::delete_fun<aiMesh>());
+		std::for_each(materials.begin(),materials.end(),Util::delete_fun<aiMaterial>());
 	}
 
 
@@ -103,30 +116,148 @@
 	// find scene root and trigger recursive scene conversion
 	void ConvertRootNode() 
 	{
+		out->mRootNode = new aiNode();
+		out->mRootNode->mName.Set("Model::RootNode");
 
+		// root has ID 0
+		ConvertNodes(0L, *out->mRootNode);
 	}
 
 
 	// ------------------------------------------------------------------------------------------------
-	// MeshGeometry -> aiMesh
-	void ConvertMesh(const MeshGeometry& mesh)
+	// collect and assign child nodes
+	void ConvertNodes(uint64_t id, aiNode& parent)
 	{
+		const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(id);
+
+		std::vector<aiNode*> nodes;
+		nodes.reserve(conns.size());
+
+		BOOST_FOREACH(const Connection* con, conns) {
+
+			// ignore object-property links
+			if(con->PropertyName().length()) {
+				continue;
+			}
+
+			const Object* const object = con->SourceObject();
+			if(!object) {
+				FBXImporter::LogWarn("failed to convert source object for node link");
+				continue;
+			}
+
+			const Model* const model = dynamic_cast<const Model*>(object);
+
+		
+			if(model) {
+				aiNode* nd = new aiNode();
+				nd->mName.Set(model->Name());
+				nd->mParent = &parent;
+
+				// XXX handle transformation
+
+				ConvertModel(*model, *nd);
+				ConvertNodes(model->ID(), *nd);
+			}
+		}
+
+		if(nodes.size()) {
+			parent.mChildren = new aiNode*[nodes.size()]();
+			parent.mNumChildren = static_cast<unsigned int>(nodes.size());
+
+			std::swap_ranges(nodes.begin(),nodes.end(),parent.mChildren);
+		}
+	}
+
+
+	// ------------------------------------------------------------------------------------------------
+	void ConvertModel(const Model& model, aiNode& nd)
+	{
+		const std::vector<const Geometry*>& geos = model.GetGeometry();
+
+		std::vector<unsigned int> meshes;
+		meshes.reserve(geos.size());
+
+		BOOST_FOREACH(const Geometry* geo, geos) {
+
+			const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*>(geo);
+			if(mesh) {
+				std::vector<unsigned int>& indices = ConvertMesh(*mesh, model);
+
+				// mesh indices are shifted by 1 and 0 entries are failed conversions -
+				// XXX maybe log how many conversions went wrong?
+				std::remove(indices.begin(),indices.end(),0);
+				std::transform(indices.begin(),indices.end(),std::back_inserter(meshes), std::bind2nd(std::minus<unsigned int>(),1) );
+			}
+			else {
+				FBXImporter::LogWarn("ignoring unrecognized geometry: " + geo->Name());
+			}
+		}
+
+		if(meshes.size()) {
+			nd.mMeshes = new unsigned int[meshes.size()]();
+			nd.mNumMeshes = static_cast<unsigned int>(meshes.size());
+
+			std::swap_ranges(meshes.begin(),meshes.end(),nd.mMeshes);
+		}
+	}
+
+
+	// ------------------------------------------------------------------------------------------------
+	// MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
+	std::vector<unsigned int> ConvertMesh(const MeshGeometry& mesh, const Model& model)
+	{
+		std::vector<unsigned int> temp; 
+
+		MeshMap::const_iterator it = meshes_converted.find(&mesh);
+		if (it != meshes_converted.end()) {
+			temp.push_back((*it).second + 1);
+			return temp;
+		}
+
 		const std::vector<aiVector3D>& vertices = mesh.GetVertices();
 		const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts();
 		if(vertices.empty() || faces.empty()) {
-			return;
+			FBXImporter::LogWarn("ignoring empty geometry: " + mesh.Name());
+			return temp;
 		}
 
 		aiMesh* out_mesh = new aiMesh();
 		meshes.push_back(out_mesh);
 
+		meshes_converted[&mesh] = static_cast<unsigned int>(meshes.size()-1);
+
+		// one material per mesh maps easily to aiMesh. Multiple material 
+		// meshes need to be split.
+		const std::vector<unsigned int>& mindices = mesh.GetMaterialIndices();
+		if (!mindices.empty()) {
+			const unsigned int base = mindices[0];
+			BOOST_FOREACH(unsigned int index, mindices) {
+				if(index != base) {
+					return ConvertMeshMultiMaterial(out_mesh, mesh, model);
+				}
+			}
+		}
+
+		// faster codepath, just copy the data
+		temp.push_back(ConvertMeshSingleMaterial(out_mesh, mesh, model));
+		return temp;
+	}
+
+
+	// ------------------------------------------------------------------------------------------------
+	unsigned int ConvertMeshSingleMaterial(aiMesh* out_mesh, const MeshGeometry& mesh, const Model& model)	
+	{
+		const std::vector<aiVector3D>& vertices = mesh.GetVertices();
+		const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts();
+
 		// copy vertices
-		out_mesh->mNumVertices = static_cast<size_t>(vertices.size());
+		out_mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
 		out_mesh->mVertices = new aiVector3D[vertices.size()];
 		std::copy(vertices.begin(),vertices.end(),out_mesh->mVertices);
 
 		// generate dummy faces
-		out_mesh->mNumFaces = static_cast<size_t>(faces.size());
+		out_mesh->mNumFaces = static_cast<unsigned int>(faces.size());
 		aiFace* fac = out_mesh->mFaces = new aiFace[faces.size()]();
 
 		unsigned int cursor = 0;
@@ -136,18 +267,18 @@
 			f.mIndices = new unsigned int[pcount];
 			switch(pcount) 
 			{
-				case 1:
-					out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
-					break;
-				case 2:
-					out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
-					break;
-				case 3:
-					out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
-					break;
-				default:
-					out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
-					break;
+			case 1:
+				out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
+				break;
+			case 2:
+				out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+				break;
+			case 3:
+				out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+				break;
+			default:
+				out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+				break;
 			}
 			for (unsigned int i = 0; i < pcount; ++i) {
 				f.mIndices[i] = cursor++;
@@ -155,7 +286,7 @@
 		}
 
 		// copy normals
-		const std::vector<aiVector3D>& normals = mesh.GetVertices();
+		const std::vector<aiVector3D>& normals = mesh.GetNormals();
 		if(normals.size()) {
 			ai_assert(normals.size() == vertices.size());
 
@@ -221,10 +352,457 @@
 			out_mesh->mColors[i] = new aiColor4D[vertices.size()];
 			std::copy(colors.begin(),colors.end(),out_mesh->mColors[i]);
 		}
+
+		const std::vector<unsigned int>& mindices = mesh.GetMaterialIndices();
+		if(mindices.empty()) {
+			FBXImporter::LogError("no material assigned to mesh, setting default material");
+			out_mesh->mMaterialIndex = GetDefaultMaterial();
+		}
+		else {
+			ConvertMaterialForMesh(out_mesh,model,mesh,mindices[0]);
+		}
+
+		return static_cast<unsigned int>(meshes.size());
 	}
 
 
 	// ------------------------------------------------------------------------------------------------
+	std::vector<unsigned int> ConvertMeshMultiMaterial(aiMesh* out_mesh, const MeshGeometry& mesh, const Model& model)	
+	{
+		const std::vector<unsigned int>& mindices = mesh.GetMaterialIndices();
+		ai_assert(mindices.size());
+	
+		std::set<unsigned int> had;
+		std::vector<unsigned int> indices;
+
+		BOOST_FOREACH(unsigned int index, mindices) {
+			if(had.find(index) != had.end()) {
+
+				indices.push_back(ConvertMeshMultiMaterial(out_mesh, mesh, model, index));
+				had.insert(index);
+			}
+		}
+
+		return indices;
+	}
+
+
+	// ------------------------------------------------------------------------------------------------
+	unsigned int ConvertMeshMultiMaterial(aiMesh* out_mesh, const MeshGeometry& mesh, const Model& model, unsigned int index)	
+	{
+		const std::vector<unsigned int>& mindices = mesh.GetMaterialIndices();
+		ai_assert(mindices.size());
+
+		const std::vector<aiVector3D>& vertices = mesh.GetVertices();

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list