Skip to content

Commit 99767b5

Browse files
authored
fix: Preserve border edges bones not applied on build (#30)
1 parent c201a90 commit 99767b5

File tree

6 files changed

+87
-52
lines changed

6 files changed

+87
-52
lines changed

Ndmf/Editor/Meshia.MeshSimplification.Ndmf.Editor.asmdef

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
"Meshia.MeshSimplification.Ndmf.Runtime",
77
"nadena.dev.ndmf",
88
"nadena.dev.ndmf.runtime",
9-
"nadena.dev.modular-avatar.core",
10-
"Unity.Mathematics"
9+
"nadena.dev.modular-avatar.core"
1110
],
1211
"includePlatforms": [
1312
"Editor"

Ndmf/Editor/NdmfPlugin.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using nadena.dev.ndmf;
55
using nadena.dev.ndmf.preview;
66
using System;
7+
using System.Collections;
78
using UnityEditor;
89
using UnityEngine;
910
using UnityEngine.Pool;
@@ -39,19 +40,19 @@ protected override void Configure()
3940
{
4041
var meshiaMeshSimplifiers = context.AvatarRootObject.GetComponentsInChildren<MeshiaMeshSimplifier>(true);
4142
#if ENABLE_MODULAR_AVATAR
42-
43+
4344
var meshiaCascadingMeshSimplifiers = context.AvatarRootObject.GetComponentsInChildren<MeshiaCascadingAvatarMeshSimplifier>(true);
4445
#endif
4546

46-
using (ListPool<(Mesh Mesh, MeshSimplificationTarget Target, MeshSimplifierOptions Options, Mesh Destination)>.Get(out var parameters))
47+
using (ListPool<(Mesh Mesh, MeshSimplificationTarget Target, MeshSimplifierOptions Options, BitArray? preserveBorderEdgesBoneIndices, Mesh Destination)>.Get(out var parameters))
4748
{
4849
foreach (var meshiaMeshSimplifier in meshiaMeshSimplifiers)
4950
{
5051
if(meshiaMeshSimplifier.enabled && meshiaMeshSimplifier.TryGetComponent<Renderer>(out var renderer))
5152
{
5253
var sourceMesh = RendererUtility.GetRequiredMesh(renderer);
5354
Mesh simplifiedMesh = new();
54-
parameters.Add((sourceMesh, meshiaMeshSimplifier.target, meshiaMeshSimplifier.options, simplifiedMesh));
55+
parameters.Add((sourceMesh, meshiaMeshSimplifier.target, meshiaMeshSimplifier.options, null, simplifiedMesh));
5556
}
5657
}
5758
#if ENABLE_MODULAR_AVATAR
@@ -64,7 +65,10 @@ protected override void Configure()
6465
var mesh = RendererUtility.GetRequiredMesh(entry.GetTargetRenderer(meshiaCascadingMeshSimplifier)!);
6566
var target = new MeshSimplificationTarget() { Kind = MeshSimplificationTargetKind.AbsoluteTriangleCount, Value = entry.TargetTriangleCount };
6667
Mesh simplifiedMesh = new();
67-
parameters.Add((mesh, target, entry.Options, simplifiedMesh));
68+
69+
var preserveBorderEdgesBoneIndices = MeshiaCascadingAvatarMeshSimplifier.GetPreserveBorderEdgesBoneIndices(context.AvatarRootObject, meshiaCascadingMeshSimplifier, entry);
70+
71+
parameters.Add((mesh, target, entry.Options, preserveBorderEdgesBoneIndices, simplifiedMesh));
6872
}
6973
}
7074

@@ -78,7 +82,7 @@ protected override void Configure()
7882
{
7983
if(meshiaMeshSimplifier.enabled && meshiaMeshSimplifier.TryGetComponent<Renderer>(out var renderer))
8084
{
81-
var (mesh, target, options, simplifiedMesh) = parameters[i++];
85+
var (mesh, target, options, _, simplifiedMesh) = parameters[i++];
8286
AssetDatabase.AddObjectToAsset(simplifiedMesh, context.AssetContainer);
8387
RendererUtility.SetMesh(renderer, simplifiedMesh);
8488
}
@@ -96,7 +100,7 @@ protected override void Configure()
96100
{
97101
if (!cascadingTarget.IsValid(meshiaCascadingMeshSimplifier) || !cascadingTarget.Enabled) continue;
98102
var renderer = cascadingTarget.GetTargetRenderer(meshiaCascadingMeshSimplifier)!;
99-
var (mesh, target, options, simplifiedMesh) = parameters[i++];
103+
var (mesh, target, options, _, simplifiedMesh) = parameters[i++];
100104
AssetDatabase.AddObjectToAsset(simplifiedMesh, context.AssetContainer);
101105
RendererUtility.SetMesh(renderer, simplifiedMesh);
102106

Ndmf/Editor/Preview/MeshiaCascadingAvatarMeshSimplifierPreview.cs

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
using System.Collections.Immutable;
88
using System.Linq;
99
using nadena.dev.ndmf.preview;
10-
using nadena.dev.ndmf.util;
11-
using Unity.Mathematics;
1210
using UnityEngine;
1311

1412
namespace Meshia.MeshSimplification.Ndmf.Editor.Preview
@@ -50,42 +48,12 @@ protected override (MeshSimplificationTarget, MeshSimplifierOptions, BitArray?)
5048
var cascadingTarget = context.Observe(component, c => c.Entries[index] with { }, (a, b) => a.Equals(b));
5149
var target = new MeshSimplificationTarget() { Kind = MeshSimplificationTargetKind.AbsoluteTriangleCount, Value = cascadingTarget.TargetTriangleCount };
5250

53-
54-
55-
56-
if(original is SkinnedMeshRenderer skinnedMeshRenderer)
57-
{
58-
var avatarRoot = context.GetAvatarRoot(original.gameObject);
59-
if(avatarRoot != null)
60-
{
61-
var avatarAnimator = avatarRoot.GetComponent<Animator>();
62-
63-
var bones = skinnedMeshRenderer.bones;
64-
var preserveBorderEdgeBoneIndices = new BitArray(bones.Length);
65-
66-
for (ulong boneMask = cascadingTarget.PreserveBorderEdgesBones; boneMask != 0ul; boneMask &= boneMask - 1)
67-
{
68-
var bone = (HumanBodyBones)math.tzcnt(boneMask);
69-
var boneTransform = avatarAnimator.GetBoneTransform(bone);
70-
if (boneTransform != null)
71-
{
72-
var boneIndex = Array.IndexOf(bones, boneTransform);
73-
if (boneIndex >= 0)
74-
{
75-
preserveBorderEdgeBoneIndices.Set(boneIndex, true);
76-
}
77-
}
78-
}
79-
80-
return (target, cascadingTarget.Options, preserveBorderEdgeBoneIndices);
81-
}
82-
83-
}
84-
return (target, cascadingTarget.Options, null);
85-
86-
87-
51+
var avatarRoot = context.GetAvatarRoot(original.gameObject);
52+
var preserveBorderEdgeBoneIndices = MeshiaCascadingAvatarMeshSimplifier.GetPreserveBorderEdgesBoneIndices(avatarRoot, component, cascadingTarget);
53+
return (target, cascadingTarget.Options, preserveBorderEdgeBoneIndices);
8854
}
55+
56+
8957
}
9058
}
9159

