Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Ndmf/Editor/Meshia.MeshSimplification.Ndmf.Editor.asmdef
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"Meshia.MeshSimplification.Ndmf.Runtime",
"nadena.dev.ndmf",
"nadena.dev.ndmf.runtime",
"nadena.dev.modular-avatar.core"
"nadena.dev.modular-avatar.core",
"Unity.Mathematics"
],
"includePlatforms": [
"Editor"
Expand Down
44 changes: 42 additions & 2 deletions Ndmf/Editor/MeshiaCascadingAvatarMeshSimplifierEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ public override VisualElement CreateInspectorGUI()
var targetTriangleCountField = itemRoot.Q<IntegerField>("TargetTriangleCountField");
var originalTriangleCountField = itemRoot.Q<IntegerField>("OriginalTriangleCountField");
var unknownOriginalTriangleCountField = itemRoot.Q<TextField>("UnknownOriginalTriangleCountField");
var preserveBorderEdgesBonesFoldout = itemRoot.Q<Foldout>("PreserveBorderEdgesBonesFoldout");
itemRoot.BindProperty(entryProperty);
itemRoot.userData = index;
var targetRenderer = entry.GetTargetRenderer(Target);
Expand Down Expand Up @@ -225,7 +226,15 @@ public override VisualElement CreateInspectorGUI()

}

var humanBodyBoneIndex = 0;
var preserveBorderEdgesBonesProperty = EntriesProperty.GetArrayElementAtIndex(index).FindPropertyRelative(nameof(MeshiaCascadingAvatarMeshSimplifierRendererEntry.PreserveBorderEdgesBones));
var preserveBorderEdgesBones = preserveBorderEdgesBonesProperty.ulongValue;
foreach (var preserveBorderEdgesBoneToggle in preserveBorderEdgesBonesFoldout.Children().OfType<Toggle>())
{
preserveBorderEdgesBoneToggle.value = (preserveBorderEdgesBones & (1ul << humanBodyBoneIndex)) != 0ul;

humanBodyBoneIndex++;
}
};


Expand All @@ -239,6 +248,7 @@ public override VisualElement CreateInspectorGUI()
var triangleCountDivider = itemRoot.Q<Label>("TriangleCountDivider");
var optionsToggle = itemRoot.Q<Toggle>("OptionsToggle");
var optionsField = itemRoot.Q<PropertyField>("OptionsField");
var preserveBorderEdgesBonesFoldout = itemRoot.Q<Foldout>("PreserveBorderEdgesBonesFoldout");
enabledToggle.RegisterValueChangedCallback(changeEvent =>
{
var enabled = changeEvent.newValue;
Expand Down Expand Up @@ -268,9 +278,39 @@ public override VisualElement CreateInspectorGUI()

optionsToggle.RegisterValueChangedCallback(changeEvent =>
{
optionsField.style.display = changeEvent.newValue ? DisplayStyle.Flex : DisplayStyle.None;
optionsField.style.display = preserveBorderEdgesBonesFoldout.style.display = changeEvent.newValue ? DisplayStyle.Flex : DisplayStyle.None;
});




for (HumanBodyBones bone = 0; bone < HumanBodyBones.LastBone; bone++)
{
var humanBodyBoneIndex = (int)bone;
Toggle preserveBorderEdgesBoneToggle = new(bone.ToString());
preserveBorderEdgesBoneToggle.RegisterValueChangedCallback(changeEvent =>
{
if(itemRoot.userData is int itemIndex)
{
var preserveBorderEdgesBonesProperty = EntriesProperty.GetArrayElementAtIndex(itemIndex).FindPropertyRelative(nameof(MeshiaCascadingAvatarMeshSimplifierRendererEntry.PreserveBorderEdgesBones));
serializedObject.Update();
var currentMask = preserveBorderEdgesBonesProperty.ulongValue;
if (changeEvent.newValue)
{
currentMask |= (1ul << humanBodyBoneIndex);
}
else
{
currentMask &= ~(1ul << humanBodyBoneIndex);
}
preserveBorderEdgesBonesProperty.ulongValue = currentMask;

serializedObject.ApplyModifiedProperties();
}

});
preserveBorderEdgesBonesFoldout.Add(preserveBorderEdgesBoneToggle);
}

return itemRoot;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
<ui:Toggle name="OptionsToggle" style="align-self: center;" />
</ui:VisualElement>
<uie:PropertyField binding-path="Options" name="OptionsField" style="display: none;" />
<ui:Foldout text="Preserve Border Edges Bones" name="PreserveBorderEdgesBonesFoldout" value="false" style="display: none;" />
</ui:UXML>
43 changes: 41 additions & 2 deletions Ndmf/Editor/Preview/MeshiaCascadingAvatarMeshSimplifierPreview.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
#nullable enable
#if ENABLE_MODULAR_AVATAR

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using nadena.dev.ndmf.preview;
using nadena.dev.ndmf.util;
using Unity.Mathematics;
using UnityEngine;

namespace Meshia.MeshSimplification.Ndmf.Editor.Preview
Expand Down Expand Up @@ -37,15 +41,50 @@ public override ImmutableList<RenderGroup> GetTargetGroups(ComputeContext contex
return groups.ToImmutableList();
}

protected override (MeshSimplificationTarget, MeshSimplifierOptions) QueryTarget(ComputeContext context, RenderGroup group, Renderer original, Renderer proxy)
protected override (MeshSimplificationTarget, MeshSimplifierOptions, BitArray?) QueryTarget(ComputeContext context, RenderGroup group, Renderer original, Renderer proxy)
{
var data = group.GetData<(MeshiaCascadingAvatarMeshSimplifier, int)>();
var component = data.Item1;
var index = data.Item2;

var cascadingTarget = context.Observe(component, c => c.Entries[index] with { }, (a, b) => a.Equals(b));
var target = new MeshSimplificationTarget() { Kind = MeshSimplificationTargetKind.AbsoluteTriangleCount, Value = cascadingTarget.TargetTriangleCount };
return (target, cascadingTarget.Options);




if(original is SkinnedMeshRenderer skinnedMeshRenderer)
{
var avatarRoot = context.GetAvatarRoot(original.gameObject);
if(avatarRoot != null)
{
var avatarAnimator = avatarRoot.GetComponent<Animator>();

var bones = skinnedMeshRenderer.bones;
var preserveBorderEdgeBoneIndices = new BitArray(bones.Length);

for (ulong boneMask = cascadingTarget.PreserveBorderEdgesBones; boneMask != 0ul; boneMask &= boneMask - 1)
{
var bone = (HumanBodyBones)math.tzcnt(boneMask);
var boneTransform = avatarAnimator.GetBoneTransform(bone);
if (boneTransform != null)
{
var boneIndex = Array.IndexOf(bones, boneTransform);
if (boneIndex >= 0)
{
preserveBorderEdgeBoneIndices.Set(boneIndex, true);
}
}
}

return (target, cascadingTarget.Options, preserveBorderEdgeBoneIndices);
}

}
return (target, cascadingTarget.Options, null);



}
}
}
Expand Down
5 changes: 3 additions & 2 deletions Ndmf/Editor/Preview/MeshiaMeshSimplifierPreview.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#nullable enable

