Merge pull request #1483 from ousttrue/fix/use_native_array

Fix/use native array
This commit is contained in:
ousttrue 2022-01-26 15:07:59 +09:00 committed by GitHub
commit 00a046a06c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 460 additions and 330 deletions

View File

@ -2,7 +2,7 @@
using System.Linq;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Unity.Collections;
namespace UniGLTF
{
@ -102,7 +102,7 @@ namespace UniGLTF
public static class ListExtensions
{
public static void Assign<T>(this List<T> dst, T[] src, Func<T, T> pred)
public static void Assign<T>(this List<T> dst, NativeArray<T> src, Func<T, T> pred) where T : struct
{
dst.Capacity = src.Length;
dst.AddRange(src.Select(pred));

View File

@ -208,8 +208,8 @@ namespace UniGLTF
clip,
relativePath,
new string[] { "localPosition.x", "localPosition.y", "localPosition.z" },
input,
output,
input.ToArray(),
output.ToArray(),
sampler.interpolation,
typeof(Transform),
(values, last) =>
@ -231,8 +231,8 @@ namespace UniGLTF
clip,
relativePath,
new string[] { "localRotation.x", "localRotation.y", "localRotation.z", "localRotation.w" },
input,
output,
input.ToArray(),
output.ToArray(),
sampler.interpolation,
typeof(Transform),
(values, last) =>
@ -257,8 +257,8 @@ namespace UniGLTF
clip,
relativePath,
new string[] { "localScale.x", "localScale.y", "localScale.z" },
input,
output,
input.ToArray(),
output.ToArray(),
sampler.interpolation,
typeof(Transform),
(values, last) => values);
@ -289,8 +289,8 @@ namespace UniGLTF
clip,
relativePath,
keyNames,
input,
output,
input.ToArray(),
output.ToArray(),
sampler.interpolation,
typeof(SkinnedMeshRenderer),
(values, last) =>

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using Unity.Collections;
namespace UniGLTF
{
@ -9,7 +10,7 @@ namespace UniGLTF
/// * JSON is parsed but not validated as glTF
/// * For glb, bin chunks are already available
/// </summary>
public sealed class GltfData
public sealed class GltfData : IDisposable
{
/// <summary>
/// Source file path.
@ -43,21 +44,7 @@ namespace UniGLTF
/// > This chunk MUST be the second chunk of the Binary glTF asset
/// </summary>
/// <returns></returns>
public ArraySegment<byte> Bin
{
get
{
if (Chunks == null)
{
return default;
}
if (Chunks.Count < 2)
{
return default;
}
return Chunks[1].Bytes;
}
}
public NativeArray<byte> Bin { get; }
/// <summary>
/// Migration Flags used by ImporterContext
@ -74,7 +61,9 @@ namespace UniGLTF
/// uri = 相対パス。File.ReadAllBytes
/// </summary>
/// <returns></returns>
Dictionary<string, ArraySegment<byte>> _UriCache = new Dictionary<string, ArraySegment<byte>>();
Dictionary<string, NativeArray<byte>> _UriCache = new Dictionary<string, NativeArray<byte>>();
List<IDisposable> m_disposables = new List<IDisposable>();
public GltfData(string targetPath, string json, glTF gltf, IReadOnlyList<GlbChunk> chunks, IStorage storage, MigrationFlags migrationFlags)
{
@ -84,6 +73,25 @@ namespace UniGLTF
Chunks = chunks;
_storage = storage;
MigrationFlags = migrationFlags;
// init
if (Chunks != null)
{
if (Chunks.Count >= 2)
{
Bin = CreateNativeArray(Chunks[1].Bytes);
}
}
}
public void Dispose()
{
foreach (var disposable in m_disposables)
{
disposable.Dispose();
}
m_disposables.Clear();
_UriCache.Clear();
}
public static GltfData CreateFromExportForTest(ExportingGltfData data)
@ -107,14 +115,14 @@ namespace UniGLTF
);
}
ArraySegment<Byte> GetBytesFromUri(string uri)
NativeArray<Byte> GetBytesFromUri(string uri)
{
if (string.IsNullOrEmpty(uri))
{
throw new ArgumentNullException();
}
if (_UriCache.TryGetValue(uri, out ArraySegment<byte> data))
if (_UriCache.TryGetValue(uri, out NativeArray<byte> data))
{
// return cache
return data;
@ -122,20 +130,20 @@ namespace UniGLTF
if (uri.StartsWith("data:", StringComparison.Ordinal))
{
data = new ArraySegment<byte>(UriByteBuffer.ReadEmbedded(uri));
data = CreateNativeArray(UriByteBuffer.ReadEmbedded(uri));
}
else
{
data = _storage.Get(uri);
data = CreateNativeArray(_storage.Get(uri));
}
_UriCache.Add(uri, data);
return data;
}
public ArraySegment<Byte> GetBytesFromBuffer(int bufferIndex)
public NativeArray<Byte> GetBytesFromBuffer(int bufferIndex)
{
var buffer = GLTF.buffers[bufferIndex];
if (bufferIndex == 0 && Bin.Array != null)
if (bufferIndex == 0 && Bin.IsCreated)
{
// https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#glb-stored-buffer
return Bin;
@ -146,23 +154,20 @@ namespace UniGLTF
}
}
public ArraySegment<Byte> GetBytesFromBufferView(int bufferView)
public NativeArray<Byte> GetBytesFromBufferView(int bufferView)
{
var view = GLTF.bufferViews[bufferView];
var segment = GetBytesFromBuffer(view.buffer);
return new ArraySegment<byte>(segment.Array, segment.Offset + view.byteOffset, view.byteLength);
return segment.GetSubArray(view.byteOffset, view.byteLength);
}
T[] GetTypedFromBufferView<T>(int count, int byteOffset, glTFBufferView view) where T : struct
NativeArray<T> GetTypedFromBufferView<T>(int count, int byteOffset, glTFBufferView view) where T : struct
{
var segment = GetBytesFromBuffer(view.buffer);
var attrib = new T[count];
var bytes = new ArraySegment<Byte>(segment.Array, segment.Offset + view.byteOffset + byteOffset, count * Marshal.SizeOf<T>());
SafeMarshalCopy.CopyBytesToArray(bytes, attrib);
return attrib;
return segment.GetSubArray(view.byteOffset + byteOffset, count * Marshal.SizeOf<T>()).Reinterpret<T>(1);
}
T[] GetTypedFromAccessor<T>(glTFAccessor accessor, glTFBufferView view) where T : struct
NativeArray<T> GetTypedFromAccessor<T>(glTFAccessor accessor, glTFBufferView view) where T : struct
{
return GetTypedFromBufferView<T>(accessor.count, accessor.byteOffset, view);
}
@ -247,15 +252,15 @@ namespace UniGLTF
return indices;
}
public T[] GetArrayFromAccessor<T>(int accessorIndex) where T : struct
public NativeArray<T> GetArrayFromAccessor<T>(int accessorIndex) where T : struct
{
var vertexAccessor = GLTF.accessors[accessorIndex];
if (vertexAccessor.count <= 0) return new T[] { };
if (vertexAccessor.count <= 0) return CreateNativeArray<T>(0);
var result = (vertexAccessor.bufferView != -1)
? GetTypedFromAccessor<T>(vertexAccessor, GLTF.bufferViews[vertexAccessor.bufferView])
: new T[vertexAccessor.count]
: CreateNativeArray<T>(vertexAccessor.count)
;
var sparse = vertexAccessor.sparse;
@ -275,27 +280,24 @@ namespace UniGLTF
return result;
}
public float[] FlatternFloatArrayFromAccessor(int accessorIndex)
public NativeArray<float> FlatternFloatArrayFromAccessor(int accessorIndex)
{
var vertexAccessor = GLTF.accessors[accessorIndex];
if (vertexAccessor.count <= 0) return new float[] { };
if (vertexAccessor.count <= 0) return CreateNativeArray<float>(0);
var bufferCount = vertexAccessor.count * vertexAccessor.TypeCount;
float[] result = null;
NativeArray<float> result = default;
if (vertexAccessor.bufferView != -1)
{
var attrib = new float[vertexAccessor.count * vertexAccessor.TypeCount];
var view = GLTF.bufferViews[vertexAccessor.bufferView];
var segment = GetBytesFromBuffer(view.buffer);
var bytes = new ArraySegment<Byte>(segment.Array, segment.Offset + view.byteOffset + vertexAccessor.byteOffset, vertexAccessor.count * 4 * vertexAccessor.TypeCount);
SafeMarshalCopy.CopyBytesToArray(bytes, attrib);
result = attrib;
result = segment.GetSubArray(view.byteOffset + vertexAccessor.byteOffset, vertexAccessor.count * 4 * vertexAccessor.TypeCount).Reinterpret<float>(1);
}
else
{
result = new float[bufferCount];
result = CreateNativeArray<float>(bufferCount);
}
var sparse = vertexAccessor.sparse;
@ -315,7 +317,7 @@ namespace UniGLTF
return result;
}
public (ArraySegment<byte> binary, string mimeType)? GetBytesFromImage(int imageIndex)
public (NativeArray<byte> binary, string mimeType)? GetBytesFromImage(int imageIndex)
{
if (imageIndex < 0 || imageIndex >= GLTF.images.Count) return default;
@ -373,5 +375,34 @@ namespace UniGLTF
return false;
}
/// <summary>
/// NativeArrayを新規作成し、Dispose管理する。
/// 個別にDisposeする必要が無い。
/// </summary>
/// <param name="size"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public NativeArray<T> CreateNativeArray<T>(int size) where T : struct
{
var array = new NativeArray<T>(size, Allocator.Persistent);
m_disposables.Add(array);
return array;
}
NativeArray<T> CreateNativeArray<T>(ArraySegment<T> data) where T : struct
{
var array = CreateNativeArray<T>(data.Count);
// TODO: remove ToArray
array.CopyFrom(data.ToArray());
return array;
}
NativeArray<T> CreateNativeArray<T>(T[] data) where T : struct
{
var array = CreateNativeArray<T>(data.Length);
array.CopyFrom(data);
return array;
}
}
}

