MAX SDK之对象处理(三)-(3.3 网格对象)

来源:互联网 发布:博微工程造价软件 编辑:程序博客网 时间:2024/05/16 14:14

三、对象处理

3.3 网格对象(Meshes)

      本节介绍网格类(Mesh),包括与Mesh类紧密相关的一些知识,如纹理贴图等。
      • Mesh网格的特点
      Mesh类是三角网格类,也就是说它的面片全部是三角形,与之相对应的物体对象类为TriObject。MAX中的一切可渲染的对象最终都必须转换为三角形网格类型,因为无论多复杂的物体,底层也只能绘制三角形。2.0版本后,提供了另一个MNMesh类来处理网格,该类可以完成很多复杂的拓扑编辑,并且可以支持三条边以上的面片。应该来说,MNMesh在实际使用中非常有用也非常方便。当然,在最终使用MNMesh类处理后仍然要将处理后的结果转换为Mesh类。
      从一个结点中可以使用INode::EvalWorldState()方法,获取几何物体的TriObject对象,而mesh是TriObject的一个数据成员,调用TriObject::GetMesh()即得到对象在该状态下的三角网格。
      • 构建Mesh网格对象的规则(Rules when Building Meshes)
      开发者在构建网格时应该遵循这些简单但非常重要的规则,以便修改器在几何管线中能够正确的处理网格。这六条基本的规则是:
      1. 在同一个方向上一条边最多只能被引用一次;
      2. 避免面片的自相交情况;
      3. 在创建面片时不要时面片的顶点出现重合;
      4. 不要用一个点来联接两个不同的网格部分;
      5. 将网格分解成较容易理解的子元素;
      6. 在任何方便的时候封闭网格;
      • 材质应用(Material Assignment)
      3DS MAX中的材质是处于结点级别上的,每一个结点对应一个材质。材质本身定义如何在网格上显示,如3ds max中的多重材质用材质标识符(Material ID)来对应网格面片所使用的子材质。用这样的方法,用户可以为一个网格对象匹配多个材质,并且可以为不同的面片设置不同的材质ID。
      • 纹理顶点和纹理面片(Texture Vertices and Texture Faces)
     网格类维持一个指向纹理顶点的指针,当网格分配UV坐标后就会生成一个纹理顶点数组,注意这些纹理顶点跟网格的顶点是完全独立的。此外与纹理顶点对应的是纹理面片,纹理面片是和网格面片一一对应的,这就使得每个网格面片都可以有自己的映射方式。
      • 贴图通道(Mapping Channels)
      在材质编辑器中用户可以选择纹理贴图通道,Coordinates卷展栏的Texture Mapping下拉列表中选择"Explicit Map Channel"。可以选择1-99之间的任何一个数组,1对应于3.0版本之前的TVerts数组,2-99是在3.0版本后使用的。如果选择"Vertex Color Channel",则Map Channel的微调控制项将会失效,原因是Vertex Color Channel对应的索引为0。
      在2.0版本的时候只有两个的贴图通道,一个是1.x版本中的贴图通道,另一个是顶点颜色通道。现在这两个通道仍然存在,只是它们的索引发生了变化。也就说,现在索引0表示顶点颜色通道(以前的索引为1),而索引1表示以前的贴图通道。改变的原因是因为顶点颜色的处理方式不同于贴图通道,这样做有利于将两种通道类型分离。
      处理通道的主要方法有下面这些:

      • 顶点颜色信息(Color Per Vertex Information)
      2.0之后和4.0之前,顶点颜色信息由下面几个公有数据成员表示:

      4.0版本后,对该数据组织方式进行了增强,所谓增强其实就是使得颜色顶点数组可以指向一个外部的数组,其中:

      • 面法线和顶点法线(Computing Face and Vertex Normals)
      使用过OpenGL的朋友应该对法线的概念非常清楚了。面法线决定了一个面的朝向,该朝向决定了它是否可见。这里在赘述一下它们的计算方法:
     (1) 面法线(Face Normal): 面法线的计算可谓是非常简单,它只需要对面片的两条边进行叉乘即可。
     (2) 顶点法线(Vertex Normal): 顶点法线的计算建立在面法线的基础上,它首先计算所有包含该顶点的面片的面法线,然后采用某种加权手段来得到一个平均的法线,该法线即可作为顶点法线。最简单的一种顶点法线确定方法是面法线简单平均,这也是比较经常使用的方法。当然这种简单平均的方法可能还不足以反应该顶点的方向状态,因此也存在对该顶点法线计算方法的改进,通常利用角度加权或者面积加权的方法来校正顶点的法线。从个人经验来看,面积加权的计算量较小并且起到了必要的校正作用。
      • 创建管线友好的网格

      3DS MAX对于开发者来说具有很大的弹性,几乎很少有规则限制。网格可以有洞,比如从一个长方体或球上删除面片后就后形成洞。网格可以由一系列独立的,不连通的单元组成,即使它们是自相交的。一个只有十个面片的“风扇型”模型可以使用相同的边(即使用相同的两个点)。一个栅格可以简单地由二维点集和一系列指向上面或者下面的面片来创建。
      然而,不是所有的网格都适合于在3DS MAX的管线中操作,例如布尔操作,像其它布尔操作一样,它将网格作为实体的外表面。布尔求交操作由两个操作数决定的体积来定义。而含有洞的网格,比如茶壶,是没有体积的,因此进行布尔操作会得到奇怪的结果。
      另外,在布尔或者其它复合物体和修改器中,要将网格转换到MNMesh中,而MNMesh中的有翼边结构决定每一条边只能控制两个面,所有上面说的“风扇形”物体就不能正确转换。如果一个网格不能正确地转换到MNMesh中,那么它在MeshSmooth, Tesselate,ShapeMerge,Connect,Boolean,Slice甚至更多的功能都不能正确实现。
      如果网格不是以易理解的方式创建,用户可能在修改器中处理它的时候遇到困难(如在Edit Mesh中)。当然,用户可以在Edit或者Editable Mesh中创建很奇怪的物体,但如果不需要的话,尽量避免在参数物体或者修改器中引入这些复杂的操作。
      最后,在创建管线友好的网格中,下面介绍几条重要的指导原则。它们不是必须要遵守的,但是你能够遵守越多,创建的网格在3DS MAX环境中就会越灵活。
      1. 一条边在同一个方向上最多被引用一次
      3DS MAX并不包含真正的“边”,这意味着如果你在一个面片中用到了点(a,b),你就需要在另外一个面片中以相反的方向引用它们,即(b,a)。在第二个面片就称为边(a,b)的另一边。如果相同的边被使用超过两次,或者在同一方向上使用超过一次,MeshSmooth和其它基于MNMesh的功能就会复制顶点以生成其它的面片来使用这些边。
      2. 避免自相交
      作为自相交的例子,我们参看3DS MAX标准基本体中的茶壶,它有四个组成部分,每一个组成部分都是一个独立的元素,但是茶壶柄和茶壶嘴都与茶壶主体相交。即使这个模型通过补洞修改器实现封闭,在布尔操作中也会出现问题,因为无法界定什么是“里面”什么是“外面”。
      对于自相交,如果想要用SDK中的布尔操作,在计算其正确的连接结果是非常费时的。如果独立的元素是封闭的或者是适合布尔操作的,那么仅仅对它们进行并操作就可以了。布尔操作速度有些慢,但是它的结果在通常一些情况下还是明确的。
      3. 避免创建顶点可能处于同一位置的面片
      一个面片包含相同的点两次或者包含两个不同但处于同一位置的点,这种情况对模型没有任何好处,反而会干扰模型的显示和渲染。在旋转面片等操作(比如ShapeMerge或者Editable Mesh的Cut函数)都会引起混乱。最后,Edit Mesh使用者不得不对处于同一位置的多个点进行排序,以便找到他们想要移动的那个点,而这时候,用户将会因为难以分辨这些点而感到绝望。
      4. 不要试图用一个点来连接两个独立的网格部分
      比如两个BOX共享某一个顶点,这些顶点在MNMesh中将被分割成两个点.MNMesh可以处理这些点,但复制操作偶尔会导致奇异结果。
      5. 如果一个网格看起来就是一个独立的元素,那么它就应该是一个独立的元素
      用户不应该将看起来是一个独立的物体拆卸成许多元素。如果一个模型看起来像长方体,就不应该把它拆成6个独立的面。这不仅在MeshSmooth等修改器中能够正确运行,而且在Edit Mesh中也能得到合理的结果。
      6. 在任何方便的时候使网格封闭
      一个封闭的网格说明它的每一条边都有两个面,一边一个。封闭网格在三维空间表示一个实体物体,而开放的网格仅仅是一个壳;封闭物体适合做布尔操作而非封闭物体不行,因为没有办法确定A的某一部分是否在B物体的“里面”,反之亦然。封闭物体可以测量体积而非封闭物体没有体积。
      在Editalbe Mesh中经常要删除或创建面片,但是,要避免留下细小不可见的洞,即两个边界边非常靠近以致于这些洞不容易被发现。用户可能没有发现这些洞,但它们在依赖于实体、封闭模型的管线中将会产生问题并影响渲染。

原创粉丝点击