mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-02 06:19:22 +00:00
[BetterShadowClone] Reworked vert finding for exclusions to not nuke game for 20s
This commit is contained in:
parent
0d82606308
commit
df45fb50d9
4 changed files with 64 additions and 44 deletions
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using ABI_RC.Core;
|
||||
using ABI.CCK.Components;
|
||||
using UnityEngine;
|
||||
|
@ -44,8 +45,13 @@ public static class ShadowCloneHelper
|
|||
|
||||
private static void ProcessRenderers(IEnumerable<Renderer> renderers, Transform root, Transform headBone)
|
||||
{
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
|
||||
IReadOnlyDictionary<Transform, FPRExclusion> exclusions = CollectTransformToExclusionMap(root, headBone);
|
||||
|
||||
// log current time
|
||||
ShadowCloneMod.Logger.Msg($"CollectTransformToExclusionMap in {sw.ElapsedMilliseconds}ms");
|
||||
|
||||
foreach (Renderer renderer in renderers)
|
||||
{
|
||||
ConfigureRenderer(renderer);
|
||||
|
@ -59,6 +65,11 @@ public static class ShadowCloneHelper
|
|||
ITransformHider hider = TransformHiderManager.CreateTransformHider(renderer, exclusions);
|
||||
if (hider != null) TransformHiderManager.Instance.AddTransformHider(hider);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
// log current time
|
||||
ShadowCloneMod.Logger.Msg($"ProcessRenderers in {sw.ElapsedMilliseconds}ms");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -10,6 +10,8 @@ public class FPRExclusion : MonoBehaviour
|
|||
{
|
||||
public Transform target;
|
||||
|
||||
internal readonly List<int> affectedVertexIndices = new();
|
||||
|
||||
internal readonly List<Transform> affectedChildren = new();
|
||||
internal readonly List<IFPRExclusionTask> relatedTasks = new();
|
||||
|
||||
|
|
|
@ -16,9 +16,6 @@ public class MeshTransformHider : ITransformHider, IFPRExclusionTask
|
|||
private readonly MeshRenderer _mainMesh;
|
||||
private bool _enabledState;
|
||||
|
||||
// exclusion
|
||||
private readonly FPRExclusion _exclusion;
|
||||
|
||||
#region ITransformHider Methods
|
||||
|
||||
public bool IsActive { get; set; } = true; // default hide, but FPRExclusion can override
|
||||
|
@ -36,9 +33,8 @@ public class MeshTransformHider : ITransformHider, IFPRExclusionTask
|
|||
Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
_exclusion = exclusion;
|
||||
_exclusion.relatedTasks.Add(this);
|
||||
|
||||
exclusion.relatedTasks.Add(this);
|
||||
|
||||
_mainMesh = renderer;
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
|
@ -38,6 +39,8 @@ public class SkinnedTransformHider : ITransformHider
|
|||
|
||||
public SkinnedTransformHider(SkinnedMeshRenderer renderer, IReadOnlyDictionary<Transform, FPRExclusion> exclusions)
|
||||
{
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
|
||||
_mainMesh = renderer;
|
||||
|
||||
if (_mainMesh == null
|
||||
|
@ -52,36 +55,35 @@ public class SkinnedTransformHider : ITransformHider
|
|||
_rootBone = _mainMesh.rootBone;
|
||||
_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;
|
||||
List<FPRExclusion> fprExclusions = new();
|
||||
|
||||
foreach (Transform bone in bones)
|
||||
{
|
||||
if (bone == null)
|
||||
continue; // thanks AdvancedSafety for preventing null ref for so long...
|
||||
|
||||
if (!exclusions.TryGetValue(bone, out FPRExclusion exclusion))
|
||||
continue;
|
||||
|
||||
fprExclusions.Add(exclusion);
|
||||
}
|
||||
SubTask.FindExclusionVertList(renderer, exclusions);
|
||||
|
||||
List<int> exclusionVerts;
|
||||
foreach (FPRExclusion exclusion in fprExclusions)
|
||||
foreach (var exclusion in exclusions)
|
||||
{
|
||||
exclusionVerts = SubTask.FindExclusionVertList(renderer, exclusion);
|
||||
if (exclusionVerts.Count == 0)
|
||||
continue;
|
||||
FPRExclusion fprExclusion = exclusion.Value;
|
||||
if (fprExclusion.affectedVertexIndices.Count == 0)
|
||||
continue; // no affected verts
|
||||
|
||||
SubTask subTask = new(this, exclusion, exclusionVerts);
|
||||
SubTask subTask = new(this, fprExclusion, fprExclusion.affectedVertexIndices);
|
||||
_subTasks.Add(subTask);
|
||||
exclusion.relatedTasks.Add(subTask);
|
||||
fprExclusion.relatedTasks.Add(subTask);
|
||||
fprExclusion.affectedVertexIndices.Clear(); // clear list for next SkinnedTransformHider
|
||||
}
|
||||
|
||||
if (_subTasks.Count == 0)
|
||||
// log current time
|
||||
ShadowCloneMod.Logger.Msg($"SkinnedTransformHider part 3 in {sw.ElapsedMilliseconds}ms");
|
||||
|
||||
if (_subTasks.Count == 0)
|
||||
{
|
||||
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()
|
||||
|
@ -176,14 +178,11 @@ public class SkinnedTransformHider : ITransformHider
|
|||
private readonly int _vertexCount;
|
||||
private readonly ComputeBuffer _computeBuffer;
|
||||
private readonly int _threadGroups;
|
||||
|
||||
private readonly FPRExclusion _exclusion;
|
||||
|
||||
|
||||
public SubTask(SkinnedTransformHider parent, FPRExclusion exclusion, List<int> exclusionVerts)
|
||||
{
|
||||
_parent = parent;
|
||||
_exclusion = exclusion;
|
||||
_shrinkBone = _exclusion.target;
|
||||
_shrinkBone = exclusion.target;
|
||||
|
||||
_vertexCount = exclusionVerts.Count;
|
||||
_computeBuffer = new ComputeBuffer(_vertexCount, sizeof(int));
|
||||
|
@ -211,28 +210,40 @@ public class SkinnedTransformHider : ITransformHider
|
|||
|
||||
#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 bones = exclusion.affectedChildren;
|
||||
|
||||
HashSet<int> weights = new();
|
||||
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++)
|
||||
{
|
||||
BoneWeight weight = boneWeights[i];
|
||||
|
||||
Transform bone = null;
|
||||
const float minWeightThreshold = 0.2f;
|
||||
if (weights.Contains(weight.boneIndex0) && weight.weight0 > minWeightThreshold
|
||||
|| weights.Contains(weight.boneIndex1) && weight.weight1 > minWeightThreshold
|
||||
|| weights.Contains(weight.boneIndex2) && weight.weight2 > minWeightThreshold
|
||||
|| weights.Contains(weight.boneIndex3) && weight.weight3 > minWeightThreshold)
|
||||
headVertices.Add(i);
|
||||
if (weights.Contains(weight.boneIndex0) && weight.weight0 > minWeightThreshold)
|
||||
bone = renderer.bones[weight.boneIndex0];
|
||||
else if (weights.Contains(weight.boneIndex1) && weight.weight1 > minWeightThreshold)
|
||||
bone = renderer.bones[weight.boneIndex1];
|
||||
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];
|
||||
|
||||
if (bone == null) continue; // no bone found
|
||||
|
||||
// add vertex to exclusion list
|
||||
exclusions[bone].affectedVertexIndices.Add(i);
|
||||
}
|
||||
|
||||
return headVertices;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue