SkinnedMeshRendererかつボーンが存在しないとき、挙動がおかしくなる問題を修正した

This commit is contained in:
notargs
2022-01-19 18:30:15 +09:00
parent 95fb2eba1d
commit 9008ec0bf0
4 changed files with 115 additions and 52 deletions

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
@@ -10,6 +11,7 @@ namespace UniGLTF
internal class MeshContext
{
private readonly List<MeshVertex> _vertices = new List<MeshVertex>();
private readonly List<SkinnedMeshVertex> _skinnedMeshVertices = new List<SkinnedMeshVertex>();
private readonly List<int> _indices = new List<int>();
private readonly List<SubMeshDescriptor> _subMeshes = new List<SubMeshDescriptor>();
private readonly List<int> _materialIndices = new List<int>();
@@ -28,9 +30,30 @@ namespace UniGLTF
/// <param name="mesh"></param>
public void UploadMeshVertices(Mesh mesh)
{
mesh.SetVertexBufferParams(_vertices.Count, MeshVertex.GetVertexAttributeDescriptor());
var vertexAttributeDescriptor = MeshVertex.GetVertexAttributeDescriptor();
// Weight情報等は存在しないパターンがあり、かつこの存在の有無によって内部的に条件分岐が走ってしまうため、
// Streamを分けて必要に応じてアップロードする
if (_skinnedMeshVertices.Count > 0)
{
vertexAttributeDescriptor = vertexAttributeDescriptor.Concat(SkinnedMeshVertex
.GetVertexAttributeDescriptor().Select(
attr =>
{
attr.stream = 1;
return attr;
})).ToArray();
}
mesh.SetVertexBufferParams(_vertices.Count, vertexAttributeDescriptor);
mesh.SetVertexBufferData(_vertices, 0, 0, _vertices.Count);
if (_skinnedMeshVertices.Count > 0)
{
mesh.SetVertexBufferData(_skinnedMeshVertices, 0, 0, _skinnedMeshVertices.Count, 1);
}
}
/// <summary>
/// インデックス情報をMeshに対して送る
/// </summary>
@@ -149,7 +172,11 @@ namespace UniGLTF
normal,
texCoord0,
texCoord1,
color,
color
));
if (jointsGetter != null)
{
_skinnedMeshVertices.Add(new SkinnedMeshVertex(
joints.x,
joints.y,
joints.z,
@@ -157,8 +184,8 @@ namespace UniGLTF
weights.x,
weights.y,
weights.z,
weights.w
));
weights.w));
}
}
// blendshape
@@ -213,7 +240,8 @@ namespace UniGLTF
else
{
var indexOffset = _indices.Count;
_indices.AddRange(TriangleUtil.FlipTriangle(Enumerable.Range(0, _vertices.Count)).Select(index => index + vertexOffset));
_indices.AddRange(TriangleUtil.FlipTriangle(Enumerable.Range(0, _vertices.Count))
.Select(index => index + vertexOffset));
_subMeshes.Add(new SubMeshDescriptor(indexOffset, _vertices.Count));
}
@@ -284,16 +312,20 @@ namespace UniGLTF
normal,
texCoord0,
texCoord1,
color,
joints.x,
joints.y,
joints.z,
joints.w,
weights.x,
weights.y,
weights.z,
weights.w
color
));
if (jointsGetter != null)
{
_skinnedMeshVertices.Add(new SkinnedMeshVertex(
joints.x,
joints.y,
joints.z,
joints.w,
weights.x,
weights.y,
weights.z,
weights.w));
}
}
// blendshape
@@ -403,6 +435,7 @@ namespace UniGLTF
Truncate(blendShape.Normals, maxIndex);
Truncate(blendShape.Tangents, maxIndex);
}
Profiler.EndSample();
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Rendering;
@@ -6,8 +6,8 @@ using UnityEngine.Rendering;
namespace UniGLTF
{
/// <summary>
/// インターリーブされたメッシュの頂点情報を表す構造体
/// そのままGPUにアップロードされる
/// インターリーブされたメッシュの頂点情報のうち、基本的なものを表す構造体
/// 必要に応じてSkinnedMeshVertexとあわせてGPUにアップロードされる
/// </summary>
[Serializable, StructLayout(LayoutKind.Sequential)]
internal readonly struct MeshVertex
@@ -17,53 +17,27 @@ namespace UniGLTF
private readonly Color _color;
private readonly Vector2 _texCoord0;
private readonly Vector2 _texCoord1;
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 texCoord0,
Vector2 texCoord1,
Color color,
ushort boneIndex0,
ushort boneIndex1,
ushort boneIndex2,
ushort boneIndex3,
float boneWeight0,
float boneWeight1,
float boneWeight2,
float boneWeight3)
Color color)
{
_position = position;
_normal = normal;
_texCoord0 = texCoord0;
_texCoord1 = texCoord1;
_color = color;
_boneIndex0 = boneIndex0;
_boneIndex1 = boneIndex1;
_boneIndex2 = boneIndex2;
_boneIndex3 = boneIndex3;
_boneWeight0 = boneWeight0;
_boneWeight1 = boneWeight1;
_boneWeight2 = boneWeight2;
_boneWeight3 = boneWeight3;
}
public static VertexAttributeDescriptor[] GetVertexAttributeDescriptor() => new[] {
new VertexAttributeDescriptor(VertexAttribute.Position),
new VertexAttributeDescriptor(VertexAttribute.Normal),
new VertexAttributeDescriptor(VertexAttribute.Color, dimension: 4),
new VertexAttributeDescriptor(VertexAttribute.TexCoord0, dimension: 2),
new VertexAttributeDescriptor(VertexAttribute.TexCoord1, dimension: 2),
new VertexAttributeDescriptor(VertexAttribute.BlendWeight, dimension: 4),
new VertexAttributeDescriptor(VertexAttribute.BlendIndices, VertexAttributeFormat.UInt16, 4),
};
new VertexAttributeDescriptor(VertexAttribute.Normal),
new VertexAttributeDescriptor(VertexAttribute.Color, dimension: 4),
new VertexAttributeDescriptor(VertexAttribute.TexCoord0, dimension: 2),
new VertexAttributeDescriptor(VertexAttribute.TexCoord1, dimension: 2)
};
}
}

