OldBlueWater/BlueWater/Assets/Quibli/Scripts/Mesh Generators/CurveRenderer.cs
2023-08-02 18:12:26 +09:00

166 lines
5.0 KiB
C#

#if UNITY_EDITOR
using System;
using ExternalPropertyAttributes;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Dustyroom {
[RequireComponent(typeof(MeshRenderer))]
[RequireComponent(typeof(MeshFilter))]
[ExecuteInEditMode]
public class CurveRenderer : MonoBehaviour {
[Required()]
public Transform end1;
[Required()]
public Transform end2;
[Space]
public int points = 20;
public AnimationCurve curve = AnimationCurve.EaseInOut(0, 0, 1, 0);
public float curveMultiplier = 1;
[Space]
public float thickness = 0.02f;
[Space, BoxGroup("Multiple Curves")]
public int quantity = 1;
[EnableIf(nameof(IsMultipleWires)), BoxGroup("Multiple Curves")]
public float curveVariability = 0.2f;
[EnableIf(nameof(IsMultipleWires)), BoxGroup("Multiple Curves")] [Range(0, 1)]
public float thicknessVariability = 0.1f;
[EnableIf(nameof(IsMultipleWires)), BoxGroup("Multiple Curves")]
public int randomSeed = 0;
[EnableIf(nameof(IsMultipleWires)), BoxGroup("Multiple Curves")]
public Vector3 interval = new Vector3(0.5f, 0, 0);
private bool IsMultipleWires => quantity > 1;
[Foldout("Advanced"), Label("UV")]
public Vector2 uv = Vector2.zero;
private MeshFilter _meshFilter;
private Mesh _mesh;
private Vector3 _lastPositionEnd1;
private Vector3 _lastPositionEnd2;
private void OnValidate() {
points = Mathf.Max(points, 2);
quantity = Mathf.Max(quantity, 1);
curveVariability = Mathf.Max(curveVariability, 0);
Refresh();
}
private void Update() {
#if UNITY_EDITOR
if (!end1 || !end2) return;
if (end1.position != _lastPositionEnd1 || end2.position != _lastPositionEnd2) {
Refresh();
}
_meshFilter.sharedMesh = _mesh;
#endif
}
private void Refresh() {
if (!end1 || !end2) return;
_meshFilter = GetComponent<MeshFilter>();
if (_meshFilter == null) {
return;
}
if (_mesh == null) {
if (_meshFilter.sharedMesh == null) {
_meshFilter.sharedMesh = new Mesh();
}
_mesh = Instantiate(_meshFilter.sharedMesh);
_mesh.name = "Curve Mesh";
}
var numPathPoints = (points + 1) * quantity;
const int numVerticesPerPathPoint = 4;
Vector3[] verts = new Vector3[numPathPoints * numVerticesPerPathPoint];
int numTris = 2 * numVerticesPerPathPoint * (numPathPoints - 1);
int[] triangles = new int[numTris * 3];
int vertIndex = 0;
int triIndex = 0;
// @formatter:off
int[] triangleMap = {
0, 4, 1, 1, 4, 5,
0, 3, 7, 0, 7, 4,
2, 7, 3, 2, 6, 7,
2, 1, 5, 2, 5, 6
};
// @formatter:on
// Fix the random seed for deterministic output.
var state = Random.state;
Random.InitState(randomSeed);
for (int line = 0; line < quantity; line++) {
var scale = curveMultiplier + Random.Range(-curveVariability, curveVariability);
var lineThickness = thickness * (1f + Random.Range(-thicknessVariability, thicknessVariability));
for (int i = 0; i <= points; ++i) {
float alpha = i / (float)points;
var positionLine = Vector3.Lerp(end1.position, end2.position, alpha) +
Vector3.up * curve.Evaluate(alpha) * scale;
var pointPosition = transform.InverseTransformPoint(positionLine + line * interval);
{
Vector3 localUp = transform.up;
Vector3 localRight = transform.right;
float ht = lineThickness * 0.5f;
// 0 --- 1
// | p |
// 3 --- 2
verts[vertIndex + 0] = pointPosition - localRight * ht + localUp * ht;
verts[vertIndex + 1] = pointPosition + localRight * ht + localUp * ht;
verts[vertIndex + 2] = pointPosition + localRight * ht - localUp * ht;
verts[vertIndex + 3] = pointPosition - localRight * ht - localUp * ht;
if (i < points) {
for (int j = 0; j < triangleMap.Length; j++) {
triangles[triIndex + j] = vertIndex + triangleMap[j];
}
}
vertIndex += 4;
triIndex += triangleMap.Length;
}
}
}
Random.state = state;
_mesh.Clear();
_mesh.vertices = verts;
_mesh.SetTriangles(triangles, 0);
var uvs = new Vector2[verts.Length];
for (int i = 0; i < uvs.Length; i++) {
uvs[i] = uv;
}
_mesh.SetUVs(0, uvs);
_mesh.RecalculateBounds();
_mesh.RecalculateNormals();
_mesh.RecalculateTangents();
_lastPositionEnd1 = end1.position;
_lastPositionEnd2 = end2.position;
}
}
}
#endif