操作流程:
1. VS运行代码,生成插件
2. 打开Maya绘制曲线,加载插件
3. 选中绘制的曲线,运行插件
代码:
#include <maya/MSimple.h> #include <maya/MGlobal.h> #include <maya/MFnPlugin.h> #include <maya/MPxCommand.h> #include <maya/MSelectionList.h> #include <maya/MDagPath.h> #include <maya/MFnNurbsCurve.h> #include <maya/MItSelectionList.h> #include <maya/MPoint.h>// 命令类 class PostsCmd : public MPxCommand { public : // 执行命令时调用,完成命令的实际工作 virtual MStatus doIt(const MArgList&); // 返回的是命令已分配过的一个实例 static void *creator() { return new PostsCmd; } }; MStatus PostsCmd::doIt(const MArgList&) { // 初始化原著的数目、半径、高度 const int nPosts = 5; const double radius = 0.5; const double height = 5.0; // 创建当前已选定对象的一个清单,Selection对象用语保存清单对象 MSelectionList selection; MGlobal::getActiveSelectionList(selection); MDagPath dagPath; MFnNurbsCurve curveFn; // cylinder不允许显示设置其高度,必须通过heightRatio的值来设置 double heightRatio = height / radius; // 设置了一个过滤器的迭代器,排除不是NURBS曲线的所有其他对象 MItSelectionList iter(selection, MFn::kNurbsCurve); MGlobal::displayInfo("Now...\n"); int it = 0; // 迭代NURBS曲线 for (; !iter.isDone(); iter.next()) { MGlobal::displayInfo("NURBS Curve " + it); it++; // 找出当前曲线的完整DAG路径 iter.getDagPath(dagPath); // 将NURBS曲线函数集MFnNurbsCurve与DAG路径相关联 // 这样就规定了以后的所有函数集操作均被应用到DAG路径给出的对象上 curveFn.setObject(dagPath); // 得到曲线参数范围的始末值 double tStart, tEnd; curveFn.getKnotDomain(tStart, tEnd); MPoint pt; unsigned int i; double t; // 沿曲线长度创建了数目为nPosts的圆柱,参数范围按圆柱数目来分割 double tIncr = (tEnd - tStart) / (nPosts - 1); // t值没变一步,就沿曲线生成一个圆柱 for (i = 0, t = tStart; i < nPosts; i++, t += tIncr) { // 返回曲线上的一个点(世界坐标) curveFn.getPointAtParam(t, pt, MSpace::kWorld); // 中心点在轴心,做出调整使其地面位于曲线上 pt.y += 0.5 * height; // 执行MEL命令创建圆柱 // pivot-轴心 MGlobal::executeCommand(MString("cylinder -pivot ") + pt.x + " " + pt.y + " " + pt.z + " -radius " + radius + " -axis 0 1 0 -heightRatio " + heightRatio); } } return MS::kSuccess; } // 初始化 // obj指向有关插件类型的maya内部数据的一个句柄 MStatus initializePlugin(MObject obj) { // 将MFnPlugin关联到MObject上 MFnPlugin pluginFn(obj, "Amber W", "1.0"); MStatus stat; stat = pluginFn.registerCommand("Posts", PostsCmd::creator); if (!stat) { stat.perror("registerCommand failed"); } return stat; } // 卸载 MStatus uninitializePlugin(MObject obj) { MFnPlugin pluginFn(obj); MStatus stat; stat = pluginFn.deregisterCommand("Posts"); if (!stat) { stat.perror("deregisterCommand failed"); } return stat; }
其中大部分代码都是创建命令必须的,可以用一句话来代替:
DeclareSimpleCommand( PostsCmd, "", "2018");
因此,最终代码简化版为
#include <maya/MSimple.h> #include <maya/MGlobal.h> #include <maya/MFnPlugin.h> #include <maya/MPxCommand.h> #include <maya/MSelectionList.h> #include <maya/MDagPath.h> #include <maya/MFnNurbsCurve.h> #include <maya/MItSelectionList.h> #include <maya/MPoint.h> DeclareSimpleCommand( PostsCmd, "", "2018"); MStatus PostsCmd::doIt(const MArgList&) { // 初始化原著的数目、半径、高度 const int nPosts = 5; const double radius = 0.5; const double height = 5.0; // 创建当前已选定对象的一个清单,Selection对象用语保存清单对象 MSelectionList selection; MGlobal::getActiveSelectionList(selection); MDagPath dagPath; MFnNurbsCurve curveFn; // cylinder不允许显示设置其高度,必须通过heightRatio的值来设置 double heightRatio = height / radius; // 设置了一个过滤器的迭代器,排除不是NURBS曲线的所有其他对象 MItSelectionList iter(selection, MFn::kNurbsCurve); MGlobal::displayInfo("Now...\n"); int it = 0; // 迭代NURBS曲线 for (; !iter.isDone(); iter.next()) { MGlobal::displayInfo("NURBS Curve " + it); it++; // 找出当前曲线的完整DAG路径 iter.getDagPath(dagPath); // 将NURBS曲线函数集MFnNurbsCurve与DAG路径相关联 // 这样就规定了以后的所有函数集操作均被应用到DAG路径给出的对象上 curveFn.setObject(dagPath); // 得到曲线参数范围的始末值 double tStart, tEnd; curveFn.getKnotDomain(tStart, tEnd); MPoint pt; unsigned int i; double t; // 沿曲线长度创建了数目为nPosts的圆柱,参数范围按圆柱数目来分割 double tIncr = (tEnd - tStart) / (nPosts - 1); // t值没变一步,就沿曲线生成一个圆柱 for (i = 0, t = tStart; i < nPosts; i++, t += tIncr) { // 返回曲线上的一个点(世界坐标) curveFn.getPointAtParam(t, pt, MSpace::kWorld); // 中心点在轴心,做出调整使其地面位于曲线上 pt.y += 0.5 * height; // 执行MEL命令创建圆柱 // pivot-轴心 MGlobal::executeCommand(MString("cylinder -pivot ") + pt.x + " " + pt.y + " " + pt.z + " -radius " + radius + " -axis 0 1 0 -heightRatio " + heightRatio); } } return MS::kSuccess; }
参考:《Maya5.0编程全攻略》