intersectOnNurbsSurfaceCmd.cpp
#include <math.h>
#include <maya/MIOStream.h>
#include <maya/MArgList.h>
#include <maya/MPxCommand.h>
#include <maya/MGlobal.h>
#include <maya/MSelectionList.h>
#include <maya/MPoint.h>
#include <maya/MNurbsIntersector.h>
#include <maya/MDagPath.h>
#include <maya/MMatrix.h>
#include <maya/MFnDagNode.h>
#include <maya/MFnTransform.h>
#include <maya/MVector.h>
#include <maya/MFnPlugin.h>
#include <maya/MFnNurbsSurface.h>
#include "intersectOnNurbsSurfaceCmd.h"
intersectOnNurbsSurfaceCmd::intersectOnNurbsSurfaceCmd()
{
}
intersectOnNurbsSurfaceCmd::~intersectOnNurbsSurfaceCmd()
{
}
void* intersectOnNurbsSurfaceCmd::creator()
{
   return new intersectOnNurbsSurfaceCmd;
}
bool intersectOnNurbsSurfaceCmd::isUndoable() const
{
   return false;
}
MStatus intersectOnNurbsSurfaceCmd::doIt(const MArgList& args)
{
        bool debug = false;     
        bool treeBased = true;
        MStatus stat = MStatus::kSuccess;
        if(debug) cout << "intersectOnNurbsSurfaceCmd::doIt\n";
        
        MSelectionList list;
        stat = MGlobal::getActiveSelectionList(list);
        if(!stat) {
                if(debug) cout << "getActiveSelectionList FAILED\n";
                return( stat );
        }
        MDagPath path;
        MObject nurbsObject;
        stat = list.getDependNode(0,nurbsObject);
        if(!stat)
                if(debug) cout << "getDependNode FAILED\n";
        MFnDagNode nodeFn(nurbsObject);
        
        if(nodeFn.childCount() > 0) {
                MObject child = nodeFn.child(0);
                nodeFn.setObject(child);
        }
        list.getDagPath(0,path);
        if(debug) cout << "Working with: " << path.partialPathName() << endl;
        MMatrix mat = path.inclusiveMatrixInverse();
        if(debug) cout << mat << endl;
        MObject loc1Object;
        stat = list.getDependNode(1, loc1Object); 
        if(!stat) {
                if(debug) cout << "FAILED grabbing locator1\n";
                return( stat );
        }
        MObject loc2Object;
        stat = list.getDependNode(2, loc2Object); 
        if(!stat) {
                if(debug) cout << "FAILED grabbing locator2\n";
                return( stat );
        }
        MFnTransform loc1Fn(loc1Object);
        MVector t = loc1Fn.getTranslation(MSpace::kObject);
        MFnTransform loc2Fn(loc2Object);
        MVector t2 = loc2Fn.getTranslation(MSpace::kObject);
        MVector ray = t2 - t;
        
        MPoint pt(t[0], t[1], t[2]);
        if(debug) cout << "test point: " << pt << endl;
        if(debug) cout << "transformed:" << pt * mat << endl;
        MPoint resultPoint;
        double u=0, v=0;
        if ( treeBased ) {
                
                
                
                
                
                if(debug) cout << "tree-based NURBS intersect (MNurbsIntersector)\n";
                MNurbsIntersector nurbIntersect;
                stat = nurbIntersect.create(nurbsObject, mat);
                if(!stat) {
                        if(debug) cout << "MNurbsIntersector::create FAILED\n";
                        return( stat );
                }
                stat = nurbIntersect.getIntersect(pt, ray, u, v, resultPoint, kMFnNurbsEpsilon);
                if(!stat) {
                        if(debug) cout << "MNurbsIntersector::getIntersect FAILED!\n";
                        return( stat );
                }
        } else {
                
                
                MFnNurbsSurface ns = MFnNurbsSurface( nurbsObject );
                pt *= mat;      
                bool result = ns.intersect(pt, ray, u, v, resultPoint, kMFnNurbsEpsilon, MSpace::kObject, false, NULL, false, NULL, &stat );
                if(!result || !stat) {
                        if(debug) cout << "MFnNurbsSurface::intersect FAILED!\n";
                        if(stat) {
                                stat = MStatus::kFailure;
                        }
                        return( stat );
                }
        }
        
        
        
        if(debug) cout << "result UV: " << u << ", " << v << endl;
        MString cmd = "pointOnSurface -u ";
        cmd += u;
        cmd += " -v ";
        cmd += v;
        cmd += " ";
        cmd += path.partialPathName();
        MDoubleArray arr;
        MGlobal::executeCommand(cmd, arr); 
        if(debug) cout << "check results:  result UV corresponds to world point: " << arr << endl;
        MPoint worldResultPoint = resultPoint * path.inclusiveMatrix();
        if(debug) cout << "local space result point: " << resultPoint << endl;
        if(debug) cout << "world space result point: " << worldResultPoint << endl;
        if ( fabs( arr[0] - worldResultPoint.x ) > 0.0001
                        || fabs( arr[1] - worldResultPoint.y ) > 0.0001
                        || fabs( arr[2] - worldResultPoint.z ) > 0.0001 ) {
                cout << "check results: pointOnSurface does not match world point: " << arr << endl;
                return( MS::kFailure );
        }
        
        
        
        
        
        stat = loc2Fn.setTranslation(worldResultPoint, MSpace::kTransform);
        return stat;
}
MStatus intersectOnNurbsSurfaceCmd::undoIt()
{
        MStatus status;
        
        return status;
}
MStatus initializePlugin( MObject obj )
{
    MStatus   status;
    MFnPlugin plugin( obj, PLUGIN_COMPANY, "8.5", "Any");
    status = plugin.registerCommand( "intersectOnNurbsSurface",
                        intersectOnNurbsSurfaceCmd::creator );
    if (!status) {
        status.perror("registerCommand");
        return status;
    }
    return status;
}
MStatus uninitializePlugin( MObject obj)
{
    MStatus   status;
    MFnPlugin plugin( obj );
    status = plugin.deregisterCommand( "intersectOnNurbsSurface" );
    if (!status) {
        status.perror("deregisterCommand");
        return status;
    }
    return status;
}