Пример #1
0
        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);
        }
Пример #2
0
        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;
                    }
                }
            }
        }