adds labyrinth and subjects as well as performance increases

This commit is contained in:
zomseffen 2022-02-07 21:08:45 +01:00
parent 6c5cae958b
commit 0638d5e666
10 changed files with 1591 additions and 234 deletions

View file

@ -19,6 +19,9 @@ class Structure(Renderable):
self.Objects = {}
self.vais = {}
self.dirty = True
self.dirty_pos = True
self.dirty_color = True
self.dirty_size = True
self.x_offset = x_offset
self.y_offset = y_offset
@ -31,6 +34,7 @@ class Structure(Renderable):
@x_offset.setter
def x_offset(self, value):
self.dirty = True
self.dirty_pos = True
self._x_offset = value
@property
@ -40,6 +44,7 @@ class Structure(Renderable):
@y_offset.setter
def y_offset(self, value):
self.dirty = True
self.dirty_pos = True
self._y_offset = value
@property
@ -49,6 +54,7 @@ class Structure(Renderable):
@z_offset.setter
def z_offset(self, value):
self.dirty = True
self.dirty_pos = True
self._z_offset = value
def addShape(self, program, shape):
@ -56,6 +62,9 @@ class Structure(Renderable):
self.Objects[program] = []
self.Objects[program].append(shape)
self.dirty = True
self.dirty_color = True
self.dirty_pos = True
self.dirty_size = True
def removeShape(self, program, shape):
if program in self.Objects.keys():
@ -63,72 +72,89 @@ class Structure(Renderable):
if len(self.Objects[program]) == 0:
self.Objects.pop(program)
self.dirty = True
self.dirty_color = True
self.dirty_pos = True
self.dirty_size = True
def buildvertexArrays(self):
if self.dirty:
self.clearVertexArrays()
# 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)
num = len(objects)
glGenVertexArrays(1, tvai)
needs_new_buffers = key not in self.vais.keys()
if needs_new_buffers:
tvai = GLuint(0)
tpbi = GLuint(0)
tcbi = GLuint(0)
tsbi = GLuint(0)
num = len(objects)
else:
tvai, tpbi, tcbi, tsbi, num = self.vais[key]
if needs_new_buffers:
glGenVertexArrays(1, tvai)
glBindVertexArray(tvai)
if self.dirty_pos:
if needs_new_buffers:
vid = glGetAttribLocation(key, "in_position")
glEnableVertexAttribArray(vid)
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] + self.x_offset)
positions.append(o.pos[1] + self.y_offset)
positions.append(o.pos[2] + self.z_offset)
glBufferData(GL_ARRAY_BUFFER, np.array(positions, dtype=np.float32), GL_STATIC_DRAW)
glVertexAttribPointer(vid, 3, GL_FLOAT, GL_FALSE, 0, None)
self.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)
self.check_error("Could not create color buffer")
if hasattr(objects[0], 'size'):
sizes = []
tpbi = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, tpbi)
positions = []
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)
self.check_error("Could not create size buffer")
positions.append(o.pos[0] + self.x_offset)
positions.append(o.pos[1] + self.y_offset)
positions.append(o.pos[2] + self.z_offset)
glBufferData(GL_ARRAY_BUFFER, np.array(positions, dtype=np.float32), GL_STATIC_DRAW)
if needs_new_buffers:
glVertexAttribPointer(vid, 3, GL_FLOAT, GL_FALSE, 0, None)
self.check_error("Could not create position buffer")
if self.dirty_color:
colors = []
for o in objects:
colors.append(o.color[0])
colors.append(o.color[1])
colors.append(o.color[2])
if needs_new_buffers:
tcbi = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, tcbi)
glBufferData(GL_ARRAY_BUFFER, np.array(colors, dtype=np.float32), GL_STATIC_DRAW)
if needs_new_buffers:
vc = glGetAttribLocation(key, "MyInColor")
if vc != -1:
glEnableVertexAttribArray(vc)
glVertexAttribPointer(vc, 3, GL_FLOAT, GL_FALSE, 0, None)
self.check_error("Could not create color buffer")
if self.dirty_size:
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])
if needs_new_buffers:
tsbi = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, tsbi)
glBufferData(GL_ARRAY_BUFFER, np.array(sizes, dtype=np.float32), GL_STATIC_DRAW)
if needs_new_buffers:
vs = glGetAttribLocation(key, "MyInSize")
if vs != -1:
glEnableVertexAttribArray(vs)
glVertexAttribPointer(vs, 3, GL_FLOAT, GL_FALSE, 0, None)
self.check_error("Could not create size buffer")
glBindVertexArray(0)
self.vais[key] = (tvai, tpbi, tcbi, tsbi, num)
self.dirty = False
self.dirty_pos = False
self.dirty_color = False
self.dirty_size = False
def clearVertexArrays(self):
temp = dict(self.vais)

