From 9c3624d0d970f95b1c60f71d7a59031b5e806a6b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 7 Feb 2014 14:25:48 -0800 Subject: [PATCH] Fix for texture on jellyrob_blue_blender.fbx; apparently you can map textures, as well as materials, by polygon. Closes #1844. --- interface/src/renderer/FBXReader.cpp | 102 ++++++++++++++++++--------- 1 file changed, 68 insertions(+), 34 deletions(-) diff --git a/interface/src/renderer/FBXReader.cpp b/interface/src/renderer/FBXReader.cpp index 5a27b51b70..e4dfd7dd84 100644 --- a/interface/src/renderer/FBXReader.cpp +++ b/interface/src/renderer/FBXReader.cpp @@ -601,6 +601,7 @@ public: FBXMesh mesh; QMultiHash newIndices; QVector > blendshapeIndexMaps; + QVector > partMaterialTextures; }; class MeshData { @@ -667,6 +668,7 @@ void appendIndex(MeshData& data, QVector& indices, int index) { ExtractedMesh extractMesh(const FBXNode& object) { MeshData data; QVector materials; + QVector textures; foreach (const FBXNode& child, object.children) { if (child.name == "Vertices") { data.vertices = createVec3Vector(getDoubleVector(child.properties, 0)); @@ -703,19 +705,32 @@ ExtractedMesh extractMesh(const FBXNode& object) { materials = getIntVector(subdata.properties, 0); } } + } else if (child.name == "LayerElementTexture") { + foreach (const FBXNode& subdata, child.children) { + if (subdata.name == "TextureId") { + textures = getIntVector(subdata.properties, 0); + } + } } } // convert the polygons to quads and triangles int polygonIndex = 0; + QHash, int> materialTextureParts; for (int beginIndex = 0; beginIndex < data.polygonIndices.size(); polygonIndex++) { int endIndex = beginIndex; while (data.polygonIndices.at(endIndex++) >= 0); - int materialIndex = (polygonIndex < materials.size()) ? materials.at(polygonIndex) : 0; - data.extracted.mesh.parts.resize(max(data.extracted.mesh.parts.size(), materialIndex + 1)); - FBXMeshPart& part = data.extracted.mesh.parts[materialIndex]; - + QPair materialTexture((polygonIndex < materials.size()) ? materials.at(polygonIndex) : 0, + (polygonIndex < textures.size()) ? textures.at(polygonIndex) : 0); + int& partIndex = materialTextureParts[materialTexture]; + if (partIndex == 0) { + data.extracted.partMaterialTextures.append(materialTexture); + data.extracted.mesh.parts.resize(data.extracted.mesh.parts.size() + 1); + partIndex = data.extracted.mesh.parts.size(); + } + FBXMeshPart& part = data.extracted.mesh.parts[partIndex - 1]; + if (endIndex - beginIndex == 4) { appendIndex(data, part.quadIndices, beginIndex++); appendIndex(data, part.quadIndices, beginIndex++); @@ -1265,41 +1280,60 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) glm::mat4 modelTransform = getGlobalTransform(parentMap, models, modelID); // look for textures, material properties - int partIndex = extracted.mesh.parts.size() - 1; + int materialIndex = 0; + int textureIndex = 0; bool generateTangents = false; - foreach (const QString& childID, childMap.values(modelID)) { - if (partIndex < 0) { - break; - } - FBXMeshPart& part = extracted.mesh.parts[partIndex]; - if (textureFilenames.contains(childID)) { - part.diffuseFilename = textureFilenames.value(childID); - continue; - } - if (!materials.contains(childID)) { - continue; - } - Material material = materials.value(childID); - part.diffuseColor = material.diffuse; - part.specularColor = material.specular; - part.shininess = material.shininess; - QString diffuseTextureID = diffuseTextures.value(childID); - if (!diffuseTextureID.isNull()) { - part.diffuseFilename = textureFilenames.value(diffuseTextureID); + QList children = childMap.values(modelID); + for (int i = children.size() - 1; i >= 0; i--) { + const QString& childID = children.at(i); + if (materials.contains(childID)) { + Material material = materials.value(childID); + + QByteArray diffuseFilename; + QString diffuseTextureID = diffuseTextures.value(childID); + if (!diffuseTextureID.isNull()) { + diffuseFilename = textureFilenames.value(diffuseTextureID); - // FBX files generated by 3DSMax have an intermediate texture parent, apparently - foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) { - if (textureFilenames.contains(childTextureID)) { - part.diffuseFilename = textureFilenames.value(childTextureID); + // FBX files generated by 3DSMax have an intermediate texture parent, apparently + foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) { + if (textureFilenames.contains(childTextureID)) { + diffuseFilename = textureFilenames.value(childTextureID); + } } } + + QByteArray normalFilename; + QString bumpTextureID = bumpTextures.value(childID); + if (!bumpTextureID.isNull()) { + normalFilename = textureFilenames.value(bumpTextureID); + generateTangents = true; + } + + for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { + if (extracted.partMaterialTextures.at(j).first == materialIndex) { + FBXMeshPart& part = extracted.mesh.parts[j]; + part.diffuseColor = material.diffuse; + part.specularColor = material.specular; + part.shininess = material.shininess; + if (!diffuseFilename.isNull()) { + part.diffuseFilename = diffuseFilename; + } + if (!normalFilename.isNull()) { + part.normalFilename = normalFilename; + } + } + } + materialIndex++; + + } else if (textureFilenames.contains(childID)) { + QByteArray filename = textureFilenames.value(childID); + for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { + if (extracted.partMaterialTextures.at(j).second == textureIndex) { + extracted.mesh.parts[j].diffuseFilename = filename; + } + } + textureIndex++; } - QString bumpTextureID = bumpTextures.value(childID); - if (!bumpTextureID.isNull()) { - part.normalFilename = textureFilenames.value(bumpTextureID); - generateTangents = true; - } - partIndex--; } // if we have a normal map (and texture coordinates), we must compute tangents