예제 #1
0
        public void RelativePathFromTest()
        {
            var nodes = new List <glTFNode>();

            for (var i = 0; i < 10; i++)
            {
                nodes.Add(new glTFNode()
                {
                    name = $"node{i}"
                });
            }

            nodes[0].children = new[] { 1, 2 };
            nodes[2].children = new[] { 3, 4 };
            nodes[4].children = new[] { 5, 6, 7 };

            string res = null;

            res = AnimationImporterUtil.RelativePathFrom(nodes, null, nodes[0]);
            Assert.AreEqual("node0", res);

            res = AnimationImporterUtil.RelativePathFrom(nodes, null, nodes[8]);
            Assert.AreEqual("node8", res);

            res = AnimationImporterUtil.RelativePathFrom(nodes, null, nodes[4]);
            Assert.AreEqual("node0/node2/node4", res);

            res = AnimationImporterUtil.RelativePathFrom(nodes, null, nodes[7]);
            Assert.AreEqual("node0/node2/node4/node7", res);

            res = AnimationImporterUtil.RelativePathFrom(nodes, nodes[0], nodes[4]);
            Assert.AreEqual("node2/node4", res);

            res = AnimationImporterUtil.RelativePathFrom(nodes, nodes[0], nodes[7]);
            Assert.AreEqual("node2/node4/node7", res);

            res = AnimationImporterUtil.RelativePathFrom(nodes, nodes[2], nodes[7]);
            Assert.AreEqual("node4/node7", res);

            // rootとtargetが同じ場合は空になる。
            res = AnimationImporterUtil.RelativePathFrom(nodes, nodes[4], nodes[4]);
            Assert.AreEqual("", res);

            // rootとtargetがnullの場合は空になる。
            res = AnimationImporterUtil.RelativePathFrom(nodes, null, null);
            Assert.AreEqual("", res);

            // rootよりもtargetが下層の場合は、rootを無視する。
            res = AnimationImporterUtil.RelativePathFrom(nodes, nodes[7], nodes[4]);
            Assert.AreEqual("node0/node2/node4", res);
        }
예제 #2
0
        public static AnimationClip ImportAnimationClip(ImporterContext ctx, glTFAnimation animation, glTFNode root = null)
        {
            var clip = new AnimationClip();

            clip.ClearCurves();
            clip.legacy   = true;
            clip.name     = animation.name;
            clip.wrapMode = WrapMode.Loop;

            foreach (var channel in animation.channels)
            {
                var relativePath = RelativePathFrom(ctx.GLTF.nodes, root, ctx.GLTF.nodes[channel.target.node]);
                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);

                    AnimationImporterUtil.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);

                    AnimationImporterUtil.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(AnimationImporterUtil.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);

                    AnimationImporterUtil.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);
                    AnimationImporterUtil.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;
                }
            }
            return(clip);
        }
예제 #3
0
        public void Import(ImporterContext context)
        {
            var animationClips = new AnimationClip[context.GLTF.animations.Count];

            // node extension animation
            for (int i = 0; i < context.GLTF.nodes.Count; i++)
            {
                var node = context.GLTF.nodes[i];
                if (node.extensions == null || node.extensions.VCAST_vci_animation == null)
                {
                    continue;
                }

                var vciAnimation = node.extensions.VCAST_vci_animation;
                var root         = context.Nodes[i];
                var animation    = root.gameObject.AddComponent <Animation>();

                foreach (var animationReference in vciAnimation.animationReferences)
                {
                    var           gltfAnimation = context.GLTF.animations[animationReference.animation];
                    AnimationClip clip          = null;
                    if (animationClips[animationReference.animation] == null)
                    {
                        clip = AnimationImporterUtil.ImportAnimationClip(context, gltfAnimation, root);
                        animationClips[animationReference.animation] = clip;
                    }
                    else
                    {
                        clip = animationClips[animationReference.animation];
                    }

                    if (clip != null)
                    {
                        animation.AddClip(clip, clip.name);
                    }
                }
            }

            // root animation
            var rootAnimation = context.Root.GetComponent <Animation>();

            if (rootAnimation == null)
            {
                rootAnimation = context.Root.AddComponent <Animation>();
            }

            for (int i = 0; i < animationClips.Length; i++)
            {
                if (animationClips[i] != null)
                {
                    continue;
                }

                var gltfAnimation = context.GLTF.animations[i];

                animationClips[i] = AnimationImporterUtil.ImportAnimationClip(context, gltfAnimation, context.Root.transform);
                rootAnimation.AddClip(animationClips[i], animationClips[i].name);
            }

            context.AnimationClips = new List <AnimationClip>(animationClips);
        }