Inheritance: IJsonSerializable
        public static string ToJson(this glTFSkin self)
        {
            var f = new JsonFormatter();

            GltfSerializer.Serialize_gltf_skins_ITEM(f, self);
            return(f.ToString());
        }
 public void SkinTestError()
 {
     var model = new glTFSkin()
     {
         name   = "b",
         joints = new int[] { },
     };
 }
 public void SkinTestErrorNull()
 {
     var model = new glTFSkin()
     {
         name   = "b",
         joints = null,
     };
 }
        public void SkinTest()
        {
            var model = new glTFSkin()
            {
                inverseBindMatrices = 0,
                name   = "b",
                joints = new int[] { 1 },
            };

            var json = model.ToJson();

            Assert.AreEqual(@"{""inverseBindMatrices"":0,""joints"":[1],""name"":""b""}", json);
            Debug.Log(json);
        }
        public void SkinTestEmptyName()
        {
            var model = new glTFSkin()
            {
                name = "",
                inverseBindMatrices = 4,
                joints = new int[] { 1 },
            };

            var json = model.ToJson();

            // "name" = "", not excluded
            Assert.AreEqual(@"{""inverseBindMatrices"":4,""joints"":[1]}", json);
            Debug.Log(json);
        }
Example #6
0
        public void SkinTestError()
        {
            var model = new glTFSkin()
            {
                name   = "b",
                joints = new int[] { },
            };

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

            Assert.AreEqual("[joints.String] minItems", ex.Message);
        }
Example #7
0
        public static void Serialize_gltf_skins_ITEM(JsonFormatter f, glTFSkin value)
        {
            f.BeginMap();


            if (value.inverseBindMatrices >= 0)
            {
                f.Key("inverseBindMatrices");
                f.Value(value.inverseBindMatrices);
            }

            if (value.joints != null && value.joints.Length >= 1)
            {
                f.Key("joints");
                Serialize_gltf_skins__joints(f, value.joints);
            }

            if (value.skeleton >= 0)
            {
                f.Key("skeleton");
                f.Value(value.skeleton);
            }

            if (value.extensions != null)
            {
                f.Key("extensions");
                value.extensions.Serialize(f);
            }

            if (value.extras != null)
            {
                f.Key("extras");
                value.extras.Serialize(f);
            }

            if (!string.IsNullOrEmpty(value.name))
            {
                f.Key("name");
                f.Value(value.name);
            }

            f.EndMap();
        }
Example #8
0
        public void SkinTest()
        {
            var model = new glTFSkin()
            {
                name   = "b",
                joints = new int[] { 1 },
            };

            var json = model.ToJson();

            Assert.AreEqual(@"{""inverseBindMatrices"":-1,""joints"":[1]}", json);
            Debug.Log(json);

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

            Assert.AreEqual(@"{""joints"":[1],""name"":""b""}", json2);
        }
