天天看點

android 3dmax

android 3dmax

一、 在Android顯示3D模型,用obj檔案

android 3dmax

利用網絡上找到的obj檔案,自行寫了一個objLoader類,并分析他的obj檔案和結構,最後解析出data檔案。

必須确認obj檔案的f 參數下必須有

f 1137/1/1 1212/2/2 1115/3/3

對應頂點座标、材質座标、法向量座标

大部分的obj檔案可能隻有對應的頂點座标

這樣的模型就沒有材質跟燈光可以使用

附檔有範例

objLoader一般java專案用于分析出OPGL需要的vertices、texture、normals、indices

OpglTest3模型測試 :源碼: 

android 3dmax

   1. 使用模組化工具建立模型并導出obj檔案

要渲染一個模型,首先要有一個模型檔案。目前絕大多數流行的模組化軟體都支援将模型輸出為OBJ檔案。這裡以3DS Max為例,介紹建立OBJ模型的方法。

首先,啟動3DS Max,并向往常一樣建立模型。如圖

所示。

android 3dmax

模型建立完後,執行檔案(File)菜單->導出(Export)指令。在彈出的儲存對話框中,輸入檔案名,并在”儲存類型”項中,選則”Wavefront Object (*.obj)”項。

如圖

android 3dmax

單擊”儲存”按鈕後,會彈出如圖

所示的選項對話框。

android 3dmax

在這裡,請注意在Faces欄中,選擇Triangles以使用三角形作為基本圖元。還要注意鈎去Relative Vertex一項,禁止使用相對頂點索引。這是因為在後面的程式中,我們将不考慮相對頂點索引以簡化代碼。

單擊”OK”按鈕後,會緊接着彈出另一個選項對話框,如圖

android 3dmax

這一步是在設定與此OBJ檔案對應的MTL檔案(用于儲存材質資訊),注意要選擇”Scene”并勾選”Export”複選框。然後單擊”OK”按鈕完成設定。這樣,在指定的檔案夾下,我們得到了兩個檔案:一個*.OBJ檔案,存儲了模型的頂點、法線和紋理坐标資訊;一個*.MTL檔案,存儲了該模型所用的材質資訊。

  2

.OBJ檔案格式OBJ檔案格式是非常簡單的。這種檔案以純文字的形式存儲了模型的頂點、法線和紋理坐标和材質使用資訊。OBJ檔案的每一行,都有極其相似的格式。在OBJ檔案中,每行的格式如下:

字首 參數1 參數2 參數3 …

其中,字首辨別了這一行所存儲的資訊類型。參數則是具體的資料。OBJ檔案的字首可以有:

表7.2-1 OBJ檔案中的字首

字首

說明

v

表示本行指定一個頂點。 

此字首後跟着3個單精度浮點數,分别表示該定點的X、Y、Z坐标值

vt

表示本行指定一個紋理坐标。 

此字首後跟着兩個單精度浮點數。分别表示此紋理坐标的U、V值

vn

表示本行指定一個法線向量。 

此字首後跟着3個單精度浮點數,分别表示該法向量的X、Y、Z坐标值

f

表示本行指定一個表面(Face)。 

一個表面實際上就是一個三角形圖元。此字首行的參數格式後面将詳細介紹。

usemtl

此字首後隻跟着一個參數。該參數指定了從此行之後到下一個以usemtl開頭的行之間的所有表面所使用的材質名稱。該材質可以在此OBJ檔案所附屬的MTL檔案中找到具體資訊。

mtllib

此字首後隻跟着一個參數。該參數指定了此OBJ檔案所使用的材質庫檔案(*.mtl)的檔案路徑

我們使用3DS Max建立了一個長方體,并儲存為OBJ格式。用寫字闆打開這個OBJ檔案,可以看到如下内容:

# Max2Obj Version 4.0 Mar 10th, 2001 

mtllib ./Box.mtl 

# object (null) to come … 

v -46.508743 -45.052959 50.796341 

v 49.442947 -45.052959 50.796341 

v -46.508743 -45.052959 -48.019585 

v 49.442947 -45.052959 -48.019585 

v -46.508743 48.034504 50.796341 

v 49.442947 48.034504 50.796341 

v -46.508743 48.034504 -48.019585 

v 49.442947 48.034504 -48.019585 

# 8 vertices 

vt 0.000000 0.000000 0.000000 

vt 1.000000 0.000000 0.000000 

vt 0.000000 1.000000 0.000000 

vt 1.000000 1.000000 0.000000 

# 12 texture vertices 

g (null) 

s 2 

f 1/10 3/12 4/11 

f 4/11 2/9 1/10 

s 4 

f 5/9 6/10 8/12 

f 8/12 7/11 5/9 

s 8 

f 1/5 2/6 6/8 

f 6/8 5/7 1/5 

s 16 

f 2/1 4/2 8/4 

f 8/4 6/3 2/1 

s 32 

f 4/5 3/6 7/8 

f 7/8 8/7 4/5 

