Files
2026-02-21 16:45:37 +08:00

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;
}
}
}