Example #9
0
        public virtual void Export(ITextureSerializer textureSerializer)
        {
            Nodes = Copy.transform.Traverse()
                    .Skip(1) // exclude root object for the symmetry with the importer
                    .ToList();

            var uniqueUnityMeshes = new MeshExportList();

            uniqueUnityMeshes.GetInfo(Nodes, m_settings);

            #region Materials and Textures
            ReportProgress("Materials and Textures", 0.2f);
            Materials = uniqueUnityMeshes.GetUniqueMaterials().ToList();

            _textureExporter = new TextureExporter(textureSerializer);

            var materialExporter = CreateMaterialExporter();
            _gltf.materials = Materials.Select(x => materialExporter.ExportMaterial(x, TextureExporter, m_settings)).ToList();
            #endregion

            #region Meshes
            ReportProgress("Meshes", 0.4f);
            MeshBlendShapeIndexMap = new Dictionary <Mesh, Dictionary <int, int> >();
            foreach (var unityMesh in uniqueUnityMeshes)
            {
                if (!unityMesh.CanExport)
                {
                    continue;
                }

                var(gltfMesh, blendShapeIndexMap) = m_settings.DivideVertexBuffer
                    ? MeshExporter_DividedVertexBuffer.Export(_data, unityMesh, Materials, m_settings.InverseAxis.Create(), m_settings)
                    : MeshExporter_SharedVertexBuffer.Export(_data, unityMesh, Materials, m_settings.InverseAxis.Create(), m_settings)
                ;
                _gltf.meshes.Add(gltfMesh);
                Meshes.Add(unityMesh.Mesh);
                if (!MeshBlendShapeIndexMap.ContainsKey(unityMesh.Mesh))
                {
                    // 重複防止
                    MeshBlendShapeIndexMap.Add(unityMesh.Mesh, blendShapeIndexMap);
                }
            }
            #endregion

            #region Nodes and Skins
            ReportProgress("Nodes and Skins", 0.8f);
            var skins = uniqueUnityMeshes
                        .SelectMany(x => x.Renderers)
                        .Where(x => x.Item1 is SkinnedMeshRenderer && x.UniqueBones != null)
                        .Select(x => x.Item1 as SkinnedMeshRenderer)
                        .ToList()
            ;
            foreach (var node in Nodes)
            {
                var gltfNode = ExportNode(node, Nodes, uniqueUnityMeshes, skins);
                _gltf.nodes.Add(gltfNode);
            }
            _gltf.scenes = new List <gltfScene>
            {
                new gltfScene
                {
                    nodes = Copy.transform.GetChildren().Select(x => Nodes.IndexOf(x)).ToArray(),
                }
            };

            foreach (var x in uniqueUnityMeshes)
            {
                foreach (var(renderer, uniqueBones) in x.Renderers)
                {
                    if (uniqueBones != null && renderer is SkinnedMeshRenderer smr)
                    {
                        var matrices = x.GetBindPoses().Select(m_settings.InverseAxis.Create().InvertMat4).ToArray();
                        var accessor = _data.ExtendBufferAndGetAccessorIndex(matrices, glBufferTarget.NONE);
                        var skin     = new glTFSkin
                        {
                            inverseBindMatrices = accessor,
                            joints   = uniqueBones.Select(y => Nodes.IndexOf(y)).ToArray(),
                            skeleton = Nodes.IndexOf(smr.rootBone),
                        };
                        var skinIndex = _gltf.skins.Count;
                        _gltf.skins.Add(skin);

                        foreach (var z in Nodes.Where(y => y.Has(renderer)))
                        {
                            var nodeIndex = Nodes.IndexOf(z);
                            var node      = _gltf.nodes[nodeIndex];
                            node.skin = skinIndex;
                        }
                    }
                }
            }
            #endregion

#if UNITY_EDITOR
            #region Animations
            ReportProgress("Animations", 0.9f);

            var clips     = new List <AnimationClip>();
            var animator  = Copy.GetComponent <Animator>();
            var animation = Copy.GetComponent <Animation>();
            if (animator != null)
            {
                clips = AnimationExporter.GetAnimationClips(animator);
            }
            else if (animation != null)
            {
                clips = AnimationExporter.GetAnimationClips(animation);
            }

            if (clips.Any())
            {
                foreach (AnimationClip clip in clips)
                {
                    var animationWithCurve = AnimationExporter.Export(clip, Copy.transform, Nodes);

                    foreach (var kv in animationWithCurve.SamplerMap)
                    {
                        var sampler = animationWithCurve.Animation.samplers[kv.Key];

                        var inputAccessorIndex = _data.ExtendBufferAndGetAccessorIndex(kv.Value.Input);
                        sampler.input = inputAccessorIndex;

                        var outputAccessorIndex = _data.ExtendBufferAndGetAccessorIndex(kv.Value.Output);
                        sampler.output = outputAccessorIndex;

                        // modify accessors
                        var outputAccessor = _gltf.accessors[outputAccessorIndex];
                        var channel        = animationWithCurve.Animation.channels.First(x => x.sampler == kv.Key);
                        switch (glTFAnimationTarget.GetElementCount(channel.target.path))
                        {
                        case 1:
                            outputAccessor.type = "SCALAR";
                            //outputAccessor.count = ;
                            break;

                        case 3:
                            outputAccessor.type   = "VEC3";
                            outputAccessor.count /= 3;
                            break;

                        case 4:
                            outputAccessor.type   = "VEC4";
                            outputAccessor.count /= 4;
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                    }
                    animationWithCurve.Animation.name = clip.name;
                    _gltf.animations.Add(animationWithCurve.Animation);
                }
            }
            #endregion
#endif

            ExportExtensions(textureSerializer);

            // Extension で Texture が増える場合があるので最後に呼ぶ
            var exported = _textureExporter.Export();
            for (var exportedTextureIdx = 0; exportedTextureIdx < exported.Count; ++exportedTextureIdx)
            {
                var(unityTexture, colorSpace) = exported[exportedTextureIdx];
                GltfTextureExporter.PushGltfTexture(_data, unityTexture, colorSpace, textureSerializer);
            }

            FixName(_gltf);
        }
Example #10
0
        public void FromGameObject(glTF gltf, GameObject go, bool useSparseAccessorForMorphTarget = false)
        {
            var bytesBuffer = new ArrayByteBuffer(new byte[50 * 1024 * 1024]);
            var bufferIndex = gltf.AddBuffer(bytesBuffer);

            GameObject tmpParent = null;

            if (go.transform.childCount == 0)
            {
                tmpParent = new GameObject("tmpParent");
                go.transform.SetParent(tmpParent.transform, true);
                go = tmpParent;
            }

            try
            {
                Nodes = go.transform.Traverse()
                        .Skip(1) // exclude root object for the symmetry with the importer
                        .ToList();

                #region Materials and Textures
                Materials = Nodes.SelectMany(x => x.GetSharedMaterials()).Where(x => x != null).Distinct().ToList();
                var unityTextures = Materials.SelectMany(x => TextureIO.GetTextures(x)).Where(x => x.Texture != null).Distinct().ToList();

                List <Texture> exportTextures = null;
                Textures = unityTextures.Select(y => y.Texture).ToList();
                var materialExporter = CreateMaterialExporter();
                gltf.materials = Materials.Select(x => materialExporter.ExportMaterial(x, Textures, out exportTextures)).ToList();

                for (int i = 0; i < unityTextures.Count; ++i)
                {
                    var unityTexture = unityTextures[i];
                    TextureIO.ExportTexture(gltf, bufferIndex, exportTextures[i], unityTexture.TextureType);
                }
                #endregion


                #region Meshes
                var unityMeshes = Nodes
                                  .Select(x => new MeshWithRenderer
                {
                    Mesh       = x.GetSharedMesh(),
                    Rendererer = x.GetComponent <Renderer>(),
                })
                                  .Where(x =>
                {
                    if (x.Mesh == null)
                    {
                        return(false);
                    }
                    if (x.Rendererer.sharedMaterials == null ||
                        x.Rendererer.sharedMaterials.Length == 0)
                    {
                        return(false);
                    }

                    return(true);
                })
                                  .ToList();
                ExportMeshes(gltf, bufferIndex, unityMeshes, Materials, useSparseAccessorForMorphTarget);
                Meshes = unityMeshes.Select(x => x.Mesh).ToList();
                #endregion

                #region Skins
                var unitySkins = Nodes
                                 .Select(x => x.GetComponent <SkinnedMeshRenderer>()).Where(x =>
                                                                                            x != null &&
                                                                                            x.bones != null &&
                                                                                            x.bones.Length > 0)
                                 .ToList();
                gltf.nodes  = Nodes.Select(x => ExportNode(x, Nodes, unityMeshes.Select(y => y.Mesh).ToList(), unitySkins)).ToList();
                gltf.scenes = new List <gltfScene>
                {
                    new gltfScene
                    {
                        nodes = go.transform.GetChildren().Select(x => Nodes.IndexOf(x)).ToArray(),
                    }
                };

                foreach (var x in unitySkins)
                {
                    var matrices = x.sharedMesh.bindposes.Select(y => y.ReverseZ()).ToArray();
                    var accessor = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, matrices, glBufferTarget.NONE);

                    var skin = new glTFSkin
                    {
                        inverseBindMatrices = accessor,
                        joints   = x.bones.Select(y => Nodes.IndexOf(y)).ToArray(),
                        skeleton = Nodes.IndexOf(x.rootBone),
                    };
                    var skinIndex = gltf.skins.Count;
                    gltf.skins.Add(skin);

                    foreach (var z in Nodes.Where(y => y.Has(x)))
                    {
                        var nodeIndex = Nodes.IndexOf(z);
                        var node      = gltf.nodes[nodeIndex];
                        node.skin = skinIndex;
                    }
                }
                #endregion

#if UNITY_EDITOR
                #region Animations

                var clips     = new List <AnimationClip>();
                var animator  = go.GetComponent <Animator>();
                var animation = go.GetComponent <Animation>();
                if (animator != null)
                {
                    clips = AnimationExporter.GetAnimationClips(animator);
                }
                else if (animation != null)
                {
                    clips = AnimationExporter.GetAnimationClips(animation);
                }

                if (clips.Any())
                {
                    foreach (AnimationClip clip in clips)
                    {
                        var animationWithCurve = AnimationExporter.Export(clip, go.transform, Nodes);

                        foreach (var kv in animationWithCurve.SamplerMap)
                        {
                            var sampler = animationWithCurve.Animation.samplers[kv.Key];

                            var inputAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Input);
                            sampler.input = inputAccessorIndex;

                            var outputAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Output);
                            sampler.output = outputAccessorIndex;

                            // modify accessors
                            var outputAccessor = gltf.accessors[outputAccessorIndex];
                            var channel        = animationWithCurve.Animation.channels.First(x => x.sampler == kv.Key);
                            switch (glTFAnimationTarget.GetElementCount(channel.target.path))
                            {
                            case 1:
                                outputAccessor.type  = "SCALAR";
                                outputAccessor.count = 1;
                                break;

                            case 3:
                                outputAccessor.type   = "VEC3";
                                outputAccessor.count /= 3;
                                break;

                            case 4:
                                outputAccessor.type   = "VEC4";
                                outputAccessor.count /= 4;
                                break;

                            default:
                                throw new NotImplementedException();
                            }
                        }

                        gltf.animations.Add(animationWithCurve.Animation);
                    }
                }
                #endregion
