[wxPython] glcanvas flickers on linux

Okay, here's the whole demo. Unfortunately, it relies on all sorts of stuff
that I can't release, but it doesn't flicker. Things to note:

    self.Refresh(eraseBackground=FALSE)
  Uses double buffered OpenGL (swapbuffers)

Other than that, I'm at a loss. I used to fool with the Frame's styles to
attempt to get it to no draw in the client areas, but it didn't seem to make
a difference (so I removed it).

Good luck,
Mike

from math import pi
dependencies = '''This demo requires:
  wxPython (with wxGLCanvas compiled)
  PyOpenGL
  Numeric Python
  PyOpenGL extensions to support array drawing.
'''
try:
  from wxPython.wx import *
  from OpenGL.GL import *
  from OpenGL.GLU import *
  from wxPython import glcanvas
  import Numeric # just to make sure it's there before we start
working...
except ImportError, value:
  print dependencies
  raise

from glscenegraph import viewplatform
from glscenegraph.constants import *

class GLCanvas(glcanvas.wxGLCanvas):
  deltaTurn = pi/64
  step = 0.1
  multiplier = 4
  fieldOfView = pi/2
  lookAroundRotations = {
    WXK_UP:(1,0,0,-deltaTurn),
    WXK_DOWN: (1,0,0,deltaTurn),
    WXK_RIGHT: (0,1,0,-deltaTurn),
    WXK_LEFT: (0,1,0,deltaTurn),
  }
  def __init__(self, parent):
    glcanvas.wxGLCanvas.__init__(self, parent, -1)
    self.init = false
    EVT_ERASE_BACKGROUND(self, self.OnEraseBackground)
    EVT_CHAR(self, self.OnChar)
    EVT_LEFT_DOWN( self, self.OnMouseClickLeft )
    EVT_MOTION( self, self.OnMouseMove )
    EVT_LEFT_UP( self, self.OnMouseReleaseLeft )
    self.platform = viewplatform.ViewPlatform(
fieldOfView=self.fieldOfView )
  def OnPaint(self, event):
    dc = wxPaintDC(self)

    ctx = self.GetContext()
    if not ctx: return

    self.SetCurrent()

    if not self.init:
      self.InitGL()
      self.init = true
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    self.platform.render()
    self.DrawGeometry ()
    self.SwapBuffers()
  def DrawGeometry (self, mode=RENDER_MODE_OPAQUE ):
    ''' Override this to draw your own geometry '''
  def InitGL(self):
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glMatrixMode(GL_PROJECTION);
    self.platform.setup()
    glMatrixMode(GL_MODELVIEW);

    glDisable( GL_FOG )
    glDisable( GL_TEXTURE_2D );

    glEnable( GL_CULL_FACE );
    glFrontFace( GL_CCW );
    glCullFace( GL_BACK );

    glDisable( GL_COLOR_MATERIAL );
    glDisable(GL_BLEND);
    glShadeModel( GL_SMOOTH );
  def OnMouseMove ( self, event ):
    # see if we're over a sensitive child
    result = glSelectWithCallback( event.GetX(), event.GetY(),
self.renderPick)
    if result: # is over a sensitive object:
      print "over", result
  def OnMouseClickLeft( self, event ):
## print "OnMouseClickLeft", event.GetX(), event.GetY()
    result = glSelectWithCallback( event.GetX(), event.GetY(),
self.renderPick)
    if result: # is over a sensitive object:
      print "click", result
  def OnMouseReleaseLeft( self, event ):
    result = glSelectWithCallback( event.GetX(), event.GetY(),
self.renderPick)
    if result: # is over a sensitive object:
      print "release over", result
  
  def renderPick( self ):
    self.DrawGeometry( mode = RENDER_MODE_SELECT_FORCED )
    # do interpretation here...

  def OnChar(self, event):
    code = event.KeyCode()
    # general commands
    if code == ord('-'): #
      self.platform.straighten()
    # control modes...
    elif event.ControlDown():
      # This is the "look around" mode
      rotation = self.lookAroundRotations.get( code)
      if rotation:
        self.platform.turn ( rotation )
      else:
        event.Skip ()
        return
    else:
      # default is "walk/fly" mode
      if event.ShiftDown():
        multiplier = self.multiplier
      else:
        multiplier = 1
      if code == WXK_UP:
        # forward
        self.platform.forward(self.step*multiplier)
      elif code ==WXK_DOWN:
        # backward
        self.platform.forward