using System.Collections;
using System.Collections.Immutable;
using System.Linq;
using nadena.dev.ndmf.preview;
Expand All @@ -18,12 +19,12 @@ public override ImmutableList<RenderGroup> GetTargetGroups(ComputeContext contex
.Select(renderer => RenderGroup.For(renderer))
.ToImmutableList();
}
protected override (MeshSimplificationTarget, MeshSimplifierOptions) QueryTarget(ComputeContext context, RenderGroup group, Renderer original, Renderer proxy)
protected override (MeshSimplificationTarget, MeshSimplifierOptions, BitArray?) QueryTarget(ComputeContext context, RenderGroup group, Renderer original, Renderer proxy)
{
var ndmfMeshSimplifier = original.GetComponent<MeshiaMeshSimplifier>();
var target = context.Observe(ndmfMeshSimplifier, ndmfMeshSimplifier => ndmfMeshSimplifier.target, (x, y) => x == y);
var options = context.Observe(ndmfMeshSimplifier, ndmfMeshSimplifier => ndmfMeshSimplifier.options, (x, y) => x == y);
return (target, options);
return (target, options, null);
}
}
}
7 changes: 4 additions & 3 deletions Ndmf/Editor/Preview/MeshiaMeshSimplifierPreviewBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Threading.Tasks;
using UnityEngine;
using nadena.dev.ndmf.preview;
using System.Collections;