#endif
            }
            finally
            {
                if (tmpParent != null)
                {
                    tmpParent.transform.GetChild(0).SetParent(null);
                    if (Application.isPlaying)
                    {
                        GameObject.Destroy(tmpParent);
                    }
                    else
                    {
                        GameObject.DestroyImmediate(tmpParent);
                    }
                }
            }
        }
Example #11
0
        public static Exported FromGameObject(glTF gltf, GameObject go, bool useSparseAccessorForMorphTarget = false)
        {
            var bytesBuffer = new ArrayByteBuffer(new byte[50 * 1024 * 1024]);
            var bufferIndex = gltf.AddBuffer(bytesBuffer);

            if (go.transform.childCount == 0)
            {
                throw new UniGLTFException("root node required");
            }

            var unityNodes = go.transform.Traverse()
                             .Skip(1) // exclude root object for the symmetry with the importer
                             .ToList();

            #region Material
            var unityMaterials = unityNodes.SelectMany(x => x.GetSharedMaterials()).Where(x => x != null).Distinct().ToList();
            var unityTextures  = unityMaterials.SelectMany(x => x.GetTextures()).Where(x => x != null).Distinct().ToList();

            for (int i = 0; i < unityTextures.Count; ++i)
            {
                var texture = unityTextures[i];
                ExportTexture(gltf, bufferIndex, texture);
            }

            gltf.materials = unityMaterials.Select(x => ExportMaterial(x, unityTextures)).ToList();
            #endregion

            #region Meshes
            var unityMeshes = unityNodes
                              .Select(x => new MeshWithRenderer
            {
                Mesh       = x.GetSharedMesh(),
                Rendererer = x.GetComponent <Renderer>(),
            })
                              .Where(x => x.Mesh != null)
                              .ToList();
            ExportMeshes(gltf, bufferIndex, unityMeshes, unityMaterials, useSparseAccessorForMorphTarget);
            #endregion

            #region Skins
            var unitySkins = unityNodes
                             .Select(x => x.GetComponent <SkinnedMeshRenderer>()).Where(x => x != null)
                             .ToList();
            gltf.nodes  = unityNodes.Select(x => ExportNode(x, unityNodes, unityMeshes.Select(y => y.Mesh).ToList(), unitySkins)).ToList();
            gltf.scenes = new List <gltfScene>
            {
                new gltfScene
                {
                    nodes = go.transform.GetChildren().Select(x => unityNodes.IndexOf(x)).ToArray(),
                }
            };

            foreach (var x in unitySkins)
            {
                var matrices = x.sharedMesh.bindposes.Select(y => y.ReverseZ()).ToArray();
                var accessor = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, matrices, glBufferTarget.NONE);

                var skin = new glTFSkin
                {
                    inverseBindMatrices = accessor,
                    joints   = x.bones.Select(y => unityNodes.IndexOf(y)).ToArray(),
                    skeleton = unityNodes.IndexOf(x.rootBone),
                };
                var skinIndex = gltf.skins.Count;
                gltf.skins.Add(skin);

                foreach (var z in unityNodes.Where(y => y.Has(x)))
                {
                    var nodeIndex = unityNodes.IndexOf(z);
                    var node      = gltf.nodes[nodeIndex];
                    node.skin = skinIndex;
                    node.extras.skinRootBone = unityNodes.IndexOf(x.rootBone);
                }
            }
            #endregion