(-self.step*multiplier)
      else:
        # either a turn or nothing
        rotation = self.lookAroundRotations.get(
code)
        if rotation:
          self.platform.turn ( rotation )
        else:
          event.Skip ()
          return
    # force a repaint
    self.Refresh(eraseBackground=FALSE)
  def OnEraseBackground(self, event):
    pass # Do nothing, to avoid flashing.

  def OnSize(self, event):
    size = self.GetClientSize()
    if self.GetContext() != 'NULL':
      self.SetCurrent()
      # aspect ratio calculation
      # fov represents the vertical field of view
      # aspect represents ratio of width to height for
field of view
      # we want the field of view to the constant for the
smallest dimension
      # and all visible ratios to be 1.0:1.0
      if size.height > 0 and size.width >0:
        ratio = size.width/float(size.height )
        if size.height < size.width:
          # width specifies field of view
          fieldOfView = self.fieldOfView/ratio
        else:
          fieldOfView = self.fieldOfView
        self.platform.set_frustrum( fieldOfView,
ratio)
        self.platform.setup()
        self.Refresh (eraseBackground=FALSE)
      glViewport(0, 0, size.width, size.height)
      
if __name__ == '__main__':
  class TestGLCanvas( GLCanvas ):
    def DrawGeometry (self):
      ''' Override this to draw your own geometry '''
      glMatrixMode(GL_MODELVIEW)
      glPushMatrix()
      glRotate(1,0,0,-90)
      glDisable(GL_LIGHTING)
      glColor3f( 0,0,.3)
      fullsize = 40
      tilesize = 4
      
      glBegin(GL_QUADS)
      for x in range(-(fullsize/2),(fullsize/2),tilesize):
        for y in
range(-(fullsize/2),(fullsize/2),tilesize):
          if (((x+y)/tilesize)%2):
            glNormal3f( 0.0, 1.0, 0.0)
            glVertex3f( x, 0, y)
            glVertex3f( x, 0,
y+tilesize)
            glVertex3f( x+tilesize, 0,
y+tilesize)
            glVertex3f( x+tilesize, 0,
y)
      glEnd( )
      glColor3f( 1,1,0)
      glBegin(GL_QUADS)
      for x in range(-(fullsize/2),(fullsize/2),tilesize):
        for y in
