[BetterShadowClone] Reworked vert finding for exclusions to not nuke game for 20s

This commit is contained in:
NotAKidoS 2024-02-03 05:40:11 -06:00
parent 0d82606308
commit df45fb50d9
4 changed files with 64 additions and 44 deletions

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using ABI_RC.Core; using ABI_RC.Core;
using ABI.CCK.Components; using ABI.CCK.Components;
using UnityEngine; using UnityEngine;
@ -44,8 +45,13 @@ public static class ShadowCloneHelper
private static void ProcessRenderers(IEnumerable<Renderer> renderers, Transform root, Transform headBone) private static void ProcessRenderers(IEnumerable<Renderer> renderers, Transform root, Transform headBone)
{ {
Stopwatch sw = Stopwatch.StartNew();
IReadOnlyDictionary<Transform, FPRExclusion> exclusions = CollectTransformToExclusionMap(root, headBone); IReadOnlyDictionary<Transform, FPRExclusion> exclusions = CollectTransformToExclusionMap(root, headBone);
// log current time
ShadowCloneMod.Logger.Msg($"CollectTransformToExclusionMap in {sw.ElapsedMilliseconds}ms");
foreach (Renderer renderer in renderers) foreach (Renderer renderer in renderers)
{ {
ConfigureRenderer(renderer); ConfigureRenderer(renderer);
@ -59,6 +65,11 @@ public static class ShadowCloneHelper
ITransformHider hider = TransformHiderManager.CreateTransformHider(renderer, exclusions); ITransformHider hider = TransformHiderManager.CreateTransformHider(renderer, exclusions);
if (hider != null) TransformHiderManager.Instance.AddTransformHider(hider); if (hider != null) TransformHiderManager.Instance.AddTransformHider(hider);
} }
sw.Stop();
// log current time
ShadowCloneMod.Logger.Msg($"ProcessRenderers in {sw.ElapsedMilliseconds}ms");
} }
#endregion #endregion

View file

@ -10,6 +10,8 @@ public class FPRExclusion : MonoBehaviour
{ {
public Transform target; public Transform target;
internal readonly List<int> affectedVertexIndices = new();
internal readonly List<Transform> affectedChildren = new(); internal readonly List<Transform> affectedChildren = new();
internal readonly List<IFPRExclusionTask> relatedTasks = new(); internal readonly List<IFPRExclusionTask> relatedTasks = new();

View file

@ -16,9 +16,6 @@ public class MeshTransformHider : ITransformHider, IFPRExclusionTask
private readonly MeshRenderer _mainMesh; private readonly MeshRenderer _mainMesh;
private bool _enabledState; private bool _enabledState;
// exclusion
private readonly FPRExclusion _exclusion;
#region ITransformHider Methods #region ITransformHider Methods
public bool IsActive { get; set; } = true; // default hide, but FPRExclusion can override public bool IsActive { get; set; } = true; // default hide, but FPRExclusion can override
@ -37,8 +34,7 @@ public class MeshTransformHider : ITransformHider, IFPRExclusionTask
return; return;
} }
_exclusion = exclusion; exclusion.relatedTasks.Add(this);
_exclusion.relatedTasks.Add(this);
_mainMesh = renderer; _mainMesh = renderer;

View file

