Exemplo n.º 1
0
    def get_ray(self, x, y):
        """ Generate a ray beginning at the near plane, in the direction that the x, y coordinates are facing

            Consumes: x, y coordinates of mouse on screen

            Return: start, direction of the ray """

        self.init_view()

        glMatrixMode(GL_MODELVIEW)

        glLoadIdentity()

        # get two points on the line.

        start = numpy.array(gluUnProject(x, y, 0.001))

        end = numpy.array(gluUnProject(x, y, 0.999))

        # convert those points into a ray

        direction = end - start

        direction = direction / norm(direction)

        return (start, direction)
Exemplo n.º 2
0
Arquivo: main.py Projeto: timo/kuspak
def pickFloor(x, y):
  viewp = (0, 0) + screensize
  mat = glGetDoublev(GL_PROJECTION_MATRIX)
  p1 = gluUnProject(x, viewp[3] - y, 0.0, scene_matrix, mat, viewp)
  p2 = gluUnProject(x, viewp[3] - y, 1.0, scene_matrix, mat, viewp)
  ln = -1 * p1[2] / (p2[2] - p1[2])
  return [p1[0] + (p2[0] - p1[0]) * ln, p1[1] + (p2[1] - p1[1]) * ln]
Exemplo n.º 3
0
 def plane_intersection(self, x, y):
     # Unproject coordinates into object space
     nx, ny, nz = gluUnProject(x, y, 0.0)
     fx, fy, fz = gluUnProject(x, y, 1.0)
     # Calculate the ray
     near = Point3(nx, ny, nz)
     far = Point3(fx, fy, fz)
     ray = LineSegment3(near, far)
     # Define our planes
     # XXX origin assumes planes are at zero offsets, should really
     # XXX respect any grid plane offset here
     origin = self.voxels.voxel_to_world(0, 0, self.voxels.depth)
     planes = (Plane(Vector3(1, 0, 0), origin[0]), Plane(Vector3(0, 1, 0), origin[1]),
               Plane(Vector3(0, 0, 1), origin[2] + 0.001))
     intersection = None, None, None
     distance = sys.maxint
     for plane in planes:
         # Get intersection point
         intersect = plane.intersect(ray)
         if intersect:
             # Adjust to voxel space coordinates
             x, y, z = self.voxels.world_to_voxel(intersect.x, intersect.y, intersect.z)
             x = int(x)
             y = int(y)
             z = int(z)
             # Ignore out of bounds insections
             if not self.voxels.is_valid_bounds(x, y, z):
                 continue
             length = near.distance(Point3(intersect.x, intersect.y, intersect.z))
             if length < distance:
                 intersection = int(x), int(y), int(z)
                 distance = length
     return intersection
    def _Screen2Real(self, x, y, expZ=0.0):
        '''
        Return the x and y in real coordination if the input is the x and y in screen coordination
        http://nehe.gamedev.net/article/using_gluunproject/16013/
        Inputs:
            - x, y: coordinates get from mouse in screen coordination
            - expZ: expected Z of the real coordinates
        Outputs: coordinates in the real world
        '''
        if not self.init:
            return 0, 0, 0
        
        projection = glGetDoublev(GL_PROJECTION_MATRIX)
        modelview = glGetDoublev(GL_MODELVIEW_MATRIX)
        viewport = glGetIntegerv(GL_VIEWPORT)
        
        winX = float(x)
        winY = float(viewport[3]) - float(y)
#         winZ = glReadPixels(x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)
        
        try:
            posXF, posYF, posZF = gluUnProject(winX, winY, 1, modelview, projection, viewport)
            posXN, posYN, posZN = gluUnProject(winX, winY, -1, modelview, projection, viewport)
            posZ = expZ
            posX = (posZ - posZN) / (posZF - posZN) * (posXF - posXN) + posXN
            posY = (posZ - posZN) / (posZF - posZN) * (posYF - posYN) + posYN
#             posX, posY, posZ = gluUnProject(winX, winY, winZ, modelview, projection, viewport)
        except:
            return 0, 0, 0
        return posX, posY, posZ
Exemplo n.º 5
0
    def get_ray(self, x, y):
        self.init_view()

        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

        start = numpy.array(gluUnProject(x, y, 0.001))
        end = numpy.array(gluUnProject(x, y, 0.999))
        direction = end - start
        direction = direction / norm(direction)

        return (start, direction)
