diff options
Diffstat (limited to 'chunk.gd')
-rw-r--r-- | chunk.gd | 353 |
1 files changed, 282 insertions, 71 deletions
@@ -1,90 +1,301 @@ class_name Chunk -extends Node +extends Node3D -var chunk_size := Vector3(16, 16, 16) +var grid_position := Vector3i.ZERO +var mesh: ArrayMesh = ArrayMesh.new() @export var noise: FastNoiseLite +@export var blocks: Array = [] -var blocks: Array[Block] = [] - -func generate_chunk(row, column, depth): - #var material := StandardMaterial3D.new() - #material.albedo_texture = preload("res://new_atlas_texture.tres") - #material.vertex_color_use_as_albedo = true - var material := preload("res://new_shader_material.tres") - var st = SurfaceTool.new() - st.begin(Mesh.PRIMITIVE_TRIANGLES) - st.set_material(material) +func generate_block_data(row: int, column: int, depth: int, empty: bool = false): + grid_position = Vector3i(row, column, depth) - var blocks = [] + blocks = [] + blocks.resize(Global.CHUNK_SIZE.x * Global.CHUNK_SIZE.y * Global.CHUNK_SIZE.z) - for x in chunk_size.x: - #blocks[x] = [] - blocks.append([]) - for y in chunk_size.y: - #blocks[x][y] = [] - blocks[x].append([]) - for z in chunk_size.z: - var block_position = Vector3( - row*chunk_size.x + x, - column*chunk_size.y + y, - depth*chunk_size.z + z - #x, - #y, - #z - ) * 2 - var value = noise.get_noise_3d(block_position.x, block_position.y, block_position.z) * 100 + for x in Global.CHUNK_SIZE.x: + for z in Global.CHUNK_SIZE.z: + var block_position := Vector3i(x, 0, z) + var block_global_position := Vector3i( + grid_position.x * Global.CHUNK_SIZE.x + block_position.x, + 0, + grid_position.z * Global.CHUNK_SIZE.z + block_position.z + ) + var height := Global.CHUNK_SIZE.y + + if grid_position.y >= Global.GROUND_LEVEL: + var noise_2d := noise.get_noise_2d( + block_global_position.x, + block_global_position.z + ) * 100 + height = round(clamp(abs(noise_2d), 0, Global.CHUNK_SIZE.y)) + + for y in Global.CHUNK_SIZE.y: + block_position.y = y + block_global_position. y = grid_position.y * Global.CHUNK_SIZE.y + block_position.y + + var value = noise.get_noise_3d( + block_global_position.x, + block_global_position.y, + block_global_position.z + ) * 100 - var type = Block.Type.AIR - if value > -15: - type = Block.Type.GRASS - elif value > -20: - type = Block.Type.STONE + var type := Block.Type.AIR + if height < y: + type = Block.Type.AIR + else: + if value > -15: + type = Block.Type.GRASS + elif value > -20: + type = Block.Type.STONE + #if value > 4: + #type = Block.Type.GRASS + #if value < -4: + #type = Block.Type.STONE + ##if value < -16: + ##type = Block.Type.DIRT + #if value < -17 and value > -20: + #type = Block.Type.SAND + #if abs(value) > 21 and abs(value) < 21.25: + #type = [Block.Type.STONE, Block.Type.YELLOW_STONE, Block.Type.BLUE_STONE, Block.Type.RED_STONE, Block.Type.BLACK_STONE].pick_random() + ##print(value) var block = Block.new() block.position = block_position + block.global_position = block_global_position block.type = type - blocks[x][y].append(block) - - for x in blocks.size(): - for y in blocks[x].size(): - for z in blocks[x][y].size(): - var block = blocks[x][y][z] - var block_position = block.position + if empty or Global.MAX_HEIGHT < block.global_position.y: + block.type = Block.Type.AIR - if not block.type == Block.Type.AIR: - if block.type == Block.Type.GRASS and blocks[x].size() > y + 1 and not blocks[x][y + 1][z].type == Block.Type.AIR: - block.type = Block.Type.DIRT - - var rng = RandomNumberGenerator.new() - rng.seed = randi() - st.set_color(Color(rng.randf(), rng.randf(), rng.randf())) - - st.set_uv(Vector2(0, 0)) - - if (blocks[x][y].size() > z+1 and blocks[x][y][z + 1].type == Block.Type.AIR) or blocks[x][y].size() == z+1: - block.add_face(st, Block.Face.FRONT, block) - - if (blocks.size() > x+1 and blocks[x + 1][y][z].type == Block.Type.AIR) or blocks.size() == x+1: - block.add_face(st, Block.Face.RIGHT) - - if blocks[x][y].size() > z-1 and (blocks[x][y][z - 1].type == Block.Type.AIR or z == 0): - block.add_face(st, Block.Face.BACK) - - if blocks.size() > x-1 and (blocks[x - 1][y][z].type == Block.Type.AIR or x == 0): - block.add_face(st, Block.Face.LEFT) - - if (blocks[x].size() > y+1 and blocks[x][y + 1][z].type == Block.Type.AIR) or blocks[x].size() == y+1: - block.add_face(st, Block.Face.TOP) - - if blocks[x].size() > y-1 and (blocks[x][y - 1][z].type == Block.Type.AIR or y == 0): - block.add_face(st, Block.Face.BOTTOM) + var index := x + Global.CHUNK_SIZE.x * y + Global.CHUNK_SIZE.x * Global.CHUNK_SIZE.y * z + blocks[index] = block + + +func generate_mesh(): + var material := preload("res://new_shader_material.tres") + var st = SurfaceTool.new() + st.begin(Mesh.PRIMITIVE_TRIANGLES) + st.set_material(material) + + for index in blocks.size(): + var block: Block = blocks[index] + if block.type == Block.Type.AIR: + continue + + var block_front: Block + if is_chunk_border_face(block.position, Block.Face.BACK): + if chunk_exists(grid_position + Vector3i(0, 0, 1)): + var chunk_front := Global.chunks[grid_position + Vector3i(0, 0, 1)] + if chunk_front.is_inside_tree(): + block_front = chunk_front.get_block(Vector3i(block.position.x, block.position.y, 0)) + else: + block_front = get_block(block.position + Vector3i(0, 0, 1)) + + var block_back: Block + if is_chunk_border_face(block.position, Block.Face.FRONT): + if chunk_exists(grid_position + Vector3i(0, 0, -1)): + var chunk_back := Global.chunks[grid_position + Vector3i(0, 0, -1)] + if chunk_back.is_inside_tree(): + block_back = chunk_back.get_block(Vector3i( + block.position.x, block.position.y, Global.CHUNK_SIZE.z - 1) + ) + else: + block_back = get_block(block.position + Vector3i(0, 0, -1)) + + var block_right: Block + if is_chunk_border_face(block.position, Block.Face.RIGHT): + if chunk_exists(grid_position + Vector3i(1, 0, 0)): + var chunk_right := Global.chunks[grid_position + Vector3i(1, 0, 0)] + if chunk_right.is_inside_tree(): + block_right = chunk_right.get_block(Vector3i(0, block.position.y, block.position.z)) + else: + block_right = get_block(block.position + Vector3i(1, 0, 0)) + + var block_left: Block + if is_chunk_border_face(block.position, Block.Face.LEFT): + if chunk_exists(grid_position + Vector3i(-1, 0, 0)): + var chunk_left := Global.chunks[grid_position + Vector3i(-1, 0, 0)] + if chunk_left.is_inside_tree(): + block_left = chunk_left.get_block(Vector3i( + Global.CHUNK_SIZE.x - 1, block.position.y, block.position.z) + ) + else: + block_left = get_block(block.position + Vector3i(-1, 0, 0)) + + var block_top: Block + if is_chunk_border_face(block.position, Block.Face.TOP): + if chunk_exists(grid_position + Vector3i(0, 1, 0)): + var chunk_top := Global.chunks[grid_position + Vector3i(0, 1, 0)] + if chunk_top.is_inside_tree(): + block_top = chunk_top.get_block(Vector3i(block.position.x, 0, block.position.z)) + else: + block_top = get_block(block.position + Vector3i(0, 1, 0)) + + var block_bottom: Block + if is_chunk_border_face(block.position, Block.Face.BOTTOM): + if chunk_exists(grid_position + Vector3i(0, -1, 0)): + var chunk_bottom := Global.chunks[grid_position + Vector3i(0, -1, 0)] + if chunk_bottom.is_inside_tree(): + block_bottom = chunk_bottom.get_block(Vector3i( + block.position.x, Global.CHUNK_SIZE.y - 1, block.position.z) + ) + else: + block_bottom = get_block(block.position + Vector3i(0, -1, 0)) + + if not block.type == Block.Type.AIR: + if block.type == Block.Type.GRASS: + if block_top and block_top.type != Block.Type.AIR: + block.type = Block.Type.DIRT + elif block.type == Block.Type.DIRT: + if not block_top or block_top.type == Block.Type.AIR: + block.type = Block.Type.GRASS + + var rng = RandomNumberGenerator.new() + rng.seed = randi() + st.set_color(Color(rng.randf(), rng.randf(), rng.randf())) + + st.set_uv(Vector2(0, 0)) + + if not block_front or block_front.type == Block.Type.AIR: + block.add_face(st, Block.Face.FRONT) + + if not block_back or block_back.type == Block.Type.AIR: + block.add_face(st, Block.Face.BACK) + + if not block_right or block_right.type == Block.Type.AIR: + block.add_face(st, Block.Face.RIGHT) + + if not block_left or block_left.type == Block.Type.AIR: + block.add_face(st, Block.Face.LEFT) + + if not block_top or block_top.type == Block.Type.AIR: + block.add_face(st, Block.Face.TOP) + + if not block_bottom or block_bottom.type == Block.Type.AIR: + block.add_face(st, Block.Face.BOTTOM) #st.generate_normals() - var mesh = MeshInstance3D.new() - mesh.mesh = st.commit() - mesh.create_trimesh_collision() + mesh = st.commit() + + +func update_mesh() -> void: + $MeshInstance3D.mesh = mesh + + var shape := ConcavePolygonShape3D.new() + var faces := mesh.get_faces() + if faces.size() > 0: + shape.set_faces(mesh.get_faces()) + $StaticBody3D/CollisionShape3D.shape = shape + + +func add_to(node: Node) -> void: + name = "Chunk_%s_%s_%s" % [grid_position.x, grid_position.y, grid_position.z] + node.add_child(self, true) + update_mesh() + + +func generate_chunk(row: int, column: int, depth: int): + if blocks.is_empty(): + generate_block_data(row, column, depth) + + generate_mesh() + + +func add_block(block_position: Vector3, block_type: Block.Type = Block.Type.GRASS) -> void: + var block = Block.new() + block.position = Vector3i(block_position) + block.global_position = Vector3i( + grid_position.x * Global.CHUNK_SIZE.x + block.position.x, + grid_position.y * Global.CHUNK_SIZE.y + block.position.y, + grid_position.z * Global.CHUNK_SIZE.z + block.position.z + ) + block.type = block_type + + #blocks[block_position.x][block_position.y][block_position.z] = block + set_block(block.position, block) + #generate_mesh.call_deferred() + + +func remove_block(block_position: Vector3) -> void: + #blocks[block_position.x][block_position.y][block_position.z].type = Block.Type.AIR + var block := get_block(block_position) + block.type = Block.Type.AIR + set_block(block.position, block) + print(block_position) + + +func get_block(p: Vector3i) -> Block: + return blocks[p.x + Global.CHUNK_SIZE.x * p.y + Global.CHUNK_SIZE.x * Global.CHUNK_SIZE.y * p.z] + +func set_block(p: Vector3i, block: Block) -> void: + blocks[p.x + Global.CHUNK_SIZE.x * p.y + Global.CHUNK_SIZE.x * Global.CHUNK_SIZE.y * p.z] = block + + +static func chunk_exists(chunk_position: Vector3i): + return Global.chunks.has(chunk_position) + #return x >= 0 and chunks.size() - 1 >= x and y >= 0 and chunks[x].size() - 1 >= y and z >= 0 and chunks[x][y].size() - 1 >= z + +func block_exists(x: int, y: int, z: int): + return x >= 0 and blocks.size() - 1 >= x and y >= 0 and blocks[x].size() - 1 >= y and z >= 0 and blocks[x][y].size() - 1 >= z + +func is_chunk_border(p: Vector3i): + return p.x == 0 or p.x == Global.CHUNK_SIZE.x - 1 or p.y == 0 or p.y == Global.CHUNK_SIZE.y - 1 or p.z == 0 or p.z == Global.CHUNK_SIZE.z - 1 + +func is_chunk_border_face(block_position: Vector3i, face: Block.Face) -> bool: + if face == Block.Face.FRONT: + return block_position.z == 0 + elif face == Block.Face.BACK: + return block_position.z == Global.CHUNK_SIZE.z - 1 + elif face == Block.Face.LEFT: + return block_position.x == 0 + elif face == Block.Face.RIGHT: + return block_position.x == Global.CHUNK_SIZE.z - 1 + elif face == Block.Face.BOTTOM: + return block_position.y == 0 + elif face == Block.Face.TOP: + return block_position.y == Global.CHUNK_SIZE.y - 1 + + return false + +func get_bordering_chunks(block_position: Vector3i) -> Array[Vector3i]: + var bordering_chunks := [] as Array[Vector3i] + + if not is_chunk_border(block_position): + return bordering_chunks + + if block_position.z == 0: + bordering_chunks.append(grid_position + Vector3i(0, 0, -1)) + elif block_position.z == Global.CHUNK_SIZE.z - 1: + bordering_chunks.append(grid_position + Vector3i(0, 0, 1)) + + if block_position.x == 0: + bordering_chunks.append(grid_position + Vector3i(-1, 0, 0)) + elif block_position.x == Global.CHUNK_SIZE.x - 1: + bordering_chunks.append(grid_position + Vector3i(1, 0, 0)) + + if block_position.y == 0: + bordering_chunks.append(grid_position + Vector3i(0, -1, 0)) + elif block_position.y == Global.CHUNK_SIZE.y - 1: + bordering_chunks.append(grid_position + Vector3i(0, 1, 0)) + + return bordering_chunks + +func get_neighboring_blocks(_block_position: Vector3i) -> Array[Vector3i]: + return [] + + +@warning_ignore("shadowed_variable_base_class") +static func global_to_chunk(global_position: Vector3, normal: Vector3) -> Vector3i: + return floor((global_position - normal * (Block.BLOCK_SIZE * 0.5)) / Vector3(Global.CHUNK_SIZE)) + +@warning_ignore("shadowed_variable_base_class") +static func global_to_chunk_block(global_position: Vector3, normal: Vector3) -> Vector3i: + return global_to_block(global_position, normal) - Global.CHUNK_SIZE * global_to_chunk(global_position, normal) + +@warning_ignore("shadowed_variable_base_class") +static func global_to_block(global_position: Vector3, normal: Vector3) -> Vector3i: + return floor(global_position - normal * (Block.BLOCK_SIZE * 0.5)) |