renderViewInteractiveRenderCmd.cpp

//-
// ==========================================================================
// Copyright 1995,2006,2008 Autodesk, Inc. All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk
// license agreement provided at the time of installation or download,
// or which otherwise accompanies this software in either electronic
// or hard copy form.
// ==========================================================================
//+

#include <maya/MSimple.h>
#include <maya/MIOStream.h>
#include <maya/MRenderView.h>
#include <maya/M3dView.h>
#include <math.h>
#include <maya/MSyntax.h>
#include <maya/MArgDatabase.h>

//
//      renderViewInteractiveRender command declaration
//
class renderViewInteractiveRender : public MPxCommand 
{                                                       
public:                                 
        renderViewInteractiveRender() {};
        ~renderViewInteractiveRender() {};

        virtual MStatus doIt ( const MArgList& );
        
        static void*    creator();
        
        static MSyntax  newSyntax();
        MStatus parseSyntax (MArgDatabase &argData);

        static const char * cmdName;

        private:

        RV_PIXEL evaluate(int x, int y) const;

        bool fullRefresh;
        bool immediateRefresh;
        bool doNotClearBackground;
        bool verbose;
        double radius;
        unsigned int size[2];
        unsigned int tileSize[2];
        unsigned int numberLoops;
        RV_PIXEL color1;
        RV_PIXEL color2;
};

static const char * kVerbose                                    = "-v";
static const char * kVerboseLong                                = "-verbose";
static const char * kDoNotClearBackground               = "-b";
static const char * kDoNotClearBackgroundLong   = "-background";
static const char * kRadius                                             = "-r";
static const char * kRadiusLong                                 = "-radius";
static const char * kSizeX                                              = "-sx";
static const char * kSizeXLong                                  = "-sizeX";
static const char * kSizeY                                              = "-sy";
static const char * kSizeYLong                                  = "-sizeY";
static const char * kSizeTileX                                  = "-tx";
static const char * kSizeTileXLong                              = "-sizeTileX";
static const char * kSizeTileY                                  = "-ty";
static const char * kSizeTileYLong                              = "-sizeTileY";
static const char * kNumberLoops                                = "-nl";
static const char * kNumberLoopsLong                    = "-numberLoops";
static const char * kImmediateRefresh                   = "-ir";
static const char * kImmediateRefreshLong               = "-immediateRefresh";
static const char * kFullRefresh                                = "-fr";
static const char * kFullRefreshLong                    = "-fullRefresh";

const char * renderViewInteractiveRender::cmdName = "renderViewInteractiveRender";

void* renderViewInteractiveRender::creator()                                    
{
        return new renderViewInteractiveRender;
}                                                                                                       

MSyntax renderViewInteractiveRender::newSyntax()
{
        MStatus status;
        MSyntax syntax;

        syntax.addFlag(kDoNotClearBackground, kDoNotClearBackgroundLong);
        CHECK_MSTATUS_AND_RETURN(status, syntax);

        syntax.addFlag(kVerbose, kVerboseLong);
        CHECK_MSTATUS_AND_RETURN(status, syntax);

        syntax.addFlag(kImmediateRefresh, kImmediateRefreshLong);
        CHECK_MSTATUS_AND_RETURN(status, syntax);

        syntax.addFlag(kFullRefresh, kFullRefreshLong);
        CHECK_MSTATUS_AND_RETURN(status, syntax);

        syntax.addFlag(kRadius, kRadiusLong, MSyntax::kDouble);
        CHECK_MSTATUS_AND_RETURN(status, syntax);

        syntax.addFlag(kSizeX, kSizeXLong, MSyntax::kLong);
        CHECK_MSTATUS_AND_RETURN(status, syntax);

        syntax.addFlag(kSizeY, kSizeYLong, MSyntax::kLong);
        CHECK_MSTATUS_AND_RETURN(status, syntax);

        syntax.addFlag(kSizeTileX, kSizeTileXLong, MSyntax::kLong);
        CHECK_MSTATUS_AND_RETURN(status, syntax);

        syntax.addFlag(kSizeTileY, kSizeTileYLong, MSyntax::kLong);
        CHECK_MSTATUS_AND_RETURN(status, syntax);

        syntax.addFlag(kNumberLoops, kNumberLoopsLong, MSyntax::kLong);
        CHECK_MSTATUS_AND_RETURN(status, syntax);

        return syntax;
}

