- fbx: work on resolving material links.

pull/14/head
Alexander Gessler 2012-07-04 15:07:57 +02:00
parent 2f5ec6f136
commit 17629f1ff1
7 changed files with 120 additions and 18 deletions

View File

@ -85,17 +85,22 @@ public:
} }
} }
// hack to process all materials if(doc.Settings().readAllMaterials) {
BOOST_FOREACH(const ObjectMap::value_type& v,doc.Objects()) { // unfortunately this means we have to evaluate all objects
BOOST_FOREACH(const ObjectMap::value_type& v,doc.Objects()) {
const Object* ob = v.second->Get(); const Object* ob = v.second->Get();
if(!ob) { if(!ob) {
continue; continue;
} }
const Material* mat = dynamic_cast<const Material*>(ob); const Material* mat = dynamic_cast<const Material*>(ob);
if(mat) { if(mat) {
ConvertMaterial(*mat);
if (materials_converted.find(mat) == materials_converted.end()) {
ConvertMaterial(*mat);
}
}
} }
} }
@ -244,18 +249,60 @@ private:
out_mesh->mColors[i] = new aiColor4D[vertices.size()]; out_mesh->mColors[i] = new aiColor4D[vertices.size()];
std::copy(colors.begin(),colors.end(),out_mesh->mColors[i]); std::copy(colors.begin(),colors.end(),out_mesh->mColors[i]);
} }
const std::vector<unsigned int>& mindices = mesh.GetMaterialIndices();
ConvertMaterialForMesh(out_mesh,mesh,mindices.size() ? mindices[0] : 9);
}
// ------------------------------------------------------------------------------------------------
void ConvertMaterialForMesh(aiMesh* out, const MeshGeometry& geo, unsigned int materialIndex)
{
// locate source materials for this mesh
const std::vector<const Material*>& mats = geo.GetMaterials();
if (materialIndex >= mats.size()) {
FBXImporter::LogError("material index out of bounds, ignoring");
out->mMaterialIndex = GetDefaultMaterial();
return;
}
out->mMaterialIndex = ConvertMaterial(*mats[materialIndex]);
}
// ------------------------------------------------------------------------------------------------
unsigned int GetDefaultMaterial()
{
if (defaultMaterialIndex) {
return defaultMaterialIndex - 1;
}
aiMaterial* out_mat = new aiMaterial();
materials.push_back(out_mat);
const aiColor3D diffuse = aiColor3D(0.8f,0.8f,0.8f);
out_mat->AddProperty(&diffuse,1,AI_MATKEY_COLOR_DIFFUSE);
aiString s;
s.Set(AI_DEFAULT_MATERIAL_NAME);
out_mat->AddProperty(&s,AI_MATKEY_NAME);
defaultMaterialIndex = static_cast<unsigned int>(materials.size());
return defaultMaterialIndex - 1;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Material -> aiMaterial // Material -> aiMaterial
void ConvertMaterial(const Material& material) unsigned int ConvertMaterial(const Material& material)
{ {
const PropertyTable& props = material.Props(); const PropertyTable& props = material.Props();
// generate empty output material // generate empty output material
aiMaterial* out_mat = new aiMaterial(); aiMaterial* out_mat = new aiMaterial();
materials.push_back(out_mat); materials.push_back(out_mat);
materials_converted.insert(&material);
aiString str; aiString str;
@ -268,6 +315,8 @@ private:
// texture assignments // texture assignments
SetTextureProperties(out_mat,material.Textures()); SetTextureProperties(out_mat,material.Textures());
return static_cast<unsigned int>(materials.size() - 1);
} }
@ -475,9 +524,14 @@ private:
private: private:
// 0: not assigned yet, others: index is value - 1
unsigned int defaultMaterialIndex;
std::vector<aiMesh*> meshes; std::vector<aiMesh*> meshes;
std::vector<aiMaterial*> materials; std::vector<aiMaterial*> materials;
std::set<const Material*> materials_converted;
std::vector<const MeshGeometry*> sourceMeshes; std::vector<const MeshGeometry*> sourceMeshes;
aiScene* const out; aiScene* const out;

View File

@ -410,7 +410,7 @@ const Object* LazyObject::Get()
const size_t length = static_cast<size_t>(key.end()-key.begin()); const size_t length = static_cast<size_t>(key.end()-key.begin());
if (!strncmp(obtype,"Geometry",length)) { if (!strncmp(obtype,"Geometry",length)) {
if (!strcmp(classtag.c_str(),"Mesh")) { if (!strcmp(classtag.c_str(),"Mesh")) {
object.reset(new MeshGeometry(id,element,name,doc.Settings())); object.reset(new MeshGeometry(id,element,name,doc));
} }
} }
else if (!strncmp(obtype,"Material",length)) { else if (!strncmp(obtype,"Material",length)) {

View File

@ -240,7 +240,7 @@ class MeshGeometry : public Geometry
public: public:
MeshGeometry(uint64_t id, const Element& element, const std::string& name, const ImportSettings& settings); MeshGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc);
~MeshGeometry(); ~MeshGeometry();
public: public:
@ -302,10 +302,16 @@ public:
return materials; return materials;
} }
/** Get per-face-vertex material assignments */
const std::vector<const Material*>& GetMaterials() const {
return materials_resolved;
}
public: public:
private: private:
void ResolveMaterialLinks(const Element& element, const Document& doc);
void ReadLayer(const Scope& layer); void ReadLayer(const Scope& layer);
void ReadLayerElement(const Scope& layerElement); void ReadLayerElement(const Scope& layerElement);
void ReadVertexData(const std::string& type, int index, const Scope& source); void ReadVertexData(const std::string& type, int index, const Scope& source);
@ -336,6 +342,8 @@ private:
private: private:
std::vector<const Material*> materials_resolved;
// cached data arrays // cached data arrays
std::vector<unsigned int> materials; std::vector<unsigned int> materials;
std::vector<aiVector3D> vertices; std::vector<aiVector3D> vertices;

