diff options
author | dusoleil <howcansocksbereal@gmail.com> | 2022-09-19 10:32:24 -0400 |
---|---|---|
committer | dusoleil <howcansocksbereal@gmail.com> | 2022-09-19 10:32:24 -0400 |
commit | 51a0664a1c2265adddbf4c42d4eda747c8ea8aaf (patch) | |
tree | 1bcdb3bcee5a0c1e303d55a001158ec906810329 | |
parent | 9bc2a0767e15d4dde7fd6231b07882d6456af71e (diff) | |
download | godot_wildjam_49-51a0664a1c2265adddbf4c42d4eda747c8ea8aaf.tar.gz godot_wildjam_49-51a0664a1c2265adddbf4c42d4eda747c8ea8aaf.zip |
Add Levels of Detail per Chunk
-rw-r--r-- | world/World.gd | 37 | ||||
-rw-r--r-- | world/World.tscn | 4 | ||||
-rw-r--r-- | world/chunk/Chunk.gd | 37 | ||||
-rw-r--r-- | world/chunk/Chunk.tscn | 10 | ||||
-rw-r--r-- | world/chunk/ChunkGen.gd | 87 | ||||
-rw-r--r-- | world/chunk/ChunkLoader.gd | 32 | ||||
-rw-r--r-- | world/obstacles/Rock.gd | 18 | ||||
-rw-r--r-- | world/obstacles/Rock.tscn | 32 | ||||
-rw-r--r-- | world/obstacles/Rock_coll.tres | 4 | ||||
-rw-r--r-- | world/obstacles/Rock_lowres_mesh.tres | 4 |
10 files changed, 143 insertions, 122 deletions
diff --git a/world/World.gd b/world/World.gd index 2c8d822..04c3ef1 100644 --- a/world/World.gd +++ b/world/World.gd @@ -4,11 +4,13 @@ export(NodePath) var traveler = null onready var _traveler = get_node(traveler) export var acceleration = 10.0 -onready var lod_distance = $"ChunkRenderDistance" -onready var lod_mid = $"ChunkRenderMid" -onready var lod_close = $"ChunkRenderClose" +onready var chunk_render_distance = $"ChunkRenderDistance" +onready var chunk_render_mid = $"ChunkRenderMid" +onready var chunk_render_close = $"ChunkRenderClose" -onready var chunk_render_distance = lod_distance.get_node("Radius").shape.radius +onready var lod_distance = chunk_render_distance.get_node("Radius").shape.radius +onready var lod_mid = chunk_render_mid.get_node("Radius").shape.radius +onready var lod_close = chunk_render_close.get_node("Radius").shape.radius onready var chunk_half_size = $"Chunks/Chunk/Size".shape.radius onready var chunk_size = chunk_half_size * 2.0 @@ -33,7 +35,7 @@ func _on_ChunkRenderClose_area_entered(area:Area): area.lod_update() func _on_ChunkRenderDistance_area_exited(area:Area): - ChunkLoader.free_chunk(chunk_coords(v2_coords(area.transform.origin))) + free_chunk(area) func _on_ChunkRenderMid_area_exited(area:Area): area.lod = area.LOD.DISTANCE @@ -52,26 +54,13 @@ func travel(direction:Vector3): $"Chunks".add_central_force(direction*acceleration) func _physics_process(_state): - chunk_process() + ChunkLoader.chunk_update() var stick = Input.get_axis("ship_down","ship_up") if stick != 0.0: self.travel(Vector3.FORWARD*stick) -func v2_coords(coords:Vector3): - return Vector2(coords.x,coords.z) - -func chunk_coords(coords:Vector2): - return coords.snapped(Vector2(chunk_size,chunk_size)) - -func chunk_process(): - var gen_center = -v2_coords($"Chunks".transform.origin) - var gen_radius = chunk_render_distance - var gen_radius_rounded = stepify(gen_radius, chunk_size) - for x in range(-gen_radius_rounded, gen_radius_rounded+chunk_size, chunk_size): - for y in range(-gen_radius_rounded, gen_radius_rounded+chunk_size, chunk_size): - var gen_coords = Vector2(x,y) - if gen_coords.length() > gen_radius: - continue - var coords = chunk_coords(gen_coords + gen_center) - ChunkLoader.add_chunk(coords) - ChunkLoader.chunk_update() +func free_chunk(chunk): + var coords = chunk.transform.origin + coords = Vector2(coords.x,coords.z) + coords = coords.snapped(Vector2(chunk_size,chunk_size)) + ChunkLoader.free_chunk(coords) diff --git a/world/World.tscn b/world/World.tscn index 81b2201..647f47b 100644 --- a/world/World.tscn +++ b/world/World.tscn @@ -4,10 +4,10 @@ [ext_resource path="res://world/chunk/Chunk.tscn" type="PackedScene" id=3] [sub_resource type="SphereShape" id=24] -radius = 500.0 +radius = 1000.0 [sub_resource type="SphereShape" id=25] -radius = 300.0 +radius = 500.0 [sub_resource type="SphereShape" id=26] radius = 150.0 diff --git a/world/chunk/Chunk.gd b/world/chunk/Chunk.gd index 1860c84..4356caf 100644 --- a/world/chunk/Chunk.gd +++ b/world/chunk/Chunk.gd @@ -3,15 +3,30 @@ extends Area enum LOD {DISTANCE,MID,CLOSE} var lod = -1 +onready var lod_distance = $"gen_tree/lod_distance" +onready var lod_mid = $"gen_tree/lod_mid" +onready var lod_close = $"gen_tree/lod_close" + +onready var _collision_enabled = lod_close.collision_layer + +func _ready(): + lod_update() + func lod_update(): - return - for obj in $"gen_tree".get_children(): - match lod: - LOD.CLOSE: - obj.lod_close() - LOD.MID: - obj.lod_mid() - LOD.DISTANCE: - obj.lod_distance() - _: - obj.lod_distance() + match lod: + LOD.CLOSE: + lod_distance.visible = false + lod_mid.visible = true + lod_close.collision_layer = _collision_enabled + LOD.MID: + lod_distance.visible = false + lod_mid.visible = true + lod_close.collision_layer = 0 + LOD.DISTANCE: + lod_distance.visible = true + lod_mid.visible = false + lod_close.collision_layer = 0 + _: + lod_distance.visible = true + lod_mid.visible = false + lod_close.collision_layer = 0 diff --git a/world/chunk/Chunk.tscn b/world/chunk/Chunk.tscn index 4ce985b..5377ae9 100644 --- a/world/chunk/Chunk.tscn +++ b/world/chunk/Chunk.tscn @@ -34,3 +34,13 @@ _mesh = SubResource( 2 ) operation = 2 script = ExtResource( 2 ) _mesh = SubResource( 4 ) + +[node name="gen_tree" type="Spatial" parent="."] + +[node name="lod_distance" type="Spatial" parent="gen_tree"] + +[node name="lod_mid" type="Spatial" parent="gen_tree"] + +[node name="lod_close" type="StaticBody" parent="gen_tree"] +collision_layer = 8 +collision_mask = 0 diff --git a/world/chunk/ChunkGen.gd b/world/chunk/ChunkGen.gd index 75d3736..e71cc57 100644 --- a/world/chunk/ChunkGen.gd +++ b/world/chunk/ChunkGen.gd @@ -25,10 +25,18 @@ func rng_2dv(coords:Vector2): self.rng.seed = hash(coords) func gen_chunk(chunk): - var gen_tree = Spatial.new() - gen_tree.name = "gen_tree" - chunk.add_child(gen_tree) - gen_rocks(chunk) + gen_distance(chunk,chunk.get_node("gen_tree/lod_distance")) + gen_mid(chunk,chunk.get_node("gen_tree/lod_mid")) + gen_close(chunk,chunk.get_node("gen_tree/lod_close")) + +func gen_distance(chunk,tree): + gen_lowres_rocks(chunk,tree) + +func gen_mid(chunk,tree): + gen_rocks(chunk,tree) + +func gen_close(chunk,tree): + gen_rock_hitboxes(chunk,tree) func v2_coords(coords:Vector3): return Vector2(coords.x,coords.z) @@ -36,15 +44,43 @@ func v2_coords(coords:Vector3): func v3_coords(coords:Vector2): return Vector3(coords.x,0.0,coords.y) -func iterate_chunk(chunk,step:Vector2,cb:FuncRef): +func iterate_chunk(chunk,tree,step:Vector2,cb:FuncRef,data): var chunk_size_rounded = Vector2(chunk_half_size,chunk_half_size).snapped(step) for x in range(-chunk_size_rounded.x,chunk_size_rounded.x,step.x): for y in range(-chunk_size_rounded.y,chunk_size_rounded.y,step.y): - cb.call_func(chunk,Vector2(x,y)) + cb.call_func(chunk,tree,Vector2(x,y),data) + +func make_multimesh(name,cnt,mesh): + var multi_inst = MultiMeshInstance.new() + multi_inst.name = name + var multi = MultiMesh.new() + multi_inst.multimesh = multi + multi.transform_format = MultiMesh.TRANSFORM_3D + multi.instance_count = cnt + multi.visible_instance_count = 0 + multi.mesh = mesh + return multi_inst var rock_mesh = preload("res://world/obstacles/Rock_mesh.tres") var rock_mat = preload("res://world/obstacles/Rock_mat.tres") -func make_rock(chunk,chunk_coords:Vector2): +func gen_rocks(chunk,tree): + rock_mesh.material = rock_mat + var multi = make_multimesh("rocks",200,rock_mesh) + tree.add_child(multi) + iterate_chunk(chunk, multi.multimesh, Vector2(10.0,10.0), funcref(self,"rock_rng"), [0.4,0.6,1.0,4.0,1.0,funcref(self,"make_rock")]) + +var rock_lowres_mesh = preload("res://world/obstacles/Rock_lowres_mesh.tres") +func gen_lowres_rocks(chunk,tree): + rock_lowres_mesh.material = rock_mat + var multi = make_multimesh("rocks",50,rock_lowres_mesh) + tree.add_child(multi) + iterate_chunk(chunk, multi.multimesh, Vector2(20.0,20.0), funcref(self,"rock_rng"), [0.4,0.6,2.0,8.0,0.5,funcref(self,"make_rock")]) + +var rock_coll = preload("res://world/obstacles/Rock_coll.tres") +func gen_rock_hitboxes(chunk,tree): + iterate_chunk(chunk, tree, Vector2(20.0,20.0), funcref(self,"rock_rng"), [0.4,0.6,1.0,4.0,1.0,funcref(self,"make_rock_hitbox")]) + +func rock_rng(chunk,rocks,chunk_coords:Vector2,data): var coords = v3_coords(chunk_coords) var basis = Basis() var world_coords = chunk_coords + v2_coords(chunk.transform.origin) @@ -52,28 +88,23 @@ func make_rock(chunk,chunk_coords:Vector2): var rng_val = self.rng.randf_range(0.0,TAU) basis = Basis(Vector3.UP,rng_val) * basis var noise_val = self.noise.get_noise_2dv(world_coords * 0.125) - if noise_val < 0.4: + if noise_val < data[0]: return - noise_val = min(noise_val,0.6) - noise_val -= 0.4 - noise_val /= 0.2 - noise_val = lerp(1.0,4.0,noise_val) + noise_val = min(noise_val,data[1]) + noise_val -= data[0] + noise_val /= data[1] - data[0] + noise_val = lerp(data[2],data[3],noise_val) basis = basis.scaled(Vector3.ONE*noise_val) - coords.y += (noise_val*5.0)-5.0 - var gen_tree = chunk.get_node("gen_tree") - var rocks = gen_tree.get_node("rocks").multimesh + basis = basis.scaled(Vector3(1.0,data[4],1.0)) + coords.y += (noise_val*data[4]*5.0)-5.0 + data[5].call_func(rocks,Transform(basis,coords)) + +func make_rock(rocks,xform:Transform): rocks.visible_instance_count += 1 - rocks.set_instance_transform(rocks.visible_instance_count-1, Transform(basis,coords)) + rocks.set_instance_transform(rocks.visible_instance_count-1, xform) -func gen_rocks(chunk): - var multi_inst = MultiMeshInstance.new() - multi_inst.name = "rocks" - var multi = MultiMesh.new() - multi_inst.multimesh = multi - chunk.get_node("gen_tree").add_child(multi_inst) - multi.transform_format = MultiMesh.TRANSFORM_3D - multi.instance_count = 1000 - multi.visible_instance_count = 0 - multi.mesh = rock_mesh - rock_mesh.material = rock_mat - iterate_chunk(chunk, Vector2(10.0,10.0), funcref(self,"make_rock")) +func make_rock_hitbox(rocks,xform:Transform): + var shape = CollisionShape.new() + shape.shape = rock_coll + shape.transform = xform + rocks.add_child(shape) diff --git a/world/chunk/ChunkLoader.gd b/world/chunk/ChunkLoader.gd index 2e01bca..42e40bb 100644 --- a/world/chunk/ChunkLoader.gd +++ b/world/chunk/ChunkLoader.gd @@ -3,13 +3,13 @@ extends Node var world = null var Chunk = preload("res://world/chunk/Chunk.tscn") -var chunks = {} var loaded_chunks = {} var chunk_thread = Thread.new() var mtx = Mutex.new() var sgnl = Semaphore.new() var exit = false var chunk_to_load = null +var chunk_to_len func _ready(): chunk_thread.start(self, "chunk_loader") @@ -21,8 +21,11 @@ func _exit_tree(): mtx.unlock() chunk_thread.wait_to_finish() -func add_chunk(coords:Vector2): - chunks[coords] = coords.length() +func v2_coords(coords:Vector3): + return Vector2(coords.x,coords.z) + +func chunk_coords(coords:Vector2): + return coords.snapped(Vector2(world.chunk_size,world.chunk_size)) func free_chunk(coords:Vector2): if !loaded_chunks.has(coords): @@ -33,23 +36,35 @@ func free_chunk(coords:Vector2): loaded_chunks.erase(coords) func chunk_update(): + var chunks = {} + var gen_center = -v2_coords(world.get_node("Chunks").transform.origin) + var gen_radius = world.lod_distance + var gen_radius_rounded = stepify(gen_radius, world.chunk_size) + for x in range(-gen_radius_rounded, gen_radius_rounded+world.chunk_size, world.chunk_size): + for y in range(-gen_radius_rounded, gen_radius_rounded+world.chunk_size, world.chunk_size): + var gen_coords = Vector2(x,y) + if gen_coords.length() > gen_radius: + continue + var coords = chunk_coords(gen_coords + gen_center) + chunks[coords] = coords.length() var closest_unloaded_chunk = null var closest_len = 0.0 for chunk in chunks.keys(): if !loaded_chunks.has(chunk): - if closest_unloaded_chunk == null || closest_len > chunks[chunk]: + var chunk_len = chunks[chunk] + if closest_unloaded_chunk == null || closest_len > chunk_len: closest_unloaded_chunk = chunk - closest_len = chunks[chunk] + closest_len = chunk_len if closest_unloaded_chunk != null: mtx.lock() if chunk_to_load == null: chunk_to_load = closest_unloaded_chunk + chunk_to_len = closest_len sgnl.post() mtx.unlock() for chunk in loaded_chunks.keys(): if !chunks.has(chunk): free_chunk(chunk) - chunks = {} func chunk_loader(): while true: @@ -57,15 +72,18 @@ func chunk_loader(): mtx.lock() var x = exit var coords = chunk_to_load + var owo = chunk_to_len chunk_to_load = null mtx.unlock() if x: break var chunk = Chunk.instance() chunk.transform.origin = Vector3(coords.x,0.0,coords.y) + owo -= world.chunk_size + chunk.lod = 2 if owo <= world.lod_close else 1 if owo <= world.lod_mid else 0 ChunkGen.gen_chunk(chunk) self.call_deferred("finish_chunk", chunk) func finish_chunk(chunk): world.get_node("Chunks").add_child(chunk) - loaded_chunks[Vector2(chunk.transform.origin.x,chunk.transform.origin.z)] = weakref(chunk) + loaded_chunks[v2_coords(chunk.transform.origin)] = weakref(chunk) diff --git a/world/obstacles/Rock.gd b/world/obstacles/Rock.gd deleted file mode 100644 index 577e626..0000000 --- a/world/obstacles/Rock.gd +++ /dev/null @@ -1,18 +0,0 @@ -extends StaticBody - -onready var collision_enabled = self.collision_layer - -func lod_distance(): - $"MeshInstance".visible = false - $"MeshInstance2".visible = true - self.collision_layer = 0 - -func lod_mid(): - $"MeshInstance".visible = true - $"MeshInstance2".visible = false - self.collision_layer = 0 - -func lod_close(): - $"MeshInstance".visible = true - $"MeshInstance2".visible = false - self.collision_layer = collision_enabled diff --git a/world/obstacles/Rock.tscn b/world/obstacles/Rock.tscn deleted file mode 100644 index 819e9a8..0000000 --- a/world/obstacles/Rock.tscn +++ /dev/null @@ -1,32 +0,0 @@ -[gd_scene load_steps=7 format=2] - -[ext_resource path="res://world/obstacles/Rock.gd" type="Script" id=1] -[ext_resource path="res://world/chunk/helper/ChunkedMeshInstance.gd" type="Script" id=2] -[ext_resource path="res://world/obstacles/Rock_mesh.tres" type="PrismMesh" id=3] -[ext_resource path="res://world/obstacles/Rock_mat.tres" type="Material" id=4] - -[sub_resource type="ConvexPolygonShape" id=2] -points = PoolVector3Array( 2.5, -5, 2.5, 2.5, -5, -2.5, -2.5, -5, -2.5, -2.5, -5, 2.5, 0, 5, 2.5, 0, 5, -2.5 ) - -[sub_resource type="CubeMesh" id=9] -size = Vector3( 5, 10, 5 ) - -[node name="Rock" type="StaticBody"] -collision_layer = 8 -collision_mask = 0 -script = ExtResource( 1 ) - -[node name="CollisionShape" type="CollisionShape" parent="."] -shape = SubResource( 2 ) - -[node name="MeshInstance" type="MeshInstance" parent="."] -visible = false -material_override = ExtResource( 4 ) -script = ExtResource( 2 ) -_mesh = ExtResource( 3 ) - -[node name="MeshInstance2" type="MeshInstance" parent="."] -visible = false -material_override = ExtResource( 4 ) -script = ExtResource( 2 ) -_mesh = SubResource( 9 ) diff --git a/world/obstacles/Rock_coll.tres b/world/obstacles/Rock_coll.tres new file mode 100644 index 0000000..b06d080 --- /dev/null +++ b/world/obstacles/Rock_coll.tres @@ -0,0 +1,4 @@ +[gd_resource type="ConvexPolygonShape" format=2] + +[resource] +points = PoolVector3Array( 2.5, -5, 2.5, 2.5, -5, -2.5, -2.5, -5, -2.5, -2.5, -5, 2.5, 0, 5, 2.5, 0, 5, -2.5 ) diff --git a/world/obstacles/Rock_lowres_mesh.tres b/world/obstacles/Rock_lowres_mesh.tres new file mode 100644 index 0000000..910d7f6 --- /dev/null +++ b/world/obstacles/Rock_lowres_mesh.tres @@ -0,0 +1,4 @@ +[gd_resource type="CubeMesh" format=2] + +[resource] +size = Vector3( 5, 10, 5 ) |