Maya編程——沿Curve繪製圓柱

操做流程:編程

1. VS運行代碼,生成插件函數

2. 打開Maya繪製曲線,加載插件spa

3. 選中繪製的曲線,運行插件插件

Posts1.0 命令行

代碼:code

#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( Posts, "", "2018");

所以,最終代碼簡化版爲blog

#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( Posts, "", "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;
}

 Posts2.0索引

能夠在命令行出現參數,執行時輸入:get

Posts -r 1.0 -n 6 -h 10.0;

修改doIt前面一部分的代碼爲:

MStatus Posts::doIt(const MArgList& args)
{
    // 初始化的數目、半徑、高度
    int nPosts = 5;
    double radius = 0.5;
    double height = 5.0;

    // 從命令行中獲取參數值
    unsigned index;
    // 返回含有給定標記的參數的索引(兩種標記)
    index = args.flagIndex("n", "number");
    // 若是命令行中沒有設置該值,index就被設置爲MArgList::kInvalidArgIndex
    if (MArgList::kInvalidArgIndex != index) {
        args.get(index + 1, nPosts);
    }

    index = args.flagIndex("r", "radius");
    if (MArgList::kInvalidArgIndex != index) {
        args.get(index + 1, radius);
    }

    index = args.flagIndex("h", "height");
    if (MArgList::kInvalidArgIndex != index) {
        args.get(index + 1, height);
    }


    .......
}

Posts3.0

使用MSyntax和MArgsDatabase類。這兩個類在能夠使用的參數數目和類型方面帶來了更大的靈活性。並且提供了更好的參數,類型檢查機制。

MSyntax類提供了一種簡便的方法來爲你的命令行指定全部可能的參數。

MArgsDatabase類被用來分析和分隔不一樣的標記和它們的值。

#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>
#include <maya/MSyntax.h>
#include <maya/MArgDatabase.h>

const char *numberFlag = "-n", *numberLongFlag = "-number";
const char *radiusFlag = "-r", *radiusLongFlag = "-radius";
const char *heightFlag = "-h", *heightLongFlag = "-height";

class PostsCmd : public MPxCommand
{
public:
    // 執行命令時調用,完成命令的實際工做
    virtual MStatus doIt(const MArgList&);

    // 返回的是命令已分配過的一個實例
    static void *creator() {
        return new PostsCmd;
    }

    static MSyntax newSyntax();

};

// 指定標記的參數的數據類型
MSyntax PostsCmd::newSyntax()
{
    MSyntax syntax;
    syntax.addFlag(numberFlag, numberLongFlag, MSyntax::kLong);
    syntax.addFlag(radiusFlag, radiusLongFlag, MSyntax::kDouble);
    syntax.addFlag(heightFlag, heightLongFlag, MSyntax::kDouble);
    return syntax;
}

MStatus PostsCmd::doIt(const MArgList& args)
{
    // 初始化的數目、半徑、高度
    int nPosts = 5;
    double radius = 0.5;
    double height = 5.0;

    MArgDatabase argData(syntax(), args);

    // 依次檢查每一個標記,看其值是否已經設置
    if (argData.isFlagSet(numberFlag))
    {
        argData.getFlagArgument(numberFlag, 0, nPosts);
    }
    if (argData.isFlagSet(radiusFlag))
    {
        argData.getFlagArgument(radiusFlag, 0, radius);
    }
    if (argData.isFlagSet(heightFlag))
    {
        argData.getFlagArgument(heightFlag, 0, height);
    }


    // 建立當前已選定對象的一個清單,Selection對象用語保存清單對象
    MSelectionList selection;
    MGlobal::getActiveSelectionList(selection);

    MDagPath dagPath;
    MFnNurbsCurve curveFn;
    // cylinder不容許顯示設置其高度,必須經過heightRatio的值來設置
    double heightRatio = height / radius;

    // 設置了一個過濾器的迭代器,排除不是NURBS曲線的全部其餘對象
    MItSelectionList iter(selection, MFn::kNurbsCurve);

    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;

    // 爲了讓maya知道要使用自定義的MSyntax對象
    stat = pluginFn.registerCommand("Posts", PostsCmd::creator,
        PostsCmd::newSyntax );

    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;
}

Posts4.0

 

 

 

 

 

參考:《Maya5.0編程全攻略》

相關文章
相關標籤/搜索