View File

@ -0,0 +1,25 @@
using System.IO;
using System.Threading.Tasks;
using UnityEngine;
using VRMShaders;
namespace UniGLTF
{
public static class GltfUtility
{
public static async Task<RuntimeGltfInstance> LoadAsync(string path, IAwaitCaller awaitCaller = null, IMaterialDescriptorGenerator materialGenerator = null)
{
if (!File.Exists(path))
{
throw new FileNotFoundException(path);
}
Debug.LogFormat("{0}", path);
using (GltfData data = new AutoGltfFileParser(path).Parse())
using (var loader = new UniGLTF.ImporterContext(data, materialGenerator: materialGenerator))
{
return await loader.LoadAsync(awaitCaller);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 317decd1053397d4b9bdb9fb183bba4a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -142,7 +142,7 @@ namespace UniGLTF
for (var i = 0; i < positions.Length; ++i)
{
var position = inverter.InvertVector3(positions[i]);
var normal = normals != null ? inverter.InvertVector3(normals[i]) : Vector3.zero;
var normal = normals != null ? inverter.InvertVector3(normals.Value[i]) : Vector3.zero;
var texCoord0 = Vector2.zero;
if (texCoords0 != null)
@ -151,20 +151,20 @@ namespace UniGLTF
{
#pragma warning disable 0612
// backward compatibility
texCoord0 = texCoords0[i].ReverseY();
texCoord0 = texCoords0.Value[i].ReverseY();
#pragma warning restore 0612
}
else
{
texCoord0 = texCoords0[i].ReverseUV();
texCoord0 = texCoords0.Value[i].ReverseUV();
}
}
var texCoord1 = texCoords1 != null ? texCoords1[i].ReverseUV() : Vector2.zero;
var texCoord1 = texCoords1 != null ? texCoords1.Value[i].ReverseUV() : Vector2.zero;
var joints = jointsGetter?.Invoke(i) ?? (0, 0, 0, 0);
var weights = weightsGetter != null ? NormalizeBoneWeight(weightsGetter(i)) : (0, 0, 0, 0);
var color = colors != null ? colors[i] : Color.white;
var color = colors != null ? colors.Value[i] : Color.white;
_vertices.Add(
new MeshVertex(
position,
@ -285,24 +285,24 @@ namespace UniGLTF
for (var i = 0; i < positions.Length; ++i)
{
var position = inverter.InvertVector3(positions[i]);
var normal = normals != null ? inverter.InvertVector3(normals[i]) : Vector3.zero;
var normal = normals != null ? inverter.InvertVector3(normals.Value[i]) : Vector3.zero;
var texCoord0 = Vector2.zero;
if (texCoords0 != null)
{
if (data.GLTF.IsGeneratedUniGLTFAndOlder(1, 16))
{
#pragma warning disable 0612
texCoord0 = texCoords0[i].ReverseY();
texCoord0 = texCoords0.Value[i].ReverseY();
#pragma warning restore 0612
}
else
{
texCoord0 = texCoords0[i].ReverseUV();
texCoord0 = texCoords0.Value[i].ReverseUV();
}
}
var texCoord1 = texCoords1 != null ? texCoords1[i].ReverseUV() : Vector2.zero;
var color = colors != null ? colors[i] : Color.white;
var texCoord1 = texCoords1 != null ? texCoords1.Value[i].ReverseUV() : Vector2.zero;
var color = colors != null ? colors.Value[i] : Color.white;
var joints = jointsGetter?.Invoke(i) ?? (0, 0, 0, 0);
var weights = weightsGetter != null ? NormalizeBoneWeight(weightsGetter(i)) : (0, 0, 0, 0);

View File

@ -1,4 +1,5 @@
using System;
using Unity.Collections;
using UnityEngine;
namespace UniGLTF
@ -11,12 +12,12 @@ namespace UniGLTF
public static bool HasSkin(this glTFPrimitives primitives) => primitives.attributes.JOINTS_0 != -1 && primitives.attributes.WEIGHTS_0 != -1;
public static bool HasColor(this glTFPrimitives primitives) => primitives.attributes.COLOR_0 != -1;
public static Vector3[] GetPositions(this glTFPrimitives primitives, GltfData data)
public static NativeArray<Vector3> GetPositions(this glTFPrimitives primitives, GltfData data)
{
return data.GetArrayFromAccessor<Vector3>(primitives.attributes.POSITION);
}
public static Vector3[] GetNormals(this glTFPrimitives primitives, GltfData data, int positionsLength)
public static NativeArray<Vector3>? GetNormals(this glTFPrimitives primitives, GltfData data, int positionsLength)
{
if (!HasNormal(primitives)) return null;
var result = data.GetArrayFromAccessor<Vector3>(primitives.attributes.NORMAL);
@ -28,7 +29,7 @@ namespace UniGLTF
return result;
}
public static Vector2[] GetTexCoords0(this glTFPrimitives primitives, GltfData data, int positionsLength)
public static NativeArray<Vector2>? GetTexCoords0(this glTFPrimitives primitives, GltfData data, int positionsLength)
{
if (!HasTexCoord0(primitives)) return null;
var result = data.GetArrayFromAccessor<Vector2>(primitives.attributes.TEXCOORD_0);
@ -39,8 +40,8 @@ namespace UniGLTF
return result;
}
public static Vector2[] GetTexCoords1(this glTFPrimitives primitives, GltfData data, int positionsLength)
public static NativeArray<Vector2>? GetTexCoords1(this glTFPrimitives primitives, GltfData data, int positionsLength)
{
if (!HasTexCoord1(primitives)) return null;
var result = data.GetArrayFromAccessor<Vector2>(primitives.attributes.TEXCOORD_1);
@ -48,33 +49,33 @@ namespace UniGLTF
{
throw new Exception("different length");
}
return result;
}
public static Color[] GetColors(this glTFPrimitives primitives, GltfData data, int positionsLength)
public static NativeArray<Color>? GetColors(this glTFPrimitives primitives, GltfData data, int positionsLength)
{
if (!HasColor(primitives)) return null;
switch (data.GLTF.accessors[primitives.attributes.COLOR_0].TypeCount)
{
case 3:
{
var vec3Color = data.GetArrayFromAccessor<Vector3>(primitives.attributes.COLOR_0);
if (vec3Color.Length != positionsLength)
{
throw new Exception("different length");
}
var colors = new Color[vec3Color.Length];
var vec3Color = data.GetArrayFromAccessor<Vector3>(primitives.attributes.COLOR_0);
if (vec3Color.Length != positionsLength)
{
throw new Exception("different length");
}
var colors = data.CreateNativeArray<Color>(vec3Color.Length);
for (var index = 0; index < vec3Color.Length; index++)
{
var color = vec3Color[index];
colors[index] = new Color(color.x, color.y, color.z);
}
for (var index = 0; index < vec3Color.Length; index++)
{
var color = vec3Color[index];
colors[index] = new Color(color.x, color.y, color.z);
}
return colors;
}
return colors;
}
case 4:
var result = data.GetArrayFromAccessor<Color>(primitives.attributes.COLOR_0);
if (result.Length != positionsLength)
@ -89,7 +90,7 @@ namespace UniGLTF
}
}
public static JointsAccessor.Getter GetJoints(this glTFPrimitives primitives, GltfData data, int positionsLength)
public static JointsAccessor.Getter GetJoints(this glTFPrimitives primitives, GltfData data, int positionsLength)
{
// skin
if (!HasSkin(primitives)) return null;

View File

@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
using Unity.Collections;
using UnityEngine;
using VRMShaders;
@ -201,22 +202,23 @@ namespace UniGLTF
return data.GLTF.textures[textureIndex].source;
}
private static byte[] ToArray(ArraySegment<byte> bytes)
private static byte[] ToArray(NativeArray<byte> bytes)
{
if (bytes.Array == null)
{
return new byte[] { };
}
else if (bytes.Offset == 0 && bytes.Count == bytes.Array.Length)
{
return bytes.Array;
}
else
{
var result = new byte[bytes.Count];
Buffer.BlockCopy(bytes.Array, bytes.Offset, result, 0, result.Length);
return result;
}
// if (bytes.Array == null)
// {
// return new byte[] { };
// }
// else if (bytes.Offset == 0 && bytes.Count == bytes.Array.Length)
// {
// return bytes.Array;
// }
// else
// {
// var result = new byte[bytes.Count];
// Buffer.BlockCopy(bytes.Array, bytes.Offset, result, 0, result.Length);
// return result;
// }
return bytes.ToArray();
}
}
}

View File

@ -143,16 +143,17 @@ namespace UniGLTF
UnityEngine.Object.DestroyImmediate(mat);
UnityEngine.Object.DestroyImmediate(root);
var parsed = GltfData.CreateFromGltfDataForTest(gltf, data.BinBytes);
using (var parsed = GltfData.CreateFromGltfDataForTest(gltf, data.BinBytes))
{
// Extract Image to Texture2D
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);
Assert.AreEqual(srcTex.height, exportedTexture.height);
// Extract Image to Texture2D
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);
Assert.AreEqual(srcTex.height, exportedTexture.height);
return exportedTexture;
return exportedTexture;
}
}
private static Color32 GetFirstPixelInTexture2D(Texture2D tex)

View File

@ -33,11 +33,13 @@ namespace UniGLTF
});
var parser = new GlbLowLevelParser("Test", data.ToGlbBytes());
var parsed = parser.Parse();
using (var parsed = parser.Parse())
{
Assert.AreEqual("FooBar", parsed.GLTF.textures[0].name);
// NOTE: 大文字小文字が違うだけの名前は、同一としてみなされ、Suffix が付く。
Assert.AreEqual("foobar__UNIGLTF__DUPLICATED__2", parsed.GLTF.textures[1].name);
Assert.AreEqual("FooBar", parsed.GLTF.textures[0].name);
// NOTE: 大文字小文字が違うだけの名前は、同一としてみなされ、Suffix が付く。
Assert.AreEqual("foobar__UNIGLTF__DUPLICATED__2", parsed.GLTF.textures[1].name);
}
}
/// <summary>
@ -61,16 +63,18 @@ namespace UniGLTF
Assert.True(File.Exists(path));
var bytes = File.ReadAllBytes(path);
var data = new GlbBinaryParser(bytes, Path.GetFileNameWithoutExtension(path)).Parse();
// glb header + 1st chunk only
var mod = bytes.Take(12 + 8 + data.Chunks[0].Bytes.Count).ToArray();
Assert.Throws<GlbParseException>(() =>
using (var data = new GlbBinaryParser(bytes, Path.GetFileNameWithoutExtension(path)).Parse())
{
// glb header + 1st chunk only
var mod = bytes.Take(12 + 8 + data.Chunks[0].Bytes.Count).ToArray();
Assert.Throws<GlbParseException>(() =>
{
// 再パース
var data2 = new GlbBinaryParser(mod, Path.GetFileNameWithoutExtension(path)).Parse();
});
});
}
}
}
}

