176 lines
5.0 KiB
GDScript
176 lines
5.0 KiB
GDScript
@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
|