From 5cd72b640167aa72a1965cd819321da3b4e226cc Mon Sep 17 00:00:00 2001 From: Robert Long Date: Sun, 29 Jan 2023 17:29:36 -0800 Subject: [PATCH 1/2] Add ability to export files and buffer views --- .../Runtime/Scripts/GLTFSceneExporter.cs | 59 +++++++++++++++++-- .../SceneExporter/ExporterAccessors.cs | 8 +++ .../Scripts/SceneExporter/ExporterTextures.cs | 2 +- 3 files changed, 62 insertions(+), 7 deletions(-) diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs index 8977845f0..e954c7466 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs @@ -248,6 +248,12 @@ private struct ImageInfo public bool canBeExportedFromDisk; } + private struct FileInfo + { + public string path; + public string uniqueFileName; + } + public IReadOnlyList RootTransforms => _rootTransforms; private Transform[] _rootTransforms; @@ -255,12 +261,14 @@ private struct ImageInfo private BufferId _bufferId; private GLTFBuffer _buffer; private List _imageInfos; + private List _fileInfos; + private HashSet _fileNames; private List _textures; private Dictionary _exportedMaterials; #if ANIMATION_SUPPORTED private List<(Transform tr, AnimationClip clip)> _animationClips; #endif - private bool _shouldUseInternalBufferForImages; + public bool shouldUseInternalBuffer; private Dictionary _exportedTransforms; private List _animatedNodes; @@ -511,6 +519,8 @@ public GLTFSceneExporter(Transform[] rootTransforms, ExportOptions options) }; _imageInfos = new List(); + _fileInfos = new List(); + _fileNames = new HashSet(); _exportedMaterials = new Dictionary(); _textures = new List(); #if ANIMATION_SUPPORTED @@ -546,16 +556,17 @@ public void SaveGLB(string path, string fileName) var dirName = Path.GetDirectoryName(fullPath); if (dirName != null && !Directory.Exists(dirName)) Directory.CreateDirectory(dirName); - _shouldUseInternalBufferForImages = true; + shouldUseInternalBuffer = true; using (FileStream glbFile = new FileStream(fullPath, FileMode.Create)) { SaveGLBToStream(glbFile, fileName); } - if (!_shouldUseInternalBufferForImages) + if (!shouldUseInternalBuffer) { ExportImages(path); + ExportFiles(path); } } @@ -566,7 +577,7 @@ public void SaveGLB(string path, string fileName) /// public byte[] SaveGLBToByteArray(string sceneName) { - _shouldUseInternalBufferForImages = true; + shouldUseInternalBuffer = true; using (var stream = new MemoryStream()) { SaveGLBToStream(stream, sceneName); @@ -586,7 +597,7 @@ public void SaveGLBToStream(Stream stream, string sceneName) exportGltfInitMarker.Begin(); Stream binStream = new MemoryStream(); Stream jsonStream = new MemoryStream(); - _shouldUseInternalBufferForImages = true; + shouldUseInternalBuffer = true; _bufferWriter = new BinaryWriterWithLessAllocations(binStream); @@ -679,7 +690,7 @@ public void SaveGLTFandBin(string path, string fileName) exportGltfMarker.Begin(); exportGltfInitMarker.Begin(); - _shouldUseInternalBufferForImages = false; + shouldUseInternalBuffer = false; var toLower = fileName.ToLowerInvariant(); if (toLower.EndsWith(".gltf")) fileName = fileName.Substring(0, fileName.Length - 5); @@ -746,6 +757,7 @@ public void SaveGLTFandBin(string path, string fileName) binFile.Close(); #endif ExportImages(path); + ExportFiles(path); gltfWriteOutMarker.End(); exportGltfMarker.End(); @@ -1048,6 +1060,41 @@ private void FilterPrimitives(Transform transform, out GameObject[] primitives, // && ContainsValidRenderer(gameObject); // } + public string ExportFile(string path) { + var fileName = Path.GetFileName(path); + var uniqueFileName = GetUniqueName(_fileNames, fileName); + + _fileNames.Add(uniqueFileName); + + _fileInfos.Add( + new FileInfo { + path = path, + uniqueFileName = uniqueFileName, + } + ); + + return uniqueFileName; + } + + private void ExportFiles(string outputPath) + { + for (int i = 0; i < _fileInfos.Count; ++i) + { + var fileInfo = _fileInfos[i]; + + var fileOutputPath = Path.Combine(outputPath, fileInfo.uniqueFileName); + + var dir = Path.GetDirectoryName(fileOutputPath); + if (!Directory.Exists(dir) && dir != null) + Directory.CreateDirectory(dir); + + var data = File.ReadAllBytes(fileInfo.path); + + File.WriteAllBytes(fileOutputPath, data); + + } + } + private void ExportAnimation() { for (int i = 0; i < _animatedNodes.Count; ++i) diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterAccessors.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterAccessors.cs index 55909a3d2..41a0f4664 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterAccessors.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterAccessors.cs @@ -1119,6 +1119,14 @@ private AccessorId ExportAccessor(Color[] arr, bool exportAlphaChannel) return id; } + public BufferViewId ExportBufferView(byte[] bytes) { + AlignToBoundary(_bufferWriter.BaseStream, 0x00); + uint byteOffset = CalculateAlignment((uint)_bufferWriter.BaseStream.Position, 4); + _bufferWriter.Write(bytes); + uint byteLength = CalculateAlignment((uint)_bufferWriter.BaseStream.Position - byteOffset, 4); + return ExportBufferView((uint)byteOffset, (uint)byteLength); + } + private BufferViewId ExportBufferView(uint byteOffset, uint byteLength, uint byteStride = 0) { var bufferView = new BufferView diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterTextures.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterTextures.cs index 058b2a2c1..54a82954c 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterTextures.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/SceneExporter/ExporterTextures.cs @@ -173,7 +173,7 @@ public TextureId ExportTexture(Texture textureObj, string textureSlot, TextureEx texture.Name = textureObj.name; } - if (_shouldUseInternalBufferForImages) + if (shouldUseInternalBuffer) { texture.Source = ExportImageInternalBuffer(uniqueTexture, textureSlot); } From 34a7153e05cb70dc0b575fa7b2bcb910d1ab4a15 Mon Sep 17 00:00:00 2001 From: Robert Long Date: Mon, 17 Apr 2023 12:55:52 -0700 Subject: [PATCH 2/2] Update to use streams --- .../Runtime/Scripts/GLTFSceneExporter.cs | 53 +++++++++++++------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs index e954c7466..ed7874265 100644 --- a/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs +++ b/UnityGLTF/Assets/UnityGLTF/Runtime/Scripts/GLTFSceneExporter.cs @@ -250,10 +250,17 @@ private struct ImageInfo private struct FileInfo { - public string path; + public Stream stream; public string uniqueFileName; } + public struct ExportFileResult + { + public string uri; + public string mimeType; + public BufferViewId bufferView; + } + public IReadOnlyList RootTransforms => _rootTransforms; private Transform[] _rootTransforms; @@ -268,7 +275,7 @@ private struct FileInfo #if ANIMATION_SUPPORTED private List<(Transform tr, AnimationClip clip)> _animationClips; #endif - public bool shouldUseInternalBuffer; + private bool shouldUseInternalBuffer; private Dictionary _exportedTransforms; private List _animatedNodes; @@ -1060,20 +1067,32 @@ private void FilterPrimitives(Transform transform, out GameObject[] primitives, // && ContainsValidRenderer(gameObject); // } - public string ExportFile(string path) { - var fileName = Path.GetFileName(path); - var uniqueFileName = GetUniqueName(_fileNames, fileName); + public ExportFileResult ExportFile(string fileName, string mimeType, Stream stream) { + if (shouldUseInternalBuffer) { + byte[] data = new byte[stream.Length]; + stream.Read(data, 0, (int)stream.Length); + stream.Close(); - _fileNames.Add(uniqueFileName); + return new ExportFileResult { + bufferView = this.ExportBufferView(data), + mimeType = mimeType, + }; + } else { + var uniqueFileName = GetUniqueName(_fileNames, fileName); - _fileInfos.Add( - new FileInfo { - path = path, - uniqueFileName = uniqueFileName, - } - ); + _fileNames.Add(uniqueFileName); - return uniqueFileName; + _fileInfos.Add( + new FileInfo { + stream = stream, + uniqueFileName = uniqueFileName, + } + ); + + return new ExportFileResult { + uri = uniqueFileName, + }; + } } private void ExportFiles(string outputPath) @@ -1088,10 +1107,10 @@ private void ExportFiles(string outputPath) if (!Directory.Exists(dir) && dir != null) Directory.CreateDirectory(dir); - var data = File.ReadAllBytes(fileInfo.path); - - File.WriteAllBytes(fileOutputPath, data); - + var outputStream = File.Create(fileOutputPath); + fileInfo.stream.Seek(0, SeekOrigin.Begin); + fileInfo.stream.CopyTo(outputStream); + outputStream.Close(); } }