[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