#!/usr/bin/env python # -*- coding: iso-8859-1 -*- ##################################################################### # Drawing methods comparison (part of FoFiX) # # Copyright (C) 2009 Pascal Giard # # # # This program is free software; you can redistribute it and/or # # modify it under the terms of the GNU General Public License # # as published by the Free Software Foundation; either version 2 # # of the License, or (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the Free Software # # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # # MA 02110-1301, USA. # ##################################################################### from OpenGL.GL import * try: from OpenGL.arrays import vbo vbo_support = True except: vbo_support = False from numpy import array, float32, append, hstack import pygame from pygame.locals import * from math import cos, sin, sqrt rot = 0.0 scale = 1.0 mode = 2 def init(): global mode, triangVbo, triangVtx, triangCol global spiralVtx, spiralVbo, spiralCol triangVtx = array( [[ 0, 1, 0], [-1, -1, 0], [ 1, -1, 0]], dtype=float32) triangCol = array( [[ 0, 1, 0], [ 1, 0, 0], [ 0, 0, 1]], dtype=float32) nbSteps = 200.0 for i in range(int(nbSteps)): ratio = i/nbSteps; angle = 21*ratio c = cos(angle) s = sin(angle); r1 = 1.0 - 0.8*ratio; r2 = 0.8 - 0.8*ratio; alt = ratio - 0.5 nor = 0.5 up = sqrt(1.0-nor*nor) if i == 0: spiralVtx = array([[r1*c, alt, r1*s]],dtype=float32) spiralCol = array([[1.0-ratio, 0.2, ratio]],dtype=float32) else: spiralVtx = append(spiralVtx,[[r1*c, alt, r1*s]],axis=0) spiralCol = append(spiralCol,[[1.0-ratio, 0.2, ratio]],axis=0) spiralVtx = append(spiralVtx,[[r2*c, alt+0.05, r2*s]],axis=0) spiralCol = append(spiralCol,[[1.0-ratio, 0.2, ratio]],axis=0) if vbo_support: triangArray = hstack((triangVtx, triangCol)).astype(float32) spiralArray = hstack((spiralVtx, spiralCol)).astype(float32) triangVbo = vbo.VBO( triangArray, usage='GL_STATIC_DRAW' ) spiralVbo = vbo.VBO( spiralArray, usage='GL_STATIC_DRAW' ) else: print "VBO not supported, fallbacking to array-based drawing." mode = 1 def draw(): global mode, triangVbo, triangVtx, triangCol global spiralVtx, spiralVbo, spiralCol, rot, scale glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) glLoadIdentity() glPushMatrix() glColor(1,1,1) # triangle color glScale(scale,scale,scale) glRotate(rot,0,1,0) # VBO drawing if mode == 0 and vbo_support: # Draw triangle triangVbo.bind() glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(3, GL_FLOAT, 24, triangVbo ) glColorPointer(3, GL_FLOAT, 24, triangVbo+12 ) glDrawArrays(GL_TRIANGLES, 0, triangVtx.shape[0]) glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); triangVbo.unbind() # Draw spiral # evilynux - FIXME: The following doesn't work... why? spiralVbo.bind() glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY) glVertexPointer(3, GL_FLOAT, 24, spiralVbo ) glColorPointer(3, GL_FLOAT, 24, spiralVbo+12 ) glDrawArrays(GL_TRIANGLE_STRIP, 0, spiralVtx.shape[0]) glDisableClientState(GL_COLOR_ARRAY) glDisableClientState(GL_VERTEX_ARRAY) spiralVbo.unbind() # Array-based drawing elif mode == 1: # Draw triangle glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_COLOR_ARRAY) glColorPointerf(triangCol) glVertexPointerf(triangVtx) glDrawArrays(GL_TRIANGLES, 0, triangVtx.shape[0]) # Draw spiral glColorPointerf(spiralCol) glVertexPointerf(spiralVtx) glDrawArrays(GL_TRIANGLE_STRIP, 0, spiralVtx.shape[0]) glDisableClientState(GL_COLOR_ARRAY) glDisableClientState(GL_VERTEX_ARRAY) # Direct drawing # With pyopengl3.x, glVertex3fv() is much slower than glVertex3f(). else: # mode == 2 glBegin(GL_TRIANGLES) for i in range(triangVtx.shape[0]): glColor(triangCol[i]) #glVertex3fv(triangVtx[i]) glVertex3f(triangVtx[i][0],triangVtx[i][1],triangVtx[i][2]) glEnd() # Draw spiral glBegin(GL_TRIANGLE_STRIP); for i in range(spiralVtx.shape[0]): #glColor(spiralCol[i]) #glVertex3fv(spiralVtx[i]) glColor(spiralCol[i][0],spiralCol[i][1],spiralCol[i][2]) glVertex3f(spiralVtx[i][0],spiralVtx[i][1],spiralVtx[i][2]) glEnd() glPopMatrix() def main(): global rot, scale, mode scale_dir = -1 modeName = ["VBO", "Array-based", "Direct-mode"] fps = 0 video_flags = DOUBLEBUF|OPENGL|HWPALETTE|HWSURFACE pygame.init() pygame.display.set_mode((640,480), video_flags) init() frames = 0 ticks = pygame.time.get_ticks() clock = pygame.time.Clock() while 1: event = pygame.event.poll() if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): break elif event.type == KEYDOWN and event.key == K_RIGHT: mode = (mode + 1) % 3 if mode == 0 and not vbo_support: mode = (mode + 1) % 3 print "VBO not supported, fallbacking to %s drawing." % modeName[mode] elif event.type == KEYDOWN and event.key == K_LEFT: mode = (mode - 1) % 3 if mode == 0 and not vbo_support: mode = (mode - 1) % 3 print "VBO not supported, fallbacking to %s drawing." % modeName[mode] ticksDiff = pygame.time.get_ticks()-ticks # draw all objects draw() # update rotation counters rot += 0.2 scale += scale_dir*0.0002 if scale > 1.0 or scale < 0.5: scale_dir = scale_dir*-1 # make changes visible pygame.display.flip() frames = frames+1 if( ticksDiff > 2000 ): fps = ((frames*1000)/(ticksDiff)) ticks = pygame.time.get_ticks() frames = 0 print "mode: %s, %.2f fps" % (modeName[mode], fps) # evilynux - commented the following so we go as fast as we can #clock.tick(60) if __name__ == '__main__': main()