diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Plugins/GLTFSerialization/Schema/GLTFMesh.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Plugins/GLTFSerialization/Schema/GLTFMesh.cs index ba35dcd6a..cbb5723a2 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Plugins/GLTFSerialization/Schema/GLTFMesh.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Plugins/GLTFSerialization/Schema/GLTFMesh.cs @@ -101,7 +101,7 @@ public static GLTFMesh Deserialize(GLTFRoot root, JsonReader reader) foreach (MeshPrimitive mp in mesh.Primitives) { if (mp == null) continue; - mp.TargetNames = mesh.TargetNames; + if(mp.Targets == null || mp.Targets.Count != mesh.TargetNames.Count) throw new GLTFParseException("Invalid number of morphtarget names on mesh!"); } } } diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Plugins/GLTFSerialization/Schema/MeshPrimitive.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Plugins/GLTFSerialization/Schema/MeshPrimitive.cs index 59f1960a0..dd358ebac 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Plugins/GLTFSerialization/Schema/MeshPrimitive.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Plugins/GLTFSerialization/Schema/MeshPrimitive.cs @@ -219,7 +219,7 @@ public static MeshPrimitive Deserialize(GLTFRoot root, JsonReader reader) skipStartObjectRead: true); }); break; - case "extras": + /*case "extras": // GLTF does not support morph target names, serialize in extras for now // https://github.com/KhronosGroup/glTF/issues/1036 if (reader.Read() && reader.TokenType == JsonToken.StartObject) @@ -236,12 +236,39 @@ public static MeshPrimitive Deserialize(GLTFRoot root, JsonReader reader) } } - break; + break;*/ default: primitive.DefaultPropertyDeserializer(root, reader); break; } } + + // GLTF does not support morph target names, serialize in extras for now + // https://github.com/KhronosGroup/glTF/issues/1036 + if (primitive.Extras != null) + { + var extrasReader = primitive.Extras.CreateReader(); + extrasReader.Read(); + + while (extrasReader.Read() && extrasReader.TokenType == JsonToken.PropertyName) + { + var extraProperty = extrasReader.Value.ToString(); + switch (extraProperty) + { + case "targetNames": + primitive.TargetNames = extrasReader.ReadStringList(); + break; + default: + extrasReader.Skip(); + break; + } + } + + extrasReader.Close(); + + if (primitive.TargetNames != null && primitive.TargetNames.Count > 0 && (primitive.Targets == null || primitive.Targets.Count != primitive.TargetNames.Count)) + throw new GLTFParseException("Invalid number of morphtarget names on primitive!"); + } return primitive; } diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneImporter/ImporterMeshes.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneImporter/ImporterMeshes.cs index 8323a03cf..df1e0b009 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneImporter/ImporterMeshes.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneImporter/ImporterMeshes.cs @@ -150,15 +150,29 @@ protected async Task ConstructUnityMesh(UnityMeshData unityMeshData, int meshInd if (unityMeshData.MorphTargetVertices != null) { - var firstPrim = _gltfRoot.Meshes[meshIndex].Primitives[0]; - for (int i = 0; i < firstPrim.Targets.Count; i++) - { - var targetName = firstPrim.TargetNames != null ? firstPrim.TargetNames[i] : $"Morphtarget{i}"; - mesh.AddBlendShapeFrame(targetName, 100, - unityMeshData.MorphTargetVertices[i], - unityMeshData.MorphTargetNormals != null ? unityMeshData.MorphTargetNormals[i] : null, - unityMeshData.MorphTargetTangents != null ? unityMeshData.MorphTargetTangents[i] : null - ); + if(_gltfRoot.Meshes[meshIndex].TargetNames != null && _gltfRoot.Meshes[meshIndex].TargetNames.Count > 0) + { // Get target names from mesh extras + for (int i = 0; i < _gltfRoot.Meshes[meshIndex].TargetNames.Count; i++) + { + var targetName = _gltfRoot.Meshes[meshIndex].TargetNames[i] != null && _gltfRoot.Meshes[meshIndex].TargetNames[i].Length > 0 ? _gltfRoot.Meshes[meshIndex].TargetNames[i] : $"Morphtarget{i}"; + mesh.AddBlendShapeFrame(targetName, 100, + unityMeshData.MorphTargetVertices[i], + unityMeshData.MorphTargetNormals != null ? unityMeshData.MorphTargetNormals[i] : null, + unityMeshData.MorphTargetTangents != null ? unityMeshData.MorphTargetTangents[i] : null + ); + } + } else { + // Get target names from first primitive's extras + var firstPrim = _gltfRoot.Meshes[meshIndex].Primitives[0]; + for (int i = 0; i < firstPrim.Targets.Count; i++) + { + var targetName = firstPrim.TargetNames != null ? firstPrim.TargetNames[i] : $"Morphtarget{i}"; + mesh.AddBlendShapeFrame(targetName, 100, + unityMeshData.MorphTargetVertices[i], + unityMeshData.MorphTargetNormals != null ? unityMeshData.MorphTargetNormals[i] : null, + unityMeshData.MorphTargetTangents != null ? unityMeshData.MorphTargetTangents[i] : null + ); + } } } await YieldOnTimeoutAndThrowOnLowMemory();