"""
This module processes an application's vertex buffer objects (VBOs)
NOTE:
- VBOs are buffer objects we use for vertex processing
- In reality, we can use buffer objects for means outside of vertex processing
"""
# Import Python modules
if __name__ == '__main__':
import numpy as np
import pywavefront
[docs]
class VBO:
def __init__(self, ctx):
self.vbos = {}
self.vbos['cube'] = CubeVBO(ctx)
self.vbos['cat'] = CatVBO(ctx)
self.vbos['skybox'] = SkyBoxVBO(ctx)
self.vbos['advanced_skybox'] = AdvancedSkyBoxVBO(ctx)
[docs]
def destroy(self):
[vbo.destroy() for vbo in self.vbos.values()]
[docs]
class BaseVBO:
def __init__(self, ctx):
self.ctx = ctx
self.vbo = self.get_vbo()
self.format: str = None
self.attribs: list = None
# NOTE: Override get_vertex_data() in a subclass because it is geometry-dependant
[docs]
def get_vertex_data(self): ...
[docs]
def get_vbo(self):
vertex_data = self.get_vertex_data()
vbo = self.ctx.buffer(vertex_data)
return vbo
[docs]
def destroy(self):
self.vbo.release()
[docs]
class CubeVBO(BaseVBO):
def __init__(self, ctx):
super().__init__(ctx)
self.format = '2f 3f 3f'
self.attribs = ['in_texcoord_0', 'in_normal', 'in_position']
[docs]
@staticmethod
def get_data(vertices, indices):
# NOTE: Uses list comprehension to Outputs large list of tuples!
data = [vertices[ind] for triangle in indices for ind in triangle]
return np.array(data, dtype='f4')
[docs]
def get_vertex_data(self):
# Get vertex coordinates
vertices = [(-1, -1, 1), ( 1, -1, 1), (1, 1, 1), (-1, 1, 1),
(-1, 1, -1), (-1, -1, -1), (1, -1, -1), ( 1, 1, -1)]
indices = [(0, 2, 3), (0, 1, 2),
(1, 7, 2), (1, 6, 7),
(6, 5, 4), (4, 7, 6),
(3, 4, 5), (3, 5, 0),
(3, 7, 4), (3, 2, 7),
(0, 6, 1), (0, 5, 6)]
vertex_data = self.get_data(vertices, indices)
# Get texture coordinates
tex_coord_vertices = [(0, 0), (1, 0), (1, 1), (0, 1)]
tex_coord_indices = [(0, 2, 3), (0, 1, 2),
(0, 2, 3), (0, 1, 2),
(0, 1, 2), (2, 3, 0),
(2, 3, 0), (2, 0, 1),
(0, 2, 3), (0, 1, 2),
(3, 1, 2), (3, 0, 1),]
tex_coord_data = self.get_data(tex_coord_vertices, tex_coord_indices)
# Get normals
# NOTE: Multiply tuples by 6 because each face, which has 6 vertices, have the same normal
normals = [( 0, 0, 1) * 6,
( 1, 0, 0) * 6,
( 0, 0,-1) * 6,
(-1, 0, 0) * 6,
( 0, 1, 0) * 6,
( 0,-1, 0) * 6,]
normals = np.array(normals, dtype='f4').reshape(36, 3)
# NOTE: We horizontally concat per-vertex data
vertex_data = np.hstack([normals, vertex_data])
vertex_data = np.hstack([tex_coord_data, vertex_data])
return vertex_data
[docs]
class CatVBO(BaseVBO):
def __init__(self, app):
super().__init__(app)
self.format = '2f 3f 3f'
self.attribs = ['in_texcoord_0', 'in_normal', 'in_position']
[docs]
def get_vertex_data(self):
objs = pywavefront.Wavefront('objects/cat/20430_Cat_v1_NEW.obj', cache=True, parse=True)
obj = objs.materials.popitem()[1]
vertex_data = obj.vertices
vertex_data = np.array(vertex_data, dtype='f4')
return vertex_data
[docs]
class SkyBoxVBO(BaseVBO):
def __init__(self, ctx):
super().__init__(ctx)
self.format = '3f'
self.attribs = ['in_position']
[docs]
@staticmethod
def get_data(vertices, indices):
# NOTE: Uses list comprehension to Outputs large list of tuples!
data = [vertices[ind] for triangle in indices for ind in triangle]
return np.array(data, dtype='f4')
[docs]
def get_vertex_data(self):
# Get vertex coordinates
vertices = [(-1, -1, 1), ( 1, -1, 1), (1, 1, 1), (-1, 1, 1),
(-1, 1, -1), (-1, -1, -1), (1, -1, -1), ( 1, 1, -1)]
indices = [(0, 2, 3), (0, 1, 2),
(1, 7, 2), (1, 6, 7),
(6, 5, 4), (4, 7, 6),
(3, 4, 5), (3, 5, 0),
(3, 7, 4), (3, 2, 7),
(0, 6, 1), (0, 5, 6)]
vertex_data = self.get_data(vertices, indices)
vertex_data = np.flip(vertex_data, 1).copy(order='C')
return vertex_data
[docs]
class AdvancedSkyBoxVBO(BaseVBO):
def __init__(self, ctx):
super().__init__(ctx)
self.format = '3f'
self.attribs = ['in_position']
[docs]
def get_vertex_data(self):
# NOTE: Generates a fullscreen quad through a large triangle
z = 0.9999
vertices = [(-1, -1, z), (3, -1, z), (-1, 3, z)]
vertex_data = np.array(vertices, dtype='f4')
return vertex_data