From b06f9f188702fbb00a18e1a202e797732c04471b Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sun, 10 Nov 2019 19:05:41 +0100 Subject: [PATCH] [otwarty teren] wydzielenie generowania ze skryptow unity part 4 --- Assets/Common/LocationGenerator.cs.meta | 3 - Assets/Common/MapSite.cs | 23 - Assets/Editor/CityGeneratorUI.cs | 35 +- Assets/Editor/ForestRendererUI.cs | 2 +- Assets/Editor/GraphGeneratorUI.cs | 77 -- Assets/Editor/LandmassGeneratorUI.cs | 34 + ...UI.cs.meta => LandmassGeneratorUI.cs.meta} | 0 Assets/Editor/MapRendererUI.cs | 2 +- Assets/Scenes/OverworldExample.unity | 59 ++ .../{ => AnnotationPass}/IAnnotationPass.cs | 2 +- .../AnnotationPass/IAnnotationPass.cs.meta | 3 + .../AnnotationPass/LocationPass.cs} | 75 +- ...tionsPass.cs.meta => LocationPass.cs.meta} | 0 .../Scripts/AnnotationPass/LocationsPass.cs | 12 - Assets/Scripts/CityGenerator.cs | 854 +++++++++--------- Assets/{ => Scripts}/Common.meta | 0 Assets/{ => Scripts}/Common/Bounding.cs | 0 Assets/{ => Scripts}/Common/Bounding.cs.meta | 0 Assets/{ => Scripts}/Common/Extensions.cs | 0 .../{ => Scripts}/Common/Extensions.cs.meta | 0 Assets/{ => Scripts}/Common/Graph.cs | 0 Assets/{ => Scripts}/Common/Graph.cs.meta | 0 Assets/{ => Scripts}/Common/Location.cs | 11 +- Assets/{ => Scripts}/Common/Location.cs.meta | 0 Assets/{ => Scripts}/Common/LocationSite.cs | 0 .../{ => Scripts}/Common/LocationSite.cs.meta | 0 Assets/{ => Scripts}/Common/Map.cs | 1 + Assets/{ => Scripts}/Common/Map.cs.meta | 0 Assets/Scripts/Common/MapSite.cs | 28 + Assets/{ => Scripts}/Common/MapSite.cs.meta | 0 Assets/{ => Scripts}/Common/Metadata.cs | 0 Assets/{ => Scripts}/Common/Metadata.cs.meta | 0 Assets/{ => Scripts}/Common/Point.cs | 0 Assets/{ => Scripts}/Common/Point.cs.meta | 0 Assets/{ => Scripts}/Common/PointUtils.cs | 0 .../{ => Scripts}/Common/PointUtils.cs.meta | 0 Assets/Scripts/ForestGenerator.cs | 166 ++-- Assets/Scripts/GridGenerator.meta | 3 + .../{ => GridGenerator}/IGridGenerator.cs | 2 +- .../GridGenerator/IGridGenerator.cs.meta | 3 + .../VoronoiGridGenerator.cs | 23 +- .../VoronoiGridGenerator.cs.meta | 0 Assets/Scripts/IAnnotationPass.cs.meta | 3 - Assets/Scripts/IGridGenerator.cs.meta | 3 - Assets/Scripts/LandmassGenerator.cs | 305 ++----- Assets/Scripts/MapGenerator.cs | 4 +- Assets/Scripts/MapRenderer.cs | 370 ++++---- Assets/Scripts/RenderPass.meta | 3 + .../Scripts/{ => RenderPass}/IRenderPass.cs | 2 +- .../{ => RenderPass}/IRenderPass.cs.meta | 0 Assets/{ => Scripts}/Triangulator.cs | 0 Assets/{ => Scripts}/Triangulator.cs.meta | 0 Assets/Scripts/Utils.meta | 3 + Assets/Scripts/Utils/DebugUtils.cs | 43 + Assets/Scripts/Utils/DebugUtils.cs.meta | 3 + Assets/{ => Scripts}/Voronoi.meta | 0 Assets/{ => Scripts}/Voronoi/BeachLine.cs | 0 .../{ => Scripts}/Voronoi/BeachLine.cs.meta | 0 Assets/{ => Scripts}/Voronoi/Tree.cs | 0 Assets/{ => Scripts}/Voronoi/Tree.cs.meta | 0 .../{ => Scripts}/Voronoi/VoronoiGenerator.cs | 0 .../Voronoi/VoronoiGenerator.cs.meta | 0 62 files changed, 1060 insertions(+), 1097 deletions(-) delete mode 100644 Assets/Common/LocationGenerator.cs.meta delete mode 100644 Assets/Common/MapSite.cs delete mode 100644 Assets/Editor/GraphGeneratorUI.cs create mode 100644 Assets/Editor/LandmassGeneratorUI.cs rename Assets/Editor/{GraphGeneratorUI.cs.meta => LandmassGeneratorUI.cs.meta} (100%) rename Assets/Scripts/{ => AnnotationPass}/IAnnotationPass.cs (76%) create mode 100644 Assets/Scripts/AnnotationPass/IAnnotationPass.cs.meta rename Assets/{Common/LocationGenerator.cs => Scripts/AnnotationPass/LocationPass.cs} (53%) rename Assets/Scripts/AnnotationPass/{LocationsPass.cs.meta => LocationPass.cs.meta} (100%) delete mode 100644 Assets/Scripts/AnnotationPass/LocationsPass.cs rename Assets/{ => Scripts}/Common.meta (100%) rename Assets/{ => Scripts}/Common/Bounding.cs (100%) rename Assets/{ => Scripts}/Common/Bounding.cs.meta (100%) rename Assets/{ => Scripts}/Common/Extensions.cs (100%) rename Assets/{ => Scripts}/Common/Extensions.cs.meta (100%) rename Assets/{ => Scripts}/Common/Graph.cs (100%) rename Assets/{ => Scripts}/Common/Graph.cs.meta (100%) rename Assets/{ => Scripts}/Common/Location.cs (82%) rename Assets/{ => Scripts}/Common/Location.cs.meta (100%) rename Assets/{ => Scripts}/Common/LocationSite.cs (100%) rename Assets/{ => Scripts}/Common/LocationSite.cs.meta (100%) rename Assets/{ => Scripts}/Common/Map.cs (96%) rename Assets/{ => Scripts}/Common/Map.cs.meta (100%) create mode 100644 Assets/Scripts/Common/MapSite.cs rename Assets/{ => Scripts}/Common/MapSite.cs.meta (100%) rename Assets/{ => Scripts}/Common/Metadata.cs (100%) rename Assets/{ => Scripts}/Common/Metadata.cs.meta (100%) rename Assets/{ => Scripts}/Common/Point.cs (100%) rename Assets/{ => Scripts}/Common/Point.cs.meta (100%) rename Assets/{ => Scripts}/Common/PointUtils.cs (100%) rename Assets/{ => Scripts}/Common/PointUtils.cs.meta (100%) create mode 100644 Assets/Scripts/GridGenerator.meta rename Assets/Scripts/{ => GridGenerator}/IGridGenerator.cs (80%) create mode 100644 Assets/Scripts/GridGenerator/IGridGenerator.cs.meta rename Assets/Scripts/{ => GridGenerator}/VoronoiGridGenerator.cs (64%) rename Assets/Scripts/{ => GridGenerator}/VoronoiGridGenerator.cs.meta (100%) delete mode 100644 Assets/Scripts/IAnnotationPass.cs.meta delete mode 100644 Assets/Scripts/IGridGenerator.cs.meta create mode 100644 Assets/Scripts/RenderPass.meta rename Assets/Scripts/{ => RenderPass}/IRenderPass.cs (83%) rename Assets/Scripts/{ => RenderPass}/IRenderPass.cs.meta (100%) rename Assets/{ => Scripts}/Triangulator.cs (100%) rename Assets/{ => Scripts}/Triangulator.cs.meta (100%) create mode 100644 Assets/Scripts/Utils.meta create mode 100644 Assets/Scripts/Utils/DebugUtils.cs create mode 100644 Assets/Scripts/Utils/DebugUtils.cs.meta rename Assets/{ => Scripts}/Voronoi.meta (100%) rename Assets/{ => Scripts}/Voronoi/BeachLine.cs (100%) rename Assets/{ => Scripts}/Voronoi/BeachLine.cs.meta (100%) rename Assets/{ => Scripts}/Voronoi/Tree.cs (100%) rename Assets/{ => Scripts}/Voronoi/Tree.cs.meta (100%) rename Assets/{ => Scripts}/Voronoi/VoronoiGenerator.cs (100%) rename Assets/{ => Scripts}/Voronoi/VoronoiGenerator.cs.meta (100%) diff --git a/Assets/Common/LocationGenerator.cs.meta b/Assets/Common/LocationGenerator.cs.meta deleted file mode 100644 index 28ca7e2..0000000 --- a/Assets/Common/LocationGenerator.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 1a667fae02f346199ad742a83f9d8610 -timeCreated: 1573304795 \ No newline at end of file diff --git a/Assets/Common/MapSite.cs b/Assets/Common/MapSite.cs deleted file mode 100644 index 8f9c359..0000000 --- a/Assets/Common/MapSite.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Assets.Common -{ - [Serializable] - public class MapSite - { - public readonly Metadata Metadata = new Metadata(); - - public MapSite(Point center, IEnumerable boundary) - { - Center = center; - Boundary = boundary; - } - - public Point Center { get; set; } - public IEnumerable Boundary { get; set; } - - [field: NonSerialized] - public Map Map { get; internal set; } - } -} \ No newline at end of file diff --git a/Assets/Editor/CityGeneratorUI.cs b/Assets/Editor/CityGeneratorUI.cs index b5f2e71..2ea0189 100644 --- a/Assets/Editor/CityGeneratorUI.cs +++ b/Assets/Editor/CityGeneratorUI.cs @@ -1,6 +1,5 @@ using System; using Assets; -using Assets.Scripts; using UnityEditor; using UnityEngine; using Random = UnityEngine.Random; @@ -10,31 +9,27 @@ namespace Assets.Editor [CustomEditor(typeof(CityGenerator))] public class CityGeneratorUI : UnityEditor.Editor { - - public override void OnInspectorGUI() { CityGenerator generator = (CityGenerator)target; DrawDefaultInspector(); - if (GUILayout.Button("Reset")) - { - generator.Reset(); - } - - if (GUILayout.Button("Generate")) - { - generator.Reset(); - generator.Generate(); - } - - if (GUILayout.Button("New City")) - { - generator.NewCity(); - } - - +// if (GUILayout.Button("Reset")) +// { +// generator.Reset(); +// } +// +// if (GUILayout.Button("Generate")) +// { +// generator.Reset(); +// generator.Generate(); +// } +// +// if (GUILayout.Button("New City")) +// { +// generator.NewCity(); +// } } } } diff --git a/Assets/Editor/ForestRendererUI.cs b/Assets/Editor/ForestRendererUI.cs index be431c5..c3bb15b 100644 --- a/Assets/Editor/ForestRendererUI.cs +++ b/Assets/Editor/ForestRendererUI.cs @@ -15,7 +15,7 @@ namespace Editor if (GUILayout.Button("Generate")) { - target.Generate(); +// target.Generate(); } } } diff --git a/Assets/Editor/GraphGeneratorUI.cs b/Assets/Editor/GraphGeneratorUI.cs deleted file mode 100644 index 8f717d1..0000000 --- a/Assets/Editor/GraphGeneratorUI.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using Assets; -using UnityEditor; -using UnityEngine; -using Random = UnityEngine.Random; - -namespace Editor -{ - [CustomEditor(typeof (LandmassGenerator))] - public class GraphGeneratorUI : UnityEditor.Editor - { - private string _threshold; - private bool _showInfo = false; - - public override void OnInspectorGUI() - { - LandmassGenerator generator = (LandmassGenerator)target; - - _showInfo = EditorGUILayout.Foldout(_showInfo, "Debug info"); - - if (_showInfo) - { - EditorGUILayout.LabelField($"Stage: ", generator.Stage.ToString()); - EditorGUILayout.LabelField($"Took: ", $"{generator.debug.generationTime:F3}s"); - } - - DrawDefaultInspector(); - - if (GUILayout.Button("Reset")) { - generator.Reset(); - } - - if (GUILayout.Button("Generate Random")) - { - generator.seed = (int)(Random.value * int.MaxValue); - generator.Reset(); - generator.Generate(); - } - - if (GUILayout.Button("Generate")) { - generator.Generate(); - } - - if (GUILayout.Button("Step")) { - generator.Step(); - } - - GUILayout.BeginHorizontal(); - { - _threshold = GUILayout.TextField(_threshold); - - if (GUILayout.Button("Go")) { - try - { - generator.Rewind(float.Parse(_threshold)); - } - catch - { - GUILayout.Label("You should pass valid number."); - } - } - } - GUILayout.EndHorizontal(); - } - - private void OnSceneGUI() - { - LandmassGenerator generator = (LandmassGenerator)target; - - if (generator.VoronoiGenerator != null) - { - var moved = Handles.PositionHandle(generator.transform.position + Vector3.up * (float)generator.VoronoiGenerator.Line.Directrix, Quaternion.identity); - generator.VoronoiGenerator.Line.Directrix = moved.y; - } - } - } -} \ No newline at end of file diff --git a/Assets/Editor/LandmassGeneratorUI.cs b/Assets/Editor/LandmassGeneratorUI.cs new file mode 100644 index 0000000..d1cf12b --- /dev/null +++ b/Assets/Editor/LandmassGeneratorUI.cs @@ -0,0 +1,34 @@ +using System; +using Assets; +using UnityEditor; +using UnityEngine; +using Random = UnityEngine.Random; + +namespace Editor +{ + [CustomEditor(typeof (LandmassGenerator))] + public class LandmassGeneratorUI : UnityEditor.Editor + { + public override void OnInspectorGUI() + { + LandmassGenerator generator = (LandmassGenerator)target; + + DrawDefaultInspector(); + + if (GUILayout.Button("Reset")) { + generator.Reset(); + } + + if (GUILayout.Button("Generate Random")) + { + generator.seed = (int)(Random.value * int.MaxValue); + generator.Reset(); + generator.Generate(); + } + + if (GUILayout.Button("Generate")) { + generator.Generate(); + } + } + } +} \ No newline at end of file diff --git a/Assets/Editor/GraphGeneratorUI.cs.meta b/Assets/Editor/LandmassGeneratorUI.cs.meta similarity index 100% rename from Assets/Editor/GraphGeneratorUI.cs.meta rename to Assets/Editor/LandmassGeneratorUI.cs.meta diff --git a/Assets/Editor/MapRendererUI.cs b/Assets/Editor/MapRendererUI.cs index 40b2198..04f76dc 100644 --- a/Assets/Editor/MapRendererUI.cs +++ b/Assets/Editor/MapRendererUI.cs @@ -15,7 +15,7 @@ namespace Editor if (GUILayout.Button("Generate")) { - target.Generate(); +// target.Generate(); } } } diff --git a/Assets/Scenes/OverworldExample.unity b/Assets/Scenes/OverworldExample.unity index 4709c52..2125922 100644 --- a/Assets/Scenes/OverworldExample.unity +++ b/Assets/Scenes/OverworldExample.unity @@ -120,6 +120,65 @@ NavMeshSettings: debug: m_Flags: 0 m_NavMeshData: {fileID: 0} +--- !u!1 &319467306 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 319467308} + - component: {fileID: 319467307} + m_Layer: 0 + m_Name: Map + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &319467307 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 319467306} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 06dfaa94f8713f12fbe207b61b694c90, type: 3} + m_Name: + m_EditorClassIdentifier: + debug: + enabled: 1 + displayPoints: 1 + displayBoundary: 1 + displayVertices: 1 + displayNeighbours: 0 + displayLabels: 0 + displayEdges: 1 + displayLocations: 1 + displayLocationCells: 1 + displayLocationEdges: 1 + displayLocationPoints: 1 + size: {x: 100, y: 100} + types: [] + radius: 4 + seed: 2040725760 +--- !u!4 &319467308 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 319467306} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &519420028 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/IAnnotationPass.cs b/Assets/Scripts/AnnotationPass/IAnnotationPass.cs similarity index 76% rename from Assets/Scripts/IAnnotationPass.cs rename to Assets/Scripts/AnnotationPass/IAnnotationPass.cs index 0df85e7..10bf7e4 100644 --- a/Assets/Scripts/IAnnotationPass.cs +++ b/Assets/Scripts/AnnotationPass/IAnnotationPass.cs @@ -1,6 +1,6 @@ using Assets.Common; -namespace Assets +namespace Assets.AnnotationPass { public interface IAnnotationPass { diff --git a/Assets/Scripts/AnnotationPass/IAnnotationPass.cs.meta b/Assets/Scripts/AnnotationPass/IAnnotationPass.cs.meta new file mode 100644 index 0000000..e517901 --- /dev/null +++ b/Assets/Scripts/AnnotationPass/IAnnotationPass.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2f8409bbb3b843a7b41dd4ee8f6ea4d2 +timeCreated: 1573389323 \ No newline at end of file diff --git a/Assets/Common/LocationGenerator.cs b/Assets/Scripts/AnnotationPass/LocationPass.cs similarity index 53% rename from Assets/Common/LocationGenerator.cs rename to Assets/Scripts/AnnotationPass/LocationPass.cs index 54c380b..336bce8 100644 --- a/Assets/Common/LocationGenerator.cs +++ b/Assets/Scripts/AnnotationPass/LocationPass.cs @@ -1,47 +1,48 @@ using System; using System.Collections.Generic; using System.Linq; -using Assets.Voronoi; -using Random = System.Random; +using Assets.Common; -namespace Assets.Common +namespace Assets.AnnotationPass { - public class LocationGenerator + public class LocationPass : IAnnotationPass { - private readonly IList _points; - private readonly Graph _sites; + public const string MapLocationsProperty = "Locations"; + public const string SiteLocationProperty = "Location"; + + private IList _points; + private Graph _sites; + private readonly Graph _locations; private readonly List<(int, Location)> _queue = new List<(int, Location)>(); - private readonly Random _random; - - public Graph Sites => _sites; - public Graph Result => _locations; - - public bool Done => _queue.Count == 0; + private Random _random; - public LocationGenerator(List locations, Graph sites, IList points, Random random = null) + public LocationPass(IEnumerable locations, Random random = null) { - _points = points; - _sites = sites.Morph(s => s); _locations = new Graph { Vertices = new List(locations) }; - _random = random ?? new Random(); } - public void SetLocation(int vertex, Location location) + private void Process(int vertex, Location location) { location.AddSite(_sites.Vertices[vertex]); + + _sites.Vertices[vertex].Metadata.SetProperty(SiteLocationProperty, location); foreach (var neighbour in _sites.Neighbours(vertex)) - if (_sites.Vertices[neighbour].Location == null) + { + var site = _sites[neighbour]; + + if (!site.Metadata.HasProperty(SiteLocationProperty)) _queue.Add((neighbour, location)); - else if (location != _sites.Vertices[neighbour].Location) + else if (location != site.Metadata.GetProperty(SiteLocationProperty)) _locations.AddEdge( _locations.Vertices.IndexOf(location), - _locations.Vertices.IndexOf(_sites.Vertices[neighbour].Location) + _locations.Vertices.IndexOf(site.Metadata.GetProperty(SiteLocationProperty)) ); + } } private (int, Location) Dequeue() @@ -53,19 +54,19 @@ namespace Assets.Common _queue.RemoveAt(index); - if (_sites.Vertices[pair.Item1].Location == null) return pair; + if (!_sites[pair.Item1].Metadata.HasProperty(SiteLocationProperty)) return pair; } throw new Exception("No more elements."); } - public void Step() + private void Step() { try { var (vertex, location) = Dequeue(); - SetLocation(vertex, location); + Process(vertex, location); } catch (Exception ex) { @@ -79,7 +80,7 @@ namespace Assets.Common var center = location.Center; var left = location.BoundaryEdges; - location.BoundaryEdges = new List<(int, int)>() { EnsureClockwise(center, left[0]) }; + location.BoundaryEdges = new List<(int, int)> { EnsureClockwise(center, left[0]) }; (int, int) last = location.BoundaryEdges[0]; left.RemoveAt(0); @@ -104,5 +105,31 @@ namespace Assets.Common { return PointUtils.IsClockwise(center, _points[edge.Item1], _points[edge.Item2]) ? (edge.Item2, edge.Item1) : edge; } + + public void Annotate(Map map) + { + _random = new Random(map.Seed); + _sites = map.Sites; + _points = map.Boundaries.Vertices; + + map.Metadata.SetProperty(MapLocationsProperty, _locations); + + var initial = + from location in _locations.Vertices.Skip(1) + select (_random.Next(map.Sites.Vertices.Count), location); + + initial = initial.Concat( + map.Sites.Vertices + .Select((s, i) => (Site: s, Vertex: i)) + .Where(t => t.Site.IsOuter) + .Select(t => (t.Vertex, _locations[0])) + ); + + foreach (var (vertex, location) in initial) + Process(vertex, location); + + while (_queue.Count != 0) + Step(); + } } } \ No newline at end of file diff --git a/Assets/Scripts/AnnotationPass/LocationsPass.cs.meta b/Assets/Scripts/AnnotationPass/LocationPass.cs.meta similarity index 100% rename from Assets/Scripts/AnnotationPass/LocationsPass.cs.meta rename to Assets/Scripts/AnnotationPass/LocationPass.cs.meta diff --git a/Assets/Scripts/AnnotationPass/LocationsPass.cs b/Assets/Scripts/AnnotationPass/LocationsPass.cs deleted file mode 100644 index 273994e..0000000 --- a/Assets/Scripts/AnnotationPass/LocationsPass.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Assets.Common; - -namespace Assets.AnnotationPass -{ - public class LocationsPass : IAnnotationPass - { - public void Annotate(Map map) - { - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/Assets/Scripts/CityGenerator.cs b/Assets/Scripts/CityGenerator.cs index c00091a..8cfb560 100644 --- a/Assets/Scripts/CityGenerator.cs +++ b/Assets/Scripts/CityGenerator.cs @@ -5,433 +5,433 @@ using System.Collections.Generic; using System.Linq; using UnityEngine; -namespace Assets.Scripts -{ - public class PointProximityComparer : IEqualityComparer - { - double _threshold; - - public PointProximityComparer(double threshold = 0.2) - { - _threshold = threshold; - } - - public bool Equals(Point x, Point y) - { - return Point.Dist(x, y) < _threshold; - } - - public int GetHashCode(Point obj) - { - return obj.GetHashCode(); - } - } - - public class CityField - { - public List boundary; - } - - public class City - { - public Graph startGraph; - public List sites; - - public Graph roads = new Graph(); - public Graph fieldBoundaries = new Graph(); - - public List fields = new List(); - - public List<(int, int)> edges; - - public City(Graph startGraph) - { - this.startGraph = startGraph; - - this.sites = new List(); - this.edges = new List<(int, int)>(); - } - - public City(Graph startGraph, List sitesList) : this(startGraph) - { - this.sites = sitesList; - } - - public void AddSite(Site site) - { - sites.Add(site); - FixBoundaryEdges(site); - } - - private void FixBoundaryEdges(Site site) - { - var a = edges; - var b = site.Edges.Select(x => x.Item1 < x.Item2 ? x : (x.Item2, x.Item1)); - - edges = a.Union(b).Except(a.Intersect(b)).ToList(); - } - - public void CreateRoadGraph(IList points) - { - var pointsForRoads = sites.SelectMany(site => site.Vertices.Select(i => (i, points[i])).Append((-1, site.Point))).Distinct().ToList(); - var mapping = pointsForRoads.Select((x, i) => x.Item1 == -1 ? (-1, -1) : (i, x.Item1)).Where(x => x.Item1 != -1).ToDictionary(x => x.Item2, x => x.Item1); - - VoronoiGenerator generator = new VoronoiGenerator(pointsForRoads.Select(x => x.Item2)); - generator.Generate(); - - roads = generator.Delaunay.Morph(s => s.Point); - - fieldBoundaries = new Graph { Vertices = roads.Vertices, Edges = edges.Select(e => (mapping[e.Item1], mapping[e.Item2])) }; - } - } - - [Serializable] - public class GraphGeneratorDebug - { - public bool displayVertices = false; - public bool displayCrossroads = true; - public bool displayEdges = false; - public bool displayCities = true; - public bool displayCityRoads = true; - public bool displayFieldBoundaries = true; - public bool displayWorldRoads = false; - } - - [RequireComponent(typeof(LandmassGenerator))] +//namespace Assets.Scripts +//{ +// public class PointProximityComparer : IEqualityComparer +// { +// double _threshold; +// +// public PointProximityComparer(double threshold = 0.2) +// { +// _threshold = threshold; +// } +// +// public bool Equals(Point x, Point y) +// { +// return Point.Dist(x, y) < _threshold; +// } +// +// public int GetHashCode(Point obj) +// { +// return obj.GetHashCode(); +// } +// } +// +// public class CityField +// { +// public List boundary; +// } +// +// public class City +// { +// public Graph startGraph; +// public List sites; +// +// public Graph roads = new Graph(); +// public Graph fieldBoundaries = new Graph(); +// +// public List fields = new List(); +// +// public List<(int, int)> edges; +// +// public City(Graph startGraph) +// { +// this.startGraph = startGraph; +// +// this.sites = new List(); +// this.edges = new List<(int, int)>(); +// } +// +// public City(Graph startGraph, List sitesList) : this(startGraph) +// { +// this.sites = sitesList; +// } +// +// public void AddSite(Site site) +// { +// sites.Add(site); +// FixBoundaryEdges(site); +// } +// +// private void FixBoundaryEdges(Site site) +// { +// var a = edges; +// var b = site.Edges.Select(x => x.Item1 < x.Item2 ? x : (x.Item2, x.Item1)); +// +// edges = a.Union(b).Except(a.Intersect(b)).ToList(); +// } +// +// public void CreateRoadGraph(IList points) +// { +// var pointsForRoads = sites.SelectMany(site => site.Vertices.Select(i => (i, points[i])).Append((-1, site.Point))).Distinct().ToList(); +// var mapping = pointsForRoads.Select((x, i) => x.Item1 == -1 ? (-1, -1) : (i, x.Item1)).Where(x => x.Item1 != -1).ToDictionary(x => x.Item2, x => x.Item1); +// +// VoronoiGenerator generator = new VoronoiGenerator(pointsForRoads.Select(x => x.Item2)); +// generator.Generate(); +// +// roads = generator.Delaunay.Morph(s => s.Point); +// +// fieldBoundaries = new Graph { Vertices = roads.Vertices, Edges = edges.Select(e => (mapping[e.Item1], mapping[e.Item2])) }; +// } +// } +// +// [Serializable] +// public class GraphGeneratorDebug +// { +// public bool displayVertices = false; +// public bool displayCrossroads = true; +// public bool displayEdges = false; +// public bool displayCities = true; +// public bool displayCityRoads = true; +// public bool displayFieldBoundaries = true; +// public bool displayWorldRoads = false; +// } +// +// [RequireComponent(typeof(LandmassGenerator))] public class CityGenerator : MonoBehaviour { - private System.Random _random; - private Graph _voronoiGraph; - private Graph _locationGraph; - private Graph _basicGraph; - private List verticesForRoads; - private List verticesForCitites; - - public GraphGeneratorDebug debug; - public double minimumAngle = 0.25; - - public List cities = new List(); - - Graph roads = new Graph(); - - Graph mainRoads = new Graph(); - - List CountProbablitityOfCity(List vertices) - { - List probabilities = new List(); - vertices.ForEach(v => probabilities.Add((v % 2 == 0 ? _random.Next(0, 50) : _random.Next(50, 100)))); - return probabilities; - } - - List LocateCities() - { - // var verticesForCitites = CountProbablitityOfCity(ChoosePoints(20)); - // verticesForCitites.Sort(); - // return verticesForCitites.GetRange(0, 10); - return ChoosePoints(20); - } - - public bool IsPointInsideCity(City city, Point point) - { - return city.sites.Any(s => PointUtils.IsPointInside(point, s.Vertices.Select(i => _voronoiGraph[i]).ToArray())); - } - - City CreateCity(int vertex, int size) - { - City newCity = new City(_basicGraph); - var site = _basicGraph.Vertices[vertex]; - var sites = new List() { site }; - var location = site.Location; - - for (int i = 0; i < size - 1; i++) - { - location = site.Location; - var neighbours = _basicGraph.Neighbours(site.Index).Select(j => _basicGraph.Vertices[j]).Where(s => s.Location == location).ToList(); - site = neighbours[_random.Next(neighbours.Count)]; - sites.Add(site); - } - - foreach (var s in sites.Distinct()) - { - newCity.AddSite(s); - } - - newCity.CreateRoadGraph(_voronoiGraph.Vertices); - - var edges = newCity.roads.Edges.ToList(); - foreach (var (a, b) in edges) - { - var (va, vb) = (newCity.roads[a], newCity.roads[b]); - var center = (va + vb) / 2; - - if (!IsPointInsideCity(newCity, center)) - newCity.roads.DeleteEdge(a, b); - } - - ConnectPointsIntoRoads(newCity); - FixRoadsDensity(newCity, minimumAngle); - CreateFieldBoundaries(newCity); - - return newCity; - } - - List ChoosePoints(int number) - { - var vertices = new List(); - for (int i = 0; i < number; i++) - { - var randomLocation = _locationGraph.Vertices[_random.Next(1, _locationGraph.Vertices.Count())]; - var count = randomLocation.Sites.Count(); - var randomPoint = randomLocation.Sites[_random.Next(0, count)]; - vertices.Add(randomPoint.Index); - } - return vertices; - } - - void ConnectPointsIntoRoads(City city) - { - var original = city.roads.Morph(s => s, e => Point.Dist(city.roads[e.Item1], city.roads[e.Item2])); - - //1.Sort all the edges in non - decreasing order of their weight. - //2.Pick the smallest edge.Check if it forms a cycle with the spanning tree formed so far. If cycle is not formed, include this edge.Else, discard it. - //3.Repeat step#2 until there are (V-1) edges in the spanning tree. - - var edges = original.Edges.OrderByDescending(e => original.GetEdgeData(e)); - - Graph roads = new Graph() { Vertices = city.roads.Vertices }; - - foreach (var edge in original.Edges) - { - roads.AddEdge(edge.Item1, edge.Item2); - - if (Graph.HasCycle(roads)) - roads.DeleteEdge(edge.Item1, edge.Item2); - if (roads.Edges.Count() == roads.Vertices.Count() - 1) - break; - } - - city.roads = roads; - } - - private void CreateFieldBoundaries(City city) - { - foreach (var (a, b) in city.roads.Edges) - city.fieldBoundaries.AddEdge(a, b); - - var deadEnds = city.fieldBoundaries.Vertices.Select((_, i) => i).Where(i => city.fieldBoundaries.Neighbours(i).Count() == 1); - - foreach (var deadEnd in deadEnds) - { - var neighbour = city.fieldBoundaries.Neighbours(deadEnd).First(); - var closest = city.fieldBoundaries.Vertices - .Select((_, i) => i) - .OrderBy(i => Point.Dist(city.fieldBoundaries[i], city.fieldBoundaries[deadEnd])) - .Skip(1) - .First(c => c != neighbour); - - city.fieldBoundaries.AddEdge(deadEnd, closest); - city.roads.AddEdge(deadEnd, closest); - } - } - - - private void FixRoadsDensity(City city, double angle = 0.25f) - { - // dla każdego punktu w grafie dróg - // chyba że ma 2 to pomiń? - // wyznacz punkt 0 - // oblicz odległości kątowe do wszystkich punktów - // posortuj je - // między wszystkimiu parami oblicz kąt - // potem według jakiegoś parametru usuń te, które są za bliskie - - - for (int i = 0; i < city.roads.Vertices.Count(); i++) - { - var p = city.roads[i]; - if (city.roads.Neighbours(i).Count() <= 2) - continue; - - var reference = new Point(p.x, p.y + 30); - - var orderedNeighours = city.roads.Neighbours(i) - .Select(n => (Vertex: n, Point: city.roads[n])) - .Select(x => (Vertex: x.Vertex, Angle: PointUtils.AngleBetween(p, reference, x.Point))) - .OrderBy(x => x.Angle) - .Select(x => x.Vertex); - - foreach (var (a, b) in orderedNeighours.RotateRight(1).Zip(orderedNeighours, (a, b) => (a, b))) - { - if( PointUtils.AngleBetween(p, city.roads[a], city.roads[b]) < angle) - { - city.roads.DeleteEdge(i, a); - } - } - } - } - - - - - - - void CreateWorldRoadGraph() - { - roads.Vertices = verticesForCitites.Select(i => _basicGraph.Vertices[i]).ToList(); - - VoronoiGenerator generator = new VoronoiGenerator(roads.Vertices.Select(s => s.Point).ToList()); - generator.Generate(); - - roads.Edges = generator.Delaunay.Edges; - } - - - void AddLanesToRoads() - { - // ergo dodaj randomowe połączenia xd - } - - - - - // UI Methods - - - public void Start() - { - Reset(); - } - - public void Reset() - { - - var graphGenerator = GetComponent(); - _random = new System.Random(graphGenerator.seed); - cities = new List(); - } - - public void NewCity() - { - cities.Add(CreateCity(LocateCities()[_random.Next(0, 10)], _random.Next(0, 10))); - } - - public void Generate() - { - var graphGenerator = GetComponent(); - graphGenerator.Generate(); - _basicGraph = graphGenerator.VoronoiGenerator.Delaunay.Morph(l => l); - _voronoiGraph = graphGenerator.VoronoiGenerator.Voronoi; - _locationGraph = graphGenerator.LocationGenerator.Result; - - verticesForCitites = LocateCities(); - foreach (var index in verticesForCitites) - { - cities.Add(CreateCity(index, _random.Next(0, 10))); - } - - CreateWorldRoadGraph(); - mainRoads = roads.Morph(s => s.Point); - - } - - private void DisplayGraphVertices(Graph graph) - { - var vertices = graph.Vertices.Select(p => p.ToVector3()); - var offset = Vector3.right; - - foreach (var (v, i) in vertices.Select((x, i) => (x, i))) - { - Gizmos.DrawSphere(v, 1); - } - } - - private void DisplayGraphCrossroads(Graph graph, List vertices) - { - //foreach (var v in vertices.Select(i => graph.Vertices[i].ToVector3())) - //{ - // Gizmos.DrawSphere(v, 1); - //} - } - - - private void DisplayGraphCities(List cities) - { - foreach (City city in cities) - { - Gizmos.color = Color.magenta; - foreach (var (a, b) in city.edges) - { - Gizmos.DrawLine(_voronoiGraph.Vertices[a].ToVector3(), _voronoiGraph.Vertices[b].ToVector3()); - } - - foreach (var a in city.sites) - Gizmos.DrawSphere(a.Point.ToVector3(), 1); - } - } - - - private void DisplayGraphEdges(Graph graph) - { - var edges = graph.Edges - .Select(edge => (graph.Vertices[edge.Item1], graph.Vertices[edge.Item2])) - .Select(edge => (edge.Item1.ToVector3(), edge.Item2.ToVector3())); - - foreach (var (s, e) in edges) Gizmos.DrawLine(s, e); - } - - private void OnDrawGizmos() - { - - if (debug.displayVertices) - { - Gizmos.color = Color.white; - DisplayGraphVertices(_basicGraph.Morph(l => l.Point)); - } - - if (debug.displayEdges) - { - Gizmos.color = Color.white; - DisplayGraphEdges(_basicGraph.Morph(l => l.Point)); - } - - if (debug.displayCrossroads) - { - Gizmos.color = Color.magenta; - DisplayGraphCrossroads(_basicGraph.Morph(l => l.Point), verticesForRoads); - } - - if (debug.displayCities) - { - Gizmos.color = Color.magenta; - DisplayGraphCities(cities); - } - - if (debug.displayFieldBoundaries) - { - Gizmos.color = Color.white; - - foreach (var city in cities) - DisplayGraphEdges(city.fieldBoundaries); - } - - if (debug.displayCityRoads) - { - Gizmos.color = Color.green; - - foreach (var city in cities) - { - DisplayGraphEdges(city.roads); - DisplayGraphVertices(city.roads); - } - } - - - if (debug.displayWorldRoads) - { - // Gizmos.color = new Color(0.254f, 0.127f, 0.156f); - Gizmos.color = Color.blue; - DisplayGraphEdges(mainRoads); - } - } +// private System.Random _random; +// private Graph _voronoiGraph; +// private Graph _locationGraph; +// private Graph _basicGraph; +// private List verticesForRoads; +// private List verticesForCitites; +// +// public GraphGeneratorDebug debug; +// public double minimumAngle = 0.25; +// +// public List cities = new List(); +// +// Graph roads = new Graph(); +// +// Graph mainRoads = new Graph(); +// +// List CountProbablitityOfCity(List vertices) +// { +// List probabilities = new List(); +// vertices.ForEach(v => probabilities.Add((v % 2 == 0 ? _random.Next(0, 50) : _random.Next(50, 100)))); +// return probabilities; +// } +// +// List LocateCities() +// { +// // var verticesForCitites = CountProbablitityOfCity(ChoosePoints(20)); +// // verticesForCitites.Sort(); +// // return verticesForCitites.GetRange(0, 10); +// return ChoosePoints(20); +// } +// +// public bool IsPointInsideCity(City city, Point point) +// { +// return city.sites.Any(s => PointUtils.IsPointInside(point, s.Vertices.Select(i => _voronoiGraph[i]).ToArray())); +// } +// +// City CreateCity(int vertex, int size) +// { +// City newCity = new City(_basicGraph); +// var site = _basicGraph.Vertices[vertex]; +// var sites = new List() { site }; +// var location = site.Location; +// +// for (int i = 0; i < size - 1; i++) +// { +// location = site.Location; +// var neighbours = _basicGraph.Neighbours(site.Index).Select(j => _basicGraph.Vertices[j]).Where(s => s.Location == location).ToList(); +// site = neighbours[_random.Next(neighbours.Count)]; +// sites.Add(site); +// } +// +// foreach (var s in sites.Distinct()) +// { +// newCity.AddSite(s); +// } +// +// newCity.CreateRoadGraph(_voronoiGraph.Vertices); +// +// var edges = newCity.roads.Edges.ToList(); +// foreach (var (a, b) in edges) +// { +// var (va, vb) = (newCity.roads[a], newCity.roads[b]); +// var center = (va + vb) / 2; +// +// if (!IsPointInsideCity(newCity, center)) +// newCity.roads.DeleteEdge(a, b); +// } +// +// ConnectPointsIntoRoads(newCity); +// FixRoadsDensity(newCity, minimumAngle); +// CreateFieldBoundaries(newCity); +// +// return newCity; +// } +// +// List ChoosePoints(int number) +// { +// var vertices = new List(); +// for (int i = 0; i < number; i++) +// { +// var randomLocation = _locationGraph.Vertices[_random.Next(1, _locationGraph.Vertices.Count())]; +// var count = randomLocation.Sites.Count(); +// var randomPoint = randomLocation.Sites[_random.Next(0, count)]; +// vertices.Add(randomPoint.Index); +// } +// return vertices; +// } +// +// void ConnectPointsIntoRoads(City city) +// { +// var original = city.roads.Morph(s => s, e => Point.Dist(city.roads[e.Item1], city.roads[e.Item2])); +// +// //1.Sort all the edges in non - decreasing order of their weight. +// //2.Pick the smallest edge.Check if it forms a cycle with the spanning tree formed so far. If cycle is not formed, include this edge.Else, discard it. +// //3.Repeat step#2 until there are (V-1) edges in the spanning tree. +// +// var edges = original.Edges.OrderByDescending(e => original.GetEdgeData(e)); +// +// Graph roads = new Graph() { Vertices = city.roads.Vertices }; +// +// foreach (var edge in original.Edges) +// { +// roads.AddEdge(edge.Item1, edge.Item2); +// +// if (Graph.HasCycle(roads)) +// roads.DeleteEdge(edge.Item1, edge.Item2); +// if (roads.Edges.Count() == roads.Vertices.Count() - 1) +// break; +// } +// +// city.roads = roads; +// } +// +// private void CreateFieldBoundaries(City city) +// { +// foreach (var (a, b) in city.roads.Edges) +// city.fieldBoundaries.AddEdge(a, b); +// +// var deadEnds = city.fieldBoundaries.Vertices.Select((_, i) => i).Where(i => city.fieldBoundaries.Neighbours(i).Count() == 1); +// +// foreach (var deadEnd in deadEnds) +// { +// var neighbour = city.fieldBoundaries.Neighbours(deadEnd).First(); +// var closest = city.fieldBoundaries.Vertices +// .Select((_, i) => i) +// .OrderBy(i => Point.Dist(city.fieldBoundaries[i], city.fieldBoundaries[deadEnd])) +// .Skip(1) +// .First(c => c != neighbour); +// +// city.fieldBoundaries.AddEdge(deadEnd, closest); +// city.roads.AddEdge(deadEnd, closest); +// } +// } +// +// +// private void FixRoadsDensity(City city, double angle = 0.25f) +// { +// // dla każdego punktu w grafie dróg +// // chyba że ma 2 to pomiń? +// // wyznacz punkt 0 +// // oblicz odległości kątowe do wszystkich punktów +// // posortuj je +// // między wszystkimiu parami oblicz kąt +// // potem według jakiegoś parametru usuń te, które są za bliskie +// +// +// for (int i = 0; i < city.roads.Vertices.Count(); i++) +// { +// var p = city.roads[i]; +// if (city.roads.Neighbours(i).Count() <= 2) +// continue; +// +// var reference = new Point(p.x, p.y + 30); +// +// var orderedNeighours = city.roads.Neighbours(i) +// .Select(n => (Vertex: n, Point: city.roads[n])) +// .Select(x => (Vertex: x.Vertex, Angle: PointUtils.AngleBetween(p, reference, x.Point))) +// .OrderBy(x => x.Angle) +// .Select(x => x.Vertex); +// +// foreach (var (a, b) in orderedNeighours.RotateRight(1).Zip(orderedNeighours, (a, b) => (a, b))) +// { +// if( PointUtils.AngleBetween(p, city.roads[a], city.roads[b]) < angle) +// { +// city.roads.DeleteEdge(i, a); +// } +// } +// } +// } +// +// +// +// +// +// +// void CreateWorldRoadGraph() +// { +// roads.Vertices = verticesForCitites.Select(i => _basicGraph.Vertices[i]).ToList(); +// +// VoronoiGenerator generator = new VoronoiGenerator(roads.Vertices.Select(s => s.Point).ToList()); +// generator.Generate(); +// +// roads.Edges = generator.Delaunay.Edges; +// } +// +// +// void AddLanesToRoads() +// { +// // ergo dodaj randomowe połączenia xd +// } +// +// +// +// +// // UI Methods +// +// +// public void Start() +// { +// Reset(); +// } +// +// public void Reset() +// { +// +// var graphGenerator = GetComponent(); +// _random = new System.Random(graphGenerator.seed); +// cities = new List(); +// } +// +// public void NewCity() +// { +// cities.Add(CreateCity(LocateCities()[_random.Next(0, 10)], _random.Next(0, 10))); +// } +// +// public void Generate() +// { +// var graphGenerator = GetComponent(); +// graphGenerator.Generate(); +// _basicGraph = graphGenerator.VoronoiGenerator.Delaunay.Morph(l => l); +// _voronoiGraph = graphGenerator.VoronoiGenerator.Voronoi; +// _locationGraph = graphGenerator.LocationGenerator.Result; +// +// verticesForCitites = LocateCities(); +// foreach (var index in verticesForCitites) +// { +// cities.Add(CreateCity(index, _random.Next(0, 10))); +// } +// +// CreateWorldRoadGraph(); +// mainRoads = roads.Morph(s => s.Point); +// +// } +// +// private void DisplayGraphVertices(Graph graph) +// { +// var vertices = graph.Vertices.Select(p => p.ToVector3()); +// var offset = Vector3.right; +// +// foreach (var (v, i) in vertices.Select((x, i) => (x, i))) +// { +// Gizmos.DrawSphere(v, 1); +// } +// } +// +// private void DisplayGraphCrossroads(Graph graph, List vertices) +// { +// //foreach (var v in vertices.Select(i => graph.Vertices[i].ToVector3())) +// //{ +// // Gizmos.DrawSphere(v, 1); +// //} +// } +// +// +// private void DisplayGraphCities(List cities) +// { +// foreach (City city in cities) +// { +// Gizmos.color = Color.magenta; +// foreach (var (a, b) in city.edges) +// { +// Gizmos.DrawLine(_voronoiGraph.Vertices[a].ToVector3(), _voronoiGraph.Vertices[b].ToVector3()); +// } +// +// foreach (var a in city.sites) +// Gizmos.DrawSphere(a.Point.ToVector3(), 1); +// } +// } +// +// +// private void DisplayGraphEdges(Graph graph) +// { +// var edges = graph.Edges +// .Select(edge => (graph.Vertices[edge.Item1], graph.Vertices[edge.Item2])) +// .Select(edge => (edge.Item1.ToVector3(), edge.Item2.ToVector3())); +// +// foreach (var (s, e) in edges) Gizmos.DrawLine(s, e); +// } +// +// private void OnDrawGizmos() +// { +// +// if (debug.displayVertices) +// { +// Gizmos.color = Color.white; +// DisplayGraphVertices(_basicGraph.Morph(l => l.Point)); +// } +// +// if (debug.displayEdges) +// { +// Gizmos.color = Color.white; +// DisplayGraphEdges(_basicGraph.Morph(l => l.Point)); +// } +// +// if (debug.displayCrossroads) +// { +// Gizmos.color = Color.magenta; +// DisplayGraphCrossroads(_basicGraph.Morph(l => l.Point), verticesForRoads); +// } +// +// if (debug.displayCities) +// { +// Gizmos.color = Color.magenta; +// DisplayGraphCities(cities); +// } +// +// if (debug.displayFieldBoundaries) +// { +// Gizmos.color = Color.white; +// +// foreach (var city in cities) +// DisplayGraphEdges(city.fieldBoundaries); +// } +// +// if (debug.displayCityRoads) +// { +// Gizmos.color = Color.green; +// +// foreach (var city in cities) +// { +// DisplayGraphEdges(city.roads); +// DisplayGraphVertices(city.roads); +// } +// } +// +// +// if (debug.displayWorldRoads) +// { +// // Gizmos.color = new Color(0.254f, 0.127f, 0.156f); +// Gizmos.color = Color.blue; +// DisplayGraphEdges(mainRoads); +// } +// } } -} \ No newline at end of file +//} \ No newline at end of file diff --git a/Assets/Common.meta b/Assets/Scripts/Common.meta similarity index 100% rename from Assets/Common.meta rename to Assets/Scripts/Common.meta diff --git a/Assets/Common/Bounding.cs b/Assets/Scripts/Common/Bounding.cs similarity index 100% rename from Assets/Common/Bounding.cs rename to Assets/Scripts/Common/Bounding.cs diff --git a/Assets/Common/Bounding.cs.meta b/Assets/Scripts/Common/Bounding.cs.meta similarity index 100% rename from Assets/Common/Bounding.cs.meta rename to Assets/Scripts/Common/Bounding.cs.meta diff --git a/Assets/Common/Extensions.cs b/Assets/Scripts/Common/Extensions.cs similarity index 100% rename from Assets/Common/Extensions.cs rename to Assets/Scripts/Common/Extensions.cs diff --git a/Assets/Common/Extensions.cs.meta b/Assets/Scripts/Common/Extensions.cs.meta similarity index 100% rename from Assets/Common/Extensions.cs.meta rename to Assets/Scripts/Common/Extensions.cs.meta diff --git a/Assets/Common/Graph.cs b/Assets/Scripts/Common/Graph.cs similarity index 100% rename from Assets/Common/Graph.cs rename to Assets/Scripts/Common/Graph.cs diff --git a/Assets/Common/Graph.cs.meta b/Assets/Scripts/Common/Graph.cs.meta similarity index 100% rename from Assets/Common/Graph.cs.meta rename to Assets/Scripts/Common/Graph.cs.meta diff --git a/Assets/Common/Location.cs b/Assets/Scripts/Common/Location.cs similarity index 82% rename from Assets/Common/Location.cs rename to Assets/Scripts/Common/Location.cs index 8f6e747..b728cd4 100644 --- a/Assets/Common/Location.cs +++ b/Assets/Scripts/Common/Location.cs @@ -6,29 +6,28 @@ namespace Assets.Common { public class Location { - public List Sites = new List(); + public List Sites = new List(); - public IEnumerable Points => Sites.SelectMany(site => site.Vertices); + public IEnumerable Points => Sites.SelectMany(site => site.Boundary); public IEnumerable BoundaryPoints => BoundaryEdges.SelectMany(edge => new [] { edge.Item1, edge.Item2 }).Distinct(); public IEnumerable InsidePoints => Points.Except(BoundaryPoints); public List<(int, int)> BoundaryEdges = new List<(int, int)>(); - public Point Center => PointUtils.Mean(Sites.Select(s => s.Point)); + public Point Center => PointUtils.Mean(Sites.Select(s => s.Center)); public LocationType Type; public List DetailedEdge = new List(); - public void AddSite(Site site) + public void AddSite(MapSite site) { - site.Location = this; Sites.Add(site); FixBoundaryEdges(site); } - private void FixBoundaryEdges(Site site) + private void FixBoundaryEdges(MapSite site) { var a = BoundaryEdges; var b = site.Edges.Select(x => x.Item1 < x.Item2 ? x : (x.Item2, x.Item1)); diff --git a/Assets/Common/Location.cs.meta b/Assets/Scripts/Common/Location.cs.meta similarity index 100% rename from Assets/Common/Location.cs.meta rename to Assets/Scripts/Common/Location.cs.meta diff --git a/Assets/Common/LocationSite.cs b/Assets/Scripts/Common/LocationSite.cs similarity index 100% rename from Assets/Common/LocationSite.cs rename to Assets/Scripts/Common/LocationSite.cs diff --git a/Assets/Common/LocationSite.cs.meta b/Assets/Scripts/Common/LocationSite.cs.meta similarity index 100% rename from Assets/Common/LocationSite.cs.meta rename to Assets/Scripts/Common/LocationSite.cs.meta diff --git a/Assets/Common/Map.cs b/Assets/Scripts/Common/Map.cs similarity index 96% rename from Assets/Common/Map.cs rename to Assets/Scripts/Common/Map.cs index 85a8004..fd2ce1d 100644 --- a/Assets/Common/Map.cs +++ b/Assets/Scripts/Common/Map.cs @@ -6,6 +6,7 @@ namespace Assets.Common [Serializable] public class Map { + [SerializeField] private Graph _sites = new Graph(); public int Seed { get; set; } diff --git a/Assets/Common/Map.cs.meta b/Assets/Scripts/Common/Map.cs.meta similarity index 100% rename from Assets/Common/Map.cs.meta rename to Assets/Scripts/Common/Map.cs.meta diff --git a/Assets/Scripts/Common/MapSite.cs b/Assets/Scripts/Common/MapSite.cs new file mode 100644 index 0000000..6105d66 --- /dev/null +++ b/Assets/Scripts/Common/MapSite.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace Assets.Common +{ + [Serializable] + public class MapSite + { + public readonly Metadata Metadata = new Metadata(); + + public MapSite(Point center, IEnumerable boundary) + { + Center = center; + Boundary = boundary; + } + + public Point Center { get; set; } + public bool IsOuter { get; set; } = false; + public IEnumerable Boundary { get; set; } +// public IEnumerable<(int, int)> Edges => Boundary.Append(Boundary.First()).Zip(Boundary.RotateRight(), (a, b) => (a, b)); + public IEnumerable<(int, int)> Edges { get; set; } + + [field: NonSerialized] + public Map Map { get; internal set; } + } +} \ No newline at end of file diff --git a/Assets/Common/MapSite.cs.meta b/Assets/Scripts/Common/MapSite.cs.meta similarity index 100% rename from Assets/Common/MapSite.cs.meta rename to Assets/Scripts/Common/MapSite.cs.meta diff --git a/Assets/Common/Metadata.cs b/Assets/Scripts/Common/Metadata.cs similarity index 100% rename from Assets/Common/Metadata.cs rename to Assets/Scripts/Common/Metadata.cs diff --git a/Assets/Common/Metadata.cs.meta b/Assets/Scripts/Common/Metadata.cs.meta similarity index 100% rename from Assets/Common/Metadata.cs.meta rename to Assets/Scripts/Common/Metadata.cs.meta diff --git a/Assets/Common/Point.cs b/Assets/Scripts/Common/Point.cs similarity index 100% rename from Assets/Common/Point.cs rename to Assets/Scripts/Common/Point.cs diff --git a/Assets/Common/Point.cs.meta b/Assets/Scripts/Common/Point.cs.meta similarity index 100% rename from Assets/Common/Point.cs.meta rename to Assets/Scripts/Common/Point.cs.meta diff --git a/Assets/Common/PointUtils.cs b/Assets/Scripts/Common/PointUtils.cs similarity index 100% rename from Assets/Common/PointUtils.cs rename to Assets/Scripts/Common/PointUtils.cs diff --git a/Assets/Common/PointUtils.cs.meta b/Assets/Scripts/Common/PointUtils.cs.meta similarity index 100% rename from Assets/Common/PointUtils.cs.meta rename to Assets/Scripts/Common/PointUtils.cs.meta diff --git a/Assets/Scripts/ForestGenerator.cs b/Assets/Scripts/ForestGenerator.cs index 8b8ec09..3475e5f 100644 --- a/Assets/Scripts/ForestGenerator.cs +++ b/Assets/Scripts/ForestGenerator.cs @@ -6,89 +6,89 @@ using Assets.Voronoi; using UnityEngine; using Random = System.Random; -namespace Assets -{ - [RequireComponent(typeof(MeshFilter))] - [RequireComponent(typeof(MeshRenderer))] - [RequireComponent(typeof(LandmassGenerator))] +//namespace Assets +//{ +// [RequireComponent(typeof(MeshFilter))] +// [RequireComponent(typeof(MeshRenderer))] +// [RequireComponent(typeof(LandmassGenerator))] public class ForestGenerator : MonoBehaviour { - public GameObject[] trees; - [Range(1, 15)] - public float radius = 3.0f; - public GameObject forest; - - private Random _random = new Random(); - private List _sites; - - private LandmassGenerator Generator => GetComponent(); - - public void Generate() - { - Cleanup(); - - Generator.EnsureGenerated(); - - FindForestSites(); - PlaceTrees(); - - _random = new Random(Generator.seed); - } - - private void PlaceTrees() - { - foreach (Site site in _sites) - { - var sampler = new PoissonDiskSampler(radius) { Generator = _random }; - - Bounding bounding = - BoundingTools.GetBounding(site.Vertices.Select(i => Generator.BoundariesGraph.Vertices[i])); - - var offset = Vector3.up * site.Location.Type.height; - var points = sampler.Generate((float)bounding.Width, (float)bounding.Height); - - foreach (var point in points.Select(point => point + bounding.Min).Where(point => IsPointInSite(site, point))) - PlaceRandomTree(point.ToVector3() + offset); - } - } - - public void Cleanup() - { - var destroy = new List(); - - foreach (var child in forest.transform) - if (child is Transform t) - destroy.Add(t.gameObject); - - foreach (var @object in destroy) - DestroyImmediate(@object); - } - - private void FindForestSites() - { - _sites = new List(); - - foreach (var location in Generator.LocationGraph.Vertices.Skip(1)) - { - var count = _random.Next(10); - - for (int i = 0; i < count; i++) - _sites.Add(location.Sites[_random.Next(location.Sites.Count)]); - } - } - - private void PlaceRandomTree(Vector3 pos) - { - GameObject tree = Instantiate(trees[_random.Next(trees.Length)], forest.transform); - - tree.transform.position = pos - Vector3.down * 0.2f; - } - - private bool IsPointInSite(Site site, Point point) - { - var polygon = site.Vertices.Select(i => Generator.BoundariesGraph[i]).ToArray(); - - return PointUtils.IsPointInside(point, polygon); - } +// public GameObject[] trees; +// [Range(1, 15)] +// public float radius = 3.0f; +// public GameObject forest; +// +// private Random _random = new Random(); +// private List _sites; +// +// private LandmassGenerator Generator => GetComponent(); +// +// public void Generate() +// { +// Cleanup(); +// +// Generator.EnsureGenerated(); +// +// FindForestSites(); +// PlaceTrees(); +// +// _random = new Random(Generator.seed); +// } +// +// private void PlaceTrees() +// { +// foreach (Site site in _sites) +// { +// var sampler = new PoissonDiskSampler(radius) { Generator = _random }; +// +// Bounding bounding = +// BoundingTools.GetBounding(site.Vertices.Select(i => Generator.BoundariesGraph.Vertices[i])); +// +// var offset = Vector3.up * site.Location.Type.height; +// var points = sampler.Generate((float)bounding.Width, (float)bounding.Height); +// +// foreach (var point in points.Select(point => point + bounding.Min).Where(point => IsPointInSite(site, point))) +// PlaceRandomTree(point.ToVector3() + offset); +// } +// } +// +// public void Cleanup() +// { +// var destroy = new List(); +// +// foreach (var child in forest.transform) +// if (child is Transform t) +// destroy.Add(t.gameObject); +// +// foreach (var @object in destroy) +// DestroyImmediate(@object); +// } +// +// private void FindForestSites() +// { +// _sites = new List(); +// +// foreach (var location in Generator.LocationGraph.Vertices.Skip(1)) +// { +// var count = _random.Next(10); +// +// for (int i = 0; i < count; i++) +// _sites.Add(location.Sites[_random.Next(location.Sites.Count)]); +// } +// } +// +// private void PlaceRandomTree(Vector3 pos) +// { +// GameObject tree = Instantiate(trees[_random.Next(trees.Length)], forest.transform); +// +// tree.transform.position = pos - Vector3.down * 0.2f; +// } +// +// private bool IsPointInSite(Site site, Point point) +// { +// var polygon = site.Vertices.Select(i => Generator.BoundariesGraph[i]).ToArray(); +// +// return PointUtils.IsPointInside(point, polygon); +// } } -} \ No newline at end of file +//} \ No newline at end of file diff --git a/Assets/Scripts/GridGenerator.meta b/Assets/Scripts/GridGenerator.meta new file mode 100644 index 0000000..0d5354d --- /dev/null +++ b/Assets/Scripts/GridGenerator.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 71568e6595e041ef95f62998c310450e +timeCreated: 1573389260 \ No newline at end of file diff --git a/Assets/Scripts/IGridGenerator.cs b/Assets/Scripts/GridGenerator/IGridGenerator.cs similarity index 80% rename from Assets/Scripts/IGridGenerator.cs rename to Assets/Scripts/GridGenerator/IGridGenerator.cs index 63621ef..b8a5a7d 100644 --- a/Assets/Scripts/IGridGenerator.cs +++ b/Assets/Scripts/GridGenerator/IGridGenerator.cs @@ -1,6 +1,6 @@ using Assets.Common; -namespace Assets +namespace Assets.GridGenerator { public interface IGridGenerator { diff --git a/Assets/Scripts/GridGenerator/IGridGenerator.cs.meta b/Assets/Scripts/GridGenerator/IGridGenerator.cs.meta new file mode 100644 index 0000000..f607e37 --- /dev/null +++ b/Assets/Scripts/GridGenerator/IGridGenerator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7d6304beabfe4be58588b56d52f262fe +timeCreated: 1573389342 \ No newline at end of file diff --git a/Assets/Scripts/VoronoiGridGenerator.cs b/Assets/Scripts/GridGenerator/VoronoiGridGenerator.cs similarity index 64% rename from Assets/Scripts/VoronoiGridGenerator.cs rename to Assets/Scripts/GridGenerator/VoronoiGridGenerator.cs index 22ea4a6..179165c 100644 --- a/Assets/Scripts/VoronoiGridGenerator.cs +++ b/Assets/Scripts/GridGenerator/VoronoiGridGenerator.cs @@ -1,10 +1,10 @@ -using System; using System.Collections.Generic; +using System.Linq; using Assets.Common; using Assets.PointDistribution; using Assets.Voronoi; -namespace Assets +namespace Assets.GridGenerator { public class VoronoiGridGenerator : IGridGenerator { @@ -31,13 +31,16 @@ namespace Assets result.Boundaries = (Graph)generator.Voronoi.Clone(); result.Sites = generator.Delaunay.Morph(s => { - var site = new MapSite(s.Point, new List()); + var site = new MapSite(s.Point, ClockwiseVertices(generator.Voronoi, s.Vertices)) { Edges = s.Edges }; site.Metadata.SetProperty(VoronoiSiteProperty, s); return site; }); + foreach (var site in result.Sites.Vertices.Take(4)) + site.IsOuter = true; + return result; } @@ -55,5 +58,19 @@ namespace Assets return points; } + + private IEnumerable ClockwiseVertices(Graph graph, IEnumerable vertices) + { + var enumerated = vertices as int[] ?? vertices.ToArray(); + + var center = PointUtils.Mean(enumerated.Select(n => graph[n])); + var reference = center + new Point(0, 1); + + return enumerated + .Select(n => (Vertex: n, Point: graph[n])) + .Select(x => (Vertex: x.Vertex, Angle: PointUtils.AngleBetween(center, reference, x.Point))) + .OrderBy(x => x.Angle) + .Select(x => x.Vertex); + } } } \ No newline at end of file diff --git a/Assets/Scripts/VoronoiGridGenerator.cs.meta b/Assets/Scripts/GridGenerator/VoronoiGridGenerator.cs.meta similarity index 100% rename from Assets/Scripts/VoronoiGridGenerator.cs.meta rename to Assets/Scripts/GridGenerator/VoronoiGridGenerator.cs.meta diff --git a/Assets/Scripts/IAnnotationPass.cs.meta b/Assets/Scripts/IAnnotationPass.cs.meta deleted file mode 100644 index baf5e33..0000000 --- a/Assets/Scripts/IAnnotationPass.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: f29f3a8ef63c47e4acb0f0fe114e7cda -timeCreated: 1573323034 \ No newline at end of file diff --git a/Assets/Scripts/IGridGenerator.cs.meta b/Assets/Scripts/IGridGenerator.cs.meta deleted file mode 100644 index 14ca5e5..0000000 --- a/Assets/Scripts/IGridGenerator.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: bbbede9954254e208a6e9701f51a6d9b -timeCreated: 1573323655 \ No newline at end of file diff --git a/Assets/Scripts/LandmassGenerator.cs b/Assets/Scripts/LandmassGenerator.cs index f040606..a38a117 100644 --- a/Assets/Scripts/LandmassGenerator.cs +++ b/Assets/Scripts/LandmassGenerator.cs @@ -1,12 +1,15 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Assets.AnnotationPass; using Assets.Common; +using Assets.GridGenerator; using Assets.PointDistribution; -using Assets.Voronoi; -using UnityEditor; +using Assets.Utils; using UnityEngine; +using UnityEngine.Serialization; using Random = System.Random; namespace Assets @@ -15,14 +18,12 @@ namespace Assets public class GraphGeneratorDebug { public bool enabled = true; + public bool displayPoints = true; public bool displayBoundary = 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; public bool displayLocations = true; public bool displayLocationCells = true; @@ -40,291 +41,151 @@ namespace Assets public float height = 0.0f; } - public enum GenerationStage - { - Start, - Voronoi, - Location, - Done - }; - [ExecuteInEditMode] public class LandmassGenerator : MonoBehaviour { - private IPointDistribution _sampler; - private Random _random; + [NonSerialized] public Map Map; + [NonSerialized] public Thread GenerationThread; - private VoronoiGenerator _voronoiGenerator; - private LocationGenerator _locationGenerator; + public GraphGeneratorDebug debug; - private List _points = new List(); - private List _locations = new List(); - private Graph<(Point, Location)> _locationGraph; - + public Vector2 size = new Vector2(); public List types = new List(); - - public Graph SitesGraph => _voronoiGenerator.Delaunay; - public Graph BoundariesGraph => _voronoiGenerator.Voronoi; - public Graph LocationGraph => _locationGenerator.Result; - [Range(2.0f, 64.0f)] public float radius = 8; public int seed = Environment.TickCount; - public Vector2 size = new Vector2(); - - public GraphGeneratorDebug debug; - - public GenerationStage Stage { get; private set; } = GenerationStage.Start; - public VoronoiGenerator VoronoiGenerator => _voronoiGenerator; - public LocationGenerator LocationGenerator => _locationGenerator; - - void Start() - { - Reset(); - } - - public void Reset() - { - _random = new Random(seed); - _sampler = new PoissonDiskSampler(radius) { Generator = _random }; - _points = new List(); - - Stage = GenerationStage.Voronoi; - - _voronoiGenerator = null; - _locationGenerator = null; - _locationGraph = null; - - _locations = new List() { new Location() { Type = new LocationType() { color = Color.clear, name = "Ocean", height = -1 } } }; - _locations.AddRange(types.Select(type => new Location { Type = type })); - } + public Graph SitesGraph => Map?.Sites; + public Graph BoundariesGraph => Map?.Boundaries; + public Graph LocationGraph => Map?.Metadata.GetProperty>(LocationPass.MapLocationsProperty); public void Generate() { - var stopwatch = new Stopwatch(); - stopwatch.Start(); + GenerationThread?.Abort(); + GenerationThread = new Thread(() => + { + var generator = CreateMapGenerator(); + var result = generator.Generate(size.x, size.y); + + lock (GetType()) + { + Map = result; + } + }); - debug.generationTime = 0; - - _points = new List(); - _points.Add(new Vector3(-size.x/8, size.y / 2 + 0.1f)); - _points.Add(new Vector3(size.x * 1.125f, size.y / 2 - 0.1f)); - _points.Add(new Vector3(size.x / 2 - 0.1f, -size.y/8)); - _points.Add(new Vector3(size.x / 2 + 0.1f, size.y * 1.125f)); - - _points.AddRange(_sampler.Generate(size.x, size.y).Select(x => new Vector3((float)x.x, (float)x.y))); - - - while (Stage != GenerationStage.Done) - { - Step(); - debug.generationTime = stopwatch.ElapsedMilliseconds / 1000.0f; - } - - stopwatch.Stop(); - debug.generationTime = stopwatch.ElapsedMilliseconds / 1000.0f; + GenerationThread.Start(); } - public void EnsureGenerated() + public void OnDisable() { - if (this.Stage != GenerationStage.Done) - Generate(); + GenerationThread?.Abort(); } - - public void Step() + + private MapGenerator CreateMapGenerator() { - if (Stage == GenerationStage.Voronoi) - { - _voronoiGenerator.Step(); + var generator = new MapGenerator(new VoronoiGridGenerator(seed, new PoissonDiskSampler(radius) { Generator = new Random(seed) })); - if (_voronoiGenerator.Done) - { - Stage = GenerationStage.Location; - - _locationGenerator = new LocationGenerator(_locations, _voronoiGenerator.Delaunay, _voronoiGenerator.Voronoi.Vertices, _random); + generator.AddAnnotationPass(new LocationPass(types.Prepend(new LocationType { name = "Ocean", height = -1 }).Select(t => new Location { Type = t }), new Random(seed))); + + return generator; + } - var initial = - from location in _locations - select (_random.Next(_voronoiGenerator.Delaunay.Vertices.Count), location); - - initial = initial.Concat(new List { 0, 1, 2, 3 }.Select(i => (i, _locations[0]))); - - foreach (var (vertex, location) in initial) - _locationGenerator.SetLocation(vertex, location); - } - } - else if (Stage == GenerationStage.Location) - { - _locationGenerator.Step(); - - if (_locationGenerator.Done) - { - Stage = GenerationStage.Done; - RecalculateLocationGraph(); - } - } + public void Reset() + { + GenerationThread?.Abort(); } void OnDrawGizmos() { - + if (!debug.enabled || Map == null) return; + if (debug.displayBoundary) { Gizmos.color = Color.gray; - - Gizmos.DrawLine(new Vector3(0, 0), new Vector3(size.x, 0)); - Gizmos.DrawLine(new Vector3(0, 0), new Vector3(0, size.y)); - Gizmos.DrawLine(new Vector3(size.x, size.y), new Vector3(size.x, 0)); - Gizmos.DrawLine(new Vector3(size.x, size.y), new Vector3(0, size.y)); + + Gizmos.DrawLine(new Vector3(0, 0, 0), new Vector3(size.x, 0, 0)); + Gizmos.DrawLine(new Vector3(0, 0, 0), new Vector3(0, 0, size.y)); + Gizmos.DrawLine(new Vector3(size.x, 0, size.y), new Vector3(size.x, 0, 0)); + Gizmos.DrawLine(new Vector3(size.x, 0, size.y), new Vector3(0, 0, size.y)); } - if (!debug.enabled || _voronoiGenerator == null) return; - if (debug.displayPoints) { Gizmos.color = Color.white; - DisplayGraphVertices(_voronoiGenerator.Delaunay.Morph(x => x.Point)); + DebugUtils.DisplayGraphVertices(Map.Sites, s => s.Center, displayLabels: debug.displayLabels); } if (debug.displayNeighbours) { Gizmos.color = Color.yellow; - DisplayGraphEdges(_voronoiGenerator.Delaunay.Morph(x => x.Point)); + DebugUtils.DisplayGraphEdges(Map.Sites, s => s.Center); } if (debug.displayVertices) { Gizmos.color = Color.blue; - DisplayGraphVertices(_voronoiGenerator.Voronoi); - } - - if (debug.displayHalfEdges) - { - Gizmos.color = Color.green; - foreach (var edge in _voronoiGenerator.HalfEdges) - { - Gizmos.DrawLine(edge.Start.ToVector3(), edge.End.ToVector3()); - } + DebugUtils.DisplayGraphVertices(Map.Boundaries, displayLabels: debug.displayLabels); } if (debug.displayEdges) { Gizmos.color = Color.white; - DisplayGraphEdges(_voronoiGenerator.Voronoi); + DebugUtils.DisplayGraphEdges(Map.Boundaries); } - - Gizmos.color = Color.red; - Gizmos.DrawLine(new Vector3(0, (float)_voronoiGenerator.Line.Directrix), new Vector3(size.x, (float)_voronoiGenerator.Line.Directrix)); + Gizmos.color = Color.blue; - Vector3 start; + if (!Map.Metadata.HasProperty(LocationPass.MapLocationsProperty)) return; + + var locations = Map.Metadata.GetProperty>(LocationPass.MapLocationsProperty); - if (debug.displayParabolas) - { - foreach (var parabola in _voronoiGenerator.Line.Parabolas) - { - start = new Vector3(-size.x, (float)_voronoiGenerator.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)_voronoiGenerator.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)_voronoiGenerator.Line.Eval(-size.x)); - for (var x = -size.x + 0.1f; x < size.x * 2; x += 0.1f) - { - var point = new Vector3(x, (float)_voronoiGenerator.Line.Eval(x)); - Gizmos.DrawLine(start, point); - - start = point; - } - } - - if (LocationGenerator == null) return; - if (debug.displayLocationCells) { - foreach (var location in LocationGenerator.Sites.Vertices.Where(l => l.Location != null && l.Location != _locations[0])) - { - Gizmos.color = location.Location.Type.color; - Gizmos.DrawSphere(location.Point.ToVector3(), 2); - } - } - - if (debug.displayLocations && _locationGraph != null) - { - DisplayGraphEdges(_locationGraph.Morph(a => a.Item1)); - } - - if (debug.displayLocationPoints) - { - foreach (var location in _locations.Skip(1)) + var cells = Map.Sites.Vertices + .Where(s => s.Metadata.HasProperty(LocationPass.SiteLocationProperty)) + .Where(s => s.Metadata.GetProperty(LocationPass.SiteLocationProperty).Type.name != "Ocean"); + + foreach (var site in cells) { + var location = site.Metadata.GetProperty(LocationPass.SiteLocationProperty); + Gizmos.color = location.Type.color; - foreach (var point in location.BoundaryPoints) - { - var v = VoronoiGenerator.Voronoi.Vertices[point].ToVector3(); - Gizmos.DrawSphere(v, 1); - if (debug.displayLabels) Handles.Label(v + Vector3.right, $"{point} at {v.x:F2}, {v.y:f2}"); - } + Gizmos.DrawSphere(site.Center.ToVector3(), 2); } } +// +// if (debug.displayLocations && _locationGraph != null) +// { +// DisplayGraphEdges(_locationGraph.Morph(a => a.Item1)); +// } +// +// if (debug.displayLocationPoints) +// { +// foreach (var location in _locations.Skip(1)) +// { +// Gizmos.color = location.Type.color; +// foreach (var point in location.BoundaryPoints) +// { +// var v = VoronoiGenerator.Voronoi.Vertices[point].ToVector3(); +// Gizmos.DrawSphere(v, 1); +// if (debug.displayLabels) Handles.Label(v + Vector3.right, $"{point} at {v.x:F2}, {v.y:f2}"); +// } +// } +// } +// if (debug.displayLocationEdges) { - foreach (var location in _locations.Skip(1)) + foreach (var location in Map.Metadata.GetProperty>(LocationPass.MapLocationsProperty).Vertices) { Gizmos.color = location.Type.color; foreach (var (a, b) in location.BoundaryEdges) { - Gizmos.DrawLine(VoronoiGenerator.Voronoi.Vertices[a].ToVector3(), VoronoiGenerator.Voronoi.Vertices[b].ToVector3()); + Gizmos.DrawLine(BoundariesGraph[a].ToVector3(), BoundariesGraph[b].ToVector3()); } } } } - - public void Rewind(float y) - { - while (_voronoiGenerator.Line.Directrix < y && !_voronoiGenerator.Done) - { - _voronoiGenerator.Step(); - } - } - - private void DisplayGraphVertices(Graph graph) - { - var vertices = graph.Vertices.Select(p => p.ToVector3()); - var offset = Vector3.right; - - foreach (var (v, i) in vertices.Select((x, i) => (x, i))) - { - Gizmos.DrawSphere(v, 1); - if (debug.displayLabels) Handles.Label(v + offset, $"{i} at {v.x:F2}, {v.y:f2}"); - } - } - - private void DisplayGraphEdges(Graph graph) - { - var edges = graph.Edges - .Select(edge => (graph.Vertices[edge.Item1], graph.Vertices[edge.Item2])) - .Select(edge => (edge.Item1.ToVector3(), edge.Item2.ToVector3())); - - foreach (var (s, e) in edges) Gizmos.DrawLine(s, e); - } - - private void RecalculateLocationGraph() - { - _locationGraph = LocationGenerator.Result.Morph(location => (location.Center, location)); - } } - } \ No newline at end of file diff --git a/Assets/Scripts/MapGenerator.cs b/Assets/Scripts/MapGenerator.cs index 1817344..26f33b3 100644 --- a/Assets/Scripts/MapGenerator.cs +++ b/Assets/Scripts/MapGenerator.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; +using Assets.AnnotationPass; using Assets.Common; +using Assets.GridGenerator; namespace Assets { - public class MapGenerator + class MapGenerator { private IGridGenerator _gridGenerator; private ICollection _annotationPasses = new List(); diff --git a/Assets/Scripts/MapRenderer.cs b/Assets/Scripts/MapRenderer.cs index 32fbe5f..ea5b38c 100644 --- a/Assets/Scripts/MapRenderer.cs +++ b/Assets/Scripts/MapRenderer.cs @@ -6,192 +6,192 @@ 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); - } - } - } +// 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); +// } +// } +// } } } \ No newline at end of file diff --git a/Assets/Scripts/RenderPass.meta b/Assets/Scripts/RenderPass.meta new file mode 100644 index 0000000..cfc0097 --- /dev/null +++ b/Assets/Scripts/RenderPass.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 81821064023a48f4affdf44568a66557 +timeCreated: 1573390973 \ No newline at end of file diff --git a/Assets/Scripts/IRenderPass.cs b/Assets/Scripts/RenderPass/IRenderPass.cs similarity index 83% rename from Assets/Scripts/IRenderPass.cs rename to Assets/Scripts/RenderPass/IRenderPass.cs index eb22532..4f03b22 100644 --- a/Assets/Scripts/IRenderPass.cs +++ b/Assets/Scripts/RenderPass/IRenderPass.cs @@ -1,7 +1,7 @@ using Assets.Common; using UnityEngine; -namespace Assets +namespace Assets.RenderPass { public interface IRenderPass { diff --git a/Assets/Scripts/IRenderPass.cs.meta b/Assets/Scripts/RenderPass/IRenderPass.cs.meta similarity index 100% rename from Assets/Scripts/IRenderPass.cs.meta rename to Assets/Scripts/RenderPass/IRenderPass.cs.meta diff --git a/Assets/Triangulator.cs b/Assets/Scripts/Triangulator.cs similarity index 100% rename from Assets/Triangulator.cs rename to Assets/Scripts/Triangulator.cs diff --git a/Assets/Triangulator.cs.meta b/Assets/Scripts/Triangulator.cs.meta similarity index 100% rename from Assets/Triangulator.cs.meta rename to Assets/Scripts/Triangulator.cs.meta diff --git a/Assets/Scripts/Utils.meta b/Assets/Scripts/Utils.meta new file mode 100644 index 0000000..d8c47af --- /dev/null +++ b/Assets/Scripts/Utils.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d1235a1f76af47e6b8686c3c359e24da +timeCreated: 1573399226 \ No newline at end of file diff --git a/Assets/Scripts/Utils/DebugUtils.cs b/Assets/Scripts/Utils/DebugUtils.cs new file mode 100644 index 0000000..ba6d7c7 --- /dev/null +++ b/Assets/Scripts/Utils/DebugUtils.cs @@ -0,0 +1,43 @@ +using System.Linq; +using Assets.Common; +using UnityEditor; +using UnityEngine; + +namespace Assets.Utils +{ + public static class DebugUtils + { + public delegate Point PointExtractor(T thing); + + public static void DisplayGraphVertices(Graph graph, PointExtractor extractor, bool displayLabels = true) + { + var vertices = graph.Vertices.Select(p => extractor(p).ToVector3()); + var offset = Vector3.right; + + foreach (var (v, i) in vertices.Select((x, i) => (x, i))) + { + Gizmos.DrawSphere(v, 1); + if (displayLabels) Handles.Label(v + offset, $"{i} at {v.x:F2}, {v.y:f2}"); + } + } + + public static void DisplayGraphVertices(Graph graph, bool displayLabels = true) + { + DisplayGraphVertices(graph, l => l, displayLabels); + } + + public static void DisplayGraphEdges(Graph graph, PointExtractor extractor) + { + var edges = graph.Edges + .Select(edge => (graph.Vertices[edge.Item1], graph.Vertices[edge.Item2])) + .Select(edge => (extractor(edge.Item1).ToVector3(), extractor(edge.Item2).ToVector3())); + + foreach (var (s, e) in edges) Gizmos.DrawLine(s, e); + } + + public static void DisplayGraphEdges(Graph graph) + { + DisplayGraphEdges(graph, l => l); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Utils/DebugUtils.cs.meta b/Assets/Scripts/Utils/DebugUtils.cs.meta new file mode 100644 index 0000000..37ee66e --- /dev/null +++ b/Assets/Scripts/Utils/DebugUtils.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2248a5e781874095a731dffefaca79c1 +timeCreated: 1573399272 \ No newline at end of file diff --git a/Assets/Voronoi.meta b/Assets/Scripts/Voronoi.meta similarity index 100% rename from Assets/Voronoi.meta rename to Assets/Scripts/Voronoi.meta diff --git a/Assets/Voronoi/BeachLine.cs b/Assets/Scripts/Voronoi/BeachLine.cs similarity index 100% rename from Assets/Voronoi/BeachLine.cs rename to Assets/Scripts/Voronoi/BeachLine.cs diff --git a/Assets/Voronoi/BeachLine.cs.meta b/Assets/Scripts/Voronoi/BeachLine.cs.meta similarity index 100% rename from Assets/Voronoi/BeachLine.cs.meta rename to Assets/Scripts/Voronoi/BeachLine.cs.meta diff --git a/Assets/Voronoi/Tree.cs b/Assets/Scripts/Voronoi/Tree.cs similarity index 100% rename from Assets/Voronoi/Tree.cs rename to Assets/Scripts/Voronoi/Tree.cs diff --git a/Assets/Voronoi/Tree.cs.meta b/Assets/Scripts/Voronoi/Tree.cs.meta similarity index 100% rename from Assets/Voronoi/Tree.cs.meta rename to Assets/Scripts/Voronoi/Tree.cs.meta diff --git a/Assets/Voronoi/VoronoiGenerator.cs b/Assets/Scripts/Voronoi/VoronoiGenerator.cs similarity index 100% rename from Assets/Voronoi/VoronoiGenerator.cs rename to Assets/Scripts/Voronoi/VoronoiGenerator.cs diff --git a/Assets/Voronoi/VoronoiGenerator.cs.meta b/Assets/Scripts/Voronoi/VoronoiGenerator.cs.meta similarity index 100% rename from Assets/Voronoi/VoronoiGenerator.cs.meta rename to Assets/Scripts/Voronoi/VoronoiGenerator.cs.meta