summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Chunk.tscn19
-rw-r--r--ChunkGen.gd35
-rw-r--r--ChunkLoader.gd66
-rw-r--r--ChunkedCSGMesh.gd6
-rw-r--r--ChunkedMeshInstance.gd6
-rw-r--r--ChunkedSprite3D.gd6
-rw-r--r--World.gd60
-rw-r--r--World.tscn22
-rw-r--r--project.godot4
9 files changed, 169 insertions, 55 deletions
diff --git a/Chunk.tscn b/Chunk.tscn
index 0d0771e..0437a7e 100644
--- a/Chunk.tscn
+++ b/Chunk.tscn
@@ -1,33 +1,34 @@
-[gd_scene load_steps=6 format=2]
+[gd_scene load_steps=7 format=2]
-[ext_resource path="res://Chunk.gd" type="Script" id=1]
+[ext_resource path="res://ChunkedCSGMesh.gd" type="Script" id=3]
[sub_resource type="SphereShape" id=1]
radius = 50.0
-[sub_resource type="PlaneMesh" id=2]
-size = Vector2( 100, 100 )
-
[sub_resource type="SpatialMaterial" id=3]
flags_unshaded = true
params_cull_mode = 2
albedo_color = Color( 0.937255, 0, 1, 1 )
+[sub_resource type="PlaneMesh" id=2]
+size = Vector2( 100, 100 )
+
[sub_resource type="PlaneMesh" id=4]
size = Vector2( 98, 98 )
[node name="Chunk" type="Area"]
collision_layer = 32
collision_mask = 0
-script = ExtResource( 1 )
[node name="Size" type="CollisionShape" parent="."]
shape = SubResource( 1 )
[node name="Border" type="CSGMesh" parent="."]
-mesh = SubResource( 2 )
-material = SubResource( 3 )
+material_override = SubResource( 3 )
+script = ExtResource( 3 )
+_mesh = SubResource( 2 )
[node name="CSGMesh" type="CSGMesh" parent="Border"]
operation = 2
-mesh = SubResource( 4 )
+script = ExtResource( 3 )
+_mesh = SubResource( 4 )
diff --git a/ChunkGen.gd b/ChunkGen.gd
new file mode 100644
index 0000000..6e1f0eb
--- /dev/null
+++ b/ChunkGen.gd
@@ -0,0 +1,35 @@
+extends Node
+
+var chunk_half_size setget _set_chunk_size
+var chunk_size
+
+func _set_chunk_size(val):
+ chunk_half_size = val
+ chunk_size = val * 2.0
+
+onready var noise = OpenSimplexNoise.new()
+
+func _ready():
+ randomize()
+ noise.seed = randi()
+ noise.octaves = 4
+ noise.period = 64
+ noise.persistence = 0.001
+ noise.lacunarity = 2.0
+
+func gen_chunk(chunk):
+ var gen_tree = Spatial.new()
+ gen_tree.name = "gen_tree"
+ chunk.add_child(gen_tree)
+
+func v2_coords(coords:Vector3):
+ return Vector2(coords.x,coords.z)
+
+func v3_coords(coords:Vector2):
+ return Vector3(coords.x,0.0,coords.y)
+
+func iterate_chunk(chunk,step:Vector2,cb:FuncRef):
+ 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))
diff --git a/ChunkLoader.gd b/ChunkLoader.gd
new file mode 100644
index 0000000..90cac4f
--- /dev/null
+++ b/ChunkLoader.gd
@@ -0,0 +1,66 @@
+extends Node
+
+var world = null
+
+var Chunk = preload("res://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
+
+func _ready():
+ chunk_thread.start(self, "chunk_loader")
+
+func _exit_tree():
+ mtx.lock()
+ exit = true
+ sgnl.post()
+ mtx.unlock()
+ chunk_thread.wait_to_finish()
+
+func add_chunk(coords:Vector2):
+ chunks[coords] = coords.length()
+
+func chunk_update():
+ 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]:
+ closest_unloaded_chunk = chunk
+ closest_len = chunks[chunk]
+ if closest_unloaded_chunk != null:
+ mtx.lock()
+ if chunk_to_load == null:
+ chunk_to_load = closest_unloaded_chunk
+ sgnl.post()
+ mtx.unlock()
+ for chunk in loaded_chunks.keys():
+ if !chunks.has(chunk):
+ var c = loaded_chunks[chunk].get_ref()
+ if c != null:
+ c.queue_free()
+ loaded_chunks.erase(chunk)
+ chunks = {}
+
+func chunk_loader():
+ while true:
+ sgnl.wait()
+ mtx.lock()
+ var x = exit
+ var coords = chunk_to_load
+ chunk_to_load = null
+ mtx.unlock()
+ if x:
+ break
+ var chunk = Chunk.instance()
+ chunk.transform.origin = Vector3(coords.x,0.0,coords.y)
+ 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)
diff --git a/ChunkedCSGMesh.gd b/ChunkedCSGMesh.gd
new file mode 100644
index 0000000..2b8c6db
--- /dev/null
+++ b/ChunkedCSGMesh.gd
@@ -0,0 +1,6 @@
+extends CSGMesh
+
+export(Mesh) var _mesh
+
+func _ready():
+ self.mesh = _mesh
diff --git a/ChunkedMeshInstance.gd b/ChunkedMeshInstance.gd
new file mode 100644
index 0000000..dde7eda
--- /dev/null
+++ b/ChunkedMeshInstance.gd
@@ -0,0 +1,6 @@
+extends MeshInstance
+
+export(Mesh) var _mesh
+
+func _ready():
+ self.mesh = _mesh
diff --git a/ChunkedSprite3D.gd b/ChunkedSprite3D.gd
new file mode 100644
index 0000000..c9e0be9
--- /dev/null
+++ b/ChunkedSprite3D.gd
@@ -0,0 +1,6 @@
+extends Sprite3D
+
+export(Texture) var _tex
+
+func _ready():
+ self.texture = _tex
diff --git a/World.gd b/World.gd
index da811a8..97f0a09 100644
--- a/World.gd
+++ b/World.gd
@@ -4,45 +4,17 @@ export(NodePath) var traveler = null
onready var _traveler = get_node(traveler)
export var acceleration = 10.0
-onready var Chunk = preload("res://Chunk.tscn")
-onready var chunk_size = $"Chunks/Chunk/Size".shape.radius*2.0
-var chunks = {}
+onready var chunk_render_distance = $"ChunkRenderDistance/Radius".shape.radius
-func v2_coords(coords:Vector3):
- return Vector2(coords.x,coords.z)
-
-func v3_coords(coords:Vector2):
- return Vector3(coords.x,0.0,coords.y)
+onready var chunk_half_size = $"Chunks/Chunk/Size".shape.radius
+onready var chunk_size = chunk_half_size * 2.0
-func chunk_coords(coords:Vector2):
- return coords.snapped(Vector2(chunk_size,chunk_size))
-
-func gen_chunk(coords:Vector2):
- var chunk = Chunk.instance()
- chunk.transform.origin = v3_coords(coords)
- $"Chunks".add_child(chunk)
- chunks[coords] = chunk
-
-func gen_chunks():
- var gen_center = -v2_coords($"Chunks".transform.origin)
- var gen_radius = $"ChunkRenderDistance/Radius".shape.radius
- 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)
- if !chunks.has(coords):
- gen_chunk(coords)
+func _ready():
+ ChunkLoader.world = self
+ ChunkGen.chunk_half_size = self.chunk_half_size
func _on_ChunkRenderDistance_area_exited(area:Area):
- gen_chunks()
area.queue_free()
- chunks.erase(v2_coords(area.transform.origin))
-
-func _ready():
- gen_chunks()
func travel(direction:Vector3):
var heading = _traveler.global_transform.basis
@@ -53,6 +25,26 @@ func travel(direction:Vector3):
$"Chunks".add_central_force(direction*acceleration)
func _physics_process(_state):
+ chunk_process()
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()
diff --git a/World.tscn b/World.tscn
index db93160..3bdf371 100644
--- a/World.tscn
+++ b/World.tscn
@@ -1,17 +1,24 @@
-[gd_scene load_steps=5 format=2]
+[gd_scene load_steps=9 format=2]
[ext_resource path="res://World.gd" type="Script" id=1]
[ext_resource path="res://Chunk.tscn" type="PackedScene" id=3]
-[sub_resource type="BoxShape" id=23]
-
[sub_resource type="SphereShape" id=24]
-radius = 300.0
+radius = 500.0
+
+[sub_resource type="BoxShape" id=23]
[node name="World" type="Spatial"]
script = ExtResource( 1 )
acceleration = 50.0
+[node name="ChunkRenderDistance" type="Area" parent="."]
+collision_layer = 0
+collision_mask = 32
+
+[node name="Radius" type="CollisionShape" parent="ChunkRenderDistance"]
+shape = SubResource( 24 )
+
[node name="Chunks" type="RigidBody" parent="."]
collision_layer = 0
collision_mask = 0
@@ -29,11 +36,4 @@ shape = SubResource( 23 )
visible = false
collision_layer = 0
-[node name="ChunkRenderDistance" type="Area" parent="."]
-collision_layer = 0
-collision_mask = 32
-
-[node name="Radius" type="CollisionShape" parent="ChunkRenderDistance"]
-shape = SubResource( 24 )
-
[connection signal="area_exited" from="ChunkRenderDistance" to="." method="_on_ChunkRenderDistance_area_exited"]
diff --git a/project.godot b/project.godot
index 34e666b..a22cfe0 100644
--- a/project.godot
+++ b/project.godot
@@ -27,7 +27,8 @@ config/icon="res://icon.png"
[autoload]
Settings="*res://singletons/settings.gd"
-WorldGenRNG="*res://WorldGenRNG.gd"
+ChunkLoader="*res://ChunkLoader.gd"
+ChunkGen="*res://ChunkGen.gd"
[display]
@@ -121,5 +122,6 @@ common/enable_pause_aware_picking=true
[rendering]
+threads/thread_model=2
quality/filters/msaa=3
environment/default_environment="res://default_env.tres"