Files
AutoMorpherDecompiled/Assets/@Eden_Tools/Eden_AutoMorpher/Script/ClothInstance.cs
2026-02-01 19:30:24 +09:00

540 lines
15 KiB
C#

// Warning: Some assembly references could not be resolved automatically. This might lead to incorrect decompilation of some parts,
// for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies.
// EdenAutoMorpherScript, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.ClothInstance
using System;
using System.Collections.Generic;
using Eden.AutoMorpher;
using UnityEngine;
[Serializable]
public class ClothInstance
{
public SkinnedMeshRenderer smr;
public Mesh editableMesh;
public Mesh bakedMesh;
public Matrix4x4 worldNoScale;
public Vector3[] worldVertices;
public Vector3[] minDistanceVector;
public float[] minDistance;
public Vector3[] deltas;
public Vector3[] deltasLocal;
public List<int>[] vertexAdjacency;
public List<List<int>> equivalentVertices;
public bool[] isInsideVertex;
public bool[] excludedVertices;
public bool[] isLeftLegVertex;
public bool[] isRightLegVertex;
public Vector3[] bakedWorldNormals;
public Vector4[] bakedWorldTangents;
public Dictionary<HumanBodyBones, HashSet<Transform>> humanoidMatchedBones;
public ClothInstance(SkinnedMeshRenderer clotheSMR, bool duplicateMesh = true)
{
smr = clotheSMR;
if (duplicateMesh)
{
string name = smr.sharedMesh.name;
editableMesh = UnityEngine.Object.Instantiate(clotheSMR.sharedMesh);
editableMesh.name = name + "_EditableMesh";
smr.sharedMesh = editableMesh;
}
else
{
editableMesh = smr.sharedMesh;
}
UpdateWorldVertices();
int vertexCount = editableMesh.vertexCount;
minDistanceVector = new Vector3[vertexCount];
deltas = new Vector3[vertexCount];
minDistance = new float[vertexCount];
isInsideVertex = new bool[vertexCount];
excludedVertices = new bool[vertexCount];
isLeftLegVertex = new bool[vertexCount];
isRightLegVertex = new bool[vertexCount];
humanoidMatchedBones = new Dictionary<HumanBodyBones, HashSet<Transform>>();
vertexAdjacency = BuildVertexAdjacency(editableMesh);
BuildEquivalentVerticesFromWorld();
}
public void UpdateWorldVertices()
{
if (bakedMesh == null)
{
bakedMesh = new Mesh();
}
else
{
bakedMesh.Clear();
}
smr.BakeMesh(bakedMesh);
int vertexCount = editableMesh.vertexCount;
Vector3 lossyScale = smr.transform.lossyScale;
Vector3 vector = new Vector3(1f / Mathf.Max(lossyScale.x, 1E-08f), 1f / Mathf.Max(lossyScale.y, 1E-08f), 1f / Mathf.Max(lossyScale.z, 1E-08f));
worldNoScale = smr.transform.localToWorldMatrix * Matrix4x4.Scale(vector);
worldVertices = new Vector3[vertexCount];
deltasLocal = new Vector3[vertexCount];
for (int i = 0; i < vertexCount; i++)
{
worldVertices[i] = worldNoScale.MultiplyPoint3x4(bakedMesh.vertices[i]);
deltasLocal[i] = Vector3.zero;
}
Vector3[] normals = bakedMesh.normals;
Vector4[] tangents = bakedMesh.tangents;
bakedWorldNormals = new Vector3[vertexCount];
if (tangents != null && tangents.Length == vertexCount)
{
bakedWorldTangents = new Vector4[vertexCount];
}
else
{
bakedWorldTangents = null;
}
for (int j = 0; j < vertexCount; j++)
{
bakedWorldNormals[j] = smr.transform.TransformDirection(normals[j]).normalized;
if (bakedWorldTangents != null)
{
Vector3 normalized = smr.transform.TransformDirection(new Vector3(tangents[j].x, tangents[j].y, tangents[j].z)).normalized;
bakedWorldTangents[j] = new Vector4(normalized.x, normalized.y, normalized.z, tangents[j].w);
}
}
}
public List<int>[] BuildVertexAdjacency(Mesh mesh, float seamThreshold = 0.0001f, float proximityThreshold = 0f)
{
if (mesh == null)
{
throw new AutoMorpherException("Mesh is Missing", "[VertexAdjacencyUtil] BuildVertexAdjacency\n - mesh is null");
}
int vertexCount = mesh.vertexCount;
int[] triangles = mesh.triangles;
Vector3[] vertices = mesh.vertices;
List<int>[] array = new List<int>[vertexCount];
for (int i = 0; i < vertexCount; i++)
{
array[i] = new List<int>();
}
int num = triangles.Length / 3;
for (int j = 0; j < num; j++)
{
int num2 = triangles[j * 3];
int num3 = triangles[j * 3 + 1];
int num4 = triangles[j * 3 + 2];
AddNeighbor(array, num2, num3);
AddNeighbor(array, num3, num2);
AddNeighbor(array, num3, num4);
AddNeighbor(array, num4, num3);
AddNeighbor(array, num4, num2);
AddNeighbor(array, num2, num4);
}
if (seamThreshold > 0f)
{
float num5 = seamThreshold * 2f;
float num6 = seamThreshold * seamThreshold;
Dictionary<Vector3Int, List<int>> dictionary = new Dictionary<Vector3Int, List<int>>();
for (int k = 0; k < vertexCount; k++)
{
Vector3 vector = vertices[k];
Vector3Int key = new Vector3Int(Mathf.FloorToInt(vector.x / num5), Mathf.FloorToInt(vector.y / num5), Mathf.FloorToInt(vector.z / num5));
if (!dictionary.TryGetValue(key, out var value))
{
value = (dictionary[key] = new List<int>());
}
value.Add(k);
}
foreach (KeyValuePair<Vector3Int, List<int>> item in dictionary)
{
Vector3Int key2 = item.Key;
List<int> value2 = item.Value;
for (int l = -1; l <= 1; l++)
{
for (int m = -1; m <= 1; m++)
{
for (int n = -1; n <= 1; n++)
{
if (l < 0 || (l == 0 && m < 0) || (l == 0 && m == 0 && n < 0))
{
continue;
}
Vector3Int vector3Int = new Vector3Int(key2.x + l, key2.y + m, key2.z + n);
if (!dictionary.TryGetValue(vector3Int, out var value3))
{
continue;
}
if (vector3Int == key2)
{
for (int num7 = 0; num7 < value2.Count; num7++)
{
int num8 = value2[num7];
Vector3 vector2 = vertices[num8];
for (int num9 = num7 + 1; num9 < value2.Count; num9++)
{
int num10 = value2[num9];
if ((vertices[num10] - vector2).sqrMagnitude <= num6)
{
AddNeighbor(array, num8, num10);
AddNeighbor(array, num10, num8);
}
}
}
continue;
}
for (int num11 = 0; num11 < value2.Count; num11++)
{
int num12 = value2[num11];
Vector3 vector3 = vertices[num12];
for (int num13 = 0; num13 < value3.Count; num13++)
{
int num14 = value3[num13];
if ((vertices[num14] - vector3).sqrMagnitude <= num6)
{
AddNeighbor(array, num12, num14);
AddNeighbor(array, num14, num12);
}
}
}
}
}
}
}
}
if (proximityThreshold > 0f)
{
float num15 = proximityThreshold * 2f;
float num16 = proximityThreshold * proximityThreshold;
Dictionary<Vector3Int, List<int>> dictionary2 = new Dictionary<Vector3Int, List<int>>();
for (int num17 = 0; num17 < vertexCount; num17++)
{
Vector3 vector4 = vertices[num17];
Vector3Int key3 = new Vector3Int(Mathf.FloorToInt(vector4.x / num15), Mathf.FloorToInt(vector4.y / num15), Mathf.FloorToInt(vector4.z / num15));
if (!dictionary2.TryGetValue(key3, out var value4))
{
value4 = (dictionary2[key3] = new List<int>());
}
value4.Add(num17);
}
foreach (KeyValuePair<Vector3Int, List<int>> item2 in dictionary2)
{
Vector3Int key4 = item2.Key;
List<int> value5 = item2.Value;
for (int num18 = -1; num18 <= 1; num18++)
{
for (int num19 = -1; num19 <= 1; num19++)
{
for (int num20 = -1; num20 <= 1; num20++)
{
if (num18 < 0 || (num18 == 0 && num19 < 0) || (num18 == 0 && num19 == 0 && num20 < 0))
{
continue;
}
Vector3Int vector3Int2 = new Vector3Int(key4.x + num18, key4.y + num19, key4.z + num20);
if (!dictionary2.TryGetValue(vector3Int2, out var value6))
{
continue;
}
if (vector3Int2 == key4)
{
for (int num21 = 0; num21 < value5.Count; num21++)
{
int num22 = value5[num21];
Vector3 vector5 = vertices[num22];
for (int num23 = num21 + 1; num23 < value5.Count; num23++)
{
int num24 = value5[num23];
if ((vertices[num24] - vector5).sqrMagnitude <= num16)
{
AddNeighbor(array, num22, num24);
AddNeighbor(array, num24, num22);
}
}
}
continue;
}
for (int num25 = 0; num25 < value5.Count; num25++)
{
int num26 = value5[num25];
Vector3 vector6 = vertices[num26];
for (int num27 = 0; num27 < value6.Count; num27++)
{
int num28 = value6[num27];
if ((vertices[num28] - vector6).sqrMagnitude <= num16)
{
AddNeighbor(array, num26, num28);
AddNeighbor(array, num28, num26);
}
}
}
}
}
}
}
}
return array;
static void AddNeighbor(List<int>[] adj, int from, int to)
{
List<int> list3 = adj[from];
if (!list3.Contains(to))
{
list3.Add(to);
}
}
}
public void ApplyWorldVerticesToMesh()
{
if (editableMesh == null || smr == null || worldVertices == null)
{
return;
}
Mesh mesh = editableMesh;
int vertexCount = mesh.vertexCount;
Vector3[] vertices = mesh.vertices;
SkinningUtil skinningUtil = new SkinningUtil();
Vector3[] array = null;
int blendShapeCount = mesh.blendShapeCount;
if (blendShapeCount > 0)
{
array = new Vector3[vertexCount];
Vector3[] array2 = new Vector3[vertexCount];
Vector3[] deltaNormals = new Vector3[vertexCount];
Vector3[] deltaTangents = new Vector3[vertexCount];
for (int i = 0; i < blendShapeCount; i++)
{
float blendShapeWeight = smr.GetBlendShapeWeight(i);
if (Mathf.Approximately(blendShapeWeight, 0f))
{
continue;
}
int frameIndex = mesh.GetBlendShapeFrameCount(i) - 1;
float blendShapeFrameWeight = mesh.GetBlendShapeFrameWeight(i, frameIndex);
mesh.GetBlendShapeFrameVertices(i, frameIndex, array2, deltaNormals, deltaTangents);
float num = ((blendShapeFrameWeight != 0f) ? (blendShapeWeight / blendShapeFrameWeight) : 0f);
if (!Mathf.Approximately(num, 0f))
{
for (int j = 0; j < vertexCount; j++)
{
array[j] += array2[j] * num;
}
}
}
}
for (int k = 0; k < vertexCount; k++)
{
Vector3 vector = skinningUtil.WorldPosToBindPos_Full(smr, mesh, k, worldVertices[k]);
if (array != null)
{
vector -= array[k];
}
vertices[k] = vector;
}
mesh.vertices = vertices;
Vector3[] array3 = null;
Vector3[] array4 = null;
if (blendShapeCount > 0)
{
array3 = new Vector3[vertexCount];
array4 = new Vector3[vertexCount];
Vector3[] deltaVertices = new Vector3[vertexCount];
Vector3[] array5 = new Vector3[vertexCount];
Vector3[] array6 = new Vector3[vertexCount];
for (int l = 0; l < blendShapeCount; l++)
{
float blendShapeWeight2 = smr.GetBlendShapeWeight(l);
if (Mathf.Approximately(blendShapeWeight2, 0f))
{
continue;
}
int frameIndex2 = mesh.GetBlendShapeFrameCount(l) - 1;
float blendShapeFrameWeight2 = mesh.GetBlendShapeFrameWeight(l, frameIndex2);
mesh.GetBlendShapeFrameVertices(l, frameIndex2, deltaVertices, array5, array6);
float num2 = ((blendShapeFrameWeight2 != 0f) ? (blendShapeWeight2 / blendShapeFrameWeight2) : 0f);
if (!Mathf.Approximately(num2, 0f))
{
for (int m = 0; m < vertexCount; m++)
{
array3[m] += array5[m] * num2;
array4[m] += array6[m] * num2;
}
}
}
}
if (bakedWorldNormals == null || bakedWorldNormals.Length != vertexCount)
{
return;
}
Vector3[] array7 = new Vector3[vertexCount];
bool flag = bakedWorldTangents != null && bakedWorldTangents.Length == vertexCount;
Vector4[] array8 = (flag ? new Vector4[vertexCount] : null);
for (int n = 0; n < vertexCount; n++)
{
Vector3 vector2 = skinningUtil.WorldDirToBindDir_Full(smr, mesh, n, bakedWorldNormals[n]);
if (array3 != null)
{
vector2 -= array3[n];
}
array7[n] = vector2.normalized;
if (flag)
{
Vector3 vector3 = skinningUtil.WorldDirToBindDir_Full(targetWorldDir: new Vector3(bakedWorldTangents[n].x, bakedWorldTangents[n].y, bakedWorldTangents[n].z), smr: smr, bindMesh: mesh, vertexIndex: n);
if (array4 != null)
{
vector3 -= array4[n];
}
vector3 = vector3.normalized;
array8[n] = new Vector4(vector3.x, vector3.y, vector3.z, bakedWorldTangents[n].w);
}
}
mesh.normals = array7;
if (array8 != null)
{
mesh.tangents = array8;
}
}
public void BuildEquivalentVerticesFromWorld(float maxDistance = 1E-05f)
{
if (worldVertices == null || worldVertices.Length == 0)
{
Debug.LogWarning("[ClothInstance] BuildEquivalentVerticesFromWorld: worldVertices is null or empty. Call UpdateWorldVertices() first.");
return;
}
int num = worldVertices.Length;
if (equivalentVertices == null)
{
equivalentVertices = new List<List<int>>();
}
else
{
equivalentVertices.Clear();
}
float num2 = maxDistance * maxDistance;
Dictionary<Vector3Int, List<int>> dictionary = new Dictionary<Vector3Int, List<int>>();
for (int i = 0; i < num; i++)
{
Vector3 vector = worldVertices[i];
Vector3Int key = new Vector3Int(Mathf.FloorToInt(vector.x / maxDistance), Mathf.FloorToInt(vector.y / maxDistance), Mathf.FloorToInt(vector.z / maxDistance));
if (!dictionary.TryGetValue(key, out var value))
{
value = (dictionary[key] = new List<int>());
}
value.Add(i);
}
foreach (KeyValuePair<Vector3Int, List<int>> item in dictionary)
{
List<int> value2 = item.Value;
int count = value2.Count;
if (count < 2)
{
continue;
}
int[] parent = new int[count];
for (int j = 0; j < count; j++)
{
parent[j] = j;
}
for (int k = 0; k < count; k++)
{
int num3 = value2[k];
Vector3 vector2 = worldVertices[num3];
for (int l = k + 1; l < count; l++)
{
int num4 = value2[l];
Vector3 vector3 = worldVertices[num4];
if ((vector2 - vector3).sqrMagnitude <= num2)
{
Union(k, l);
}
}
}
Dictionary<int, List<int>> dictionary2 = new Dictionary<int, List<int>>();
for (int m = 0; m < count; m++)
{
int key2 = Find(m);
if (!dictionary2.TryGetValue(key2, out var value3))
{
value3 = (dictionary2[key2] = new List<int>());
}
value3.Add(value2[m]);
}
foreach (List<int> value4 in dictionary2.Values)
{
if (value4.Count >= 2)
{
equivalentVertices.Add(value4);
}
}
int Find(int x)
{
if (parent[x] != x)
{
parent[x] = Find(parent[x]);
}
return parent[x];
}
void Union(int a, int b)
{
int num5 = Find(a);
int num6 = Find(b);
if (num5 != num6)
{
parent[num6] = num5;
}
}
}
}
~ClothInstance()
{
Dispose();
}
public void Dispose()
{
if (bakedMesh != null)
{
UnityEngine.Object.DestroyImmediate(bakedMesh);
bakedMesh = null;
}
worldVertices = null;
minDistanceVector = null;
minDistance = null;
deltas = null;
deltasLocal = null;
isInsideVertex = null;
excludedVertices = null;
isLeftLegVertex = null;
isRightLegVertex = null;
vertexAdjacency = null;
if (equivalentVertices != null)
{
for (int i = 0; i < equivalentVertices.Count; i++)
{
equivalentVertices[i]?.Clear();
}
equivalentVertices.Clear();
equivalentVertices = null;
}
humanoidMatchedBones = null;
smr = null;
editableMesh = null;
}
}