diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index 7077c44287..b117197f48 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -157,17 +157,19 @@ bool ModelUploader::zip() { // mixamo/autodesk defaults if (!mapping.contains(SCALE_FIELD)) { - mapping.insert(SCALE_FIELD, geometry.author == "www.makehuman.org" ? 150.0 : 15.0); + mapping.insert(SCALE_FIELD, 15.0); } QVariantHash joints = mapping.value(JOINT_FIELD).toHash(); if (!joints.contains("jointEyeLeft")) { - joints.insert("jointEyeLeft", geometry.jointIndices.contains("EyeLeft") ? "EyeLeft" : "LeftEye"); + joints.insert("jointEyeLeft", geometry.jointIndices.contains("jointEyeLeft") ? "jointEyeLeft" : + (geometry.jointIndices.contains("EyeLeft") ? "EyeLeft" : "LeftEye")); } if (!joints.contains("jointEyeRight")) { - joints.insert("jointEyeRight", geometry.jointIndices.contains("EyeRight") ? "EyeRight" : "RightEye"); + joints.insert("jointEyeRight", geometry.jointIndices.contains("jointEyeRight") ? "jointEyeRight" : + geometry.jointIndices.contains("EyeRight") ? "EyeRight" : "RightEye"); } if (!joints.contains("jointNeck")) { - joints.insert("jointNeck", "Neck"); + joints.insert("jointNeck", geometry.jointIndices.contains("jointNeck") ? "jointNeck" : "Neck"); } if (!joints.contains("jointRoot")) { joints.insert("jointRoot", "Hips"); @@ -785,7 +787,9 @@ QComboBox* ModelPropertiesDialog::createJointBox(bool withNone) const { box->addItem("(none)"); } foreach (const FBXJoint& joint, _geometry.joints) { - box->addItem(joint.name); + if (joint.isSkeletonJoint || !_geometry.hasSkeletonJoints) { + box->addItem(joint.name); + } } return box; } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index b9f7d7cd71..e735e2e47b 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1015,6 +1015,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QHash textureFilenames; QHash textureContent; QHash materials; + QHash typeFlags; QHash diffuseTextures; QHash bumpTextures; QHash specularTextures; @@ -1072,6 +1073,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QMultiHash blendshapeChannelIndices; FBXGeometry geometry; + float unitScaleFactor = 1.0f; foreach (const FBXNode& child, node.children) { if (child.name == "FBXHeaderExtension") { foreach (const FBXNode& object, child.children) { @@ -1094,6 +1096,17 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } } } + } else if (child.name == "GlobalSettings") { + foreach (const FBXNode& object, child.children) { + if (object.name == "Properties70") { + foreach (const FBXNode& subobject, object.children) { + if (subobject.name == "P" && subobject.properties.size() >= 5 && + subobject.properties.at(0) == "UnitScaleFactor") { + unitScaleFactor = subobject.properties.at(4).toFloat(); + } + } + } + } } else if (child.name == "Objects") { foreach (const FBXNode& object, child.children) { if (object.name == "Geometry") { @@ -1323,6 +1336,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) material.id = getID(object.properties); materials.insert(material.id, material); + } else if (object.name == "NodeAttribute") { + foreach (const FBXNode& subobject, object.children) { + if (subobject.name == "TypeFlags") { + typeFlags.insert(getID(object.properties), subobject.properties.at(0).toString()); + } + } } else if (object.name == "Deformer") { if (object.properties.last() == "Cluster") { Cluster cluster; @@ -1405,7 +1424,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } // get offset transform from mapping - float offsetScale = mapping.value("scale", 1.0f).toFloat(); + float offsetScale = mapping.value("scale", 1.0f).toFloat() * unitScaleFactor; glm::quat offsetRotation = glm::quat(glm::radians(glm::vec3(mapping.value("rx").toFloat(), mapping.value("ry").toFloat(), mapping.value("rz").toFloat()))); geometry.offset = glm::translate(glm::vec3(mapping.value("tx").toFloat(), mapping.value("ty").toFloat(), @@ -1461,12 +1480,13 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) // convert the models to joints QVariantList freeJoints = mapping.values("freeJoint"); + geometry.hasSkeletonJoints = false; foreach (const QString& modelID, modelIDs) { const FBXModel& model = models[modelID]; FBXJoint joint; joint.isFree = freeJoints.contains(model.name); joint.parentIndex = model.parentIndex; - + // get the indices of all ancestors starting with the first free one (if any) int jointIndex = geometry.joints.size(); joint.freeLineage.append(jointIndex); @@ -1506,6 +1526,15 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) joint.name = model.name; joint.shapePosition = glm::vec3(0.f); joint.shapeType = UNKNOWN_SHAPE; + + foreach (const QString& childID, childMap.values(modelID)) { + QString type = typeFlags.value(childID); + if (!type.isEmpty()) { + geometry.hasSkeletonJoints |= (joint.isSkeletonJoint = type.toLower().contains("Skeleton")); + break; + } + } + geometry.joints.append(joint); geometry.jointIndices.insert(model.name, geometry.joints.size()); diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 6a7a0904da..cbf0cfcca6 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -80,6 +80,7 @@ public: glm::vec3 shapePosition; // in joint frame glm::quat shapeRotation; // in joint frame Shape::Type shapeType; + bool isSkeletonJoint; }; @@ -182,6 +183,7 @@ public: QVector joints; QHash jointIndices; ///< 1-based, so as to more easily detect missing indices + bool hasSkeletonJoints; QVector meshes;