class_name Main extends Node3D var chunk_size := Vector3(16, 16, 16) @onready var noise := FastNoiseLite.new() var face_corners = [ Vector2(0, 0), Vector2(1, 0), Vector2(0, 1), Vector2(1, 1), ] enum BlockFace { FRONT, BACK, LEFT, RIGHT, TOP, BOTTOM, } var block_faces = [ [ # FRONT [Vector3(-1.0, 1.0, 1.0), Vector3(1.0, -1.0, 1.0), Vector3(-1.0, -1.0, 1.0)], [Vector3(-1.0, 1.0, 1.0), Vector3(1.0, 1.0, 1.0), Vector3(1.0, -1.0, 1.0)], ], [ # BACK [Vector3(1.0, 1.0, -1.0), Vector3(-1.0, -1.0, -1.0), Vector3(1.0, -1.0, -1.0)], [Vector3(1.0, 1.0, -1.0), Vector3(-1.0, 1.0, -1.0), Vector3(-1.0, -1.0, -1.0)], ], [ # LEFT [Vector3(-1.0, 1.0, -1.0), Vector3(-1.0, -1.0, 1.0), Vector3(-1.0, -1.0, -1.0)], [Vector3(-1.0, 1.0, -1.0), Vector3(-1.0, 1.0, 1.0), Vector3(-1.0, -1.0, 1.0)], ], [ # RIGHT [Vector3(1.0, 1.0, 1.0), Vector3(1.0, -1.0, -1.0), Vector3(1.0, -1.0, 1.0)], [Vector3(1.0, 1.0, 1.0), Vector3(1.0, 1.0, -1.0), Vector3(1.0, -1.0, -1.0)], ], [ # TOP [Vector3(-1.0, 1.0, -1.0), Vector3(1.0, 1.0, 1.0), Vector3(-1.0, 1.0, 1.0)], [Vector3(-1.0, 1.0, -1.0), Vector3(1.0, 1.0, -1.0), Vector3(1.0, 1.0, 1.0)], ], [ # BOTTOM [Vector3(-1.0, -1.0, 1.0), Vector3(1.0, -1.0, -1.0), Vector3(-1.0, -1.0, -1.0)], [Vector3(-1.0, -1.0, 1.0), Vector3(1.0, -1.0, 1.0), Vector3(1.0, -1.0, -1.0)], ], ] var block_face_uvs = [ [ # FRONT [Vector2(0.0, 0.0), Vector2(1.0, 1.0), Vector2(0.0, 1.0)], [Vector2(0.0, 0.0), Vector2(1.0, 0.0), Vector2(1.0, 1.0)], ], [ # BACK [Vector2(0.0, 0.0), Vector2(1.0, 1.0), Vector2(0.0, 1.0)], [Vector2(0.0, 0.0), Vector2(1.0, 0.0), Vector2(1.0, 1.0)], ], [ # LEFT [Vector2(0.0, 0.0), Vector2(1.0, 1.0), Vector2(0.0, 1.0)], [Vector2(0.0, 0.0), Vector2(1.0, 0.0), Vector2(1.0, 1.0)], ], [ # RIGHT [Vector2(0.0, 0.0), Vector2(1.0, 1.0), Vector2(0.0, 1.0)], [Vector2(0.0, 0.0), Vector2(1.0, 0.0), Vector2(1.0, 1.0)], ], [ # TOP [Vector2(0.0, 1.0), Vector2(1.0, 2.0), Vector2(0.0, 2.0)], [Vector2(0.0, 1.0), Vector2(1.0, 1.0), Vector2(1.0, 2.0)], ], [ # BOTTOM [Vector2(1.0, 0.0), Vector2(2.0, 1.0), Vector2(1.0, 1.0)], [Vector2(1.0, 0.0), Vector2(2.0, 0.0), Vector2(2.0, 1.0)], ], ] var block_face_normals = [ Vector3(0, 0, 1), # FRONT Vector3(0, 0, -1), # BACK Vector3(-1, 0, 0), # LEFT Vector3(1, 0, 0), # RIGHT Vector3(0, 1, 0), # TOP Vector3(0, -1, 0), # BOTTOM ] enum BlockType { AIR, GRASS, DIRT, LEAVES, STONE, } var block_types = { BlockType.GRASS: { "uv2s": [ Vector2(0, 0), # FRONT Vector2(0, 0), # BACK Vector2(0, 0), # LEFT Vector2(0, 0), # RIGHT Vector2(0, 1), # TOP Vector2(1, 0), # BOTTOM ], }, BlockType.DIRT: { "uv2s": [ Vector2(1, 0), # FRONT Vector2(1, 0), # BACK Vector2(1, 0), # LEFT Vector2(1, 0), # RIGHT Vector2(1, 0), # TOP Vector2(1, 0), # BOTTOM ], }, BlockType.LEAVES: { "uv2s": [ Vector2(2, 2), # FRONT Vector2(2, 2), # BACK Vector2(2, 2), # LEFT Vector2(2, 2), # RIGHT Vector2(2, 2), # TOP Vector2(2, 2), # BOTTOM ], }, BlockType.STONE: { "uv2s": [ Vector2(2, 0), # FRONT Vector2(2, 0), # BACK Vector2(2, 0), # LEFT Vector2(2, 0), # RIGHT Vector2(2, 0), # TOP Vector2(2, 0), # BOTTOM ], }, } var chunks := [] func _ready() -> void: brrr() class OtherThread extends Thread: func _exit_tree(): wait_to_finish() func brrr(): noise.seed = randi() var thread = OtherThread.new() var rrrb = func(): for row in range(0, 8): chunks.append([]) for column in range(0, 4): chunks[row].append([]) for depth in range(0, 8): chunks[row][column].append([]) generate_chunk(row, column, depth) thread.start(rrrb) #thread.wait_to_finish() 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) var blocks = [] 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 var type = BlockType.AIR if value > -15: type = BlockType.GRASS elif value > -20: type = BlockType.STONE var block = { "position": block_position, "type": type, } #blocks[x][y][z] = block_position 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 not block.type == BlockType.AIR: if block.type == BlockType.GRASS and blocks[x].size() > y + 1 and not blocks[x][y + 1][z].type == BlockType.AIR: block.type = BlockType.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 == BlockType.AIR) or blocks[x][y].size() == z+1: add_face(st, BlockFace.FRONT, block) if (blocks.size() > x+1 and blocks[x + 1][y][z].type == BlockType.AIR) or blocks.size() == x+1: add_face(st, BlockFace.RIGHT, block) if blocks[x][y].size() > z-1 and (blocks[x][y][z - 1].type == BlockType.AIR or z == 0): add_face(st, BlockFace.BACK, block) if blocks.size() > x-1 and (blocks[x - 1][y][z].type == BlockType.AIR or x == 0): add_face(st, BlockFace.LEFT, block) if (blocks[x].size() > y+1 and blocks[x][y + 1][z].type == BlockType.AIR) or blocks[x].size() == y+1: add_face(st, BlockFace.TOP, block) if blocks[x].size() > y-1 and (blocks[x][y - 1][z].type == BlockType.AIR or y == 0): add_face(st, BlockFace.BOTTOM, block) chunks[row][column][depth] = blocks #st.generate_normals() var mesh = MeshInstance3D.new() mesh.mesh = st.commit() mesh.create_trimesh_collision() add_child.call_deferred(mesh) # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(_delta: float) -> void: pass func add_face(surface_tool: SurfaceTool, face: BlockFace, block: Dictionary): var block_position: Vector3 = block.position var type: BlockType = block.type var uv2s = [] uv2s.resize(3) uv2s.fill(block_types[type].uv2s[face]) var normals = [] normals.resize(3) normals.fill(block_face_normals[face]) for idx in block_faces[face].size(): var triangle = block_faces[face][idx] var triangle_positions = triangle.map(func(item): return item + block_position ) var uvs = block_face_uvs[face][idx] surface_tool.add_triangle_fan( PackedVector3Array(triangle_positions), PackedVector2Array(uvs), PackedColorArray(), PackedVector2Array(uv2s), PackedVector3Array(normals) )