Rubberband Problems using OpenGL/wxPython

OK. I’m really beating my head against this problem.

Here is the program in it’s entirety. We think that there is a bug in the drivers. I have the following hardware specs:

QuadroFX 4600 Nvidia
Drivers: 173.14.12
OpenGL drivers: 2.1.2

Using the XOR operation does NOT work properly in doublebuffer mode using this card. We pulled a QuadroFX 3700 vid card and ran the same drivers and it draws the rectangle fine.

Here’s the code:


#! /usr/bin/env python
import wx
from wx import glcanvas
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
import time, sys

class MyCanvasBase(glcanvas.GLCanvas):
    def __init__(self,parent):
        attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER)
        glcanvas.GLCanvas.__init__(self,parent, attribList=attribList)
        self.init = False
        self.m_stpoint = (0.0, 0.0)
        self.m_endpoint = (0.0, 0.0)
        self.size = None
        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
        self.Bind(wx.EVT_SIZE, self.OnSize)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
        self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
        self.Bind(wx.EVT_MOTION, self.OnMouseMotion)
       
    def InitGL(self):
        glutInit([])
        # set viewing projection
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glFrustum(-0.5, 0.5, -0.5, 0.5, 1.0, 300.0)
        glMatrixMode(GL_MODELVIEW)
        glTranslatef(0.0, 0.0, -2.0)
        glLineWidth(1.0)
       
    def OnEraseBackground(self, event):
        pass
   
    def OnSize(self, event):
        size = self.size = self.GetClientSize()
        self.SetCurrent()
        glViewport(0, 0, size.width, size.height)
       
    def OnPaint(self,event):
        dc = wx.PaintDC(self)
        self.SetCurrent()
        if not self.init:
            self.InitGL()
            self.init = True
        self.OnDraw()
      
    def DrawRectangle(self, evt):
        sw,sh = self.GetClientSize()
        rect = (self.m_stpoint[0], self.m_stpoint[1], self.m_endpoint[0], self.m_endpoint[1])
        minX = -1.0 + 2*(self.m_stpoint[0]/sw)
        minY = 1.0 - 2*(self.m_stpoint[1]/sh)
        maxX = -1.0 + 2*(self.m_endpoint[0]/sw)
        maxY = 1.0 - 2*(self.m_endpoint[1]/sh)
       
        if evt != None and evt.Dragging():
            glEnable(GL_COLOR_LOGIC_OP)
            glLogicOp(GL_XOR)
            glEnable(GL_LINE_STIPPLE)
            factor = 3
            pattern = 0x5555
            glLineStipple(factor, pattern)
            ed = evt.GetPosition()
            self.m_endpoint = (float(ed.x), float(ed.y))
        else:
            glColor3f(1.0, 0.0, 0.0)
   
        # erase old rectangle.
        # gl canvas
        glBegin(GL_LINE_LOOP)
        glVertex2f(minX,minY)
        glVertex2f(maxX,minY)
        glVertex2f(maxX,maxY)
        glVertex2f(minX,maxY)
        glEnd()
        #glFlush()
       
        if evt != None and evt.Dragging():
            # draw the marquee on the
            rect = (self.m_stpoint[0], self.m_stpoint[1], self.m_endpoint[0], self.m_endpoint[1])
            minX = -1.0 + 2*(self.m_stpoint[0]/sw)
            minY = 1.0 - 2*(self.m_stpoint[1]/sh)
            maxX = -1.0 + 2*(self.m_endpoint[0]/sw)
            maxY = 1.0 - 2*(self.m_endpoint[1]/sh)
            glBegin(GL_LINE_LOOP)
            glVertex2f(minX,minY)
            glVertex2f(maxX,minY)
            glVertex2f(maxX,maxY)
            glVertex2f(minX,maxY)
            glEnd()
        #glFlush()
        self.SwapBuffers()
       
        if evt != None and evt.Dragging():
            glDisable(GL_LINE_STIPPLE)
            glDisable(GL_COLOR_LOGIC_OP)
   
    def OnMouseDown(self, evt):
        self.CaptureMouse()
        if evt.LeftIsDown():
            st = evt.GetPosition()
            self.m_endpoint = self.m_stpoint = (float(st.x), float(st.y))
        self.Refresh()
           
    def OnMouseUp(self, evt):
        if self.HasCapture():
            cr = evt.GetPosition()
            self.current_m_endpoint = (float(cr.x),float(cr.y))
            if self.current_m_endpoint == self.m_stpoint:
                self.m_endpoint = self.m_stpoint = self.previous_endpoint = wx.Point(0, 0)
                # clear the buffer
                self.OnDraw()
            self.ReleaseMouse()
            self.Refresh()
       
    def OnMouseMotion(self, evt):
        if evt.Dragging() and evt.LeftIsDown():
            #ed = evt.GetPosition()
            #self.m_endpoint = (float(ed.x), float(ed.y))
            self.DrawRectangle(evt)
           
    def OnDraw(self):
        glClearColor(0.0, 0.0, 0.0, 1.0)
        glClear(GL_COLOR_BUFFER_BIT)
        glColor3f(1.0, 1.0, 1.0)
        # only redraw the rectangle if
        # we have a region drawn.
        if self.m_stpoint != self.m_endpoint:
            self.DrawRectangle( None )
        self.SwapBuffers()
        #glFlush()
       
class MainWindow(wx.Frame):

    def __init__(self, parent = None, id = -1, title = "Marquee Test"):
        # Init
        wx.Frame.__init__(
                self, parent, id, title, size = (640,480),
                style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE
        )

        # TextCtrl
        #self.control = wx.TextCtrl(self, -1, style = wx.TE_MULTILINE)
        self.control = MyCanvasBase(self)

        # StatusBar
        self.CreateStatusBar()

        # Filemenu
        filemenu = wx.Menu()

        # Filemenu - About
        menuitem = filemenu.Append(-1, "&About", "Information about this program")
        self.Bind(wx.EVT_MENU, self.OnAbout, menuitem) # here comes the event-handler
        # Filemenu - Separator
        filemenu.AppendSeparator()

        # Filemenu - Exit
        menuitem = filemenu.Append(-1, "E&xit", "Terminate the program")
        self.Bind(wx.EVT_MENU, self.OnExit, menuitem) # here comes the event-handler

        # Menubar
        menubar = wx.MenuBar()
        menubar.Append(filemenu,"&File")
        self.SetMenuBar(menubar)

        # Show
        self.Show(True)


    def OnAbout(self,event):
        message = "A OpenGL program
 in wxPython"
        caption = "About Marquee"
        wx.MessageBox(message, caption, wx.OK)


    def OnExit(self,event):
        self.Close(True)  # Close the frame.


app = wx.PySimpleApp()
frame = MainWindow()
app.MainLoop()

# destroying the objects, so that this script works more than once in IDLEdieses Beispiel
del frame
del app

We really REALLY need this to work in the studio so it’s a high priority for me as most of our artists use the QuadroFX 4600.

-M

Did you try newer or older drivers ? 173 is getting old.

We did try 180 drivers with no luck. If anyone can get this to work as-is, please let me know.

The other fishy thing is that if I load up another window using OpenGL, then the state is in sync and I can get the rectangle to draw. I must be doing something wrong with setting the logic operation.