- fbx: support ByPolygon mapping for materials, refactor code to read material indices.

pull/14/head
Alexander Gessler 2012-06-28 17:13:13 +02:00
parent e821988c64
commit 3f10314656
2 changed files with 102 additions and 25 deletions

View File

@ -262,7 +262,7 @@ void ReadVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read an array of ints // read an array of ints
void ReadIntDataArray(std::vector<int>& out, const Element& el) void ReadVectorDataArray(std::vector<int>& out, const Element& el)
{ {
out.clear(); out.clear();
const TokenList& tok = el.Tokens(); const TokenList& tok = el.Tokens();
@ -279,6 +279,30 @@ void ReadIntDataArray(std::vector<int>& out, const Element& el)
out.push_back(ival); out.push_back(ival);
} }
} }
// ------------------------------------------------------------------------------------------------
// read an array of uints
void ReadVectorDataArray(std::vector<unsigned int>& out, const Element& el)
{
out.clear();
const TokenList& tok = el.Tokens();
const size_t dim = ParseTokenAsDim(*tok[0]);
// see notes in ReadVectorDataArray()
out.reserve(dim);
const Scope& scope = GetRequiredScope(el);
const Element& a = GetRequiredElement(scope,"a",&el);
for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
const int ival = ParseTokenAsInt(**it++);
if(ival < 0) {
DOMError("encountered negative integer index");
}
out.push_back(static_cast<unsigned int>(ival));
}
}
} // end anon. } // end anon.
@ -387,7 +411,7 @@ MeshGeometry::MeshGeometry(const Element& element, const std::string& name)
ReadVectorDataArray(tempVerts,Vertices); ReadVectorDataArray(tempVerts,Vertices);
std::vector<int> tempFaces; std::vector<int> tempFaces;
ReadIntDataArray(tempFaces,PolygonVertexIndex); ReadVectorDataArray(tempFaces,PolygonVertexIndex);
vertices.reserve(tempFaces.size()); vertices.reserve(tempFaces.size());
faces.reserve(tempFaces.size() / 3); faces.reserve(tempFaces.size() / 3);
@ -515,32 +539,34 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
return; return;
} }
ReadVertexDataUV(uvs[index],source,MappingInformationType,ReferenceInformationType); ReadVertexDataUV(uvs[index],source,
MappingInformationType,
ReferenceInformationType
);
} }
else if (type == "LayerElementMaterial") { else if (type == "LayerElementMaterial") {
ReadVertexDataMaterials(materials,source,
materials.resize(vertices.size()); MappingInformationType,
ReferenceInformationType
std::vector<int> tempMaterials; );
ReadIntDataArray(tempMaterials,GetRequiredElement(source,"Materials"));
if (MappingInformationType == "AllSame") {
// easy - same material for all faces
materials.assign(vertices.size(),tempMaterials[0]);
}
else {
FBXImporter::LogError(Formatter::format("ignoring material assignments, unrecognized access type: ")
<< MappingInformationType << "," << ReferenceInformationType);
}
} }
else if (type == "LayerElementNormal") { else if (type == "LayerElementNormal") {
ReadVertexDataNormals(normals,source,MappingInformationType,ReferenceInformationType); ReadVertexDataNormals(normals,source,
MappingInformationType,
ReferenceInformationType
);
} }
else if (type == "LayerElementTangent") { else if (type == "LayerElementTangent") {
ReadVertexDataTangents(tangents,source,MappingInformationType,ReferenceInformationType); ReadVertexDataTangents(tangents,source,
MappingInformationType,
ReferenceInformationType
);
} }
else if (type == "LayerElementBinormal") { else if (type == "LayerElementBinormal") {
ReadVertexDataBinormals(binormals,source,MappingInformationType,ReferenceInformationType); ReadVertexDataBinormals(binormals,source,
MappingInformationType,
ReferenceInformationType
);
} }
else if (type == "LayerElementColor") { else if (type == "LayerElementColor") {
if(index >= AI_MAX_NUMBER_OF_COLOR_SETS) { if(index >= AI_MAX_NUMBER_OF_COLOR_SETS) {
@ -549,7 +575,10 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
return; return;
} }
ReadVertexDataColors(colors[index],source,MappingInformationType,ReferenceInformationType); ReadVertexDataColors(colors[index],source,
MappingInformationType,
ReferenceInformationType
);
} }
} }
@ -588,7 +617,7 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
data_out.resize(vertex_count); data_out.resize(vertex_count);
std::vector<int> uvIndices; std::vector<int> uvIndices;
ReadIntDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); ReadVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
for (size_t i = 0, e = uvIndices.size(); i < e; ++i) { for (size_t i = 0, e = uvIndices.size(); i < e; ++i) {
@ -603,7 +632,9 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
} }
else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "Direct") { else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "Direct") {
if (tempUV.size() != vertex_count) { if (tempUV.size() != vertex_count) {
FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping"); FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
<< tempUV.size() << ", expected " << vertex_count
);
return; return;
} }
@ -613,7 +644,7 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
data_out.resize(vertex_count); data_out.resize(vertex_count);
std::vector<int> uvIndices; std::vector<int> uvIndices;
ReadIntDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); ReadVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
if (uvIndices.size() != vertex_count) { if (uvIndices.size() != vertex_count) {
FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping"); FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping");
@ -630,7 +661,7 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
} }
} }
else { else {
FBXImporter::LogError(Formatter::format("ignoring vertex data channel, unrecognized access type: ") FBXImporter::LogError(Formatter::format("ignoring vertex data channel, access type not implemented: ")
<< MappingInformationType << "," << ReferenceInformationType); << MappingInformationType << "," << ReferenceInformationType);
} }
} }
@ -709,6 +740,48 @@ void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_ou
mappings); mappings);
} }
// ------------------------------------------------------------------------------------------------
void MeshGeometry::ReadVertexDataMaterials(std::vector<unsigned int>& materials_out, const Scope& source,
const std::string& MappingInformationType,
const std::string& ReferenceInformationType)
{
const size_t face_count = faces.size();
ai_assert(face_count);
// materials are handled separately. First of all, they are assigned per-face
// and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect
// has a slightly different meaning for materials.
ReadVectorDataArray(materials_out,GetRequiredElement(source,"Materials"));
if (MappingInformationType == "AllSame") {
// easy - same material for all faces
if (materials_out.empty()) {
FBXImporter::LogError(Formatter::format("expected material index, ignoring"));
return;
}
else if (materials_out.size() > 1) {
FBXImporter::LogWarn(Formatter::format("expected only a single material index, ignoring all except the first one"));
materials_out.clear();
}
materials.assign(vertices.size(),materials_out[0]);
}
else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
materials.resize(face_count);
if(materials_out.size() != face_count) {
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
<< materials_out.size() << ", expected " << face_count
);
return;
}
}
else {
FBXImporter::LogError(Formatter::format("ignoring material assignments, access type not implemented: ")
<< MappingInformationType << "," << ReferenceInformationType);
}
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Document::Document(const Parser& parser) Document::Document(const Parser& parser)

View File

@ -198,6 +198,10 @@ private:
const std::string& MappingInformationType, const std::string& MappingInformationType,
const std::string& ReferenceInformationType); const std::string& ReferenceInformationType);
void ReadVertexDataMaterials(std::vector<unsigned int>& materials_out, const Scope& source,
const std::string& MappingInformationType,
const std::string& ReferenceInformationType);
private: private:
// cached data arrays // cached data arrays