Published using Google Docs
rotatePolyCmd

/**@file rotatePolyCmd.cpp

@note select a polygon and type in mel -- rotatePolyCmd -r 90;  which will rotate in x all vertices by 90 degrees

@author Nathaniel O. Anozie (ogbonnawork at gmail dot com)

@note Modify at your own risk

@note date created: 02/19/2013

@note this has some useful info for undo, user argument, using rotation matrices

@note inspired by Foley & Van Dam Chapter 5, Geometrical Transformations

@note inspired by Rick Parent (cse dot ohio-state dot edu) accessVertices.cpp

@note inspired by Autdodesk Api tutorial examples surfaceTwistCmd.cpp, translateCmd.cpp learning about MMatrix, and MItMeshVertex

*/

//07-07-13  ----    fixed bug so it rotates all vertices, added user argument option, added undo

#include <maya/MGlobal.h>

//im guessing these are needed almost always

//printing stuff, selecting stuff

#include <maya/MItSelectionList.h>

#include <maya/MSelectionList.h>

//need iterating for polygon vertex

#include <maya/MItMeshVertex.h>

//need finding outliner polys

#include <maya/MDagpath.h>

//need for matrix stuff

#include <math.h>

#include <maya/MPoint.h>

#include <maya/MMatrix.h>

//for using arguments hence command

#include <maya/MPxCommand.h>

#include <maya/MFnPlugin.h>

#include <maya/MSyntax.h>

#include <maya/MArgList.h>

#include <maya/MArgDatabase.h>

static const char* g_rFlag = "-r";

static const char* g_rFlagLong = "-rotate";

//for undo

#define DOIT 0

#define UNDOIT 1

static double pi = 3.14159265359;

//if using user arguments

class rotatePolyCmd: public MPxCommand{

   

public:

    rotatePolyCmd(); //needed because we need to initialize data

    virtual ~rotatePolyCmd();

    virtual bool isUndoable() const;

    MStatus doIt( const MArgList& args );

    MStatus undoIt();

    static void* creator();

    //for syntax

    static MSyntax newSyntax();

   

private:

    //any other functions

    MStatus action( int flag );

    double deg;

};

rotatePolyCmd::rotatePolyCmd()

{

    deg = 90;

   

}

rotatePolyCmd::~rotatePolyCmd(){}

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

bool rotatePolyCmd::isUndoable() const{ return true; }

MSyntax rotatePolyCmd::newSyntax()

{

    MSyntax syntax;

   

    //add flag

    syntax.addFlag(g_rFlag, g_rFlagLong, MSyntax::kDouble);

    return syntax;

}

//last stuff

MStatus initializePlugin( MObject obj)

{

    MStatus stat;

    MFnPlugin fnPlugin( obj, "Nathaniel Anozie", "1.0", "Any");

    //need user argument function and creator

    stat = fnPlugin.registerCommand("rotatePolyCmd",rotatePolyCmd::creator, rotatePolyCmd::newSyntax);

    if(stat != MS::kSuccess){stat.perror("could not register !!!");};

    return stat;

}

MStatus uninitializePlugin(MObject obj)

{

    MStatus stat;

    MFnPlugin fnPlugin(obj);

    stat = fnPlugin.deregisterCommand("rotatePolyCmd");

    if(stat != MS::kSuccess){stat.perror("could not de-register !!!");};

    return stat;

}

////

/**the names here needs to match that used in our command or DeclareSimpleCommand

@note notice no dollar signs, also we

@note need to do search manual to figure out the kind of thing that will help us find keyframes

@note the ampersand is alot different from MEL cause in MEL

@note i think only arrays are passed by reference

@note here a boolean type thing can be edited somewhere else and we can see what we got for error checking            

*/

MStatus rotatePolyCmd::doIt( const MArgList& args )

{

    MStatus stat = MS::kSuccess; //we want this for error checking

   

    double degree = 90; //default degrees to rotate

    //---------- constants    

    //rotate in x all polys of all selected polys about origin

   

    //create parser for user arguments

    MArgDatabase argData(syntax(), args, &stat);

   

    if(stat != MS::kSuccess)

    {

        stat.perror("arguments not correct !!!");

        return stat;

    }

    //get user argument

    if(argData.isFlagSet(g_rFlag))

        argData.getFlagArgument(g_rFlag, 0, degree );

   

    deg = degree;

   

   

    return action( DOIT );//give back success of a different function

}

MStatus rotatePolyCmd::undoIt( )

{

    return action( UNDOIT );

}

//flag -- DOIT or UNDOIT

//deg DEGREES to rotate

MStatus rotatePolyCmd::action( int flag )

{

 

    MStatus stat;

   

    //figure out rotation amount for undo it will be negative of the do

    double degree = deg;

    switch( flag )

    {

        case UNDOIT:

            degree = -degree;

        case DOIT:

            break;

        default:

            break;

    }

    double rotAmt = (pi/180) * degree; //in radians

 

   

    MSelectionList selList;

    MGlobal::getActiveSelectionList(selList);

    if(selList.length() != 1){

        MGlobal::displayError("Requires a Polygon Selected !!!\n");

        return MS::kFailure;

    }

   

    //not yet any restrictions

    MItSelectionList polyIt(selList, MFn::kMesh, &stat);//instead of setFilter

    //if used MFn::kInvalid i think more items possible. for any kind poly,nurbs, ..

   

    if(MS::kSuccess == stat){

       

       

        MDagPath meshDag;

        MObject mComponent; //will hold current vtx

       

        //loop polys, were not looping vertices yet

        for( ; !polyIt.isDone(); polyIt.next() )

        {

            polyIt.getDagPath(meshDag, mComponent); //saves how to find this poly from outliner

           

            MItMeshVertex vtxIter( meshDag, mComponent, &stat);

            if( MS::kSuccess == stat ){

               

                //How we should rotate is fixed for all vertices

                //This is counter clockwise rotation about --- X --- axis

                double rotation = rotAmt;

                MMatrix rMatrix;

                rMatrix(0,0) = 1;

                rMatrix(0,1) = 0;

                rMatrix(0,2) = 0;

                rMatrix(1,0) = 0;

                rMatrix(1,1) = cos( rotation );

                rMatrix(1,2) = sin( rotation );

                rMatrix(2,0) = 0;

                rMatrix(2,1) = -sin( rotation );

                rMatrix(2,2) = cos( rotation );

               

                //rotate vertices

                for( ; !vtxIter.isDone(); vtxIter.next() ){

                   

                    MPoint pnt = vtxIter.position( MSpace::kWorld); //MSpace::kWorld

                    MPoint newPnt;

                    //rotate computation

                    newPnt = ( rMatrix * pnt );

                   

                    stat = vtxIter.setPosition( newPnt, MSpace::kWorld);

                    if( MS::kSuccess != stat ){

                        cerr << "Error setting Vertex\n -- Exiting";

                        break;

                    }

                }//end vertex loop

            }

           

        }//end poly loop

       

    }

        return MS::kSuccess;

   

}