201 lines
6.4 KiB
C#
201 lines
6.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using UniJSON;
|
|
using Unity.Collections;
|
|
|
|
namespace UniGLTF
|
|
{
|
|
public class ExportingGltfData
|
|
{
|
|
public glTF Gltf { get; } = new glTF();
|
|
|
|
protected ArrayByteBuffer _buffer;
|
|
/// <summary>
|
|
/// bin chunk
|
|
/// </summary>
|
|
public ArraySegment<byte> BinBytes => _buffer.Bytes;
|
|
|
|
public ExportingGltfData(int reserved = default)
|
|
{
|
|
if (reserved == 0)
|
|
{
|
|
reserved = 50 * 1024 * 1024;
|
|
}
|
|
|
|
// buffers[0] is export target
|
|
Gltf.buffers.Add(new glTFBuffer());
|
|
_buffer = new ArrayByteBuffer(new byte[reserved]);
|
|
}
|
|
|
|
#region Buffer management for export
|
|
public glTFBufferView ExtendBufferAndGetView<T>(ArraySegment<T> segment, glBufferTarget target) where T : struct
|
|
{
|
|
var view = _buffer.Extend(segment, target);
|
|
Gltf.buffers[0].byteLength = _buffer.Bytes.Count;
|
|
return view;
|
|
}
|
|
|
|
public int ExtendBufferAndGetViewIndex<T>(
|
|
ArraySegment<T> array,
|
|
glBufferTarget target = glBufferTarget.NONE) where T : struct
|
|
{
|
|
if (array.Count == 0)
|
|
{
|
|
return -1;
|
|
}
|
|
var view = ExtendBufferAndGetView(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;
|
|
}
|
|
|
|
public void Reserve(int bytesLength)
|
|
{
|
|
_buffer.ExtendCapacity(bytesLength);
|
|
}
|
|
|
|
public int AppendToBuffer(NativeArray<byte> segment)
|
|
{
|
|
var gltfBufferView = _buffer.Extend(segment);
|
|
var viewIndex = Gltf.bufferViews.Count;
|
|
Gltf.bufferViews.Add(gltfBufferView);
|
|
return viewIndex;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ToGltf & ToGlb
|
|
/// <summary>
|
|
/// GLBバイト列
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public byte[] ToGlbBytes()
|
|
{
|
|
var f = new JsonFormatter();
|
|
GltfSerializer.Serialize(f, Gltf);
|
|
|
|
var json = f.ToString().ParseAsJson().ToString(" ");
|
|
|
|
json = GltfJsonUtil.FindUsedExtensionsAndUpdateJson(json);
|
|
|
|
return Glb.Create(json, BinBytes).ToBytes();
|
|
}
|
|
|
|
/// <summary>
|
|
/// glTF 形式で出力する?
|
|
/// </summary>
|
|
/// <param name="gltfPath"></param>
|
|
/// <returns></returns>
|
|
public (string, 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(" ");
|
|
|
|
json = GltfJsonUtil.FindUsedExtensionsAndUpdateJson(json);
|
|
|
|
return (json, Gltf.buffers[0]);
|
|
}
|
|
#endregion
|
|
}
|
|
}
|