Working, but...
This commit is contained in:
parent
0c042c79d7
commit
b1edaf6fc1
20 changed files with 807 additions and 0 deletions
32
mesh/base.py
Normal file
32
mesh/base.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import numpy
|
||||
|
||||
|
||||
class BaseMesh:
|
||||
def __init__(self):
|
||||
# OpenGL context
|
||||
self.ctx = None
|
||||
# shader program
|
||||
self.program = None
|
||||
# vertex buffer data type format: "3f 3f"
|
||||
self.vbo_format = None
|
||||
# attribute names according to the format: ("in_position", "in_color")
|
||||
self.attributes: tuple[str, ...] = None
|
||||
# vertex array object
|
||||
self.vao = None
|
||||
|
||||
def get_vertex_data(self) -> numpy.array: ...
|
||||
|
||||
def get_vao(self):
|
||||
vertex_data = self.get_vertex_data()
|
||||
vbo = self.ctx.buffer(vertex_data)
|
||||
vao = self.ctx.vertex_array(
|
||||
self.program,
|
||||
[(vbo, self.vbo_format, *self.attributes)],
|
||||
skip_errors=True
|
||||
)
|
||||
return vao
|
||||
|
||||
def render(self):
|
||||
self.vao.render()
|
28
mesh/chunk.py
Normal file
28
mesh/chunk.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
from mesh.base import BaseMesh
|
||||
from mesh.chunk_builder import build_chunk_mesh
|
||||
|
||||
|
||||
class ChunkMesh(BaseMesh):
|
||||
def __init__(self, chunk):
|
||||
super().__init__()
|
||||
self.app = chunk.app
|
||||
self.chunk = chunk
|
||||
self.ctx = self.app.ctx
|
||||
self.program = self.app.shader_program.chunk
|
||||
|
||||
self.vbo_format = "3u1 1u1 1u1 1u1 1u1"
|
||||
self.format_size = sum(int(fmt[:1]) for fmt in self.vbo_format.split())
|
||||
self.attributes = ("in_position", "voxel_id", "face_id", "ao_id", "flip_id")
|
||||
self.vao = self.get_vao()
|
||||
|
||||
def get_vertex_data(self):
|
||||
mesh = build_chunk_mesh(
|
||||
chunk_voxels=self.chunk.voxels,
|
||||
format_size=self.format_size,
|
||||
chunk_pos=self.chunk.position,
|
||||
world_voxels=self.chunk.world.voxels
|
||||
)
|
||||
|
||||
return mesh
|
211
mesh/chunk_builder.py
Normal file
211
mesh/chunk_builder.py
Normal file
|
@ -0,0 +1,211 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
from settings import *
|
||||
from numba import uint8
|
||||
|
||||
|
||||
@njit
|
||||
def get_ao(local_pos, world_pos, world_voxels, plane):
|
||||
x, y, z = local_pos
|
||||
wx, wy, wz = world_pos
|
||||
|
||||
if plane == "Y":
|
||||
a = is_void((x , y, z - 1), (wx , wy, wz - 1), world_voxels)
|
||||
b = is_void((x - 1, y, z - 1), (wx - 1, wy, wz - 1), world_voxels)
|
||||
c = is_void((x - 1, y, z ), (wx - 1, wy, wz ), world_voxels)
|
||||
d = is_void((x - 1, y, z + 1), (wx - 1, wy, wz + 1), world_voxels)
|
||||
e = is_void((x , y, z + 1), (wx , wy, wz + 1), world_voxels)
|
||||
f = is_void((x + 1, y, z + 1), (wx + 1, wy, wz + 1), world_voxels)
|
||||
g = is_void((x + 1, y, z ), (wx + 1, wy, wz ), world_voxels)
|
||||
h = is_void((x + 1, y, z - 1), (wx + 1, wy, wz - 1), world_voxels)
|
||||
|
||||
elif plane == "X":
|
||||
a = is_void((x, y , z - 1), (wx, wy , wz - 1), world_voxels)
|
||||
b = is_void((x, y - 1, z - 1), (wx, wy - 1, wz - 1), world_voxels)
|
||||
c = is_void((x, y - 1, z ), (wx, wy - 1, wz ), world_voxels)
|
||||
d = is_void((x, y - 1, z + 1), (wx, wy - 1, wz + 1), world_voxels)
|
||||
e = is_void((x, y , z + 1), (wx, wy , wz + 1), world_voxels)
|
||||
f = is_void((x, y + 1, z + 1), (wx, wy + 1, wz + 1), world_voxels)
|
||||
g = is_void((x, y + 1, z ), (wx, wy + 1, wz ), world_voxels)
|
||||
h = is_void((x, y + 1, z - 1), (wx, wy + 1, wz - 1), world_voxels)
|
||||
|
||||
else: # Z plane
|
||||
a = is_void((x - 1, y , z), (wx - 1, wy , z), world_voxels)
|
||||
b = is_void((x - 1, y - 1, z), (wx - 1, wy - 1, z), world_voxels)
|
||||
c = is_void((x , y - 1, z), (wx , wy - 1, z), world_voxels)
|
||||
d = is_void((x + 1, y - 1, z), (wx + 1, wy - 1, z), world_voxels)
|
||||
e = is_void((x + 1, y , z), (wx + 1, wy , z), world_voxels)
|
||||
f = is_void((x + 1, y + 1, z), (wx + 1, wy + 1, z), world_voxels)
|
||||
g = is_void((x , y + 1, z), (wx , wy + 1, z), world_voxels)
|
||||
h = is_void((x - 1, y + 1, z), (wx - 1, wy + 1, z), world_voxels)
|
||||
|
||||
ao = (a + b + c), (g + h + a), (e + f + g), (c + d + e)
|
||||
return ao
|
||||
|
||||
|
||||
@njit
|
||||
def to_uint8(x, y, z, voxel_id, face_id, ao_id, flip_id):
|
||||
return (uint8(x), uint8(y), uint8(z),
|
||||
uint8(voxel_id), uint8(face_id), uint8(ao_id), uint8(flip_id)
|
||||
)
|
||||
|
||||
|
||||
@njit
|
||||
def get_chunk_index(world_voxel_pos):
|
||||
wx, wy, wz = world_voxel_pos
|
||||
cx = wx // CHUNK_SIZE
|
||||
cy = wy // CHUNK_SIZE
|
||||
cz = wz // CHUNK_SIZE
|
||||
|
||||
if not (0 <= cx < WORLD_W and 0 <= cy < WORLD_H and 0 <= cz < WORLD_D):
|
||||
return -1
|
||||
|
||||
index = cx + WORLD_W * cz + WORLD_AREA * cy
|
||||
return index
|
||||
|
||||
|
||||
@njit
|
||||
def is_void(local_voxel_pos, world_voxel_pos, world_voxels):
|
||||
chunk_index = get_chunk_index(world_voxel_pos)
|
||||
|
||||
if chunk_index == -1:
|
||||
return False
|
||||
|
||||
chunk_voxels = world_voxels[chunk_index]
|
||||
x, y, z = local_voxel_pos
|
||||
voxel_index = x % CHUNK_SIZE + z % CHUNK_SIZE * CHUNK_SIZE + y % CHUNK_SIZE * CHUNK_AREA
|
||||
|
||||
if chunk_voxels[voxel_index]:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@njit
|
||||
def add_data(vertex_data, index, *vertices):
|
||||
for vertex in vertices:
|
||||
for attribute in vertex:
|
||||
vertex_data[index] = attribute
|
||||
index += 1
|
||||
|
||||
return index
|
||||
|
||||
|
||||
@njit
|
||||
def build_chunk_mesh(chunk_voxels, format_size, chunk_pos, world_voxels):
|
||||
vertex_data = numpy.empty(CHUNK_VOL * 18 * format_size, dtype="uint8")
|
||||
index = 0
|
||||
|
||||
for x in range(CHUNK_SIZE):
|
||||
for y in range(CHUNK_SIZE):
|
||||
for z in range(CHUNK_SIZE):
|
||||
voxel_id = chunk_voxels[x + CHUNK_SIZE * z + CHUNK_AREA * y]
|
||||
|
||||
if not voxel_id:
|
||||
continue
|
||||
|
||||
# voxel world position
|
||||
cx, cy, cz = chunk_pos
|
||||
wx = x + cx * CHUNK_SIZE
|
||||
wy = y + cy * CHUNK_SIZE
|
||||
wz = z + cz * CHUNK_SIZE
|
||||
|
||||
# top face
|
||||
if is_void((x, y + 1, z), (wx, wy + 1, wz), world_voxels):
|
||||
# get ao values
|
||||
ao = get_ao((x, y + 1, z), (wx, wy + 1, wz), world_voxels, plane="Y")
|
||||
flip_id = ao[1] + ao[3] > ao[0] + ao[2]
|
||||
|
||||
# format: x, y, z, voxel_id, face_id, ao_id
|
||||
v0 = to_uint8(x , y + 1, z , voxel_id, 0, ao[0], flip_id)
|
||||
v1 = to_uint8(x + 1, y + 1, z , voxel_id, 0, ao[1], flip_id)
|
||||
v2 = to_uint8(x + 1, y + 1, z + 1, voxel_id, 0, ao[2], flip_id)
|
||||
v3 = to_uint8(x , y + 1, z + 1, voxel_id, 0, ao[3], flip_id)
|
||||
|
||||
if flip_id:
|
||||
index = add_data(vertex_data, index, v1, v0, v3, v1, v3, v2)
|
||||
|
||||
else:
|
||||
index = add_data(vertex_data, index, v0, v3, v2, v0, v2, v1)
|
||||
|
||||
# bottom face
|
||||
if is_void((x, y - 1, z), (wx, wy - 1, wz), world_voxels):
|
||||
ao = get_ao((x, y - 1, z), (wx, wy - 1, wz), world_voxels, plane="Y")
|
||||
flip_id = ao[1] + ao[3] > ao[0] + ao[2]
|
||||
|
||||
v0 = to_uint8(x , y, z , voxel_id, 1, ao[0], flip_id)
|
||||
v1 = to_uint8(x + 1, y, z , voxel_id, 1, ao[1], flip_id)
|
||||
v2 = to_uint8(x + 1, y, z + 1, voxel_id, 1, ao[2], flip_id)
|
||||
v3 = to_uint8(x , y, z + 1, voxel_id, 1, ao[3], flip_id)
|
||||
|
||||
if flip_id:
|
||||
index = add_data(vertex_data, index, v1, v3, v0, v1, v2, v3)
|
||||
|
||||
else:
|
||||
index = add_data(vertex_data, index, v0, v2, v3, v0, v1, v2)
|
||||
|
||||
# right face
|
||||
if is_void((x + 1, y, z), (wx + 1, wy, wz), world_voxels):
|
||||
ao = get_ao((x + 1, y, z), (wx + 1, wy, wz), world_voxels, plane="X")
|
||||
flip_id = ao[1] + ao[3] > ao[0] + ao[2]
|
||||
|
||||
v0 = to_uint8(x + 1, y , z , voxel_id, 2, ao[0], flip_id)
|
||||
v1 = to_uint8(x + 1, y + 1, z , voxel_id, 2, ao[1], flip_id)
|
||||
v2 = to_uint8(x + 1, y + 1, z + 1, voxel_id, 2, ao[2], flip_id)
|
||||
v3 = to_uint8(x + 1, y , z + 1, voxel_id, 2, ao[3], flip_id)
|
||||
|
||||
if flip_id:
|
||||
index = add_data(vertex_data, index, v3, v0, v1, v3, v1, v2)
|
||||
|
||||
else:
|
||||
index = add_data(vertex_data, index, v0, v1, v2, v0, v2, v3)
|
||||
|
||||
# left face
|
||||
if is_void((x - 1, y, z), (wx - 1, wy, wz), world_voxels):
|
||||
ao = get_ao((x - 1, y, z), (wx - 1, wy, wz), world_voxels, plane="X")
|
||||
flip_id = ao[1] + ao[3] > ao[0] + ao[2]
|
||||
|
||||
v0 = to_uint8(x, y , z , voxel_id, 3, ao[0], flip_id)
|
||||
v1 = to_uint8(x, y + 1, z , voxel_id, 3, ao[1], flip_id)
|
||||
v2 = to_uint8(x, y + 1, z + 1, voxel_id, 3, ao[2], flip_id)
|
||||
v3 = to_uint8(x, y , z + 1, voxel_id, 3, ao[3], flip_id)
|
||||
|
||||
if flip_id:
|
||||
index = add_data(vertex_data, index, v3, v1, v0, v3, v2, v1)
|
||||
|
||||
else:
|
||||
index = add_data(vertex_data, index, v0, v2, v1, v0, v3, v2)
|
||||
|
||||
# back face
|
||||
if is_void((x, y, z - 1), (wx, wy, wz - 1), world_voxels):
|
||||
ao = get_ao((x, y, z - 1), (wx, wy, wz - 1), world_voxels, plane="Z")
|
||||
flip_id = ao[1] + ao[3] > ao[0] + ao[2]
|
||||
|
||||
v0 = to_uint8(x , y , z, voxel_id, 4, ao[0], flip_id)
|
||||
v1 = to_uint8(x , y + 1, z, voxel_id, 4, ao[1], flip_id)
|
||||
v2 = to_uint8(x + 1, y + 1, z, voxel_id, 4, ao[2], flip_id)
|
||||
v3 = to_uint8(x + 1, y , z, voxel_id, 4, ao[3], flip_id)
|
||||
|
||||
if flip_id:
|
||||
index = add_data(vertex_data, index, v3, v0, v1, v3, v1, v2)
|
||||
|
||||
else:
|
||||
index = add_data(vertex_data, index, v0, v1, v2, v0, v2, v3)
|
||||
|
||||
# front face
|
||||
if is_void((x, y, z + 1), (wx, wy, wz + 1), world_voxels):
|
||||
ao = get_ao((x, y, z + 1), (wx, wy, wz + 1), world_voxels, plane="Z")
|
||||
flip_id = ao[1] + ao[3] > ao[0] + ao[2]
|
||||
|
||||
v0 = to_uint8(x , y , z + 1, voxel_id, 5, ao[0], flip_id)
|
||||
v1 = to_uint8(x , y + 1, z + 1, voxel_id, 5, ao[1], flip_id)
|
||||
v2 = to_uint8(x + 1, y + 1, z + 1, voxel_id, 5, ao[2], flip_id)
|
||||
v3 = to_uint8(x + 1, y , z + 1, voxel_id, 5, ao[3], flip_id)
|
||||
|
||||
if flip_id:
|
||||
index = add_data(vertex_data, index, v3, v1, v0, v3, v2, v1)
|
||||
|
||||
else:
|
||||
index = add_data(vertex_data, index, v0, v2, v1, v0, v3, v2)
|
||||
|
||||
return vertex_data[:index + 1]
|
31
mesh/quad.py
Normal file
31
mesh/quad.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
from settings import *
|
||||
from mesh.base import BaseMesh
|
||||
|
||||
|
||||
class QuadMesh(BaseMesh):
|
||||
def __init__(self, app):
|
||||
super().__init__()
|
||||
|
||||
self.app = app
|
||||
self.ctx = app.ctx
|
||||
self.program = app.shader_program.quad
|
||||
|
||||
self.vbo_format = "3f 3f"
|
||||
self.attributes = ("in_position", "in_color")
|
||||
self.vao = self.get_vao()
|
||||
|
||||
def get_vertex_data(self):
|
||||
vertices = [
|
||||
(0.5, 0.5, 0.0), (-0.5, 0.5, 0.0), (-0.5, -0.5, 0.0),
|
||||
(0.5, 0.5, 0.0), (-0.5, -0.5, 0.0), (0.5, -0.5, 0.0)
|
||||
]
|
||||
|
||||
colors = [
|
||||
(0, 1, 0), (1, 0, 0), (1, 1, 0),
|
||||
(0, 1, 0), (1, 1, 0), (0, 0, 1)
|
||||
]
|
||||
|
||||
vertex_data = numpy.hstack([vertices, colors], dtype="float32")
|
||||
return vertex_data
|
Loading…
Add table
Add a link
Reference in a new issue