View File

@ -89,6 +89,7 @@ namespace UniGLTF
Debug.LogException(ex);
}
using (data)
using (var loader = new ImporterContext(data))
{
try
@ -136,12 +137,15 @@ namespace UniGLTF
}
// should unique
var gltfTextures = new GltfTextureDescriptorGenerator(data).Get().GetEnumerable()
.Select(x => x.SubAssetKey)
.ToArray();
var distinct = gltfTextures.Distinct().ToArray();
Assert.True(gltfTextures.Length == distinct.Length);
Assert.True(gltfTextures.SequenceEqual(distinct));
using (data)
{
var gltfTextures = new GltfTextureDescriptorGenerator(data).Get().GetEnumerable()
.Select(x => x.SubAssetKey)
.ToArray();
var distinct = gltfTextures.Distinct().ToArray();
Assert.True(gltfTextures.Length == distinct.Length);
Assert.True(gltfTextures.SequenceEqual(distinct));
}
}
static bool Exclude(FileInfo f)
@ -220,13 +224,14 @@ namespace UniGLTF
{
var path = Path.Combine(root.FullName, "DamagedHelmet/glTF-Binary/DamagedHelmet.glb");
var data = new AutoGltfFileParser(path).Parse();
var matDesc = new GltfMaterialDescriptorGenerator().Get(data, 0);
Assert.AreEqual("Standard", matDesc.ShaderName);
Assert.AreEqual(5, matDesc.TextureSlots.Count);
var (key, value) = matDesc.EnumerateSubAssetKeyValue().First();
Assert.AreEqual(new SubAssetKey(typeof(Texture2D), "texture_0"), key);
using (var data = new AutoGltfFileParser(path).Parse())
{
var matDesc = new GltfMaterialDescriptorGenerator().Get(data, 0);
Assert.AreEqual("Standard", matDesc.ShaderName);
Assert.AreEqual(5, matDesc.TextureSlots.Count);
var (key, value) = matDesc.EnumerateSubAssetKeyValue().First();
Assert.AreEqual(new SubAssetKey(typeof(Texture2D), "texture_0"), key);
}
}
}
}