#if UNITY_EDITOR
            #region Animations
            var animation = go.GetComponent <Animation>();
            if (animation != null)
            {
                foreach (AnimationState state in animation)
                {
                    var animationWithCurve = ExportAnimation(state.clip, go.transform, unityNodes);

                    foreach (var kv in animationWithCurve.SamplerMap)
                    {
                        var sampler = animationWithCurve.Animation.samplers[kv.Key];

                        var inputAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Input);
                        sampler.input = inputAccessorIndex;

                        var outputAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Output);
                        sampler.output = outputAccessorIndex;

                        // modify accessors
                        var outputAccessor = gltf.accessors[outputAccessorIndex];
                        var channel        = animationWithCurve.Animation.channels.First(x => x.sampler == kv.Key);
                        switch (glTFAnimationTarget.GetElementCount(channel.target.path))
                        {
                        case 3:
                            outputAccessor.type   = "VEC3";
                            outputAccessor.count /= 3;
                            break;

                        case 4:
                            outputAccessor.type   = "VEC4";
                            outputAccessor.count /= 4;
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                    }

                    gltf.animations.Add(animationWithCurve.Animation);
                }
            }
            #endregion
#endif

            return(new Exported
            {
                Meshes = unityMeshes,
                Nodes = unityNodes.Select(x => x.transform).ToList(),
                Materials = unityMaterials,
                Textures = unityTextures,
            });
        }
