Remise des chunks + charger les chunks proche de la caméra en priorité

pull/52/head
Valentin Stark 3 years ago
parent abe2611f29
commit 74bfc0c163
  1. 6
      project.godot
  2. 2
      utils/world_generation/WorldGeneration.gd
  3. 77
      world/Chunk.gd
  4. 95
      world/World3d.gd

@ -19,6 +19,11 @@ _global_script_classes=[ {
"language": "GDScript", "language": "GDScript",
"path": "res://utils/camera/outline.gd" "path": "res://utils/camera/outline.gd"
}, { }, {
"base": "Spatial",
"class": "Chunk",
"language": "GDScript",
"path": "res://world/Chunk.gd"
}, {
"base": "Reference", "base": "Reference",
"class": "Delaunator", "class": "Delaunator",
"language": "GDScript", "language": "GDScript",
@ -52,6 +57,7 @@ _global_script_classes=[ {
_global_script_class_icons={ _global_script_class_icons={
"CameraController": "", "CameraController": "",
"CameraOutline": "", "CameraOutline": "",
"Chunk": "",
"Delaunator": "", "Delaunator": "",
"LoadingHelper": "", "LoadingHelper": "",
"PoissonDiscSampling": "", "PoissonDiscSampling": "",

@ -260,7 +260,7 @@ func fill_oceans():
stack.append(first_center.get_index()) stack.append(first_center.get_index())
while stack.size(): while stack.size():
var current_point_id = stack.pop_back() var current_point_id = stack.pop_front()
Global.terrain.get_point(current_point_id).set_data("ocean", true) Global.terrain.get_point(current_point_id).set_data("ocean", true)
for neighbour in Global.terrain.get_point(current_point_id).points_around(): for neighbour in Global.terrain.get_point(current_point_id).points_around():
if neighbour.get_data("water") and not neighbour.get_data("ocean"): if neighbour.get_data("water") and not neighbour.get_data("ocean"):

@ -0,0 +1,77 @@
extends Spatial
class_name Chunk
var noise
var should_remove = true
var x
var z
var empty = true
func _init(x, z):
self.x = x
self.z = z
func _ready():
generate_chunk()
pass
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)
# print(x)
# print(z)
for center in Global.terrain.get_chunk(Vector2(x, z)):
# print(center.get_data("water"))
if not center.get_data("water"):
empty = false
# print(center.get_data("material"))
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)
if not empty:
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)

@ -8,7 +8,8 @@ var unready_chunks = {}
var thread var thread
func _ready(): func _ready():
add_world() # add_world()
thread = Thread.new()
add_trees() add_trees()
func add_world(): func add_world():
@ -40,3 +41,95 @@ func add_trees():
tree.rotate_y(rng.randi_range(0, 2*PI)) tree.rotate_y(rng.randi_range(0, 2*PI))
tree.translation = Vector3(point.x, center.get_elevation() * 120, point.y) tree.translation = Vector3(point.x, center.get_elevation() * 120, point.y)
add_child(tree) 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]
# print(x)
# print(z)
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
var c_x = int(camera_translation.x) / chunk_size
var c_z = int(camera_translation.y) / chunk_size * -1
var stack = []
var used = []
stack.append(Vector2(c_x, c_z))
while stack.size():
var current_vector = stack.pop_back()
used.append(current_vector)
add_chunk(current_vector.x, current_vector.y)
var chunk = get_chunk(current_vector.x, current_vector.y)
if chunk != null:
chunk.should_remove = false
var neighbours = [
Vector2(current_vector.x, current_vector.y - 1), # n
Vector2(current_vector.x + 1, current_vector.y - 1), # n_e
Vector2(current_vector.x + 1, current_vector.y), # e
Vector2(current_vector.x + 1, current_vector.y + 1), # s_e
Vector2(current_vector.x, current_vector.y + 1), # s
Vector2(current_vector.x - 1, current_vector.y + 1), # s_w
Vector2(current_vector.x - 1, current_vector.y), # w
Vector2(current_vector.x - 1, current_vector.y - 1) # n_w
]
for neighbour in neighbours:
if(
neighbour.x >= c_x - chunk_amount * 0.5
and neighbour.x <= c_x + chunk_amount * 0.5
and neighbour.y >= c_z - chunk_amount * 0.5
and neighbour.y <= c_z + chunk_amount * 0.53
and not neighbour in used
):
stack.append(neighbour)
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

Loading…
Cancel
Save