diff --git a/project.godot b/project.godot index baed0d8..3750e34 100644 --- a/project.godot +++ b/project.godot @@ -19,6 +19,11 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://utils/camera/outline.gd" }, { +"base": "Spatial", +"class": "Chunk", +"language": "GDScript", +"path": "res://world/chunk.gd" +}, { "base": "Reference", "class": "Delaunator", "language": "GDScript", @@ -42,6 +47,7 @@ _global_script_classes=[ { _global_script_class_icons={ "CameraController": "", "CameraOutline": "", +"Chunk": "", "Delaunator": "", "PoissonDiscSampling": "", "Terrain": "", diff --git a/utils/terrain/Terrain.gd b/utils/terrain/Terrain.gd index a24ebc7..de35550 100644 --- a/utils/terrain/Terrain.gd +++ b/utils/terrain/Terrain.gd @@ -850,3 +850,8 @@ func get_voronoi_cells_as_polygon(): list_polygon.append(center.polygon()) return(list_polygon) +func get_chunk(vect): + var centers = [] + for idx in _data["find_point"][int(vect[0] / 64.0) * 32 + int(vect[1] / 64.0)]: + centers.append(get_center(idx)) + return centers diff --git a/utils/world_generation/WorldGeneration.gd b/utils/world_generation/WorldGeneration.gd index f00364b..c409e6c 100644 --- a/utils/world_generation/WorldGeneration.gd +++ b/utils/world_generation/WorldGeneration.gd @@ -44,8 +44,9 @@ func _init(): Global.terrain.save() if Global.terrain.is_created() or Global.terrain.is_loaded(): + pass # create_map() - Global.terrain.set_data("mesh", create_mesh()) + # Global.terrain.set_data("mesh", create_mesh()) # add_trees() # get_tree().change_scene("res://world/game.tscn") else: diff --git a/world/World3d.gd b/world/World3d.gd index 62c90ef..2682307 100644 --- a/world/World3d.gd +++ b/world/World3d.gd @@ -1,11 +1,17 @@ extends Spatial var rng = RandomNumberGenerator.new() +var chunk_size = 16 +var chunk_amount = 16 +var chunks = {} +var unready_chunks = {} +var thread func _ready(): - var mi = Global.terrain.get_data("mesh") - add_child(mi) - add_trees() + # var mi = Global.terrain.get_data("mesh") + # add_child(mi) + # add_trees() + thread = Thread.new() func add_trees(): rng.randomize() @@ -25,3 +31,67 @@ func add_trees(): tree.rotate_y(rng.randi_range(0, 2*PI)) tree.translation = Vector3(point.x, center.get_elevation() * 120, point.y) add_child(tree) + + +func add_chunk(x, z): + var key = str(x) + "," + str(z) + if chunks.has(key) or unready_chunks.has(key): + return + + if not thread.is_active(): + thread.start(self, "load_chunk", [thread, x, z]) + unready_chunks[key] = 1 + +func load_chunk(array): + var thread = array[0] + var x = array[1] + var z = array[2] + + var chunk = Chunk.new(x * chunk_size, z * chunk_size) + + chunk.translation = Vector3(x * chunk_size, 0, z * chunk_size) + + call_deferred("load_done", chunk, thread) + +func load_done(chunk, thread): + add_child(chunk) + var key = str(chunk.x / chunk_size) + "," + str(chunk.z / chunk_size) + chunks[key] = chunk + unready_chunks.erase(key) + thread.wait_to_finish() + +func get_chunk(x, z): + var key = str(x) + "," + str(z) + if chunks.has(key): + return chunks.get(key) + + return null + +func _process(delta): + update_chunks() + clean_up_chunks() + reset_chunks() + +func update_chunks(): + var camera_translation = $CamBase/Camera.translation +# print(camera_translation) + var c_x = int(camera_translation.x) / chunk_size + var c_z = int(camera_translation.z) / chunk_size + + for x in range(c_x - chunk_amount * 0.5, c_x + chunk_amount * 0.53): + for z in range(c_z - chunk_amount * 0.5, c_z + chunk_amount * 0.53): + add_chunk(x, z) + var chunk = get_chunk(x, z) + if chunk != null: + chunk.should_remove = false + +func clean_up_chunks(): + for key in chunks: + var chunk = chunks[key] + if chunk.should_remove: + chunk.queue_free() + chunks.erase(key) + +func reset_chunks(): + for key in chunks: + chunks[key].should_remove = true diff --git a/world/chunk.gd b/world/chunk.gd new file mode 100644 index 0000000..b5430a8 --- /dev/null +++ b/world/chunk.gd @@ -0,0 +1,71 @@ +extends Spatial +class_name Chunk + +var noise +var should_remove = true +var x +var z + +func _init(x, z): + self.x = x + self.z = z + +func _ready(): + generate_chunk() + +func generate_chunk(): + var file = File.new() + file.open("res://world/materials/materials.json", File.READ) + var materials = JSON.parse(file.get_as_text()).result + + var st = SurfaceTool.new() + + st.begin(Mesh.PRIMITIVE_TRIANGLES) + var factor = Vector3(1, 120, 1) + for center in Global.terrain.get_chunk(Vector2(x, z)): + if not center.get_data("water"): + var material_id = materials[center.get_data("material")] + var top_uv = Vector2(0, float(material_id) / (materials.size()-1)) + var border_uv = Vector2(1, float(material_id) / (materials.size()-1)) + + for edge in center.borders(): + if edge.end_center().get_elevation() < edge.start_center().get_elevation(): + var top = edge.start_center().get_elevation() + # if edge.start_center().get_data("ocean"): + # top = -1.0 + var bottom = edge.end_center().get_elevation() + if edge.end_center().get_data("ocean"): + bottom = 0.0 + st.add_uv(border_uv) + st.add_vertex(Vector3(edge.start_corner().point3d().x, bottom, edge.start_corner().point3d().z) * factor) + st.add_vertex(Vector3(edge.end_corner().point3d().x, top, edge.end_corner().point3d().z) * factor) + st.add_vertex(Vector3(edge.start_corner().point3d().x, top, edge.start_corner().point3d().z) * factor) + + st.add_vertex(Vector3(edge.start_corner().point3d().x, bottom, edge.start_corner().point3d().z) * factor) + st.add_vertex(Vector3(edge.end_corner().point3d().x, bottom, edge.end_corner().point3d().z) * factor) + st.add_vertex(Vector3(edge.end_corner().point3d().x, top, edge.end_corner().point3d().z) * factor) + + for corner_count in center.corners().size(): + var current_corner = center.corners()[corner_count] + var next_corner + if corner_count < center.corners().size() - 1: + next_corner = center.corners()[corner_count+1] + else: + next_corner = center.corners()[0] + + st.add_uv(Vector2(top_uv)) + st.add_vertex(Vector3(current_corner.point2d().x, center.get_elevation(), current_corner.point2d().y) * factor) + st.add_vertex(Vector3(next_corner.point2d().x, center.get_elevation(), next_corner.point2d().y) * factor) + st.add_vertex(Vector3(center.point2d().x, center.get_elevation(), center.point2d().y) * factor) + Global.loading.increment_step() + + st.generate_normals() + st.index() + + var mi = MeshInstance.new() + mi.mesh = st.commit() + var material = load("res://world/materials/world.material") + mi.set_surface_material(0, material) + mi.create_trimesh_collision() + mi.cast_shadow = GeometryInstance.SHADOW_CASTING_SETTING_ON + add_child(mi) diff --git a/world/materials/world.material b/world/materials/world.material index c5148d2..dce9da7 100644 Binary files a/world/materials/world.material and b/world/materials/world.material differ