Beispiel #1
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);
            }
        }