def draw(self):
     planes = self.planes
     assert len(planes) <= len(GL_CLIP_PLANE_table), \
            "no more than %d clipping planes are permitted" % \
            len(GL_CLIP_PLANE_table)
         # even if your OpenGL driver supports more -- no sense writing an expr that not everyone can draw!
         #    WARNING: this ignores the issue of nested Clipped constructs!
         # In fact, it assumes nothing in thing or above self uses any clipping planes.
         # (Not merely "assumes no more than 6 in all", because we hardcode which specific planes to use!)
         #    Worse, we don't even detect the error. Fixing the behavior is just as easy
         # (let graphical dynenv (self.env) know which planes are still available to any drawing-kid), so do that instead. ##e
         # Note that we might need to work inside a display list, and therefore we'd need to get the "next plane to use"
         # from an env which stays fixed (or from an env var which is changedtracked), not just from each draw call's caller
         # (i.e. a glpane attr).
     # enable the planes
     for i, plane in zip(range(len(planes)), planes):
         assert len(plane) == 4
         glEnable( GL_CLIP_PLANE_table[i] )
         glClipPlane( GL_CLIP_PLANE_table[i], plane)
     # draw thing
     self.drawkid( self.thing)
     # disable the planes
     for i in range(len(planes)):
         glDisable( GL_CLIP_PLANE_table[i] )
     return
Exemple #2
0
 def draw(self):
     planes = self.planes
     assert len(planes) <= len(GL_CLIP_PLANE_table), \
            "no more than %d clipping planes are permitted" % \
            len(GL_CLIP_PLANE_table)
     # even if your OpenGL driver supports more -- no sense writing an expr that not everyone can draw!
     #    WARNING: this ignores the issue of nested Clipped constructs!
     # In fact, it assumes nothing in thing or above self uses any clipping planes.
     # (Not merely "assumes no more than 6 in all", because we hardcode which specific planes to use!)
     #    Worse, we don't even detect the error. Fixing the behavior is just as easy
     # (let graphical dynenv (self.env) know which planes are still available to any drawing-kid), so do that instead. ##e
     # Note that we might need to work inside a display list, and therefore we'd need to get the "next plane to use"
     # from an env which stays fixed (or from an env var which is changedtracked), not just from each draw call's caller
     # (i.e. a glpane attr).
     # enable the planes
     for i, plane in zip(range(len(planes)), planes):
         assert len(plane) == 4
         glEnable(GL_CLIP_PLANE_table[i])
         glClipPlane(GL_CLIP_PLANE_table[i], plane)
     # draw thing
     self.drawkid(self.thing)
     # disable the planes
     for i in range(len(planes)):
         glDisable(GL_CLIP_PLANE_table[i])
     return
Exemple #3
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
def drawSiCGrid(color, line_type, w, h, up, right):
    """
    Draw SiC grid.
    """
    
    if line_type == NO_LINE:
        return
    
    XLen = sic_uLen * 3.0
    YLen = sic_yU * 2.0
    hw = w/2.0; hh = h/2.0
    i1 = int(floor(-hw/XLen))
    i2 = int(ceil(hw/XLen))
    j1 = int(floor(-hh/YLen))
    j2 = int(ceil(hh/YLen))
    
    glDisable(GL_LIGHTING)
    glColor3fv(color)

    if line_type > 1:
        glEnable(GL_LINE_STIPPLE)
        if line_type == DASHED_LINE:
            glLineStipple (1, 0x00FF)  #  dashed
        elif line_type == DOTTED_LINE:
            glLineStipple (1, 0x0101)  #  dotted
        else:
            print "drawer.drawSiCGrid(): line_type '", line_type, \
                  "' is not valid.  Drawing dashed grid line."
            glLineStipple (1, 0x00FF)  #  dashed
    
    glClipPlane(GL_CLIP_PLANE0, (1.0, 0.0, 0.0, hw))
    glClipPlane(GL_CLIP_PLANE1, (-1.0, 0.0, 0.0, hw))
    glClipPlane(GL_CLIP_PLANE2, (0.0, 1.0, 0.0, hh))
    glClipPlane(GL_CLIP_PLANE3, (0.0, -1.0, 0.0, hh))
    glEnable(GL_CLIP_PLANE0)
    glEnable(GL_CLIP_PLANE1)
    glEnable(GL_CLIP_PLANE2)
    glEnable(GL_CLIP_PLANE3)
     
    glPushMatrix()
    glTranslate(i1*XLen,  j1*YLen, 0.0)
    for i in range(i1, i2):
        glPushMatrix()
        for j in range(j1, j2):
            glCallList(SiCGridList)
            glTranslate(0.0, YLen, 0.0)
        glPopMatrix()
        glTranslate(XLen, 0.0, 0.0)
    glPopMatrix()
    
    glDisable(GL_CLIP_PLANE0)
    glDisable(GL_CLIP_PLANE1)
    glDisable(GL_CLIP_PLANE2)
    glDisable(GL_CLIP_PLANE3)
        
    if line_type > 1:
        glDisable (GL_LINE_STIPPLE)

    xpos, ypos = hw, 0.0
    f3d = Font3D(xpos=xpos, ypos=ypos, right=right, up=up,
                 rot90=False, glBegin=False)
    for j in range(j1, j2):
        yoff = j * YLen
        if -hh < yoff + ypos < hh:
            f3d.drawString("%-.4g" % yoff, color=color, yoff=yoff)

    xpos, ypos = 0.0, hh
    f3d = Font3D(xpos=xpos, ypos=ypos, right=right, up=up,
                 rot90=True, glBegin=False)
    for i in range(2*i1, 2*i2):
        yoff = i * (XLen/2)
        if -hw < yoff + xpos < hw:
            f3d.drawString("%-.4g" % yoff, color=color, yoff=yoff)
    
    glEnable(GL_LIGHTING)
    return
