- fbx: work on resolving material links.
parent
2f5ec6f136
commit
17629f1ff1
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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) );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue