Maya编程——沿Curve绘制圆柱

操作流程:

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编程全攻略》

上一篇:paper每日谈——动机


下一篇:android 2d弧碰撞检测