From a3674a992bb91f9ab34440207f9841407abe2dea Mon Sep 17 00:00:00 2001 From: notargs Date: Fri, 12 Nov 2021 13:25:03 +0900 Subject: [PATCH 01/12] =?UTF-8?q?UniVRM10=E3=81=AEVertex=E3=81=AE=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E3=82=92New=20Mesh=20API=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UniGLTF/Runtime/UniGLTF/IO/SkinJoint.cs | 1 + .../IO/Model/InterleaveMeshVerticesJob.cs | 65 +++++++++++++++ .../Model/InterleaveMeshVerticesJob.cs.meta | 3 + Assets/VRM10/Runtime/IO/Model/MeshImporter.cs | 81 +++++++++++-------- .../Runtime/IO/Model/MeshImporterDivided.cs | 50 ++++++------ Assets/VRM10/Runtime/IO/Model/MeshVertex.cs | 70 ++++++++++++++++ .../VRM10/Runtime/IO/Model/MeshVertex.cs.meta | 3 + Assets/VRM10/Runtime/VRM10.asmdef | 11 ++- Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs | 21 +++++ Assets/VRM10/vrmlib/Runtime/VrmLib.asmdef | 2 +- 10 files changed, 247 insertions(+), 60 deletions(-) create mode 100644 Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs create mode 100644 Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs.meta create mode 100644 Assets/VRM10/Runtime/IO/Model/MeshVertex.cs create mode 100644 Assets/VRM10/Runtime/IO/Model/MeshVertex.cs.meta diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/SkinJoint.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/SkinJoint.cs index 6e38e6642..5c2ec357f 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/SkinJoint.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/SkinJoint.cs @@ -2,6 +2,7 @@ using System; namespace UniGLTF { + [Serializable] public struct SkinJoints : IEquatable { public ushort Joint0; diff --git a/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs b/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs new file mode 100644 index 000000000..ac77288cf --- /dev/null +++ b/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs @@ -0,0 +1,65 @@ +using UniGLTF; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Jobs; +using UnityEngine; + +#if ENABLE_VRM10_BURST +using Unity.Burst; +#endif + +namespace UniVRM10 +{ + #if ENABLE_VRM10_BURST + [BurstCompile] + #endif + internal struct InterleaveMeshVerticesJob : IJobParallelFor + { + [WriteOnly] private NativeArray _vertices; + + [ReadOnly] private readonly NativeArray _positions; + + // default値を許容する + [ReadOnly, NativeDisableContainerSafetyRestriction] private readonly NativeArray _normals; + [ReadOnly, NativeDisableContainerSafetyRestriction] private readonly NativeArray _texCoords; + [ReadOnly, NativeDisableContainerSafetyRestriction] private readonly NativeArray _colors; + [ReadOnly, NativeDisableContainerSafetyRestriction] private readonly NativeArray _weights; + [ReadOnly, NativeDisableContainerSafetyRestriction] private readonly NativeArray _joints; + + public InterleaveMeshVerticesJob( + NativeArray vertices, + NativeArray positions, + NativeArray normals = default, + NativeArray texCoords = default, + NativeArray colors = default, + NativeArray weights = default, + NativeArray joints = default) + { + _vertices = vertices; + _positions = positions; + _normals = normals; + _texCoords = texCoords; + _colors = colors; + _weights = weights; + _joints = joints; + } + + public void Execute(int index) + { + _vertices[index] = new MeshVertex( + _positions[index], + _normals.IsCreated ? _normals[index] : Vector3.zero, + _texCoords.IsCreated ? _texCoords[index] : Vector2.zero, + _colors.IsCreated ? _colors[index] : Color.white, + _joints.IsCreated ? _joints[index].Joint0 : (ushort)0, + _joints.IsCreated ? _joints[index].Joint1 : (ushort)0, + _joints.IsCreated ? _joints[index].Joint2 : (ushort)0, + _joints.IsCreated ? _joints[index].Joint3 : (ushort)0, + _weights.IsCreated ? _weights[index].x : 0, + _weights.IsCreated ? _weights[index].y : 0, + _weights.IsCreated ? _weights[index].z : 0, + _weights.IsCreated ? _weights[index].w : 0 + ); + } + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs.meta b/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs.meta new file mode 100644 index 000000000..6a54c7ebc --- /dev/null +++ b/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 01d2fcab0a3941fa9cf2e4f1a641105b +timeCreated: 1636688648 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs b/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs index 3e0c382e2..13a98092a 100644 --- a/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs +++ b/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs @@ -1,6 +1,9 @@ using System; using UniGLTF; +using Unity.Collections; +using Unity.Jobs; using UnityEngine; +using UnityEngine.Profiling; namespace UniVRM10 { @@ -12,55 +15,63 @@ namespace UniVRM10 /// /// /// - public static UnityEngine.Mesh LoadSharedMesh(VrmLib.Mesh src, VrmLib.Skin skin = null) + public static Mesh LoadSharedMesh(VrmLib.Mesh src, VrmLib.Skin skin = null) { - // submesh 方式 - var mesh = new UnityEngine.Mesh(); - if (src.IndexBuffer.Count > UInt16.MaxValue) + Profiler.BeginSample("MeshImporter.LoadSharedMesh"); + var mesh = new Mesh(); + if (src.IndexBuffer.Count > ushort.MaxValue) { mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; } - mesh.vertices = src.VertexBuffer.Positions.GetSpan().ToArray(); - mesh.normals = src.VertexBuffer.Normals?.GetSpan().ToArray(); - mesh.uv = src.VertexBuffer.TexCoords?.GetSpan().ToArray(); - mesh.colors = src.VertexBuffer.Colors?.GetSpan().ToArray(); - if (src.VertexBuffer.Weights != null && src.VertexBuffer.Joints != null) + var positions = src.VertexBuffer.Positions.GetNativeArray(Allocator.TempJob); + var normals = src.VertexBuffer.Normals?.GetNativeArray(Allocator.TempJob) ?? default; + var texCoords = src.VertexBuffer.TexCoords?.GetNativeArray(Allocator.TempJob) ?? default; + var colors = src.VertexBuffer.Colors?.GetNativeArray(Allocator.TempJob) ?? default; + var weights = src.VertexBuffer.Weights?.GetNativeArray(Allocator.TempJob) ?? default; + var joints = src.VertexBuffer.Joints?.GetNativeArray(Allocator.TempJob) ?? default; + + var vertices = new NativeArray(positions.Length, Allocator.TempJob); + + // JobとBindPoseの更新を並行して行う + var jobHandle = + new InterleaveMeshVerticesJob(vertices, positions, normals, texCoords, colors, weights, joints) + .Schedule(vertices.Length, 1); + + if (weights.IsCreated && joints.IsCreated) { - var boneWeights = new BoneWeight[mesh.vertexCount]; - if (src.VertexBuffer.Weights.Count != mesh.vertexCount || src.VertexBuffer.Joints.Count != mesh.vertexCount) + if (weights.Length != positions.Length || joints.Length != positions.Length) { throw new ArgumentException(); } - var weights = src.VertexBuffer.Weights.GetSpan(); - var joints = src.VertexBuffer.Joints.GetSpan(); if (skin != null) { mesh.bindposes = skin.InverseMatrices.GetSpan().ToArray(); } - - for (int i = 0; i < weights.Length; ++i) - { - var w = weights[i]; - boneWeights[i].weight0 = w.x; - boneWeights[i].weight1 = w.y; - boneWeights[i].weight2 = w.z; - boneWeights[i].weight3 = w.w; - } - for (int i = 0; i < joints.Length; ++i) - { - var j = joints[i]; - boneWeights[i].boneIndex0 = j.Joint0; - boneWeights[i].boneIndex1 = j.Joint1; - boneWeights[i].boneIndex2 = j.Joint2; - boneWeights[i].boneIndex3 = j.Joint3; - } - mesh.boneWeights = boneWeights; } + // 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); + + // 出力のNativeArrayを開放 + vertices.Dispose(); + + // submesh 方式 mesh.subMeshCount = src.Submeshes.Count; var triangles = src.IndexBuffer.GetAsIntList(); - for (int i = 0; i < src.Submeshes.Count; ++i) + for (var i = 0; i < src.Submeshes.Count; ++i) { var submesh = src.Submeshes[i]; mesh.SetTriangles(triangles.GetRange(submesh.Offset, submesh.DrawCount), i); @@ -68,16 +79,18 @@ namespace UniVRM10 foreach (var morphTarget in src.MorphTargets) { - var positions = + var morphTargetPositions = morphTarget.VertexBuffer.Positions != null ? morphTarget.VertexBuffer.Positions.GetSpan().ToArray() : new Vector3[mesh.vertexCount] // dummy ; - mesh.AddBlendShapeFrame(morphTarget.Name, 100.0f, positions, null, null); + mesh.AddBlendShapeFrame(morphTarget.Name, 100.0f, morphTargetPositions, null, null); } mesh.RecalculateBounds(); mesh.RecalculateTangents(); + + Profiler.EndSample(); return mesh; } diff --git a/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs b/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs index b2b108139..4f489e0ac 100644 --- a/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs +++ b/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Linq; using UniGLTF; using UnityEngine; +using UnityEngine.Profiling; +using Mesh = VrmLib.Mesh; namespace UniVRM10 { @@ -9,6 +11,8 @@ namespace UniVRM10 { public static UnityEngine.Mesh LoadDivided(VrmLib.MeshGroup src) { + Profiler.BeginSample("MeshImporterDivided.LoadDivided"); + var dst = new UnityEngine.Mesh(); if (src.Meshes.Sum(x => x.IndexBuffer.Count) > ushort.MaxValue) { @@ -23,32 +27,30 @@ namespace UniVRM10 var normals = new List(vertexCount); var uv = new List(vertexCount); var boneWeights = new List(vertexCount); - for (int meshIndex = 0; meshIndex < src.Meshes.Count; ++meshIndex) + + foreach (var mesh in src.Meshes) { - var mesh = src.Meshes[meshIndex]; positions.AddRange(mesh.VertexBuffer.Positions.GetSpan()); normals.AddRange(mesh.VertexBuffer.Normals.GetSpan()); uv.AddRange(mesh.VertexBuffer.TexCoords.GetSpan()); - if (src.Skin != null) + if (src.Skin == null) continue; + var joints = mesh.VertexBuffer.Joints.GetSpan(); + var weights = mesh.VertexBuffer.Weights.GetSpan(); + for (var i = 0; i < mesh.VertexBuffer.Count; ++i) { - var j = mesh.VertexBuffer.Joints.GetSpan(); - var w = mesh.VertexBuffer.Weights.GetSpan(); - for (int i = 0; i < mesh.VertexBuffer.Count; ++i) + var joint = joints[i]; + var weight = weights[i]; + boneWeights.Add(new BoneWeight { - var jj = j[i]; - var ww = w[i]; - boneWeights.Add(new BoneWeight - { - boneIndex0 = jj.Joint0, - boneIndex1 = jj.Joint1, - boneIndex2 = jj.Joint2, - boneIndex3 = jj.Joint3, - weight0 = ww.x, - weight1 = ww.y, - weight2 = ww.z, - weight3 = ww.w, - }); - } + boneIndex0 = joint.Joint0, + boneIndex1 = joint.Joint1, + boneIndex2 = joint.Joint2, + boneIndex3 = joint.Joint3, + weight0 = weight.x, + weight1 = weight.y, + weight2 = weight.z, + weight3 = weight.w, + }); } } @@ -74,7 +76,7 @@ namespace UniVRM10 // dst.subMeshCount = src.Meshes.Count; var offset = 0; - for (int meshIndex = 0; meshIndex < src.Meshes.Count; ++meshIndex) + for (var meshIndex = 0; meshIndex < src.Meshes.Count; ++meshIndex) { var mesh = src.Meshes[meshIndex]; var indices = mesh.IndexBuffer.GetAsIntArray().Select(x => offset + x).ToArray(); @@ -89,12 +91,12 @@ namespace UniVRM10 // blendshape // var blendShapeCount = src.Meshes[0].MorphTargets.Count; - for (int i = 0; i < blendShapeCount; ++i) + for (var i = 0; i < blendShapeCount; ++i) { positions.Clear(); normals.Clear(); var name = src.Meshes[0].MorphTargets[i].Name; - for (int meshIndex = 0; meshIndex < src.Meshes.Count; ++meshIndex) + for (var meshIndex = 0; meshIndex < src.Meshes.Count; ++meshIndex) { var morphTarget = src.Meshes[meshIndex].MorphTargets[i]; positions.AddRange(morphTarget.VertexBuffer.Positions.GetSpan()); @@ -111,6 +113,8 @@ namespace UniVRM10 dst.AddBlendShapeFrame(name, 100.0f, positions.ToArray(), normals.ToArray(), null); } + Profiler.EndSample(); + return dst; } } diff --git a/Assets/VRM10/Runtime/IO/Model/MeshVertex.cs b/Assets/VRM10/Runtime/IO/Model/MeshVertex.cs new file mode 100644 index 000000000..d5bdd34d5 --- /dev/null +++ b/Assets/VRM10/Runtime/IO/Model/MeshVertex.cs @@ -0,0 +1,70 @@ +using System.Runtime.InteropServices; +using UnityEditor.UI; +using UnityEngine; +using UnityEngine.Rendering; + +namespace UniVRM10 +{ + /// + /// インターリーブされたメッシュの頂点情報を表す構造体 + /// そのままGPUにアップロードされる + /// + [StructLayout(LayoutKind.Sequential)] + internal readonly struct MeshVertex + { + private readonly Vector3 _position; + private readonly Vector3 _normal; + private readonly Color _color; + private readonly Vector2 _texCoord; + private readonly float _boneWeight0; + private readonly float _boneWeight1; + private readonly float _boneWeight2; + private readonly float _boneWeight3; + private readonly ushort _boneIndex0; + private readonly ushort _boneIndex1; + private readonly ushort _boneIndex2; + private readonly ushort _boneIndex3; + + public MeshVertex( + Vector3 position, + Vector3 normal, + Vector2 texCoord, + Color color, + ushort boneIndex0, + ushort boneIndex1, + ushort boneIndex2, + ushort boneIndex3, + float boneWeight0, + float boneWeight1, + float boneWeight2, + float boneWeight3) + { + _position = position; + _normal = normal; + _texCoord = texCoord; + _color = color; + _boneIndex0 = boneIndex0; + _boneIndex1 = boneIndex1; + _boneIndex2 = boneIndex2; + _boneIndex3 = boneIndex3; + _boneWeight0 = boneWeight0; + _boneWeight1 = boneWeight1; + _boneWeight2 = boneWeight2; + _boneWeight3 = boneWeight3; + } + + private static readonly VertexAttributeDescriptor[] vertexAttributeDescriptor = { + new VertexAttributeDescriptor(VertexAttribute.Position), + new VertexAttributeDescriptor(VertexAttribute.Normal), + new VertexAttributeDescriptor(VertexAttribute.Color, dimension: 4), + new VertexAttributeDescriptor(VertexAttribute.TexCoord0, dimension: 2), + new VertexAttributeDescriptor(VertexAttribute.BlendWeight, dimension: 4), + new VertexAttributeDescriptor(VertexAttribute.BlendIndices, VertexAttributeFormat.UInt16, 4), + }; + + public static void SetVertexBufferParamsToMesh(Mesh mesh, int length) + { + mesh.SetVertexBufferParams(length, vertexAttributeDescriptor); + } + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/IO/Model/MeshVertex.cs.meta b/Assets/VRM10/Runtime/IO/Model/MeshVertex.cs.meta new file mode 100644 index 000000000..0e80ae0bd --- /dev/null +++ b/Assets/VRM10/Runtime/IO/Model/MeshVertex.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 78c70746c10e46bc97de0a7afedb23c7 +timeCreated: 1636625951 \ No newline at end of file diff --git a/Assets/VRM10/Runtime/VRM10.asmdef b/Assets/VRM10/Runtime/VRM10.asmdef index b65ef4c5a..e8a38f04c 100644 --- a/Assets/VRM10/Runtime/VRM10.asmdef +++ b/Assets/VRM10/Runtime/VRM10.asmdef @@ -8,7 +8,8 @@ "GUID:bce005214fa49654d93927908c15b1f2", "GUID:0aaf403bd13871a44b7127aef2695ff8", "GUID:b7aa47b240b57de44a4b2021c143c9bf", - "GUID:f2ca1407928ebdc4bbe7765cc278be44" + "GUID:f2ca1407928ebdc4bbe7765cc278be44", + "GUID:2665a8d13d1b3f18800f46e256720795" ], "includePlatforms": [], "excludePlatforms": [], @@ -17,6 +18,12 @@ "precompiledReferences": [], "autoReferenced": true, "defineConstraints": [], - "versionDefines": [], + "versionDefines": [ + { + "name": "com.unity.burst", + "expression": "0.0.1", + "define": "ENABLE_VRM10_BURST" + } + ], "noEngineReferences": false } \ No newline at end of file diff --git a/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs b/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs index 0d6336e7e..90b6e5405 100644 --- a/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs +++ b/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs @@ -4,6 +4,8 @@ using System.Linq; using System.Numerics; using System.Runtime.InteropServices; using UniGLTF; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; namespace VrmLib { @@ -103,6 +105,25 @@ namespace VrmLib return SpanLike.Wrap(Bytes); } + /// + /// バッファをNativeArrayに変換して返す + /// 開放の責務は使い手側にある点に注意 + /// + public unsafe NativeArray GetNativeArray(Allocator allocator, bool checkStride = true) where T : struct + { + if (checkStride && Marshal.SizeOf(typeof(T)) != Stride) + { + throw new Exception("different sizeof(T) with stride"); + } + + 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; + } + } + public void Assign(T[] values) where T : struct { if (Marshal.SizeOf(typeof(T)) != Stride) diff --git a/Assets/VRM10/vrmlib/Runtime/VrmLib.asmdef b/Assets/VRM10/vrmlib/Runtime/VrmLib.asmdef index d3ffc1a7f..0e41a1f25 100644 --- a/Assets/VRM10/vrmlib/Runtime/VrmLib.asmdef +++ b/Assets/VRM10/vrmlib/Runtime/VrmLib.asmdef @@ -5,7 +5,7 @@ ], "includePlatforms": [], "excludePlatforms": [], - "allowUnsafeCode": false, + "allowUnsafeCode": true, "overrideReferences": false, "precompiledReferences": [], "autoReferenced": false, From c8fff439fb8a05304de00d6e43038f839e90a1c8 Mon Sep 17 00:00:00 2001 From: notargs Date: Fri, 12 Nov 2021 13:28:31 +0900 Subject: [PATCH 02/12] Add comment --- Assets/VRM10/Runtime/IO/Model/MeshImporter.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs b/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs index 13a98092a..90cd2cf84 100644 --- a/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs +++ b/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs @@ -38,6 +38,7 @@ namespace UniVRM10 new InterleaveMeshVerticesJob(vertices, positions, normals, texCoords, colors, weights, joints) .Schedule(vertices.Length, 1); + // BindPoseを更新 if (weights.IsCreated && joints.IsCreated) { if (weights.Length != positions.Length || joints.Length != positions.Length) From f566804cc483952303ede2e6ffe2602c0ead9fa2 Mon Sep 17 00:00:00 2001 From: notargs Date: Fri, 12 Nov 2021 14:01:08 +0900 Subject: [PATCH 03/12] =?UTF-8?q?IndexBuffer=E3=82=92New=20Mesh=20API?= =?UTF-8?q?=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/VRM10/Runtime/IO/Model/MeshImporter.cs | 51 +++++++++++++------ Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs | 2 +- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs b/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs index 90cd2cf84..8ec486aee 100644 --- a/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs +++ b/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs @@ -4,6 +4,9 @@ using Unity.Collections; using Unity.Jobs; using UnityEngine; using UnityEngine.Profiling; +using UnityEngine.Rendering; +using VrmLib; +using Mesh = UnityEngine.Mesh; namespace UniVRM10 { @@ -19,17 +22,13 @@ namespace UniVRM10 { Profiler.BeginSample("MeshImporter.LoadSharedMesh"); var mesh = new Mesh(); - if (src.IndexBuffer.Count > ushort.MaxValue) - { - mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; - } - var positions = src.VertexBuffer.Positions.GetNativeArray(Allocator.TempJob); - var normals = src.VertexBuffer.Normals?.GetNativeArray(Allocator.TempJob) ?? default; - var texCoords = src.VertexBuffer.TexCoords?.GetNativeArray(Allocator.TempJob) ?? default; - var colors = src.VertexBuffer.Colors?.GetNativeArray(Allocator.TempJob) ?? default; - var weights = src.VertexBuffer.Weights?.GetNativeArray(Allocator.TempJob) ?? default; - var joints = src.VertexBuffer.Joints?.GetNativeArray(Allocator.TempJob) ?? default; + var positions = src.VertexBuffer.Positions.GetAsNativeArray(Allocator.TempJob); + var normals = src.VertexBuffer.Normals?.GetAsNativeArray(Allocator.TempJob) ?? default; + var texCoords = src.VertexBuffer.TexCoords?.GetAsNativeArray(Allocator.TempJob) ?? default; + var colors = src.VertexBuffer.Colors?.GetAsNativeArray(Allocator.TempJob) ?? default; + var weights = src.VertexBuffer.Weights?.GetAsNativeArray(Allocator.TempJob) ?? default; + var joints = src.VertexBuffer.Joints?.GetAsNativeArray(Allocator.TempJob) ?? default; var vertices = new NativeArray(positions.Length, Allocator.TempJob); @@ -69,15 +68,34 @@ namespace UniVRM10 // 出力のNativeArrayを開放 vertices.Dispose(); - // submesh 方式 - mesh.subMeshCount = src.Submeshes.Count; - var triangles = src.IndexBuffer.GetAsIntList(); - for (var i = 0; i < src.Submeshes.Count; ++i) + // Indexを更新 + switch (src.IndexBuffer.ComponentType) { - var submesh = src.Submeshes[i]; - mesh.SetTriangles(triangles.GetRange(submesh.Offset, submesh.DrawCount), i); + case AccessorValueType.UNSIGNED_SHORT: + var shortIndices = src.IndexBuffer.GetAsNativeArray(Allocator.Temp); + mesh.SetIndexBufferParams(shortIndices.Length, IndexFormat.UInt16); + mesh.SetIndexBufferData(shortIndices, 0, 0, shortIndices.Length); + shortIndices.Dispose(); + break; + case AccessorValueType.UNSIGNED_INT: + var intIndices = src.IndexBuffer.GetAsNativeArray(Allocator.Temp); + mesh.SetIndexBufferParams(intIndices.Length, IndexFormat.UInt32); + mesh.SetIndexBufferData(intIndices, 0, 0, intIndices.Length); + intIndices.Dispose(); + break; + default: + throw new NotImplementedException(); } + // SubMeshを更新 + mesh.subMeshCount = src.Submeshes.Count; + for (var i = 0; i < src.Submeshes.Count; ++i) + { + var subMesh = src.Submeshes[i]; + mesh.SetSubMesh(i, new SubMeshDescriptor(subMesh.Offset, subMesh.DrawCount)); + } + + // MorphTargetを更新 foreach (var morphTarget in src.MorphTargets) { var morphTargetPositions = @@ -88,6 +106,7 @@ namespace UniVRM10 mesh.AddBlendShapeFrame(morphTarget.Name, 100.0f, morphTargetPositions, null, null); } + // 各種パラメーターを再計算 mesh.RecalculateBounds(); mesh.RecalculateTangents(); diff --git a/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs b/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs index 90b6e5405..ac46dab04 100644 --- a/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs +++ b/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs @@ -109,7 +109,7 @@ namespace VrmLib /// バッファをNativeArrayに変換して返す /// 開放の責務は使い手側にある点に注意 /// - public unsafe NativeArray GetNativeArray(Allocator allocator, bool checkStride = true) where T : struct + public unsafe NativeArray GetAsNativeArray(Allocator allocator, bool checkStride = true) where T : struct { if (checkStride && Marshal.SizeOf(typeof(T)) != Stride) { From 6db8e5ecbf85c2d132da69ee9418ef1a1e5b32d4 Mon Sep 17 00:00:00 2001 From: notargs Date: Fri, 12 Nov 2021 18:39:10 +0900 Subject: [PATCH 04/12] =?UTF-8?q?MeshImporterDivided.LoadDivided=E3=82=92N?= =?UTF-8?q?ew=20Mesh=20API=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IO/Model/InterleaveMeshVerticesJob.cs | 46 +++++--- Assets/VRM10/Runtime/IO/Model/MeshImporter.cs | 21 ++-- .../Runtime/IO/Model/MeshImporterDivided.cs | 105 +++++++++--------- Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs | 2 +- 4 files changed, 94 insertions(+), 80 deletions(-) diff --git a/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs b/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs index ac77288cf..1cb865bb4 100644 --- a/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs +++ b/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs @@ -10,21 +10,37 @@ using Unity.Burst; namespace UniVRM10 { - #if ENABLE_VRM10_BURST - [BurstCompile] - #endif + /// + /// 渡されたバッファを一つのバッファにインターリーブする + /// +#if ENABLE_VRM10_BURST +// [BurstCompile] +#endif internal struct InterleaveMeshVerticesJob : IJobParallelFor { - [WriteOnly] private NativeArray _vertices; - - [ReadOnly] private readonly NativeArray _positions; - + [WriteOnly, NativeDisableParallelForRestriction] + private NativeArray _vertices; + + [ReadOnly, NativeDisableParallelForRestriction] + private readonly NativeArray _positions; + // default値を許容する - [ReadOnly, NativeDisableContainerSafetyRestriction] private readonly NativeArray _normals; - [ReadOnly, NativeDisableContainerSafetyRestriction] private readonly NativeArray _texCoords; - [ReadOnly, NativeDisableContainerSafetyRestriction] private readonly NativeArray _colors; - [ReadOnly, NativeDisableContainerSafetyRestriction] private readonly NativeArray _weights; - [ReadOnly, NativeDisableContainerSafetyRestriction] private readonly NativeArray _joints; + [ReadOnly, NativeDisableContainerSafetyRestriction] + private readonly NativeArray _normals; + + [ReadOnly, NativeDisableContainerSafetyRestriction] + private readonly NativeArray _texCoords; + + [ReadOnly, NativeDisableContainerSafetyRestriction] + private readonly NativeArray _colors; + + [ReadOnly, NativeDisableContainerSafetyRestriction] + private readonly NativeArray _weights; + + [ReadOnly, NativeDisableContainerSafetyRestriction] + private readonly NativeArray _joints; + + private readonly int _verticesOffset; public InterleaveMeshVerticesJob( NativeArray vertices, @@ -33,7 +49,8 @@ namespace UniVRM10 NativeArray texCoords = default, NativeArray colors = default, NativeArray weights = default, - NativeArray joints = default) + NativeArray joints = default, + int verticesOffset = 0) { _vertices = vertices; _positions = positions; @@ -42,11 +59,12 @@ namespace UniVRM10 _colors = colors; _weights = weights; _joints = joints; + _verticesOffset = verticesOffset; } public void Execute(int index) { - _vertices[index] = new MeshVertex( + _vertices[index + _verticesOffset] = new MeshVertex( _positions[index], _normals.IsCreated ? _normals[index] : Vector3.zero, _texCoords.IsCreated ? _texCoords[index] : Vector2.zero, diff --git a/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs b/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs index 8ec486aee..22d5e9845 100644 --- a/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs +++ b/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs @@ -18,17 +18,18 @@ namespace UniVRM10 /// /// /// - public static Mesh LoadSharedMesh(VrmLib.Mesh src, VrmLib.Skin skin = null) + public static Mesh LoadSharedMesh(VrmLib.Mesh src, Skin skin = null) { Profiler.BeginSample("MeshImporter.LoadSharedMesh"); var mesh = new Mesh(); - var positions = src.VertexBuffer.Positions.GetAsNativeArray(Allocator.TempJob); - var normals = src.VertexBuffer.Normals?.GetAsNativeArray(Allocator.TempJob) ?? default; - var texCoords = src.VertexBuffer.TexCoords?.GetAsNativeArray(Allocator.TempJob) ?? default; - var colors = src.VertexBuffer.Colors?.GetAsNativeArray(Allocator.TempJob) ?? default; - var weights = src.VertexBuffer.Weights?.GetAsNativeArray(Allocator.TempJob) ?? default; - var joints = src.VertexBuffer.Joints?.GetAsNativeArray(Allocator.TempJob) ?? default; + // これらのNativeArrayはJobによって開放される + 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 vertices = new NativeArray(positions.Length, Allocator.TempJob); @@ -60,7 +61,7 @@ namespace UniVRM10 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); @@ -72,13 +73,13 @@ namespace UniVRM10 switch (src.IndexBuffer.ComponentType) { case AccessorValueType.UNSIGNED_SHORT: - var shortIndices = src.IndexBuffer.GetAsNativeArray(Allocator.Temp); + var shortIndices = src.IndexBuffer.AsNativeArray(Allocator.Temp); mesh.SetIndexBufferParams(shortIndices.Length, IndexFormat.UInt16); mesh.SetIndexBufferData(shortIndices, 0, 0, shortIndices.Length); shortIndices.Dispose(); break; case AccessorValueType.UNSIGNED_INT: - var intIndices = src.IndexBuffer.GetAsNativeArray(Allocator.Temp); + var intIndices = src.IndexBuffer.AsNativeArray(Allocator.Temp); mesh.SetIndexBufferParams(intIndices.Length, IndexFormat.UInt32); mesh.SetIndexBufferData(intIndices, 0, 0, intIndices.Length); intIndices.Dispose(); diff --git a/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs b/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs index 4f489e0ac..a64c48409 100644 --- a/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs +++ b/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs @@ -1,15 +1,17 @@ +using System; using System.Collections.Generic; using System.Linq; using UniGLTF; +using Unity.Collections; +using Unity.Jobs; using UnityEngine; using UnityEngine.Profiling; -using Mesh = VrmLib.Mesh; namespace UniVRM10 { public static class MeshImporterDivided { - public static UnityEngine.Mesh LoadDivided(VrmLib.MeshGroup src) + public static Mesh LoadDivided(VrmLib.MeshGroup src) { Profiler.BeginSample("MeshImporterDivided.LoadDivided"); @@ -19,61 +21,54 @@ namespace UniVRM10 dst.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; } - // - // vertices - // + // 頂点バッファを構築 var vertexCount = src.Meshes.Sum(x => x.VertexBuffer.Count); - var positions = new List(vertexCount); - var normals = new List(vertexCount); - var uv = new List(vertexCount); - var boneWeights = new List(vertexCount); + var vertices = new NativeArray(vertexCount, Allocator.TempJob); + + var jobDisposables = new List(); + // JobのSchedule + JobHandle jobHandle = default; + var indexOffset = 0; foreach (var mesh in src.Meshes) { - positions.AddRange(mesh.VertexBuffer.Positions.GetSpan()); - normals.AddRange(mesh.VertexBuffer.Normals.GetSpan()); - uv.AddRange(mesh.VertexBuffer.TexCoords.GetSpan()); - if (src.Skin == null) continue; - var joints = mesh.VertexBuffer.Joints.GetSpan(); - var weights = mesh.VertexBuffer.Weights.GetSpan(); - for (var i = 0; i < mesh.VertexBuffer.Count; ++i) - { - var joint = joints[i]; - var weight = weights[i]; - boneWeights.Add(new BoneWeight - { - boneIndex0 = joint.Joint0, - boneIndex1 = joint.Joint1, - boneIndex2 = joint.Joint2, - boneIndex3 = joint.Joint3, - weight0 = weight.x, - weight1 = weight.y, - weight2 = weight.z, - weight3 = weight.w, - }); - } + // これらのNativeArrayはJobによって開放される + 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 weights = src.Skin != null ? mesh.VertexBuffer.Weights.AsNativeArray(Allocator.TempJob) : default; + var joints = src.Skin != null ? mesh.VertexBuffer.Joints.AsNativeArray(Allocator.TempJob) : default; + if (positions.IsCreated) jobDisposables.Add(positions); + if (normals.IsCreated) jobDisposables.Add(normals); + if (texCoords.IsCreated) jobDisposables.Add(texCoords); + if (weights.IsCreated) jobDisposables.Add(weights); + if (joints.IsCreated) jobDisposables.Add(joints); + + jobHandle = new InterleaveMeshVerticesJob(vertices, positions, normals, texCoords, default, weights, joints, indexOffset) + .Schedule(mesh.VertexBuffer.Count, 1, jobHandle); + indexOffset += mesh.VertexBuffer.Count; } - dst.name = src.Name; - dst.vertices = positions.ToArray(); - dst.normals = normals.ToArray(); - dst.uv = uv.ToArray(); - if (src.Skin != null) - { - dst.boneWeights = boneWeights.ToArray(); - } - - // - // skin - // + // Jobと並行してBindposeの更新を行う if (src.Skin != null) { dst.bindposes = src.Skin.InverseMatrices.GetSpan().ToArray(); } + + // Jobを完了 + jobHandle.Complete(); + + foreach (var disposable in jobDisposables) + { + disposable.Dispose(); + } + + MeshVertex.SetVertexBufferParamsToMesh(dst, vertices.Length); + dst.SetVertexBufferData(vertices, 0, 0, vertices.Length); + + vertices.Dispose(); - // // triangles - // dst.subMeshCount = src.Meshes.Count; var offset = 0; for (var meshIndex = 0; meshIndex < src.Meshes.Count; ++meshIndex) @@ -87,30 +82,30 @@ namespace UniVRM10 dst.RecalculateBounds(); dst.RecalculateTangents(); - // // blendshape - // var blendShapeCount = src.Meshes[0].MorphTargets.Count; + var blendShapePositions = new List(); + var blendShapeNormals = new List(); for (var i = 0; i < blendShapeCount; ++i) { - positions.Clear(); - normals.Clear(); + blendShapePositions.Clear(); + blendShapeNormals.Clear(); var name = src.Meshes[0].MorphTargets[i].Name; - for (var meshIndex = 0; meshIndex < src.Meshes.Count; ++meshIndex) + foreach (var mesh in src.Meshes) { - var morphTarget = src.Meshes[meshIndex].MorphTargets[i]; - positions.AddRange(morphTarget.VertexBuffer.Positions.GetSpan()); + var morphTarget = mesh.MorphTargets[i]; + blendShapePositions.AddRange(morphTarget.VertexBuffer.Positions.GetSpan()); if (morphTarget.VertexBuffer.Normals != null) { - normals.AddRange(morphTarget.VertexBuffer.Normals.GetSpan()); + blendShapeNormals.AddRange(morphTarget.VertexBuffer.Normals.GetSpan()); } else { // fill zero - normals.AddRange(Enumerable.Range(0, morphTarget.VertexBuffer.Count).Select(x => Vector3.zero)); + blendShapeNormals.AddRange(Enumerable.Range(0, morphTarget.VertexBuffer.Count).Select(x => Vector3.zero)); } } - dst.AddBlendShapeFrame(name, 100.0f, positions.ToArray(), normals.ToArray(), null); + dst.AddBlendShapeFrame(name, 100.0f, blendShapePositions.ToArray(), blendShapeNormals.ToArray(), null); } Profiler.EndSample(); diff --git a/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs b/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs index ac46dab04..6d5be079f 100644 --- a/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs +++ b/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs @@ -109,7 +109,7 @@ namespace VrmLib /// バッファをNativeArrayに変換して返す /// 開放の責務は使い手側にある点に注意 /// - public unsafe NativeArray GetAsNativeArray(Allocator allocator, bool checkStride = true) where T : struct + public unsafe NativeArray AsNativeArray(Allocator allocator, bool checkStride = true) where T : struct { if (checkStride && Marshal.SizeOf(typeof(T)) != Stride) { From ed4aada948a2eb6c0be0bea681403faeb5469c00 Mon Sep 17 00:00:00 2001 From: notargs Date: Fri, 12 Nov 2021 19:09:05 +0900 Subject: [PATCH 05/12] Fix jobs --- Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs b/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs index 1cb865bb4..d3249c45d 100644 --- a/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs +++ b/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs @@ -14,14 +14,14 @@ namespace UniVRM10 /// 渡されたバッファを一つのバッファにインターリーブする /// #if ENABLE_VRM10_BURST -// [BurstCompile] + [BurstCompile] #endif internal struct InterleaveMeshVerticesJob : IJobParallelFor { [WriteOnly, NativeDisableParallelForRestriction] private NativeArray _vertices; - [ReadOnly, NativeDisableParallelForRestriction] + [ReadOnly] private readonly NativeArray _positions; // default値を許容する From 7b32f07c7829ad2a2c8db6da23306a0238a50697 Mon Sep 17 00:00:00 2001 From: notargs Date: Tue, 16 Nov 2021 18:38:37 +0900 Subject: [PATCH 06/12] =?UTF-8?q?MeshImporterDivided=E3=82=92=E9=AB=98?= =?UTF-8?q?=E9=80=9F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IO/Model/InterleaveMeshVerticesJob.cs | 48 ++- Assets/VRM10/Runtime/IO/Model/MeshImporter.cs | 6 +- .../Runtime/IO/Model/MeshImporterDivided.cs | 300 +++++++++++++----- Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs | 7 +- 4 files changed, 255 insertions(+), 106 deletions(-) diff --git a/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs b/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs index d3249c45d..ddbb76b53 100644 --- a/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs +++ b/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs @@ -18,39 +18,36 @@ namespace UniVRM10 #endif internal struct InterleaveMeshVerticesJob : IJobParallelFor { - [WriteOnly, NativeDisableParallelForRestriction] - private NativeArray _vertices; + [WriteOnly] + private NativeSlice _vertices; [ReadOnly] - private readonly NativeArray _positions; + private readonly NativeSlice _positions; // default値を許容する [ReadOnly, NativeDisableContainerSafetyRestriction] - private readonly NativeArray _normals; + private readonly NativeSlice _normals; [ReadOnly, NativeDisableContainerSafetyRestriction] - private readonly NativeArray _texCoords; + private readonly NativeSlice _texCoords; [ReadOnly, NativeDisableContainerSafetyRestriction] - private readonly NativeArray _colors; + private readonly NativeSlice _colors; [ReadOnly, NativeDisableContainerSafetyRestriction] - private readonly NativeArray _weights; + private readonly NativeSlice _weights; [ReadOnly, NativeDisableContainerSafetyRestriction] - private readonly NativeArray _joints; - - private readonly int _verticesOffset; + private readonly NativeSlice _joints; public InterleaveMeshVerticesJob( - NativeArray vertices, + NativeSlice vertices, NativeArray positions, NativeArray normals = default, NativeArray texCoords = default, NativeArray colors = default, NativeArray weights = default, - NativeArray joints = default, - int verticesOffset = 0) + NativeArray joints = default) { _vertices = vertices; _positions = positions; @@ -59,24 +56,23 @@ namespace UniVRM10 _colors = colors; _weights = weights; _joints = joints; - _verticesOffset = verticesOffset; } public void Execute(int index) { - _vertices[index + _verticesOffset] = new MeshVertex( + _vertices[index] = new MeshVertex( _positions[index], - _normals.IsCreated ? _normals[index] : Vector3.zero, - _texCoords.IsCreated ? _texCoords[index] : Vector2.zero, - _colors.IsCreated ? _colors[index] : Color.white, - _joints.IsCreated ? _joints[index].Joint0 : (ushort)0, - _joints.IsCreated ? _joints[index].Joint1 : (ushort)0, - _joints.IsCreated ? _joints[index].Joint2 : (ushort)0, - _joints.IsCreated ? _joints[index].Joint3 : (ushort)0, - _weights.IsCreated ? _weights[index].x : 0, - _weights.IsCreated ? _weights[index].y : 0, - _weights.IsCreated ? _weights[index].z : 0, - _weights.IsCreated ? _weights[index].w : 0 + _normals.Length > 0 ? _normals[index] : Vector3.zero, + _texCoords.Length > 0 ? _texCoords[index] : Vector2.zero, + _colors.Length > 0 ? _colors[index] : Color.white, + _joints.Length > 0 ? _joints[index].Joint0 : (ushort)0, + _joints.Length > 0 ? _joints[index].Joint1 : (ushort)0, + _joints.Length > 0 ? _joints[index].Joint2 : (ushort)0, + _joints.Length > 0 ? _joints[index].Joint3 : (ushort)0, + _weights.Length > 0 ? _weights[index].x : 0, + _weights.Length > 0 ? _weights[index].y : 0, + _weights.Length > 0 ? _weights[index].z : 0, + _weights.Length > 0 ? _weights[index].w : 0 ); } } diff --git a/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs b/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs index 22d5e9845..113d54653 100644 --- a/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs +++ b/Assets/VRM10/Runtime/IO/Model/MeshImporter.cs @@ -23,7 +23,6 @@ namespace UniVRM10 Profiler.BeginSample("MeshImporter.LoadSharedMesh"); var mesh = new Mesh(); - // これらのNativeArrayはJobによって開放される 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; @@ -37,6 +36,7 @@ namespace UniVRM10 var jobHandle = new InterleaveMeshVerticesJob(vertices, positions, normals, texCoords, colors, weights, joints) .Schedule(vertices.Length, 1); + JobHandle.ScheduleBatchedJobs(); // BindPoseを更新 if (weights.IsCreated && joints.IsCreated) @@ -73,13 +73,13 @@ namespace UniVRM10 switch (src.IndexBuffer.ComponentType) { case AccessorValueType.UNSIGNED_SHORT: - var shortIndices = src.IndexBuffer.AsNativeArray(Allocator.Temp); + var shortIndices = src.IndexBuffer.AsNativeArray(Allocator.Temp); 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.AsNativeArray(Allocator.Temp); mesh.SetIndexBufferParams(intIndices.Length, IndexFormat.UInt32); mesh.SetIndexBufferData(intIndices, 0, 0, intIndices.Length); intIndices.Dispose(); diff --git a/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs b/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs index a64c48409..bd57d6b95 100644 --- a/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs +++ b/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs @@ -6,92 +6,58 @@ using Unity.Collections; using Unity.Jobs; using UnityEngine; using UnityEngine.Profiling; +using UnityEngine.Rendering; +using VrmLib; +using Mesh = UnityEngine.Mesh; namespace UniVRM10 { public static class MeshImporterDivided { - public static Mesh LoadDivided(VrmLib.MeshGroup src) + public static Mesh LoadDivided(MeshGroup meshGroup) { Profiler.BeginSample("MeshImporterDivided.LoadDivided"); - - var dst = new UnityEngine.Mesh(); - if (src.Meshes.Sum(x => x.IndexBuffer.Count) > ushort.MaxValue) - { - dst.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; - } - // 頂点バッファを構築 - var vertexCount = src.Meshes.Sum(x => x.VertexBuffer.Count); - var vertices = new NativeArray(vertexCount, Allocator.TempJob); + var vertexCount = meshGroup.Meshes.Sum(mesh => mesh.VertexBuffer.Count); + var indexCount = meshGroup.Meshes.Sum(mesh => mesh.IndexBuffer.Count); - var jobDisposables = new List(); - - // JobのSchedule - JobHandle jobHandle = default; + var resultMesh = new Mesh(); + + // 頂点バッファ・BindPoseを構築して更新 + UpdateVerticesAndBindPose(meshGroup, vertexCount, resultMesh); + + // インデックスバッファを構築して更新 + UpdateIndices(meshGroup, vertexCount, indexCount, resultMesh); + + // SubMeshを更新 + resultMesh.subMeshCount = meshGroup.Meshes.Count; var indexOffset = 0; - foreach (var mesh in src.Meshes) + for (var i = 0; i < meshGroup.Meshes.Count; ++i) { - // これらのNativeArrayはJobによって開放される - 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 weights = src.Skin != null ? mesh.VertexBuffer.Weights.AsNativeArray(Allocator.TempJob) : default; - var joints = src.Skin != null ? mesh.VertexBuffer.Joints.AsNativeArray(Allocator.TempJob) : default; - if (positions.IsCreated) jobDisposables.Add(positions); - if (normals.IsCreated) jobDisposables.Add(normals); - if (texCoords.IsCreated) jobDisposables.Add(texCoords); - if (weights.IsCreated) jobDisposables.Add(weights); - if (joints.IsCreated) jobDisposables.Add(joints); - - jobHandle = new InterleaveMeshVerticesJob(vertices, positions, normals, texCoords, default, weights, joints, indexOffset) - .Schedule(mesh.VertexBuffer.Count, 1, jobHandle); - indexOffset += mesh.VertexBuffer.Count; + var mesh = meshGroup.Meshes[i]; + resultMesh.SetSubMesh(i, new SubMeshDescriptor(indexOffset, mesh.IndexBuffer.Count)); + indexOffset += mesh.IndexBuffer.Count; } - // Jobと並行してBindposeの更新を行う - if (src.Skin != null) - { - dst.bindposes = src.Skin.InverseMatrices.GetSpan().ToArray(); - } - - // Jobを完了 - jobHandle.Complete(); - - foreach (var disposable in jobDisposables) - { - disposable.Dispose(); - } + // 各種データを再構築 + Profiler.BeginSample("Bounds"); + resultMesh.RecalculateBounds(); + Profiler.EndSample(); + Profiler.BeginSample("Tangents"); + resultMesh.RecalculateTangents(); + Profiler.EndSample(); - MeshVertex.SetVertexBufferParamsToMesh(dst, vertices.Length); - dst.SetVertexBufferData(vertices, 0, 0, vertices.Length); - - vertices.Dispose(); - - // triangles - dst.subMeshCount = src.Meshes.Count; - var offset = 0; - for (var meshIndex = 0; meshIndex < src.Meshes.Count; ++meshIndex) - { - var mesh = src.Meshes[meshIndex]; - var indices = mesh.IndexBuffer.GetAsIntArray().Select(x => offset + x).ToArray(); - dst.SetTriangles(indices, meshIndex); - offset += mesh.VertexBuffer.Count; - } - - dst.RecalculateBounds(); - dst.RecalculateTangents(); - - // blendshape - var blendShapeCount = src.Meshes[0].MorphTargets.Count; + // BlendShapeを更新 + Profiler.BeginSample("BlendShape"); + var blendShapeCount = meshGroup.Meshes[0].MorphTargets.Count; var blendShapePositions = new List(); var blendShapeNormals = new List(); for (var i = 0; i < blendShapeCount; ++i) { blendShapePositions.Clear(); blendShapeNormals.Clear(); - var name = src.Meshes[0].MorphTargets[i].Name; - foreach (var mesh in src.Meshes) + var name = meshGroup.Meshes[0].MorphTargets[i].Name; + foreach (var mesh in meshGroup.Meshes) { var morphTarget = mesh.MorphTargets[i]; blendShapePositions.AddRange(morphTarget.VertexBuffer.Positions.GetSpan()); @@ -102,15 +68,207 @@ namespace UniVRM10 else { // fill zero - blendShapeNormals.AddRange(Enumerable.Range(0, morphTarget.VertexBuffer.Count).Select(x => Vector3.zero)); + blendShapeNormals.AddRange(Enumerable.Range(0, morphTarget.VertexBuffer.Count) + .Select(x => Vector3.zero)); } } - dst.AddBlendShapeFrame(name, 100.0f, blendShapePositions.ToArray(), blendShapeNormals.ToArray(), null); + + resultMesh.AddBlendShapeFrame(name, 100.0f, blendShapePositions.ToArray(), blendShapeNormals.ToArray(), + null); + } + Profiler.EndSample(); + + Profiler.EndSample(); + + return resultMesh; + } + + /// + /// インデックスバッファを更新する + /// MEMO: 出力に対するushortを考慮することをやめればかなりシンプルに書ける + /// + private static void UpdateIndices(MeshGroup meshGroup, int vertexCount, int indexCount, Mesh resultMesh) + { + Profiler.BeginSample("MeshImporterDivided.UpdateIndices"); + + JobHandle jobHandle = default; + + var disposables = new List(); + + // 出力をushortにするべきかどうかを判別 + if (vertexCount < ushort.MaxValue) + { + var indices = new NativeArray(indexCount, Allocator.TempJob); + disposables.Add(indices); + var indexOffset = 0; + var vertexOffset = 0; + foreach (var mesh in meshGroup.Meshes) + { + switch (mesh.IndexBuffer.ComponentType) + { + case AccessorValueType.SHORT: + { + // unsigned short -> unsigned short + var source = mesh.IndexBuffer.AsNativeArray(Allocator.TempJob); + disposables.Add(source); + jobHandle = new CopyIndicesJobs.Ushort2Ushort( + (ushort)vertexOffset, + new NativeSlice(source), + new NativeSlice(indices, indexOffset, mesh.IndexBuffer.Count)) + .Schedule(mesh.IndexBuffer.Count, 1, jobHandle); + break; + } + case AccessorValueType.UNSIGNED_INT: + { + // unsigned int -> unsigned short + var source = mesh.IndexBuffer.AsNativeArray(Allocator.TempJob); + disposables.Add(source); + jobHandle = new CopyIndicesJobs.Uint2Ushort( + (ushort)vertexOffset, + source, + new NativeSlice(indices, indexOffset, mesh.IndexBuffer.Count)) + .Schedule(mesh.IndexBuffer.Count, 1, jobHandle); + break; + } + default: + throw new ArgumentOutOfRangeException(); + } + + vertexOffset += mesh.VertexBuffer.Count; + indexOffset += mesh.IndexBuffer.Count; + } + + jobHandle.Complete(); + + resultMesh.SetIndexBufferParams(indexCount, IndexFormat.UInt16); + resultMesh.SetIndexBufferData(indices, 0, 0, indexCount); + } + else + { + var indices = new NativeArray(indexCount, Allocator.TempJob); + disposables.Add(indices); + var indexOffset = 0; + var vertexOffset = 0; + foreach (var mesh in meshGroup.Meshes) + { + switch (mesh.IndexBuffer.ComponentType) + { + case AccessorValueType.SHORT: + { + // unsigned short -> unsigned int + var source = mesh.IndexBuffer.AsNativeArray(Allocator.TempJob); + disposables.Add(source); + jobHandle = new CopyIndicesJobs.Ushort2Uint( + (uint)vertexOffset, + source, + new NativeSlice(indices, indexOffset, mesh.IndexBuffer.Count)) + .Schedule(mesh.IndexBuffer.Count, 1, jobHandle); + break; + } + case AccessorValueType.UNSIGNED_INT: + { + // unsigned int -> unsigned int + var source = mesh.IndexBuffer.AsNativeArray(Allocator.TempJob); + disposables.Add(source); + jobHandle = new CopyIndicesJobs.UInt2UInt( + (uint)vertexOffset, + source, + new NativeSlice(indices, indexOffset, mesh.IndexBuffer.Count)) + .Schedule(mesh.IndexBuffer.Count, 1, jobHandle); + break; + } + default: + throw new ArgumentOutOfRangeException(); + } + + vertexOffset += mesh.VertexBuffer.Count; + indexOffset += mesh.IndexBuffer.Count; + } + + jobHandle.Complete(); + + resultMesh.SetIndexBufferParams(indexCount, IndexFormat.UInt32); + resultMesh.SetIndexBufferData(indices, 0, 0, indexCount); + } + + foreach (var disposable in disposables) + { + disposable.Dispose(); + } + + Profiler.EndSample(); + } + + /// + /// メッシュの頂点情報の更新を行う際、MainThreadが空くため、その間にBindPoseの更新も行う + /// + private static void UpdateVerticesAndBindPose( + MeshGroup meshGroup, + int vertexCount, + Mesh resultMesh) + { + Profiler.BeginSample("MeshImporterDivided.UpdateVerticesAndBindPose"); + + var disposables = new List(); + + // JobのSchedule + var vertices = new NativeArray(vertexCount, Allocator.TempJob); + disposables.Add(vertices); + + var indexOffset = 0; + JobHandle interleaveVertexJob = default; + + 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 weights = meshGroup.Skin != null + ? mesh.VertexBuffer.Weights.AsNativeArray(Allocator.TempJob) + : default; + var joints = meshGroup.Skin != null + ? mesh.VertexBuffer.Joints.AsNativeArray(Allocator.TempJob) + : 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), + positions, + normals, + texCoords, + default, + weights, + joints) + .Schedule(mesh.VertexBuffer.Count, 1, interleaveVertexJob); + indexOffset += mesh.VertexBuffer.Count; + } + + JobHandle.ScheduleBatchedJobs(); + + // 並行してBindposeの更新を行う + if (meshGroup.Skin != null) + { + resultMesh.bindposes = meshGroup.Skin.InverseMatrices.GetSpan().ToArray(); + } + + // Jobを完了 + interleaveVertexJob.Complete(); + + // VertexBufferを設定 + MeshVertex.SetVertexBufferParamsToMesh(resultMesh, vertices.Length); + resultMesh.SetVertexBufferData(vertices, 0, 0, vertices.Length); + + // 各種バッファを破棄 + foreach (var disposable in disposables) + { + disposable.Dispose(); } Profiler.EndSample(); - - return dst; } } -} +} \ No newline at end of file diff --git a/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs b/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs index 6d5be079f..5ea2defb7 100644 --- a/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs +++ b/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs @@ -109,13 +109,8 @@ namespace VrmLib /// バッファをNativeArrayに変換して返す /// 開放の責務は使い手側にある点に注意 /// - public unsafe NativeArray AsNativeArray(Allocator allocator, bool checkStride = true) where T : struct + public unsafe NativeArray AsNativeArray(Allocator allocator) where T : struct { - if (checkStride && Marshal.SizeOf(typeof(T)) != Stride) - { - throw new Exception("different sizeof(T) with stride"); - } - fixed (byte* byteArray = Bytes.Array) { var nativeArray = new NativeArray(Bytes.Count / Marshal.SizeOf(), allocator); From be35f19cb737423051ace7e63e4efa62875c6868 Mon Sep 17 00:00:00 2001 From: notargs Date: Tue, 16 Nov 2021 19:11:53 +0900 Subject: [PATCH 07/12] =?UTF-8?q?MeshImporterDivided=E3=81=AEBlendShape?= =?UTF-8?q?=E3=81=AE=E6=9B=B4=E6=96=B0=E3=81=AB=E3=81=8B=E3=81=AA=E3=82=8A?= =?UTF-8?q?=E6=99=82=E9=96=93=E3=81=8C=E3=81=8B=E3=81=8B=E3=81=A3=E3=81=A6?= =?UTF-8?q?=E3=81=84=E3=81=9F=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/IO/Model/MeshImporterDivided.cs | 61 ++++++++++++------- Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs | 11 ++++ 2 files changed, 49 insertions(+), 23 deletions(-) diff --git a/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs b/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs index bd57d6b95..53577d6fe 100644 --- a/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs +++ b/Assets/VRM10/Runtime/IO/Model/MeshImporterDivided.cs @@ -40,43 +40,58 @@ namespace UniVRM10 } // 各種データを再構築 - Profiler.BeginSample("Bounds"); resultMesh.RecalculateBounds(); - Profiler.EndSample(); - Profiler.BeginSample("Tangents"); resultMesh.RecalculateTangents(); - Profiler.EndSample(); // BlendShapeを更新 - Profiler.BeginSample("BlendShape"); var blendShapeCount = meshGroup.Meshes[0].MorphTargets.Count; - var blendShapePositions = new List(); - var blendShapeNormals = new List(); + for (var i = 0; i < blendShapeCount; ++i) { - blendShapePositions.Clear(); - blendShapeNormals.Clear(); - var name = meshGroup.Meshes[0].MorphTargets[i].Name; + var positionsCount = 0; + var normalsCount = 0; foreach (var mesh in meshGroup.Meshes) { var morphTarget = mesh.MorphTargets[i]; - blendShapePositions.AddRange(morphTarget.VertexBuffer.Positions.GetSpan()); - if (morphTarget.VertexBuffer.Normals != null) - { - blendShapeNormals.AddRange(morphTarget.VertexBuffer.Normals.GetSpan()); - } - else - { - // fill zero - blendShapeNormals.AddRange(Enumerable.Range(0, morphTarget.VertexBuffer.Count) - .Select(x => Vector3.zero)); - } + positionsCount += morphTarget.VertexBuffer.Positions.Count; + normalsCount += morphTarget.VertexBuffer.Normals?.Count ?? morphTarget.VertexBuffer.Count; } - resultMesh.AddBlendShapeFrame(name, 100.0f, blendShapePositions.ToArray(), blendShapeNormals.ToArray(), + var blendShapePositions = new NativeArray(positionsCount, Allocator.Temp); + var blendShapeNormals = new NativeArray(normalsCount, Allocator.Temp); + + var blendShapePositionOffset = 0; + var blendShapeNormalOffset = 0; + foreach (var mesh in meshGroup.Meshes) + { + var morphTarget = mesh.MorphTargets[i]; + morphTarget.VertexBuffer.Positions.CopyToNativeSlice( + new NativeSlice( + blendShapePositions, + blendShapePositionOffset, + morphTarget.VertexBuffer.Positions.Count + ) + ); + + // nullならdefault(0)のまま + morphTarget.VertexBuffer.Normals?.CopyToNativeSlice( + new NativeSlice( + blendShapeNormals, + blendShapeNormalOffset, + morphTarget.VertexBuffer.Normals.Count + ) + ); + + blendShapePositionOffset += morphTarget.VertexBuffer.Positions.Count; + blendShapeNormalOffset += morphTarget.VertexBuffer.Normals?.Count ?? morphTarget.VertexBuffer.Count; + } + + resultMesh.AddBlendShapeFrame(meshGroup.Meshes[0].MorphTargets[i].Name, + 100.0f, + blendShapePositions.ToArray(), + blendShapeNormals.ToArray(), null); } - Profiler.EndSample(); Profiler.EndSample(); diff --git a/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs b/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs index 5ea2defb7..b37fd8ac3 100644 --- a/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs +++ b/Assets/VRM10/vrmlib/Runtime/BufferAccessor.cs @@ -119,6 +119,17 @@ namespace VrmLib } } + /// + /// バッファを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); + } + } + public void Assign(T[] values) where T : struct { if (Marshal.SizeOf(typeof(T)) != Stride) From b1afcf4c0177646921ba85ee7e11d222a1f09299 Mon Sep 17 00:00:00 2001 From: notargs Date: Tue, 16 Nov 2021 19:27:51 +0900 Subject: [PATCH 08/12] =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs b/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs index ddbb76b53..72bb7d2ad 100644 --- a/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs +++ b/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs @@ -11,7 +11,7 @@ using Unity.Burst; namespace UniVRM10 { /// - /// 渡されたバッファを一つのバッファにインターリーブする + /// 渡されたバッファを一つのバッファにインターリーブするJob /// #if ENABLE_VRM10_BURST [BurstCompile] From 550a5ae9f834bb1fac62c4cf6615af511b575a96 Mon Sep 17 00:00:00 2001 From: notargs Date: Tue, 16 Nov 2021 19:29:40 +0900 Subject: [PATCH 09/12] Add Serializable --- Assets/VRM10/Runtime/IO/Model/MeshVertex.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Assets/VRM10/Runtime/IO/Model/MeshVertex.cs b/Assets/VRM10/Runtime/IO/Model/MeshVertex.cs index d5bdd34d5..d5926b1b3 100644 --- a/Assets/VRM10/Runtime/IO/Model/MeshVertex.cs +++ b/Assets/VRM10/Runtime/IO/Model/MeshVertex.cs @@ -1,3 +1,4 @@ +using System; using System.Runtime.InteropServices; using UnityEditor.UI; using UnityEngine; @@ -9,7 +10,7 @@ namespace UniVRM10 /// インターリーブされたメッシュの頂点情報を表す構造体 /// そのままGPUにアップロードされる /// - [StructLayout(LayoutKind.Sequential)] + [Serializable, StructLayout(LayoutKind.Sequential)] internal readonly struct MeshVertex { private readonly Vector3 _position; From 4da92aa797d3f5319e43fc2ccd2fd53558d2d789 Mon Sep 17 00:00:00 2001 From: notargs Date: Tue, 16 Nov 2021 19:30:00 +0900 Subject: [PATCH 10/12] Serializable --- Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshVertex.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshVertex.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshVertex.cs index 4db319f40..4bb6d1d35 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshVertex.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshVertex.cs @@ -1,3 +1,4 @@ +using System; using System.Runtime.InteropServices; using UnityEngine; using UnityEngine.Rendering; @@ -8,7 +9,7 @@ namespace UniGLTF /// インターリーブされたメッシュの頂点情報を表す構造体 /// そのままGPUにアップロードされる /// - [StructLayout(LayoutKind.Sequential)] + [Serializable, StructLayout(LayoutKind.Sequential)] internal readonly struct MeshVertex { private readonly Vector3 _position; From c98a94bccb097ead9d767079767aa3f13954aa2f Mon Sep 17 00:00:00 2001 From: notargs Date: Tue, 16 Nov 2021 19:53:29 +0900 Subject: [PATCH 11/12] Add CopyIndicesJobs --- .../VRM10/Runtime/IO/Model/CopyIndicesJob.cs | 120 ++++++++++++++++++ .../Runtime/IO/Model/CopyIndicesJob.cs.meta | 3 + 2 files changed, 123 insertions(+) create mode 100644 Assets/VRM10/Runtime/IO/Model/CopyIndicesJob.cs create mode 100644 Assets/VRM10/Runtime/IO/Model/CopyIndicesJob.cs.meta diff --git a/Assets/VRM10/Runtime/IO/Model/CopyIndicesJob.cs b/Assets/VRM10/Runtime/IO/Model/CopyIndicesJob.cs new file mode 100644 index 000000000..757083812 --- /dev/null +++ b/Assets/VRM10/Runtime/IO/Model/CopyIndicesJob.cs @@ -0,0 +1,120 @@ +using Unity.Collections; +using Unity.Jobs; + +#if ENABLE_VRM10_BURST +using Unity.Burst; +#endif + +namespace UniVRM10 +{ + /// + /// インデックス配列を、オフセットを加えながら複製するJob郡 + /// MEMO: ushortを考慮することをやめればかなりシンプルに書ける + /// + internal struct CopyIndicesJobs + { + /// + /// unsigned int -> unsigned int + /// +#if ENABLE_VRM10_BURST + [BurstCompile] +#endif + public struct UInt2UInt : IJobParallelFor + { + private readonly uint _vertexOffset; + + [ReadOnly] private readonly NativeSlice _source; + [WriteOnly] private NativeSlice _destination; + + public UInt2UInt(uint vertexOffset, NativeSlice source, NativeSlice destination) + { + _vertexOffset = vertexOffset; + _source = source; + _destination = destination; + } + + public void Execute(int index) + { + _destination[index] = _source[index] + _vertexOffset; + } + } + + /// + /// unsigned short -> unsigned int + /// +#if ENABLE_VRM10_BURST + [BurstCompile] +#endif + public struct Ushort2Uint : IJobParallelFor + { + private readonly uint _vertexOffset; + + [ReadOnly] private readonly NativeSlice _source; + [WriteOnly] private NativeSlice _destination; + + public Ushort2Uint(uint vertexOffset, NativeSlice source, NativeSlice destination) + { + _vertexOffset = vertexOffset; + _source = source; + _destination = destination; + } + + public void Execute(int index) + { + _destination[index] = _source[index] + _vertexOffset; + } + } + + /// + /// unsigned short -> unsigned short + /// +#if ENABLE_VRM10_BURST + [BurstCompile] +#endif + public struct Ushort2Ushort : IJobParallelFor + { + private readonly ushort _vertexOffset; + + [ReadOnly] private readonly NativeSlice _source; + [WriteOnly] private NativeSlice _destination; + + public Ushort2Ushort(ushort vertexOffset, NativeSlice source, NativeSlice destination) + { + _vertexOffset = vertexOffset; + _source = source; + _destination = destination; + } + + public void Execute(int index) + { + _destination[index] = (ushort)(_source[index] + _vertexOffset); + } + } + + /// + /// unsigned int -> unsigned short + /// +#if ENABLE_VRM10_BURST + [BurstCompile] +#endif + public struct Uint2Ushort : IJobParallelFor + { + private readonly ushort _vertexOffset; + + [ReadOnly] private readonly NativeSlice _source; + [WriteOnly] private NativeSlice _destination; + + public Uint2Ushort(ushort vertexOffset, NativeSlice source, NativeSlice destination) + { + _vertexOffset = vertexOffset; + _source = source; + _destination = destination; + } + + public void Execute(int index) + { + _destination[index] = (ushort)(_source[index] + _vertexOffset); + } + } + } +} \ No newline at end of file diff --git a/Assets/VRM10/Runtime/IO/Model/CopyIndicesJob.cs.meta b/Assets/VRM10/Runtime/IO/Model/CopyIndicesJob.cs.meta new file mode 100644 index 000000000..454e4dc5a --- /dev/null +++ b/Assets/VRM10/Runtime/IO/Model/CopyIndicesJob.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3c6a7113ee13415e9b8c1063a683f3f8 +timeCreated: 1637033014 \ No newline at end of file From e53065aeff3c87605483c9ad4c70942a859c1ceb Mon Sep 17 00:00:00 2001 From: notargs Date: Tue, 16 Nov 2021 19:56:40 +0900 Subject: [PATCH 12/12] Use NativeSlice --- .../Runtime/IO/Model/InterleaveMeshVerticesJob.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs b/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs index 72bb7d2ad..f16040cca 100644 --- a/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs +++ b/Assets/VRM10/Runtime/IO/Model/InterleaveMeshVerticesJob.cs @@ -42,12 +42,12 @@ namespace UniVRM10 public InterleaveMeshVerticesJob( NativeSlice vertices, - NativeArray positions, - NativeArray normals = default, - NativeArray texCoords = default, - NativeArray colors = default, - NativeArray weights = default, - NativeArray joints = default) + NativeSlice positions, + NativeSlice normals = default, + NativeSlice texCoords = default, + NativeSlice colors = default, + NativeSlice weights = default, + NativeSlice joints = default) { _vertices = vertices; _positions = positions;