From b98c2f852fd63c90c4fd8a611dd9283e98f774d0 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 10 Feb 2022 22:23:39 +0900 Subject: [PATCH] BufferAccessor use NativeArray --- .../Runtime/UniGLTF/IO/ArrayByteBuffer.cs | 8 +- .../Runtime/UniGLTF/IO/ExportingGltfData.cs | 3 +- Assets/VRM10/Editor/Vrm10ExportDialog.cs | 47 +-- .../VRM10/Runtime/IO/BufferAccessorAdapter.cs | 83 ++--- Assets/VRM10/Runtime/IO/Model/MeshImporter.cs | 26 +- .../Runtime/IO/Model/MeshImporterDivided.cs | 27 +- Assets/VRM10/Runtime/IO/Model/MeshWriter.cs | 61 ++-- .../VRM10/Runtime/IO/Model/ModelExporter.cs | 71 ++-- Assets/VRM10/Runtime/IO/Vrm10Exporter.cs | 51 +-- Assets/VRM10/Runtime/IO/Vrm10ImportData.cs | 6 +- Assets/VRM10/Runtime/IO/Vrm10Importer.cs | 2 +- Assets/VRM10/Runtime/Migration/MeshUpdater.cs | 29 +- Assets/VRM10/Tests.PlayMode/MaterialTests.cs | 13 +- Assets/VRM10/vrmlib/Runtime/Animation.cs | 186 +++++----- Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs | 332 ++++++++---------- Assets/VRM10/vrmlib/Runtime/Mesh.cs | 7 +- Assets/VRM10/vrmlib/Runtime/Model.cs | 119 +++---- Assets/VRM10/vrmlib/Runtime/NodeAnimation.cs | 2 +- Assets/VRM10/vrmlib/Runtime/Skin.cs | 101 +++--- Assets/VRM10/vrmlib/Runtime/VertexBuffer.cs | 126 +++---- Assets/VRM10/vrmlib/Tests/ModifierTests.cs | 16 +- 21 files changed, 646 insertions(+), 670 deletions(-) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ArrayByteBuffer.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ArrayByteBuffer.cs index 462d3c891..722c1f8c2 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ArrayByteBuffer.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ArrayByteBuffer.cs @@ -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(NativeArray array, glBufferTarget target = default) where T : struct + { + return Extend(new ArraySegment(array.ToArray()), target); + } + public glTFBufferView Extend(ArraySegment array, glBufferTarget target = default) where T : struct { using (var pin = Pin.Create(array)) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs index a785af7a3..94903c2b9 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs @@ -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 segment) + public int AppendToBuffer(NativeArray segment) { var gltfBufferView = _buffer.Extend(segment); var viewIndex = Gltf.bufferViews.Count; diff --git a/Assets/VRM10/Editor/Vrm10ExportDialog.cs b/Assets/VRM10/Editor/Vrm10ExportDialog.cs index cab5d65c9..b2518cd9c 100644 --- a/Assets/VRM10/Editor/Vrm10ExportDialog.cs +++ b/Assets/VRM10/Editor/Vrm10ExportDialog.cs @@ -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) diff --git a/Assets/VRM10/Runtime/IO/BufferAccessorAdapter.cs b/Assets/VRM10/Runtime/IO/BufferAccessorAdapter.cs index 2b403e3c0..c3ae9509c 100644 --- a/Assets/VRM10/Runtime/IO/BufferAccessorAdapter.cs +++ b/Assets/VRM10/Runtime/IO/BufferAccessorAdapter.cs @@ -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, glTFAccessor> minMax = null, + Action, 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, glTFAccessor> minMax = null, + Action, 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(new byte[sparseValuesWithIndex.Count * 4]); - var sparseIndexSpan = SpanLike.Wrap(sparseIndexBin); - var sparseValueBin = new ArraySegment(new byte[sparseValuesWithIndex.Count * 12]); - var sparseValueSpan = SpanLike.Wrap(sparseValueBin); - - for (int i = 0; i < sparseValuesWithIndex.Count; ++i) + using (var sparseIndexBin = new NativeArray(sparseValuesWithIndex.Count * 4, Allocator.Persistent)) + using (var sparseValueBin = new NativeArray(sparseValuesWithIndex.Count * 12, Allocator.Persistent)) { - var (index, value) = sparseValuesWithIndex[i]; - sparseIndexSpan[i] = index; - sparseValueSpan[i] = value; - } + var sparseIndexSpan = sparseIndexBin.Reinterpret(1); + var sparseValueSpan = sparseValueBin.Reinterpret(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; } } diff --git a/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs b/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs index 7fdf0c4fe..aa86ff17b 100644 --- a/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs +++ b/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs @@ -23,12 +23,12 @@ namespace UniVRM10 Profiler.BeginSample("MeshImporter.LoadSharedMesh"); var mesh = new Mesh(); - var positions = src.VertexBuffer.Positions.AsNativeArray(Allocator.TempJob); - var normals = src.VertexBuffer.Normals?.AsNativeArray(Allocator.TempJob) ?? default; - var texCoords = src.VertexBuffer.TexCoords?.AsNativeArray(Allocator.TempJob) ?? default; - var colors = src.VertexBuffer.Colors?.AsNativeArray(Allocator.TempJob) ?? default; - var weights = src.VertexBuffer.Weights?.AsNativeArray(Allocator.TempJob) ?? default; - var joints = src.VertexBuffer.Joints?.AsNativeArray(Allocator.TempJob) ?? default; + var positions = src.VertexBuffer.Positions.Bytes.Reinterpret(1); + var normals = src.VertexBuffer.Normals?.Bytes.Reinterpret(1) ?? default; + var texCoords = src.VertexBuffer.TexCoords?.Bytes.Reinterpret(1) ?? default; + var colors = src.VertexBuffer.Colors?.Bytes.Reinterpret(1) ?? default; + var weights = src.VertexBuffer.Weights?.Bytes.Reinterpret(1) ?? default; + var joints = src.VertexBuffer.Joints?.Bytes.Reinterpret(1) ?? default; using (var vertices = new NativeArray(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(Allocator.Temp); + var shortIndices = src.IndexBuffer.Bytes.Reinterpret(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(Allocator.Temp); + var intIndices = src.IndexBuffer.Bytes.Reinterpret(1); mesh.SetIndexBufferParams(intIndices.Length, IndexFormat.UInt32); mesh.SetIndexBufferData(intIndices, 0, 0, intIndices.Length); - intIndices.Dispose(); break; default: throw new NotImplementedException(); diff --git a/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs b/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs index f27badeea..bda8578c2 100644 --- a/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs +++ b/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs @@ -126,8 +126,7 @@ namespace UniVRM10 case AccessorValueType.SHORT: { // unsigned short -> unsigned short - var source = mesh.IndexBuffer.AsNativeArray(Allocator.TempJob); - disposables.Add(source); + var source = mesh.IndexBuffer.Bytes.Reinterpret(1); jobHandle = new CopyIndicesJobs.Ushort2Ushort( (ushort)vertexOffset, new NativeSlice(source), @@ -138,8 +137,7 @@ namespace UniVRM10 case AccessorValueType.UNSIGNED_INT: { // unsigned int -> unsigned short - var source = mesh.IndexBuffer.AsNativeArray(Allocator.TempJob); - disposables.Add(source); + var source = mesh.IndexBuffer.Bytes.Reinterpret(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(Allocator.TempJob); - disposables.Add(source); + var source = mesh.IndexBuffer.Bytes.Reinterpret(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(Allocator.TempJob); - disposables.Add(source); + var source = mesh.IndexBuffer.Bytes.Reinterpret(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(Allocator.TempJob); - var normals = mesh.VertexBuffer.Normals.AsNativeArray(Allocator.TempJob); - var texCoords = mesh.VertexBuffer.TexCoords.AsNativeArray(Allocator.TempJob); + var positions = mesh.VertexBuffer.Positions.Bytes.Reinterpret(1); + var normals = mesh.VertexBuffer.Normals.Bytes.Reinterpret(1); + var texCoords = mesh.VertexBuffer.TexCoords.Bytes.Reinterpret(1); var weights = meshGroup.Skin != null - ? mesh.VertexBuffer.Weights.AsNativeArray(Allocator.TempJob) + ? mesh.VertexBuffer.Weights.Bytes.Reinterpret(1) : default; var joints = meshGroup.Skin != null - ? mesh.VertexBuffer.Joints.AsNativeArray(Allocator.TempJob) + ? mesh.VertexBuffer.Joints.Bytes.Reinterpret(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(vertices, indexOffset, mesh.VertexBuffer.Count), diff --git a/Assets/VRM10/Runtime/IO/Model/MeshWriter.cs b/Assets/VRM10/Runtime/IO/Model/MeshWriter.cs index 236a2492d..d63bba48d 100644 --- a/Assets/VRM10/Runtime/IO/Model/MeshWriter.cs +++ b/Assets/VRM10/Runtime/IO/Model/MeshWriter.cs @@ -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().Slice(offset, count); - var bytes = new byte[src.Length * 2]; - var dst = SpanLike.Wrap(new ArraySegment(bytes)); - for (int i = 0; i < src.Length; ++i) - { - dst[i] = (ushort)src[i]; - } - var accessor = new BufferAccessor(new ArraySegment(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().Slice(offset, count); + // var bytes = new byte[src.Length * 2]; + // var dst = SpanLike.Wrap(new ArraySegment(bytes)); + // for (int i = 0; i < src.Length; ++i) + // { + // dst[i] = (ushort)src[i]; + // } + // var accessor = new BufferAccessor(new ArraySegment(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); + // } + // } /// /// https://github.com/vrm-c/UniVRM/issues/800 @@ -69,7 +70,7 @@ namespace UniVRM10 ExportingGltfData writer, ExportArgs option) { var usedIndices = new List(); - var meshIndices = SpanLike.CopyFrom(mesh.IndexBuffer.GetAsIntArray()); + var meshIndices = mesh.IndexBuffer.GetAsIntArray(); var positions = mesh.VertexBuffer.Positions.GetSpan().ToArray(); var normals = mesh.VertexBuffer.Normals.GetSpan().ToArray(); var uv = mesh.VertexBuffer.TexCoords.GetSpan().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(indices); // mesh @@ -131,7 +132,7 @@ namespace UniVRM10 // index の順に attributes を蓄える var morph = mesh.MorphTargets[j]; var blendShapePositions = morph.VertexBuffer.Positions.GetSpan(); - SpanLike? blendShapeNormals = default; + NativeArray? blendShapeNormals = default; if (morph.VertexBuffer.Normals != null) { blendShapeNormals = morph.VertexBuffer.Normals.GetSpan(); diff --git a/Assets/VRM10/Runtime/IO/Model/ModelExporter.cs b/Assets/VRM10/Runtime/IO/Model/ModelExporter.cs index 6ac424cde..3efa9caae 100644 --- a/Assets/VRM10/Runtime/IO/Model/ModelExporter.cs +++ b/Assets/VRM10/Runtime/IO/Model/ModelExporter.cs @@ -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 /// /// /// - 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(); 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 materials) + private static VrmLib.MeshGroup CreateMesh(NativeArrayManager arrayManager, UnityEngine.Mesh mesh, Renderer renderer, List 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 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[] value, VrmLib.AccessorValueType valueType, VrmLib.AccessorVectorType vectorType) where T : struct + private static VrmLib.BufferAccessor ToBufferAccessor(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(Marshal.SizeOf()), valueType, vectorType, value.Length diff --git a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs index 53fb1847a..bc3cfbee2 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs @@ -70,7 +70,7 @@ namespace UniVRM10 } } - public static IEnumerable<(glTFNode, glTFSkin)> ExportNodes(List nodes, List groups, ExportingGltfData data, ExportArgs option) + public static IEnumerable<(glTFNode, glTFSkin)> ExportNodes(NativeArrayManager arrayManager, List nodes, List 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 /// 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(); + } } } } diff --git a/Assets/VRM10/Runtime/IO/Vrm10ImportData.cs b/Assets/VRM10/Runtime/IO/Vrm10ImportData.cs index 8c1fab866..2f477104e 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10ImportData.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10ImportData.cs @@ -202,7 +202,7 @@ namespace UniVRM10 var accessor = Gltf.accessors[accessorIndex]; var bytes = GetAccessorBytes(accessorIndex); var vectorType = EnumUtil.Parse(accessor.type); - ba = new BufferAccessor(new ArraySegment(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(bytes.ToArray()), + return new BufferAccessor(m_data.NativeArrayManager, bytes, (AccessorValueType)firstAccessor.componentType, EnumUtil.Parse(firstAccessor.type), totalCount); @@ -339,7 +339,7 @@ namespace UniVRM10 throw new NotImplementedException($"accessor.componentType: {accessor.componentType}"); } } - return new BufferAccessor(new ArraySegment(indices.ToArray()), AccessorValueType.UNSIGNED_INT, AccessorVectorType.SCALAR, totalCount); + return new BufferAccessor(m_data.NativeArrayManager, indices, AccessorValueType.UNSIGNED_INT, AccessorVectorType.SCALAR, totalCount); } } } diff --git a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs index c9951949c..a57022852 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs @@ -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}"); } diff --git a/Assets/VRM10/Runtime/Migration/MeshUpdater.cs b/Assets/VRM10/Runtime/Migration/MeshUpdater.cs index f20040456..ce62da032 100644 --- a/Assets/VRM10/Runtime/Migration/MeshUpdater.cs +++ b/Assets/VRM10/Runtime/Migration/MeshUpdater.cs @@ -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 bytes) + int AddBuffer(NativeArray bytes) { var bufferView = _buffer.Extend(bytes); var index = _bufferViews.Count; @@ -31,9 +33,9 @@ namespace UniVRM10 return index; } - int AddAccessor(SpanLike span) where T : struct + int AddAccessor(NativeArray span) where T : struct { - var bufferViewIndex = AddBuffer(span.Bytes); + var bufferViewIndex = AddBuffer(span.Reinterpret(Marshal.SizeOf())); 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(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 indices; + NativeArray indices; switch (mesh.IndexBuffer.Stride) { case 1: { // byte var byte_indices = mesh.IndexBuffer.GetSpan(); - indices = SpanLike.Create(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(); - indices = SpanLike.Create(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()); gltf.skins.Add(gltfSkin); } - else{ + else + { // multi nodes sharing a same skin may be error ? // edge case. } diff --git a/Assets/VRM10/Tests.PlayMode/MaterialTests.cs b/Assets/VRM10/Tests.PlayMode/MaterialTests.cs index 9b817596c..3026c4d0b 100644 --- a/Assets/VRM10/Tests.PlayMode/MaterialTests.cs +++ b/Assets/VRM10/Tests.PlayMode/MaterialTests.cs @@ -31,7 +31,7 @@ namespace UniVRM10.Test private (GameObject, IReadOnlyList) 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) diff --git a/Assets/VRM10/vrmlib/Runtime/Animation.cs b/Assets/VRM10/vrmlib/Runtime/Animation.cs index 975d81bac..77a650fdb 100644 --- a/Assets/VRM10/vrmlib/Runtime/Animation.cs +++ b/Assets/VRM10/vrmlib/Runtime/Animation.cs @@ -128,7 +128,7 @@ namespace VrmLib { get { - var span = SpanLike.Wrap(Rotation.In.Bytes); + var span = Rotation.In.Bytes.Reinterpret(1); if (Index < span.Length) { return span[Index]; @@ -219,107 +219,107 @@ namespace VrmLib } } - /// - /// モーションの基本姿勢を basePose ベースに再計算する - /// - /// basePose は Humanoid.CopyNodes が必用 ! - /// - public Animation RebaseAnimation(Humanoid basePose) - { - var map = NodeMap.ToDictionary(kv => kv.Key, kv => new List()); - var hipsPositions = new List(); + // /// + // /// モーションの基本姿勢を basePose ベースに再計算する + // /// + // /// basePose は Humanoid.CopyNodes が必用 ! + // /// + // public Animation RebaseAnimation(Humanoid basePose) + // { + // var map = NodeMap.ToDictionary(kv => kv.Key, kv => new List()); + // var hipsPositions = new List(); - 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; + // } - /// - /// 指定された数のフレームを先頭から取り除く - /// - public void SkipFrame(int skipFrames) - { - foreach (var kv in NodeMap) - { - foreach (var curve in kv.Value.Curves) - { - curve.Value.SkipFrame(skipFrames); - } - } - } + // /// + // /// 指定された数のフレームを先頭から取り除く + // /// + // public void SkipFrame(int skipFrames) + // { + // foreach (var kv in NodeMap) + // { + // foreach (var curve in kv.Value.Curves) + // { + // curve.Value.SkipFrame(skipFrames); + // } + // } + // } } } diff --git a/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs b/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs index 4d8c81ef4..5000e5431 100644 --- a/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs +++ b/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs @@ -79,7 +79,9 @@ namespace VrmLib public class BufferAccessor { - public ArraySegment Bytes; + public NativeArrayManager ArrayManager { get; } + + public NativeArray Bytes; public AccessorValueType ComponentType; @@ -91,19 +93,20 @@ namespace VrmLib public int ByteLength => Stride * Count; - public BufferAccessor(ArraySegment bytes, AccessorValueType componentType, AccessorVectorType accessorType, int count) + public BufferAccessor(NativeArrayManager arrayManager, NativeArray bytes, AccessorValueType componentType, AccessorVectorType accessorType, int count) { + ArrayManager = arrayManager; Bytes = bytes; ComponentType = componentType; AccessorType = accessorType; Count = count; } - public static BufferAccessor Create(T[] list) where T : struct + public static BufferAccessor Create(NativeArrayManager arrayManager, T[] list) where T : struct { var t = typeof(T); - var bytes = new byte[list.Length * Marshal.SizeOf(t)]; - var span = SpanLike.Wrap(new ArraySegment(bytes)); + var bytes = arrayManager.CreateNativeArray(list.Length * Marshal.SizeOf(t)); + var span = bytes.Reinterpret(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(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 GetSpan(bool checkStride = true) where T : struct + public NativeArray GetSpan(bool checkStride = true) where T : struct { if (checkStride && Marshal.SizeOf(typeof(T)) != Stride) { throw new Exception("different sizeof(T) with stride"); } - return SpanLike.Wrap(Bytes); + return Bytes.Reinterpret(1); } - /// - /// バッファをNativeArrayに変換して返す - /// 開放の責務は使い手側にある点に注意 - /// - public unsafe NativeArray AsNativeArray(Allocator allocator) where T : struct - { - if (Stride == Marshal.SizeOf(typeof(T))) - { - fixed (byte* byteArray = Bytes.Array) - { - var nativeArray = new NativeArray(Bytes.Count / Marshal.SizeOf(), 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(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))}"); - } - } - } + // /// + // /// バッファをNativeArrayに変換して返す + // /// 開放の責務は使い手側にある点に注意 + // /// + // public unsafe NativeArray AsNativeArray(Allocator allocator) where T : struct + // { + // if (Stride == Marshal.SizeOf(typeof(T))) + // { + // fixed (byte* byteArray = Bytes.Array) + // { + // var nativeArray = new NativeArray(Bytes.Count / Marshal.SizeOf(), 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(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))}"); + // } + // } + // } /// /// バッファをNativeSliceへと書き込む /// public unsafe void CopyToNativeSlice(NativeSlice 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[] 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(array); - values.ToBytes(Bytes); + Bytes = ArrayManager.CreateNativeArray(Stride * values.Length); Count = values.Length; + Bytes.Reinterpret(1).CopyFrom(values); } - public void Assign(SpanLike values) where T : struct + public void Assign(NativeArray values) where T : struct { if (Marshal.SizeOf(typeof(T)) != Stride) { throw new Exception("invalid element size"); } - Bytes = values.Bytes; + Bytes = ArrayManager.CreateNativeArray(Marshal.SizeOf() * values.Length); + NativeArray.Copy(values, Bytes.Reinterpret(1)); Count = values.Length; } // for index buffer - public void AssignAsShort(SpanLike values) + public void AssignAsShort(NativeArray values) { if (AccessorType != AccessorVectorType.SCALAR) { @@ -238,17 +238,12 @@ namespace VrmLib } ComponentType = AccessorValueType.UNSIGNED_SHORT; - Bytes = new ArraySegment(new byte[Stride * values.Length]); - var span = GetSpan(); + Bytes = ArrayManager.Convert(values, (int x) => (ushort)x).Reinterpret(Marshal.SizeOf()); Count = values.Length; - for (int i = 0; i < values.Length; ++i) - { - span[i] = (ushort)values[i]; - } } // Index用 - public int[] GetAsIntArray() + public NativeArray GetAsIntArray() { if (AccessorType != AccessorVectorType.SCALAR) { @@ -257,109 +252,101 @@ namespace VrmLib switch (ComponentType) { case AccessorValueType.UNSIGNED_SHORT: - { - var span = SpanLike.Wrap(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(1), (ushort x) => (int)x); case AccessorValueType.UNSIGNED_INT: - return SpanLike.Wrap(Bytes).ToArray(); + return Bytes.Reinterpret(1); default: throw new NotImplementedException(); } } - public List GetAsIntList() - { - if (AccessorType != AccessorVectorType.SCALAR) - { - throw new InvalidOperationException("not scalar"); - } - switch (ComponentType) - { - case AccessorValueType.UNSIGNED_SHORT: - { - var span = SpanLike.Wrap(Bytes); - var array = new List(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 GetAsIntList() + // { + // if (AccessorType != AccessorVectorType.SCALAR) + // { + // throw new InvalidOperationException("not scalar"); + // } + // switch (ComponentType) + // { + // case AccessorValueType.UNSIGNED_SHORT: + // { + // var span = SpanLike.Wrap(Bytes); + // var array = new List(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(Bytes).ToArray().ToList(); + // case AccessorValueType.UNSIGNED_INT: + // return SpanLike.Wrap(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(Bytes).ToArray(); + // // Joints用 + // public UShort4[] GetAsUShort4() + // { + // if (AccessorType != AccessorVectorType.VEC4) + // { + // throw new InvalidOperationException("not vec4"); + // } + // switch (ComponentType) + // { + // case AccessorValueType.UNSIGNED_SHORT: + // return SpanLike.Wrap(Bytes).ToArray(); - case AccessorValueType.UNSIGNED_BYTE: - { - var array = new UShort4[Count]; - var span = SpanLike.Wrap(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(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(Bytes).ToArray(); + // // Weigt用 + // public Vector4[] GetAsVector4() + // { + // if (AccessorType != AccessorVectorType.VEC4) + // { + // throw new InvalidOperationException("not vec4"); + // } + // switch (ComponentType) + // { + // case AccessorValueType.FLOAT: + // return SpanLike.Wrap(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(newBytes); + var newBytes = ArrayManager.CreateNativeArray(byteLength); + NativeArray.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(a.Bytes).Slice(0, a.Count); - var bytes = new byte[src.Length * 4]; - var dst = SpanLike.Wrap(new ArraySegment(bytes)); - for (int i = 0; i < src.Length; ++i) - { - dst[i] = (uint)src[i]; - } - var accessor = new BufferAccessor(new ArraySegment(bytes), AccessorValueType.UNSIGNED_INT, AccessorVectorType.SCALAR, a.Count); + var bytes = ArrayManager.Convert(a.Bytes.Reinterpret(1), (UInt16 x) => (UInt32)x).Reinterpret(Marshal.SizeOf()); + 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(a.Bytes).Slice(0, a.Count); - var bytes = new byte[src.Length * 2]; - var dst = SpanLike.Wrap(new ArraySegment(bytes)); - for (int i = 0; i < src.Length; ++i) - { - dst[i] = (ushort)src[i]; - } - var accessor = new BufferAccessor(new ArraySegment(bytes), ComponentType, AccessorVectorType.SCALAR, a.Count); + var bytes = ArrayManager.Convert(a.Bytes.Reinterpret(1), (UInt32 x) => (UInt16)x).Reinterpret(Marshal.SizeOf()); + 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.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(Bytes.Slice(oldLength)); + var span = Bytes.GetSubArray(oldLength, Bytes.Length - oldLength).Reinterpret(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(Bytes.Slice(oldLength)); + var span = Bytes.GetSubArray(oldLength, Bytes.Length - oldLength).Reinterpret(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(buffer), ComponentType, AccessorType, Count + offsetCount); + var buffer = ArrayManager.CreateNativeArray(offsetSize + Bytes.Length); + NativeArray.Copy(Bytes, buffer.GetSubArray(offsetSize, buffer.Length - offsetSize)); + return new BufferAccessor(ArrayManager, buffer, ComponentType, AccessorType, Count + offsetCount); } public void AddTo(Dictionary dict, string key) diff --git a/Assets/VRM10/vrmlib/Runtime/Mesh.cs b/Assets/VRM10/vrmlib/Runtime/Mesh.cs index e58faa97f..0751bc610 100644 --- a/Assets/VRM10/vrmlib/Runtime/Mesh.cs +++ b/Assets/VRM10/vrmlib/Runtime/Mesh.cs @@ -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を代入する /// - public void AssignIndexBuffer(SpanLike indices) + public void AssignIndexBuffer(NativeArray indices) { bool isInt = false; foreach (var i in indices) @@ -247,8 +248,8 @@ namespace VrmLib { m.Translation = Vector3.Zero; - var position = SpanLike.Wrap(VertexBuffer.Positions.Bytes); - var normal = SpanLike.Wrap(VertexBuffer.Normals.Bytes); + var position = VertexBuffer.Positions.Bytes.Reinterpret(1); + var normal = VertexBuffer.Normals.Bytes.Reinterpret(1); for (int i = 0; i < position.Length; ++i) { diff --git a/Assets/VRM10/vrmlib/Runtime/Model.cs b/Assets/VRM10/vrmlib/Runtime/Model.cs index 12d17c194..7234845f6 100644 --- a/Assets/VRM10/vrmlib/Runtime/Model.cs +++ b/Assets/VRM10/vrmlib/Runtime/Model.cs @@ -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); } - /// - /// Nodeを置き換える。参照を置換する。 - /// - public void NodeReplace(Node src, Node dst) - { - if (src == null) - { - throw new ArgumentNullException(); - } - if (dst == null) - { - throw new ArgumentNullException(); - } + // /// + // /// Nodeを置き換える。参照を置換する。 + // /// + // 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(ba.Bytes); + var span = ba.Bytes.Reinterpret(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(ba.Bytes); + var span = ba.Bytes.Reinterpret(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(ba.Bytes); + var span = ba.Bytes.Reinterpret(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(ba.Bytes); + var span = ba.Bytes.Reinterpret(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(uv.Bytes); + var span = uv.Bytes.Reinterpret(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>(); + var unique = new HashSet>(); foreach (var g in MeshGroups) { @@ -521,13 +522,13 @@ namespace VrmLib switch (m.IndexBuffer.ComponentType) { case AccessorValueType.UNSIGNED_BYTE: - FlipTriangle(SpanLike.Wrap(m.IndexBuffer.Bytes)); + FlipTriangle(m.IndexBuffer.Bytes); break; case AccessorValueType.UNSIGNED_SHORT: - FlipTriangle(SpanLike.Wrap(m.IndexBuffer.Bytes)); + FlipTriangle(m.IndexBuffer.Bytes.Reinterpret(1)); break; case AccessorValueType.UNSIGNED_INT: - FlipTriangle(SpanLike.Wrap(m.IndexBuffer.Bytes)); + FlipTriangle(m.IndexBuffer.Bytes.Reinterpret(1)); break; default: throw new NotImplementedException(); @@ -580,7 +581,7 @@ namespace VrmLib } } - static void FlipTriangle(SpanLike indices) + static void FlipTriangle(NativeArray indices) { for (int i = 0; i < indices.Length; i += 3) { @@ -591,7 +592,7 @@ namespace VrmLib } } - static void FlipTriangle(SpanLike indices) + static void FlipTriangle(NativeArray indices) { for (int i = 0; i < indices.Length; i += 3) { @@ -602,7 +603,7 @@ namespace VrmLib } } - static void FlipTriangle(SpanLike indices) + static void FlipTriangle(NativeArray indices) { for (int i = 0; i < indices.Length; i += 3) { diff --git a/Assets/VRM10/vrmlib/Runtime/NodeAnimation.cs b/Assets/VRM10/vrmlib/Runtime/NodeAnimation.cs index 642910979..c4aa312cf 100644 --- a/Assets/VRM10/vrmlib/Runtime/NodeAnimation.cs +++ b/Assets/VRM10/vrmlib/Runtime/NodeAnimation.cs @@ -25,7 +25,7 @@ namespace VrmLib { if (In.ComponentType == AccessorValueType.FLOAT) { - var times = SpanLike.Wrap(In.Bytes); + var times = In.Bytes.Reinterpret(1); return times[times.Length - 1]; } else diff --git a/Assets/VRM10/vrmlib/Runtime/Skin.cs b/Assets/VRM10/vrmlib/Runtime/Skin.cs index d87689c0f..e788469a8 100644 --- a/Assets/VRM10/vrmlib/Runtime/Skin.cs +++ b/Assets/VRM10/vrmlib/Runtime/Skin.cs @@ -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 /// /// BoneSkinningもしくはMorphTargetの適用 /// - 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(InverseMatrices.Bytes).ToArray(); + var inverseArray = InverseMatrices.Bytes.Reinterpret(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(vertexBuffer.Positions.Bytes); + var dstPosition = vertexBuffer.Positions.Bytes.Reinterpret(1); // Span emptyNormal = stackalloc Vector3[0]; - Apply(vertexBuffer, dstPosition, vertexBuffer.Normals != null ? SpanLike.Wrap(vertexBuffer.Normals.Bytes) : default); + Apply(arrayManager, vertexBuffer, dstPosition, vertexBuffer.Normals != null ? vertexBuffer.Normals.Bytes.Reinterpret(1) : default); } - public void Apply(VertexBuffer vertexBuffer, SpanLike dstPosition, SpanLike dstNormal) + public void Apply(NativeArrayManager arrayManager, VertexBuffer vertexBuffer, NativeArray dstPosition, NativeArray dstNormal) { var jointsBuffer = vertexBuffer.Joints; var joints = (jointsBuffer != null || jointsBuffer.Count == 0) - ? SpanLike.Wrap(jointsBuffer.Bytes) - : SpanLike.Create(vertexBuffer.Count) // when MorphTarget only + ? jointsBuffer.Bytes.Reinterpret(1) + : arrayManager.CreateNativeArray(vertexBuffer.Count) // when MorphTarget only ; var weightsBuffer = vertexBuffer.Weights; var weights = (weightsBuffer != null || weightsBuffer.Count == 0) - ? SpanLike.Wrap(weightsBuffer.Bytes) - : SpanLike.Create(vertexBuffer.Count) // when MorphTarget only + ? weightsBuffer.Bytes.Reinterpret(1) + : arrayManager.CreateNativeArray(vertexBuffer.Count) // when MorphTarget only ; var positionBuffer = vertexBuffer.Positions; - var position = SpanLike.Wrap(positionBuffer.Bytes); + var position = positionBuffer.Bytes.Reinterpret(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(normalBuffer.Bytes) : dstNormal; + var normal = normalBuffer != null ? normalBuffer.Bytes.Reinterpret(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(InverseMatrices.Bytes); + var matrices = InverseMatrices.Bytes.Reinterpret(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(new ArraySegment(matricesBytes)); + var matricesBytes = arrayManager.CreateNativeArray(Marshal.SizeOf(typeof(Matrix4x4)) * Joints.Count); + var matrices = matricesBytes.Reinterpret(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(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 } } - /// - /// nullになったjointを除去して、boneweightを前に詰める - /// - 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); + // /// + // /// nullになったjointを除去して、boneweightを前に詰める + // /// + // 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(); - var weights = weightsAccessor.GetSpan(); - for (int i = 0; i < joints.Length; ++i) - { - var j = joints[i]; - var w = weights[i]; + // var joints = jointsAccessor.GetSpan(); + // var weights = weightsAccessor.GetSpan(); + // 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(); + // } } } \ No newline at end of file diff --git a/Assets/VRM10/vrmlib/Runtime/VertexBuffer.cs b/Assets/VRM10/vrmlib/Runtime/VertexBuffer.cs index 6d23fafb0..37168892e 100644 --- a/Assets/VRM10/vrmlib/Runtime/VertexBuffer.cs +++ b/Assets/VRM10/vrmlib/Runtime/VertexBuffer.cs @@ -196,33 +196,33 @@ namespace VrmLib return vb; } - public SpanLike GetOrCreateJoints() - { - var buffer = Joints; - if (buffer == null) - { - buffer = new BufferAccessor( - new ArraySegment(new byte[Marshal.SizeOf(typeof(SkinJoints)) * Count]), - AccessorValueType.UNSIGNED_SHORT, - AccessorVectorType.VEC4, Count); - Add(JointKey, buffer); - } - return SpanLike.Wrap(buffer.Bytes); - } + // public SpanLike GetOrCreateJoints() + // { + // var buffer = Joints; + // if (buffer == null) + // { + // buffer = new BufferAccessor( + // new ArraySegment(new byte[Marshal.SizeOf(typeof(SkinJoints)) * Count]), + // AccessorValueType.UNSIGNED_SHORT, + // AccessorVectorType.VEC4, Count); + // Add(JointKey, buffer); + // } + // return SpanLike.Wrap(buffer.Bytes); + // } - public SpanLike GetOrCreateWeights() - { - var buffer = Weights; - if (buffer == null) - { - buffer = new BufferAccessor( - new ArraySegment(new byte[Marshal.SizeOf(typeof(Vector4)) * Count]), - AccessorValueType.FLOAT, - AccessorVectorType.VEC4, Count); - Add(WeightKey, buffer); - } - return SpanLike.Wrap(buffer.Bytes); - } + // public SpanLike GetOrCreateWeights() + // { + // var buffer = Weights; + // if (buffer == null) + // { + // buffer = new BufferAccessor( + // new ArraySegment(new byte[Marshal.SizeOf(typeof(Vector4)) * Count]), + // AccessorValueType.FLOAT, + // AccessorVectorType.VEC4, Count); + // Add(WeightKey, buffer); + // } + // return SpanLike.Wrap(buffer.Bytes); + // } static bool HasSameKeys(Dictionary lhs, Dictionary 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(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(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) { diff --git a/Assets/VRM10/vrmlib/Tests/ModifierTests.cs b/Assets/VRM10/vrmlib/Tests/ModifierTests.cs index c0b963f14..b59a58932 100644 --- a/Assets/VRM10/vrmlib/Tests/ModifierTests.cs +++ b/Assets/VRM10/vrmlib/Tests/ModifierTests.cs @@ -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); } } }