class Geometry: def __init__(self, dynamic=False, material=None, model=None): self._vertices = [] self._indicies = [] self._normals = [] self._texture_coords = [] self._name = "" self._parent = None self._type = None self._centroid = None self.vao = None self.shader = Shader() self.material = material if material else Material() self.model = model if model else Model() self.vertex_attrib = None self.normal_attrib = None self.index_buffer = None self.vertex_buffer = None self.normal_buffer = None self.draw_mode = GL_DYNAMIC_DRAW if dynamic else GL_STATIC_DRAW def get_parent(self): return self._parent def set_parent(self, parent_name): self._parent = parent_name def get_name(self): return self._name def get_type(self): return self._type def get_vertices(self): return self._vertices def get_normals(self): return self._normals def get_texture_coords(self): return self._texture_coords def get_indices(self): return self._indicies def set_vertices(self, verts): self._vertices = verts def create_vao(self): self.vao = glGenVertexArrays(1) def bind(self): glBindVertexArray(self.vao) def bind_vao(self): glBindVertexArray(self.vao) def unbind_vao(self): glBindVertexArray(0) def set_diffuse_texture(self, filename): self.material.set_diffuse_texture("./res/materials/" + filename) def link_material(self): self.shader.link_vec3("material.ambient", self.material.ambient.to_list(), 1) self.shader.link_vec3("material.diffuse", self.material.diffuse.to_list(), 1) self.shader.link_vec3("material.specular", self.material.specular.to_list(), 1) self.shader.link_float("material.alpha", self.material.alpha) self.shader.link_float("material.shininess", self.material.n) if (self.material.diffuseTexture): glActiveTexture(GL_TEXTURE0 + self.material.diffuseTexture) self.shader.link_int("diffuseSamplerExists", 1) self.shader.link_int( "diffuseSampler", self.material.diffuseTexture) glBindTexture(GL_TEXTURE_2D, self.material.diffuseTexture) def link_model(self): model_matrix = glm.mat4() model_matrix = glm.translate(model_matrix, self.model.get_position()) model_matrix = glm.translate(model_matrix, self.get_centroid()) model_matrix *= self.model.get_rotation() model_matrix = glm.scale(model_matrix, self.model.get_scale()) model_matrix = glm.translate(model_matrix, -(self.get_centroid())) glUniformMatrix4fv(glGetUniformLocation( self.shader.program_id, "modelMatrix"), 1, False, model_matrix.to_list()) self.model.set_matrix(model_matrix) def create_vertex_buffer(self): self.vertex_attrib = 0 # No particular reason for 0, # but must match the layout location in the shader. self.vertex_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.vertex_buffer) array_type = (GLfloat * len(self.get_vertices())) glBufferData(GL_ARRAY_BUFFER, len(self.get_vertices()) * ctypes.sizeof(ctypes.c_float), array_type(*self.get_vertices()), self.draw_mode) glEnableVertexAttribArray(self.vertex_attrib) glVertexAttribPointer( self.vertex_attrib, # attribute 0. 3, # components per vertex attribute GL_FLOAT, # type False, # to be normalized? 0, # stride None # array buffer offset ) def create_normal_buffer(self): self.normal_attrib = 1 self.normal_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.normal_buffer) array_type = (GLfloat * len(self.get_normals())) glBufferData(GL_ARRAY_BUFFER, len(self.get_normals()) * ctypes.sizeof(ctypes.c_float), array_type(*self.get_normals()), self.draw_mode) glEnableVertexAttribArray(self.normal_attrib) glVertexAttribPointer( self.normal_attrib, # attribute 0. 3, # components per vertex attribute GL_FLOAT, # type False, # to be normalized? 0, # stride None # array buffer offset ) def create_texture_buffer(self): self.texture_attrib = 2 self.texture_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.texture_buffer) array_type = (GLfloat * len(self.get_texture_coords())) glBufferData(GL_ARRAY_BUFFER, len(self.get_texture_coords()) * ctypes.sizeof(ctypes.c_float), array_type(*self.get_texture_coords()), self.draw_mode) glEnableVertexAttribArray(self.texture_attrib) glVertexAttribPointer( self.texture_attrib, # attribute 0. 2, # components per vertex attribute GL_FLOAT, # type False, # to be normalized? 0, # stride None # array buffer offset ) def create_index_buffer(self): index_buffer = glGenBuffers(1) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer) array_type = (GLuint * len(self.get_indices())) glBufferData( GL_ELEMENT_ARRAY_BUFFER, len(self.get_indices()) * ctypes.sizeof(ctypes.c_uint), array_type(*self.get_indices()), self.draw_mode ) self.index_buffer = index_buffer def update_buffers(self): self.bind_vao() glBindBuffer(GL_ARRAY_BUFFER, self.vertex_buffer) array_type = (GLfloat * len(self.get_vertices())) glBufferData(GL_ARRAY_BUFFER, len(self.get_vertices()) * ctypes.sizeof(ctypes.c_float), array_type(*self.get_vertices()), self.draw_mode) glEnableVertexAttribArray(self.vertex_attrib) glBindBuffer(GL_ARRAY_BUFFER, self.normal_buffer) array_type = (GLfloat * len(self.get_normals())) glBufferData(GL_ARRAY_BUFFER, len(self.get_normals()) * ctypes.sizeof(ctypes.c_float), array_type(*self.get_normals()), self.draw_mode) glEnableVertexAttribArray(self.normal_attrib) glBindBuffer(GL_ARRAY_BUFFER, self.texture_buffer) array_type = (GLfloat * len(self.get_texture_coords())) glBufferData(GL_ARRAY_BUFFER, len(self.get_texture_coords()) * ctypes.sizeof(ctypes.c_float), array_type(*self.get_texture_coords()), self.draw_mode) glEnableVertexAttribArray(self.texture_attrib) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.index_buffer) array_type = (GLuint * len(self.get_indices())) glBufferData( GL_ELEMENT_ARRAY_BUFFER, len(self.get_indices()) * ctypes.sizeof(ctypes.c_uint), array_type(*self.get_indices()), self.draw_mode ) self.unbind_vao() def render(self): glDrawElements(GL_TRIANGLES, len( self.get_indices()), GL_UNSIGNED_INT, ctypes.c_void_p(0)) self.unbind_vao() def setup(self): self.create_vao() self.bind_vao() self.calculate_centroid() self.create_vertex_buffer() self.create_normal_buffer() self.create_texture_buffer() self.create_index_buffer() self.unbind_vao() def rotate(self, vector, angle): self.model.rotate(vector, angle) def scale(self, scale_vec): # print(scale_vec) self.model.scale(scale_vec) def translate(self, trans_vec): self.model.translate(trans_vec) def calculate_centroid(self): center = glm.vec3() for i in range(0, len(self._vertices), 3): center += glm.vec3(self._vertices[i], self._vertices[i + 1], self._vertices[i + 2]) center *= 1/(len(self._vertices)/3) self._centroid = center def get_centroid(self): return self._centroid def set_centroid(self, center): self._centroid = center