天行健 君子当自强而不息

三角网格(1)

 

最简单的情形,多边形网格不过是一个多边形列表;三角网格就是全部由三角形组成的多边形网格。多边形和三角网格在图形学和建模中广泛使用,用来模拟复杂物体的表面,如建筑、车辆、人体,当然还有茶壶等。图14.1给出一些例子:

当然,任意多边形网格都能转换成三角网格,三角网格以其简单性而吸引人,相对于一般多边形网格,许多操作对三角网格更容易。

 

表示网格

三角网格为一个三角形列表,所以最直接的表示方法是用三角形数组:

Listing 14.1: A trivial representation of a triangle mesh

struct Triangle {
  Vector3 p[3];
};

struct TriangleMesh {
  int triCount;
  Triangle *triList;
};

对于某些应用程序,这种表示方法已经足够。然而,术语"网格"隐含的相邻三角形的连通性却未在这种简单表示中有任何体现。实际应用中出现的三角网格,每个三角形都和其他三角形共享边。于是,三角网格需要存储三类信息:

(1)顶点。每个三角形都有三个顶点,各顶点都有可能和其他三角形共享。

(2)边。连接两个顶点的边,每个三角形有三条边。

(3)面。每个三角形对应一个面,我们可以用顶点或边列表表示面。

 

索引三角网格

在索引三角网格中,我们维护了两个列表:顶点表与三角形表。

每个顶点包含一个3D位置,也可能有如纹理映射坐标、表面法向量、光照值等附加数据。

每个三角形由顶点列表的三个索引组成。通常,顶点列出的顺序是非常重要的,因为我们必须考虑面的"正面"和"反面"。从前面看时,我们将用顺时针方向列出顶点。另外一些信息也存在这一级中,如预先计算的表面法向量,表面属性(纹理映射)等。

程序清单14.2给出了一段高度简化的代码:

Listing 14.2: Indexed triangle mesh

// struct Vertex is the information we store at the vertex level
struct Vertex 
{
    // 3D position of the vertex
    Vector3 p;

    // Other information could include texture mapping coordinates, 
    // a surface normal, lighting values, etc.
}

// struct Triangle is the information we store at the triangle level
struct Triangle 
{
    // Indices into the vertex list
    int vertex[3];

    // Other information could include a normal, material information, etc.
}

// struct TriangleMesh stores an indexed triangle mesh
struct TriangleMesh 
{
    // The vertices
    int vertexCount;
    Vertex *vertexList;

    // The triangles
    int triangleCount;
    Triangle *triangleList;
};

实践中,三角网格类会有一系列方法,用于存取和维护顶点、三角形列表。当然,存储多边形网格,还需要定义一个多边形类,用来表达有任意多顶点的面。为简化和提高效率,我们可以对每个多边形的最大定点数做出限制。

注意到,索引三角形列表中的邻接信息是隐含的。例如:边信息没有直接存储,但我们还是可以通过搜索三角形表找出公共边。和前面"三角形数组"方式相比,这种方式确实能节省不少空间。原因是信息存于顶点级别,它的整数索引比之三角形数组里存储的顶点重复率要小得多。

 

高级技术

简单索引三角网格对于基本应用已经足够了,但为了更加高效地实现某些操作还可以进行一些改进。主要的问题是邻接信息没有显式表达,所以必须从三角形列表中搜索。另一种表达方法可以在常数时间内取得这种信息。

方法是维护一个边列表,每个边由两个端点定义,同时维护一个共享该边的三角形列表。这样,三角形可视为三条边而非三个点的列表,也就是说它是边列表而不是点列表的索引。该思想的一个扩展称作"winged edge"模型,对每一顶点,存储使用该点的边的索引。

 

针对渲染的特殊表达

大多数图形卡并不直接支持索引三角网,渲染三角形时,一般是将三个顶点同时提交。这样,共享顶点会多次提交,三角形用到一次就提交一次。因为内存和图形硬件间的数据传输是瓶颈,所以许多API和硬件支持特殊的三角网格式以减少传输量。基本思想是排序点和面,使得现存中已有的三角形不需要再次传输。

从最高灵活性到最低灵活性,我们讨论三种方案:顶点缓存,三角带,三角扇。

 

顶点缓存

与其说顶点缓存是一种特殊的存储格式,不如说是API和硬件之间的一种存储策略,用以发挥连续三角形顶点一致性的特点。通常,高级代码不需要了解顶点缓存是如何实现和执行的。

和其他缓存机制类似,顶点缓存基于最近使用的数据将来仍被使用的原则。图形处理器缓存一小部分(如,16个)最近使用的顶点,当API要发送顶点时,首先探测缓存内是否已存在。当然,这要求API了解图形卡缓存的大小和替换机制。若缓存内没有该顶点,则发生脱靶,API发送顶点并更新缓存;若缓存内有该顶点,就命中,API通知图形卡"使用缓存内位置x的顶点"。

顶点缓存其实是一种底层的优化手段,任何三角网都可用高级代码实现正确渲染而不用考虑缓存。但进行顶点顺序的调整,使共享顶点的三角形集中发送有助于提高效率。这种调整只需要进行一次,并且可以离线进行,它只会对性能有帮助,不会使没有缓存的系统性能降低。善用缓存,可能使发送到显卡的顶点数降低到平均每三角形少于一个。


posted on 2008-03-02 10:05 lovedday 阅读(3609) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论