Exemplo n.º 6
0
 def view_axis(self):
     # Shoot a ray into the scene
     x1, y1, z1 = gluUnProject(self.width() // 2, self.height() // 2, 0.0)
     x2, y2, z2 = gluUnProject(self.width() // 2, self.height() // 2, 1.0)
     dx = abs(x2 - x1)
     dy = abs(y2 - y1)
     dz = abs(z2 - z1)
     # The largest deviation is the axis we're looking down
     if dz >= dx and dz >= dy:
         return (self.X_AXIS, self.Y_AXIS)
     elif dy >= dx and dy >= dz:
         return (self.X_AXIS, self.Z_AXIS)
     return (self.Z_AXIS, self.Y_AXIS)
Exemplo n.º 7
0
 def view_axis(self):
     # Shoot a ray into the scene
     x1, y1, z1 = gluUnProject(self.width() // 2, self.height() // 2, 0.0)
     x2, y2, z2 = gluUnProject(self.width() // 2, self.height() // 2, 1.0)
     dx = abs(x2 - x1)
     dy = abs(y2 - y1)
     dz = abs(z2 - z1)
     # The largest deviation is the axis we're looking down
     if dz >= dx and dz >= dy:
         return (self.X_AXIS, self.Y_AXIS)
     elif dy >= dx and dy >= dz:
         return (self.X_AXIS, self.Z_AXIS)
     return (self.Z_AXIS, self.Y_AXIS)
Exemplo n.º 8
0
    def OnMouseLeftUp(self, evt):
        t_left, t_top, z = gluUnProject(self.startx, self.size[1] - self.starty, 0)
        right, bottom, z = gluUnProject(self.x, self.size[1] - self.y, 0)

        left = min(t_left, right)
        right = max(t_left, right)
        top = min(t_top, bottom)
        bottom = max(t_top, bottom)

        self.zoom.append((left, right, top, bottom))
        self.x = self.y = self.startx = self.starty = None
        self.ReleaseMouse()

        self.Refresh(False)
Exemplo n.º 9
0
    def leftDown(self, event):
        """
        Compute the rubber band window starting point, which
        lies on the near clipping plane, projecting into the same 
        point that current cursor points at on the screen plane.
        """
        self.pWxy = (event.pos().x(), self.glpane.height - event.pos().y())
        p1 = A(gluUnProject(self.pWxy[0], self.pWxy[1], 0.005))

        self.pStart = p1
        self.pPrev = p1
        self.firstDraw = True

        self.command.glStatesChanged = True
        # this warns our exit code to undo the following OpenGL state changes:

        self.glpane.redrawGL = False
        glDisable(GL_DEPTH_TEST)
        glDisable(GL_LIGHTING)
        rbwcolor = self.command.rbwcolor
        glColor3d(rbwcolor[0], rbwcolor[1], rbwcolor[2])

        glEnable(GL_COLOR_LOGIC_OP)
        glLogicOp(GL_XOR)

        return
Exemplo n.º 10
0
    def leftDrag(self, event):
        """
        Compute the changing rubber band window ending point. Erase the
        previous window, draw the new window.
        """
        # bugs 1190, 1818 wware 4/05/2006 - sometimes Qt neglects to call leftDown
        # before this
        if not hasattr(self, "pWxy") or not hasattr(self, "firstDraw"):
            return
        cWxy = (event.pos().x(), self.glpane.height - event.pos().y())

        rbwcolor = self.command.rbwcolor

        if not self.firstDraw: #Erase the previous rubber window
            drawrectangle(self.pStart, self.pPrev, self.glpane.up,
                          self.glpane.right, rbwcolor)
        self.firstDraw = False

        self.pPrev = A(gluUnProject(cWxy[0], cWxy[1], 0.005))
        # draw the new rubber band
        drawrectangle(self.pStart, self.pPrev, self.glpane.up,
                      self.glpane.right, rbwcolor)
        glFlush()
        self.glpane.swapBuffers() # Update display
        return
Exemplo n.º 11
0
    def leftDown(self, event):
        """
        Compute the rubber band window starting point, which
        lies on the near clipping plane, projecting into the same
        point that current cursor points at on the screen plane.
        """
        self.pWxy = (event.pos().x(), self.glpane.height - event.pos().y())
        p1 = A(gluUnProject(self.pWxy[0], self.pWxy[1], 0.005))

        self.pStart = p1
        self.pPrev = p1
        self.firstDraw = True

        self.command.glStatesChanged = True
            # this warns our exit code to undo the following OpenGL state changes:

        self.glpane.redrawGL = False
        glDisable(GL_DEPTH_TEST)
        glDisable(GL_LIGHTING)
        rbwcolor = self.command.rbwcolor
        glColor3d(rbwcolor[0], rbwcolor[1], rbwcolor[2])

        glEnable(GL_COLOR_LOGIC_OP)
        glLogicOp(GL_XOR)

        return
Exemplo n.º 12
0
    def unproject_mouse_on_scene(self,pos):
        start_x, start_y, start_z = gluUnProject(pos.x(), pos.y(), 1, model=self._modelview_matrix,
                     proj=glGetDoublev(GL_PROJECTION_MATRIX))
        end_x, end_y, end_z = gluUnProject(pos.x(), pos.y(), 0, model=self._modelview_matrix,
                     proj=glGetDoublev(GL_PROJECTION_MATRIX))

        diff_x = end_x - start_x
        diff_y = end_y - start_y
        diff_z = end_z - start_z

        t = (0 - start_z) / diff_z

        x = start_x + (diff_x * t)
        y = start_y + (diff_y * t)

        return x, y,0
Exemplo n.º 13
0
    def leftDrag(self, event):
        """
        Compute the changing rubber band window ending point. Erase the
        previous window, draw the new window.
        """
        # bugs 1190, 1818 wware 4/05/2006 - sometimes Qt neglects to call leftDown
        # before this
        if not hasattr(self, "pWxy") or not hasattr(self, "firstDraw"):
            return
        cWxy = (event.pos().x(), self.glpane.height - event.pos().y())

        rbwcolor = self.command.rbwcolor

        if not self.firstDraw:  #Erase the previous rubberband window
            drawrectangle(self.pStart, self.pPrev, self.glpane.up,
                          self.glpane.right, rbwcolor)
        self.firstDraw = False

        self.pPrev = A(gluUnProject(cWxy[0], cWxy[1], 0.005))
        # draw the new rubberband window
        drawrectangle(self.pStart, self.pPrev, self.glpane.up,
                      self.glpane.right, rbwcolor)

        glFlush()
        self.glpane.swapBuffers()  # Update display

        # Based on a suggestion in bug 2961, I added this second call to
        # swapBuffers(). It definitely helps, but the rectangle disappears
        # once the zoom cursor stops moving. I suspect this is due to
        # a gl_update() elsewhere.  I'll ask Bruce about his thoughts on
        # this. --Mark 2008-12-22.
        self.glpane.swapBuffers()
        return
Exemplo n.º 14
0
 def window_to_world(self, x, y, z = None):
     # Find depth
     y = self._height - y
     if z is None:
         z = glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)[0][0]
     fx, fy, fz = gluUnProject(x, y, z)
     return fx, fy, fz, z
Exemplo n.º 15
0
    def leftDrag(self, event):
        """
        Compute the changing rubber band window ending point. Erase the
        previous window, draw the new window.
        """
        # bugs 1190, 1818 wware 4/05/2006 - sometimes Qt neglects to call leftDown
        # before this
        if not hasattr(self, "pWxy") or not hasattr(self, "firstDraw"):
            return
        cWxy = (event.pos().x(), self.glpane.height - event.pos().y())

        rbwcolor = self.command.rbwcolor

        if not self.firstDraw: #Erase the previous rubberband window
            drawrectangle(self.pStart, self.pPrev, self.glpane.up,
                          self.glpane.right, rbwcolor)
        self.firstDraw = False

        self.pPrev = A(gluUnProject(cWxy[0], cWxy[1], 0.005))
        # draw the new rubberband window
        drawrectangle(self.pStart, self.pPrev, self.glpane.up,
                      self.glpane.right, rbwcolor)

        glFlush()
        self.glpane.swapBuffers() # Update display

        # Based on a suggestion in bug 2961, I added this second call to
        # swapBuffers(). It definitely helps, but the rectangle disappears
        # once the zoom cursor stops moving. I suspect this is due to
        # a gl_update() elsewhere.  I'll ask Bruce about his thoughts on
        # this. --Mark 2008-12-22.
        self.glpane.swapBuffers()
        return
Exemplo n.º 16
0
    def leftDrag(self, event):
        """
        Compute the changing rubber band window ending point. Erase the
        previous window, draw the new window.
        """
        # bugs 1190, 1818 wware 4/05/2006 - sometimes Qt neglects to call leftDown
        # before this
        if not hasattr(self, "pWxy") or not hasattr(self, "firstDraw"):
            return
        cWxy = (event.pos().x(), self.glpane.height - event.pos().y())

        rbwcolor = self.command.rbwcolor

        if not self.firstDraw:  #Erase the previous rubber window
            drawrectangle(self.pStart, self.pPrev, self.glpane.up,
                          self.glpane.right, rbwcolor)
        self.firstDraw = False

        self.pPrev = A(gluUnProject(cWxy[0], cWxy[1], 0.005))
        # draw the new rubber band
        drawrectangle(self.pStart, self.pPrev, self.glpane.up,
                      self.glpane.right, rbwcolor)
        glFlush()
        self.glpane.swapBuffers()  # Update display
        return
Exemplo n.º 17
0
 def window_to_world(self, x, y, z=None):
     # Find depth
     y = self._height - y
     if z is None:
         z = glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)[0][0]
     fx, fy, fz = gluUnProject(x, y, z)
     return fx, fy, fz, z
Exemplo n.º 18
0
def mymousepoints(glpane, x, y): #bruce 071017 moved this here from testdraw.py
    ### TODO: rename, docstring

    # modified from GLPane.mousepoints; x and y are window coords (except y is 0 at bottom, positive as you go up [guess 070124])
    self = glpane
    just_beyond = 0.0
    p1 = A(gluUnProject(x, y, just_beyond))
    p2 = A(gluUnProject(x, y, 1.0))

    los = self.lineOfSight # isn't this just norm(p2 - p1)?? Probably not, if we're in perspective mode! [bruce Q 061206]
        # note: this might be in abs coords (not sure!) even though p1 and p2 would be in local coords.
        # I need to review that in GLPane.__getattr__. ###k
    
    k = dot(los, -self.pov - p1) / dot(los, p2 - p1)

    p2 = p1 + k*(p2-p1)
    return (p1, p2)
Exemplo n.º 19
0
def mymousepoints(glpane, x, y): #bruce 071017 moved this here from testdraw.py
    ### TODO: rename, docstring

    # modified from GLPane.mousepoints; x and y are window coords (except y is 0 at bottom, positive as you go up [guess 070124])
    self = glpane
    just_beyond = 0.0
    p1 = A(gluUnProject(x, y, just_beyond))
    p2 = A(gluUnProject(x, y, 1.0))

    los = self.lineOfSight # isn't this just norm(p2 - p1)?? Probably not, if we're in perspective mode! [bruce Q 061206]
        # note: this might be in abs coords (not sure!) even though p1 and p2 would be in local coords.
        # I need to review that in GLPane.__getattr__. ###k

    k = dot(los, -self.pov - p1) / dot(los, p2 - p1)

    p2 = p1 + k*(p2-p1)
    return (p1, p2)
Exemplo n.º 20
0
    def get_ray(self, x, y):
        """ Generate a ray beginning at the near plane, in the direction that the x, y coordinates are facing
            Consumes: x, y coordinates of mouse on screen
            Return: start, direction of the ray """
        self.init_view()

        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

        # get two points on the line.
        start = numpy.array(gluUnProject(x, y, 0.001))
        end = numpy.array(gluUnProject(x, y, 0.999))

        # convert those points into a ray
        direction = end - start
        direction = direction / norm(direction)

        return (start, direction)
Exemplo n.º 21
0
def glLibUnProject(mouse_pos):
    viewport = glGetIntegerv(GL_VIEWPORT)
    modelview = glGetDoublev(GL_MODELVIEW_MATRIX)
    projection = glGetDoublev(GL_PROJECTION_MATRIX)
    winX = mouse_pos[0]
    winY = float(viewport[3])-mouse_pos[1]
    winZ = glReadPixels(winX,winY,1,1,GL_DEPTH_COMPONENT,GL_FLOAT)
    cursor_pos = gluUnProject(winX,winY,winZ,modelview,projection,viewport)
    return cursor_pos
Exemplo n.º 22
0
    def plane_intersection(self, x, y):
        # Unproject coordinates into object space
        nx,ny,nz = gluUnProject(x, y, 0.0)
        fx,fy,fz = gluUnProject(x, y, 1.0)
        # Calculate the ray
        near = Point3(nx, ny, nz)
        far = Point3(fx, fy, fz)
        ray = LineSegment3(near, far)

        # Retrieve the planes defined in the VoxelGrid object and iterate through them
        planes = []
        for grid_plane in self._grids.get_grid_planes_list():
            # check if the current plane is colliding. If not, then move on to the next
            if( not grid_plane.collision ):
                continue
            normal_x = 1 if grid_plane.plane == GridPlanes.X else 0
            normal_y = 1 if grid_plane.plane == GridPlanes.Y else 0
            normal_z = 1 if grid_plane.plane == GridPlanes.Z else 0
            origins = {
                       GridPlanes.X: lambda: self.voxels.voxel_to_world(grid_plane.offset-0, 0, 0)[0],
                       GridPlanes.Y: lambda: self.voxels.voxel_to_world(0, grid_plane.offset-0, 0)[1],
                       GridPlanes.Z: lambda: self.voxels.voxel_to_world(0, 0, grid_plane.offset-1)[2]
                       }
            plane = Plane( Vector3( normal_x, normal_y, normal_z), origins[grid_plane.plane]() )
            planes.append( plane )
            
        intersection = None, None, None
        distance = sys.maxint
        for plane in planes:
            # Get intersection point
            intersect = plane.intersect(ray)
            if intersect:
                # Adjust to voxel space coordinates
                x, y, z = self.voxels.world_to_voxel(intersect.x,
                    intersect.y, intersect.z)
                # Ignore out of bounds insections
                if not self.voxels.is_valid_bounds(x, y, z):
                    continue
                length = near.distance(Point3(intersect.x, intersect.y, intersect.z))
                if length < distance:
                    intersection = int(x), int(y), int(round(z))
                    distance = length
        return intersection
Exemplo n.º 23
0
 def _drawtext(self, text, color):
     # use atom positions to compute center, where text should go
     if self.picked:
         # move the text to the lower left corner, and make it big
         pos = A(gluUnProject(5, 5, 0))
         drawtext(text, color, pos, 3 * self.font_size, self.assy.o)
     else:
         pos1 = self.atoms[0].posn()
         pos2 = self.atoms[-1].posn()
         pos = (pos1 + pos2) / 2
         drawtext(text, color, pos, self.font_size, self.assy.o)
Exemplo n.º 24
0
    def send_mouseclick_to_caller(self, cursor_x, cursor_y, button='right'):

        client = zmq.Context.instance().socket(zmq.PUSH)
        client.connect('tcp://127.0.0.1:%d' % (self.mouseclick_port))
        cameras = self.on_draw(want_cameras=True)

        window_height = glutGet(GLUT_WINDOW_HEIGHT)
        depth_value = glReadPixels(cursor_x, window_height - cursor_y, 1, 1,
                                   GL_DEPTH_COMPONENT, GL_FLOAT)

        pyobj = {
            'event_type': 'mouse_click_%sbutton' % button,
            'u': None,
            'v': None,
            'x': None,
            'y': None,
            'z': None,
            'subwindow_row': None,
            'subwindow_col': None
        }

        for subwin_row, camera_list in enumerate(cameras):
            for subwin_col, camera in enumerate(camera_list):

                # test for out-of-bounds
                if cursor_x < camera['viewport'][0]:
                    continue
                if cursor_x > (camera['viewport'][0] + camera['viewport'][2]):
                    continue
                if window_height - cursor_y < camera['viewport'][1]:
                    continue
                if window_height - cursor_y > (camera['viewport'][1] +
                                               camera['viewport'][3]):
                    continue

                xx, yy, zz = gluUnProject(cursor_x, window_height - cursor_y,
                                          depth_value,
                                          camera['modelview_matrix'],
                                          camera['projection_matrix'],
                                          camera['viewport'])

                pyobj = {
                    'event_type': 'mouse_click_%sbutton' % button,
                    'u': cursor_x - camera['viewport'][0],
                    'v': window_height - cursor_y - camera['viewport'][1],
                    'x': xx,
                    'y': yy,
                    'z': zz,
                    'which_subwindow': (subwin_row, subwin_col)
                }

        client.send_pyobj(pyobj)
        del self.mouseclick_port
Exemplo n.º 25
0
 def _drawtext(self, text, color):
     # use atom positions to compute center, where text should go
     if self.picked:
         # move the text to the lower left corner, and make it big
         pos = A(gluUnProject(5, 5, 0))
         drawtext(text, color, pos,
                  3 * self.font_size, self.assy.o)
     else:
         pos1 = self.atoms[0].posn()
         pos2 = self.atoms[-1].posn()
         pos = (pos1 + pos2) / 2
         drawtext(text, color, pos, self.font_size, self.assy.o)
Exemplo n.º 26
0
    def drawCenteredText(self, text, origin):
        """
        Draws ruler text centered, so text center == origin.
        """

        # added by piotr 080326

        if not text:
            return

        fm = self.rulerFontMetrics

        # get the text dimensions in world coordinates
        x0, y0, z0 = gluUnProject(0, 0, 0)
        x1, y1, z1 = gluUnProject(fm.width(text), fm.ascent(), 0)

        # compute a new origin relative to the old one
        new_origin = origin - 0.5 * V(x1 - x0, y1 - y0, z1 - z0)

        # render the text
        self.drawText(text, new_origin)
        return
Exemplo n.º 27
0
    def drawCenteredText(self, text, origin):
        """
        Draws ruler text centered, so text center == origin.
        """       
        
        # added by piotr 080326

        if not text:
            return

        fm = self.rulerFontMetrics
        
        # get the text dimensions in world coordinates 
        x0, y0, z0 = gluUnProject(0,0,0)
        x1, y1, z1 = gluUnProject(fm.width(text),fm.ascent(),0)

        # compute a new origin relative to the old one
        new_origin = origin - 0.5 * V(x1-x0, y1-y0, z1-z0)
        
        # render the text
        self.drawText( text, new_origin)
        return    
Exemplo n.º 28
0
    def handle_press( self, x, y ):
        """
        """
        # opengl calculates coords from lower left
        width, height = self.size
        y = height - y
        print "button pressed at %d, %d" % (x, y)

        near = Vertex( *gluUnProject( x, y, 0.0 ) )
        far = Vertex( *gluUnProject( x, y, 1.0 ) )
        selection = Edge( near, far )

        print "selection edge from %s to %s" % ( str(near), str(far) )

        #self.last_click = near, far

        # find selected
        print "processing selection...",
        self.select( zone=selection )
        print "done!"

        self.redraw()
Exemplo n.º 29
0
def glLibUnProject(mouse_pos):
    viewport = glGetIntegerv(GL_VIEWPORT)
    modelview = glGetDoublev(GL_MODELVIEW_MATRIX)
    projection = glGetDoublev(GL_PROJECTION_MATRIX)
    winX = mouse_pos[0]
    winY = float(viewport[3]) - mouse_pos[1]
    winZ = glReadPixels(winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)
    if type(winZ) != float:
        # On windows glReadPixels returns a weird array
        winZ = winZ[0][0]
    cursor_pos = gluUnProject(winX, winY, winZ, modelview, projection,
                              viewport)
    return cursor_pos
Exemplo n.º 30
0
    def _set_raster_pos(x, y):  # staticmethod
        """
        """
        # If x or y is exactly 0, then numerical roundoff errors can make the raster position invalid.
        # Using 0.1 instead apparently fixes it, and causes no noticable image quality effect.
        # (Presumably they get rounded to integer window positions after the view volume clipping,
        #  though some effects I saw implied that they don't get rounded, so maybe 0.1 is close enough to 0.0.)
        # This only matters when GLPane size is 100x100 or less,
        # or when drawing this in lower left corner for debugging,
        # so we don't have to worry about whether it's perfect.
        # (The known perfect fix is to initialize both matrices, but we don't want to bother,
        #  or to worry about exceeding the projection matrix stack depth.)
        x1 = max(x, 0.1)
        y1 = max(y, 0.1)

        depth = 0.1  # this should not matter, as long as it's within the viewing volume
        x1, y1, z1 = gluUnProject(x1, y1, depth)
        glRasterPos3f(
            x1, y1, z1
        )  # z1 does matter (when in perspective view), since this is a 3d position
        # Note: using glWindowPos would be simpler and better, but it's not defined
        # by the PyOpenGL I'm using. [bruce iMac G5 070626]
        ### UPDATE [bruce 081203]: glWindowPos2i *is* defined, at least on my newer Mac.
        # There are lots of variants, all suffix-typed with [23][dfis]{,v}.
        # I need to check whether it's defined on the older Macs too, then use it here. ####FIX

        if not glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID):
            # This was happening when we used x, y = exact 0,
            # and was causing the image to not get drawn sometimes (when mousewheel zoom was used).
            # It can still happen for extreme values of mousewheel zoom (close to the ones
            # which cause OpenGL exceptions), mostly only when pos = (0, 0) but not entirely.
            # Sometimes the actual drawing positions can get messed up then, too.
            # This doesn't matter much, but indicates that re-initing the matrices would be
            # a better solution if we could be sure the projection stack depth was sufficient
            # (or if we reset the standard projection when done, rather than using push/pop).
            print "bug: not glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID); pos =", x, y
            # if this happens, the subsequent effect is that glDrawPixels draws nothing
        else:
            # verify correct raster position
            px, py, pz, pw = glGetFloatv(GL_CURRENT_RASTER_POSITION)
            if not (0 <= px - x < 0.4) and (0 <= py - y <
                                            0.4):  # change to -0.4 < px - x ??
                print "LIKELY BUG: glGetFloatv(GL_CURRENT_RASTER_POSITION) = %s" % [
                    px, py, pz, pw
                ]
                # seems to be in window coord space, but with float values,
                # roughly [0.1, 0.1, 0.1, 1.0] but depends on viewpoint, error about 10**-5
            pass

        return
Exemplo n.º 31
0
 def plane_intersection(self, x, y):
     # Unproject coordinates into object space
     nx, ny, nz = gluUnProject(x, y, 0.0)
     fx, fy, fz = gluUnProject(x, y, 1.0)
     # Calculate the ray
     near = Point3(nx, ny, nz)
     far = Point3(fx, fy, fz)
     ray = LineSegment3(near, far)
     # Define our planes
     # XXX origin assumes planes are at zero offsets, should really
     # XXX respect any grid plane offset here
     origin = self.voxels.voxel_to_world(0, 0, self.voxels.depth)
     planes = (Plane(Vector3(1, 0, 0),
                     origin[0]), Plane(Vector3(0, 1, 0), origin[1]),
               Plane(Vector3(0, 0, 1), origin[2] + 0.001))
     intersection = None, None, None
     distance = sys.maxint
     for plane in planes:
         # Get intersection point
         intersect = plane.intersect(ray)
         if intersect:
             # Adjust to voxel space coordinates
             x, y, z = self.voxels.world_to_voxel(intersect.x, intersect.y,
                                                  intersect.z)
             x = int(x)
             y = int(y)
             z = int(z)
             # Ignore out of bounds insections
             if not self.voxels.is_valid_bounds(x, y, z):
                 continue
             length = near.distance(
                 Point3(intersect.x, intersect.y, intersect.z))
             if length < distance:
                 intersection = int(x), int(y), int(z)
                 distance = length
     return intersection
Exemplo n.º 32
0
    def _set_raster_pos(x, y): # staticmethod
        """
        """
        # If x or y is exactly 0, then numerical roundoff errors can make the raster position invalid.
        # Using 0.1 instead apparently fixes it, and causes no noticable image quality effect.
        # (Presumably they get rounded to integer window positions after the view volume clipping,
        #  though some effects I saw implied that they don't get rounded, so maybe 0.1 is close enough to 0.0.)
        # This only matters when GLPane size is 100x100 or less,
        # or when drawing this in lower left corner for debugging,
        # so we don't have to worry about whether it's perfect.
        # (The known perfect fix is to initialize both matrices, but we don't want to bother,
        #  or to worry about exceeding the projection matrix stack depth.)
        x1 = max(x, 0.1)
        y1 = max(y, 0.1)

        depth = 0.1 # this should not matter, as long as it's within the viewing volume
        x1, y1, z1 = gluUnProject(x1, y1, depth)
        glRasterPos3f(x1, y1, z1) # z1 does matter (when in perspective view), since this is a 3d position
            # Note: using glWindowPos would be simpler and better, but it's not defined
            # by the PyOpenGL I'm using. [bruce iMac G5 070626]
            ### UPDATE [bruce 081203]: glWindowPos2i *is* defined, at least on my newer Mac.
            # There are lots of variants, all suffix-typed with [23][dfis]{,v}.
            # I need to check whether it's defined on the older Macs too, then use it here. ####FIX

        if not glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID):
            # This was happening when we used x, y = exact 0,
            # and was causing the image to not get drawn sometimes (when mousewheel zoom was used).
            # It can still happen for extreme values of mousewheel zoom (close to the ones
            # which cause OpenGL exceptions), mostly only when pos = (0, 0) but not entirely.
            # Sometimes the actual drawing positions can get messed up then, too.
            # This doesn't matter much, but indicates that re-initing the matrices would be
            # a better solution if we could be sure the projection stack depth was sufficient
            # (or if we reset the standard projection when done, rather than using push/pop).
            print "bug: not glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID); pos =", x, y
                # if this happens, the subsequent effect is that glDrawPixels draws nothing
        else:
            # verify correct raster position
            px, py, pz, pw = glGetFloatv(GL_CURRENT_RASTER_POSITION)
            if not (0 <= px - x < 0.4) and (0 <= py - y < 0.4): # change to -0.4 < px - x ??
                print "LIKELY BUG: glGetFloatv(GL_CURRENT_RASTER_POSITION) = %s" % [px, py, pz, pw]
                # seems to be in window coord space, but with float values,
                # roughly [0.1, 0.1, 0.1, 1.0] but depends on viewpoint, error about 10**-5
            pass
        
        return
