Esempio n. 1
0
        public virtual void Export(GltfExportSettings 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 uniqueUnityMeshes = new MeshExportList();

            uniqueUnityMeshes.GetInfo(Nodes, meshExportSettings);

            #region Materials and Textures
            Materials = uniqueUnityMeshes.GetUniqueMaterials().ToList();

            m_textureExporter = new TextureExporter(textureSerializer);

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

            #region Meshes
            MeshBlendShapeIndexMap = new Dictionary <Mesh, Dictionary <int, int> >();
            foreach (var unityMesh in uniqueUnityMeshes)
            {
                var(gltfMesh, blendShapeIndexMap) = meshExportSettings.DivideVertexBuffer
                    ? MeshExporter_DividedVertexBuffer.Export(glTF, bufferIndex, unityMesh, Materials, m_settings.InverseAxis.Create(), meshExportSettings)
                    : MeshExporter_SharedVertexBuffer.Export(glTF, bufferIndex, unityMesh, Materials, m_settings.InverseAxis.Create(), meshExportSettings)
                ;
                glTF.meshes.Add(gltfMesh);
                Meshes.Add(unityMesh.Mesh);
                if (!MeshBlendShapeIndexMap.ContainsKey(unityMesh.Mesh))
                {
                    // 重複防止
                    MeshBlendShapeIndexMap.Add(unityMesh.Mesh, blendShapeIndexMap);
                }
            }
            #endregion

            #region Nodes and Skins
            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 = glTF.ExtendBufferAndGetAccessorIndex(bufferIndex, 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

            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 が増える場合があるので最後に呼ぶ
            var exported = m_textureExporter.Export();
            for (var exportedTextureIdx = 0; exportedTextureIdx < exported.Count; ++exportedTextureIdx)
            {
                var(unityTexture, colorSpace) = exported[exportedTextureIdx];
                glTF.PushGltfTexture(bufferIndex, 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 => TextureExporter.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];
                    TextureExporter.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);
                    }
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Occlusion, Metallic, Roughness
        /// </summary>
        /// <param name="m"></param>
        /// <param name="textureManager"></param>
        /// <param name="material"></param>
        static void Export_OcclusionMetallicRoughness(Material m, TextureExporter textureManager, glTFMaterial material)
        {
            Texture metallicSmoothTexture = default;
            float   smoothness            = 1.0f;

            if (m.HasProperty("_MetallicGlossMap"))
            {
                if (m.HasProperty("_GlossMapScale"))
                {
                    smoothness = m.GetFloat("_GlossMapScale");
                }
                metallicSmoothTexture = m.GetTexture("_MetallicGlossMap");
            }

            Texture occlusionTexture  = default;
            var     occlusionStrength = 1.0f;

            if (m.HasProperty("_OcclusionMap"))
            {
                occlusionTexture = m.GetTexture("_OcclusionMap");
                if (occlusionTexture != null && m.HasProperty("_OcclusionStrength"))
                {
                    occlusionStrength = m.GetFloat("_OcclusionStrength");
                }
            }

            int index = textureManager.ExportMetallicSmoothnessOcclusion(metallicSmoothTexture, smoothness, occlusionTexture);

            if (index != -1 && metallicSmoothTexture != null)
            {
                material.pbrMetallicRoughness.metallicRoughnessTexture =
                    new glTFMaterialMetallicRoughnessTextureInfo()
                {
                    index = index,
                };
                Export_MainTextureTransform(m, material.pbrMetallicRoughness.metallicRoughnessTexture);

                // Set 1.0f as hard-coded. See: https://github.com/dwango/UniVRM/issues/212.
                material.pbrMetallicRoughness.metallicFactor  = 1.0f;
                material.pbrMetallicRoughness.roughnessFactor = 1.0f;
            }
            else
            {
                if (m.HasProperty("_Metallic"))
                {
                    material.pbrMetallicRoughness.metallicFactor = m.GetFloat("_Metallic");
                }

                if (m.HasProperty("_Glossiness"))
                {
                    material.pbrMetallicRoughness.roughnessFactor = 1.0f - m.GetFloat("_Glossiness");
                }
            }

            if (index != -1 && occlusionTexture != null)
            {
                material.occlusionTexture = new glTFMaterialOcclusionTextureInfo()
                {
                    index    = index,
                    strength = occlusionStrength,
                };
                Export_MainTextureTransform(m, material.occlusionTexture);
            }
        }