- Main Page
- Related Pages
- Modules
- Classes
- Examples

# intersectCmd.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.
    // ==========================================================================
    //+

    // MAYA HEADERS

    #include <maya/MFnPlugin.h>

    #include <maya/MDagPath.h>

    #include <maya/MFnMesh.h>

    #include <maya/MItSelectionList.h>

    #include <maya/MItMeshPolygon.h>

    #include <maya/MObject.h>

    #include <maya/MSelectionList.h>

    #include <maya/MArgList.h>

    #include <maya/MFloatPoint.h>

    #include <maya/MFnDependencyNode.h>

    #include <maya/MFnSpotLight.h>

    #include <maya/MFloatPointArray.h>

    #include <maya/MPxCommand.h>

    #include <maya/MDGModifier.h>

    #include <maya/MFnDagNode.h>

    #include <maya/MDagPath.h>

    #include <maya/MGlobal.h>

    #ifndef INTERSECTCMD

    #define INTERSECTCMD

    #define MERR_CHK(stat,msg) if ( !stat ) { MGlobal::displayError(msg); } // cerr << msg << endl; }

    //

    //  PLUGIN DESCRIPTION

    //

    //  This is an example of finding the intersection points on a mesh from a spotlight using the          //  intersection acceleration methods in MFnMesh.

    //

    //

    //  PLUGIN INSTRUCTIONS

    //

    //  - create a spotlight and a poly plane (mesh)

    //  - orient the light to shine onto the plane

    //  - run the command as such: intersectCmd <spotLightName> <planeName>

    //  - if there is an intersection, a small sphere will be created at the intersection point.

    //

    //  Use the following script to automatically display intersections on the mesh (assuming

    //  a spotlight and a mesh with the names used here exist):

    //

    //  global proc intersectExample()

    //  {

    //      intersectCmd spotLight1 pPlane1;

    //      select -r spotLight1;

    //  }

    //

    //  scriptJob -ac "spotLight1.tx" intersectExample;

    //  scriptJob -ac "spotLight1.ty" intersectExample;

    //  scriptJob -ac "spotLight1.tz" intersectExample;

    //

    //  scriptJob -ac "spotLight1.rx" intersectExample;

    //  scriptJob -ac "spotLight1.ry" intersectExample;

    //  scriptJob -ac "spotLight1.rz" intersectExample;

    //

    // MAIN CLASS FOR THE INTERSECTCMD COMMAND:

    class intersectCmd : public MPxCommand

    {

        public:

            intersectCmd();

            virtual ~intersectCmd();

            static void* creator();

            bool isUndoable() const;

            MStatus doIt(const MArgList&);

            MStatus undoIt();

    };

    #endif

    // CONSTRUCTOR:

    intersectCmd::intersectCmd()

    {

    }

    // DESTRUCTOR:

    intersectCmd::~intersectCmd()

    {

    }

    // FOR CREATING AN INSTANCE OF THIS COMMAND:

    void* intersectCmd::creator()

    {

       return new intersectCmd;

    }

    // MAKE THIS COMMAND NOT UNDOABLE:

    bool intersectCmd::isUndoable() const

    {

       return false;

    }

    MStatus intersectCmd::doIt(const MArgList& args)

    // Description:

    //      Determine if the ray from the spotlight intersects the mesh.

    //      If it does, display the intersection points.

    {

        MStatus stat = MStatus::kSuccess;

        if (args.length() != 2)

        {

            MGlobal::displayError("Need 2 items!");

            return MStatus::kFailure;

        }

        MSelectionList activeList;

        int i;

        for ( i = 0; i < 2; i++)

        {

            MString strCurrSelection;

            stat = args.get(i, strCurrSelection);

            if (MStatus::kSuccess == stat) activeList.add(strCurrSelection);

        }

        MItSelectionList iter(activeList);

        MFnSpotLight fnLight;

        MFnMesh fnMesh;

        MFnDagNode dagNod;

        MFnDependencyNode fnDN;

        float fX = 0;

        float fY = 0;

        float fZ = 0;

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

        {

            MObject tempObjectParent, tempObjectChild;

            iter.getDependNode(tempObjectParent);

            if (tempObjectParent.apiType() == MFn::kTransform)

            {

                dagNod.setObject(tempObjectParent);

                tempObjectChild = dagNod.child(0, &stat);

            }

            // check what type of object is selected

            if (tempObjectChild.apiType() == MFn::kSpotLight)

            {

                MDagPath pathToLight;

                MERR_CHK(MDagPath::getAPathTo(tempObjectParent, pathToLight), "Couldn't get a path to the spotlight");

                MERR_CHK(fnLight.setObject(pathToLight), "Failure on assigning light");

                stat = fnDN.setObject(tempObjectParent);

                MPlug pTempPlug = fnDN.findPlug("translateX", &stat);

                if (MStatus::kSuccess == stat)

                {

                    pTempPlug.getValue(fX);

                }

                pTempPlug = fnDN.findPlug("translateY", &stat);

                if (MStatus::kSuccess == stat)

                {

                    pTempPlug.getValue(fY);

                }

                pTempPlug = fnDN.findPlug("translateZ", &stat);

                if (MStatus::kSuccess == stat)

                {

                    pTempPlug.getValue(fZ);

                }

            }

            else if (tempObjectChild.apiType() == MFn::kMesh)

            {

                MDagPath pathToMesh;

                MERR_CHK(MDagPath::getAPathTo(tempObjectChild, pathToMesh), "Couldn't get a path to the spotlight");

                MERR_CHK(fnMesh.setObject(pathToMesh), "Failure on assigning light");

            }

            else

            {

                MGlobal::displayError("Need a spotlight and a mesh");

                return MStatus::kFailure;

            }

        }

        MFloatPoint fpSource(fX, fY, fZ);

        MFloatVector fvRayDir = fnLight.lightDirection(0, MSpace::kWorld, &stat);

        MFloatPoint hitPoint;

        MMeshIsectAccelParams mmAccelParams = fnMesh.autoUniformGridParams();

        float fHitRayParam, fHitBary1, fHitBary2;

        int nHitFace, nHitTriangle;

        // a large positive number is used here for the maxParam parameter

        bool bAnyIntersection = fnMesh.anyIntersection(fpSource, fvRayDir, NULL, NULL, false,               MSpace::kWorld, (float)9999, false, &mmAccelParams, hitPoint, &fHitRayParam, &nHitFace, &nHitTriangle,      &fHitBary1, &fHitBary2, (float)1e-6, &stat);

        if (! bAnyIntersection)

        {

            MGlobal::displayInfo("There were no intersection points detected");

            return stat;

        }

        MFloatPointArray hitPoints;

        MFloatArray faHitRayParams;

        MIntArray iaHitFaces;

        MIntArray iaHitTriangles;

        MFloatArray faHitBary1;

        MFloatArray faHitBary2;

        bool bAllIntersections = fnMesh.allIntersections(fpSource, fvRayDir, NULL, NULL, false, MSpace::kWorld, 9999, false, NULL, false, hitPoints, &faHitRayParams, &iaHitFaces, &iaHitTriangles, &faHitBary1, &faHitBary2, 0.000001f, &stat);

        if (! bAllIntersections)

        {

            MGlobal::displayInfo("Error getting all intersections");

            return stat;

        }

        // check how many intersections are found

        unsigned int nNumberHitPoints = hitPoints.length();

        if (! nNumberHitPoints)

        {

            MGlobal::displayInfo("No hit points detected");

            return MStatus::kSuccess;

        }

        // Intersection exists; display intersections as spheres

        MString strCommandString = "string $strBall[] = `polySphere -r 0.5`;";

        strCommandString += "$strBallName = $strBall[0];";

        float x = 0;

        float y = 0;

        float z = 0;

        for (i = 0; i < (int)nNumberHitPoints; i++)

        {

            // get the points

            x = hitPoints[i][0];

            y = hitPoints[i][1];

            z = hitPoints[i][2];

            // execute some MEL to create a small sphere

            strCommandString += "setAttr ($strBallName + \".tx\") ";

            strCommandString += x;

            strCommandString += ";";

            strCommandString += "setAttr ($strBallName + \".ty\") ";

            strCommandString += y;

            strCommandString += ";";

            strCommandString += "setAttr ($strBallName + \".tz\") ";

            strCommandString += z;

            strCommandString += ";";

            MGlobal::executeCommand(strCommandString);

        }

        return stat;

    }

    // UNDO THE COMMAND

    MStatus intersectCmd::undoIt()

    {

        MStatus status;

        // undo not implemented

        return status;

    }

    // INITIALIZE THE PLUGIN:

    MStatus initializePlugin(MObject obj)

    {

        MStatus status;

        MFnPlugin plugin(obj, PLUGIN_COMPANY, "6.5", "Any");

        status = plugin.registerCommand("intersectCmd", intersectCmd::creator);

        return status;

    }

    // UNINITIALIZE THE PLUGIN:

    MStatus uninitializePlugin(MObject obj)

    {

        MStatus status;

        MFnPlugin plugin(obj);

        plugin.deregisterCommand("intersectCmd");

        return status;

    }