From 98cef38aea8b19a770c89213488d6bc1547f09a4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 29 Aug 2020 09:14:49 +1200 Subject: [PATCH 01/11] Initial tidying --- libraries/fbx/src/GLTFSerializer.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 8234f2b17d2..bccc93083f8 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -21,7 +21,6 @@ #include #include - #include #include @@ -537,8 +536,7 @@ bool GLTFSerializer::addMesh(const QJsonObject& object) { } QJsonArray jsTargets; - if (getObjectArrayVal(jsPrimitive, "targets", jsTargets, primitive.defined)) - { + if (getObjectArrayVal(jsPrimitive, "targets", jsTargets, primitive.defined)) { foreach(const QJsonValue & tar, jsTargets) { if (tar.isObject()) { QJsonObject jsTarget = tar.toObject(); @@ -827,6 +825,8 @@ void GLTFSerializer::generateTargetData(int index, float weight, QVectordebugDump(); + + return HFMModel::Pointer(hfmModel); } diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index bccc93083f8..274a1b5dc19 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1669,7 +1669,9 @@ HFMModel::Pointer GLTFSerializer::read(const hifi::ByteArray& data, const hifi:: HFMModel& hfmModel = *hfmModelPtr; buildGeometry(hfmModel, mapping, _url); - //hfmDebugDump(data); + //hfmModel.debugDump(); + //glTFDebugDump(); + return hfmModelPtr; } else { qCDebug(modelformat) << "Error parsing GLTF file."; @@ -2020,181 +2022,28 @@ void GLTFSerializer::retriangulate(const QVector& inIndices, const QVector< } void GLTFSerializer::glTFDebugDump() { + qCDebug(modelformat) << "\n"; + qCDebug(modelformat) << "---------------- GLTF Model ----------------"; + qCDebug(modelformat) << "---------------- Nodes ----------------"; for (GLTFNode node : _file.nodes) { if (node.defined["mesh"]) { - qCDebug(modelformat) << "\n"; qCDebug(modelformat) << " node_transforms" << node.transforms; - qCDebug(modelformat) << "\n"; } } qCDebug(modelformat) << "---------------- Accessors ----------------"; for (GLTFAccessor accessor : _file.accessors) { - qCDebug(modelformat) << "\n"; qCDebug(modelformat) << "count: " << accessor.count; qCDebug(modelformat) << "byteOffset: " << accessor.byteOffset; - qCDebug(modelformat) << "\n"; } qCDebug(modelformat) << "---------------- Textures ----------------"; for (GLTFTexture texture : _file.textures) { if (texture.defined["source"]) { - qCDebug(modelformat) << "\n"; QString url = _file.images[texture.source].uri; QString fname = hifi::URL(url).fileName(); qCDebug(modelformat) << "fname: " << fname; - qCDebug(modelformat) << "\n"; } } - - qCDebug(modelformat) << "\n"; -} - -void GLTFSerializer::hfmDebugDump(const HFMModel& hfmModel) { - qCDebug(modelformat) << "---------------- hfmModel ----------------"; - qCDebug(modelformat) << " originalURL =" << hfmModel.originalURL; - - 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.count(); - qCDebug(modelformat) << "---------------- Meshes ----------------"; - qCDebug(modelformat) << " meshes.count() =" << hfmModel.meshes.count(); - qCDebug(modelformat) << " blendshapeChannelNames = " << hfmModel.blendshapeChannelNames; - foreach(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.count(); - qCDebug(modelformat) << "---------------- Meshes (blendshapes)--------"; - foreach(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)--------"; - foreach(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(); - foreach(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 ----------------"; - foreach(HFMAnimationFrame anim, hfmModel.animationFrames) { - qCDebug(modelformat) << " anim.translations = " << anim.translations; - qCDebug(modelformat) << " anim.rotations = " << anim.rotations; - } - QList mitomona_keys = hfmModel.meshIndicesToModelNames.keys(); - foreach(int key, mitomona_keys) { - qCDebug(modelformat) << " meshIndicesToModelNames key =" << key << " val =" << hfmModel.meshIndicesToModelNames[key]; - } - - qCDebug(modelformat) << "---------------- Materials ----------------"; - - foreach(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"; - } - - qCDebug(modelformat) << "---------------- GLTF Model ----------------"; - glTFDebugDump(); - - qCDebug(modelformat) << "\n"; } diff --git a/libraries/fbx/src/GLTFSerializer.h b/libraries/fbx/src/GLTFSerializer.h index b1020f7154d..79524ea7ff3 100755 --- a/libraries/fbx/src/GLTFSerializer.h +++ b/libraries/fbx/src/GLTFSerializer.h @@ -851,11 +851,10 @@ class GLTFSerializer : public QObject, public HFMSerializer { QNetworkReply* request(hifi::URL& url, bool isTest); bool doesResourceExist(const QString& url); - void setHFMMaterial(HFMMaterial& hfmMat, const GLTFMaterial& material); HFMTexture getHFMTexture(const GLTFTexture& texture); + void glTFDebugDump(); - void hfmDebugDump(const HFMModel& hfmModel); }; #endif // hifi_GLTFSerializer_h \ No newline at end of file diff --git a/libraries/hfm/src/hfm/HFM.cpp b/libraries/hfm/src/hfm/HFM.cpp index 236445bfdae..8fb0720c0d4 100644 --- a/libraries/hfm/src/hfm/HFM.cpp +++ b/libraries/hfm/src/hfm/HFM.cpp @@ -208,3 +208,138 @@ void HFMModel::computeKdops() { } } } + +void HFMModel::debugDump() { + qCDebug(modelformat) << "---------------- hfmModel ----------------"; + qCDebug(modelformat) << " originalURL =" << originalURL; + + 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) << " jointIndices.size() =" << jointIndices.size(); + qCDebug(modelformat) << " joints.count() =" << joints.count(); + + qCDebug(modelformat) << "---------------- Meshes ----------------"; + qCDebug(modelformat) << " meshes.count() =" << meshes.count(); + qCDebug(modelformat) << " blendshapeChannelNames = " << blendshapeChannelNames; + foreach(HFMMesh mesh, meshes) { + 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.count(); + + qCDebug(modelformat) << "---------------- Meshes (blendshapes)--------"; + foreach(HFMBlendshape bshape, mesh.blendshapes) { + 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) << "---------------- Meshes (meshparts)--------"; + foreach(HFMMeshPart meshPart, mesh.parts) { + qCDebug(modelformat) << " quadIndices.count() =" << meshPart.quadIndices.count(); + qCDebug(modelformat) << " triangleIndices.count() =" << meshPart.triangleIndices.count(); + qCDebug(modelformat) << " materialID =" << meshPart.materialID; + } + + qCDebug(modelformat) << "---------------- Meshes (clusters)--------"; + qCDebug(modelformat) << " clusters.count() =" << mesh.clusters.count(); + foreach(HFMCluster cluster, mesh.clusters) { + qCDebug(modelformat) << " jointIndex =" << cluster.jointIndex; + qCDebug(modelformat) << " inverseBindMatrix =" << cluster.inverseBindMatrix; + } + } + + qCDebug(modelformat) << "---------------- AnimationFrames ----------------"; + foreach(HFMAnimationFrame anim, animationFrames) { + qCDebug(modelformat) << " anim.translations = " << anim.translations; + qCDebug(modelformat) << " anim.rotations = " << anim.rotations; + } + + qCDebug(modelformat) << "---------------- Mesh model names ----------------"; + QList mitomona_keys = meshIndicesToModelNames.keys(); + foreach(int key, mitomona_keys) { + qCDebug(modelformat) << " meshIndicesToModelNames key =" << key << " val =" << meshIndicesToModelNames[key]; + } + + qCDebug(modelformat) << "---------------- Materials ----------------"; + foreach(HFMMaterial mat, materials) { + 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) << "---------------- Joints ----------------"; + foreach(HFMJoint joint, joints) { + 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; + } +} diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index d37d509d38c..aadc9e49abd 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -340,6 +340,8 @@ class Model { QMap jointRotationOffsets; std::vector shapeVertices; FlowData flowData; + + void debugDump(); }; }; From 77dbe7a254deddb4e456d566bb7a2a2c30267b41 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 29 Aug 2020 11:21:56 +1200 Subject: [PATCH 03/11] Rename FACESHIFT_BLENDSHAPES to BLENDSHAPE_NAMES --- interface/src/ModelPackager.cpp | 2 +- libraries/avatars-renderer/src/avatars-renderer/Head.cpp | 2 +- libraries/fbx/src/FBXSerializer.cpp | 2 +- libraries/fbx/src/FST.cpp | 2 +- libraries/fbx/src/GLTFSerializer.cpp | 2 +- libraries/shared/src/BlendshapeConstants.cpp | 4 ++-- libraries/shared/src/BlendshapeConstants.h | 6 ++++-- 7 files changed, 11 insertions(+), 9 deletions(-) diff --git a/interface/src/ModelPackager.cpp b/interface/src/ModelPackager.cpp index c145d40549c..11a6bf43782 100644 --- a/interface/src/ModelPackager.cpp +++ b/interface/src/ModelPackager.cpp @@ -296,7 +296,7 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename mapping.insert(JOINT_FIELD, joints); // If there are no blendshape mappings, and we detect that this is likely a mixamo file, - // then we can add the default mixamo to "faceshift" mappings + // then we can add the default mixamo to blendshape mappings. if (!mapping.contains(BLENDSHAPE_FIELD) && likelyMixamoFile) { QVariantHash blendshapes; blendshapes.insertMulti("BrowsD_L", QVariantList() << "BrowsDown_Left" << 1.0); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index ee0543fa6b4..8e6a746f555 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -157,7 +157,7 @@ void Head::simulate(float deltaTime) { updateEyeLookAt(); } - // use data to update fake Faceshift blendshape coefficients + // Use data to update fake blendshape coefficients. if (getProceduralAnimationFlag(HeadData::AudioProceduralBlendshapeAnimation) && !getSuppressProceduralAnimationFlag(HeadData::AudioProceduralBlendshapeAnimation)) { diff --git a/libraries/fbx/src/FBXSerializer.cpp b/libraries/fbx/src/FBXSerializer.cpp index e6413e30794..9c700be607d 100644 --- a/libraries/fbx/src/FBXSerializer.cpp +++ b/libraries/fbx/src/FBXSerializer.cpp @@ -421,7 +421,7 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const QMultiHash blendshapeIndices; for (int i = 0;; i++) { - hifi::ByteArray blendshapeName = FACESHIFT_BLENDSHAPES[i]; + hifi::ByteArray blendshapeName = BLENDSHAPE_NAMES[i]; if (blendshapeName.isEmpty()) { break; } diff --git a/libraries/fbx/src/FST.cpp b/libraries/fbx/src/FST.cpp index b6f109c217e..fd074099608 100644 --- a/libraries/fbx/src/FST.cpp +++ b/libraries/fbx/src/FST.cpp @@ -84,7 +84,7 @@ FST* FST::createFSTFromModel(const QString& fstPath, const QString& modelFilePat // If there are no blendshape mappings, and we detect that this is likely a mixamo file, - // then we can add the default mixamo to "faceshift" mappings + // then we can add the default mixamo to blendshape mappings. if (likelyMixamoFile) { QVariantHash blendshapes; blendshapes.insertMulti("BrowsD_L", QVariantList() << "BrowsDown_Left" << 1.0); diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 274a1b5dc19..dcf310c6a0c 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1550,7 +1550,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& QMultiHash blendshapeIndices; for (int i = 0;; ++i) { - hifi::ByteArray blendshapeName = FACESHIFT_BLENDSHAPES[i]; + hifi::ByteArray blendshapeName = BLENDSHAPE_NAMES[i]; if (blendshapeName.isEmpty()) { break; } diff --git a/libraries/shared/src/BlendshapeConstants.cpp b/libraries/shared/src/BlendshapeConstants.cpp index 83c8271340e..9035b105298 100644 --- a/libraries/shared/src/BlendshapeConstants.cpp +++ b/libraries/shared/src/BlendshapeConstants.cpp @@ -11,7 +11,7 @@ #include "BlendshapeConstants.h" -const char* FACESHIFT_BLENDSHAPES[] = { +const char* BLENDSHAPE_NAMES[] = { "EyeBlink_L", "EyeBlink_R", "EyeSquint_L", @@ -80,7 +80,7 @@ const char* FACESHIFT_BLENDSHAPES[] = { const QMap BLENDSHAPE_LOOKUP_MAP = [] { QMap toReturn; for (int i = 0; i < (int)Blendshapes::BlendshapeCount; i++) { - toReturn[FACESHIFT_BLENDSHAPES[i]] = i; + toReturn[BLENDSHAPE_NAMES[i]] = i; } return toReturn; }(); diff --git a/libraries/shared/src/BlendshapeConstants.h b/libraries/shared/src/BlendshapeConstants.h index 33d02de57dc..1c378920883 100644 --- a/libraries/shared/src/BlendshapeConstants.h +++ b/libraries/shared/src/BlendshapeConstants.h @@ -17,8 +17,8 @@ #include -/// The names of the blendshapes expected by Faceshift, terminated with an empty string. -extern const char* FACESHIFT_BLENDSHAPES[]; +/// The names of the supported blendshapes, terminated with an empty string. +extern const char* BLENDSHAPE_NAMES[]; extern const QMap BLENDSHAPE_LOOKUP_MAP; enum class Blendshapes : int { @@ -97,6 +97,8 @@ enum class LegacyBlendshpaes : int { LegacyBlendshapeCount }; +// Original blendshapes were per Faceshift. + // NEW in ARKit // * MouthClose // * MouthUpperUp_L From f9467917915937738bf9827e8f6ec3059ec40ff1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 29 Aug 2020 14:17:13 +1200 Subject: [PATCH 04/11] Make blendshaps work for glTF with single mesh part --- libraries/fbx/src/GLTFSerializer.cpp | 30 +++++++++++----------------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index dcf310c6a0c..109262f9ee1 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1563,26 +1563,25 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& // glTF morph targets may or may not have names. if they are labeled, add them based on // the corresponding names from the FST. otherwise, just add them in the order they are given - mesh.blendshapes.resize(blendshapeMappings.size()); - auto values = blendshapeIndices.values(); + mesh.blendshapes.resize((int)Blendshapes::BlendshapeCount); auto keys = blendshapeIndices.keys(); + auto values = blendshapeIndices.values(); auto names = _file.meshes[node.mesh].extras.targetNames; QVector weights = _file.meshes[node.mesh].weights; - for (int weightedIndex = 0; weightedIndex < values.size(); ++weightedIndex) { - float weight = 0.1f; + for (int weightedIndex = 0; weightedIndex < keys.size(); ++weightedIndex) { + float weight = 1.0f; int indexFromMapping = weightedIndex; int targetIndex = weightedIndex; hfmModel.blendshapeChannelNames.push_back("target_" + QString::number(weightedIndex)); - if (!names.isEmpty()) { + if (!names.isEmpty() && names.contains(keys[weightedIndex])) { targetIndex = names.indexOf(keys[weightedIndex]); indexFromMapping = values[weightedIndex].first; - weight = weight * values[weightedIndex].second; + weight = values[weightedIndex].second; hfmModel.blendshapeChannelNames[weightedIndex] = keys[weightedIndex]; } HFMBlendshape& blendshape = mesh.blendshapes[indexFromMapping]; - blendshape.indices = part.triangleIndices; auto target = primitive.targets[targetIndex]; QVector normals; @@ -1601,18 +1600,13 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& if (target.values.contains((QString) "POSITION")) { generateTargetData(target.values.value((QString) "POSITION"), weight, vertices); } - bool isNewBlendshape = blendshape.vertices.size() < vertices.size(); - int count = 0; - for (int i : blendshape.indices) { - if (isNewBlendshape) { - blendshape.vertices.push_back(vertices[i]); - blendshape.normals.push_back(normals[i]); - } else { - blendshape.vertices[count] = blendshape.vertices[count] + vertices[i]; - blendshape.normals[count] = blendshape.normals[count] + normals[i]; - ++count; - } + + for (int i = 0; i < vertices.size(); i++) { + blendshape.indices.push_back(i); + blendshape.vertices.push_back(vertices.value(i)); + blendshape.normals.push_back(normals.value(i)); } + } } From a819b140dc29171fd2a8767771e4366c1d8dd0c6 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 29 Aug 2020 14:17:54 +1200 Subject: [PATCH 05/11] Don't weight blendshapes by default blendshape values --- libraries/fbx/src/GLTFSerializer.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 109262f9ee1..d503a374757 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1567,7 +1567,6 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& auto keys = blendshapeIndices.keys(); auto values = blendshapeIndices.values(); auto names = _file.meshes[node.mesh].extras.targetNames; - QVector weights = _file.meshes[node.mesh].weights; for (int weightedIndex = 0; weightedIndex < keys.size(); ++weightedIndex) { float weight = 1.0f; @@ -1587,13 +1586,6 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& QVector normals; QVector vertices; - if (weights.size() == primitive.targets.size()) { - int targetWeight = weights[targetIndex]; - if (targetWeight != 0) { - weight = weight * targetWeight; - } - } - if (target.values.contains((QString) "NORMAL")) { generateTargetData(target.values.value((QString) "NORMAL"), weight, normals); } From 128745ef36c89858eb8c598feea12aa71358b59e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 29 Aug 2020 16:11:35 +1200 Subject: [PATCH 06/11] Make blendshapes work for glTF with multiple mesh parts --- libraries/fbx/src/GLTFSerializer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index d503a374757..8d7688fcff3 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1593,8 +1593,9 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& generateTargetData(target.values.value((QString) "POSITION"), weight, vertices); } + auto blendshapeIndicesCount = blendshape.indices.count(); for (int i = 0; i < vertices.size(); i++) { - blendshape.indices.push_back(i); + blendshape.indices.push_back(blendshapeIndicesCount + i); blendshape.vertices.push_back(vertices.value(i)); blendshape.normals.push_back(normals.value(i)); } From 5d02e0fe28860584646b25c94f07c7c0da996ece Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 29 Aug 2020 16:12:10 +1200 Subject: [PATCH 07/11] Fix blendshapes on planar meshes --- libraries/fbx/src/GLTFSerializer.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 8d7688fcff3..cd2e4e27207 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1610,12 +1610,14 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& } } - // Add epsilon to mesh extents to compensate for planar meshes - mesh.meshExtents.minimum -= glm::vec3(EPSILON, EPSILON, EPSILON); - mesh.meshExtents.maximum += glm::vec3(EPSILON, EPSILON, EPSILON); - hfmModel.meshExtents.minimum -= glm::vec3(EPSILON, EPSILON, EPSILON); - hfmModel.meshExtents.maximum += glm::vec3(EPSILON, EPSILON, EPSILON); - + // Mesh extents must be at least minimum entity size, in particular for blendshapes to work on planar meshes. + const float ENTITY_ITEM_MIN_DIMENSION = 0.001f; + auto delta = glm::max(glm::vec3(ENTITY_ITEM_MIN_DIMENSION) - mesh.meshExtents.size(), glm::vec3(0.0f)) / 2.0f; + mesh.meshExtents.minimum -= delta; + mesh.meshExtents.maximum += delta; + hfmModel.meshExtents.minimum -= delta; + hfmModel.meshExtents.maximum += delta; + mesh.meshIndex = hfmModel.meshes.size(); } ++nodecount; From 0fcc73d5cd6a7610adcd58e3d7bef17d3d0b79ba Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 31 Aug 2020 11:20:56 +1200 Subject: [PATCH 08/11] Fix multiple blendshapes targeted to one model blendshape --- libraries/fbx/src/GLTFSerializer.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index cd2e4e27207..337c9d7f703 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1593,11 +1593,15 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& generateTargetData(target.values.value((QString) "POSITION"), weight, vertices); } - auto blendshapeIndicesCount = blendshape.indices.count(); + if (blendshape.indices.size() < prevMeshVerticesCount + vertices.size()) { + blendshape.indices.resize(prevMeshVerticesCount + vertices.size()); + blendshape.vertices.resize(prevMeshVerticesCount + vertices.size()); + blendshape.normals.resize(prevMeshVerticesCount + vertices.size()); + } for (int i = 0; i < vertices.size(); i++) { - blendshape.indices.push_back(blendshapeIndicesCount + i); - blendshape.vertices.push_back(vertices.value(i)); - blendshape.normals.push_back(normals.value(i)); + blendshape.indices[prevMeshVerticesCount + i] = prevMeshVerticesCount + i; + blendshape.vertices[prevMeshVerticesCount + i] += vertices.value(i); + blendshape.normals[prevMeshVerticesCount + i] += normals.value(i); } } From bd1be872a8df25a114f16911a5432dd4a3cc85a3 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 31 Aug 2020 21:31:55 +1200 Subject: [PATCH 09/11] Support using blendshapes in file without needing an FST --- libraries/fbx/src/GLTFSerializer.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 337c9d7f703..806fbd76192 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1544,25 +1544,33 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& // Build morph targets (blend shapes) if (!primitive.targets.isEmpty()) { - // Build list of blendshapes from FST + // Build list of blendshapes from FST and model. typedef QPair WeightedIndex; hifi::VariantHash blendshapeMappings = mapping.value("bs").toHash(); QMultiHash blendshapeIndices; for (int i = 0;; ++i) { - hifi::ByteArray blendshapeName = BLENDSHAPE_NAMES[i]; + auto blendshapeName = QString(BLENDSHAPE_NAMES[i]); if (blendshapeName.isEmpty()) { break; } - QList mappings = blendshapeMappings.values(blendshapeName); - foreach (const QVariant& mapping, mappings) { - QVariantList blendshapeMapping = mapping.toList(); - blendshapeIndices.insert(blendshapeMapping.at(0).toByteArray(), WeightedIndex(i, blendshapeMapping.at(1).toFloat())); + auto mappings = blendshapeMappings.values(blendshapeName); + if (mappings.count() > 0) { + // Use blendshape from mapping. + foreach(const QVariant& mapping, mappings) { + auto blendshapeMapping = mapping.toList(); + blendshapeIndices.insert(blendshapeMapping.at(0).toString(), + WeightedIndex(i, blendshapeMapping.at(1).toFloat())); + } + } else { + // Use blendshape from model. + if (_file.meshes[node.mesh].extras.targetNames.contains(blendshapeName)) { + blendshapeIndices.insert(blendshapeName, WeightedIndex(i, 1.0f)); + } } } - // glTF morph targets may or may not have names. if they are labeled, add them based on - // the corresponding names from the FST. otherwise, just add them in the order they are given + // Create blendshapes. mesh.blendshapes.resize((int)Blendshapes::BlendshapeCount); auto keys = blendshapeIndices.keys(); auto values = blendshapeIndices.values(); From 22e6ae97102c36bf44753e247aaf8dc9f01f5d5c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 31 Aug 2020 21:44:19 +1200 Subject: [PATCH 10/11] Fix hasBlendedMeshes() value --- libraries/fbx/src/GLTFSerializer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 806fbd76192..ad0987410cd 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1571,7 +1571,9 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& } // Create blendshapes. - mesh.blendshapes.resize((int)Blendshapes::BlendshapeCount); + if (!blendshapeIndices.isEmpty()) { + mesh.blendshapes.resize((int)Blendshapes::BlendshapeCount); + } auto keys = blendshapeIndices.keys(); auto values = blendshapeIndices.values(); auto names = _file.meshes[node.mesh].extras.targetNames; From 9fc9b203aed86c5b60a27606ffae503f0a196977 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 2 Sep 2020 12:45:44 +1200 Subject: [PATCH 11/11] Rename constant --- libraries/fbx/src/GLTFSerializer.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index ad0987410cd..3d2a7edca89 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1624,9 +1624,10 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& } } - // Mesh extents must be at least minimum entity size, in particular for blendshapes to work on planar meshes. - const float ENTITY_ITEM_MIN_DIMENSION = 0.001f; - auto delta = glm::max(glm::vec3(ENTITY_ITEM_MIN_DIMENSION) - mesh.meshExtents.size(), glm::vec3(0.0f)) / 2.0f; + // Mesh extents must be at least a minimum size, in particular for blendshapes to work on planar meshes. + const float MODEL_MIN_DIMENSION = 0.001f; + auto x = EPSILON; + auto delta = glm::max(glm::vec3(MODEL_MIN_DIMENSION) - mesh.meshExtents.size(), glm::vec3(0.0f)) / 2.0f; mesh.meshExtents.minimum -= delta; mesh.meshExtents.maximum += delta; hfmModel.meshExtents.minimum -= delta;