最簡單的情形,多邊形網(wǎng)格不過是一個多邊形列表;三角網(wǎng)格就是全部由三角形組成的多邊形網(wǎng)格。多邊形和三角網(wǎng)格在圖形學(xué)和建模中廣泛使用,用來模擬復(fù)雜物體的表面,如建筑、車輛、人體,當(dāng)然還有茶壺等。圖14.1給出一些例子:

當(dāng)然,任意多邊形網(wǎng)格都能轉(zhuǎn)換成三角網(wǎng)格,三角網(wǎng)格以其簡單性而吸引人,相對于一般多邊形網(wǎng)格,許多操作對三角網(wǎng)格更容易。
表示網(wǎng)格
三角網(wǎng)格為一個三角形列表,所以最直接的表示方法是用三角形數(shù)組:
Listing 14.1: A trivial representation of a triangle mesh
struct Triangle {
Vector3 p[3];
};
struct TriangleMesh {
int triCount;
Triangle *triList;
};
對于某些應(yīng)用程序,這種表示方法已經(jīng)足夠。然而,術(shù)語"網(wǎng)格"隱含的相鄰三角形的連通性卻未在這種簡單表示中有任何體現(xiàn)。實際應(yīng)用中出現(xiàn)的三角網(wǎng)格,每個三角形都和其他三角形共享邊。于是,三角網(wǎng)格需要存儲三類信息:
(1)頂點。每個三角形都有三個頂點,各頂點都有可能和其他三角形共享。
(2)邊。連接兩個頂點的邊,每個三角形有三條邊。
(3)面。每個三角形對應(yīng)一個面,我們可以用頂點或邊列表表示面。
索引三角網(wǎng)格
在索引三角網(wǎng)格中,我們維護了兩個列表:頂點表與三角形表。
每個頂點包含一個3D位置,也可能有如紋理映射坐標(biāo)、表面法向量、光照值等附加數(shù)據(jù)。
每個三角形由頂點列表的三個索引組成。通常,頂點列出的順序是非常重要的,因為我們必須考慮面的"正面"和"反面"。從前面看時,我們將用順時針方向列出頂點。另外一些信息也存在這一級中,如預(yù)先計算的表面法向量,表面屬性(紋理映射)等。
程序清單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;
};
實踐中,三角網(wǎng)格類會有一系列方法,用于存取和維護頂點、三角形列表。當(dāng)然,存儲多邊形網(wǎng)格,還需要定義一個多邊形類,用來表達有任意多頂點的面。為簡化和提高效率,我們可以對每個多邊形的最大定點數(shù)做出限制。
注意到,索引三角形列表中的鄰接信息是隱含的。例如:邊信息沒有直接存儲,但我們還是可以通過搜索三角形表找出公共邊。和前面"三角形數(shù)組"方式相比,這種方式確實能節(jié)省不少空間。原因是信息存于頂點級別,它的整數(shù)索引比之三角形數(shù)組里存儲的頂點重復(fù)率要小得多。
高級技術(shù)
簡單索引三角網(wǎng)格對于基本應(yīng)用已經(jīng)足夠了,但為了更加高效地實現(xiàn)某些操作還可以進行一些改進。主要的問題是鄰接信息沒有顯式表達,所以必須從三角形列表中搜索。另一種表達方法可以在常數(shù)時間內(nèi)取得這種信息。
方法是維護一個邊列表,每個邊由兩個端點定義,同時維護一個共享該邊的三角形列表。這樣,三角形可視為三條邊而非三個點的列表,也就是說它是邊列表而不是點列表的索引。該思想的一個擴展稱作"winged
edge"模型,對每一頂點,存儲使用該點的邊的索引。
針對渲染的特殊表達
大多數(shù)圖形卡并不直接支持索引三角網(wǎng),渲染三角形時,一般是將三個頂點同時提交。這樣,共享頂點會多次提交,三角形用到一次就提交一次。因為內(nèi)存和圖形硬件間的數(shù)據(jù)傳輸是瓶頸,所以許多API和硬件支持特殊的三角網(wǎng)格式以減少傳輸量。基本思想是排序點和面,使得現(xiàn)存中已有的三角形不需要再次傳輸。
從最高靈活性到最低靈活性,我們討論三種方案:頂點緩存,三角帶,三角扇。
頂點緩存
與其說頂點緩存是一種特殊的存儲格式,不如說是API和硬件之間的一種存儲策略,用以發(fā)揮連續(xù)三角形頂點一致性的特點。通常,高級代碼不需要了解頂點緩存是如何實現(xiàn)和執(zhí)行的。
和其他緩存機制類似,頂點緩存基于最近使用的數(shù)據(jù)將來仍被使用的原則。圖形處理器緩存一小部分(如,16個)最近使用的頂點,當(dāng)API要發(fā)送頂點時,首先探測緩存內(nèi)是否已存在。當(dāng)然,這要求API了解圖形卡緩存的大小和替換機制。若緩存內(nèi)沒有該頂點,則發(fā)生脫靶,API發(fā)送頂點并更新緩存;若緩存內(nèi)有該頂點,就命中,API通知圖形卡"使用緩存內(nèi)位置x的頂點"。
頂點緩存其實是一種底層的優(yōu)化手段,任何三角網(wǎng)都可用高級代碼實現(xiàn)正確渲染而不用考慮緩存。但進行頂點順序的調(diào)整,使共享頂點的三角形集中發(fā)送有助于提高效率。這種調(diào)整只需要進行一次,并且可以離線進行,它只會對性能有幫助,不會使沒有緩存的系統(tǒng)性能降低。善用緩存,可能使發(fā)送到顯卡的頂點數(shù)降低到平均每三角形少于一個。