Maya的模型信息提取研究
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Maya的模型信息提取研究
摘要 maya是autodesk公司中和3dmax并列的三维建模和动画
软件,而且在模型的细节渲染方面有着更为突出功能,随着技术的
进步和用户对三维图形动画要求的提高,maya已经广泛的应用到电
影、电视、游戏等领域。因此,如果能将maya中的模型信息从maya
软件中提取出来,并按照一定的渲染方法重新组建,就能将依赖
maya的图形文件用于其他设备上进行三维展示,例如平板电脑,智
能手机等移动设备上。这样,就能在很大程度上提高产品模型的展
示效果。本文将介绍如何利用maya的api 将maya模型中的信息提
取出来,并按照opengl的模型渲染格式进行储存。
关键词 maya;node;mesh;face;vertex;opengl
中图分类号tp31 文献标识码a 文章编号 1674-6708
(2012)58-0157-02
0 引言
要成功的提取maya模型中的信息,必须要知道maya中的数据
结构,知道maya中的api运行模式,掌握maya模型的类别,模型
的构成方式,模型属性组成等等信息。当掌握了这些信息之后,就
能实现模型重构和再实现,以完成模型在其他显示平台的迁移。
1 maya的核心数据结构dependency graph
1.1 概述
我们可将整个maya 系统拆分为3个主要组成部分: 图形用户
界面,mel command engine ,dependency graph 。
maya用户可以与maya gui进行交互,可以选择菜单项,更改参
数,使对象动画化以及移动对象等等,当与用户界面进行交互时,
maya实际是再发出mel命令,这些命令呗发送到command engine,
并在这里被解释并执行。
大部分的mel命令运行与dependency graph直接交互。这样做
是因为dependency graph可以被直观地看做是一个完整的场景,
这个场景是组成3d世界的所有重要数据和信息。dependency graph
不仅定义当前场景中有什么数据,还定义了数据的处理方式。
dependency graph 实际就像maya的心脏和大脑。
1.2 dependency graph 与 节点
我们将dependency graph简称为dg,dg是maya的核心,它包
括maya模型的所有基本构建,它允许你创建任意的数据,这些数
据进行一系列的操作处理后,最终生成一些经过加工的数据。在dg
中,数据及其操作被封装为节点,一个节点含有任意数目的插槽,
其中还有maya使用的数据,节点也包含一个操作符,用于对其数
据进行处理以生成一些其他的数据。
由图1所示节点实际是maya的基本构件,每个节点都有一个或
者多个与其相关的特性,这些特性通常呗成为属性,每个节点根据
其属性的不同实现对数据的不同操作。
2 maya 模型的组成结构
maya中有多种模型类型,但最常用的静态模型主要使用的是
nurb,polygon 和subdiv。
2.1 mesh 与 polygon
mesh 英文翻译为网格,在maya中则用于代表一个三维实体,
例如一个立方体、圆锥体、球体,这些都是mesh。而模型中的每个
面则就是polygon,如下图的球体模型则更能体现出mesh和
polygon的关系,图中的每个四边形方格就是一个polygon。
2.2 polygon的组成
polygon主要有3个主要元素:vertices , edges, faces除
此之外还有两个有助于理解和分析polygon如何工作和运行的元素
face-vertices 和 uvs。
polygon的vertices元素是一个表示3d的浮点型数组,每个点
都有自己的元素id,每条边和每个面都是基于这个数组产生的。如
表1。
3d float point 行中每一个元素都是一个三维坐标(x,y,z)
edge元素储存在一个边数组中,数组中的每个元素储存着两个
整型变量,储存着vertices的id,第一个表示边的起始点,第二
个表示结束点,这样储存数据就能表示边的点组成,点边的方向以
及边的编号。如表2。
edge行中的每个元素都是一个二维的点,表示边的起始点和结
束点的id faces的元素储存在一个整数型数组中,每个面被一系
列数字表示,每个数字都表示一个边的索引。与之相应的的是face
offset 数组,这个数组标示了每个面在face数组中每个面的起始
点,具体格式如表3,表4。
如表4中所示,face 1 的起始点在 edgeid的index 3 即,face
1是由,0,1,2三条边组成的三角面。
face-vertices 是将一个mesh中的每个面的相对vertices 索
引,就是说,他们都是以0为起始的整数数列。并不是以整个mesh
为基础的全局索引坐标。uv uv是专门用于描绘纹理信息的元素,
其对应着每个每个点都有与之相对应的uv,我们要把二维贴图与
3d模型想匹配,必须找到每个3d坐标对应的uv。
3 提取mesh polygon 的信息的程序实现
3.1 选取模型目标
在maya的c++ api 中,选取模型有两种形式,第一种选取指定
模型信息,第二种选取全部模型信息。
选取指定模型需要用到的变量类型 : mselectionlist 。顾名
思义,这个变量类型储存了用户的模型选择信息,即用户在软件界
面选择的图像(单选或者多选)。然后利用mglobal类里面的成员
函数getactiveselectionlist函数将mselectionlist变量进行赋
值,如此我们设置的mselectionlist类型变量就得到了赋值。
得到了选取列表之后,就需要利用选择迭代器对选择列表里面
的内容进行遍历。mitselectionlist ,mitselectionlist 也是一
个类,里面有丰富的函数可以对选择列表里面的内容进行操作,利
用里面的next()函数 和isdone()函数可以对他储存的变量进
行遍历mitselectionlist遍历的内容其实就是我们上面提到的
dependency graph 中所提到的节点dagnode,但是
mitselectionlist类中并没有直接提取节点的函数,它值提供了每
个节点的路径dagpath,通过dagpath我们就可以定位到相应的节
点对模型操作。
3.2 获取模型信息
要实现模型的转移,就需要知道模型的点信息,面信息,点信
息包括 点的空间坐标,点的模型序列,点法线信息。面信息包括
面个数,每个面的组成,在模型构成中,任何一个面都可以分解成
若干个三角面,而maya中的模型构成也是按照这个原则,因此,
我们提取面的信息的时候是将模型中的面都分解为若干个三角面,
并将每个面的点和点的索引相联系。
3.2.1 提取点的坐标以及索引
通过上面一步我们得到了dagpath,这里我们就以polygon模型
为例提取上面提到过的模型信息首先创建mesh类的实力 mfnmesh
这个类 ,通过这个类我们就可以直接得到点的信息以及三角面的
信息,这里我们得到的点是以一定顺序储存的point序列。以立方
体为例,point序列的索引为0-7,分别记录了空间坐标的点,通
过getpoints函数我们就可以得到这个数列。
3.2.2 提取每个三角面的索引
通过mfnmesh类之中我们通过gettriangles函数就可以得到面
的信息,主要得到两变量,一是我们这个立方体的三角面的个数,
因为六面体是六个四边形,因此我们得到的三角面是十二个,而另
一个变量就是每个三角面的点与我们得到的点的对应索引,以这个
立方体为例,我们得到的数列如下
(0,1,2,2,1,3,2,3,4,4,3,5,4,5,6,5,7,6,7,0,0,7,1,1,7,3,3,7
,5),这些点每3个对应一个面,因为我们以立方体为对象,所以
每六个点为同一个四边形的两个三角面,而且可以看出每个四边形
的组成。
通过上面的步骤我们成功的得到了每个三角面的信息,通过这
些单独的三角面信息我们就能通过opengl进行仿真对每个面配上
颜色我们就能实现模型结构的提取。
3.2.3 提取每个点的法线
为了使一个细分度很高的polygon mesh 在转移的情况下表现的
更加平缓和光滑,即表现的和软件中更加相似,就需要提取每个点
的法线。
这里我们用到的是mitmeshvertex类来对mesh的每个点进行遍
历,然后通过getnormals函数得到一个mvectorarray变量,里面
储存了每个点相对于每个面的法线值,通过计算我们可以得到每个
点的实际法线。
下面是具体程序实现:
mitdag dagiter( mitdag::kbreadthfirst, mfn::kmesh,
&stat );
for ( ; !dagiter.isdone(); dagiter.next())
{ mdagpath dagpath;
stat = dagiter.getpath( dagpath );
if ( stat )
{ mfndagnode dagnode( dagpath, &stat ); }
mfnmesh fnmesh( dagpath );
mintarray trianglecounts;
mintarray trianglevertices;
mpointarray vertexlist;
fnmesh.gettriangles(trianglecounts,trianglevertices );
fnmesh.getpoint(vertexlist);
mvectorarray
vtxnormals,vtxtestnormals,vtxfacevatexnormals;
int lgetnormals;
for ( ; !vtxfn.isdone(); vtxfn.next() )
{ vtxfn.getnormals(vtxnormals ,mspace::kworld );