OpenGL Coordinates Problem

I’m using OpenGL to create an application that draws “billboards” with different images. The user can step though the billboards and look at the images on the different ones. The problem is that the billboards are displaying in the wrong order. The front row is in the back. In other words, if there are n rows, the order in which they are displayed is 1, 2, 3, . . ., n-1, 0. I’ve looked at the coordinates and changed the camera and lots of other things, and I have no idea what is wrong. The code that draws the billboards is below; the class that draws the billboards is called Gallery. (I can provide the rest of the application upon request.) If anyone has any ideas for me at all, even for what might be wrong or something else to help me diagnose the problem, I would be very grateful!

Thank you,
Shari

#!/usr/binh/env python2.5

import wx
import Image
from wx import glcanvas
import wx.lib.scrolledpanel as scrolled
import wx.lib.statbmp as statbmp
import wx.lib.buttons as buttons
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
from vtk.wx.wxVTKRenderWindow import *

import appData.appData
import vizGenerator.vizEngine

MAP_FILE_NAME = “/home/shari/thesisFiles/testSet.cod”
DATA_FILE_NAME = “/home/shari/thesisFiles/schoolData.vtk”
MAX_HISTORY_SIZE = 1000

class MyGlCanvas(glcanvas.GLCanvas):
def init(self, parent):
glcanvas.GLCanvas.init(self, parent, -1)
self.init = False

    # initial mouse position
    self.lastx = self.x = 30
    self.lasty = self.y = 30
    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 OnEraseBackground(self, event):
    pass # Do nothing, to avoid flashing on MSW.


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 OnMouseDown(self, evt):
    self.CaptureMouse()
    self.x, self.y = self.lastx, self.lasty = evt.GetPosition()


def OnMouseUp(self, evt):
    self.ReleaseMouse()


def OnMouseMotion(self, evt):
    if evt.Dragging() and evt.LeftIsDown():
        self.lastx, self.lasty = self.x, self.y
        self.x, self.y = evt.GetPosition()
        self.Refresh(False)     

class Gallery(MyGlCanvas):
vizImageIds = []
xMapSize = 0
yMapSize = 0
width = 0.1 # Length of a billboard
height = 0.1 # Height of a billboard
distX = 0.1 # Distance between billboards in the x direction
distZ = 0.15 # Distance between billboards in the z direction

myVizEngine = vizGenerator.vizEngine.vizEngine(MAP_FILE_NAME, DATA_FILE_NAME)
# TODO:  Put these back! 
#xMapSize = int(myVizEngine.mapMatrix.sizeX)
#yMapSize = int(myVizEngine.mapMatrix.sizeY)
xMapSize = 3
yMapSize = 3

billboardList = 0

def InitGL(self):
    print "In Gallery.InitGL"
    self.SetCurrent()
    glClearColor(0.7, 0.7, 0.7, 0.0)
    glShadeModel(GL_FLAT)
    glEnable(GL_DEPTH_TEST)
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)
    
    
    self.vizImageIds = glGenTextures(self.xMapSize * self.yMapSize + 1)
    self.CreateDisplayList()       
    
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()

    # Calculate the aspect ratio of the window
    size = self.size = self.GetClientSize()
    gluPerspective(80.0, float(size.width) / float(size.height), 
                   0.01, 20.0)
    
    print "GL Error after gluPerspective: ", glGetError()
    
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()        
    
    glClearColor(0.7, 0.7, 0.7, 0.0)

    glEnable(GL_DEPTH_TEST)
    glEnable(GL_LIGHTING)
    glEnable(GL_LIGHT0)

    self.LookAt(0, 0)
    
def OnDraw(self):
    self.SetCurrent()
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glCallList(self.billboardList)
    
    glFlush()
    
    self.SwapBuffers() 
    
def DrawBillboard(self, x, y, z, filename, textureCount):
    self.textureId = self.LoadImage(filename, textureCount)
    self.SetupTexture(textureCount)
    glBindTexture(GL_TEXTURE_2D, self.vizImageIds[textureCount]) 

    #glMatrixMode(GL_MODELVIEW)
    #glLoadIdentity()
    glBegin(GL_QUADS)

    coords = self.GetBillboardCoordinates(x, z)
    leftX = coords[0]
    rightX = coords[1]
    bottomY = coords[2]
    topY = coords[3]
    z = coords[4]
    
    #print "Drawing billboard at ", x, y, z
    print "Billboard position: ", leftX, rightX, bottomY, topY, z
    
    glNormal3f(0.0, 0.0, -1.0)
    glTexCoord2f(0.0, 0.0); glVertex3f(leftX, bottomY, z)
    glTexCoord2f(1.0, 0.0); glVertex3f(rightX, bottomY, z)
    glTexCoord2f(1.0, 1.0); glVertex3f(rightX, topY, z)
    glTexCoord2f(0.0, 1.0); glVertex3f(leftX, topY, z)
    #glTexCoord2f(0.0, 0.0); glVertex3f(leftX, bottomY, z)
    #glTexCoord2f(0.0, 1.0); glVertex3f(leftX, topY, z)
    #glTexCoord2f(1.0, 1.0); glVertex3f(rightX, topY, z)
    #glTexCoord2f(1.0, 0.0); glVertex3f(rightX, bottomY, z)
    
    glEnd()                   

