From efdfb1669b07f04e697242b6874d76ecc9e08183 Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Mon, 22 Jun 2026 05:53:16 -0700 Subject: [PATCH] feat: Add support for importing 64-bit GLB version 3 files --- .../Assets~/Unity/FormatVariants/README.md | 2 +- .../glTF-Binary/FormatVariantsGLB3.glb | 3 + .../Tests/Editor/GltfImporterTest.cs | 2 +- .../Runtime/Scripts/Import/AssetsTests.cs | 2 +- .../Scripts/Import/CancellationTests.cs | 2 +- .../Runtime/Scripts/Import/MemoryTests.cs | 2 +- .../TestCaseSets/glTF-test-models.asset | 13 +- .../{GlbBinChunk.cs => GltfBufferRange.cs} | 8 +- ...nChunk.cs.meta => GltfBufferRange.cs.meta} | 0 .../Runtime/Scripts/GltfImport.cs | 149 ++++++++++++------ .../Runtime/Scripts/Logging/LogMessages.cs | 10 ++ .../Runtime/Scripts/NativeArrayExtensions.cs | 8 +- .../Runtime/Scripts/Schema/IBufferView.cs | 2 +- graphify-out/graph.json | 16 +- 14 files changed, 144 insertions(+), 75 deletions(-) create mode 100644 Packages/com.unity.cloud.gltfast.tests/Assets~/Unity/FormatVariants/glTF-Binary/FormatVariantsGLB3.glb rename Packages/com.unity.cloud.gltfast/Runtime/Scripts/{GlbBinChunk.cs => GltfBufferRange.cs} (60%) rename Packages/com.unity.cloud.gltfast/Runtime/Scripts/{GlbBinChunk.cs.meta => GltfBufferRange.cs.meta} (100%) diff --git a/Packages/com.unity.cloud.gltfast.tests/Assets~/Unity/FormatVariants/README.md b/Packages/com.unity.cloud.gltfast.tests/Assets~/Unity/FormatVariants/README.md index 227e650d1..b85e1a7d3 100644 --- a/Packages/com.unity.cloud.gltfast.tests/Assets~/Unity/FormatVariants/README.md +++ b/Packages/com.unity.cloud.gltfast.tests/Assets~/Unity/FormatVariants/README.md @@ -5,7 +5,7 @@ Textured cube in three format variants: 1. glTF (JSON) with separate buffer and texture files. -2. glTF-Binary (.glb) +2. glTF-Binary (.glb) version 2 and version 3. 3. glTF (JSON) with embedded buffer and texture. ## Legal diff --git a/Packages/com.unity.cloud.gltfast.tests/Assets~/Unity/FormatVariants/glTF-Binary/FormatVariantsGLB3.glb b/Packages/com.unity.cloud.gltfast.tests/Assets~/Unity/FormatVariants/glTF-Binary/FormatVariantsGLB3.glb new file mode 100644 index 000000000..db3e09d11 --- /dev/null +++ b/Packages/com.unity.cloud.gltfast.tests/Assets~/Unity/FormatVariants/glTF-Binary/FormatVariantsGLB3.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3044834b5e52b7c3c851a09a2b32642c27c75d84f549419370051604bbc7a2f2 +size 2636 diff --git a/Packages/com.unity.cloud.gltfast.tests/Tests/Editor/GltfImporterTest.cs b/Packages/com.unity.cloud.gltfast.tests/Tests/Editor/GltfImporterTest.cs index 63aacdc5d..754aec7a9 100644 --- a/Packages/com.unity.cloud.gltfast.tests/Tests/Editor/GltfImporterTest.cs +++ b/Packages/com.unity.cloud.gltfast.tests/Tests/Editor/GltfImporterTest.cs @@ -36,7 +36,7 @@ public void OneTimeTearDown() AssetDatabase.Refresh(); } - [GltfTestCase("glTF-test-models", 65)] + [GltfTestCase("glTF-test-models", 66)] public IEnumerator GltfTestModels(GltfTestCaseSet testCaseSet, GltfTestCase testCase) { #if GLTFAST_EDITOR_IMPORT_OFF diff --git a/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/Scripts/Import/AssetsTests.cs b/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/Scripts/Import/AssetsTests.cs index 3458e0f78..0c906198e 100644 --- a/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/Scripts/Import/AssetsTests.cs +++ b/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/Scripts/Import/AssetsTests.cs @@ -26,7 +26,7 @@ public void OneTimeTearDown() m_Runner.Dispose(); } - [GltfTestCase("glTF-test-models", 65)] + [GltfTestCase("glTF-test-models", 66)] public IEnumerator GltfTestModels(GltfTestCaseSet testCaseSet, GltfTestCase testCase) { yield return AsyncWrapper.WaitForTask(m_Runner.Run(testCaseSet, testCase)); diff --git a/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/Scripts/Import/CancellationTests.cs b/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/Scripts/Import/CancellationTests.cs index a0e4b4f7e..7dc8c244b 100644 --- a/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/Scripts/Import/CancellationTests.cs +++ b/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/Scripts/Import/CancellationTests.cs @@ -40,7 +40,7 @@ public IEnumerator CancelImport_SampleAssets(GltfTestCaseSet testCaseSet, GltfTe yield return CancellationTestInternal(testCaseSet, testCase, k_MaxIterations); } - [GltfTestCase("glTF-test-models", 65)] + [GltfTestCase("glTF-test-models", 66)] public IEnumerator CancelImport_TestModels(GltfTestCaseSet testCaseSet, GltfTestCase testCase) { yield return CancellationTestInternal(testCaseSet, testCase, k_MaxIterations); diff --git a/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/Scripts/Import/MemoryTests.cs b/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/Scripts/Import/MemoryTests.cs index 8778c96f0..f846a996c 100644 --- a/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/Scripts/Import/MemoryTests.cs +++ b/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/Scripts/Import/MemoryTests.cs @@ -69,7 +69,7 @@ public IEnumerator LoadUnload_SampleAssets(GltfTestCaseSet testCaseSet, GltfTest yield return GetAllObjectsTestInternal(LoadFileInternal(testCaseSet, testCase), true); } - [GltfTestCase("glTF-test-models", 65)] + [GltfTestCase("glTF-test-models", 66)] public IEnumerator LoadUnload_TestModels(GltfTestCaseSet testCaseSet, GltfTestCase testCase) { yield return GetAllObjectsTestInternal(LoadFileInternal(testCaseSet, testCase), true); diff --git a/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/TestCaseSets/glTF-test-models.asset b/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/TestCaseSets/glTF-test-models.asset index f2f9a1c19..196a51ae3 100644 --- a/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/TestCaseSets/glTF-test-models.asset +++ b/Packages/com.unity.cloud.gltfast.tests/Tests/Runtime/TestCaseSets/glTF-test-models.asset @@ -23,7 +23,7 @@ MonoBehaviour: - relativeUri: EightTexcoords/EightTexcoords.gltf expectLoadFail: 0 expectInstantiationFail: 0 - expectedLogCodes: 34000000 + expectedLogCodes: 36000000 requiredExtensions: - relativeUri: EmbedBufferInvalid/EmbedBufferInvalid.gltf expectLoadFail: 1 @@ -63,7 +63,7 @@ MonoBehaviour: - relativeUri: NineTexcoords/NineTexcoords.gltf expectLoadFail: 0 expectInstantiationFail: 0 - expectedLogCodes: 34000000 + expectedLogCodes: 36000000 requiredExtensions: - relativeUri: NoNormals/NoNormals.gltf expectLoadFail: 0 @@ -128,12 +128,12 @@ MonoBehaviour: - relativeUri: Bounds/BoundsMissing/BoundsMissing.gltf expectLoadFail: 0 expectInstantiationFail: 0 - expectedLogCodes: 20000000 + expectedLogCodes: 22000000 requiredExtensions: - relativeUri: DracoSpecialCases/glTF/DracoSpecialCases.gltf expectLoadFail: 0 expectInstantiationFail: 0 - expectedLogCodes: 2000000034000000 + expectedLogCodes: 2200000036000000 requiredExtensions: 00000000 - relativeUri: FormatVariants/glTF/FormatVariants.gltf expectLoadFail: 0 @@ -145,6 +145,11 @@ MonoBehaviour: expectInstantiationFail: 0 expectedLogCodes: requiredExtensions: + - relativeUri: FormatVariants/glTF-Binary/FormatVariantsGLB3.glb + expectLoadFail: 0 + expectInstantiationFail: 0 + expectedLogCodes: + requiredExtensions: - relativeUri: FormatVariants/glTF-Embedded/FormatVariants.gltf expectLoadFail: 0 expectInstantiationFail: 0 diff --git a/Packages/com.unity.cloud.gltfast/Runtime/Scripts/GlbBinChunk.cs b/Packages/com.unity.cloud.gltfast/Runtime/Scripts/GltfBufferRange.cs similarity index 60% rename from Packages/com.unity.cloud.gltfast/Runtime/Scripts/GlbBinChunk.cs rename to Packages/com.unity.cloud.gltfast/Runtime/Scripts/GltfBufferRange.cs index 268fd2d17..5afdae3b2 100644 --- a/Packages/com.unity.cloud.gltfast/Runtime/Scripts/GlbBinChunk.cs +++ b/Packages/com.unity.cloud.gltfast/Runtime/Scripts/GltfBufferRange.cs @@ -5,13 +5,13 @@ namespace GLTFast { - readonly struct GlbBinChunk + readonly struct GltfBufferRange { - public int Start { get; } + public long Start { get; } - public uint Length { get; } + public long Length { get; } - public GlbBinChunk(int start, uint length) + public GltfBufferRange(long start, long length) { Start = start; Length = length; diff --git a/Packages/com.unity.cloud.gltfast/Runtime/Scripts/GlbBinChunk.cs.meta b/Packages/com.unity.cloud.gltfast/Runtime/Scripts/GltfBufferRange.cs.meta similarity index 100% rename from Packages/com.unity.cloud.gltfast/Runtime/Scripts/GlbBinChunk.cs.meta rename to Packages/com.unity.cloud.gltfast/Runtime/Scripts/GltfBufferRange.cs.meta diff --git a/Packages/com.unity.cloud.gltfast/Runtime/Scripts/GltfImport.cs b/Packages/com.unity.cloud.gltfast/Runtime/Scripts/GltfImport.cs index b11dfd0b4..8fc62dd98 100755 --- a/Packages/com.unity.cloud.gltfast/Runtime/Scripts/GltfImport.cs +++ b/Packages/com.unity.cloud.gltfast/Runtime/Scripts/GltfImport.cs @@ -197,10 +197,10 @@ public abstract class GltfImportBase : IGltfReadable, IGltfBuffers, IGltfAccesso ImportSettings m_Settings; - ReadOnlyNativeArray[] m_Buffers; + ReadOnlyNativeArray[] m_BufferData; List m_VolatileDisposables; - GlbBinChunk[] m_BinChunks; + GltfBufferRange[] m_BufferRanges; Dictionary> m_BufferLoadTasks; Dictionary> m_TextureLoadTasks; @@ -228,7 +228,7 @@ public abstract class GltfImportBase : IGltfReadable, IGltfBuffers, IGltfAccesso /// optional glTF-binary buffer /// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#binary-buffer - GlbBinChunk? m_GlbBinChunk; + GltfBufferRange? m_GlbBinChunk; #if MESHOPT_IS_ENABLED Dictionary> m_MeshoptBufferViews; @@ -1497,8 +1497,8 @@ async Task ParseJsonAndLoadBuffers(string json, CancellationToken cancella var bufferCount = Root.Buffers.Count; if (bufferCount > 0) { - m_Buffers = new ReadOnlyNativeArray[bufferCount]; - m_BinChunks = new GlbBinChunk[bufferCount]; + m_BufferData = new ReadOnlyNativeArray[bufferCount]; + m_BufferRanges = new GltfBufferRange[bufferCount]; } for (var i = 0; i < bufferCount; i++) @@ -1551,10 +1551,10 @@ async Task LoadBufferFromDataUri(int bufferIndex, Buffer buffer, Cancellat } m_VolatileDisposables ??= new List(); m_VolatileDisposables.Add(data); - m_Buffers[bufferIndex] = new ReadOnlyNativeArray(data); + m_BufferData[bufferIndex] = new ReadOnlyNativeArray(data); if (bufferIndex != 0 || !m_GlbBinChunk.HasValue) { - m_BinChunks[bufferIndex] = new GlbBinChunk(0, (uint)m_Buffers[bufferIndex].Length); + m_BufferRanges[bufferIndex] = new GltfBufferRange(0, (uint)m_BufferData[bufferIndex].Length); } return true; } @@ -1942,12 +1942,12 @@ async Task LoadBufferFromUriAsync(int index, Uri uri) if (download is INativeDownload nativeDownload) { var wrapper = new ReadOnlyNativeArrayFromNativeArray(nativeDownload.NativeData); - m_Buffers[index] = wrapper.Array; + m_BufferData[index] = wrapper.Array; } else { var wrapper = new ReadOnlyNativeArrayFromManagedArray(download.Data); - m_Buffers[index] = wrapper.Array; + m_BufferData[index] = wrapper.Array; m_VolatileDisposables.Add(wrapper); } @@ -1957,7 +1957,7 @@ async Task LoadBufferFromUriAsync(int index, Uri uri) if (index != 0 || !m_GlbBinChunk.HasValue) { - m_BinChunks[index] = new GlbBinChunk(0, (uint)m_Buffers[index].Length); + m_BufferRanges[index] = new GltfBufferRange(0, (uint)m_BufferData[index].Length); } return true; @@ -2011,6 +2011,12 @@ out int byteLength return false; } + /// + /// The maximum size of a byte array as limited by C# (a bit under 2 GiB). + /// https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/gcallowverylargeobjects-element + /// + private const long k_MaxByteArraySize = 0x7FFFFFC7L; + async Task LoadGltfBinaryBuffer( NativeArray.ReadOnly bytes, CancellationToken cancellationToken @@ -2026,24 +2032,41 @@ CancellationToken cancellationToken } var version = bytes.ReadUInt32(4); - - if (version != 2) + long totalLength; + long index; + long chAlignmentBitmask; + if (version == 2) + { + totalLength = bytes.ReadUInt32(8); + index = 12; + chAlignmentBitmask = 3; + } + else if (version == 3) + { + totalLength = (long)bytes.ReadUInt64(8); + index = 16; + chAlignmentBitmask = 7; + } + else { Logger?.Error(LogCode.GltfUnsupportedVersion, version.ToString()); Profiler.EndSample(); return false; } - - var totalLength = bytes.ReadUInt32(8); - if (totalLength > bytes.Length) + if (totalLength > k_MaxByteArraySize) + { + Logger?.Error(LogCode.GltfBinaryTooLarge, totalLength.ToString(), k_MaxByteArraySize.ToString()); + Profiler.EndSample(); + return false; + } + long bytesLength = (long)bytes.Length; + if (totalLength > bytesLength) { Logger?.Error(LogCode.UnexpectedEndOfContent); Profiler.EndSample(); return false; } - int index = 12; // first chunk header - Profiler.EndSample(); while (index < totalLength) @@ -2054,11 +2077,32 @@ CancellationToken cancellationToken Logger?.Error(LogCode.ChunkIncomplete); return false; } - - var chLength = bytes.ReadUInt32(index); - index += 4; - var chType = bytes.ReadUInt32(index); - index += 4; + // Read the chunk header (type, encoding, length). + uint chType = 0; + uint chEncoding = 0; + long chLength = 0; + if (version == 2) + { + chLength = (long)bytes.ReadUInt32(index); + index += 4; + chType = bytes.ReadUInt32(index); + index += 4; + } + else if (version == 3) + { + chType = bytes.ReadUInt32(index); + index += 4; + chEncoding = bytes.ReadUInt32(index); + index += 4; + chLength = (long)bytes.ReadUInt64(index); + index += 8; + } + // Only support plainly encoded chunks for now. + if (chEncoding != 0) + { + Logger?.Error(LogCode.GltfUnsupportedChunkEncoding, chEncoding.ToString()); + return false; + } if (index + chLength > totalLength) { @@ -2069,14 +2113,14 @@ CancellationToken cancellationToken if (chType == (uint)ChunkFormat.Binary) { Assert.IsFalse(m_GlbBinChunk.HasValue); // There can only be one binary chunk - m_GlbBinChunk = new GlbBinChunk(index, chLength); + m_GlbBinChunk = new GltfBufferRange(index, chLength); } else if (chType == (uint)ChunkFormat.Json) { Assert.IsNull(Root); Profiler.BeginSample("GetJSON"); - var bytesStream = bytes.ToUnmanagedMemoryStream((uint)index, chLength); + var bytesStream = bytes.ToUnmanagedMemoryStream((uint)index, (uint)chLength); var reader = new StreamReader(bytesStream); var json = await reader.ReadToEndAsync(); Profiler.EndSample(); @@ -2093,8 +2137,9 @@ CancellationToken cancellationToken Logger?.Error(LogCode.ChunkUnknown, chType.ToString()); return false; } - - index += (int)chLength; + // GLB spec says that the starts of chunks must be aligned to 4 or 8 byte boundaries, depending on the GLB version. + long paddedChLength = (chLength + chAlignmentBitmask) & ~chAlignmentBitmask; + index += paddedChLength; } if (Root == null) @@ -2103,11 +2148,11 @@ CancellationToken cancellationToken return false; } - if (m_GlbBinChunk.HasValue && m_BinChunks != null) + if (m_GlbBinChunk.HasValue && m_BufferRanges != null) { - m_BinChunks[0] = m_GlbBinChunk.Value; + m_BufferRanges[0] = m_GlbBinChunk.Value; var wrapper = new ReadOnlyNativeArrayFromNativeArray(bytes); - m_Buffers[0] = wrapper.Array; + m_BufferData[0] = wrapper.Array; } LoadImages(cancellationToken); return true; @@ -2115,7 +2160,7 @@ CancellationToken cancellationToken ReadOnlyNativeArray GetBuffer(int index) { - return m_Buffers[index]; + return m_BufferData[index]; } ReadOnlyNativeArray IGltfBuffers.GetBufferView(int bufferViewIndex, out int byteStride, int offset, int length) @@ -2208,13 +2253,13 @@ ReadOnlyNativeArray GetAccessorData( { Assert.IsTrue(offset >= 0); var bufferIndex = bufferView.Buffer; - Assert.IsNotNull(m_Buffers); - Assert.IsTrue(bufferIndex < m_Buffers.Length); - Assert.IsTrue(m_Buffers[bufferIndex].IsCreated); - var chunk = m_BinChunks[bufferIndex]; + Assert.IsNotNull(m_BufferData); + Assert.IsTrue(bufferIndex < m_BufferData.Length); + Assert.IsTrue(m_BufferData[bufferIndex].IsCreated); + var chunk = m_BufferRanges[bufferIndex]; var totalOffset = chunk.Start + bufferView.ByteOffset + offset; Assert.IsTrue(bufferView.ByteOffset + offset <= chunk.Length); - return m_Buffers[bufferIndex].GetSubArray(totalOffset, count * UnsafeUtility.SizeOf()).Reinterpret(); + return m_BufferData[bufferIndex].GetSubArray((int)totalOffset, count * UnsafeUtility.SizeOf()).Reinterpret(); } ReadOnlyNativeStridedArray GetStridedAccessorData( @@ -2225,14 +2270,14 @@ ReadOnlyNativeStridedArray GetStridedAccessorData( { Assert.IsTrue(offset >= 0); var bufferIndex = bufferView.Buffer; - Assert.IsNotNull(m_Buffers); - Assert.IsTrue(bufferIndex < m_Buffers.Length); - Assert.IsTrue(m_Buffers[bufferIndex].IsCreated); - var chunk = m_BinChunks[bufferIndex]; + Assert.IsNotNull(m_BufferData); + Assert.IsTrue(bufferIndex < m_BufferData.Length); + Assert.IsTrue(m_BufferData[bufferIndex].IsCreated); + var chunk = m_BufferRanges[bufferIndex]; var totalOffset = chunk.Start + bufferView.ByteOffset + offset; Assert.IsTrue(bufferView.ByteOffset + offset <= chunk.Length); var byteStride = bufferView.ByteStride > 0 ? bufferView.ByteStride : UnsafeUtility.SizeOf(typeof(T)); - return m_Buffers[bufferIndex].ToStrided(totalOffset, count, byteStride); + return m_BufferData[bufferIndex].ToStrided((int)totalOffset, count, byteStride); } async Task.ReadOnly> GetBufferViewAsync( @@ -2242,7 +2287,7 @@ ReadOnlyNativeStridedArray GetStridedAccessorData( ) { var bufferIndex = bufferView.Buffer; - if (!m_Buffers[bufferIndex].IsCreated) + if (!m_BufferData[bufferIndex].IsCreated) { var download = m_BufferLoadTasks?[bufferIndex]; if (download != null) @@ -2270,16 +2315,16 @@ ReadOnlyNativeArray GetBufferView( Assert.IsTrue(offset + length <= bufferView.ByteLength); var bufferIndex = bufferView.Buffer; - Assert.IsNotNull(m_Buffers); - Assert.IsTrue(bufferIndex < m_Buffers.Length); - Assert.IsTrue(m_Buffers[bufferIndex].IsCreated); + Assert.IsNotNull(m_BufferData); + Assert.IsTrue(bufferIndex < m_BufferData.Length); + Assert.IsTrue(m_BufferData[bufferIndex].IsCreated); - var chunk = m_BinChunks[bufferIndex]; - var nativeBuffer = m_Buffers[bufferIndex]; + var chunk = m_BufferRanges[bufferIndex]; + var nativeBuffer = m_BufferData[bufferIndex]; var totalOffset = chunk.Start + bufferView.ByteOffset + offset; Assert.IsTrue(bufferView.ByteOffset + offset <= chunk.Length); Assert.IsTrue(totalOffset + length <= nativeBuffer.Length); - return m_Buffers[bufferIndex].GetSubArray(totalOffset, length); + return m_BufferData[bufferIndex].GetSubArray((int)totalOffset, length); } #if MESHOPT_IS_ENABLED @@ -2937,8 +2982,8 @@ async Task DisposeTextureLoadTasks() /// void DisposeVolatileData() { - m_Buffers = null; - m_BinChunks = null; + m_BufferData = null; + m_BufferRanges = null; if (m_VolatileDisposables != null) { @@ -4036,7 +4081,7 @@ unsafe void IGltfBuffers.GetAccessorAndData(int index, out AccessorBase accessor var bufferIndex = bufferView.buffer; var buffer = GetBuffer(bufferIndex); data = (byte*)buffer.GetUnsafeReadOnlyPtr() - + (accessor.byteOffset + bufferView.byteOffset + m_BinChunks[bufferIndex].Start); + + (accessor.byteOffset + bufferView.byteOffset + m_BufferRanges[bufferIndex].Start); } // // Alternative that uses NativeArray/Slice @@ -4064,7 +4109,7 @@ public unsafe void GetAccessorSparseIndices(AccessorSparseIndices sparseIndices, var bufferIndex = bufferView.buffer; var buffer = GetBuffer(bufferIndex); data = (byte*)buffer.GetUnsafeReadOnlyPtr() - + (sparseIndices.byteOffset + bufferView.byteOffset + m_BinChunks[bufferIndex].Start); + + (sparseIndices.byteOffset + bufferView.byteOffset + m_BufferRanges[bufferIndex].Start); } } @@ -4088,7 +4133,7 @@ public unsafe void GetAccessorSparseValues(AccessorSparseValues sparseValues, ou var bufferIndex = bufferView.buffer; var buffer = GetBuffer(bufferIndex); data = (byte*)buffer.GetUnsafeReadOnlyPtr() - + (sparseValues.byteOffset + bufferView.byteOffset + m_BinChunks[bufferIndex].Start); + + (sparseValues.byteOffset + bufferView.byteOffset + m_BufferRanges[bufferIndex].Start); } } diff --git a/Packages/com.unity.cloud.gltfast/Runtime/Scripts/Logging/LogMessages.cs b/Packages/com.unity.cloud.gltfast/Runtime/Scripts/Logging/LogMessages.cs index 72bb3416c..36bf737b4 100644 --- a/Packages/com.unity.cloud.gltfast/Runtime/Scripts/Logging/LogMessages.cs +++ b/Packages/com.unity.cloud.gltfast/Runtime/Scripts/Logging/LogMessages.cs @@ -110,10 +110,18 @@ public enum LogCode : uint /// ExportImageFailed, /// + /// glTF-Binary length exceeds C# maximum byte array size + /// + GltfBinaryTooLarge, + /// /// Not a glTF-binary file /// GltfNotBinary, /// + /// Unsupported glTF chunk encoding (such as compression or encryption) + /// + GltfUnsupportedChunkEncoding, + /// /// Unsupported glTF version /// GltfUnsupportedVersion, @@ -303,8 +311,10 @@ This may result in low performance and high memory usage. Try optimizing the glT { LogCode.EmbedSlow, "JSON embed buffers are slow! consider using glTF binary" }, { LogCode.ExtensionUnsupported, "glTF extension {0} is not supported" }, { LogCode.ExportImageFailed, "Export image failed" }, + { LogCode.GltfBinaryTooLarge, "glTF-Binary length {0} exceeds C# maximum byte array size {1}" }, { LogCode.GltfNotBinary, "Not a glTF-binary file" }, { LogCode.UnexpectedEndOfContent, "Unexpected end of content" }, + { LogCode.GltfUnsupportedChunkEncoding, "Unsupported glTF chunk encoding {0} (data is compressed or encrypted)" }, { LogCode.GltfUnsupportedVersion, "Unsupported glTF version {0}" }, { LogCode.HierarchyInvalid, "Invalid hierarchy" }, { LogCode.ImageConversionNotEnabled, $"Jpeg/PNG textures failed because required built-in packages \"Image Conversion\"/\"Unity Web Request Texture\" are not enabled. {k_LinkProjectSetupTextureSupport}" }, diff --git a/Packages/com.unity.cloud.gltfast/Runtime/Scripts/NativeArrayExtensions.cs b/Packages/com.unity.cloud.gltfast/Runtime/Scripts/NativeArrayExtensions.cs index e20235bc2..44e161fd2 100644 --- a/Packages/com.unity.cloud.gltfast/Runtime/Scripts/NativeArrayExtensions.cs +++ b/Packages/com.unity.cloud.gltfast/Runtime/Scripts/NativeArrayExtensions.cs @@ -32,10 +32,16 @@ internal static unsafe UnmanagedMemoryStream ToUnmanagedMemoryStream(this Native ); } - internal static unsafe uint ReadUInt32(this NativeArray.ReadOnly data, int offset) + internal static unsafe uint ReadUInt32(this NativeArray.ReadOnly data, long offset) { var ptr = (uint*)((byte*)data.GetUnsafeReadOnlyPtr() + offset); return *ptr; } + + internal static unsafe ulong ReadUInt64(this NativeArray.ReadOnly data, long offset) + { + var ptr = (ulong*)((byte*)data.GetUnsafeReadOnlyPtr() + offset); + return *ptr; + } } } diff --git a/Packages/com.unity.cloud.gltfast/Runtime/Scripts/Schema/IBufferView.cs b/Packages/com.unity.cloud.gltfast/Runtime/Scripts/Schema/IBufferView.cs index 77d95ee7e..90063e467 100644 --- a/Packages/com.unity.cloud.gltfast/Runtime/Scripts/Schema/IBufferView.cs +++ b/Packages/com.unity.cloud.gltfast/Runtime/Scripts/Schema/IBufferView.cs @@ -26,7 +26,7 @@ public interface IBufferView int ByteLength { get; } /// - /// The stride, in bytes, between vertex attributes. + /// The stride, in bytes, between vertex attributes. If defined, must be a multiple of 4 and between 4 and 252. /// /// When this is 0 or negative, data is tightly packed. int ByteStride { get; } diff --git a/graphify-out/graph.json b/graphify-out/graph.json index aff204980..a672e911d 100644 --- a/graphify-out/graph.json +++ b/graphify-out/graph.json @@ -1522,7 +1522,7 @@ "norm_label": "list" }, { - "label": "GlbBinChunk", + "label": "GltfBufferRange", "file_type": "code", "source_file": "com.unity.cloud.gltfast/Runtime/Scripts/GltfImport.cs", "source_location": "L202", @@ -6760,9 +6760,9 @@ "norm_label": "checkreadindex()" }, { - "label": "GlbBinChunk.cs", + "label": "GltfBufferRange.cs", "file_type": "code", - "source_file": "com.unity.cloud.gltfast/Runtime/Scripts/GlbBinChunk.cs", + "source_file": "com.unity.cloud.gltfast/Runtime/Scripts/GltfBufferRange.cs", "source_location": "L1", "id": "com_unity_cloud_gltfast_runtime_scripts_glbbinchunk_cs", "community": 354, @@ -6771,7 +6771,7 @@ { "label": "GLTFast", "file_type": "code", - "source_file": "com.unity.cloud.gltfast/Runtime/Scripts/GlbBinChunk.cs", + "source_file": "com.unity.cloud.gltfast/Runtime/Scripts/GltfBufferRange.cs", "source_location": "L6", "id": "scripts_glbbinchunk_gltfast", "community": 354, @@ -33689,11 +33689,11 @@ "norm_label": "gameobjectsceneinstance" }, { - "label": "GlbBinChunk", + "label": "GltfBufferRange", "type": "struct", "file_type": "code", - "path": "Packages/com.unity.cloud.gltfast/Runtime/Scripts/GlbBinChunk.cs", - "summary": "Readonly struct describing start offset and length of a binary chunk inside a .glb file.", + "path": "Packages/com.unity.cloud.gltfast/Runtime/Scripts/GltfBufferRange.cs", + "summary": "Readonly struct describing start offset and length of a buffer in the glTF buffers array or a binary chunk inside a .glb file.", "id": "glbbinchunk_struct", "community": 448, "norm_label": "glbbinchunk" @@ -50993,7 +50993,7 @@ { "relation": "contains", "confidence": "EXTRACTED", - "source_file": "com.unity.cloud.gltfast/Runtime/Scripts/GlbBinChunk.cs", + "source_file": "com.unity.cloud.gltfast/Runtime/Scripts/GltfBufferRange.cs", "source_location": "L6", "weight": 1.0, "source": "com_unity_cloud_gltfast_runtime_scripts_glbbinchunk_cs",