124 lines
3.3 KiB
C#
124 lines
3.3 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace Mtree
|
|
{
|
|
public struct LeafPoint
|
|
{
|
|
public Vector3 position;
|
|
|
|
public Vector3 direction;
|
|
|
|
public float size;
|
|
|
|
public Mesh[] meshes;
|
|
|
|
public bool overrideNormals;
|
|
|
|
public float distanceFromOrigin;
|
|
|
|
private float length;
|
|
|
|
private int uLoops;
|
|
|
|
private float resolution;
|
|
|
|
public bool procedural;
|
|
|
|
private float gravityStrength;
|
|
|
|
public LeafPoint(Vector3 pos, Vector3 dir, float size, Mesh[] m, bool overrideNorm, float distanceFromOrigin, float length = 1f, int uLoops = 2, float resolution = 1f, bool procedural = false, float gravityStrength = 1f)
|
|
{
|
|
position = pos;
|
|
direction = dir;
|
|
this.size = size;
|
|
meshes = m;
|
|
overrideNormals = overrideNorm;
|
|
this.distanceFromOrigin = distanceFromOrigin;
|
|
this.length = length;
|
|
this.uLoops = uLoops;
|
|
this.resolution = resolution;
|
|
this.procedural = procedural;
|
|
this.gravityStrength = gravityStrength;
|
|
}
|
|
|
|
public Mesh GetMesh(int lodLevel)
|
|
{
|
|
if (!procedural)
|
|
{
|
|
if (meshes != null && meshes.Length > 0)
|
|
{
|
|
return meshes[Mathf.Min(lodLevel, meshes.Length - 1)];
|
|
}
|
|
return null;
|
|
}
|
|
return GrowLeaf();
|
|
}
|
|
|
|
private Mesh GrowLeaf()
|
|
{
|
|
Vector3[] array = new Vector3[uLoops];
|
|
Vector2[] array2 = new Vector2[uLoops];
|
|
for (int i = 0; i < uLoops; i++)
|
|
{
|
|
float num = (float)i / (float)(uLoops - 1);
|
|
float num2 = num - 0.5f;
|
|
float y = 0f - Mathf.Pow(num - 0.5f, 2f);
|
|
if (uLoops == 2)
|
|
{
|
|
y = 0f;
|
|
}
|
|
array[i] = new Vector3(num2 * 2f, y, 0f);
|
|
array2[i] = new Vector2(num, 0f);
|
|
}
|
|
Queue<Vector3> queue = new Queue<Vector3>();
|
|
Quaternion quaternion = Quaternion.FromToRotation(Vector3.up, direction);
|
|
quaternion = Quaternion.LookRotation(direction);
|
|
Vector3[] array3 = array;
|
|
foreach (Vector3 vector in array3)
|
|
{
|
|
queue.Enqueue(quaternion * vector * size + position);
|
|
}
|
|
Queue<Vector2> queue2 = new Queue<Vector2>(array2);
|
|
Queue<int> queue3 = new Queue<int>();
|
|
Vector3 vector2 = position;
|
|
Vector3 vector3 = direction.normalized;
|
|
int num3 = Mathf.Max(1, (int)(length * resolution));
|
|
float num4 = length / (float)num3;
|
|
for (int k = 0; k < num3; k++)
|
|
{
|
|
Vector3 vector4 = Vector3.Normalize(vector3 + Vector3.down * gravityStrength / resolution);
|
|
Vector3 vector5 = vector2 + vector3 * num4;
|
|
if ((Vector3.Angle(vector3, vector4) < 10f && k != num3 - 1) || vector5.y < 0f)
|
|
{
|
|
vector2 = vector5;
|
|
vector3 = vector4;
|
|
continue;
|
|
}
|
|
quaternion = Quaternion.FromToRotation(Vector3.up, Vector3.Slerp(vector3, vector4, 0.5f));
|
|
quaternion = Quaternion.LookRotation(vector3, Vector3.up);
|
|
int count = queue.Count;
|
|
for (int l = 0; l < uLoops; l++)
|
|
{
|
|
Vector3 item = quaternion * array[l] * size + vector5;
|
|
queue.Enqueue(item);
|
|
queue2.Enqueue(new Vector2((float)l / (float)(uLoops - 1), (float)(k + 1) / (float)num3));
|
|
if (l < uLoops - 1)
|
|
{
|
|
Utils.AddTriangle(queue3, count - uLoops + l, count + l, count - uLoops + 1 + l);
|
|
Utils.AddTriangle(queue3, count + l, count + l + 1, count - uLoops + l + 1);
|
|
}
|
|
}
|
|
vector2 = vector5;
|
|
vector3 = vector4;
|
|
}
|
|
Mesh mesh = new Mesh();
|
|
mesh.vertices = queue.ToArray();
|
|
mesh.uv = queue2.ToArray();
|
|
mesh.triangles = queue3.ToArray();
|
|
mesh.RecalculateNormals();
|
|
return mesh;
|
|
}
|
|
}
|
|
}
|