diff --git a/libraries/fbx/src/FBXSerializer.cpp b/libraries/fbx/src/FBXSerializer.cpp index 2c03c3c3ae..91989e5a90 100644 --- a/libraries/fbx/src/FBXSerializer.cpp +++ b/libraries/fbx/src/FBXSerializer.cpp @@ -1302,12 +1302,16 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const bool needMixamoHack = hfmModel.applicationName == "mixamo.com"; + std::vector transformForClusters; + transformForClusters.reserve((size_t)modelIDs.size()); for (const QString& modelID : modelIDs) { const FBXModel& fbxModel = fbxModels[modelID]; HFMJoint joint; joint.parentIndex = fbxModel.parentIndex; uint32_t jointIndex = (uint32_t)hfmModel.joints.size(); + // Copy default joint parameters from model + joint.translation = fbxModel.translation; // these are usually in centimeters joint.preTransform = fbxModel.preTransform; joint.preRotation = fbxModel.preRotation; @@ -1317,35 +1321,62 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const joint.rotationMin = fbxModel.rotationMin; joint.rotationMax = fbxModel.rotationMax; - joint.hasGeometricOffset = fbxModel.hasGeometricOffset; - joint.geometricTranslation = fbxModel.geometricTranslation; - joint.geometricRotation = fbxModel.geometricRotation; - joint.geometricScaling = fbxModel.geometricScaling; + if (fbxModel.hasGeometricOffset) { + joint.geometricOffset = createMatFromScaleQuatAndPos(fbxModel.geometricScaling, fbxModel.geometricRotation, fbxModel.geometricTranslation); + } joint.isSkeletonJoint = fbxModel.isLimbNode; hfmModel.hasSkeletonJoints = (hfmModel.hasSkeletonJoints || joint.isSkeletonJoint); + + joint.name = fbxModel.name; + + joint.bindTransformFoundInCluster = false; + + // With the basic joint information, we can start to calculate compound transform information + // modelIDs is ordered from parent to children, so we can safely get parent transforms from earlier joints as we iterate + + // Make adjustments to the static joint properties, and pre-calculate static transforms + if (applyUpAxisZRotation && joint.parentIndex == -1) { joint.rotation *= upAxisZRotation; joint.translation = upAxisZRotation * joint.translation; } + glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation; + joint.localTransform = glm::translate(joint.translation) * joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform; + if (joint.parentIndex == -1) { - joint.transform = hfmModel.offset * glm::translate(joint.translation) * joint.preTransform * - glm::mat4_cast(combinedRotation) * joint.postTransform; + joint.transform = joint.localTransform; + joint.globalTransform = hfmModel.offset * joint.localTransform; joint.inverseDefaultRotation = glm::inverse(combinedRotation); joint.distanceToParent = 0.0f; - } else { const HFMJoint& parentJoint = hfmModel.joints.at(joint.parentIndex); - joint.transform = parentJoint.transform * glm::translate(joint.translation) * - joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform; + joint.transform = parentJoint.transform * joint.localTransform; + joint.globalTransform = parentJoint.globalTransform * joint.localTransform; joint.inverseDefaultRotation = glm::inverse(combinedRotation) * parentJoint.inverseDefaultRotation; - joint.distanceToParent = glm::distance(extractTranslation(parentJoint.transform), - extractTranslation(joint.transform)); + joint.distanceToParent = glm::distance(extractTranslation(parentJoint.transform), extractTranslation(joint.transform)); } joint.inverseBindRotation = joint.inverseDefaultRotation; - joint.name = fbxModel.name; - joint.bindTransformFoundInCluster = false; + // If needed, separately calculate the FBX-specific transform used for inverse bind transform calculations + + glm::mat4 transformForCluster; + if (applyUpAxisZRotation) { + const glm::quat jointBindCombinedRotation = fbxModel.preRotation * fbxModel.rotation * fbxModel.postRotation; + const glm::mat4 localTransformForCluster = glm::translate(fbxModel.translation) * fbxModel.preTransform * glm::mat4_cast(jointBindCombinedRotation) * fbxModel.postTransform; + if (fbxModel.parentIndex != -1 && fbxModel.parentIndex < (int)jointIndex && !needMixamoHack) { + const glm::mat4& parenttransformForCluster = transformForClusters[fbxModel.parentIndex]; + transformForCluster = parenttransformForCluster * localTransformForCluster; + } else { + transformForCluster = localTransformForCluster; + } + } else { + transformForCluster = joint.transform; + } + transformForClusters.push_back(transformForCluster); + + // Initialize animation information next + // And also get the joint poses from the first frame of the animation, if present QString rotationID = localRotations.value(modelID); AnimationCurve xRotCurve = animationCurves.value(xComponents.value(rotationID)); @@ -1373,45 +1404,6 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const joint.translation = hfmModel.animationFrames[i].translations[jointIndex]; joint.rotation = hfmModel.animationFrames[i].rotations[jointIndex]; } - - } - - // Now that we've initialized the joint, we can define the transform - // modelIDs is ordered from parent to children, so we can safely get parent transforms from earlier joints as we iterate - joint.localTransform = glm::translate(joint.translation) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation * joint.postRotation) * joint.postTransform; - joint.globalTransform = joint.localTransform; - if (joint.parentIndex != -1 && joint.parentIndex < (int)jointIndex && !needMixamoHack) { - hfm::Joint& parentJoint = hfmModel.joints[joint.parentIndex]; - // SG Change: i think this not correct and the [parent]*[local] is the correct answer here - //joint.globalTransform = joint.globalTransform * parentJoint.globalTransform; - joint.globalTransform = parentJoint.globalTransform * joint.localTransform; - if (parentJoint.hasGeometricOffset) { - // Per the FBX standard, geometric offset should not propagate to children. - // However, we must be careful when modifying the behavior of FBXSerializer. - // So, we leave this here, as a breakpoint for debugging, or stub for implementation. - // qCDebug(modelformat) << "Geometric offset encountered on non-leaf node. jointIndex: " << jointIndex << ", modelURL: " << url; - // glm::mat4 geometricOffset = createMatFromScaleQuatAndPos(parentJoint.geometricScaling, parentJoint.geometricRotation, parentJoint.geometricTranslation); - // globalTransform = globalTransform * glm::inverse(geometricOffset); - } - } - if (joint.hasGeometricOffset) { - glm::mat4 geometricOffset = createMatFromScaleQuatAndPos(joint.geometricScaling, joint.geometricRotation, joint.geometricTranslation); - joint.globalTransform = joint.globalTransform * geometricOffset; - } - - // TODO: Remove these lines, just here to make sure we are not breaking the transform computation - // QString modelID = fbxModels.contains(it.key()) ? it.key() : _connectionParentMap.value(it.key()); - glm::mat4 anotherModelTransform = getGlobalTransform(_connectionParentMap, fbxModels, modelID, hfmModel.applicationName == "mixamo.com", url); - auto col0 = (glm::epsilonNotEqual(anotherModelTransform[0], joint.globalTransform[0], 0.001f)); - auto col1 = (glm::epsilonNotEqual(anotherModelTransform[1], joint.globalTransform[1], 0.001f)); - auto col2 = (glm::epsilonNotEqual(anotherModelTransform[2], joint.globalTransform[2], 0.001f)); - auto col3 = (glm::epsilonNotEqual(anotherModelTransform[3], joint.globalTransform[3], 0.001f)); - if ( glm::any(col0) - || glm::any(col1) - || glm::any(col2) - || glm::any(col3)) { - anotherModelTransform = getGlobalTransform(_connectionParentMap, fbxModels, modelID, hfmModel.applicationName == "mixamo.com", url); - // joint.globalTransform = anotherModelTransform; } hfmModel.joints.push_back(joint); @@ -1478,12 +1470,6 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const // meshShapes will be added to hfmModel at the very end std::vector meshShapes; meshShapes.reserve(instanceModelIDs.size() * mesh.parts.size()); - if (instanceModelIDs.size() > 1) { - qCDebug(modelformat) << "Mesh " << meshID << " made of " << mesh.parts.size() << " parts is instanced " << instanceModelIDs.size() << " times!!!"; - } - if (mesh.parts.size() < 1) { - qCDebug(modelformat) << "Mesh " << meshID << " made of " << mesh.parts.size() << " parts !!!!! "; - } for (const QString& modelID : instanceModelIDs) { // The transform node has the same indexing order as the joints int indexOfModelID = modelIDs.indexOf(modelID); @@ -1492,15 +1478,6 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const } const uint32_t transformIndex = (indexOfModelID == -1) ? 0 : (uint32_t)indexOfModelID; - // accumulate local transforms - glm::mat4 globalTransform = hfmModel.joints[transformIndex].globalTransform; - // compute the mesh extents from the transformed vertices - for (const glm::vec3& vertex : mesh.vertices) { - glm::vec3 transformedVertex = glm::vec3(globalTransform * glm::vec4(vertex, 1.0f)); - hfmModel.meshExtents.minimum = glm::min(hfmModel.meshExtents.minimum, transformedVertex); - hfmModel.meshExtents.maximum = glm::max(hfmModel.meshExtents.maximum, transformedVertex); - } - // partShapes will be added to meshShapes at the very end std::vector partShapes { mesh.parts.size() }; for (uint32_t i = 0; i < (uint32_t)partShapes.size(); ++i) { @@ -1513,16 +1490,6 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const auto materialIt = materialNameToID.find(matName.toStdString()); if (materialIt != materialNameToID.end()) { shape.material = materialIt->second; - } else { - qCDebug(modelformat) << "Unknown material ? " << matName; - } - - shape.transformedExtents.reset(); - // compute the shape extents from the transformed vertices - for (const glm::vec3& vertex : mesh.vertices) { - glm::vec3 transformedVertex = glm::vec3(globalTransform * glm::vec4(vertex, 1.0f)); - shape.transformedExtents.minimum = glm::min(shape.transformedExtents.minimum, transformedVertex); - shape.transformedExtents.maximum = glm::max(shape.transformedExtents.maximum, transformedVertex); } } @@ -1562,21 +1529,15 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const } // For baked models with FBX_DRACO_MESH_VERSION >= 2, get materials from extracted.materialIDPerMeshPart if (!extracted.materialIDPerMeshPart.empty()) { - /* if (partShapes.size() == extracted.materialIDPerMeshPart.size()) { - for (uint32_t i = 0; i < (uint32_t)extracted.materialIDPerMeshPart.size(); ++i) { - hfm::Shape& shape = partShapes[i]; - const std::string& materialID = extracted.materialIDPerMeshPart[i]; - auto materialIt = materialNameToID.find(materialID); - if (materialIt != materialNameToID.end()) { - shape.material = materialIt->second; - } + assert(partShapes.size() == extracted.materialIDPerMeshPart.size()); + for (uint32_t i = 0; i < (uint32_t)extracted.materialIDPerMeshPart.size(); ++i) { + hfm::Shape& shape = partShapes[i]; + const std::string& materialID = extracted.materialIDPerMeshPart[i]; + auto materialIt = materialNameToID.find(materialID); + if (materialIt != materialNameToID.end()) { + shape.material = materialIt->second; } - } else { - for (int p = 0; p < mesh.parts.size(); p++) { - qCDebug(modelformat) << "mesh.parts[" << p <<"] is " << mesh.parts[p].materialID; - } - qCDebug(modelformat) << "partShapes is not the same size as materialIDPerMeshPart ?"; - }*/ + } } // find the clusters with which the mesh is associated @@ -1609,7 +1570,8 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const hfmCluster.jointIndex = (uint32_t)indexOfJointID; } - hfmCluster.inverseBindMatrix = glm::inverse(fbxCluster.transformLink) * globalTransform; + const glm::mat4& transformForCluster = transformForClusters[transformIndex]; + hfmCluster.inverseBindMatrix = glm::inverse(fbxCluster.transformLink) * transformForCluster; // slam bottom row to (0, 0, 0, 1), we KNOW this is not a perspective matrix and // sometimes floating point fuzz can be introduced after the inverse. @@ -1680,17 +1642,6 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const for (hfm::Shape& shape : partShapes) { shape.skinDeformer = skinDeformerID; } - } else { - // this is a no cluster mesh - HFMJoint& joint = hfmModel.joints[transformIndex]; - - // Apply geometric offset, if present, by transforming the vertices directly - if (joint.hasGeometricOffset) { - glm::mat4 geometricOffset = createMatFromScaleQuatAndPos(joint.geometricScaling, joint.geometricRotation, joint.geometricTranslation); - for (int i = 0; i < mesh.vertices.size(); i++) { - mesh.vertices[i] = transformPoint(geometricOffset, mesh.vertices[i]); - } - } } // Store the parts for this mesh (or instance of this mesh, as the case may be) @@ -1717,16 +1668,6 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const } } - if (applyUpAxisZRotation) { - hfmModelPtr->meshExtents.transform(glm::mat4_cast(upAxisZRotation)); - hfmModelPtr->bindExtents.transform(glm::mat4_cast(upAxisZRotation)); - for (auto& shape : hfmModelPtr->shapes) { - shape.transformedExtents.transform(glm::mat4_cast(upAxisZRotation)); - } - for (auto& joint : hfmModelPtr->joints) { - joint.globalTransform = joint.globalTransform * glm::mat4_cast(upAxisZRotation); - } - } return hfmModelPtr; } diff --git a/libraries/fbx/src/FBXSerializer_Mesh.cpp b/libraries/fbx/src/FBXSerializer_Mesh.cpp index 37f2c9ec1b..e687f5e9f2 100644 --- a/libraries/fbx/src/FBXSerializer_Mesh.cpp +++ b/libraries/fbx/src/FBXSerializer_Mesh.cpp @@ -369,11 +369,6 @@ ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& me } } - if (dracoMeshNodeVersion >= 2) { - // Define the materialIDs now - data.extracted.materialIDPerMeshPart = dracoMaterialList; - } - // load the draco mesh from the FBX and create a draco::Mesh draco::Decoder decoder; draco::DecoderBuffer decodedBuffer; @@ -491,15 +486,13 @@ ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& me // grab or setup the HFMMeshPart for the part this face belongs to int& partIndexPlusOne = materialTextureParts[materialTexture]; if (partIndexPlusOne == 0) { - data.extracted.mesh.parts.resize(data.extracted.mesh.parts.size() + 1); - HFMMeshPart& part = data.extracted.mesh.parts.back(); + data.extracted.mesh.parts.emplace_back(); // Figure out if this is the older way of defining the per-part material for baked FBX if (dracoMeshNodeVersion >= 2) { - // Define the materialID now - if (materialID < dracoMaterialList.size()) { - part.materialID = QString(dracoMaterialList[materialID].c_str()); - } + // Define the materialID for this mesh part index + uint16_t safeMaterialID = materialID < dracoMaterialList.size() ? materialID : 0; + data.extracted.materialIDPerMeshPart.push_back(dracoMaterialList[safeMaterialID].c_str()); } else { // Define the materialID later, based on the order of first appearance of the materials in the _connectionChildMap data.extracted.partMaterialTextures.append(materialTexture); diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 115e7e0ca7..1ec276ba5a 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1015,7 +1015,6 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& joint.transform = parentJoint.transform * joint.transform; joint.globalTransform = joint.globalTransform * parentJoint.globalTransform; } else { - joint.transform = hfmModel.offset * joint.transform; joint.globalTransform = hfmModel.offset * joint.globalTransform; } @@ -2073,144 +2072,7 @@ void GLTFSerializer::glTFDebugDump() { } void GLTFSerializer::hfmDebugDump(const HFMModel& hfmModel) { - qCDebug(modelformat) << "---------------- hfmModel ----------------"; - qCDebug(modelformat) << " hasSkeletonJoints =" << hfmModel.hasSkeletonJoints; - qCDebug(modelformat) << " offset =" << hfmModel.offset; - - qCDebug(modelformat) << " neckPivot = " << hfmModel.neckPivot; - - qCDebug(modelformat) << " bindExtents.size() = " << hfmModel.bindExtents.size(); - qCDebug(modelformat) << " meshExtents.size() = " << hfmModel.meshExtents.size(); - - qCDebug(modelformat) << " jointIndices.size() =" << hfmModel.jointIndices.size(); - qCDebug(modelformat) << " joints.count() =" << hfmModel.joints.size(); - qCDebug(modelformat) << "---------------- Meshes ----------------"; - qCDebug(modelformat) << " meshes.count() =" << hfmModel.meshes.size(); - qCDebug(modelformat) << " blendshapeChannelNames = " << hfmModel.blendshapeChannelNames; - for (const HFMMesh& mesh : hfmModel.meshes) { - qCDebug(modelformat) << "\n"; - qCDebug(modelformat) << " meshpointer =" << mesh._mesh.get(); - qCDebug(modelformat) << " meshindex =" << mesh.meshIndex; - qCDebug(modelformat) << " vertices.count() =" << mesh.vertices.size(); - qCDebug(modelformat) << " colors.count() =" << mesh.colors.count(); - qCDebug(modelformat) << " normals.count() =" << mesh.normals.size(); - qCDebug(modelformat) << " tangents.count() =" << mesh.tangents.size(); - qCDebug(modelformat) << " colors.count() =" << mesh.colors.count(); - qCDebug(modelformat) << " texCoords.count() =" << mesh.texCoords.count(); - qCDebug(modelformat) << " texCoords1.count() =" << mesh.texCoords1.count(); - //qCDebug(modelformat) << " clusterIndices.count() =" << mesh.clusterIndices.count(); - //qCDebug(modelformat) << " clusterWeights.count() =" << mesh.clusterWeights.count(); - //qCDebug(modelformat) << " modelTransform =" << mesh.modelTransform; - qCDebug(modelformat) << " parts.count() =" << mesh.parts.size(); - qCDebug(modelformat) << "---------------- Meshes (blendshapes)--------"; - for (HFMBlendshape bshape : mesh.blendshapes) { - qCDebug(modelformat) << "\n"; - qCDebug(modelformat) << " bshape.indices.count() =" << bshape.indices.count(); - qCDebug(modelformat) << " bshape.vertices.count() =" << bshape.vertices.count(); - qCDebug(modelformat) << " bshape.normals.count() =" << bshape.normals.count(); - qCDebug(modelformat) << "\n"; - } - qCDebug(modelformat) << "---------------- Meshes (meshparts)--------"; - for (HFMMeshPart meshPart : mesh.parts) { - qCDebug(modelformat) << "\n"; - qCDebug(modelformat) << " quadIndices.count() =" << meshPart.quadIndices.count(); - qCDebug(modelformat) << " triangleIndices.count() =" << meshPart.triangleIndices.count(); - //qCDebug(modelformat) << " materialID =" << meshPart.materialID; - qCDebug(modelformat) << "\n"; - } - qCDebug(modelformat) << "---------------- Meshes (clusters)--------"; - //qCDebug(modelformat) << " clusters.count() =" << mesh.clusters.count(); - //for(HFMCluster cluster : mesh.clusters) { - // qCDebug(modelformat) << "\n"; - // qCDebug(modelformat) << " jointIndex =" << cluster.jointIndex; - // qCDebug(modelformat) << " inverseBindMatrix =" << cluster.inverseBindMatrix; - // qCDebug(modelformat) << "\n"; - //} - //qCDebug(modelformat) << "\n"; - } - qCDebug(modelformat) << "---------------- AnimationFrames ----------------"; - for (HFMAnimationFrame anim : hfmModel.animationFrames) { - qCDebug(modelformat) << " anim.translations = " << anim.translations; - qCDebug(modelformat) << " anim.rotations = " << anim.rotations; - } - QList mitomona_keys = hfmModel.meshIndicesToModelNames.keys(); - for (int key : mitomona_keys) { - qCDebug(modelformat) << " meshIndicesToModelNames key =" << key - << " val =" << hfmModel.meshIndicesToModelNames[key]; - } - - qCDebug(modelformat) << "---------------- Materials ----------------"; - - for (HFMMaterial mat : hfmModel.materials) { - qCDebug(modelformat) << "\n"; - qCDebug(modelformat) << " mat.materialID =" << mat.materialID; - qCDebug(modelformat) << " diffuseColor =" << mat.diffuseColor; - qCDebug(modelformat) << " diffuseFactor =" << mat.diffuseFactor; - qCDebug(modelformat) << " specularColor =" << mat.specularColor; - qCDebug(modelformat) << " specularFactor =" << mat.specularFactor; - qCDebug(modelformat) << " emissiveColor =" << mat.emissiveColor; - qCDebug(modelformat) << " emissiveFactor =" << mat.emissiveFactor; - qCDebug(modelformat) << " shininess =" << mat.shininess; - qCDebug(modelformat) << " opacity =" << mat.opacity; - qCDebug(modelformat) << " metallic =" << mat.metallic; - qCDebug(modelformat) << " roughness =" << mat.roughness; - qCDebug(modelformat) << " emissiveIntensity =" << mat.emissiveIntensity; - qCDebug(modelformat) << " ambientFactor =" << mat.ambientFactor; - - qCDebug(modelformat) << " materialID =" << mat.materialID; - qCDebug(modelformat) << " name =" << mat.name; - qCDebug(modelformat) << " shadingModel =" << mat.shadingModel; - qCDebug(modelformat) << " _material =" << mat._material.get(); - - qCDebug(modelformat) << " normalTexture =" << mat.normalTexture.filename; - qCDebug(modelformat) << " albedoTexture =" << mat.albedoTexture.filename; - qCDebug(modelformat) << " opacityTexture =" << mat.opacityTexture.filename; - - qCDebug(modelformat) << " lightmapParams =" << mat.lightmapParams; - - qCDebug(modelformat) << " isPBSMaterial =" << mat.isPBSMaterial; - qCDebug(modelformat) << " useNormalMap =" << mat.useNormalMap; - qCDebug(modelformat) << " useAlbedoMap =" << mat.useAlbedoMap; - qCDebug(modelformat) << " useOpacityMap =" << mat.useOpacityMap; - qCDebug(modelformat) << " useRoughnessMap =" << mat.useRoughnessMap; - qCDebug(modelformat) << " useSpecularMap =" << mat.useSpecularMap; - qCDebug(modelformat) << " useMetallicMap =" << mat.useMetallicMap; - qCDebug(modelformat) << " useEmissiveMap =" << mat.useEmissiveMap; - qCDebug(modelformat) << " useOcclusionMap =" << mat.useOcclusionMap; - qCDebug(modelformat) << "\n"; - } - - qCDebug(modelformat) << "---------------- Joints ----------------"; - - foreach (HFMJoint joint, hfmModel.joints) { - qCDebug(modelformat) << "\n"; - qCDebug(modelformat) << " shapeInfo.avgPoint =" << joint.shapeInfo.avgPoint; - qCDebug(modelformat) << " shapeInfo.debugLines =" << joint.shapeInfo.debugLines; - qCDebug(modelformat) << " shapeInfo.dots =" << joint.shapeInfo.dots; - qCDebug(modelformat) << " shapeInfo.points =" << joint.shapeInfo.points; - - qCDebug(modelformat) << " parentIndex" << joint.parentIndex; - qCDebug(modelformat) << " distanceToParent" << joint.distanceToParent; - qCDebug(modelformat) << " translation" << joint.translation; - qCDebug(modelformat) << " preTransform" << joint.preTransform; - qCDebug(modelformat) << " preRotation" << joint.preRotation; - qCDebug(modelformat) << " rotation" << joint.rotation; - qCDebug(modelformat) << " postRotation" << joint.postRotation; - qCDebug(modelformat) << " postTransform" << joint.postTransform; - qCDebug(modelformat) << " transform" << joint.transform; - qCDebug(modelformat) << " rotationMin" << joint.rotationMin; - qCDebug(modelformat) << " rotationMax" << joint.rotationMax; - qCDebug(modelformat) << " inverseDefaultRotation" << joint.inverseDefaultRotation; - qCDebug(modelformat) << " inverseBindRotation" << joint.inverseBindRotation; - qCDebug(modelformat) << " bindTransform" << joint.bindTransform; - qCDebug(modelformat) << " name" << joint.name; - qCDebug(modelformat) << " isSkeletonJoint" << joint.isSkeletonJoint; - qCDebug(modelformat) << " bindTransformFoundInCluster" << joint.hasGeometricOffset; - qCDebug(modelformat) << " bindTransformFoundInCluster" << joint.geometricTranslation; - qCDebug(modelformat) << " bindTransformFoundInCluster" << joint.geometricRotation; - qCDebug(modelformat) << " bindTransformFoundInCluster" << joint.geometricScaling; - qCDebug(modelformat) << "\n"; - } + hfmModel.debugDump(); qCDebug(modelformat) << "---------------- GLTF Model ----------------"; glTFDebugDump(); diff --git a/libraries/fbx/src/OBJSerializer.cpp b/libraries/fbx/src/OBJSerializer.cpp index 445c259650..31f92555f1 100644 --- a/libraries/fbx/src/OBJSerializer.cpp +++ b/libraries/fbx/src/OBJSerializer.cpp @@ -675,7 +675,6 @@ HFMModel::Pointer OBJSerializer::read(const hifi::ByteArray& data, const hifi::V _url = url; bool combineParts = mapping.value("combineParts").toBool(); - hfmModel.meshExtents.reset(); hfmModel.meshes.push_back(HFMMesh()); std::vector materialNamePerShape; @@ -741,8 +740,8 @@ HFMModel::Pointer OBJSerializer::read(const hifi::ByteArray& data, const hifi::V needsMaterialLibrary = groupMaterialName != SMART_DEFAULT_MATERIAL_NAME; } materials[groupMaterialName] = material; - materialNamePerShape.push_back(groupMaterialName); } + materialNamePerShape.push_back(groupMaterialName); hfm::Shape shape; @@ -826,14 +825,6 @@ HFMModel::Pointer OBJSerializer::read(const hifi::ByteArray& data, const hifi::V } } } - - mesh.meshExtents.reset(); - foreach(const glm::vec3& vertex, mesh.vertices) { - mesh.meshExtents.addPoint(vertex); - hfmModel.meshExtents.addPoint(vertex); - } - - // hfmDebugDump(hfmModel); } catch(const std::exception& e) { qCDebug(modelformat) << "OBJSerializer fail: " << e.what(); } @@ -1010,83 +1001,14 @@ HFMModel::Pointer OBJSerializer::read(const hifi::ByteArray& data, const hifi::V // GO over the shapes once more to assign the material index correctly for (uint32_t i = 0; i < (uint32_t)hfmModel.shapes.size(); ++i) { - auto foundMaterialIndex = materialNameToIndex.find(materialNamePerShape[i]); - if (foundMaterialIndex != materialNameToIndex.end()) { - hfmModel.shapes[i].material = foundMaterialIndex.value(); + const auto& materialName = materialNamePerShape[i]; + if (!materialName.isEmpty()) { + auto foundMaterialIndex = materialNameToIndex.find(materialName); + if (foundMaterialIndex != materialNameToIndex.end()) { + hfmModel.shapes[i].material = foundMaterialIndex.value(); + } } } return hfmModelPtr; } - -void hfmDebugDump(const HFMModel& hfmModel) { - qCDebug(modelformat) << "---------------- hfmModel ----------------"; - qCDebug(modelformat) << " hasSkeletonJoints =" << hfmModel.hasSkeletonJoints; - qCDebug(modelformat) << " offset =" << hfmModel.offset; - qCDebug(modelformat) << " meshes.count() =" << hfmModel.meshes.size(); - foreach (HFMMesh mesh, hfmModel.meshes) { - qCDebug(modelformat) << " vertices.count() =" << mesh.vertices.count(); - qCDebug(modelformat) << " colors.count() =" << mesh.colors.count(); - qCDebug(modelformat) << " normals.count() =" << mesh.normals.count(); - /*if (mesh.normals.count() == mesh.vertices.count()) { - for (int i = 0; i < mesh.normals.count(); i++) { - qCDebug(modelformat) << " " << mesh.vertices[ i ] << mesh.normals[ i ]; - } - }*/ - qCDebug(modelformat) << " tangents.count() =" << mesh.tangents.count(); - qCDebug(modelformat) << " colors.count() =" << mesh.colors.count(); - qCDebug(modelformat) << " texCoords.count() =" << mesh.texCoords.count(); - qCDebug(modelformat) << " texCoords1.count() =" << mesh.texCoords1.count(); - qCDebug(modelformat) << " clusterIndices.size() =" << mesh.clusterIndices.size(); - qCDebug(modelformat) << " clusterWeights.size() =" << mesh.clusterWeights.size(); - qCDebug(modelformat) << " meshExtents =" << mesh.meshExtents; - qCDebug(modelformat) << " modelTransform =" << mesh.modelTransform; - qCDebug(modelformat) << " parts.count() =" << mesh.parts.size(); - foreach (HFMMeshPart meshPart, mesh.parts) { - qCDebug(modelformat) << " quadIndices.count() =" << meshPart.quadIndices.count(); - qCDebug(modelformat) << " triangleIndices.count() =" << meshPart.triangleIndices.count(); - /* - qCDebug(modelformat) << " diffuseColor =" << meshPart.diffuseColor << "mat =" << meshPart._material->getDiffuse(); - qCDebug(modelformat) << " specularColor =" << meshPart.specularColor << "mat =" << meshPart._material->getMetallic(); - qCDebug(modelformat) << " emissiveColor =" << meshPart.emissiveColor << "mat =" << meshPart._material->getEmissive(); - qCDebug(modelformat) << " emissiveParams =" << meshPart.emissiveParams; - qCDebug(modelformat) << " gloss =" << meshPart.shininess << "mat =" << meshPart._material->getRoughness(); - qCDebug(modelformat) << " opacity =" << meshPart.opacity << "mat =" << meshPart._material->getOpacity(); - */ - qCDebug(modelformat) << " materialID =" << meshPart.materialID; - /* qCDebug(modelformat) << " diffuse texture =" << meshPart.diffuseTexture.filename; - qCDebug(modelformat) << " specular texture =" << meshPart.specularTexture.filename; - */ - } - qCDebug(modelformat) << " clusters.count() =" << mesh.clusters.count(); - foreach (HFMCluster cluster, mesh.clusters) { - qCDebug(modelformat) << " jointIndex =" << cluster.jointIndex; - qCDebug(modelformat) << " inverseBindMatrix =" << cluster.inverseBindMatrix; - } - } - - qCDebug(modelformat) << " jointIndices =" << hfmModel.jointIndices; - qCDebug(modelformat) << " joints.count() =" << hfmModel.joints.size(); - - foreach (HFMJoint joint, hfmModel.joints) { - - qCDebug(modelformat) << " parentIndex" << joint.parentIndex; - qCDebug(modelformat) << " distanceToParent" << joint.distanceToParent; - qCDebug(modelformat) << " translation" << joint.translation; - qCDebug(modelformat) << " preTransform" << joint.preTransform; - qCDebug(modelformat) << " preRotation" << joint.preRotation; - qCDebug(modelformat) << " rotation" << joint.rotation; - qCDebug(modelformat) << " postRotation" << joint.postRotation; - qCDebug(modelformat) << " postTransform" << joint.postTransform; - qCDebug(modelformat) << " transform" << joint.transform; - qCDebug(modelformat) << " rotationMin" << joint.rotationMin; - qCDebug(modelformat) << " rotationMax" << joint.rotationMax; - qCDebug(modelformat) << " inverseDefaultRotation" << joint.inverseDefaultRotation; - qCDebug(modelformat) << " inverseBindRotation" << joint.inverseBindRotation; - qCDebug(modelformat) << " bindTransform" << joint.bindTransform; - qCDebug(modelformat) << " name" << joint.name; - qCDebug(modelformat) << " isSkeletonJoint" << joint.isSkeletonJoint; - } - - qCDebug(modelformat) << "\n"; -} diff --git a/libraries/fbx/src/OBJSerializer.h b/libraries/fbx/src/OBJSerializer.h index 6fdd95e2c3..462d32a119 100644 --- a/libraries/fbx/src/OBJSerializer.h +++ b/libraries/fbx/src/OBJSerializer.h @@ -120,6 +120,5 @@ private: // What are these utilities doing here? One is used by fbx loading code in VHACD Utils, and the other a general debugging utility. void setMeshPartDefaults(HFMMeshPart& meshPart, QString materialID); -void hfmDebugDump(const HFMModel& hfmModel); #endif // hifi_OBJSerializer_h diff --git a/libraries/hfm/src/hfm/HFM.cpp b/libraries/hfm/src/hfm/HFM.cpp index f68af2b1ce..500aaaa842 100644 --- a/libraries/hfm/src/hfm/HFM.cpp +++ b/libraries/hfm/src/hfm/HFM.cpp @@ -208,3 +208,164 @@ void HFMModel::computeKdops() { } } } + +void hfm::Model::debugDump() const { + qCDebug(modelformat) << "---------------- hfmModel ----------------"; + qCDebug(modelformat) << " hasSkeletonJoints =" << hasSkeletonJoints; + qCDebug(modelformat) << " offset =" << offset; + + qCDebug(modelformat) << " neckPivot = " << neckPivot; + + qCDebug(modelformat) << " bindExtents.size() = " << bindExtents.size(); + qCDebug(modelformat) << " meshExtents.size() = " << meshExtents.size(); + + qCDebug(modelformat) << "---------------- Shapes ----------------"; + qCDebug(modelformat) << " shapes.size() =" << shapes.size(); + for (const hfm::Shape& shape : shapes) { + qCDebug(modelformat) << "\n"; + qCDebug(modelformat) << " mesh =" << shape.mesh; + qCDebug(modelformat) << " meshPart =" << shape.meshPart; + qCDebug(modelformat) << " material =" << shape.material; + qCDebug(modelformat) << " joint =" << shape.joint; + qCDebug(modelformat) << " transformedExtents =" << shape.transformedExtents; + qCDebug(modelformat) << " skinDeformer =" << shape.skinDeformer; + } + + qCDebug(modelformat) << " jointIndices.size() =" << jointIndices.size(); + qCDebug(modelformat) << " joints.size() =" << joints.size(); + qCDebug(modelformat) << "---------------- Meshes ----------------"; + qCDebug(modelformat) << " meshes.size() =" << meshes.size(); + qCDebug(modelformat) << " blendshapeChannelNames = " << blendshapeChannelNames; + for (const HFMMesh& mesh : meshes) { + qCDebug(modelformat) << "\n"; + qCDebug(modelformat) << " meshpointer =" << mesh._mesh.get(); + qCDebug(modelformat) << " meshindex =" << mesh.meshIndex; + qCDebug(modelformat) << " vertices.size() =" << mesh.vertices.size(); + qCDebug(modelformat) << " colors.size() =" << mesh.colors.size(); + qCDebug(modelformat) << " normals.size() =" << mesh.normals.size(); + qCDebug(modelformat) << " tangents.size() =" << mesh.tangents.size(); + qCDebug(modelformat) << " colors.size() =" << mesh.colors.size(); + qCDebug(modelformat) << " texCoords.size() =" << mesh.texCoords.size(); + qCDebug(modelformat) << " texCoords1.size() =" << mesh.texCoords1.size(); + qCDebug(modelformat) << " clusterIndices.size() =" << mesh.clusterIndices.size(); + qCDebug(modelformat) << " clusterWeights.size() =" << mesh.clusterWeights.size(); + qCDebug(modelformat) << " modelTransform =" << mesh.modelTransform; + qCDebug(modelformat) << " parts.size() =" << mesh.parts.size(); + qCDebug(modelformat) << "---------------- Meshes (blendshapes)--------"; + for (HFMBlendshape bshape : mesh.blendshapes) { + qCDebug(modelformat) << "\n"; + qCDebug(modelformat) << " bshape.indices.size() =" << bshape.indices.size(); + qCDebug(modelformat) << " bshape.vertices.size() =" << bshape.vertices.size(); + qCDebug(modelformat) << " bshape.normals.size() =" << bshape.normals.size(); + qCDebug(modelformat) << "\n"; + } + qCDebug(modelformat) << "---------------- Meshes (meshparts)--------"; + for (HFMMeshPart meshPart : mesh.parts) { + qCDebug(modelformat) << "\n"; + qCDebug(modelformat) << " quadIndices.size() =" << meshPart.quadIndices.size(); + qCDebug(modelformat) << " triangleIndices.size() =" << meshPart.triangleIndices.size(); + qCDebug(modelformat) << "\n"; + } + } + qCDebug(modelformat) << "---------------- AnimationFrames ----------------"; + for (HFMAnimationFrame anim : animationFrames) { + qCDebug(modelformat) << " anim.translations = " << anim.translations; + qCDebug(modelformat) << " anim.rotations = " << anim.rotations; + } + QList mitomona_keys = meshIndicesToModelNames.keys(); + for (int key : mitomona_keys) { + qCDebug(modelformat) << " meshIndicesToModelNames key =" << key + << " val =" << meshIndicesToModelNames[key]; + } + + qCDebug(modelformat) << "---------------- Materials ----------------"; + + for (HFMMaterial mat : materials) { + qCDebug(modelformat) << "\n"; + qCDebug(modelformat) << " mat.materialID =" << mat.materialID; + qCDebug(modelformat) << " diffuseColor =" << mat.diffuseColor; + qCDebug(modelformat) << " diffuseFactor =" << mat.diffuseFactor; + qCDebug(modelformat) << " specularColor =" << mat.specularColor; + qCDebug(modelformat) << " specularFactor =" << mat.specularFactor; + qCDebug(modelformat) << " emissiveColor =" << mat.emissiveColor; + qCDebug(modelformat) << " emissiveFactor =" << mat.emissiveFactor; + qCDebug(modelformat) << " shininess =" << mat.shininess; + qCDebug(modelformat) << " opacity =" << mat.opacity; + qCDebug(modelformat) << " metallic =" << mat.metallic; + qCDebug(modelformat) << " roughness =" << mat.roughness; + qCDebug(modelformat) << " emissiveIntensity =" << mat.emissiveIntensity; + qCDebug(modelformat) << " ambientFactor =" << mat.ambientFactor; + + qCDebug(modelformat) << " materialID =" << mat.materialID; + qCDebug(modelformat) << " name =" << mat.name; + qCDebug(modelformat) << " shadingModel =" << mat.shadingModel; + qCDebug(modelformat) << " _material =" << mat._material.get(); + + qCDebug(modelformat) << " normalTexture =" << mat.normalTexture.filename; + qCDebug(modelformat) << " albedoTexture =" << mat.albedoTexture.filename; + qCDebug(modelformat) << " opacityTexture =" << mat.opacityTexture.filename; + + qCDebug(modelformat) << " lightmapParams =" << mat.lightmapParams; + + qCDebug(modelformat) << " isPBSMaterial =" << mat.isPBSMaterial; + qCDebug(modelformat) << " useNormalMap =" << mat.useNormalMap; + qCDebug(modelformat) << " useAlbedoMap =" << mat.useAlbedoMap; + qCDebug(modelformat) << " useOpacityMap =" << mat.useOpacityMap; + qCDebug(modelformat) << " useRoughnessMap =" << mat.useRoughnessMap; + qCDebug(modelformat) << " useSpecularMap =" << mat.useSpecularMap; + qCDebug(modelformat) << " useMetallicMap =" << mat.useMetallicMap; + qCDebug(modelformat) << " useEmissiveMap =" << mat.useEmissiveMap; + qCDebug(modelformat) << " useOcclusionMap =" << mat.useOcclusionMap; + qCDebug(modelformat) << "\n"; + } + + qCDebug(modelformat) << "---------------- Joints ----------------"; + + for (const HFMJoint& joint : joints) { + qCDebug(modelformat) << "\n"; + qCDebug(modelformat) << " shapeInfo.avgPoint =" << joint.shapeInfo.avgPoint; + qCDebug(modelformat) << " shapeInfo.debugLines =" << joint.shapeInfo.debugLines; + qCDebug(modelformat) << " shapeInfo.dots =" << joint.shapeInfo.dots; + qCDebug(modelformat) << " shapeInfo.points =" << joint.shapeInfo.points; + + qCDebug(modelformat) << " ---"; + + qCDebug(modelformat) << " parentIndex" << joint.parentIndex; + qCDebug(modelformat) << " distanceToParent" << joint.distanceToParent; + qCDebug(modelformat) << " localTransform" << joint.localTransform; + qCDebug(modelformat) << " transform" << joint.transform; + qCDebug(modelformat) << " globalTransform" << joint.globalTransform; + + qCDebug(modelformat) << " ---"; + + qCDebug(modelformat) << " translation" << joint.translation; + qCDebug(modelformat) << " preTransform" << joint.preTransform; + qCDebug(modelformat) << " preRotation" << joint.preRotation; + qCDebug(modelformat) << " rotation" << joint.rotation; + qCDebug(modelformat) << " postRotation" << joint.postRotation; + qCDebug(modelformat) << " postTransform" << joint.postTransform; + qCDebug(modelformat) << " rotationMin" << joint.rotationMin; + qCDebug(modelformat) << " rotationMax" << joint.rotationMax; + qCDebug(modelformat) << " inverseDefaultRotation" << joint.inverseDefaultRotation; + qCDebug(modelformat) << " inverseBindRotation" << joint.inverseBindRotation; + qCDebug(modelformat) << " bindTransformFoundInCluster" << joint.bindTransformFoundInCluster; + qCDebug(modelformat) << " bindTransform" << joint.bindTransform; + qCDebug(modelformat) << " name" << joint.name; + qCDebug(modelformat) << " isSkeletonJoint" << joint.isSkeletonJoint; + qCDebug(modelformat) << " geometricOffset" << joint.geometricOffset; + qCDebug(modelformat) << "\n"; + } + + qCDebug(modelformat) << "------------- SkinDeformers ------------"; + qCDebug(modelformat) << " skinDeformers.size() =" << skinDeformers.size(); + for(const hfm::SkinDeformer& skinDeformer : skinDeformers) { + qCDebug(modelformat) << "------- SkinDeformers (Clusters) -------"; + for (const hfm::Cluster& cluster : skinDeformer.clusters) { + qCDebug(modelformat) << "\n"; + qCDebug(modelformat) << " jointIndex =" << cluster.jointIndex; + qCDebug(modelformat) << " inverseBindMatrix =" << cluster.inverseBindMatrix; + qCDebug(modelformat) << "\n"; + } + } + qCDebug(modelformat) << "\n"; +} diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index ec91bd7605..c61f03d070 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -113,11 +113,10 @@ public: bool isSkeletonJoint; bool bindTransformFoundInCluster; + // geometric offset is applied in local space but does NOT affect children. - bool hasGeometricOffset; - glm::vec3 geometricTranslation; - glm::quat geometricRotation; - glm::vec3 geometricScaling; + // TODO: Apply hfm::Joint.geometricOffset to transforms in the model preparation step + glm::mat4 geometricOffset; // globalTransform is the transform of the joint with all parent transforms applied, plus the geometric offset glm::mat4 localTransform; @@ -375,6 +374,8 @@ public: QMap jointRotationOffsets; std::vector shapeVertices; FlowData flowData; + + void debugDump() const; }; }; diff --git a/libraries/hfm/src/hfm/HFMModelMath.cpp b/libraries/hfm/src/hfm/HFMModelMath.cpp index 93687b08b0..0026378060 100644 --- a/libraries/hfm/src/hfm/HFMModelMath.cpp +++ b/libraries/hfm/src/hfm/HFMModelMath.cpp @@ -43,13 +43,13 @@ void calculateExtentsForShape(hfm::Shape& shape, const std::vector& m const auto& mesh = meshes[shape.mesh]; const auto& meshPart = mesh.parts[shape.meshPart]; - glm::mat4 globalTransform = joints[shape.joint].globalTransform; + glm::mat4 transform = joints[shape.joint].transform; forEachIndex(meshPart, [&](int32_t idx){ if (mesh.vertices.size() <= idx) { return; } const glm::vec3& vertex = mesh.vertices[idx]; - const glm::vec3 transformedVertex = glm::vec3(globalTransform * glm::vec4(vertex, 1.0f)); + const glm::vec3 transformedVertex = glm::vec3(transform * glm::vec4(vertex, 1.0f)); shapeExtents.addPoint(transformedVertex); }); diff --git a/libraries/hfm/src/hfm/HFMSerializer.h b/libraries/hfm/src/hfm/HFMSerializer.h index d0be588d60..f28ef9f9c3 100644 --- a/libraries/hfm/src/hfm/HFMSerializer.h +++ b/libraries/hfm/src/hfm/HFMSerializer.h @@ -1,5 +1,5 @@ // -// FBXSerializer.h +// HFMSerializer.h // libraries/hfm/src/hfm // // Created by Sabrina Shanman on 2018/11/07.