Exemplo n.º 33
0
    def get_position_from_click(self, x, y):
        """https://stackoverflow.com/questions/8739311/opengl-select-sphere-with-mouse?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
           https://learnopengl.com/Advanced-OpenGL/Framebuffers
        """
        viewport = glGetIntegerv(GL_VIEWPORT)
        wx = x
        wy = self.height - y
        if self.use_frame_buffer:
            self.frame_buffer.bind_intermediate()
        #self.frame_buffer.bind()

        wz = glReadPixels(wx, wy, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)[0]
        if self.use_frame_buffer:
            self.frame_buffer.unbind()
        view = np.array(self.camera.get_view_matrix(), dtype=np.double)
        proj = np.array(self.camera.get_projection_matrix(), dtype=np.double)
        p = gluUnProject(wx, wy, wz, view, proj, viewport)
        return p
Exemplo n.º 34
0
    def GetWorldCoords(self, x, y, camera_z):
        """ returns (x,y,z)  given x,y pygame screen coords.
            NOTE: try and get the model view matrix back to the camera 
             position when using.
	"""
        y = self.height - y

        mod = glGetDoublev(GL_MODELVIEW_MATRIX)
        proj = glGetDoublev(GL_PROJECTION_MATRIX)

        #view = glGetIntegerv(GL_VIEWPORT)
        view = (0, 0, self.width, self.height)

        z = abs(camera_z)
        z_buffer_value = self.buffer_calc_a + self.buffer_calc_b / z

        objx, objy, objz = gluUnProject(x, y, z_buffer_value, mod, proj, view)

        return (objx, objy, objz)
Exemplo n.º 35
0
    def GetWorldCoords(self, x,y, camera_z):
        """ returns (x,y,z)  given x,y pygame screen coords.
            NOTE: try and get the model view matrix back to the camera 
             position when using.
	"""
	y = self.height - y

	mod = glGetDoublev(GL_MODELVIEW_MATRIX)
	proj = glGetDoublev(GL_PROJECTION_MATRIX)

	#view = glGetIntegerv(GL_VIEWPORT)
	view = (0, 0, self.width, self.height)

	z = abs(camera_z)
	z_buffer_value = self.buffer_calc_a +self.buffer_calc_b / z 

	objx, objy, objz = gluUnProject(x,y,z_buffer_value, mod, proj,view)

	return (objx, objy, objz)
Exemplo n.º 36
0
    def draw(self):
        if self.delegate is None:
            # 070210 -- but I'm not sure if this is a complete ###KLUGE, or good but ought to be done more generally,
            # or if it would be better to do it totally differently by instantiating None into something like Spacer(). ##k
            return

        glMatrixMode(GL_MODELVIEW)  # not needed
        glPushMatrix()
        glLoadIdentity()
        try:
            glpane = self.env.glpane
            ##            aspect = 1.0 ###WRONG -- should use glpane.aspect (which exists as of 070919)
            aspect = glpane.aspect  # revised by bruce 070919, UNTESTED
            corner = self.corner
            delegate = self.delegate
            want_depth = self.want_depth
            # note about cov_depth:
            ## self.near = 0.25
            ## self.far = 12.0
            # so I predict cov_depth is 0.75 / 11.75 == 0.063829787234042548
            # but let's print it from a place that computes it, and see.
            # ... hmm, only place under that name is in selectMode.py, and that prints 0.765957458814 -- I bet it's something
            # different, but not sure. ###k (doesn't matter for now)

            # modified from _setup_modelview:

            saveplace = (
                self.transient_state
            )  # see if this fixes the bug 061211 1117a mentioned below -- it does, use it.
            if glpane.current_glselect or (0 and "KLUGE" and hasattr(saveplace, "_saved_stuff")):
                # kluge did make it faster; still slow, and confounded by the highlighting-delay bug;
                # now I fixed that bug, and now it seems only normally slow for this module -- ok for now.
                x1, y1, z1 = saveplace._saved_stuff  # this is needed to make highlighting work!
                ###BUG [061211 1117a; fixed now, see above, using saveplace = self.transient_state]:
                # if we click on an object in testexpr_15d (with DrawInCorner used for other objs in the testbed)
                # before it has a chance to show its highlighted form, at least after a recent reload, we get an attrerror here.
                # Easy to repeat in the test conditions mentioned (on g5). Not sure how it can affect a different obj (self)
                # than the one clicked on too quickly. Best fix would be to let glpane give us the requested info,
                # which is usually the same for all callers anyway, and the same across reloads (just not across resizes).
                # But it does depend on want_depth, and (via gluUnProject) on the current modelview coords
                # (and projection coords if we ever changed them). So it's not completely clear how to combine ease, efficiency,
                # and safety, for that optim in general, even w/o needing this bugfix.
                #    But the bug is easy to hit, so needs a soon fix... maybe memoize it with a key corresponding to your own
                # assumed choice of modelview coords and want_depth? Or maybe enough to put it into the transient_state? TRY THAT. works.
            else:
                x1, y1, z1 = saveplace._saved_stuff = gluUnProject(
                    glpane.width, glpane.height, want_depth
                )  # max x and y, i.e. right top
                # (note, min x and y would be (0,0,want_depth), since these are windows coords, 0,0 is bottom left corner (not center))
                # Note: Using gluUnProject is probably better than knowing and reversing _setup_projection,
                # since it doesn't depend on knowing the setup code, except meaning of glpane height & width attrs,
                # and knowing that origin is centered between them.
            ##            print x1,y1,z1
            x1wish = glpane.width / 2.0 * PIXELS  # / 2.0 because in these coords, screen center indeed has x == y == 0
            r = x1 / x1wish
            glScale(
                r, r, r
            )  # compensate for zoom*scale in _setup_projection, for error in PIXELS, and for want_depth != cov_depth
            ##            x1 /= r
            ##            y1 /= r
            z1 /= r
            # now the following might work except for z, so fix z here
            glTranslatef(0.0, 0.0, z1)
            del x1, y1  # not presently used

            # I don't think we need to usage-track glpane height & width (or scale or zoomFactor etc)
            # since we'll redraw when those change, and redo this calc every time we draw.
            # The only exception would be if we're rendering into a display list.
            # I don't know if this code (gluUnProject) would even work in that case.
            # [I think I wrote a similar comment in some other file earlier today. #k]

            # move to desired corner, and align it with same corner of lbox
            # (#e could use an alignment prim for the corner if we had one)

            if corner in corner_abbrevs:
                # normalize how corner is expressed, into a 2-tuple of +-1's
                corner = corner_abbrevs[corner]

            x, y = corner

            if x == -1:  # left
                x_offset = -glpane.width / 2.0 * PIXELS + delegate.bleft
            elif x == +1:  # right
                x_offset = +glpane.width / 2.0 * PIXELS - delegate.bright
            elif x == 0:  # center(x)
                x_offset = 0
                # note: before 070210 this was (+ delegate.bleft - delegate.bright) / 2.0,
                # which has an unwanted (since unavoidable) centering effect; use explicit Center if desired.
            else:
                print "invalid corner", corner  ###
                raise ValueError, "invalid corner %r" % (corner,)

            if y == -1:  # bottom
                y_offset = -glpane.height / 2.0 * PIXELS + delegate.bbottom
            elif y == +1:  # top
                y_offset = +glpane.height / 2.0 * PIXELS - delegate.btop
            elif y == 0:  # center(y)
                y_offset = 0
                # note: # note: before 070210 this was (+ delegate.bbottom - delegate.btop) / 2.0
            else:
                print "invalid corner", corner  ###
                raise ValueError, "invalid corner %r" % (corner,)

            offset = (x_offset, y_offset)
            glTranslatef(offset[0], offset[1], 0.0)

            self.drawkid(delegate)  ## delegate.draw()

        finally:
            glMatrixMode(GL_MODELVIEW)  # not needed
            glPopMatrix()

        return
