当前位置:文档之家› Maya的模型信息提取研究

Maya的模型信息提取研究

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

mvector add;

lgetnormals=vtxnormals.length();

for (int i=0;i

{ add.x = add.x+vtxnormals[i].x;

add.y = add.y+vtxnormals[i].y;

add.z = add.z+vtxnormals[i].z;}

add.normalize();

vtxtestnormals.append(add); }

通过以上几步,我们将成功得到所需要的点的空间坐标,点的个数,面的个数,每个面与相应点的索引,每个点的点法线通过归一化之后的信息。通过这些信息,我们就能成功的利用opengl模拟出模型的体信息

4 opengl仿真

通过opengl中的glbegin(gl_triangles)函数我们可以将得到的数据重新组合成图形,因为我们只提取了基本模型信息,对于纹理和材质并没有提取,所以,只能生成模型本体,通过设置glpolygonmode可以将我们形成线框实体化。如图2是软件中的图形,图3是仿真后的图形。

5 结论

我们从maya的数据结构入手,分析了他的模型信息储存结构,通过得到正确的模型信息我们就能将模型从maya中迁移出来,利

相关主题