View File

@ -52,6 +52,7 @@ struct ImportSettings
{ {
ImportSettings() ImportSettings()
: readAllLayers(true) : readAllLayers(true)
, readAllMaterials()
{} {}
/** specifies whether all geometry layers are read and scanned for /** specifies whether all geometry layers are read and scanned for
@ -61,6 +62,12 @@ struct ImportSettings
* vertex data is spread among multiple layers. The default * vertex data is spread among multiple layers. The default
* value for this option is true.*/ * value for this option is true.*/
bool readAllLayers; bool readAllLayers;
/** specifies whether all materials are read, or only those that
* are referenced by at least one mesh. Reading all materials
* may make FBX reading a lot slower since all objects
* need to be processed .*/
bool readAllMaterials;
}; };

View File

@ -94,7 +94,7 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
props = GetPropertyTable(doc,templateName,element,sc); props = GetPropertyTable(doc,templateName,element,sc);
// resolve texture links // resolve texture links
const std::vector<const Connection*> conns = doc.GetConnectionsByDestinationSequenced(ID()); const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
BOOST_FOREACH(const Connection* con, conns) { BOOST_FOREACH(const Connection* con, conns) {
// texture link to properties, not objects // texture link to properties, not objects

View File

@ -58,7 +58,7 @@ namespace FBX {
using namespace Util; using namespace Util;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::string& name, const ImportSettings& settings) MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
: Geometry(id, element,name) : Geometry(id, element,name)
{ {
const Scope* sc = element.Compound(); const Scope* sc = element.Compound();
@ -148,7 +148,7 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
DOMError(err,&element); DOMError(err,&element);
} }
if(settings.readAllLayers || index == 0) { if(doc.Settings().readAllLayers || index == 0) {
const Scope& layer = GetRequiredScope(*(*it).second); const Scope& layer = GetRequiredScope(*(*it).second);
ReadLayer(layer); ReadLayer(layer);
} }
@ -156,6 +156,8 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
FBXImporter::LogWarn("ignoring additional geometry layers"); FBXImporter::LogWarn("ignoring additional geometry layers");
} }
} }
ResolveMaterialLinks(element,doc);
} }
@ -166,6 +168,37 @@ MeshGeometry::~MeshGeometry()
} }
// ------------------------------------------------------------------------------------------------
void MeshGeometry::ResolveMaterialLinks(const Element& element, const Document& doc)
{
// resolve material
const std::vector<const Connection*>& 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<const Material*>(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) void MeshGeometry::ReadLayer(const Scope& layer)
{ {

View File

@ -82,15 +82,15 @@ const char* TokenTypeString(TokenType t)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string AddLineAndColumn(const std::string& prefix, const std::string& text, unsigned int line, unsigned int column) std::string AddLineAndColumn(const std::string& prefix, const std::string& text, unsigned int line, unsigned int column)
{ {
return static_cast<std::string>( (Formatter::format(),prefix,"(line ",line,", col ",column,") ",text) ); return static_cast<std::string>( (Formatter::format(),prefix," (line ",line,", col ",column,") ",text) );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok) std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok)
{ {
return static_cast<std::string>( (Formatter::format(),prefix, return static_cast<std::string>( (Formatter::format(),prefix,
"(",TokenTypeString(tok->Type()), " (",TokenTypeString(tok->Type()),
"line ",tok->Line(), ", line ",tok->Line(),
", col ",tok->Column(),") ", ", col ",tok->Column(),") ",
text) ); text) );
} }