View file

@ -1,3 +1,5 @@
import time
from Lights.Lights import Light
from Objects.Objects import Object
from Objects.Renderable import Renderable
@ -9,7 +11,8 @@ import math
import numpy as np
import random
import sys
import ctypes
float_pointer = ctypes.POINTER(ctypes.c_float)
# Plate Types
SEA_PLATE = 0
CONTINENTAL_PLATE = 1
@ -22,6 +25,7 @@ METAMORPH_STONE = 3
SEDIMENTAL_STONE = 4
SEDIMENT = 5
class WorldChunk(Structure):
def __init__(self, width: int, length: int, height: int, programs: dict):
assert width > 0, 'Width must be greater than 0'
@ -38,6 +42,8 @@ class WorldChunk(Structure):
self.height = height
self.programs = programs
self.objects = {}
for x in range(width):
self.content.append([])
self.visible.append([])
@ -54,6 +60,7 @@ class WorldChunk(Structure):
assert 0 <= z < self.height, 'Put out of bounds for z coordinate! Must be between 0 and %i' % self.height
no_visibility_changes = (self.content[x][y][z] is None) == (new_object is None)
old_object = self.content[x][y][z]
self.content[x][y][z] = new_object
new_object.translate(translate(x, y, z))
@ -87,6 +94,32 @@ class WorldChunk(Structure):
else:
self.visible[x][y][z - 1] += change
# todo: add visibility check for object listing
added = False
if old_object is not None:
if new_object is not None and type(old_object) == type(new_object):
new_object.buffer_id = old_object.buffer_id
self.objects[self.programs[type(old_object)]][old_object.buffer_id] = new_object
added = True
else:
# todo: maybe replace the element with a placeholder that is skipped when rendering/ saving and have a
# cleanup task, since this could be exploited to lower update rates
leading = self.objects[self.programs[type(old_object)]][:old_object.buffer_id]
following = self.objects[self.programs[type(old_object)]][old_object.buffer_id + 1:]
for element in following:
element.buffer_id -= 1
self.objects[self.programs[type(old_object)]] = leading + following
if not added and new_object is not None:
if self.programs[type(new_object)] not in self.objects.keys():
self.objects[self.programs[type(new_object)]] = []
new_object.buffer_id = len(self.objects[self.programs[type(new_object)]])
self.objects[self.programs[type(new_object)]].append(new_object)
self.dirty = True
self.dirty_pos = True
self.dirty_color = True
self.dirty_size = True
return visible_carry_over
def get_object(self, x: int, y: int, z: int):
@ -112,80 +145,92 @@ class WorldChunk(Structure):
def buildvertexArrays(self):
if self.dirty:
self.clearVertexArrays()
# self.clearVertexArrays()
glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
glEnableClientState(GL_NORMAL_ARRAY)
glEnableClientState(GL_COLOR_ARRAY)
self.vais = {}
objects = {}
counts = {}
for x in range(self.width):
for y in range(self.length):
for z in range(self.height):
if self.content[x][y][z] is not None: # and self.visible[x][y][z] > 0: TODO: check visibility...
if self.programs[type(self.content[x][y][z])] not in objects.keys():
objects[self.programs[type(self.content[x][y][z])]] = []
counts[self.programs[type(self.content[x][y][z])]] = 0
objects[self.programs[type(self.content[x][y][z])]].append(self.content[x][y][z])
counts[self.programs[type(self.content[x][y][z])]] += 1
for key, object_list in self.objects.items():
needs_new_buffers = key not in self.vais.keys()
if needs_new_buffers:
tvai = GLuint(0)
tpbi = GLuint(0)
tcbi = GLuint(0)
tsbi = GLuint(0)
for key, object_list in objects.items():
tvai = GLuint(0)
tpbi = GLuint(0)
tcbi = GLuint(0)
tsbi = GLuint(0)
glGenVertexArrays(1, tvai)
glGenVertexArrays(1, tvai)
else:
tvai, tpbi, tcbi, tsbi, old_len = self.vais[key]
glBindVertexArray(tvai)
vid = glGetAttribLocation(key, "in_position")
glEnableVertexAttribArray(vid)
if self.dirty_pos:
if needs_new_buffers:
vid = glGetAttribLocation(key, "in_position")
glEnableVertexAttribArray(vid)
tpbi = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, tpbi)
positions = []
for index, o in enumerate(object_list):
o.buffer_id = index
positions.append(o.pos[0] + self.x_offset)
positions.append(o.pos[1] + self.y_offset)
positions.append(o.pos[2] + self.z_offset)
tpbi = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, tpbi)
positions = []
for o in object_list:
positions.append(o.pos[0] + self.x_offset)
positions.append(o.pos[1] + self.y_offset)
positions.append(o.pos[2] + self.z_offset)
glBufferData(GL_ARRAY_BUFFER, np.array(positions, dtype=np.float32), GL_STATIC_DRAW)
glVertexAttribPointer(vid, 3, GL_FLOAT, GL_FALSE, 0, None)
self.check_error("Could not create position buffer")
glBufferData(GL_ARRAY_BUFFER, np.array(positions, dtype=np.float32), GL_STATIC_DRAW)
colors = []
for o in object_list:
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)
if needs_new_buffers:
glVertexAttribPointer(vid, 3, GL_FLOAT, GL_FALSE, 0, None)
self.check_error("Could not create position buffer")
if self.dirty_color:
colors = []
for o in object_list:
colors.append(o.color[0])
colors.append(o.color[1])
colors.append(o.color[2])
if needs_new_buffers:
tcbi = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, tcbi)
if needs_new_buffers or old_len != len(object_list):
glBufferData(GL_ARRAY_BUFFER, np.array(colors, dtype=np.float32), GL_STATIC_DRAW)
else:
# todo: check if this improves anything. Timewise it seems to be the same
ptr = ctypes.cast(glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE), float_pointer)
for index, value in enumerate(colors):
ptr[index] = value
glUnmapBuffer(GL_ARRAY_BUFFER)
if needs_new_buffers:
vc = glGetAttribLocation(key, "MyInColor")
if vc != -1:
glEnableVertexAttribArray(vc)
glVertexAttribPointer(vc, 3, GL_FLOAT, GL_FALSE, 0, None)
self.check_error("Could not create color buffer")
if hasattr(object_list[0], 'size'):
sizes = []
for o in object_list:
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)
if self.dirty_size:
if hasattr(object_list[0], 'size'):
sizes = []
for o in object_list:
sizes.append(o.size[0])
sizes.append(o.size[1])
sizes.append(o.size[2])
if needs_new_buffers:
tsbi = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, tsbi)
glBufferData(GL_ARRAY_BUFFER, np.array(sizes, dtype=np.float32), GL_STATIC_DRAW)
if needs_new_buffers:
vs = glGetAttribLocation(key, "MyInSize")
if vs != -1:
glEnableVertexAttribArray(vs)
glVertexAttribPointer(vs, 3, GL_FLOAT, GL_FALSE, 0, None)
self.check_error("Could not create size buffer")
glBindVertexArray(0)
self.vais[key] = (tvai, tpbi, tcbi, tsbi, counts[key])
self.vais[key] = (tvai, tpbi, tcbi, tsbi, len(object_list))
self.dirty = False
self.dirty_pos = False
self.dirty_color = False
self.dirty_size = False
def render(self, proj_matrix, geometry_rot_matrix, alternate_programs=None,
preselected_program=None, projection_pos=None, rot_pos=None):
@ -204,6 +249,17 @@ class WorldChunk(Structure):
if self.content[x][y][z] is not None:
self.content[x][y][z].setColor(r, g, b)
self.dirty = True
self.dirty_color = True
def load(self):
for x in range(self.width):
for y in range(self.length):
for z in range(self.height):
if self.content[x][y][z] is not None: # and self.visible[x][y][z] > 0: TODO: check visibility...
if self.programs[type(self.content[x][y][z])] not in self.objects.keys():
self.objects[self.programs[type(self.content[x][y][z])]] = []
self.objects[self.programs[type(self.content[x][y][z])]].append(self.content[x][y][z])
class World(Renderable):
def __init__(self, chunk_size_x: int, chunk_size_y: int, chunk_size_z: int,
@ -488,6 +544,8 @@ class World(Renderable):
y % self.chunk_size_y,
z % self.chunk_size_z,
r, g, b)
else:
print('Changing color of nonexistant element!')
def put_object(self, x: int, y: int, z: int, new_object: Object):
x = x % (self.chunk_size_x * self.chunk_n_x)