mayaAPI(3)-mll

maya Developer Resources一共是三章,第一章是API,现在开始API第三节。

躺在床上思考了一下DG和DAG。两者都是数学上的名词,在计算机里面用面向对象的方法来表达。

所以这两个类在计算机里都会变得非常不一样。毕竟计算机它不知道数学那些表达符号是什么意思,都得我们自己来做。

DAG这个类,在maya里面就是MDagPath,maya用这个类来管理一个或者多个DAG Node。每个MDagPath的实例,都有很多的方法,它可以得到与路径有关的(父,子,路径名等等)以及类型,名字这一些通用属性。

所以说,在maya里面,一个DAG Node是和path融合在一起写为一个类的,是不能分开的。(这样我们也方便了,不用新建两个类,我们写一个类就OK了。)

DG的话题以后再说,现在继续研究plugin,抛开MSimple这个macor头文件。

——————>
突然发现vs6之后,就没有make file了。这让我有写一个bat和make file的冲动。。

想到这个念头,就又去看了看masm里面的bat写法,果然很强大,以前没有注意到命令行的if语句,现在知道了。

真的很想多学学nmake的语法,还有cl和link的各种选项以及PE文件。。希望更加熟悉一点。。不过,还是暂时放着吧。。

咱还是有VS2005 的IDE的,虽然不够完全灵活,但是至少很实用。。

不过这个IDE产生了很多的废文件。。比如ncb,比如sln。。

——————>回到maya plugin

helix2这个plugin 充分演示了redo-undo plugin该是如何来写,以及非常实用的maya API的使用方法。

我们来看helix2这个cpp的写法。

它在逻辑上是有这样一个过程:

1)

我们把这个cpp编译成dll,虽然它的后缀是mll

这个dll有2个导出函数(链接器选项里面有,这是maya template wizard做的,虽然这个导出也是可以在代码里面写特定的calling convention,但是maya的标准template并没有显式声明calling convention ):

initializePlugin和uninitializePlugin

插一段:在C++中要写个dll有三种方法:

前提是要写好一个dllentry方法,然后再link里面加上/dll

1.使用def文件,这个比较平常的,它的写法是:

LIBRARY   BTREE    // 库名为BTREE,省略库名即为动态链接库文件名
EXPORTS        // 输出
Insert   @1    // 带序号的输出函数名
Delete   @2
Member   @3
Min   @4

(library这行在VS里面似乎有些不同,似乎和工程名要对应。)

2.直接在link后面加上后缀/export:xxx 。有几个就加几个。

3.使用C++的_declspec(dllexport)引用约束前缀来(附加上extren “C”更好)来进行prototype声明(这种calling convention用起来比较麻烦)

使用dll:

如果是前2种写的dll,那么使用起来很简单,就和其他的系统API使用是一样的,毕竟在C和C++中都是_cdel这个引用约束。而第三种由于改变了引用约束,所以,我们需要用_declspec(dllimport)来声明prototype。

2)

may会调用initializePlugin并且会传入一个MObject的对象,里面有一些信息

我们使用:

MFnPlugin plugin( obj, “lizhong”, “2009″, “Any”);

obj里面有什么信息呢:

This MObject contains Maya private information such as the name of the plug-in file and the directory it was loaded from.

比较神奇的是,我在MObject的API里面找不到这样的公开方法,似乎是没有公开的API部分。。

然后:

status = plugin.registerCommand( “LzHello”, LzHello::creator );

我们传递了一个字符串,以及一个函数的地址过去。

API是这样解释的:

MStatus MFnPlugin::registerCommand  ( const MString &  commandName,
  MCreatorFunction  creatorFunction,
  MCreateSyntaxFunction  createSyntaxFunction = NULL
 )    

Register a new command with Maya. Once registered,
the command can be invoked from MEL in a manner identical to built-in Maya commands.

Parameters:
[in]  commandName  the name of the command to register
[in]  creatorFunction  a pointer to a function that will return a pointer
to a new instance of the class (derived from MPxCommand)
 that implements the new command.
[in]  createSyntaxFunction  a pointer to a function
that will return a new instance of a syntax object (MSyntax)
that implements the syntax of the command.

它解释的很清楚了,不过第三个参数涉及到MSyntax,以后再说。

有了这个函数地址,我们就可以调用这个函数,一个这样的函数最大的用途就是返回一个我们写的类的new实例,也就是申请一块内存来初始化我们的类。

因为maya从始至终都不知道我们的代码会是什么样子的,它只会一步一步执行下去,我们要做完所有的事情。

我们的这个类不能随便编写一个了事,我们必须按照maya给我们的规范(因为maya只会调用固定的接口,它只访问固定的几个函数地址)