def GetBillboardCoordinates(self, x, z):
    #leftX = (self.xMapSize * self.distX) - (x * self.distX) + (self.xMapSize * self.width) - (x * self.width)
    leftX = -x * (self.distX + self.width) - self.width
    rightX = leftX + self.width
    bottomY = 0
    topY = bottomY + self.height
    zCoord = (self.distZ * self.yMapSize) - (z + 1) * self.distZ
    print "In GetBillboardCoordinates, zCoord is ", zCoord
    
    return leftX, rightX, bottomY, topY, zCoord

def SetupTexture(self, textureId):
    glEnable(GL_TEXTURE_2D)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
    
    glBindTexture(GL_TEXTURE_2D, self.vizImageIds[textureId]) # Added 20061003
    
def LoadImage(self, filename, id):
    #print "In LoadImage, filename is ", filename
    # First, load bitmap
    if filename == None:
        return None
    textureImageFile = None
    textureImageFile = open(filename, 'r')
    if textureImageFile:
        textureImageFile.close()
        im = Image.open(filename)
        # The images are mirrored, so flip it so they look the same
        #im = im.transpose(Image.FLIP_LEFT_RIGHT)
        try:
            ix, iy, image = im.size[0], im.size[1], im.tostring("raw", "RGBA", 0, -1)
        except SystemError:
            ix, iy, image = im.size[0], im.size[1], im.tostring("raw", "RGBX", 0, -1)
    else:
        print "ERROR - Image File not found"
            
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
    glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image)
    return self.vizImageIds[id]
        
def CreateDisplayList(self):
    self.billboardList = glGenLists(1)
    glNewList(self.billboardList, GL_COMPILE)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    # Draw a matrix of billboards
    textureCount = 0

    for x in range(0, self.xMapSize):
        for z in range(0, self.yMapSize):
            textureFilename = self.myVizEngine.getViz([x, z])
            y = 0
            print "Drawing billboard for filename", textureFilename
            self.DrawBillboard(x, y, z, textureFilename, textureCount)
            textureCount += 1

gluLookAt(0.2, 0.05, 0.01,

0.2, 0.05, 0.1,

0, 1, 0)

    glColor3f(0.0, 1.0, 0.0)    # green for x axis
    glBegin(GL_LINES)
    #glLineStipple(1, 0x0101)    # dotted 
    glVertex3f(0.0, 0.0, 0.0)
    glVertex3f(-2.0, 0.0, 0.0)
    glEnd()
    glColor3f(1.0, 0.0, 0.0)    # red for z axis
    glBegin(GL_LINES)
    #glLineStipple(1, 0x00FF)    # dashed
    glVertex3f(0.0, 0.0, 0.0)
    glVertex3f(0.0, 0.0, 2.0)
    glEnd()
    
    glFlush()
    glEndList()            
        
def SetPosition(self, camX, camY, camZ, viewX, viewY, viewZ):
   """Sets the viewpoint at which to look
       Called when the user moves from one location to another"""
   print "In Gallery.SetPosition"
   self.SetCurrent()
   # Viewing transformation
   print "Camera: ", camX, camY, camZ
   print "View: ", viewX, viewY, viewZ
   glMatrixMode(GL_MODELVIEW)
   glLoadIdentity()
   gluLookAt(camX, camY, camZ, # camera position
             viewX, viewY, viewZ , # camera aimed at
             0.0, 1.0, 0.0) # view-up matrix
   
   self.OnDraw()
   #self.SwapBuffers()
   
