Exemple #1
0
    def __init__(self):
        """
        The init function
        """
        debugMsg("Called Scene.__init__()")
        BaseScene.__init__(self)

        self.renderer = Renderer()

        self.xSize = 640
        self.ySize = 480

        self.objectList = []
Exemple #2
0
class Scene(BaseScene):
    """
    The main object controlling the scene.
    
    Scene object methods and classes overriding the BaseScene class.
    """

    def __init__(self):
        """
        The init function
        """
        debugMsg("Called Scene.__init__()")
        BaseScene.__init__(self)

        self.renderer = Renderer()

        self.xSize = 640
        self.ySize = 480

        self.objectList = []

    def add(self, obj):
        """
        Add a new item to the scene

        @param obj: The object to add to the scene
        @type obj: object
        """
        debugMsg("Called Scene.add()")

        if obj is None:
            raise ValueError, "You must specify an object to add"

        self.objectList.append(obj)

        return

    def place(self, obj):
        """
        Place an object within a scene

        @param obj: The object to place within the scene
        @type obj: object
        """
        debugMsg("Called Scene.place()")

        if obj is None:
            raise ValueError, "You must specify an object to place"

        return

    def render(self, pause=False, interactive=False, save=False):
        """
        Render (or re-render) the scene
        
        Render the scene, either to screen, or to a buffer waiting for a save

        @param pause: Flag to wait at end of script evaluation for user input
        @type pause: boolean

        @param interactive: Whether or not to have interactive use of the output
        @type interactive: boolean

        @param save: Whether or not to save the output when render
        @type save: boolean
        """
        debugMsg("Called Scene.render()")
        renderer = self.renderer

        # I don't yet know where to put this, but just to get stuff going...
        renderer.runString("# Scene.render()")

        # if saving to file, try not to render to the screen
        # this needs to be done BEFORE setting up the renderer
        if save:
            evalString = "_factGraphics = vtk.vtkGraphicsFactory()\n"
            evalString += "_factGraphics.SetUseMesaClasses(1)\n"
            evalString += "_factImage = vtk.vtkImagingFactory()\n"
            evalString += "_factImage.SetUseMesaClasses(1)\n"
            renderer.addToInitStack(evalString)
        else:
            #evalString = "_factGraphics = vtk.vtkGraphicsFactory()\n"
            #evalString += "_factGraphics.SetUseMesaClasses(0)\n"
            #evalString += "_factImage = vtk.vtkImagingFactory()\n"
            #evalString += "_factImage.SetUseMesaClasses(0)\n"
            #renderer.addToInitStack(evalString)
            pass

        # set up the renderer and render window
        renderer.addToInitStack("_renderer = vtk.vtkRenderer()")
        # this next line should only be done if we have an active display
        renderer.addToInitStack("_renderWindow = vtk.vtkRenderWindow()")
        renderer.addToInitStack("_renderWindow.AddRenderer(_renderer)")
        evalString = "_renderWindow.SetSize(%d,%d)" % \
                (renderer.renderWindowWidth,renderer.renderWindowHeight)
        renderer.addToInitStack(evalString)
        renderer.addToInitStack("_renderer.SetBackground(1,1,1)")

        if save:
            evalString = "_renderWindow.OffScreenRenderingOn()\n"
            renderer.runString(evalString)

        # set up the lookup table properly
        # we reverse the sense of the normal vtk lookup table as then red
        # refers to high values and blue to low values which seems more
        # natural and is more standard
        # NOTE: we will probably need to make this an object at some stage
        # so that we can set the ramp of the reference lookup table
        evalString = "_lut = vtk.vtkLookupTable()\n"
        evalString += "_refLut = vtk.vtkLookupTable()\n"
        evalString += "_lut.Build()\n"
        evalString += "_refLut.Build()\n"
        evalString += "for _i in range(256):\n"
        evalString += "    _lut.SetTableValue(_i, "
        evalString += "_refLut.GetTableValue(255-_i))"
        renderer.runString(evalString)

        # if we have an interactive display, put some of the relevant code in
        if interactive:
            renderer.runString(\
                    "_iRenderer = vtk.vtkRenderWindowInteractor()")
            renderer.runString(\
                    "_iRenderer.SetRenderWindow(_renderWindow)")

        # get all objects in the scene to render themselves
        for obj in self.objectList:
            obj.render()

        # render the scene total
        renderer.runString("_renderWindow.Render()")

        # if interactive, start up the render window interactor
        if interactive:
            renderer.runString("_iRenderer.Start()")

        # write it
        if save:
            self.renderer.runString("_outWriter.Write()")

        # add some code to pause after rendering if asked to
        if pause:
            renderer.runString("raw_input(\"Press enter to continue\")")

        # prepend the init stack to the eval stack
        self.renderer._evalStack = self.renderer._initStack + \
                self.renderer._evalStack

        # optionally print out the evaluation stack to make sure we're doing
        # the right thing
        debugMsg("Here is the evaluation stack")
        debugMsg(60*"#")
        debugMsg(renderer.getEvalStack())
        debugMsg(60*"#")

        # execute the eval stack
        evalStack = renderer.getEvalStack()
        exec evalStack in self.renderer.renderDict

        # flush the evaluation stack
        debugMsg("Flushing evaluation stack")
        renderer.resetEvalStack()

        return

    def save(self, fname, format):
        """
        Save the scene to a file

        Possible formats are:
            - Postscript
            - PNG
            - JPEG
            - TIFF
            - BMP
            - PNM

        @param fname: Name of output file
        @type fname: string

        @param format: Graphics format of output file
        @type format: Image object or string
        """
        debugMsg("Called Scene.save()")
        self.renderer.runString("# Scene.save()")

        # if the format is passed in as a string or object, react
        # appropriately
        import types
        if type(format) is types.StringType:
            fmt = format.lower()
        else:
            fmt = format.format

        # need to pass the render window through a filter to an image object
        self.renderer.runString(
                "_win2imgFilter = vtk.vtkWindowToImageFilter()")
        self.renderer.runString("_win2imgFilter.SetInput(_renderWindow)")

        # set the output format
        if fmt == "ps":
            self.renderer.runString(
                    "_outWriter = vtk.vtkPostScriptWriter()")
        elif fmt == "png":
            self.renderer.runString(
                    "_outWriter = vtk.vtkPNGWriter()")
        elif fmt == "jpeg" or fmt == "jpg":
            self.renderer.runString(
                    "_outWriter = vtk.vtkJPEGWriter()")
        elif fmt == "tiff" or fmt == "tif":
            self.renderer.runString(
                    "_outWriter = vtk.vtkTIFFWriter()")
        elif fmt == "bmp":
            self.renderer.runString(
                    "_outWriter = vtk.vtkBMPWriter()")
        elif fmt == "pnm":
            self.renderer.runString(
                    "_outWriter = vtk.vtkPNMWriter()")
        else:
            raise ValueError, "Unknown graphics format.  I got %s" % fmt

        # set stuff up to write
        self.renderer.runString(
                "_outWriter.SetInput(_win2imgFilter.GetOutput())")
        evalString = "_outWriter.SetFileName(\"%s\")" % fname
        self.renderer.runString(evalString)
        
        # rerender the scene to get the output
        self.render(save=True)

        return

    # set up an alias for the save method
    write = save

    def setBackgroundColor(self, *color):
        """
        Sets the background color of the Scene

        @param color: The color to set the background to.  Can be RGB or CMYK
        @type color: tuple
        """
        debugMsg("Called Scene.setBackgroundColor()")

        # pity this code doesn't work....
        # need to check on the values given in the *color array.
        # if they're greater than 1, scale so that the largest is 1
        #maxColor = None
        #for i in range(len(color)):
            #if color[i] > 1:
                #maxColor = color[i]
                #print maxColor