Exemplo n.º 37
0
def drawfont2(glpane, msg = None, charwidth = None, charheight = None,
              testpattern = False, pixelwidth = None):
    """
    Draws a rect of chars (dimensions given as char counts: charwidth x
    charheight

    [#e those args are misnamed] using vv's font texture
    [later 061113: assumed currently bound, i think -- see
    ensure_courierfile_loaded()], in a klugy way;

    msg gives the chars to draw (lines must be shorter than charwidth or they
    will be truncated)
    """
    _bind_courier_font_texture()
    # adjust these guessed params (about the specific font image we're using as
    # a texture) until they work right:   
    # (tex_origin_chars appears lower down, since it is revised there)
    tex_size = (128,128) # tex size in pixels
    tex_nx = 16 # number of chars in a row, in the tex image
    tex_ny = 8  # number of chars in a column

    if msg is None:
        msg = "(redraw %d)" % env.redraw_counter
        charwidth = tex_nx
        charheight = tex_ny + 1

    lines = msg.split('\n') # tab not supported

    if charwidth is None:
        charwidth = 14 # could be max linelength plus 1
    if charheight is None:
        charheight = len(lines)

    if not testpattern:
        while len(lines) < charheight:
            lines.append('')
    
    # draw individual chars from font-texture,
    # but first, try to position it so they look perfect (which worked for a
    # while, but broke sometime before 060728)

    ## glTranslatef( 0, pixelheight / 2, 0 ) # perfect!
        # (Ortho mode, home view, a certain window size -- not sure if that
        # matters but it might)
        # restoring last-saved window position (782, 44) and size (891, 749)
    
    ## gap = 2 # in pixels - good for debugging
        # good for looking nice! but note that idlehack uses one extra pixel of
        # vspace, and that does probably look better.
    gap = 0
    # to do that efficiently i'd want another image to start from.
      # (or to modify this one to make the texture, by moving pixrects around)
    pixfactor = 1
    # try *2... now i can see some fuzz... what if i start at origin, to draw?
    # Did that, got it tolerable for pixfactor 2, then back to 1 and i've lost
    # the niceness! Is it no longer starting at origin?

    ##pixelwidth = pixelheight = 0.05 * 2/3

    #070124 revisions, general comment... current caveats/bugs: ####
    # - Only tested in Ortho mode.
    # - Working well but the bugs depend on whether we add "1 or" before
    #     "pixelwidth is None" in if statement below:
    #   Bugs when it computes pixelwidth here (even when passed, as always in
    #   these tests):
    #   - Textlabel for "current redraw" (in exprs/test.py bottom_left_corner)
    #       disappears during highlighting.
    #   Bugs when it doesn't [usual state & state I'll leave it in]:
    #   - Not tested with displists off, maybe. ###
    #   - Fuzzy text in testexpr_18 [not yet understood.]
    #   - [fixed] Fuzzy text in "current redraw" textlabel during anything's
    #       highlighting. [Fixed by removing DisplayListChunk from that.]
    #   - [No bug in clarity of text in highlighted checkbox prefs themselves.]
    # - Works with displists on or off now.
    # - Is disable_translate helping?? Not sure (only matters when it computes
    #     pixelwidth here -- not now.)
    #   - ##e Use direct drawing_phase test instead? doesn't seem to be needed
    #         anymore, from remaining bugs listed above.
    disable_translate = False #070124
    #061211 permit caller to pass it [note: the exprs module usually or always
    #  passes it, acc'd to test 070124]
    if pixelwidth is None:
        p1junk, p2a = mymousepoints(glpane, 10, 10)
        p1junk, p2b = mymousepoints(glpane, 11, 10)
        px,py,pz = vec = p2b - p2a # should be DX * pixelwidth
        ## print px,py,pz
        ### 0.0313971755382 0.0 0.0 (in Ortho mode, near but not at home view,
        ### also at it (??))
            # 0.0313971755382 0.0 0.0 home ortho
            # 0.03139613018 0.0 0.0 home perspective -- still looks good (looks
            # the same) (with false "smoother textures")
        ## pixelwidth = pixelheight = px * pixfactor
            # 061211 Work better for rotated text (still not good unless
            # screen-parallel.)
        pixelwidth = pixelheight = vlen(vec) * pixfactor
        # print "pixelwidth",pixelwidth
            ####@@@@ can be one of:
            #    0.0319194157846
            # or 0.0313961295259
            # or 0.00013878006302
        if pixelwidth < 0.01:
            # print "low pixelwidth:",pixelwidth, glpane.drawing_phase
            # e.g. 0.000154639183832 glselect
            pixelwidth = 0.0319194157846
            ### kluge, in case you didn't notice [guess: formula is wrong during
            # highlighting] but this failed to fix the bug in which a TextRect
            # doesn't notice clicks unless you slide onto it from a Rect
            # ####@@@@
            # Q 070124: when this happens (presumably due to small window in
            # glSelect) should we disable glTranslatef below?
            # I guess yes, so try it. Not that it'll help when we re-disable
            # always using this case.
            disable_translate = True
            # I'll leave this in since it seems right, but it's not obviously
            # helping by test.
        pass
    else:
        pixelheight = pixelwidth

    tex_origin_chars = V(3, 64) # revised 070124

    #070124 -- note that disable_translate is never set given if statements
    #above --
    if 1 and not disable_translate:
            ##e Use glpane.drawing_phase == 'glselect' instead? doesn't seem to
            ##  be needed anymore, from remaining bugs listed above.
        # Translate slightly to make characters clearer (since we're still too
        #   lazy to use glDrawPixels or whatever it's called).
        # Caveats:
        # - Assumes we're either not in a displist, or it's always drawn in the
        #     same place.
        # - Will only work if we're drawing at correct depth for pixelwidth, I
        #     presume -- and of course, parallel to screen.
        x,y,depth = gluProject(0.0, 0.0, 0.0)
        # Where we'd draw without any correction (ORIGIN).

        # Change x and y to a better place to draw (in pixel coords on screen.)
        # (note: This int(x+0.5) was compared by test to int(x) and int(x)+0.5
        # -- this is best, as one might guess; not same for y...)
        ## if we need a "boldface kluge", using int(x)+0.5 here would be one...
        x = int(x+0.5)
        ### NOT UNDERSTOOD: Why x & y differ, in whether it's best to add this
        ### 0.5.
        y = int(y+0.5)+0.5
        # [btw I'd guessed y+0.5 in int() should be (y-0.5)+0.5 due to outer
        #  +0.5, but that looks worse in checkbox_pref centering; I don't know
        #  why.]
            # [later, 080521: could it be +0.5 effect differing for x & y due to
            # different sign, since int() rounds towards zero rather than
            # towards neginf? ### REVIEW: fix this using intRound?]
            #
            # Adding outer 0.5 to y became best after I fixed a bug of
            # translating before glu*Project (just before this if-statement),
            # which fails inside displists since the translate effect doesn't
            # show up in glu*Project then.
            #
            # I wonder if the x/y difference could be related to the use of
            # CenterY around TextRect inside displists, which ought to produce a
            # similar bug if the shift is not by an exact number of pixels
            # (which is surely the case since the caller is guessing pixelwidth
            # as a hardcoded constant, IIRC). So the guess is that caller's
            # pixelwidth is wrong and/or CenterY shifts by an odd number of
            # halfpixels, inside displist and not seen by this glu*Project,
            # causing a bug which this +0.5 sometimes compensates for, but not
            # always due to pixelwidth being wrong.  It's not worth
            # understanding this compared to switching over to glDrawPixels or
            # whatever it's called. ###DO THAT SOMETIME.
        p1 = A(gluUnProject(x, y, depth)) # where we'd like to draw (p1)
        # Test following code -- with this line, it should make us draw
        # noticeably higher up the screen -- works.
        ## p1 += DY
        glTranslatef( p1[0], p1[1], p1[2])
            # fyi: NameError if we try glTranslatefv or glTranslatev -- didn't
            # look for other variants or in gl doc.
        pass
    
    tex_dx = V(tex_width, 0) # in pixels
    tex_dy = V(0, tex_height)
    # Using those guesses, come up with tex-rects for each char as triples of
    # 2-vectors (tex_origin, tex_dx, tex_dy).

    # i for y, j or x (is that order normal??), still starting at bottom left
    def ff(i,j):
        """
        Which char to draw at this position? i is y, going up, -1 is lowest line
        (sorry.)
        """
        nlines = len(lines)
        bottom = -1 # Change this api sometime.
        # This one too -- caller ought to be able to use 0 or 1 for the top
        # (first) line.
        abovethat = i - bottom
        if abovethat < nlines:
            # Draw chars from lines.
            test = lines[nlines-1 - abovethat]
                # Few-day(?)-old comment [as of 060728], not sure why it's
                # exactly here, maybe since this tells when we redraw, but it
                # might be correct other than that: this shows that mouseover of
                # objects (pixels) w/o glnames causes redraws! I understand
                # glselect ones, but they should not be counted, and should not
                # show up on the screen, so I don't understand any good reason
                # for these visible ones to happen.
                #e To try to find out, we could also record compact_stack of the
                #  first gl_update that caused this redraw...
            if j < len(test):
                # Replace i,j with new ones so as to draw those chars instead.
                ch1 = ord(test[j]) - 32
                j = ch1 % tex_nx
                i = 5 - (ch1 / tex_nx)
            else:
                # Draw a blank instead.
                ch1 = 32 - 32
                j = ch1 % tex_nx
                i = 5 - (ch1 / tex_nx)
        else:
            # Use i,j to index the texture, meaning, draw test chars, perhaps
            # the entire thing.
            pass
        return tex_origin_chars + i * tex_dy + j * tex_dx , tex_dx, tex_dy

    # Now think about where to draw all this... use a gap, but otherwise the
    # same layout.
    charwidth1 = tex_width * pixelwidth
    charheight1 = tex_height * pixelheight
    char_dx = (tex_width + gap) * pixelwidth
    char_dy = (tex_height + gap) * pixelheight

    def gg(i,j):
        return (ORIGIN + j * char_dx * DX + (i + 1) * char_dy * DY,
                charwidth1 * DX, charheight1 * DY)

    # Now draw them.

    if 1: #### for n in range(65): # Simulate delay of a whole page of chars.
        # Note, this is significantly slow even if we just draw 5x as many
        # chars!  (range was -1,tex_ny == 8, length 9) - Note, increasing i goes
        # up on screen, not down!
        for i in range(-1, charheight - 1):
            for j in range(charwidth): # Was tex_nx == 16
                origin, dx, dy = gg(i,j) # Where to draw this char ###k
                # Still in pixel ints. # What tex coords to use to find it?
                tex_origin, ltex_dx, ltex_dy = ff(i,j)
                # Kluge until i look up how to use pixels directly.
                tex_origin, ltex_dx, ltex_dy = 1.0/tex_size[0] \
                                               * V(tex_origin, ltex_dx, ltex_dy)
                #print (origin, dx, dy, tex_origin, tex_dx, tex_dy)
                # Cool bug effect bfr 'l's here.
                draw_textured_rect(origin, dx, dy, tex_origin, ltex_dx, ltex_dy)
            
    # draw some other ones? done above, with test string inside ff function.
    # Interesting q -- if i use vertex arrays or displist-index arrays, can
    # drawing 10k chars be fast? (guess: yes.)
    # Some facts: this window now has 70 lines, about 135 columns... of course
    # it's mostly blank, and in fact just now it has about 3714 chars, not 70 *
    # 135 = 9450 as if it was nowhere blank.
    # Above we draw 9 * 16 = 144, so ratio is 3714 / 144 = 25, or 9450 / 144 =
    # 65.
    # Try 65 redundant loops above & see what happens. It takes it a couple
    # seconds! Too slow! Of course it's mostly the py code.
    # Anyway, it means we *will* have to do one of those optims mentioned, or
    # some other one like not clearing/redrawing the entire screen during most
    # text editing, or having per-line display lists.

    return #drawfont2 #e rename, clean up
