Merge pull request #1339 from ousttrue/gltf_buffer_helper

[Maintenance] refactoring gltf buffer access
This commit is contained in:
ousttrue
2021-10-27 14:23:01 +09:00
committed by GitHub
43 changed files with 806 additions and 685 deletions

View File

@@ -100,8 +100,8 @@ namespace UniGLTF
default: throw new System.Exception();
}
var gltf = new glTF();
using (var exporter = new gltfExporter(gltf, Settings))
var data = new ExportingGltfData();
using (var exporter = new gltfExporter(data, Settings))
{
exporter.Prepare(State.ExportRoot);
exporter.Export(new EditorTextureSerializer());
@@ -109,12 +109,12 @@ namespace UniGLTF
if (isGlb)
{
var bytes = gltf.ToGlbBytes();
var bytes = data.ToGlbBytes();
File.WriteAllBytes(path, bytes);
}
else
{
var (json, buffers) = gltf.ToGltf(path);
var (json, buffers) = data.ToGltf(path);
// without BOM
var encoding = new System.Text.UTF8Encoding(false);
File.WriteAllText(path, json, encoding);

View File

@@ -17,7 +17,6 @@ namespace UniGLTF
public GltfData Data => m_data;
public glTF GLTF => m_data.GLTF;
public IStorage Storage => m_data.Storage;
public readonly Dictionary<SubAssetKey, UnityPath> Textures = new Dictionary<SubAssetKey, UnityPath>();
private readonly IReadOnlyDictionary<SubAssetKey, Texture> m_subAssets;

View File

@@ -1,46 +1,11 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using System.IO;
using UniJSON;
namespace UniGLTF
{
[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Byte4
{
public readonly byte x;
public readonly byte y;
public readonly byte z;
public readonly byte w;
public Byte4(byte _x, byte _y, byte _z, byte _w)
{
x = _x;
y = _y;
z = _z;
w = _w;
}
}
[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct UShort4
{
public readonly ushort x;
public readonly ushort y;
public readonly ushort z;
public readonly ushort w;
public UShort4(ushort _x, ushort _y, ushort _z, ushort _w)
{
x = _x;
y = _y;
z = _z;
w = _w;
}
}
public static class glTFExtensions
{
struct ComponentVec
@@ -131,367 +96,6 @@ namespace UniGLTF
}
}
public static int ExtendBufferAndGetAccessorIndex<T>(this glTF gltf, int bufferIndex, T[] array,
glBufferTarget target = glBufferTarget.NONE) where T : struct
{
return gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, new ArraySegment<T>(array), target);
}
public static int ExtendBufferAndGetAccessorIndex<T>(this glTF gltf, int bufferIndex,
ArraySegment<T> array,
glBufferTarget target = glBufferTarget.NONE) where T : struct
{
if (array.Count == 0)
{
return -1;
}
var viewIndex = ExtendBufferAndGetViewIndex(gltf, bufferIndex, array, target);
// index buffer's byteStride is unnecessary
gltf.bufferViews[viewIndex].byteStride = 0;
var accessorIndex = gltf.accessors.Count;
gltf.accessors.Add(new glTFAccessor
{
bufferView = viewIndex,
byteOffset = 0,
componentType = GetComponentType<T>(),
type = GetAccessorType<T>(),
count = array.Count,
});
return accessorIndex;
}
public static int ExtendBufferAndGetViewIndex<T>(this glTF gltf, int bufferIndex,
T[] array,
glBufferTarget target = glBufferTarget.NONE) where T : struct
{
return ExtendBufferAndGetViewIndex(gltf, bufferIndex, new ArraySegment<T>(array), target);
}
public static int ExtendBufferAndGetViewIndex<T>(this glTF gltf, int bufferIndex,
ArraySegment<T> array,
glBufferTarget target = glBufferTarget.NONE) where T : struct
{
if (array.Count == 0)
{
return -1;
}
var view = gltf.buffers[bufferIndex].Append(array, target);
var viewIndex = gltf.bufferViews.Count;
gltf.bufferViews.Add(view);
return viewIndex;
}
/// <summary>
/// sparseValues は間引かれた配列
/// </summary>
public static int ExtendSparseBufferAndGetAccessorIndex<T>(this glTF gltf, int bufferIndex,
int accessorCount,
T[] sparseValues, int[] sparseIndices, int sparseViewIndex,
glBufferTarget target = glBufferTarget.NONE) where T : struct
{
return ExtendSparseBufferAndGetAccessorIndex(gltf, bufferIndex,
accessorCount,
new ArraySegment<T>(sparseValues), sparseIndices, sparseViewIndex,
target);
}
public static int ExtendSparseBufferAndGetAccessorIndex<T>(this glTF gltf, int bufferIndex,
int accessorCount,
ArraySegment<T> sparseValues, int[] sparseIndices, int sparseIndicesViewIndex,
glBufferTarget target = glBufferTarget.NONE) where T : struct
{
if (sparseValues.Count == 0)
{
return -1;
}
var sparseValuesViewIndex = ExtendBufferAndGetViewIndex(gltf, bufferIndex, sparseValues, target);
var accessorIndex = gltf.accessors.Count;
gltf.accessors.Add(new glTFAccessor
{
byteOffset = 0,
componentType = GetComponentType<T>(),
type = GetAccessorType<T>(),
count = accessorCount,
sparse = new glTFSparse
{
count = sparseIndices.Length,
indices = new glTFSparseIndices
{
bufferView = sparseIndicesViewIndex,
componentType = glComponentType.UNSIGNED_INT
},
values = new glTFSparseValues
{
bufferView = sparseValuesViewIndex,
}
}
});
return accessorIndex;
}
public static int AddBuffer(this glTF self, IBytesBuffer bytesBuffer)
{
var index = self.buffers.Count;
self.buffers.Add(new glTFBuffer(bytesBuffer));
return index;
}
static T[] GetAttrib<T>(this glTF self, int count, int byteOffset, glTFBufferView view) where T : struct
{
var attrib = new T[count];
var segment = self.buffers[view.buffer].GetBytes();
var bytes = new ArraySegment<Byte>(segment.Array, segment.Offset + view.byteOffset + byteOffset, count * view.byteStride);
bytes.MarshalCopyTo(attrib);
return attrib;
}
static T[] GetAttrib<T>(this glTF self, glTFAccessor accessor, glTFBufferView view) where T : struct
{
return self.GetAttrib<T>(accessor.count, accessor.byteOffset, view);
}
static IEnumerable<int> _GetIndices(this glTF self, glTFAccessor accessor, out int count)
{
count = accessor.count;
var view = self.bufferViews[accessor.bufferView];
switch ((glComponentType)accessor.componentType)
{
case glComponentType.UNSIGNED_BYTE:
{
return self.GetAttrib<Byte>(accessor, view).Select(x => (int)(x));
}
case glComponentType.UNSIGNED_SHORT:
{
return self.GetAttrib<UInt16>(accessor, view).Select(x => (int)(x));
}
case glComponentType.UNSIGNED_INT:
{
return self.GetAttrib<UInt32>(accessor, view).Select(x => (int)(x));
}
}
throw new NotImplementedException("GetIndices: unknown componenttype: " + accessor.componentType);
}
static IEnumerable<int> _GetIndices(this glTF self, glTFBufferView view, int count, int byteOffset, glComponentType componentType)
{
switch (componentType)
{
case glComponentType.UNSIGNED_BYTE:
{
return self.GetAttrib<Byte>(count, byteOffset, view).Select(x => (int)(x));
}
case glComponentType.UNSIGNED_SHORT:
{
return self.GetAttrib<UInt16>(count, byteOffset, view).Select(x => (int)(x));
}
case glComponentType.UNSIGNED_INT:
{
return self.GetAttrib<UInt32>(count, byteOffset, view).Select(x => (int)(x));
}
}
throw new NotImplementedException("GetIndices: unknown componenttype: " + componentType);
}
public static int[] GetIndices(this glTF self, int accessorIndex)
{
int count;
var result = self._GetIndices(self.accessors[accessorIndex], out count);
var indices = new int[count];
// flip triangles
var it = result.GetEnumerator();
{
for (int i = 0; i < count; i += 3)
{
it.MoveNext(); indices[i + 2] = it.Current;
it.MoveNext(); indices[i + 1] = it.Current;
it.MoveNext(); indices[i] = it.Current;
}
}
return indices;
}
public static T[] GetArrayFromAccessor<T>(this glTF self, int accessorIndex) where T : struct
{
var vertexAccessor = self.accessors[accessorIndex];
if (vertexAccessor.count <= 0) return new T[] { };
var result = (vertexAccessor.bufferView != -1)
? self.GetAttrib<T>(vertexAccessor, self.bufferViews[vertexAccessor.bufferView])
: new T[vertexAccessor.count]
;
var sparse = vertexAccessor.sparse;
if (sparse != null && sparse.count > 0)
{
// override sparse values
var indices = self._GetIndices(self.bufferViews[sparse.indices.bufferView], sparse.count, sparse.indices.byteOffset, sparse.indices.componentType);
var values = self.GetAttrib<T>(sparse.count, sparse.values.byteOffset, self.bufferViews[sparse.values.bufferView]);
var it = indices.GetEnumerator();
for (int i = 0; i < sparse.count; ++i)
{
it.MoveNext();
result[it.Current] = values[i];
}
}
return result;
}
public static float[] FlatternFloatArrayFromAccessor(this glTF self, int accessorIndex)
{
var vertexAccessor = self.accessors[accessorIndex];
if (vertexAccessor.count <= 0) return new float[] { };
var bufferCount = vertexAccessor.count * vertexAccessor.TypeCount;
float[] result = null;
if (vertexAccessor.bufferView != -1)
{
var attrib = new float[vertexAccessor.count * vertexAccessor.TypeCount];
var view = self.bufferViews[vertexAccessor.bufferView];
var segment = self.buffers[view.buffer].GetBytes();
var bytes = new ArraySegment<Byte>(segment.Array, segment.Offset + view.byteOffset + vertexAccessor.byteOffset, vertexAccessor.count * view.byteStride);
bytes.MarshalCopyTo(attrib);
result = attrib;
}
else
{
result = new float[bufferCount];
}
var sparse = vertexAccessor.sparse;
if (sparse != null && sparse.count > 0)
{
// override sparse values
var indices = self._GetIndices(self.bufferViews[sparse.indices.bufferView], sparse.count, sparse.indices.byteOffset, sparse.indices.componentType);
var values = self.GetAttrib<float>(sparse.count * vertexAccessor.TypeCount, sparse.values.byteOffset, self.bufferViews[sparse.values.bufferView]);
var it = indices.GetEnumerator();
for (int i = 0; i < sparse.count; ++i)
{
it.MoveNext();
result[it.Current] = values[i];
}
}
return result;
}
public static ArraySegment<Byte> GetImageBytesFromTextureIndex(this glTF self, IStorage storage, int textureIndex)
{
var imageIndex = self.textures[textureIndex].source;
return self.GetImageBytes(storage, imageIndex);
}
public static ArraySegment<Byte> GetImageBytes(this glTF self, IStorage storage, int imageIndex)
{
var image = self.images[imageIndex];
if (string.IsNullOrEmpty(image.uri))
{
return self.GetViewBytes(image.bufferView);
}
else
{
return storage.Get(image.uri);
}
}
static Utf8String s_extensions = Utf8String.From("extensions");
static bool UsedExtension(this glTF self, string key)
{
if (self.extensionsUsed.Contains(key))
{
return true;
}
return false;
}
static void Traverse(this glTF self, JsonNode node, JsonFormatter f, Utf8String parentKey)
{
if (node.IsMap())
{
f.BeginMap();
foreach (var kv in node.ObjectItems())
{
if (parentKey == s_extensions)
{
if (!self.UsedExtension(kv.Key.GetString()))
{
continue;
}
}
f.Key(kv.Key.GetUtf8String());
self.Traverse(kv.Value, f, kv.Key.GetUtf8String());
}
f.EndMap();
}
else if (node.IsArray())
{
f.BeginList();
foreach (var x in node.ArrayItems())
{
self.Traverse(x, f, default(Utf8String));
}
f.EndList();
}
else
{
f.Value(node);
}
}
static string RemoveUnusedExtensions(this glTF self, string json)
{
var f = new JsonFormatter();
self.Traverse(JsonParser.Parse(json), f, default(Utf8String));
return f.ToString();
}
public static byte[] ToGlbBytes(this glTF self)
{
var f = new JsonFormatter();
GltfSerializer.Serialize(f, self);
// remove unused extenions
var json = f.ToString().ParseAsJson().ToString(" ");
self.RemoveUnusedExtensions(json);
return Glb.Create(json, self.buffers[0].GetBytes()).ToBytes();
}
public static (string, List<glTFBuffer>) ToGltf(this glTF self, string gltfPath)
{
var f = new JsonFormatter();
// fix buffer path
if (self.buffers.Count == 1)
{
var withoutExt = Path.GetFileNameWithoutExtension(gltfPath);
self.buffers[0].uri = $"{withoutExt}.bin";
}
else
{
throw new NotImplementedException();
}
GltfSerializer.Serialize(f, self);
var json = f.ToString().ParseAsJson().ToString(" ");
self.RemoveUnusedExtensions(json);
return (json, self.buffers);
}
public static bool IsGeneratedUniGLTFAndOlderThan(string generatorVersion, int major, int minor)
{
if (string.IsNullOrEmpty(generatorVersion)) return false;

View File

@@ -2,15 +2,23 @@ using System;
namespace UniGLTF
{
/// <summary>
/// Represents bytes access by URL in gltf
/// </summary>
public interface IStorage
{
ArraySegment<Byte> Get(string url = default);
/// <summary>
/// Get original filepath if exists
/// gltf の buffer の バイト列アクセス を実装する。
/// 1. url による相対パス
/// 2. url によるbase64 encoding
/// 3. url がnullのときに bin chunk(buffers[0]) にアクセスする
///
/// TODO:
/// 1. url による相対パス
/// 以外をやめて、呼び出し側で分岐させる。
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
string GetPath(string url);
ArraySegment<Byte> Get(string url = default);
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 6e3316b83a7396047839d12538e5db52
guid: f87f7ed809642e0429061fd5f6c169f3
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -40,13 +40,6 @@ namespace UniGLTF
[JsonSchema(MinItems = 1, ExplicitIgnorableItemLength = 0)]
public List<glTFAccessor> accessors = new List<glTFAccessor>();
public ArraySegment<Byte> GetViewBytes(int bufferView)
{
var view = bufferViews[bufferView];
var segment = buffers[view.buffer].GetBytes();
return new ArraySegment<byte>(segment.Array, segment.Offset + view.byteOffset, view.byteLength);
}
#endregion
[JsonSchema(MinItems = 1, ExplicitIgnorableItemLength = 0)]

View File

@@ -185,7 +185,7 @@ namespace UniGLTF
return string.Join("/", path);
}
public static AnimationClip ConvertAnimationClip(glTF gltf, glTFAnimation animation, IAxisInverter inverter, glTFNode root = null)
public static AnimationClip ConvertAnimationClip(GltfData data, glTFAnimation animation, IAxisInverter inverter, glTFNode root = null)
{
var clip = new AnimationClip();
clip.ClearCurves();
@@ -195,14 +195,14 @@ namespace UniGLTF
foreach (var channel in animation.channels)
{
var relativePath = RelativePathFrom(gltf.nodes, root, gltf.nodes[channel.target.node]);
var relativePath = RelativePathFrom(data.GLTF.nodes, root, data.GLTF.nodes[channel.target.node]);
switch (channel.target.path)
{
case glTFAnimationTarget.PATH_TRANSLATION:
{
var sampler = animation.samplers[channel.sampler];
var input = gltf.GetArrayFromAccessor<float>(sampler.input);
var output = gltf.FlatternFloatArrayFromAccessor(sampler.output);
var input = data.GetArrayFromAccessor<float>(sampler.input);
var output = data.FlatternFloatArrayFromAccessor(sampler.output);
AnimationImporterUtil.SetAnimationCurve(
clip,
@@ -224,8 +224,8 @@ namespace UniGLTF
case glTFAnimationTarget.PATH_ROTATION:
{
var sampler = animation.samplers[channel.sampler];
var input = gltf.GetArrayFromAccessor<float>(sampler.input);
var output = gltf.FlatternFloatArrayFromAccessor(sampler.output);
var input = data.GetArrayFromAccessor<float>(sampler.input);
var output = data.FlatternFloatArrayFromAccessor(sampler.output);
AnimationImporterUtil.SetAnimationCurve(
clip,
@@ -250,8 +250,8 @@ namespace UniGLTF
case glTFAnimationTarget.PATH_SCALE:
{
var sampler = animation.samplers[channel.sampler];
var input = gltf.GetArrayFromAccessor<float>(sampler.input);
var output = gltf.FlatternFloatArrayFromAccessor(sampler.output);
var input = data.GetArrayFromAccessor<float>(sampler.input);
var output = data.FlatternFloatArrayFromAccessor(sampler.output);
AnimationImporterUtil.SetAnimationCurve(
clip,
@@ -267,8 +267,8 @@ namespace UniGLTF
case glTFAnimationTarget.PATH_WEIGHT:
{
var node = gltf.nodes[channel.target.node];
var mesh = gltf.meshes[node.mesh];
var node = data.GLTF.nodes[channel.target.node];
var mesh = data.GLTF.meshes[node.mesh];
var primitive = mesh.primitives.FirstOrDefault();
var targets = primitive.targets;
@@ -283,8 +283,8 @@ namespace UniGLTF
.ToArray();
var sampler = animation.samplers[channel.sampler];
var input = gltf.GetArrayFromAccessor<float>(sampler.input);
var output = gltf.GetArrayFromAccessor<float>(sampler.output);
var input = data.GetArrayFromAccessor<float>(sampler.input);
var output = data.GetArrayFromAccessor<float>(sampler.output);
AnimationImporterUtil.SetAnimationCurve(
clip,
relativePath,

View File

@@ -0,0 +1,26 @@
using System;
using System.Runtime.InteropServices;
namespace UniGLTF
{
[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
public readonly struct Byte4 : IEquatable<Byte4>
{
public readonly byte x;
public readonly byte y;
public readonly byte z;
public readonly byte w;
public Byte4(byte _x, byte _y, byte _z, byte _w)
{
x = _x;
y = _y;
z = _z;
w = _w;
}
public bool Equals(Byte4 other)
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
}
}

View File

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

View File

@@ -0,0 +1,229 @@
using System;
using System.Collections.Generic;
using System.IO;
using UniJSON;
namespace UniGLTF
{
public class ExportingGltfData
{
readonly glTF _gltf = new glTF();
public glTF GLTF => _gltf;
public ExportingGltfData(int reserved = default)
{
if (reserved == 0)
{
reserved = 50 * 1024 * 1024;
}
// glb body と gltf の bin 兼用
_gltf.buffers.Add(new glTFBuffer(new ArrayByteBuffer(new byte[reserved])));
}
#region Buffer management for export
public int ExtendBufferAndGetViewIndex<T>(
ArraySegment<T> array,
glBufferTarget target = glBufferTarget.NONE) where T : struct
{
if (array.Count == 0)
{
return -1;
}
var view = _gltf.buffers[0].Append(array, target);
var viewIndex = _gltf.bufferViews.Count;
_gltf.bufferViews.Add(view);
return viewIndex;
}
public int ExtendBufferAndGetViewIndex<T>(
T[] array,
glBufferTarget target = glBufferTarget.NONE) where T : struct
{
return ExtendBufferAndGetViewIndex(new ArraySegment<T>(array), target);
}
public int ExtendBufferAndGetAccessorIndex<T>(
ArraySegment<T> array,
glBufferTarget target = glBufferTarget.NONE) where T : struct
{
if (array.Count == 0)
{
return -1;
}
var viewIndex = ExtendBufferAndGetViewIndex(array, target);
// index buffer's byteStride is unnecessary
_gltf.bufferViews[viewIndex].byteStride = 0;
var accessorIndex = _gltf.accessors.Count;
_gltf.accessors.Add(new glTFAccessor
{
bufferView = viewIndex,
byteOffset = 0,
componentType = glTFExtensions.GetComponentType<T>(),
type = glTFExtensions.GetAccessorType<T>(),
count = array.Count,
});
return accessorIndex;
}
public int ExtendBufferAndGetAccessorIndex<T>(T[] array,
glBufferTarget target = glBufferTarget.NONE) where T : struct
{
return ExtendBufferAndGetAccessorIndex(new ArraySegment<T>(array), target);
}
/// <summary>
/// sparseValues は間引かれた配列
/// </summary>
public int ExtendSparseBufferAndGetAccessorIndex<T>(
int accessorCount,
T[] sparseValues, int[] sparseIndices, int sparseViewIndex,
glBufferTarget target = glBufferTarget.NONE) where T : struct
{
return ExtendSparseBufferAndGetAccessorIndex(
accessorCount,
new ArraySegment<T>(sparseValues), sparseIndices, sparseViewIndex,
target);
}
public int ExtendSparseBufferAndGetAccessorIndex<T>(
int accessorCount,
ArraySegment<T> sparseValues, int[] sparseIndices, int sparseIndicesViewIndex,
glBufferTarget target = glBufferTarget.NONE) where T : struct
{
if (sparseValues.Count == 0)
{
return -1;
}
var sparseValuesViewIndex = ExtendBufferAndGetViewIndex(sparseValues, target);
var accessorIndex = _gltf.accessors.Count;
_gltf.accessors.Add(new glTFAccessor
{
byteOffset = 0,
componentType = glTFExtensions.GetComponentType<T>(),
type = glTFExtensions.GetAccessorType<T>(),
count = accessorCount,
sparse = new glTFSparse
{
count = sparseIndices.Length,
indices = new glTFSparseIndices
{
bufferView = sparseIndicesViewIndex,
componentType = glComponentType.UNSIGNED_INT
},
values = new glTFSparseValues
{
bufferView = sparseValuesViewIndex,
}
}
});
return accessorIndex;
}
#endregion
#region ToGltf & ToGlb
static Utf8String s_extensions = Utf8String.From("extensions");
static bool UsedExtension(glTF self, string key)
{
if (self.extensionsUsed.Contains(key))
{
return true;
}
return false;
}
static void Traverse(glTF self, JsonNode node, JsonFormatter f, Utf8String parentKey)
{
if (node.IsMap())
{
f.BeginMap();
foreach (var kv in node.ObjectItems())
{
if (parentKey == s_extensions)
{
if (!UsedExtension(self, kv.Key.GetString()))
{
// skip extension not in used
continue;
}
}
f.Key(kv.Key.GetUtf8String());
Traverse(self, kv.Value, f, kv.Key.GetUtf8String());
}
f.EndMap();
}
else if (node.IsArray())
{
f.BeginList();
foreach (var x in node.ArrayItems())
{
Traverse(self, x, f, default(Utf8String));
}
f.EndList();
}
else
{
f.Value(node);
}
}
/// <summary>
/// 出力前に不要な extension を削除する
/// </summary>
/// <param name="self"></param>
/// <param name="json"></param>
/// <returns></returns>
static string RemoveUnusedExtensions(glTF self, string json)
{
var f = new JsonFormatter();
Traverse(self, JsonParser.Parse(json), f, default(Utf8String));
return f.ToString();
}
/// <summary>
/// GLBバイト列
/// </summary>
/// <returns></returns>
public byte[] ToGlbBytes()
{
var f = new JsonFormatter();
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();
}
/// <summary>
/// glTF 形式で出力する?
/// </summary>
/// <param name="gltfPath"></param>
/// <returns></returns>
public (string, List<glTFBuffer>) ToGltf(string gltfPath)
{
// fix buffer path
if (_gltf.buffers.Count == 1)
{
var withoutExt = Path.GetFileNameWithoutExtension(gltfPath);
_gltf.buffers[0].uri = $"{withoutExt}.bin";
}
else
{
throw new NotImplementedException();
}
var f = new JsonFormatter();
GltfSerializer.Serialize(f, _gltf);
var json = f.ToString().ParseAsJson().ToString(" ");
RemoveUnusedExtensions(_gltf, json);
return (json, _gltf.buffers);
}
#endregion
}
}

View File

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

View File

@@ -1,8 +1,12 @@
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;
@@ -20,13 +24,11 @@ namespace UniGLTF
{
return m_bytes;
}
public string GetPath(string url)
{
return null;
}
}
/// <summary>
/// Implement url that represnet relative path
/// </summary>
public class FileSystemStorage : IStorage
{
string m_root;
@@ -45,17 +47,23 @@ namespace UniGLTF
;
return new ArraySegment<byte>(bytes);
}
}
public string GetPath(string url)
/// <summary>
/// for UnitTest
/// </summary>
public sealed class GltfStorage : IStorage
{
glTF _gltf;
public GltfStorage(glTF gltf)
{
if (url.FastStartsWith("data:"))
{
return null;
}
else
{
return Path.Combine(m_root, url).Replace("\\", "/");
}
_gltf = gltf;
}
public ArraySegment<byte> Get(string url)
{
return _gltf.buffers[0].GetBytes();
}
}
}

View File

@@ -1,8 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace UniGLTF
{
/// <summary>
/// * JSON is parsed but not validated as glTF
/// * For glb, bin chunks are already available
/// </summary>
public sealed class GltfData
{
/// <summary>
@@ -42,7 +47,7 @@ namespace UniGLTF
/// <summary>
/// URI access
/// </summary>
public IStorage Storage { get; }
public IStorage _storage;
/// <summary>
/// Migration Flags used by ImporterContext
@@ -55,20 +60,216 @@ namespace UniGLTF
Json = json;
GLTF = gltf;
Chunks = chunks;
Storage = storage;
_storage = storage;
MigrationFlags = migrationFlags;
}
public static GltfData CreateFromGltfDataForTest(glTF gltf)
public static GltfData CreateFromGltfDataForTest(glTF gltf, ArraySegment<byte> bytes = default)
{
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>(),
new SimpleStorage(new ArraySegment<byte>()),
storage,
new MigrationFlags()
);
}
public ArraySegment<Byte> GetBytes(int bufferIndex)
{
// TODO:
var buffer = GLTF.buffers[bufferIndex];
return _storage.Get(buffer.uri);
}
public ArraySegment<Byte> GetViewBytes(int bufferView)
{
var view = GLTF.bufferViews[bufferView];
var segment = GetBytes(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
{
var segment = GetBytes(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
{
return GetAttrib<T>(accessor.count, accessor.byteOffset, view);
}
IEnumerable<int> _GetIndices(glTFBufferView view, int count, int byteOffset, glComponentType componentType)
{
switch (componentType)
{
case glComponentType.UNSIGNED_BYTE:
{
return GetAttrib<Byte>(count, byteOffset, view).Select(x => (int)(x));
}
case glComponentType.UNSIGNED_SHORT:
{
return GetAttrib<UInt16>(count, byteOffset, view).Select(x => (int)(x));
}
case glComponentType.UNSIGNED_INT:
{
return GetAttrib<UInt32>(count, byteOffset, view).Select(x => (int)(x));
}
}
throw new NotImplementedException("GetIndices: unknown componenttype: " + componentType);
}
/// <summary>
/// Get indices and cast to int
/// </summary>
/// <param name="accessor"></param>
/// <param name="count"></param>
/// <returns></returns>
IEnumerable<int> _GetIndices(glTFAccessor accessor, out int count)
{
count = accessor.count;
var view = GLTF.bufferViews[accessor.bufferView];
switch ((glComponentType)accessor.componentType)
{
case glComponentType.UNSIGNED_BYTE:
{
return GetAttrib<Byte>(accessor, view).Select(x => (int)(x));
}
case glComponentType.UNSIGNED_SHORT:
{
return GetAttrib<UInt16>(accessor, view).Select(x => (int)(x));
}
case glComponentType.UNSIGNED_INT:
{
return GetAttrib<UInt32>(accessor, view).Select(x => (int)(x));
}
}
throw new NotImplementedException("GetIndices: unknown componenttype: " + accessor.componentType);
}
public int[] GetIndices(int accessorIndex)
{
int count;
var result = _GetIndices(GLTF.accessors[accessorIndex], out count);
var indices = new int[count];
// flip triangles
var it = result.GetEnumerator();
{
for (int i = 0; i < count; i += 3)
{
it.MoveNext(); indices[i + 2] = it.Current;
it.MoveNext(); indices[i + 1] = it.Current;
it.MoveNext(); indices[i] = it.Current;
}
}
return indices;
}
public T[] GetArrayFromAccessor<T>(int accessorIndex) where T : struct
{
var vertexAccessor = GLTF.accessors[accessorIndex];
if (vertexAccessor.count <= 0) return new T[] { };
var result = (vertexAccessor.bufferView != -1)
? GetAttrib<T>(vertexAccessor, GLTF.bufferViews[vertexAccessor.bufferView])
: new T[vertexAccessor.count]
;
var sparse = vertexAccessor.sparse;
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 it = indices.GetEnumerator();
for (int i = 0; i < sparse.count; ++i)
{
it.MoveNext();
result[it.Current] = values[i];
}
}
return result;
}
public float[] FlatternFloatArrayFromAccessor(int accessorIndex)
{
var vertexAccessor = GLTF.accessors[accessorIndex];
if (vertexAccessor.count <= 0) return new float[] { };
var bufferCount = vertexAccessor.count * vertexAccessor.TypeCount;
float[] result = null;
if (vertexAccessor.bufferView != -1)
{
var attrib = new float[vertexAccessor.count * vertexAccessor.TypeCount];
var view = GLTF.bufferViews[vertexAccessor.bufferView];
var segment = GetBytes(view.buffer);
var bytes = new ArraySegment<Byte>(segment.Array, segment.Offset + view.byteOffset + vertexAccessor.byteOffset, vertexAccessor.count * view.byteStride);
bytes.MarshalCopyTo(attrib);
result = attrib;
}
else
{
result = new float[bufferCount];
}
var sparse = vertexAccessor.sparse;
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 it = indices.GetEnumerator();
for (int i = 0; i < sparse.count; ++i)
{
it.MoveNext();
result[it.Current] = values[i];
}
}
return result;
}
public ArraySegment<Byte> GetImageBytes(int imageIndex)
{
var image = GLTF.images[imageIndex];
if (string.IsNullOrEmpty(image.uri))
{
return GetViewBytes(image.bufferView);
}
else
{
return _storage.Get(image.uri);
}
}
public ArraySegment<Byte> GetImageBytesFromTextureIndex(int textureIndex)
{
var imageIndex = GLTF.textures[textureIndex].source;
return GetImageBytes(imageIndex);
}
}
}

View File

@@ -57,7 +57,6 @@ namespace UniGLTF
public GltfData Data { get; }
public String Json => Data.Json;
public glTF GLTF => Data.GLTF;
public IStorage Storage => Data.Storage;
#endregion
// configuration
@@ -135,7 +134,7 @@ namespace UniGLTF
{
await AnimationClipFactory.LoadAnimationClipAsync(key, () =>
{
var clip = AnimationImporterUtil.ConvertAnimationClip(GLTF, gltfAnimation, InvertAxis.Create());
var clip = AnimationImporterUtil.ConvertAnimationClip(Data, gltfAnimation, InvertAxis.Create());
return Task.FromResult(clip);
});
}
@@ -178,7 +177,7 @@ namespace UniGLTF
var index = i;
using (MeasureTime("ReadMesh"))
{
var x = await awaitCaller.Run(() => meshImporter.ReadMesh(GLTF, index, inverter));
var x = await awaitCaller.Run(() => meshImporter.ReadMesh(Data, index, inverter));
var y = await BuildMeshAsync(awaitCaller, MeasureTime, x, index);
Meshes.Add(y);
}
@@ -225,7 +224,7 @@ namespace UniGLTF
Profiler.BeginSample("NodeImporter.SetupSkinning");
for (var i = 0; i < nodes.Count; ++i)
{
NodeImporter.SetupSkinning(GLTF, nodes, i, inverter);
NodeImporter.SetupSkinning(Data, nodes, i, inverter);
}
Profiler.EndSample();

View File

@@ -7,7 +7,7 @@ namespace UniGLTF
{
public static class BlendShapeExporter
{
public static gltfMorphTarget Export(glTF gltf, int gltfBuffer, Vector3[] positions, Vector3[] normals, bool useSparse)
public static gltfMorphTarget Export(ExportingGltfData data, Vector3[] positions, Vector3[] normals, bool useSparse)
{
var accessorCount = positions.Length;
if (normals != null && positions.Length != normals.Length)
@@ -44,8 +44,8 @@ namespace UniGLTF
var positionAccessorIndex = -1;
if (sparseIndices.Length > 0)
{
var sparseIndicesViewIndex = gltf.ExtendBufferAndGetViewIndex(gltfBuffer, sparseIndices);
positionAccessorIndex = gltf.ExtendSparseBufferAndGetAccessorIndex(gltfBuffer, accessorCount,
var sparseIndicesViewIndex = data.ExtendBufferAndGetViewIndex(sparseIndices);
positionAccessorIndex = data.ExtendSparseBufferAndGetAccessorIndex(accessorCount,
sparseIndices.Select(x => positions[x]).ToArray(), sparseIndices, sparseIndicesViewIndex,
glBufferTarget.NONE);
}
@@ -57,8 +57,8 @@ namespace UniGLTF
var sparseNormalIndices = Enumerable.Range(0, positions.Length).Where(x => normals[x] != Vector3.zero).ToArray();
if (sparseNormalIndices.Length > 0)
{
var sparseNormalIndicesViewIndex = gltf.ExtendBufferAndGetViewIndex(gltfBuffer, sparseNormalIndices);
normalAccessorIndex = gltf.ExtendSparseBufferAndGetAccessorIndex(gltfBuffer, accessorCount,
var sparseNormalIndicesViewIndex = data.ExtendBufferAndGetViewIndex(sparseNormalIndices);
normalAccessorIndex = data.ExtendSparseBufferAndGetAccessorIndex(accessorCount,
sparseNormalIndices.Select(x => normals[x]).ToArray(), sparseNormalIndices, sparseNormalIndicesViewIndex,
glBufferTarget.NONE);
}
@@ -73,15 +73,15 @@ namespace UniGLTF
else
{
// position
var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(gltfBuffer, positions, glBufferTarget.ARRAY_BUFFER);
gltf.accessors[positionAccessorIndex].min = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray();
gltf.accessors[positionAccessorIndex].max = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray();
var positionAccessorIndex = data.ExtendBufferAndGetAccessorIndex(positions, glBufferTarget.ARRAY_BUFFER);
data.GLTF.accessors[positionAccessorIndex].min = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray();
data.GLTF.accessors[positionAccessorIndex].max = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray();
// normal
var normalAccessorIndex = -1;
if (normals != null)
{
normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(gltfBuffer, normals, glBufferTarget.ARRAY_BUFFER);
normalAccessorIndex = data.ExtendBufferAndGetAccessorIndex(normals, glBufferTarget.ARRAY_BUFFER);
}
return new gltfMorphTarget

View File

@@ -9,14 +9,14 @@ namespace UniGLTF
{
public delegate (ushort x, ushort y, ushort z, ushort w) Getter(int index);
public static (Getter, int) GetAccessor(glTF gltf, int accessorIndex)
public static (Getter, int) GetAccessor(GltfData data, int accessorIndex)
{
var gltfAccessor = gltf.accessors[accessorIndex];
var gltfAccessor = data.GLTF.accessors[accessorIndex];
switch (gltfAccessor.componentType)
{
case glComponentType.UNSIGNED_BYTE:
{
var array = gltf.GetArrayFromAccessor<Byte4>(accessorIndex);
var array = data.GetArrayFromAccessor<Byte4>(accessorIndex);
Getter getter = (i) =>
{
var value = array[i];
@@ -27,7 +27,7 @@ namespace UniGLTF
case glComponentType.UNSIGNED_SHORT:
{
var array = gltf.GetArrayFromAccessor<UShort4>(accessorIndex);
var array = data.GetArrayFromAccessor<UShort4>(accessorIndex);
Getter getter = (i) =>
{
var value = array[i];

View File

@@ -30,9 +30,9 @@ namespace UniGLTF
m_normals[index] = normal;
}
public gltfMorphTarget ToGltf(glTF gltf, int gltfBuffer, bool useNormal, bool useSparse)
public gltfMorphTarget ToGltf(ExportingGltfData data, bool useNormal, bool useSparse)
{
return BlendShapeExporter.Export(gltf, gltfBuffer,
return BlendShapeExporter.Export(data,
m_positions,
useNormal ? m_normals : null,
useSparse);
@@ -103,24 +103,24 @@ namespace UniGLTF
m_weights.Add(new Vector4(boneWeight.weight0, boneWeight.weight1, boneWeight.weight2, boneWeight.weight3));
}
public glTFPrimitives ToGltfPrimitive(glTF gltf, int bufferIndex, int materialIndex, IEnumerable<int> indices)
public glTFPrimitives ToGltfPrimitive(ExportingGltfData data, int materialIndex, IEnumerable<int> indices)
{
var indicesAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, indices.Select(x => (uint)m_vertexIndexMap[x]).ToArray(), glBufferTarget.ELEMENT_ARRAY_BUFFER);
var indicesAccessorIndex = data.ExtendBufferAndGetAccessorIndex(indices.Select(x => (uint)m_vertexIndexMap[x]).ToArray(), glBufferTarget.ELEMENT_ARRAY_BUFFER);
var positions = m_positions.ToArray();
var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, positions, glBufferTarget.ARRAY_BUFFER);
var positionAccessorIndex = data.ExtendBufferAndGetAccessorIndex(positions, glBufferTarget.ARRAY_BUFFER);
var normals = m_normals.ToArray();
var normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, normals, glBufferTarget.ARRAY_BUFFER);
var uvAccessorIndex0 = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, m_uv.ToArray(), glBufferTarget.ARRAY_BUFFER);
var normalAccessorIndex = data.ExtendBufferAndGetAccessorIndex(normals, glBufferTarget.ARRAY_BUFFER);
var uvAccessorIndex0 = data.ExtendBufferAndGetAccessorIndex(m_uv.ToArray(), glBufferTarget.ARRAY_BUFFER);
int? jointsAccessorIndex = default;
if (m_joints != null)
{
jointsAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, m_joints.ToArray(), glBufferTarget.ARRAY_BUFFER);
jointsAccessorIndex = data.ExtendBufferAndGetAccessorIndex(m_joints.ToArray(), glBufferTarget.ARRAY_BUFFER);
}
int? weightAccessorIndex = default;
if (m_weights != null)
{
weightAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, m_weights.ToArray(), glBufferTarget.ARRAY_BUFFER);
weightAccessorIndex = data.ExtendBufferAndGetAccessorIndex(m_weights.ToArray(), glBufferTarget.ARRAY_BUFFER);
}
var primitive = new glTFPrimitives

View File

@@ -17,7 +17,7 @@ namespace UniGLTF
/// <param name="axisInverter"></param>
/// <param name="settings"></param>
/// <returns></returns>
public static (glTFMesh, Dictionary<int, int>) Export(glTF gltf, int gltfBuffer,
public static (glTFMesh, Dictionary<int, int>) Export(ExportingGltfData data,
MeshExportInfo unityMesh, List<Material> unityMaterials,
IAxisInverter axisInverter, GltfExportSettings settings)
{
@@ -84,7 +84,7 @@ namespace UniGLTF
flipped.Add(t1);
flipped.Add(t0);
}
var gltfPrimitive = buffer.ToGltfPrimitive(gltf, gltfBuffer, materialIndex, flipped);
var gltfPrimitive = buffer.ToGltfPrimitive(data, materialIndex, flipped);
// blendShape(morph target)
for (int j = 0; j < mesh.blendShapeCount; ++j)
@@ -101,7 +101,7 @@ namespace UniGLTF
axisInverter.InvertVector3(blendShapeNormals[k]));
}
gltfPrimitive.targets.Add(blendShape.ToGltf(gltf, gltfBuffer, !settings.ExportOnlyBlendShapePosition,
gltfPrimitive.targets.Add(blendShape.ToGltf(data, !settings.ExportOnlyBlendShapePosition,
settings.UseSparseAccessorForMorphTarget));
}

View File

@@ -24,27 +24,27 @@ namespace UniGLTF
/// <param name="axisInverter"></param>
/// <param name="settings"></param>
/// <returns></returns>
public static (glTFMesh, Dictionary<int, int> blendShapeIndexMap) Export(glTF gltf, int bufferIndex,
public static (glTFMesh, Dictionary<int, int> blendShapeIndexMap) Export(ExportingGltfData data,
MeshExportInfo unityMesh, List<Material> unityMaterials,
IAxisInverter axisInverter, GltfExportSettings settings)
{
var mesh = unityMesh.Mesh;
var materials = unityMesh.Materials;
var positions = mesh.vertices.Select(axisInverter.InvertVector3).ToArray();
var positionAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, positions, glBufferTarget.ARRAY_BUFFER);
gltf.accessors[positionAccessorIndex].min = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray();
gltf.accessors[positionAccessorIndex].max = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray();
var positionAccessorIndex = data.ExtendBufferAndGetAccessorIndex(positions, glBufferTarget.ARRAY_BUFFER);
data.GLTF.accessors[positionAccessorIndex].min = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Min(a.x, b.x), Math.Min(a.y, b.y), Mathf.Min(a.z, b.z))).ToArray();
data.GLTF.accessors[positionAccessorIndex].max = positions.Aggregate(positions[0], (a, b) => new Vector3(Mathf.Max(a.x, b.x), Math.Max(a.y, b.y), Mathf.Max(a.z, b.z))).ToArray();
var normalAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.normals.Select(y => axisInverter.InvertVector3(y.normalized)).ToArray(), glBufferTarget.ARRAY_BUFFER);
var normalAccessorIndex = data.ExtendBufferAndGetAccessorIndex(mesh.normals.Select(y => axisInverter.InvertVector3(y.normalized)).ToArray(), glBufferTarget.ARRAY_BUFFER);
int? tangentAccessorIndex = default;
if (settings.ExportTangents)
{
tangentAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.tangents.Select(axisInverter.InvertVector4).ToArray(), glBufferTarget.ARRAY_BUFFER);
tangentAccessorIndex = data.ExtendBufferAndGetAccessorIndex(mesh.tangents.Select(axisInverter.InvertVector4).ToArray(), glBufferTarget.ARRAY_BUFFER);
}
var uvAccessorIndex0 = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.uv.Select(y => y.ReverseUV()).ToArray(), glBufferTarget.ARRAY_BUFFER);
var uvAccessorIndex1 = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.uv2.Select(y => y.ReverseUV()).ToArray(), glBufferTarget.ARRAY_BUFFER);
var uvAccessorIndex0 = data.ExtendBufferAndGetAccessorIndex(mesh.uv.Select(y => y.ReverseUV()).ToArray(), glBufferTarget.ARRAY_BUFFER);
var uvAccessorIndex1 = data.ExtendBufferAndGetAccessorIndex(mesh.uv2.Select(y => y.ReverseUV()).ToArray(), glBufferTarget.ARRAY_BUFFER);
var colorAccessorIndex = -1;
@@ -54,12 +54,12 @@ namespace UniGLTF
)
{
// UniUnlit で Multiply 設定になっている
colorAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, mesh.colors, glBufferTarget.ARRAY_BUFFER);
colorAccessorIndex = data.ExtendBufferAndGetAccessorIndex(mesh.colors, glBufferTarget.ARRAY_BUFFER);
}
var boneweights = mesh.boneWeights;
var weightAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneweights.Select(y => new Vector4(y.weight0, y.weight1, y.weight2, y.weight3)).ToArray(), glBufferTarget.ARRAY_BUFFER);
var jointsAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, boneweights.Select(y =>
var weightAccessorIndex = data.ExtendBufferAndGetAccessorIndex(boneweights.Select(y => new Vector4(y.weight0, y.weight1, y.weight2, y.weight3)).ToArray(), glBufferTarget.ARRAY_BUFFER);
var jointsAccessorIndex = data.ExtendBufferAndGetAccessorIndex(boneweights.Select(y =>
new UShort4(
(ushort)unityMesh.GetJointIndex(y.boneIndex0),
(ushort)unityMesh.GetJointIndex(y.boneIndex1),
@@ -127,7 +127,7 @@ namespace UniGLTF
indices.Add((uint)i0);
}
var indicesAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, indices.ToArray(), glBufferTarget.ELEMENT_ARRAY_BUFFER);
var indicesAccessorIndex = data.ExtendBufferAndGetAccessorIndex(indices.ToArray(), glBufferTarget.ELEMENT_ARRAY_BUFFER);
if (indicesAccessorIndex < 0)
{
// https://github.com/vrm-c/UniVRM/issues/664
@@ -156,7 +156,7 @@ namespace UniGLTF
int exportBlendShapes = 0;
for (int j = 0; j < unityMesh.Mesh.blendShapeCount; ++j)
{
var morphTarget = ExportMorphTarget(gltf, bufferIndex,
var morphTarget = ExportMorphTarget(data,
unityMesh.Mesh, j,
settings.UseSparseAccessorForMorphTarget,
settings.ExportOnlyBlendShapePosition, axisInverter);
@@ -200,7 +200,7 @@ namespace UniGLTF
return useSparse;
}
static gltfMorphTarget ExportMorphTarget(glTF gltf, int bufferIndex,
static gltfMorphTarget ExportMorphTarget(ExportingGltfData data,
Mesh mesh, int blendShapeIndex,
bool useSparseAccessorForMorphTarget,
bool exportOnlyBlendShapePosition,
@@ -244,7 +244,7 @@ namespace UniGLTF
normals[i] = axisInverter.InvertVector3(normals[i]);
}
return BlendShapeExporter.Export(gltf, bufferIndex,
return BlendShapeExporter.Export(data,
blendShapeVertices,
exportOnlyBlendShapePosition && useNormal ? null : blendShapeNormals,
useSparseAccessorForMorphTarget);

View File

@@ -139,7 +139,7 @@ namespace UniGLTF
/// <param name="ctx"></param>
/// <param name="gltfMesh"></param>
/// <returns></returns>
public void ImportMeshIndependentVertexBuffer(glTF gltf, glTFMesh gltfMesh, IAxisInverter inverter)
public void ImportMeshIndependentVertexBuffer(GltfData data, glTFMesh gltfMesh, IAxisInverter inverter)
{
foreach (var prim in gltfMesh.primitives)
{
@@ -147,14 +147,14 @@ namespace UniGLTF
var indexBuffer = prim.indices;
// position は必ずある
var positions = gltf.GetArrayFromAccessor<Vector3>(prim.attributes.POSITION);
var positions = data.GetArrayFromAccessor<Vector3>(prim.attributes.POSITION);
m_positions.AddRange(positions.Select(inverter.InvertVector3));
var fillLength = m_positions.Count;
// normal
if (prim.attributes.NORMAL != -1)
{
var normals = gltf.GetArrayFromAccessor<Vector3>(prim.attributes.NORMAL);
var normals = data.GetArrayFromAccessor<Vector3>(prim.attributes.NORMAL);
if (normals.Length != positions.Length)
{
throw new Exception("different length");
@@ -166,12 +166,12 @@ namespace UniGLTF
// uv
if (prim.attributes.TEXCOORD_0 != -1)
{
var uvs = gltf.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_0);
var uvs = data.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_0);
if (uvs.Length != positions.Length)
{
throw new Exception("different length");
}
if (gltf.IsGeneratedUniGLTFAndOlder(1, 16))
if (data.GLTF.IsGeneratedUniGLTFAndOlder(1, 16))
{
#pragma warning disable 0612
// backward compatibility
@@ -189,7 +189,7 @@ namespace UniGLTF
// uv2
if (prim.attributes.TEXCOORD_1 != -1)
{
var uvs = gltf.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_1);
var uvs = data.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_1);
if (uvs.Length != positions.Length)
{
throw new Exception("different length");
@@ -201,7 +201,7 @@ namespace UniGLTF
// color
if (prim.attributes.COLOR_0 != -1)
{
var colors = gltf.GetArrayFromAccessor<Color>(prim.attributes.COLOR_0);
var colors = data.GetArrayFromAccessor<Color>(prim.attributes.COLOR_0);
if (colors.Length != positions.Length)
{
throw new Exception("different length");
@@ -213,8 +213,8 @@ namespace UniGLTF
// skin
if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1)
{
var (joints0, jointsLength) = JointsAccessor.GetAccessor(gltf, prim.attributes.JOINTS_0);
var (weights0, weightsLength) = WeightsAccessor.GetAccessor(gltf, prim.attributes.WEIGHTS_0);
var (joints0, jointsLength) = JointsAccessor.GetAccessor(data, prim.attributes.JOINTS_0);
var (weights0, weightsLength) = WeightsAccessor.GetAccessor(data, prim.attributes.WEIGHTS_0);
if (jointsLength != positions.Length)
{
throw new Exception("different length");
@@ -258,7 +258,7 @@ namespace UniGLTF
var blendShape = GetOrCreateBlendShape(i);
if (primTarget.POSITION != -1)
{
var array = gltf.GetArrayFromAccessor<Vector3>(primTarget.POSITION);
var array = data.GetArrayFromAccessor<Vector3>(primTarget.POSITION);
if (array.Length != positions.Length)
{
throw new Exception("different length");
@@ -268,7 +268,7 @@ namespace UniGLTF
}
if (primTarget.NORMAL != -1)
{
var array = gltf.GetArrayFromAccessor<Vector3>(primTarget.NORMAL);
var array = data.GetArrayFromAccessor<Vector3>(primTarget.NORMAL);
if (array.Length != positions.Length)
{
throw new Exception("different length");
@@ -278,7 +278,7 @@ namespace UniGLTF
}
if (primTarget.TANGENT != -1)
{
var array = gltf.GetArrayFromAccessor<Vector3>(primTarget.TANGENT);
var array = data.GetArrayFromAccessor<Vector3>(primTarget.TANGENT);
if (array.Length != positions.Length)
{
throw new Exception("different length");
@@ -291,7 +291,7 @@ namespace UniGLTF
var indices =
(indexBuffer >= 0)
? gltf.GetIndices(indexBuffer)
? data.GetIndices(indexBuffer)
: TriangleUtil.FlipTriangle(Enumerable.Range(0, m_positions.Count)).ToArray() // without index array
;
for (int i = 0; i < indices.Length; ++i)
@@ -314,17 +314,17 @@ namespace UniGLTF
/// <param name="ctx"></param>
/// <param name="gltfMesh"></param>
/// <returns></returns>
public void ImportMeshSharingVertexBuffer(glTF gltf, glTFMesh gltfMesh, IAxisInverter inverter)
public void ImportMeshSharingVertexBuffer(GltfData data, glTFMesh gltfMesh, IAxisInverter inverter)
{
{
// 同じVertexBufferを共有しているので先頭のモを使う
var prim = gltfMesh.primitives.First();
m_positions.AddRange(gltf.GetArrayFromAccessor<Vector3>(prim.attributes.POSITION).SelectInplace(inverter.InvertVector3));
m_positions.AddRange(data.GetArrayFromAccessor<Vector3>(prim.attributes.POSITION).SelectInplace(inverter.InvertVector3));
// normal
if (prim.attributes.NORMAL != -1)
{
m_normals.AddRange(gltf.GetArrayFromAccessor<Vector3>(prim.attributes.NORMAL).SelectInplace(inverter.InvertVector3));
m_normals.AddRange(data.GetArrayFromAccessor<Vector3>(prim.attributes.NORMAL).SelectInplace(inverter.InvertVector3));
}
#if false
@@ -338,31 +338,31 @@ namespace UniGLTF
// uv
if (prim.attributes.TEXCOORD_0 != -1)
{
if (gltf.IsGeneratedUniGLTFAndOlder(1, 16))
if (data.GLTF.IsGeneratedUniGLTFAndOlder(1, 16))
{
#pragma warning disable 0612
// backward compatibility
m_uv.AddRange(gltf.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseY()));
m_uv.AddRange(data.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseY()));
#pragma warning restore 0612
}
else
{
m_uv.AddRange(gltf.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseUV()));
m_uv.AddRange(data.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_0).SelectInplace(x => x.ReverseUV()));
}
}
// uv2
if (prim.attributes.TEXCOORD_1 != -1)
{
m_uv2.AddRange(gltf.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_1).SelectInplace(x => x.ReverseUV()));
m_uv2.AddRange(data.GetArrayFromAccessor<Vector2>(prim.attributes.TEXCOORD_1).SelectInplace(x => x.ReverseUV()));
}
// color
if (prim.attributes.COLOR_0 != -1)
{
if (gltf.accessors[prim.attributes.COLOR_0].TypeCount == 3)
if (data.GLTF.accessors[prim.attributes.COLOR_0].TypeCount == 3)
{
var vec3Color = gltf.GetArrayFromAccessor<Vector3>(prim.attributes.COLOR_0);
var vec3Color = data.GetArrayFromAccessor<Vector3>(prim.attributes.COLOR_0);
m_colors.AddRange(new Color[vec3Color.Length]);
for (int i = 0; i < vec3Color.Length; i++)
@@ -371,21 +371,21 @@ namespace UniGLTF
m_colors[i] = new Color(color.x, color.y, color.z);
}
}
else if (gltf.accessors[prim.attributes.COLOR_0].TypeCount == 4)
else if (data.GLTF.accessors[prim.attributes.COLOR_0].TypeCount == 4)
{
m_colors.AddRange(gltf.GetArrayFromAccessor<Color>(prim.attributes.COLOR_0));
m_colors.AddRange(data.GetArrayFromAccessor<Color>(prim.attributes.COLOR_0));
}
else
{
throw new NotImplementedException(string.Format("unknown color type {0}", gltf.accessors[prim.attributes.COLOR_0].type));
throw new NotImplementedException(string.Format("unknown color type {0}", data.GLTF.accessors[prim.attributes.COLOR_0].type));
}
}
// skin
if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1)
{
var (joints0, jointsLength) = JointsAccessor.GetAccessor(gltf, prim.attributes.JOINTS_0);
var (weights0, weightsLength) = WeightsAccessor.GetAccessor(gltf, prim.attributes.WEIGHTS_0);
var (joints0, jointsLength) = JointsAccessor.GetAccessor(data, prim.attributes.JOINTS_0);
var (weights0, weightsLength) = WeightsAccessor.GetAccessor(data, prim.attributes.WEIGHTS_0);
for (int j = 0; j < jointsLength; ++j)
{
@@ -425,17 +425,17 @@ namespace UniGLTF
if (primTarget.POSITION != -1)
{
blendShape.Positions.Assign(
gltf.GetArrayFromAccessor<Vector3>(primTarget.POSITION), inverter.InvertVector3);
data.GetArrayFromAccessor<Vector3>(primTarget.POSITION), inverter.InvertVector3);
}
if (primTarget.NORMAL != -1)
{
blendShape.Normals.Assign(
gltf.GetArrayFromAccessor<Vector3>(primTarget.NORMAL), inverter.InvertVector3);
data.GetArrayFromAccessor<Vector3>(primTarget.NORMAL), inverter.InvertVector3);
}
if (primTarget.TANGENT != -1)
{
blendShape.Tangents.Assign(
gltf.GetArrayFromAccessor<Vector3>(primTarget.TANGENT), inverter.InvertVector3);
data.GetArrayFromAccessor<Vector3>(primTarget.TANGENT), inverter.InvertVector3);
}
}
}
@@ -449,7 +449,7 @@ namespace UniGLTF
}
else
{
var indices = gltf.GetIndices(prim.indices);
var indices = data.GetIndices(prim.indices);
m_subMeshes.Add(indices);
}
@@ -531,18 +531,18 @@ namespace UniGLTF
return sharedAttributes;
}
public MeshContext ReadMesh(glTF gltf, int meshIndex, IAxisInverter inverter)
public MeshContext ReadMesh(GltfData data, int meshIndex, IAxisInverter inverter)
{
var gltfMesh = gltf.meshes[meshIndex];
var gltfMesh = data.GLTF.meshes[meshIndex];
var meshContext = new MeshContext(gltfMesh.name, meshIndex);
if (HasSharedVertexBuffer(gltfMesh))
{
meshContext.ImportMeshSharingVertexBuffer(gltf, gltfMesh, inverter);
meshContext.ImportMeshSharingVertexBuffer(data, gltfMesh, inverter);
}
else
{
meshContext.ImportMeshIndependentVertexBuffer(gltf, gltfMesh, inverter);
meshContext.ImportMeshIndependentVertexBuffer(data, gltfMesh, inverter);
}
meshContext.RenameBlendShape(gltfMesh);

View File

@@ -10,14 +10,14 @@ namespace UniGLTF
/// </summary>
public delegate (float x, float y, float z, float w) Getter(int index);
public static (Getter, int) GetAccessor(glTF gltf, int accessorIndex)
public static (Getter, int) GetAccessor(GltfData data, int accessorIndex)
{
var gltfAccessor = gltf.accessors[accessorIndex];
var gltfAccessor = data.GLTF.accessors[accessorIndex];
switch (gltfAccessor.componentType)
{
case glComponentType.UNSIGNED_BYTE:
{
var array = gltf.GetArrayFromAccessor<Byte4>(accessorIndex);
var array = data.GetArrayFromAccessor<Byte4>(accessorIndex);
Getter getter = (i) =>
{
var value = array[i];
@@ -29,7 +29,7 @@ namespace UniGLTF
case glComponentType.UNSIGNED_SHORT:
{
var array = gltf.GetArrayFromAccessor<UShort4>(accessorIndex);
var array = data.GetArrayFromAccessor<UShort4>(accessorIndex);
Getter getter = (i) =>
{
var value = array[i];
@@ -41,7 +41,7 @@ namespace UniGLTF
case glComponentType.FLOAT:
{
var array = gltf.GetArrayFromAccessor<Vector4>(accessorIndex);
var array = data.GetArrayFromAccessor<Vector4>(accessorIndex);
Getter getter = (i) =>
{
var value = array[i];

View File

@@ -156,7 +156,7 @@ namespace UniGLTF
}
}
public static void SetupSkinning(glTF gltf, List<TransformWithSkin> nodes, int i, IAxisInverter inverter)
public static void SetupSkinning(GltfData data, List<TransformWithSkin> nodes, int i, IAxisInverter inverter)
{
var x = nodes[i];
var skinnedMeshRenderer = x.Transform.GetComponent<SkinnedMeshRenderer>();
@@ -168,12 +168,12 @@ namespace UniGLTF
if (mesh == null) throw new Exception();
if (skinnedMeshRenderer == null) throw new Exception();
if (x.SkinIndex.Value < gltf.skins.Count)
if (x.SkinIndex.Value < data.GLTF.skins.Count)
{
// calculate internal values(boundingBox etc...) when sharedMesh assigned ?
skinnedMeshRenderer.sharedMesh = null;
var skin = gltf.skins[x.SkinIndex.Value];
var skin = data.GLTF.skins[x.SkinIndex.Value];
var joints = skin.joints.Select(y => nodes[y].Transform).ToArray();
if (joints.Any())
{
@@ -182,7 +182,7 @@ namespace UniGLTF
if (skin.inverseBindMatrices != -1)
{
var bindPoses = gltf.GetArrayFromAccessor<Matrix4x4>(skin.inverseBindMatrices)
var bindPoses = data.GetArrayFromAccessor<Matrix4x4>(skin.inverseBindMatrices)
.Select(inverter.InvertMat4)
.ToArray()
;

View File

@@ -11,7 +11,7 @@ namespace UniGLTF
{
private readonly string _json;
private readonly IStorage _storage;
public JsonWithStorageParser(string json, IStorage storage = null)
{
_json = json;

View File

@@ -22,17 +22,16 @@ namespace UniGLTF
/// <param name="bufferIndex"></param>
/// <param name="texture"></param>
/// <returns>gltf texture index</returns>
public static int PushGltfTexture(this glTF gltf, int bufferIndex, Texture2D texture, ColorSpace textureColorSpace, ITextureSerializer textureSerializer)
public static int PushGltfTexture(ExportingGltfData data, Texture2D texture, ColorSpace textureColorSpace, ITextureSerializer textureSerializer)
{
var bytesWithMime = textureSerializer.ExportBytesWithMime(texture, textureColorSpace);
// add view
var view = gltf.buffers[bufferIndex].Append(bytesWithMime.bytes, glBufferTarget.NONE);
var viewIndex = gltf.AddBufferView(view);
var viewIndex = data.ExtendBufferAndGetViewIndex(bytesWithMime.bytes);
// add image
var imageIndex = gltf.images.Count;
gltf.images.Add(new glTFImage
var imageIndex = data.GLTF.images.Count;
data.GLTF.images.Add(new glTFImage
{
name = TextureImportName.RemoveSuffix(texture.name),
bufferView = viewIndex,
@@ -40,13 +39,13 @@ namespace UniGLTF
});
// add sampler
var samplerIndex = gltf.samplers.Count;
var samplerIndex = data.GLTF.samplers.Count;
var sampler = TextureSamplerUtil.Export(texture);
gltf.samplers.Add(sampler);
data.GLTF.samplers.Add(sampler);
// add texture
var textureIndex = gltf.textures.Count;
gltf.textures.Add(new glTFTexture
var textureIndex = data.GLTF.textures.Count;
data.GLTF.textures.Add(new glTFTexture
{
sampler = samplerIndex,
source = imageIndex,

View File

@@ -35,7 +35,7 @@ namespace UniGLTF
var gltfImage = data.GLTF.images[gltfTexture.source];
var name = TextureImportName.GetUnityObjectName(TextureImportTypes.sRGB, gltfTexture.name, gltfImage.uri);
var sampler = TextureSamplerUtil.CreateSampler(data.GLTF, textureIndex);
GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(data.GLTF.GetImageBytesFromTextureIndex(data.Storage, textureIndex)));
GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(data.GetImageBytesFromTextureIndex(textureIndex)));
var param = new TextureDescriptor(name, gltfImage.GetExt(), gltfImage.uri, offset, scale, sampler, TextureImportTypes.sRGB, default, default, getTextureBytesAsync, default, default, default, default, default);
return (param.SubAssetKey, param);
}
@@ -46,7 +46,7 @@ namespace UniGLTF
var gltfImage = data.GLTF.images[gltfTexture.source];
var name = TextureImportName.GetUnityObjectName(TextureImportTypes.Linear, gltfTexture.name, gltfImage.uri);
var sampler = TextureSamplerUtil.CreateSampler(data.GLTF, textureIndex);
GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(data.GLTF.GetImageBytesFromTextureIndex(data.Storage, textureIndex)));
GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(data.GetImageBytesFromTextureIndex(textureIndex)));
var param = new TextureDescriptor(name, gltfImage.GetExt(), gltfImage.uri, offset, scale, sampler, TextureImportTypes.Linear, default, default, getTextureBytesAsync, default, default, default, default, default);
return (param.SubAssetKey, param);
}
@@ -57,7 +57,7 @@ namespace UniGLTF
var gltfImage = data.GLTF.images[gltfTexture.source];
var name = TextureImportName.GetUnityObjectName(TextureImportTypes.NormalMap, gltfTexture.name, gltfImage.uri);
var sampler = TextureSamplerUtil.CreateSampler(data.GLTF, textureIndex);
GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(data.GLTF.GetImageBytesFromTextureIndex(data.Storage, textureIndex)));
GetTextureBytesAsync getTextureBytesAsync = () => Task.FromResult(ToArray(data.GetImageBytesFromTextureIndex(textureIndex)));
var param = new TextureDescriptor(name, gltfImage.GetExt(), gltfImage.uri, offset, scale, sampler, TextureImportTypes.NormalMap, default, default, getTextureBytesAsync, default, default, default, default, default);
return (param.SubAssetKey, param);
}
@@ -73,7 +73,7 @@ namespace UniGLTF
var gltfTexture = data.GLTF.textures[metallicRoughnessTextureIndex.Value];
name = TextureImportName.GetUnityObjectName(TextureImportTypes.StandardMap, gltfTexture.name, data.GLTF.images[gltfTexture.source].uri);
sampler = TextureSamplerUtil.CreateSampler(data.GLTF, metallicRoughnessTextureIndex.Value);
getMetallicRoughnessAsync = () => Task.FromResult(ToArray(data.GLTF.GetImageBytesFromTextureIndex(data.Storage, metallicRoughnessTextureIndex.Value)));
getMetallicRoughnessAsync = () => Task.FromResult(ToArray(data.GetImageBytesFromTextureIndex(metallicRoughnessTextureIndex.Value)));
}
GetTextureBytesAsync getOcclusionAsync = default;
@@ -85,7 +85,7 @@ namespace UniGLTF
name = TextureImportName.GetUnityObjectName(TextureImportTypes.StandardMap, gltfTexture.name, data.GLTF.images[gltfTexture.source].uri);
}
sampler = TextureSamplerUtil.CreateSampler(data.GLTF, occlusionTextureIndex.Value);
getOcclusionAsync = () => Task.FromResult(ToArray(data.GLTF.GetImageBytesFromTextureIndex(data.Storage, occlusionTextureIndex.Value)));
getOcclusionAsync = () => Task.FromResult(ToArray(data.GetImageBytesFromTextureIndex(occlusionTextureIndex.Value)));
}
var texDesc = new TextureDescriptor(name, ".png", null, offset, scale, sampler, TextureImportTypes.StandardMap, metallicFactor, roughnessFactor, getMetallicRoughnessAsync, getOcclusionAsync, default, default, default, default);

View File

@@ -0,0 +1,27 @@
using System;
using System.Runtime.InteropServices;
namespace UniGLTF
{
[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
public readonly struct UShort4 : IEquatable<UShort4>
{
public readonly ushort x;
public readonly ushort y;
public readonly ushort z;
public readonly ushort w;
public UShort4(ushort _x, ushort _y, ushort _z, ushort _w)
{
x = _x;
y = _y;
z = _z;
w = _w;
}
public bool Equals(UShort4 other)
{
return x == other.x && y == other.y && z == other.z && w == other.w;
}
}
}

View File

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

View File

@@ -292,6 +292,9 @@ namespace UniGLTF.Zip
}
}
/// <summary>
/// Implement url that reference zip archive
/// </summary>
class ZipArchiveStorage : IStorage
{
public override string ToString()
@@ -378,10 +381,5 @@ namespace UniGLTF.Zip
throw new NotImplementedException(found.CompressionMethod.ToString());
}
public string GetPath(string url)
{
return null;
}
}
}

View File

@@ -10,7 +10,9 @@ namespace UniGLTF
{
public class gltfExporter : IDisposable
{
protected glTF glTF;
protected ExportingGltfData _data;
protected glTF _gltf => _data.GLTF;
public GameObject Copy
{
@@ -67,13 +69,13 @@ namespace UniGLTF
GltfExportSettings m_settings;
public gltfExporter(glTF gltf, GltfExportSettings settings)
public gltfExporter(ExportingGltfData data, GltfExportSettings settings)
{
glTF = gltf;
_data = data;
glTF.extensionsUsed.AddRange(ExtensionUsed);
_gltf.extensionsUsed.AddRange(ExtensionUsed);
glTF.asset = new glTFAssets
_gltf.asset = new glTFAssets
{
generator = "UniGLTF-" + UniGLTFVersion.VERSION,
version = "2.0",
@@ -224,9 +226,6 @@ namespace UniGLTF
public virtual void Export(ITextureSerializer textureSerializer)
{
var bytesBuffer = new ArrayByteBuffer(new byte[50 * 1024 * 1024]);
var bufferIndex = glTF.AddBuffer(bytesBuffer);
Nodes = Copy.transform.Traverse()
.Skip(1) // exclude root object for the symmetry with the importer
.ToList();
@@ -240,7 +239,7 @@ namespace UniGLTF
m_textureExporter = new TextureExporter(textureSerializer);
var materialExporter = CreateMaterialExporter();
glTF.materials = Materials.Select(x => materialExporter.ExportMaterial(x, TextureExporter, m_settings)).ToList();
_gltf.materials = Materials.Select(x => materialExporter.ExportMaterial(x, TextureExporter, m_settings)).ToList();
#endregion
#region Meshes
@@ -253,10 +252,10 @@ namespace UniGLTF
}
var (gltfMesh, blendShapeIndexMap) = m_settings.DivideVertexBuffer
? MeshExporter_DividedVertexBuffer.Export(glTF, bufferIndex, unityMesh, Materials, m_settings.InverseAxis.Create(), m_settings)
: MeshExporter_SharedVertexBuffer.Export(glTF, bufferIndex, unityMesh, Materials, m_settings.InverseAxis.Create(), m_settings)
? MeshExporter_DividedVertexBuffer.Export(_data, unityMesh, Materials, m_settings.InverseAxis.Create(), m_settings)
: MeshExporter_SharedVertexBuffer.Export(_data, unityMesh, Materials, m_settings.InverseAxis.Create(), m_settings)
;
glTF.meshes.Add(gltfMesh);
_gltf.meshes.Add(gltfMesh);
Meshes.Add(unityMesh.Mesh);
if (!MeshBlendShapeIndexMap.ContainsKey(unityMesh.Mesh))
{
@@ -276,9 +275,9 @@ namespace UniGLTF
foreach (var node in Nodes)
{
var gltfNode = ExportNode(node, Nodes, uniqueUnityMeshes, skins);
glTF.nodes.Add(gltfNode);
_gltf.nodes.Add(gltfNode);
}
glTF.scenes = new List<gltfScene>
_gltf.scenes = new List<gltfScene>
{
new gltfScene
{
@@ -293,20 +292,20 @@ namespace UniGLTF
if (uniqueBones != null && renderer is SkinnedMeshRenderer smr)
{
var matrices = x.GetBindPoses().Select(m_settings.InverseAxis.Create().InvertMat4).ToArray();
var accessor = glTF.ExtendBufferAndGetAccessorIndex(bufferIndex, matrices, glBufferTarget.NONE);
var accessor = _data.ExtendBufferAndGetAccessorIndex(matrices, glBufferTarget.NONE);
var skin = new glTFSkin
{
inverseBindMatrices = accessor,
joints = uniqueBones.Select(y => Nodes.IndexOf(y)).ToArray(),
skeleton = Nodes.IndexOf(smr.rootBone),
};
var skinIndex = glTF.skins.Count;
glTF.skins.Add(skin);
var skinIndex = _gltf.skins.Count;
_gltf.skins.Add(skin);
foreach (var z in Nodes.Where(y => y.Has(renderer)))
{
var nodeIndex = Nodes.IndexOf(z);
var node = glTF.nodes[nodeIndex];
var node = _gltf.nodes[nodeIndex];
node.skin = skinIndex;
}
}
@@ -339,14 +338,14 @@ namespace UniGLTF
{
var sampler = animationWithCurve.Animation.samplers[kv.Key];
var inputAccessorIndex = glTF.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Input);
var inputAccessorIndex = _data.ExtendBufferAndGetAccessorIndex(kv.Value.Input);
sampler.input = inputAccessorIndex;
var outputAccessorIndex = glTF.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Output);
var outputAccessorIndex = _data.ExtendBufferAndGetAccessorIndex(kv.Value.Output);
sampler.output = outputAccessorIndex;
// modify accessors
var outputAccessor = glTF.accessors[outputAccessorIndex];
var outputAccessor = _gltf.accessors[outputAccessorIndex];
var channel = animationWithCurve.Animation.channels.First(x => x.sampler == kv.Key);
switch (glTFAnimationTarget.GetElementCount(channel.target.path))
{
@@ -369,8 +368,9 @@ namespace UniGLTF
}
}
animationWithCurve.Animation.name = clip.name;
glTF.animations.Add(animationWithCurve.Animation);
_gltf.animations.Add(animationWithCurve.Animation);
}
}
#endregion
#endif
@@ -382,10 +382,10 @@ namespace UniGLTF
for (var exportedTextureIdx = 0; exportedTextureIdx < exported.Count; ++exportedTextureIdx)
{
var (unityTexture, colorSpace) = exported[exportedTextureIdx];
glTF.PushGltfTexture(bufferIndex, unityTexture, colorSpace, textureSerializer);
GltfTextureExporter.PushGltfTexture(_data, unityTexture, colorSpace, textureSerializer);
}
FixName(glTF);
FixName(_gltf);
}
/// <summary>

View File

@@ -122,8 +122,8 @@ namespace UniGLTF
root.GetComponent<MeshRenderer>().sharedMaterial = mat;
// Export glTF
var gltf = new glTF();
using (var exporter = new gltfExporter(gltf, new GltfExportSettings
var data = new ExportingGltfData();
using (var exporter = new gltfExporter(data, new GltfExportSettings
{
InverseAxis = Axes.X,
ExportOnlyBlendShapePosition = false,
@@ -134,6 +134,7 @@ namespace UniGLTF
exporter.Prepare(root);
exporter.Export(new EditorTextureSerializer());
}
var gltf = data.GLTF;
Assert.AreEqual(1, gltf.images.Count);
var exportedImage = gltf.images[0];
Assert.AreEqual("image/png", exportedImage.mimeType);
@@ -142,8 +143,10 @@ namespace UniGLTF
UnityEngine.Object.DestroyImmediate(mat);
UnityEngine.Object.DestroyImmediate(root);
var parsed = GltfData.CreateFromGltfDataForTest(gltf);
// Extract Image to Texture2D
var exportedBytes = gltf.GetViewBytes(exportedImage.bufferView).ToArray();
var exportedBytes = parsed.GetViewBytes(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);

View File

@@ -8,34 +8,35 @@ namespace UniGLTF
[Test]
public void TextureNameUniqueness()
{
var gltfData = new glTF();
gltfData.asset.version = "2.0";
gltfData.buffers.Add(new glTFBuffer(new ArrayByteBuffer(Array.Empty<byte>())));
gltfData.textures.Add(new glTFTexture
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",
source = 0,
});
gltfData.textures.Add(new glTFTexture
gltf.textures.Add(new glTFTexture
{
name = "foobar",
source = 1,
});
gltfData.images.Add(new glTFImage
gltf.images.Add(new glTFImage
{
name = "HogeFuga",
});
gltfData.images.Add(new glTFImage
gltf.images.Add(new glTFImage
{
name = "hogefuga",
});
var parser = new GlbLowLevelParser("Test", gltfData.ToGlbBytes());
var data = parser.Parse();
var parser = new GlbLowLevelParser("Test", data.ToGlbBytes());
var parsed = parser.Parse();
Assert.AreEqual("FooBar", data.GLTF.textures[0].name);
Assert.AreEqual("FooBar", parsed.GLTF.textures[0].name);
// NOTE: 大文字小文字が違うだけの名前は、同一としてみなされ、Suffix が付く。
Assert.AreEqual("foobar__UNIGLTF__DUPLICATED__2", data.GLTF.textures[1].name);
Assert.AreEqual("foobar__UNIGLTF__DUPLICATED__2", parsed.GLTF.textures[1].name);
}
}
}

View File

@@ -57,13 +57,13 @@ namespace UniGLTF
static Byte[] Export(GameObject root)
{
var gltf = new glTF();
using (var exporter = new gltfExporter(gltf, new GltfExportSettings()))
var data = new ExportingGltfData();
using (var exporter = new gltfExporter(data, new GltfExportSettings()))
{
exporter.Prepare(root);
exporter.Export(new EditorTextureSerializer());
return gltf.ToGlbBytes();
}
return data.ToGlbBytes();
}
// Unsolved Animation Export issue

View File

@@ -25,7 +25,6 @@ namespace UniGLTF
w.Write(8.0f);
bytes = ms.ToArray();
}
var storage = new SimpleStorage(new ArraySegment<byte>(bytes));
var gltf = new glTF
{
@@ -54,9 +53,9 @@ namespace UniGLTF
}
}
};
gltf.buffers[0].OpenStorage(storage);
var (getter, len) = WeightsAccessor.GetAccessor(gltf, 0);
var data = GltfData.CreateFromGltfDataForTest(gltf, new ArraySegment<byte>(bytes));
var (getter, len) = WeightsAccessor.GetAccessor(data, 0);
Assert.AreEqual((1.0f, 2.0f, 3.0f, 4.0f), getter(0));
Assert.AreEqual((5.0f, 6.0f, 7.0f, 8.0f), getter(1));
}
@@ -118,9 +117,7 @@ namespace UniGLTF
[Test]
public void SharedVertexBufferTest()
{
var glTF = new glTF();
var bytesBuffer = new ArrayByteBuffer(new byte[50 * 1024 * 1024]);
var bufferIndex = glTF.AddBuffer(bytesBuffer);
var data = new ExportingGltfData(50 * 1024 * 1024);
var Materials = new List<Material>{
new Material(Shader.Find("Standard")), // A
@@ -136,12 +133,14 @@ namespace UniGLTF
var unityMesh = MeshExportList.Create(go);
var (gltfMesh, blendShapeIndexMap) = meshExportSettings.DivideVertexBuffer
? MeshExporter_DividedVertexBuffer.Export(glTF, bufferIndex, unityMesh, Materials, axisInverter, meshExportSettings)
: MeshExporter_SharedVertexBuffer.Export(glTF, bufferIndex, unityMesh, Materials,axisInverter, meshExportSettings)
? MeshExporter_DividedVertexBuffer.Export(data, unityMesh, Materials, axisInverter, meshExportSettings)
: MeshExporter_SharedVertexBuffer.Export(data, unityMesh, Materials, axisInverter, meshExportSettings)
;
var parsed = GltfData.CreateFromGltfDataForTest(data.GLTF);
{
var indices = glTF.GetIndices(gltfMesh.primitives[0].indices);
var indices = parsed.GetIndices(gltfMesh.primitives[0].indices);
Assert.AreEqual(0, indices[0]);
Assert.AreEqual(1, indices[1]);
Assert.AreEqual(5, indices[2]);
@@ -149,8 +148,9 @@ namespace UniGLTF
Assert.AreEqual(1, indices[4]);
Assert.AreEqual(4, indices[5]);
}
{
var indices = glTF.GetIndices(gltfMesh.primitives[1].indices);
var indices = parsed.GetIndices(gltfMesh.primitives[1].indices);
Assert.AreEqual(1, indices[0]);
Assert.AreEqual(2, indices[1]);
Assert.AreEqual(4, indices[2]);
@@ -159,16 +159,14 @@ namespace UniGLTF
Assert.AreEqual(3, indices[5]);
}
var positions = glTF.GetArrayFromAccessor<Vector3>(gltfMesh.primitives[0].attributes.POSITION);
var positions = parsed.GetArrayFromAccessor<Vector3>(gltfMesh.primitives[0].attributes.POSITION);
Assert.AreEqual(6, positions.Length);
}
[Test]
public void DividedVertexBufferTest()
{
var glTF = new glTF();
var bytesBuffer = new ArrayByteBuffer(new byte[50 * 1024 * 1024]);
var bufferIndex = glTF.AddBuffer(bytesBuffer);
var data = new ExportingGltfData(50 * 1024 * 1024);
var Materials = new List<Material>{
new Material(Shader.Find("Standard")), // A
@@ -184,12 +182,13 @@ namespace UniGLTF
var unityMesh = MeshExportList.Create(go);
var (gltfMesh, blendShapeIndexMap) = meshExportSettings.DivideVertexBuffer
? MeshExporter_DividedVertexBuffer.Export(glTF, bufferIndex, unityMesh, Materials, axisInverter, meshExportSettings)
: MeshExporter_SharedVertexBuffer.Export(glTF, bufferIndex, unityMesh, Materials,axisInverter, meshExportSettings)
? MeshExporter_DividedVertexBuffer.Export(data, unityMesh, Materials, axisInverter, meshExportSettings)
: MeshExporter_SharedVertexBuffer.Export(data, unityMesh, Materials, axisInverter, meshExportSettings)
;
var parsed = GltfData.CreateFromGltfDataForTest(data.GLTF);
{
var indices = glTF.GetIndices(gltfMesh.primitives[0].indices);
var indices = parsed.GetIndices(gltfMesh.primitives[0].indices);
Assert.AreEqual(0, indices[0]);
Assert.AreEqual(1, indices[1]);
Assert.AreEqual(3, indices[2]);
@@ -198,12 +197,12 @@ namespace UniGLTF
Assert.AreEqual(2, indices[5]);
}
{
var positions = glTF.GetArrayFromAccessor<Vector3>(gltfMesh.primitives[0].attributes.POSITION);
var positions = parsed.GetArrayFromAccessor<Vector3>(gltfMesh.primitives[0].attributes.POSITION);
Assert.AreEqual(4, positions.Length);
}
{
var indices = glTF.GetIndices(gltfMesh.primitives[1].indices);
var indices = parsed.GetIndices(gltfMesh.primitives[1].indices);
Assert.AreEqual(0, indices[0]);
Assert.AreEqual(1, indices[1]);
Assert.AreEqual(3, indices[2]);
@@ -212,7 +211,7 @@ namespace UniGLTF
Assert.AreEqual(2, indices[5]);
}
{
var positions = glTF.GetArrayFromAccessor<Vector3>(gltfMesh.primitives[1].attributes.POSITION);
var positions = parsed.GetArrayFromAccessor<Vector3>(gltfMesh.primitives[1].attributes.POSITION);
Assert.AreEqual(4, positions.Length);
}
}

View File

@@ -100,25 +100,25 @@ namespace UniGLTF
var go = CreateSimpleScene();
// export
var gltf = new glTF();
var data = new ExportingGltfData();
string json = null;
using (var exporter = new gltfExporter(gltf, new GltfExportSettings()))
using (var exporter = new gltfExporter(data, new GltfExportSettings()))
{
exporter.Prepare(go);
exporter.Export(new EditorTextureSerializer());
// remove empty buffer
gltf.buffers.Clear();
data.GLTF.buffers.Clear();
json = gltf.ToJson();
json = data.GLTF.ToJson();
}
// parse
var data = new JsonWithStorageParser(json).Parse();
var parsed = new JsonWithStorageParser(json).Parse();
// import
using (var context = new ImporterContext(data))
using (var context = new ImporterContext(parsed))
using (var loaded = context.Load())
{
AssertAreEqual(go.transform, loaded.transform);
@@ -293,14 +293,14 @@ namespace UniGLTF
[Test]
public void GlTFToJsonTest()
{
var gltf = new glTF();
using (var exporter = new gltfExporter(gltf, new GltfExportSettings()))
var data = new ExportingGltfData();
using (var exporter = new gltfExporter(data, new GltfExportSettings()))
{
exporter.Prepare(CreateSimpleScene());
exporter.Export(new EditorTextureSerializer());
}
var expected = gltf.ToJson().ParseAsJson();
var expected = data.GLTF.ToJson().ParseAsJson();
expected.AddKey(Utf8String.From("meshes"));
expected.AddValue(default(ArraySegment<byte>), ValueNodeType.Array);
expected["meshes"].AddValue(default(ArraySegment<byte>), ValueNodeType.Object);
@@ -334,7 +334,7 @@ namespace UniGLTF
primitive["targets"][1].AddKey(Utf8String.From("TANGENT"));
primitive["targets"][1].AddValue(Utf8String.From("0").Bytes, ValueNodeType.Integer);
gltf.meshes.Add(new glTFMesh("test")
data.GLTF.meshes.Add(new glTFMesh("test")
{
primitives = new List<glTFPrimitives>
{
@@ -362,7 +362,7 @@ namespace UniGLTF
}
}
});
var actual = gltf.ToJson().ParseAsJson();
var actual = data.GLTF.ToJson().ParseAsJson();
Assert.AreEqual(expected, actual);
}
@@ -528,9 +528,10 @@ namespace UniGLTF
}
// export
var gltf = new glTF();
var data = new ExportingGltfData();
var gltf = data.GLTF;
var json = default(string);
using (var exporter = new gltfExporter(gltf, new GltfExportSettings()))
using (var exporter = new gltfExporter(data, new GltfExportSettings()))
{
exporter.Prepare(go);
exporter.Export(new EditorTextureSerializer());
@@ -553,9 +554,9 @@ namespace UniGLTF
// import
{
var storage = new SimpleStorage(new ArraySegment<byte>(new byte[1024 * 1024]));
var data = new JsonWithStorageParser(json, storage).Parse();
var parsed = new JsonWithStorageParser(json, storage).Parse();
using (var context = new ImporterContext(data))
using (var context = new ImporterContext(parsed))
using (var loaded = context.Load())
{
var importedRed = loaded.transform.GetChild(0);
@@ -573,10 +574,10 @@ namespace UniGLTF
// import new version
{
var storage = new SimpleStorage(new ArraySegment<byte>(new byte[1024 * 1024]));
var data = new JsonWithStorageParser(json, storage).Parse();
var parsed = new JsonWithStorageParser(json, storage).Parse();
//Debug.LogFormat("{0}", context.Json);
using (var context = new ImporterContext(data))
using (var context = new ImporterContext(parsed))
using (var loaded = context.Load())
{
var importedRed = loaded.transform.GetChild(0);
@@ -610,9 +611,10 @@ namespace UniGLTF
}
// export
var gltf = new glTF();
var data = new ExportingGltfData();
var gltf = data.GLTF;
string json;
using (var exporter = new gltfExporter(gltf, new GltfExportSettings()))
using (var exporter = new gltfExporter(data, new GltfExportSettings()))
{
exporter.Prepare(go);
exporter.Export(new EditorTextureSerializer());
@@ -627,9 +629,9 @@ namespace UniGLTF
// import
{
var storage = new SimpleStorage(new ArraySegment<byte>(new byte[1024 * 1024]));
var data = new JsonWithStorageParser(json, storage).Parse();
var parsed = new JsonWithStorageParser(json, storage).Parse();
using (var context = new ImporterContext(data))
using (var context = new ImporterContext(parsed))
using (var loaded = context.Load())
{
Assert.AreEqual(1, loaded.transform.GetChildren().Count());
@@ -674,9 +676,10 @@ namespace UniGLTF
Assert.True(vs.All(x => x.CanExport));
// export
var gltf = new glTF();
var data = new ExportingGltfData();
var gltf = data.GLTF;
string json;
using (var exporter = new gltfExporter(gltf, new GltfExportSettings()))
using (var exporter = new gltfExporter(data, new GltfExportSettings()))
{
exporter.Prepare(root);
exporter.Export(new EditorTextureSerializer());
@@ -692,9 +695,9 @@ namespace UniGLTF
// import
{
var storage = new SimpleStorage(new ArraySegment<byte>(new byte[1024 * 1024]));
var data = new JsonWithStorageParser(json, storage).Parse();
var parsed = new JsonWithStorageParser(json, storage).Parse();
using (var context = new ImporterContext(data))
using (var context = new ImporterContext(parsed))
using (var loaded = context.Load())
{
Assert.AreEqual(2, loaded.transform.GetChildren().Count());

View File

@@ -222,13 +222,13 @@ namespace VRM
// 出力
var sw = System.Diagnostics.Stopwatch.StartNew();
var gltf = new UniGLTF.glTF();
using (var exporter = new VRMExporter(gltf, settings.MeshExportSettings))
var data = new UniGLTF.ExportingGltfData();
using (var exporter = new VRMExporter(data, settings.MeshExportSettings))
{
exporter.Prepare(target);
exporter.Export(new EditorTextureSerializer());
}
var bytes = gltf.ToGlbBytes();
var bytes = data.ToGlbBytes();
Debug.LogFormat("Export elapsed {0}", sw.Elapsed);
return bytes;
}

View File

@@ -12,27 +12,27 @@ namespace VRM
{
public const Axes Vrm0xSpecificationInverseAxis = Axes.Z;
public static glTF Export(GltfExportSettings configuration, GameObject go, ITextureSerializer textureSerializer)
public static ExportingGltfData Export(GltfExportSettings configuration, GameObject go, ITextureSerializer textureSerializer)
{
var gltf = new glTF();
using (var exporter = new VRMExporter(gltf, configuration))
var data = new ExportingGltfData();
using (var exporter = new VRMExporter(data, configuration))
{
exporter.Prepare(go);
exporter.Export(textureSerializer);
}
return gltf;
return data;
}
public readonly VRM.glTF_VRM_extensions VRM = new glTF_VRM_extensions();
public VRMExporter(glTF gltf, GltfExportSettings exportSettings) : base(gltf, exportSettings)
public VRMExporter(ExportingGltfData data, GltfExportSettings exportSettings) : base(data, exportSettings)
{
if (exportSettings == null || exportSettings.InverseAxis != Vrm0xSpecificationInverseAxis)
{
throw new Exception( $"VRM specification requires InverseAxis settings as {Vrm0xSpecificationInverseAxis}");
throw new Exception($"VRM specification requires InverseAxis settings as {Vrm0xSpecificationInverseAxis}");
}
gltf.extensionsUsed.Add(glTF_VRM_extensions.ExtensionName);
_gltf.extensionsUsed.Add(glTF_VRM_extensions.ExtensionName);
}
protected override IMaterialExporter CreateMaterialExporter()
@@ -118,7 +118,7 @@ namespace VRM
VRM.meta.title = meta.Title;
if (meta.Thumbnail != null)
{
VRM.meta.texture = glTF.PushGltfTexture(glTF.buffers.Count - 1, meta.Thumbnail, ColorSpace.sRGB, textureSerializer);
VRM.meta.texture = GltfTextureExporter.PushGltfTexture(_data, meta.Thumbnail, ColorSpace.sRGB, textureSerializer);
}
VRM.meta.licenseType = meta.LicenseType;
@@ -213,7 +213,7 @@ namespace VRM
var f = new JsonFormatter();
VRMSerializer.Serialize(f, VRM);
var bytes = f.GetStoreBytes();
glTFExtensionExport.GetOrCreate(ref glTF.extensions).Add("VRM", bytes);
glTFExtensionExport.GetOrCreate(ref _gltf.extensions).Add("VRM", bytes);
}
}
}

View File

@@ -170,7 +170,7 @@ namespace VRM.Samples
// TODO: Check contents in JSON
/*var exportJson = */
JsonParser.Parse(vrm.ToJson());
JsonParser.Parse(vrm.GLTF.ToJson());
// TODO: Check contents in JSON
/*var newExportedJson = */

View File

@@ -65,9 +65,9 @@ namespace UniVRM10
/// <param name="storage"></param>
/// <param name="gltfMesh"></param>
/// <param name="option"></param>
static IEnumerable<glTFPrimitives> ExportMeshDivided(this VrmLib.Mesh mesh, List<object> materials, Vrm10Storage storage, ExportArgs option)
static IEnumerable<glTFPrimitives> ExportMeshDivided(this VrmLib.Mesh mesh, List<object> materials,
ExportingGltfData writer, ExportArgs option)
{
var bufferIndex = 0;
var usedIndices = new List<int>();
var meshIndices = SpanLike.CopyFrom(mesh.IndexBuffer.GetAsIntArray());
var positions = mesh.VertexBuffer.Positions.GetSpan<UnityEngine.Vector3>().ToArray();
@@ -121,7 +121,7 @@ namespace UniVRM10
}
}
var materialIndex = submesh.Material;
var gltfPrimitive = buffer.ToGltfPrimitive(storage.Gltf, bufferIndex, materialIndex, indices);
var gltfPrimitive = buffer.ToGltfPrimitive(writer, materialIndex, indices);
// blendShape
for (int j = 0; j < mesh.MorphTargets.Count; ++j)
@@ -145,7 +145,7 @@ namespace UniVRM10
);
}
gltfPrimitive.targets.Add(blendShape.ToGltf(storage.Gltf, bufferIndex, !option.removeMorphNormal, option.sparse));
gltfPrimitive.targets.Add(blendShape.ToGltf(writer, !option.removeMorphNormal, option.sparse));
}
yield return gltfPrimitive;
@@ -160,7 +160,7 @@ namespace UniVRM10
/// <param name="storage"></param>
/// <param name="option"></param>
/// <returns></returns>
public static glTFMesh ExportMeshGroup(this MeshGroup src, List<object> materials, Vrm10Storage storage, ExportArgs option)
public static glTFMesh ExportMeshGroup(this MeshGroup src, List<object> materials, ExportingGltfData writer, ExportArgs option)
{
var gltfMesh = new glTFMesh
{
@@ -172,7 +172,7 @@ namespace UniVRM10
throw new NotImplementedException();
}
foreach (var prim in src.Meshes[0].ExportMeshDivided(materials, storage, option))
foreach (var prim in src.Meshes[0].ExportMeshDivided(materials, writer, option))
{
gltfMesh.primitives.Add(prim);
}

View File

@@ -110,7 +110,7 @@ namespace UniVRM10
GetTextureBytesAsync getThumbnailImageBytesAsync = () =>
{
var bytes = data.GLTF.GetImageBytes(data.Storage, imageIndex);
var bytes = data.GetImageBytes(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,

View File

@@ -37,10 +37,6 @@ namespace UniVRM10
Storage.Gltf.extensionsUsed.Add(UniGLTF.Extensions.VRMC_materials_mtoon.VRMC_materials_mtoon.ExtensionName);
Storage.Gltf.extensionsUsed.Add(UniGLTF.Extensions.VRMC_springBone.VRMC_springBone.ExtensionName);
Storage.Gltf.extensionsUsed.Add(UniGLTF.Extensions.VRMC_node_constraint.VRMC_node_constraint.ExtensionName);
Storage.Gltf.buffers.Add(new glTFBuffer
{
});
m_textureSerializer = textureSerializer;
m_textureExporter = new TextureExporter(m_textureSerializer);
@@ -61,11 +57,11 @@ namespace UniVRM10
return asset;
}
public static IEnumerable<glTFMesh> ExportMeshes(List<MeshGroup> groups, List<object> materials, Vrm10Storage storage, ExportArgs option)
public static IEnumerable<glTFMesh> ExportMeshes(List<MeshGroup> groups, List<object> materials, ExportingGltfData data, ExportArgs option)
{
foreach (var group in groups)
{
yield return group.ExportMeshGroup(materials, storage, option);
yield return group.ExportMeshGroup(materials, data, option);
}
}
@@ -201,7 +197,7 @@ namespace UniVRM10
for (var exportedTextureIdx = 0; exportedTextureIdx < exportedTextures.Count; ++exportedTextureIdx)
{
var (unityTexture, texColorSpace) = exportedTextures[exportedTextureIdx];
Storage.Gltf.PushGltfTexture(0, unityTexture, texColorSpace, m_textureSerializer);
GltfTextureExporter.PushGltfTexture(Storage, unityTexture, texColorSpace, m_textureSerializer);
}
if (thumbnailTextureIndex.HasValue)

View File

@@ -10,7 +10,7 @@ using VrmLib;
namespace UniVRM10
{
public class Vrm10Storage
public class Vrm10Storage : ExportingGltfData
{
UniGLTF.GltfData m_data;
public UniGLTF.glTF Gltf => m_data.GLTF;
@@ -29,10 +29,7 @@ namespace UniVRM10
m_data = new GltfData(
string.Empty,
string.Empty,
new glTF
{
extensionsUsed = new List<string>(),
},
GLTF,
new List<GlbChunk>(),
new SimpleStorage(new ArraySegment<byte>()),
new MigrationFlags()
@@ -41,8 +38,6 @@ namespace UniVRM10
{
new UniGLTF.ArrayByteBuffer()
};
Gltf.AddBuffer(Buffers[0]);
}
/// <summary>

View File

@@ -69,7 +69,7 @@ namespace UniVRM10
// copy images
foreach (var image in gltf.images)
{
var bytes = gltf.GetViewBytes(image.bufferView);
var bytes = _data.GetViewBytes(image.bufferView);
image.bufferView = AddBuffer(bytes);
}

View File

@@ -47,7 +47,7 @@ namespace UniVRM10
}
}
static void ReverseVector3Array(glTF gltf, int accessorIndex, HashSet<int> used)
static void ReverseVector3Array(GltfData data, int accessorIndex, HashSet<int> used)
{
if (accessorIndex == -1)
{
@@ -59,7 +59,7 @@ namespace UniVRM10
return;
}
var accessor = gltf.accessors[accessorIndex];
var accessor = data.GLTF.accessors[accessorIndex];
var bufferViewIndex = -1;
if (accessor.bufferView != -1)
{
@@ -72,7 +72,7 @@ namespace UniVRM10
if (bufferViewIndex != -1)
{
var buffer = gltf.GetViewBytes(bufferViewIndex);
var buffer = data.GetViewBytes(bufferViewIndex);
var span = SpanLike.Wrap<UnityEngine.Vector3>(buffer);
for (int i = 0; i < span.Length; ++i)
{
@@ -85,35 +85,35 @@ namespace UniVRM10
/// シーンをY軸で180度回転する
/// </summary>
/// <param name="gltf"></param>
public static void Rotate(glTF gltf)
public static void Rotate(GltfData data)
{
foreach (var node in gltf.nodes)
foreach (var node in data.GLTF.nodes)
{
Rotate(node);
}
// mesh の回転のみでよい
var used = new HashSet<int>();
foreach (var mesh in gltf.meshes)
foreach (var mesh in data.GLTF.meshes)
{
foreach (var prim in mesh.primitives)
{
ReverseVector3Array(gltf, prim.attributes.POSITION, used);
ReverseVector3Array(gltf, prim.attributes.NORMAL, used);
ReverseVector3Array(data, prim.attributes.POSITION, used);
ReverseVector3Array(data, prim.attributes.NORMAL, used);
foreach (var target in prim.targets)
{
ReverseVector3Array(gltf, target.POSITION, used);
ReverseVector3Array(gltf, target.NORMAL, used);
ReverseVector3Array(data, target.POSITION, used);
ReverseVector3Array(data, target.NORMAL, used);
}
}
}
foreach (var skin in gltf.skins)
foreach (var skin in data.GLTF.skins)
{
if (used.Add(skin.inverseBindMatrices))
{
var accessor = gltf.accessors[skin.inverseBindMatrices];
var buffer = gltf.GetViewBytes(accessor.bufferView);
var accessor = data.GLTF.accessors[skin.inverseBindMatrices];
var buffer = data.GetViewBytes(accessor.bufferView);
var span = SpanLike.Wrap<UnityEngine.Matrix4x4>(buffer);
for (int i = 0; i < span.Length; ++i)
{