接下來要介紹的模型檔案格式是OBJ格式。該格式非常流行,而且可以使用大量3D建模軟體匯出。OBJ是一種簡單的格式,它是可以用任何文字編輯器開啟和儲存的文字檔。準確的說,OBJ檔案並不是設計用於處理與動畫相關的資訊,但如果有一個需要快速載入到情境中的靜態對象,OBJ也許會有用。已經被匯出OBJ格式的模型由頂點、法線、紋理座標和三角形索引(外觀)組成。因此,在OBJ格式中將不為除了簡單靜態網格之外的任何對象使用模型。
【注意】
使用由不同類型軟體匯出的OBJ檔案時一定要謹慎。例如,用Lightwave7.5建立的OBJ檔案就不同於3D Studio
Max匯出的OBJ檔案。試著用為稍有不同類型檔案編寫的代碼開啟用Lightwave7.5建立的OBJ檔案會產生錯誤。為了避免出現錯誤,這裡只負載檔案開始處包含Wavefront的OBJ檔案。
12.3.1 OBJ檔案格式介紹
誠如所知,OBJ格式是基於文本的格式。在OBJ檔案中每行開始處的單詞將決定這一行所代表的資訊。如果該行是以字母v開頭,那麼跟隨它後面的將是三個不同的浮點值以代表頂點位置。如果該行以字母vt開頭,那麼跟隨它後面的將是兩個不同的浮點值以代表紋理座標。跟隨在vn後面的將是代表法線的三個浮點值。通常,跟隨在f後面的是三對索引值。每組索引代表一個三角形,由三個索引索引構成,一個代表頂點,一個代表該頂點的紋理座標,最後一個代表該頂點使用的法線。例如,1/1/1,2/3/2,3/1/2。第一組意味著三角形的第一個頂點使用頂點數組中的第一個頂點,紋理座標數組中的第一個紋理座標,法線數組中的第一個法線。第二組意味著該三角形的第二個頂點使用頂點數組中的第二個頂點,紋理座標數組中的第三個紋理座標,法線數組中的第二個法線。所以這三對中的每一對都是用索引描述頂點、紋理座標和法線數組。由於有三組數值,所以每個頂點用一個,每個頂點都有自己的位置、紋理座標和法線。某些點也許會共用位置、紋理座標和/或法線,這樣可以重用資料。
除了提到的這些字元之外,還有一些其他字元,如mtllib,它指的是為模型儲存材質資訊的檔案名稱,#號和C語言中的注釋符號“//”的功能一樣。程式清單12.12給出了MilkShape3D匯出的OBJ模型檔案樣本。
程式清單12.2 OBJ格式的紋理立方體樣本
# Wavefront OBJ exported by MilkShape 3D
mtllib test.mtl
v -21.000000 20.750000 20.750000
v -21.000000 -21.250000 20.750000
v -21.000000 20.750000 20.750000
v -21.000000 -21.250000 20.750000
v -21.000000 20.750000 -19.000000
v -21.000000 -21.250000 -19.000000
v -21.000000 20.750000 -19.000000
v -21.000000 -21.250000 -19.000000
# 8 vertices
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 1.000000
vt 1.000000 0.000000
# 4 texture coordinates
vn 0.000000 0.000000 1.000000
vn 1.000000 0.000000 0.000000
vn 0.000000 0.000000 -1.000000
vn -1.000000 0.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 -1.000000 1.000000
# 6 normals
g Box01
usemtl Material01
s 1
f 1/1/1 2/2/1 3/3/1
f 2/2/1 4/4/1 3/3/1
s 2
f 3/1/2 4/2/2 5/3/2
f 4/2/2 6/4/2 5/3/2
s1
f 5/1/3 6/2/3 7/3/3
f 6/2/3 8/4/3 7/3/3
s2
f 7/1/4 8/2/4 1/3/4
f 8/2/4 2/4/4 1/3/4
s3
f 7/1/5 1/2/5 5/3/5
f 1/2/5 3/4/5 5/3/5
f 2/1/6 8/2/6 4/3/6
f 8/2/6 6/4/6 4/3/6
# 12 triangles in group
# 12 triangles total
由程式清單12.12可以看到,一旦定義完所有的頂點、紋理座標和法線,接下來就是定義每個對象。開始先是對象名稱、對象使用的從檔案中得到的檔案名稱以及構成該對象的多邊形。一旦讀取完最後一個外觀,要麼是在檔案結尾處,要麼就是準備開始讀取另一個對象。如果讀取的內容既不是注釋,也不是檔案結尾標識符,那麼可以假定還有要讀取的對象。一直讀取直到所有的對象都被讀取出來為止。在定義對象時,檔案在頂點、紋理座標和法線的數組中使用索引。有共同邊、紋理座標和法線的對象就可以讓檔案比平常的要小一些。然而,在Direct3D中建立對象時,不得不尋找所有的資料而不是像這樣一樣可以直接使用的索引。
和OBJ檔案自身一起,同樣還要材質檔案。材質檔案通常包含了.MTL副檔名,以及為對象添加紋理所需的全部資訊。像OBJ檔案一樣,.MTL檔案每行包含了一些其後跟隨資料的字元。這包括代表環境屬性的Ka、代表漫反射的Kd、代表鏡面反射的Ks以及代表反射能量的Ns。如果在材質檔案中見到newmtl這樣的單詞,就意味要定義一種新材質。map_Kd表示材質包含與它關聯的紋理映像,而且這一行後面就是紋理映像的檔案名稱。MilkShape3D匯出的.MTL材質檔案樣本如程式清單12.13所示。
程式清單12.13 OBJ模型使用的材質檔案樣本
#
# test.mtl
#
newmtl Material01
Ka 0.200000 0.200000 0.200000
Ka 0.800000 0.800000 0.800000
Ks 0.000000 0.000000 0.000000
Ns 0.000000
map_Kd .\decal.tga
匯出到OBJ的模型基於文本,它們是易於分析。大量不同的建模軟體可以匯出為Wavefront
OBJ檔案格式,當與靜態對象打交道時,或是如果需要在將其轉換成自訂的類型之前將模型轉換成中間格式,這非常有用。使用不同類型的軟體匯出OBJ檔案一定要謹慎。回憶一下,LightWave
7.5並不能匯出Wavefront
OBJ檔案,如果不作為一些預防措施,就會產生大量的錯誤。當為載入OBJ檔案的示範程式編寫代碼時,一定要添加檢查語句,以查看Wavefront單詞是否出現在檔案頂部的某個位置。如果出現了這個單詞,就可以假定軟體導粗豪的OBJ檔案使用的是Wavefront格式。