我们的代码就是这样声明的:

class LzHello : public MPxCommand
{

public:
	LzHello();
	virtual		~LzHello();

	MStatus		doIt( const MArgList& );
	MStatus		redoIt();
	MStatus		undoIt();
	bool		isUndoable() const;

	static		void* creator();

};

这里还有个MArgList,所以前面可以写个类前置声明,或者导入这个头文件。

对于C++来说,构造函数和析构函数是不可少的,对于maya来说,这5个方法是不可少的。

所以就一共7个方法,至于拷贝构造函数这个东西,不知道在我们写的类中会不会出现new操作符呢。

这里之所以使用virtual析构函数,也就是考虑到我们写的类也可能要被继承的,所以当出现动态绑定的时候用virtual可以解决子类动态申请的内存不被释放的问题。

3)

在函数执行完构造函数之后,它会调用doIt方法

doIt方法里面就可以处理2方面的问题,1是参数列表,2是MGlobal selectionlist

这时,产生的数据都可以存为私有成员属性,doIt方法只会调用一次,所以作为数据存储方法是再好不过了。

而redo方法是作为真正的执行方法(这样也就是做到了各司其职,代码复用)

4)redo方法里就可以随意私有成员对象进行处理了。不过,如果要对目标进行改造的时候,要记得存储改动的数据,这个也要存在私有成员属性里面,不然我们undo的时候就没办法还原了。

5)undo其实很简单,在redo里面已经保存好了改动前的目标属性,我们只要利用这个原始属性变回来就可以了。

6)我们的函数也可以有返回值,这个返回值可以输出到output窗口里面,也可以输出到mel 命令行窗口里面。

这个就是SetResult。API里面有3个例子来说明,总而言之我们主要有3个API可以用:

clearResult();

appendToResult();

setResult();

具体还是参看MPxCommand这个的API。

不过SetResult被重载了相当多次。。

static void  setResult (int val)
static void  setResult (double val)
static void  setResult (bool val)
static void  setResult (const char *val)
static void  setResult (const MString &val)
static void  setResult (const MIntArray &val)
static void  setResult (const MDoubleArray &val)
static void  setResult (const MStringArray &val)

——————>

maya的API明显非常强大,不过好像依靠它开发的人不太多,毕竟CG也没多少岁数,maya的岁数也很小,而且也不像操作系统那样受众广泛,其实maya从中国开始流行估计也就是05年的样子吧。98年生出来的软件,现在13岁了。不像商用操作系统那样,都已经20岁了。在中国,时间得退个至少年,操作系统的利用还处于初中生阶段,maya这样的三维软件的应用。。刚入小学。。说明我还是挺明智的。。

其实你要掌握一样计算机工具来实现电脑效果,最直接的方法就是编程。虽然三维中有许多方面还是与二维绘画有关,不过openGL毕竟是计算机绘图接口,编程占有的比重更大。

——————>Syntax Object

maya的API帮助文档上的文字硬邦邦的,思维都没个衔接。。明晃晃的不带衔接的总分-总分-总分结构

首先是三个类:

MSyntax

MArgDatabase

MArgParser(这个与Context Commands,说到context那就是与IO设备有关了。)

这个Sytax是干嘛的呢,这个是专门为参数准备的数据结构,我们要用C++来处理类似windows命令行类型的参数传递方式,就必须要有处理方法。

MArgDatabase就带有处理参数的方法集

先看看API说明:

MSyntax:

This class is used to specify flags and arguments passed to commands. Once the syntax of the command has been defined by calls to the methods in this class, Maya will be able to automatically parse invocations of the command and reject syntactically invalid ones.

常用的API有这么几个:

addFlag(),makeFlagMultiUse(),useSelectionAsDefult()以及setObjectType()

前2个是用来设置command argument的,后两个是设置object。
addFlag支持设置6个command argument,也就是我们可以在一个flag后面最多跟着6个argument。

object和command argument是不兼容的,我们可以看到mel表达式里面,flag argument都是有”-”前缀的flag,而object是没有的。

——————>晚上10点多睡,然后凌晨4点钟起来的话,对白天的影响其实不大,可以试试到4点半之后吧,那样身体应该会更舒服一点。但肯定不要两点起床。。我试过。。很不舒服。

MSyntax nodeInfo::newSyntax()
{
	MSyntax syntax;
	syntax.addFlag(NFLAG, NFLAGLONG, MSyntax::kString) ;
	syntax.makeFlagMultiUse(NFLAG) ;
	return syntax;
}

我们要写一个类似这样的静态方法,其实声明static的意思,就是说明这个方法是类的通用方法,那么我们就可以在类的内部调用这个方法了,而不需要实例化。
这个方法要在类注册的时候使用,作为第三个参数。

——————>MArgDatabase

这个类是用来处理参数的,它继承于MArgParser

所以,我们很多方法都是用继承自MArgParser的公开方法。

我们新建MSytax实例,并设置好我们需要的flag和object之后,在doIt方法中,同MArgList实例一起,来初始化MArgDatabase。

常用方法是:
isFlagSet(),getFlagArgument(),getObjects()

如果有在MSytax中有makeFlagMultiUse(),那么我们需要用getFlagArgumentList()
getFlagArgumentList和getFlagArgument参数相同,但是意义好像有些许不同。
第一个参数都是Flag(我可以传字符串,也可以定义宏),
在getFlagArgument中:
the index of the argument to the flag
在getFlagArgumentList中:
the desired instance of the flag on the command line
对于getFlagArgument来说,指定的i是后面argument的index,我们要获取argument需要给第三个参数指定合适的结构来存,

这些结构除了MSelectionList(存放MObject)可以放对象之外,其他都是存放单个对象,就是说,这里并没有对Array的支持!

所以,maya在这里就是说,argument要一个一个的取。取完之后要放在Array或者Point之类的结构,需要自己一个一个放。

mayaAPI(2)

我尝试了一下10点睡觉2点起的感觉,还不错哦。

——————>

Proxies

The Maya API uses proxy objects to create new types of Maya objects. Proxies are objects that you create but Maya owns.

proxy是啥类呢。。目前还不知道。继续看下文:

Naming Conventions

The Maya API uses a convention of prefixes on its classes to distinguish the various types of C++ objects that it uses.

MFn

Any class with this prefix is a function set used to operate on MObjects of a particular type.

MIt

These classes are iterators and work on MObjects much the way a function set does. For example, MItCurveCV is used to operate on an individual NURBS curve CV (there is no MFnNurbsCurveCV), or iteratively, on all the CVs of a curve.

MPx

Classes with this prefix are all Proxies, API classes designed for you to derive from and create your own object types.

M classes

Most of these classes are Wrappers, though there are others. For example, Function sets is a handle on Maya’s internal objects, and MGlobal is a class of static methods that operate globally and do not require an MObject on which to operate. (See Selecting with the API for information on MGlobal.)

加上之前的说明,我们可以列举一下maya基础的classes

wrapper(除了object和global之外,单独M开头的类),object(MObject),funtion set(MFn),proxy(MPx),iterator(MIt),global static(MGlobal)

其实整体来看,就可以分为wrapper和proxy两种。

——————>关于error

可以参照maya的readAndWrite这个app的写法。

另外还有独立文件errorlog,要使用它有几个静态方法:

MGlobal::startErrorLogging()

MGlobal::doErrorLogEntry()

MGlobal::stopErrorLogging()

这个以后再说。

——————>关于选择

我们还是使用MGlobal中的静态方法来进行物体的选择

物体的选择多种多样,但是主要运用到的API是:
MGlobal::getActiveSelectionList
MGlobal::setActiveSelectionList
还有其他API也提供相似功能,maya提供的API太多,也许是为了照顾不同的编码思想。
我们这里有个MSelectionList数据结构,这当然是个wrapper,里面有很多的方法,我们增删查改都很方便。

但是呢,这个静态方法并没有过滤机制,所以我们得到的list是完整的list。

如果我们想要过滤,就必须要用iterator。当然iterator的作用远不止如此,还需要多看API。

maya内核中贯穿了STL的思想,所以,我们也有iterator对这个wrapper进行操作。

对应MSelectionList的是MItSelectionList,我们可以做用MSelectionList来实例化它。

它操作的是List的一个copy,所以不会对List进行修改,同时,iterator也带有getDagPath方法。

官方的例子是这样的:

    MSelectionList & activeList = MGlobal::activeSelectionList();
    MItSelectionList iter( activeList );

    for ( ; !iter.isDone(); iter.next() )
    {
        MDagPath item;
        MObject component;
        iter.getDagPath( item, component );

        // do something with it
    }

——————>

在用function set来创建dag的时候,所得到的MObject我感觉一般都是transform节点

虽然这和我们所创建的dag节点类型有些不服,因为我们是用某个特定的function set创建,自然是希望得到相应的shape节点。所以这个返回值其实是废的。。不用考虑。

我们使用mel的时候,如果想得到shape节点,那就是使用hilite来选取。

在写插件的时候,我们操控dag对象就可以了,这个对象有几个关于shap节点的方法,其中这个具有通用性:

MStatus extendToShapeDirectlyBelow (unsigned int)

这个DAG Path里面很多方法都是和path有关的。很多操作都感觉和在outline里面查询位置有关。

所谓的DAG其实很大一部分是和path有关的,

而MObject主要是类型判断用处的。

而functon set 这个set的意思,融合了初始化和集合的意思,像MFnDagNode这个类,它主要是来操纵DAG Path 类的,两者的方法有些重合的感觉,但是毕竟Function set的功能更强大,用来查询和顺序更改(还有个复制功能,真是大杂烩。。)

但是function set毕竟还是初级的工具类,它只能修改一些结构上的和显示上的方式。

对DagPath的选择需要通过:selectionlist配合全局静态选择方法以及MIt的使用

当选好了需要的Path之后(transform和shape是两种DagPath Node ,要存为两个对象。)

理解DAG还是要依靠outline那种IDE视图比较好。

mayaAPI(1)

嗯。对于mayaUI操作部分,其实自己至少已经知道8,9成了,现在最需要的是加深对maya的掌握,其中最实在的方案就是研究maya的API,好了,这几天的任务就是学习maya的API,这个API很大哦,估计要花不少的时间了。

maya中的dynamic library是mll后缀的。

头文件的名字有三种含义:

Fn for function set, It for iterator, Px for proxy class.

proxy也就是adapter,就是属于修改接口类。

我们有4个SDK可以用:

OpenMaya—Contains fundamental classes for defining nodes and commands and for assembling them into a plug-in.

OpenMayaUI—Contains classes necessary for creating new user interface elements such as manipulators, contexts, and locators.

OpenMayaAnim—Contains classes for animation, including deformers and inverse kinematics.

OpenMayaFX—Contains classes for Autodesk® Dynamics.

OpenMayaRender—Contains classes for performing rendering functions.

——————>

maya提供了一个开发模板,这也是我第一次接触这个模板,

它位于devkit文件夹的pluginwizard中,按照上面的说明就可以安装了。

不过要注意一点,那就是版本问题,这个MayaPluginWizard2.0所支持的版本应该是2003

2005也是兼容的,只要把MayaPluginWizard.vsz中:

Wizard=VsWizard.VsWizardEngine.7.1

改为:

Wizard=VsWizard.VsWizardEngine.8.0

2010是不兼容的,我把这行改为VsWizard.VsWizardEngine.10.0

但是依然会报automation无文件错误。这个比较让人头疼。今天我装了05又卸载了05。。再装了05。。

都是这个兼容问题。

——————>

使用这个模板它会生成project,直接编译就可以生成mll了,很方便的。

——————>

小玩了一下maya的stand alone应用,其中surfaceCreate.exe

会把ma文件存放在:C:\Documents and Settings\Administrator\My Documents\maya\projects\default下。

没有研究它的makeSurf函数是如何写的。不过至少算个入门吧。

readandwrite.exe非常让我痛恨。。这个maya用一种比较奇怪的格式来取地址:

它使用”/”而不是”\”,readandwrite.exe的默认文件夹依然是上面的,它转换之后比较可喜的是,不仅文件大小有所缩小,而且文件会从6模式变到4模式状态下。

MFileIO::saveAs命令原来有这样的用处,呵呵。

其实这个readandwrite更大的用途是用来做版本转换的,配合asciitobinary这个app,就可以做到不打开maya进行转换了,非常方便呢!!遇到某些版本不符合的文件,就可以试试这个。

我想,应该有个命令来设定默认路径的,这个要找找看。(耗费了我好多时间,搜搜google,其实关键词很重要,我换了几次才找到答案。)

——————>开始plug-in之旅

MAYA_PLUG_IN_PATH这个环境变量是maya用来scan 插件的路径的。

修改这个变量值会是个好主意,要不然我的mll和系统的mll放在一起,岂不是很乱。。

所以呢,我试了一下改写环境变量,在用户变量里面加上

MAYA_PLUG_IN_PATH,它的值就是我的mll的路径。

这个果然是可行的,设置环境变量的方式我也知道了,那就是在HKCU/Environment里面新建一个SZ就可以了。

还是很简单的。想要动态加载mll的话,还有一个loadPlugin方法,动态卸载有unloadPlugin方法

现在我体验了一下最简单的插件,不过这个插件只有一个入口方法,肯定有方法提供多个入口的,接着看下去吧。

——————>

原来目前我用的是simple command plug-ins的模板。

它使用MSimlpe.h

这个的好处就是用一个宏就可以解决问题了DeclareSimpleCommand

这个宏的作用应该就是把我们的方法注册为一个类

