using System; using System.Collections.Generic; using UnityEngine; namespace Mtree { public static class DensityAO { private static void BakeAo(Color[] colors, Vector3[] verts, Vector3[] normals, int[] triangles, Matrix4x4 transform, float resolution, float distance, string TreeName) { float[] array = new float[triangles.Length / 3]; float num = 0f; for (int i = 0; i < triangles.Length; i += 3) { array[i / 3] = GetTriangleArea(verts[triangles[i]], verts[triangles[i + 1]], verts[triangles[i + 2]]); num += array[i / 3]; } for (int j = 0; j < array.Length; j++) { array[j] /= num; } List list = new List(); WeightedRandom weightedRandom = new WeightedRandom(array); int num2 = (int)(num / (resolution * resolution)); System.Random random = new System.Random(); for (int k = 0; k < num2; k++) { int randomIndex = weightedRandom.GetRandomIndex(random); Vector3 point = SamplePointInTriangle(verts[triangles[randomIndex * 3]], verts[triangles[randomIndex * 3 + 1]], verts[triangles[randomIndex * 3 + 2]], random); point = transform.MultiplyPoint3x4(point); list.Add(point); } KDTree kDTree = new KDTree(list.ToArray(), transform.MultiplyPoint3x4(Vector3.zero), TreeName); float[] array2 = new float[verts.Length]; float num3 = 0f; for (int l = 0; l < verts.Length; l++) { Vector3 vector = transform.MultiplyPoint3x4(verts[l]); List list2 = kDTree.RadiusSearch(vector, distance); float num4 = 0f; Vector3 lhs = transform.MultiplyVector(normals[l]); foreach (Vector3 item in list2) { float num5 = Vector3.Distance(item, vector); num4 += Mathf.Clamp01(Vector3.Dot(lhs, item - vector) / num5 + 0.5f) * Mathf.Exp(0f - num5); } num3 = Mathf.Max(num4, num3); array2[l] = num4; } for (int m = 0; m < array2.Length; m++) { array2[m] /= num3; } for (int n = 0; n < colors.Length; n++) { colors[n].a = Mathf.Pow(1f - array2[n], 5f); } } public static float GetTriangleArea(Vector3 v1, Vector3 v2, Vector3 v3) { Vector3 lhs = v2 - v1; Vector3 rhs = v3 - v1; return Vector3.Cross(lhs, rhs).magnitude / 2f; } private static Vector3 SamplePointInTriangle(Vector3 v1, Vector3 v2, Vector3 v3, System.Random random) { float f = (float)random.NextDouble(); float num = (float)random.NextDouble(); return (1f - Mathf.Sqrt(f)) * v1 + Mathf.Sqrt(f) * (1f - num) * v2 + num * Mathf.Sqrt(f) * v3; } public static ThreadHandleEditor BakeAoAsync(MeshFilter meshFilter, GameObject ob, float resolution, float distance) { Mesh mesh = meshFilter.sharedMesh; Color[] colors = mesh.colors; Vector3[] verts = mesh.vertices; Vector3[] normals = mesh.normals; int[] triangles = mesh.triangles; string name = ob.name; if (meshFilter == null || ob == null) { return null; } Matrix4x4 transformMatrix = ob.transform.localToWorldMatrix; ThreadHandleEditor threadHandleEditor = new ThreadHandleEditor(null, delegate { BakeAo(colors, verts, normals, triangles, transformMatrix, resolution, distance, name); }, delegate { mesh.colors = colors; if (meshFilter != null) { meshFilter.sharedMesh = mesh; } }); threadHandleEditor.Start(); return threadHandleEditor; } public static void BakeAo(MeshFilter meshFilter, GameObject ob, float resolution, float distance) { Mesh sharedMesh = meshFilter.sharedMesh; Color[] colors = sharedMesh.colors; Vector3[] vertices = sharedMesh.vertices; Vector3[] normals = sharedMesh.normals; int[] triangles = sharedMesh.triangles; Matrix4x4 localToWorldMatrix = ob.transform.localToWorldMatrix; BakeAo(colors, vertices, normals, triangles, localToWorldMatrix, resolution, distance, ob.name); sharedMesh.colors = colors; meshFilter.sharedMesh = sharedMesh; } } }