diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index d49a2a17d..0886edc3c 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -262,7 +262,7 @@ void ReadVectorDataArray(std::vector& out, const Element& el) // ------------------------------------------------------------------------------------------------ // read an array of ints -void ReadIntDataArray(std::vector& out, const Element& el) +void ReadVectorDataArray(std::vector& out, const Element& el) { out.clear(); const TokenList& tok = el.Tokens(); @@ -279,6 +279,30 @@ void ReadIntDataArray(std::vector& out, const Element& el) out.push_back(ival); } } + + +// ------------------------------------------------------------------------------------------------ +// read an array of uints +void ReadVectorDataArray(std::vector& 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(ival)); + } +} } // end anon. @@ -387,7 +411,7 @@ MeshGeometry::MeshGeometry(const Element& element, const std::string& name) ReadVectorDataArray(tempVerts,Vertices); std::vector tempFaces; - ReadIntDataArray(tempFaces,PolygonVertexIndex); + ReadVectorDataArray(tempFaces,PolygonVertexIndex); vertices.reserve(tempFaces.size()); faces.reserve(tempFaces.size() / 3); @@ -515,32 +539,34 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop return; } - ReadVertexDataUV(uvs[index],source,MappingInformationType,ReferenceInformationType); + ReadVertexDataUV(uvs[index],source, + MappingInformationType, + ReferenceInformationType + ); } else if (type == "LayerElementMaterial") { - - materials.resize(vertices.size()); - - std::vector 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); - } + ReadVertexDataMaterials(materials,source, + MappingInformationType, + ReferenceInformationType + ); } else if (type == "LayerElementNormal") { - ReadVertexDataNormals(normals,source,MappingInformationType,ReferenceInformationType); + ReadVertexDataNormals(normals,source, + MappingInformationType, + ReferenceInformationType + ); } else if (type == "LayerElementTangent") { - ReadVertexDataTangents(tangents,source,MappingInformationType,ReferenceInformationType); + ReadVertexDataTangents(tangents,source, + MappingInformationType, + ReferenceInformationType + ); } else if (type == "LayerElementBinormal") { - ReadVertexDataBinormals(binormals,source,MappingInformationType,ReferenceInformationType); + ReadVertexDataBinormals(binormals,source, + MappingInformationType, + ReferenceInformationType + ); } else if (type == "LayerElementColor") { if(index >= AI_MAX_NUMBER_OF_COLOR_SETS) { @@ -549,7 +575,10 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop return; } - ReadVertexDataColors(colors[index],source,MappingInformationType,ReferenceInformationType); + ReadVertexDataColors(colors[index],source, + MappingInformationType, + ReferenceInformationType + ); } } @@ -588,7 +617,7 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, data_out.resize(vertex_count); std::vector uvIndices; - ReadIntDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); + ReadVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); for (size_t i = 0, e = uvIndices.size(); i < e; ++i) { @@ -603,7 +632,9 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, } else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "Direct") { 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; } @@ -613,7 +644,7 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, data_out.resize(vertex_count); std::vector uvIndices; - ReadIntDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); + ReadVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); if (uvIndices.size() != vertex_count) { FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping"); @@ -630,7 +661,7 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, } } 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); } } @@ -709,6 +740,48 @@ void MeshGeometry::ReadVertexDataBinormals(std::vector& binormals_ou mappings); } +// ------------------------------------------------------------------------------------------------ +void MeshGeometry::ReadVertexDataMaterials(std::vector& 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) diff --git a/code/FBXDocument.h b/code/FBXDocument.h index cb6192f70..cddbfd99d 100644 --- a/code/FBXDocument.h +++ b/code/FBXDocument.h @@ -198,6 +198,10 @@ private: const std::string& MappingInformationType, const std::string& ReferenceInformationType); + void ReadVertexDataMaterials(std::vector& materials_out, const Scope& source, + const std::string& MappingInformationType, + const std::string& ReferenceInformationType); + private: // cached data arrays