s 64 

f 3/1 1/2 5/4 

f 5/4 7/3 3/1 

# 12 faces 

g

仔細觀察,你會發現這個檔案中包含了一些我們沒有提到的字首,如以”#”開頭的注釋,以g開頭的表示組的字首等等。但這些字首并不影響模型的外觀,是以我們可以忽略它們。在解釋以f為字首的行的格式之前,我們不得不提一個新的概念,這就是頂點索引(Vertex Indices)。我們知道,對于每一個三角形,都需要用3個頂點來表示。例如在上面的立方體模型中,一共有6×2×3=36個頂點。仔細想想就會知道,在這36個頂點中,又相當數量的頂點是重合的。如果把這些重合的頂點都一一表示出來,就太浪費存儲空間了。于是,我們提出了頂點索引的想法,解決空間占用問題。頂點索引的思想是建立兩個數組,一個數組用于存儲模型中所有的頂點坐标值,另一個數組則存儲每一個表面所對應的三個頂點在第一個數組中的索引。圖 7.2-1顯示了這種一一對應的關系。

android 3dmax

建立這樣的頂點索引顯然更加節約存儲空間。假設Indices:array of Integer是頂點索引數組,Vertices:array of TVertex是頂點數組,使用下面的代碼段就可以把整個頂點索引對應的所有三角形繪制出來:procedure DrawIndex(Indices:array of Integer;Vertices:array of TVertex);var i :Integer;beginglBegin(GL_TRIANGLES);for i := 0 to (High(Vertices)+1) div 3 -1 dobeginglVertex3fv(@Vertices[Indices[i*3]]);glVertex3fv(@Vertices[Indices[i*3+1]]);glVertex3fv(@Vertices[Indices[i*3+2]]);end;glEnd;end;以此類推,我們可以為模型中所有的法線、紋理坐标都建立起相應的索引,以節省更多的空間。而事實上,OBJ檔案就是這麼做的。現在,我們再來看一下OBJ檔案的結構。在一個OBJ檔案中,首先有一些以v、vt或vn字首開頭的行指定了所有的頂點、紋理坐标、法線的坐标。然後再由一些以f開頭的行指定每一個三角形所對應的頂點、紋理坐标和法線的索引。在頂點、紋理坐标和法線的索引之間,使用符号”/”隔開的。一個f行可以以下面幾種格式出現:f 1 2 3這樣的行表示以第1、2、3号頂點組成一個三角形。f 1/3 2/5 3/4這樣的行表示以第1、2、3号頂點組成一個三角形,其中第一個頂點的紋理坐标的索引值為3,第二個頂點的紋理坐标的索引值為5,第三個頂點的紋理坐标的索引值為4。f 1/3/4 2/5/6 3/4/2這樣的行表示以第1、2、3号頂點組成一個三角形,其中第一個頂點的紋理坐标的索引值為3,其法線的索引值是4;第二個頂點的紋理坐标的索引值為5,其法線的索引值是6;第三個頂點的紋理坐标的索引值為6,其法線的索引值是2。f 1//4 2//6 3//2這樣的行表示以第1、2、3号頂點組成一個三角形,且忽略紋理坐标。其中第一個頂點的法線的索引值是4;第二個頂點的法線的索引值是6;第三個頂點的法線的索引值是2。值得注意的是檔案中的索引值是以1作為起點的,這一點與Delphi中以0作為起點有很大的不同。在渲染的時候應注意将從檔案中讀取的坐标值減去1。7.3 用于存儲材質資訊的MTL檔案MTL檔案與OBJ檔案極其相似。隻是用于辨別行的字首有所不同。這些字首的意義如表7.3-1所示。

表7.3-1 MTL檔案中的字首

newmtl

表示建立一個材質。 

此字首後跟一個字元串,表示此材質的名稱。 

此行之後的資訊都是對這個材質進行設定。

Ka

指定最後建立的材質的環境光成分。此行包含3個單精度浮點參數。

Kd

指定最後建立的材質的漫射光成分。此行包含3個單精度浮點參數。

Ks

指定最後建立的材質的鏡面光成分。此行包含3個單精度浮點參數。

map_Kd

指定最後建立的材質的反射貼圖。如果此行的第一個參數為字元串”-s”,則此行将包括5個參數。其中第二、第三和第四個參數為此紋理貼圖在U、V、W方向的縮放值,第五個參數為紋理圖檔的檔案名。如果第一個字元串不是”-s”,那麼第一個參數就是此紋理圖檔的檔案名。

map_Ks

指定最後建立的材質的鏡面貼圖。如果此行的第一個參數為字元串”-s”,則此行将包括5個參數。其中第二、第三和第四個參數為此紋理貼圖在U、V、W方向的縮放值,第五個參數為紋理圖檔的檔案名。如果第一個字元串不是”-s”,那麼第一個參數就是此紋理圖檔的檔案名。

由這些資訊,我們就足以寫一個類,用于讀取和渲染OBJ模型了。

繼續閱讀