From 367f433639ed25a3704c3f33720068dda6224334 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sat, 16 Nov 2019 20:54:04 +0100 Subject: [PATCH] renderer do map --- Assets/Editor/MapRendererUI.cs | 4 +- Assets/Scenes/OverworldExample.unity | 10 +- Assets/Scripts/Common/Extensions.cs | 9 + Assets/Scripts/Common/IHasMetadata.cs | 7 + Assets/Scripts/Common/IHasMetadata.cs.meta | 3 + Assets/Scripts/Common/Location.cs | 4 +- Assets/Scripts/Common/Map.cs | 4 +- Assets/Scripts/Common/MapSite.cs | 4 +- Assets/Scripts/LandmassGenerator.cs | 8 +- Assets/Scripts/MapRenderer.cs | 239 ++++-------------- .../{IRenderPass.cs => IRenderer.cs} | 4 +- ...{IRenderPass.cs.meta => IRenderer.cs.meta} | 0 Assets/Scripts/RenderPass/LandmassRenderer.cs | 174 +++++++++++++ .../RenderPass/LandmassRenderer.cs.meta | 3 + 14 files changed, 274 insertions(+), 199 deletions(-) create mode 100644 Assets/Scripts/Common/IHasMetadata.cs create mode 100644 Assets/Scripts/Common/IHasMetadata.cs.meta rename Assets/Scripts/RenderPass/{IRenderPass.cs => IRenderer.cs} (60%) rename Assets/Scripts/RenderPass/{IRenderPass.cs.meta => IRenderer.cs.meta} (100%) create mode 100644 Assets/Scripts/RenderPass/LandmassRenderer.cs create mode 100644 Assets/Scripts/RenderPass/LandmassRenderer.cs.meta diff --git a/Assets/Editor/MapRendererUI.cs b/Assets/Editor/MapRendererUI.cs index 04f76dc..d0a66f4 100644 --- a/Assets/Editor/MapRendererUI.cs +++ b/Assets/Editor/MapRendererUI.cs @@ -13,9 +13,9 @@ namespace Editor DrawDefaultInspector(); - if (GUILayout.Button("Generate")) + if (GUILayout.Button("Render")) { -// target.Generate(); + target.Render(); } } } diff --git a/Assets/Scenes/OverworldExample.unity b/Assets/Scenes/OverworldExample.unity index d3d0133..fb03a81 100644 --- a/Assets/Scenes/OverworldExample.unity +++ b/Assets/Scenes/OverworldExample.unity @@ -159,7 +159,7 @@ MonoBehaviour: displayEdges: 0 displayLocations: 0 displayLocationCells: 0 - displayLocationEdges: 0 + displayLocationEdges: 1 displayCities: 1 displayLocationPoints: 0 displayFieldBoundaries: 1 @@ -183,7 +183,7 @@ MonoBehaviour: minimumNudgeDistance: 0.25 maximumNudgeDistance: 0.75 radius: 5 - seed: 1686660096 + seed: 1770256640 --- !u!4 &319467308 Transform: m_ObjectHideFlags: 0 @@ -274,13 +274,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 519420028} - m_LocalRotation: {x: 0.35355338, y: -0.35355338, z: 0.1464466, w: 0.8535535} - m_LocalPosition: {x: 290.29, y: 43.7, z: 190.7} + m_LocalRotation: {x: 0.5187663, y: -0.3166594, z: 0.21488002, w: 0.7644835} + m_LocalPosition: {x: 250, y: 98.4, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 0} m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 45.000004, y: -45, z: 0} + m_LocalEulerAnglesHint: {x: 68.32, y: -45.000004, z: 0} --- !u!1 &1831814988 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Common/Extensions.cs b/Assets/Scripts/Common/Extensions.cs index aa05833..f6cfb98 100644 --- a/Assets/Scripts/Common/Extensions.cs +++ b/Assets/Scripts/Common/Extensions.cs @@ -30,4 +30,13 @@ namespace Assets.Common return tail.Concat(head); } } + + public static class HasMetadataExtensions + { + + public static bool HasProperty(this IHasMetadata subject, string name) => subject.Metadata.HasProperty(name); + public static bool HasProperty(this IHasMetadata subject, string name) => subject.Metadata.HasProperty(name); + public static void SetProperty(this IHasMetadata subject, string name, T property) => subject.Metadata.SetProperty(name, property); + public static T GetProperty(this IHasMetadata subject, string name) => subject.Metadata.GetProperty(name); + } } \ No newline at end of file diff --git a/Assets/Scripts/Common/IHasMetadata.cs b/Assets/Scripts/Common/IHasMetadata.cs new file mode 100644 index 0000000..f2324c7 --- /dev/null +++ b/Assets/Scripts/Common/IHasMetadata.cs @@ -0,0 +1,7 @@ +namespace Assets.Common +{ + public interface IHasMetadata + { + Metadata Metadata { get; } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Common/IHasMetadata.cs.meta b/Assets/Scripts/Common/IHasMetadata.cs.meta new file mode 100644 index 0000000..7ce388e --- /dev/null +++ b/Assets/Scripts/Common/IHasMetadata.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b1254b30c38e4b03ab2d571e411522f6 +timeCreated: 1573931268 \ No newline at end of file diff --git a/Assets/Scripts/Common/Location.cs b/Assets/Scripts/Common/Location.cs index b728cd4..4bc2efc 100644 --- a/Assets/Scripts/Common/Location.cs +++ b/Assets/Scripts/Common/Location.cs @@ -4,7 +4,7 @@ using Assets.Voronoi; namespace Assets.Common { - public class Location + public class Location : IHasMetadata { public List Sites = new List(); @@ -34,5 +34,7 @@ namespace Assets.Common BoundaryEdges = a.Union(b).Except(a.Intersect(b)).ToList(); } + + public Metadata Metadata { get; } = new Metadata(); } } \ No newline at end of file diff --git a/Assets/Scripts/Common/Map.cs b/Assets/Scripts/Common/Map.cs index 959df69..94d4baa 100644 --- a/Assets/Scripts/Common/Map.cs +++ b/Assets/Scripts/Common/Map.cs @@ -4,7 +4,7 @@ using UnityEngine; namespace Assets.Common { [Serializable] - public class Map + public class Map : IHasMetadata { [SerializeField] private Graph _sites = new Graph(); @@ -28,7 +28,7 @@ namespace Assets.Common public Graph Boundaries { get; set; } - public readonly Metadata Metadata = new Metadata(); + public Metadata Metadata { get; } = new Metadata(); public Map(int seed) { diff --git a/Assets/Scripts/Common/MapSite.cs b/Assets/Scripts/Common/MapSite.cs index 8cb4ff2..c9057a7 100644 --- a/Assets/Scripts/Common/MapSite.cs +++ b/Assets/Scripts/Common/MapSite.cs @@ -6,9 +6,9 @@ using System.Linq; namespace Assets.Common { [Serializable] - public class MapSite + public class MapSite : IHasMetadata { - public readonly Metadata Metadata = new Metadata(); + public Metadata Metadata { get; } = new Metadata(); public MapSite(Point center, IEnumerable boundary) { diff --git a/Assets/Scripts/LandmassGenerator.cs b/Assets/Scripts/LandmassGenerator.cs index aa1f9e4..164dfee 100644 --- a/Assets/Scripts/LandmassGenerator.cs +++ b/Assets/Scripts/LandmassGenerator.cs @@ -74,7 +74,7 @@ namespace Assets public Graph BoundariesGraph => Map?.Boundaries; public Graph LocationGraph => Map?.Metadata.GetProperty>(LandmassPass.MapLocationsProperty); - public void Generate() + public void Generate(Action onDone) { GenerationThread?.Abort(); GenerationThread = new Thread(() => @@ -85,12 +85,18 @@ namespace Assets lock (GetType()) { Map = result; + onDone(result); } }); GenerationThread.Start(); } + public void Generate() + { + Generate(_ => { }); + } + public void OnDisable() { GenerationThread?.Abort(); diff --git a/Assets/Scripts/MapRenderer.cs b/Assets/Scripts/MapRenderer.cs index ea5b38c..71c0c55 100644 --- a/Assets/Scripts/MapRenderer.cs +++ b/Assets/Scripts/MapRenderer.cs @@ -1,197 +1,66 @@ +using System; using System.Collections.Generic; using System.Linq; using Assets.Common; +using Assets.RenderPass; using UnityEngine; +using UnityEngine.UIElements; using Random = UnityEngine.Random; namespace Assets { -// [RequireComponent(typeof(MeshFilter))] -// [RequireComponent(typeof(MeshRenderer))] -// [RequireComponent(typeof(LandmassGenerator))] + [RequireComponent(typeof(MeshFilter))] + [RequireComponent(typeof(MeshRenderer))] + [RequireComponent(typeof(LandmassGenerator))] public class MapRenderer : MonoBehaviour { -// public float UVScale = 1.0f; -// -// private List _vertices; -// private List _uv; -// private List _normals; -// private List _colors; -// private List _triangles; -// -// private List> _edges; -// -// 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)) -// { -// GenerateLocationEdges(location, points); -// GenerateLocationMeshAlt(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 GenerateLocationEdges(Location location, List 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 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 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 points) -// { -// foreach (var vertices in location.Sites.Select(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; -// -// 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)); -// -// } -// } -// -// 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.DetailedEdge.Append(location.DetailedEdge.First()); -// 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) -// { -// 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; -// } -// } -// -// private void OnDrawGizmos() -// { -// var graph = GetComponent(); -// -// if (graph?.LocationGenerator?.Result == null) return; -// -// 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); -// } -// } -// } + private bool _rerender = false; + + private IList _renderers = new List + { + new LandmassRenderer() + }; + + public void GenerateRandom() + { + var generator = GetComponent(); + + generator.seed = Environment.TickCount; + generator.Generate(map => _rerender = true); + } + + private void Update() + { + if (Input.GetMouseButtonDown(0)) + GenerateRandom(); + + if (_rerender) + { + Render(); + _rerender = false; + } + } + + public void Render() + { + var map = GetComponent().Map; + + if (map == null) + return; + + foreach (var current in _renderers) + current.Render(map, this); + } + + public void OnDrawGizmos() + { + var map = GetComponent().Map; + + if (map == null) + return; + + foreach (var current in _renderers) + current.DrawGizmos(map, this); + } } } \ No newline at end of file diff --git a/Assets/Scripts/RenderPass/IRenderPass.cs b/Assets/Scripts/RenderPass/IRenderer.cs similarity index 60% rename from Assets/Scripts/RenderPass/IRenderPass.cs rename to Assets/Scripts/RenderPass/IRenderer.cs index 4f03b22..aa7062a 100644 --- a/Assets/Scripts/RenderPass/IRenderPass.cs +++ b/Assets/Scripts/RenderPass/IRenderer.cs @@ -3,8 +3,10 @@ using UnityEngine; namespace Assets.RenderPass { - public interface IRenderPass + public interface IRenderer { void Render(Map map, Component component); + + void DrawGizmos(Map map, Component component); } } \ No newline at end of file diff --git a/Assets/Scripts/RenderPass/IRenderPass.cs.meta b/Assets/Scripts/RenderPass/IRenderer.cs.meta similarity index 100% rename from Assets/Scripts/RenderPass/IRenderPass.cs.meta rename to Assets/Scripts/RenderPass/IRenderer.cs.meta diff --git a/Assets/Scripts/RenderPass/LandmassRenderer.cs b/Assets/Scripts/RenderPass/LandmassRenderer.cs new file mode 100644 index 0000000..61e912f --- /dev/null +++ b/Assets/Scripts/RenderPass/LandmassRenderer.cs @@ -0,0 +1,174 @@ +using System.Collections.Generic; +using System.Linq; +using Assets.AnnotationPass; +using Assets.Common; +using UnityEngine; + +namespace Assets.RenderPass +{ + public class LandmassRenderer : IRenderer + { + public float UVScale { get; set; } = 1.0f; + + private List _vertices; + private List _uv; + private List _normals; + private List _colors; + private List _triangles; + private List> _edges; + + public void Render(Map map, Component component) + { + var points = map.Boundaries.Vertices; + var locations = map.GetProperty>(LandmassPass.MapLocationsProperty); + + _vertices = new List(); + _normals = new List(); + _uv = new List(); + _colors = new List(); + _triangles = new List(); + + foreach (var location in locations.Vertices.Skip(1)) + { + GenerateLocationEdges(location, points); + 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(); + + var mf = component.GetComponent(); + mf.sharedMesh = mesh; + } + + private void GenerateLocationEdges(Location location, List 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 SplitEdge(Point a, Point b, int count) + { + 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 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 points) + { + foreach (var vertices in location.Sites.Select(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; + + 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)); + + } + } + + 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.DetailedEdge.Append(location.DetailedEdge.First()); + 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) + { + 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; + } + } + + public void DrawGizmos(Map map, Component component) + { + + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/RenderPass/LandmassRenderer.cs.meta b/Assets/Scripts/RenderPass/LandmassRenderer.cs.meta new file mode 100644 index 0000000..540927f --- /dev/null +++ b/Assets/Scripts/RenderPass/LandmassRenderer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0ca9f42ceab24d34ad59014726adf348 +timeCreated: 1573931440 \ No newline at end of file