def OnInit( self ): """Setup running params""" glMaterialfv(GL_FRONT, GL_SPECULAR, array((1.0, 1.0, 1.0, 0.15),'f') ); glMaterialfv(GL_FRONT, GL_SHININESS, array((100.0, ),'f') ); self.sphereList = glGenLists(1); if not self.sphereList: raise SystemError("""Unable to generate display list using glGenLists""") glNewList(self.sphereList, GL_COMPILE); glutSolidSphere (0.4, 16, 16); glEndList(); self.cubeList = glGenLists(1); glNewList(self.cubeList, GL_COMPILE); glutSolidCube (0.6); glEndList(); self.solidZ = 8.0 self.solidTimer = Timer( 8.0 ) self.transparentZ = -8.0 self.transparentTimer = Timer( 4.0 ) self.animating = 1 self.startTime = time.time() self.addEventHandler( "keypress", name = 'a', function = self.OnAnimate ) print 'Press "a" to stop animation\nNote: r key has no effect'
def Render( self, mode = 0): BaseContext.Render( self, mode ) glClearColor(0,0,0,1.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) glLightfv(GL_LIGHT0, GL_POSITION, array( (0.5, 0.5, 1.0, 0.0),'f') ); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); self.updatePositions() glPushMatrix (); glTranslatef (-0.15, -0.15, self.solidZ); glMaterialfv(GL_FRONT, GL_EMISSION, array(( 0.0, 0.0, 0.0, 1.0),'f'), ); glMaterialfv(GL_FRONT, GL_DIFFUSE, array((0.75, 0.75, 0.0, 1.0),'f'), ); glCallList (self.sphereList); glPopMatrix (); glPushMatrix (); glTranslatef (0.15, 0.15, self.transparentZ); glRotatef (15.0, 1.0, 1.0, 0.0); glRotatef (30.0, 0.0, 1.0, 0.0); glMaterialfv(GL_FRONT, GL_EMISSION,array( ( 0.0, 0.3, 0.3, 0.6),'f') ); glMaterialfv(GL_FRONT, GL_DIFFUSE,array( ( 0.0, 0.8, 0.8, 0.8),'f') ); glEnable (GL_BLEND); glDepthMask (GL_FALSE); glBlendFunc (GL_SRC_ALPHA, GL_ONE); # note assumption that background is black... glCallList (self.cubeList); glDepthMask (GL_TRUE); glDisable (GL_BLEND); glPopMatrix ();
def OnInit(self): """Setup running params""" glMaterialfv(GL_FRONT, GL_SPECULAR, array((1.0, 1.0, 1.0, 0.15), 'f')) glMaterialfv(GL_FRONT, GL_SHININESS, array((100.0, ), 'f')) self.sphereList = glGenLists(1) if not self.sphereList: raise SystemError( """Unable to generate display list using glGenLists""") glNewList(self.sphereList, GL_COMPILE) glutSolidSphere(0.4, 16, 16) glEndList() self.cubeList = glGenLists(1) glNewList(self.cubeList, GL_COMPILE) glutSolidCube(0.6) glEndList() self.solidZ = 8.0 self.solidTimer = Timer(8.0) self.transparentZ = -8.0 self.transparentTimer = Timer(4.0) self.animating = 1 self.startTime = time.time() self.addEventHandler("keypress", name='a', function=self.OnAnimate) print 'Press "a" to stop animation\nNote: r key has no effect'
def compile( self, mode=None ): """Compile the box as a display-list""" if vbo.get_implementation(): vb = vbo.VBO( array( list(yieldVertices( self.size )), 'f')) def draw( textured=True,lit=True ): vb.bind() try: glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS) try: glEnableClientState( GL_VERTEX_ARRAY ) if lit: glEnableClientState( GL_NORMAL_ARRAY ) glNormalPointer( GL_FLOAT, 32, vb+8 ) if textured: glEnableClientState( GL_TEXTURE_COORD_ARRAY ) glTexCoordPointer( 2, GL_FLOAT, 32, vb ) glVertexPointer( 3, GL_FLOAT, 32, vb+20 ) glDrawArrays( GL_TRIANGLES, 0, 36 ) finally: glPopClientAttrib() finally: vb.unbind() else: vb = array( list(yieldVertices( self.size )), 'f') def draw(textured=True,lit=True): glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS) try: glInterleavedArrays( GL_T2F_N3F_V3F, 0, vb ) glDrawArrays( GL_TRIANGLES, 0, 36 ) finally: glPopClientAttrib() holder = mode.cache.holder(self, draw) holder.depend( self, protofunctions.getField(self, 'size') ) return draw
def Render( self, mode = 0): BaseContext.Render( self, mode ) glTranslatef( 1,0,0) vertices = array([ 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0 ], 'f') indices = array([2, 3, 0, 1 ],'I') glInterleavedArrays( GL_V3F, # 3 vertex floats/item 0, # tight packing vertices.tostring(), ) glDrawElementsui(GL_QUADS,indices) glTranslatef( 0,-2,0) vertices = array([ 0,0,1, 0.0, 0.0, 0.0, 0,0,1, 1.0, 0.0, 0.0, 0,0,1, 1.0, 1.0, 0.0, 0,0,1, 0.0, 1.0, 0.0, ], 'f') glInterleavedArrays( GL_N3F_V3F, # 3 vertex floats/item, 3 normals/item 0, # tight packing vertices.tostring(), ) glDrawElementsui(GL_QUADS, indices)
def Render( self, mode = 0): BaseContext.Render( self, mode ) glTranslatef( 1,0,0) vertices = array([ 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0 ], 'f') indices = array([2, 3, 0, 1 ],'I') glInterleavedArrays( GL_V3F, # 3 vertex floats/item 0, # tight packing vertices.tobytes(), ) glDrawElementsui(GL_QUADS,indices) glTranslatef( 0,-2,0) vertices = array([ 0,0,1, 0.0, 0.0, 0.0, 0,0,1, 1.0, 0.0, 0.0, 0,0,1, 1.0, 1.0, 0.0, 0,0,1, 0.0, 1.0, 0.0, ], 'f') glInterleavedArrays( GL_N3F_V3F, # 3 vertex floats/item, 3 normals/item 0, # tight packing vertices.tobytes(), ) glDrawElementsui(GL_QUADS, indices)
def Render( self, mode = 0): BaseContext.Render( self, mode ) glColor( *self.colors[self.useArrays]) glDisable( GL_LIGHTING ) # following is required, the indices are in # CW, rather than default CCW order... glDisable( GL_CULL_FACE ) VertexArray=[ [0,0,0],[1,0,0],[2,0,0], [0,1,0],[1,1,0],[2,1,0], [0,2,0],[1,2,0],[2,2,0] ] IndiceArray=[ 0,3,4, 0,4,1, 1,4,5, 1,5,2, 3,6,7, 3,7,4, 4,7,8, 4,8,5 ] if self.useArrays: VertexArray=array(VertexArray, 'f') #Here's the problem line IndiceArray=array(IndiceArray, 'I') glVertexPointerf(VertexArray) glEnableClientState(GL_VERTEX_ARRAY); glDrawElementsui( GL_TRIANGLES, IndiceArray )
class TestContext(BaseContext): ''' creates a simple vertex shader ''' def OnInit(self): try: self.shader = compileProgram( compileShader(VERTEX_SHADER, gl.GL_VERTEX_SHADER), compileShader(FRAGMENT_SHADER, gl.GL_FRAGMENT_SHADER)) except RuntimeError, err: sys.stderr.write(err.args[0]) sys.exit(1) self.vbo = vbo.VBO( array([ [0, 1, 0, 0, 1, 0], [-1, -1, 0, 1, 1, 0], [1, -1, 0, 0, 1, 1], [2, -1, 0, 1, 0, 0], [4, -1, 0, 0, 1, 0], [4, 1, 0, 0, 0, 1], [2, -1, 0, 1, 0, 0], [4, 1, 0, 0, 0, 1], [2, 1, 0, 0, 1, 1], ], 'f'))
def renderCap(self, scale=400.0): """The cap is generated with GLU tessellation routines... """ gluTessCallback(self.tess, GLU_TESS_BEGIN, glBegin) def test(t, polyData=None): glNormal(0, 0, -1) glColor3f(t[0] / 2.0, t[1] / 2.0, t[2] / 2.0) return glVertex3f(t[0], t[1], t[2]) gluTessCallback(self.tess, GLU_TESS_VERTEX_DATA, test) gluTessCallback(self.tess, GLU_TESS_END, glEnd) def combine(points, vertices, weights): #print 'combine called', points, vertices, weights return points gluTessCallback(self.tess, GLU_TESS_COMBINE, combine) gluTessBeginPolygon(self.tess, None) try: gluTessBeginContour(self.tess) try: for (x, y) in outline: vertex = array((x / scale, y / scale, 0.0), 'd') gluTessVertex(self.tess, vertex, vertex) finally: gluTessEndContour(self.tess) finally: gluTessEndPolygon(self.tess)
def OnMand(self, event): shader = self.shaders[2] zoom = shader.objects[0].getVariable('Zoom') center = shader.objects[0].getVariable('Center') iterations = shader.objects[0].getVariable('MaxIterations') if event.name == 'z': zoom.value = zoom.value * .85 print 'zoom value', zoom.value elif event.name == 'x': zoom.value = zoom.value * 1.15 print 'zoom value', zoom.value elif event.name == 'r': if iterations is not None: iterations.value += 5 if iterations.value[0] > 105: # limit of floating-point precision... iterations.value = 105 print 'max iterations', iterations.value[0] else: print 'shader objects 0', shader.objects[0].toString() elif event.name == 'f': if iterations is not None: iterations.value -= 5 if iterations.value[0] <= 0: iterations.value = 1 print 'max iterations', iterations.value[0] directions = {'a': (-1, 0), 'd': (1, 0), 'w': (0, 1), 's': (0, -1)} if event.name in directions: step = zoom.value / 10.0 vec = array(directions[event.name], 'f') * step center.value = center.value + vec print 'new center', center.value
def OnInit(self): """Init""" vertex = shaders.compileShader( """ #version 120 void main() { gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } """, GL_VERTEX_SHADER) fragment = shaders.compileShader( """ #version 120 void main () { gl_FragColor = vec4(0, 1, 0, 1); } """, GL_FRAGMENT_SHADER) self.shader = shaders.compileProgram(vertex, fragment) self.vbo = vbo.VBO( array([ [0, 1, 0], [-1, -1, 0], [1, -1, 0], [2, -1, 0], [4, -1, 0], [4, 1, 0], [2, -1, 0], [4, 1, 0], [2, 1, 0], ], 'f') )
def OnMand( self, event ): shader = self.shaders[2] zoom = shader.objects[0].getVariable( 'Zoom' ) center = shader.objects[0].getVariable( 'Center' ) iterations = shader.objects[0].getVariable( 'MaxIterations' ) if event.name == 'z': zoom.value = zoom.value * .85 print 'zoom value', zoom.value elif event.name == 'x': zoom.value = zoom.value * 1.15 print 'zoom value', zoom.value elif event.name == 'r': if iterations is not None: iterations.value += 5 if iterations.value[0] > 105: # limit of floating-point precision... iterations.value = 105 print 'max iterations', iterations.value[0] else: print 'shader objects 0', shader.objects[0].toString() elif event.name == 'f': if iterations is not None: iterations.value -= 5 if iterations.value[0] <= 0: iterations.value = 1 print 'max iterations', iterations.value[0] directions = { 'a':(-1,0),'d':(1,0),'w':(0,1),'s':(0,-1) } if event.name in directions: step = zoom.value / 10.0 vec = array(directions[event.name],'f') * step center.value = center.value + vec print 'new center', center.value
def OnInit(self): try: self.shader = compileProgram( compileShader(VERTEX_SHADER, gl.GL_VERTEX_SHADER), compileShader(FRAGMENT_SHADER, gl.GL_FRAGMENT_SHADER)) except RuntimeError as err: sys.stderr.write(err.args[0]) sys.exit(1) self.vbo = vbo.VBO(array(VERTEX_DATA, 'f')) for uniform in ( 'Global_ambient', 'Light_ambient', 'Light_diffuse', 'Light_location', 'Material_ambient', 'Material_diffuse', ): location = gl.glGetUniformLocation(self.shader, uniform) if location in (None, -1): print('Warning, no uniform: %s' % uniform) setattr(self, uniform + '_loc', location) for attribute in ( 'Vertex_position', 'Vertex_normal', ): location = gl.glGetAttribLocation(self.shader, attribute) if location in (None, -1): print('Warning, no attribute: %s' % attribute) setattr(self, attribute + '_loc', location)
def __init__ ( self, point = (0,0,0), color = None, normal = None, textureCoordinate = None, metaIndex = -1, coordIndex = -1, indexKey = None, ): """Initialize the Vertex point -- three-dimensional coordinate color -- optional three-float color normal -- optional three-dimensional normalized vector textureCoordinate -- optional two-dimensional texture coordinate metaIndex -- optional integer index into the source index array (i.e. coordIndex[metaIndex], colorIndex[metaIndex],... is the index which produced the vertex. """ self.point = array( point,'d') self.color = color self.normal = normal self.textureCoordinate = textureCoordinate self.metaIndex = int(metaIndex) self.coordIndex = int(coordIndex) self.indexKey = indexKey
def __init__( self, point=(0, 0, 0), color=None, normal=None, textureCoordinate=None, metaIndex=-1, coordIndex=-1, indexKey=None, ): """Initialize the Vertex point -- three-dimensional coordinate color -- optional three-float color normal -- optional three-dimensional normalized vector textureCoordinate -- optional two-dimensional texture coordinate metaIndex -- optional integer index into the source index array (i.e. coordIndex[metaIndex], colorIndex[metaIndex],... is the index which produced the vertex. """ self.point = array(point, 'd') self.color = color self.normal = normal self.textureCoordinate = textureCoordinate self.metaIndex = int(metaIndex) self.coordIndex = int(coordIndex) self.indexKey = indexKey
class TestContext( BaseContext ): ''' creates a simple vertex shader ''' def OnInit( self ): try: self.shader = compileProgram( compileShader( VERTEX_SHADER, gl.GL_VERTEX_SHADER ), compileShader( FRAGMENT_SHADER, gl.GL_FRAGMENT_SHADER ) ) except RuntimeError, err: sys.stderr.write( err.args[0] ) sys.exit( 1 ) self.vbo = vbo.VBO( array( VERTEX_DATA, 'f' ) ) self.position = gl.glGetAttribLocation( self.shader, 'position' ) self.tweened = gl.glGetAttribLocation( self.shader, 'tweened' ) self.color = gl.glGetAttribLocation( self.shader, 'color' ) self.tween = gl.glGetUniformLocation( self.shader, 'tween' ) self.time = Timer( duration = 2.0, repeating = 1 ) self.time.addEventHandler( "fraction", self.OnTimerFraction ) self.time.register( self ) self.time.start()
def coords( self ): """Return our bottom-left and top-right coordinate pairs""" if self._coords is None: tx,ty,d = self.atlas.size() tx,ty = float(tx),float(ty) x,y = self.offset sx,sy = self.size self._coords = array( ((x/tx,y/ty),((x+sx)/tx,(y+sy)/ty)), 'f') return self._coords
def drawCube(): """Draw a cube 2,2,2 units centered around the origin""" # draw six faces of a cube global VBO if VBO is None: if vbo.get_implementation(): data = vbo.VBO(array(list(box.yieldVertices((2, 2, 2))), 'f')) def draw(): data.bind() try: glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS) try: glEnable(GL_VERTEX_ARRAY) glEnable(GL_NORMAL_ARRAY) glEnable(GL_TEXTURE_COORD_ARRAY) glVertexPointer(3, GL_FLOAT, 32, data + 20) glNormalPointer(GL_FLOAT, 32, data + 8) glTexCoordPointer(2, GL_FLOAT, 32, data) glDrawArrays(GL_TRIANGLES, 0, 36) finally: glPopClientAttrib() finally: data.unbind() VBO = draw else: data = array(list(yieldVertices((2, 2, 2))), 'f') def draw(): try: glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS) try: # interleaved arrays is not 3.1 compatible, # but this is the old-code path... glInterleavedArrays(GL_T2F_N3F_V3F, 0, data) glDrawArrays(GL_TRIANGLES, 0, 36) finally: glPopClientAttrib() finally: data.unbind() VBO = draw return VBO()
def Render(self, mode=0): BaseContext.Render(self, mode) glColor(*self.colors[self.useArrays]) glDisable(GL_LIGHTING) # following is required, the indices are in # CW, rather than default CCW order... glDisable(GL_CULL_FACE) VertexArray = [[0, 0, 0], [1, 0, 0], [2, 0, 0], [0, 1, 0], [1, 1, 0], [2, 1, 0], [0, 2, 0], [1, 2, 0], [2, 2, 0]] IndiceArray = [ 0, 3, 4, 0, 4, 1, 1, 4, 5, 1, 5, 2, 3, 6, 7, 3, 7, 4, 4, 7, 8, 4, 8, 5 ] if self.useArrays: VertexArray = array(VertexArray, 'f') #Here's the problem line IndiceArray = array(IndiceArray, 'I') glVertexPointerf(VertexArray) glEnableClientState(GL_VERTEX_ARRAY) glDrawElementsui(GL_TRIANGLES, IndiceArray)
def OnInit( self ): """Initialisation""" print """Should see a simplistic terrain when you look down (<ctrl+down-arrow>)""" points = Image.open( "heightmap.png" ).convert('L') print points.format ix,iy,data = points.size[0],points.size[1],points.tostring() data = arrays.frombuffer( data, 'B' ).astype( 'f' ) self.data = arrays.zeros( (ix,iy,3), 'f' ) markers = arrays.swapaxes( arrays.indices( (ix,iy), 'f'), 0,2 ) self.data[:,:,0] = markers[:,:,0] self.data[:,:,2] = markers[:,:,1] #self.data[:,:,2] = arrays.arange( 0,iy, dtype='f' ).reshape( (1,iy) ) #self.data[:,:,0] = arrays.arange( 0,ix, dtype='f' ) self.data[:,:,1] = data.reshape( (ix,iy) ) # GL_QUAD_STRIP values (simple rendering) # If iy is not event this goes to heck! assert not iy%2, ("""Need a power-of-2 image for heightmap!""", iy) lefts = arrays.arange( 0, iy*(ix-1), dtype='I' ) # create the right sides of the rectangles lrs = arrays.repeat( lefts, 2 ) lrs[1::2] += iy self.indices = lrs.reshape( (ix-1,iy*2) ) self.shape = IndexedPolygons( polygonSides = GL_QUAD_STRIP, index = self.indices, coord = Coordinate( point = self.data, ), solid= False, normal = Normal( vector= array([0,1,0]*(ix*iy),'f'), ), ) self.sg = sceneGraph( children = [ Transform( translation = (0,-10,0), scale = (1.0, 0.002, 1), children = [ Shape( appearance = Appearance( material = Material( diffuseColor = (.5,1,.5), )), geometry = self.shape, ), ], ), PointLight( location=(10,8,5), ), ], )
def Light( self, lightID, mode=None ): """Render light using given light ID for the given mode This will check for: mode.lighting mode.lightingAmbient mode.lightingDiffuse and appropriately enable/disable the various features. Returns whether or not the light ID has been used, which allows us to reuse the light ID in case this light does not actually need it for this particular rendering pass. """ if self.on and mode.lighting and (mode.lightingAmbient or mode.lightingDiffuse): glEnable( GL_LIGHTING ) glEnable( lightID ) ### The following code allows for ambient-only lighting ### and/or diffuse-only if mode.lightingAmbient: x,y,z = self.color * self.ambientIntensity else: x,y,z = 0.0, 0.0, 0.0 glLightfv(lightID, GL_AMBIENT, array((x,y,z,1.0),'f')) if mode.lightingDiffuse: x,y,z = self.color else: x,y,z = 0.0, 0.0, 0.0 glLightfv( lightID, GL_DIFFUSE, array((x,y,z,1.0),'f')*self.intensity ) if hasattr( self, 'location' ): x,y,z = self.location else: x,y,z = -self.direction glLightfv(lightID, GL_POSITION, array((x,y,z,self.pointSource),'f')) return 1 else: return 0
def test_matrix(self): """Test that a texture matrix can produce a proper scale/offset""" map = self.atlasManager.add(NumpyAdapter(zeros((64, 64, 4), 'B'))) matrix = map.matrix() assert matrix is not None bottom_left = dot(array([0, 0, 0, 1], 'f'), matrix) assert allclose(bottom_left, [0, 0, 0, 1]), bottom_left top_right = dot(array([1, 1, 0, 1], 'f'), matrix) assert allclose(top_right, [.25, .25, 0, 1]), top_right map = self.atlasManager.add(NumpyAdapter(zeros((64, 64, 4), 'B'))) matrix = map.matrix() assert matrix is not None bottom_left = dot(array([0, 0, 0, 1], 'f'), matrix) assert allclose(bottom_left, [.25, 0, 0, 1]), (bottom_left, matrix) top_right = dot(array([1, 1, 0, 1], 'f'), matrix) assert allclose(top_right, [.5, .25, 0, 1]), (top_right, matrix) set = dot(array([[0, 0, 0, 1], [1, 1, 0, 1]], 'f'), matrix) assert allclose(set, [[.25, 0, 0, 1], [.5, .25, 0, 1]]), (set, matrix)
def Render(self, mode=0): BaseContext.Render(self, mode) glClearColor(0, 0, 0, 1.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLightfv(GL_LIGHT0, GL_POSITION, array((0.5, 0.5, 1.0, 0.0), 'f')) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) self.updatePositions() glPushMatrix() glTranslatef(-0.15, -0.15, self.solidZ) glMaterialfv( GL_FRONT, GL_EMISSION, array((0.0, 0.0, 0.0, 1.0), 'f'), ) glMaterialfv( GL_FRONT, GL_DIFFUSE, array((0.75, 0.75, 0.0, 1.0), 'f'), ) glCallList(self.sphereList) glPopMatrix() glPushMatrix() glTranslatef(0.15, 0.15, self.transparentZ) glRotatef(15.0, 1.0, 1.0, 0.0) glRotatef(30.0, 0.0, 1.0, 0.0) glMaterialfv(GL_FRONT, GL_EMISSION, array((0.0, 0.3, 0.3, 0.6), 'f')) glMaterialfv(GL_FRONT, GL_DIFFUSE, array((0.0, 0.8, 0.8, 0.8), 'f')) glEnable(GL_BLEND) glDepthMask(GL_FALSE) glBlendFunc(GL_SRC_ALPHA, GL_ONE) # note assumption that background is black... glCallList(self.cubeList) glDepthMask(GL_TRUE) glDisable(GL_BLEND) glPopMatrix()
def Light(self, lightID, mode=None): """Render light using given light ID for the given mode This will check for: mode.lighting mode.lightingAmbient mode.lightingDiffuse and appropriately enable/disable the various features. Returns whether or not the light ID has been used, which allows us to reuse the light ID in case this light does not actually need it for this particular rendering pass. """ if self.on and mode.lighting and (mode.lightingAmbient or mode.lightingDiffuse): glEnable(GL_LIGHTING) glEnable(lightID) ### The following code allows for ambient-only lighting ### and/or diffuse-only if mode.lightingAmbient: x, y, z = self.color * self.ambientIntensity else: x, y, z = 0.0, 0.0, 0.0 glLightfv(lightID, GL_AMBIENT, array((x, y, z, 1.0), 'f')) if mode.lightingDiffuse: x, y, z = self.color else: x, y, z = 0.0, 0.0, 0.0 glLightfv(lightID, GL_DIFFUSE, array((x, y, z, 1.0), 'f') * self.intensity) if hasattr(self, 'location'): x, y, z = self.location else: x, y, z = -self.direction glLightfv(lightID, GL_POSITION, array((x, y, z, self.pointSource), 'f')) return 1 else: return 0
def SceneGraphDefaultlight( self, lightID ): """Create the default headlight VRML browsers generally have a default lighting scheme where, if there are no lights in the scene, a headlight is created pointing from the viewpoint forward into the scene. The light paths found by the OverallPass are used to transform the individual light objects to their appropriate positions in the scene. XXX This code is not quite right, instead of creating a headlight, it is just creating a simple light pointing forward from 0,0,10. What we want is a light that always points forward from the current viewpoint in the current view direction. """ if self.lightingDiffuse: glEnable(lightID) glLight(lightID, GL_DIFFUSE, array((1.0,1.0,1.0,1.0),'f')) glLight(lightID, GL_POSITION, array((0.0,0.0,10.0,1.0),'f'))
def SceneGraphDefaultlight(self, lightID): """Create the default headlight VRML browsers generally have a default lighting scheme where, if there are no lights in the scene, a headlight is created pointing from the viewpoint forward into the scene. The light paths found by the OverallPass are used to transform the individual light objects to their appropriate positions in the scene. XXX This code is not quite right, instead of creating a headlight, it is just creating a simple light pointing forward from 0,0,10. What we want is a light that always points forward from the current viewpoint in the current view direction. """ if self.lightingDiffuse: glEnable(lightID) glLight(lightID, GL_DIFFUSE, array((1.0, 1.0, 1.0, 1.0), 'f')) glLight(lightID, GL_POSITION, array((0.0, 0.0, 10.0, 1.0), 'f'))
def compile(self, mode=None): """Compile the box as a display-list""" if vbo.get_implementation(): vb = vbo.VBO(array(list(yieldVertices(self.size)), 'f')) def draw(textured=True, lit=True): vb.bind() try: glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS) try: glEnableClientState(GL_VERTEX_ARRAY) if lit: glEnableClientState(GL_NORMAL_ARRAY) glNormalPointer(GL_FLOAT, 32, vb + 8) if textured: glEnableClientState(GL_TEXTURE_COORD_ARRAY) glTexCoordPointer(2, GL_FLOAT, 32, vb) glVertexPointer(3, GL_FLOAT, 32, vb + 20) glDrawArrays(GL_TRIANGLES, 0, 36) finally: glPopClientAttrib() finally: vb.unbind() else: vb = array(list(yieldVertices(self.size)), 'f') def draw(textured=True, lit=True): glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS) try: glInterleavedArrays(GL_T2F_N3F_V3F, 0, vb) glDrawArrays(GL_TRIANGLES, 0, 36) finally: glPopClientAttrib() holder = mode.cache.holder(self, draw) holder.depend(self, protofunctions.getField(self, 'size')) return draw
def OnInit(self): """Initialisation""" print( """Should see a simplistic terrain when you look down (<ctrl+down-arrow>)""" ) points = Image.open("heightmap.png").convert('L') print(points.format) ix, iy, data = points.size[0], points.size[1], points.tobytes() data = arrays.frombuffer(data, 'B').astype('f') self.data = arrays.zeros((ix, iy, 3), 'f') markers = arrays.swapaxes(arrays.indices((ix, iy), 'f'), 0, 2) self.data[:, :, 0] = markers[:, :, 0] self.data[:, :, 2] = markers[:, :, 1] #self.data[:,:,2] = arrays.arange( 0,iy, dtype='f' ).reshape( (1,iy) ) #self.data[:,:,0] = arrays.arange( 0,ix, dtype='f' ) self.data[:, :, 1] = data.reshape((ix, iy)) # GL_QUAD_STRIP values (simple rendering) # If iy is not event this goes to heck! assert not iy % 2, ("""Need a power-of-2 image for heightmap!""", iy) lefts = arrays.arange(0, iy * (ix - 1), dtype='I') # create the right sides of the rectangles lrs = arrays.repeat(lefts, 2) lrs[1::2] += iy self.indices = lrs.reshape((ix - 1, iy * 2)) self.shape = IndexedPolygons( polygonSides=GL_QUAD_STRIP, index=self.indices, coord=Coordinate(point=self.data, ), solid=False, normal=Normal(vector=array([0, 1, 0] * (ix * iy), 'f'), ), ) self.sg = sceneGraph(children=[ Transform( translation=(0, -10, 0), scale=(1.0, 0.002, 1), children=[ Shape( appearance=Appearance( material=Material(diffuseColor=(.5, 1, .5), )), geometry=self.shape, ), ], ), PointLight(location=(10, 8, 5), ), ], )
def OnTimerFraction( self, event ): """Update light position/direction""" '''Every cycle we want to do a full rotation, and we want the light to be 10 units from the y axis in the x,z plane. All else is math.''' light = self.lights[0] a = event.fraction() * 2 * pi xz = array( [ sin(a),cos(a), ],'f') * 10 # radius position = light.location position[0] = xz[0] position[2] = xz[1] light.location = position '''We point the light at the origin, mostly because it's easy.''' light.direction = -position
def DrawSphereNew(radius, color): vertices = [] vertices.append([0.0, 0.0, 0.0, color[0], color[1], color[2]]) for angle in range(0, 360, 5): vertices.append([(math.sin(angle) * radius), (math.cos(angle) * radius), 0.0, color[0], color[1], color[2]]) spherevbo = vbo.VBO(array(vertices, 'f')) spherevbo.bind() glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_COLOR_ARRAY) glVertexPointer(3, GL_FLOAT, 24, spherevbo) glColorPointer(3, GL_FLOAT, 24, spherevbo + 12) glDrawArrays(GL_TRIANGLE_FAN, 0, 72) glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_COLOR_ARRAY) spherevbo.unbind()
def OnTimerFraction(self, event): """Update light position/direction""" '''Every cycle we want to do a full rotation, and we want the light to be 10 units from the y axis in the x,z plane. All else is math.''' light = self.lights[0] a = event.fraction() * 2 * pi xz = array([ sin(a), cos(a), ], 'f') * 10 # radius position = light.location position[0] = xz[0] position[2] = xz[1] light.location = position '''We point the light at the origin, mostly because it's easy.''' light.direction = -position
def OnInit( self ): self.shader = compileProgram( compileShader( VERTEX_SHADER, gl.GL_VERTEX_SHADER ), compileShader( FRAGMENT_SHADER, gl.GL_FRAGMENT_SHADER ) ) self.vbo = vbo.VBO( array( [ [ 0, 1, 0 ], [ -1,-1, 0 ], [ 1,-1, 0 ], [ 2,-1, 0 ], [ 4,-1, 0 ], [ 4, 1, 0 ], [ 2,-1, 0 ], [ 4, 1, 0 ], [ 2, 1, 0 ], ], 'f') )
def unproject(self, viewCoordinate=None): """Get the world coordinates for viewCoordinate for the event viewCoordinate -- coordinate to project, if omitted, the first "hit" entry in the name-stack will be used. Otherwise should be a three-item array/tuple. The z component of this tuple is interpreted acording to type. If it's an integer or long, it's consider a raw OpenGL depth-buffer value as returned in the name-stack, and is converted to a floating-point depth value. If it's already a floating- point value, it's left as-is. """ if viewCoordinate is None: if self.worldCoordinate: return self.worldCoordinate if not self.viewCoordinate: if self.getNameStack(): x,y = self.getPickPoint() z = self.getNameStack()[0][0] # near of the first result-set z = z / (2.0**32-1.0) self.viewCoordinate = x,y,z else: raise ValueError( """Attempting to unproject a mouse event without a viewCoordinate or namestack %s"""%self) else: x,y,z = self.viewCoordinate else: x,y,z = viewCoordinate if isinstance( z, (int,long)): z = z / (2.0**32-1.0) viewport = self.viewport if viewport is not None: viewport = array(viewport,'i') worldCoordinate = gluUnProject( x,y,z, self.modelViewMatrix.astype('d'), self.projectionMatrix.astype('d'), viewport, ) if viewCoordinate is None: self.worldCoordinate = worldCoordinate return worldCoordinate
def onPositionFraction( self, event ): """Process fractional update of our position""" fraction = (event.fraction() / 2.0) + .5 x,y,z = self.posInterpolator.on_set_fraction( fraction ) self.platform.position = arrays.array([x,y,z,0.0], 'f' )
"""VRML97-style TextureTransform node""" from OpenGL.GL import * from vrml.vrml97 import basenodes from OpenGLContext.arrays import array, any, allclose from math import pi RADTODEG = 180/pi NULLSCALE = array([1,1],'d') class TextureTransform(basenodes.TextureTransform): """Texture-transformation node based on the VRML node A texture transform should be applied within a block that switches to texture-transform mode first, applies the change, then switches back. You should then pop the texture-transform stack when you're done. http://www.web3d.org/x3d/specifications/vrml/ISO-IEC-14772-IS-VRML97WithAmendment1/part1/nodesRef.html#TextureTransform """ def transform( self, mode=None, translate=1, scale=1, rotate=1 ): ''' Perform the actual alteration of the current matrix ''' if translate and any(self.translation): x,y = self.translation glTranslatef(x,y,0) if (rotate or scale) and any(self.center): cx,cy = self.center glTranslatef(cx,cy,0) if rotate and self.rotation: glRotatef( self.rotation * RADTODEG, 0,0,1) if scale and not allclose(self.scale, NULLSCALE): sx,sy = self.scale
def OnTimerFraction(self, event): self.sg.rotation = array([0, 1, 0, event.fraction() * pi * 2], 'f') self.appearance.material.diffuseColor = [event.fraction()] * 3 self.triggerRedraw(False)
from OpenGL.GL import * from OpenGLContext.arrays import array from OpenGLContext.scenegraph.basenodes import * import string, time ## Control points for the bezier surface ctrlpoints = array([ [[-1.5, -1.5, 4.0] , [-0.5, -1.5, 2.0] , [0.5, -1.5, -1.0] , [1.5, -1.5, 2.0]] , [[-1.5, -0.5, 1.0] , [-0.5, -0.5, 3.0] , [0.5, -0.5, 0.0] , [1.5, -0.5, -1.0]] , [[-1.5, 0.5, 4.0] , [-0.5, 0.5, 0.0] , [0.5, 0.5, 3.0] , [1.5, 0.5, 4.0]] , [[-1.5, 1.5, -2.0] , [-0.5, 1.5, -2.0] , [0.5, 1.5, 0.0] , [1.5, 1.5, -1.0]] , ], 'f' ) ## Texture control points texpts = array([ [[0.0, 0.0], [0.0, 1.0]], [[1.0, 0.0], [1.0, 1.0]],
class _CubeBackground(object): right = field.newField('right', 'SFNode', default=imagetexture.ImageTexture) top = field.newField('top', 'SFNode', default=imagetexture.ImageTexture) back = field.newField('back', 'SFNode', default=imagetexture.ImageTexture) left = field.newField('left', 'SFNode', default=imagetexture.ImageTexture) front = field.newField('front', 'SFNode', default=imagetexture.ImageTexture) bottom = field.newField('bottom', 'SFNode', default=imagetexture.ImageTexture) rightUrl = URLField('rightUrl') topUrl = URLField('topUrl') backUrl = URLField('backUrl') leftUrl = URLField('leftUrl') frontUrl = URLField('frontUrl') bottomUrl = URLField('bottomUrl') bound = field.newField('bound', 'SFBool', 1, 0) def Render(self, mode, clear=1): """Render the cube background This renders those of our cube-faces which are facing us, and which have a non-0 component-count. After it's finished, it clears the depth-buffer to make the geometry appear "behind" everything else. """ if mode.passCount == 0: render_data = mode.cache.getData(self) if render_data is None: render_data = self.compile(mode) if not render_data: return texture, vert_vbo, index_vbo, shader, vertex_loc, mvp_matrix_loc = render_data if clear: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) glDisable(GL_LIGHTING) glDisable(GL_COLOR_MATERIAL) try: with texture: # we don't currently have it handy... with shader: glEnableVertexAttribArray(vertex_loc) with vert_vbo: glVertexAttribPointer(vertex_loc, 3, GL_FLOAT, GL_FALSE, 0, vert_vbo) matrix = dot(mode.matrix, mode.projection) glUniformMatrix4fv(mvp_matrix_loc, 1, GL_FALSE, matrix) with index_vbo: # 6 faces, 4 indices each glDrawElements(GL_QUADS, 24, GL_UNSIGNED_SHORT, index_vbo) glDisableVertexAttribArray(vertex_loc) finally: glDepthMask(GL_TRUE) glEnable(GL_LIGHTING) glEnable(GL_COLOR_MATERIAL) CUBE_VERTICES = array([ -100.0, 100.0, 100.0, -100.0, -100.0, 100.0, 100.0, -100.0, 100.0, 100.0, 100.0, 100.0, -100.0, 100.0, -100.0, -100.0, -100.0, -100.0, 100.0, -100.0, -100.0, 100.0, 100.0, -100.0, ], 'f') CUBE_INDICES = array([ 3, 2, 1, 0, 0, 1, 5, 4, 7, 6, 2, 3, 4, 5, 6, 7, 4, 7, 3, 0, 1, 2, 6, 5, ], 'H') # TODO: should have one-per-context... def compile(self, mode): """Compile a VBO with our various triangles to render""" images = { '-x': self.left, '+x': self.right, '+y': self.top, '-y': self.bottom, '-z': self.front, '+z': self.back, } def all_same(key): current = None for k, value in images.items(): new = getattr(value, key) if current is None: current = new else: if new != current: return False return True if not all_same('components'): return None tex = texture.CubeTexture() try: tex.fromPIL([(k, i.image) for k, i in images.items()]) except ValueError as err: return None vert_vbo = vbo.VBO(self.CUBE_VERTICES) index_vbo = vbo.VBO(self.CUBE_INDICES, target=GL_ELEMENT_ARRAY_BUFFER) # this shader is from shader = shaders.compileProgram( shaders.compileShader( '''#version 130 in vec3 vertex; out vec3 texCoord; uniform mat4 mvp_matrix; void main() { gl_Position = mvp_matrix * vec4( vertex, 1.0); texCoord = normalize(vertex); }''', GL_VERTEX_SHADER), shaders.compileShader( '''#version 130 in vec3 texCoord; out vec4 fragColor; uniform samplerCube cube_map; void main( ) { fragColor = texture(cube_map, texCoord); }''', GL_FRAGMENT_SHADER), ) vertex_loc = glGetAttribLocation(shader, 'vertex') mvp_matrix_loc = glGetUniformLocation(shader, 'mvp_matrix') render_data = (tex, vert_vbo, index_vbo, shader, vertex_loc, mvp_matrix_loc) if hasattr(mode, 'cache'): holder = mode.cache.holder(self, render_data) for key in ('right', 'left', 'top', 'bottom', 'front', 'back'): holder.depend(self, key + 'Url') return render_data
"""Shader node implementation""" from OpenGL.GL import * from OpenGL.GL import shaders as GL_shaders from OpenGL.GLU import * from OpenGL.GLUT import * from OpenGL import error from OpenGL.arrays import vbo from OpenGLContext.arrays import array, reshape from OpenGLContext import context from vrml.vrml97 import shaders import operator from vrml import field, node, fieldtypes, protofunctions from OpenGLContext.scenegraph import polygonsort, boundingvolume from OpenGLContext.arrays import array, transpose LOCAL_ORIGIN = array([[0, 0, 0, 1.0]], 'f') import time, sys from OpenGL.extensions import alternate import logging log = logging.getLogger(__name__) class _Buffer(object): """VBO based buffer implementation for generic geometry""" GL_USAGE_MAPPING = { 'STREAM_DRAW': GL_STREAM_DRAW, 'STREAM_READ': GL_STREAM_READ, 'STREAM_COPY': GL_STREAM_COPY, 'STATIC_DRAW': GL_STATIC_DRAW,
"""Geometry type for "point-arrays" w/ colour support""" from OpenGL.GL import * from vrml.vrml97 import basenodes from OpenGLContext.scenegraph import coordinatebounded from OpenGLContext.arrays import array from OpenGL.extensions import alternate from OpenGL.GL.ARB.point_parameters import * from OpenGL.GL.EXT.point_parameters import * import logging log = logging.getLogger(__name__) glPointParameterf = alternate(glPointParameterf, glPointParameterfARB, glPointParameterfEXT) glPointParameterfv = alternate(glPointParameterfv, glPointParameterfvARB, glPointParameterfEXT) RESET_ATTENUATION = array([1, 0, 0], 'f') class PointSet(coordinatebounded.CoordinateBounded, basenodes.PointSet): """VRML97-style Point-Set object http://www.web3d.org/x3d/specifications/vrml/ISO-IEC-14772-IS-VRML97WithAmendment1/part1/nodesRef.html#PointSet """ def render( self, visible=1, # can skip normals and textures if not lit=1, # can skip normals if not textured=1, # can skip textureCoordinates if not transparent=0, # need to sort triangle geometry... mode=None, # the renderpass object ):
"""Shader node implementation""" from OpenGL.GL import * from OpenGL.GL import shaders as GL_shaders from OpenGL.GLU import * from OpenGL.GLUT import * from OpenGL import error from OpenGL.arrays import vbo from OpenGLContext.arrays import array,reshape from OpenGLContext import context from vrml.vrml97 import shaders import operator from vrml import field,node,fieldtypes,protofunctions from OpenGLContext.scenegraph import polygonsort,boundingvolume from OpenGLContext.arrays import array, transpose LOCAL_ORIGIN = array( [[0,0,0,1.0]], 'f') import time, sys from OpenGL.extensions import alternate import logging log = logging.getLogger( __name__ ) class _Buffer( object ): """VBO based buffer implementation for generic geometry""" GL_USAGE_MAPPING = { 'STREAM_DRAW': GL_STREAM_DRAW, 'STREAM_READ': GL_STREAM_READ, 'STREAM_COPY': GL_STREAM_COPY, 'STATIC_DRAW': GL_STATIC_DRAW, 'STATIC_READ': GL_STATIC_READ, 'STATIC_COPY': GL_STATIC_COPY,
def OnTimerFraction( self, event ): self.sg.rotation = array([0,1,0,event.fraction()*pi*2],'f') self.appearance.material.diffuseColor = [event.fraction()]*3 self.triggerRedraw( False )
from vrml.vrml97 import basenodes from OpenGLContext.scenegraph import coordinatebounded from OpenGLContext.arrays import array from OpenGL.extensions import alternate from OpenGL.GL.ARB.point_parameters import * from OpenGL.GL.EXT.point_parameters import * import logging log = logging.getLogger( __name__ ) glPointParameterf = alternate( glPointParameterf, glPointParameterfARB,glPointParameterfEXT ) glPointParameterfv = alternate( glPointParameterfv, glPointParameterfvARB, glPointParameterfEXT ) RESET_ATTENUATION = array( [1,0,0],'f') class PointSet( coordinatebounded.CoordinateBounded, basenodes.PointSet ): """VRML97-style Point-Set object http://www.web3d.org/x3d/specifications/vrml/ISO-IEC-14772-IS-VRML97WithAmendment1/part1/nodesRef.html#PointSet """ def render ( self, visible = 1, # can skip normals and textures if not lit = 1, # can skip normals if not textured = 1, # can skip textureCoordinates if not transparent = 0, # need to sort triangle geometry...
def Render( self, mode=None ): if mode.visible and not self._rendered: self._rendered = True for char in self.testText: if not char in self.maps: dataArray, metrics = self.font.createCharTexture( char, mode=mode ) dataArray = array( dataArray[:,:,1] ) dataArray.shape = dataArray.shape + (1,) map = self.tc.getTexture( dataArray, texture.Texture ) self.maps[char] = (map,metrics) atlas = self.atlas = self.maps.values()[0][0].atlas atlas.render() self.img = ImageTexture.forTexture( atlas.texture, mode=mode ) self.shape.appearance.texture = self.img points = zeros( (len(self.testText)*6,4),'f') ll = 0,0 for i,char in enumerate(self.testText): map,metrics = self.maps[char] # six points for each character... coords = map.coords() x,y = ll w,h = metrics.width/20.,metrics.height/20. texcoords = array([ [coords[0][0],coords[0][1]], [coords[1][0],coords[0][1]], [coords[1][0],coords[1][1]], [coords[0][0],coords[0][1]], [coords[1][0],coords[1][1]], [coords[0][0],coords[1][1]], ],'f') vertices = array([ (x,y), (x+w,y), (x+w,y+h), (x,y), (x+w,y+h), (x,y+h), ],'f') j = i*6 points[j:j+6,2:] = texcoords points[j:j+6,:2] = vertices ll = (x+w,0) self.vbo = vbo.VBO( points ) self.shape.Render( mode = mode ) if self.vbo is not None: glUseProgram( self.shader ) self.vbo.bind() glActiveTexture(GL_TEXTURE1) glEnable( GL_TEXTURE_2D ) # atlas.render() doesn't work here, need to fix that! self.img.render( visible=True, mode=mode ) glUniform1i( self.atlas_loc, 1 ) # texture *unit* 0 glUniform3f( self.color_loc, 1.0, 0.0, 0.0 ) # texture *unit* 0 glEnableVertexAttribArray( self.coord__loc ) glVertexAttribPointer( self.coord__loc, 2, GL_FLOAT,False, 4*4, self.vbo ) glEnableVertexAttribArray( self.tex__loc ) glVertexAttribPointer( self.tex__loc, 2, GL_FLOAT,False, 4*4, self.vbo+(2*4) ) glDrawArrays(GL_TRIANGLES, 0, 6*len(self.testText)) self.vbo.unbind() glDisableVertexAttribArray( self.coord__loc ) glDisableVertexAttribArray( self.tex__loc ) glUseProgram( 0 ) glDisable( GL_TEXTURE_2D ) glActiveTexture(GL_TEXTURE0)
def selectRender(self, mode, toRender, events): """Render each path to color buffer We render all geometry as non-transparent geometry with unique colour values for each object. We should be able to handle up to 2**24 objects before that starts failing. """ # TODO: allow context to signal that it is "captured" by a # movement manager that doesn't need select rendering... # e.g. for an examine manager there's no reason to do select # render passes... # TODO: do line-box intersection tests for bounding boxes to # only render the geometry which is under the cursor # TODO: render to an FBO instead of the back buffer # (when available) # TODO: render at 1/2 size compared to context to create a # 2x2 selection square and reduce overhead. glClearColor(0, 0, 0, 0) glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT) self.visible = False self.transparent = False self.lighting = False self.textured = False matrix = self.matrix map = {} pickPoints = {} # TODO: this could be faster, and we could do further filtering # using a frustum a-la select render mode approach... min_x, min_y = self.getViewport()[2:] max_x, max_y = 0, 0 pickSize = 2 offset = pickSize // 2 for event in events.values(): x, y = key = tuple(event.getPickPoint()) pickPoints.setdefault(key, []).append(event) min_x = min((x - offset, min_x)) max_x = max((x + offset, max_x)) min_y = min((y - offset, min_y)) max_y = max((y + offset, max_y)) min_x = int(max((0, min_x))) min_y = int(max((0, min_y))) if max_x < min_x or max_y < min_y: # no pick points were found return debugSelection = mode.context.contextDefinition.debugSelection if not debugSelection: glScissor(min_x, min_y, int(max_x) - min_x, int(max_y) - min_y) glEnable(GL_SCISSOR_TEST) glMatrixMode(GL_MODELVIEW) try: idHolder = array([0, 0, 0, 0], 'B') idSetter = idHolder.view('<I') for id, (key, mvmatrix, tmatrix, bvolume, path) in enumerate(toRender): id = (id + 1) << 12 idSetter[0] = id glColor4ubv(idHolder) self.matrix = mvmatrix self.renderPath = path glLoadMatrixf(mvmatrix) path[-1].Render(mode=self) map[id] = path pixel = array([0, 0, 0, 0], 'B') depth_pixel = array([[0]], 'f') for point, eventSet in pickPoints.items(): # get the pixel colour (id) under the cursor. glReadPixels(point[0], point[1], 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel) lpixel = long(pixel.view('<I')[0]) paths = map.get(lpixel, []) event.setObjectPaths([paths]) # get the depth value under the cursor... glReadPixels(point[0], point[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, depth_pixel) event.viewCoordinate = point[0], point[1], depth_pixel[0][0] event.modelViewMatrix = matrix event.projectionMatrix = self.projection event.viewport = self.viewport if hasattr(mode.context, 'ProcessEvent'): mode.context.ProcessEvent(event) finally: glColor4f(1.0, 1.0, 1.0, 1.0) glDisable(GL_COLOR_MATERIAL) glEnable(GL_LIGHTING) glDisable(GL_SCISSOR_TEST)
def selectRender( self, mode, toRender, events ): """Render each path to color buffer We render all geometry as non-transparent geometry with unique colour values for each object. We should be able to handle up to 2**24 objects before that starts failing. """ # TODO: allow context to signal that it is "captured" by a # movement manager that doesn't need select rendering... # e.g. for an examine manager there's no reason to do select # render passes... # TODO: do line-box intersection tests for bounding boxes to # only render the geometry which is under the cursor # TODO: render to an FBO instead of the back buffer # (when available) # TODO: render at 1/2 size compared to context to create a # 2x2 selection square and reduce overhead. glClearColor( 0,0,0, 0 ) glClear( GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT ) self.visible = False self.transparent = False self.lighting = False self.textured = False matrix = self.matrix map = {} pickPoints = {} # TODO: this could be faster, and we could do further filtering # using a frustum a-la select render mode approach... min_x,min_y = self.getViewport()[2:] max_x,max_y = 0,0 pickSize = 2 offset = pickSize//2 for event in events.values(): x,y = key = tuple(event.getPickPoint()) pickPoints.setdefault( key, []).append( event ) min_x = min((x-offset,min_x)) max_x = max((x+offset,max_x)) min_y = min((y-offset,min_y)) max_y = max((y+offset,max_y)) min_x = int(max((0,min_x))) min_y = int(max((0,min_y))) if max_x < min_x or max_y < min_y: # no pick points were found return debugSelection = mode.context.contextDefinition.debugSelection if not debugSelection: glScissor( min_x,min_y,int(max_x)-min_x,int(max_y)-min_y) glEnable( GL_SCISSOR_TEST ) glMatrixMode( GL_MODELVIEW ) try: idHolder = array( [0,0,0,0], 'B' ) idSetter = idHolder.view( '<I' ) for id,(key,mvmatrix,tmatrix,bvolume,path) in enumerate(toRender): id = (id+1) << 12 idSetter[0] = id glColor4ubv( idHolder ) self.matrix = mvmatrix self.renderPath = path glLoadMatrixf( mvmatrix ) path[-1].Render( mode=self ) map[id] = path pixel = array([0,0,0,0],'B') depth_pixel = array([[0]],'f') for point,eventSet in pickPoints.items(): # get the pixel colour (id) under the cursor. glReadPixels( point[0],point[1],1,1,GL_RGBA,GL_UNSIGNED_BYTE, pixel ) lpixel = long( pixel.view( '<I' )[0] ) paths = map.get( lpixel, [] ) event.setObjectPaths( [paths] ) # get the depth value under the cursor... glReadPixels( point[0],point[1],1,1,GL_DEPTH_COMPONENT,GL_FLOAT,depth_pixel ) event.viewCoordinate = point[0],point[1],depth_pixel[0][0] event.modelViewMatrix = matrix event.projectionMatrix = self.projection event.viewport = self.viewport if hasattr( mode.context, 'ProcessEvent'): mode.context.ProcessEvent( event ) finally: glColor4f( 1.0,1.0,1.0, 1.0) glDisable( GL_COLOR_MATERIAL ) glEnable( GL_LIGHTING ) glDisable( GL_SCISSOR_TEST )
def Render(self, mode=None): if mode.visible and not self._rendered: self._rendered = True for char in self.testText: if not char in self.maps: dataArray, metrics = self.font.createCharTexture(char, mode=mode) dataArray = array(dataArray[:, :, 1]) dataArray.shape = dataArray.shape + (1, ) map = self.tc.getTexture(dataArray, texture.Texture) self.maps[char] = (map, metrics) atlas = self.atlas = self.maps.values()[0][0].atlas atlas.render() self.img = ImageTexture.forTexture(atlas.texture, mode=mode) self.shape.appearance.texture = self.img points = zeros((len(self.testText) * 6, 4), 'f') ll = 0, 0 for i, char in enumerate(self.testText): map, metrics = self.maps[char] # six points for each character... coords = map.coords() x, y = ll w, h = metrics.width / 20., metrics.height / 20. texcoords = array([ [coords[0][0], coords[0][1]], [coords[1][0], coords[0][1]], [coords[1][0], coords[1][1]], [coords[0][0], coords[0][1]], [coords[1][0], coords[1][1]], [coords[0][0], coords[1][1]], ], 'f') vertices = array([ (x, y), (x + w, y), (x + w, y + h), (x, y), (x + w, y + h), (x, y + h), ], 'f') j = i * 6 points[j:j + 6, 2:] = texcoords points[j:j + 6, :2] = vertices ll = (x + w, 0) self.vbo = vbo.VBO(points) self.shape.Render(mode=mode) if self.vbo is not None: glUseProgram(self.shader) self.vbo.bind() glActiveTexture(GL_TEXTURE1) glEnable(GL_TEXTURE_2D) # atlas.render() doesn't work here, need to fix that! self.img.render(visible=True, mode=mode) glUniform1i(self.atlas_loc, 1) # texture *unit* 0 glUniform3f(self.color_loc, 1.0, 0.0, 0.0) # texture *unit* 0 glEnableVertexAttribArray(self.coord__loc) glVertexAttribPointer(self.coord__loc, 2, GL_FLOAT, False, 4 * 4, self.vbo) glEnableVertexAttribArray(self.tex__loc) glVertexAttribPointer(self.tex__loc, 2, GL_FLOAT, False, 4 * 4, self.vbo + (2 * 4)) glDrawArrays(GL_TRIANGLES, 0, 6 * len(self.testText)) self.vbo.unbind() glDisableVertexAttribArray(self.coord__loc) glDisableVertexAttribArray(self.tex__loc) glUseProgram(0) glDisable(GL_TEXTURE_2D) glActiveTexture(GL_TEXTURE0)