// Decompiled with JetBrains decompiler // Type: Eden.AutoMorpher.BvhTriangleMesh // Assembly: EdenAutoMorpherScript, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null // MVID: D39968B3-E151-4276-BDB4-E82752BBAFF0 // Assembly location: D:\dev\AutoMorpher\Assets\@Eden_Tools\Eden_AutoMorpher\Script\EdenAutoMorpherScript.dll using System.Collections.Generic; using UnityEngine; namespace Eden.AutoMorpher { public class BvhTriangleMesh { private TriangleUtil triangleUtil; private HumanBodyBones[] humanBones; public BvhTriangle[] triangles; public BvhNode[] nodes; public int[] triIndices; private const int LeafMaxTriangles = 4; public BvhTriangleMesh() { // ISSUE: unable to decompile the method. } private HumanBodyBones[] BuildVertexMainHumanBone( SkinnedMeshRenderer smr, Animator animator, HumanBodyBones[] bodyBones) { Mesh sharedMesh = smr.sharedMesh; BoneWeight[] boneWeights = sharedMesh.boneWeights; int[] boneToBodyIndex = this.BuildBoneToBodyIndexMap(smr, animator, bodyBones); HumanBodyBones[] humanBodyBonesArray = new HumanBodyBones[sharedMesh.vertexCount]; for (int index = 0; index < sharedMesh.vertexCount; ++index) { BoneWeight boneWeight = boneWeights[index]; int bestBodyIdx = -1; float bestWeight = 0.0f; Try(((BoneWeight)ref boneWeight).boneIndex0, ((BoneWeight)ref boneWeight).weight0); Try(((BoneWeight)ref boneWeight).boneIndex1, ((BoneWeight)ref boneWeight).weight1); Try(((BoneWeight)ref boneWeight).boneIndex2, ((BoneWeight)ref boneWeight).weight2); Try(((BoneWeight)ref boneWeight).boneIndex3, ((BoneWeight)ref boneWeight).weight3); humanBodyBonesArray[index] = bestBodyIdx >= 0 ? (HumanBodyBones)(int)bodyBones[bestBodyIdx] : (HumanBodyBones)55; void Try(int boneIdx, float w) { if ((double)w <= 0.0 || boneIdx < 0 || boneIdx >= boneToBodyIndex.Length) return; int num = boneToBodyIndex[boneIdx]; if (num < 0 || (double)w <= (double)bestWeight) return; bestWeight = w; bestBodyIdx = num; } } return humanBodyBonesArray; } public BvhTriangleMesh BuildFromSkinnedMeshes( IReadOnlyList renderers, Animator animator) { if (renderers == null || renderers.Count == 0) return (BvhTriangleMesh)null; BvhTriangleMesh bvhTriangleMesh = new BvhTriangleMesh(); int length = 0; foreach (SkinnedMeshRenderer renderer in (IEnumerable)renderers) { if (!Object.op_Equality((Object)renderer, (Object)null) && !Object.op_Equality((Object)renderer.sharedMesh, (Object)null)) length += renderer.sharedMesh.triangles.Length / 3; } if (length == 0) return (BvhTriangleMesh)null; bvhTriangleMesh.triangles = new BvhTriangle[length]; int num1 = 0; Mesh mesh = new Mesh(); foreach (SkinnedMeshRenderer renderer in (IEnumerable)renderers) { if (!Object.op_Equality((Object)renderer, (Object)null) && !Object.op_Equality((Object)renderer.sharedMesh, (Object)null)) { mesh.Clear(); renderer.BakeMesh(mesh); Vector3[] vertices = mesh.vertices; int[] triangles = renderer.sharedMesh.triangles; BoneWeight[] boneWeights = renderer.sharedMesh.boneWeights; int[] bodyIndexMap = this.BuildBoneToBodyIndexMap(renderer, animator, this.humanBones); int num2 = triangles.Length / 3; Transform transform = ((Component)renderer).transform; Vector3 lossyScale = transform.lossyScale; Vector3 vector3_1; // ISSUE: explicit constructor call ((Vector3)ref vector3_1).\u002Ector(1f / Mathf.Max(lossyScale.x, 1E-08f), 1f / Mathf.Max(lossyScale.y, 1E-08f), 1f / Mathf.Max(lossyScale.z, 1E-08f)); Matrix4x4 matrix4x4 = Matrix4x4.op_Multiply(transform.localToWorldMatrix, Matrix4x4.Scale(vector3_1)); for (int index = 0; index < num2; ++index) { int vi0 = triangles[index * 3]; int vi1 = triangles[index * 3 + 1]; int vi2 = triangles[index * 3 + 2]; Vector3 vector3_2 = ((Matrix4x4)ref matrix4x4).MultiplyPoint3x4(vertices[vi0]); Vector3 vector3_3 = ((Matrix4x4)ref matrix4x4).MultiplyPoint3x4(vertices[vi1]); Vector3 vector3_4 = ((Matrix4x4)ref matrix4x4).MultiplyPoint3x4(vertices[vi2]); Vector3 vector3_5 = Vector3.Cross(Vector3.op_Subtraction(vector3_3, vector3_2), Vector3.op_Subtraction(vector3_4, vector3_2)); float magnitude = ((Vector3)ref vector3_5).magnitude; Vector3 vector3_6 = (double)magnitude <= 9.99999993922529E-09 ? Vector3.up : Vector3.op_Division(vector3_5, magnitude); int mainHumanBoneIndex = this.ComputeTriangleMainHumanBoneIndex(vi0, vi1, vi2, boneWeights, bodyIndexMap, this.humanBones.Length); HumanBodyBones humanBodyBones = mainHumanBoneIndex >= 0 ? (HumanBodyBones)(int)this.humanBones[mainHumanBoneIndex] : (HumanBodyBones)55; bvhTriangleMesh.triangles[num1++] = new BvhTriangle() { a = vector3_2, b = vector3_3, c = vector3_4, normal = vector3_6, mainHumanBone = humanBodyBones }; mesh.Clear(); } } } int count = length; int[] triIndices = new int[count]; for (int index = 0; index < count; ++index) triIndices[index] = index; bvhTriangleMesh.triIndices = triIndices; List outNodes = new List(); this.BuildRecursive(bvhTriangleMesh.triangles, triIndices, 0, count, outNodes); bvhTriangleMesh.nodes = outNodes.ToArray(); return bvhTriangleMesh; } private int[] BuildBoneToBodyIndexMap( SkinnedMeshRenderer smr, Animator animator, HumanBodyBones[] bodyBones) { Transform[] bones = smr.bones; int[] bodyIndexMap = new int[bones.Length]; for (int index = 0; index < bodyIndexMap.Length; ++index) bodyIndexMap[index] = -1; if (Object.op_Equality((Object)animator, (Object)null) || bodyBones == null || bones == null) return bodyIndexMap; Dictionary dictionary1 = new Dictionary(); for (int index = 0; index < bones.Length; ++index) { if (!Object.op_Equality((Object)bones[index], (Object)null) && !dictionary1.ContainsKey(bones[index])) dictionary1.Add(bones[index], index); } Dictionary> dictionary2 = new MeshClassifier().MeshHumanoidBoneMatcher(animator, (IReadOnlyList)new SkinnedMeshRenderer[1] { smr }); for (int index1 = 0; index1 < bodyBones.Length; ++index1) { HumanBodyBones bodyBone = (HumanBodyBones)(int)bodyBones[index1]; HashSet transformSet; if (dictionary2.TryGetValue(bodyBone, out transformSet) && transformSet != null) { foreach (Transform key in transformSet) { int index2; if (!Object.op_Equality((Object)key, (Object)null) && dictionary1.TryGetValue(key, out index2)) bodyIndexMap[index2] = index1; } } } for (int index3 = 0; index3 < bones.Length; ++index3) { if (bodyIndexMap[index3] == -1) { Transform transform = bones[index3]; if (!Object.op_Equality((Object)transform, (Object)null)) { Transform parent = transform.parent; int index4; if (!Object.op_Equality((Object)parent, (Object)null) && dictionary1.TryGetValue(parent, out index4)) { int num = bodyIndexMap[index4]; if (num != -1) bodyIndexMap[index3] = num; } } } } return bodyIndexMap; } private int ComputeTriangleMainHumanBoneIndex( int vi0, int vi1, int vi2, BoneWeight[] weights, int[] boneToBodyIndex, int bodyBonesCount) { if (weights == null || weights.Length == 0 || boneToBodyIndex == null || boneToBodyIndex.Length == 0) return -1; float[] scores = new float[bodyBonesCount]; Accumulate(vi0); Accumulate(vi1); Accumulate(vi2); int mainHumanBoneIndex = -1; float num = 0.0f; for (int index = 0; index < scores.Length; ++index) { if ((double)scores[index] > (double)num) { num = scores[index]; mainHumanBoneIndex = index; } } return mainHumanBoneIndex; void Accumulate(int v) { if (v < 0 || v >= weights.Length) return; BoneWeight weight = weights[v]; Add(((BoneWeight)ref weight).boneIndex0, ((BoneWeight)ref weight).weight0); Add(((BoneWeight)ref weight).boneIndex1, ((BoneWeight)ref weight).weight1); Add(((BoneWeight)ref weight).boneIndex2, ((BoneWeight)ref weight).weight2); Add(((BoneWeight)ref weight).boneIndex3, ((BoneWeight)ref weight).weight3); } void Add(int boneIdx, float w) { if ((double)w <= 0.0 || boneIdx < 0 || boneIdx >= boneToBodyIndex.Length) return; int index = boneToBodyIndex[boneIdx]; if (index < 0) return; scores[index] += w; } } public BvhTriangleMesh BuildFromSkinnedMeshes(IList renderers) { if (renderers == null || renderers.Count == 0) return (BvhTriangleMesh)null; BvhTriangleMesh bvhTriangleMesh = new BvhTriangleMesh(); int length = 0; foreach (SkinnedMeshRenderer renderer in (IEnumerable)renderers) { if (!Object.op_Equality((Object)renderer, (Object)null) && !Object.op_Equality((Object)renderer.sharedMesh, (Object)null)) length += renderer.sharedMesh.triangles.Length / 3; } if (length == 0) return (BvhTriangleMesh)null; bvhTriangleMesh.triangles = new BvhTriangle[length]; int num1 = 0; foreach (SkinnedMeshRenderer renderer in (IEnumerable)renderers) { if (!Object.op_Equality((Object)renderer, (Object)null) && !Object.op_Equality((Object)renderer.sharedMesh, (Object)null)) { Mesh sharedMesh = renderer.sharedMesh; Vector3[] vertices = sharedMesh.vertices; int[] triangles = sharedMesh.triangles; int num2 = triangles.Length / 3; for (int index1 = 0; index1 < num2; ++index1) { int index2 = triangles[index1 * 3]; int index3 = triangles[index1 * 3 + 1]; int index4 = triangles[index1 * 3 + 2]; Vector3 vector3_1 = ((Component)renderer).transform.TransformPoint(vertices[index2]); Vector3 vector3_2 = ((Component)renderer).transform.TransformPoint(vertices[index3]); Vector3 vector3_3 = ((Component)renderer).transform.TransformPoint(vertices[index4]); Vector3 vector3_4 = Vector3.Cross(Vector3.op_Subtraction(vector3_2, vector3_1), Vector3.op_Subtraction(vector3_3, vector3_1)); float magnitude = ((Vector3)ref vector3_4).magnitude; Vector3 vector3_5 = (double)magnitude <= 9.99999993922529E-09 ? Vector3.up : Vector3.op_Division(vector3_4, magnitude); bvhTriangleMesh.triangles[num1++] = new BvhTriangle() { a = vector3_1, b = vector3_2, c = vector3_3, normal = vector3_5 }; } } } int count = length; int[] triIndices = new int[count]; for (int index = 0; index < count; ++index) triIndices[index] = index; bvhTriangleMesh.triIndices = triIndices; List outNodes = new List(); this.BuildRecursive(bvhTriangleMesh.triangles, triIndices, 0, count, outNodes); bvhTriangleMesh.nodes = outNodes.ToArray(); return bvhTriangleMesh; } public BvhTriangleMesh BuildFromMesh(Mesh mesh, Transform transform) { BvhTriangleMesh bvhTriangleMesh = new BvhTriangleMesh(); Vector3[] vertices = mesh.vertices; int[] triangles = mesh.triangles; int count = triangles.Length / 3; bvhTriangleMesh.triangles = new BvhTriangle[count]; for (int index1 = 0; index1 < count; ++index1) { int index2 = triangles[index1 * 3]; int index3 = triangles[index1 * 3 + 1]; int index4 = triangles[index1 * 3 + 2]; Vector3 vector3_1 = transform.TransformPoint(vertices[index2]); Vector3 vector3_2 = transform.TransformPoint(vertices[index3]); Vector3 vector3_3 = transform.TransformPoint(vertices[index4]); Vector3 vector3_4 = Vector3.Cross(Vector3.op_Subtraction(vector3_2, vector3_1), Vector3.op_Subtraction(vector3_3, vector3_1)); float magnitude = ((Vector3)ref vector3_4).magnitude; vector3_4 = (double)magnitude <= 9.99999993922529E-09 ? Vector3.up : Vector3.op_Division(vector3_4, magnitude); bvhTriangleMesh.triangles[index1] = new BvhTriangle() { a = vector3_1, b = vector3_2, c = vector3_3, normal = vector3_4 }; } int[] triIndices = new int[count]; for (int index = 0; index < count; ++index) triIndices[index] = index; bvhTriangleMesh.triIndices = triIndices; List outNodes = new List(); this.BuildRecursive(bvhTriangleMesh.triangles, triIndices, 0, count, outNodes); bvhTriangleMesh.nodes = outNodes.ToArray(); return bvhTriangleMesh; } private int BuildRecursive( BvhTriangle[] tris, int[] triIndices, int start, int count, List outNodes) { int count1 = outNodes.Count; BvhNode bvhNode = new BvhNode(); Bounds bounds = new Bounds(); bool flag = true; for (int index = start; index < start + count; ++index) { BvhTriangle tri = tris[triIndices[index]]; if (flag) { // ISSUE: explicit constructor call ((Bounds)ref bounds).\u002Ector(tri.a, Vector3.zero); ((Bounds)ref bounds).Encapsulate(tri.b); ((Bounds)ref bounds).Encapsulate(tri.c); flag = false; } else { ((Bounds)ref bounds).Encapsulate(tri.a); ((Bounds)ref bounds).Encapsulate(tri.b); ((Bounds)ref bounds).Encapsulate(tri.c); } } bvhNode.bounds = bounds; if (count <= 4) { bvhNode.isLeaf = true; bvhNode.start = start; bvhNode.count = count; bvhNode.leftChild = -1; bvhNode.rightChild = -1; outNodes.Add(bvhNode); return count1; } Vector3 size = ((Bounds)ref bounds).size; int axis = 0; if ((double)size.y > (double)size.x && (double)size.y > (double)size.z) axis = 1; else if ((double)size.z > (double)size.x && (double)size.z > (double)size.y) axis = 2; float num1 = 0.0f; for (int index = start; index < start + count; ++index) { BvhTriangle tri = tris[triIndices[index]]; Vector3 vector3 = Vector3.op_Division(Vector3.op_Addition(Vector3.op_Addition(tri.a, tri.b), tri.c), 3f); num1 += ((Vector3)ref vector3)[axis]; } float splitPos = num1 / (float)count; int start1 = this.Partition(tris, triIndices, start, count, axis, splitPos); if (start1 == start || start1 == start + count) start1 = start + count / 2; bvhNode.isLeaf = false; bvhNode.start = -1; bvhNode.count = 0; outNodes.Add(bvhNode); int num2 = this.BuildRecursive(tris, triIndices, start, start1 - start, outNodes); int num3 = this.BuildRecursive(tris, triIndices, start1, start + count - start1, outNodes); bvhNode.leftChild = num2; bvhNode.rightChild = num3; outNodes[count1] = bvhNode; return count1; } private int Partition( BvhTriangle[] tris, int[] triIndices, int start, int count, int axis, float splitPos) { int index1 = start; int index2 = start + count - 1; while (index1 <= index2) { BvhTriangle tri1 = tris[triIndices[index1]]; BvhTriangle tri2 = tris[triIndices[index2]]; double num1 = ((double)((Vector3)ref tri1.a)[axis] + (double)((Vector3)ref tri1.b)[axis] + (double)((Vector3)ref tri1.c)[axis]) / 3.0; double num2 = ((double)((Vector3)ref tri2.a)[axis] + (double)((Vector3)ref tri2.b)[axis] + (double)((Vector3)ref tri2.c)[axis]) / 3.0; double num3 = (double)splitPos; if (num1 < num3) { ++index1; } else { int triIndex = triIndices[index1]; triIndices[index1] = triIndices[index2]; triIndices[index2] = triIndex; --index2; } } return index1; } public BvhTriangleMesh.ClosestHit QueryClosest(Vector3 point) { BvhTriangleMesh.ClosestHit best = new BvhTriangleMesh.ClosestHit() { triangleIndex = -1, sqrDistance = float.MaxValue }; if (this.nodes == null || this.nodes.Length == 0) return best; this.QueryClosestRecursive(0, point, ref best); return best; } public BvhTriangleMesh.ClosestHit QueryClosest( Vector3 point, HashSet allowedBones) { BvhTriangleMesh.ClosestHit best = new BvhTriangleMesh.ClosestHit() { triangleIndex = -1, sqrDistance = float.MaxValue }; if (this.nodes == null || this.nodes.Length == 0) return best; if (allowedBones == null || allowedBones.Count == 0) this.QueryClosestRecursive(0, point, ref best); else this.QueryClosestRecursiveFiltered(0, point, ref best, allowedBones); return best; } private void QueryClosestRecursiveFiltered( int nodeIndex, Vector3 p, ref BvhTriangleMesh.ClosestHit best, HashSet allowedBones) { BvhNode node = this.nodes[nodeIndex]; if ((double)this.DistanceSqPointAABB(p, node.bounds) > (double)best.sqrDistance) return; if (node.isLeaf) { int num = node.start + node.count; for (int start = node.start; start < num; ++start) { int triIndex = this.triIndices[start]; BvhTriangle triangle = this.triangles[triIndex]; if (allowedBones.Contains(triangle.mainHumanBone)) { Vector3 vector3_1 = this.triangleUtil.ClosestPointOnTriangle(p, triangle.a, triangle.b, triangle.c); Vector3 vector3_2 = Vector3.op_Subtraction(p, vector3_1); float sqrMagnitude = ((Vector3)ref vector3_2).sqrMagnitude; if ((double)sqrMagnitude < (double)best.sqrDistance) { best.sqrDistance = sqrMagnitude; best.triangleIndex = triIndex; best.closestPoint = vector3_1; best.normal = triangle.normal; best.mainHumanBone = triangle.mainHumanBone; } } } } else { int leftChild = node.leftChild; int rightChild = node.rightChild; if ((double)this.DistanceSqPointAABB(p, this.nodes[leftChild].bounds) < (double)this.DistanceSqPointAABB(p, this.nodes[rightChild].bounds)) { this.QueryClosestRecursiveFiltered(leftChild, p, ref best, allowedBones); this.QueryClosestRecursiveFiltered(rightChild, p, ref best, allowedBones); } else { this.QueryClosestRecursiveFiltered(rightChild, p, ref best, allowedBones); this.QueryClosestRecursiveFiltered(leftChild, p, ref best, allowedBones); } } } private void QueryClosestRecursive(int nodeIndex, Vector3 p, ref BvhTriangleMesh.ClosestHit best) { BvhNode node = this.nodes[nodeIndex]; if ((double)this.DistanceSqPointAABB(p, node.bounds) > (double)best.sqrDistance) return; if (node.isLeaf) { int num = node.start + node.count; for (int start = node.start; start < num; ++start) { int triIndex = this.triIndices[start]; BvhTriangle triangle = this.triangles[triIndex]; Vector3 vector3_1 = this.triangleUtil.ClosestPointOnTriangle(p, triangle.a, triangle.b, triangle.c); Vector3 vector3_2 = Vector3.op_Subtraction(p, vector3_1); float sqrMagnitude = ((Vector3)ref vector3_2).sqrMagnitude; if ((double)sqrMagnitude < (double)best.sqrDistance) { best.sqrDistance = sqrMagnitude; best.triangleIndex = triIndex; best.closestPoint = vector3_1; best.normal = triangle.normal; best.mainHumanBone = triangle.mainHumanBone; } } } else { int leftChild = node.leftChild; int rightChild = node.rightChild; if ((double)this.DistanceSqPointAABB(p, this.nodes[leftChild].bounds) < (double)this.DistanceSqPointAABB(p, this.nodes[rightChild].bounds)) { this.QueryClosestRecursive(leftChild, p, ref best); this.QueryClosestRecursive(rightChild, p, ref best); } else { this.QueryClosestRecursive(rightChild, p, ref best); this.QueryClosestRecursive(leftChild, p, ref best); } } } private float DistanceSqPointAABB(Vector3 p, Bounds b) { float num1 = Mathf.Max(new float[3] { ((Bounds) ref b).min.x - p.x, 0.0f, p.x - ((Bounds) ref b).max.x }); float num2 = Mathf.Max(new float[3] { ((Bounds) ref b).min.y - p.y, 0.0f, p.y - ((Bounds) ref b).max.y }); float num3 = Mathf.Max(new float[3] { ((Bounds) ref b).min.z - p.z, 0.0f, p.z - ((Bounds) ref b).max.z }); return (float)((double)num1 * (double)num1 + (double)num2 * (double)num2 + (double)num3 * (double)num3); } public int QueryClosestN( Vector3 point, int maxCount, float maxDistance, List results) { results.Clear(); if (this.nodes == null || this.nodes.Length == 0 || maxCount <= 0) return 0; float maxDistanceSq = maxDistance * maxDistance; float currentMaxSq = maxDistanceSq; this.QueryClosestNRecursive(0, point, maxCount, maxDistanceSq, results, ref currentMaxSq); return results.Count; } private void QueryClosestNRecursive( int nodeIndex, Vector3 p, int maxCount, float maxDistanceSq, List bestHits, ref float currentMaxSq) { BvhNode node = this.nodes[nodeIndex]; if ((double)this.DistanceSqPointAABB(p, node.bounds) > (double)currentMaxSq) return; if (node.isLeaf) { int num1 = node.start + node.count; for (int start = node.start; start < num1; ++start) { int triIndex = this.triIndices[start]; BvhTriangle triangle = this.triangles[triIndex]; Vector3 vector3_1 = this.triangleUtil.ClosestPointOnTriangle(p, triangle.a, triangle.b, triangle.c); Vector3 vector3_2 = Vector3.op_Subtraction(p, vector3_1); float sqrMagnitude = ((Vector3)ref vector3_2).sqrMagnitude; BvhTriangleMesh.ClosestHit closestHit1; if ((double)sqrMagnitude <= (double)maxDistanceSq) { if (bestHits.Count < maxCount) { List closestHitList = bestHits; closestHit1 = new BvhTriangleMesh.ClosestHit(); closestHit1.triangleIndex = triIndex; closestHit1.closestPoint = vector3_1; closestHit1.normal = triangle.normal; closestHit1.sqrDistance = sqrMagnitude; closestHit1.mainHumanBone = triangle.mainHumanBone; BvhTriangleMesh.ClosestHit closestHit2 = closestHit1; closestHitList.Add(closestHit2); if (bestHits.Count == maxCount) currentMaxSq = this.GetMaxSqrDistance(bestHits, maxDistanceSq); } else if ((double)sqrMagnitude < (double)currentMaxSq) { int num2 = 0; float sqrDistance = bestHits[0].sqrDistance; for (int index = 1; index < bestHits.Count; ++index) { if ((double)bestHits[index].sqrDistance > (double)sqrDistance) { sqrDistance = bestHits[index].sqrDistance; num2 = index; } } List closestHitList = bestHits; int index1 = num2; closestHit1 = new BvhTriangleMesh.ClosestHit(); closestHit1.triangleIndex = triIndex; closestHit1.closestPoint = vector3_1; closestHit1.normal = triangle.normal; closestHit1.sqrDistance = sqrMagnitude; BvhTriangleMesh.ClosestHit closestHit3 = closestHit1; closestHitList[index1] = closestHit3; currentMaxSq = this.GetMaxSqrDistance(bestHits, maxDistanceSq); } } } } else { int leftChild = node.leftChild; int rightChild = node.rightChild; if ((double)this.DistanceSqPointAABB(p, this.nodes[leftChild].bounds) < (double)this.DistanceSqPointAABB(p, this.nodes[rightChild].bounds)) { this.QueryClosestNRecursive(leftChild, p, maxCount, maxDistanceSq, bestHits, ref currentMaxSq); this.QueryClosestNRecursive(rightChild, p, maxCount, maxDistanceSq, bestHits, ref currentMaxSq); } else { this.QueryClosestNRecursive(rightChild, p, maxCount, maxDistanceSq, bestHits, ref currentMaxSq); this.QueryClosestNRecursive(leftChild, p, maxCount, maxDistanceSq, bestHits, ref currentMaxSq); } } } private float GetMaxSqrDistance(List bestHits, float maxDistanceSq) { if (bestHits.Count == 0) return maxDistanceSq; float sqrDistance = bestHits[0].sqrDistance; for (int index = 1; index < bestHits.Count; ++index) { if ((double)bestHits[index].sqrDistance > (double)sqrDistance) sqrDistance = bestHits[index].sqrDistance; } return Mathf.Min(sqrDistance, maxDistanceSq); } public Vector3 ComputeMoveVectorToSurface(Vector3 p, float targetGap = 0.0f) { BvhTriangleMesh.ClosestHit closestHit = this.QueryClosest(p); if (closestHit.triangleIndex < 0) return Vector3.zero; Vector3 moveVectorToSurface = Vector3.op_Subtraction(closestHit.closestPoint, p); if ((double)targetGap > 0.0) moveVectorToSurface = Vector3.op_Addition(moveVectorToSurface, Vector3.op_Multiply(((Vector3)ref closestHit.normal).normalized, targetGap)); return moveVectorToSurface; } public struct ClosestHit { public int triangleIndex; public Vector3 closestPoint; public Vector3 normal; public float sqrDistance; public HumanBodyBones mainHumanBone; } } }