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