Ndmf/Runtime/Meshia.MeshSimplification.Ndmf.Runtime.asmdef

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
"Meshia.MeshSimplification.Runtime",
66
"VRC.SDKBase",
77
"nadena.dev.modular-avatar.core",
8-
"nadena.dev.ndmf.runtime"
8+
"nadena.dev.ndmf.runtime",
9+
"Unity.Mathematics"
910
],
1011
"includePlatforms": [],
1112
"excludePlatforms": [],

Ndmf/Runtime/MeshiaCascadingAvatarMeshSimplifier.cs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
using System.Collections.Generic;
77
using System.Linq;
88
using UnityEngine;
9-
using nadena.dev.ndmf.runtime;
109
using nadena.dev.modular_avatar.core;
1110
using UnityEngine.Pool;
1211
using System.Diagnostics.CodeAnalysis;
12+
using System.Collections;
13+
using Unity.Mathematics;
1314

1415
namespace Meshia.MeshSimplification.Ndmf
1516
{
@@ -127,6 +128,35 @@ public void ResolveReferences()
127128
target.ResolveReference(this);
128129
}
129130
}
131+
public static BitArray? GetPreserveBorderEdgesBoneIndices(GameObject avatarRoot, MeshiaCascadingAvatarMeshSimplifier avatarMeshSimplifier, MeshiaCascadingAvatarMeshSimplifierRendererEntry entry)
132+
{
133+
if (avatarRoot.TryGetComponent(out Animator avatarAnimator) && entry.GetTargetRenderer(avatarMeshSimplifier) is SkinnedMeshRenderer skinnedMeshRenderer)
134+
{
135+
var bones = skinnedMeshRenderer.bones;
136+
var preserveBorderEdgeBoneIndices = new BitArray(bones.Length);
137+
138+
for (ulong boneMask = entry.PreserveBorderEdgesBones; boneMask != 0ul; boneMask &= boneMask - 1)
139+
{
140+
var bone = (HumanBodyBones)math.tzcnt(boneMask);
141+
var boneTransform = avatarAnimator.GetBoneTransform(bone);
142+
if (boneTransform != null)
143+
{
144+
var boneIndex = Array.IndexOf(bones, boneTransform);
145+
if (boneIndex != -1)
146+
{
147+
preserveBorderEdgeBoneIndices.Set(boneIndex, true);
148+
}
149+
}
150+
}
151+
return preserveBorderEdgeBoneIndices;
152+
}
153+
else
154+
{
155+
return null;
156+
}
157+
158+
159+
}
130160
}
131161