@ -1,4 +1,5 @@
using System; using System;
using System.Diagnostics;
using UnityEngine; using UnityEngine;
using UnityEngine.Rendering; using UnityEngine.Rendering;
@ -38,6 +39,8 @@ public class SkinnedTransformHider : ITransformHider
public SkinnedTransformHider(SkinnedMeshRenderer renderer, IReadOnlyDictionary<Transform, FPRExclusion> exclusions) public SkinnedTransformHider(SkinnedMeshRenderer renderer, IReadOnlyDictionary<Transform, FPRExclusion> exclusions)
{ {
Stopwatch sw = Stopwatch.StartNew();
_mainMesh = renderer; _mainMesh = renderer;
if (_mainMesh == null if (_mainMesh == null
@ -52,36 +55,35 @@ public class SkinnedTransformHider : ITransformHider
_rootBone = _mainMesh.rootBone; _rootBone = _mainMesh.rootBone;
_rootBone ??= _mainMesh.transform; // fallback to transform if no root bone _rootBone ??= _mainMesh.transform; // fallback to transform if no root bone
// subtask creation // log current time
ShadowCloneMod.Logger.Msg($"SkinnedTransformHider part 1 in {sw.ElapsedMilliseconds}ms");
var bones = renderer.bones; SubTask.FindExclusionVertList(renderer, exclusions);
List<FPRExclusion> fprExclusions = new();
foreach (Transform bone in bones) foreach (var exclusion in exclusions)
{ {
if (bone == null) FPRExclusion fprExclusion = exclusion.Value;
continue; // thanks AdvancedSafety for preventing null ref for so long... if (fprExclusion.affectedVertexIndices.Count == 0)
continue; // no affected verts
if (!exclusions.TryGetValue(bone, out FPRExclusion exclusion)) SubTask subTask = new(this, fprExclusion, fprExclusion.affectedVertexIndices);
continue;
fprExclusions.Add(exclusion);
}
List<int> exclusionVerts;
foreach (FPRExclusion exclusion in fprExclusions)
{
exclusionVerts = SubTask.FindExclusionVertList(renderer, exclusion);
if (exclusionVerts.Count == 0)
continue;
SubTask subTask = new(this, exclusion, exclusionVerts);
_subTasks.Add(subTask); _subTasks.Add(subTask);
exclusion.relatedTasks.Add(subTask); fprExclusion.relatedTasks.Add(subTask);
fprExclusion.affectedVertexIndices.Clear(); // clear list for next SkinnedTransformHider
} }
// log current time
ShadowCloneMod.Logger.Msg($"SkinnedTransformHider part 3 in {sw.ElapsedMilliseconds}ms");
if (_subTasks.Count == 0) if (_subTasks.Count == 0)
{
Dispose(); // had the bones, but not the weights :? Dispose(); // had the bones, but not the weights :?
ShadowCloneMod.Logger.Warning("SkinnedTransformHider No valid exclusions found!");
}
sw.Stop();
ShadowCloneMod.Logger.Msg($"SkinnedTransformHider created in {sw.ElapsedMilliseconds}ms");
} }
public bool Process() public bool Process()
@ -177,13 +179,10 @@ public class SkinnedTransformHider : ITransformHider
private readonly ComputeBuffer _computeBuffer; private readonly ComputeBuffer _computeBuffer;
private readonly int _threadGroups; private readonly int _threadGroups;
private readonly FPRExclusion _exclusion;
public SubTask(SkinnedTransformHider parent, FPRExclusion exclusion, List<int> exclusionVerts) public SubTask(SkinnedTransformHider parent, FPRExclusion exclusion, List<int> exclusionVerts)
{ {
_parent = parent; _parent = parent;
_exclusion = exclusion; _shrinkBone = exclusion.target;
_shrinkBone = _exclusion.target;
_vertexCount = exclusionVerts.Count; _vertexCount = exclusionVerts.Count;
_computeBuffer = new ComputeBuffer(_vertexCount, sizeof(int)); _computeBuffer = new ComputeBuffer(_vertexCount, sizeof(int));
@ -211,28 +210,40 @@ public class SkinnedTransformHider : ITransformHider
#region Private Methods #region Private Methods
public static List<int> FindExclusionVertList(SkinnedMeshRenderer renderer, FPRExclusion exclusion) public static void FindExclusionVertList(SkinnedMeshRenderer renderer, IReadOnlyDictionary<Transform, FPRExclusion> exclusions)
{ {
var boneWeights = renderer.sharedMesh.boneWeights; var boneWeights = renderer.sharedMesh.boneWeights;
var bones = exclusion.affectedChildren;
HashSet<int> weights = new(); HashSet<int> weights = new();
for (int i = 0; i < renderer.bones.Length; i++) for (int i = 0; i < renderer.bones.Length; i++)
if (bones.Contains(renderer.bones[i])) weights.Add(i); {
// if bone == any key in exclusions, add to weights
if (!exclusions.TryGetValue(renderer.bones[i], out FPRExclusion _))
continue;
weights.Add(i);
}
List<int> headVertices = new();
for (int i = 0; i < boneWeights.Length; i++) for (int i = 0; i < boneWeights.Length; i++)
{ {
BoneWeight weight = boneWeights[i]; BoneWeight weight = boneWeights[i];
Transform bone = null;
const float minWeightThreshold = 0.2f; const float minWeightThreshold = 0.2f;
if (weights.Contains(weight.boneIndex0) && weight.weight0 > minWeightThreshold if (weights.Contains(weight.boneIndex0) && weight.weight0 > minWeightThreshold)
|| weights.Contains(weight.boneIndex1) && weight.weight1 > minWeightThreshold bone = renderer.bones[weight.boneIndex0];
|| weights.Contains(weight.boneIndex2) && weight.weight2 > minWeightThreshold else if (weights.Contains(weight.boneIndex1) && weight.weight1 > minWeightThreshold)
|| weights.Contains(weight.boneIndex3) && weight.weight3 > minWeightThreshold) bone = renderer.bones[weight.boneIndex1];
headVertices.Add(i); else if (weights.Contains(weight.boneIndex2) && weight.weight2 > minWeightThreshold)
} bone = renderer.bones[weight.boneIndex2];
else if (weights.Contains(weight.boneIndex3) && weight.weight3 > minWeightThreshold)
bone = renderer.bones[weight.boneIndex3];
return headVertices; if (bone == null) continue; // no bone found
// add vertex to exclusion list
exclusions[bone].affectedVertexIndices.Add(i);
}
} }
#endregion #endregion