diff --git a/interface/src/renderer/FBXReader.cpp b/interface/src/renderer/FBXReader.cpp index ba898748e2..8398ba2513 100644 --- a/interface/src/renderer/FBXReader.cpp +++ b/interface/src/renderer/FBXReader.cpp @@ -41,6 +41,7 @@ template QVariant readArray(QDataStream& in) { QByteArray uncompressed = qUncompress(compressed); QDataStream uncompressedIn(uncompressed); uncompressedIn.setByteOrder(QDataStream::LittleEndian); + uncompressedIn.setVersion(QDataStream::Qt_4_5); // for single/double precision switch for (int i = 0; i < arrayLength; i++) { T value; uncompressedIn >> value; @@ -132,7 +133,7 @@ FBXNode parseFBXNode(QDataStream& in) { if (endOffset < MIN_VALID_OFFSET || nameLength == 0) { // use a null name to indicate a null node return node; - } + } node.name = in.device()->read(nameLength); for (int i = 0; i < propertyCount; i++) { @@ -155,6 +156,7 @@ FBXNode parseFBXNode(QDataStream& in) { FBXNode parseFBX(QIODevice* device) { QDataStream in(device); in.setByteOrder(QDataStream::LittleEndian); + in.setVersion(QDataStream::Qt_4_5); // for single/double precision switch // see http://code.blender.org/index.php/2013/08/fbx-binary-file-format-specification/ for an explanation // of the FBX format @@ -258,18 +260,23 @@ QHash createBlendshapeMap() { } FBXGeometry extractFBXGeometry(const FBXNode& node) { - FBXGeometry geometry; + QVector blendshapes; + QHash meshMap; + qint64 blendshapeId = 0; + QHash parentMap; foreach (const FBXNode& child, node.children) { if (child.name == "Objects") { - foreach (const FBXNode& object, child.children) { + foreach (const FBXNode& object, child.children) { if (object.name == "Geometry") { if (object.properties.at(2) == "Mesh") { + FBXGeometry mesh; + QVector vertices; QVector polygonIndices; foreach (const FBXNode& data, object.children) { if (data.name == "Vertices") { - geometry.vertices = createVec3Vector(data.properties.at(0).value >()); + mesh.vertices = createVec3Vector(data.properties.at(0).value >()); } else if (data.name == "PolygonVertexIndex") { polygonIndices = data.properties.at(0).value >(); @@ -277,7 +284,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node) { } else if (data.name == "LayerElementNormal") { foreach (const FBXNode& subdata, data.children) { if (subdata.name == "Normals") { - geometry.normals = createVec3Vector( + mesh.normals = createVec3Vector( subdata.properties.at(0).value >()); } } @@ -290,25 +297,26 @@ FBXGeometry extractFBXGeometry(const FBXNode& node) { while (*endIndex++ >= 0); if (endIndex - beginIndex == 4) { - geometry.quadIndices.append(*beginIndex++); - geometry.quadIndices.append(*beginIndex++); - geometry.quadIndices.append(*beginIndex++); - geometry.quadIndices.append(-*beginIndex++ - 1); + mesh.quadIndices.append(*beginIndex++); + mesh.quadIndices.append(*beginIndex++); + mesh.quadIndices.append(*beginIndex++); + mesh.quadIndices.append(-*beginIndex++ - 1); } else { for (const int* nextIndex = beginIndex + 1;; ) { - geometry.triangleIndices.append(*beginIndex); - geometry.triangleIndices.append(*nextIndex++); + mesh.triangleIndices.append(*beginIndex); + mesh.triangleIndices.append(*nextIndex++); if (*nextIndex >= 0) { - geometry.triangleIndices.append(*nextIndex); + mesh.triangleIndices.append(*nextIndex); } else { - geometry.triangleIndices.append(-*nextIndex - 1); + mesh.triangleIndices.append(-*nextIndex - 1); break; } } beginIndex = endIndex; } } + meshMap.insert(object.properties.at(0).value(), mesh); } else { // object.properties.at(2) == "Shape" FBXBlendshape blendshape; @@ -328,14 +336,31 @@ FBXGeometry extractFBXGeometry(const FBXNode& node) { QByteArray name = object.properties.at(1).toByteArray(); static QHash blendshapeMap = createBlendshapeMap(); int index = blendshapeMap.value(name.left(name.indexOf('\0'))); - geometry.blendshapes.resize(qMax(geometry.blendshapes.size(), index + 1)); - geometry.blendshapes[index] = blendshape; + blendshapes.resize(qMax(blendshapes.size(), index + 1)); + blendshapes[index] = blendshape; } - } + } else if (object.name == "Deformer" && object.properties.at(2) == "BlendShape") { + blendshapeId = object.properties.at(0).value(); + } + } + } else if (child.name == "Connections") { + foreach (const FBXNode& connection, child.children) { + if (connection.name == "C") { + parentMap.insert(connection.properties.at(1).value(), connection.properties.at(2).value()); + } } } } + // get the mesh that owns the blendshape + FBXGeometry geometry; + if (meshMap.size() == 1) { + geometry = *meshMap.begin(); + } else { + geometry = meshMap.take(parentMap.value(blendshapeId)); + } + geometry.blendshapes = blendshapes; + return geometry; }