Exemplo n.º 38
0
def drawfont2(glpane,
              msg=None,
              charwidth=None,
              charheight=None,
              testpattern=False,
              pixelwidth=None):
    """
    Draws a rect of chars (dimensions given as char counts: charwidth x
    charheight

    [#e those args are misnamed] using vv's font texture
    [later 061113: assumed currently bound, i think -- see
    ensure_courierfile_loaded()], in a klugy way;

    msg gives the chars to draw (lines must be shorter than charwidth or they
    will be truncated)
    """
    _bind_courier_font_texture()
    # adjust these guessed params (about the specific font image we're using as
    # a texture) until they work right:
    # (tex_origin_chars appears lower down, since it is revised there)
    tex_size = (128, 128)  # tex size in pixels
    tex_nx = 16  # number of chars in a row, in the tex image
    tex_ny = 8  # number of chars in a column

    if msg is None:
        msg = "(redraw %d)" % env.redraw_counter
        charwidth = tex_nx
        charheight = tex_ny + 1

    lines = msg.split('\n')  # tab not supported

    if charwidth is None:
        charwidth = 14  # could be max linelength plus 1
    if charheight is None:
        charheight = len(lines)

    if not testpattern:
        while len(lines) < charheight:
            lines.append('')

    # draw individual chars from font-texture,
    # but first, try to position it so they look perfect (which worked for a
    # while, but broke sometime before 060728)

    ## glTranslatef( 0, pixelheight / 2, 0 ) # perfect!
    # (Ortho mode, home view, a certain window size -- not sure if that
    # matters but it might)
    # restoring last-saved window position (782, 44) and size (891, 749)

    ## gap = 2 # in pixels - good for debugging
    # good for looking nice! but note that idlehack uses one extra pixel of
    # vspace, and that does probably look better.
    gap = 0
    # to do that efficiently i'd want another image to start from.
    # (or to modify this one to make the texture, by moving pixrects around)
    pixfactor = 1
    # try *2... now i can see some fuzz... what if i start at origin, to draw?
    # Did that, got it tolerable for pixfactor 2, then back to 1 and i've lost
    # the niceness! Is it no longer starting at origin?

    ##pixelwidth = pixelheight = 0.05 * 2/3

    #070124 revisions, general comment... current caveats/bugs: ####
    # - Only tested in Ortho mode.
    # - Working well but the bugs depend on whether we add "1 or" before
    #     "pixelwidth is None" in if statement below:
    #   Bugs when it computes pixelwidth here (even when passed, as always in
    #   these tests):
    #   - Textlabel for "current redraw" (in exprs/test.py bottom_left_corner)
    #       disappears during highlighting.
    #   Bugs when it doesn't [usual state & state I'll leave it in]:
    #   - Not tested with displists off, maybe. ###
    #   - Fuzzy text in testexpr_18 [not yet understood.]
    #   - [fixed] Fuzzy text in "current redraw" textlabel during anything's
    #       highlighting. [Fixed by removing DisplayListChunk from that.]
    #   - [No bug in clarity of text in highlighted checkbox prefs themselves.]
    # - Works with displists on or off now.
    # - Is disable_translate helping?? Not sure (only matters when it computes
    #     pixelwidth here -- not now.)
    #   - ##e Use direct drawing_phase test instead? doesn't seem to be needed
    #         anymore, from remaining bugs listed above.
    disable_translate = False  #070124
    #061211 permit caller to pass it [note: the exprs module usually or always
    #  passes it, acc'd to test 070124]
    if pixelwidth is None:
        p1junk, p2a = mymousepoints(glpane, 10, 10)
        p1junk, p2b = mymousepoints(glpane, 11, 10)
        px, py, pz = vec = p2b - p2a  # should be DX * pixelwidth
        ## print px,py,pz
        ### 0.0313971755382 0.0 0.0 (in Ortho mode, near but not at home view,
        ### also at it (??))
        # 0.0313971755382 0.0 0.0 home ortho
        # 0.03139613018 0.0 0.0 home perspective -- still looks good (looks
        # the same) (with false "smoother textures")
        ## pixelwidth = pixelheight = px * pixfactor
        # 061211 Work better for rotated text (still not good unless
        # screen-parallel.)
        pixelwidth = pixelheight = vlen(vec) * pixfactor
        # print "pixelwidth",pixelwidth
        ####@@@@ can be one of:
        #    0.0319194157846
        # or 0.0313961295259
        # or 0.00013878006302
        if pixelwidth < 0.01:
            # print "low pixelwidth:",pixelwidth, glpane.drawing_phase
            # e.g. 0.000154639183832 glselect
            pixelwidth = 0.0319194157846
            ### kluge, in case you didn't notice [guess: formula is wrong during
            # highlighting] but this failed to fix the bug in which a TextRect
            # doesn't notice clicks unless you slide onto it from a Rect
            # ####@@@@
            # Q 070124: when this happens (presumably due to small window in
            # glSelect) should we disable glTranslatef below?
            # I guess yes, so try it. Not that it'll help when we re-disable
            # always using this case.
            disable_translate = True
            # I'll leave this in since it seems right, but it's not obviously
            # helping by test.
        pass
    else:
        pixelheight = pixelwidth

    tex_origin_chars = V(3, 64)  # revised 070124

    #070124 -- note that disable_translate is never set given if statements
    #above --
    if 1 and not disable_translate:
        ##e Use glpane.drawing_phase == 'glselect' instead? doesn't seem to
        ##  be needed anymore, from remaining bugs listed above.
        # Translate slightly to make characters clearer (since we're still too
        #   lazy to use glDrawPixels or whatever it's called).
        # Caveats:
        # - Assumes we're either not in a displist, or it's always drawn in the
        #     same place.
        # - Will only work if we're drawing at correct depth for pixelwidth, I
        #     presume -- and of course, parallel to screen.
        x, y, depth = gluProject(0.0, 0.0, 0.0)
        # Where we'd draw without any correction (ORIGIN).

        # Change x and y to a better place to draw (in pixel coords on screen.)
        # (note: This int(x+0.5) was compared by test to int(x) and int(x)+0.5
        # -- this is best, as one might guess; not same for y...)
        ## if we need a "boldface kluge", using int(x)+0.5 here would be one...
        x = int(x + 0.5)
        ### NOT UNDERSTOOD: Why x & y differ, in whether it's best to add this
        ### 0.5.
        y = int(y + 0.5) + 0.5
        # [btw I'd guessed y+0.5 in int() should be (y-0.5)+0.5 due to outer
        #  +0.5, but that looks worse in checkbox_pref centering; I don't know
        #  why.]
        # [later, 080521: could it be +0.5 effect differing for x & y due to
        # different sign, since int() rounds towards zero rather than
        # towards neginf? ### REVIEW: fix this using intRound?]
        #
        # Adding outer 0.5 to y became best after I fixed a bug of
        # translating before glu*Project (just before this if-statement),
        # which fails inside displists since the translate effect doesn't
        # show up in glu*Project then.
        #
        # I wonder if the x/y difference could be related to the use of
        # CenterY around TextRect inside displists, which ought to produce a
        # similar bug if the shift is not by an exact number of pixels
        # (which is surely the case since the caller is guessing pixelwidth
        # as a hardcoded constant, IIRC). So the guess is that caller's
        # pixelwidth is wrong and/or CenterY shifts by an odd number of
        # halfpixels, inside displist and not seen by this glu*Project,
        # causing a bug which this +0.5 sometimes compensates for, but not
        # always due to pixelwidth being wrong.  It's not worth
        # understanding this compared to switching over to glDrawPixels or
        # whatever it's called. ###DO THAT SOMETIME.
        p1 = A(gluUnProject(x, y, depth))  # where we'd like to draw (p1)
        # Test following code -- with this line, it should make us draw
        # noticeably higher up the screen -- works.
        ## p1 += DY
        glTranslatef(p1[0], p1[1], p1[2])
        # fyi: NameError if we try glTranslatefv or glTranslatev -- didn't
        # look for other variants or in gl doc.
        pass

    tex_dx = V(tex_width, 0)  # in pixels
    tex_dy = V(0, tex_height)

    # Using those guesses, come up with tex-rects for each char as triples of
    # 2-vectors (tex_origin, tex_dx, tex_dy).

    # i for y, j or x (is that order normal??), still starting at bottom left
    def ff(i, j):
        """
        Which char to draw at this position? i is y, going up, -1 is lowest line
        (sorry.)
        """
        nlines = len(lines)
        bottom = -1  # Change this api sometime.
        # This one too -- caller ought to be able to use 0 or 1 for the top
        # (first) line.
        abovethat = i - bottom
        if abovethat < nlines:
            # Draw chars from lines.
            test = lines[nlines - 1 - abovethat]
            # Few-day(?)-old comment [as of 060728], not sure why it's
            # exactly here, maybe since this tells when we redraw, but it
            # might be correct other than that: this shows that mouseover of
            # objects (pixels) w/o glnames causes redraws! I understand
            # glselect ones, but they should not be counted, and should not
            # show up on the screen, so I don't understand any good reason
            # for these visible ones to happen.
            #e To try to find out, we could also record compact_stack of the
            #  first gl_update that caused this redraw...
            if j < len(test):
                # Replace i,j with new ones so as to draw those chars instead.
                ch1 = ord(test[j]) - 32
                j = ch1 % tex_nx
                i = 5 - (ch1 / tex_nx)
            else:
                # Draw a blank instead.
                ch1 = 32 - 32
                j = ch1 % tex_nx
                i = 5 - (ch1 / tex_nx)
        else:
            # Use i,j to index the texture, meaning, draw test chars, perhaps
            # the entire thing.
            pass
        return tex_origin_chars + i * tex_dy + j * tex_dx, tex_dx, tex_dy

    # Now think about where to draw all this... use a gap, but otherwise the
    # same layout.
    charwidth1 = tex_width * pixelwidth
    charheight1 = tex_height * pixelheight
    char_dx = (tex_width + gap) * pixelwidth
    char_dy = (tex_height + gap) * pixelheight

    def gg(i, j):
        return (ORIGIN + j * char_dx * DX + (i + 1) * char_dy * DY,
                charwidth1 * DX, charheight1 * DY)

    # Now draw them.

    if 1:  #### for n in range(65): # Simulate delay of a whole page of chars.
        # Note, this is significantly slow even if we just draw 5x as many
        # chars!  (range was -1,tex_ny == 8, length 9) - Note, increasing i goes
        # up on screen, not down!
        for i in range(-1, charheight - 1):
            for j in range(charwidth):  # Was tex_nx == 16
                origin, dx, dy = gg(i, j)  # Where to draw this char ###k
                # Still in pixel ints. # What tex coords to use to find it?
                tex_origin, ltex_dx, ltex_dy = ff(i, j)
                # Kluge until i look up how to use pixels directly.
                tex_origin, ltex_dx, ltex_dy = 1.0/tex_size[0] \
                                               * V(tex_origin, ltex_dx, ltex_dy)
                #print (origin, dx, dy, tex_origin, tex_dx, tex_dy)
                # Cool bug effect bfr 'l's here.
                draw_textured_rect(origin, dx, dy, tex_origin, ltex_dx,
                                   ltex_dy)

    # draw some other ones? done above, with test string inside ff function.
    # Interesting q -- if i use vertex arrays or displist-index arrays, can
    # drawing 10k chars be fast? (guess: yes.)
    # Some facts: this window now has 70 lines, about 135 columns... of course
    # it's mostly blank, and in fact just now it has about 3714 chars, not 70 *
    # 135 = 9450 as if it was nowhere blank.
    # Above we draw 9 * 16 = 144, so ratio is 3714 / 144 = 25, or 9450 / 144 =
    # 65.
    # Try 65 redundant loops above & see what happens. It takes it a couple
    # seconds! Too slow! Of course it's mostly the py code.
    # Anyway, it means we *will* have to do one of those optims mentioned, or
    # some other one like not clearing/redrawing the entire screen during most
    # text editing, or having per-line display lists.

    glpane.kluge_reset_texture_mode_to_work_around_renderText_bug()

    return  #drawfont2 #e rename, clean up
Exemplo n.º 39
0
    def select(self, wX, wY):
        """
        Use the OpenGL picking/selection to select any object. Return the
        selected object, otherwise, return None. Restore projection and 
        model/view matrices before returning.
        """
        ####@@@@ WARNING: The original code for this, in GLPane, has been duplicated and slightly modified
        # in at least three other places (search for glRenderMode to find them). This is bad; common code
        # should be used. Furthermore, I suspect it's sometimes needlessly called more than once per frame;
        # that should be fixed too. [bruce 060721 comment]
        wZ = glReadPixelsf(wX, wY, 1, 1, GL_DEPTH_COMPONENT)
        gz = wZ[0][0]

        if gz >= GL_FAR_Z:  ##Empty space was clicked
            return None

        pxyz = A(gluUnProject(wX, wY, gz))
        pn = self.out
        pxyz -= 0.0002 * pn
        # Note: if this runs before the model is drawn, this can have an
        # exception "OverflowError: math range error", presumably because
        # appropriate state for gluUnProject was not set up. That doesn't
        # normally happen but can happen due to bugs (no known open bugs
        # of that kind).
        # Sometimes our drawing area can become "stuck at gray",
        # and when that happens, the same exception can occur from this line.
        # Could it be that too many accidental mousewheel scrolls occurred
        # and made the scale unreasonable? (To mitigate, we should prevent
        # those from doing anything unless we have a valid model, and also
        # reset that scale when loading a new model (latter is probably
        # already done, but I didn't check).) [bruce 080220 comment]
        dp = -dot(pxyz, pn)

        # Save projection matrix before it's changed.
        glMatrixMode(GL_PROJECTION)
        glPushMatrix()

        current_glselect = (wX, wY, 1, 1)
        self._setup_projection(glselect=current_glselect)

        glSelectBuffer(self.glselectBufferSize)
        glRenderMode(GL_SELECT)
        glInitNames()
        glMatrixMode(GL_MODELVIEW)
        # Save model view matrix before it's changed.
        glPushMatrix()
        try:
            glClipPlane(GL_CLIP_PLANE0, (pn[0], pn[1], pn[2], dp))
            glEnable(GL_CLIP_PLANE0)
            self.drawModel()
            glDisable(GL_CLIP_PLANE0)
        except:
            print_compact_traceback("exception in mode.Draw() during GL_SELECT; ignored; restoring modelview matrix: ")
            glPopMatrix()
            glRenderMode(GL_RENDER)
            return None
        else:
            # Restore model/view matrix
            glPopMatrix()

        # Restore project matrix and set matrix mode to Model/View
        glMatrixMode(GL_PROJECTION)
        glPopMatrix()
        glMatrixMode(GL_MODELVIEW)

        glFlush()

        hit_records = list(glRenderMode(GL_RENDER))
        if debug_flags.atom_debug and 0:
            print "%d hits" % len(hit_records)
        for (near, far, names) in hit_records:  # see example code, renderpass.py
            if debug_flags.atom_debug and 0:
                print "hit record: near, far, names:", near, far, names
                # e.g. hit record: near, far, names: 1439181696 1453030144 (1638426L,)
                # which proves that near/far are too far apart to give actual depth,
                # in spite of the 1-pixel drawing window (presumably they're vertices
                # taken from unclipped primitives, not clipped ones).
            if names:
                name = names[-1]
                assy = self.assy
                obj = assy and assy.object_for_glselect_name(name)
                # k should always return an obj
                return obj
        return None  # from ThumbView.select
Exemplo n.º 40
0
    def draw(self):
        if self.delegate is None:
            # 070210 -- but I'm not sure if this is a complete ###KLUGE, or good but ought to be done more generally,
            # or if it would be better to do it totally differently by instantiating None into something like Spacer(). ##k
            return

        glMatrixMode(GL_MODELVIEW)  # not needed
        glPushMatrix()
        glLoadIdentity()
        try:
            glpane = self.env.glpane
            aspect = glpane.aspect  # revised by bruce 070919
            corner = self.corner
            delegate = self.delegate
            want_depth = self.want_depth
            # note about cov_depth:
            ## self.near = 0.25
            ## self.far = 12.0
            # so I predict cov_depth is 0.75 / 11.75 == 0.063829787234042548
            # but let's print it from a place that computes it, and see.
            # ... hmm, only place under that name is in selectMode.py, and that prints 0.765957458814 -- I bet it's something
            # different, but not sure. ###k (doesn't matter for now)

            # modified from _setup_modelview:

            saveplace = self.transient_state  # see if this fixes the bug 061211 1117a mentioned below -- it does, use it.
            # BUG (probably not related to this code, but not known for sure):
            # mousewheel zoom makes checkboxes inside DrawInCorner
            # either not highlight, or if they are close enough to
            # the center of the screen (I guess), highlight in the
            # wrong size and place. For more info and a partial theory,
            # see the 081202 update in DisplayListChunk.py docstring.
            # Before I realized the connection to DisplayListChunk,
            # I tried using saveplace = self.per_frame_state instead of
            # self.transient_state above, but that had no effect on the bug.
            # That was before I fixed some bugs in same_vals related to
            # numpy.ndarray, when I was plagued with mysterious behavior
            # from those in my debug code (since solved), but I tried it
            # again afterwards and it still doesn't fix this bug, which
            # makes sense if my partial theory about it is true.
            #
            # In principle (unrelated to this bug), I'm dubious we're
            # storing this state in the right place, but I won't change
            # it for now (see related older comments below).
            #
            # Note: I fixed the bug in another way, by changing
            # Highlightable's projection option to default True.
            # [bruce 081202]

            if glpane.current_glselect or (0 and 'KLUGE' and hasattr(
                    saveplace, '_saved_stuff')):
                # kluge did make it faster; still slow, and confounded by the highlighting-delay bug;
                # now I fixed that bug, and now it seems only normally slow for this module -- ok for now.

                # when that cond is false, we have a nonstandard projection matrix
                # (see also the related comments in save_coords_if_safe in Highlightable.py)
                # [bruce 081204 comment]

                x1, y1, z1 = saveplace._saved_stuff  # this is needed to make highlighting work!
                ###BUG [061211 1117a; fixed now, see above, using saveplace = self.transient_state]:
                # if we click on an object in testexpr_15d (with DrawInCorner used for other objs in the testbed)
                # before it has a chance to show its highlighted form, at least after a recent reload, we get an attrerror here.
                # Easy to repeat in the test conditions mentioned (on g5). Not sure how it can affect a different obj (self)
                # than the one clicked on too quickly. Best fix would be to let glpane give us the requested info,
                # which is usually the same for all callers anyway, and the same across reloads (just not across resizes).
                # But it does depend on want_depth, and (via gluUnProject) on the current modelview coords
                # (and projection coords if we ever changed them). So it's not completely clear how to combine ease, efficiency,
                # and safety, for that optim in general, even w/o needing this bugfix.
                #    But the bug is easy to hit, so needs a soon fix... maybe memoize it with a key corresponding to your own
                # assumed choice of modelview coords and want_depth? Or maybe enough to put it into the transient_state? TRY THAT. works.
                if _DEBUG_SAVED_STUFF:
                    print "_DEBUG_SAVED_STUFF: retrieved", x1, y1, z1
            else:
                x1, y1, z1 = saveplace._saved_stuff = \
                             gluUnProject(glpane.width, glpane.height, want_depth)
                # max x and y, i.e. right top
                # (note, to get the min x and y we'd want to pass (0, 0, want_depth),
                #  since these are windows coords -- (0, 0) is bottom left corner (not center))
                #
                # Note: Using gluUnProject is probably better than knowing and reversing _setup_projection,
                # since it doesn't depend on knowing the setup code, except meaning of glpane height & width attrs,
                # and knowing that origin is centered between them and 0.
                if _DEBUG_SAVED_STUFF:
                    print "_DEBUG_SAVED_STUFF: saved", x1, y1, z1


