204 lines
6.2 KiB
C#
204 lines
6.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Assets.Generators;
|
|
using Assets.Map;
|
|
using Assets.Voronoi;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using Random = System.Random;
|
|
|
|
namespace Assets
|
|
{
|
|
[Serializable]
|
|
public class GraphGeneratorDebug
|
|
{
|
|
public bool enabled = true;
|
|
public bool displayPoints = true;
|
|
public bool displayBeachLine = true;
|
|
public bool displayParabolas = false;
|
|
public bool displayVertices = true;
|
|
public bool displayNeighbours = false;
|
|
public bool displayLabels = false;
|
|
public bool displayHalfEdges = false;
|
|
public bool displayEdges = true;
|
|
}
|
|
|
|
[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter)), ExecuteInEditMode]
|
|
public class GraphGenerator : MonoBehaviour
|
|
{
|
|
MeshFilter _filter;
|
|
private PoissonDiskSampler _sampler;
|
|
IList<Vector3> _points = new List<Vector3>();
|
|
|
|
public VoronoiGenerator generator;
|
|
public int seed = Environment.TickCount;
|
|
public Vector2 size = new Vector2();
|
|
public GraphGeneratorDebug debug;
|
|
[Range(2.0f, 64.0f)]
|
|
public float radius = 8;
|
|
|
|
private double _directrix = 0.0f;
|
|
|
|
private Random _random;
|
|
private Dictionary<Vector3, Color> _colors;
|
|
|
|
void Start()
|
|
{
|
|
_filter = GetComponent<MeshFilter>();
|
|
|
|
Reset();
|
|
}
|
|
|
|
public Vector3 RandomPoint()
|
|
{
|
|
return _points[_random.Next(_points.Count)];
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
_colors = new Dictionary<Vector3, Color>();
|
|
_random = new System.Random(seed);
|
|
|
|
_sampler = new PoissonDiskSampler(radius);
|
|
_sampler.Generator = _random;
|
|
|
|
_points = new List<Vector3>(_sampler.Generate(size.x, size.y));
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
_colors[RandomPoint()] = Color.yellow;
|
|
}
|
|
|
|
// points = new List<Vector3>()
|
|
// {
|
|
// new Vector3(15.7f, 5.9f),
|
|
// new Vector3(37.9f, 10.3f),
|
|
// new Vector3(24.6f, 18.1f),
|
|
// new Vector3(53.5f, 8.0f),
|
|
// };
|
|
|
|
generator = new VoronoiGenerator(_points.Select(x => new Point(x.x, x.y)).ToList());
|
|
}
|
|
|
|
public void Generate()
|
|
{
|
|
generator.Generate();
|
|
}
|
|
|
|
public void Step()
|
|
{
|
|
generator.Step();
|
|
_directrix = generator.Line.Directrix;
|
|
}
|
|
|
|
void OnDrawGizmos()
|
|
{
|
|
|
|
if (!debug.enabled) return;
|
|
|
|
if (debug.displayPoints)
|
|
{
|
|
foreach (var point in _points)
|
|
{
|
|
Gizmos.color = _colors.ContainsKey(point) ? _colors[point] : Color.white;
|
|
Gizmos.DrawSphere(point, 1);
|
|
}
|
|
}
|
|
|
|
if (generator is null) return;
|
|
|
|
if (debug.displayNeighbours)
|
|
{
|
|
Gizmos.color = Color.yellow;
|
|
DisplayGraphEdges(generator.Delaunay);
|
|
}
|
|
|
|
if (debug.displayVertices)
|
|
{
|
|
Gizmos.color = Color.blue;
|
|
DisplayGraphVertices(generator.Voronoi);
|
|
}
|
|
|
|
if (debug.displayHalfEdges)
|
|
{
|
|
Gizmos.color = Color.green;
|
|
foreach (var edge in generator.HalfEdges)
|
|
{
|
|
var vecStart = new Vector3((float)edge.Start.x, (float)edge.Start.y);
|
|
var vecEnd = new Vector3((float)edge.End.x, (float)edge.End.y);
|
|
|
|
Gizmos.DrawLine(vecStart, vecEnd);
|
|
}
|
|
}
|
|
|
|
if (debug.displayEdges)
|
|
{
|
|
Gizmos.color = Color.white;
|
|
DisplayGraphEdges(generator.Voronoi);
|
|
}
|
|
|
|
Gizmos.color = Color.red;
|
|
Gizmos.DrawLine(new Vector3(0, (float)generator.Line.Directrix), new Vector3(size.x, (float)generator.Line.Directrix));
|
|
Gizmos.color = Color.blue;
|
|
|
|
Vector3 start;
|
|
|
|
if (debug.displayParabolas)
|
|
{
|
|
foreach (var parabola in generator.Line.Parabolas)
|
|
{
|
|
start = new Vector3(-size.x, (float)generator.Line.EvalParabola(parabola.Site.Point, -size.x));
|
|
for (var x = -size.x + 0.1f; x < size.x * 2; x += 0.1f)
|
|
{
|
|
var point = new Vector3(x, (float)generator.Line.EvalParabola(parabola.Site.Point, x));
|
|
Gizmos.DrawLine(start, point);
|
|
|
|
start = point;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (debug.displayBeachLine)
|
|
{
|
|
Gizmos.color = Color.white;
|
|
start = new Vector3(-size.x, (float)generator.Line.Eval(-size.x));
|
|
for (var x = -size.x + 0.1f; x < size.x * 2; x += 0.1f)
|
|
{
|
|
var point = new Vector3(x, (float)generator.Line.Eval(x));
|
|
Gizmos.DrawLine(start, point);
|
|
|
|
start = point;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Rewind(float y)
|
|
{
|
|
while (generator.Line.Directrix < y && !generator.Done)
|
|
{
|
|
generator.Step();
|
|
}
|
|
}
|
|
|
|
private void DisplayGraphVertices(Graph<Point> graph)
|
|
{
|
|
var vertices = graph.Vertices.Select(p => new Vector3((float) p.x, (float) p.y));
|
|
|
|
foreach (var v in vertices)
|
|
{
|
|
Gizmos.DrawSphere(v, 1);
|
|
if (debug.displayLabels) Handles.Label(v, $"({v.x:F2}, {v.y:F2})");
|
|
}
|
|
}
|
|
|
|
private void DisplayGraphEdges(Graph<Point> graph)
|
|
{
|
|
var edges = graph.Edges
|
|
.Select(edge => (graph.Vertices[edge.Item1], graph.Vertices[edge.Item2]))
|
|
.Select(edge => (new Vector3((float)edge.Item1.x, (float)edge.Item1.y), new Vector3((float)edge.Item2.x, (float)edge.Item2.y)));
|
|
|
|
foreach (var (s, e) in edges) Gizmos.DrawLine(s, e);
|
|
}
|
|
}
|
|
} |