def loadProjection(self,force=False,pick=None):
        """Load the projection/perspective matrix.

        The caller will have to setup the correct GL environment beforehand.
        No need to set matrix mode though. This function will switch to
        GL_PROJECTION mode before loading the matrix, and go back to
        GL_MODELVIEW mode on exit.

        A pick region can be defined to use the camera in picking mode.
        pick defines the picking region center and size (x,y,w,h).

        This function does it best at autodetecting changes in the lens
        settings, and will only reload the matrix if such changes are
        detected. You can optionally force loading the matrix.
        """
        if self.lensChanged or force:
            GL.glMatrixMode(GL.GL_PROJECTION)
            GL.glLoadIdentity()
            if pick:
                #print 'PICK: %s' % str(pick)
                GLU.gluPickMatrix(*pick)
            if self.perspective:
                GLU.gluPerspective(self.fovy,self.aspect,self.near,self.far)
            else:
                #print "FOVY: %s" % self.fovy
                top = tand(self.fovy*0.5) * self.dist
                bottom = -top
                right = top * self.aspect
                left = bottom * self.aspect
                #print "Ortho %s" % [left,right,bottom,top,self.near,self.far]
                GL.glOrtho(left,right,bottom,top,self.near,self.far)
            GL.glMatrixMode(GL.GL_MODELVIEW)     
    def setCamera(self,bbox=None,angles=None):
        """Sets the camera looking under angles at bbox.

        This function sets the camera angles and adjusts the zooming.
        The camera distance remains unchanged.
        
        If a bbox is specified, the camera will be zoomed to make the whole
        bbox visible.
        If no bbox is specified, the current scene bbox will be used.
        If no current bbox has been set, it will be calculated as the
        bbox of the whole scene.

        If no camera angles are given, the camera orientation is kept.
        angles can be a set of 3 angles, or a string
        """
        self.makeCurrent()
        # go to a distance to have a good view with a 45 degree angle lens
        if bbox is not None:
            self.setBbox(bbox)
        #GD.debug("USING BBOX: %s" % self.bbox)
        X0,X1 = self.bbox
        center = 0.5*(X0+X1)
        # calculating the bounding circle: this is rather conservative
        self.camera.setCenter(*center)
        if type(angles) is str:
            angles = self.view_angles.get(angles)
        if angles is not None:
            try:
                self.camera.setAngles(angles)
            except:
                raise ValueError,'Invalid view angles specified'
        # Currently, we keep the default fovy/aspect
        # and change the camera distance to focus
        fovy = self.camera.fovy
        #GD.debug("FOVY: %s" % fovy)
        self.camera.setLens(fovy,self.aspect)
        # Default correction is sqrt(3)
        correction = float(GD.cfg.get('gui/autozoomfactor',1.732))
        tf = tand(fovy/2.)

        import simple,coords
        bbix = simple.regularGrid(X0,X1,[1,1,1])
        bbix = dot(bbix,self.camera.rot[:3,:3])
        bbox = coords.Coords(bbix).bbox()
        dx,dy = bbox[1][:2] - bbox[0][:2]
        hsize = max(dx,dy/self.aspect)
        offset = abs(bbox[1][2]+bbox[0][2])
        #print "hsize,offset = %s,%s" % (hsize,offset)
        dist = (hsize/tf + offset) / correction
        #print "new dist = %s" % (dist)
        
        if dist == nan or dist == inf:
            GD.debug("DIST: %s" % dist)
            return
        if dist <= 0.0:
            dist = 1.0
        self.camera.setDist(dist)
        self.camera.setClip(0.01*dist,100.*dist)
        self.camera.resetArea()
