Problems with Rubberband Technique in PyGL+WXPython!

All:

I am beating my head to the ground trying to figure out what is going on with my marquee program. I have an exact duplicate copy written in C that seems to work. Can anyone help me with this? I’m trying to get a rectangle to be rubberbanded.

#! /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, 3.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()
    if self.GetContext():
        self.SetCurrent()
        glViewport(0, 0, size.width, size.height)
    event.Skip()
   
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):
    glEnable(GL_COLOR_LOGIC_OP)
    glLogicOp(GL_SET)
    sw,sh = self.GetClientSize()
    rect = (self.m_stpoint[0], self.m_stpoint[1], self.m_endpoint[0], self.m_endpoint[1])
    print 'erase pos(%s,%s)' % (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)
    glEnable(GL_LINE_STIPPLE)
    factor = 3
    pattern = 0x5555
    glLineStipple(factor, pattern)

    # erase the already drawn marquee
    glBegin(GL_LINES)
    glVertex2f(minX,minY)
    glVertex2f(maxX,minY)
    #glVertex2f(maxX,maxY)
    #glVertex2f(minX,maxY)
    glEnd()
    glFlush()
   
    # draw it again
    #end_pt = evt.GetPosition()
    #print 'redraw pos(%s,%s)' % (end_pt[0], end_pt[1])
    #rect = (self.m_stpoint[0], self.m_stpoint[1], float(end_pt[0]), float(end_pt[1]))
    #minX = -1.0 + 2*(self.m_stpoint[0]/sw)
    #minY = 1.0 - 2*(self.m_stpoint[1]/sh)
    #maxX = -1.0 + 2*(end_pt[0]/sw)
    #maxY = 1.0 - 2*(end_pt[1]/sh)
    glBegin(GL_LINES)
    glVertex2f(minX,minY)
    glVertex2f(maxX,minY)
    #glVertex2f(maxX,maxY)
    #glVertex2f(minX,maxY)
    glEnd()
    glFlush()
    glDisable(GL_LINE_STIPPLE)
    glDisable(GL_COLOR_LOGIC_OP)
    #self.SwapBuffers()

def OnMouseDown(self, evt):
    self.CaptureMouse()
    if evt.LeftIsDown():
        st = evt.GetPosition()
        self.m_stpoint = (float(st.x), float(st.y))
   
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()
   
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)# | GL_DEPTH_BUFFER_BIT)
    #glLogicOp(GL_COPY)
    glColor3f(1.0, 1.0, 1.0)
    glFlush()
    #self.SwapBuffers()

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\n 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

···

Hotmail® goes with you. Get it on your BlackBerry or iPhone.

Marlin Rowley wrote:

All:

I am beating my head to the ground trying to figure out what is going
on with my marquee program. I have an exact duplicate copy written in
C that seems to work. Can anyone help me with this? I'm trying to
get a rectangle to be rubberbanded.

On my system your code just doesn't do anything because the
self.GetContext() call is returning a False value. Didn't have time to
figure out what's going on with your code, but with the attached patch
the Context starts up and renders something.

HTH,
Mike

wx_not_working.diff (3.31 KB)

···

--
________________________________________________
  Mike C. Fletcher
  Designer, VR Plumber, Coder
  http://www.vrplumber.com
  http://blog.vrplumber.com

Mike,

It’s the drawing of the line in GL_XOR mode that’s causing my problem. If you take the function DrawRectangle and change the glLogicOp(GL_XOR) to glLogicOp(GL_SET), then you can drag the mouse and create a stippled line. The problem is that you can’t use it in GL_XOR mode where you can move the mouse back to the original point and the line gets erased!

-M

···

Date: Wed, 20 May 2009 16:40:38 -0400
From: mcfletch@vrplumber.com
To: wxpython-users@lists.wxwidgets.org
Subject: Re: [wxpython-users] Problems with Rubberband Technique in PyGL+WXPython!

Marlin Rowley wrote:

All:

I am beating my head to the ground trying to figure out what is going
on with my marquee program. I have an exact duplicate copy written in
C that seems to work. Can anyone help me with this? I’m trying to
get a rectangle to be rubberbanded.
On my system your code just doesn’t do anything because the
self.GetContext() call is returning a False value. Didn’t have time to
figure out what’s going on with your code, but with the attached patch
the Context starts up and renders something.

HTH,
Mike


Mike C. Fletcher
Designer, VR Plumber, Coder
http://www.vrplumber.com
http://blog.vrplumber.com


Hotmail® has ever-growing storage! Don’t worry about storage limits. Check it out.

Marlin Rowley wrote:

Mike,

It's the drawing of the line in GL_XOR mode that's causing my
problem. If you take the function DrawRectangle and change the
glLogicOp(GL_XOR) to glLogicOp(GL_SET), then you can drag the mouse
and create a stippled line. The problem is that you can't use it in
GL_XOR mode where you can move the mouse back to the original point
and the line gets erased!

-M

Maybe I'm missing something here, when I alter the code so that there's
a rectangle drawn and choose GL_XOR, I get the XOR operation apparently
happening correctly. If I comment out lines 90 through 95 in the
attached I see the rectangle drawn. If I leave them enabled then I see
the XOR effect happening and the top/bottom lines of the rectangle
disappear.

