Posts: 544 Threads: 15 Joined: Oct 2016 import numpy as np class BoxProperty: def __init__(self, pos, pos2=None, div=False): self.pos = pos self.pos2 = pos2 self.div = [1.0, 0.5][div] def __get__(self, instance, owner): if self.pos2 is None: return instance[self.pos] return instance[self.pos] + instance[self.pos2] * self.div def __set__(self, instance, value): if self.pos2 is None: instance[self.pos] = value else: instance[self.pos] = value - instance[self.pos2] * self.div class BoxCombineProperty: def __init__(self, pos1, pos2, pos3): if isinstance(pos1, (tuple, list)): self.pos1 = BoxProperty(*pos1) else: self.pos1 = BoxProperty(pos1) if isinstance(pos2, (tuple, list)): self.pos2 = BoxProperty(*pos2) else: self.pos2 = BoxProperty(pos2) if isinstance(pos3, (tuple, list)): self.pos3 = BoxProperty(*pos3) else: self.pos3 = BoxProperty(pos3) def __get__(self, instance, owner): return (self.pos1.__get__(instance, owner), self.pos2.__get__(instance, owner), self.pos3.__get__(instance, owner)) def __set__(self, instance, value): self.pos1.__set__(instance, value[0]) self.pos2.__set__(instance, value[1]) self.pos3.__set__(instance, value[2]) class ArrayProperty: def __init__(self, position): self.position = position def __get__(self, instance, owner): return instance[self.position] def __set__(self, instance, value): instance[self.position] = value class BoundingBox(np.ndarray): def __new__(cls, x, y, z, w, h, d): return np.asarray((x, y, z, w, h, d)).view(cls) def collidepoint(self, x, y=None, z=None): if y is None: x, y, z = x if (self.left < x < self.right and self.top < y < self.bottom and self.front < z < self.back): return True return False def collidebox(self, box): return ( ((self[0] > box[0] and self[0] < box[3] + box[0]) or (box[0] > self[0] and box[0] < self[3] + self[0])) and ((self[1] > box[1] and self[1] < box[4] + box[1]) or (box[1] > self[1] and box[1] < self[4] + self[1])) and ((self[2] > box[2] and self[2] < box[5] + box[2]) or (box[2] > self[2] and box[2] < self[5] + self[2]))) #return ( ((self.left > box.left and self.left < box.right) or # (box.left > self.left and box.left < self.right)) and # ((self.top > box.top and self.top < box.bottom) or # (box.top > self.top and box.top < self.bottom)) and # ((self.front > box.front and self.front < box.back) or # (box.front > self.front and box.front < self.back))) def _clamp(self, box): x, y, z = self[:3] clamp = 'xyz' if self[3] >= box[3]: x = box[0] + box[3] / 2 - self[3] / 2 elif self[0] < box[0]: x = box[0] elif self[0] + self[3] > box[0] + box[3]: x = box[0] + box[3] - self[3] else: clamp = 'yz' if self[4] >= box[4]: y = box[1] + box[4] / 2 - self[4] / 2 elif self[1] < box[1]: y = box[1] elif self[1] + self[4] > box[1] + box[4]: y = box[1] + box[4] - self[4] else: if clamp == 'yz': clamp = 'z' else: clamp = 'xz' if self[5] >= box[5]: z = box[2] + box[5] / 2 - self[5] / 2 elif self[2] < box[2]: z = box[2] elif self[2] + self[5] > box[2] + box[5]: z = box[2] + box[5] - self[5] else: if clamp == 'z': clamp = None elif clamp == 'yz': clamp = 'y' elif clamp == 'xz': clamp = 'x' else: clamp = 'xy' return x, y, z, clamp def clamp(self, box): c = self._clamp(box) return BoundingBox(*c[:3], *self[3:]), c[3] def clamp_ip(self, box): c = self._clamp(box) self[:3] = c[:3] return c[3] x = ArrayProperty(0) y = ArrayProperty(1) z = ArrayProperty(2) w = ArrayProperty(3) h = ArrayProperty(4) d = ArrayProperty(5) left = ArrayProperty(0) top = ArrayProperty(1) front = ArrayProperty(2) right = BoxProperty(0, 3) bottom = BoxProperty(1, 4) back = BoxProperty(2, 5) topleft_front = BoxCombineProperty(0, 1, 2) topright_front = BoxCombineProperty((0, 3), 1, 2) bottomleft_front = BoxCombineProperty(0, (1, 4), 2) bottomright_front = BoxCombineProperty((0, 3), (1, 4), 2) topleft_back = BoxCombineProperty(0, 1, (2, 5)) topright_back = BoxCombineProperty((0, 3), 1, (2, 5)) bottomleft_back = BoxCombineProperty(0, (1, 4), (2, 5)) bottomright_back = BoxCombineProperty((0, 3), (1, 4), (2, 5)) center = BoxCombineProperty((0, 3, 1), (1, 4, 1), (2, 5, 1)) boxsize = BoxCombineProperty(3, 4, 5) centerx = BoxProperty(0, 3, 1) centery = BoxProperty(1, 4, 1) centerz = BoxProperty(2, 5, 1) def main(): a = BoundingBox(10,10,10,50,50,50) b = BoundingBox(40,40,40,30,30,30) c = BoundingBox(10,60,10,50,50,50) print(a) print(a.collidebox(b)) print(a.collidebox(c)) print(b.collidebox(c)) print(a.collidepoint(45, 20, 45)) print(b.collidepoint(45, 20, 45)) print() #a[:3] -= 20 # move in place print(a) screen = BoundingBox(0,0,50,800,600,250) clamp = a.clamp_ip(screen) print(a, clamp) print(screen) print(screen.center) if __name__ == '__main__': main() Example pyglet import pyglet from pyglet.gl import * from pyglet.graphics.vertexbuffer import create_buffer from boundingbox import BoundingBox from random import randrange import numpy as np import ctypes import math import os # base on gl3n row major def perspective(width, height, fov, near, far): array = np.array([0 for i in range(16)], dtype=GLfloat).reshape(4,4) mat = np.matrix(array) aspect = width/height top = near * math.tan(fov * (math.pi/360.0)) bottom = -top right = top * aspect left = -right mat[0,0] = (2 * near) / (right - left) mat[0,2] = (right + left) / (right - left) mat[1,1] = (2 * near) / (top - bottom) mat[1,2] = (top + bottom) / (top - bottom) mat[2,2] = -(far + near) / (far - near) mat[2,3] = -(2 * far + near) / (far - near) mat[3,2] = -1 return mat def normalized(array): if np.linalg.norm(array) != 0: return array / np.linalg.norm(array) return array def matrix_idenity(): return np.matrix(np.identity(4, GLfloat)) def look_at(eye, target, up): look_dir = normalized(target - eye) up_dir = normalized(up) right_dir = normalized(np.cross(look_dir, up_dir)) perp_up_dir = np.cross(right_dir, look_dir) mat = matrix_idenity() mat[0] = np.append(right_dir, [-np.dot(eye, right_dir)]) mat[1] = np.append(perp_up_dir, [-np.dot(eye, perp_up_dir)]) mat[2] = np.append(-look_dir, [np.dot(eye, look_dir)]) return mat def unit_vector(data): data = np.array(data, dtype=GLfloat, copy=True) if data.ndim == 1: data /= math.sqrt(np.dot(data, data)) return data def rotation(alpha, axis): cosa = math.cos(alpha) sina = math.sin(alpha) axis = unit_vector(axis) R = np.diag([cosa, cosa, cosa]) R += np.outer(axis, axis) * (1.0 - cosa) axis *= sina R += np.array([[0.0, -axis[2], axis[1]], [axis[2], 0.0, -axis[0]], [-axis[1], axis[0], 0.0]], GLfloat) M = np.identity(4) M[:3, :3] = R return M class Face: FRONT = 1 # counter clockwise BACK = 2 LEFT = 4 # counter clockwise RIGHT = 8 TOP = 16 # counter clockwise BOTTOM = 32 ALL = 63 def create_cube(size, face=Face.ALL, element=True): array = np.array([ size, size, size, #0 + + + right top front -size, -size, -size, #1 - - - left bottom back size, -size, -size, #2 + - - right bottom back size, size, -size, #3 + + - right top back -size, size, -size, #4 - + - left top back -size, size, size, #5 - + + left top front -size, -size, size, #6 - - + left bottom front size, -size, size #7 + - + right bottom front ], GLfloat) elements = np.array([], GLuint) if face & Face.BACK: elements = np.append(elements, [1,3,2,3,1,4]) if face & Face.FRONT: elements = np.append(elements, [6,7,0,0,5,6]) if face & Face.LEFT: elements = np.append(elements, [5,4,1,1,6,5]) if face & Face.RIGHT: elements = np.append(elements, [0,2,3,2,0,7]) if face & Face.TOP: elements = np.append(elements, [4,0,3,0,4,5]) if face & Face.BOTTOM: elements = np.append(elements, [1,2,7,7,6,1]) if element: return array, elements pylist = [] for i in elements: n = i * 3 pylist.extend(array[n:n + 3]) return np.array(pylist, GLfloat) class Shader: def __init__(self, vstring, fstring): self.program = GLuint(glCreateProgram()) if not os.path.exists(vstring): print(vstring, "doesn't exists") return if not os.path.exists(fstring): print(fstring, "doesn't exists") return vbuffer = open(vstring, 'r') vshader = glCreateShader(GL_VERTEX_SHADER) vbuff = ctypes.create_string_buffer(vbuffer.read().encode()) vtext = ctypes.cast(ctypes.pointer(ctypes.pointer(vbuff)), ctypes.POINTER(ctypes.POINTER(GLchar))) glShaderSource(vshader, 1, vtext, None) glCompileShader(vshader) success = GLint() infoLog = ctypes.create_string_buffer(512) glGetShaderiv(vshader, GL_COMPILE_STATUS, ctypes.byref(success)) if not success: glGetShaderInfoLog(vshader, 512, None, infoLog) print("Error: Vertex Shader ", infoLog.value) fbuffer = open(fstring, 'r') fshader = glCreateShader(GL_FRAGMENT_SHADER) fbuff = ctypes.create_string_buffer(fbuffer.read().encode()) ftext = ctypes.cast(ctypes.pointer(ctypes.pointer(fbuff)), ctypes.POINTER(ctypes.POINTER(GLchar))) glShaderSource(fshader, 1, ftext, None) glCompileShader(fshader) glGetShaderiv(fshader, GL_COMPILE_STATUS, ctypes.byref(success)) if not success: glGetShaderInfoLog(fshader, 512, None, infoLog) print("Error: Fragment Shader ", infoLog.value) glAttachShader(self.program, vshader) glAttachShader(self.program, fshader) glLinkProgram(self.program) glGetProgramiv(self.program, GL_LINK_STATUS, ctypes.byref(success)) if not success: glGetShaderInfoLog(fshader, 512, None, infoLog) print("Error: Program ", infoLog.value) # clean up glDeleteShader(vshader) glDeleteShader(fshader) vbuffer.close() fbuffer.close() def uniformMatrix4fv(self, key, count, transpose, value): buff = ctypes.create_string_buffer(key.encode()) location = glGetUniformLocation(self.program, buff) nvalue = np.array(value, GLfloat) # .flatten() nref = nvalue.ctypes.data_as(ctypes.POINTER(ctypes.c_float)) glUniformMatrix4fv(location, count, transpose, nref) def use(self): glUseProgram(self.program) def destroy(self): glDeleteProgram(self.program) class CubeRandom: def __init__(self, w, h): ar = np.arange(0, 1, 0.1) self.box = BoundingBox(np.random.choice(ar), np.random.choice(ar), np.random.choice(ar), 0.1, 0.1, 0.1).astype(float) speed = np.arange(0, 0.05, 0.002) self.dir = np.array([np.random.choice(speed) for i in range(3)]) def move(self, screenbox): screenbox = BoundingBox(0.0, 0.0, 0.0, 2.0, 2.0, 2.0) self.box[:3] += self.dir clamp = self.box.clamp_ip(screenbox) if clamp is None: return if 'x' in clamp: self.dir[0] = -self.dir[0] if 'y' in clamp: self.dir[1] = -self.dir[1] if 'z' in clamp: self.dir[2] = -self.dir[2] class Window(pyglet.window.Window): def __init__(self): pyglet.window.Window.__init__(self) self.context.config.alpha_size = 8 self.context.config.buffer_size = 32 self.context.config.sample_buffers = 1 self.context.config.samples = 4 glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) glClearColor(0.1, 0.0, 0.0, 1.0) glViewport(0, 0, self.width, self.height) self.model = matrix_idenity() self.view = look_at( np.array([4,3,3], dtype=GLfloat), np.array([0,0,0], dtype=GLfloat), np.array([0,1,0], dtype=GLfloat)) self.projection = perspective(self.width, self.height, 45.0, 1.0, 100.0) self.mvp = self.projection * self.view * self.model self.vertices = create_cube(0.1, element=False) print("How many vertices.", len(self.vertices) / 3) color_choice = [[1.0,0.0,0.0], [0.0,1.0,0.0], [0.0,0.0,1.0], [1.0,0.0,1.0], [1.0,1.0,0.0], [0.0,0.5,1.0]] colors = [] for i in range(6): color = color_choice[i] colors.extend(color + color + color + color + color + color) self.colors = np.array(colors, GLfloat) print("How many colors.", len(self.colors) / 3) self.vao = GLuint() glGenVertexArrays(1, self.vao) glBindVertexArray(self.vao) self.vbo = create_buffer(self.vertices.nbytes, GL_ARRAY_BUFFER, GL_STATIC_DRAW) self.vbo.set_data(self.vertices.ctypes.data) self.vbo.bind() glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(0); self.color_vbo = create_buffer(self.colors.nbytes, GL_ARRAY_BUFFER, GL_STATIC_DRAW) self.color_vbo.set_data(self.colors.ctypes.data) self.color_vbo.bind() glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(1); glBindVertexArray(0); self.tick = 0.0 self.shader = Shader('vshader.glsl', 'fshader.glsl') pyglet.clock.schedule_interval(self.tick_update, 1.0 / 30.0) self.screenbox = BoundingBox(0,0,10, self.width, self.height, 100) self.cubes = [CubeRandom(self.width, self.height) for i in range(6)] def tick_update(self, dt): self.tick += dt #self.model = rotation(self.tick, np.array([0.2, 0.4, 0.2], GLfloat)) for cube in self.cubes: cube.move(self.screenbox) #self.mvp = self.projection * self.view * self.model def on_draw(self): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.shader.use() #self.shader.uniformMatrix4fv('mvp', 1, GL_TRUE, self.mvp) glBindVertexArray(self.vao); for cube in self.cubes: model = np.identity(4) model[0::1, 3][:3] = cube.box[:3] mvp = self.projection * self.view * np.matrix(model) self.shader.uniformMatrix4fv('mvp', 1, GL_TRUE, mvp) glDrawArrays(GL_TRIANGLES, 0, len(self.vertices)) glBindVertexArray(0) def clean_up(self): self.shader.destroy() self.vbo.delete() self.color_vbo.delete() glDeleteVertexArrays(1, self.vao) if __name__ == '__main__': window = Window() pyglet.app.run() window.clean_up() 99 percent of computer problems exists between chair and keyboard. Posts: 544 Threads: 15 Joined: Oct 2016 Jan-06-2018, 12:41 AM (This post was last modified: Jan-06-2018, 12:41 AM by Windspar.) Made very small improvement import numpy as np class BoxProperty: def __init__(self, pos, pos2=None, div=False): self.pos = pos self.pos2 = pos2 self.div = [1.0, 0.5][div] def __get__(self, instance, owner): if self.pos2 is None: return instance[self.pos] return instance[self.pos] + instance[self.pos2] * self.div def __set__(self, instance, value): if self.pos2 is None: instance[self.pos] = value else: instance[self.pos] = value - instance[self.pos2] * self.div class BoxCombineProperty: def __init__(self, pos1, pos2, pos3): if isinstance(pos1, (tuple, list)): self.pos1 = BoxProperty(*pos1) else: self.pos1 = BoxProperty(pos1) if isinstance(pos2, (tuple, list)): self.pos2 = BoxProperty(*pos2) else: self.pos2 = BoxProperty(pos2) if isinstance(pos3, (tuple, list)): self.pos3 = BoxProperty(*pos3) else: self.pos3 = BoxProperty(pos3) def __get__(self, instance, owner): return (self.pos1.__get__(instance, owner), self.pos2.__get__(instance, owner), self.pos3.__get__(instance, owner)) def __set__(self, instance, value): self.pos1.__set__(instance, value[0]) self.pos2.__set__(instance, value[1]) self.pos3.__set__(instance, value[2]) class ArrayProperty: def __init__(self, position): self.position = position def __get__(self, instance, owner): return instance[self.position] def __set__(self, instance, value): instance[self.position] = value class BoundingBox(np.ndarray): def __new__(cls, x, y, z, w, h, d): return np.asarray((x, y, z, w, h, d)).view(cls) def collidepoint(self, x, y=None, z=None): if y is None: x, y, z = x if (self.left < x < self.right and self.top < y < self.bottom and self.front < z < self.back): return True return False def collidebox(self, box): return ( ((self[0] > box[0] and self[0] < box[3] + box[0]) or (box[0] > self[0] and box[0] < self[3] + self[0])) and ((self[1] > box[1] and self[1] < box[4] + box[1]) or (box[1] > self[1] and box[1] < self[4] + self[1])) and ((self[2] > box[2] and self[2] < box[5] + box[2]) or (box[2] > self[2] and box[2] < self[5] + self[2]))) #return ( ((self.left > box.left and self.left < box.right) or # (box.left > self.left and box.left < self.right)) and # ((self.top > box.top and self.top < box.bottom) or # (box.top > self.top and box.top < self.bottom)) and # ((self.front > box.front and self.front < box.back) or # (box.front > self.front and box.front < self.back))) def _clamp(self, box): x, y, z = self[:3] clamp = 'xyz' if self[3] >= box[3]: x = box[0] + box[3] / 2 - self[3] / 2 elif self[0] < box[0]: x = box[0] elif self[0] + self[3] > box[0] + box[3]: x = box[0] + box[3] - self[3] else: clamp = 'yz' if self[4] >= box[4]: y = box[1] + box[4] / 2 - self[4] / 2 elif self[1] < box[1]: y = box[1] elif self[1] + self[4] > box[1] + box[4]: y = box[1] + box[4] - self[4] else: clamp = clamp.replace('y', '') if self[5] >= box[5]: z = box[2] + box[5] / 2 - self[5] / 2 elif self[2] < box[2]: z = box[2] elif self[2] + self[5] > box[2] + box[5]: z = box[2] + box[5] - self[5] else: clamp = clamp.replace('z', '') return x, y, z, clamp def clamp(self, box): c = self._clamp(box) return BoundingBox(*c[:3], *self[3:]), c[3] def clamp_ip(self, box): c = self._clamp(box) self[:3] = c[:3] return c[3] x = ArrayProperty(0) y = ArrayProperty(1) z = ArrayProperty(2) w = ArrayProperty(3) h = ArrayProperty(4) d = ArrayProperty(5) left = ArrayProperty(0) top = ArrayProperty(1) front = ArrayProperty(2) right = BoxProperty(0, 3) bottom = BoxProperty(1, 4) back = BoxProperty(2, 5) topleft_front = BoxCombineProperty(0, 1, 2) topright_front = BoxCombineProperty((0, 3), 1, 2) bottomleft_front = BoxCombineProperty(0, (1, 4), 2) bottomright_front = BoxCombineProperty((0, 3), (1, 4), 2) topleft_back = BoxCombineProperty(0, 1, (2, 5)) topright_back = BoxCombineProperty((0, 3), 1, (2, 5)) bottomleft_back = BoxCombineProperty(0, (1, 4), (2, 5)) bottomright_back = BoxCombineProperty((0, 3), (1, 4), (2, 5)) center = BoxCombineProperty((0, 3, 1), (1, 4, 1), (2, 5, 1)) boxsize = BoxCombineProperty(3, 4, 5) centerx = BoxProperty(0, 3, 1) centery = BoxProperty(1, 4, 1) centerz = BoxProperty(2, 5, 1) def main(): a = BoundingBox(10,10,10,50,50,50) b = BoundingBox(40,40,40,30,30,30) c = BoundingBox(10,60,10,50,50,50) print(a) print(a.collidebox(b)) print(a.collidebox(c)) print(b.collidebox(c)) print(a.collidepoint(45, 20, 45)) print(b.collidepoint(45, 20, 45)) print() #a[:3] -= 20 # move in place print(a) screen = BoundingBox(0,0,50,800,600,250) clamp = a.clamp_ip(screen) print(a, clamp) print(screen) print(screen.center) if __name__ == '__main__': main()Example pyglet. Now with mouse and wasd, qe movement. import pyglet from pyglet.gl import * from pyglet.graphics.vertexbuffer import create_buffer from boundingbox import BoundingBox from random import randrange import numpy as np import ctypes import math import os # base on gl3n row major def perspective(width, height, fov, near, far): array = np.array([0 for i in range(16)], dtype=GLfloat).reshape(4,4) mat = np.matrix(array) aspect = width/height top = near * math.tan(fov * (math.pi/360.0)) bottom = -top right = top * aspect left = -right mat[0,0] = (2 * near) / (right - left) mat[0,2] = (right + left) / (right - left) mat[1,1] = (2 * near) / (top - bottom) mat[1,2] = (top + bottom) / (top - bottom) mat[2,2] = -(far + near) / (far - near) mat[2,3] = -(2 * far + near) / (far - near) mat[3,2] = -1 return mat def normalized(array): if np.linalg.norm(array) != 0: return array / np.linalg.norm(array) return array def matrix_idenity(): return np.matrix(np.identity(4, GLfloat)) def look_at(eye, target, up): look_dir = normalized(target - eye) up_dir = normalized(up) right_dir = normalized(np.cross(look_dir, up_dir)) perp_up_dir = np.cross(right_dir, look_dir) mat = matrix_idenity() mat[0] = np.append(right_dir, [-np.dot(eye, right_dir)]) mat[1] = np.append(perp_up_dir, [-np.dot(eye, perp_up_dir)]) mat[2] = np.append(-look_dir, [np.dot(eye, look_dir)]) return mat def unit_vector(data): data = np.array(data, dtype=GLfloat, copy=True) if data.ndim == 1: data /= math.sqrt(np.dot(data, data)) return data def rotation(alpha, axis): cosa = math.cos(alpha) sina = math.sin(alpha) axis = unit_vector(axis) R = np.diag([cosa, cosa, cosa]) R += np.outer(axis, axis) * (1.0 - cosa) axis *= sina R += np.array([[0.0, -axis[2], axis[1]], [axis[2], 0.0, -axis[0]], [-axis[1], axis[0], 0.0]], GLfloat) M = np.identity(4) M[:3, :3] = R return M class Face: FRONT = 1 # counter clockwise BACK = 2 LEFT = 4 # counter clockwise RIGHT = 8 TOP = 16 # counter clockwise BOTTOM = 32 ALL = 63 def create_cube(size, face=Face.ALL, element=True): array = np.array([ size, size, size, #0 + + + right top front -size, -size, -size, #1 - - - left bottom back size, -size, -size, #2 + - - right bottom back size, size, -size, #3 + + - right top back -size, size, -size, #4 - + - left top back -size, size, size, #5 - + + left top front -size, -size, size, #6 - - + left bottom front size, -size, size #7 + - + right bottom front ], GLfloat) elements = np.array([], GLuint) if face & Face.BACK: elements = np.append(elements, [1,3,2,3,1,4]) if face & Face.FRONT: elements = np.append(elements, [6,7,0,0,5,6]) if face & Face.LEFT: elements = np.append(elements, [5,4,1,1,6,5]) if face & Face.RIGHT: elements = np.append(elements, [0,2,3,2,0,7]) if face & Face.TOP: elements = np.append(elements, [4,0,3,0,4,5]) if face & Face.BOTTOM: elements = np.append(elements, [1,2,7,7,6,1]) if element: return array, elements pylist = [] for i in elements: n = i * 3 pylist.extend(array[n:n + 3]) return np.array(pylist, GLfloat) class Shader: def __init__(self, vstring, fstring): self.program = GLuint(glCreateProgram()) if not os.path.exists(vstring): print(vstring, "doesn't exists") return if not os.path.exists(fstring): print(fstring, "doesn't exists") return vbuffer = open(vstring, 'r') vshader = glCreateShader(GL_VERTEX_SHADER) vbuff = ctypes.create_string_buffer(vbuffer.read().encode()) vtext = ctypes.cast(ctypes.pointer(ctypes.pointer(vbuff)), ctypes.POINTER(ctypes.POINTER(GLchar))) glShaderSource(vshader, 1, vtext, None) glCompileShader(vshader) success = GLint() infoLog = ctypes.create_string_buffer(512) glGetShaderiv(vshader, GL_COMPILE_STATUS, ctypes.byref(success)) if not success: glGetShaderInfoLog(vshader, 512, None, infoLog) print("Error: Vertex Shader ", infoLog.value) fbuffer = open(fstring, 'r') fshader = glCreateShader(GL_FRAGMENT_SHADER) fbuff = ctypes.create_string_buffer(fbuffer.read().encode()) ftext = ctypes.cast(ctypes.pointer(ctypes.pointer(fbuff)), ctypes.POINTER(ctypes.POINTER(GLchar))) glShaderSource(fshader, 1, ftext, None) glCompileShader(fshader) glGetShaderiv(fshader, GL_COMPILE_STATUS, ctypes.byref(success)) if not success: glGetShaderInfoLog(fshader, 512, None, infoLog) print("Error: Fragment Shader ", infoLog.value) glAttachShader(self.program, vshader) glAttachShader(self.program, fshader) glLinkProgram(self.program) glGetProgramiv(self.program, GL_LINK_STATUS, ctypes.byref(success)) if not success: glGetShaderInfoLog(fshader, 512, None, infoLog) print("Error: Program ", infoLog.value) # clean up glDeleteShader(vshader) glDeleteShader(fshader) vbuffer.close() fbuffer.close() def uniformMatrix4fv(self, key, count, transpose, value): buff = ctypes.create_string_buffer(key.encode()) location = glGetUniformLocation(self.program, buff) nvalue = np.array(value, GLfloat) # .flatten() nref = nvalue.ctypes.data_as(ctypes.POINTER(ctypes.c_float)) glUniformMatrix4fv(location, count, transpose, nref) def use(self): glUseProgram(self.program) def destroy(self): glDeleteProgram(self.program) class Camera: def __init__(self): self.position = np.array((0.0, 1.0, 5.0)) self.front = np.array((0.0, 0.0, 0.0)) self.up = np.array((0.0, 1.0, 0.0)) self.yaw = -80.0 self.pitch = 0.0 self.sensitivity = 0.05 self.speed = 1.0 self.push_front() def view(self): return look_at(self.position, self.position + self.front, self.up) def push_front(self): self.front[0] = np.cos(np.radians(self.yaw)) * np.cos(np.radians(self.pitch)) self.front[1] = np.sin(np.radians(self.pitch)) self.front[2] = np.sin(np.radians(self.yaw)) * np.cos(np.radians(self.pitch)) def mouse_motion(self, dx, dy): self.yaw += dx * self.sensitivity self.yaw %= 360 self.pitch -= dy * self.sensitivity if self.pitch > 89.0: self.pitch = 89.0 if self.pitch < -89.0: self.pitch = -89.0 self.push_front() def movement(self, keys, dt): if keys[pyglet.window.key.W]: self.position += self.front * self.speed * dt elif keys[pyglet.window.key.S]: self.position -= self.front * self.speed * dt if keys[pyglet.window.key.A]: self.position -= normalized(np.cross(self.front, self.up)) * self.speed * dt elif keys[pyglet.window.key.D]: self.position += normalized(np.cross(self.front, self.up)) * self.speed * dt if keys[pyglet.window.key.Q]: self.yaw -= 20.0 * dt self.push_front() elif keys[pyglet.window.key.E]: self.yaw += 20.0 * dt self.push_front() class CubeRandom: def __init__(self, w, h): ar = np.arange(0, 1, 0.1) self.box = BoundingBox(np.random.choice(ar), np.random.choice(ar), np.random.choice(ar), 0.1, 0.1, 0.1).astype(float) speed = np.arange(0, 0.05, 0.002) self.dir = np.array([np.random.choice(speed) for i in range(3)]) def move(self, screenbox): screenbox = BoundingBox(0.0, 0.0, 0.0, 2.0, 2.0, 2.0) self.box[:3] += self.dir clamp = self.box.clamp_ip(screenbox) if 'x' in clamp: self.dir[0] = -self.dir[0] if 'y' in clamp: self.dir[1] = -self.dir[1] if 'z' in clamp: self.dir[2] = -self.dir[2] class Window(pyglet.window.Window): def __init__(self): pyglet.window.Window.__init__(self) self.context.config.alpha_size = 8 self.context.config.buffer_size = 32 self.context.config.sample_buffers = 1 self.context.config.samples = 4 glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) glClearColor(0.1, 0.0, 0.0, 1.0) glViewport(0, 0, self.width, self.height) self.set_exclusive_mouse(True) self.camera = Camera() self.model = matrix_idenity() #self.view = camera.view() self.projection = perspective(self.width, self.height, 45.0, 1.0, 100.0) #self.mvp = self.projection * self.view * self.model self.vertices = create_cube(0.1, element=False) print("How many vertices.", len(self.vertices) / 3) color_choice = [[1.0,0.0,0.0], [0.0,1.0,0.0], [0.0,0.0,1.0], [1.0,0.0,1.0], [1.0,1.0,0.0], [0.0,0.5,1.0]] colors = [] for i in range(6): color = color_choice[i] colors.extend(color + color + color + color + color + color) self.colors = np.array(colors, GLfloat) print("How many colors.", len(self.colors) / 3) self.vao = GLuint() glGenVertexArrays(1, self.vao) glBindVertexArray(self.vao) self.vbo = create_buffer(self.vertices.nbytes, GL_ARRAY_BUFFER, GL_STATIC_DRAW) self.vbo.set_data(self.vertices.ctypes.data) self.vbo.bind() glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(0); self.color_vbo = create_buffer(self.colors.nbytes, GL_ARRAY_BUFFER, GL_STATIC_DRAW) self.color_vbo.set_data(self.colors.ctypes.data) self.color_vbo.bind() glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(1); glBindVertexArray(0); self.keys = pyglet.window.key.KeyStateHandler() self.push_handlers(self.keys, self.on_mouse_motion) self.tick = 0.0 self.shader = Shader('vshader.glsl', 'fshader.glsl') pyglet.clock.schedule_interval(self.tick_update, 1.0 / 30.0) self.screenbox = BoundingBox(0,0,10, self.width, self.height, 100) self.cubes = [CubeRandom(self.width, self.height) for i in range(6)] self.still_cubes = [(10,0,0), (0,10,0), (0,0,10), (-10,0,0), (0,-10,0), (0,0,-10), (10,10,0), (10,0,10), (0,10,10), (-10,-10,0), (-10,0,-10), (0,-10,-10),] def on_mouse_motion(self, x, y, dx, dy): self.camera.mouse_motion(dx, dy) def tick_update(self, dt): self.tick += dt self.camera.movement(self.keys, dt) for cube in self.cubes: cube.move(self.screenbox) def on_draw(self): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.shader.use() #self.shader.uniformMatrix4fv('mvp', 1, GL_TRUE, self.mvp) view = self.camera.view() glBindVertexArray(self.vao); for cube in self.cubes: model = np.identity(4) model[0::1, 3][:3] = cube.box[:3] mvp = self.projection * view * np.matrix(model) self.shader.uniformMatrix4fv('mvp', 1, GL_TRUE, mvp) glDrawArrays(GL_TRIANGLES, 0, len(self.vertices)) for pos in self.still_cubes: model = np.identity(4) model[0::1, 3][:3] = pos mvp = self.projection * view * np.matrix(model) self.shader.uniformMatrix4fv('mvp', 1, GL_TRUE, mvp) glDrawArrays(GL_TRIANGLES, 0, len(self.vertices)) glBindVertexArray(0) def clean_up(self): self.shader.destroy() self.vbo.delete() self.color_vbo.delete() glDeleteVertexArrays(1, self.vao) if __name__ == '__main__': window = Window() pyglet.app.run() window.clean_up() 99 percent of computer problems exists between chair and keyboard. Posts: 544 Threads: 15 Joined: Oct 2016 Improve pyglet example. commonglet.py import os import ctypes import pyglet import numpy as np from pyglet.gl import * from glmath import normalize, GlMat class VertexArray: def __init__(self, size=1): self.vao = GLuint(0) self.size = size glGenVertexArrays(size, self.vao) def attribute(self, index, size, gl_type, gl_norm, stride, pointer): glVertexAttribPointer(index, size, gl_type, gl_norm, stride, pointer) glEnableVertexAttribArray(index) def bind(self): glBindVertexArray(self.vao) def destroy(self): glDeleteVertexArrays(self.size, self.vao) def disable_attribute(self, n): glDisableVertexAttribArray(n) def enable_attribute(self, n): glEnableVertexAttribArray(n) def unbind(self): glBindVertexArray(0) class Shader: def __init__(self, vstring, fstring): self.program = GLuint(glCreateProgram()) if not os.path.exists(vstring): print(vstring, "doesn't exists") return if not os.path.exists(fstring): print(fstring, "doesn't exists") return vbuffer = open(vstring, 'r') vshader = glCreateShader(GL_VERTEX_SHADER) vbuff = ctypes.create_string_buffer(vbuffer.read().encode()) vtext = ctypes.cast(ctypes.pointer(ctypes.pointer(vbuff)), ctypes.POINTER(ctypes.POINTER(GLchar))) glShaderSource(vshader, 1, vtext, None) glCompileShader(vshader) success = GLint() infoLog = ctypes.create_string_buffer(512) glGetShaderiv(vshader, GL_COMPILE_STATUS, ctypes.byref(success)) if not success: glGetShaderInfoLog(vshader, 512, None, infoLog) print("Error: Vertex Shader ", infoLog.value) fbuffer = open(fstring, 'r') fshader = glCreateShader(GL_FRAGMENT_SHADER) fbuff = ctypes.create_string_buffer(fbuffer.read().encode()) ftext = ctypes.cast(ctypes.pointer(ctypes.pointer(fbuff)), ctypes.POINTER(ctypes.POINTER(GLchar))) glShaderSource(fshader, 1, ftext, None) glCompileShader(fshader) glGetShaderiv(fshader, GL_COMPILE_STATUS, ctypes.byref(success)) if not success: glGetShaderInfoLog(fshader, 512, None, infoLog) print("Error: Fragment Shader ", infoLog.value) glAttachShader(self.program, vshader) glAttachShader(self.program, fshader) glLinkProgram(self.program) glGetProgramiv(self.program, GL_LINK_STATUS, ctypes.byref(success)) if not success: glGetShaderInfoLog(fshader, 512, None, infoLog) print("Error: Program ", infoLog.value) # clean up glDeleteShader(vshader) glDeleteShader(fshader) vbuffer.close() fbuffer.close() def uniformMatrix4fv(self, key, count, transpose, value): buff = ctypes.create_string_buffer(key.encode()) location = glGetUniformLocation(self.program, buff) nvalue = np.array(value, GLfloat) # .flatten() nref = nvalue.ctypes.data_as(ctypes.POINTER(ctypes.c_float)) glUniformMatrix4fv(location, count, transpose, nref) def use(self): glUseProgram(self.program) def destroy(self): glDeleteProgram(self.program) class Camera: def __init__(self, position = np.array((0.0, 0.0, 5.0)), yaw = -90, pitch = 0, roll = 0, sensitivity = 0.05, speed = 5.0, turn = 70.0): self.position = position self.front = np.array((0,0,0), float) self.top = np.array((0.0, 1.0, 0.0)) self.yaw = float(yaw) self.pitch = float(pitch) self.roll = float(roll) self.sensitivity = sensitivity self.speed = speed self.turn = turn self.update() def view(self): return GlMat.look_at(self.position, self.position + self.front, self.up) def constrain_pitch(self): if self.pitch > 89.0: self.pitch = 89.0 if self.pitch < -89.0: self.pitch = -89.0 def update(self): self.front[0] = np.cos(np.radians(self.yaw)) * np.cos(np.radians(self.pitch)) self.front[1] = np.sin(np.radians(self.pitch)) self.front[2] = np.sin(np.radians(self.yaw)) * np.cos(np.radians(self.pitch)) self.front = normalize(self.front) self.across = normalize(np.cross(self.front, self.top)) self.up = normalize(np.cross(self.across, self.front)) # roll self.up[0] = np.sin(np.radians(self.roll)) * np.cos(np.radians(self.pitch)) self.up[1] = np.cos(np.radians(self.roll)) * np.cos(np.radians(self.pitch)) self.up[2] = np.sin(np.radians(self.pitch)) self.up = normalize(self.up) def mouse_motion(self, dx, dy): self.yaw += dx * self.sensitivity self.yaw %= 360 self.pitch -= dy * self.sensitivity self.constrain_pitch() self.update() def movement(self, keys, dt): if keys[pyglet.window.key.SPACE]: self.pitch = 0.0 self.roll = 0.0 self.update() if keys[pyglet.window.key.W]: self.position += self.front * self.speed * dt elif keys[pyglet.window.key.S]: self.position -= self.front * self.speed * dt if keys[pyglet.window.key.A]: self.position -= self.across * self.speed * dt elif keys[pyglet.window.key.D]: self.position += self.across * self.speed * dt if keys[pyglet.window.key.Q]: self.yaw -= self.turn * dt self.update() elif keys[pyglet.window.key.E]: self.yaw += self.turn * dt self.update() def movement_plus(self, keys, dt): self.movement(keys, dt) # works but needs more testing if keys[pyglet.window.key.Z]: self.roll -= self.turn * dt self.update() elif keys[pyglet.window.key.X]: self.roll += self.turn * dt self.update() if keys[pyglet.window.key.R]: self.position += normalize(self.up) * self.speed * dt elif keys[pyglet.window.key.F]: self.position -= normalize(self.up) * self.speed * dtglmath.py import numpy as np import numpy.matlib as matlib def normalize(array): norm = np.linalg.norm(array) if norm != 0: return array / norm return array # row major, base on gl3n class GlMat(np.matrix): def __new__(cls, data=None, dtype=float): if data is None: data = matlib.identity(4, dtype) return np.asmatrix(data, dtype).view(cls) def identity(self): self[:] = matlib.identity(4, self.dtype) def translate(self, vec3): for i in range(3): self[i,3] += vec3[i] def translation(self, vec3): for i in range(3): self[i,3] = vec3[i] def rotate(self, alpha, x, y, z): self[:] = GlMat.rotation(alpha, x, y, z) * self def rotatex(self, alpha): self[:] = GlMat.xrotation(alpha) * self def rotatey(self, alpha): self[:] = GlMat.yrotation(alpha) * self def rotatez(self, alpha): self[:] = GlMat.zrotation(alpha) * self @staticmethod def rotation(alpha, x, y, z): mult = GlMat() axis = normalize(np.array((x,y,z))) cosa = np.cos(alpha) sina = np.sin(alpha) temp = np.array((1 - cosa) * axis) mult[0,0] = temp[0] * axis[0] + cosa mult[0,1] = temp[0] * axis[1] + sina * axis[2] mult[0,2] = temp[0] * axis[2] - sina * axis[1] mult[1,0] = temp[1] * axis[0] - sina * axis[2] mult[1,1] = temp[1] * axis[1] + cosa mult[1,2] = temp[1] * axis[2] + sina * axis[0] mult[2,0] = temp[2] * axis[0] + sina * axis[1] mult[2,1] = temp[2] * axis[1] - sina * axis[0] mult[2,2] = temp[2] * axis[2] + cosa return mult @staticmethod def xrotation(alpha): mult = GlMat() cosa = np.cos(alpha) sina = np.sin(alpha) mult[1,1] = cosa mult[1,2] = -sina mult[2,1] = sina mult[2,2] = cosa return mult @staticmethod def yrotation(alpha): mult = GlMat() cosa = np.cos(alpha) sina = np.sin(alpha) mult[0,0] = cosa mult[0,2] = sina mult[2,0] = -sina mult[2,2] = cosa return mult @staticmethod def zrotation(alpha): mult = GlMat() cosa = np.cos(alpha) sina = np.sin(alpha) mult[0,0] = cosa mult[0,1] = -sina mult[1,0] = sina mult[1,1] = cosa return mult @staticmethod def perspective(width, height, fov, near, far): mat = GlMat() aspect = width/height top = near * np.tan(fov * (np.pi/360.0)) bottom = -top right = top * aspect left = -right mat[0,0] = (2 * near) / (right - left) mat[0,2] = (right + left) / (right - left) mat[1,1] = (2 * near) / (top - bottom) mat[1,2] = (top + bottom) / (top - bottom) mat[2,2] = -(far + near) / (far - near) mat[2,3] = -(2 * far + near) / (far - near) mat[3,2] = -1 return mat @staticmethod def look_at(eye, target, up): look_dir = normalize(target - eye) up_dir = normalize(up) right_dir = normalize(np.cross(look_dir, up_dir)) perp_up_dir = np.cross(right_dir, look_dir) mat = GlMat() mat[0] = np.append(right_dir, [-np.dot(eye, right_dir)]) mat[1] = np.append(perp_up_dir, [-np.dot(eye, perp_up_dir)]) mat[2] = np.append(-look_dir, [np.dot(eye, look_dir)]) return mat if __name__ == '__main__': m = GlMat() m.translate(np.array((1,2,3))) m.rotatez(0.2) print(m) print(GlMat.rotation(0.5,0.1,0.2,0.3)) shapes.py import numpy as np import numpy.matlib as matlib def normalize(array): norm = np.linalg.norm(array) if norm != 0: return array / norm return array # row major, base on gl3n class GlMat(np.matrix): def __new__(cls, data=None, dtype=float): if data is None: data = matlib.identity(4, dtype) return np.asmatrix(data, dtype).view(cls) def identity(self): self[:] = matlib.identity(4, self.dtype) def translate(self, vec3): for i in range(3): self[i,3] += vec3[i] def translation(self, vec3): for i in range(3): self[i,3] = vec3[i] def rotate(self, alpha, x, y, z): self[:] = GlMat.rotation(alpha, x, y, z) * self def rotatex(self, alpha): self[:] = GlMat.xrotation(alpha) * self def rotatey(self, alpha): self[:] = GlMat.yrotation(alpha) * self def rotatez(self, alpha): self[:] = GlMat.zrotation(alpha) * self @staticmethod def rotation(alpha, x, y, z): mult = GlMat() axis = normalize(np.array((x,y,z))) cosa = np.cos(alpha) sina = np.sin(alpha) temp = np.array((1 - cosa) * axis) mult[0,0] = temp[0] * axis[0] + cosa mult[0,1] = temp[0] * axis[1] + sina * axis[2] mult[0,2] = temp[0] * axis[2] - sina * axis[1] mult[1,0] = temp[1] * axis[0] - sina * axis[2] mult[1,1] = temp[1] * axis[1] + cosa mult[1,2] = temp[1] * axis[2] + sina * axis[0] mult[2,0] = temp[2] * axis[0] + sina * axis[1] mult[2,1] = temp[2] * axis[1] - sina * axis[0] mult[2,2] = temp[2] * axis[2] + cosa return mult @staticmethod def xrotation(alpha): mult = GlMat() cosa = np.cos(alpha) sina = np.sin(alpha) mult[1,1] = cosa mult[1,2] = -sina mult[2,1] = sina mult[2,2] = cosa return mult @staticmethod def yrotation(alpha): mult = GlMat() cosa = np.cos(alpha) sina = np.sin(alpha) mult[0,0] = cosa mult[0,2] = sina mult[2,0] = -sina mult[2,2] = cosa return mult @staticmethod def zrotation(alpha): mult = GlMat() cosa = np.cos(alpha) sina = np.sin(alpha) mult[0,0] = cosa mult[0,1] = -sina mult[1,0] = sina mult[1,1] = cosa return mult @staticmethod def perspective(width, height, fov, near, far): mat = GlMat() aspect = width/height top = near * np.tan(fov * (np.pi/360.0)) bottom = -top right = top * aspect left = -right mat[0,0] = (2 * near) / (right - left) mat[0,2] = (right + left) / (right - left) mat[1,1] = (2 * near) / (top - bottom) mat[1,2] = (top + bottom) / (top - bottom) mat[2,2] = -(far + near) / (far - near) mat[2,3] = -(2 * far + near) / (far - near) mat[3,2] = -1 return mat @staticmethod def look_at(eye, target, up): look_dir = normalize(target - eye) up_dir = normalize(up) right_dir = normalize(np.cross(look_dir, up_dir)) perp_up_dir = np.cross(right_dir, look_dir) mat = GlMat() mat[0] = np.append(right_dir, [-np.dot(eye, right_dir)]) mat[1] = np.append(perp_up_dir, [-np.dot(eye, perp_up_dir)]) mat[2] = np.append(-look_dir, [np.dot(eye, look_dir)]) return mat if __name__ == '__main__': m = GlMat() m.translate(np.array((1,2,3))) m.rotatez(0.2) print(m) print(GlMat.rotation(0.5,0.1,0.2,0.3)) cube.py main import ctypes import pyglet import numpy as np from pyglet.gl import * from boundingbox import BoundingBox from shapes import create_cube, Face from glmath import GlMat, normalize from commonglet import VertexArray, Shader, Camera from pyglet.graphics.vertexbuffer import create_buffer class CubeRandom: def __init__(self): ar = np.arange(-1, 1, 0.1) self.box = BoundingBox(np.random.choice(ar), np.random.choice(ar), np.random.choice(ar), 0.1, 0.1, 0.1).astype(float) speed = np.arange(-0.05, 0.05, 0.002) self.dir = np.array([np.random.choice(speed) for i in range(3)]) def move(self): screenbox = BoundingBox(-5.0, -5.0, -5.0, 10.0, 10.0, 10.0) self.box[:3] += self.dir clamp = self.box.clamp_ip(screenbox) if 'x' in clamp: self.dir[0] = -self.dir[0] if 'y' in clamp: self.dir[1] = -self.dir[1] if 'z' in clamp: self.dir[2] = -self.dir[2] class Window(pyglet.window.Window): def __init__(self): pyglet.window.Window.__init__(self) self.set_location(100,100) self._gl_setup() self._cube_setup(0.2) self.cube_shader = Shader('vshader.glsl', 'fshader.glsl') pyglet.clock.schedule_interval(self.time_update, 1.0 / 30.0) self.projection = GlMat.perspective(self.width, self.height, 45.0, 1.0, 100.0) self.cubes = [CubeRandom() for i in range(10)] self.set_exclusive_mouse(True) self.camera = Camera(np.array((0, 0, 20), float)) self.keys = pyglet.window.key.KeyStateHandler() self.push_handlers(self.keys, self.on_mouse_motion) def on_mouse_motion(self, x, y, dx, dy): self.camera.mouse_motion(dx, dy) def time_update(self, dt): self.camera.movement_plus(self.keys, dt) for cube in self.cubes: cube.move() def _gl_setup(self): self.context.config.alpha_size = 8 self.context.config.buffer_size = 32 self.context.config.sample_buffers = 1 self.context.config.samples = 4 glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) glClearColor(0.1, 0.0, 0.0, 1.0) glViewport(0, 0, self.width, self.height) def _cube_setup(self, size): color_choice = [ [1.0,0.0,0.0], [0.0,1.0,0.0], [0.0,0.0,1.0], [1.0,0.0,1.0], [1.0,1.0,0.0], [0.0,0.5,1.0]] colors = [] for i in range(6): color = color_choice[i] colors.extend(color + color + color + color + color + color) self.colors = np.array(colors, GLfloat) self.vertices = create_cube(size, element=False) self.cube_vao = VertexArray() self.cube_vao.bind() self.cube_vbo = create_buffer(self.vertices.nbytes, GL_ARRAY_BUFFER, GL_STATIC_DRAW) self.cube_vbo.set_data(self.vertices.ctypes.data) self.cube_vbo.bind() self.cube_vao.attribute(0, 3, GL_FLOAT, GL_FALSE, 0, 0) self.cube_color_vbo = create_buffer(self.colors.nbytes, GL_ARRAY_BUFFER, GL_STATIC_DRAW) self.cube_color_vbo.set_data(self.colors.ctypes.data) self.cube_color_vbo.bind() self.cube_vao.attribute(1, 3, GL_FLOAT, GL_FALSE, 0, 0) self.cube_vao.unbind() def on_draw(self): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.cube_shader.use() self.cube_vao.bind() for cube in self.cubes: model = GlMat() model.translate(cube.box[:3]) mvp = self.projection * self.camera.view() * model self.cube_shader.uniformMatrix4fv('mvp', 1, GL_TRUE, mvp) glDrawArrays(GL_TRIANGLES, 0, len(self.vertices)) self.cube_vao.unbind() def clean_up(self): self.cube_vbo.delete() self.cube_color_vbo.delete() self.cube_shader.destroy() self.cube_vao.destroy() if __name__ == '__main__': window = Window() pyglet.app.run() window.clean_up() 99 percent of computer problems exists between chair and keyboard. |