Exemple #5
0
 def set_clip_plane(self, index, coefficients):
     glEnable(self.clip_constants[index])
     glClipPlane(self.clip_constants[index], coefficients)
Exemple #6
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
def drawSiCGrid(color, line_type, w, h, up, right):
    """
    Draw SiC grid.
    """

    if line_type == NO_LINE:
        return

    XLen = sic_uLen * 3.0
    YLen = sic_yU * 2.0
    hw = w / 2.0
    hh = h / 2.0
    i1 = int(floor(-hw / XLen))
    i2 = int(ceil(hw / XLen))
    j1 = int(floor(-hh / YLen))
    j2 = int(ceil(hh / YLen))

    glDisable(GL_LIGHTING)
    glColor3fv(color)

    if line_type > 1:
        glEnable(GL_LINE_STIPPLE)
        if line_type == DASHED_LINE:
            glLineStipple(1, 0x00FF)  #  dashed
        elif line_type == DOTTED_LINE:
            glLineStipple(1, 0x0101)  #  dotted
        else:
            print "drawer.drawSiCGrid(): line_type '", line_type, \
                  "' is not valid.  Drawing dashed grid line."
            glLineStipple(1, 0x00FF)  #  dashed

    glClipPlane(GL_CLIP_PLANE0, (1.0, 0.0, 0.0, hw))
    glClipPlane(GL_CLIP_PLANE1, (-1.0, 0.0, 0.0, hw))
    glClipPlane(GL_CLIP_PLANE2, (0.0, 1.0, 0.0, hh))
    glClipPlane(GL_CLIP_PLANE3, (0.0, -1.0, 0.0, hh))
    glEnable(GL_CLIP_PLANE0)
    glEnable(GL_CLIP_PLANE1)
    glEnable(GL_CLIP_PLANE2)
    glEnable(GL_CLIP_PLANE3)

    glPushMatrix()
    glTranslate(i1 * XLen, j1 * YLen, 0.0)
    for i in range(i1, i2):
        glPushMatrix()
        for j in range(j1, j2):
            glCallList(SiCGridList)
            glTranslate(0.0, YLen, 0.0)
        glPopMatrix()
        glTranslate(XLen, 0.0, 0.0)
    glPopMatrix()

    glDisable(GL_CLIP_PLANE0)
    glDisable(GL_CLIP_PLANE1)
    glDisable(GL_CLIP_PLANE2)
    glDisable(GL_CLIP_PLANE3)

    if line_type > 1:
        glDisable(GL_LINE_STIPPLE)

    xpos, ypos = hw, 0.0
    f3d = Font3D(xpos=xpos,
                 ypos=ypos,
                 right=right,
                 up=up,
                 rot90=False,
                 glBegin=False)
    for j in range(j1, j2):
        yoff = j * YLen
        if -hh < yoff + ypos < hh:
            f3d.drawString("%-.4g" % yoff, color=color, yoff=yoff)

    xpos, ypos = 0.0, hh
    f3d = Font3D(xpos=xpos,
                 ypos=ypos,
                 right=right,
                 up=up,
                 rot90=True,
                 glBegin=False)
    for i in range(2 * i1, 2 * i2):
        yoff = i * (XLen / 2)
        if -hw < yoff + xpos < hw:
            f3d.drawString("%-.4g" % yoff, color=color, yoff=yoff)

    glEnable(GL_LIGHTING)
    return
    def _enable_stereo(self,
                       stereo_image,
                       preserve_colors=False,
                       no_clipping=False):
        """
        Enables stereo rendering.        

        This should be called before entering a drawing phase
        and should be accompanied by a self._disable_stereo call
        after the drawing for that phase.
        
        These methods push a modelview matrix on the matrix stack
        and modify the matrix.

        @param stereo_image: Indicates which stereo image is being drawn
                             (-1 == left, 1 == right, 0 == stereo is disabled)
        
        @param preserve_colors: Disable color mask manipulations,
                                which normally occur in anaglyph mode.
                                (Also disable depth buffer clearing
                                 for 2nd image, which occurs then.)

        @param no_clipping: Disable clipping, which normally occurs in
                            side-by-side mode.
        """
        if not self.stereo_enabled:
            return

        glPushAttrib(GL_TRANSFORM_BIT)

        stereo_mode = self.stereo_mode
        stereo_separation = self.stereo_separation
        stereo_angle = self.stereo_angle

        # push the modelview matrix on the stack
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()

        separation = stereo_separation * self.scale
        angle = stereo_angle  # might be modified below

        if stereo_mode <= 2:
            # side-by-side stereo mode
            # clip left or right image
            # reset the modelview matrix

            if not no_clipping:
                glPushMatrix()  # Note: this might look redundant with the
                # glPushMatrix above, but removing it (and its glPopMatrix
                # 10 lines below) causes a bug (no image visible).
                # Guess: it's needed so the glLoadIdentity needed to set up
                # the clipping plane just below has only a temporary effect.
                # [bruce 080911 comment]
                glLoadIdentity()
                if stereo_image == -1:
                    clip_eq = (-1.0, 0.0, 0.0, 0.0)
                else:
                    clip_eq = (1.0, 0.0, 0.0, 0.0)
                # using GL_CLIP_PLANE5 for stereo clipping
                glClipPlane(GL_CLIP_PLANE5, clip_eq)
                glEnable(GL_CLIP_PLANE5)
                glPopMatrix()

            # for cross-eyed mode, exchange left and right views
            if stereo_mode == 2:
                angle *= -1

            # translate images for side-by-side stereo
            glTranslatef(separation * stereo_image * self.right[0],
                         separation * stereo_image * self.right[1],
                         separation * stereo_image * self.right[2])

            # rotate the stereo image ("toe-in" method)
            glRotatef(angle * stereo_image, self.up[0], self.up[1], self.up[2])

        else:
            # Anaglyphs stereo mode - Red plus Blue, Cyan, or Green image.
            angle *= 0.5
            if not preserve_colors:
                if stereo_image == -1:
                    # red image
                    glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE)
                else:
                    # clear depth buffer to combine red/blue images
                    # REVIEW: this would cause bugs in the predraw_glselectdict code
                    # used for depth-testing selobj candidates. Maybe it does
                    # not happen then? The name of the flag 'preserve_colors'
                    # does not say anything about preserving depths.
                    # Anyway, it *does* happen then, so I think there is a bug.
                    # Also, remind me, what's the 4th arg to glColorMask?
                    # [bruce 080911 comment]
                    #
                    # piotr 080911 response: You are right. This technically
                    # causes a bug: the red image is not highlightable,
                    # but actually when using anaglyph glasses, the bug is not
                    # noticeable, as both red and blue images converge.
                    # The bug becomes noticeable if user tries to highlight an
                    # object without wearing the anaglyph glasses.
                    # At this point, I think we can either leave it as it is,
                    # or consider implementing anaglyph stereo by using
                    # OpenGL alpha blending.
                    # Also, I am not sure if highlighting problem is the only bug
                    # that is caused by clearing the GL_DEPTH_BUFFER_BIT.
                    glClear(GL_DEPTH_BUFFER_BIT)
                    if stereo_mode == 3:
                        # blue image
                        glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE)
                    elif stereo_mode == 4:
                        # cyan image
                        glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE)
                    elif stereo_mode == 5:
                        # green image
                        glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE)

            # rotate the stereo image ("toe-in" method)
            glRotatef(angle * stereo_image, self.up[0], self.up[1], self.up[2])
        return
    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