#
        ## if a maximum colour is found, then scale the colours
        #if maxColor is not None:
            #for i in range(len(color)):
                #color[i] = color[i]/maxColor
        
        # if color is of length 3, then we have rgb
        # if length is 4 then cmyk
        # if length is 1 then greyscale
        # otherwise barf
        if len(color) == 3:
            # ok, using rgb
            # probably should use a Color object or something
            # this will do in the meantime
            evalString = "_renderer.SetBackground(%f,%f,%f)" % \
                    (color[0], color[1], color[2])
            self.renderer.runString(evalString)
        else:
            raise ValueError, "Sorry, only RGB color is supported at present"

        return

    def getBackgroundColor(self):
        """
        Gets the current background color setting of the Scene
        """
        debugMsg("Called Scene.getBackgroundColor()")
        return

    def setSize(self, xSize, ySize):
        """
        Sets the size of the scene.

        This size is effectively the renderer window size.

        @param xSize: the size to set the x dimension
        @type xSize: float

        @param ySize: the size to set the y dimension
        @type ySize: float
        """
        debugMsg("Called Scene.setSize()")

        self.xSize = xSize
        self.ySize = ySize
        
        return

    def getSize(self):
        """
        Gets the current size of the scene

        This size is effectively the renderer window size.  Returns a tuple
        of the x and y dimensions respectively, in pixel units(??).
        """
        debugMsg("Called Scene.getSize()")
        return (self.xSize, self.ySize)