Name stack based picking problem

Started by
3 comments, last by 0beron 17 years, 6 months ago
I'm working on a 3d version of a 2d board game, in which square tiles can be placed onto a board made up of square spaces (in the 3d version the board squares can be oriented vertically and upside down as well as flat like in the 2d version you play on a table). The board squares are coloured quads, and the game tiles fit within a board square, but are made up of a number of sub-objects which are just a selection of coloured triangles. I want to be able to pick these sub objects with the mouse, and I've set up the openGL name stack to do this. The board squares are drawn by feeding absolute coordinates into glVertex3fv(), and their names work fine - picking of board squares is accurate from any viewing position and orientation. The game tiles are drawn relative to the corner of the tile, and are shuffled into place using glTranslatef. When drawn to the framebuffer the tile appears in the correct position, but picking only seems to work accurately when the tile is placed at the origin. Applying a small translation to it causes the picking to shift off to the side, and apllying a large translation means I can no longer locate the place where the tile is picked since it so far from where the tile actually appears. What part of the pipeline could be causing this effect, given that the board squares work fine from any angle? My code is a bit scattered, and it's written in Python - I'm happy to post some relevant snippets if no-one can guess the problem from the description above. Any help much appreciated, thanks.
Advertisement
post your short code WRT the picking routine
It sounds like you don't have the same translations for the picking routine and normal rendering.
The picking routine IS the normal rendering routine at the moment...

I'll post some code shortly (currently it is half past midnight and I need to be at work at 9...)
Ok, here are some snippets...

This is the draw routine for the game tile, where the names are assigned.
def draw(self):        print glGetInteger(GL_RENDER_MODE)        gen.reset()        glColor3f(0.8,0.8,0.8)        for road in self.roads:            if road['model'] is not None:                glPushName(gen.generatename())                road['model'].draw()                glPopName()        glColor3f(0.4,1.0,0.4)        for farm in self.farms:            if farm['model'] is not None:                glPushName(gen.generatename())                farm['model'].draw()                glPopName()



The above is called below, in the draw routine for the board squares, which render either a flat quad, or the tile occupying the square. The two translations either side of self.tile.draw are the ones giving me trouble. They work fine for drawing the tile but they seem to disrupt the picking if they are anything other than a zero vector.
    def draw(self):                print glGetInteger(GL_RENDER_MODE)        if self.tile is not None:            c = list(self.centre())            c[self.uaxis]-=0.5            c[self.vaxis]-=0.5            glTranslatef(c[0],c[1],c[2])            self.tile.draw()            glTranslatef(-c[0],-c[1],-c[2])            return        #glPolygonOffset(1.1,4)        #glEnable(GL_POLYGON_OFFSET_FILL)        glColor3fv(self.col)        p = Vertex()        p[self.naxis] = (1-self.ori[self.naxis])/2.0        glBegin(GL_QUADS)        glNormal3fv(self.ori)        for i in [0.0,1.0]:           for j in [i,1.0-i]:               p[self.uaxis] = i               p[self.vaxis] = j               glVertex3fv((p+self.pos).p)        glEnd()



The whole process is started from here:
def pick(self, event):        self.focus()        self.tkRecordMouse(event)        if self.pickmode == PM_BUFFER:            glMatrixMode(GL_MODELVIEW)            glPushMatrix()            glInitNames()            buffer = glSelectWithCallback(event.x, event.y, lambda: self.bufferdraw(pick=True), 1, 1)            glMatrixMode(GL_MODELVIEW)            glPopMatrix()            self.pickcallback(buffer)        else:            self.pick_xyz(event)


lambda: self.bufferdraw(pick=True) results in a call to the main drawing routine, and the pick argument specifies that everything should be redrawn instead of calling the stored display lists. self.pickcallback just passes the buffer back to the calling class.

This works perfectly for the board squares ( I push a name onto the stack before drawing the whole board and don't pop it until the end, and everything that is drawn gets that name.) Picking the board squares works perfectly, but the tiles drift off from where they actually appear...

This topic is closed to new replies.

Advertisement