range(-(fullsize/2),(fullsize/2),tilesize):
          if not (((x+y)/tilesize)%2):
            glNormal3f( 0.0, 1.0, 0.0)
            glVertex3f( x, 0, y)
            glVertex3f( x, 0,
y+tilesize)
            glVertex3f( x+tilesize, 0,
y+tilesize)
            glVertex3f( x+tilesize, 0,
y)
      glEnd( )
      glPopMatrix()
      # clear color and depth buffers
      glEnable(GL_LIGHTING)

      glPushMatrix()
      glColor3f( .8,.8,0)
      glTranslate( 0,.5,0)
      glRotatef(30.0, 1.0, 0.0, 0.0);
      glRotatef(30.0, 0.0, 1.0, 0.0);
      # draw six faces of a cube
      glBegin(GL_QUADS)
      glNormal3f( 0.0, 0.0, 1.0)
      glVertex3f( 0.5, 0.5, 0.5)
      glVertex3f(-0.5, 0.5, 0.5)
      glVertex3f(-0.5,-0.5, 0.5)
      glVertex3f( 0.5,-0.5, 0.5)

      glNormal3f( 0.0, 0.0,-1.0)
      glVertex3f(-0.5,-0.5,-0.5)
      glVertex3f(-0.5, 0.5,-0.5)
      glVertex3f( 0.5, 0.5,-0.5)
      glVertex3f( 0.5,-0.5,-0.5)

      glNormal3f( 0.0, 1.0, 0.0)
      glVertex3f( 0.5, 0.5, 0.5)
      glVertex3f( 0.5, 0.5,-0.5)
      glVertex3f(-0.5, 0.5,-0.5)
      glVertex3f(-0.5, 0.5, 0.5)

      glNormal3f( 0.0,-1.0, 0.0)
      glVertex3f(-0.5,-0.5,-0.5)
      glVertex3f( 0.5,-0.5,-0.5)
      glVertex3f( 0.5,-0.5, 0.5)
      glVertex3f(-0.5,-0.5, 0.5)

      glNormal3f( 1.0, 0.0, 0.0)
      glVertex3f( 0.5, 0.5, 0.5)
      glVertex3f( 0.5,-0.5, 0.5)
      glVertex3f( 0.5,-0.5,-0.5)
      glVertex3f( 0.5, 0.5,-0.5)

      glNormal3f(-1.0, 0.0, 0.0)
      glVertex3f(-0.5,-0.5,-0.5)
      glVertex3f(-0.5,-0.5, 0.5)
      glVertex3f(-0.5, 0.5, 0.5)
      glVertex3f(-0.5, 0.5,-0.5)
      glEnd()

      glPopMatrix()
  class MyApp(wxApp):
    def OnInit(self):
      frame = wxFrame(NULL, -1, "GL Cube",
wxDefaultPosition, wxSize(400,300))
      win = TestGLCanvas(frame)
      frame.Show(TRUE)
      self.SetTopWindow(frame)
      return TRUE

  app = MyApp(0)
  app.MainLoop()

···

-----Original Message-----
From: Ryan Martin [mailto:ryanm@wag.caltech.edu]
Sent: Wednesday, July 05, 2000 8:01 PM
To: Mike Fletcher
Cc: wxpython-users@wxwindows.org
Subject: Re: [wxPython] glcanvas flickers on linux

Sorry, forgot to mention I already have an empty OnEraseBackground
handler. The problem is something else.

-Ryan

Mike Fletcher (mfletch@tpresence.com) [000705 16:54]

>From a little internal project...

class GLCanvas(glcanvas.wxGLCanvas):
  def __init__(self, parent):
    glcanvas.wxGLCanvas.__init__(self, parent, -1)
    self.init = false
    EVT_ERASE_BACKGROUND(self, self.OnEraseBackground)
    EVT_CHAR(self, self.OnChar)
    EVT_LEFT_DOWN( self, self.OnMouseClickLeft )
    EVT_MOTION( self, self.OnMouseMove )
    EVT_LEFT_UP( self, self.OnMouseReleaseLeft )
    self.platform = viewplatform.ViewPlatform(
fieldOfView=self.fieldOfView )
  def OnEraseBackground(self, event):
    pass # Do nothing, to avoid flashing.

HTH,
Mike

-----Original Message-----
From: Ryan Martin [mailto:ryanm@wag.caltech.edu]
Sent: Wednesday, July 05, 2000 6:47 PM
To: wxpython-users@wxwindows.org
Subject: [wxPython] glcanvas flickers on linux

I have a program that loads and saves molecular description files and
gives the option to display them using opengl. When the user double
clicks on a molecule, I render that molecule in a second frame
containing a glcanvas object. It works fine but the moment I start
to rotate, translate or zoom on the molecule(meaning OnPaint is
being called a lot) the canvas flickers. I'm using the standard
SwapBuffers command that comes with glcanvas. Has anyone else run into
this problem using wxGTK on linux? Hopefully I can find a fix for this
so I don't have to go back to tkinter and try to get togl to work.

I'm using wxPython 2.1.16, wxWindows 2.1.16, GTK+ 1.2.8, and Mesa 3.2.

I'm not subscribe to the list, so can you please cc me on any replies.

Thanks.

-Ryan

_______________________________________________
wxPython-users mailing list wxPython-users@wxwindows.org
http://wxwindows.org/mailman/listinfo/wxpython-users

_______________________________________________
wxPython-users mailing list wxPython-users@wxwindows.org
http://wxwindows.org/mailman/listinfo/wxpython-users