mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-11 13:29:41 -05:00
BufferAccessor use NativeArray
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
@@ -25,6 +26,11 @@ namespace UniGLTF
|
||||
m_bytes = bytes;
|
||||
}
|
||||
|
||||
public glTFBufferView Extend<T>(NativeArray<T> array, glBufferTarget target = default) where T : struct
|
||||
{
|
||||
return Extend(new ArraySegment<T>(array.ToArray()), target);
|
||||
}
|
||||
|
||||
public glTFBufferView Extend<T>(ArraySegment<T> array, glBufferTarget target = default) where T : struct
|
||||
{
|
||||
using (var pin = Pin.Create(array))
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UniJSON;
|
||||
using Unity.Collections;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
@@ -141,7 +142,7 @@ namespace UniGLTF
|
||||
_buffer.ExtendCapacity(bytesLength);
|
||||
}
|
||||
|
||||
public int AppendToBuffer(ArraySegment<byte> segment)
|
||||
public int AppendToBuffer(NativeArray<byte> segment)
|
||||
{
|
||||
var gltfBufferView = _buffer.Extend(segment);
|
||||
var viewIndex = Gltf.bufferViews.Count;
|
||||
|
||||
@@ -266,29 +266,32 @@ namespace UniVRM10
|
||||
|
||||
try
|
||||
{
|
||||
var converter = new UniVRM10.ModelExporter();
|
||||
var model = converter.Export(root);
|
||||
|
||||
// 右手系に変換
|
||||
m_logLabel += $"convert to right handed coordinate...\n";
|
||||
model.ConvertCoordinate(VrmLib.Coordinates.Vrm1, ignoreVrm: false);
|
||||
|
||||
// export vrm-1.0
|
||||
var exporter = new UniVRM10.Vrm10Exporter(new EditorTextureSerializer(), new GltfExportSettings());
|
||||
var option = new VrmLib.ExportArgs();
|
||||
exporter.Export(root, model, converter, option, Vrm ? Vrm.Meta : m_tmpObject.Meta);
|
||||
|
||||
var exportedBytes = exporter.Storage.ToGlbBytes();
|
||||
|
||||
m_logLabel += $"write to {path}...\n";
|
||||
File.WriteAllBytes(path, exportedBytes);
|
||||
Debug.Log("exportedBytes: " + exportedBytes.Length);
|
||||
|
||||
var assetPath = UniGLTF.UnityPath.FromFullpath(path);
|
||||
if (assetPath.IsUnderAssetsFolder)
|
||||
using (var arrayManager = new NativeArrayManager())
|
||||
{
|
||||
// asset folder 内。import を発動
|
||||
assetPath.ImportAsset();
|
||||
var converter = new UniVRM10.ModelExporter();
|
||||
var model = converter.Export(arrayManager, root);
|
||||
|
||||
// 右手系に変換
|
||||
m_logLabel += $"convert to right handed coordinate...\n";
|
||||
model.ConvertCoordinate(VrmLib.Coordinates.Vrm1, ignoreVrm: false);
|
||||
|
||||
// export vrm-1.0
|
||||
var exporter = new UniVRM10.Vrm10Exporter(new EditorTextureSerializer(), new GltfExportSettings());
|
||||
var option = new VrmLib.ExportArgs();
|
||||
exporter.Export(root, model, converter, option, Vrm ? Vrm.Meta : m_tmpObject.Meta);
|
||||
|
||||
var exportedBytes = exporter.Storage.ToGlbBytes();
|
||||
|
||||
m_logLabel += $"write to {path}...\n";
|
||||
File.WriteAllBytes(path, exportedBytes);
|
||||
Debug.Log("exportedBytes: " + exportedBytes.Length);
|
||||
|
||||
var assetPath = UniGLTF.UnityPath.FromFullpath(path);
|
||||
if (assetPath.IsUnderAssetsFolder)
|
||||
{
|
||||
// asset folder 内。import を発動
|
||||
assetPath.ImportAsset();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using UniGLTF;
|
||||
using Unity.Collections;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
@@ -38,7 +39,7 @@ namespace UniVRM10
|
||||
{
|
||||
count = self.Count;
|
||||
}
|
||||
var slice = self.Bytes.Slice(offset * stride, count * stride);
|
||||
var slice = self.Bytes.GetSubArray(offset * stride, count * stride);
|
||||
return data.AppendToBuffer(slice);
|
||||
}
|
||||
|
||||
@@ -61,7 +62,7 @@ namespace UniVRM10
|
||||
|
||||
public static int AddAccessorTo(this VrmLib.BufferAccessor self,
|
||||
ExportingGltfData data, int viewIndex,
|
||||
Action<ArraySegment<byte>, glTFAccessor> minMax = null,
|
||||
Action<NativeArray<byte>, glTFAccessor> minMax = null,
|
||||
int offset = 0, int count = 0)
|
||||
{
|
||||
var gltf = data.Gltf;
|
||||
@@ -79,7 +80,7 @@ namespace UniVRM10
|
||||
ExportingGltfData data, int bufferIndex,
|
||||
// GltfBufferTargetType targetType,
|
||||
bool useSparse,
|
||||
Action<ArraySegment<byte>, glTFAccessor> minMax = null,
|
||||
Action<NativeArray<byte>, glTFAccessor> minMax = null,
|
||||
int offset = 0, int count = 0)
|
||||
{
|
||||
if (self.ComponentType == VrmLib.AccessorValueType.FLOAT
|
||||
@@ -104,48 +105,50 @@ namespace UniVRM10
|
||||
&& sparseValuesWithIndex.Count * 16 < values.Length * 12)
|
||||
{
|
||||
// use sparse
|
||||
var sparseIndexBin = new ArraySegment<byte>(new byte[sparseValuesWithIndex.Count * 4]);
|
||||
var sparseIndexSpan = SpanLike.Wrap<Int32>(sparseIndexBin);
|
||||
var sparseValueBin = new ArraySegment<byte>(new byte[sparseValuesWithIndex.Count * 12]);
|
||||
var sparseValueSpan = SpanLike.Wrap<Vector3>(sparseValueBin);
|
||||
|
||||
for (int i = 0; i < sparseValuesWithIndex.Count; ++i)
|
||||
using (var sparseIndexBin = new NativeArray<byte>(sparseValuesWithIndex.Count * 4, Allocator.Persistent))
|
||||
using (var sparseValueBin = new NativeArray<byte>(sparseValuesWithIndex.Count * 12, Allocator.Persistent))
|
||||
{
|
||||
var (index, value) = sparseValuesWithIndex[i];
|
||||
sparseIndexSpan[i] = index;
|
||||
sparseValueSpan[i] = value;
|
||||
}
|
||||
var sparseIndexSpan = sparseIndexBin.Reinterpret<Int32>(1);
|
||||
var sparseValueSpan = sparseValueBin.Reinterpret<Vector3>(1);
|
||||
|
||||
var sparseIndexView = data.AppendToBuffer(sparseIndexBin);
|
||||
var sparseValueView = data.AppendToBuffer(sparseValueBin);
|
||||
|
||||
var accessorIndex = data.Gltf.accessors.Count;
|
||||
var accessor = new glTFAccessor
|
||||
{
|
||||
componentType = (glComponentType)self.ComponentType,
|
||||
type = self.AccessorType.ToString(),
|
||||
count = self.Count,
|
||||
byteOffset = -1,
|
||||
sparse = new glTFSparse
|
||||
for (int i = 0; i < sparseValuesWithIndex.Count; ++i)
|
||||
{
|
||||
count = sparseValuesWithIndex.Count,
|
||||
indices = new glTFSparseIndices
|
||||
{
|
||||
componentType = (glComponentType)VrmLib.AccessorValueType.UNSIGNED_INT,
|
||||
bufferView = sparseIndexView,
|
||||
},
|
||||
values = new glTFSparseValues
|
||||
{
|
||||
bufferView = sparseValueView,
|
||||
},
|
||||
var (index, value) = sparseValuesWithIndex[i];
|
||||
sparseIndexSpan[i] = index;
|
||||
sparseValueSpan[i] = value;
|
||||
}
|
||||
};
|
||||
if (minMax != null)
|
||||
{
|
||||
minMax(sparseValueBin, accessor);
|
||||
|
||||
var sparseIndexView = data.AppendToBuffer(sparseIndexBin);
|
||||
var sparseValueView = data.AppendToBuffer(sparseValueBin);
|
||||
|
||||
var accessorIndex = data.Gltf.accessors.Count;
|
||||
var accessor = new glTFAccessor
|
||||
{
|
||||
componentType = (glComponentType)self.ComponentType,
|
||||
type = self.AccessorType.ToString(),
|
||||
count = self.Count,
|
||||
byteOffset = -1,
|
||||
sparse = new glTFSparse
|
||||
{
|
||||
count = sparseValuesWithIndex.Count,
|
||||
indices = new glTFSparseIndices
|
||||
{
|
||||
componentType = (glComponentType)VrmLib.AccessorValueType.UNSIGNED_INT,
|
||||
bufferView = sparseIndexView,
|
||||
},
|
||||
values = new glTFSparseValues
|
||||
{
|
||||
bufferView = sparseValueView,
|
||||
},
|
||||
}
|
||||
};
|
||||
if (minMax != null)
|
||||
{
|
||||
minMax(sparseValueBin, accessor);
|
||||
}
|
||||
data.Gltf.accessors.Add(accessor);
|
||||
return accessorIndex;
|
||||
}
|
||||
data.Gltf.accessors.Add(accessor);
|
||||
return accessorIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,12 +23,12 @@ namespace UniVRM10
|
||||
Profiler.BeginSample("MeshImporter.LoadSharedMesh");
|
||||
var mesh = new Mesh();
|
||||
|
||||
var positions = src.VertexBuffer.Positions.AsNativeArray<Vector3>(Allocator.TempJob);
|
||||
var normals = src.VertexBuffer.Normals?.AsNativeArray<Vector3>(Allocator.TempJob) ?? default;
|
||||
var texCoords = src.VertexBuffer.TexCoords?.AsNativeArray<Vector2>(Allocator.TempJob) ?? default;
|
||||
var colors = src.VertexBuffer.Colors?.AsNativeArray<Color>(Allocator.TempJob) ?? default;
|
||||
var weights = src.VertexBuffer.Weights?.AsNativeArray<Vector4>(Allocator.TempJob) ?? default;
|
||||
var joints = src.VertexBuffer.Joints?.AsNativeArray<SkinJoints>(Allocator.TempJob) ?? default;
|
||||
var positions = src.VertexBuffer.Positions.Bytes.Reinterpret<Vector3>(1);
|
||||
var normals = src.VertexBuffer.Normals?.Bytes.Reinterpret<Vector3>(1) ?? default;
|
||||
var texCoords = src.VertexBuffer.TexCoords?.Bytes.Reinterpret<Vector2>(1) ?? default;
|
||||
var colors = src.VertexBuffer.Colors?.Bytes.Reinterpret<Color>(1) ?? default;
|
||||
var weights = src.VertexBuffer.Weights?.Bytes.Reinterpret<Vector4>(1) ?? default;
|
||||
var joints = src.VertexBuffer.Joints?.Bytes.Reinterpret<SkinJoints>(1) ?? default;
|
||||
|
||||
using (var vertices = new NativeArray<MeshVertex>(positions.Length, Allocator.TempJob))
|
||||
{
|
||||
@@ -55,14 +55,6 @@ namespace UniVRM10
|
||||
// Jobを完了
|
||||
jobHandle.Complete();
|
||||
|
||||
// 入力のNativeArrayを開放
|
||||
positions.Dispose();
|
||||
if (normals.IsCreated) normals.Dispose();
|
||||
if (texCoords.IsCreated) texCoords.Dispose();
|
||||
if (colors.IsCreated) colors.Dispose();
|
||||
if (weights.IsCreated) weights.Dispose();
|
||||
if (joints.IsCreated) joints.Dispose();
|
||||
|
||||
// 頂点を更新
|
||||
MeshVertex.SetVertexBufferParamsToMesh(mesh, vertices.Length);
|
||||
mesh.SetVertexBufferData(vertices, 0, 0, vertices.Length);
|
||||
@@ -74,16 +66,14 @@ namespace UniVRM10
|
||||
switch (src.IndexBuffer.ComponentType)
|
||||
{
|
||||
case AccessorValueType.UNSIGNED_SHORT:
|
||||
var shortIndices = src.IndexBuffer.AsNativeArray<ushort>(Allocator.Temp);
|
||||
var shortIndices = src.IndexBuffer.Bytes.Reinterpret<ushort>(1);
|
||||
mesh.SetIndexBufferParams(shortIndices.Length, IndexFormat.UInt16);
|
||||
mesh.SetIndexBufferData(shortIndices, 0, 0, shortIndices.Length);
|
||||
shortIndices.Dispose();
|
||||
break;
|
||||
case AccessorValueType.UNSIGNED_INT:
|
||||
var intIndices = src.IndexBuffer.AsNativeArray<uint>(Allocator.Temp);
|
||||
var intIndices = src.IndexBuffer.Bytes.Reinterpret<uint>(1);
|
||||
mesh.SetIndexBufferParams(intIndices.Length, IndexFormat.UInt32);
|
||||
mesh.SetIndexBufferData(intIndices, 0, 0, intIndices.Length);
|
||||
intIndices.Dispose();
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -126,8 +126,7 @@ namespace UniVRM10
|
||||
case AccessorValueType.SHORT:
|
||||
{
|
||||
// unsigned short -> unsigned short
|
||||
var source = mesh.IndexBuffer.AsNativeArray<ushort>(Allocator.TempJob);
|
||||
disposables.Add(source);
|
||||
var source = mesh.IndexBuffer.Bytes.Reinterpret<ushort>(1);
|
||||
jobHandle = new CopyIndicesJobs.Ushort2Ushort(
|
||||
(ushort)vertexOffset,
|
||||
new NativeSlice<ushort>(source),
|
||||
@@ -138,8 +137,7 @@ namespace UniVRM10
|
||||
case AccessorValueType.UNSIGNED_INT:
|
||||
{
|
||||
// unsigned int -> unsigned short
|
||||
var source = mesh.IndexBuffer.AsNativeArray<uint>(Allocator.TempJob);
|
||||
disposables.Add(source);
|
||||
var source = mesh.IndexBuffer.Bytes.Reinterpret<uint>(1);
|
||||
jobHandle = new CopyIndicesJobs.Uint2Ushort(
|
||||
(ushort)vertexOffset,
|
||||
source,
|
||||
@@ -173,8 +171,7 @@ namespace UniVRM10
|
||||
case AccessorValueType.SHORT:
|
||||
{
|
||||
// unsigned short -> unsigned int
|
||||
var source = mesh.IndexBuffer.AsNativeArray<ushort>(Allocator.TempJob);
|
||||
disposables.Add(source);
|
||||
var source = mesh.IndexBuffer.Bytes.Reinterpret<ushort>(1);
|
||||
jobHandle = new CopyIndicesJobs.Ushort2Uint(
|
||||
(uint)vertexOffset,
|
||||
source,
|
||||
@@ -185,8 +182,7 @@ namespace UniVRM10
|
||||
case AccessorValueType.UNSIGNED_INT:
|
||||
{
|
||||
// unsigned int -> unsigned int
|
||||
var source = mesh.IndexBuffer.AsNativeArray<uint>(Allocator.TempJob);
|
||||
disposables.Add(source);
|
||||
var source = mesh.IndexBuffer.Bytes.Reinterpret<uint>(1);
|
||||
jobHandle = new CopyIndicesJobs.UInt2UInt(
|
||||
(uint)vertexOffset,
|
||||
source,
|
||||
@@ -237,20 +233,15 @@ namespace UniVRM10
|
||||
|
||||
foreach (var mesh in meshGroup.Meshes)
|
||||
{
|
||||
var positions = mesh.VertexBuffer.Positions.AsNativeArray<Vector3>(Allocator.TempJob);
|
||||
var normals = mesh.VertexBuffer.Normals.AsNativeArray<Vector3>(Allocator.TempJob);
|
||||
var texCoords = mesh.VertexBuffer.TexCoords.AsNativeArray<Vector2>(Allocator.TempJob);
|
||||
var positions = mesh.VertexBuffer.Positions.Bytes.Reinterpret<Vector3>(1);
|
||||
var normals = mesh.VertexBuffer.Normals.Bytes.Reinterpret<Vector3>(1);
|
||||
var texCoords = mesh.VertexBuffer.TexCoords.Bytes.Reinterpret<Vector2>(1);
|
||||
var weights = meshGroup.Skin != null
|
||||
? mesh.VertexBuffer.Weights.AsNativeArray<Vector4>(Allocator.TempJob)
|
||||
? mesh.VertexBuffer.Weights.Bytes.Reinterpret<Vector4>(1)
|
||||
: default;
|
||||
var joints = meshGroup.Skin != null
|
||||
? mesh.VertexBuffer.Joints.AsNativeArray<SkinJoints>(Allocator.TempJob)
|
||||
? mesh.VertexBuffer.Joints.Bytes.Reinterpret<SkinJoints>(1)
|
||||
: default;
|
||||
if (positions.IsCreated) disposables.Add(positions);
|
||||
if (normals.IsCreated) disposables.Add(normals);
|
||||
if (texCoords.IsCreated) disposables.Add(texCoords);
|
||||
if (weights.IsCreated) disposables.Add(weights);
|
||||
if (joints.IsCreated) disposables.Add(joints);
|
||||
|
||||
interleaveVertexJob = new InterleaveMeshVerticesJob(
|
||||
new NativeSlice<MeshVertex>(vertices, indexOffset, mesh.VertexBuffer.Count),
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using UniGLTF;
|
||||
using Unity.Collections;
|
||||
using VrmLib;
|
||||
|
||||
namespace UniVRM10
|
||||
@@ -26,33 +27,33 @@ namespace UniVRM10
|
||||
accessor.max = max.ToFloat3();
|
||||
}
|
||||
|
||||
static int ExportIndices(ExportingGltfData data, BufferAccessor x, int offset, int count, ExportArgs option)
|
||||
{
|
||||
if (x.Count <= ushort.MaxValue)
|
||||
{
|
||||
if (x.ComponentType == AccessorValueType.UNSIGNED_INT)
|
||||
{
|
||||
// ensure ushort
|
||||
var src = x.GetSpan<UInt32>().Slice(offset, count);
|
||||
var bytes = new byte[src.Length * 2];
|
||||
var dst = SpanLike.Wrap<UInt16>(new ArraySegment<byte>(bytes));
|
||||
for (int i = 0; i < src.Length; ++i)
|
||||
{
|
||||
dst[i] = (ushort)src[i];
|
||||
}
|
||||
var accessor = new BufferAccessor(new ArraySegment<byte>(bytes), AccessorValueType.UNSIGNED_SHORT, AccessorVectorType.SCALAR, count);
|
||||
return accessor.AddAccessorTo(data, 0, option.sparse, null, 0, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
return x.AddAccessorTo(data, 0, option.sparse, null, offset, count);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return x.AddAccessorTo(data, 0, option.sparse, null, offset, count);
|
||||
}
|
||||
}
|
||||
// static int ExportIndices(ExportingGltfData data, BufferAccessor x, int offset, int count, ExportArgs option)
|
||||
// {
|
||||
// if (x.Count <= ushort.MaxValue)
|
||||
// {
|
||||
// if (x.ComponentType == AccessorValueType.UNSIGNED_INT)
|
||||
// {
|
||||
// // ensure ushort
|
||||
// var src = x.GetSpan<UInt32>().Slice(offset, count);
|
||||
// var bytes = new byte[src.Length * 2];
|
||||
// var dst = SpanLike.Wrap<UInt16>(new ArraySegment<byte>(bytes));
|
||||
// for (int i = 0; i < src.Length; ++i)
|
||||
// {
|
||||
// dst[i] = (ushort)src[i];
|
||||
// }
|
||||
// var accessor = new BufferAccessor(new ArraySegment<byte>(bytes), AccessorValueType.UNSIGNED_SHORT, AccessorVectorType.SCALAR, count);
|
||||
// return accessor.AddAccessorTo(data, 0, option.sparse, null, 0, count);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return x.AddAccessorTo(data, 0, option.sparse, null, offset, count);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return x.AddAccessorTo(data, 0, option.sparse, null, offset, count);
|
||||
// }
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// https://github.com/vrm-c/UniVRM/issues/800
|
||||
@@ -69,7 +70,7 @@ namespace UniVRM10
|
||||
ExportingGltfData writer, ExportArgs option)
|
||||
{
|
||||
var usedIndices = new List<int>();
|
||||
var meshIndices = SpanLike.CopyFrom(mesh.IndexBuffer.GetAsIntArray());
|
||||
var meshIndices = mesh.IndexBuffer.GetAsIntArray();
|
||||
var positions = mesh.VertexBuffer.Positions.GetSpan<UnityEngine.Vector3>().ToArray();
|
||||
var normals = mesh.VertexBuffer.Normals.GetSpan<UnityEngine.Vector3>().ToArray();
|
||||
var uv = mesh.VertexBuffer.TexCoords.GetSpan<UnityEngine.Vector2>().ToArray();
|
||||
@@ -87,7 +88,7 @@ namespace UniVRM10
|
||||
|
||||
foreach (var submesh in mesh.Submeshes)
|
||||
{
|
||||
var indices = meshIndices.Slice(submesh.Offset, submesh.DrawCount).ToArray();
|
||||
var indices = meshIndices.GetSubArray(submesh.Offset, submesh.DrawCount).ToArray();
|
||||
var hash = new HashSet<int>(indices);
|
||||
|
||||
// mesh
|
||||
@@ -131,7 +132,7 @@ namespace UniVRM10
|
||||
// index の順に attributes を蓄える
|
||||
var morph = mesh.MorphTargets[j];
|
||||
var blendShapePositions = morph.VertexBuffer.Positions.GetSpan<UnityEngine.Vector3>();
|
||||
SpanLike<UnityEngine.Vector3>? blendShapeNormals = default;
|
||||
NativeArray<UnityEngine.Vector3>? blendShapeNormals = default;
|
||||
if (morph.VertexBuffer.Normals != null)
|
||||
{
|
||||
blendShapeNormals = morph.VertexBuffer.Normals.GetSpan<UnityEngine.Vector3>();
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using UniGLTF;
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
using VrmLib;
|
||||
|
||||
@@ -23,11 +25,11 @@ namespace UniVRM10
|
||||
/// </summary>
|
||||
/// <param name="root"></param>
|
||||
/// <returns></returns>
|
||||
public VrmLib.Model Export(GameObject root)
|
||||
public VrmLib.Model Export(NativeArrayManager arrayManager, GameObject root)
|
||||
{
|
||||
Model = new VrmLib.Model(VrmLib.Coordinates.Unity);
|
||||
|
||||
_Export(root);
|
||||
_Export(arrayManager, root);
|
||||
|
||||
// humanoid
|
||||
{
|
||||
@@ -51,7 +53,7 @@ namespace UniVRM10
|
||||
return Model;
|
||||
}
|
||||
|
||||
VrmLib.Model _Export(GameObject root)
|
||||
VrmLib.Model _Export(NativeArrayManager arrayManager, GameObject root)
|
||||
{
|
||||
if (Model == null)
|
||||
{
|
||||
@@ -94,8 +96,8 @@ namespace UniVRM10
|
||||
{
|
||||
if (skinnedMeshRenderer.sharedMesh != null)
|
||||
{
|
||||
var mesh = CreateMesh(skinnedMeshRenderer.sharedMesh, skinnedMeshRenderer, Materials);
|
||||
var skin = CreateSkin(skinnedMeshRenderer, Nodes, root);
|
||||
var mesh = CreateMesh(arrayManager, skinnedMeshRenderer.sharedMesh, skinnedMeshRenderer, Materials);
|
||||
var skin = CreateSkin(arrayManager, skinnedMeshRenderer, Nodes, root);
|
||||
if (skin != null)
|
||||
{
|
||||
// blendshape only で skinning が無いやつがある
|
||||
@@ -112,7 +114,7 @@ namespace UniVRM10
|
||||
var filter = meshRenderer.gameObject.GetComponent<MeshFilter>();
|
||||
if (filter != null && filter.sharedMesh != null)
|
||||
{
|
||||
var mesh = CreateMesh(filter.sharedMesh, meshRenderer, Materials);
|
||||
var mesh = CreateMesh(arrayManager, filter.sharedMesh, meshRenderer, Materials);
|
||||
Model.MeshGroups.Add(mesh);
|
||||
Nodes[renderer.gameObject].MeshGroup = mesh;
|
||||
if (!Meshes.ContainsKey(filter.sharedMesh))
|
||||
@@ -167,30 +169,30 @@ namespace UniVRM10
|
||||
return null;
|
||||
}
|
||||
|
||||
private static VrmLib.MeshGroup CreateMesh(UnityEngine.Mesh mesh, Renderer renderer, List<UnityEngine.Material> materials)
|
||||
private static VrmLib.MeshGroup CreateMesh(NativeArrayManager arrayManager, UnityEngine.Mesh mesh, Renderer renderer, List<UnityEngine.Material> materials)
|
||||
{
|
||||
var meshGroup = new VrmLib.MeshGroup(mesh.name);
|
||||
var vrmMesh = new VrmLib.Mesh();
|
||||
vrmMesh.VertexBuffer = new VrmLib.VertexBuffer();
|
||||
vrmMesh.VertexBuffer.Add(VrmLib.VertexBuffer.PositionKey, ToBufferAccessor(mesh.vertices));
|
||||
vrmMesh.VertexBuffer.Add(VrmLib.VertexBuffer.PositionKey, ToBufferAccessor(arrayManager, mesh.vertices));
|
||||
|
||||
if (mesh.boneWeights.Length == mesh.vertexCount)
|
||||
{
|
||||
vrmMesh.VertexBuffer.Add(
|
||||
VrmLib.VertexBuffer.WeightKey,
|
||||
ToBufferAccessor(mesh.boneWeights.Select(x =>
|
||||
ToBufferAccessor(arrayManager, mesh.boneWeights.Select(x =>
|
||||
new Vector4(x.weight0, x.weight1, x.weight2, x.weight3)).ToArray()
|
||||
));
|
||||
vrmMesh.VertexBuffer.Add(
|
||||
VrmLib.VertexBuffer.JointKey,
|
||||
ToBufferAccessor(mesh.boneWeights.Select(x =>
|
||||
ToBufferAccessor(arrayManager, mesh.boneWeights.Select(x =>
|
||||
new SkinJoints((ushort)x.boneIndex0, (ushort)x.boneIndex1, (ushort)x.boneIndex2, (ushort)x.boneIndex3)).ToArray()
|
||||
));
|
||||
}
|
||||
if (mesh.uv.Length == mesh.vertexCount) vrmMesh.VertexBuffer.Add(VrmLib.VertexBuffer.TexCoordKey, ToBufferAccessor(mesh.uv));
|
||||
if (mesh.normals.Length == mesh.vertexCount) vrmMesh.VertexBuffer.Add(VrmLib.VertexBuffer.NormalKey, ToBufferAccessor(mesh.normals));
|
||||
if (mesh.colors.Length == mesh.vertexCount) vrmMesh.VertexBuffer.Add(VrmLib.VertexBuffer.ColorKey, ToBufferAccessor(mesh.colors));
|
||||
vrmMesh.IndexBuffer = ToBufferAccessor(mesh.triangles);
|
||||
if (mesh.uv.Length == mesh.vertexCount) vrmMesh.VertexBuffer.Add(VrmLib.VertexBuffer.TexCoordKey, ToBufferAccessor(arrayManager, mesh.uv));
|
||||
if (mesh.normals.Length == mesh.vertexCount) vrmMesh.VertexBuffer.Add(VrmLib.VertexBuffer.NormalKey, ToBufferAccessor(arrayManager, mesh.normals));
|
||||
if (mesh.colors.Length == mesh.vertexCount) vrmMesh.VertexBuffer.Add(VrmLib.VertexBuffer.ColorKey, ToBufferAccessor(arrayManager, mesh.colors));
|
||||
vrmMesh.IndexBuffer = ToBufferAccessor(arrayManager, mesh.triangles);
|
||||
|
||||
int offset = 0;
|
||||
for (int i = 0; i < mesh.subMeshCount; i++)
|
||||
@@ -240,7 +242,7 @@ namespace UniVRM10
|
||||
{
|
||||
var morphTarget = new VrmLib.MorphTarget(mesh.GetBlendShapeName(i));
|
||||
morphTarget.VertexBuffer = new VrmLib.VertexBuffer();
|
||||
morphTarget.VertexBuffer.Add(VrmLib.VertexBuffer.PositionKey, ToBufferAccessor(blendShapeVertices));
|
||||
morphTarget.VertexBuffer.Add(VrmLib.VertexBuffer.PositionKey, ToBufferAccessor(arrayManager, blendShapeVertices));
|
||||
vrmMesh.MorphTargets.Add(morphTarget);
|
||||
}
|
||||
}
|
||||
@@ -249,7 +251,7 @@ namespace UniVRM10
|
||||
return meshGroup;
|
||||
}
|
||||
|
||||
private static VrmLib.Skin CreateSkin(
|
||||
private static VrmLib.Skin CreateSkin(NativeArrayManager arrayManager,
|
||||
SkinnedMeshRenderer skinnedMeshRenderer,
|
||||
Dictionary<GameObject, VrmLib.Node> nodes,
|
||||
GameObject root)
|
||||
@@ -260,7 +262,7 @@ namespace UniVRM10
|
||||
}
|
||||
|
||||
var skin = new VrmLib.Skin();
|
||||
skin.InverseMatrices = ToBufferAccessor(skinnedMeshRenderer.sharedMesh.bindposes);
|
||||
skin.InverseMatrices = ToBufferAccessor(arrayManager, skinnedMeshRenderer.sharedMesh.bindposes);
|
||||
if (skinnedMeshRenderer.rootBone != null)
|
||||
{
|
||||
skin.Root = nodes[skinnedMeshRenderer.rootBone.gameObject];
|
||||
@@ -270,46 +272,45 @@ namespace UniVRM10
|
||||
return skin;
|
||||
}
|
||||
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor(SkinJoints[] values)
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor(NativeArrayManager arrayManager, SkinJoints[] values)
|
||||
{
|
||||
return ToBufferAccessor(values, VrmLib.AccessorValueType.UNSIGNED_SHORT, VrmLib.AccessorVectorType.VEC4);
|
||||
return ToBufferAccessor(arrayManager, values, VrmLib.AccessorValueType.UNSIGNED_SHORT, VrmLib.AccessorVectorType.VEC4);
|
||||
}
|
||||
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor(Color[] colors)
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor(NativeArrayManager arrayManager, Color[] colors)
|
||||
{
|
||||
return ToBufferAccessor(colors, VrmLib.AccessorValueType.FLOAT, VrmLib.AccessorVectorType.VEC4);
|
||||
return ToBufferAccessor(arrayManager, colors, VrmLib.AccessorValueType.FLOAT, VrmLib.AccessorVectorType.VEC4);
|
||||
}
|
||||
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor(Vector4[] vectors)
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor(NativeArrayManager arrayManager, Vector4[] vectors)
|
||||
{
|
||||
return ToBufferAccessor(vectors, VrmLib.AccessorValueType.FLOAT, VrmLib.AccessorVectorType.VEC4);
|
||||
return ToBufferAccessor(arrayManager, vectors, VrmLib.AccessorValueType.FLOAT, VrmLib.AccessorVectorType.VEC4);
|
||||
}
|
||||
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor(Vector3[] vectors)
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor(NativeArrayManager arrayManager, Vector3[] vectors)
|
||||
{
|
||||
return ToBufferAccessor(vectors, VrmLib.AccessorValueType.FLOAT, VrmLib.AccessorVectorType.VEC3);
|
||||
return ToBufferAccessor(arrayManager, vectors, VrmLib.AccessorValueType.FLOAT, VrmLib.AccessorVectorType.VEC3);
|
||||
}
|
||||
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor(Vector2[] vectors)
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor(NativeArrayManager arrayManager, Vector2[] vectors)
|
||||
{
|
||||
return ToBufferAccessor(vectors, VrmLib.AccessorValueType.FLOAT, VrmLib.AccessorVectorType.VEC2);
|
||||
return ToBufferAccessor(arrayManager, vectors, VrmLib.AccessorValueType.FLOAT, VrmLib.AccessorVectorType.VEC2);
|
||||
}
|
||||
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor(int[] scalars)
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor(NativeArrayManager arrayManager, int[] scalars)
|
||||
{
|
||||
return ToBufferAccessor(scalars, VrmLib.AccessorValueType.UNSIGNED_INT, VrmLib.AccessorVectorType.SCALAR);
|
||||
return ToBufferAccessor(arrayManager, scalars, VrmLib.AccessorValueType.UNSIGNED_INT, VrmLib.AccessorVectorType.SCALAR);
|
||||
}
|
||||
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor(Matrix4x4[] matrixes)
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor(NativeArrayManager arrayManager, Matrix4x4[] matrixes)
|
||||
{
|
||||
return ToBufferAccessor(matrixes, VrmLib.AccessorValueType.FLOAT, VrmLib.AccessorVectorType.MAT4);
|
||||
return ToBufferAccessor(arrayManager, matrixes, VrmLib.AccessorValueType.FLOAT, VrmLib.AccessorVectorType.MAT4);
|
||||
}
|
||||
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor<T>(T[] value, VrmLib.AccessorValueType valueType, VrmLib.AccessorVectorType vectorType) where T : struct
|
||||
private static VrmLib.BufferAccessor ToBufferAccessor<T>(NativeArrayManager arrayManager, T[] value, VrmLib.AccessorValueType valueType, VrmLib.AccessorVectorType vectorType) where T : struct
|
||||
{
|
||||
var span = SpanLike.CopyFrom(value);
|
||||
return new VrmLib.BufferAccessor(
|
||||
span.Bytes,
|
||||
return new VrmLib.BufferAccessor(arrayManager,
|
||||
arrayManager.CreateNativeArray(value).Reinterpret<byte>(Marshal.SizeOf<T>()),
|
||||
valueType,
|
||||
vectorType,
|
||||
value.Length
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace UniVRM10
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<(glTFNode, glTFSkin)> ExportNodes(List<Node> nodes, List<MeshGroup> groups, ExportingGltfData data, ExportArgs option)
|
||||
public static IEnumerable<(glTFNode, glTFSkin)> ExportNodes(NativeArrayManager arrayManager, List<Node> nodes, List<MeshGroup> groups, ExportingGltfData data, ExportArgs option)
|
||||
{
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
@@ -96,7 +96,7 @@ namespace UniVRM10
|
||||
};
|
||||
if (skin.InverseMatrices == null)
|
||||
{
|
||||
skin.CalcInverseMatrices();
|
||||
skin.CalcInverseMatrices(arrayManager);
|
||||
}
|
||||
if (skin.InverseMatrices != null)
|
||||
{
|
||||
@@ -180,14 +180,17 @@ namespace UniVRM10
|
||||
Storage.Gltf.meshes.Add(mesh);
|
||||
}
|
||||
|
||||
foreach (var (node, skin) in ExportNodes(model.Nodes, model.MeshGroups, Storage, option))
|
||||
using (var arrayManager = new NativeArrayManager())
|
||||
{
|
||||
Storage.Gltf.nodes.Add(node);
|
||||
if (skin != null)
|
||||
foreach (var (node, skin) in ExportNodes(arrayManager, model.Nodes, model.MeshGroups, Storage, option))
|
||||
{
|
||||
var skinIndex = Storage.Gltf.skins.Count;
|
||||
Storage.Gltf.skins.Add(skin);
|
||||
node.skin = skinIndex;
|
||||
Storage.Gltf.nodes.Add(node);
|
||||
if (skin != null)
|
||||
{
|
||||
var skinIndex = Storage.Gltf.skins.Count;
|
||||
Storage.Gltf.skins.Add(skin);
|
||||
node.skin = skinIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
Storage.Gltf.scenes.Add(new gltfScene()
|
||||
@@ -343,7 +346,8 @@ namespace UniVRM10
|
||||
colliders.Length == 0 &&
|
||||
controller.SpringBone.ColliderGroups.Count == 0 &&
|
||||
controller.SpringBone.Springs.Count == 0
|
||||
) {
|
||||
)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -803,20 +807,23 @@ namespace UniVRM10
|
||||
/// <returns></returns>
|
||||
public static byte[] Export(GameObject go, ITextureSerializer textureSerializer = null)
|
||||
{
|
||||
// ヒエラルキーからジオメトリーを収集
|
||||
var converter = new UniVRM10.ModelExporter();
|
||||
var model = converter.Export(go);
|
||||
|
||||
// 右手系に変換
|
||||
model.ConvertCoordinate(VrmLib.Coordinates.Vrm1);
|
||||
|
||||
// Model と go から VRM-1.0 にExport
|
||||
var exporter10 = new Vrm10Exporter(textureSerializer ?? new RuntimeTextureSerializer(), new GltfExportSettings());
|
||||
var option = new VrmLib.ExportArgs
|
||||
using (var arrayManager = new NativeArrayManager())
|
||||
{
|
||||
};
|
||||
exporter10.Export(go, model, converter, option);
|
||||
return exporter10.Storage.ToGlbBytes();
|
||||
// ヒエラルキーからジオメトリーを収集
|
||||
var converter = new UniVRM10.ModelExporter();
|
||||
var model = converter.Export(arrayManager, go);
|
||||
|
||||
// 右手系に変換
|
||||
model.ConvertCoordinate(VrmLib.Coordinates.Vrm1);
|
||||
|
||||
// Model と go から VRM-1.0 にExport
|
||||
var exporter10 = new Vrm10Exporter(textureSerializer ?? new RuntimeTextureSerializer(), new GltfExportSettings());
|
||||
var option = new VrmLib.ExportArgs
|
||||
{
|
||||
};
|
||||
exporter10.Export(go, model, converter, option);
|
||||
return exporter10.Storage.ToGlbBytes();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ namespace UniVRM10
|
||||
var accessor = Gltf.accessors[accessorIndex];
|
||||
var bytes = GetAccessorBytes(accessorIndex);
|
||||
var vectorType = EnumUtil.Parse<AccessorVectorType>(accessor.type);
|
||||
ba = new BufferAccessor(new ArraySegment<byte>(bytes.ToArray()),
|
||||
ba = new BufferAccessor(m_data.NativeArrayManager, bytes,
|
||||
(AccessorValueType)accessor.componentType, vectorType, accessor.count);
|
||||
return true;
|
||||
}
|
||||
@@ -275,7 +275,7 @@ namespace UniVRM10
|
||||
var buffer = Gltf.buffers[firstViewBufferIndex];
|
||||
var bin = GetBufferBytes(buffer);
|
||||
var bytes = bin.GetSubArray(start, totalCount * firstAccessor.GetStride());
|
||||
return new BufferAccessor(new ArraySegment<byte>(bytes.ToArray()),
|
||||
return new BufferAccessor(m_data.NativeArrayManager, bytes,
|
||||
(AccessorValueType)firstAccessor.componentType,
|
||||
EnumUtil.Parse<AccessorVectorType>(firstAccessor.type),
|
||||
totalCount);
|
||||
@@ -339,7 +339,7 @@ namespace UniVRM10
|
||||
throw new NotImplementedException($"accessor.componentType: {accessor.componentType}");
|
||||
}
|
||||
}
|
||||
return new BufferAccessor(new ArraySegment<byte>(indices.ToArray()), AccessorValueType.UNSIGNED_INT, AccessorVectorType.SCALAR, totalCount);
|
||||
return new BufferAccessor(m_data.NativeArrayManager, indices, AccessorValueType.UNSIGNED_INT, AccessorVectorType.SCALAR, totalCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace UniVRM10
|
||||
|
||||
if (m_doNormalize)
|
||||
{
|
||||
var result = m_model.SkinningBake();
|
||||
var result = m_model.SkinningBake(Data.NativeArrayManager);
|
||||
Debug.Log($"SkinningBake: {result}");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using UniGLTF;
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
@@ -23,7 +25,7 @@ namespace UniVRM10
|
||||
_buffer = new ArrayByteBuffer(new byte[data.Bin.Length]);
|
||||
}
|
||||
|
||||
int AddBuffer(ArraySegment<byte> bytes)
|
||||
int AddBuffer(NativeArray<byte> bytes)
|
||||
{
|
||||
var bufferView = _buffer.Extend(bytes);
|
||||
var index = _bufferViews.Count;
|
||||
@@ -31,9 +33,9 @@ namespace UniVRM10
|
||||
return index;
|
||||
}
|
||||
|
||||
int AddAccessor<T>(SpanLike<T> span) where T : struct
|
||||
int AddAccessor<T>(NativeArray<T> span) where T : struct
|
||||
{
|
||||
var bufferViewIndex = AddBuffer(span.Bytes);
|
||||
var bufferViewIndex = AddBuffer(span.Reinterpret<byte>(Marshal.SizeOf<T>()));
|
||||
var accessor = new glTFAccessor
|
||||
{
|
||||
bufferView = bufferViewIndex,
|
||||
@@ -70,24 +72,20 @@ namespace UniVRM10
|
||||
foreach (var image in gltf.images)
|
||||
{
|
||||
var bytes = _data.GetBytesFromBufferView(image.bufferView);
|
||||
image.bufferView = AddBuffer(new ArraySegment<byte>(bytes.ToArray()));
|
||||
image.bufferView = AddBuffer(bytes);
|
||||
}
|
||||
|
||||
// update Mesh
|
||||
foreach (var (gltfMesh, mesh) in Enumerable.Zip(gltf.meshes, model.MeshGroups, (l, r) => (l, r.Meshes[0])))
|
||||
{
|
||||
SpanLike<uint> indices;
|
||||
NativeArray<uint> indices;
|
||||
switch (mesh.IndexBuffer.Stride)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
// byte
|
||||
var byte_indices = mesh.IndexBuffer.GetSpan<byte>();
|
||||
indices = SpanLike.Create<uint>(byte_indices.Length);
|
||||
for (int i = 0; i < byte_indices.Length; ++i)
|
||||
{
|
||||
indices[i] = byte_indices[i];
|
||||
}
|
||||
indices = _data.NativeArrayManager.Convert(byte_indices, (byte x) => (uint)x);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -95,11 +93,7 @@ namespace UniVRM10
|
||||
{
|
||||
// ushort
|
||||
var ushort_indices = mesh.IndexBuffer.GetSpan<ushort>();
|
||||
indices = SpanLike.Create<uint>(ushort_indices.Length);
|
||||
for (int i = 0; i < ushort_indices.Length; ++i)
|
||||
{
|
||||
indices[i] = ushort_indices[i];
|
||||
}
|
||||
indices = _data.NativeArrayManager.Convert(ushort_indices, (ushort x) => (uint)x);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -132,7 +126,7 @@ namespace UniVRM10
|
||||
|
||||
foreach (var (gltfPrim, submesh) in Enumerable.Zip(gltfMesh.primitives, mesh.Submeshes, (l, r) => (l, r)))
|
||||
{
|
||||
var subIndices = indices.Slice(submesh.Offset, submesh.DrawCount);
|
||||
var subIndices = indices.GetSubArray(submesh.Offset, submesh.DrawCount);
|
||||
gltfPrim.indices = AddAccessor(subIndices);
|
||||
gltfPrim.attributes.POSITION = position.Value;
|
||||
gltfPrim.attributes.NORMAL = normal.GetValueOrDefault(-1); // たぶん、ありえる
|
||||
@@ -178,7 +172,8 @@ namespace UniVRM10
|
||||
gltfSkin.inverseBindMatrices = AddAccessor(node.MeshGroup.Skin.InverseMatrices.GetSpan<Matrix4x4>());
|
||||
gltf.skins.Add(gltfSkin);
|
||||
}
|
||||
else{
|
||||
else
|
||||
{
|
||||
// multi nodes sharing a same skin may be error ?
|
||||
// edge case.
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace UniVRM10.Test
|
||||
private (GameObject, IReadOnlyList<VRMShaders.MaterialFactory.MaterialLoadInfo>) ToUnity(byte[] bytes)
|
||||
{
|
||||
// Vrm => Model
|
||||
using(var data = new GlbBinaryParser(bytes, "tmp.vrm").Parse())
|
||||
using (var data = new GlbBinaryParser(bytes, "tmp.vrm").Parse())
|
||||
using (var migrated = Vrm10Data.Migrate(data, out Vrm10Data result, out MigrationData migration))
|
||||
{
|
||||
if (result == null)
|
||||
@@ -54,11 +54,14 @@ namespace UniVRM10.Test
|
||||
|
||||
private Model ToVrmModel(GameObject root)
|
||||
{
|
||||
var exporter = new UniVRM10.ModelExporter();
|
||||
var model = exporter.Export(root);
|
||||
using (var arrayManager = new NativeArrayManager())
|
||||
{
|
||||
var exporter = new UniVRM10.ModelExporter();
|
||||
var model = exporter.Export(arrayManager, root);
|
||||
|
||||
model.ConvertCoordinate(VrmLib.Coordinates.Vrm1, ignoreVrm: false);
|
||||
return model;
|
||||
model.ConvertCoordinate(VrmLib.Coordinates.Vrm1, ignoreVrm: false);
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
||||
void EqualColor(Color color1, Color color2)
|
||||
|
||||
@@ -128,7 +128,7 @@ namespace VrmLib
|
||||
{
|
||||
get
|
||||
{
|
||||
var span = SpanLike.Wrap<Single>(Rotation.In.Bytes);
|
||||
var span = Rotation.In.Bytes.Reinterpret<Single>(1);
|
||||
if (Index < span.Length)
|
||||
{
|
||||
return span[Index];
|
||||
@@ -219,107 +219,107 @@ namespace VrmLib
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// モーションの基本姿勢を basePose ベースに再計算する
|
||||
///
|
||||
/// basePose は Humanoid.CopyNodes が必用 !
|
||||
/// </summary>
|
||||
public Animation RebaseAnimation(Humanoid basePose)
|
||||
{
|
||||
var map = NodeMap.ToDictionary(kv => kv.Key, kv => new List<Quaternion>());
|
||||
var hipsPositions = new List<Vector3>();
|
||||
// /// <summary>
|
||||
// /// モーションの基本姿勢を basePose ベースに再計算する
|
||||
// ///
|
||||
// /// basePose は Humanoid.CopyNodes が必用 !
|
||||
// /// </summary>
|
||||
// public Animation RebaseAnimation(Humanoid basePose)
|
||||
// {
|
||||
// var map = NodeMap.ToDictionary(kv => kv.Key, kv => new List<Quaternion>());
|
||||
// var hipsPositions = new List<Vector3>();
|
||||
|
||||
foreach (var (seconds, keyframes) in KeyFramesGroupBySeconds())
|
||||
{
|
||||
// モーション適用
|
||||
SetTime(seconds);
|
||||
Root.CalcWorldMatrix();
|
||||
// foreach (var (seconds, keyframes) in KeyFramesGroupBySeconds())
|
||||
// {
|
||||
// // モーション適用
|
||||
// SetTime(seconds);
|
||||
// Root.CalcWorldMatrix();
|
||||
|
||||
foreach (var keyframe in keyframes)
|
||||
{
|
||||
if (!keyframe.Node.HumanoidBone.HasValue
|
||||
|| keyframe.Node.HumanoidBone.Value == HumanoidBones.unknown)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// foreach (var keyframe in keyframes)
|
||||
// {
|
||||
// if (!keyframe.Node.HumanoidBone.HasValue
|
||||
// || keyframe.Node.HumanoidBone.Value == HumanoidBones.unknown)
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// ローカル回転を算出する
|
||||
var t = basePose[keyframe.Node].Rotation;
|
||||
var w = keyframe.Node.Rotation;
|
||||
var w_from_t = w * Quaternion.Inverse(t);
|
||||
// // ローカル回転を算出する
|
||||
// var t = basePose[keyframe.Node].Rotation;
|
||||
// var w = keyframe.Node.Rotation;
|
||||
// var w_from_t = w * Quaternion.Inverse(t);
|
||||
|
||||
// parent
|
||||
var key = keyframe.Node.HumanoidBone.Value;
|
||||
var curve = map[keyframe.Node];
|
||||
if (key != HumanoidBones.hips)
|
||||
{
|
||||
if (basePose[key].Parent == null)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
var parent_t = basePose[key].Parent.Rotation;
|
||||
var parent_w = keyframe.Node.Parent.Rotation;
|
||||
var parent_w_from_t = parent_w * Quaternion.Inverse(parent_t);
|
||||
// // parent
|
||||
// var key = keyframe.Node.HumanoidBone.Value;
|
||||
// var curve = map[keyframe.Node];
|
||||
// if (key != HumanoidBones.hips)
|
||||
// {
|
||||
// if (basePose[key].Parent == null)
|
||||
// {
|
||||
// throw new Exception();
|
||||
// }
|
||||
// var parent_t = basePose[key].Parent.Rotation;
|
||||
// var parent_w = keyframe.Node.Parent.Rotation;
|
||||
// var parent_w_from_t = parent_w * Quaternion.Inverse(parent_t);
|
||||
|
||||
var r = Quaternion.Inverse(parent_w_from_t) * w_from_t;
|
||||
curve.Add(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
// hips
|
||||
curve.Add(w_from_t);
|
||||
hipsPositions.Add(keyframe.Node.Translation);
|
||||
}
|
||||
}
|
||||
}
|
||||
// var r = Quaternion.Inverse(parent_w_from_t) * w_from_t;
|
||||
// curve.Add(r);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // hips
|
||||
// curve.Add(w_from_t);
|
||||
// hipsPositions.Add(keyframe.Node.Translation);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
var dst = new Animation(Name + ".tpose");
|
||||
foreach (var kv in map)
|
||||
{
|
||||
if (!kv.Value.Any())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// var dst = new Animation(Name + ".tpose");
|
||||
// foreach (var kv in map)
|
||||
// {
|
||||
// if (!kv.Value.Any())
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
var bone = kv.Key.HumanoidBone.Value;
|
||||
// var bone = kv.Key.HumanoidBone.Value;
|
||||
|
||||
var inCurve = NodeMap[kv.Key].Curves[AnimationPathType.Rotation].In;
|
||||
if (inCurve.Count != kv.Value.Count)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
// var inCurve = NodeMap[kv.Key].Curves[AnimationPathType.Rotation].In;
|
||||
// if (inCurve.Count != kv.Value.Count)
|
||||
// {
|
||||
// throw new Exception();
|
||||
// }
|
||||
|
||||
var nodeAnimation = new NodeAnimation();
|
||||
nodeAnimation.Curves.Add(AnimationPathType.Rotation, new CurveSampler
|
||||
{
|
||||
In = inCurve,
|
||||
Out = BufferAccessor.Create(kv.Value.ToArray()),
|
||||
});
|
||||
if (bone == HumanoidBones.hips)
|
||||
{
|
||||
nodeAnimation.Curves.Add(AnimationPathType.Translation, new CurveSampler
|
||||
{
|
||||
In = inCurve,
|
||||
Out = BufferAccessor.Create(hipsPositions.ToArray()),
|
||||
});
|
||||
}
|
||||
dst.AddCurve(kv.Key, nodeAnimation);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
// var nodeAnimation = new NodeAnimation();
|
||||
// nodeAnimation.Curves.Add(AnimationPathType.Rotation, new CurveSampler
|
||||
// {
|
||||
// In = inCurve,
|
||||
// Out = BufferAccessor.Create(kv.Value.ToArray()),
|
||||
// });
|
||||
// if (bone == HumanoidBones.hips)
|
||||
// {
|
||||
// nodeAnimation.Curves.Add(AnimationPathType.Translation, new CurveSampler
|
||||
// {
|
||||
// In = inCurve,
|
||||
// Out = BufferAccessor.Create(hipsPositions.ToArray()),
|
||||
// });
|
||||
// }
|
||||
// dst.AddCurve(kv.Key, nodeAnimation);
|
||||
// }
|
||||
// return dst;
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// 指定された数のフレームを先頭から取り除く
|
||||
/// </summary>
|
||||
public void SkipFrame(int skipFrames)
|
||||
{
|
||||
foreach (var kv in NodeMap)
|
||||
{
|
||||
foreach (var curve in kv.Value.Curves)
|
||||
{
|
||||
curve.Value.SkipFrame(skipFrames);
|
||||
}
|
||||
}
|
||||
}
|
||||
// /// <summary>
|
||||
// /// 指定された数のフレームを先頭から取り除く
|
||||
// /// </summary>
|
||||
// public void SkipFrame(int skipFrames)
|
||||
// {
|
||||
// foreach (var kv in NodeMap)
|
||||
// {
|
||||
// foreach (var curve in kv.Value.Curves)
|
||||
// {
|
||||
// curve.Value.SkipFrame(skipFrames);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,9 @@ namespace VrmLib
|
||||
|
||||
public class BufferAccessor
|
||||
{
|
||||
public ArraySegment<byte> Bytes;
|
||||
public NativeArrayManager ArrayManager { get; }
|
||||
|
||||
public NativeArray<byte> Bytes;
|
||||
|
||||
public AccessorValueType ComponentType;
|
||||
|
||||
@@ -91,19 +93,20 @@ namespace VrmLib
|
||||
|
||||
public int ByteLength => Stride * Count;
|
||||
|
||||
public BufferAccessor(ArraySegment<byte> bytes, AccessorValueType componentType, AccessorVectorType accessorType, int count)
|
||||
public BufferAccessor(NativeArrayManager arrayManager, NativeArray<byte> bytes, AccessorValueType componentType, AccessorVectorType accessorType, int count)
|
||||
{
|
||||
ArrayManager = arrayManager;
|
||||
Bytes = bytes;
|
||||
ComponentType = componentType;
|
||||
AccessorType = accessorType;
|
||||
Count = count;
|
||||
}
|
||||
|
||||
public static BufferAccessor Create<T>(T[] list) where T : struct
|
||||
public static BufferAccessor Create<T>(NativeArrayManager arrayManager, T[] list) where T : struct
|
||||
{
|
||||
var t = typeof(T);
|
||||
var bytes = new byte[list.Length * Marshal.SizeOf(t)];
|
||||
var span = SpanLike.Wrap<T>(new ArraySegment<byte>(bytes));
|
||||
var bytes = arrayManager.CreateNativeArray<byte>(list.Length * Marshal.SizeOf(t));
|
||||
var span = bytes.Reinterpret<T>(1);
|
||||
for (int i = 0; i < list.Length; ++i)
|
||||
{
|
||||
span[i] = list[i];
|
||||
@@ -144,8 +147,7 @@ namespace VrmLib
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
return new BufferAccessor(
|
||||
new ArraySegment<byte>(bytes), componentType, accessorType, list.Length);
|
||||
return new BufferAccessor(arrayManager, bytes, componentType, accessorType, list.Length);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -153,58 +155,56 @@ namespace VrmLib
|
||||
return $"{Stride}stride x{Count}";
|
||||
}
|
||||
|
||||
public SpanLike<T> GetSpan<T>(bool checkStride = true) where T : struct
|
||||
public NativeArray<T> GetSpan<T>(bool checkStride = true) where T : struct
|
||||
{
|
||||
if (checkStride && Marshal.SizeOf(typeof(T)) != Stride)
|
||||
{
|
||||
throw new Exception("different sizeof(T) with stride");
|
||||
}
|
||||
return SpanLike.Wrap<T>(Bytes);
|
||||
return Bytes.Reinterpret<T>(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// バッファをNativeArrayに変換して返す
|
||||
/// 開放の責務は使い手側にある点に注意
|
||||
/// </summary>
|
||||
public unsafe NativeArray<T> AsNativeArray<T>(Allocator allocator) where T : struct
|
||||
{
|
||||
if (Stride == Marshal.SizeOf(typeof(T)))
|
||||
{
|
||||
fixed (byte* byteArray = Bytes.Array)
|
||||
{
|
||||
var nativeArray = new NativeArray<T>(Bytes.Count / Marshal.SizeOf<T>(), allocator);
|
||||
UnsafeUtility.MemCpy(nativeArray.GetUnsafePtr(), byteArray + Bytes.Offset, Bytes.Count);
|
||||
return nativeArray;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (typeof(T) == typeof(SkinJoints) && Stride == 4)
|
||||
{
|
||||
// 例えば SkinJoints を使う JOINTS_0 は UNSIGNED_BYTE と UNSIGNED_SHORT の2種類がありえる。
|
||||
fixed (UShort4* p = GetAsUShort4())
|
||||
{
|
||||
var nativeArray = new NativeArray<T>(Count, allocator);
|
||||
UnsafeUtility.MemCpy(nativeArray.GetUnsafePtr(), p, Bytes.Count);
|
||||
return nativeArray;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"Stride:{Stride}!= sizeof({typeof(T).Name}:{Marshal.SizeOf(typeof(T))}");
|
||||
}
|
||||
}
|
||||
}
|
||||
// /// <summary>
|
||||
// /// バッファをNativeArrayに変換して返す
|
||||
// /// 開放の責務は使い手側にある点に注意
|
||||
// /// </summary>
|
||||
// public unsafe NativeArray<T> AsNativeArray<T>(Allocator allocator) where T : struct
|
||||
// {
|
||||
// if (Stride == Marshal.SizeOf(typeof(T)))
|
||||
// {
|
||||
// fixed (byte* byteArray = Bytes.Array)
|
||||
// {
|
||||
// var nativeArray = new NativeArray<T>(Bytes.Count / Marshal.SizeOf<T>(), allocator);
|
||||
// UnsafeUtility.MemCpy(nativeArray.GetUnsafePtr(), byteArray + Bytes.Offset, Bytes.Count);
|
||||
// return nativeArray;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (typeof(T) == typeof(SkinJoints) && Stride == 4)
|
||||
// {
|
||||
// // 例えば SkinJoints を使う JOINTS_0 は UNSIGNED_BYTE と UNSIGNED_SHORT の2種類がありえる。
|
||||
// fixed (UShort4* p = GetAsUShort4())
|
||||
// {
|
||||
// var nativeArray = new NativeArray<T>(Count, allocator);
|
||||
// UnsafeUtility.MemCpy(nativeArray.GetUnsafePtr(), p, Bytes.Count);
|
||||
// return nativeArray;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// throw new Exception($"Stride:{Stride}!= sizeof({typeof(T).Name}:{Marshal.SizeOf(typeof(T))}");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// バッファをNativeSliceへと書き込む
|
||||
/// </summary>
|
||||
public unsafe void CopyToNativeSlice<T>(NativeSlice<T> destArray) where T : unmanaged
|
||||
{
|
||||
fixed (byte* byteArray = Bytes.Array)
|
||||
{
|
||||
UnsafeUtility.MemCpy((T*)destArray.GetUnsafePtr(), byteArray + Bytes.Offset, Bytes.Count);
|
||||
}
|
||||
var byteArray = NativeArrayUnsafeUtility.GetUnsafePtr(Bytes);
|
||||
UnsafeUtility.MemCpy((T*)destArray.GetUnsafePtr(), byteArray, Bytes.Length);
|
||||
}
|
||||
|
||||
public void Assign<T>(T[] values) where T : struct
|
||||
@@ -213,24 +213,24 @@ namespace VrmLib
|
||||
{
|
||||
throw new Exception("invalid element size");
|
||||
}
|
||||
var array = new byte[Stride * values.Length];
|
||||
Bytes = new ArraySegment<byte>(array);
|
||||
values.ToBytes(Bytes);
|
||||
Bytes = ArrayManager.CreateNativeArray<byte>(Stride * values.Length);
|
||||
Count = values.Length;
|
||||
Bytes.Reinterpret<T>(1).CopyFrom(values);
|
||||
}
|
||||
|
||||
public void Assign<T>(SpanLike<T> values) where T : struct
|
||||
public void Assign<T>(NativeArray<T> values) where T : struct
|
||||
{
|
||||
if (Marshal.SizeOf(typeof(T)) != Stride)
|
||||
{
|
||||
throw new Exception("invalid element size");
|
||||
}
|
||||
Bytes = values.Bytes;
|
||||
Bytes = ArrayManager.CreateNativeArray<byte>(Marshal.SizeOf<T>() * values.Length);
|
||||
NativeArray<T>.Copy(values, Bytes.Reinterpret<T>(1));
|
||||
Count = values.Length;
|
||||
}
|
||||
|
||||
// for index buffer
|
||||
public void AssignAsShort(SpanLike<int> values)
|
||||
public void AssignAsShort(NativeArray<int> values)
|
||||
{
|
||||
if (AccessorType != AccessorVectorType.SCALAR)
|
||||
{
|
||||
@@ -238,17 +238,12 @@ namespace VrmLib
|
||||
}
|
||||
ComponentType = AccessorValueType.UNSIGNED_SHORT;
|
||||
|
||||
Bytes = new ArraySegment<byte>(new byte[Stride * values.Length]);
|
||||
var span = GetSpan<ushort>();
|
||||
Bytes = ArrayManager.Convert(values, (int x) => (ushort)x).Reinterpret<Byte>(Marshal.SizeOf<ushort>());
|
||||
Count = values.Length;
|
||||
for (int i = 0; i < values.Length; ++i)
|
||||
{
|
||||
span[i] = (ushort)values[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Index用
|
||||
public int[] GetAsIntArray()
|
||||
public NativeArray<int> GetAsIntArray()
|
||||
{
|
||||
if (AccessorType != AccessorVectorType.SCALAR)
|
||||
{
|
||||
@@ -257,109 +252,101 @@ namespace VrmLib
|
||||
switch (ComponentType)
|
||||
{
|
||||
case AccessorValueType.UNSIGNED_SHORT:
|
||||
{
|
||||
var span = SpanLike.Wrap<UInt16>(Bytes);
|
||||
var array = new int[span.Length];
|
||||
for (int i = 0; i < span.Length; ++i)
|
||||
{
|
||||
array[i] = span[i];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
return ArrayManager.Convert(Bytes.Reinterpret<ushort>(1), (ushort x) => (int)x);
|
||||
|
||||
case AccessorValueType.UNSIGNED_INT:
|
||||
return SpanLike.Wrap<Int32>(Bytes).ToArray();
|
||||
return Bytes.Reinterpret<Int32>(1);
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public List<int> GetAsIntList()
|
||||
{
|
||||
if (AccessorType != AccessorVectorType.SCALAR)
|
||||
{
|
||||
throw new InvalidOperationException("not scalar");
|
||||
}
|
||||
switch (ComponentType)
|
||||
{
|
||||
case AccessorValueType.UNSIGNED_SHORT:
|
||||
{
|
||||
var span = SpanLike.Wrap<UInt16>(Bytes);
|
||||
var array = new List<int>(Count);
|
||||
if (span.Length != Count)
|
||||
{
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
array.Add(span[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Spanが動かない?WorkAround
|
||||
var bytes = Bytes.ToArray();
|
||||
var offset = 0;
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
array.Add(BitConverter.ToUInt16(bytes, offset));
|
||||
offset += 2;
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
// public List<int> GetAsIntList()
|
||||
// {
|
||||
// if (AccessorType != AccessorVectorType.SCALAR)
|
||||
// {
|
||||
// throw new InvalidOperationException("not scalar");
|
||||
// }
|
||||
// switch (ComponentType)
|
||||
// {
|
||||
// case AccessorValueType.UNSIGNED_SHORT:
|
||||
// {
|
||||
// var span = SpanLike.Wrap<UInt16>(Bytes);
|
||||
// var array = new List<int>(Count);
|
||||
// if (span.Length != Count)
|
||||
// {
|
||||
// for (int i = 0; i < Count; ++i)
|
||||
// {
|
||||
// array.Add(span[i]);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // Spanが動かない?WorkAround
|
||||
// var bytes = Bytes.ToArray();
|
||||
// var offset = 0;
|
||||
// for (int i = 0; i < Count; ++i)
|
||||
// {
|
||||
// array.Add(BitConverter.ToUInt16(bytes, offset));
|
||||
// offset += 2;
|
||||
// }
|
||||
// }
|
||||
// return array;
|
||||
// }
|
||||
|
||||
case AccessorValueType.UNSIGNED_INT:
|
||||
return SpanLike.Wrap<Int32>(Bytes).ToArray().ToList();
|
||||
// case AccessorValueType.UNSIGNED_INT:
|
||||
// return SpanLike.Wrap<Int32>(Bytes).ToArray().ToList();
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
// default:
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
// }
|
||||
|
||||
// Joints用
|
||||
public UShort4[] GetAsUShort4()
|
||||
{
|
||||
if (AccessorType != AccessorVectorType.VEC4)
|
||||
{
|
||||
throw new InvalidOperationException("not vec4");
|
||||
}
|
||||
switch (ComponentType)
|
||||
{
|
||||
case AccessorValueType.UNSIGNED_SHORT:
|
||||
return SpanLike.Wrap<UShort4>(Bytes).ToArray();
|
||||
// // Joints用
|
||||
// public UShort4[] GetAsUShort4()
|
||||
// {
|
||||
// if (AccessorType != AccessorVectorType.VEC4)
|
||||
// {
|
||||
// throw new InvalidOperationException("not vec4");
|
||||
// }
|
||||
// switch (ComponentType)
|
||||
// {
|
||||
// case AccessorValueType.UNSIGNED_SHORT:
|
||||
// return SpanLike.Wrap<UShort4>(Bytes).ToArray();
|
||||
|
||||
case AccessorValueType.UNSIGNED_BYTE:
|
||||
{
|
||||
var array = new UShort4[Count];
|
||||
var span = SpanLike.Wrap<Byte4>(Bytes);
|
||||
for (int i = 0; i < span.Length; ++i)
|
||||
{
|
||||
array[i] = new UShort4(span[i].x, span[i].y, span[i].z, span[i].w);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
// case AccessorValueType.UNSIGNED_BYTE:
|
||||
// {
|
||||
// var array = new UShort4[Count];
|
||||
// var span = SpanLike.Wrap<Byte4>(Bytes);
|
||||
// for (int i = 0; i < span.Length; ++i)
|
||||
// {
|
||||
// array[i] = new UShort4(span[i].x, span[i].y, span[i].z, span[i].w);
|
||||
// }
|
||||
// return array;
|
||||
// }
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
// default:
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
// }
|
||||
|
||||
// Weigt用
|
||||
public Vector4[] GetAsVector4()
|
||||
{
|
||||
if (AccessorType != AccessorVectorType.VEC4)
|
||||
{
|
||||
throw new InvalidOperationException("not vec4");
|
||||
}
|
||||
switch (ComponentType)
|
||||
{
|
||||
case AccessorValueType.FLOAT:
|
||||
return SpanLike.Wrap<Vector4>(Bytes).ToArray();
|
||||
// // Weigt用
|
||||
// public Vector4[] GetAsVector4()
|
||||
// {
|
||||
// if (AccessorType != AccessorVectorType.VEC4)
|
||||
// {
|
||||
// throw new InvalidOperationException("not vec4");
|
||||
// }
|
||||
// switch (ComponentType)
|
||||
// {
|
||||
// case AccessorValueType.FLOAT:
|
||||
// return SpanLike.Wrap<Vector4>(Bytes).ToArray();
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
// default:
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
// }
|
||||
|
||||
public void Resize(int count)
|
||||
{
|
||||
@@ -374,14 +361,14 @@ namespace VrmLib
|
||||
|
||||
void ToByteLength(int byteLength)
|
||||
{
|
||||
var newBytes = new byte[byteLength];
|
||||
Buffer.BlockCopy(Bytes.Array, Bytes.Offset, newBytes, 0, Bytes.Count);
|
||||
Bytes = new ArraySegment<byte>(newBytes);
|
||||
var newBytes = ArrayManager.CreateNativeArray<byte>(byteLength);
|
||||
NativeArray<byte>.Copy(Bytes, newBytes);
|
||||
Bytes = newBytes;
|
||||
}
|
||||
|
||||
public void Extend(int count)
|
||||
{
|
||||
var oldLength = Bytes.Count;
|
||||
var oldLength = Bytes.Length;
|
||||
ToByteLength(oldLength + Stride * count);
|
||||
Count += count;
|
||||
}
|
||||
@@ -406,30 +393,17 @@ namespace VrmLib
|
||||
//ushort to uint
|
||||
case AccessorValueType.UNSIGNED_SHORT:
|
||||
{
|
||||
var src = SpanLike.Wrap<UInt16>(a.Bytes).Slice(0, a.Count);
|
||||
var bytes = new byte[src.Length * 4];
|
||||
var dst = SpanLike.Wrap<UInt32>(new ArraySegment<byte>(bytes));
|
||||
for (int i = 0; i < src.Length; ++i)
|
||||
{
|
||||
dst[i] = (uint)src[i];
|
||||
}
|
||||
var accessor = new BufferAccessor(new ArraySegment<byte>(bytes), AccessorValueType.UNSIGNED_INT, AccessorVectorType.SCALAR, a.Count);
|
||||
var bytes = ArrayManager.Convert(a.Bytes.Reinterpret<UInt16>(1), (UInt16 x) => (UInt32)x).Reinterpret<byte>(Marshal.SizeOf<UInt32>());
|
||||
var accessor = new BufferAccessor(ArrayManager, bytes, AccessorValueType.UNSIGNED_INT, AccessorVectorType.SCALAR, a.Count);
|
||||
a = accessor;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//uint to ushort (おそらく通ることはない)
|
||||
case AccessorValueType.UNSIGNED_INT:
|
||||
{
|
||||
var src = SpanLike.Wrap<UInt32>(a.Bytes).Slice(0, a.Count);
|
||||
var bytes = new byte[src.Length * 2];
|
||||
var dst = SpanLike.Wrap<UInt16>(new ArraySegment<byte>(bytes));
|
||||
for (int i = 0; i < src.Length; ++i)
|
||||
{
|
||||
dst[i] = (ushort)src[i];
|
||||
}
|
||||
var accessor = new BufferAccessor(new ArraySegment<byte>(bytes), ComponentType, AccessorVectorType.SCALAR, a.Count);
|
||||
var bytes = ArrayManager.Convert(a.Bytes.Reinterpret<UInt32>(1), (UInt32 x) => (UInt16)x).Reinterpret<byte>(Marshal.SizeOf<UInt16>());
|
||||
var accessor = new BufferAccessor(ArrayManager, bytes, ComponentType, AccessorVectorType.SCALAR, a.Count);
|
||||
a = accessor;
|
||||
break;
|
||||
}
|
||||
@@ -441,10 +415,10 @@ namespace VrmLib
|
||||
}
|
||||
|
||||
// 連結した新しいバッファを確保
|
||||
var oldLength = Bytes.Count;
|
||||
ToByteLength(oldLength + a.Bytes.Count);
|
||||
var oldLength = Bytes.Length;
|
||||
ToByteLength(oldLength + a.Bytes.Length);
|
||||
// 後ろにコピー
|
||||
Buffer.BlockCopy(a.Bytes.Array, a.Bytes.Offset, Bytes.Array, Bytes.Offset + oldLength, a.Bytes.Count);
|
||||
NativeArray<byte>.Copy(a.Bytes, Bytes.GetSubArray(oldLength, Bytes.Length - oldLength));
|
||||
Count += a.Count;
|
||||
|
||||
if (offset > 0)
|
||||
@@ -454,7 +428,7 @@ namespace VrmLib
|
||||
{
|
||||
case AccessorValueType.UNSIGNED_SHORT:
|
||||
{
|
||||
var span = SpanLike.Wrap<UInt16>(Bytes.Slice(oldLength));
|
||||
var span = Bytes.GetSubArray(oldLength, Bytes.Length - oldLength).Reinterpret<UInt16>(1);
|
||||
var ushortOffset = (ushort)offset;
|
||||
for (int i = 0; i < span.Length; ++i)
|
||||
{
|
||||
@@ -465,7 +439,7 @@ namespace VrmLib
|
||||
|
||||
case AccessorValueType.UNSIGNED_INT:
|
||||
{
|
||||
var span = SpanLike.Wrap<UInt32>(Bytes.Slice(oldLength));
|
||||
var span = Bytes.GetSubArray(oldLength, Bytes.Length - oldLength).Reinterpret<UInt32>(1);
|
||||
var uintOffset = (uint)offset;
|
||||
for (int i = 0; i < span.Length; ++i)
|
||||
{
|
||||
@@ -487,18 +461,16 @@ namespace VrmLib
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
return new BufferAccessor(Bytes.Slice(Stride * skipFrames), ComponentType, AccessorType, Count - skipFrames);
|
||||
var start = Stride * skipFrames;
|
||||
return new BufferAccessor(ArrayManager, Bytes.GetSubArray(start, Bytes.Length - start), ComponentType, AccessorType, Count - skipFrames);
|
||||
}
|
||||
|
||||
public BufferAccessor CloneWithOffset(int offsetCount)
|
||||
{
|
||||
var offsetSize = Stride * offsetCount;
|
||||
var buffer = new byte[offsetSize + Bytes.Count];
|
||||
|
||||
Buffer.BlockCopy(Bytes.Array, Bytes.Offset, buffer, offsetSize, Bytes.Count);
|
||||
|
||||
return new BufferAccessor(new ArraySegment<byte>(buffer), ComponentType, AccessorType, Count + offsetCount);
|
||||
var buffer = ArrayManager.CreateNativeArray<byte>(offsetSize + Bytes.Length);
|
||||
NativeArray<byte>.Copy(Bytes, buffer.GetSubArray(offsetSize, buffer.Length - offsetSize));
|
||||
return new BufferAccessor(ArrayManager, buffer, ComponentType, AccessorType, Count + offsetCount);
|
||||
}
|
||||
|
||||
public void AddTo(Dictionary<string, BufferAccessor> dict, string key)
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using UniGLTF;
|
||||
using Unity.Collections;
|
||||
|
||||
namespace VrmLib
|
||||
{
|
||||
@@ -65,7 +66,7 @@ namespace VrmLib
|
||||
/// indicesの最大値が65535未満(-1を避ける)ならばushort 型で、
|
||||
/// そうでなければ int型で IndexBufferを代入する
|
||||
/// </summary>
|
||||
public void AssignIndexBuffer(SpanLike<int> indices)
|
||||
public void AssignIndexBuffer(NativeArray<int> indices)
|
||||
{
|
||||
bool isInt = false;
|
||||
foreach (var i in indices)
|
||||
@@ -247,8 +248,8 @@ namespace VrmLib
|
||||
{
|
||||
m.Translation = Vector3.Zero;
|
||||
|
||||
var position = SpanLike.Wrap<Vector3>(VertexBuffer.Positions.Bytes);
|
||||
var normal = SpanLike.Wrap<Vector3>(VertexBuffer.Normals.Bytes);
|
||||
var position = VertexBuffer.Positions.Bytes.Reinterpret<Vector3>(1);
|
||||
var normal = VertexBuffer.Normals.Bytes.Reinterpret<Vector3>(1);
|
||||
|
||||
for (int i = 0; i < position.Length; ++i)
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using UniGLTF;
|
||||
using Unity.Collections;
|
||||
|
||||
namespace VrmLib
|
||||
{
|
||||
@@ -223,60 +224,60 @@ namespace VrmLib
|
||||
this.Nodes.Remove(remove);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Nodeを置き換える。参照を置換する。
|
||||
/// </summary>
|
||||
public void NodeReplace(Node src, Node dst)
|
||||
{
|
||||
if (src == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
if (dst == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
// /// <summary>
|
||||
// /// Nodeを置き換える。参照を置換する。
|
||||
// /// </summary>
|
||||
// public void NodeReplace(Node src, Node dst)
|
||||
// {
|
||||
// if (src == null)
|
||||
// {
|
||||
// throw new ArgumentNullException();
|
||||
// }
|
||||
// if (dst == null)
|
||||
// {
|
||||
// throw new ArgumentNullException();
|
||||
// }
|
||||
|
||||
// add dst same parent
|
||||
src.Parent.Add(dst, ChildMatrixMode.KeepWorld);
|
||||
// // add dst same parent
|
||||
// src.Parent.Add(dst, ChildMatrixMode.KeepWorld);
|
||||
|
||||
// remove all child
|
||||
foreach (var child in src.Children.ToArray())
|
||||
{
|
||||
dst.Add(child, ChildMatrixMode.KeepWorld);
|
||||
}
|
||||
// // remove all child
|
||||
// foreach (var child in src.Children.ToArray())
|
||||
// {
|
||||
// dst.Add(child, ChildMatrixMode.KeepWorld);
|
||||
// }
|
||||
|
||||
// remove from parent
|
||||
src.Parent.Remove(src);
|
||||
this.Nodes.Remove(src);
|
||||
// // remove from parent
|
||||
// src.Parent.Remove(src);
|
||||
// this.Nodes.Remove(src);
|
||||
|
||||
// remove from skinning
|
||||
foreach (var skin in this.Skins)
|
||||
{
|
||||
skin.Replace(src, dst);
|
||||
}
|
||||
// // remove from skinning
|
||||
// foreach (var skin in this.Skins)
|
||||
// {
|
||||
// skin.Replace(src, dst);
|
||||
// }
|
||||
|
||||
// fix animation reference
|
||||
foreach (var animation in this.Animations)
|
||||
{
|
||||
if (animation.NodeMap.TryGetValue(src, out NodeAnimation nodeAnimation))
|
||||
{
|
||||
animation.NodeMap.Remove(src);
|
||||
animation.NodeMap.Add(dst, nodeAnimation);
|
||||
}
|
||||
}
|
||||
// // fix animation reference
|
||||
// foreach (var animation in this.Animations)
|
||||
// {
|
||||
// if (animation.NodeMap.TryGetValue(src, out NodeAnimation nodeAnimation))
|
||||
// {
|
||||
// animation.NodeMap.Remove(src);
|
||||
// animation.NodeMap.Add(dst, nodeAnimation);
|
||||
// }
|
||||
// }
|
||||
|
||||
if (this.Nodes.Contains(dst))
|
||||
{
|
||||
throw new Exception("already exists");
|
||||
}
|
||||
this.Nodes.Add(dst);
|
||||
// if (this.Nodes.Contains(dst))
|
||||
// {
|
||||
// throw new Exception("already exists");
|
||||
// }
|
||||
// this.Nodes.Add(dst);
|
||||
|
||||
// TODO: SpringBone
|
||||
}
|
||||
// // TODO: SpringBone
|
||||
// }
|
||||
#endregion
|
||||
|
||||
public string SkinningBake()
|
||||
public string SkinningBake(NativeArrayManager arrayManager)
|
||||
{
|
||||
foreach (var node in this.Nodes)
|
||||
{
|
||||
@@ -294,7 +295,7 @@ namespace VrmLib
|
||||
{
|
||||
{
|
||||
// Skinningの出力先を自身にすることでBakeする
|
||||
meshGroup.Skin.Skinning(mesh.VertexBuffer);
|
||||
meshGroup.Skin.Skinning(arrayManager, mesh.VertexBuffer);
|
||||
}
|
||||
|
||||
// morphのPositionは相対値が入っているはずなので、手を加えない(正規化されていない場合、二重に補正が掛かる)
|
||||
@@ -339,7 +340,7 @@ namespace VrmLib
|
||||
{
|
||||
if (meshGroup.Skin != null)
|
||||
{
|
||||
meshGroup.Skin.CalcInverseMatrices();
|
||||
meshGroup.Skin.CalcInverseMatrices(arrayManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -355,7 +356,7 @@ namespace VrmLib
|
||||
}
|
||||
if (ba.AccessorType == AccessorVectorType.VEC3)
|
||||
{
|
||||
var span = SpanLike.Wrap<Vector3>(ba.Bytes);
|
||||
var span = ba.Bytes.Reinterpret<Vector3>(1);
|
||||
for (int i = 0; i < span.Length; ++i)
|
||||
{
|
||||
span[i] = span[i].ReverseX();
|
||||
@@ -363,7 +364,7 @@ namespace VrmLib
|
||||
}
|
||||
else if (ba.AccessorType == AccessorVectorType.MAT4)
|
||||
{
|
||||
var span = SpanLike.Wrap<Matrix4x4>(ba.Bytes);
|
||||
var span = ba.Bytes.Reinterpret<Matrix4x4>(1);
|
||||
for (int i = 0; i < span.Length; ++i)
|
||||
{
|
||||
span[i] = span[i].ReverseX();
|
||||
@@ -383,7 +384,7 @@ namespace VrmLib
|
||||
}
|
||||
if (ba.AccessorType == AccessorVectorType.VEC3)
|
||||
{
|
||||
var span = SpanLike.Wrap<Vector3>(ba.Bytes);
|
||||
var span = ba.Bytes.Reinterpret<Vector3>(1);
|
||||
for (int i = 0; i < span.Length; ++i)
|
||||
{
|
||||
span[i] = span[i].ReverseZ();
|
||||
@@ -391,7 +392,7 @@ namespace VrmLib
|
||||
}
|
||||
else if (ba.AccessorType == AccessorVectorType.MAT4)
|
||||
{
|
||||
var span = SpanLike.Wrap<Matrix4x4>(ba.Bytes);
|
||||
var span = ba.Bytes.Reinterpret<Matrix4x4>(1);
|
||||
for (int i = 0; i < span.Length; ++i)
|
||||
{
|
||||
span[i] = span[i].ReverseZ();
|
||||
@@ -476,7 +477,7 @@ namespace VrmLib
|
||||
var uv = m.VertexBuffer.TexCoords;
|
||||
if (uv != null)
|
||||
{
|
||||
var span = SpanLike.Wrap<Vector2>(uv.Bytes);
|
||||
var span = uv.Bytes.Reinterpret<Vector2>(1);
|
||||
for (int i = 0; i < span.Length; ++i)
|
||||
{
|
||||
span[i] = span[i].UVVerticalFlip();
|
||||
@@ -495,7 +496,7 @@ namespace VrmLib
|
||||
{
|
||||
// 複数の gltf.accessor が別の要素間で共有されている場合に、2回処理されることを防ぐ
|
||||
// edgecase: InverseBindMatrices で遭遇
|
||||
var unique = new HashSet<ArraySegment<byte>>();
|
||||
var unique = new HashSet<NativeArray<byte>>();
|
||||
|
||||
foreach (var g in MeshGroups)
|
||||
{
|
||||
@@ -521,13 +522,13 @@ namespace VrmLib
|
||||
switch (m.IndexBuffer.ComponentType)
|
||||
{
|
||||
case AccessorValueType.UNSIGNED_BYTE:
|
||||
FlipTriangle(SpanLike.Wrap<Byte>(m.IndexBuffer.Bytes));
|
||||
FlipTriangle(m.IndexBuffer.Bytes);
|
||||
break;
|
||||
case AccessorValueType.UNSIGNED_SHORT:
|
||||
FlipTriangle(SpanLike.Wrap<UInt16>(m.IndexBuffer.Bytes));
|
||||
FlipTriangle(m.IndexBuffer.Bytes.Reinterpret<UInt16>(1));
|
||||
break;
|
||||
case AccessorValueType.UNSIGNED_INT:
|
||||
FlipTriangle(SpanLike.Wrap<UInt32>(m.IndexBuffer.Bytes));
|
||||
FlipTriangle(m.IndexBuffer.Bytes.Reinterpret<UInt32>(1));
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
@@ -580,7 +581,7 @@ namespace VrmLib
|
||||
}
|
||||
}
|
||||
|
||||
static void FlipTriangle(SpanLike<byte> indices)
|
||||
static void FlipTriangle(NativeArray<byte> indices)
|
||||
{
|
||||
for (int i = 0; i < indices.Length; i += 3)
|
||||
{
|
||||
@@ -591,7 +592,7 @@ namespace VrmLib
|
||||
}
|
||||
}
|
||||
|
||||
static void FlipTriangle(SpanLike<ushort> indices)
|
||||
static void FlipTriangle(NativeArray<ushort> indices)
|
||||
{
|
||||
for (int i = 0; i < indices.Length; i += 3)
|
||||
{
|
||||
@@ -602,7 +603,7 @@ namespace VrmLib
|
||||
}
|
||||
}
|
||||
|
||||
static void FlipTriangle(SpanLike<uint> indices)
|
||||
static void FlipTriangle(NativeArray<uint> indices)
|
||||
{
|
||||
for (int i = 0; i < indices.Length; i += 3)
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace VrmLib
|
||||
{
|
||||
if (In.ComponentType == AccessorValueType.FLOAT)
|
||||
{
|
||||
var times = SpanLike.Wrap<Single>(In.Bytes);
|
||||
var times = In.Bytes.Reinterpret<Single>(1);
|
||||
return times[times.Length - 1];
|
||||
}
|
||||
else
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using UniGLTF;
|
||||
using Unity.Collections;
|
||||
|
||||
namespace VrmLib
|
||||
{
|
||||
@@ -29,7 +30,7 @@ namespace VrmLib
|
||||
/// <summary>
|
||||
/// BoneSkinningもしくはMorphTargetの適用
|
||||
/// <summary>
|
||||
public void Skinning(VertexBuffer vertexBuffer = null)
|
||||
public void Skinning(NativeArrayManager arrayManager, VertexBuffer vertexBuffer = null)
|
||||
{
|
||||
m_indexOfRoot = (ushort)Joints.IndexOf(Root);
|
||||
var addRoot = Root != null && m_indexOfRoot == ushort.MaxValue;
|
||||
@@ -46,13 +47,13 @@ namespace VrmLib
|
||||
|
||||
if (InverseMatrices == null)
|
||||
{
|
||||
CalcInverseMatrices();
|
||||
CalcInverseMatrices(arrayManager);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (addRoot)
|
||||
{
|
||||
var inverseArray = SpanLike.Wrap<Matrix4x4>(InverseMatrices.Bytes).ToArray();
|
||||
var inverseArray = InverseMatrices.Bytes.Reinterpret<Matrix4x4>(1);
|
||||
var concat = inverseArray.Concat(new[] { Root.InverseMatrix }).ToArray();
|
||||
InverseMatrices.Assign(concat);
|
||||
}
|
||||
@@ -80,33 +81,33 @@ namespace VrmLib
|
||||
|
||||
if (vertexBuffer != null)
|
||||
{
|
||||
Apply(vertexBuffer);
|
||||
Apply(arrayManager, vertexBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void Apply(VertexBuffer vertexBuffer)
|
||||
void Apply(NativeArrayManager arrayManager, VertexBuffer vertexBuffer)
|
||||
{
|
||||
var dstPosition = SpanLike.Wrap<Vector3>(vertexBuffer.Positions.Bytes);
|
||||
var dstPosition = vertexBuffer.Positions.Bytes.Reinterpret<Vector3>(1);
|
||||
// Span<Vector3> emptyNormal = stackalloc Vector3[0];
|
||||
Apply(vertexBuffer, dstPosition, vertexBuffer.Normals != null ? SpanLike.Wrap<Vector3>(vertexBuffer.Normals.Bytes) : default);
|
||||
Apply(arrayManager, vertexBuffer, dstPosition, vertexBuffer.Normals != null ? vertexBuffer.Normals.Bytes.Reinterpret<Vector3>(1) : default);
|
||||
}
|
||||
|
||||
public void Apply(VertexBuffer vertexBuffer, SpanLike<Vector3> dstPosition, SpanLike<Vector3> dstNormal)
|
||||
public void Apply(NativeArrayManager arrayManager, VertexBuffer vertexBuffer, NativeArray<Vector3> dstPosition, NativeArray<Vector3> dstNormal)
|
||||
{
|
||||
var jointsBuffer = vertexBuffer.Joints;
|
||||
var joints = (jointsBuffer != null || jointsBuffer.Count == 0)
|
||||
? SpanLike.Wrap<SkinJoints>(jointsBuffer.Bytes)
|
||||
: SpanLike.Create<SkinJoints>(vertexBuffer.Count) // when MorphTarget only
|
||||
? jointsBuffer.Bytes.Reinterpret<SkinJoints>(1)
|
||||
: arrayManager.CreateNativeArray<SkinJoints>(vertexBuffer.Count) // when MorphTarget only
|
||||
;
|
||||
|
||||
var weightsBuffer = vertexBuffer.Weights;
|
||||
var weights = (weightsBuffer != null || weightsBuffer.Count == 0)
|
||||
? SpanLike.Wrap<Vector4>(weightsBuffer.Bytes)
|
||||
: SpanLike.Create<Vector4>(vertexBuffer.Count) // when MorphTarget only
|
||||
? weightsBuffer.Bytes.Reinterpret<Vector4>(1)
|
||||
: arrayManager.CreateNativeArray<Vector4>(vertexBuffer.Count) // when MorphTarget only
|
||||
;
|
||||
|
||||
var positionBuffer = vertexBuffer.Positions;
|
||||
var position = SpanLike.Wrap<Vector3>(positionBuffer.Bytes);
|
||||
var position = positionBuffer.Bytes.Reinterpret<Vector3>(1);
|
||||
|
||||
bool useNormal = false;
|
||||
if (dstNormal.Length > 0)
|
||||
@@ -148,7 +149,7 @@ namespace VrmLib
|
||||
if (useNormal)
|
||||
{
|
||||
var normalBuffer = vertexBuffer.Normals;
|
||||
var normal = normalBuffer != null ? SpanLike.Wrap<Vector3>(normalBuffer.Bytes) : dstNormal;
|
||||
var normal = normalBuffer != null ? normalBuffer.Bytes.Reinterpret<Vector3>(1) : dstNormal;
|
||||
var src = new Vector4(normal[i], 0); // 方向ベクトル
|
||||
var dst = Vector4.Zero;
|
||||
if (w.X > 0) dst += Vector4.Transform(src, m_matrices[j.Joint0]) * w.X * factor;
|
||||
@@ -190,7 +191,7 @@ namespace VrmLib
|
||||
if (InverseMatrices != null)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var matrices = SpanLike.Wrap<Matrix4x4>(InverseMatrices.Bytes);
|
||||
var matrices = InverseMatrices.Bytes.Reinterpret<Matrix4x4>(1);
|
||||
var count = 0;
|
||||
// var rootMatrix = Matrix4x4.Identity;
|
||||
// if (Root != null)
|
||||
@@ -221,7 +222,7 @@ namespace VrmLib
|
||||
}
|
||||
}
|
||||
|
||||
public void Replace(Node src, Node dst)
|
||||
public void Replace(NativeArrayManager arrayManager, Node src, Node dst)
|
||||
{
|
||||
var removeIndex = Joints.IndexOf(src);
|
||||
if (removeIndex >= 0)
|
||||
@@ -229,11 +230,11 @@ namespace VrmLib
|
||||
Joints[removeIndex] = dst;
|
||||
|
||||
// エクスポート時に再計算させる
|
||||
CalcInverseMatrices();
|
||||
CalcInverseMatrices(arrayManager);
|
||||
}
|
||||
}
|
||||
|
||||
public void CalcInverseMatrices()
|
||||
public void CalcInverseMatrices(NativeArrayManager arrayManager)
|
||||
{
|
||||
// var root = Root;
|
||||
// if (root == null)
|
||||
@@ -243,8 +244,8 @@ namespace VrmLib
|
||||
// root.CalcWorldMatrix(Matrix4x4.Identity, true);
|
||||
|
||||
// calc inverse bind matrices
|
||||
var matricesBytes = new Byte[Marshal.SizeOf(typeof(Matrix4x4)) * Joints.Count];
|
||||
var matrices = SpanLike.Wrap<Matrix4x4>(new ArraySegment<byte>(matricesBytes));
|
||||
var matricesBytes = arrayManager.CreateNativeArray<Byte>(Marshal.SizeOf(typeof(Matrix4x4)) * Joints.Count);
|
||||
var matrices = matricesBytes.Reinterpret<Matrix4x4>(1);
|
||||
for (int i = 0; i < Joints.Count; ++i)
|
||||
{
|
||||
// var w = Joints[i].Matrix;
|
||||
@@ -254,7 +255,7 @@ namespace VrmLib
|
||||
matrices[i] = Joints[i].InverseMatrix;
|
||||
}
|
||||
}
|
||||
InverseMatrices = new BufferAccessor(new ArraySegment<byte>(matricesBytes), AccessorValueType.FLOAT, AccessorVectorType.MAT4, Joints.Count);
|
||||
InverseMatrices = new BufferAccessor(arrayManager, matricesBytes, AccessorValueType.FLOAT, AccessorVectorType.MAT4, Joints.Count);
|
||||
}
|
||||
|
||||
static void Update(ref float weight, ref ushort index, int[] indexMap)
|
||||
@@ -276,38 +277,38 @@ namespace VrmLib
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// nullになったjointを除去して、boneweightを前に詰める
|
||||
/// </summary>
|
||||
public void FixBoneWeight(BufferAccessor jointsAccessor, BufferAccessor weightsAccessor)
|
||||
{
|
||||
var map = Joints.Select((x, i) => ValueTuple.Create(i, x)).Where(x => x.Item2 != null).ToArray();
|
||||
var indexMap = Enumerable.Repeat(-1, Joints.Count).ToArray();
|
||||
{
|
||||
for (int i = 0; i < map.Length; ++i)
|
||||
{
|
||||
indexMap[map[i].Item1] = i;
|
||||
}
|
||||
}
|
||||
Joints.RemoveAll(x => x == null);
|
||||
// /// <summary>
|
||||
// /// nullになったjointを除去して、boneweightを前に詰める
|
||||
// /// </summary>
|
||||
// public void FixBoneWeight(BufferAccessor jointsAccessor, BufferAccessor weightsAccessor)
|
||||
// {
|
||||
// var map = Joints.Select((x, i) => ValueTuple.Create(i, x)).Where(x => x.Item2 != null).ToArray();
|
||||
// var indexMap = Enumerable.Repeat(-1, Joints.Count).ToArray();
|
||||
// {
|
||||
// for (int i = 0; i < map.Length; ++i)
|
||||
// {
|
||||
// indexMap[map[i].Item1] = i;
|
||||
// }
|
||||
// }
|
||||
// Joints.RemoveAll(x => x == null);
|
||||
|
||||
var joints = jointsAccessor.GetSpan<SkinJoints>();
|
||||
var weights = weightsAccessor.GetSpan<Vector4>();
|
||||
for (int i = 0; i < joints.Length; ++i)
|
||||
{
|
||||
var j = joints[i];
|
||||
var w = weights[i];
|
||||
// var joints = jointsAccessor.GetSpan<SkinJoints>();
|
||||
// var weights = weightsAccessor.GetSpan<Vector4>();
|
||||
// for (int i = 0; i < joints.Length; ++i)
|
||||
// {
|
||||
// var j = joints[i];
|
||||
// var w = weights[i];
|
||||
|
||||
Update(ref w.X, ref j.Joint0, indexMap);
|
||||
Update(ref w.Y, ref j.Joint1, indexMap);
|
||||
Update(ref w.Z, ref j.Joint2, indexMap);
|
||||
Update(ref w.W, ref j.Joint3, indexMap);
|
||||
// Update(ref w.X, ref j.Joint0, indexMap);
|
||||
// Update(ref w.Y, ref j.Joint1, indexMap);
|
||||
// Update(ref w.Z, ref j.Joint2, indexMap);
|
||||
// Update(ref w.W, ref j.Joint3, indexMap);
|
||||
|
||||
joints[i] = j;
|
||||
weights[i] = w;
|
||||
}
|
||||
// joints[i] = j;
|
||||
// weights[i] = w;
|
||||
// }
|
||||
|
||||
CalcInverseMatrices();
|
||||
}
|
||||
// CalcInverseMatrices();
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -196,33 +196,33 @@ namespace VrmLib
|
||||
return vb;
|
||||
}
|
||||
|
||||
public SpanLike<SkinJoints> GetOrCreateJoints()
|
||||
{
|
||||
var buffer = Joints;
|
||||
if (buffer == null)
|
||||
{
|
||||
buffer = new BufferAccessor(
|
||||
new ArraySegment<byte>(new byte[Marshal.SizeOf(typeof(SkinJoints)) * Count]),
|
||||
AccessorValueType.UNSIGNED_SHORT,
|
||||
AccessorVectorType.VEC4, Count);
|
||||
Add(JointKey, buffer);
|
||||
}
|
||||
return SpanLike.Wrap<SkinJoints>(buffer.Bytes);
|
||||
}
|
||||
// public SpanLike<SkinJoints> GetOrCreateJoints()
|
||||
// {
|
||||
// var buffer = Joints;
|
||||
// if (buffer == null)
|
||||
// {
|
||||
// buffer = new BufferAccessor(
|
||||
// new ArraySegment<byte>(new byte[Marshal.SizeOf(typeof(SkinJoints)) * Count]),
|
||||
// AccessorValueType.UNSIGNED_SHORT,
|
||||
// AccessorVectorType.VEC4, Count);
|
||||
// Add(JointKey, buffer);
|
||||
// }
|
||||
// return SpanLike.Wrap<SkinJoints>(buffer.Bytes);
|
||||
// }
|
||||
|
||||
public SpanLike<Vector4> GetOrCreateWeights()
|
||||
{
|
||||
var buffer = Weights;
|
||||
if (buffer == null)
|
||||
{
|
||||
buffer = new BufferAccessor(
|
||||
new ArraySegment<byte>(new byte[Marshal.SizeOf(typeof(Vector4)) * Count]),
|
||||
AccessorValueType.FLOAT,
|
||||
AccessorVectorType.VEC4, Count);
|
||||
Add(WeightKey, buffer);
|
||||
}
|
||||
return SpanLike.Wrap<Vector4>(buffer.Bytes);
|
||||
}
|
||||
// public SpanLike<Vector4> GetOrCreateWeights()
|
||||
// {
|
||||
// var buffer = Weights;
|
||||
// if (buffer == null)
|
||||
// {
|
||||
// buffer = new BufferAccessor(
|
||||
// new ArraySegment<byte>(new byte[Marshal.SizeOf(typeof(Vector4)) * Count]),
|
||||
// AccessorValueType.FLOAT,
|
||||
// AccessorVectorType.VEC4, Count);
|
||||
// Add(WeightKey, buffer);
|
||||
// }
|
||||
// return SpanLike.Wrap<Vector4>(buffer.Bytes);
|
||||
// }
|
||||
|
||||
static bool HasSameKeys<T>(Dictionary<string, T> lhs, Dictionary<string, T> rhs)
|
||||
{
|
||||
@@ -237,48 +237,48 @@ namespace VrmLib
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Append(VertexBuffer v)
|
||||
{
|
||||
var keys = VertexBuffers.Keys.ToList();
|
||||
// public void Append(VertexBuffer v)
|
||||
// {
|
||||
// var keys = VertexBuffers.Keys.ToList();
|
||||
|
||||
var lastCount = Count;
|
||||
// var lastCount = Count;
|
||||
|
||||
// v から VertexBufferfs に足す
|
||||
foreach (var kv in v.VertexBuffers)
|
||||
{
|
||||
if (VertexBuffers.TryGetValue(kv.Key, out BufferAccessor buffer))
|
||||
{
|
||||
// used
|
||||
keys.Remove(kv.Key);
|
||||
if (buffer.Count != lastCount)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// add empty
|
||||
var byteLength = lastCount * kv.Value.Stride;
|
||||
buffer = new BufferAccessor(new ArraySegment<byte>(new byte[byteLength]), kv.Value.ComponentType, kv.Value.AccessorType, lastCount);
|
||||
if (buffer.Count != lastCount)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
VertexBuffers.Add(kv.Key, buffer);
|
||||
}
|
||||
// // v から VertexBufferfs に足す
|
||||
// foreach (var kv in v.VertexBuffers)
|
||||
// {
|
||||
// if (VertexBuffers.TryGetValue(kv.Key, out BufferAccessor buffer))
|
||||
// {
|
||||
// // used
|
||||
// keys.Remove(kv.Key);
|
||||
// if (buffer.Count != lastCount)
|
||||
// {
|
||||
// throw new ArgumentException();
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // add empty
|
||||
// var byteLength = lastCount * kv.Value.Stride;
|
||||
// buffer = new BufferAccessor(new ArraySegment<byte>(new byte[byteLength]), kv.Value.ComponentType, kv.Value.AccessorType, lastCount);
|
||||
// if (buffer.Count != lastCount)
|
||||
// {
|
||||
// throw new ArgumentException();
|
||||
// }
|
||||
// VertexBuffers.Add(kv.Key, buffer);
|
||||
// }
|
||||
|
||||
buffer.Append(kv.Value);
|
||||
}
|
||||
// buffer.Append(kv.Value);
|
||||
// }
|
||||
|
||||
// 足されなかったキーに同じ長さを詰める
|
||||
foreach (var key in keys)
|
||||
{
|
||||
var dst = VertexBuffers[key];
|
||||
dst.Extend(v.Positions.Count);
|
||||
}
|
||||
// // 足されなかったキーに同じ長さを詰める
|
||||
// foreach (var key in keys)
|
||||
// {
|
||||
// var dst = VertexBuffers[key];
|
||||
// dst.Extend(v.Positions.Count);
|
||||
// }
|
||||
|
||||
ValidateLength();
|
||||
}
|
||||
// ValidateLength();
|
||||
// }
|
||||
|
||||
public void Resize(int n)
|
||||
{
|
||||
|
||||
@@ -20,15 +20,15 @@ namespace VrmLibTests
|
||||
model.NodeAdd(node1, node0);
|
||||
Assert.AreEqual(2, model.Nodes.Count);
|
||||
|
||||
var node2 = new Node("node2");
|
||||
model.NodeReplace(node0, node2);
|
||||
Assert.AreEqual(2, model.Nodes.Count);
|
||||
Assert.AreEqual(node2, model.Nodes[1]);
|
||||
Assert.AreEqual(1, node2.Children.Count);
|
||||
// var node2 = new Node("node2");
|
||||
// model.NodeReplace(node0, node2);
|
||||
// Assert.AreEqual(2, model.Nodes.Count);
|
||||
// Assert.AreEqual(node2, model.Nodes[1]);
|
||||
// Assert.AreEqual(1, node2.Children.Count);
|
||||
|
||||
model.NodeRemove(node1);
|
||||
Assert.AreEqual(1, model.Nodes.Count);
|
||||
Assert.AreEqual(0, node2.Children.Count);
|
||||
// model.NodeRemove(node1);
|
||||
// Assert.AreEqual(1, model.Nodes.Count);
|
||||
// Assert.AreEqual(0, node2.Children.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user