[visionegg] Re: Dropping into C
- From: Simeon Fitch <simeon.fitch@xxxxxxxxxxxxx>
- To: visionegg@xxxxxxxxxxxxx
- Date: Thu, 2 Feb 2006 09:13:37 -0500
Doug,
Unfortunately, I've not had time to look over this, but if you are changing
the point values directly you need to look into using write enabled vertex
buffer objects (advanced, but basically an extension of vertex arrays) or
vertex programs (very advanced, requires very modern hardware, but very
fast). Either that or consider if your model con be re-organized/broken up
such that your transformations can be applied with simple matrix operations
on subsections of the model.
I hope this helps. I suspect vertex buffer objects are what you need. See
http://developer.nvidia.com/object/using_VBOs.html
Simeon
On 1/31/06, Douglas Taylor <dtaylor@xxxxxxx> wrote:
>
> Hi Simeon,
>
> I've included my test app which I use to test things before I
> incorporate them into the VisionEgg(it's kinda a mess ;) ). Since
> the data is dynamically changing from frame to frame you do
> have to call glVertexPointer() each frame. Curiously enough this
> is the call that is hanging up things. glDrawarrays is quick. This
> is from my own profiling. My develope machine here is a Mac.
> Using the PythonIDE I made an applet out of glcube2.py but
> I couldn't get the profiler to work with it. I may post to the Apple
> OpenGl list to see if they have any hints.
>
> My experiment with glVertexArray in C seemed to only show
> a slight performance increase on NVidia harware over the draw_in_c
> method. Best,
>
> Doug
>
>
> Simeon Fitch wrote:
>
> Doug,
>
> I think the reason you might have been getting *worse* performance was
> that you are (I'm inferring here) calling "glVertexPointer()" inside each
> call to draw(). This means that every time draw() is called you are copying
> all the data to the driver/hardware, which is exactly what you don't want to
> do.
>
> In your __init__ method (or something called before you enter the draw()
> loop) you should call the glEnableClientState() and glVertexPointer(), and
> then in your draw() method call "glDrawArrays()". Don't call
> glDisableClientState() at all unless there is some specific reason you need
> to.
>
> IMHO, you should be able to achieve the performance you desire without
> "dropping into C". If not, and you are running on MacOS X, and have the
> developer tools installed, try running the "OpenGL Profiler" tool to help
> identify OpenGL calls that are perhaps not necessary and slowing things down
> (remembering that OpenGL is a "state machine"). This tool is installed to
> "/Developer/Applications/Graphics Tools".
>
> Best,
>
> Simeon
>
> On 1/27/06, Douglas Taylor <dtaylor@xxxxxxx> wrote:
> >
> > Hi Andrew,
> >
> > I was trying to optimize the dot drawing routine
> > using the Vertex Array method
> >
> > xy[:,0] = xstart #where xy is an [npoints][2] array
> > xy[:,1] = ystart
> > # Pass a pointer to the start of the point-coordinate array:
> > glVertexPointerd(xy);
> > # glVertexPointer(2, GL_DOUBLE, 0, xy); Python did not like
> > it this way
> > # Enable fast rendering of arrays:
> > glEnableClientState(GL_VERTEX_ARRAY);
> > # Render all n points, starting at point 0, render them as
> > POINTS:
> > glDrawArrays(GL_POINTS, 0, len(xstart));
> > # Disable fast rendering of arrays:
> > glDisableClientState(GL_VERTEX_ARRAY);
> >
> > and on the Mac(10.3 and 10.4) I actually got worse performance than the
> > GL_POINTS loop method. So I would like to drop into C and I found
> > the _draw_in_c.c code which looks like a good place to start. I don't
> > understand however how you generated the .so file. I couldn't find
> > any examples on the Apple site either. I have XCODE and CodeWarrior.
> > Could you point me in the right direction here. Thanks much,
> >
> > Doug
> >
> >
> > ======================================
> > The Vision Egg mailing list
> > Archives: http://www.freelists.org/archives/visionegg
> > Website: http://www.visionegg.org/mailinglist.html
> >
>
>
>
> --
> Simeon H.K. Fitch, Owner
> Mustard Seed Software
> 1634 Brandywine Drive
> Charlottesville, VA 22901
> 210.867.1616
>
>
> #!/usr/bin/env python
>
> """Draw a cube on the screen. every frame we orbit
> the camera around by a small amount and it appears
> the object is spinning. note i've setup some simple
> data structures here to represent a multicolored cube,
> we then go through a semi-unopimized loop to draw
> the cube points onto the screen. opengl does all the
> hard work for us. :]
> """
>
> import Numeric,time,sys,RandomArray,random,pygame
> from pygame.locals import *
>
> from random import *
>
> print sys.platform
>
> try:
> from OpenGL.GL import *
> from OpenGL.GLU import *
> except:
> print 'The GLCUBE example requires PyOpenGL'
> raise SystemExit
>
> if sys.platform == "darwin":
> try:
> import _darwin_sync_swap
> #_darwin_sync_swap.sync_swap()
> success = 1
> except:
> print 'This GLCUBE example requires _darwin_sync_swap'
> raise SystemExit
>
> import VisionEgg
>
> try:
> ### C version of draw_dots() isn't (yet) as fast as Python version:
> import VisionEgg._draw_in_c
> success = 1
> ##draw_dots = VisionEgg._draw_in_c.draw_dots # draw in C for speed
> except:
> print 'The GLCUBE example requires _draw_in_c'
> raise SystemExit
>
>
> #some simple data for a colored cube
> #here we have the 3D point position and color
> #for each corner. then we have a list of indices
> #that describe each face, and a list of indieces
> #that describes each edge
>
> NUM_POINTS = 512
> #use_vertex_array = True
>
> CUBE_POINTS = (
> (0.5, -0.5, -0.5), (0.5, 0.5, -0.5),
> (-0.5, 0.5, -0.5), (-0.5, -0.5, -0.5),
> (0.5, -0.5, 0.5), (0.5, 0.5, 0.5),
> (-0.5, -0.5, 0.5), (-0.5, 0.5, 0.5)
> )
>
> #colors are 0-1 floating values
> CUBE_COLORS = (
> (1, 0, 0), (1, 1, 0), (0, 1, 0), (0, 0, 0),
> (1, 0, 1), (1, 1, 1), (0, 0, 1), (0, 1, 1)
> )
>
> CUBE_QUAD_VERTS = (
> (0, 1, 2, 3), (3, 2, 7, 6), (6, 7, 5, 4),
> (4, 5, 1, 0), (1, 5, 7, 2), (4, 0, 3, 6)
> )
>
> CUBE_EDGES = (
> (0,1), (0,3), (0,4), (2,1), (2,3), (2,7),
> (6,3), (6,4), (6,7), (5,1), (5,4), (5,7),
> )
>
>
>
> def drawcube():
> "draw the cube"
> allpoints = zip(CUBE_POINTS, CUBE_COLORS)
>
> glBegin(GL_QUADS)
> for face in CUBE_QUAD_VERTS:
> for vert in face:
> pos, color = allpoints[vert]
> glColor3fv(color)
> glVertex3fv(pos)
> glEnd()
>
> glColor3f(1.0, 1.0, 1.0)
> glBegin(GL_LINES)
> for line in CUBE_EDGES:
> for vert in line:
> pos, color = allpoints[vert]
> glVertex3fv(pos)
>
> glEnd()
>
>
> def main():
> "run the demo"
> use_vertex_array = input('Use vertex array method(1=yes)? ')
> #input('Use vertex arrayy method? ')
> #initialize pygame and setup an opengl display
> pygame.init()
> pygame.display.set_mode((1024,768),
> OPENGL|DOUBLEBUF|FULLSCREEN|HWSURFACE)
>
> #glEnable(GL_DEPTH_TEST) #use our zbuffer
> #glClearColor(1.0,0.0,0.0,1.0)
> if sys.platform == "darwin":
> _darwin_sync_swap.sync_swap()
>
> #setup the camera
> glMatrixMode(GL_PROJECTION)
> #gluPerspective(45.0,640/480.0,0.1,100.0) #setup lens
> #glTranslatef(0.0, 0.0, -3.0) #move back
> #glRotatef(25, 1, 0, 0) #orbit higher
> gluOrtho2D(-1.33333, 1.33333, -1.0, 1.0)
> glEnable(GL_POINT_SMOOTH)
> # allow max_alpha value to control blending
> glEnable( GL_BLEND )
> glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA )
>
> xstart = RandomArray.uniform(-1.0, 1.0, (NUM_POINTS,))
> ystart = RandomArray.uniform(-1.0,1.0, (NUM_POINTS,))
> zstart = RandomArray.uniform(0.0,1.0, (NUM_POINTS,))
> t1 = RandomArray.uniform(0.0,1.0, (NUM_POINTS,))
> xy = RandomArray.uniform(0.0,1.0, (2,NUM_POINTS))
> xyTrans = RandomArray.uniform(0.0,1.0, (NUM_POINTS,2))
> print xy[:,0]
> frame = 0
> t1[frame] = time.time()
>
> for i in range(NUM_POINTS):
> zstart[i] = 0.0
> while xstart[i]*xstart[i]+ystart[i]*ystart[i] > 1.0:
> xstart[i] = random()*2 - 1.0
> ystart[i] = random()*2 - 1.0
>
> xy[0,:] = xstart
> xy[1,:] = ystart
> #print len(xstart)
>
> while 1:
> #check for quit'n events
> event = pygame.event.poll()
> if event.type == QUIT or (event.type == KEYDOWN and event.key ==
> K_ESCAPE) or frame==NUM_POINTS-1:
> break
>
> t1[frame] = time.time()
>
> #clear screen and move camera
> #glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
> glClear(GL_COLOR_BUFFER_BIT)
>
> #orbit camera around by 1 degree
> #glRotatef(1, 0, 1, 0)
>
> drawcube()
> glPointSize(16)
>
> t1[frame] = time.time()
> if use_vertex_array == False:
> glColor4f(1.0, 0.0, 0.0,1.0);
> VisionEgg._draw_in_c.draw_dots(xstart,ystart,zstart)
> #glBegin(GL_POINTS);
> #for i in range(NUM_POINTS):
> #glVertex3f(random.random(),random.random(),1.0);
> #glVertex3f(xstart[i],ystart[i],zstart[i]);
> #glVertex2f(xstart[i],ystart[i]);
> #glVertex3f(xy[0,i],xy[1,i],zstart[i]);
> #glEnd()
> else:
> # Pass a pointer to the start of the point-coordinate array:
> #xyTrans = Numeric.transpose(xy)
> #glVertexPointer(2, GL_DOUBLE, 0, xyTrans);
> glColor4f(0.0, 1.0, 0.0,1.0);
> xyTrans[:,0] = xstart
> xyTrans[:,1] = ystart
> #VisionEgg._draw_in_c.draw_dots(xyTrans)
> glVertexPointerd(xyTrans);
> # glVertexPointer(2, GL_DOUBLE, 0, xyTrans);
> # Enable fast rendering of arrays:
> glEnableClientState(GL_VERTEX_ARRAY);
> # Render all n points, starting at point 0, render them as
> POINTS:
> glDrawArrays(GL_POINTS, 0, len(xstart));
> # Disable fast rendering of arrays:
> #glDisableClientState(GL_VERTEX_ARRAY);
> #glFlush()
> t1[frame] = time.time() - t1[frame]
>
> pygame.display.flip()
> #pygame.time.wait(10)
> xstart = xstart + 0.008
> #xy[0,:] = xy[0,:] + 0.008
> #t1[frame] = time.time()
> #xstart_mask = Numeric.where(xy[0,:] > 1.0, 1, 0)
> #Numeric.putmask(xy[0,:], xstart_mask, -xy[0,:])
> #t1[frame] = time.time()
> #xstart = xy[0,:]
> #ystart = xy[1,:]
> x = xstart*xstart
> y = ystart*ystart
> limit = x+y
> #xy[0,:] = Numeric.choose(Numeric.greater(limit,1.0), (xy[0,:],
> -xy[0,:]))
> xstart = Numeric.choose(Numeric.greater(limit,1.0), (xstart,
> -xstart))
> ystart = Numeric.choose(Numeric.greater(limit,1.0), (ystart,
> -ystart))
> #xstart = xy[0,:]
> #t1[frame] = time.time() - t1[frame]
>
> frame += 1
> #To replace the values in the original data array T for which
> bigpts_mask is true (i.e. 1), use the Numeric.putmask command. For
> instance, to replace all the points where T is greater than 280 K with 5 K:
>
> #print zip([xstart,ystart]), xstart,ystart
> count = 0
> for i in range(NUM_POINTS):
> if t1[i]*1000 > 0.20:
> count += 1
> print count,t1[i]*1000
> #for i in range(10):
> # print "%d\t" % random.randint(0,NUM_POINTS)
>
>
> if __name__ == '__main__': main()
>
>
>
--
Simeon H.K. Fitch, Owner
Mustard Seed Software
1634 Brandywine Drive
Charlottesville, VA 22901
210.867.1616
Other related posts: