247 lines
10 KiB
C#
247 lines
10 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.MeshMatcher
|
|
using Eden.AutoMorpher;
|
|
using System.Collections.Generic;
|
|
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<HumanBodyBones> LeftLegBones = new HashSet<HumanBodyBones>
|
|
{
|
|
HumanBodyBones.LeftUpperLeg,
|
|
HumanBodyBones.LeftLowerLeg,
|
|
HumanBodyBones.LeftFoot,
|
|
HumanBodyBones.LeftToes
|
|
};
|
|
|
|
private readonly HashSet<HumanBodyBones> RightLegBones = new HashSet<HumanBodyBones>
|
|
{
|
|
HumanBodyBones.RightUpperLeg,
|
|
HumanBodyBones.RightLowerLeg,
|
|
HumanBodyBones.RightFoot,
|
|
HumanBodyBones.RightToes
|
|
};
|
|
|
|
public BvhTriangleMesh BuildBvhMulti(IReadOnlyList<SkinnedMeshRenderer> 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 (this.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] ? this.bodyBVH.QueryClosest(worldVertices[i], this.LeftLegBones) : ((!clothInstance.isRightLegVertex[i]) ? this.bodyBVH.QueryClosest(worldVertices[i]) : this.bodyBVH.QueryClosest(worldVertices[i], this.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 (this.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] ? this.bodyBVH.QueryClosest(worldVertices[i], this.LeftLegBones) : ((!clothInstance.isRightLegVertex[i]) ? this.bodyBVH.QueryClosest(worldVertices[i]) : this.bodyBVH.QueryClosest(worldVertices[i], this.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 (this.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 = this.bodyBVH.QueryClosest(vector).closestPoint - vector;
|
|
array[i] = vector2;
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public bool[] GetBodyInsideFlags(Vector3[] worldVertices)
|
|
{
|
|
if (this.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 = this.bodyBVH.QueryClosest(worldVertices[i]);
|
|
float num = Vector3.Dot((closestHit.closestPoint - worldVertices[i]).normalized, closestHit.normal.normalized);
|
|
array[i] = num > 0f;
|
|
}
|
|
return array;
|
|
}
|
|
}
|