GlbLowLevelParserの入力をMemoryでとれるようにする

This commit is contained in:
momoma-null
2026-06-10 13:19:15 +09:00
committed by hadashiA
parent a4711bbf8c
commit 7bcf2f6496
5 changed files with 64 additions and 31 deletions

View File

@@ -28,10 +28,11 @@ namespace UniGLTF
public struct GlbChunk
{
public GlbChunkType ChunkType => ChunkTypeString.ToChunkType();
public GlbChunkType ChunkType => ChunkTypeBytes.ToChunkType();
public string ChunkTypeString;
public ArraySegment<Byte> Bytes;
public string ChunkTypeString => Encoding.ASCII.GetString(ChunkTypeBytes.Span);
public ReadOnlyMemory<byte> Bytes;
public ReadOnlyMemory<byte> ChunkTypeBytes;
public GlbChunk(string json) : this(
GlbChunkType.JSON.ToChunkTypeString(),
@@ -49,7 +50,13 @@ namespace UniGLTF
public GlbChunk(string chunkTypeString, ArraySegment<Byte> bytes)
{
ChunkTypeString = chunkTypeString;
ChunkTypeBytes = Encoding.ASCII.GetBytes(chunkTypeString);
Bytes = bytes;
}
public GlbChunk(ReadOnlyMemory<byte> chunkTypeBytes, ReadOnlyMemory<byte> bytes)
{
ChunkTypeBytes = chunkTypeBytes;
Bytes = bytes;
}
@@ -60,12 +67,12 @@ namespace UniGLTF
public static GlbChunk CreateJson(ArraySegment<byte> bytes)
{
return new GlbChunk(GlbChunkType.JSON.ToChunkTypeString(), bytes);
return new GlbChunk(glbImporter.GLB_JSON_BYTES, bytes);
}
public static GlbChunk CreateBin(ArraySegment<Byte> 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;
}
}

View File

@@ -87,6 +87,15 @@ namespace UniGLTF
return array;
}
public NativeArray<T> CreateNativeArray<T>(ReadOnlyMemory<T> data) where T : struct
{
var array = CreateNativeArray<T>(data.Length);
var toSpan = array.AsSpan();
var fromSpan = data.Span;
fromSpan.CopyTo(toSpan);
return array;
}
/// <summary>
/// サイズの違う型にコピーする。
///

View File

@@ -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<byte> binary)
{
try
{
var chunks = ParseGlbChunks(_binary);
var chunks = ParseGlbChunks(binary);
var jsonBytes = chunks[0].Bytes;
return ParseGltf(
_path,
new Utf8String(new ArraySegment<byte>(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<GlbChunk> ParseGlbChunks(byte[] data)
public static List<GlbChunk> ParseGlbChunks(ReadOnlyMemory<byte> data)
{
var chunks = glbImporter.ParseGlbChunks(data);

View File

@@ -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<byte> GLB_MAGIC_BYTES = Encoding.ASCII.GetBytes(GLB_MAGIC);
public static readonly ReadOnlyMemory<byte> GLB_JSON_BYTES = BitConverter.GetBytes((uint)GlbChunkType.JSON);
public static readonly ReadOnlyMemory<byte> 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<byte> 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<GlbChunk> ParseGlbChanks(Byte[] bytes)
{
return ParseGlbChunks(bytes);
}
public static List<GlbChunk> ParseGlbChunks(Byte[] bytes)
public static List<GlbChunk> ParseGlbChunks(ReadOnlyMemory<byte> 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<GlbChunk>();
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<byte>(bytes, (int)pos, (int)chunkDataSize)
});
chunks.Add(new GlbChunk(chunkTypeBytes, bytes.Slice(pos, chunkDataSize)));
pos += chunkDataSize;
}

View File

@@ -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<GlbParseException>(() =>
{