View File

@@ -1,3 +1,11 @@
fileFormatVersion: 2
guid: 0d540d8e32d54e7089a72156edb7ad80
timeCreated: 1636526648
fileFormatVersion: 2
guid: 3f4d5804612c4bddb05ece3a4b29bbdf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,48 @@
using System;
using System.Runtime.InteropServices;
using UnityEngine.Rendering;
namespace UniGLTF
{
/// <summary>
/// インターリーブされたメッシュの頂点情報のうち、SkinnedMeshに関連した情報を表す構造体
/// そのままGPUにアップロードされる
/// </summary>
[Serializable, StructLayout(LayoutKind.Sequential)]
internal readonly struct SkinnedMeshVertex
{
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 SkinnedMeshVertex(
ushort boneIndex0,
ushort boneIndex1,
ushort boneIndex2,
ushort boneIndex3,
float boneWeight0,
float boneWeight1,
float boneWeight2,
float boneWeight3)
{
_boneIndex0 = boneIndex0;
_boneIndex1 = boneIndex1;
_boneIndex2 = boneIndex2;
_boneIndex3 = boneIndex3;
_boneWeight0 = boneWeight0;
_boneWeight1 = boneWeight1;
_boneWeight2 = boneWeight2;
_boneWeight3 = boneWeight3;
}
public static VertexAttributeDescriptor[] GetVertexAttributeDescriptor() => new[] {
new VertexAttributeDescriptor(VertexAttribute.BlendWeight, dimension: 4),
new VertexAttributeDescriptor(VertexAttribute.BlendIndices, VertexAttributeFormat.UInt16, 4),
};
}
}