using System; using System.Collections.Generic; using System.Linq; using Assets.Common; using Assets.Map; using UnityEngine; namespace Assets { [RequireComponent(typeof(MeshFilter))] [RequireComponent(typeof(MeshRenderer))] [RequireComponent(typeof(GraphGenerator))] public class MapRenderer : MonoBehaviour { public float UVScale = 1.0f; private List _vertices; private List _uv; private List _normals; private List _colors; private List _triangles; public void Generate() { var graph = GetComponent(); graph.Reset(); graph.Generate(); var points = graph.VoronoiGenerator.Voronoi.Vertices; _vertices = new List(); _normals = new List(); _uv = new List(); _colors = new List(); _triangles = new List(); foreach (var location in graph.LocationGenerator.Result.Vertices.Skip(1)) { GenerateLocationMesh(location, points); GenerateLocationWall(location, points); } Mesh mesh = new Mesh(); mesh.vertices = _vertices.ToArray(); mesh.uv = _uv.ToArray(); mesh.normals = _normals.ToArray(); mesh.triangles = _triangles.ToArray(); mesh.colors = _colors.ToArray(); GetComponent().sharedMesh = mesh; } private void GenerateLocationMesh(Location location, IList points) { foreach (var vertices in location.Sites.Select(site => site.Site.Edges.Select(x => x.Item1).Reverse())) { int start = _vertices.Count; foreach (var i in vertices) { var isEdge = location.BoundaryPoints.Contains(i); var vertex = points[i]; var v = PointToVector(location, vertex); _vertices.Add(v); _normals.Add(Vector3.up); _uv.Add(new Vector2(v.x, v.z) / UVScale); _colors.Add(isEdge ? Color.red : Color.blue); } int end = _vertices.Count; for (int i = start + 1; i < end - 1; i++) { _triangles.AddRange(new []{ start, i, i+1 }); } } } private static Vector3 PointToVector(Location location, Point vertex) { return new Vector3((float)vertex.x, location.Type.height + Mathf.PerlinNoise((float)vertex.x, (float)vertex.y) / 4, (float)vertex.y); } private void GenerateLocationWall(Location location, IList points) { var length = 0.0; var collection = location.BoundaryPoints.Append(location.BoundaryPoints.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])); foreach (var (p, c, n) in edges) { int start = _vertices.Count; var dist = Point.Dist(p, c); var veca = PointToVector(location, p); var vecb = PointToVector(location, c); _vertices.Add(veca); _vertices.Add(new Vector3((float)p.x, -10,(float)p.y)); _vertices.Add(vecb); _vertices.Add(new Vector3((float)c.x, -10,(float)c.y)); var normal = new Vector3((float)(p.x + n.x - c.x) / 2.0f, 0, (float)(p.y + n.y - c.y) / 2.0f).normalized; _normals.AddRange(Enumerable.Repeat(normal, 4)); _colors.AddRange(Enumerable.Repeat(Color.red, 4)); _triangles.AddRange(new [] { start, start + 2, start + 1, start + 1, start + 2, start + 3 }); _uv.AddRange(new [] { new Vector2((float)length, veca.y) / UVScale, new Vector2((float)length, -10) / UVScale, new Vector2((float)(length + dist), vecb.y) / UVScale, new Vector2((float)(length + dist), -10) / UVScale, }); length += dist; } } } }