From 7bcf2f6496f6501e7c39ca86974eb52a68e66f49 Mon Sep 17 00:00:00 2001 From: momoma-null Date: Wed, 10 Jun 2026 13:19:15 +0900 Subject: [PATCH] =?UTF-8?q?GlbLowLevelParser=E3=81=AE=E5=85=A5=E5=8A=9B?= =?UTF-8?q?=E3=82=92Memory=E3=81=A7=E3=81=A8=E3=82=8C=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/UniGLTF/Format/glbTypes.cs | 27 +++++++----- .../Runtime/UniGLTF/IO/NativeArrayManager.cs | 9 ++++ .../UniGLTF/IO/Parser/GlbLowLevelParser.cs | 13 +++--- .../UniGLTF/Runtime/UniGLTF/IO/glbImporter.cs | 44 ++++++++++++------- .../UniGLTF/Tests/UniGLTF/GlbParserTests.cs | 2 +- 5 files changed, 64 insertions(+), 31 deletions(-) diff --git a/Packages/UniGLTF/Runtime/UniGLTF/Format/glbTypes.cs b/Packages/UniGLTF/Runtime/UniGLTF/Format/glbTypes.cs index 9628e9344..999d6c352 100644 --- a/Packages/UniGLTF/Runtime/UniGLTF/Format/glbTypes.cs +++ b/Packages/UniGLTF/Runtime/UniGLTF/Format/glbTypes.cs @@ -28,10 +28,11 @@ namespace UniGLTF public struct GlbChunk { - public GlbChunkType ChunkType => ChunkTypeString.ToChunkType(); + public GlbChunkType ChunkType => ChunkTypeBytes.ToChunkType(); - public string ChunkTypeString; - public ArraySegment Bytes; + public string ChunkTypeString => Encoding.ASCII.GetString(ChunkTypeBytes.Span); + public ReadOnlyMemory Bytes; + public ReadOnlyMemory ChunkTypeBytes; public GlbChunk(string json) : this( GlbChunkType.JSON.ToChunkTypeString(), @@ -49,7 +50,13 @@ namespace UniGLTF public GlbChunk(string chunkTypeString, ArraySegment bytes) { - ChunkTypeString = chunkTypeString; + ChunkTypeBytes = Encoding.ASCII.GetBytes(chunkTypeString); + Bytes = bytes; + } + + public GlbChunk(ReadOnlyMemory chunkTypeBytes, ReadOnlyMemory bytes) + { + ChunkTypeBytes = chunkTypeBytes; Bytes = bytes; } @@ -60,12 +67,12 @@ namespace UniGLTF public static GlbChunk CreateJson(ArraySegment bytes) { - return new GlbChunk(GlbChunkType.JSON.ToChunkTypeString(), bytes); + return new GlbChunk(glbImporter.GLB_JSON_BYTES, bytes); } public static GlbChunk CreateBin(ArraySegment bytes) { - return new GlbChunk(GlbChunkType.BIN.ToChunkTypeString(), bytes); + return new GlbChunk(glbImporter.GLB_BIN_BYTES, bytes); } byte GetPaddingByte() @@ -87,11 +94,11 @@ namespace UniGLTF public int WriteTo(Stream s) { // padding - var paddingValue = Bytes.Count % 4; + var paddingValue = Bytes.Length % 4; var padding = (paddingValue > 0) ? 4 - paddingValue : 0; // size - var bytes = BitConverter.GetBytes((int)(Bytes.Count + padding)); + var bytes = BitConverter.GetBytes((int)(Bytes.Length + padding)); s.Write(bytes, 0, bytes.Length); // chunk type @@ -116,7 +123,7 @@ namespace UniGLTF } // body - s.Write(Bytes.Array, Bytes.Offset, Bytes.Count); + s.Write(Bytes.Span); // 4byte align var pad = GetPaddingByte(); @@ -125,7 +132,7 @@ namespace UniGLTF s.WriteByte(pad); } - return 4 + 4 + Bytes.Count + padding; + return 4 + 4 + Bytes.Length + padding; } } diff --git a/Packages/UniGLTF/Runtime/UniGLTF/IO/NativeArrayManager.cs b/Packages/UniGLTF/Runtime/UniGLTF/IO/NativeArrayManager.cs index 58e0b833b..01f358f95 100644 --- a/Packages/UniGLTF/Runtime/UniGLTF/IO/NativeArrayManager.cs +++ b/Packages/UniGLTF/Runtime/UniGLTF/IO/NativeArrayManager.cs @@ -87,6 +87,15 @@ namespace UniGLTF return array; } + public NativeArray CreateNativeArray(ReadOnlyMemory data) where T : struct + { + var array = CreateNativeArray(data.Length); + var toSpan = array.AsSpan(); + var fromSpan = data.Span; + fromSpan.CopyTo(toSpan); + return array; + } + /// /// サイズの違う型にコピーする。 /// diff --git a/Packages/UniGLTF/Runtime/UniGLTF/IO/Parser/GlbLowLevelParser.cs b/Packages/UniGLTF/Runtime/UniGLTF/IO/Parser/GlbLowLevelParser.cs index 4aa2739d3..7b5f4723c 100644 --- a/Packages/UniGLTF/Runtime/UniGLTF/IO/Parser/GlbLowLevelParser.cs +++ b/Packages/UniGLTF/Runtime/UniGLTF/IO/Parser/GlbLowLevelParser.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Text; using System.Text.RegularExpressions; using UniJSON; @@ -24,15 +25,17 @@ namespace UniGLTF _binary = specifiedBinary; } - public GltfData Parse() + public GltfData Parse() => Parse(_path, _binary); + + public static GltfData Parse(string path, ReadOnlyMemory binary) { try { - var chunks = ParseGlbChunks(_binary); + var chunks = ParseGlbChunks(binary); var jsonBytes = chunks[0].Bytes; return ParseGltf( - _path, - new Utf8String(new ArraySegment(jsonBytes.Array, jsonBytes.Offset, jsonBytes.Count)), + path, + Encoding.UTF8.GetString(jsonBytes.Span), chunks, default, new MigrationFlags() @@ -48,7 +51,7 @@ namespace UniGLTF } } - public static List ParseGlbChunks(byte[] data) + public static List ParseGlbChunks(ReadOnlyMemory data) { var chunks = glbImporter.ParseGlbChunks(data); diff --git a/Packages/UniGLTF/Runtime/UniGLTF/IO/glbImporter.cs b/Packages/UniGLTF/Runtime/UniGLTF/IO/glbImporter.cs index ac3eabf2d..3df655ee8 100644 --- a/Packages/UniGLTF/Runtime/UniGLTF/IO/glbImporter.cs +++ b/Packages/UniGLTF/Runtime/UniGLTF/IO/glbImporter.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; @@ -9,7 +8,11 @@ namespace UniGLTF public static class glbImporter { public const string GLB_MAGIC = "glTF"; - public const float GLB_VERSION = 2.0f; + public const uint GLB_VERSION = 2; + + public static readonly ReadOnlyMemory GLB_MAGIC_BYTES = Encoding.ASCII.GetBytes(GLB_MAGIC); + public static readonly ReadOnlyMemory GLB_JSON_BYTES = BitConverter.GetBytes((uint)GlbChunkType.JSON); + public static readonly ReadOnlyMemory GLB_BIN_BYTES = BitConverter.GetBytes((uint)GlbChunkType.BIN); public static GlbChunkType ToChunkType(this string src) { @@ -39,13 +42,30 @@ namespace UniGLTF } } + public static GlbChunkType ToChunkType(this ReadOnlyMemory src) + { + if (src.Length != 4) + { + throw new FormatException("invalid chunk type: " + src); + } + if (src.Span.SequenceEqual(GLB_JSON_BYTES.Span)) + { + return GlbChunkType.JSON; + } + if (src.Span.SequenceEqual(GLB_BIN_BYTES.Span)) + { + return GlbChunkType.BIN; + } + throw new FormatException("unknown chunk type: " + src); + } + [Obsolete("Use ParseGlbChunks(bytes)")] public static List ParseGlbChanks(Byte[] bytes) { return ParseGlbChunks(bytes); } - public static List ParseGlbChunks(Byte[] bytes) + public static List ParseGlbChunks(ReadOnlyMemory bytes) { // // glb header(12byte) @@ -56,20 +76,20 @@ namespace UniGLTF } int pos = 0; - if (Encoding.ASCII.GetString(bytes, 0, 4) != GLB_MAGIC) + if (!bytes[..4].Span.SequenceEqual(GLB_MAGIC_BYTES.Span)) { throw new GlbParseException("invalid magic"); } pos += 4; - var version = BitConverter.ToUInt32(bytes, pos); + var version = BitConverter.ToUInt32(bytes[pos..].Span); if (version != GLB_VERSION) { throw new GlbParseException($"unknown version: {version}"); } pos += 4; - var totalLength = BitConverter.ToUInt32(bytes, pos); + var totalLength = BitConverter.ToUInt32(bytes[pos..].Span); if (bytes.Length < totalLength) { throw new GlbParseException($"not enough size: {bytes.Length} < {totalLength}"); @@ -79,19 +99,13 @@ namespace UniGLTF var chunks = new List(); while (pos < bytes.Length) { - var chunkDataSize = BitConverter.ToInt32(bytes, pos); + var chunkDataSize = BitConverter.ToInt32(bytes[pos..].Span); pos += 4; - //var type = (GlbChunkType)BitConverter.ToUInt32(bytes, pos); - var chunkTypeBytes = bytes.Skip(pos).Take(4).Where(x => x != 0).ToArray(); - var chunkTypeStr = Encoding.ASCII.GetString(chunkTypeBytes); + var chunkTypeBytes = bytes.Slice(pos, 4); pos += 4; - chunks.Add(new GlbChunk - { - ChunkTypeString = chunkTypeStr, - Bytes = new ArraySegment(bytes, (int)pos, (int)chunkDataSize) - }); + chunks.Add(new GlbChunk(chunkTypeBytes, bytes.Slice(pos, chunkDataSize))); pos += chunkDataSize; } diff --git a/Packages/UniGLTF/Tests/UniGLTF/GlbParserTests.cs b/Packages/UniGLTF/Tests/UniGLTF/GlbParserTests.cs index 15c184b75..00f66c0b0 100644 --- a/Packages/UniGLTF/Tests/UniGLTF/GlbParserTests.cs +++ b/Packages/UniGLTF/Tests/UniGLTF/GlbParserTests.cs @@ -66,7 +66,7 @@ namespace UniGLTF { // glb header + 1st chunk only - var mod = bytes.Take(12 + 8 + data.Chunks[0].Bytes.Count).ToArray(); + var mod = bytes.Take(12 + 8 + data.Chunks[0].Bytes.Length).ToArray(); Assert.Throws(() => {