def _disable_merged_chunk(self, chunk_coords: Tuple[int, int]): """Zero out the region of memory in the merged chunks related to a given chunk""" if chunk_coords in self._merged_chunk_locations: ( offset, size, translucent_offset, translucent_size, ) = self._merged_chunk_locations.pop(chunk_coords) glBindVertexArray(self._vao) glBindBuffer(GL_ARRAY_BUFFER, self._vbo) glBufferSubData( GL_ARRAY_BUFFER, offset * 4, size * 4, numpy.zeros(size, dtype=numpy.float32), ) glBufferSubData( GL_ARRAY_BUFFER, translucent_offset * 4, translucent_size * 4, numpy.zeros(translucent_size, dtype=numpy.float32), ) glBindVertexArray(0) glBindBuffer(GL_ARRAY_BUFFER, 0)
def paintGL(self): if self.crashFlag: #run cleanup operations glUseProgram(0) glDisableVertexAttribArray(self.attrID) glDeleteBuffers(1,[self.vertexBuffer]) glDeleteVertexArrays(1, [self.vertexArrayID]) glLoadIdentity() gluPerspective(45, self.sizeX / self.sizeY, 0.1, 110.0) #set perspective glTranslatef(0, 0, self.zoomLevel) glRotatef(self.rotateDegreeV + self.vOffset, 1, 0, 0) glRotatef(self.rotateDegreeH, 0, 0, 1) glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) self.vertexData = [ -1, 1, 0, 0, -1, 0, 1, 1, 0 ] arrayType = GLfloat * len(self.vertexData) target = GL_ARRAY_BUFFER offset = 0 size = len(self.vertexData) * ctypes.sizeof(ctypes.c_float) data = arrayType(*self.vertexData) glBufferSubData(target, offset, size, data) glDrawArrays(GL_TRIANGLES, 0, 3)
def glBufferSubData(self, byte_start, byte_length, data): with self: glBufferSubData(GL_ARRAY_BUFFER, byte_start, byte_length, data)
def build(self) -> bool: """ Build OpenGL Vertex Array for the object This function gets automatically called if `self._vao` does not exists in the first render cycle. Once the vba is built, geometry changes or material display mode changes will not be automatically effected. So, in every geometry or display mode change, a `build` call is necessary. If `self.static` is `True`, then the system assumes that another update call is not expected, thus frees `_normals`, `_textcoords`, `_vertices` and `_indices` lists to free memory. So in this case, calling `build` function twice will result in an invisible object (will not be drawn). Returns: bool """ if len(self._indices) == 0: return False # If we don't have a VAO yet, we need to create one if not self.has_vao: # Generate Vertex Array self._vao = glGenVertexArrays(1) # We need 5 buffers (vertex, normal, texcoord, color, indices) self._vbos = glGenBuffers(5) glBindVertexArray(self._vao) # Material shader must be built when there is an active binding # to vertex array self.material.build_shader() else: # Ok, we already have vertex array object, just bind it to modify glBindVertexArray(self._vao) # Turn python arrays into C type arrays using Numpy. # This is required for OpenGL. Python memory model is a bit # different than raw memory model of C (OpenGL) vertices = np.array(self._vertices, dtype=np.float32).flatten() normals = np.array(self._normals, dtype=np.float32).flatten() texcoords = np.array(self._texcoords, dtype=np.float32).flatten() colors = np.array(self._vertex_colors, dtype=np.float32).flatten() indices = np.array(self._indices, dtype=np.int32).flatten() self._calc_bounds() # OpenGL allocates buffers in different mechanisms between # STATIC and DYNAMIC draw modes. If you select STATIC, then OpenGL # will assume that object buffer will not change and allocate it in a # more suitable way. draw = GL_STATIC_DRAW if not self.static: draw = GL_DYNAMIC_DRAW # Buffer overflow, we need more space. if self._buffer_size < vertices.nbytes: self._buffer_size = vertices.nbytes self._buffer_size_changed = True if self._t_buffer_size < texcoords.nbytes: self._t_buffer_size = texcoords.nbytes self._t_buffer_size_changed = True # Bind Vertices glBindBuffer(GL_ARRAY_BUFFER, self._vbos[0]) glEnableVertexAttribArray(0) # shader layout location glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, ctypes.c_void_p(0)) if self._buffer_size_changed: # glBufferData creates a new data area glBufferData(GL_ARRAY_BUFFER, self._buffer_size, vertices, draw) else: # glBufferSubData just replaces memory area in buffer so it is # much more efficient way to handle things. glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.nbytes, vertices) # Bind Normals glBindBuffer(GL_ARRAY_BUFFER, self._vbos[1]) glEnableVertexAttribArray(1) # shader layout location glVertexAttribPointer(1, 3, GL_FLOAT, False, 0, ctypes.c_void_p(0)) if self._buffer_size_changed: glBufferData(GL_ARRAY_BUFFER, self._buffer_size, normals, draw) else: glBufferSubData(GL_ARRAY_BUFFER, 0, normals.nbytes, normals) # Bind TexCoords if len(self._texcoords) == len(self._vertices): glBindBuffer(GL_ARRAY_BUFFER, self._vbos[2]) glEnableVertexAttribArray(2) # shader layout location glVertexAttribPointer(2, 2, GL_FLOAT, False, 0, ctypes.c_void_p(0)) if self._t_buffer_size_changed: glBufferData( GL_ARRAY_BUFFER, self._t_buffer_size, texcoords, draw ) else: glBufferSubData( GL_ARRAY_BUFFER, 0, texcoords.nbytes, texcoords ) # Bind Vertex Colors if len(self._vertex_colors) == len(self._vertices): glBindBuffer(GL_ARRAY_BUFFER, self._vbos[4]) glEnableVertexAttribArray(3) # shader layout location glVertexAttribPointer(3, 3, GL_FLOAT, False, 0, ctypes.c_void_p(0)) self._has_vertex_colors = True if self._buffer_size_changed: glBufferData(GL_ARRAY_BUFFER, self._buffer_size, colors, draw) else: glBufferSubData(GL_ARRAY_BUFFER, 0, colors.nbytes, colors) self._buffer_size_changed = False self._t_buffer_size_changed = False # Bind Indices glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self._vbos[3]) glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.nbytes, indices, draw) self._vertex_count = len(indices) glBindVertexArray(0) glBindBuffer(GL_ARRAY_BUFFER, 0) if self.static: # we can clear this data to free some more memory glDeleteBuffers(4, self._vbos) self._vbos = [] self._needs_update = False return True