@tool extends MeshInstance3D @export var backface_culling: bool @export var tex_div = Vector2(1.0/4.0, 1.0/3.0) var chunk_size: int var array_mesh = ArrayMesh.new() var vertices = PackedVector3Array() var indices = PackedInt32Array() var uvs = PackedVector2Array() var face_count: int var blocks = [] var first_load = true const AXIS := [ Vector3i(1, 0, 0), Vector3i(0, 1, 0), Vector3i(0, 0, 1), ] func _ready() -> void: pass func _process(delta: float) -> void: pass func init_blocks(_chunk_size: int, pos: Vector3i): chunk_size = _chunk_size blocks.resize(chunk_size) for x in range(chunk_size): blocks[x] = [] for y in range(chunk_size): blocks[x].append([]) for z in range(chunk_size): var block_type = get_parent().GetBlock(Vector3i(pos.x + x, pos.y + y, pos.z + z), first_load) blocks[x][y].append(block_type) first_load = false func SetBlockAtPosition(pos: Vector3i, block_type: Block.BlockType): blocks[pos.x][pos.y][pos.z] = block_type func GetBlockAtPosition(pos: Vector3i): return blocks[pos.x][pos.y][pos.z] func generate_chunk(): array_mesh = ArrayMesh.new() vertices = PackedVector3Array() indices = PackedInt32Array() uvs = PackedVector2Array() face_count = 0 for x in range(chunk_size): for y in range(chunk_size): for z in range(chunk_size): if blocks[x][y][z] == Block.BlockType.Air: pass else: generate_cube_mesh(Vector3i(x, y, z)) if not vertices.size() == 0: var array = [] array.resize(Mesh.ARRAY_MAX) array[Mesh.ARRAY_VERTEX] = vertices array[Mesh.ARRAY_INDEX] = indices array[Mesh.ARRAY_TEX_UV] = uvs array_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, array) var trimesh_collision = array_mesh.create_trimesh_shape() var collisionShape3D: CollisionShape3D = find_child("StaticBody3D").find_child("CollisionShape3D") collisionShape3D.set_shape(trimesh_collision) mesh = array_mesh func add_uvs(x, y): uvs.append(Vector2(tex_div.x * x, tex_div.y * y)) uvs.append(Vector2(tex_div.x * x + tex_div.x, tex_div.y * y)) uvs.append(Vector2(tex_div.x * x + tex_div.x, tex_div.y * y + tex_div.y)) uvs.append(Vector2(tex_div.x * x, tex_div.y * y + tex_div.y)) func add_triangles(): indices.append(face_count * 4 + 0) indices.append(face_count * 4 + 1) indices.append(face_count * 4 + 2) indices.append(face_count * 4 + 0) indices.append(face_count * 4 + 2) indices.append(face_count * 4 + 3) face_count += 1 #func generate_smooth_mesh(pos: Vector3i): func generate_cube_mesh(pos: Vector3): var is_top_block = false # face +y if is_block_air(pos + Vector3(0, 1, 0)) || not backface_culling: vertices.append(pos + Vector3(-0.5, 0.5, -0.5)) vertices.append(pos + Vector3(0.5, 0.5, -0.5)) vertices.append(pos + Vector3(0.5, 0.5, 0.5)) vertices.append(pos + Vector3(-0.5, 0.5, 0.5)) add_triangles() add_uvs(1, 0) is_top_block = true # face +x if is_block_air(pos + Vector3(1, 0, 0)) || not backface_culling: vertices.append(pos + Vector3(0.5, 0.5, 0.5)) vertices.append(pos + Vector3(0.5, 0.5, -0.5)) vertices.append(pos + Vector3(0.5, -0.5, -0.5)) vertices.append(pos + Vector3(0.5, -0.5, 0.5)) add_triangles() if is_top_block: add_uvs(1, 1) else: add_uvs(1, 2) # face +z if is_block_air(pos + Vector3(0, 0, 1)) || not backface_culling: vertices.append(pos + Vector3(-0.5, 0.5, 0.5)) vertices.append(pos + Vector3(0.5, 0.5, 0.5)) vertices.append(pos + Vector3(0.5, -0.5, 0.5)) vertices.append(pos + Vector3(-0.5, -0.5, 0.5)) add_triangles() if is_top_block: add_uvs(0, 1) else: add_uvs(1, 2) # face -y if is_block_air(pos + Vector3(0, -1, 0)) || not backface_culling: vertices.append(pos + Vector3(0.5, -0.5, 0.5)) vertices.append(pos + Vector3(0.5, -0.5, -0.5)) vertices.append(pos + Vector3(-0.5, -0.5, -0.5)) vertices.append(pos + Vector3(-0.5, -0.5, 0.5)) add_triangles() add_uvs(1, 2) # face -x if is_block_air(pos + Vector3(-1, 0, 0)) || not backface_culling: vertices.append(pos + Vector3(-0.5, 0.5, -0.5)) vertices.append(pos + Vector3(-0.5, 0.5, 0.5)) vertices.append(pos + Vector3(-0.5, -0.5, 0.5)) vertices.append(pos + Vector3(-0.5, -0.5, -0.5)) add_triangles() if is_top_block: add_uvs(2, 1) else: add_uvs(1, 2) # face -z if is_block_air(pos + Vector3(0, 0, -1)) || not backface_culling: vertices.append(pos + Vector3(0.5, 0.5, -0.5)) vertices.append(pos + Vector3(-0.5, 0.5, -0.5)) vertices.append(pos + Vector3(-0.5, -0.5, -0.5)) vertices.append(pos + Vector3(0.5, -0.5, -0.5)) add_triangles() if is_top_block: add_uvs(0, 1) else: add_uvs(1, 2) func is_block_air(pos: Vector3): # outside of chunk if pos.x < 0 or pos.y < 0 or pos.z < 0: var block = get_parent().GetBlock(pos + position, first_load) return block == Block.BlockType.Air elif pos.x >= chunk_size or pos.y >= chunk_size or pos.z >= chunk_size: var block = get_parent().GetBlock(pos + position, first_load) return block == Block.BlockType.Air else: return blocks[pos.x][pos.y][pos.z] == Block.BlockType.Air