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 Objects.Renderable import Renderable class Structure(Renderable): def __init__(self, x_offset=0, y_offset=1, z_offset=0): 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 self.z_offset = z_offset @property def x_offset(self): return self._x_offset @x_offset.setter def x_offset(self, value): self.dirty = True self.dirty_pos = True self._x_offset = value @property def y_offset(self): return self._y_offset @y_offset.setter def y_offset(self, value): self.dirty = True self.dirty_pos = True self._y_offset = value @property def z_offset(self): return self._z_offset @z_offset.setter def z_offset(self, value): self.dirty = True self.dirty_pos = True self._z_offset = value def addShape(self, program, shape): if not program in self.Objects.keys(): 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(): self.Objects[program].remove(shape) 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() glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_TEXTURE_COORD_ARRAY) glEnableClientState(GL_NORMAL_ARRAY) glEnableClientState(GL_COLOR_ARRAY) for key, objects 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) 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) 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) 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) self.vais = {} for key, vertex_array_ids in temp.items(): if vertex_array_ids[1] != -1 and vertex_array_ids[1] != GLuint(-1): glDeleteBuffers(1, [vertex_array_ids[1]]) self.check_error("Could not destroy buffer") if vertex_array_ids[2] != -1 and vertex_array_ids[2] != GLuint(-1): glDeleteBuffers(1, [vertex_array_ids[2]]) self.check_error("Could not destroy buffer") if vertex_array_ids[3] != -1 and vertex_array_ids[3] != GLuint(-1): glDeleteBuffers(1, [vertex_array_ids[3]]) self.check_error("Could not destroy buffer") glDeleteVertexArrays(1, vertex_array_ids[0]) self.check_error("Could not destroy vertex array") def render(self, projMatrix, geometryRotMatrix, alternateprograms=None, preselected_program=None, projection_pos=None, rot_pos=None): self.buildvertexArrays() for key, vertex_array_ids in self.vais.items(): if alternateprograms == None: program_id = key else: assert key in alternateprograms.keys() program_id = alternateprograms[key] # check if a program was preloaded if preselected_program is not None: # if preloaded we only want to render the matching vertex arrays if preselected_program != program_id: continue else: glUseProgram(program_id) self.check_error("Renderingprogram is not initialized!") if rot_pos is None: rot = glGetUniformLocation(program_id, 'rotMatrix') glUniformMatrix3fv(rot, 1, GL_FALSE, np.array(geometryRotMatrix)) if projection_pos is None: projection = glGetUniformLocation(program_id, 'projModelViewMatrix') glUniformMatrix4fv(projection, 1, GL_FALSE, np.array(projMatrix)) glBindVertexArray(vertex_array_ids[0]) glDrawArrays(GL_POINTS, 0, vertex_array_ids[4]) self.check_error("Rendering problem") glBindVertexArray(0) if preselected_program is None: 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, preselected_program=None, projection_pos=None, rot_pos=None): for (structure, M, R) in self.Structures: structure.render(M * projMatrix, R * geometryRotMatrix, alternateprograms, preselected_program, projection_pos, rot_pos) def __eq__(self, other): if type(other) is type(self): return self.Structures == other.Structures else: return False