##            print x1,y1,z1
# use glScale to compensate for zoom * scale in _setup_projection,
# for error in PIXELS, and for want_depth != cov_depth
            x1wish = glpane.width / 2.0 * PIXELS  # / 2.0 because in these coords, screen center indeed has x == y == 0
            r = x1 / x1wish
            glScale(r, r, r)
            ##            x1 /= r
            ##            y1 /= r
            z1 /= r
            # now the following might work except for z, so fix z here
            glTranslatef(0.0, 0.0, z1)
            del x1, y1  # not presently used
            if _DEBUG_SAVED_STUFF:
                print "_DEBUG_SAVED_STUFF:     r = %r, translated z by z1 == %r" % (
                    r, z1)

            # I don't think we need to usage-track glpane height & width (or scale or zoomFactor etc)
            # since we'll redraw when those change, and redo this calc every time we draw.
            # The only exception would be if we're rendering into a display list.
            # I don't know if this code (gluUnProject) would even work in that case.
            # [I think I wrote a similar comment in some other file earlier today. #k]

            # move to desired corner, and align it with same corner of lbox
            # (#e could use an alignment prim for the corner if we had one)

            if corner in corner_abbrevs:
                # normalize how corner is expressed, into a 2-tuple of +-1's
                corner = corner_abbrevs[corner]

            x, y = corner

            if x == -1:  # left
                x_offset = -glpane.width / 2.0 * PIXELS + delegate.bleft
            elif x == +1:  # right
                x_offset = +glpane.width / 2.0 * PIXELS - delegate.bright
            elif x == 0:  # center(x)
                x_offset = 0
                # note: before 070210 this was (+ delegate.bleft - delegate.bright) / 2.0,
                # which has an unwanted (since unavoidable) centering effect; use explicit Center if desired.
            else:
                print "invalid corner", corner  ###
                raise ValueError, "invalid corner %r" % (corner, )

            if y == -1:  # bottom
                y_offset = -glpane.height / 2.0 * PIXELS + delegate.bbottom
            elif y == +1:  # top
                y_offset = +glpane.height / 2.0 * PIXELS - delegate.btop
            elif y == 0:  # center(y)
                y_offset = 0
                # note: # note: before 070210 this was (+ delegate.bbottom - delegate.btop) / 2.0
            else:
                print "invalid corner", corner  ###
                raise ValueError, "invalid corner %r" % (corner, )

            offset = (x_offset, y_offset)
            glTranslatef(offset[0], offset[1], 0.0)

            if _DEBUG_SAVED_STUFF:
                print "_DEBUG_SAVED_STUFF:     offset =", offset

            self.drawkid(delegate)  ## delegate.draw()

        finally:
            glMatrixMode(GL_MODELVIEW)  # not needed
            glPopMatrix()

        return
Exemplo n.º 41
0
    def render_pointcloud(self, width, height, cam_yaw=0):
        """Return an image as 3D points"""
        # Move the camera with the base_pos
        base_pos, orn = self.physics.getBasePositionAndOrientation(
            self.robot.racecarUniqueId)

        cam_yaw = 180 * cam_yaw / math.pi + 90
        cam_yaw = cam_yaw % 360
        cam_dist = 1
        cam_roll = 0
        cam_pitch = 0

        base_pos = (base_pos[0], base_pos[1], base_pos[2] + 1)
        view_matrix = self.physics.computeViewMatrixFromYawPitchRoll(
            cameraTargetPosition=base_pos,
            distance=cam_dist,
            yaw=cam_yaw,
            pitch=cam_pitch,
            roll=cam_roll,
            upAxisIndex=2)

        view_matrix_reverse = self.physics.computeViewMatrixFromYawPitchRoll(
            cameraTargetPosition=base_pos,
            distance=cam_dist,
            yaw=(cam_yaw + 180) % 360,
            pitch=cam_pitch,
            roll=cam_roll,
            upAxisIndex=2)

        proj_matrix = self.physics.computeProjectionMatrixFOV(
            fov=60, aspect=float(width) / height, nearVal=1, farVal=40.0)

        (_, _, rgb, depth, segmentation) = self.physics.getCameraImage(
            width=width,
            height=height,
            viewMatrix=view_matrix,
            projectionMatrix=proj_matrix,
            renderer=pybullet.ER_BULLET_HARDWARE_OPENGL)

        # Make image
        rgb_image = np.array(rgb)
        rgb_image = rgb_image[:, :, :3]

        # Make points
        viewport = (0, 0, width, height)
        matrixModelView = view_matrix
        matrixProjection = proj_matrix

        # Make points slightly noise
        depth += np.random.normal(scale=ZED_NOISE, size=depth.shape)

        # Make camera params
        camera = make_camera(height, width, view_matrix_reverse, proj_matrix)

        # Output vectors
        pts = np.zeros((width * height, 3))
        pts_rgb = np.zeros((width * height, 3))
        pts_seg = np.zeros((width * height, ))

        for y in range(height):
            if y % 10 == 0:
                pass
                #print('row:',y)
            for x in range(width):
                z = depth[y, x]
                if z == 1.0: continue
                if z < ZED_MIN_RANGE or z > ZED_MAX_RANGE: continue
                i = x + y * width  # Simple counter
                pts[i, :] = gluUnProject(x, y, z, matrixModelView,
                                         matrixProjection, viewport)
                pts_rgb[i, :] = rgb_image[y, x, :] / 255
                pts_seg[i] = segmentation[y, x]
        return pts, pts_rgb, pts_seg, camera
Exemplo n.º 42
0
    def draw(self):
        if self.delegate is None:
            # 070210 -- but I'm not sure if this is a complete ###KLUGE, or good but ought to be done more generally,
            # or if it would be better to do it totally differently by instantiating None into something like Spacer(). ##k
            return
        
        glMatrixMode(GL_MODELVIEW) # not needed
        glPushMatrix()
        glLoadIdentity()
        try:
            glpane = self.env.glpane
##            aspect = 1.0 ###WRONG -- should use glpane.aspect (which exists as of 070919)
            aspect = glpane.aspect # revised by bruce 070919, UNTESTED
            corner = self.corner
            delegate = self.delegate
            want_depth = self.want_depth
                # note about cov_depth:
                ## self.near = 0.25
                ## self.far = 12.0
                # so I predict cov_depth is 0.75 / 11.75 == 0.063829787234042548
                # but let's print it from a place that computes it, and see.
                # ... hmm, only place under that name is in selectMode.py, and that prints 0.765957458814 -- I bet it's something
                # different, but not sure. ###k (doesn't matter for now)

            # modified from _setup_modelview:

            saveplace = self.transient_state # see if this fixes the bug 061211 1117a mentioned below -- it does, use it.
            if glpane.current_glselect or (0 and 'KLUGE' and hasattr(saveplace, '_saved_stuff')):
                            # kluge did make it faster; still slow, and confounded by the highlighting-delay bug;
                            # now I fixed that bug, and now it seems only normally slow for this module -- ok for now.
                x1, y1, z1 = saveplace._saved_stuff # this is needed to make highlighting work!
                ###BUG [061211 1117a; fixed now, see above, using saveplace = self.transient_state]:
                # if we click on an object in testexpr_15d (with DrawInCorner used for other objs in the testbed)
                # before it has a chance to show its highlighted form, at least after a recent reload, we get an attrerror here.
                # Easy to repeat in the test conditions mentioned (on g5). Not sure how it can affect a different obj (self)
                # than the one clicked on too quickly. Best fix would be to let glpane give us the requested info,
                # which is usually the same for all callers anyway, and the same across reloads (just not across resizes).
                # But it does depend on want_depth, and (via gluUnProject) on the current modelview coords
                # (and projection coords if we ever changed them). So it's not completely clear how to combine ease, efficiency,
                # and safety, for that optim in general, even w/o needing this bugfix.
                #    But the bug is easy to hit, so needs a soon fix... maybe memoize it with a key corresponding to your own
                # assumed choice of modelview coords and want_depth? Or maybe enough to put it into the transient_state? TRY THAT. works.
            else:
                x1, y1, z1 = saveplace._saved_stuff = gluUnProject(glpane.width, glpane.height, want_depth) # max x and y, i.e. right top
                # (note, min x and y would be (0,0,want_depth), since these are windows coords, 0,0 is bottom left corner (not center))
                # Note: Using gluUnProject is probably better than knowing and reversing _setup_projection,
                # since it doesn't depend on knowing the setup code, except meaning of glpane height & width attrs,
                # and knowing that origin is centered between them.
##            print x1,y1,z1
            x1wish = glpane.width / 2.0 * PIXELS # / 2.0 because in these coords, screen center indeed has x == y == 0
            r = x1/x1wish
            glScale(r,r,r) # compensate for zoom*scale in _setup_projection, for error in PIXELS, and for want_depth != cov_depth
##            x1 /= r
##            y1 /= r
            z1 /= r
            # now the following might work except for z, so fix z here
            glTranslatef( 0.0, 0.0, z1)
            del x1,y1 # not presently used
            
            # I don't think we need to usage-track glpane height & width (or scale or zoomFactor etc)
            # since we'll redraw when those change, and redo this calc every time we draw.
            # The only exception would be if we're rendering into a display list.
            # I don't know if this code (gluUnProject) would even work in that case.
            # [I think I wrote a similar comment in some other file earlier today. #k]
            
            # move to desired corner, and align it with same corner of lbox
            # (#e could use an alignment prim for the corner if we had one)

            if corner in corner_abbrevs:
                # normalize how corner is expressed, into a 2-tuple of +-1's
                corner = corner_abbrevs[corner]

            x, y = corner

            if x == -1: # left
                x_offset = - glpane.width / 2.0 * PIXELS + delegate.bleft
            elif x == +1: # right
                x_offset = + glpane.width / 2.0 * PIXELS - delegate.bright
            elif x == 0: # center(x)
                x_offset = 0
                    # note: before 070210 this was (+ delegate.bleft - delegate.bright) / 2.0,
                    # which has an unwanted (since unavoidable) centering effect; use explicit Center if desired.
            else:
                print "invalid corner",corner###
                raise ValueError, "invalid corner %r" % (corner,)
                
            if y == -1: # bottom
                y_offset = - glpane.height / 2.0 * PIXELS + delegate.bbottom
            elif y == +1: # top
                y_offset = + glpane.height / 2.0 * PIXELS - delegate.btop
            elif y == 0: # center(y)
                y_offset = 0
                    # note: # note: before 070210 this was (+ delegate.bbottom - delegate.btop) / 2.0
            else:
                print "invalid corner",corner###
                raise ValueError, "invalid corner %r" % (corner,)

            offset = (x_offset, y_offset)
            glTranslatef(offset[0], offset[1], 0.0)
            
            self.drawkid( delegate) ## delegate.draw()
            
        finally:
            glMatrixMode(GL_MODELVIEW) # not needed
            glPopMatrix()

        return