Example #12
0
        public static Exported FromGameObject(glTF gltf, GameObject go)
        {
            var bytesBuffer = new ArrayByteBuffer();
            var bufferIndex = gltf.AddBuffer(bytesBuffer);

            var unityNodes = go.transform.Traverse()
                             .Skip(1) // exclude root object for the symmetry with the importer
                             .ToList();

            #region Material
            var unityMaterials = unityNodes.SelectMany(x => x.GetSharedMaterials()).Where(x => x != null).Distinct().ToList();
            var unityTextures  = unityMaterials.SelectMany(x => x.GetTextures()).Where(x => x != null).Distinct().ToList();

            for (int i = 0; i < unityTextures.Count; ++i)
            {
                var texture = unityTextures[i];

                var bytesWithPath = new BytesWithPath(texture);;

                // add view
                var view      = gltf.buffers[bufferIndex].Storage.Extend(bytesWithPath.Bytes, glBufferTarget.NONE);
                var viewIndex = gltf.AddBufferView(view);

                // add image
                var imageIndex = gltf.images.Count;
                gltf.images.Add(new glTFImage
                {
                    bufferView = viewIndex,
                    mimeType   = bytesWithPath.Mime,
                });

                // add sampler
                var filter = default(glFilter);
                switch (texture.filterMode)
                {
                case FilterMode.Point:
                    filter = glFilter.NEAREST;
                    break;

                default:
                    filter = glFilter.LINEAR;
                    break;
                }
                var wrap = default(glWrap);

                switch (texture.wrapMode)
                {
                case TextureWrapMode.Clamp:
                    wrap = glWrap.CLAMP_TO_EDGE;
                    break;

                case TextureWrapMode.Repeat:
                    wrap = glWrap.REPEAT;
                    break;

#if UNITY_2017_OR_NEWER
                case TextureWrapMode.Mirror:
                    wrap = glWrap.MIRRORED_REPEAT;
                    break;
#endif

                default:
                    throw new NotImplementedException();
                }

                var samplerIndex = gltf.samplers.Count;
                gltf.samplers.Add(new glTFTextureSampler
                {
                    magFilter = filter,
                    minFilter = filter,
                    wrapS     = wrap,
                    wrapT     = wrap,
                });

                // add texture
                gltf.textures.Add(new glTFTexture
                {
                    sampler = samplerIndex,
                    source  = imageIndex,
                });
            }

            gltf.materials = unityMaterials.Select(x => ExportMaterial(x, unityTextures)).ToList();
            #endregion

            #region Meshes
            var unityMeshes = unityNodes
                              .Select(x => new MeshWithRenderer
            {
                Mesh       = x.GetSharedMesh(),
                Rendererer = x.GetComponent <Renderer>(),
            })
                              .Where(x => x.Mesh != null)
                              .ToList();
            for (int i = 0; i < unityMeshes.Count; ++i)
            {
                var x         = unityMeshes[i];
                var mesh      = x.Mesh;
                var materials = x.Rendererer.sharedMaterials;

                var positions             = mesh.vertices.Select(y => y.ReverseZ()).ToArray();
                var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, positions, glBufferTarget.ARRAY_BUFFER);
                gltf.accessors[positionAccessorIndex].min = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray();
                gltf.accessors[positionAccessorIndex].max = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray();

                var normalAccessorIndex  = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.normals.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER);
                var tangentAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.tangents.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER);
                var colorAccessorIndex   = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.colors.Select(y => (Vector4)y).ToArray(), glBufferTarget.ARRAY_BUFFER);
                var uvAccessorIndex      = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.uv.Select(y => y.ReverseY()).ToArray(), glBufferTarget.ARRAY_BUFFER);

                var boneweights         = mesh.boneWeights;
                var weightAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneweights.Select(y => new Vector4(y.weight0, y.weight1, y.weight2, y.weight3)).ToArray(), glBufferTarget.ARRAY_BUFFER);
                var jointsAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneweights.Select(y => new UShort4((ushort)y.boneIndex0, (ushort)y.boneIndex1, (ushort)y.boneIndex2, (ushort)y.boneIndex3)).ToArray(), glBufferTarget.ARRAY_BUFFER);

                var attributes = new glTFAttributes
                {
                    POSITION = positionAccessorIndex,
                };
                if (normalAccessorIndex != -1)
                {
                    attributes.NORMAL = normalAccessorIndex;
                }
                if (tangentAccessorIndex != -1)
                {
                    attributes.TANGENT = tangentAccessorIndex;
                }
                if (colorAccessorIndex != -1)
                {
                    attributes.COLOR_0 = colorAccessorIndex;
                }
                if (uvAccessorIndex != -1)
                {
                    attributes.TEXCOORD_0 = uvAccessorIndex;
                }
                if (weightAccessorIndex != -1)
                {
                    attributes.WEIGHTS_0 = weightAccessorIndex;
                }
                if (jointsAccessorIndex != -1)
                {
                    attributes.JOINTS_0 = jointsAccessorIndex;
                }

                gltf.meshes.Add(new glTFMesh(mesh.name));

                for (int j = 0; j < mesh.subMeshCount; ++j)
                {
                    var indices = TriangleUtil.FlipTriangle(mesh.GetIndices(j)).Select(y => (uint)y).ToArray();
                    var indicesAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, indices, glBufferTarget.ELEMENT_ARRAY_BUFFER);

                    gltf.meshes.Last().primitives.Add(new glTFPrimitives
                    {
                        attributes = attributes,
                        indices    = indicesAccessorIndex,
                        mode       = 4,                                 // triangels ?
                        //material = unityMaterials.IndexOf(materials[j])
                        material = unityMaterials.IndexOf(materials[0]) // JIA change for Maquette image entity
                    });
                }

                if (mesh.blendShapeCount > 0)
                {
                    for (int j = 0; j < mesh.blendShapeCount; ++j)
                    {
                        var blendShapeVertices = mesh.vertices;
                        var blendShpaeNormals  = mesh.normals;
                        var blendShapeTangents = mesh.tangents.Select(y => (Vector3)y).ToArray();
                        var blendShapeColors   = mesh.colors.Select(y => (Vector4)y).ToArray();
                        var k = mesh.GetBlendShapeFrameCount(j);
                        mesh.GetBlendShapeFrameVertices(j, k - 1, blendShapeVertices, blendShpaeNormals, null);

                        var blendShapePositionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex,
                                                                                                   blendShapeVertices.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER);
                        var blendShapeNormalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex,
                                                                                                 blendShpaeNormals.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER);
                        var blendShapeTangentAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex,
                                                                                                  blendShapeTangents.Select(y => y.ReverseZ()).ToArray(), glBufferTarget.ARRAY_BUFFER);
                        var blendShapeColorAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex,
                                                                                                blendShapeColors.ToArray(), glBufferTarget.ARRAY_BUFFER);
                        //
                        // first primitive has whole blendShape
                        //
                        gltf.meshes.Last().primitives[0].targets.Add(new glTFAttributes
                        {
                            POSITION = blendShapePositionAccessorIndex,
                            NORMAL   = blendShapeNormalAccessorIndex,
                            TANGENT  = blendShapeTangentAccessorIndex,
                            COLOR_0  = blendShapeColorAccessorIndex,
                        });
                    }
                }
            }
            #endregion

            #region Skins
            var unitySkins = unityNodes
                             .Select(x => x.GetComponent <SkinnedMeshRenderer>()).Where(x => x != null)
                             .ToList();
            gltf.nodes  = unityNodes.Select(x => ExportNode(x, unityNodes, unityMeshes.Select(y => y.Mesh).ToList(), unitySkins)).ToList();
            gltf.scenes = new List <gltfScene>
            {
                new gltfScene
                {
                    nodes = go.transform.GetChildren().Select(x => unityNodes.IndexOf(x)).ToArray(),
                }
            };

            foreach (var x in unitySkins)
            {
                var matrices = x.sharedMesh.bindposes.Select(y => y.ReverseZ()).ToArray();
                var accessor = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, matrices, glBufferTarget.NONE);

                var skin = new glTFSkin
                {
                    inverseBindMatrices = accessor,
                    joints   = x.bones.Select(y => unityNodes.IndexOf(y)).ToArray(),
                    skeleton = unityNodes.IndexOf(x.rootBone),
                };
                var skinIndex = gltf.skins.Count;
                gltf.skins.Add(skin);

                foreach (var z in unityNodes.Where(y => y.Has(x)))
                {
                    var nodeIndex = unityNodes.IndexOf(z);
                    gltf.nodes[nodeIndex].skin = skinIndex;
                }
            }
            #endregion

