// 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.MeshMatcher using System.Collections.Generic; using Eden.AutoMorpher; using UnityEngine; public class MeshMatcher { public struct ClosestHit { public Vector3 closestP; public Vector3 direction; public Vector3 moveVector; public float distance; } public BvhTriangleMesh bodyBVH; private readonly HashSet LeftLegBones = new HashSet { HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot, HumanBodyBones.LeftToes }; private readonly HashSet RightLegBones = new HashSet { HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot, HumanBodyBones.RightToes }; public BvhTriangleMesh BuildBvhMulti(IReadOnlyList bodies, Animator bodyAnimator) { if (bodies == null || bodies.Count == 0) { throw new AutoMorpherException("Body Meshes are Missing", "[BuildBvhMulti] BuildBvhMulti\n - bodies is null or empty"); } BvhTriangleMesh bvhTriangleMesh = new BvhTriangleMesh().BuildFromSkinnedMeshes(bodies, bodyAnimator); if (bvhTriangleMesh == null || bvhTriangleMesh.triangles == null) { Debug.LogError("Failed to build multi-body BVH (no triangles)."); throw new AutoMorpherException(LanguageManager.Get("UI.Exception.title.BodyBVHFail"), LanguageManager.GetFormat("UI.Exception.message.BodyBVHFail", new object[3] { bodyAnimator.gameObject.name, bvhTriangleMesh == null, bvhTriangleMesh.triangles == null })); } return bvhTriangleMesh; } public Vector3[] ExpandVertexMatch(ClothInstance clothInstance, float defaultMinDist = 0.005f, bool skipFootFitting = false, float maxMatchDistance = 0.1f) { Vector3[] worldVertices = clothInstance.worldVertices; float[] minDistance = clothInstance.minDistance; if (bodyBVH == null) { throw new AutoMorpherException("Body BVH is Missing", "[ExpandVertexMatch] ExpandVertexMatch\n - bodyBVH is null"); } if (worldVertices == null) { throw new AutoMorpherException("Cloth World Vertices are Missing", "[ExpandVertexMatch] ExpandVertexMatch\n - clothInstance.worldVertices is null"); } if (worldVertices.Length == 0) { Debug.LogWarning("clothes mesh has no vertices"); return null; } if (minDistance == null) { Debug.LogWarning("minDists is null"); } if (minDistance.Length != worldVertices.Length) { Debug.LogWarning("minDists.Length != worldVertexs.Length"); } Vector3[] array = new Vector3[worldVertices.Length]; float num = maxMatchDistance * maxMatchDistance; for (int i = 0; i < worldVertices.Length; i++) { if (clothInstance.excludedVertices[i]) { array[i] = Vector3.zero; continue; } if (clothInstance.isInsideVertex[i]) { array[i] = Vector3.zero; continue; } float num2 = minDistance[i] + defaultMinDist; BvhTriangleMesh.ClosestHit closestHit = (clothInstance.isLeftLegVertex[i] ? bodyBVH.QueryClosest(worldVertices[i], LeftLegBones) : ((!clothInstance.isRightLegVertex[i]) ? bodyBVH.QueryClosest(worldVertices[i]) : bodyBVH.QueryClosest(worldVertices[i], RightLegBones))); if (skipFootFitting && (closestHit.mainHumanBone == HumanBodyBones.LeftFoot || closestHit.mainHumanBone == HumanBodyBones.RightFoot || closestHit.mainHumanBone == HumanBodyBones.RightToes || closestHit.mainHumanBone == HumanBodyBones.LeftToes)) { array[i] = Vector3.zero; continue; } if (closestHit.sqrDistance > num) { array[i] = Vector3.zero; continue; } Vector3 normalized = (closestHit.closestPoint - worldVertices[i]).normalized; float num3 = Vector3.Dot(normalized, closestHit.normal.normalized); if (num3 > 0.7f) { array[i] = closestHit.closestPoint + normalized * num2 - worldVertices[i]; } else if (num3 < -0.7f) { if (closestHit.sqrDistance < num2 * num2) { array[i] = closestHit.closestPoint - normalized * num2 - worldVertices[i]; } } else { array[i] = Vector3.zero; } } return array; } public Vector3[] ShrinkVertexMatch(ClothInstance clothInstance, float defaultMinDist = 0.005f, float maxMatchDistance = 0.1f) { Vector3[] worldVertices = clothInstance.worldVertices; float[] minDistance = clothInstance.minDistance; if (bodyBVH == null) { throw new AutoMorpherException("Body BVH is Missing", "[ShrinkVertexMatch] ShrinkVertexMatch\n - bodyBVH is null"); } if (worldVertices == null) { throw new AutoMorpherException("Cloth World Vertices are Missing", "[ShrinkVertexMatch] ShrinkVertexMatch\n - clothInstance.worldVertices is null"); } if (worldVertices.Length == 0) { Debug.LogWarning("clothes mesh has no vertices"); return null; } if (minDistance == null) { Debug.LogWarning("minDists is null"); } if (minDistance.Length != worldVertices.Length) { Debug.LogWarning("minDists.Length != worldVertexs.Length"); } Vector3[] array = new Vector3[worldVertices.Length]; float num = maxMatchDistance * maxMatchDistance; _ = clothInstance.isLeftLegVertex; _ = clothInstance.isRightLegVertex; for (int i = 0; i < worldVertices.Length; i++) { if (clothInstance.excludedVertices[i]) { array[i] = Vector3.zero; continue; } if (clothInstance.isInsideVertex[i]) { array[i] = Vector3.zero; continue; } float num2 = minDistance[i] + defaultMinDist; BvhTriangleMesh.ClosestHit closestHit = (clothInstance.isLeftLegVertex[i] ? bodyBVH.QueryClosest(worldVertices[i], LeftLegBones) : ((!clothInstance.isRightLegVertex[i]) ? bodyBVH.QueryClosest(worldVertices[i]) : bodyBVH.QueryClosest(worldVertices[i], RightLegBones))); if (closestHit.sqrDistance > num) { array[i] = Vector3.zero; continue; } if (closestHit.mainHumanBone == HumanBodyBones.LeftFoot || closestHit.mainHumanBone == HumanBodyBones.RightFoot || closestHit.mainHumanBone == HumanBodyBones.RightToes || closestHit.mainHumanBone == HumanBodyBones.LeftToes) { array[i] = Vector3.zero; continue; } Vector3 normalized = (closestHit.closestPoint - worldVertices[i]).normalized; float num3 = Vector3.Dot(normalized, closestHit.normal.normalized); if (num3 < -0.7f) { array[i] = closestHit.closestPoint - normalized * num2 - worldVertices[i]; } else if (num3 < -0.7f) { if (closestHit.sqrDistance < num2 * num2) { array[i] = closestHit.closestPoint + normalized * num2 - worldVertices[i]; } } else { array[i] = Vector3.zero; } } return array; } public Vector3[] GetMinDistanceToBody(Vector3[] clothesVertices) { if (bodyBVH == null) { throw new AutoMorpherException("sourceBodyBVH is null", "[MeshMatcher] GetMinDistanceToBodysourceBodyBVH is null"); } if (clothesVertices == null || clothesVertices.Length == 0) { throw new AutoMorpherException("Source Vertices is null", "[MeshMatcher] GetMinDistanceToBodySource Vertices is null or no vertices"); } Vector3[] array = new Vector3[clothesVertices.Length]; for (int i = 0; i < clothesVertices.Length; i++) { Vector3 vector = clothesVertices[i]; Vector3 vector2 = bodyBVH.QueryClosest(vector).closestPoint - vector; array[i] = vector2; } return array; } public bool[] GetBodyInsideFlags(Vector3[] worldVertices) { if (bodyBVH == null) { throw new AutoMorpherException("sourceBodyBVH is null", "[MeshMatcher] GetBodyInsideFlagssourceBodyBVH is null"); } if (worldVertices == null || worldVertices.Length == 0) { Debug.LogError("clothes is null"); throw new AutoMorpherException("Source Vertices is null", "[MeshMatcher] GetMinDistanceToBodySource Vertices is null or no vertices"); } bool[] array = new bool[worldVertices.Length]; for (int i = 0; i < worldVertices.Length; i++) { BvhTriangleMesh.ClosestHit closestHit = bodyBVH.QueryClosest(worldVertices[i]); float num = Vector3.Dot((closestHit.closestPoint - worldVertices[i]).normalized, closestHit.normal.normalized); array[i] = num > 0f; } return array; } }