View File

@ -137,30 +137,32 @@ namespace UniGLTF
: MeshExporter_SharedVertexBuffer.Export(data, unityMesh, Materials, axisInverter, meshExportSettings)
;
var parsed = GltfData.CreateFromGltfDataForTest(data.GLTF, data.BinBytes);
using (var parsed = GltfData.CreateFromGltfDataForTest(data.GLTF, data.BinBytes))
{
var indices = parsed.GetIndices(gltfMesh.primitives[0].indices);
Assert.AreEqual(0, indices[0]);
Assert.AreEqual(1, indices[1]);
Assert.AreEqual(5, indices[2]);
Assert.AreEqual(5, indices[3]);
Assert.AreEqual(1, indices[4]);
Assert.AreEqual(4, indices[5]);
}
{
var indices = parsed.GetIndices(gltfMesh.primitives[1].indices);
Assert.AreEqual(1, indices[0]);
Assert.AreEqual(2, indices[1]);
Assert.AreEqual(4, indices[2]);
Assert.AreEqual(4, indices[3]);
Assert.AreEqual(2, indices[4]);
Assert.AreEqual(3, indices[5]);
}
{
var indices = parsed.GetIndices(gltfMesh.primitives[0].indices);
Assert.AreEqual(0, indices[0]);
Assert.AreEqual(1, indices[1]);
Assert.AreEqual(5, indices[2]);
Assert.AreEqual(5, indices[3]);
Assert.AreEqual(1, indices[4]);
Assert.AreEqual(4, indices[5]);
}
var positions = parsed.GetArrayFromAccessor<Vector3>(gltfMesh.primitives[0].attributes.POSITION);
Assert.AreEqual(6, positions.Length);
{
var indices = parsed.GetIndices(gltfMesh.primitives[1].indices);
Assert.AreEqual(1, indices[0]);
Assert.AreEqual(2, indices[1]);
Assert.AreEqual(4, indices[2]);
Assert.AreEqual(4, indices[3]);
Assert.AreEqual(2, indices[4]);
Assert.AreEqual(3, indices[5]);
}
var positions = parsed.GetArrayFromAccessor<Vector3>(gltfMesh.primitives[0].attributes.POSITION);
Assert.AreEqual(6, positions.Length);
}
}
[Test]