而我们就简单的写个doit函数的实现就行了

但是这个很局限的,它也不能写redo,undo功能。
——————>

MStatus是个很重要的类,它的头文件有很多operator操作,我有点困惑。先不管这些,遇到问题再说。。

DeclareSimpleCommand的解释是这样的:

The DeclareSimpleCommand macro requires three parameters: the name of a class that will be used to implement the command, the name of the vendor (or author) of the command, and the command’s version number.

As in MSimple.h, the DeclareSimpleCommand() macro saves you from writing the registration code necessary for Maya to properly recognize your file as a plug-in. To keep it simple, though, you cannot specify an undo method for the command, so you cannot create truly undoable commands using this macro.

后面有一行解释,就是不带有undo的plugin的用途:

Commands that do not support undo must not change the state of the scene in any way. They can be used to query different aspects of the scene, but not to change anything. If an non-undoable command does in fact change anything, Maya’s undo capability will break.

——————>

原来maya的output window是用来做cout输出的哦。。我才知道呢。maya的helloworld原来是在这里写东西,呵呵

——————>

看到的第二个例子是个创建NURBS 曲线的,这个例子融合了2个方面,一个是对于参数列表的使用方式,一个是NURBS的创建方式。

NURBS的创建方式暂时不考虑(附录A里面),先看看参数列表的迭代:

for ( i = 0; i < args.length(); i++ )
		if ( MString( "-p" ) == args.asString( i, &stat )
				&& MS::kSuccess == stat)
		{
			double tmp = args.asDouble( ++i, &stat );
			if ( MS::kSuccess == stat )
				pitch = tmp;
		}
		else if ( MString( "-r" ) == args.asString( i, &stat )
				&& MS::kSuccess == stat)
		{
			double tmp = args.asDouble( ++i, &stat );
			if ( MS::kSuccess == stat )
				radius = tmp;
		}

C里面是没有类似windows命令解释器里面的参数传递方式的,C是写了方法来修改的,转化为自己的所认识的数据结构。
在windows下面自然是利用API:GetCommandLine

——————>

Interacting with Maya

Maya’s API contains four types of C++ objects which you use in the code to interact with Maya. These are wrappers, objects, function sets, and proxies.

Object ownership in the API

The combination of an object and a function set is similar to a wrapper, but the distinction is necessary to simplify ownership. Object ownership in the API is important. If not properly defined, you may delete something the system needs, or use something the system has just deleted. API wrappers, objects, and function sets remove any question of ownership. Therefore, the potential for using an object at an inconvenient time, like right after the system has deleted it, is removed.

这里提到的wrapper就是C++里面的类似template(其实就是动态生成的指针数组,当然还是具有面向对象性质的)

在maya里面,Wrapper是对基础数据类型的封装了。

function set也就是做容器,具体比较复杂。以后再说。

object ownership其实就是指这个object所占用的virtual memeory的归属问题,因为这段内存可能被更高级的对象或者系统所删去,所以可能造成错误的引用。

关于绑定

我觉得不应该局限于某一个种类的绑定,这对于我的视野来说会有些限制。

毕竟要绑定的话,天下万物,种类太多了,虽然可以分门别类,但是其中各有不同的。

这时的我,更应该了解其中通用的部分,在骨骼权重和设置小插件上下功夫。

当然,creativecrush上面有许许多多的插件,一一拿来做是不太可能的,对于这些插件,我也没有办法迅速的评估。

嗯,主要还是基础骨骼的设置还有权重。IKFK或者驱动表达式之类都是为了动画师方便,但是这个并不能短期的做得很好,它需要一个积累过程。

另外,生长动画需要研究,还有碎裂动画。

绑定可以有很多的方案的,穷极技巧还不如把基础打好。

明天来做什么呢。。研究maya2011?不对,应该花上2天时间,把身体绑定复习一下,然后去研究表情绑定。

之后研究动物(多足,翅膀),植物生长,器物(布料),最后才是碎裂(裂纹,碎片)

多接触一些种类,可以更深入的了解我用的工具

开始回归

开始回归到动画绑定这块了,还要更关注一些特效方面。

openGL也就沾一点,其他的以后再说了。NeHe的教程暂时结束到第6课。

目前的我,需要多maya绑定有个更全面,系统的认识。以及对解决问题的方法有一个统一的概括,对于maya的API和新功能,需要一个系统而有效的学习,这个是最为主要的需求!

嗯,要研究一下如何给maya挂插件以及maya的layout如何来做。

以前心中总有些不安定,不过现在好了,谢谢我的父母。

第 10 页,共 31 页« 最新...891011122030...最旧 »