public static List <AnimationClip> ImportAnimationClip(ImporterContext ctx) { List <AnimationClip> animationClips = new List <AnimationClip>(); for (int i = 0; i < ctx.GLTF.animations.Count; ++i) { var clip = new AnimationClip(); clip.ClearCurves(); clip.legacy = true; clip.name = ctx.GLTF.animations[i].name; if (string.IsNullOrEmpty(clip.name)) { clip.name = "legacy_" + i; } clip.wrapMode = WrapMode.Loop; var animation = ctx.GLTF.animations[i]; if (string.IsNullOrEmpty(animation.name)) { animation.name = string.Format("animation:{0}", i); } foreach (var channel in animation.channels) { var targetTransform = ctx.Nodes[channel.target.node]; var relativePath = targetTransform.RelativePathFrom(ctx.Root.transform); switch (channel.target.path) { case glTFAnimationTarget.PATH_TRANSLATION: { var sampler = animation.samplers[channel.sampler]; var input = ctx.GLTF.GetArrayFromAccessor <float>(sampler.input); var output = ctx.GLTF.GetArrayFromAccessorAsFloat(sampler.output); AnimationImporter.SetAnimationCurve( clip, relativePath, new string[] { "localPosition.x", "localPosition.y", "localPosition.z" }, input, output, sampler.interpolation, typeof(Transform), (values, last) => { Vector3 temp = new Vector3(values[0], values[1], values[2]); return(temp.ReverseZ().ToArray()); } ); } break; case glTFAnimationTarget.PATH_ROTATION: { var sampler = animation.samplers[channel.sampler]; var input = ctx.GLTF.GetArrayFromAccessor <float>(sampler.input); var output = ctx.GLTF.GetArrayFromAccessorAsFloat(sampler.output); AnimationImporter.SetAnimationCurve( clip, relativePath, new string[] { "localRotation.x", "localRotation.y", "localRotation.z", "localRotation.w" }, input, output, sampler.interpolation, typeof(Transform), (values, last) => { Quaternion currentQuaternion = new Quaternion(values[0], values[1], values[2], values[3]); Quaternion lastQuaternion = new Quaternion(last[0], last[1], last[2], last[3]); return(AnimationImporter.GetShortest(lastQuaternion, currentQuaternion.ReverseZ()).ToArray()); } ); clip.EnsureQuaternionContinuity(); } break; case glTFAnimationTarget.PATH_SCALE: { var sampler = animation.samplers[channel.sampler]; var input = ctx.GLTF.GetArrayFromAccessor <float>(sampler.input); var output = ctx.GLTF.GetArrayFromAccessorAsFloat(sampler.output); AnimationImporter.SetAnimationCurve( clip, relativePath, new string[] { "localScale.x", "localScale.y", "localScale.z" }, input, output, sampler.interpolation, typeof(Transform), (values, last) => values); } break; case glTFAnimationTarget.PATH_WEIGHT: { var node = ctx.GLTF.nodes[channel.target.node]; var mesh = ctx.GLTF.meshes[node.mesh]; //var primitive = mesh.primitives.FirstOrDefault(); //var targets = primitive.targets; List <string> blendShapeNames = new List <string>(); var transform = ctx.Nodes[channel.target.node]; var skinnedMeshRenderer = transform.GetComponent <SkinnedMeshRenderer>(); if (skinnedMeshRenderer == null) { continue; } for (int j = 0; j < skinnedMeshRenderer.sharedMesh.blendShapeCount; j++) { blendShapeNames.Add(skinnedMeshRenderer.sharedMesh.GetBlendShapeName(j)); } var keyNames = blendShapeNames .Where(x => !string.IsNullOrEmpty(x)) .Select(x => "blendShape." + x) .ToArray(); var sampler = animation.samplers[channel.sampler]; var input = ctx.GLTF.GetArrayFromAccessor <float>(sampler.input); var output = ctx.GLTF.GetArrayFromAccessor <float>(sampler.output); AnimationImporter.SetAnimationCurve( clip, relativePath, keyNames, input, output, sampler.interpolation, typeof(SkinnedMeshRenderer), (values, last) => { for (int j = 0; j < values.Length; j++) { values[j] *= 100.0f; } return(values); }); } break; default: Debug.LogWarningFormat("unknown path: {0}", channel.target.path); break; } } animationClips.Add(clip); } return(animationClips); }
public static void ImportAnimation(ImporterContext ctx, AnimationClip clip) { for (int i = 0; i < ctx.GLTF.animations.Count; ++i) { var animation = ctx.GLTF.animations[i]; if (string.IsNullOrEmpty(animation.name)) { animation.name = string.Format("animation:{0}", i); } foreach (var channel in animation.channels) { var targetTransform = ctx.Nodes[channel.target.node]; var relativePath = targetTransform.RelativePathFrom(ctx.Root.transform); switch (channel.target.path) { case glTFAnimationTarget.PATH_TRANSLATION: { var sampler = animation.samplers[channel.sampler]; var input = ctx.GLTF.GetArrayFromAccessor <float>(sampler.input); var output = ctx.GLTF.GetArrayFromAccessorAsFloat(sampler.output); AnimationImporter.SetAnimationCurve( clip, relativePath, new string[] { "localPosition.x", "localPosition.y", "localPosition.z" }, input, output, sampler.interpolation, (values, last) => { Vector3 temp = new Vector3(values[0], values[1], values[2]); return(temp.ReverseZ().ToArray()); } ); } break; case glTFAnimationTarget.PATH_ROTATION: { var sampler = animation.samplers[channel.sampler]; var input = ctx.GLTF.GetArrayFromAccessor <float>(sampler.input); var output = ctx.GLTF.GetArrayFromAccessorAsFloat(sampler.output); AnimationImporter.SetAnimationCurve( clip, relativePath, new string[] { "localRotation.x", "localRotation.y", "localRotation.z", "localRotation.w" }, input, output, sampler.interpolation, (values, last) => { Quaternion currentQuaternion = new Quaternion(values[0], values[1], values[2], values[3]); Quaternion lastQuaternion = new Quaternion(last[0], last[1], last[2], last[3]); return(AnimationImporter.GetShortest(lastQuaternion, currentQuaternion.ReverseZ()).ToArray()); } ); clip.EnsureQuaternionContinuity(); } break; case glTFAnimationTarget.PATH_SCALE: { var sampler = animation.samplers[channel.sampler]; var input = ctx.GLTF.GetArrayFromAccessor <float>(sampler.input); var output = ctx.GLTF.GetArrayFromAccessorAsFloat(sampler.output); AnimationImporter.SetAnimationCurve( clip, relativePath, new string[] { "localScale.x", "localScale.y", "localScale.z" }, input, output, sampler.interpolation, (values, last) => values); } break; case glTFAnimationTarget.PATH_WEIGHT: { var node = ctx.GLTF.nodes[channel.target.node]; var mesh = ctx.GLTF.meshes[node.mesh]; for (int k = 0; k < mesh.weights.Length; ++k) { //var weight = mesh.weights[k]; var curve = new AnimationCurve(); var sampler = animation.samplers[channel.sampler]; var input = ctx.GLTF.GetArrayFromAccessor <float>(sampler.input); var output = ctx.GLTF.GetArrayFromAccessor <float>(sampler.output); for (int j = 0, l = k; j < input.Length; ++j, l += mesh.weights.Length) { curve.AddKey(input[j], output[l] * 100); } clip.SetCurve(relativePath, typeof(SkinnedMeshRenderer), "blendShape." + k, curve); } } break; default: Debug.LogWarningFormat("unknown path: {0}", channel.target.path); break; } } } }