116 lines
3.8 KiB
C#
116 lines
3.8 KiB
C#
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<Vector3> list = new List<Vector3>();
|
|
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<Vector3> 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;
|
|
}
|
|
}
|
|
}
|