HTH,
Mike

wx_not_working.py (6.05 KB)

···

--
________________________________________________
  Mike C. Fletcher
  Designer, VR Plumber, Coder
  http://www.vrplumber.com
  http://blog.vrplumber.com

I’ll try this code tomorrow when I get to work.

The rectangle should be like the rubberband effect. That is, it should extend out however long you drag it with the mouse and it should shrink in size if you close up the rectangle. All of this should be happening with double buffer enabled.

-M

···

Date: Wed, 20 May 2009 23:20:35 -0400
From: mcfletch@vrplumber.com
To: wxpython-users@lists.wxwidgets.org
Subject: Re: [wxpython-users] Problems with Rubberband Technique in PyGL+WXPython!

Marlin Rowley wrote:

Mike,

It’s the drawing of the line in GL_XOR mode that’s causing my
problem. If you take the function DrawRectangle and change the
glLogicOp(GL_XOR) to glLogicOp(GL_SET), then you can drag the mouse
and create a stippled line. The problem is that you can’t use it in
GL_XOR mode where you can move the mouse back to the original point
and the line gets erased!

-M

Maybe I’m missing something here, when I alter the code so that there’s
a rectangle drawn and choose GL_XOR, I get the XOR operation apparently
happening correctly. If I comment out lines 90 through 95 in the
attached I see the rectangle drawn. If I leave them enabled then I see
the XOR effect happening and the top/bottom lines of the rectangle
disappear.

HTH,
Mike


Mike C. Fletcher
Designer, VR Plumber, Coder
http://www.vrplumber.com
http://blog.vrplumber.com


Windows Live™: Keep your life in sync. Check it out.

Mike,

Thanks for the modifications. It seems like we may have a problem with Fedora 8 or it’s OpenGL version. The rectangle (when drawn) seems like it can’t erase itself as the mouse is being dragged and I’m getting cascading rectangles. When I lift up the left mouse button and the OnDraw() is called, the rectangle clears and I get the correct result (the insides of the rectangle are black).

What version of GL are you using and what version of Linux?

Thanks,

-M

···

Date: Wed, 20 May 2009 23:20:35 -0400
From: mcfletch@vrplumber.com
To: wxpython-users@lists.wxwidgets.org
Subject: Re: [wxpython-users] Problems with Rubberband Technique in PyGL+WXPython!

Marlin Rowley wrote:

Mike,

It’s the drawing of the line in GL_XOR mode that’s causing my
problem. If you take the function DrawRectangle and change the
glLogicOp(GL_XOR) to glLogicOp(GL_SET), then you can drag the mouse
and create a stippled line. The problem is that you can’t use it in
GL_XOR mode where you can move the mouse back to the original point
and the line gets erased!

-M

Maybe I’m missing something here, when I alter the code so that there’s
a rectangle drawn and choose GL_XOR, I get the XOR operation apparently
happening correctly. If I comment out lines 90 through 95 in the
attached I see the rectangle drawn. If I leave them enabled then I see
the XOR effect happening and the top/bottom lines of the rectangle
disappear.

HTH,
Mike


Mike C. Fletcher
Designer, VR Plumber, Coder
http://www.vrplumber.com
http://blog.vrplumber.com


Hotmail® has a new way to see what’s up with your friends. Check it out.

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\n 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

···

From: marlin_rowley@hotmail.com
To: wxpython-users@lists.wxwidgets.org
Subject: RE: [wxpython-users] Problems with Rubberband Technique in PyGL+WXPython!
Date: Thu, 21 May 2009 09:28:37 -0500

Mike,

Thanks for the modifications. It seems like we may have a problem with Fedora 8 or it’s OpenGL version. The rectangle (when drawn) seems like it can’t erase itself as the mouse is being dragged and I’m getting cascading rectangles. When I lift up the left mouse button and the OnDraw() is called, the rectangle clears and I get the correct result (the insides of the rectangle are black).

What version of GL are you using and what version of Linux?

Thanks,

-M

Date: Wed, 20 May 2009 23:20:35 -0400
From: mcfletch@vrplumber.com
To: wxpython-users@lists.wxwidgets.org
Subject: Re: [wxpython-users] Problems with Rubberband Technique in PyGL+WXPython!

Marlin Rowley wrote:

Mike,

It’s the drawing of the line in GL_XOR mode that’s causing my
problem. If you take the function DrawRectangle and change the
glLogicOp(GL_XOR) to glLogicOp(GL_SET), then you can drag the mouse
and create a stippled line. The problem is that you can’t use it in
GL_XOR mode where you can move the mouse back to the original point
and the line gets erased!

-M

Maybe I’m missing something here, when I alter the code so that there’s
a rectangle drawn and choose GL_XOR, I get the XOR operation apparently
happening correctly. If I comment out lines 90 through 95 in the
attached I see the rectangle drawn. If I leave them enabled then I see
the XOR effect happening and the top/bottom lines of the rectangle
disappear.

HTH,
Mike


Mike C. Fletcher
Designer, VR Plumber, Coder
http://www.vrplumber.com
http://blog.vrplumber.com


Hotmail® has a new way to see what’s up with your friends. Check it out.


Hotmail® goes with you. Get it on your BlackBerry or iPhone.