예제 #1
0
        private List <AnimationClip> ImportAnimationClips(glTF gltf, Axises invertAxis)
        {
            var animationClips = new List <AnimationClip>();

            for (var i = 0; i < gltf.animations.Count; ++i)
            {
                var clip = new AnimationClip();
                clip.ClearCurves();
                clip.legacy = true;
                clip.name   = gltf.animations[i].name;
                if (string.IsNullOrEmpty(clip.name))
                {
                    clip.name = $"legacy_{i}";
                }
                clip.wrapMode = WrapMode.Loop;

                var animation = gltf.animations[i];
                if (string.IsNullOrEmpty(animation.name))
                {
                    animation.name = $"animation:{i}";
                }

                AxisInverter inverter = default;
                switch (invertAxis)
                {
                case Axises.X:
                    inverter = AxisInverter.ReverseX;
                    break;

                case Axises.Z:
                    inverter = AxisInverter.ReverseZ;
                    break;

                default:
                    throw new System.Exception();
                }

                animationClips.Add(AnimationImporterUtil.ConvertAnimationClip(gltf, animation, inverter));
            }

            return(animationClips);
        }
예제 #2
0
        public static void SetupSkinning(ImporterContext context, List <TransformWithSkin> nodes, int i, AxisInverter inverter)
        {
            var x = nodes[i];
            var skinnedMeshRenderer = x.Transform.GetComponent <SkinnedMeshRenderer>();

            if (skinnedMeshRenderer != null)
            {
                var mesh = skinnedMeshRenderer.sharedMesh;
                if (x.SkinIndex.HasValue)
                {
                    if (mesh == null)
                    {
                        throw new Exception();
                    }
                    if (skinnedMeshRenderer == null)
                    {
                        throw new Exception();
                    }

                    if (x.SkinIndex.Value < context.GLTF.skins.Count)
                    {
                        // calculate internal values(boundingBox etc...) when sharedMesh assigned ?
                        skinnedMeshRenderer.sharedMesh = null;

                        var skin   = context.GLTF.skins[x.SkinIndex.Value];
                        var joints = skin.joints.Select(y => nodes[y].Transform).ToArray();
                        if (joints.Any())
                        {
                            // have bones
                            skinnedMeshRenderer.bones = joints;

                            if (skin.inverseBindMatrices != -1)
                            {
                                var bindPoses = context.GLTF.GetArrayFromAccessor <Matrix4x4>(skin.inverseBindMatrices)
                                                .Select(inverter.InvertMat4)
                                                .ToArray()
                                ;
                                mesh.bindposes = bindPoses;
                            }
                            else
                            {
                                //
                                // calc default matrices
                                // https://docs.unity3d.com/ScriptReference/Mesh-bindposes.html
                                //
                                var meshCoords          = skinnedMeshRenderer.transform; // ?
                                var calculatedBindPoses = joints.Select(y => y.worldToLocalMatrix * meshCoords.localToWorldMatrix).ToArray();
                                mesh.bindposes = calculatedBindPoses;
                            }
                        }
                        else
                        {
                            // BlendShape only ?
                        }

                        skinnedMeshRenderer.sharedMesh = mesh;
                        if (skin.skeleton >= 0 && skin.skeleton < nodes.Count)
                        {
                            skinnedMeshRenderer.rootBone = nodes[skin.skeleton].Transform;
                        }
                    }
                }
            }
        }
예제 #3
0
        public static AnimationClip ConvertAnimationClip(glTF gltf, glTFAnimation animation, AxisInverter inverter, 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(gltf.nodes, root, gltf.nodes[channel.target.node]);
                switch (channel.target.path)
                {
                case glTFAnimationTarget.PATH_TRANSLATION:
                {
                    var sampler = animation.samplers[channel.sampler];
                    var input   = gltf.GetArrayFromAccessor <float>(sampler.input);
                    var output  = gltf.FlatternFloatArrayFromAccessor(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(inverter.InvertVector3(temp).ToArray());
                        }
                        );
                }
                break;

                case glTFAnimationTarget.PATH_ROTATION:
                {
                    var sampler = animation.samplers[channel.sampler];
                    var input   = gltf.GetArrayFromAccessor <float>(sampler.input);
                    var output  = gltf.FlatternFloatArrayFromAccessor(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, inverter.InvertQuaternion(currentQuaternion)).ToArray());
                        }
                        );

                    clip.EnsureQuaternionContinuity();
                }
                break;

                case glTFAnimationTarget.PATH_SCALE:
                {
                    var sampler = animation.samplers[channel.sampler];
                    var input   = gltf.GetArrayFromAccessor <float>(sampler.input);
                    var output  = gltf.FlatternFloatArrayFromAccessor(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      = gltf.nodes[channel.target.node];
                    var mesh      = gltf.meshes[node.mesh];
                    var primitive = mesh.primitives.FirstOrDefault();
                    var targets   = primitive.targets;

                    if (!gltf_mesh_extras_targetNames.TryGet(mesh, out List <string> targetNames))
                    {
                        throw new Exception("glTF BlendShape Animation. targetNames invalid.");
                    }

                    var keyNames = targetNames
                                   .Where(x => !string.IsNullOrEmpty(x))
                                   .Select(x => "blendShape." + x)
                                   .ToArray();

                    var sampler = animation.samplers[channel.sampler];
                    var input   = gltf.GetArrayFromAccessor <float>(sampler.input);
                    var output  = 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);
        }
예제 #4
0
        //
        // fix node's coordinate. z-back to z-forward
        //
        public static void FixCoordinate(ImporterContext context, List <TransformWithSkin> nodes, AxisInverter inverter)
        {
            var globalTransformMap = nodes.ToDictionary(x => x.Transform, x => new PosRot
            {
                Position = x.Transform.position,
                Rotation = x.Transform.rotation,
            });

            foreach (var x in context.GLTF.rootnodes)
            {
                // fix nodes coordinate
                // reverse Z in global
                var t = nodes[x].Transform;
                //t.SetParent(root.transform, false);

                foreach (var transform in t.Traverse())
                {
                    var g = globalTransformMap[transform];
                    transform.position = inverter.InvertVector3(g.Position);
                    transform.rotation = inverter.InvertQuaternion(g.Rotation);
                }
            }
        }