//
// Description:
//              Read the values of the additionnal flags for this command.
//
MStatus renderViewInteractiveRender::parseSyntax (MArgDatabase &argData)
{
        // Get the flag values, otherwise the default values are used.
        doNotClearBackground = argData.isFlagSet( kDoNotClearBackground );
        verbose = argData.isFlagSet( kVerbose );
        fullRefresh = argData.isFlagSet( kFullRefresh );
        immediateRefresh = argData.isFlagSet( kImmediateRefresh );

        radius = 50.;                                                   // pattern frequency, in pixels
        if (argData.isFlagSet( kRadius ))
                argData.getFlagArgument(kRadius, 0, radius);

        size[0] = 640;
        size[1] = 480;
        if (argData.isFlagSet( kSizeX ))
                argData.getFlagArgument(kSizeX, 0, size[0]);
        if (argData.isFlagSet( kSizeY ))
                argData.getFlagArgument(kSizeY, 0, size[1]);

        tileSize[0] = 16;
        tileSize[1] = 16;
        if (argData.isFlagSet( kSizeTileX ))
                argData.getFlagArgument(kSizeTileX, 0, tileSize[0]);
        if (argData.isFlagSet( kSizeTileY ))
                argData.getFlagArgument(kSizeTileY, 0, tileSize[1]);

        numberLoops = 10;
        if (argData.isFlagSet( kNumberLoops ))
                argData.getFlagArgument(kNumberLoops, 0, numberLoops);

        return MS::kSuccess;
}

//
// Description:
//              register the command
//
MStatus initializePlugin( MObject obj )                 
{                                                                                                                       
        MFnPlugin       plugin( obj, PLUGIN_COMPANY, "4.5" );   
        MStatus         stat;                                                                           
        stat = plugin.registerCommand(  renderViewInteractiveRender::cmdName,
                                                                        renderViewInteractiveRender::creator,
                                                                        renderViewInteractiveRender::newSyntax);        
        if ( !stat )                                                                                            
                stat.perror( "registerCommand" );                                                       
        return stat;                                                                                            
}                                                                                                                               

//
// Description:
//              unregister the command
//
MStatus uninitializePlugin( MObject obj )                                               
{                                                                                                                               
        MFnPlugin       plugin( obj );                                                                  
        MStatus         stat;                                                                                   
        stat = plugin.deregisterCommand( renderViewInteractiveRender::cmdName );
        if ( !stat )                                                                    
                stat.perror( "deregisterCommand" );                     
        return stat;                                                                    
}

RV_PIXEL renderViewInteractiveRender::evaluate(int x, int y) const
//
//      Description:
//              Generates a simple procedural circular pattern to be sent to the 
//              Render View.
//
//      Arguments:
//              x, y - coordinates in the current tile (the pattern is centred 
//                         around (0,0) ).
//
//      Return Value:
//              An RV_PIXEL structure containing the colour of pixel (x,y).
//
{
        double distance = sqrt(double((x*x) + (y*y))) / radius;
        float percent = (float)(cos(distance*2*3.1415927)/2.+.5);

        RV_PIXEL pixel;
        pixel.r = color1.r * percent + color2.r * (1-percent);
        pixel.g = color1.g * percent + color2.g * (1-percent);
        pixel.b = color1.b * percent + color2.b * (1-percent);
        pixel.a = 255.0f;

        return pixel;
}