Exemple #10
0
 def set_clip_plane(self, index, coefficients):
     glEnable(self.clip_constants[index])
     glClipPlane(self.clip_constants[index], coefficients)
    def _enable_stereo(self, stereo_image, preserve_colors = False, no_clipping = False):
        """
        Enables stereo rendering.

        This should be called before entering a drawing phase
        and should be accompanied by a self._disable_stereo call
        after the drawing for that phase.

        These methods push a modelview matrix on the matrix stack
        and modify the matrix.

        @param stereo_image: Indicates which stereo image is being drawn
                             (-1 == left, 1 == right, 0 == stereo is disabled)

        @param preserve_colors: Disable color mask manipulations,
                                which normally occur in anaglyph mode.
                                (Also disable depth buffer clearing
                                 for 2nd image, which occurs then.)

        @param no_clipping: Disable clipping, which normally occurs in
                            side-by-side mode.
        """
        if not self.stereo_enabled:
            return

        glPushAttrib(GL_TRANSFORM_BIT)

        stereo_mode = self.stereo_mode
        stereo_separation = self.stereo_separation
        stereo_angle = self.stereo_angle

        # push the modelview matrix on the stack
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()

        separation = stereo_separation * self.scale
        angle = stereo_angle # might be modified below

        if stereo_mode <= 2:
            # side-by-side stereo mode
            # clip left or right image
            # reset the modelview matrix

            if not no_clipping:
                glPushMatrix() # Note: this might look redundant with the
                    # glPushMatrix above, but removing it (and its glPopMatrix
                    # 10 lines below) causes a bug (no image visible).
                    # Guess: it's needed so the glLoadIdentity needed to set up
                    # the clipping plane just below has only a temporary effect.
                    # [bruce 080911 comment]
                glLoadIdentity()
                if stereo_image == -1:
                    clip_eq = (-1.0, 0.0, 0.0, 0.0)
                else:
                    clip_eq = ( 1.0, 0.0, 0.0, 0.0)
                # using GL_CLIP_PLANE5 for stereo clipping
                glClipPlane(GL_CLIP_PLANE5, clip_eq)
                glEnable(GL_CLIP_PLANE5)
                glPopMatrix()

            # for cross-eyed mode, exchange left and right views
            if stereo_mode == 2:
                angle *= -1

            # translate images for side-by-side stereo
            glTranslatef(separation * stereo_image * self.right[0],
                         separation * stereo_image * self.right[1],
                         separation * stereo_image * self.right[2])

            # rotate the stereo image ("toe-in" method)
            glRotatef(angle * stereo_image,
                      self.up[0],
                      self.up[1],
                      self.up[2])

        else:
            # Anaglyphs stereo mode - Red plus Blue, Cyan, or Green image.
            angle *= 0.5
            if not preserve_colors:
                if stereo_image == -1:
                    # red image
                    glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE)
                else:
                    # clear depth buffer to combine red/blue images
                    # REVIEW: this would cause bugs in the predraw_glselectdict code
                    # used for depth-testing selobj candidates. Maybe it does
                    # not happen then? The name of the flag 'preserve_colors'
                    # does not say anything about preserving depths.
                    # Anyway, it *does* happen then, so I think there is a bug.
                    # Also, remind me, what's the 4th arg to glColorMask?
                    # [bruce 080911 comment]
                    #
                    # piotr 080911 response: You are right. This technically
                    # causes a bug: the red image is not highlightable,
                    # but actually when using anaglyph glasses, the bug is not
                    # noticeable, as both red and blue images converge.
                    # The bug becomes noticeable if user tries to highlight an
                    # object without wearing the anaglyph glasses.
                    # At this point, I think we can either leave it as it is,
                    # or consider implementing anaglyph stereo by using
                    # OpenGL alpha blending.
                    # Also, I am not sure if highlighting problem is the only bug
                    # that is caused by clearing the GL_DEPTH_BUFFER_BIT.
                    glClear(GL_DEPTH_BUFFER_BIT)
                    if stereo_mode == 3:
                        # blue image
                        glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE)
                    elif stereo_mode == 4:
                        # cyan image
                        glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE)
                    elif stereo_mode == 5:
                        # green image
                        glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE)

            # rotate the stereo image ("toe-in" method)
            glRotatef(angle * stereo_image,
                      self.up[0],
                      self.up[1],
                      self.up[2])
        return
    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