diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 0d288a8d4..be2954686 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -70,20 +70,7 @@ public: : out(out) , doc(doc) { - //ConvertRootNode(); - - // hack to process all meshes - BOOST_FOREACH(const ObjectMap::value_type& v,doc.Objects()) { - - const Object* ob = v.second->Get(); - if(!ob) { - continue; - } - const MeshGeometry* geo = dynamic_cast(ob); - if(geo) { - ConvertMesh(*geo); - } - } + ConvertRootNode(); if(doc.Settings().readAllMaterials) { // unfortunately this means we have to evaluate all objects @@ -129,24 +116,112 @@ private: // 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& conns = doc.GetConnectionsByDestinationSequenced(id); + + std::vector 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(object); + + + if(model) { + aiNode* nd = new aiNode(); + nd->mName.Set(model->Name()); + nd->mParent = &parent; + + // XXX handle transformation + + ConvertModel(*model, *nd); + } + } + + if(nodes.size()) { + parent.mChildren = new aiNode*[nodes.size()](); + parent.mNumChildren = static_cast(nodes.size()); + + std::swap_ranges(nodes.begin(),nodes.end(),parent.mChildren); + } + } + + + // ------------------------------------------------------------------------------------------------ + void ConvertModel(const Model& model, aiNode& nd) + { + const std::vector& geos = model.GetGeometry(); + + std::vector meshes; + meshes.reserve(geos.size()); + + BOOST_FOREACH(const Geometry* geo, geos) { + + const MeshGeometry* const mesh = dynamic_cast(geo); + if(mesh) { + const unsigned int index = ConvertMesh(*mesh, model); + if(index == 0) { + continue; + } + + meshes.push_back(index-1); + } + else { + FBXImporter::LogWarn("ignoring unrecognized geometry: " + geo->Name()); + } + } + + if(meshes.size()) { + nd.mMeshes = new unsigned int[meshes.size()](); + nd.mNumMeshes = static_cast(meshes.size()); + + std::swap_ranges(meshes.begin(),meshes.end(),nd.mMeshes); + } + } + + + // ------------------------------------------------------------------------------------------------ + // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed + unsigned int ConvertMesh(const MeshGeometry& mesh, const Model& model) + { + MeshMap::const_iterator it = meshes_converted.find(&mesh); + if (it != meshes_converted.end()) { + return (*it).second + 1; + } + const std::vector& vertices = mesh.GetVertices(); const std::vector& faces = mesh.GetFaceIndexCounts(); if(vertices.empty() || faces.empty()) { - return; + FBXImporter::LogWarn("ignoring empty geometry: " + mesh.Name()); + return 0; } aiMesh* out_mesh = new aiMesh(); meshes.push_back(out_mesh); - sourceMeshes.push_back(&mesh); + meshes_converted[&mesh] = static_cast(meshes.size()-1); // copy vertices out_mesh->mNumVertices = static_cast(vertices.size()); @@ -251,22 +326,32 @@ private: } const std::vector& mindices = mesh.GetMaterialIndices(); - ConvertMaterialForMesh(out_mesh,mesh,mindices.size() ? mindices[0] : 9); + ConvertMaterialForMesh(out_mesh,model,mesh,mindices.size() ? mindices[0] : 0); + + return static_cast(meshes.size()); } // ------------------------------------------------------------------------------------------------ - void ConvertMaterialForMesh(aiMesh* out, const MeshGeometry& geo, unsigned int materialIndex) + void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo, unsigned int materialIndex) { // locate source materials for this mesh - const std::vector& mats = geo.GetMaterials(); + const std::vector& mats = model.GetMaterials(); if (materialIndex >= mats.size()) { FBXImporter::LogError("material index out of bounds, ignoring"); out->mMaterialIndex = GetDefaultMaterial(); return; } - out->mMaterialIndex = ConvertMaterial(*mats[materialIndex]); + const Material* const mat = mats[materialIndex]; + MaterialMap::const_iterator it = materials_converted.find(mat); + if (it != materials_converted.end()) { + out->mMaterialIndex = (*it).second; + return; + } + + out->mMaterialIndex = ConvertMaterial(*mat); + materials_converted[mat] = out->mMaterialIndex; } @@ -301,8 +386,9 @@ private: // generate empty output material aiMaterial* out_mat = new aiMaterial(); + materials_converted[&material] = static_cast(materials.size()); + materials.push_back(out_mat); - materials_converted.insert(&material); aiString str; @@ -366,8 +452,11 @@ private: ); uvIndex = -1; - BOOST_FOREACH(const MeshGeometry* mesh,sourceMeshes) { - ai_assert(mesh); + BOOST_FOREACH(const MeshMap::value_type& v,meshes_converted) { + const MeshGeometry* const mesh = dynamic_cast (v.first); + if(!mesh) { + continue; + } const std::vector& mats = mesh->GetMaterialIndices(); if(std::find(mats.begin(),mats.end(),matIndex) == mats.end()) { @@ -386,7 +475,7 @@ private: } } if(index == -1) { - FBXImporter::LogWarn("did not found UV channel named " + uvSet + " in a mesh using this material"); + FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); continue; } @@ -398,6 +487,11 @@ private: " appears at different positions in meshes, results will be wrong"); } } + + if(uvIndex == -1) { + FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); + uvIndex = 0; + } } } @@ -530,9 +624,11 @@ private: std::vector meshes; std::vector materials; - std::set materials_converted; + typedef std::map MaterialMap; + MaterialMap materials_converted; - std::vector sourceMeshes; + typedef std::map MeshMap; + MeshMap meshes_converted; aiScene* const out; const FBX::Document& doc; diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index 9a07e1865..cd27acbab 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -413,6 +413,9 @@ const Object* LazyObject::Get() object.reset(new MeshGeometry(id,element,name,doc)); } } + else if (!strncmp(obtype,"Model",length)) { + object.reset(new Model(id,element,doc,name)); + } else if (!strncmp(obtype,"Material",length)) { object.reset(new Material(id,element,doc,name)); } @@ -603,7 +606,8 @@ void Document::ReadConnections() continue; } - if(objects.find(dest) == objects.end()) { + // dest may be 0 (root node) + if(dest && objects.find(dest) == objects.end()) { DOMWarning("destination object for connection does not exist",&el); continue; } @@ -669,7 +673,8 @@ Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, co , doc(doc) { ai_assert(doc.Objects().find(src) != doc.Objects().end()); - ai_assert(doc.Objects().find(dest) != doc.Objects().end()); + // dest may be 0 (root node) + ai_assert(!dest || doc.Objects().find(dest) != doc.Objects().end()); } diff --git a/code/FBXDocument.h b/code/FBXDocument.h index 38e3a85c9..2ec784237 100644 --- a/code/FBXDocument.h +++ b/code/FBXDocument.h @@ -57,6 +57,8 @@ namespace FBX { class PropertyTable; class Document; + class Material; + class Geometry; /** Represents a delay-parsed FBX objects. Many objects in the scene @@ -123,6 +125,54 @@ protected: }; +/** DOM base class for FBX models */ +class Model : public Object +{ +public: + + Model(uint64_t id, const Element& element, const Document& doc, const std::string& name); + ~Model(); + +public: + + const std::string& Shading() const { + return shading; + } + + const std::string& Culling() const { + return culling; + } + + const PropertyTable& Props() const { + ai_assert(props.get()); + return *props.get(); + } + + /** Get material links */ + const std::vector& GetMaterials() const { + return materials; + } + + + /** Get geometry links */ + const std::vector& GetGeometry() const { + return geometry; + } + +private: + + void ResolveLinks(const Element& element, const Document& doc); + +private: + + std::vector materials; + std::vector geometry; + + std::string shading; + std::string culling; + boost::shared_ptr props; +}; + /** DOM class for generic FBX textures */ @@ -302,16 +352,10 @@ public: return materials; } - /** Get per-face-vertex material assignments */ - const std::vector& GetMaterials() const { - return materials_resolved; - } - public: private: - void ResolveMaterialLinks(const Element& element, const Document& doc); void ReadLayer(const Scope& layer); void ReadLayerElement(const Scope& layerElement); void ReadVertexData(const std::string& type, int index, const Scope& source); @@ -342,8 +386,6 @@ private: private: - std::vector materials_resolved; - // cached data arrays std::vector materials; std::vector vertices; diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index 2b35ef137..631df06fa 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -156,8 +156,6 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin FBXImporter::LogWarn("ignoring additional geometry layers"); } } - - ResolveMaterialLinks(element,doc); } @@ -168,36 +166,6 @@ MeshGeometry::~MeshGeometry() } -// ------------------------------------------------------------------------------------------------ -void MeshGeometry::ResolveMaterialLinks(const Element& element, const Document& doc) -{ - // resolve material - const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID()); - - materials_resolved.reserve(conns.size()); - BOOST_FOREACH(const Connection* con, conns) { - - // material links should be Object-Object connections - if (con->PropertyName().length()) { - continue; - } - - const Object* const ob = con->SourceObject(); - if(!ob) { - DOMWarning("failed to read source object for material link, ignoring",&element); - continue; - } - - const Material* const mat = dynamic_cast(ob); - if(!mat) { - DOMWarning("source object for material link is not a material, ignoring",&element); - continue; - } - - materials_resolved.push_back(mat); - } -} - // ------------------------------------------------------------------------------------------------ void MeshGeometry::ReadLayer(const Scope& layer) diff --git a/workspaces/vc9/assimp.vcproj b/workspaces/vc9/assimp.vcproj index 352957caf..8df1ee8f2 100644 --- a/workspaces/vc9/assimp.vcproj +++ b/workspaces/vc9/assimp.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2267,6 +2271,14 @@ UsePrecompiledHeader="0" /> + + + @@ -2291,6 +2303,14 @@ UsePrecompiledHeader="0" /> + + + @@ -2315,22 +2335,6 @@ UsePrecompiledHeader="0" /> - - - - - - @@ -2465,6 +2469,14 @@ PrecompiledHeaderThrough="AssimpPCH.h" /> + + + @@ -2492,6 +2504,14 @@ PrecompiledHeaderThrough="AssimpPCH.h" /> + + + @@ -2519,22 +2539,6 @@ PrecompiledHeaderThrough="AssimpPCH.h" /> - - - - - - @@ -2842,62 +2846,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -2906,6 +2854,14 @@ UsePrecompiledHeader="0" /> + + + @@ -2914,6 +2870,14 @@ UsePrecompiledHeader="0" /> + + + @@ -2922,6 +2886,14 @@ UsePrecompiledHeader="0" /> + + + @@ -2930,6 +2902,14 @@ UsePrecompiledHeader="0" /> + + + @@ -2938,6 +2918,14 @@ UsePrecompiledHeader="0" /> + + + @@ -2946,6 +2934,14 @@ UsePrecompiledHeader="0" /> + + + @@ -2954,6 +2950,14 @@ UsePrecompiledHeader="0" /> + + + @@ -2986,62 +2990,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -3050,6 +2998,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3058,6 +3014,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3066,6 +3030,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3074,6 +3046,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3082,6 +3062,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3090,6 +3078,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3098,6 +3094,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3118,62 +3122,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -3182,6 +3130,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3190,6 +3146,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3198,6 +3162,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3206,6 +3178,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3214,6 +3194,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3222,6 +3210,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3230,6 +3226,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3258,62 +3262,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -3322,6 +3270,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3330,6 +3286,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3338,6 +3302,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3346,6 +3318,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3354,6 +3334,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3362,6 +3350,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3370,6 +3366,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3398,62 +3402,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -3462,6 +3410,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3470,6 +3426,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3478,6 +3442,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3486,6 +3458,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3494,6 +3474,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3502,6 +3490,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3510,6 +3506,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3534,62 +3538,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -3598,6 +3546,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3606,6 +3562,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3614,6 +3578,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3622,6 +3594,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3630,6 +3610,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3638,6 +3626,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3646,6 +3642,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3670,62 +3674,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -3734,6 +3682,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3742,6 +3698,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3750,6 +3714,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3758,6 +3730,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3766,6 +3746,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3774,6 +3762,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3782,6 +3778,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3806,62 +3810,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -3870,6 +3818,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3878,6 +3834,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3886,6 +3850,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3894,6 +3866,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3902,6 +3882,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3910,6 +3898,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3918,6 +3914,14 @@ UsePrecompiledHeader="0" /> + + + @@ -3954,62 +3958,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -4018,6 +3966,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4026,6 +3982,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4034,6 +3998,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4042,6 +4014,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4050,6 +4030,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4058,6 +4046,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4066,6 +4062,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4094,62 +4098,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -4158,6 +4106,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4166,6 +4122,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4174,6 +4138,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4182,6 +4154,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4190,6 +4170,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4198,6 +4186,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4206,6 +4202,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4234,62 +4238,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -4298,6 +4246,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4306,6 +4262,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4314,6 +4278,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4322,6 +4294,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4330,6 +4310,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4338,6 +4326,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4346,6 +4342,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4370,62 +4374,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -4434,6 +4382,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4442,6 +4398,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4450,6 +4414,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4458,6 +4430,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4466,6 +4446,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4474,6 +4462,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4482,6 +4478,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4510,62 +4514,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -4574,6 +4522,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4582,6 +4538,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4590,6 +4554,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4598,6 +4570,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4606,6 +4586,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4614,6 +4602,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4622,6 +4618,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4646,62 +4650,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -4710,6 +4658,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4718,6 +4674,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4726,6 +4690,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4734,6 +4706,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4742,6 +4722,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4750,6 +4738,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4758,6 +4754,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4782,62 +4786,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -4846,6 +4794,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4854,6 +4810,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4862,6 +4826,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4870,6 +4842,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4878,6 +4858,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4886,6 +4874,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4894,6 +4890,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4926,62 +4930,6 @@ UsePrecompiledHeader="0" /> - - - - - - - - - - - - - - - - - - - - - @@ -4990,6 +4938,14 @@ UsePrecompiledHeader="0" /> + + + @@ -4998,6 +4954,14 @@ UsePrecompiledHeader="0" /> + + + @@ -5006,6 +4970,14 @@ UsePrecompiledHeader="0" /> + + + @@ -5014,6 +4986,14 @@ UsePrecompiledHeader="0" /> + + + @@ -5022,6 +5002,14 @@ UsePrecompiledHeader="0" /> + + + @@ -5030,6 +5018,14 @@ UsePrecompiledHeader="0" /> + + + @@ -5038,6 +5034,14 @@ UsePrecompiledHeader="0" /> + + +