def LookAt(self, x, z):
    """Positions the camera and viewpoint to look at the billboard
        at array position (x, z)"""
    print "Looking at position: ", x, z
    #self.SetCurrent()
    
    coords = self.GetBillboardCoordinates(x, z)
    leftX = coords[0]
    rightX = coords[1]
    bottomY = coords[2]
    topY = coords[3]
    z = coords[4]
    
    billboardX = (leftX + rightX) / 2
    billboardY = (bottomY + topY) / 2
    billboardZ = z

    print "In LookAt, billboard position = ", billboardX, billboardY, billboardZ
    #billboardZ = (z - 1) * self.distZ
    camX = billboardX
    camY = billboardY
    #camZ = billboardZ - (self.distZ / 5.0)
    #camZ = billboardZ - ((self.distZ / 4.0) * 3) # Step back 3/4 of the way to the next billboard
    camZ = billboardZ + (self.distZ * 0.8) #- self.distZ / 4.0
    self.SetPosition(camX, camY, camZ, 
                     billboardX, billboardY, billboardZ)
    #self.SwapBuffers()         
    
def getVizEngine(self):   
    return self.myVizEngine

class CubeCanvas(MyGlCanvas):
def InitGL(self):
print “In CubeCanvas.InitGL”
# set viewing projection
glMatrixMode(GL_PROJECTION)
glFrustum(-0.5, 0.5, -0.5, 0.5, 1.0, 3.0)

    # position viewer
    glMatrixMode(GL_MODELVIEW)
    glTranslatef(0.0, 0.0, -2.0)

    # position object
    glRotatef(self.y, 1.0, 0.0, 0.0)
    glRotatef(self.x, 0.0, 1.0, 0.0)

    glEnable(GL_DEPTH_TEST)
    glEnable(GL_LIGHTING)
    glEnable(GL_LIGHT0)


def OnDraw(self):
    print "In CubeCanvas.OnDraw"
    # clear color and depth buffers
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    # 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()

    if self.size is None:
        self.size = self.GetClientSize()
    w, h = self.size
    w = max(w, 1.0)
    h = max(h, 1.0)
    xScale = 180.0 / w
    yScale = 180.0 / h
    glRotatef((self.y - self.lasty) * yScale, 1.0, 0.0, 0.0);
    glRotatef((self.x - self.lastx) * xScale, 0.0, 1.0, 0.0);

    self.SwapBuffers()        

class CurrentView(wx.Panel):
def init(self, parent):
print “Entering CurrentView.init
self.parent = parent

self.position = [self.parent.currAppData.position.x,

self.parent.currAppData.position.z]

    wx.Panel.__init__(self, self.parent, style=wx.BORDER_SUNKEN, size=(60, 200))
    
    box = wx.BoxSizer(wx.VERTICAL)
    
    self.widget = wxVTKRenderWindow(self, -1, pos=(100, 100), size=(170, 170))
    self.myVizEngine = vizGenerator.vizEngine.vizEngine(MAP_FILE_NAME, DATA_FILE_NAME) 
    #ren = self.myVizEngine.getVtkViz(self.position)
    
    #self.widget.GetRenderWindow().AddRenderer(ren)
    self.OnDraw()
    box.Add(self.widget, 0, wx.ALIGN_RIGHT)
    self.SetSizer(box)
    print "CurrentView.__init__ has completed"

def SetPosition(self, position):
    self.position = position
    
def OnDraw(self):
    print "In CurrentView.OnDraw"
    self.position = [self.parent.currAppData.position.x, 
                     self.parent.currAppData.position.z]
    print "Position is ", self.position
    self.widget = wxVTKRenderWindow(self, -1, pos=(100, 100), size=(170, 170))
    #myVizEngine = vizGenerator.vizEngine.vizEngine(MAP_FILE_NAME, DATA_FILE_NAME)
    ren = self.myVizEngine.getVtkViz(self.position)
    
    #renWin = self.widget.GetRenderWindow()
    #renWin.AddRenderer(ren)
    
    self.widget.GetRenderWindow().AddRenderer(ren)

self.widget.GetRenderWindow().Render()

    #self.widget.Render()

renWin.Render()

camera = ren.GetActiveCamera()

camera.SetViewUp(1, 0, 0)

ren.SetActiveCamera(camera)

    #self.widget.Render()
    #self.widget.GetRenderWindow().Render()
    
    
    print "Finished CurrentView.OnDraw" 

class HistoryView(scrolled.ScrolledPanel):
#class HistoryView(wx.ScrolledWindow):
SPACING = 1

def __init__(self, parent):

