private static glTFNode ExportNode(Transform x, List <Transform> nodes, List <Renderer> renderers,
                                           List <SkinnedMeshRenderer> skins)
        {
            var node = new glTFNode
            {
                name        = x.name,
                children    = x.transform.GetChildren().Select(y => nodes.IndexOf(y)).ToArray(),
                rotation    = x.transform.localRotation.ToArray(),
                translation = x.transform.localPosition.ToArray(),
                scale       = x.transform.localScale.ToArray(),
            };

            if (x.gameObject.activeInHierarchy)
            {
                var meshRenderer = x.GetComponent <MeshRenderer>();
                if (meshRenderer != null)
                {
                    node.mesh = renderers.IndexOf(meshRenderer);
                }

                var skinnredMeshRenderer = x.GetComponent <SkinnedMeshRenderer>();
                if (skinnredMeshRenderer != null)
                {
                    node.mesh = renderers.IndexOf(skinnredMeshRenderer);
                    node.skin = skins.IndexOf(skinnredMeshRenderer);
                }
            }

            return(node);
        }
Beispiel #2
0
        private static string RelativePathFrom(List <glTFNode> nodes, glTFNode root, glTFNode target, List <string> path)
        {
            if (path.Count == 0)
            {
                path.Add(target.name);
            }

            var targetIndex = nodes.IndexOf(target);

            foreach (var parent in nodes)
            {
                if (parent.children == null || parent.children.Length == 0)
                {
                    continue;
                }

                foreach (var child in parent.children)
                {
                    if (child != targetIndex)
                    {
                        continue;
                    }

                    if (parent == root)
                    {
                        return(string.Join("/", path));
                    }

                    path.Insert(0, parent.name);
                    return(RelativePathFrom(nodes, root, parent, path));
                }
            }

            return(string.Join("/", path));
        }
Beispiel #3
0
        public static string RelativePathFrom(List <glTFNode> nodes, glTFNode root, glTFNode target)
        {
            if (root == target)
            {
                return("");
            }
            var path = new List <string>();

            return(RelativePathFrom(nodes, root, target, path));
        }
Beispiel #4
0
        public static GameObject ImportNode(glTFNode node, int nodeIndex)
        {
            var nodeName = node.name;

            if (!string.IsNullOrEmpty(nodeName) && nodeName.Contains("/"))
            {
                Debug.LogWarningFormat("node {0} contains /. replace _", node.name);
                nodeName = nodeName.Replace("/", "_");
            }
            if (string.IsNullOrEmpty(nodeName))
            {
                nodeName = string.Format("nodeIndex_{0}", nodeIndex);
            }
            var go = new GameObject(nodeName);

            //
            // transform
            //
            if (node.translation != null && node.translation.Length > 0)
            {
                go.transform.localPosition = new Vector3(
                    node.translation[0],
                    node.translation[1],
                    node.translation[2]);
            }
            if (node.rotation != null && node.rotation.Length > 0)
            {
                go.transform.localRotation = new Quaternion(
                    node.rotation[0],
                    node.rotation[1],
                    node.rotation[2],
                    node.rotation[3]);
            }
            if (node.scale != null && node.scale.Length > 0)
            {
                go.transform.localScale = new Vector3(
                    node.scale[0],
                    node.scale[1],
                    node.scale[2]);
            }
            if (node.matrix != null && node.matrix.Length > 0)
            {
                var m = UnityExtensions.MatrixFromArray(node.matrix);
                go.transform.localRotation = m.ExtractRotation();
                go.transform.localPosition = m.ExtractPosition();
                go.transform.localScale    = m.ExtractScale();
            }
            return(go);
        }
Beispiel #5
0
        public void NodeTestError()
        {
            var model = new glTFNode()
            {
                name   = "a",
                camera = -2,
            };

            var c = new JsonSchemaValidationContext("")
            {
                EnableDiagnosisForNotRequiredFields = true,
            };
            var ex = Assert.Throws <JsonSchemaValidationException>(
                () => JsonSchema.FromType <glTFNode>().Serialize(model, c)
                );

            Assert.AreEqual("[camera.String] minimum: ! -2>=0", ex.Message);
        }
Beispiel #6
0
        public void NodeMeshTest()
        {
            var model = new glTFNode()
            {
                name   = "a",
                mesh   = 2,
                skin   = 0,
                camera = -1,
            };

            var c = new JsonSchemaValidationContext("")
            {
                EnableDiagnosisForNotRequiredFields = true,
            };
            var json = JsonSchema.FromType <glTFNode>().Serialize(model, c);

            Assert.AreEqual(@"{""name"":""a"",""mesh"":2,""skin"":0,""extras"":{}}", json);
        }
Beispiel #7
0
        static glTFNode ExportNode(Transform x, List <Transform> nodes, List <MeshWithRenderer> meshAndRenderers, List <SkinnedMeshRenderer> skins)
        {
            var node = new glTFNode
            {
                name        = x.name,
                children    = x.transform.GetChildren().Select(y => nodes.IndexOf(y)).ToArray(),
                rotation    = x.transform.localRotation.ToArray(),
                translation = x.transform.localPosition.ToArray(),
                scale       = x.transform.localScale.ToArray(),
            };

            if (x.gameObject.activeInHierarchy)
            {
                var skinnedMeshRenderer = x.GetComponent <SkinnedMeshRenderer>();
                if (skinnedMeshRenderer != null)
                {
                    var mesh      = skinnedMeshRenderer.sharedMesh;
                    var materials = skinnedMeshRenderer.sharedMaterials;
                    var meshIndex = -1;
                    for (var i = 0; i < meshAndRenderers.Count; i++)
                    {
                        if (meshAndRenderers[i].IsSameMeshAndMaterials(mesh, materials))
                        {
                            meshIndex = i;
                            break;
                        }
                    }

                    if (meshIndex == -1)
                    {
                        throw new Exception("Mesh not found.");
                    }

                    node.mesh = meshIndex;
                    node.skin = skins.IndexOf(skinnedMeshRenderer);
                }
                else
                {
                    var meshFilter   = x.GetComponent <MeshFilter>();
                    var meshRenderer = x.GetComponent <MeshRenderer>();
                    if (meshFilter != null && meshRenderer != null && !x.HasTextMeshProComponent())
                    {
                        var mesh      = meshFilter.sharedMesh;
                        var materials = meshRenderer.sharedMaterials;
                        if (mesh != null && materials != null && materials.Length > 0)
                        {
                            var meshIndex = -1;
                            for (var i = 0; i < meshAndRenderers.Count; i++)
                            {
                                if (meshAndRenderers[i].IsSameMeshAndMaterials(mesh, materials))
                                {
                                    meshIndex = i;
                                    break;
                                }
                            }
                            if (meshIndex == -1)
                            {
                                throw new Exception("Mesh not found.");
                            }
                            node.mesh = meshIndex;
                        }
                    }
                }
            }
            return(node);
        }
Beispiel #8
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);
        }