From 31b585f1d7cf2a2c89e9661a146a037219934f7c Mon Sep 17 00:00:00 2001 From: Alain STARK Date: Fri, 19 Aug 2022 22:44:48 +0200 Subject: [PATCH 1/4] Voronoi class VoronoiCenter, VoronoiCorner and VoronoiEdge --- utils/terrain/Terrain.gd | 140 +++++++++++++++++++++++++++++++++++++++ world/game.gd | 26 +++++++- 2 files changed, 165 insertions(+), 1 deletion(-) diff --git a/utils/terrain/Terrain.gd b/utils/terrain/Terrain.gd index ba4c050..522c524 100644 --- a/utils/terrain/Terrain.gd +++ b/utils/terrain/Terrain.gd @@ -3,6 +3,140 @@ extends Reference # Build terrain from delaunay graph class_name Terrain +# Voronoi Center iterator +class VoronoiCenters: + var _terrain + var _curr + var _end + + func _init(terrain): + self._terrain = terrain + self._curr = 0 + self._end = _terrain._points.size() + + func _should_continue(): + return (_curr < _end) + + func _iter_init(_arg): + _curr = 0 + return _should_continue() + + func _iter_next(_arg): + _curr += 1 + return _should_continue() + + func _iter_get(_arg): + var point = Point.new(_curr,_terrain) + return point + + func size(): + return _end + +# Voronoi Center object +class VoronoiCenter: + var _idx + var _terrain + + func _init(idx, terrain): + self._idx = idx + self._terrain = terrain + + func to_point(): + return Point.new(_idx, _terrain) + + func get_index(): + return _idx + + func has_key(key): + return _terrain._points_data[_idx].has(key) + + func set_data(key,value): + var data = _terrain._points_data[_idx] + data[key] = value + + func get_data(key): + var data = _terrain._points_data[_idx] + if data.has(key): + return data[key] + + func point3d(): + return _terrain._points[_idx] + + func point2d(): + var point3d:Vector3 = _terrain._points[_idx] + var point2d:Vector2 = Vector2(point3d.x, point3d.z) + return(point2d) + + func set_elevation(elevation:float): + _terrain._points[_idx].y = elevation + + func get_elevation(): + return(_terrain._points[_idx].y) + + func neighbors(): + var list_centers = [] + + for point in to_point().points_around(): + list_centers.append(point.to_center()) + return list_centers + + func borders(): + var list_edges = [] + for edge in to_point().edges_around(): + var center_start = edge.start().to_center() + var center_end = edge.end().to_center() + var corner_start = VoronoiCorner.new(edge.triangle()) + var corner_end = VoronoiCorner.new(edge.opposite().triangle()) + list_edges.append(VoronoiEdge.new(corner_start,corner_end,center_start,center_end)) + return list_edges + + + func corners(): + var list_corners = [] + + for triangle in to_point().triangles_around(): + var corner = VoronoiCorner.new(triangle) + list_corners.append(corner) + return list_corners + +# Voronoi Corner object +class VoronoiCorner: + var _triangle + + func _init(triangle): + self._triangle = triangle + + func point3d(): + return _triangle.center3d() + + func point2d(): + return _triangle.center2d() + +# Voronoi Edge object +class VoronoiEdge: + var _start_corner + var _end_corner + var _start_center + var _end_center + + func _init(start_corner, end_corner, start_center, end_center): + self._start_corner = end_corner + self._end_corner = start_corner + self._start_center = end_center + self._end_center = start_center + + func start_corner(): + return _start_corner + + func end_corner(): + return _end_corner + + func start_center(): + return _start_center + + func end_center(): + return _end_center + # Triangles iterator class Triangles: var _terrain @@ -124,6 +258,9 @@ class Point: func _init(idx, terrain): self._idx = idx self._terrain = terrain + + func to_center(): + return VoronoiCenter.new(_idx, _terrain) func get_index(): return _idx @@ -391,6 +528,9 @@ func get_points(): func get_point(idx): return Point.new(idx, self) +func get_center(idx): + return VoronoiCenter.new(idx, self) + func get_edge(idx): return Edge.new(idx, self) diff --git a/world/game.gd b/world/game.gd index 824a37a..6ed5629 100644 --- a/world/game.gd +++ b/world/game.gd @@ -24,7 +24,7 @@ func _ready(): noise.octaves = octaves # terrain = Terrain.new(width,height,spacing,false) - var terrain_name="bonjour" + var terrain_name="bonjour01" terrain = Terrain.new() print(terrain.list()) @@ -35,6 +35,30 @@ func _ready(): terrain.create(width,height,spacing,terrain_name) if terrain.is_created() or terrain.is_loaded(): + + var center = terrain.get_center(43) + for edge in center.borders(): + Global.print_debug("Corner start :") + Global.print_debug(edge.start_corner().point2d()) + Global.print_debug("Corner end :") + Global.print_debug(edge.end_corner().point2d()) + Global.print_debug("Center start :") + Global.print_debug(edge.start_center().point2d()) + Global.print_debug("Center end :") + Global.print_debug(edge.end_center().point2d()) + + """ + Global.print_debug("Corners of center :") + for corner in center.corners(): + Global.print_debug(corner.point2d()) + + Global.print_debug("Find neighbors") + for neighbor in center.neighbors(): + Global.print_debug("Corners of neighbor :") + for corner in neighbor.corners(): + Global.print_debug(corner.point2d()) + """ + init_data() add_trees() emit_signal("world_loaded", terrain) From 797f4efcd1664f1dc990ff7868a49e49f512979a Mon Sep 17 00:00:00 2001 From: Alain STARK Date: Mon, 22 Aug 2022 22:19:01 +0200 Subject: [PATCH 2/4] Debug Terrain.gd --- utils/terrain/Terrain.gd | 59 ++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/utils/terrain/Terrain.gd b/utils/terrain/Terrain.gd index 522c524..a2a7f76 100644 --- a/utils/terrain/Terrain.gd +++ b/utils/terrain/Terrain.gd @@ -26,8 +26,8 @@ class VoronoiCenters: return _should_continue() func _iter_get(_arg): - var point = Point.new(_curr,_terrain) - return point + var center = VoronoiCenter.new(_curr,_terrain) + return center func size(): return _end @@ -98,6 +98,12 @@ class VoronoiCenter: var corner = VoronoiCorner.new(triangle) list_corners.append(corner) return list_corners + + func polygon(): + var polygon = [] + for corner in corners(): + polygon.append(corner.point2d()) + return polygon # Voronoi Corner object class VoronoiCorner: @@ -111,6 +117,28 @@ class VoronoiCorner: func point2d(): return _triangle.center2d() + + func touches(): + var list_centers = [] + for point in _triangle.points(): + list_centers.append(point.to_center()) + return list_centers + + func protudes(): + var list_edges = [] + for edge in _triangle.edges(): + var center_start = edge.start().to_center() + var center_end = edge.end().to_center() + var corner_start = VoronoiCorner.new(edge.triangle()) + var corner_end = VoronoiCorner.new(edge.opposite().triangle()) + list_edges.append(VoronoiEdge.new(corner_start,corner_end,center_start,center_end)) + return list_edges + + func adjacents(): + var list_corners = [] + for triangle in _triangle.adjacents(): + list_corners.append(VoronoiCorner.new(triangle)) + return list_corners # Voronoi Edge object class VoronoiEdge: @@ -136,6 +164,12 @@ class VoronoiEdge: func end_center(): return _end_center + + func line(): + var line = [] + line.append(start_corner().point2d()) + line.append(end_corner().point2d()) + return line # Triangles iterator class Triangles: @@ -199,7 +233,7 @@ class Triangle: list_points.append(Point.new(_terrain._triangles[edge._idx], _terrain)) return list_points - func triangles_adjacent(): + func adjacents(): var list_triangles = [] for edge in edges(): var opposite = Edge.new(_terrain._halfedges[edge._idx], _terrain) @@ -293,13 +327,14 @@ class Point: func edges_around(): var list_edges = [] - var incoming_edge = Edge.new(_idx, _terrain) + var incoming = _terrain._points_to_halfedges.get(_idx) + var incoming_edge = Edge.new(incoming, _terrain) var outgoing_edge while true: list_edges.append(incoming_edge); outgoing_edge = incoming_edge.next_half() incoming_edge = Edge.new(_terrain._halfedges[outgoing_edge._idx], _terrain); - if not (incoming_edge._idx != -1 and incoming_edge._idx != _idx): + if not (incoming_edge._idx != -1 and incoming_edge._idx != incoming): break return list_edges @@ -320,6 +355,7 @@ class Point: var list_triangles = [] for edge in edges_around(): list_triangles.append(edge.triangle()) +# list_triangles.append(edge.opposite().triangle()) return list_triangles # Edges iterator @@ -356,7 +392,7 @@ class Edge: var _idx var _terrain - func _init(idx, terrain): + func _init(idx:int, terrain): self._idx = idx self._terrain = terrain @@ -527,6 +563,10 @@ func get_points(): func get_point(idx): return Point.new(idx, self) + +func get_centers(): + var centers = VoronoiCenters.new(self) + return centers func get_center(idx): return VoronoiCenter.new(idx, self) @@ -698,10 +738,7 @@ func get_voronoi_edges_as_line(): func get_voronoi_cells_as_polygon(): var list_polygon = [] - for point in get_points(): - var polygon = [] - for edge in point.edges_around(): - polygon.append(edge.triangle().center2d()) - list_polygon.append(polygon) + for center in get_centers(): + list_polygon.append(center.polygon()) return(list_polygon) From ddaa83a472a6d6eecafa80c5ca09b81ef26ac563 Mon Sep 17 00:00:00 2001 From: Alain STARK Date: Tue, 23 Aug 2022 21:48:22 +0200 Subject: [PATCH 3/4] Find point --- utils/terrain/Terrain.gd | 33 ++++++++++++++++++++++++++++++++- world/game.gd | 30 +++--------------------------- world/game.tscn | 1 + 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/utils/terrain/Terrain.gd b/utils/terrain/Terrain.gd index d221ba4..acd387f 100644 --- a/utils/terrain/Terrain.gd +++ b/utils/terrain/Terrain.gd @@ -309,8 +309,15 @@ class Point: func to_center(): return VoronoiCenter.new(_idx, _terrain) + func find_index(): + var vect=point2d() + return int(vect[0] / 64.0) * 32 + int(vect[1] / 64.0) + func get_index(): return _idx + + func distance(vect): + return(point2d().distance_to(vect)) func has_key(key): return _terrain._points_data[_idx].has(key) @@ -533,6 +540,14 @@ func create(width:int, height:int, spacing:int, name:String): _halfedges = PoolIntArray(delaunay.halfedges) _triangles = PoolIntArray(delaunay.triangles) + # Initialize find_point + _data["find_point"]=[] + _data["find_point"].resize(1024) + for idx in 1024: + _data["find_point"][idx]=[] + for point in get_points(): + _data["find_point"][point.find_index()].append(point.get_index()) + # Initialize _points_to_halfedges for edge in get_edges(): var endpoint = _triangles[edge.next_half().get_index()] @@ -579,7 +594,23 @@ func get_points(): func get_point(idx): return Point.new(idx, self) - + +func find_point(vect): + var selected_point + var minimum = 999999.99 + for idx in _data["find_point"][int(vect[0] / 64.0) * 32 + int(vect[1] / 64.0)]: + var point=get_point(idx) + var distance = point.distance(vect) + if(distance < minimum): + selected_point = point + minimum=distance + for point_around in selected_point.points_around(): + var distance = point_around.distance(vect) + if(distance < minimum): + selected_point = point_around + minimum=distance + return selected_point + func get_centers(): var centers = VoronoiCenters.new(self) return centers diff --git a/world/game.gd b/world/game.gd index 9394f0e..abf8a85 100644 --- a/world/game.gd +++ b/world/game.gd @@ -2,8 +2,8 @@ extends Node signal world_loaded -export(int) var width = 2000 -export(int) var height = 2000 +export(int) var width = 2048 +export(int) var height = 2048 export(int) var spacing = 20 export(int, 1, 9) var octaves = 5 export(int, 1, 30) var wavelength = 8 @@ -34,31 +34,7 @@ func _ready(): else: terrain.create(width,height,spacing,terrain_name) - if terrain.is_created() or terrain.is_loaded(): - - var center = terrain.get_center(43) - for edge in center.borders(): - Global.print_debug("Corner start :") - Global.print_debug(edge.start_corner().point2d()) - Global.print_debug("Corner end :") - Global.print_debug(edge.end_corner().point2d()) - Global.print_debug("Center start :") - Global.print_debug(edge.start_center().point2d()) - Global.print_debug("Center end :") - Global.print_debug(edge.end_center().point2d()) - - """ - Global.print_debug("Corners of center :") - for corner in center.corners(): - Global.print_debug(corner.point2d()) - - Global.print_debug("Find neighbors") - for neighbor in center.neighbors(): - Global.print_debug("Corners of neighbor :") - for corner in neighbor.corners(): - Global.print_debug(corner.point2d()) - """ - + if terrain.is_created() or terrain.is_loaded(): init_data() add_trees() emit_signal("world_loaded", terrain) diff --git a/world/game.tscn b/world/game.tscn index af1b6c5..51f1d10 100644 --- a/world/game.tscn +++ b/world/game.tscn @@ -40,6 +40,7 @@ environment = ExtResource( 3 ) [node name="Camera" parent="World3d/CamBase" index="0"] transform = Transform( 1, 0, 0, 0, 0.659983, -0.75128, 0, 0.75128, 0.659983, 0, -1.90735e-06, 6.618 ) fov = 55.0 +depth_multiplier = 99.0 zoom_sensibility = 1.436 [node name="DirectionalLight" type="DirectionalLight" parent="World3d"] From 7415190866c1d7531335f4e8ec3d174d59e2a5da Mon Sep 17 00:00:00 2001 From: Alain STARK Date: Tue, 23 Aug 2022 22:30:18 +0200 Subject: [PATCH 4/4] Delete terrain --- utils/terrain/Terrain.gd | 25 +++++++++++++++++++++++++ world/game.gd | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/utils/terrain/Terrain.gd b/utils/terrain/Terrain.gd index acd387f..9513319 100644 --- a/utils/terrain/Terrain.gd +++ b/utils/terrain/Terrain.gd @@ -641,6 +641,31 @@ func save(): save_parameter() save_graph() save_data() + +func delete(name): + var directory = Directory.new() + Global.print_debug("Delete terrain : %s" %(name)) + + # Goto terrain directory + directory.open("user://") + if not directory.dir_exists("terrain"): + directory.make_dir("terrain") + directory.change_dir("terrain") + if directory.dir_exists(name): + directory.change_dir(name) + directory.list_dir_begin() + var filename = directory.get_next() + while filename != "": + if( directory.file_exists(filename)): + print("Found file: " + filename) + directory.remove(filename) + filename = directory.get_next() + directory.list_dir_end() + directory.change_dir("..") + var result = directory.remove(name) + if(result != OK): + print(result) + func save_parameter(): var file = File.new() diff --git a/world/game.gd b/world/game.gd index abf8a85..a680ee2 100644 --- a/world/game.gd +++ b/world/game.gd @@ -27,7 +27,7 @@ func _ready(): terrain = Terrain.new() - print(terrain.list()) + Global.print_debug(terrain.list()) if terrain.exists(terrain_name): terrain.load(terrain_name)