132162
[Serializable]

Runtime/MeshSimplifier.cs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System;
33
using System.Collections;
44
using System.Collections.Generic;
5+
using System.Linq;
56
using System.Threading;
67
using System.Threading.Tasks;
78
using Unity.Collections;
@@ -67,7 +68,17 @@ public struct MeshSimplifier : INativeDisposable
6768
/// <param name="options">The options for this mesh simplification.</param>
6869
/// <param name="destination">The destination to write simplified mesh.</param>
6970
/// <remarks>To process multiple meshes at once, use <see cref="SimplifyBatch(IReadOnlyList{ValueTuple{Mesh, MeshSimplificationTarget, MeshSimplifierOptions, Mesh}})"/> instead.</remarks>
70-
public static void Simplify(Mesh mesh, MeshSimplificationTarget target, MeshSimplifierOptions options, Mesh destination)
71+
public static void Simplify(Mesh mesh, MeshSimplificationTarget target, MeshSimplifierOptions options, Mesh destination)
72+
=> Simplify(mesh, target, options, null, destination);
73+
/// <summary>
74+
/// Simplifies the given <paramref name="mesh"/> and writes the result to <paramref name="destination"/>.
75+
/// </summary>
76+
/// <param name="mesh">The mesh to simplify.</param>
77+
/// <param name="target">The simplification target for this mesh simplification.</param>
78+
/// <param name="options">The options for this mesh simplification.</param>
79+
/// <param name="destination">The destination to write simplified mesh.</param>
80+
/// <remarks>To process multiple meshes at once, use <see cref="SimplifyBatch(IReadOnlyList{ValueTuple{Mesh, MeshSimplificationTarget, MeshSimplifierOptions, Mesh}})"/> instead.</remarks>
81+
public static void Simplify(Mesh mesh, MeshSimplificationTarget target, MeshSimplifierOptions options, BitArray? preserveBorderEdgesBoneIndices, Mesh destination)
7182
{
7283
Allocator allocator = Unity.Collections.Allocator.TempJob;
7384
var originalMeshDataArray = Mesh.AcquireReadOnlyMeshData(mesh);
@@ -76,11 +87,21 @@ public static void Simplify(Mesh mesh, MeshSimplificationTarget target, MeshSimp
7687

7788
var meshSimplifier = new MeshSimplifier(allocator);
7889

90+
NativeBitArray nativePreserveBorderEdgesBoneIndices = new(preserveBorderEdgesBoneIndices?.Length ?? 0, allocator, NativeArrayOptions.UninitializedMemory);
91+
if (preserveBorderEdgesBoneIndices is not null)
92+
{
93+
for (int i = 0; i < preserveBorderEdgesBoneIndices.Length; i++)
94+
{
95+
nativePreserveBorderEdgesBoneIndices.Set(i, preserveBorderEdgesBoneIndices[i]);
96+
}
97+
}
98+
7999
var load = meshSimplifier.ScheduleLoadMeshData(originalMeshData, options);
80100

81101
var simplifiedMeshDataArray = Mesh.AllocateWritableMeshData(1);
82102
NativeList<BlendShapeData> simplifiedBlendShapes = new(allocator);
83-
var simplify = meshSimplifier.ScheduleSimplify(originalMeshData, blendShapes, target, load);
103+
var simplify = meshSimplifier.ScheduleSimplify(originalMeshData, blendShapes, target, nativePreserveBorderEdgesBoneIndices, load);
104+
nativePreserveBorderEdgesBoneIndices.Dispose(simplify);
84105
var write = meshSimplifier.ScheduleWriteMeshData(originalMeshData, blendShapes, simplifiedMeshDataArray[0], simplifiedBlendShapes, simplify);
85106
meshSimplifier.Dispose(write);
86107
JobHandle.ScheduleBatchedJobs();
@@ -102,7 +123,10 @@ public static void Simplify(Mesh mesh, MeshSimplificationTarget target, MeshSimp
102123
}
103124
simplifiedBlendShapes.Dispose();
104125
}
105-
public static void SimplifyBatch(IReadOnlyList<(Mesh Mesh, MeshSimplificationTarget Target, MeshSimplifierOptions Options, Mesh Destination)> parameters)
126+
public static void SimplifyBatch(IReadOnlyList<(Mesh Mesh, MeshSimplificationTarget Target, MeshSimplifierOptions Options, Mesh Destination)> parameters)
127+
=> SimplifyBatch(parameters.Select<(Mesh Mesh, MeshSimplificationTarget Target, MeshSimplifierOptions Options, Mesh Destination), (Mesh, MeshSimplificationTarget, MeshSimplifierOptions, BitArray?, Mesh)>(p => (p.Mesh, p.Target, p.Options, null, p.Destination)).ToList());
128+
129+
public static void SimplifyBatch(IReadOnlyList<(Mesh Mesh, MeshSimplificationTarget Target, MeshSimplifierOptions Options, BitArray? PreserveBorderEdgesBoneIndices, Mesh Destination)> parameters)
106130
{
107131
Allocator allocator = Unity.Collections.Allocator.TempJob;
108132

@@ -124,16 +148,25 @@ public static void SimplifyBatch(IReadOnlyList<(Mesh Mesh, MeshSimplificationTar
124148

125149
for (int i = 0; i < parameters.Count; i++)
126150
{
127-
var (mesh, target, options, destination) = parameters[i];
151+
var (mesh, target, options, preserveBorderEdgesBoneIndices, destination) = parameters[i];
128152
var originalMeshData = originalMeshDataArray[i];
129153
var blendShapes = BlendShapeData.GetMeshBlendShapes(mesh, allocator);
130154
blendShapesList[i] = blendShapes;
131155
var meshSimplifier = new MeshSimplifier(allocator);
156+
NativeBitArray nativePreserveBorderEdgesBoneIndices = new(preserveBorderEdgesBoneIndices?.Length ?? 0, allocator, NativeArrayOptions.UninitializedMemory);
157+
if (preserveBorderEdgesBoneIndices is not null)
158+
{
159+
for (int boneIndex = 0; boneIndex < preserveBorderEdgesBoneIndices.Length; boneIndex++)
160+
{
161+
nativePreserveBorderEdgesBoneIndices.Set(boneIndex, preserveBorderEdgesBoneIndices[boneIndex]);
162+
}
163+
}
132164
var load = meshSimplifier.ScheduleLoadMeshData(originalMeshData, options);
133165
NativeList<BlendShapeData> simplifiedBlendShapes = new(allocator);
134166
simplifiedBlendShapesList[i] = simplifiedBlendShapes;
135167

136-
var simplify = meshSimplifier.ScheduleSimplify(originalMeshData, blendShapes, target, load);
168+
var simplify = meshSimplifier.ScheduleSimplify(originalMeshData, blendShapes, target, nativePreserveBorderEdgesBoneIndices, load);
169+
nativePreserveBorderEdgesBoneIndices.Dispose(simplify);
137170
var write = meshSimplifier.ScheduleWriteMeshData(originalMeshData, blendShapes, simplifiedMeshDataArray[i], simplifiedBlendShapes, simplify);
138171
meshSimplifier.Dispose(write);
139172
jobHandles[i] = write;

0 commit comments

Comments
 (0)