mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-08 11:59:26 -05:00
Merge pull request #1343 from ousttrue/fix/data_uri_handling
bufferView の data uri を実装
This commit is contained in:
@@ -114,16 +114,19 @@ namespace UniGLTF
|
||||
}
|
||||
else
|
||||
{
|
||||
var (json, buffers) = data.ToGltf(path);
|
||||
// without BOM
|
||||
var encoding = new System.Text.UTF8Encoding(false);
|
||||
File.WriteAllText(path, json, encoding);
|
||||
// write to local folder
|
||||
var dir = Path.GetDirectoryName(path);
|
||||
foreach (var b in buffers)
|
||||
var (json, buffer0) = data.ToGltf(path);
|
||||
|
||||
{
|
||||
var bufferPath = Path.Combine(dir, b.uri);
|
||||
File.WriteAllBytes(bufferPath, b.GetBytes().ToArray());
|
||||
// write JSON without BOM
|
||||
var encoding = new System.Text.UTF8Encoding(false);
|
||||
File.WriteAllText(path, json, encoding);
|
||||
}
|
||||
|
||||
{
|
||||
// write to buffer0 local folder
|
||||
var dir = Path.GetDirectoryName(path);
|
||||
var bufferPath = Path.Combine(dir, buffer0.uri);
|
||||
File.WriteAllBytes(bufferPath, data.BinBytes.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,10 +12,6 @@ namespace UniGLTF
|
||||
/// 1. url による相対パス
|
||||
/// 2. url によるbase64 encoding
|
||||
/// 3. url がnullのときに bin chunk(buffers[0]) にアクセスする
|
||||
///
|
||||
/// TODO:
|
||||
/// 1. url による相対パス
|
||||
/// 以外をやめて、呼び出し側で分岐させる。
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
@@ -6,24 +6,6 @@ namespace UniGLTF
|
||||
[Serializable]
|
||||
public class glTFBuffer
|
||||
{
|
||||
IBytesBuffer m_buffer;
|
||||
public IBytesBuffer Buffer => m_buffer;
|
||||
|
||||
public void OpenStorage(IStorage storage)
|
||||
{
|
||||
m_buffer = new ArraySegmentByteBuffer(storage.Get(uri));
|
||||
}
|
||||
|
||||
public glTFBuffer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public glTFBuffer(IBytesBuffer storage)
|
||||
{
|
||||
m_buffer = storage;
|
||||
}
|
||||
|
||||
public string uri;
|
||||
|
||||
[JsonSchema(Required = true, Minimum = 1)]
|
||||
@@ -33,22 +15,6 @@ namespace UniGLTF
|
||||
public glTFExtension extensions;
|
||||
public glTFExtension extras;
|
||||
public string name;
|
||||
|
||||
public glTFBufferView Append<T>(T[] array, glBufferTarget target) where T : struct
|
||||
{
|
||||
return Append(new ArraySegment<T>(array), target);
|
||||
}
|
||||
public glTFBufferView Append<T>(ArraySegment<T> segment, glBufferTarget target) where T : struct
|
||||
{
|
||||
var view = m_buffer.Extend(segment, target);
|
||||
byteLength = m_buffer.Bytes.Count;
|
||||
return view;
|
||||
}
|
||||
|
||||
public ArraySegment<Byte> GetBytes()
|
||||
{
|
||||
return m_buffer.Bytes;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
||||
@@ -7,9 +7,13 @@ namespace UniGLTF
|
||||
{
|
||||
public class ExportingGltfData
|
||||
{
|
||||
readonly glTF _gltf = new glTF();
|
||||
public glTF GLTF { get; } = new glTF();
|
||||
|
||||
public glTF GLTF => _gltf;
|
||||
protected IBytesBuffer _buffer;
|
||||
/// <summary>
|
||||
/// bin chunk
|
||||
/// </summary>
|
||||
public ArraySegment<byte> BinBytes => _buffer.Bytes;
|
||||
|
||||
public ExportingGltfData(int reserved = default)
|
||||
{
|
||||
@@ -17,11 +21,20 @@ namespace UniGLTF
|
||||
{
|
||||
reserved = 50 * 1024 * 1024;
|
||||
}
|
||||
// glb body と gltf の bin 兼用
|
||||
_gltf.buffers.Add(new glTFBuffer(new ArrayByteBuffer(new byte[reserved])));
|
||||
|
||||
// buffers[0] is export target
|
||||
GLTF.buffers.Add(new glTFBuffer());
|
||||
_buffer = new ArrayByteBuffer(new byte[reserved]);
|
||||
}
|
||||
|
||||
#region Buffer management for export
|
||||
public glTFBufferView ExtendBufferAndGetView<T>(ArraySegment<T> segment, glBufferTarget target) where T : struct
|
||||
{
|
||||
var view = _buffer.Extend(segment, target);
|
||||
GLTF.buffers[0].byteLength = _buffer.Bytes.Count;
|
||||
return view;
|
||||
}
|
||||
|
||||
public int ExtendBufferAndGetViewIndex<T>(
|
||||
ArraySegment<T> array,
|
||||
glBufferTarget target = glBufferTarget.NONE) where T : struct
|
||||
@@ -30,9 +43,9 @@ namespace UniGLTF
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
var view = _gltf.buffers[0].Append(array, target);
|
||||
var viewIndex = _gltf.bufferViews.Count;
|
||||
_gltf.bufferViews.Add(view);
|
||||
var view = ExtendBufferAndGetView(array, target);
|
||||
var viewIndex = GLTF.bufferViews.Count;
|
||||
GLTF.bufferViews.Add(view);
|
||||
return viewIndex;
|
||||
}
|
||||
|
||||
@@ -54,10 +67,10 @@ namespace UniGLTF
|
||||
var viewIndex = ExtendBufferAndGetViewIndex(array, target);
|
||||
|
||||
// index buffer's byteStride is unnecessary
|
||||
_gltf.bufferViews[viewIndex].byteStride = 0;
|
||||
GLTF.bufferViews[viewIndex].byteStride = 0;
|
||||
|
||||
var accessorIndex = _gltf.accessors.Count;
|
||||
_gltf.accessors.Add(new glTFAccessor
|
||||
var accessorIndex = GLTF.accessors.Count;
|
||||
GLTF.accessors.Add(new glTFAccessor
|
||||
{
|
||||
bufferView = viewIndex,
|
||||
byteOffset = 0,
|
||||
@@ -98,8 +111,8 @@ namespace UniGLTF
|
||||
return -1;
|
||||
}
|
||||
var sparseValuesViewIndex = ExtendBufferAndGetViewIndex(sparseValues, target);
|
||||
var accessorIndex = _gltf.accessors.Count;
|
||||
_gltf.accessors.Add(new glTFAccessor
|
||||
var accessorIndex = GLTF.accessors.Count;
|
||||
GLTF.accessors.Add(new glTFAccessor
|
||||
{
|
||||
byteOffset = 0,
|
||||
componentType = glTFExtensions.GetComponentType<T>(),
|
||||
@@ -192,12 +205,12 @@ namespace UniGLTF
|
||||
public byte[] ToGlbBytes()
|
||||
{
|
||||
var f = new JsonFormatter();
|
||||
GltfSerializer.Serialize(f, _gltf);
|
||||
GltfSerializer.Serialize(f, GLTF);
|
||||
|
||||
// remove unused extenions
|
||||
var json = f.ToString().ParseAsJson().ToString(" ");
|
||||
RemoveUnusedExtensions(_gltf, json);
|
||||
return Glb.Create(json, _gltf.buffers[0].GetBytes()).ToBytes();
|
||||
RemoveUnusedExtensions(GLTF, json);
|
||||
return Glb.Create(json, BinBytes).ToBytes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -205,13 +218,13 @@ namespace UniGLTF
|
||||
/// </summary>
|
||||
/// <param name="gltfPath"></param>
|
||||
/// <returns></returns>
|
||||
public (string, List<glTFBuffer>) ToGltf(string gltfPath)
|
||||
public (string, glTFBuffer) ToGltf(string gltfPath)
|
||||
{
|
||||
// fix buffer path
|
||||
if (_gltf.buffers.Count == 1)
|
||||
if (GLTF.buffers.Count == 1)
|
||||
{
|
||||
var withoutExt = Path.GetFileNameWithoutExtension(gltfPath);
|
||||
_gltf.buffers[0].uri = $"{withoutExt}.bin";
|
||||
GLTF.buffers[0].uri = $"{withoutExt}.bin";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -219,10 +232,10 @@ namespace UniGLTF
|
||||
}
|
||||
|
||||
var f = new JsonFormatter();
|
||||
GltfSerializer.Serialize(f, _gltf);
|
||||
GltfSerializer.Serialize(f, GLTF);
|
||||
var json = f.ToString().ParseAsJson().ToString(" ");
|
||||
RemoveUnusedExtensions(_gltf, json);
|
||||
return (json, _gltf.buffers);
|
||||
RemoveUnusedExtensions(GLTF, json);
|
||||
return (json, GLTF.buffers[0]);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -1,31 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
/// <summary>
|
||||
/// Implement bin chunk access
|
||||
/// </summary>
|
||||
public class SimpleStorage : IStorage
|
||||
{
|
||||
ArraySegment<Byte> m_bytes;
|
||||
|
||||
public SimpleStorage() : this(new ArraySegment<byte>())
|
||||
{
|
||||
}
|
||||
|
||||
public SimpleStorage(ArraySegment<Byte> bytes)
|
||||
{
|
||||
m_bytes = bytes;
|
||||
}
|
||||
|
||||
public ArraySegment<byte> Get(string url)
|
||||
{
|
||||
return m_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implement url that represnet relative path
|
||||
/// </summary>
|
||||
@@ -40,30 +17,8 @@ namespace UniGLTF
|
||||
|
||||
public ArraySegment<byte> Get(string url)
|
||||
{
|
||||
var bytes =
|
||||
(url.FastStartsWith("data:"))
|
||||
? UriByteBuffer.ReadEmbedded(url)
|
||||
: File.ReadAllBytes(Path.Combine(m_root, url))
|
||||
;
|
||||
var bytes = File.ReadAllBytes(Path.Combine(m_root, url));
|
||||
return new ArraySegment<byte>(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// for UnitTest
|
||||
/// </summary>
|
||||
public sealed class GltfStorage : IStorage
|
||||
{
|
||||
glTF _gltf;
|
||||
|
||||
public GltfStorage(glTF gltf)
|
||||
{
|
||||
_gltf = gltf;
|
||||
}
|
||||
|
||||
public ArraySegment<byte> Get(string url)
|
||||
{
|
||||
return _gltf.buffers[0].GetBytes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,18 +42,34 @@ namespace UniGLTF
|
||||
/// > This chunk MUST be the second chunk of the Binary glTF asset
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ArraySegment<byte> Bin => Chunks[1].Bytes;
|
||||
|
||||
/// <summary>
|
||||
/// URI access
|
||||
/// </summary>
|
||||
public IStorage _storage;
|
||||
public ArraySegment<byte> Bin
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Chunks == null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
if (Chunks.Count < 2)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
return Chunks[1].Bytes;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Migration Flags used by ImporterContext
|
||||
/// </summary>
|
||||
public MigrationFlags MigrationFlags { get; }
|
||||
|
||||
/// <summary>
|
||||
/// URI access
|
||||
/// </summary>
|
||||
IStorage _storage;
|
||||
|
||||
Dictionary<string, ArraySegment<byte>> _dataUriCache = new Dictionary<string, ArraySegment<byte>>();
|
||||
|
||||
public GltfData(string targetPath, string json, glTF gltf, IReadOnlyList<GlbChunk> chunks, IStorage storage, MigrationFlags migrationFlags)
|
||||
{
|
||||
TargetPath = targetPath;
|
||||
@@ -64,72 +80,114 @@ namespace UniGLTF
|
||||
MigrationFlags = migrationFlags;
|
||||
}
|
||||
|
||||
public static GltfData CreateFromGltfDataForTest(glTF gltf, ArraySegment<byte> bytes = default)
|
||||
public static GltfData CreateFromExportForTest(ExportingGltfData data)
|
||||
{
|
||||
return CreateFromGltfDataForTest(data.GLTF, data.BinBytes);
|
||||
}
|
||||
|
||||
public static GltfData CreateFromGltfDataForTest(glTF gltf, ArraySegment<byte> bytes)
|
||||
{
|
||||
IStorage storage = null;
|
||||
if (bytes.Array != null)
|
||||
{
|
||||
storage = new SimpleStorage(bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
storage = new GltfStorage(gltf);
|
||||
}
|
||||
return new GltfData(
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
gltf,
|
||||
new List<GlbChunk>(),
|
||||
storage,
|
||||
new List<GlbChunk>
|
||||
{
|
||||
new GlbChunk(), // json
|
||||
GlbChunk.CreateBin(bytes),
|
||||
},
|
||||
default,
|
||||
new MigrationFlags()
|
||||
);
|
||||
}
|
||||
|
||||
public ArraySegment<Byte> GetBytes(int bufferIndex)
|
||||
public ArraySegment<Byte> GetBytesFromUri(string uri)
|
||||
{
|
||||
// TODO:
|
||||
var buffer = GLTF.buffers[bufferIndex];
|
||||
return _storage.Get(buffer.uri);
|
||||
if (string.IsNullOrEmpty(uri))
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
if (uri.StartsWith("data:", StringComparison.Ordinal))
|
||||
{
|
||||
if (_dataUriCache.TryGetValue(uri, out ArraySegment<byte> data))
|
||||
{
|
||||
return data;
|
||||
}
|
||||
data = new ArraySegment<byte>(UriByteBuffer.ReadEmbedded(uri));
|
||||
_dataUriCache.Add(uri, data);
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _storage.Get(uri);
|
||||
}
|
||||
}
|
||||
|
||||
public ArraySegment<Byte> GetViewBytes(int bufferView)
|
||||
public ArraySegment<Byte> GetBytesFromBuffer(int bufferIndex)
|
||||
{
|
||||
var buffer = GLTF.buffers[bufferIndex];
|
||||
if (bufferIndex == 0 && string.IsNullOrEmpty(buffer.uri))
|
||||
{
|
||||
// https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#glb-stored-buffer
|
||||
// this buffer is reference bin chunk
|
||||
if (Bin.Array == null)
|
||||
{
|
||||
throw new NullReferenceException();
|
||||
}
|
||||
return Bin;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetBytesFromUri(buffer.uri);
|
||||
}
|
||||
}
|
||||
|
||||
public ArraySegment<Byte> GetBytesFromBufferView(int bufferView)
|
||||
{
|
||||
var view = GLTF.bufferViews[bufferView];
|
||||
var segment = GetBytes(view.buffer);
|
||||
var segment = GetBytesFromBuffer(view.buffer);
|
||||
return new ArraySegment<byte>(segment.Array, segment.Offset + view.byteOffset, view.byteLength);
|
||||
}
|
||||
|
||||
T[] GetAttrib<T>(int count, int byteOffset, glTFBufferView view) where T : struct
|
||||
T[] GetTypedFromBufferView<T>(int count, int byteOffset, glTFBufferView view) where T : struct
|
||||
{
|
||||
var segment = GetBytes(view.buffer);
|
||||
var segment = GetBytesFromBuffer(view.buffer);
|
||||
var attrib = new T[count];
|
||||
var bytes = new ArraySegment<Byte>(segment.Array, segment.Offset + view.byteOffset + byteOffset, count * view.byteStride);
|
||||
bytes.MarshalCopyTo(attrib);
|
||||
return attrib;
|
||||
}
|
||||
|
||||
T[] GetAttrib<T>(glTFAccessor accessor, glTFBufferView view) where T : struct
|
||||
T[] GetTypedFromAccessor<T>(glTFAccessor accessor, glTFBufferView view) where T : struct
|
||||
{
|
||||
return GetAttrib<T>(accessor.count, accessor.byteOffset, view);
|
||||
return GetTypedFromBufferView<T>(accessor.count, accessor.byteOffset, view);
|
||||
}
|
||||
|
||||
IEnumerable<int> _GetIndices(glTFBufferView view, int count, int byteOffset, glComponentType componentType)
|
||||
/// <summary>
|
||||
/// for sparse
|
||||
/// </summary>
|
||||
/// <param name="view"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <param name="byteOffset"></param>
|
||||
/// <param name="componentType"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<int> GetIntIndicesFromView(glTFBufferView view, int count, int byteOffset, glComponentType componentType)
|
||||
{
|
||||
switch (componentType)
|
||||
{
|
||||
case glComponentType.UNSIGNED_BYTE:
|
||||
{
|
||||
return GetAttrib<Byte>(count, byteOffset, view).Select(x => (int)(x));
|
||||
return GetTypedFromBufferView<Byte>(count, byteOffset, view).Select(x => (int)(x));
|
||||
}
|
||||
|
||||
case glComponentType.UNSIGNED_SHORT:
|
||||
{
|
||||
return GetAttrib<UInt16>(count, byteOffset, view).Select(x => (int)(x));
|
||||
return GetTypedFromBufferView<UInt16>(count, byteOffset, view).Select(x => (int)(x));
|
||||
}
|
||||
|
||||
case glComponentType.UNSIGNED_INT:
|
||||
{
|
||||
return GetAttrib<UInt32>(count, byteOffset, view).Select(x => (int)(x));
|
||||
return GetTypedFromBufferView<UInt32>(count, byteOffset, view).Select(x => (int)(x));
|
||||
}
|
||||
}
|
||||
throw new NotImplementedException("GetIndices: unknown componenttype: " + componentType);
|
||||
@@ -141,7 +199,7 @@ namespace UniGLTF
|
||||
/// <param name="accessor"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<int> _GetIndices(glTFAccessor accessor, out int count)
|
||||
IEnumerable<int> GetIntIndicesFromAccessor(glTFAccessor accessor, out int count)
|
||||
{
|
||||
count = accessor.count;
|
||||
var view = GLTF.bufferViews[accessor.bufferView];
|
||||
@@ -149,17 +207,17 @@ namespace UniGLTF
|
||||
{
|
||||
case glComponentType.UNSIGNED_BYTE:
|
||||
{
|
||||
return GetAttrib<Byte>(accessor, view).Select(x => (int)(x));
|
||||
return GetTypedFromAccessor<Byte>(accessor, view).Select(x => (int)(x));
|
||||
}
|
||||
|
||||
case glComponentType.UNSIGNED_SHORT:
|
||||
{
|
||||
return GetAttrib<UInt16>(accessor, view).Select(x => (int)(x));
|
||||
return GetTypedFromAccessor<UInt16>(accessor, view).Select(x => (int)(x));
|
||||
}
|
||||
|
||||
case glComponentType.UNSIGNED_INT:
|
||||
{
|
||||
return GetAttrib<UInt32>(accessor, view).Select(x => (int)(x));
|
||||
return GetTypedFromAccessor<UInt32>(accessor, view).Select(x => (int)(x));
|
||||
}
|
||||
}
|
||||
throw new NotImplementedException("GetIndices: unknown componenttype: " + accessor.componentType);
|
||||
@@ -168,7 +226,7 @@ namespace UniGLTF
|
||||
public int[] GetIndices(int accessorIndex)
|
||||
{
|
||||
int count;
|
||||
var result = _GetIndices(GLTF.accessors[accessorIndex], out count);
|
||||
var result = GetIntIndicesFromAccessor(GLTF.accessors[accessorIndex], out count);
|
||||
var indices = new int[count];
|
||||
|
||||
// flip triangles
|
||||
@@ -192,7 +250,7 @@ namespace UniGLTF
|
||||
if (vertexAccessor.count <= 0) return new T[] { };
|
||||
|
||||
var result = (vertexAccessor.bufferView != -1)
|
||||
? GetAttrib<T>(vertexAccessor, GLTF.bufferViews[vertexAccessor.bufferView])
|
||||
? GetTypedFromAccessor<T>(vertexAccessor, GLTF.bufferViews[vertexAccessor.bufferView])
|
||||
: new T[vertexAccessor.count]
|
||||
;
|
||||
|
||||
@@ -200,8 +258,8 @@ namespace UniGLTF
|
||||
if (sparse != null && sparse.count > 0)
|
||||
{
|
||||
// override sparse values
|
||||
var indices = _GetIndices(GLTF.bufferViews[sparse.indices.bufferView], sparse.count, sparse.indices.byteOffset, sparse.indices.componentType);
|
||||
var values = GetAttrib<T>(sparse.count, sparse.values.byteOffset, GLTF.bufferViews[sparse.values.bufferView]);
|
||||
var indices = GetIntIndicesFromView(GLTF.bufferViews[sparse.indices.bufferView], sparse.count, sparse.indices.byteOffset, sparse.indices.componentType);
|
||||
var values = GetTypedFromBufferView<T>(sparse.count, sparse.values.byteOffset, GLTF.bufferViews[sparse.values.bufferView]);
|
||||
|
||||
var it = indices.GetEnumerator();
|
||||
for (int i = 0; i < sparse.count; ++i)
|
||||
@@ -226,7 +284,7 @@ namespace UniGLTF
|
||||
{
|
||||
var attrib = new float[vertexAccessor.count * vertexAccessor.TypeCount];
|
||||
var view = GLTF.bufferViews[vertexAccessor.bufferView];
|
||||
var segment = GetBytes(view.buffer);
|
||||
var segment = GetBytesFromBuffer(view.buffer);
|
||||
var bytes = new ArraySegment<Byte>(segment.Array, segment.Offset + view.byteOffset + vertexAccessor.byteOffset, vertexAccessor.count * view.byteStride);
|
||||
bytes.MarshalCopyTo(attrib);
|
||||
result = attrib;
|
||||
@@ -240,8 +298,8 @@ namespace UniGLTF
|
||||
if (sparse != null && sparse.count > 0)
|
||||
{
|
||||
// override sparse values
|
||||
var indices = _GetIndices(GLTF.bufferViews[sparse.indices.bufferView], sparse.count, sparse.indices.byteOffset, sparse.indices.componentType);
|
||||
var values = GetAttrib<float>(sparse.count * vertexAccessor.TypeCount, sparse.values.byteOffset, GLTF.bufferViews[sparse.values.bufferView]);
|
||||
var indices = GetIntIndicesFromView(GLTF.bufferViews[sparse.indices.bufferView], sparse.count, sparse.indices.byteOffset, sparse.indices.componentType);
|
||||
var values = GetTypedFromBufferView<float>(sparse.count * vertexAccessor.TypeCount, sparse.values.byteOffset, GLTF.bufferViews[sparse.values.bufferView]);
|
||||
|
||||
var it = indices.GetEnumerator();
|
||||
for (int i = 0; i < sparse.count; ++i)
|
||||
@@ -253,23 +311,23 @@ namespace UniGLTF
|
||||
return result;
|
||||
}
|
||||
|
||||
public ArraySegment<Byte> GetImageBytes(int imageIndex)
|
||||
public ArraySegment<Byte> GetBytesFromImage(int imageIndex)
|
||||
{
|
||||
var image = GLTF.images[imageIndex];
|
||||
if (string.IsNullOrEmpty(image.uri))
|
||||
{
|
||||
return GetViewBytes(image.bufferView);
|
||||
return GetBytesFromBufferView(image.bufferView);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _storage.Get(image.uri);
|
||||
return GetBytesFromUri(image.uri);
|
||||
}
|
||||
}
|
||||
|
||||
public ArraySegment<Byte> GetImageBytesFromTextureIndex(int textureIndex)
|
||||
{
|
||||
var imageIndex = GLTF.textures[textureIndex].source;
|
||||
return GetImageBytes(imageIndex);
|
||||
return GetBytesFromImage(imageIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace UniGLTF
|
||||
_path,
|
||||
Encoding.UTF8.GetString(jsonBytes.Array, jsonBytes.Offset, jsonBytes.Count),
|
||||
chunks,
|
||||
new SimpleStorage(chunks[1].Bytes),
|
||||
default,
|
||||
new MigrationFlags()
|
||||
);
|
||||
}
|
||||
@@ -92,13 +92,6 @@ namespace UniGLTF
|
||||
FixNodeName(GLTF);
|
||||
FixAnimationNameUnique(GLTF);
|
||||
|
||||
// parepare byte buffer
|
||||
//GLTF.baseDir = System.IO.Path.GetDirectoryName(Path);
|
||||
foreach (var buffer in GLTF.buffers)
|
||||
{
|
||||
buffer.OpenStorage(storage);
|
||||
}
|
||||
|
||||
return new GltfData(path, json, GLTF, chunks, storage, migrationFlags);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
/// <summary>
|
||||
/// For unit tests.
|
||||
/// JSON string with storage parser.
|
||||
/// </summary>
|
||||
public sealed class JsonWithStorageParser
|
||||
{
|
||||
private readonly string _json;
|
||||
private readonly IStorage _storage;
|
||||
|
||||
public JsonWithStorageParser(string json, IStorage storage = null)
|
||||
{
|
||||
_json = json;
|
||||
_storage = storage ?? new SimpleStorage(new ArraySegment<byte>());
|
||||
}
|
||||
|
||||
public GltfData Parse()
|
||||
{
|
||||
return GlbLowLevelParser.ParseGltf(
|
||||
string.Empty,
|
||||
_json,
|
||||
new List<GlbChunk>(),
|
||||
_storage,
|
||||
new MigrationFlags()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c103da8b4a2b4050be09e7bfce2769fd
|
||||
timeCreated: 1624803637
|
||||
@@ -143,10 +143,10 @@ namespace UniGLTF
|
||||
UnityEngine.Object.DestroyImmediate(mat);
|
||||
UnityEngine.Object.DestroyImmediate(root);
|
||||
|
||||
var parsed = GltfData.CreateFromGltfDataForTest(gltf);
|
||||
var parsed = GltfData.CreateFromGltfDataForTest(gltf, data.BinBytes);
|
||||
|
||||
// Extract Image to Texture2D
|
||||
var exportedBytes = parsed.GetViewBytes(exportedImage.bufferView).ToArray();
|
||||
var exportedBytes = parsed.GetBytesFromBufferView(exportedImage.bufferView).ToArray();
|
||||
var exportedTexture = new Texture2D(2, 2, TextureFormat.ARGB32, mipChain: false, linear: false);
|
||||
Assert.IsTrue(exportedTexture.LoadImage(exportedBytes)); // Always true ?
|
||||
Assert.AreEqual(srcTex.width, exportedTexture.width);
|
||||
|
||||
@@ -11,7 +11,6 @@ namespace UniGLTF
|
||||
var data = new ExportingGltfData();
|
||||
var gltf = data.GLTF;
|
||||
gltf.asset.version = "2.0";
|
||||
gltf.buffers.Add(new glTFBuffer(new ArrayByteBuffer(Array.Empty<byte>())));
|
||||
gltf.textures.Add(new glTFTexture
|
||||
{
|
||||
name = "FooBar",
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace UniGLTF
|
||||
: MeshExporter_SharedVertexBuffer.Export(data, unityMesh, Materials, axisInverter, meshExportSettings)
|
||||
;
|
||||
|
||||
var parsed = GltfData.CreateFromGltfDataForTest(data.GLTF);
|
||||
var parsed = GltfData.CreateFromGltfDataForTest(data.GLTF, data.BinBytes);
|
||||
|
||||
{
|
||||
var indices = parsed.GetIndices(gltfMesh.primitives[0].indices);
|
||||
@@ -186,7 +186,7 @@ namespace UniGLTF
|
||||
: MeshExporter_SharedVertexBuffer.Export(data, unityMesh, Materials, axisInverter, meshExportSettings)
|
||||
;
|
||||
|
||||
var parsed = GltfData.CreateFromGltfDataForTest(data.GLTF);
|
||||
var parsed = GltfData.CreateFromGltfDataForTest(data.GLTF, data.BinBytes);
|
||||
{
|
||||
var indices = parsed.GetIndices(gltfMesh.primitives[0].indices);
|
||||
Assert.AreEqual(0, indices[0]);
|
||||
|
||||
@@ -235,7 +235,7 @@ namespace UniGLTF
|
||||
string.Empty,
|
||||
gltf,
|
||||
new List<GlbChunk>(),
|
||||
new SimpleStorage(new ArraySegment<byte>()),
|
||||
default,
|
||||
new MigrationFlags()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace UniGLTF
|
||||
}
|
||||
|
||||
// parse
|
||||
var parsed = new JsonWithStorageParser(json).Parse();
|
||||
var parsed = GltfData.CreateFromExportForTest(data);
|
||||
|
||||
// import
|
||||
using (var context = new ImporterContext(parsed))
|
||||
@@ -129,7 +129,8 @@ namespace UniGLTF
|
||||
{
|
||||
var initBytes = init == 0 ? null : new byte[init];
|
||||
var storage = new ArrayByteBuffer(initBytes);
|
||||
var buffer = new glTFBuffer(storage);
|
||||
var data = new ExportingGltfData();
|
||||
// var buffer = new glTFBuffer(storage);
|
||||
|
||||
var values = new List<byte>();
|
||||
int offset = 0;
|
||||
@@ -139,11 +140,11 @@ namespace UniGLTF
|
||||
values.AddRange(nums);
|
||||
var bytes = new ArraySegment<Byte>(nums);
|
||||
offset += x;
|
||||
buffer.Append(bytes, glBufferTarget.NONE);
|
||||
data.ExtendBufferAndGetView(bytes, glBufferTarget.NONE);
|
||||
}
|
||||
|
||||
Assert.AreEqual(values.Count, buffer.byteLength);
|
||||
Assert.True(Enumerable.SequenceEqual(values, buffer.GetBytes().ToArray()));
|
||||
Assert.AreEqual(values.Count, data.GLTF.buffers[0].byteLength);
|
||||
Assert.True(Enumerable.SequenceEqual(values, data.BinBytes.ToArray()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -553,9 +554,7 @@ namespace UniGLTF
|
||||
|
||||
// import
|
||||
{
|
||||
var storage = new SimpleStorage(new ArraySegment<byte>(new byte[1024 * 1024]));
|
||||
var parsed = new JsonWithStorageParser(json, storage).Parse();
|
||||
|
||||
var parsed = GltfData.CreateFromExportForTest(data);
|
||||
using (var context = new ImporterContext(parsed))
|
||||
using (var loaded = context.Load())
|
||||
{
|
||||
@@ -573,10 +572,7 @@ namespace UniGLTF
|
||||
|
||||
// import new version
|
||||
{
|
||||
var storage = new SimpleStorage(new ArraySegment<byte>(new byte[1024 * 1024]));
|
||||
var parsed = new JsonWithStorageParser(json, storage).Parse();
|
||||
|
||||
//Debug.LogFormat("{0}", context.Json);
|
||||
var parsed = GltfData.CreateFromExportForTest(data);
|
||||
using (var context = new ImporterContext(parsed))
|
||||
using (var loaded = context.Load())
|
||||
{
|
||||
@@ -628,9 +624,7 @@ namespace UniGLTF
|
||||
|
||||
// import
|
||||
{
|
||||
var storage = new SimpleStorage(new ArraySegment<byte>(new byte[1024 * 1024]));
|
||||
var parsed = new JsonWithStorageParser(json, storage).Parse();
|
||||
|
||||
var parsed = GltfData.CreateFromExportForTest(data);
|
||||
using (var context = new ImporterContext(parsed))
|
||||
using (var loaded = context.Load())
|
||||
{
|
||||
@@ -694,9 +688,7 @@ namespace UniGLTF
|
||||
|
||||
// import
|
||||
{
|
||||
var storage = new SimpleStorage(new ArraySegment<byte>(new byte[1024 * 1024]));
|
||||
var parsed = new JsonWithStorageParser(json, storage).Parse();
|
||||
|
||||
var parsed = GltfData.CreateFromExportForTest(data);
|
||||
using (var context = new ImporterContext(parsed))
|
||||
using (var loaded = context.Load())
|
||||
{
|
||||
|
||||
@@ -58,7 +58,8 @@ namespace VRM
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
default
|
||||
);
|
||||
var vrm = new glTF_VRM_extensions
|
||||
{
|
||||
@@ -119,7 +120,8 @@ namespace VRM
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
default
|
||||
);
|
||||
var vrm = new glTF_VRM_extensions
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace UniVRM10
|
||||
count = self.Count;
|
||||
}
|
||||
var slice = self.Bytes.Slice(offset * stride, count * stride);
|
||||
return storage.AppendToBuffer(bufferIndex, slice);
|
||||
return storage.AppendToBuffer(slice);
|
||||
}
|
||||
|
||||
static glTFAccessor CreateGltfAccessor(this VrmLib.BufferAccessor self,
|
||||
@@ -116,8 +116,8 @@ namespace UniVRM10
|
||||
sparseValueSpan[i] = value;
|
||||
}
|
||||
|
||||
var sparseIndexView = storage.AppendToBuffer(bufferIndex, sparseIndexBin);
|
||||
var sparseValueView = storage.AppendToBuffer(bufferIndex, sparseValueBin);
|
||||
var sparseIndexView = storage.AppendToBuffer(sparseIndexBin);
|
||||
var sparseValueView = storage.AppendToBuffer(sparseValueBin);
|
||||
|
||||
var accessorIndex = storage.Gltf.accessors.Count;
|
||||
var accessor = new glTFAccessor
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace UniVRM10
|
||||
|
||||
GetTextureBytesAsync getThumbnailImageBytesAsync = () =>
|
||||
{
|
||||
var bytes = data.GetImageBytes(imageIndex);
|
||||
var bytes = data.GetBytesFromImage(imageIndex);
|
||||
return Task.FromResult(GltfTextureImporter.ToArray(bytes));
|
||||
};
|
||||
var texDesc = new TextureDescriptor(objectName, gltfImage.GetExt(), gltfImage.uri, Vector2.zero, Vector2.one, default, TextureImportTypes.sRGB, default, default,
|
||||
|
||||
@@ -15,8 +15,6 @@ namespace UniVRM10
|
||||
UniGLTF.GltfData m_data;
|
||||
public UniGLTF.glTF Gltf => m_data.GLTF;
|
||||
|
||||
public List<UniGLTF.IBytesBuffer> Buffers;
|
||||
|
||||
public UniGLTF.Extensions.VRMC_vrm.VRMC_vrm gltfVrm;
|
||||
|
||||
public UniGLTF.Extensions.VRMC_springBone.VRMC_springBone gltfVrmSpringBone;
|
||||
@@ -31,13 +29,9 @@ namespace UniVRM10
|
||||
string.Empty,
|
||||
GLTF,
|
||||
new List<GlbChunk>(),
|
||||
new SimpleStorage(new ArraySegment<byte>()),
|
||||
default,
|
||||
new MigrationFlags()
|
||||
);
|
||||
Buffers = new List<UniGLTF.IBytesBuffer>()
|
||||
{
|
||||
new UniGLTF.ArrayByteBuffer()
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -61,20 +55,17 @@ namespace UniVRM10
|
||||
gltfVrmSpringBone = springBone;
|
||||
}
|
||||
|
||||
Buffers = new List<UniGLTF.IBytesBuffer>()
|
||||
{
|
||||
Gltf.buffers[0].Buffer,
|
||||
};
|
||||
_buffer = new ArraySegmentByteBuffer(data.Bin);
|
||||
}
|
||||
|
||||
public void Reserve(int bytesLength)
|
||||
{
|
||||
Buffers[0].ExtendCapacity(bytesLength);
|
||||
_buffer.ExtendCapacity(bytesLength);
|
||||
}
|
||||
|
||||
public int AppendToBuffer(int bufferIndex, ArraySegment<byte> segment)
|
||||
public int AppendToBuffer(ArraySegment<byte> segment)
|
||||
{
|
||||
var gltfBufferView = Buffers[bufferIndex].Extend(segment);
|
||||
var gltfBufferView = _buffer.Extend(segment);
|
||||
var viewIndex = Gltf.bufferViews.Count;
|
||||
Gltf.bufferViews.Add(gltfBufferView);
|
||||
return viewIndex;
|
||||
@@ -138,7 +129,7 @@ namespace UniVRM10
|
||||
var view = Gltf.bufferViews[bufferViewIndex];
|
||||
if (view.buffer.TryGetValidIndex(Gltf.buffers.Count, out int bufferIndex))
|
||||
{
|
||||
var buffer = Buffers[bufferIndex];
|
||||
var buffer = _buffer;
|
||||
var bin = buffer.Bytes;
|
||||
var byteSize = accessor.CalcByteSize();
|
||||
bytes = bin.Slice(view.byteOffset, view.byteLength).Slice(accessor.byteOffset, byteSize);
|
||||
@@ -480,18 +471,22 @@ namespace UniVRM10
|
||||
public ArraySegment<byte> GetBufferBytes(UniGLTF.glTFBuffer buffer)
|
||||
{
|
||||
int index = Gltf.buffers.IndexOf(buffer);
|
||||
return Buffers[index].Bytes;
|
||||
if (index != 0)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
return _buffer.Bytes;
|
||||
}
|
||||
|
||||
public byte[] ToBytes()
|
||||
{
|
||||
Gltf.buffers[0].byteLength = Buffers[0].Bytes.Count;
|
||||
Gltf.buffers[0].byteLength = _buffer.Bytes.Count;
|
||||
|
||||
var f = new JsonFormatter();
|
||||
UniGLTF.GltfSerializer.Serialize(f, Gltf);
|
||||
var json = f.GetStoreBytes();
|
||||
|
||||
var glb = UniGLTF.Glb.Create(json, Buffers[0].Bytes);
|
||||
var glb = UniGLTF.Glb.Create(json, _buffer.Bytes);
|
||||
return glb.ToBytes();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace UniVRM10
|
||||
// copy images
|
||||
foreach (var image in gltf.images)
|
||||
{
|
||||
var bytes = _data.GetViewBytes(image.bufferView);
|
||||
var bytes = _data.GetBytesFromBufferView(image.bufferView);
|
||||
image.bufferView = AddBuffer(bytes);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace UniVRM10
|
||||
|
||||
if (bufferViewIndex != -1)
|
||||
{
|
||||
var buffer = data.GetViewBytes(bufferViewIndex);
|
||||
var buffer = data.GetBytesFromBufferView(bufferViewIndex);
|
||||
var span = SpanLike.Wrap<UnityEngine.Vector3>(buffer);
|
||||
for (int i = 0; i < span.Length; ++i)
|
||||
{
|
||||
@@ -113,7 +113,7 @@ namespace UniVRM10
|
||||
if (used.Add(skin.inverseBindMatrices))
|
||||
{
|
||||
var accessor = data.GLTF.accessors[skin.inverseBindMatrices];
|
||||
var buffer = data.GetViewBytes(accessor.bufferView);
|
||||
var buffer = data.GetBytesFromBufferView(accessor.bufferView);
|
||||
var span = SpanLike.Wrap<UnityEngine.Matrix4x4>(buffer);
|
||||
for (int i = 0; i < span.Length; ++i)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user