- 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
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) {
ConvertMaterial(*mat);
const Material* mat = dynamic_cast<const Material*>(ob);
if(mat) {
if (materials_converted.find(mat) == materials_converted.end()) {
ConvertMaterial(*mat);
}
}
}
}
@ -244,18 +249,60 @@ private:
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();
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
void ConvertMaterial(const Material& material)
unsigned int ConvertMaterial(const Material& material)
{
const PropertyTable& props = material.Props();
// generate empty output material
aiMaterial* out_mat = new aiMaterial();
materials.push_back(out_mat);
materials_converted.insert(&material);
aiString str;
@ -268,6 +315,8 @@ private:
// texture assignments
SetTextureProperties(out_mat,material.Textures());
return static_cast<unsigned int>(materials.size() - 1);
}
@ -475,9 +524,14 @@ private:
private:
// 0: not assigned yet, others: index is value - 1
unsigned int defaultMaterialIndex;
std::vector<aiMesh*> meshes;
std::vector<aiMaterial*> materials;
std::set<const Material*> materials_converted;
std::vector<const MeshGeometry*> sourceMeshes;
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());
if (!strncmp(obtype,"Geometry",length)) {
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)) {

View File

@ -240,7 +240,7 @@ class MeshGeometry : public Geometry
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();
public:
@ -302,10 +302,16 @@ public:
return materials;
}
/** Get per-face-vertex material assignments */
const std::vector<const Material*>& 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);
@ -336,6 +342,8 @@ private:
private:
std::vector<const Material*> materials_resolved;
// cached data arrays
std::vector<unsigned int> materials;
std::vector<aiVector3D> vertices;

View File

@ -52,6 +52,7 @@ struct ImportSettings
{
ImportSettings()
: readAllLayers(true)
, readAllMaterials()
{}
/** 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
* value for this option is true.*/
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);
// 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) {
// texture link to properties, not objects

View File

@ -58,7 +58,7 @@ namespace FBX {
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)
{
const Scope* sc = element.Compound();
@ -148,7 +148,7 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
DOMError(err,&element);
}
if(settings.readAllLayers || index == 0) {
if(doc.Settings().readAllLayers || index == 0) {
const Scope& layer = GetRequiredScope(*(*it).second);
ReadLayer(layer);
}
@ -156,6 +156,8 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
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)
{

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)
{
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)
{
return static_cast<std::string>( (Formatter::format(),prefix,
"(",TokenTypeString(tok->Type()),
"line ",tok->Line(),
" (",TokenTypeString(tok->Type()),
", line ",tok->Line(),
", col ",tok->Column(),") ",
text) );
}