Chinaunix首页 | 论坛 | 博客
  • 博客访问: 484286
  • 博文数量: 135
  • 博客积分: 3010
  • 博客等级: 中校
  • 技术积分: 905
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-24 19:31
文章分类

全部博文(135)

文章存档

2010年(135)

我的朋友

分类: LINUX

2010-07-15 16:23:06

前面已经写过一个Hello EGL的练习程序,手工设计和推算3D坐标是非常累,非常没有效率的,实际上我们应该使用专业的三维建模工具来制作模型。

Maya是我最喜欢的三维制作软件,除了操作界面非常符合我的直觉外,它强大而开放的MEL及SDK也是非常重要的因素。前些日子偶遇一个在好莱坞 混过三维制作的朋友说,最强悍而又符合程序员思维的工具是Houdini,不过还没学习过,目前Maya是我会用的最好的3D制作工具了。可惜曾经3D高 端的代名词SGI把它卖给Autodesk了,这让我心里多少有些郁闷。

Maya内部对3D场景有一个相当优美的描述,由结点连接而成的网络,这个网络可以MEL脚本来访问和控制,当然更可以通过SDK来利用和增强。

由于OpenGL|ES 1.x不支持QUADE,所以在为这类应用转换模型之前,注意先将模型表面三角化:
maya triangulate model

在MEL中转换模型的要点如下:

  1. 获取当前选中的物体清单,对每个物体分别进行转换和导出
    1. string $objs[] = `ls -sl`
    2. for( $obj in $objs ) { ... }
  2. 读取一个物体的所有的面
    1. string $f2v[]=`polyInfo -faceToVertex`
      1. 注意:这条命令在PSE版本里是不支持的,如果你是在使用这个版本学习建模的话,可能需要找一个有正式版本的朋友帮你导出模型。
      2. 这条命令的结果包含很多个字符串,每个字符串描述一个面,其内容类似于"FACE 0: 88 64 85",如果是没有三角化的模型,还会多出一个数字来(默认使用四边形)。
      3. FACE id:后面的数字是形成该面的顶点的索引
    2. int $faceCount = `size $f2v`
    3. 对于每一个面的字符串进行分析,读取构成面的顶点索引
      1. for ( int $i = 0; $i < $faceCount; $i++ )
      2. string oneFace[]
      3. tokenize($f2v[$i], $oneFace)
      4. (int) $oneFace[2,3,4] 就得到了顶点索引 (a,b,c)
  3. 读取物体所有的顶点
    1. int vc[] = `polyEvaluate -vertex`
    2. [0]是vertexCount
    3. 对于每一个顶点,读取其坐标
      1. for ( int $i = 0; $i < $faceCount; $i++ )
      2. string $point = $obj.vtx[$i]
      3. float v[] = `$pointPosition -l $point`
        1. ([0], [1], [2])就是(x, y, z)
  4. 读取法向坐标
    1. 对于每一个面 (参考2.2)
    2. 对于面的每一个顶点
      1. string $v = $obj.vtxFace[$f2v[$i*3 + 0,1,2]][$i]
        1. $i 是面的索引
        2. $f2v[$i*3 + 0,1,2] 分别取出第$i个面的三个顶点索引
        3. $obj.vtxFace[vertex][face]是一个关联数组或者说伪数组
        4. 比较有意思的是我在Maya联机文档里并没有找到这个vtxFace的说明,在网上倒有些讨论,感兴趣的可以之为关键字google之。
    3. 选中该顶点
      1. select -r $v
    4. 计算其法向
      1. float n[] = `polyNormalPerVertex -q -xyz`
      2. 取得的n[0],[1],[2]就是该顶点法向的(x,y,z)
  5. 恢复最初的选中状态
    1. select -r $objs;
  6. 读取UV坐标
    1. 对于每一个面 (参考2.2)
    2. 对于面上的每一个顶点 (参考4.2)
    3. 选中该顶点
    4. 分析UV坐标
      1. string u[] = `polyListComponentConversion -fromVertexFace -toUV`
      2. 如果返回数组长度为0,则未指定UV坐标
      3. 否则可获取UV坐标
        1. float uv[] = `polyEditUV -q u[0]`
        2. [0],[1]就是(u,v)
  7. 将读取的数据写入文件
    1. 打开文件 int $fid = `fopen $fname "w"`
    2. 写入数据 fwrite $fid $data
      1. 可写入MEL能识别的各种数据类型
      2. string写入后尾部会跟一个0(BYTE)
      3. int写入成32位
      4. float写入成64位,对应C语言里的double
      5. vector将写入三个float
    3. 关闭文件 fclose $fid

有经验的程序员都知道合理的代码重用是提高效率的好办法,自己重头写一个对于掌握以上要点是有好处的,但直接找一个现成的脚本来用显然可以节省大量 的时间,要知道,脚本程序的调试可是非常麻烦的。

网上可以找到一个简单易用的(), 作者也把这个脚本发布到highend3d() 了。 使用相当简单,选好要导出的物体,从ScriptEditor里打开这个脚本,在最后写上一行:exportToOgl( "fileName" ); 然后执行即可。我已经写了一个小程序,可以DUMP导出后的文件内容:可执行文件 程序源码(如 果你打算利用这些代码,注意有很多malloc没有free) 。

可以直接修改MEL以输出自己想要的格式,也可以修改程序适应导出格式,不过我觉得两者都太麻烦,还是再写一个转换程序将MEL输出格式转成自己认 为使用较为文件格式比较爽。

阅读(3172) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~