View File

@ -0,0 +1,26 @@
using System;
using NUnit.Framework;
using Unity.Collections;
namespace UniGLTF
{
public class NativeArrayTests
{
[Test]
public void DisposeTest()
{
var array = new NativeArray<byte>(64, Allocator.Persistent);
var sub = array.GetSubArray(10, 4);
Assert.Throws<InvalidOperationException>(() => { sub.Dispose(); });
var cast = array.Reinterpret<int>(1);
// Dispose可能
cast.Dispose();
// Disposed
Assert.Throws<InvalidOperationException>(() => { var c = cast[0]; });
Assert.Throws<InvalidOperationException>(() => { var a = array[0]; });
Assert.Throws<InvalidOperationException>(() => { var s = sub[0]; });
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d3712bde0d2a4b348ab5bb661fe1a51a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -88,10 +88,7 @@ namespace UniGLTF
return;
}
// parse
var data = new GlbFileParser(path.FullName).Parse();
// load
using (var data = new GlbFileParser(path.FullName).Parse())
using (var context = new ImporterContext(data))
{
var instance = context.Load();

View File

@ -115,9 +115,7 @@ namespace UniGLTF
}
// parse
var parsed = GltfData.CreateFromExportForTest(data);
// import
using (var parsed = GltfData.CreateFromExportForTest(data))
using (var context = new ImporterContext(parsed))
using (var loaded = context.Load())
{

View File

@ -0,0 +1,57 @@
using System;
using System.IO;
using System.Threading.Tasks;
using UniGLTF;
using UnityEngine;
using VRMShaders;
namespace VRM
{
public static class VrmUtility
{
public delegate IMaterialDescriptorGenerator MaterialGeneratorCallback(VRM.glTF_VRM_extensions vrm);
public delegate void MetaCallback(VRMMetaObject meta);
public static async Task<RuntimeGltfInstance> LoadAsync(string path,
IAwaitCaller awaitCaller = null,
MaterialGeneratorCallback materialGeneratorCallback = null,
MetaCallback metaCallback = null
)
{
if (!File.Exists(path))
{
throw new FileNotFoundException(path);
}
using (GltfData data = new AutoGltfFileParser(path).Parse())
{
try
{
var vrm = new VRMData(data);
IMaterialDescriptorGenerator materialGen = default;
if (materialGeneratorCallback != null)
{
materialGen = materialGeneratorCallback(vrm.VrmExtension);
}
using (var loader = new VRMImporterContext(vrm, materialGenerator: materialGen))
{
if (metaCallback != null)
{
var meta = await loader.ReadMetaAsync(new ImmediateCaller(), true);
metaCallback(meta);
}
return await loader.LoadAsync(awaitCaller);
}
}
catch (NotVrm0Exception)
{
// retry
Debug.LogWarning("file extension is vrm. but not vrm ?");
using (var loader = new UniGLTF.ImporterContext(data))
{
return await loader.LoadAsync(awaitCaller);
}
}
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 431e57aed523ae240a0c88b0657677f8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -72,6 +72,7 @@ namespace VRM
try
{
using (data)
using (var importer = new VRMImporterContext(new VRMData(data)))
{
return importer.Load().gameObject;

View File

@ -22,6 +22,7 @@ namespace VRM
{
var data = new GlbFileParser(AliciaPath).Parse();
byte[] bytes = default;
using (data)
using (var loader = new VRMImporterContext(new VRMData(data)))
using (var loaded = loader.Load())
{
@ -37,7 +38,7 @@ namespace VRM
});
}
var data2 = new GlbLowLevelParser(AliciaPath, bytes).Parse();
using (var data2 = new GlbLowLevelParser(AliciaPath, bytes).Parse())
using (var loader2 = new VRMImporterContext(new VRMData(data2)))
{
Assert.AreEqual(LookAtType.BlendShape, loader2.VRM.firstPerson.lookAtType);
@ -50,6 +51,7 @@ namespace VRM
var data = new GlbFileParser(AliciaPath).Parse();
byte[] bytes = default;
CurveMapper horizontalInner = default;
using (data)
using (var loader = new VRMImporterContext(new VRMData(data)))
using (var loaded = loader.Load())
{
@ -65,7 +67,7 @@ namespace VRM
});
}
var data2 = new GlbLowLevelParser(AliciaPath, bytes).Parse();
using (var data2 = new GlbLowLevelParser(AliciaPath, bytes).Parse())
using (var loader = new VRMImporterContext(new VRMData(data2)))
using (var loaded = loader.Load())
{
@ -83,6 +85,7 @@ namespace VRM
var data = new GlbFileParser(AliciaPath).Parse();
byte[] bytes = default;
CurveMapper horizontalInner = default;
using (data)
using (var loader = new VRMImporterContext(new VRMData(data)))
using (var loaded = loader.Load())
{
@ -98,7 +101,7 @@ namespace VRM
});
}
var data2 = new GlbLowLevelParser(AliciaPath, bytes).Parse();
using (var data2 = new GlbLowLevelParser(AliciaPath, bytes).Parse())
using (var loader = new VRMImporterContext(new VRMData(data2)))
using (var loaded = loader.Load())
{

View File

@ -21,13 +21,15 @@ namespace VRM
static GameObject Load(byte[] bytes, string path)
{
var gltf = new GlbLowLevelParser(path, bytes).Parse();
var data = new VRMData(gltf);
using (var loader = new VRMImporterContext(data))
using (var gltf = new GlbLowLevelParser(path, bytes).Parse())
{
var loaded = loader.Load();
loaded.ShowMeshes();
return loaded.gameObject;
var data = new VRMData(gltf);
using (var loader = new VRMImporterContext(data))
{
var loaded = loader.Load();
loaded.ShowMeshes();
return loaded.gameObject;
}
}
}

View File

@ -14,7 +14,7 @@ namespace UniVRM10
Other,
}
public class Vrm10Data
public class Vrm10Data : IDisposable
{
public GltfData Data { get; }
public UniGLTF.Extensions.VRMC_vrm.VRMC_vrm VrmExtension { get; }
@ -52,6 +52,11 @@ namespace UniVRM10
MigratedBytes = migratedBytes;
}
public void Dispose()
{
Data.Dispose();
}
public static bool TryParseOrMigrate(string path, bool doMigrate, out Vrm10Data result)
{
return TryParseOrMigrate(path, File.ReadAllBytes(path), doMigrate, out result);

View File

@ -55,7 +55,7 @@ namespace UniVRM10
gltfVrmSpringBone = springBone;
}
_buffer = new ArraySegmentByteBuffer(data.Bin);
_buffer = new ArraySegmentByteBuffer(new ArraySegment<byte>(data.Bin.ToArray()));
}
public void Reserve(int bytesLength)

View File

@ -20,7 +20,7 @@ namespace UniVRM10
public MeshUpdater(GltfData data)
{
_data = data;
_buffer = new ArrayByteBuffer(new byte[data.Bin.Count]);
_buffer = new ArrayByteBuffer(new byte[data.Bin.Length]);
}
int AddBuffer(ArraySegment<byte> bytes)
@ -70,7 +70,7 @@ namespace UniVRM10
foreach (var image in gltf.images)
{
var bytes = _data.GetBytesFromBufferView(image.bufferView);
image.bufferView = AddBuffer(bytes);
image.bufferView = AddBuffer(new ArraySegment<byte>(bytes.ToArray()));
}
// update Mesh

View File

@ -73,7 +73,7 @@ namespace UniVRM10
if (bufferViewIndex != -1)
{
var buffer = data.GetBytesFromBufferView(bufferViewIndex);
var span = SpanLike.Wrap<UnityEngine.Vector3>(buffer);
var span = buffer.Reinterpret<UnityEngine.Vector3>(1);
for (int i = 0; i < span.Length; ++i)
{
span[i] = span[i].RotateY180();
@ -114,7 +114,7 @@ namespace UniVRM10
{
var accessor = data.GLTF.accessors[skin.inverseBindMatrices];
var buffer = data.GetBytesFromBufferView(accessor.bufferView);
var span = SpanLike.Wrap<UnityEngine.Matrix4x4>(buffer);
var span = buffer.Reinterpret<UnityEngine.Matrix4x4>(1);
for (int i = 0; i < span.Length; ++i)
{
span[i] = span[i].RotateY180();

View File

@ -40,14 +40,16 @@ namespace UniVRM10.Test
Debug.Log($"load: {path}");
Assert.IsTrue(Vrm10Data.TryParseOrMigrate(path, true, out Vrm10Data result));
using (result)
{
var go = BuildGameObject(result, true);
Debug.Log(go);
var go = BuildGameObject(result, true);
Debug.Log(go);
// export
var vrmBytes = Vrm10Exporter.Export(go, new EditorTextureSerializer());
// export
var vrmBytes = Vrm10Exporter.Export(go, new EditorTextureSerializer());
Debug.Log($"export {vrmBytes.Length} bytes");
Debug.Log($"export {vrmBytes.Length} bytes");
}
}
}
}

View File

@ -22,22 +22,24 @@ namespace UniVRM10
public void MaterialImporterTest()
{
var migratedBytes = MigrationVrm.Migrate(File.ReadAllBytes(AliciaPath));
var data = new GlbLowLevelParser(AliciaPath, migratedBytes).Parse();
using (var data = new GlbLowLevelParser(AliciaPath, migratedBytes).Parse())
{
var matDesc = new Vrm10MaterialDescriptorGenerator().Get(data, 0);
Assert.AreEqual("Alicia_body", matDesc.Name);
Assert.AreEqual("VRM10/MToon10", matDesc.ShaderName);
Assert.AreEqual("Alicia_body", matDesc.TextureSlots["_MainTex"].UnityObjectName);
Assert.AreEqual("Alicia_body", matDesc.TextureSlots["_ShadeTex"].UnityObjectName);
var matDesc = new Vrm10MaterialDescriptorGenerator().Get(data, 0);
Assert.AreEqual("Alicia_body", matDesc.Name);
Assert.AreEqual("VRM10/MToon10", matDesc.ShaderName);
Assert.AreEqual("Alicia_body", matDesc.TextureSlots["_MainTex"].UnityObjectName);
Assert.AreEqual("Alicia_body", matDesc.TextureSlots["_ShadeTex"].UnityObjectName);
AreColorEqualApproximately(new Color(1, 1, 1, 1), matDesc.Colors["_Color"]);
ColorUtility.TryParseHtmlString("#FFDDD6", out var shadeColor);
AreColorEqualApproximately(shadeColor, matDesc.Colors["_ShadeColor"]);
AreColorEqualApproximately(new Color(1, 1, 1, 1), matDesc.Colors["_Color"]);
ColorUtility.TryParseHtmlString("#FFDDD6", out var shadeColor);
AreColorEqualApproximately(shadeColor, matDesc.Colors["_ShadeColor"]);
Assert.AreEqual(1.0f - 0.1f, matDesc.FloatValues["_GiEqualization"]);
Assert.AreEqual(1.0f - 0.1f, matDesc.FloatValues["_GiEqualization"]);
var (key, value) = matDesc.EnumerateSubAssetKeyValue().First();
Assert.AreEqual(new SubAssetKey(typeof(Texture2D), "Alicia_body"), key);
var (key, value) = matDesc.EnumerateSubAssetKeyValue().First();
Assert.AreEqual(new SubAssetKey(typeof(Texture2D), "Alicia_body"), key);
}
}
private void AreColorEqualApproximately(Color expected, Color actual)

View File

@ -22,9 +22,11 @@ namespace UniVRM10
static JsonNode GetVRM0(byte[] bytes)
{
var glb = new GlbBinaryParser(bytes, "vrm0").Parse();
var json = glb.Json.ParseAsJson();
return json["extensions"]["VRM"];
using (var glb = new GlbBinaryParser(bytes, "vrm0").Parse())
{
var json = glb.Json.ParseAsJson();
return json["extensions"]["VRM"];
}
}
T GetExtension<T>(UniGLTF.glTFExtension extensions, UniJSON.Utf8String key, Func<JsonNode, T> deserializer)
@ -50,14 +52,16 @@ namespace UniVRM10
var vrm0Json = GetVRM0(vrm0Bytes);
var vrm1 = MigrationVrm.Migrate(vrm0Bytes);
var glb = new GlbBinaryParser(vrm1, "vrm1").Parse();
var json = glb.Json.ParseAsJson();
var gltf = UniGLTF.GltfDeserializer.Deserialize(json);
using (var glb = new GlbBinaryParser(vrm1, "vrm1").Parse())
{
var json = glb.Json.ParseAsJson();
var gltf = UniGLTF.GltfDeserializer.Deserialize(json);
MigrationVrm.Check(vrm0Json, GetExtension(gltf.extensions, UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.ExtensionNameUtf8,
UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.Deserialize), MigrationVrm.CreateMeshToNode(gltf));
MigrationVrm.Check(vrm0Json, GetExtension(gltf.extensions, UniGLTF.Extensions.VRMC_springBone.GltfDeserializer.ExtensionNameUtf8,
UniGLTF.Extensions.VRMC_springBone.GltfDeserializer.Deserialize), gltf.nodes);
MigrationVrm.Check(vrm0Json, GetExtension(gltf.extensions, UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.ExtensionNameUtf8,
UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.Deserialize), MigrationVrm.CreateMeshToNode(gltf));
MigrationVrm.Check(vrm0Json, GetExtension(gltf.extensions, UniGLTF.Extensions.VRMC_springBone.GltfDeserializer.ExtensionNameUtf8,
UniGLTF.Extensions.VRMC_springBone.GltfDeserializer.Deserialize), gltf.nodes);
}
}
const float EPS = 1e-4f;
@ -194,7 +198,8 @@ namespace UniVRM10
{
try
{
Vrm10Data.TryParseOrMigrate(gltf.FullName, true, out Vrm10Data vrm);
Assert.True(Vrm10Data.TryParseOrMigrate(gltf.FullName, true, out Vrm10Data vrm));
using (vrm)
using (var loader = new Vrm10Importer(vrm))
{
loader.LoadAsync().Wait();
@ -218,41 +223,47 @@ namespace UniVRM10
//
var VALUE = new Vector3(-0.0359970331f, -0.0188314915f, 0.00566166639f);
var bytes0 = File.ReadAllBytes(AliciaPath);
var data0 = new GlbLowLevelParser(AliciaPath, bytes0).Parse();
var json0 = data0.Json.ParseAsJson();
var groupIndex = json0["extensions"]["VRM"]["secondaryAnimation"]["boneGroups"][0]["colliderGroups"][0].GetInt32();
var x = json0["extensions"]["VRM"]["secondaryAnimation"]["colliderGroups"][groupIndex]["colliders"][0]["offset"]["x"].GetSingle();
var y = json0["extensions"]["VRM"]["secondaryAnimation"]["colliderGroups"][groupIndex]["colliders"][0]["offset"]["y"].GetSingle();
var z = json0["extensions"]["VRM"]["secondaryAnimation"]["colliderGroups"][groupIndex]["colliders"][0]["offset"]["z"].GetSingle();
Assert.AreEqual(VALUE.x, x);
Assert.AreEqual(VALUE.y, y);
Assert.AreEqual(VALUE.z, z);
int groupIndex = default;
using (var data0 = new GlbLowLevelParser(AliciaPath, bytes0).Parse())
{
var json0 = data0.Json.ParseAsJson();
groupIndex = json0["extensions"]["VRM"]["secondaryAnimation"]["boneGroups"][0]["colliderGroups"][0].GetInt32();
var x = json0["extensions"]["VRM"]["secondaryAnimation"]["colliderGroups"][groupIndex]["colliders"][0]["offset"]["x"].GetSingle();
var y = json0["extensions"]["VRM"]["secondaryAnimation"]["colliderGroups"][groupIndex]["colliders"][0]["offset"]["y"].GetSingle();
var z = json0["extensions"]["VRM"]["secondaryAnimation"]["colliderGroups"][groupIndex]["colliders"][0]["offset"]["z"].GetSingle();
Assert.AreEqual(VALUE.x, x);
Assert.AreEqual(VALUE.y, y);
Assert.AreEqual(VALUE.z, z);
}
//
// vrm1 に migrate
//
var bytes1 = MigrationVrm.Migrate(bytes0);
var data1 = new GlbLowLevelParser(AliciaPath, bytes1).Parse();
Assert.True(UniGLTF.Extensions.VRMC_springBone.GltfDeserializer.TryGet(data1.GLTF.extensions, out UniGLTF.Extensions.VRMC_springBone.VRMC_springBone springBone));
var spring = springBone.Springs[0];
// var colliderNodeIndex = spring.ColliderGroups[0];
// x軸だけが反転する
var colliderIndex = 0;
for (int i = 0; i < groupIndex; ++i)
using (var data1 = new GlbLowLevelParser(AliciaPath, bytes1).Parse())
{
colliderIndex += springBone.ColliderGroups[i].Colliders.Length;
}
Assert.True(UniGLTF.Extensions.VRMC_springBone.GltfDeserializer.TryGet(data1.GLTF.extensions, out UniGLTF.Extensions.VRMC_springBone.VRMC_springBone springBone));
var spring = springBone.Springs[0];
// var colliderNodeIndex = spring.ColliderGroups[0];
// x軸だけが反転する
Assert.AreEqual(-VALUE.x, springBone.Colliders[colliderIndex].Shape.Sphere.Offset[0]);
Assert.AreEqual(VALUE.y, springBone.Colliders[colliderIndex].Shape.Sphere.Offset[1]);
Assert.AreEqual(VALUE.z, springBone.Colliders[colliderIndex].Shape.Sphere.Offset[2]);
var colliderIndex = 0;
for (int i = 0; i < groupIndex; ++i)
{
colliderIndex += springBone.ColliderGroups[i].Colliders.Length;
}
Assert.AreEqual(-VALUE.x, springBone.Colliders[colliderIndex].Shape.Sphere.Offset[0]);
Assert.AreEqual(VALUE.y, springBone.Colliders[colliderIndex].Shape.Sphere.Offset[1]);
Assert.AreEqual(VALUE.z, springBone.Colliders[colliderIndex].Shape.Sphere.Offset[2]);
}
}
[Test]
public void MigrateMeta()
{
Assert.True(Vrm10Data.TryParseOrMigrate(AliciaPath, true, out Vrm10Data vrm));
vrm.Dispose();
}
}
}

View File

@ -17,6 +17,7 @@ namespace UniVRM10
public static Vrm10Instance LoadAlicia()
{
Vrm10Data.TryParseOrMigrate(AliciaPath, true, out Vrm10Data vrm);
using (vrm)
using (var loader = new Vrm10Importer(vrm))
{
var task = loader.LoadAsync(new VRMShaders.ImmediateCaller());

View File

@ -85,27 +85,8 @@ namespace VRM.FirstPersonSample
// GLB形式でJSONを取得しParseします
// VRM extension を parse します
var data = new GlbFileParser(path).Parse();
var vrm = new VRMData(data);
using (var context = new VRMImporterContext(vrm))
{
// metaを取得(todo: thumbnailテクスチャのロード)
var meta = await context.ReadMetaAsync();
Debug.LogFormat("meta: title:{0}", meta.Title);
// ParseしたJSONをシーンオブジェクトに変換していく
var loaded = default(RuntimeGltfInstance);
if (m_loadAsync)
{
loaded = await context.LoadAsync();
}
else
{
loaded = context.Load();
}
OnLoaded(loaded);
}
var loaded = await VrmUtility.LoadAsync(path);
OnLoaded(loaded);
}
/// <summary>

View File

@ -49,25 +49,11 @@ namespace VRM.RuntimeExporterSample
return;
}
// GLB形式でJSONを取得しParseします
var data = new GlbFileParser(path).Parse();
// VRM extension を parse します
var vrm = new VRMData(data);
using (var context = new VRMImporterContext(vrm))
{
var loaded = await VrmUtility.LoadAsync(path);
// metaを取得(todo: thumbnailテクスチャのロード)
var meta = await context.ReadMetaAsync();
Debug.LogFormat("meta: title:{0}", meta.Title);
// ParseしたJSONをシーンオブジェクトに変換していく
var loaded = await context.LoadAsync();
loaded.ShowMeshes();
loaded.EnableUpdateWhenOffscreen();
OnLoaded(loaded.gameObject);
}
loaded.ShowMeshes();
loaded.EnableUpdateWhenOffscreen();
OnLoaded(loaded.gameObject);
}
void OnLoaded(GameObject go)

View File

@ -103,10 +103,8 @@ namespace VRM.SimpleViewer
m_textDistributionOther.text = "";
}
public async Task UpdateMetaAsync(VRMImporterContext context)
public void UpdateMeta(VRMMetaObject meta)
{
var meta = await context.ReadMetaAsync(new ImmediateCaller(), true);
m_textModelTitle.text = meta.Title;
m_textModelVersion.text = meta.Version;
m_textModelAuthor.text = meta.Author;
@ -321,7 +319,7 @@ namespace VRM.SimpleViewer
string[] cmds = System.Environment.GetCommandLineArgs();
if (cmds.Length > 1)
{
LoadModel(cmds[1]);
LoadModelAsync(cmds[1]);
}
m_texts.Start();
@ -366,10 +364,10 @@ namespace VRM.SimpleViewer
return;
}
LoadModel(path);
LoadModelAsync(path);
}
void LoadModel(string path)
async void LoadModelAsync(string path)
{
var ext = Path.GetExtension(path).ToLower();
switch (ext)
@ -377,12 +375,21 @@ namespace VRM.SimpleViewer
case ".gltf":
case ".glb":
case ".zip":
LoadModelAsync(path, false);
break;
{
var instance = await GltfUtility.LoadAsync(path,
GetIAwaitCaller(m_useAsync.isOn),
GetGltfMaterialGenerator(m_useUrpMaterial.isOn));
break;
}
case ".vrm":
LoadModelAsync(path, true);
break;
{
VrmUtility.MaterialGeneratorCallback materialCallback = (VRM.glTF_VRM_extensions vrm) => GetVrmMaterialGenerator(m_useUrpMaterial.isOn, vrm);
VrmUtility.MetaCallback metaCallback = m_texts.UpdateMeta;
var instance = await VrmUtility.LoadAsync(path, GetIAwaitCaller(m_useAsync.isOn), materialCallback, metaCallback);
SetModel(instance);
break;
}
case ".bvh":
LoadMotion(path, File.ReadAllText(path));
@ -431,59 +438,6 @@ namespace VRM.SimpleViewer
}
}
async void LoadModelAsync(string path, bool isVrm)
{
if (!File.Exists(path))
{
return;
}
Debug.LogFormat("{0}", path);
GltfData data;
try
{
data = new AutoGltfFileParser(path).Parse();
}
catch (Exception ex)
{
Debug.LogWarningFormat("parse error: {0}", ex);
return;
}
if (isVrm)
{
try
{
var vrm = new VRMData(data);
using (var loader = new VRMImporterContext(vrm, materialGenerator: GetVrmMaterialGenerator(m_useUrpMaterial.isOn, vrm.VrmExtension)))
{
await m_texts.UpdateMetaAsync(loader);
var instance = await loader.LoadAsync(GetIAwaitCaller(m_useAsync.isOn));
SetModel(instance);
}
}
catch (NotVrm0Exception)
{
// retry
Debug.LogWarning("file extension is vrm. but not vrm ?");
using (var loader = new UniGLTF.ImporterContext(data, materialGenerator: GetGltfMaterialGenerator(m_useUrpMaterial.isOn)))
{
var instance = await loader.LoadAsync(GetIAwaitCaller(m_useAsync.isOn));
SetModel(instance);
}
}
}
else
{
using (var loader = new UniGLTF.ImporterContext(data, materialGenerator: GetGltfMaterialGenerator(m_useUrpMaterial.isOn)))
{
var instance = await loader.LoadAsync(GetIAwaitCaller(m_useAsync.isOn));
SetModel(instance);
}
}
}
void SetModel(RuntimeGltfInstance instance)
{
// cleanup
@ -495,7 +449,7 @@ namespace VRM.SimpleViewer
if (m_useFastSpringBone.isOn)
{
FastSpringBoneReplacer.ReplaceAsync(instance.Root);
var _ = FastSpringBoneReplacer.ReplaceAsync(instance.Root);
}
instance.EnableUpdateWhenOffscreen();