public ExportingGltfData(int reserved = default) { if (reserved == 0) { reserved = 50 * 1024 * 1024; } // buffers[0] is export target Gltf.buffers.Add(new glTFBuffer()); _buffer = new ArrayByteBuffer(new byte[reserved]); }
public void DividedVertexBufferTest() { var glTF = new glTF(); var bytesBuffer = new ArrayByteBuffer(new byte[50 * 1024 * 1024]); var bufferIndex = glTF.AddBuffer(bytesBuffer); var Materials = new List <Material> { new Material(Shader.Find("Standard")), // A new Material(Shader.Find("Standard")), // B }; var(go, mesh) = CreateMesh(Materials.ToArray()); var meshExportSettings = new GltfExportSettings { DivideVertexBuffer = true }; var axisInverter = Axes.X.Create(); var unityMesh = MeshExportList.Create(go); var(gltfMesh, blendShapeIndexMap) = meshExportSettings.DivideVertexBuffer ? MeshExporter_DividedVertexBuffer.Export(glTF, bufferIndex, unityMesh, Materials, axisInverter, meshExportSettings) : MeshExporter_SharedVertexBuffer.Export(glTF, bufferIndex, unityMesh, Materials, axisInverter, meshExportSettings) ; { var indices = glTF.GetIndices(gltfMesh.primitives[0].indices); Assert.AreEqual(0, indices[0]); Assert.AreEqual(1, indices[1]); Assert.AreEqual(3, indices[2]); Assert.AreEqual(3, indices[3]); Assert.AreEqual(1, indices[4]); Assert.AreEqual(2, indices[5]); } { var positions = glTF.GetArrayFromAccessor <Vector3>(gltfMesh.primitives[0].attributes.POSITION); Assert.AreEqual(4, positions.Length); } { var indices = glTF.GetIndices(gltfMesh.primitives[1].indices); Assert.AreEqual(0, indices[0]); Assert.AreEqual(1, indices[1]); Assert.AreEqual(3, indices[2]); Assert.AreEqual(3, indices[3]); Assert.AreEqual(1, indices[4]); Assert.AreEqual(2, indices[5]); } { var positions = glTF.GetArrayFromAccessor <Vector3>(gltfMesh.primitives[1].attributes.POSITION); Assert.AreEqual(4, positions.Length); } }
void BufferTest(int init, params int[] size) { var initBytes = init == 0 ? null : new byte[init]; var storage = new ArrayByteBuffer(initBytes); var buffer = new glTFBuffer(storage); var values = new List <byte>(); int offset = 0; foreach (var x in size) { var nums = Enumerable.Range(offset, x).Select(y => (Byte)y).ToArray(); values.AddRange(nums); var bytes = new ArraySegment <Byte>(nums); offset += x; buffer.Append(bytes, glBufferTarget.NONE); } Assert.AreEqual(values.Count, buffer.byteLength); Assert.True(Enumerable.SequenceEqual(values, buffer.GetBytes().ToArray())); }
void BufferTest(int init, params int[] size) { var initBytes = init == 0 ? null : new byte[init]; var storage = new ArrayByteBuffer(initBytes); var data = new ExportingGltfData(); // var buffer = new glTFBuffer(storage); var values = new List <byte>(); int offset = 0; foreach (var x in size) { var nums = Enumerable.Range(offset, x).Select(y => (Byte)y).ToArray(); values.AddRange(nums); var bytes = new ArraySegment <Byte>(nums); offset += x; data.ExtendBufferAndGetView(bytes, glBufferTarget.NONE); } Assert.AreEqual(values.Count, data.GLTF.buffers[0].byteLength); Assert.True(Enumerable.SequenceEqual(values, data.BinBytes.ToArray())); }
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); } } } }
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, }); }
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, }); }
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); } }
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); } } } }