Re: [PyOpenGL-Users] constructing a VBO containing mixture of floats, ubytes, etc
Brought to you by:
mcfletch
From: Nicolas R. <Nic...@in...> - 2011-02-03 13:35:30
|
> If I do go ahead, I'm not certain how to construct the vbo containing > mixed types like this. Is there anything in OpenGL.arrays that might > help, or do I need to brush up on my ctypes-fu to construct an array of > structs manually? Maybe the script below may help you (it needs numpy). Nicolas import sys import ctypes import numpy as np import OpenGL import OpenGL.GL as gl import OpenGL.GLU as glu import OpenGL.GLUT as glut # ----------------------------------------------------------------------------- class VertexAttribute(object): def __init__(self, count, gltype, stride, offset): self.count = count self.gltype = gltype self.stride = stride self.offset = ctypes.c_void_p(offset) # ----------------------------------------------------------------------------- class VertexAttribute_color(VertexAttribute): def __init__(self, count, gltype, stride, offset): assert count in (3, 4), \ 'Color attributes must have count of 3 or 4' VertexAttribute.__init__(self, count, gltype, stride, offset) def enable(self): gl.glColorPointer(self.count, self.gltype, self.stride, self.offset) gl.glEnableClientState(gl.GL_COLOR_ARRAY) # ----------------------------------------------------------------------------- class VertexAttribute_edge_flag(VertexAttribute): def __init__(self, count, gltype, stride, offset): assert count == 1, \ 'Edge flag attribute must have a size of 1' assert gltype in (gl.GL_BYTE, gl.GL_UNSIGNED_BYTE, gl.GL_BOOL), \ 'Edge flag attribute must have boolean type' VertexAttribute.__init__(self, 1, gltype, stride, offset) def enable(self): gl.glEdgeFlagPointer(self.stride, self.offset) gl.glEnableClientState(gl.GL_EDGE_FLAG_ARRAY) # ----------------------------------------------------------------------------- class VertexAttribute_fog_coord(VertexAttribute): def __init__(self, count, gltype, stride, offset): VertexAttribute.__init__(self, count, gltype, stride, offset) def enable(self): gl.glFogCoordPointer(self.count, self.gltype, self.stride, self.offset) gl.glEnableClientState(gl.GL_FOG_COORD_ARRAY) # ----------------------------------------------------------------------------- class VertexAttribute_normal(VertexAttribute): def __init__(self, count, gltype, stride, offset): assert count == 3, \ 'Normal attribute must have a size of 3' assert gltype in (gl.GL_BYTE, gl.GL_SHORT, gl.GL_INT, gl.GL_FLOAT, gl.GL_DOUBLE), \ 'Normal attribute must have signed type' VertexAttribute.__init__(self, 3, gltype, stride, offset) def enable(self): gl.glNormalPointer(self.gltype, self.stride, self.offset) gl.glEnableClientState(gl.GL_NORMAL_ARRAY) # ----------------------------------------------------------------------------- class VertexAttribute_secondary_color(VertexAttribute): def __init__(self, count, gltype, strude, offset): assert count == 3, \ 'Secondary color attribute must have a size of 3' VertexAttribute.__init__(self, 3, gltype, stride, offset) def enable(self): gl.glSecondaryColorPointer(3, self.gltype, self.stride, self.offset) gl.glEnableClientState(gl.GL_SECONDARY_COLOR_ARRAY) # ----------------------------------------------------------------------------- class VertexAttribute_tex_coord(VertexAttribute): def __init__(self, count, gltype, stride, offset): assert gltype in (gl.GL_SHORT, gl.GL_INT, gl.GL_FLOAT, gl.GL_DOUBLE), \ 'Texture coord attribute must have non-byte signed type' VertexAttribute.__init__(self, count, gltype, stride, offset) def enable(self): gl.glTexCoordPointer(self.count, self.gltype, self.stride, self.offset) gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY) # ----------------------------------------------------------------------------- class VertexAttribute_position(VertexAttribute): def __init__(self, count, gltype, stride, offset): assert count > 1, \ 'Vertex attribute must have count of 2, 3 or 4' assert gltype in (gl.GL_SHORT, gl.GL_INT, gl.GL_FLOAT, gl.GL_DOUBLE), \ 'Vertex attribute must have signed type larger than byte' VertexAttribute.__init__(self, count, gltype, stride, offset) def enable(self): gl.glVertexPointer(self.count, self.gltype, self.stride, self.offset) gl.glEnableClientState(gl.GL_VERTEX_ARRAY) # ----------------------------------------------------------------------------- class VertexBufferException(Exception): pass class VertexBuffer(object): def __init__(self, vertices, indices=None): gltypes = { 'float32': gl.GL_FLOAT, 'float' : gl.GL_DOUBLE, 'float64': gl.GL_DOUBLE, 'int8' : gl.GL_BYTE, 'uint8' : gl.GL_UNSIGNED_BYTE, 'int16' : gl.GL_SHORT, 'uint16' : gl.GL_UNSIGNED_SHORT, 'int32' : gl.GL_INT, 'uint32' : gl.GL_UNSIGNED_INT } dtype = vertices.dtype names = dtype.names or [] stride = vertices.itemsize offset = 0 self.attributes = {} if indices is None: indices = np.arange(vertices.size,dtype=np.uint32) for name in names: gtype = str(dtype[name].subdtype[0]) count = reduce(lambda x,y:x*y, dtype[name].shape) if gtype not in gltypes.keys(): raise VertexBufferException gltype = gltypes[gtype] vclass = 'VertexAttribute_%s' % name self.attributes[name[0]] = eval(vclass)(count,gltype,stride,offset) offset += dtype[name].itemsize self.vertices = vertices self.vertices_id = gl.glGenBuffers(1) gl.glBindBuffer( gl.GL_ARRAY_BUFFER, self.vertices_id ) gl.glBufferData( gl.GL_ARRAY_BUFFER, self.vertices, gl.GL_STATIC_DRAW ) gl.glBindBuffer( gl.GL_ARRAY_BUFFER, 0 ) self.indices = indices self.indices_id = gl.glGenBuffers(1) gl.glBindBuffer( gl.GL_ELEMENT_ARRAY_BUFFER, self.indices_id ) gl.glBufferData( gl.GL_ELEMENT_ARRAY_BUFFER, self.indices, gl.GL_STATIC_DRAW ) gl.glBindBuffer( gl.GL_ELEMENT_ARRAY_BUFFER, 0 ) def render(self, mode=gl.GL_QUADS, what='pnctesf'): gl.glPushClientAttrib( gl.GL_CLIENT_VERTEX_ARRAY_BIT ) gl.glBindBuffer( gl.GL_ARRAY_BUFFER, self.vertices_id ) gl.glBindBuffer( gl.GL_ELEMENT_ARRAY_BUFFER, self.indices_id ) for c in self.attributes.keys(): if c in what: self.attributes[c].enable() gl.glDrawElements( gl.GL_QUADS, self.indices.size, gl.GL_UNSIGNED_INT, None) gl.glBindBuffer( gl.GL_ELEMENT_ARRAY_BUFFER, 0 ) gl.glBindBuffer( gl.GL_ARRAY_BUFFER, 0 ) gl.glPopClientAttrib( ) # ----------------------------------------------------------------------------- def on_display(): global cube, theta, phi, frame, time, timebase frame += 1 time = glut.glutGet( glut.GLUT_ELAPSED_TIME ) if (time - timebase > 1000): print frame*1000.0/(time-timebase) timebase = time; frame = 0; gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) gl.glPushMatrix() gl.glRotatef(theta, 0,0,1) gl.glRotatef(phi, 0,1,0) gl.glDisable( gl.GL_BLEND ) gl.glEnable( gl.GL_LIGHTING ) gl.glEnable( gl.GL_DEPTH_TEST ) gl.glEnable( gl.GL_POLYGON_OFFSET_FILL ) gl.glPolygonMode( gl.GL_FRONT_AND_BACK, gl.GL_FILL ) cube.render( gl.GL_QUADS, 'pnc' ) gl.glDisable( gl.GL_POLYGON_OFFSET_FILL ) gl.glEnable( gl.GL_BLEND ) gl.glDisable( gl.GL_LIGHTING ) gl.glPolygonMode( gl.GL_FRONT_AND_BACK, gl.GL_LINE ) gl.glDepthMask( gl.GL_FALSE ) gl.glColor( 0.0, 0.0, 0.0, 0.5 ) cube.render( gl.GL_QUADS, 'p' ) gl.glDepthMask( gl.GL_TRUE ) gl.glPopMatrix() glut.glutSwapBuffers() def on_reshape(width, height): gl.glViewport(0, 0, width, height) gl.glMatrixMode( gl.GL_PROJECTION ) gl.glLoadIdentity( ) glu.gluPerspective( 45.0, float(width)/float(height), 2.0, 10.0 ) gl.glMatrixMode( gl.GL_MODELVIEW ) gl.glLoadIdentity( ) gl.glTranslatef( 0.0, 0.0, -5.0 ) def on_keyboard(key, x, y): if key == '\033': sys.exit() def on_timer(value): global theta, phi theta += 0.25 phi += 0.25 glut.glutPostRedisplay() glut.glutTimerFunc(10, on_timer, 0) def on_idle(): global theta, phi theta += 0.25 phi += 0.25 glut.glutPostRedisplay() if __name__ == '__main__': p = ( ( 1, 1, 1), (-1, 1, 1), (-1,-1, 1), ( 1,-1, 1), ( 1,-1,-1), ( 1, 1,-1), (-1, 1,-1), (-1,-1,-1) ) n = ( ( 0, 0, 1), (1, 0, 0), ( 0, 1, 0), (-1, 0, 1), (0,-1, 0), ( 0, 0,-1) ); c = ( ( 1, 1, 1), ( 1, 1, 0), ( 1, 0, 1), ( 0, 1, 1), ( 1, 0, 0), ( 0, 0, 1), ( 0, 1, 0), ( 0, 0, 0) ); vertices = np.array( [ (p[0],n[0],c[0]), (p[1],n[0],c[1]), (p[2],n[0],c[2]), (p[3],n[0],c[3]), (p[0],n[1],c[0]), (p[3],n[1],c[3]), (p[4],n[1],c[4]), (p[5],n[1],c[5]), (p[0],n[2],c[0]), (p[5],n[2],c[5]), (p[6],n[2],c[6]), (p[1],n[2],c[1]), (p[1],n[3],c[1]), (p[6],n[3],c[6]), (p[7],n[3],c[7]), (p[2],n[3],c[2]), (p[7],n[4],c[7]), (p[4],n[4],c[4]), (p[3],n[4],c[3]), (p[2],n[4],c[2]), (p[4],n[5],c[4]), (p[7],n[5],c[7]), (p[6],n[5],c[6]), (p[5],n[5],c[5]) ], dtype = [('position','f4',(3,)), ('normal','f4',3), ('color','f4',3)] ) glut.glutInit(sys.argv) glut.glutInitDisplayMode(glut.GLUT_DOUBLE | glut.GLUT_RGB | glut.GLUT_DEPTH) glut.glutCreateWindow("Python VBO") glut.glutReshapeWindow(400, 400) glut.glutDisplayFunc(on_display) glut.glutReshapeFunc(on_reshape) glut.glutKeyboardFunc(on_keyboard) glut.glutTimerFunc(10, on_timer, 0) #glut.glutIdleFunc(on_idle) gl.glPolygonOffset( 1, 1 ) gl.glClearColor(1,1,1,1); gl.glEnable( gl.GL_DEPTH_TEST ) gl.glEnable( gl.GL_COLOR_MATERIAL ) gl.glColorMaterial(gl.GL_FRONT_AND_BACK, gl.GL_AMBIENT_AND_DIFFUSE) gl.glBlendFunc( gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA ) gl.glEnable( gl.GL_LIGHT0 ) gl.glLight( gl.GL_LIGHT0, gl.GL_DIFFUSE, (1.0,1.0,1.0,1.0) ) gl.glLight( gl.GL_LIGHT0, gl.GL_AMBIENT, (0.1,0.1,0.1,1.0) ) gl.glLight( gl.GL_LIGHT0, gl.GL_SPECULAR, (0.0,0.0,0.0,1.0) ) gl.glLight( gl.GL_LIGHT0, gl.GL_POSITION, (0.0,1.0,2.0,1.0) ) gl.glEnable( gl.GL_LINE_SMOOTH ) theta, phi = 0, 0 frame, time, timebase = 0, 0, 0 cube = VertexBuffer(vertices) glut.glutMainLoop() |