namespace Meshia.MeshSimplification.Ndmf.Editor.Preview
{
Expand Down Expand Up @@ -39,12 +40,12 @@ async Task<IRenderFilterNode> IRenderFilter.Instantiate(RenderGroup group, IEnum
var proxy = proxyPairs.First().Item2;
var proxyMesh = RendererUtility.GetRequiredMesh(proxy);

var (target, options) = QueryTarget(context, group, original, proxy);
var (target, options, preserveBorderEdgesBoneIndices) = QueryTarget(context, group, original, proxy);

Mesh simplifiedMesh = new();
try
{
await MeshSimplifier.SimplifyAsync(proxyMesh, target, options, simplifiedMesh);
await MeshSimplifier.SimplifyAsync(proxyMesh, target, options, preserveBorderEdgesBoneIndices, simplifiedMesh);
}
catch (Exception)
{
Expand All @@ -57,7 +58,7 @@ async Task<IRenderFilterNode> IRenderFilter.Instantiate(RenderGroup group, IEnum
return new NdmfMeshSimplifierPreviewNode(simplifiedMesh);
}

protected abstract (MeshSimplificationTarget, MeshSimplifierOptions) QueryTarget(ComputeContext context, RenderGroup group, Renderer original, Renderer proxy);
protected abstract (MeshSimplificationTarget, MeshSimplifierOptions, BitArray?) QueryTarget(ComputeContext context, RenderGroup group, Renderer original, Renderer proxy);
}

internal class NdmfMeshSimplifierPreviewNode : IRenderFilterNode
Expand Down
35 changes: 34 additions & 1 deletion Ndmf/Runtime/MeshiaCascadingAvatarMeshSimplifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class MeshiaCascadingAvatarMeshSimplifier : MonoBehaviour
public List<MeshiaCascadingAvatarMeshSimplifierRendererEntry> Entries = new();
public int TargetTriangleCount = 70000;
public bool AutoAdjustEnabled = true;

public void RefreshEntries()
{
using (ListPool<Renderer>.Get(out var ownedRenderers))
Expand Down Expand Up @@ -135,6 +135,7 @@ public record MeshiaCascadingAvatarMeshSimplifierRendererEntry
public AvatarObjectReference RendererObjectReference;
public int TargetTriangleCount;
public MeshSimplifierOptions Options;
public ulong PreserveBorderEdgesBones;
public bool Enabled;
public bool Fixed;

Expand All @@ -144,6 +145,37 @@ public MeshiaCascadingAvatarMeshSimplifierRendererEntry(Renderer renderer)
RendererObjectReference.Set(renderer.gameObject);
TargetTriangleCount = RendererUtility.GetMesh(renderer)?.GetTriangleCount() ?? 0;
Options = MeshSimplifierOptions.Default;
PreserveBorderEdgesBones =
(1ul << (int)HumanBodyBones.LeftThumbProximal) |
(1ul << (int)HumanBodyBones.LeftThumbIntermediate) |
(1ul << (int)HumanBodyBones.LeftThumbDistal) |
(1ul << (int)HumanBodyBones.LeftIndexProximal) |
(1ul << (int)HumanBodyBones.LeftIndexIntermediate) |
(1ul << (int)HumanBodyBones.LeftIndexDistal) |
(1ul << (int)HumanBodyBones.LeftMiddleProximal) |
(1ul << (int)HumanBodyBones.LeftMiddleIntermediate) |
(1ul << (int)HumanBodyBones.LeftMiddleDistal) |
(1ul << (int)HumanBodyBones.LeftRingProximal) |
(1ul << (int)HumanBodyBones.LeftRingIntermediate) |
(1ul << (int)HumanBodyBones.LeftRingDistal) |
(1ul << (int)HumanBodyBones.LeftLittleProximal) |
(1ul << (int)HumanBodyBones.LeftLittleIntermediate) |
(1ul << (int)HumanBodyBones.LeftLittleDistal) |
(1ul << (int)HumanBodyBones.RightThumbProximal) |
(1ul << (int)HumanBodyBones.RightThumbIntermediate) |
(1ul << (int)HumanBodyBones.RightThumbDistal) |
(1ul << (int)HumanBodyBones.RightIndexProximal) |
(1ul << (int)HumanBodyBones.RightIndexIntermediate) |
(1ul << (int)HumanBodyBones.RightIndexDistal) |
(1ul << (int)HumanBodyBones.RightMiddleProximal) |
(1ul << (int)HumanBodyBones.RightMiddleIntermediate) |
(1ul << (int)HumanBodyBones.RightMiddleDistal) |
(1ul << (int)HumanBodyBones.RightRingProximal) |
(1ul << (int)HumanBodyBones.RightRingIntermediate) |
(1ul << (int)HumanBodyBones.RightRingDistal) |
(1ul << (int)HumanBodyBones.RightLittleProximal) |
(1ul << (int)HumanBodyBones.RightLittleIntermediate) |
(1ul << (int)HumanBodyBones.RightLittleDistal);
Enabled = true;
Fixed = false;
}
Expand Down Expand Up @@ -187,6 +219,7 @@ internal void ResolveReference(Component container)
RendererObjectReference.Get(container);
}
}

}

#endif
16 changes: 12 additions & 4 deletions Runtime/Jobs/ComputeMergesJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,28 @@ struct ComputeMergesJob : IJobParallelForDefer
public NativeBitArray VertexIsBorderEdgeBits;
[ReadOnly]
public NativeArray<int2> Edges;
[ReadOnly]
public NativeArray<uint> VertexBlendIndicesBuffer;

[ReadOnly]
public NativeBitArray PreserveBorderEdgesBoneIndices;
[WriteOnly]
public NativeArray<VertexMerge> UnorderedDirtyVertexMerges;

public MeshSimplifierOptions Options;
public bool PreserveBorderEdges;
public bool PreserveSurfaceCurvature;
public void Execute(int index)
{
var mergeFactory = new MergeFactory
{
VertexPositions = VertexPositionBuffer,
VertexPositionBuffer = VertexPositionBuffer,
VertexErrorQuadrics = VertexErrorQuadrics,
VertexContainingTriangles = VertexContainingTriangles,
VertexIsBorderEdgeBits = VertexIsBorderEdgeBits,
TriangleNormals = TriangleNormals,
Options = Options,
PreserveBorderEdges = PreserveBorderEdges,
PreserveSurfaceCurvature = PreserveSurfaceCurvature,
PreserveBorderEdgesBoneIndices = PreserveBorderEdgesBoneIndices,
VertexBlendIndicesBuffer = VertexBlendIndicesBuffer,
};
var edge = Edges[index];
VertexMerge merge;
Expand Down
Loading
Loading