MStatus renderViewInteractiveRender::doIt( const MArgList& args )
//
//      Description:
//              Implements the MEL renderViewInteractiveRender command. This command
//              Draws a 640x480 tiled pattern of circles into Maya's Render
//              View window.
//
//      Arguments:
//              args - The argument list that was passed to the command from MEL.
//
//      Return Value:
//              MS::kSuccess - command succeeded
//              MS::kFailure - command failed (returning this value will cause the 
//                     MEL script that is being run to terminate unless the
//                     error is caught using a "catch" statement.
//
{
        MStatus stat = MS::kSuccess;

        // Check if the render view exists. It should always exist, unless
        // Maya is running in batch mode.
        //
        if (!MRenderView::doesRenderEditorExist())
        {
                displayError( 
                        "Cannot renderViewInteractiveRender in batch render mode.\n"
                        "Run in interactive mode, so that the render editor exists." );
                return MS::kFailure;
        }
        
        // get optional flags
        MArgDatabase argData( syntax(), args );
        parseSyntax( argData );

        // We'll render a 640x480 image.  Tell the Render View to get ready
        // to receive 640x480 pixels of data.
        //
        unsigned int image_width = size[0], image_height = size[1];
        if (MRenderView::startRender( image_width, image_height, 
                                                                  doNotClearBackground, 
                                                                  immediateRefresh) != MS::kSuccess)
        {
                displayError("renderViewInteractiveRender: error occured in startRender.");
                return MS::kFailure;
        }

        // The image will be composed of tiles consisting of circular patterns.
        //

        // Draw each tile
        //
        static float colors[] = { 255, 150,  69, 
                                                          255,  84, 112,
                                                          255,  94, 249,
                                                           86,  62, 255,
                                                           46, 195, 255,
                                                          56, 255, 159,
                                                          130, 255, 64 };
        int indx1 = 0;
        int indx2 = 3*3;

        RV_PIXEL* pixels = new RV_PIXEL[tileSize[0] * tileSize[1]];
        for (unsigned int loopId = 0 ; loopId < numberLoops ; loopId++ )
        {
                color1.r = colors[indx1]; 
                color1.g = colors[indx1+1]; 
                color1.b = colors[indx1+2];
                color1.a = 255;
                indx1 += 3; if (indx1 >= 21) indx1 -= 21;

                color2.r = colors[indx2]; 
                color2.g = colors[indx2+1]; 
                color2.b = colors[indx2+2]; 
                color2.a = 255;
                indx2 += 6; if (indx2 >= 21) indx2 -= 21;

                for (unsigned int min_y = 0; min_y < size[1] ; min_y += tileSize[1] )
                {
                        unsigned int max_y = min_y + tileSize[1] - 1;
                        if (max_y >= size[1]) max_y = size[1]-1;

                        for (unsigned int min_x = 0; min_x < size[0] ; min_x += tileSize[0] )
                        {
                                unsigned int max_x = min_x + tileSize[0] - 1;
                                if (max_x >= size[0]) max_x = size[0]-1;

                                // Fill up the pixel array with some the pattern, which is 
                                // generated by the 'evaluate' function.  The Render View
                                // accepts floating point pixel values only.
                                //
                                unsigned int index = 0;
                                for (unsigned int j = min_y; j <= max_y; j++ )
                                {
                                        for (unsigned int i = min_x; i <= max_x; i++)
                                        {
                                                pixels[index] = evaluate(i, j);
                                                index++;
                                        }
                                }

                                // Send the data to the render view.
                                //
                                if (MRenderView::updatePixels(min_x, max_x, min_y, max_y, pixels) 
                                        != MS::kSuccess)
                                {
                                        displayError( "renderViewInteractiveRender: error occured in updatePixels." );
                                        delete [] pixels;
                                        return MS::kFailure;
                                }

                                // Force the Render View to refresh the display of the
                                // affected region.
                                //
                                MStatus st;
                                if (fullRefresh)
                                        st =MRenderView::refresh(0, image_width-1, 0, image_height-1);
                                else
                                        st = MRenderView::refresh(min_x, max_x, min_y, max_y);
                                if (st != MS::kSuccess)
                                {
                                        displayError( "renderViewInteractiveRender: error occured in refresh." );
                                        delete [] pixels;
                                        return MS::kFailure;
                                }

                                if (verbose)
                                        cerr << "Tile "<<min_x<<", "<<min_y<<
                                                " (iteration "<<loopId<<")completed\n";
                        }
                }
        }

        delete [] pixels;

        // Inform the Render View that we have completed rendering the entire image.
        //
        if (MRenderView::endRender() != MS::kSuccess)
        {
                displayError( "renderViewInteractiveRender: error occured in endRender." );
                return MS::kFailure;
        }

        displayError( "renderViewInteractiveRender completed." );
        return stat;
}





Autodesk® Maya® 2009 © 1997-2008 Autodesk, Inc. All rights reserved. Generated with doxygen 1.5.6