Exemplo n.º 43
0
    def leftUp(self, event):
        """
        Erase the final rubber band window and do zoom if user indeed draws a
        rubber band window.
        """
        # bugs 1190, 1818 wware 4/05/2006 - sometimes Qt neglects to call
        # leftDown before this
        if not hasattr(self, "pWxy") or not hasattr(self, "firstDraw"):
            return
        cWxy = (event.pos().x(), self.glpane.height - event.pos().y())
        zoomX = (abs(cWxy[0] - self.pWxy[0]) + 0.0) / (self.glpane.width + 0.0)
        zoomY = (abs(cWxy[1] - self.pWxy[1]) + 0.0) / (self.glpane.height + 0.0)

        # The rubber band window size can be larger than that of glpane.
        # Limit the zoomFactor to 1.0
        zoomFactor = min(max(zoomX, zoomY), 1.0)

        # Huaicai: when rubber band window is too small,
        # like a double click, a single line rubber band, skip zoom
        DELTA = 1.0E-5
        if self.pWxy[0] == cWxy[0] or self.pWxy[1] == cWxy[1] \
                or zoomFactor < DELTA:

            self.command.command_Done()
            return

        # Erase the last rubber-band window
        rbwcolor = self.command.rbwcolor
        drawrectangle(self.pStart, self.pPrev, self.glpane.up,
                      self.glpane.right, rbwcolor)
        glFlush()
        self.glpane.swapBuffers()

        winCenterX = (cWxy[0] + self.pWxy[0]) / 2.0
        winCenterY = (cWxy[1] + self.pWxy[1]) / 2.0
        winCenterZ = \
            glReadPixelsf(int(winCenterX), int(winCenterY), 1, 1,
                          GL_DEPTH_COMPONENT)

        assert winCenterZ[0][0] >= 0.0 and winCenterZ[0][0] <= 1.0
        if winCenterZ[0][0] >= GL_FAR_Z:  # window center touches nothing
            p1 = A(gluUnProject(winCenterX, winCenterY, 0.005))
            p2 = A(gluUnProject(winCenterX, winCenterY, 1.0))

            los = self.glpane.lineOfSight
            k = dot(los, -self.glpane.pov - p1) / dot(los, p2 - p1)

            zoomCenter = p1 + k*(p2-p1)

        else:
            zoomCenter = \
                A(gluUnProject(winCenterX, winCenterY, winCenterZ[0][0]))
        self.glpane.pov = V(-zoomCenter[0], -zoomCenter[1], -zoomCenter[2])

        # The following are 2 ways to do the zoom, the first one
        # changes view angles, the 2nd one change viewing distance
        # The advantage for the 1st one is model will not be clipped by
        #  near or back clipping planes, and the rubber band can be
        # always shown. The disadvantage: when the view field is too
        # small, a selection window may be actually act as a single pick.
        # rubber band window will not look as rectangular any more.
        #zf = self.glpane.getZoomFactor() # [note: method does not exist]
        #zoomFactor = pow(zoomFactor, 0.25)
        #zoomFactor *= zf
        #self.glpane.setZoomFactor(zoomFactor) # [note: method does not exist]

        # Change viewing distance to do zoom. This works better with
        # mouse wheel, since both are changing viewing distance, and
        # it's not too bad of model being clipped, since the near/far clip
        # plane change as scale too.
        self.glpane.scale *= zoomFactor

        self.command.command_Done()
        return
Exemplo n.º 44
0
    def select(self, wX, wY):
        """
        Use the OpenGL picking/selection to select any object. Return the
        selected object, otherwise, return None. Restore projection and 
        model/view matrices before returning.
        """
        ####@@@@ WARNING: The original code for this, in GLPane, has been duplicated and slightly modified
        # in at least three other places (search for glRenderMode to find them). This is bad; common code
        # should be used. Furthermore, I suspect it's sometimes needlessly called more than once per frame;
        # that should be fixed too. [bruce 060721 comment]
        wZ = glReadPixelsf(wX, wY, 1, 1, GL_DEPTH_COMPONENT)
        gz = wZ[0][0]

        if gz >= GL_FAR_Z:  ##Empty space was clicked
            return None

        pxyz = A(gluUnProject(wX, wY, gz))
        pn = self.out
        pxyz -= 0.0002 * pn
        # Note: if this runs before the model is drawn, this can have an
        # exception "OverflowError: math range error", presumably because
        # appropriate state for gluUnProject was not set up. That doesn't
        # normally happen but can happen due to bugs (no known open bugs
        # of that kind).
        # Sometimes our drawing area can become "stuck at gray",
        # and when that happens, the same exception can occur from this line.
        # Could it be that too many accidental mousewheel scrolls occurred
        # and made the scale unreasonable? (To mitigate, we should prevent
        # those from doing anything unless we have a valid model, and also
        # reset that scale when loading a new model (latter is probably
        # already done, but I didn't check).) [bruce 080220 comment]
        dp = -dot(pxyz, pn)

        #Save projection matrix before it's changed.
        glMatrixMode(GL_PROJECTION)
        glPushMatrix()

        current_glselect = (wX, wY, 1, 1)
        self._setup_projection(glselect=current_glselect)

        glSelectBuffer(self.glselectBufferSize)
        glRenderMode(GL_SELECT)
        glInitNames()
        glMatrixMode(GL_MODELVIEW)
        # Save model view matrix before it's changed.
        glPushMatrix()
        try:
            glClipPlane(GL_CLIP_PLANE0, (pn[0], pn[1], pn[2], dp))
            glEnable(GL_CLIP_PLANE0)
            self.drawModel()
            glDisable(GL_CLIP_PLANE0)
        except:
            print_compact_traceback(
                "exception in mode.Draw() during GL_SELECT; ignored; restoring modelview matrix: "
            )
            glPopMatrix()
            glRenderMode(GL_RENDER)
            return None
        else:
            # Restore model/view matrix
            glPopMatrix()

        #Restore project matrix and set matrix mode to Model/View
        glMatrixMode(GL_PROJECTION)
        glPopMatrix()
        glMatrixMode(GL_MODELVIEW)

        glFlush()

        hit_records = list(glRenderMode(GL_RENDER))
        if debug_flags.atom_debug and 0:
            print "%d hits" % len(hit_records)
        for (near, far,
             names) in hit_records:  # see example code, renderpass.py
            if debug_flags.atom_debug and 0:
                print "hit record: near, far, names:", near, far, names
                # e.g. hit record: near, far, names: 1439181696 1453030144 (1638426L,)
                # which proves that near/far are too far apart to give actual depth,
                # in spite of the 1-pixel drawing window (presumably they're vertices
                # taken from unclipped primitives, not clipped ones).
            if names:
                name = names[-1]
                assy = self.assy
                obj = assy and assy.object_for_glselect_name(name)
                #k should always return an obj
                return obj
        return None  # from ThumbView.select
Exemplo n.º 45
0
    def leftUp(self, event):
        """
        Erase the final rubber band window and do zoom if user indeed draws a
        rubber band window.
        """
        # bugs 1190, 1818 wware 4/05/2006 - sometimes Qt neglects to call
        # leftDown before this
        if not hasattr(self, "pWxy") or not hasattr(self, "firstDraw"):
            return
        cWxy = (event.pos().x(), self.glpane.height - event.pos().y())
        zoomX = (abs(cWxy[0] - self.pWxy[0]) + 0.0) / (self.glpane.width + 0.0)
        zoomY = (abs(cWxy[1] - self.pWxy[1]) + 0.0) / (self.glpane.height +
                                                       0.0)

        # The rubber band window size can be larger than that of glpane.
        # Limit the zoomFactor to 1.0
        zoomFactor = min(max(zoomX, zoomY), 1.0)

        # Huaicai: when rubber band window is too small,
        # like a double click, a single line rubber band, skip zoom
        DELTA = 1.0E-5
        if self.pWxy[0] == cWxy[0] or self.pWxy[1] == cWxy[1] \
                or zoomFactor < DELTA:
            self.command.Done()
            return

        # Erase the last rubber-band window
        rbwcolor = self.command.rbwcolor
        drawrectangle(self.pStart, self.pPrev, self.glpane.up,
                      self.glpane.right, rbwcolor)
        glFlush()
        self.glpane.swapBuffers()

        winCenterX = (cWxy[0] + self.pWxy[0]) / 2.0
        winCenterY = (cWxy[1] + self.pWxy[1]) / 2.0
        winCenterZ = \
            glReadPixelsf(int(winCenterX), int(winCenterY), 1, 1,
                          GL_DEPTH_COMPONENT)

        assert winCenterZ[0][0] >= 0.0 and winCenterZ[0][0] <= 1.0
        if winCenterZ[0][0] >= GL_FAR_Z:  # window center touches nothing
            p1 = A(gluUnProject(winCenterX, winCenterY, 0.005))
            p2 = A(gluUnProject(winCenterX, winCenterY, 1.0))

            los = self.glpane.lineOfSight
            k = dot(los, -self.glpane.pov - p1) / dot(los, p2 - p1)

            zoomCenter = p1 + k * (p2 - p1)

        else:
            zoomCenter = \
                A(gluUnProject(winCenterX, winCenterY, winCenterZ[0][0]))
        self.glpane.pov = V(-zoomCenter[0], -zoomCenter[1], -zoomCenter[2])

        # The following are 2 ways to do the zoom, the first one
        # changes view angles, the 2nd one change viewing distance
        # The advantage for the 1st one is model will not be clipped by
        #  near or back clipping planes, and the rubber band can be
        # always shown. The disadvantage: when the view field is too
        # small, a selection window may be actually act as a single pick.
        # rubber ban window will not look as rectanglular any more.
        #zf = self.glpane.getZoomFactor()
        #zoomFactor = pow(zoomFactor, 0.25)
        #zoomFactor *= zf
        #self.glpane.setZoomFactor(zoomFactor)

        # Change viewing distance to do zoom. This works better with
        # mouse wheel, since both are changing viewing distance, and
        # it's not too bad of model being clipped, since the near/far clip
        # plane change as scale too.
        self.glpane.scale *= zoomFactor

        self.command.Done(exit_using_done_or_cancel_button=False)
        return
Exemplo n.º 46
0
    def select(self, wX, wY):
        """
        Use the OpenGL picking/selection to select any object. Return the
        selected object, otherwise, return None. Restore projection and 
        modelview matrices before returning.
        """
        ### NOTE: this code is similar to (and was copied and modified from)
        # GLPane_highlighting_methods.do_glselect_if_wanted, but also differs
        # in significant ways (too much to make it worth merging, unless we
        # decide to merge the differing algorithms as well). It's one of
        # several instances of hit-test code that calls glRenderMode.
        # [bruce 060721/080917 comment]
        wZ = glReadPixelsf(wX, wY, 1, 1, GL_DEPTH_COMPONENT)
        gz = wZ[0][0]
        
        if gz >= GL_FAR_Z: # Empty space was clicked
            return None
        
        pxyz = A(gluUnProject(wX, wY, gz))
        pn = self.out
        pxyz -= 0.0002 * pn
            # Note: if this runs before the model is drawn, this can have an
            # exception "OverflowError: math range error", presumably because
            # appropriate state for gluUnProject was not set up. That doesn't
            # normally happen but can happen due to bugs (no known open bugs
            # of that kind).
            # Sometimes our drawing area can become "stuck at gray",
            # and when that happens, the same exception can occur from this line.
            # Could it be that too many accidental mousewheel scrolls occurred
            # and made the scale unreasonable? (To mitigate, we should prevent
            # those from doing anything unless we have a valid model, and also
            # reset that scale when loading a new model (latter is probably
            # already done, but I didn't check). See also the comments
            # in def wheelEvent.) [bruce 080220 comment]
        dp = - dot(pxyz, pn)
        
        # Save projection matrix before it's changed.
        glMatrixMode(GL_PROJECTION)
        glPushMatrix()
        
        current_glselect = (wX, wY, 1, 1) 
        self._setup_projection(glselect = current_glselect) 
        
        glSelectBuffer(self.SIZE_FOR_glSelectBuffer)
        glRenderMode(GL_SELECT)
        glInitNames()
        glMatrixMode(GL_MODELVIEW)
        # Save model view matrix before it's changed.
        glPushMatrix()

        # Draw model using glRenderMode(GL_SELECT) as set up above 
        try:
            glClipPlane(GL_CLIP_PLANE0, (pn[0], pn[1], pn[2], dp))
            glEnable(GL_CLIP_PLANE0)
            self._drawModel_using_DrawingSets()
        except:
            #bruce 080917 fixed predicted bugs in this except clause (untested)
            print_compact_traceback("exception in ThumbView._drawModel_using_DrawingSets() during GL_SELECT; ignored; restoring matrices: ")
            glDisable(GL_CLIP_PLANE0)
            glMatrixMode(GL_PROJECTION)
            glPopMatrix()
            glMatrixMode(GL_MODELVIEW)
            glPopMatrix()
            glRenderMode(GL_RENDER)
            return None
        else:
            glDisable(GL_CLIP_PLANE0)
            # Restore model/view matrix
            glPopMatrix()
        
        # Restore projection matrix and set matrix mode to Model/View
        glMatrixMode(GL_PROJECTION)
        glPopMatrix()
        glMatrixMode(GL_MODELVIEW)
        
        glFlush()
        
        hit_records = list(glRenderMode(GL_RENDER))
        ## print "%d hits" % len(hit_records)
        for (near, far, names) in hit_records:
            ## print "hit record: near, far, names:", near, far, names
            # note from testing: near/far are too far apart to give actual depth,
            # in spite of the 1-pixel drawing window (presumably they're vertices
            # taken from unclipped primitives, not clipped ones).
            ### REVIEW: this just returns the first candidate object found.
            # The clip plane may restrict the set of candidates well enough to
            # make sure that's the right one, but this is untested and unreviewed.
            # (And it's just my guess that that was Huaicai's intention in
            #  setting up clipping, since it's not documented. I'm guessing that
            #  the plane is just behind the hitpoint, but haven't confirmed this.)
            # [bruce 080917 comment]
            if names:
                name = names[-1]
                assy = self.assy
                obj = assy and assy.object_for_glselect_name(name)
                    #k should always return an obj
                return obj
        return None # from ThumbView.select