Exemple #3
0
    def setCamera(self,bbox=None,angles=None):
        """Sets the camera looking under angles at bbox.

        This function sets the camera parameters to view the specified
        bbox volume from the specified viewing direction.

        Parameters:

        - `bbox`: the bbox of the volume looked at
        - `angles`: the camera angles specifying the viewing direction.
          It can also be a string, the key of one of the predefined
          camera directions

        If no angles are specified, the viewing direction remains constant.
        The scene center (camera focus point), camera distance, fovy and
        clipping planes are adjusted to make the whole bbox viewed from the
        specified direction fit into the screen.

        If no bbox is specified, the following remain constant:
        the center of the scene, the camera distance, the lens opening
        and aspect ratio, the clipping planes. In other words the camera
        is moving on a spherical surface and keeps focusing on the same
        point.

        If both are specified, then first the scene center is set,
        then the camera angles, and finally the camera distance.

        In the current implementation, the lens fovy and aspect are not
        changed by this function. Zoom adjusting is performed solely by
        changing the camera distance.
        """
        #
        # TODO: we should add the rectangle (digital) zooming to
        #       the docstring

        self.makeCurrent()

        # set scene center
        if bbox is not None:
            pf.debug("SETTING BBOX: %s" % self.bbox,pf.DEBUG.DRAW)
            self.setBbox(bbox)

            X0,X1 = self.bbox
            self.camera.focus = 0.5*(X0+X1)

        # set camera angles
        if type(angles) is str:
            angles = self.view_angles.get(angles)
        if angles is not None:
            try:
                self.camera.setAngles(angles)
            except:
                raise ValueError,'Invalid view angles specified'

        # set camera distance and clipping planes
        if bbox is not None:
            # Currently, we keep the default fovy/aspect
            # and change the camera distance to focus
            fovy = self.camera.fovy
            #pf.debug("FOVY: %s" % fovy,pf.DEBUG.DRAW)
            self.camera.setLens(fovy,self.aspect)
            # Default correction is sqrt(3)
            correction = float(pf.cfg.get('gui/autozoomfactor',1.732))
            tf = coords.tand(fovy/2.)

            import simple
            bbix = simple.regularGrid(X0,X1,[1,1,1])
            bbix = dot(bbix,self.camera.rot[:3,:3])
            bbox = coords.Coords(bbix).bbox()
            dx,dy,dz = bbox[1] - bbox[0]
            vsize = max(dx/self.aspect,dy)
            dsize = bbox.dsize()
            offset = dz
            dist = (vsize/tf + offset) / correction

            if dist == nan or dist == inf:
                pf.debug("DIST: %s" % dist,pf.DEBUG.DRAW)
                return
            if dist <= 0.0:
                dist = 1.0
            self.camera.dist = dist

            ## print "vsize,dist = %s, %s" % (vsize,dist)
            ## near,far = 0.01*dist,100.*dist
            ## print "near,far = %s, %s" % (near,far)
            #near,far = dist-1.2*offset/correction,dist+1.2*offset/correction
            near,far = dist-1.0*dsize,dist+1.0*dsize
            # print "near,far = %s, %s" % (near,far)
            #print (0.0001*vsize,0.01*dist,near)
            # make sure near is positive
            near = max(near,0.0001*vsize,0.01*dist,finfo(coords.Float).tiny)
            # make sure far > near
            if far <= near:
                far += finfo(coords.Float).eps
            #print "near,far = %s, %s" % (near,far)
            self.camera.setClip(near,far)
            self.camera.resetArea()
Exemple #4
0
    def setCamera(self, bbox=None, angles=None):
        """Sets the camera looking under angles at bbox.

        This function sets the camera parameters to view the specified
        bbox volume from the specified viewing direction.

        Parameters:

        - `bbox`: the bbox of the volume looked at
        - `angles`: the camera angles specifying the viewing direction.
          It can also be a string, the key of one of the predefined
          camera directions

        If no angles are specified, the viewing direction remains constant.
        The scene center (camera focus point), camera distance, fovy and
        clipping planes are adjusted to make the whole bbox viewed from the
        specified direction fit into the screen.

        If no bbox is specified, the following remain constant:
        the center of the scene, the camera distance, the lens opening
        and aspect ratio, the clipping planes. In other words the camera
        is moving on a spherical surface and keeps focusing on the same
        point.

        If both are specified, then first the scene center is set,
        then the camera angles, and finally the camera distance.

        In the current implementation, the lens fovy and aspect are not
        changed by this function. Zoom adjusting is performed solely by
        changing the camera distance.
        """
        #
        # TODO: we should add the rectangle (digital) zooming to
        #       the docstring

        self.makeCurrent()

        # set scene center
        if bbox is not None:
            pf.debug("SETTING BBOX: %s" % self.bbox, pf.DEBUG.DRAW)
            self.setBbox(bbox)

            X0, X1 = self.bbox
            self.camera.focus = 0.5 * (X0 + X1)

        # set camera angles
        if type(angles) is str:
            angles = self.view_angles.get(angles)
        if angles is not None:
            try:
                self.camera.setAngles(angles)
            except:
                raise ValueError, 'Invalid view angles specified'

        # set camera distance and clipping planes
        if bbox is not None:
            # Currently, we keep the default fovy/aspect
            # and change the camera distance to focus
            fovy = self.camera.fovy
            #pf.debug("FOVY: %s" % fovy,pf.DEBUG.DRAW)
            self.camera.setLens(fovy, self.aspect)
            # Default correction is sqrt(3)
            correction = float(pf.cfg.get('gui/autozoomfactor', 1.732))
            tf = coords.tand(fovy / 2.)

            import simple
            bbix = simple.regularGrid(X0, X1, [1, 1, 1])
            bbix = dot(bbix, self.camera.rot[:3, :3])
            bbox = coords.Coords(bbix).bbox()
            dx, dy, dz = bbox[1] - bbox[0]
            vsize = max(dx / self.aspect, dy)
            dsize = bbox.dsize()
            offset = dz
            dist = (vsize / tf + offset) / correction

            if dist == nan or dist == inf:
                pf.debug("DIST: %s" % dist, pf.DEBUG.DRAW)
                return
            if dist <= 0.0:
                dist = 1.0
            self.camera.dist = dist

            ## print "vsize,dist = %s, %s" % (vsize,dist)
            ## near,far = 0.01*dist,100.*dist
            ## print "near,far = %s, %s" % (near,far)
            #near,far = dist-1.2*offset/correction,dist+1.2*offset/correction
            near, far = dist - 1.0 * dsize, dist + 1.0 * dsize
            # print "near,far = %s, %s" % (near,far)
            #print (0.0001*vsize,0.01*dist,near)
            # make sure near is positive
            near = max(near, 0.0001 * vsize, 0.01 * dist,
                       finfo(coords.Float).tiny)
            # make sure far > near
            if far <= near:
                far += finfo(coords.Float).eps
            #print "near,far = %s, %s" % (near,far)
            self.camera.setClip(near, far)
            self.camera.resetArea()