Add more detailed edges
This commit is contained in:
parent
4faf43a3ef
commit
696343f258
@ -19,6 +19,8 @@ namespace Assets.Map
|
|||||||
|
|
||||||
public LocationType Type;
|
public LocationType Type;
|
||||||
|
|
||||||
|
public List<Point> DetailedEdge = new List<Point>();
|
||||||
|
|
||||||
public void AddSite(LocationSite site)
|
public void AddSite(LocationSite site)
|
||||||
{
|
{
|
||||||
site.Location = this;
|
site.Location = this;
|
||||||
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using Assets.Common;
|
using Assets.Common;
|
||||||
using Assets.Map;
|
using Assets.Map;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Random = UnityEngine.Random;
|
||||||
|
|
||||||
namespace Assets
|
namespace Assets
|
||||||
{
|
{
|
||||||
@ -13,13 +14,15 @@ namespace Assets
|
|||||||
public class MapRenderer : MonoBehaviour
|
public class MapRenderer : MonoBehaviour
|
||||||
{
|
{
|
||||||
public float UVScale = 1.0f;
|
public float UVScale = 1.0f;
|
||||||
|
|
||||||
private List<Vector3> _vertices;
|
private List<Vector3> _vertices;
|
||||||
private List<Vector2> _uv;
|
private List<Vector2> _uv;
|
||||||
private List<Vector3> _normals;
|
private List<Vector3> _normals;
|
||||||
private List<Color> _colors;
|
private List<Color> _colors;
|
||||||
private List<int> _triangles;
|
private List<int> _triangles;
|
||||||
|
|
||||||
|
private List<List<Point>> _edges;
|
||||||
|
|
||||||
public void Generate()
|
public void Generate()
|
||||||
{
|
{
|
||||||
var graph = GetComponent<GraphGenerator>();
|
var graph = GetComponent<GraphGenerator>();
|
||||||
@ -37,7 +40,8 @@ namespace Assets
|
|||||||
|
|
||||||
foreach (var location in graph.LocationGenerator.Result.Vertices.Skip(1))
|
foreach (var location in graph.LocationGenerator.Result.Vertices.Skip(1))
|
||||||
{
|
{
|
||||||
GenerateLocationMesh(location, points);
|
GenerateLocationEdges(location, points);
|
||||||
|
GenerateLocationMeshAlt(location, points);
|
||||||
GenerateLocationWall(location, points);
|
GenerateLocationWall(location, points);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +53,53 @@ namespace Assets
|
|||||||
mesh.colors = _colors.ToArray();
|
mesh.colors = _colors.ToArray();
|
||||||
|
|
||||||
GetComponent<MeshFilter>().sharedMesh = mesh;
|
GetComponent<MeshFilter>().sharedMesh = mesh;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateLocationEdges(Location location, List<Point> points)
|
||||||
|
{
|
||||||
|
foreach (var (a, b) in location.BoundaryEdges.Select(x => (points[x.Item1], points[x.Item2])))
|
||||||
|
location.DetailedEdge.AddRange(this.SplitEdge(a, b, 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<Point> SplitEdge(Point a, Point b, int count)
|
||||||
|
{
|
||||||
|
// var direction = ;
|
||||||
|
var magnitude = Point.Dist(a, b);
|
||||||
|
var d = new Point(-(b.y - a.y) / magnitude, (b.x - a.x) / magnitude);
|
||||||
|
|
||||||
|
magnitude *= Random.value * 0.4 - 0.2;
|
||||||
|
|
||||||
|
Point c = new Point((a.x + b.x) / 2.0 + d.x * magnitude, (a.y + b.y) / 2.0 + d.y * magnitude);
|
||||||
|
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
foreach (var p in SplitEdge(a, c, count - 1))
|
||||||
|
yield return p;
|
||||||
|
|
||||||
|
yield return c;
|
||||||
|
|
||||||
|
foreach (var p in SplitEdge(c, b, count - 1))
|
||||||
|
yield return p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yield return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateLocationMeshAlt(Location location, IList<Point> points)
|
||||||
|
{
|
||||||
|
var start = _vertices.Count;
|
||||||
|
var count = location.DetailedEdge.Count;
|
||||||
|
|
||||||
|
_vertices.AddRange(location.DetailedEdge.Select(p => new Vector3((float)p.x, location.Type.height, (float)p.y)));
|
||||||
|
_normals.AddRange(Enumerable.Repeat(Vector3.up, count));
|
||||||
|
_colors.AddRange(Enumerable.Repeat(Color.blue, count));
|
||||||
|
_uv.AddRange(location.DetailedEdge.Select(p => new Vector2((float)p.x, (float)p.y) / UVScale));
|
||||||
|
|
||||||
|
var triangulator = new Triangulator(location.DetailedEdge.Select(v => new Vector2((float)v.x, (float)v.y)).ToArray());
|
||||||
|
_triangles.AddRange(triangulator.Triangulate().Select(x => x + start));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateLocationMesh(Location location, IList<Point> points)
|
private void GenerateLocationMesh(Location location, IList<Point> points)
|
||||||
@ -71,11 +122,10 @@ namespace Assets
|
|||||||
}
|
}
|
||||||
|
|
||||||
int end = _vertices.Count;
|
int end = _vertices.Count;
|
||||||
|
|
||||||
|
var triangulator = new Triangulator(_vertices.Skip(start).Take(end - start).Select(v => new Vector2(v.x, v.z)).ToArray());
|
||||||
|
_triangles.AddRange(triangulator.Triangulate().Select(x => x + start));
|
||||||
|
|
||||||
for (int i = start + 1; i < end - 1; i++)
|
|
||||||
{
|
|
||||||
_triangles.AddRange(new []{ start, i, i+1 });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,8 +138,8 @@ namespace Assets
|
|||||||
{
|
{
|
||||||
var length = 0.0;
|
var length = 0.0;
|
||||||
|
|
||||||
var collection = location.BoundaryPoints.Append(location.BoundaryPoints.First());
|
var collection = location.DetailedEdge.Append(location.DetailedEdge.First());
|
||||||
var edges = collection.Zip(collection.Skip(1), (a, b) => (a, b)).Zip(collection.Skip(2), (tuple, c) => (points[tuple.a], points[tuple.b], points[c]));
|
var edges = collection.Zip(collection.Skip(1), (a, b) => (a, b)).Zip(collection.Skip(2), (tuple, c) => (tuple.a, tuple.b, c));
|
||||||
|
|
||||||
foreach (var (p, c, n) in edges)
|
foreach (var (p, c, n) in edges)
|
||||||
{
|
{
|
||||||
@ -126,5 +176,22 @@ namespace Assets
|
|||||||
length += dist;
|
length += dist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnDrawGizmos()
|
||||||
|
{
|
||||||
|
var graph = GetComponent<GraphGenerator>();
|
||||||
|
|
||||||
|
foreach (var location in graph.LocationGenerator.Result.Vertices.Skip(1))
|
||||||
|
{
|
||||||
|
var boundary = location.DetailedEdge;
|
||||||
|
foreach (var (a, b) in boundary.Zip(boundary.Skip(1).Append(boundary.First()), (a, b) => (a, b)))
|
||||||
|
{
|
||||||
|
var va = new Vector3((float) a.x, location.Type.height, (float) a.y);
|
||||||
|
var vb = new Vector3((float) b.x, location.Type.height, (float) b.y);
|
||||||
|
|
||||||
|
Gizmos.DrawLine(va, vb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
112
Assets/Triangulator.cs
Normal file
112
Assets/Triangulator.cs
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Assets
|
||||||
|
{
|
||||||
|
public class Triangulator
|
||||||
|
{
|
||||||
|
private List<Vector2> m_points = new List<Vector2>();
|
||||||
|
|
||||||
|
public Triangulator (Vector2[] points) {
|
||||||
|
m_points = new List<Vector2>(points);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] Triangulate() {
|
||||||
|
List<int> indices = new List<int>();
|
||||||
|
|
||||||
|
int n = m_points.Count;
|
||||||
|
if (n < 3)
|
||||||
|
return indices.ToArray();
|
||||||
|
|
||||||
|
int[] V = new int[n];
|
||||||
|
if (Area() > 0) {
|
||||||
|
for (int v = 0; v < n; v++)
|
||||||
|
V[v] = v;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int v = 0; v < n; v++)
|
||||||
|
V[v] = (n - 1) - v;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nv = n;
|
||||||
|
int count = 2 * nv;
|
||||||
|
for (int v = nv - 1; nv > 2; ) {
|
||||||
|
if ((count--) <= 0)
|
||||||
|
return indices.ToArray();
|
||||||
|
|
||||||
|
int u = v;
|
||||||
|
if (nv <= u)
|
||||||
|
u = 0;
|
||||||
|
v = u + 1;
|
||||||
|
if (nv <= v)
|
||||||
|
v = 0;
|
||||||
|
int w = v + 1;
|
||||||
|
if (nv <= w)
|
||||||
|
w = 0;
|
||||||
|
|
||||||
|
if (Snip(u, v, w, nv, V)) {
|
||||||
|
int a, b, c, s, t;
|
||||||
|
a = V[u];
|
||||||
|
b = V[v];
|
||||||
|
c = V[w];
|
||||||
|
indices.Add(a);
|
||||||
|
indices.Add(b);
|
||||||
|
indices.Add(c);
|
||||||
|
for (s = v, t = v + 1; t < nv; s++, t++)
|
||||||
|
V[s] = V[t];
|
||||||
|
nv--;
|
||||||
|
count = 2 * nv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
indices.Reverse();
|
||||||
|
return indices.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private float Area () {
|
||||||
|
int n = m_points.Count;
|
||||||
|
float A = 0.0f;
|
||||||
|
for (int p = n - 1, q = 0; q < n; p = q++) {
|
||||||
|
Vector2 pval = m_points[p];
|
||||||
|
Vector2 qval = m_points[q];
|
||||||
|
A += pval.x * qval.y - qval.x * pval.y;
|
||||||
|
}
|
||||||
|
return (A * 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Snip (int u, int v, int w, int n, int[] V) {
|
||||||
|
int p;
|
||||||
|
Vector2 A = m_points[V[u]];
|
||||||
|
Vector2 B = m_points[V[v]];
|
||||||
|
Vector2 C = m_points[V[w]];
|
||||||
|
if (Mathf.Epsilon > (((B.x - A.x) * (C.y - A.y)) - ((B.y - A.y) * (C.x - A.x))))
|
||||||
|
return false;
|
||||||
|
for (p = 0; p < n; p++) {
|
||||||
|
if ((p == u) || (p == v) || (p == w))
|
||||||
|
continue;
|
||||||
|
Vector2 P = m_points[V[p]];
|
||||||
|
if (InsideTriangle(A, B, C, P))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool InsideTriangle (Vector2 A, Vector2 B, Vector2 C, Vector2 P) {
|
||||||
|
float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
|
||||||
|
float cCROSSap, bCROSScp, aCROSSbp;
|
||||||
|
|
||||||
|
ax = C.x - B.x; ay = C.y - B.y;
|
||||||
|
bx = A.x - C.x; by = A.y - C.y;
|
||||||
|
cx = B.x - A.x; cy = B.y - A.y;
|
||||||
|
apx = P.x - A.x; apy = P.y - A.y;
|
||||||
|
bpx = P.x - B.x; bpy = P.y - B.y;
|
||||||
|
cpx = P.x - C.x; cpy = P.y - C.y;
|
||||||
|
|
||||||
|
aCROSSbp = ax * bpy - ay * bpx;
|
||||||
|
cCROSSap = cx * apy - cy * apx;
|
||||||
|
bCROSScp = bx * cpy - by * cpx;
|
||||||
|
|
||||||
|
return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
Assets/Triangulator.cs.meta
Normal file
3
Assets/Triangulator.cs.meta
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0cc918130bd1443ea69b7b49290749d2
|
||||||
|
timeCreated: 1567611131
|
Loading…
Reference in New Issue
Block a user