wx.ScrolledWindow.init(self, parent, id=-1, pos=wx.DefaultPosition,

size=(700, 100), style=wx.HSCROLL,

name=“History View”)

    scrolled.ScrolledPanel.__init__(self, parent, -1, size=(840, 300))
    #self.SetSize((700, 100))
    #self.panel = wx.Panel(self, style=wx.BORDER_SUNKEN, size=(700, 100))
    #self.navigationWin = navigationWin
    self.parent = parent
    self.history = self.parent.currAppData.history
    self.boxSizer = wx.BoxSizer(wx.HORIZONTAL)
    self.boxSizer.SetMinSize((600, 200))
    self.myVizEngine = vizGenerator.vizEngine.vizEngine(MAP_FILE_NAME, DATA_FILE_NAME) 

    # Add initial position to history
    print "Adding initial position: ", self.parent.currAppData.position
    self.AddPosition(self.parent.currAppData.position)

    #self.OnDraw()
    self.SetSizerAndFit(self.boxSizer)
    #self.SetSizer(self.boxSizer)

    self.SetupScrolling(scroll_x=True, scroll_y=False)
    self.boxSizer.Fit(self)
    
def AddPosition(self, position):
    print "In HistoryView.AddPosition, adding position ", position
    historyButton = HistoryButton(self, position, self.myVizEngine)
    self.boxSizer.Add(historyButton, 0, wx.ALL, self.SPACING)
    self.boxSizer.Layout()
    self.boxSizer.FitInside(self)

class HistoryButton(buttons.GenBitmapButton):
SCALE_FACTOR = 0.75

def __init__(self, parent, position, vizEngine):
    self.position = position
    print "Button created with position: ", self.position.toString()
    self.parent = parent
    textureFilename = vizEngine.getViz([position.x, position.z])
    image = wx.Image(textureFilename, wx.BITMAP_TYPE_BMP)
    #image = wx.Bitmap(textureFilename)
    width = image.GetWidth()
    height = image.GetHeight()
    #print "Image Size: ", width, height
    scaledImage = image.Scale(width * self.SCALE_FACTOR, height * self.SCALE_FACTOR)
    bitmapImage = scaledImage.ConvertToBitmap()
    buttons.GenBitmapButton.__init__(self, parent, -1, bitmapImage, pos=(0, 0), style=0)
    self.Bind(wx.EVT_BUTTON, self.OnClick, self)
    
    
def OnClick(self, event):
    print "Button Position: ", self.position.toString()
    self.parent.parent.navigationPanel.OnStep(self.position)

#class CurrentView(wx.Panel):

def init(self, parent):

print “Entering CurrentView.init

self.parent = parent

self.position = [self.parent.currAppData.position.x,

self.parent.currAppData.position.z]

wx.Panel.init(self, parent, style=wx.BORDER_SUNKEN)

box = wx.BoxSizer(wx.VERTICAL)

self.widget = wxVTKRenderWindow(self, -1, pos=(100, 100), size=(170, 170))

myVizEngine = vizGenerator.vizEngine.vizEngine(MAP_FILE_NAME, DATA_FILE_NAME)

ren = myVizEngine.getVtkViz(self.position)

self.widget.GetRenderWindow().AddRenderer(ren)

box.Add(self)

self.SetSizer(box)

print “Leaving CurrentView.init

def OnDraw(self):

print “In CurrentView.OnDraw”

self.position = [self.parent.currAppData.position.x,

self.parent.currAppData.position.z]

myVizEngine = vizGenerator.vizEngine.vizEngine(MAP_FILE_NAME, DATA_FILE_NAME)

ren = myVizEngine.getVtkViz(self.position)

#class CurrentView(wx.Panel):

def init(self, parent):

print “Entering CurrentView.init

wx.Panel.init(self, parent, style=wx.BORDER_SUNKEN)

self.widget = wxVTKRenderWindow(self, -1, pos=(100, 100), size=(170, 170))

print “Leaving CurrentView.init

def OnDraw(self):

print “Entering CurrentView.OnDraw”

cylinder = vtk.vtkCylinderSource()

cylinder.SetResolution(8)

cylinderMapper = vtk.vtkPolyDataMapper()

cylinderMapper.SetInput(cylinder.GetOutput())

cylinderActor = vtk.vtkActor()

cylinderActor.SetMapper(cylinderMapper)

cylinderActor.GetProperty().SetColor(1.0000, 0.3882, 0.2784)

cylinderActor.RotateX(30.0)

cylinderActor.RotateY(-45.0)

ren1 = vtk.vtkRenderer()

renWin = vtk.vtkRenderWindow()

renWin.AddRenderer(ren1)

iren = vtk.vtkRenderWindowInteractor()

iren.SetRenderWindow(renWin)

ren1.AddActor(cylinderActor)

ren1.SetBackground(0.1, 0.2, 0.4)

renWin.SetSize(200, 200)

iren.Initialize()

iren.Start()

self.widget.GetRenderWindow().AddRenderer(ren1)

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)

should be :
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)

I fixed this, but it didn’t seem to make much difference. :frowning: Thank you very much for the idea. Is there something else that might help?

Thanks again,
Shari