#if UNITY_EDITOR
            #region Animations
            var animation = go.GetComponent <Animation>();
            if (animation != null)
            {
                foreach (AnimationState state in animation)
                {
                    var animationWithCurve = ExportAnimation(state.clip, go.transform, unityNodes);

                    foreach (var kv in animationWithCurve.SamplerMap)
                    {
                        var sampler = animationWithCurve.Animation.samplers[kv.Key];

                        var inputAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Input);
                        sampler.input = inputAccessorIndex;

                        var outputAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Output);
                        sampler.output = outputAccessorIndex;

                        // modify accessors
                        var outputAccessor = gltf.accessors[outputAccessorIndex];
                        var channel        = animationWithCurve.Animation.channels.First(x => x.sampler == kv.Key);
                        switch (glTFAnimationTarget.GetElementCount(channel.target.path))
                        {
                        case 3:
                            outputAccessor.type   = "VEC3";
                            outputAccessor.count /= 3;
                            break;

                        case 4:
                            outputAccessor.type   = "VEC4";
                            outputAccessor.count /= 4;
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                    }

                    gltf.animations.Add(animationWithCurve.Animation);
                }
            }
            #endregion
#endif

            // glb buffer
            gltf.buffers[bufferIndex].UpdateByteLength();

            return(new Exported
            {
                Meshes = unityMeshes,
                Nodes = unityNodes.Select(x => x.transform).ToList(),
                Materials = unityMaterials,
                Textures = unityTextures,
            });
        }
Example #13
0
        public virtual void Export(MeshExportSettings meshExportSettings, ITextureSerializer textureSerializer)
        {
            var bytesBuffer = new ArrayByteBuffer(new byte[50 * 1024 * 1024]);
            var bufferIndex = glTF.AddBuffer(bytesBuffer);

            Nodes = Copy.transform.Traverse()
                    .Skip(1) // exclude root object for the symmetry with the importer
                    .ToList();

            var unityMeshes       = MeshWithRenderer.FromNodes(Nodes).Where(x => x.Mesh.vertices.Any()).ToList();
            var uniqueUnityMeshes = new List <MeshWithRenderer>();

            foreach (var um in unityMeshes)
            {
                if (!uniqueUnityMeshes.Any(x => x.IsSameMeshAndMaterials(um)))
                {
                    uniqueUnityMeshes.Add(um);
                }
            }

            #region Materials and Textures
            Materials = uniqueUnityMeshes.SelectMany(x => x.Renderer.sharedMaterials).Where(x => x != null).Distinct().ToList();

            TextureExporter = new TextureExporter(textureSerializer);

            var materialExporter = CreateMaterialExporter();
            glTF.materials = Materials.Select(x => materialExporter.ExportMaterial(x, TextureExporter)).ToList();
            #endregion

            #region Meshes
            MeshBlendShapeIndexMap = new Dictionary <Mesh, Dictionary <int, int> >();
            foreach (var unityMesh in uniqueUnityMeshes)
            {
                var(gltfMesh, blendShapeIndexMap) = MeshExporter.ExportMesh(glTF, bufferIndex, unityMesh, Materials, meshExportSettings, m_axisInverter);
                glTF.meshes.Add(gltfMesh);
                Meshes.Add(unityMesh.Mesh);
                if (!MeshBlendShapeIndexMap.ContainsKey(unityMesh.Mesh))
                {
                    // 同じmeshが複数回現れた
                    MeshBlendShapeIndexMap.Add(unityMesh.Mesh, blendShapeIndexMap);
                }
            }
            #endregion

            #region Nodes and Skins
            var unitySkins = uniqueUnityMeshes
                             .Where(x => x.UniqueBones != null)
                             .ToList();
            glTF.nodes  = Nodes.Select(x => ExportNode(x, Nodes, uniqueUnityMeshes, unitySkins.Select(y => y.Renderer as SkinnedMeshRenderer).ToList())).ToList();
            glTF.scenes = new List <gltfScene>
            {
                new gltfScene
                {
                    nodes = Copy.transform.GetChildren().Select(x => Nodes.IndexOf(x)).ToArray(),
                }
            };

            foreach (var x in unitySkins)
            {
                var matrices = x.GetBindPoses().Select(m_axisInverter.InvertMat4).ToArray();
                var accessor = glTF.ExtendBufferAndGetAccessorIndex(bufferIndex, matrices, glBufferTarget.NONE);

                var renderer = x.Renderer as SkinnedMeshRenderer;
                var skin     = new glTFSkin
                {
                    inverseBindMatrices = accessor,
                    joints   = x.UniqueBones.Select(y => Nodes.IndexOf(y)).ToArray(),
                    skeleton = Nodes.IndexOf(renderer.rootBone),
                };
                var skinIndex = glTF.skins.Count;
                glTF.skins.Add(skin);

                foreach (var z in Nodes.Where(y => y.Has(x.Renderer)))
                {
                    var nodeIndex = Nodes.IndexOf(z);
                    var node      = glTF.nodes[nodeIndex];
                    node.skin = skinIndex;
                }
            }
            #endregion

#if UNITY_EDITOR
            #region Animations

            var clips     = new List <AnimationClip>();
            var animator  = Copy.GetComponent <Animator>();
            var animation = Copy.GetComponent <Animation>();
            if (animator != null)
            {
                clips = AnimationExporter.GetAnimationClips(animator);
            }
            else if (animation != null)
            {
                clips = AnimationExporter.GetAnimationClips(animation);
            }

            if (clips.Any())
            {
                foreach (AnimationClip clip in clips)
                {
                    var animationWithCurve = AnimationExporter.Export(clip, Copy.transform, Nodes);

                    foreach (var kv in animationWithCurve.SamplerMap)
                    {
                        var sampler = animationWithCurve.Animation.samplers[kv.Key];

                        var inputAccessorIndex = glTF.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Input);
                        sampler.input = inputAccessorIndex;

                        var outputAccessorIndex = glTF.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Output);
                        sampler.output = outputAccessorIndex;

                        // modify accessors
                        var outputAccessor = glTF.accessors[outputAccessorIndex];
                        var channel        = animationWithCurve.Animation.channels.First(x => x.sampler == kv.Key);
                        switch (glTFAnimationTarget.GetElementCount(channel.target.path))
                        {
                        case 1:
                            outputAccessor.type = "SCALAR";
                            //outputAccessor.count = ;
                            break;

                        case 3:
                            outputAccessor.type   = "VEC3";
                            outputAccessor.count /= 3;
                            break;

                        case 4:
                            outputAccessor.type   = "VEC4";
                            outputAccessor.count /= 4;
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                    }
                    animationWithCurve.Animation.name = clip.name;
                    glTF.animations.Add(animationWithCurve.Animation);
                }
            }
            #endregion