Exemplo n.º 47
0
    def draw(self):
        if self.delegate is None:
            # 070210 -- but I'm not sure if this is a complete ###KLUGE, or good but ought to be done more generally,
            # or if it would be better to do it totally differently by instantiating None into something like Spacer(). ##k
            return
        
        glMatrixMode(GL_MODELVIEW) # not needed
        glPushMatrix()
        glLoadIdentity()
        try:
            glpane = self.env.glpane
            aspect = glpane.aspect # revised by bruce 070919
            corner = self.corner
            delegate = self.delegate
            want_depth = self.want_depth
                # note about cov_depth:
                ## self.near = 0.25
                ## self.far = 12.0
                # so I predict cov_depth is 0.75 / 11.75 == 0.063829787234042548
                # but let's print it from a place that computes it, and see.
                # ... hmm, only place under that name is in selectMode.py, and that prints 0.765957458814 -- I bet it's something
                # different, but not sure. ###k (doesn't matter for now)

            # modified from _setup_modelview:

            saveplace = self.transient_state # see if this fixes the bug 061211 1117a mentioned below -- it does, use it.
                # BUG (probably not related to this code, but not known for sure):
                # mousewheel zoom makes checkboxes inside DrawInCorner
                # either not highlight, or if they are close enough to
                # the center of the screen (I guess), highlight in the
                # wrong size and place. For more info and a partial theory,
                # see the 081202 update in DisplayListChunk.py docstring.
                # Before I realized the connection to DisplayListChunk,
                # I tried using saveplace = self.per_frame_state instead of
                # self.transient_state above, but that had no effect on the bug.
                # That was before I fixed some bugs in same_vals related to
                # numpy.ndarray, when I was plagued with mysterious behavior
                # from those in my debug code (since solved), but I tried it
                # again afterwards and it still doesn't fix this bug, which
                # makes sense if my partial theory about it is true.
                #
                # In principle (unrelated to this bug), I'm dubious we're
                # storing this state in the right place, but I won't change
                # it for now (see related older comments below).
                #
                # Note: I fixed the bug in another way, by changing
                # Highlightable's projection option to default True.
                # [bruce 081202]
            
            if glpane.current_glselect or (0 and 'KLUGE' and hasattr(saveplace, '_saved_stuff')):
                            # kluge did make it faster; still slow, and confounded by the highlighting-delay bug;
                            # now I fixed that bug, and now it seems only normally slow for this module -- ok for now.
                
                # when that cond is false, we have a nonstandard projection matrix
                # (see also the related comments in save_coords_if_safe in Highlightable.py)
                # [bruce 081204 comment]

                x1, y1, z1 = saveplace._saved_stuff # this is needed to make highlighting work!
                ###BUG [061211 1117a; fixed now, see above, using saveplace = self.transient_state]:
                # if we click on an object in testexpr_15d (with DrawInCorner used for other objs in the testbed)
                # before it has a chance to show its highlighted form, at least after a recent reload, we get an attrerror here.
                # Easy to repeat in the test conditions mentioned (on g5). Not sure how it can affect a different obj (self)
                # than the one clicked on too quickly. Best fix would be to let glpane give us the requested info,
                # which is usually the same for all callers anyway, and the same across reloads (just not across resizes).
                # But it does depend on want_depth, and (via gluUnProject) on the current modelview coords
                # (and projection coords if we ever changed them). So it's not completely clear how to combine ease, efficiency,
                # and safety, for that optim in general, even w/o needing this bugfix.
                #    But the bug is easy to hit, so needs a soon fix... maybe memoize it with a key corresponding to your own
                # assumed choice of modelview coords and want_depth? Or maybe enough to put it into the transient_state? TRY THAT. works.
                if _DEBUG_SAVED_STUFF:
                    print "_DEBUG_SAVED_STUFF: retrieved", x1, y1, z1
            else:
                x1, y1, z1 = saveplace._saved_stuff = \
                             gluUnProject(glpane.width, glpane.height, want_depth)
                                # max x and y, i.e. right top
                # (note, to get the min x and y we'd want to pass (0, 0, want_depth),
                #  since these are windows coords -- (0, 0) is bottom left corner (not center))
                #
                # Note: Using gluUnProject is probably better than knowing and reversing _setup_projection,
                # since it doesn't depend on knowing the setup code, except meaning of glpane height & width attrs,
                # and knowing that origin is centered between them and 0.
                if _DEBUG_SAVED_STUFF:
                    print "_DEBUG_SAVED_STUFF: saved", x1, y1, z1
##            print x1,y1,z1
            # use glScale to compensate for zoom * scale in _setup_projection,
            # for error in PIXELS, and for want_depth != cov_depth
            x1wish = glpane.width / 2.0 * PIXELS # / 2.0 because in these coords, screen center indeed has x == y == 0
            r = x1 / x1wish
            glScale(r, r, r) 
##            x1 /= r
##            y1 /= r
            z1 /= r
            # now the following might work except for z, so fix z here
            glTranslatef( 0.0, 0.0, z1)
            del x1, y1 # not presently used
            if _DEBUG_SAVED_STUFF:
                print "_DEBUG_SAVED_STUFF:     r = %r, translated z by z1 == %r" % (r, z1)
            
            # I don't think we need to usage-track glpane height & width (or scale or zoomFactor etc)
            # since we'll redraw when those change, and redo this calc every time we draw.
            # The only exception would be if we're rendering into a display list.
            # I don't know if this code (gluUnProject) would even work in that case.
            # [I think I wrote a similar comment in some other file earlier today. #k]
            
            # move to desired corner, and align it with same corner of lbox
            # (#e could use an alignment prim for the corner if we had one)

            if corner in corner_abbrevs:
                # normalize how corner is expressed, into a 2-tuple of +-1's
                corner = corner_abbrevs[corner]

            x, y = corner

            if x == -1: # left
                x_offset = - glpane.width / 2.0 * PIXELS + delegate.bleft
            elif x == +1: # right
                x_offset = + glpane.width / 2.0 * PIXELS - delegate.bright
            elif x == 0: # center(x)
                x_offset = 0
                    # note: before 070210 this was (+ delegate.bleft - delegate.bright) / 2.0,
                    # which has an unwanted (since unavoidable) centering effect; use explicit Center if desired.
            else:
                print "invalid corner",corner###
                raise ValueError, "invalid corner %r" % (corner,)
                
            if y == -1: # bottom
                y_offset = - glpane.height / 2.0 * PIXELS + delegate.bbottom
            elif y == +1: # top
                y_offset = + glpane.height / 2.0 * PIXELS - delegate.btop
            elif y == 0: # center(y)
                y_offset = 0
                    # note: # note: before 070210 this was (+ delegate.bbottom - delegate.btop) / 2.0
            else:
                print "invalid corner",corner###
                raise ValueError, "invalid corner %r" % (corner,)

            offset = (x_offset, y_offset)
            glTranslatef(offset[0], offset[1], 0.0)

            if _DEBUG_SAVED_STUFF:
                print "_DEBUG_SAVED_STUFF:     offset =", offset
            
            self.drawkid( delegate) ## delegate.draw()
            
        finally:
            glMatrixMode(GL_MODELVIEW) # not needed
            glPopMatrix()

        return
    def renderTextAtPosition(self,
                             position,
                             textString,
                             textColor = black,
                             textFont = None,
                             fontSize = 11,
                             ):
        """
        Renders the text at the specified position (x, y, z coordinates)
        @param position: The x, y, z coordinates of the object at which the 
        text needs to be rendered. 
        @type position: B{A}
        @param textString:  the text to be rendered at the specified position.
        @type textString : str
        @see: self.renderTextNearCursor() This method is different than that 
        method. That method uses QPoint (the current cursor position) to 
        render the text (thus needs integers x and y) whereas this method
        uses the actual object coordinates        
        @see: MultiplednaSegment_GraphicsMode._drawDnaRubberbandLine() [obsolete class name, what is correct one?]
        @see: QGLWidget.renderText()

        @TODO: refactor to move the common code in this method and
        self.renderTextNearCursor().
        """
        
        if textFont is not None:
            font = textFont
        else:
            font = self._getFontForTextNearCursor(fontSize = fontSize, 
                                                  isBold = True)
        x = position[0]
        y = position[1]
        z = position[2]

        glDisable(GL_LIGHTING)
        
        #Convert the object coordinates to the window coordinates.
        wX, wY, wZ = gluProject(x, y, z)
        
        halo_color = getTextHaloColor(textColor)
        
        offset_val = 1
        bg_z_offset = 0
        fg_z_offset = -1e-7

        render_positions = (( offset_val,  offset_val, bg_z_offset, halo_color), 
                            (-offset_val, -offset_val, bg_z_offset, halo_color), 
                            (-offset_val,  offset_val, bg_z_offset, halo_color), 
                            ( offset_val, -offset_val, bg_z_offset, halo_color),
                            (          0,           0, fg_z_offset, textColor))

        for dx, dy, dz, color in render_positions:
            x1, y1, z1 = gluUnProject(wX + dx, wY + dy, wZ + dz)

            self.qglColor(RGBf_to_QColor(color)) 
            self.renderText(x1, y1, z1,
                            QString(textString),
                            font)
##            self.qglClearColor(RGBf_to_QColor(color))
##            # question: is this related to glClearColor? [bruce 071214 question]
##            # -- yes [Ninad 2008-08-20]

        glEnable(GL_LIGHTING)        
Exemplo n.º 49
0
 def model_coords(self,x,y):
     """given an (x,y) coordinate pair on the viewport, returns the
     coordinates in model space"""
     tz = gluProject(self._look_at[0],self._look_at[1],
                     self._look_at[2])[2] # retrieve the depth coordinate
     return array(gluUnProject(x,self.get_view_height()-y,tz))
Exemplo n.º 50
0
    def select(self, wX, wY):
        """
        Use the OpenGL picking/selection to select any object. Return the
        selected object, otherwise, return None. Restore projection and
        modelview matrices before returning.
        """
        ### NOTE: this code is similar to (and was copied and modified from)
        # GLPane_highlighting_methods.do_glselect_if_wanted, but also differs
        # in significant ways (too much to make it worth merging, unless we
        # decide to merge the differing algorithms as well). It's one of
        # several instances of hit-test code that calls glRenderMode.
        # [bruce 060721/080917 comment]
        wZ = glReadPixelsf(wX, wY, 1, 1, GL_DEPTH_COMPONENT)
        gz = wZ[0][0]

        if gz >= GL_FAR_Z:  # Empty space was clicked
            return None

        pxyz = A(gluUnProject(wX, wY, gz))
        pn = self.out
        pxyz -= 0.0002 * pn
        # Note: if this runs before the model is drawn, this can have an
        # exception "OverflowError: math range error", presumably because
        # appropriate state for gluUnProject was not set up. That doesn't
        # normally happen but can happen due to bugs (no known open bugs
        # of that kind).
        # Sometimes our drawing area can become "stuck at gray",
        # and when that happens, the same exception can occur from this line.
        # Could it be that too many accidental mousewheel scrolls occurred
        # and made the scale unreasonable? (To mitigate, we should prevent
        # those from doing anything unless we have a valid model, and also
        # reset that scale when loading a new model (latter is probably
        # already done, but I didn't check). See also the comments
        # in def wheelEvent.) [bruce 080220 comment]
        dp = -dot(pxyz, pn)

        # Save projection matrix before it's changed.
        glMatrixMode(GL_PROJECTION)
        glPushMatrix()

        current_glselect = (wX, wY, 1, 1)
        self._setup_projection(glselect=current_glselect)

        glSelectBuffer(self.SIZE_FOR_glSelectBuffer)
        glRenderMode(GL_SELECT)
        glInitNames()
        glMatrixMode(GL_MODELVIEW)
        # Save model view matrix before it's changed.
        glPushMatrix()

        # Draw model using glRenderMode(GL_SELECT) as set up above
        try:
            glClipPlane(GL_CLIP_PLANE0, (pn[0], pn[1], pn[2], dp))
            glEnable(GL_CLIP_PLANE0)
            self._drawModel_using_DrawingSets()
        except:
            #bruce 080917 fixed predicted bugs in this except clause (untested)
            print_compact_traceback(
                "exception in ThumbView._drawModel_using_DrawingSets() during GL_SELECT; ignored; restoring matrices: "
            )
            glDisable(GL_CLIP_PLANE0)
            glMatrixMode(GL_PROJECTION)
            glPopMatrix()
            glMatrixMode(GL_MODELVIEW)
            glPopMatrix()
            glRenderMode(GL_RENDER)
            return None
        else:
            glDisable(GL_CLIP_PLANE0)
            # Restore model/view matrix
            glPopMatrix()

        # Restore projection matrix and set matrix mode to Model/View
        glMatrixMode(GL_PROJECTION)
        glPopMatrix()
        glMatrixMode(GL_MODELVIEW)

        glFlush()

        hit_records = list(glRenderMode(GL_RENDER))
        ## print "%d hits" % len(hit_records)
        for (near, far, names) in hit_records:
            ## print "hit record: near, far, names:", near, far, names
            # note from testing: near/far are too far apart to give actual depth,
            # in spite of the 1-pixel drawing window (presumably they're vertices
            # taken from unclipped primitives, not clipped ones).
            ### REVIEW: this just returns the first candidate object found.
            # The clip plane may restrict the set of candidates well enough to
            # make sure that's the right one, but this is untested and unreviewed.
            # (And it's just my guess that that was Huaicai's intention in
            #  setting up clipping, since it's not documented. I'm guessing that
            #  the plane is just behind the hitpoint, but haven't confirmed this.)
            # [bruce 080917 comment]
            if names:
                name = names[-1]
                assy = self.assy
                obj = assy and assy.object_for_glselect_name(name)
                #k should always return an obj
                return obj
        return None  # from ThumbView.select
Exemplo n.º 51
0
 def screenToReal(self, x, y):
     x, y, z = gluUnProject(x, self.size[1] - y, 0)
     return x,y