VoxelEngine/Objects/Structure.py
2020-09-12 12:39:51 +02:00

253 lines
9.2 KiB
Python

from wsgiref.validate import check_errors
from OpenGL.GL.ARB.vertex_array_object import glDeleteVertexArrays
from OpenGL.GL.framebufferobjects import glBindFramebuffer
from OpenGL.GLUT import *
import OpenGL.GLUT.freeglut
from OpenGL.GLU import *
from OpenGL.GL import *
import numpy as np
from OpenGL.extensions import alternate
from Objects.Objects import Object
from MatrixStuff.Transformations import translate
def check_error(message):
gl_error = glGetError()
if (gl_error != GL_NO_ERROR):
print("Error: " + message)
if (gluErrorString(gl_error)):
print(gluErrorString(gl_error))
else:
print(hex(gl_error))
return True
return False
class Renderable:
def render(self, projMatrix, geometryRotMatrix, alternateprograms=None):
pass
class Structure(Renderable):
def __init__(self):
self.Objects = {}
self.vais = {}
self.Matrix = np.identity(4, np.float32)
self.dirty = False
def addShape(self, program, shape):
if not program in self.Objects.keys():
self.Objects[program] = []
self.Objects[program].append(shape)
self.dirty = True
def removeShape(self, program, shape):
if program in self.Objects.keys():
self.Objects[program].remove(shape)
if len(self.Objects[program]) == 0:
self.Objects.pop(program)
self.dirty = True
def buildvertexArrays(self):
if self.dirty:
self.clearVertexArrays()
glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
glEnableClientState(GL_NORMAL_ARRAY)
glEnableClientState(GL_COLOR_ARRAY)
self.vais = {}
for key, objects in self.Objects.items():
tvai = GLuint(0)
tpbi = GLuint(0)
tcbi = GLuint(0)
tsbi = GLuint(0)
glGenVertexArrays(1, tvai)
glBindVertexArray(tvai)
vid = glGetAttribLocation(key, "in_position")
glEnableVertexAttribArray(vid)
tpbi = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, tpbi)
positions = []
for o in objects:
positions.append(o.pos[0])
positions.append(o.pos[1])
positions.append(o.pos[2])
glBufferData(GL_ARRAY_BUFFER, np.array(positions, dtype=np.float32), GL_STATIC_DRAW)
glVertexAttribPointer(vid, 3, GL_FLOAT, GL_FALSE, 0, None)
check_error("Could not create position buffer")
colors = []
for o in objects:
colors.append(o.color[0])
colors.append(o.color[1])
colors.append(o.color[2])
tcbi = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, tcbi)
glBufferData(GL_ARRAY_BUFFER, np.array(colors, dtype=np.float32), GL_STATIC_DRAW)
vc = glGetAttribLocation(key, "MyInColor")
if vc != -1:
glEnableVertexAttribArray(vc)
glVertexAttribPointer(vc, 3, GL_FLOAT, GL_FALSE, 0, None)
check_error("Could not create color buffer")
if hasattr(objects[0], 'size'):
sizes = []
for o in objects:
sizes.append(o.size[0])
sizes.append(o.size[1])
sizes.append(o.size[2])
tsbi = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, tsbi)
glBufferData(GL_ARRAY_BUFFER, np.array(sizes, dtype=np.float32), GL_STATIC_DRAW)
vs = glGetAttribLocation(key, "MyInSize")
if vs != -1:
glEnableVertexAttribArray(vs)
glVertexAttribPointer(vs, 3, GL_FLOAT, GL_FALSE, 0, None)
check_error("Could not create size buffer")
glBindVertexArray(0)
self.vais[key] = (tvai, tpbi, tcbi, tsbi)
self.dirty = False
def clearVertexArrays(self):
for key, (a, p, c, s) in self.vais.items():
if p != -1:
glDisableVertexAttribArray(p)
glDeleteBuffers(1, [p])
if c != -1:
glDisableVertexAttribArray(c)
glDeleteBuffers(1, [c])
if s != -1 and s != GLuint(-1):
glDisableVertexAttribArray(s)
glDeleteBuffers(1, [s])
glDeleteVertexArrays(1, a)
check_error("Could not destroy vertex array")
def render(self, projMatrix, geometryRotMatrix, alternateprograms=None):
for key, tupel in self.vais.items():
if alternateprograms == None:
program_id = key
else:
assert key in alternateprograms
program_id = alternateprograms[key]
glUseProgram(program_id)
check_error("Renderingprogram is not initialized!")
projection = glGetUniformLocation(program_id, 'projModelViewMatrix')
rot = glGetUniformLocation(program_id, 'rotMatrix')
glUniformMatrix4fv(projection, 1, GL_FALSE, np.array(projMatrix))
glUniformMatrix3fv(rot, 1, GL_FALSE, np.array(geometryRotMatrix))
glBindVertexArray(tupel[0])
glDrawArrays(GL_POINTS, 0, len(self.Objects[key]))
check_error("Rendering problem")
glBindVertexArray(0)
glUseProgram(0)
def __eq__(self, other):
if type(other) is type(self):
return self.vais == other.vais and self.Objects == other.Objects
else:
return False
class CompoundStructure(Renderable):
def __init__(self):
self.Structures = []
def addStructure(self, structure: Structure, M: np.matrix = np.identity(4, np.float),
R: np.matrix = np.identity(3, np.float)):
self.Structures.append((structure, M, R))
def render(self, projMatrix, geometryRotMatrix, alternateprograms=None):
for (structure, M, R) in self.Structures:
structure.buildvertexArrays()
structure.render(M * projMatrix, R * geometryRotMatrix, alternateprograms)
def __eq__(self, other):
if type(other) is type(self):
return self.Structures == other.Structures
else:
return False
class WorldChunk(Renderable):
def __init__(self, width, length, height):
assert width > 0, 'Width must be greater than 0'
assert length > 0, 'length must be greater than 0'
assert height > 0, 'height must be greater than 0'
self.visible = []
self.content = []
self.entities = []
self.width = width
self.length = length
self.height = height
for x in range(width):
self.content.append([])
self.visible.append([])
for y in range(length):
self.content[x].append([])
self.visible[x].append([])
for z in range(height):
self.content[x][y].append(None)
self.visible[x][y].append(4)
def put_object(self, x: int, y: int, z: int, new_object: Object):
assert 0 <= x < self.width, 'Put out of bounds for x coordinate! Must be between 0 and %i' % self.width
assert 0 <= y < self.length, 'Put out of bounds for y coordinate! Must be between 0 and %i' % self.length
assert 0 <= z < self.height, 'Put out of bounds for z coordinate! Must be between 0 and %i' % self.height
self.content[x][y][z] = new_object
change = -1 if new_object is not None else 1
visible_carry_over = []
if x + 1 >= self.width:
visible_carry_over.append((1, 0, 0, change))
else:
self.visible[x + 1][y][z] += change
if x - 1 < 0:
visible_carry_over.append((-1, 0, 0, change))
else:
self.visible[x - 1][y][z] += change
if y + 1 >= self.length:
visible_carry_over.append((0, 1, 0, change))
else:
self.visible[x][y + 1][z] += change
if y - 1 < 0:
visible_carry_over.append((0, -1, 0, change))
else:
self.visible[x][y - 1][z] += change
if z + 1 >= self.height:
visible_carry_over.append((0, 0, 1, change))
else:
self.visible[x][y][z + 1] += change
if z - 1 < 0:
visible_carry_over.append((0, 0, -1, change))
else:
self.visible[x][y][z - 1] += change
return visible_carry_over
def render(self, projMatrix, geometryRotMatrix, alternateprograms=None):
for x in range(self.width):
for y in range(self.length):
for z in range(self.height):
if self.visible[x][y][z] > 0 and self.content[x][y][z] is not None:
self.content[x][y][z].render(translate(x, y, z) * projMatrix,
geometryRotMatrix, alternateprograms)
for entity in self.entities:
entity.render(projMatrix, geometryRotMatrix, alternateprograms)