closestPointOnNurbsSurfaceCmd.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 "closestPointOnNurbsSurfaceCmd.h"
closestPointOnNurbsSurfaceCmd::closestPointOnNurbsSurfaceCmd()
{
}
closestPointOnNurbsSurfaceCmd::~closestPointOnNurbsSurfaceCmd()
{
}
void* closestPointOnNurbsSurfaceCmd::creator()
{
return new closestPointOnNurbsSurfaceCmd;
}
bool closestPointOnNurbsSurfaceCmd::isUndoable() const
{
return false;
}
MStatus closestPointOnNurbsSurfaceCmd::doIt(const MArgList& args)
{
bool debug = false;
bool treeBased = true;
MStatus stat = MStatus::kSuccess;
if(debug) cout << "closestPointOnNurbsSurfaceCmd::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 );
}
MFnTransform loc1Fn(loc1Object);
MVector t = loc1Fn.getTranslation(MSpace::kObject);
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, v;
if ( treeBased ) {
if(debug) cout << "tree-based NURBS closestPoint (MNurbsIntersector)\n";
MNurbsIntersector nurbIntersect;
stat = nurbIntersect.create(nurbsObject, mat);
if(!stat) {
if(debug) cout << "MNurbsIntersector::create FAILED\n";
return( stat );
}
MPointOnNurbs ptON;
stat = nurbIntersect.getClosestPoint(pt, ptON);
if(!stat) {
if(debug) cout << "getClosestPoint FAILED!\n";
return( stat );
}
resultPoint = ptON.getPoint();
MPoint UV = ptON.getUV();
u = UV.x;
v = UV.y;
} else {
MFnNurbsSurface ns = MFnNurbsSurface( nurbsObject );
pt *= mat;
resultPoint = ns.closestPoint( pt, false, &u, &v );
}
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 );
}
MObject loc2Object;
stat = list.getDependNode(2, loc2Object);
if(!stat) {
if(debug) cout << "FAILED grabbing locator2\n";
return( stat );
}
MFnTransform loc2Fn(loc2Object);
stat = loc2Fn.setTranslation(worldResultPoint, MSpace::kTransform);
return stat;
}
MStatus closestPointOnNurbsSurfaceCmd::undoIt()
{
MStatus status;
return status;
}
MStatus initializePlugin( MObject obj )
{
MStatus status;
MFnPlugin plugin( obj, PLUGIN_COMPANY, "8.5", "Any");
status = plugin.registerCommand( "closestPointOnNurbsSurface",
closestPointOnNurbsSurfaceCmd::creator );
if (!status) {
status.perror("registerCommand");
return status;
}
return status;
}
MStatus uninitializePlugin( MObject obj)
{
MStatus status;
MFnPlugin plugin( obj );
status = plugin.deregisterCommand( "closestPointOnNurbsSurface" );
if (!status) {
status.perror("deregisterCommand");
return status;
}
return status;
}