MeshImporterDivided.LoadDividedをNew Mesh API対応

This commit is contained in:
notargs 2021-11-12 18:39:10 +09:00
parent f566804cc4
commit 6db8e5ecbf
4 changed files with 94 additions and 80 deletions

View File

@ -10,21 +10,37 @@ using Unity.Burst;
namespace UniVRM10
{
#if ENABLE_VRM10_BURST
[BurstCompile]
#endif
/// <summary>
/// 渡されたバッファを一つのバッファにインターリーブする
/// </summary>
#if ENABLE_VRM10_BURST
// [BurstCompile]
#endif
internal struct InterleaveMeshVerticesJob : IJobParallelFor
{
[WriteOnly] private NativeArray<MeshVertex> _vertices;
[ReadOnly] private readonly NativeArray<Vector3> _positions;
[WriteOnly, NativeDisableParallelForRestriction]
private NativeArray<MeshVertex> _vertices;
[ReadOnly, NativeDisableParallelForRestriction]
private readonly NativeArray<Vector3> _positions;
// default値を許容する
[ReadOnly, NativeDisableContainerSafetyRestriction] private readonly NativeArray<Vector3> _normals;
[ReadOnly, NativeDisableContainerSafetyRestriction] private readonly NativeArray<Vector2> _texCoords;
[ReadOnly, NativeDisableContainerSafetyRestriction] private readonly NativeArray<Color> _colors;
[ReadOnly, NativeDisableContainerSafetyRestriction] private readonly NativeArray<Vector4> _weights;
[ReadOnly, NativeDisableContainerSafetyRestriction] private readonly NativeArray<SkinJoints> _joints;
[ReadOnly, NativeDisableContainerSafetyRestriction]
private readonly NativeArray<Vector3> _normals;
[ReadOnly, NativeDisableContainerSafetyRestriction]
private readonly NativeArray<Vector2> _texCoords;
[ReadOnly, NativeDisableContainerSafetyRestriction]
private readonly NativeArray<Color> _colors;
[ReadOnly, NativeDisableContainerSafetyRestriction]
private readonly NativeArray<Vector4> _weights;
[ReadOnly, NativeDisableContainerSafetyRestriction]
private readonly NativeArray<SkinJoints> _joints;
private readonly int _verticesOffset;
public InterleaveMeshVerticesJob(
NativeArray<MeshVertex> vertices,
@ -33,7 +49,8 @@ namespace UniVRM10
NativeArray<Vector2> texCoords = default,
NativeArray<Color> colors = default,
NativeArray<Vector4> weights = default,
NativeArray<SkinJoints> joints = default)
NativeArray<SkinJoints> 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,

View File

@ -18,17 +18,18 @@ namespace UniVRM10
/// <param name="mesh"></param>
/// <param name="src"></param>
/// <param name="skin"></param>
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<Vector3>(Allocator.TempJob);
var normals = src.VertexBuffer.Normals?.GetAsNativeArray<Vector3>(Allocator.TempJob) ?? default;
var texCoords = src.VertexBuffer.TexCoords?.GetAsNativeArray<Vector2>(Allocator.TempJob) ?? default;
var colors = src.VertexBuffer.Colors?.GetAsNativeArray<Color>(Allocator.TempJob) ?? default;
var weights = src.VertexBuffer.Weights?.GetAsNativeArray<Vector4>(Allocator.TempJob) ?? default;
var joints = src.VertexBuffer.Joints?.GetAsNativeArray<SkinJoints>(Allocator.TempJob) ?? default;
// これらのNativeArrayはJobによって開放される
var positions = src.VertexBuffer.Positions.AsNativeArray<Vector3>(Allocator.TempJob);
var normals = src.VertexBuffer.Normals?.AsNativeArray<Vector3>(Allocator.TempJob) ?? default;
var texCoords = src.VertexBuffer.TexCoords?.AsNativeArray<Vector2>(Allocator.TempJob) ?? default;
var colors = src.VertexBuffer.Colors?.AsNativeArray<Color>(Allocator.TempJob) ?? default;
var weights = src.VertexBuffer.Weights?.AsNativeArray<Vector4>(Allocator.TempJob) ?? default;
var joints = src.VertexBuffer.Joints?.AsNativeArray<SkinJoints>(Allocator.TempJob) ?? default;
var vertices = new NativeArray<MeshVertex>(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<short>(Allocator.Temp);
var shortIndices = src.IndexBuffer.AsNativeArray<short>(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<int>(Allocator.Temp);
var intIndices = src.IndexBuffer.AsNativeArray<int>(Allocator.Temp);
mesh.SetIndexBufferParams(intIndices.Length, IndexFormat.UInt32);
mesh.SetIndexBufferData(intIndices, 0, 0, intIndices.Length);
intIndices.Dispose();

View File

@ -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<Vector3>(vertexCount);
var normals = new List<Vector3>(vertexCount);
var uv = new List<Vector2>(vertexCount);
var boneWeights = new List<BoneWeight>(vertexCount);
var vertices = new NativeArray<MeshVertex>(vertexCount, Allocator.TempJob);
var jobDisposables = new List<IDisposable>();
// JobのSchedule
JobHandle jobHandle = default;
var indexOffset = 0;
foreach (var mesh in src.Meshes)
{
positions.AddRange(mesh.VertexBuffer.Positions.GetSpan<Vector3>());
normals.AddRange(mesh.VertexBuffer.Normals.GetSpan<Vector3>());
uv.AddRange(mesh.VertexBuffer.TexCoords.GetSpan<Vector2>());
if (src.Skin == null) continue;
var joints = mesh.VertexBuffer.Joints.GetSpan<SkinJoints>();
var weights = mesh.VertexBuffer.Weights.GetSpan<Vector4>();
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<Vector3>(Allocator.TempJob);
var normals = mesh.VertexBuffer.Normals.AsNativeArray<Vector3>(Allocator.TempJob);
var texCoords = mesh.VertexBuffer.TexCoords.AsNativeArray<Vector2>(Allocator.TempJob);
var weights = src.Skin != null ? mesh.VertexBuffer.Weights.AsNativeArray<Vector4>(Allocator.TempJob) : default;
var joints = src.Skin != null ? mesh.VertexBuffer.Joints.AsNativeArray<SkinJoints>(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<Matrix4x4>().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<Vector3>();
var blendShapeNormals = new List<Vector3>();
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<Vector3>());
var morphTarget = mesh.MorphTargets[i];
blendShapePositions.AddRange(morphTarget.VertexBuffer.Positions.GetSpan<Vector3>());
if (morphTarget.VertexBuffer.Normals != null)
{
normals.AddRange(morphTarget.VertexBuffer.Normals.GetSpan<Vector3>());
blendShapeNormals.AddRange(morphTarget.VertexBuffer.Normals.GetSpan<Vector3>());
}
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();

View File

@ -109,7 +109,7 @@ namespace VrmLib
/// バッファをNativeArrayに変換して返す
/// 開放の責務は使い手側にある点に注意
/// </summary>
public unsafe NativeArray<T> GetAsNativeArray<T>(Allocator allocator, bool checkStride = true) where T : struct
public unsafe NativeArray<T> AsNativeArray<T>(Allocator allocator, bool checkStride = true) where T : struct
{
if (checkStride && Marshal.SizeOf(typeof(T)) != Stride)
{