表面。如可以建立定位点表面或CV表面。使用哪一种方法取决于设计者喜欢怎样建模。CV点的作用就象用手指按压一团黏土而使之成型。定位点方式象用针尖去按充满胶的物体,它作用于点及与其接近的区域。
凡是可以想象出来的东西都可以使用NURBS方法为其建模。NURBS方法最主要的好处是它具有多边形方法的建模及编辑的灵活性,但是不依赖于复杂的网格来细化表面。建模时你可以使用曲线来定义表面。这些表面在视口中看起来细节较少,但在渲染时却有更高层次的复杂度。许多动画设计者使用NURBS来建立人物角色,这主要是因为NURBS方法可以为你提供光滑的更接近轮廓的表面,并使网格保持相对较低的细节。由于人物角色一般比较复杂,因此与多边形方法相比使用NURBS可以提高性能。如图四,是一个NURBS人物模型,这里人物面的网格分布和接缝与多边形的建模方法是不一样的。
谈起NURBS的弱点,很难指出它有什么严重的问题,至少目前是这样的。实际上,NURBS建模几乎可以用于任何场合。尽管如此,NURBS还是有一点不能和多边形建模相比,那就是——简单。NURBS模型的最终设计比较复杂。用NURBS方法建模很难创建直角的NURBS曲面,大部分的NURBS模型需要有弯曲部分。这就是说,尽管一个模型看起来有直角,近距离看就会发现实际上在边的周围是光滑的。另外,NURBS模型的接缝问题在制作动画时也比复杂。NURBS建模方法比较适合无机类物体,Maya的NURBS工具多来源于Alias Studio Tools,但不包括一些用于精确计算的工具,所以不适合工业造型,只适合于视频动画的制作,它只重视不标准模型的塑造,精确性不高,最好不要从事专业的工业设计。
细分曲面建模可以简化复杂物体的制作过程,他吸取了Polygon和NURBS两种建模方法的技术优势,不但拥有多边形建模的灵活多变的强大功能,而且还能象NURBS模型一样保持模型的圆滑。对多边形进行多次细分,从而达到光滑细腻的效果,也就是说可以对局部区域的多边形进行细分,并能通过控制模型的渲染精度,是多边形建模的强有力的升级。但是细分技术出现的较晚,虽然其功能强大,但现在角色建模中还是以多边形的方法居多。
Maya软件还有独创的雕刻建模,直接使用雕刻建模,直接使用雕刻刀工具对表面进行雕刻,是建模过程更加形象化。Maya同时还独创了立体绘图技术,
可在模型表面直接绘制三维物体,如羽毛,胡须等。这些都是角色动画的重要工具,目前立体绘图技术仅局限于NURBS模型。
另外还有纹理置换建模,是使用纹理贴图的黑白值去映射表面的几何体,常用于制造一些立体花纹,山脉地形等模型。综合这些建模技术。多边形模型就好比点阵图像,NURBS模型就好比矢量图形,支持无级缩放,但是无论是什么类型,最终进入渲染时都会以多边形方式进行解释和计算。寻找开始点的时候,首先要自问“哪儿是根基?”对于角色来说,通常是从人体重心开始然后向外扩展。从根基出发是开始建模过程的最可靠的方法。在选定使用哪一种建模方法后,开始应该考虑如何为自己的设计建模。无论选择选择的是多边形建模方法,NURBS建模方法或者是其它的方法,还是它们的组合,都要根据需要确定在模型中,哪儿是建模开始的最佳位置。以上介绍了有关Maya的几种建模方法,同样适用于角色建模,具体选择哪一种,主要在于自己的熟练程度和习惯。
第三章Maya的C++应用程序编程接口
Maya的开发体系是一个三层体系结构,底层是Maya核心,中间层是C++API,高层是用户或开发人员。Maya核心由Alias Wave front开发的所有内部函数和数据组成,用户及普通开发人员不能直接访问。与Maya核心的所有通信,包括创建、操纵或删除数据,都必须通过C++API层进行。C++API层又称为Maya抽象层,是由一组C++类组成的,这些类的成员函数定义了用于访问和控制Maya核心的全部方法。用户或开发者可以调用中间层C++API的函数来创建、获取和操纵Maya数据。
三层体系结构的好处是显著的。第一,开发人员不必详细了解Maya核心当前实现的细节;第二,Maya工程师对Maya核心的改进不会直接影响原先的API插件的正常运行;第三,C++API作为中间层,对致命性错误有过滤作用,这些致命性错误往往会导致Maya关键数据的丢失。
Maya C++API可以创建的Maya功能插件,除了DG节点以外,还有Maya命令、变形器、着色器、操纵器、定位器、动力场、发射器等。
3改进的Maya自定义节点的创建方法
在自定义节点创建之前,需要先建立场景,确定所有需要控制的场景属性,如某物体的位置属性,速度属性,甚至更复杂的材质、灯光等等。这些场景属性将与节点的属性关联,实现数据的交互,以实现节点的个性化控制。 3.1 Maya的C++编程环境的搭建
搭建Maya编程环境是利用C++API开发Maya插件(包括自定义节点)的基础。本文选用Maya6.0和Visual C++.net,在Microsoft Windows平台下建立编程开发环境。参考Maya帮助或Maya官方网站,完成Maya的C++编程环境的搭建,在VC.net中将会生成Maya Plug-in Wizard(Maya插件向导)。通过该向导会自动生成开发所必需的工作区、项目和一些源代码文件,可以大大减轻开发者的工作量。
3.2项目工程组的建立
使用VC.net的Maya Plug-in Wizard向导来创建Maya节点插件,并在向导中选取Dependency Graph Node,以明确开发的插件是节点类型。完成工程创建后,在项目工程组里将自动生成plugin Main. cpp和以节点为名的程序文件,如创建的节点为attraction,则将自动生成attraction Node. cpp和attraction Node.h。
在文件plugin Main. cpp中的initialize Plugin()和Uninitialize Plugin()函数用于节点的注册和注销,以及一些错误检查,保留其默认内容完全可以满足一般节点的要求。
Attraction Node.h中定义了以MPx Node为基类的节点类,如class attraction:public MPxNode。节点类的成员变量中包含了所有的节点属性(Node attribution),可根据节点的实际需求增加或修改。节点类在默认情况下,定义了三个的成员函数,缺一不可,一是creator()函数,用于创建节点时,实例化自身;二是compute()函数,用于节点计算的具体实现;三是initialize()函数,用于节点属性的初始化设置。这三个成员函数的函数体均在attractionNode.cpp中得到具体实现。在节点类中,除了computer()以外的所有成员变量和函数均是静态的,即所有实例对象共享这些数据。 3.3节点属性的增加和修改
一个节点可以有多个输入属性和多个输出属性,作为节点类的成员变量存在,如:
static MObject inAt,inAv,inBt,inBv,outAt,outAv,outBt,outBv,frame,id;输入/输出属性变量均是MObject的实例对象,对于C++API来说,输入/输出属性的数据都是具有Maya数据结构的,属性变量的输入/输出性由具体程序操作使用决定。程序从输入属性中获取数据,经过计算,将新的数据传给输出属性。所有Maya节点都具有唯一的标识号,MTypeId类的实例对象id就是自定义节点的标识号,其值定义在区间(0~0x7FFFF)内,以区别Maya内部节点,避免产生节点冲突。
3.4算法实现
节点属性的计算是在函数computer()中完成的,该函数带有两个参数,一个是MPlug类型的plug,用于指示哪个节点属性需要重新计算,另一个是M Dat-a Block类型的data,包含了节点当前要使用的所有数据。其函数声明方法是“MStatus compute(const M Plug & plug, M Data Block & data)”。
需要指出的是,节点的属性与属性数据是有区别的,属性是创建节点所需使用的属性数据的结构和蓝图,而具体的属性数据存储在MDataBlock类的对象data中,并通过Mplug类的对象plug来获取和设置其状态和其他信息。
(1)发出重新计算请求
利用对象plug来监视属性的状态,仅当属性处于未更新状态时,才进入具体的算法模块计算新的数据,并更新属性数据。如,代码块if(plug==outAt||plug==outAv){......},就实现了对输出属性out At和out Av的监视。
(2)输入属性数据的获取和设置
当监视到某个属性需要更新时,首先要获得输入属性的数据,以用于具体计算。具体方法是通过参数data,调用MData Block类的input Value()函数获取输入属性句柄对象,此函数将返回一个M Data Handle类型的对象,该对象为只读,不能改写。如,MDataHandledatinAt=data.inputValue(inAt,&returnStatus);对象datinAt具有只读性,需调用MDataHandle类相应的函数进行数据转换。如,MVector At=datinAt.asVector();即,将对象datinAt的数据赋予Maya向量类型变量At。不同类型的数据可调用相应的as方法转换,常用的还有asInt(),asFloat(), asDouble() ,asLong()等。上述操作使节点属性inAt的当前属性数据传递给了变量At,而变量At才是实际算法中真正可使用的属性值。
(3)具体算法
不同的自定义节点有不同的算法,但最根本的就是根据所得到的输入数据产生新的有用数据。比如,模拟两物体(A和B)之间的引力作用,可用以下代码实现,MVector oAt,oBt;//记录新数据if(f==1)//第一帧,通常做初始化工作{??//按节点实际需求初始属性变量} else//其他帧
{//通常是具体的算法内容