#endif

            ExportExtensions(textureSerializer);

            // Extension で Texture が増える場合があるので最後に呼ぶ
            for (int i = 0; i < TextureExporter.Exported.Count; ++i)
            {
                var(unityTexture, colorSpace) = TextureExporter.Exported[i];
                glTF.PushGltfTexture(bufferIndex, unityTexture, colorSpace, textureSerializer);
            }
        }
Example #14
0
        public virtual void Export(ITextureSerializer textureSerializer)
        {
            Nodes = Copy.transform.Traverse()
                    .Skip(1) // exclude root object for the symmetry with the importer
                    .ToList();

            var uniqueUnityMeshes = new MeshExportList();

            uniqueUnityMeshes.GetInfo(Nodes, m_settings);

            #region Materials and Textures
            ReportProgress("Materials and Textures", 0.2f);
            Materials = uniqueUnityMeshes.GetUniqueMaterials().ToList();

            _textureExporter = new TextureExporter(textureSerializer);

            var materialExporter = CreateMaterialExporter();
            _gltf.materials = Materials.Select(x => materialExporter.ExportMaterial(x, TextureExporter, m_settings)).ToList();
            #endregion

            #region Meshes
            ReportProgress("Meshes", 0.4f);
            MeshBlendShapeIndexMap = new Dictionary <Mesh, Dictionary <int, int> >();
            foreach (var unityMesh in uniqueUnityMeshes)
            {
                if (!unityMesh.CanExport)
                {
                    continue;
                }

                var(gltfMesh, blendShapeIndexMap) = m_settings.DivideVertexBuffer
                    ? MeshExporter_DividedVertexBuffer.Export(_data, unityMesh, Materials, m_settings.InverseAxis.Create(), m_settings)
                    : MeshExporter_SharedVertexBuffer.Export(_data, unityMesh, Materials, m_settings.InverseAxis.Create(), m_settings)
                ;
                _gltf.meshes.Add(gltfMesh);
                Meshes.Add(unityMesh.Mesh);
                if (!MeshBlendShapeIndexMap.ContainsKey(unityMesh.Mesh))
                {
                    // 重複防止
                    MeshBlendShapeIndexMap.Add(unityMesh.Mesh, blendShapeIndexMap);
                }
            }
            #endregion

            #region Nodes and Skins
            ReportProgress("Nodes and Skins", 0.8f);
            var skins = uniqueUnityMeshes
                        .SelectMany(x => x.Renderers)
                        .Where(x => x.Item1 is SkinnedMeshRenderer && x.UniqueBones != null)
                        .Select(x => x.Item1 as SkinnedMeshRenderer)
                        .ToList()
            ;
            foreach (var node in Nodes)
            {
                var gltfNode = ExportNode(node, Nodes, uniqueUnityMeshes, skins);
                _gltf.nodes.Add(gltfNode);
            }
            _gltf.scenes = new List <gltfScene>
            {
                new gltfScene
                {
                    nodes = Copy.transform.GetChildren().Select(x => Nodes.IndexOf(x)).ToArray(),
                }
            };

            foreach (var x in uniqueUnityMeshes)
            {
                foreach (var(renderer, uniqueBones) in x.Renderers)
                {
                    if (uniqueBones != null && renderer is SkinnedMeshRenderer smr)
                    {
                        var matrices = x.GetBindPoses().Select(m_settings.InverseAxis.Create().InvertMat4).ToArray();
                        var accessor = _data.ExtendBufferAndGetAccessorIndex(matrices, glBufferTarget.NONE);
                        var skin     = new glTFSkin
                        {
                            inverseBindMatrices = accessor,
                            joints   = uniqueBones.Select(y => Nodes.IndexOf(y)).ToArray(),
                            skeleton = Nodes.IndexOf(smr.rootBone),
                        };
                        var skinIndex = _gltf.skins.Count;
                        _gltf.skins.Add(skin);

                        foreach (var z in Nodes.Where(y => y.Has(renderer)))
                        {
                            var nodeIndex = Nodes.IndexOf(z);
                            var node      = _gltf.nodes[nodeIndex];
                            node.skin = skinIndex;
                        }
                    }
                }
            }
            #endregion

            if (m_animationExporter != null)
            {
                ReportProgress("Animations", 0.9f);
                m_animationExporter.Export(_data, Copy, Nodes);
            }

            ExportExtensions(textureSerializer);

            // Extension で Texture が増える場合があるので最後に呼ぶ
            var exported = _textureExporter.Export();
            for (var exportedTextureIdx = 0; exportedTextureIdx < exported.Count; ++exportedTextureIdx)
            {
                var(unityTexture, colorSpace) = exported[exportedTextureIdx];
                GltfTextureExporter.PushGltfTexture(_data, unityTexture, colorSpace, textureSerializer);
            }

            FixName(_gltf);
        }
        public virtual void Export(MeshExportSettings meshExportSettings)
        {
            var bytesBuffer = new ArrayByteBuffer(new byte[50 * 1024 * 1024]);
            var bufferIndex = glTF.AddBuffer(bytesBuffer);

            GameObject tmpParent = null;

            if (Copy.transform.childCount == 0)
            {
                tmpParent = new GameObject("tmpParent");
                Copy.transform.SetParent(tmpParent.transform, true);
                Copy = tmpParent;
            }

            try
            {
                Nodes = Copy.transform.Traverse()
                        .Skip(1) // exclude root object for the symmetry with the importer
                        .ToList();

                #region Materials and Textures
                Materials = Nodes.SelectMany(x => x.GetSharedMaterials()).Where(x => x != null).Distinct().ToList();
                var unityTextures = Materials.SelectMany(x => TextureIO.GetTextures(x)).Where(x => x.Texture != null).Distinct().ToList();

                TextureManager = new TextureExportManager(unityTextures.Select(x => x.Texture));

                var materialExporter = CreateMaterialExporter();
                glTF.materials = Materials.Select(x => materialExporter.ExportMaterial(x, TextureManager)).ToList();

                for (int i = 0; i < unityTextures.Count; ++i)
                {
                    var unityTexture = unityTextures[i];
                    TextureIO.ExportTexture(glTF, bufferIndex, TextureManager.GetExportTexture(i), unityTexture.TextureType);
                }
                #endregion

                #region Meshes
                var unityMeshes = MeshWithRenderer.FromNodes(Nodes).ToList();

                MeshBlendShapeIndexMap = new Dictionary <Mesh, Dictionary <int, int> >();
                foreach (var(mesh, gltfMesh, blendShapeIndexMap) in MeshExporter.ExportMeshes(
                             glTF, bufferIndex, unityMeshes, Materials, meshExportSettings))
                {
                    glTF.meshes.Add(gltfMesh);
                    if (!MeshBlendShapeIndexMap.ContainsKey(mesh))
                    {
                        // 同じmeshが複数回現れた
                        MeshBlendShapeIndexMap.Add(mesh, blendShapeIndexMap);
                    }
                }
                Meshes = unityMeshes.Select(x => x.Mesh).ToList();
                #endregion

                #region Nodes and Skins
                var unitySkins = unityMeshes
                                 .Where(x => x.UniqueBones != null)
                                 .ToList();
                glTF.nodes  = Nodes.Select(x => ExportNode(x, Nodes, unityMeshes.Select(y => y.Renderer).ToList(), unitySkins.Select(y => y.Renderer as SkinnedMeshRenderer).ToList())).ToList();
                glTF.scenes = new List <gltfScene>
                {
                    new gltfScene
                    {
                        nodes = Copy.transform.GetChildren().Select(x => Nodes.IndexOf(x)).ToArray(),
                    }
                };

                foreach (var x in unitySkins)
                {
                    var matrices = x.GetBindPoses().Select(y => y.ReverseZ()).ToArray();
                    var accessor = glTF.ExtendBufferAndGetAccessorIndex(bufferIndex, matrices, glBufferTarget.NONE);

                    var renderer = x.Renderer as SkinnedMeshRenderer;
                    var skin     = new glTFSkin
                    {
                        inverseBindMatrices = accessor,
                        joints   = x.UniqueBones.Select(y => Nodes.IndexOf(y)).ToArray(),
                        skeleton = Nodes.IndexOf(renderer.rootBone),
                    };
                    var skinIndex = glTF.skins.Count;
                    glTF.skins.Add(skin);

                    foreach (var z in Nodes.Where(y => y.Has(x.Renderer)))
                    {
                        var nodeIndex = Nodes.IndexOf(z);
                        var node      = glTF.nodes[nodeIndex];
                        node.skin = skinIndex;
                    }
                }
                #endregion

#if UNITY_EDITOR
                #region Animations

                var clips     = new List <AnimationClip>();
                var animator  = Copy.GetComponent <Animator>();
                var animation = Copy.GetComponent <Animation>();
                if (animator != null)
                {
                    clips = AnimationExporter.GetAnimationClips(animator);
                }
                else if (animation != null)
                {
                    clips = AnimationExporter.GetAnimationClips(animation);
                }

                if (clips.Any())
                {
                    foreach (AnimationClip clip in clips)
                    {
                        var animationWithCurve = AnimationExporter.Export(clip, Copy.transform, Nodes);

                        foreach (var kv in animationWithCurve.SamplerMap)
                        {
                            var sampler = animationWithCurve.Animation.samplers[kv.Key];

                            var inputAccessorIndex = glTF.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Input);
                            sampler.input = inputAccessorIndex;

                            var outputAccessorIndex = glTF.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Output);
                            sampler.output = outputAccessorIndex;

                            // modify accessors
                            var outputAccessor = glTF.accessors[outputAccessorIndex];
                            var channel        = animationWithCurve.Animation.channels.First(x => x.sampler == kv.Key);
                            switch (glTFAnimationTarget.GetElementCount(channel.target.path))
                            {
                            case 1:
                                outputAccessor.type = "SCALAR";
                                //outputAccessor.count = ;
                                break;

                            case 3:
                                outputAccessor.type   = "VEC3";
                                outputAccessor.count /= 3;
                                break;

                            case 4:
                                outputAccessor.type   = "VEC4";
                                outputAccessor.count /= 4;
                                break;

                            default:
                                throw new NotImplementedException();
                            }
                        }
                        animationWithCurve.Animation.name = clip.name;
                        glTF.animations.Add(animationWithCurve.Animation);
                    }
                }
                #endregion
#endif
            }
            finally
            {
                if (tmpParent != null)
                {
                    tmpParent.transform.GetChild(0).SetParent(null);
                    if (Application.isPlaying)
                    {
                        GameObject.Destroy(tmpParent);
                    }
                    else
                    {
                        GameObject.DestroyImmediate(tmpParent);
                    }
                }
            }
        }