Obj文件格式

         我們經常見到的*.obj文件有兩種:第一種是基於COFF(Common Object File Format)格式的OBJ文件(也稱目標文件),這種格式用於編譯應用程序;第二種是Alias|Wavefront公司推出的OBJ模型文件。我要講的OBJ文件格式是指第二種-OBJ模型文件。
     說起3D文件格式,大家一定不會感到陌生,"*.3ds""*.max""*.lw""*.mb""*.dxf""*.obj",相信人人都能列舉出幾種來。但是說起OBJ文件的具體特徵,卻很少有人能給出較爲圓滿的描述。很多人認識OBJ文件是從使用Poser開始的,Poser是一款人體建模軟件,要把Poser生成的人體導出到其它3D軟件中進行再加工,就用到了OBJ文件。OBJ文件是一種標準的3D模型文件格式,很適合用於3D軟件模型之間的互導。比如你在3dsMaxLightWave中建了一個模型,想把它調到Maya裏面渲染或動畫,導出OBJ文件就是一種很好的選擇。目前幾乎所有知名的3D軟件都支持OBJ文件的讀寫,不過很多軟件需要通過插件才能做到這一點。
        
另外,作爲一種優秀的文件格式,很多遊戲引擎也都支持OBJ文件的讀取。瞭解OBJ文件格式有什麼用呢?如果你不學編程的話,用處確實不大。不過,3D軟件模型之間的互導是一件很常見的事情,不幸的是,目前的3D軟件模型導出功能都不那麼完美,經常會出現缺面少線的情況,有時還會遇到導出的模型根本打不開的情況。如果情況非常緊急的話,你一定會不惜一切代價仔細研究,期望找到原因,解決問題。在這種情況下,我的教程也許會對你有很大幫助。
  OBJ文件是一種文本文件格式,這就意味着你可以直接用寫字板打開進行查看修改,如果你能看懂每一行的內容是什麼意思,相信距離你成功的解決問題已經不遠了。
  如果Maya自身的模型出錯,也可以先轉成OBJ格式,修改之後再導回Maya

OBJ文件 --概念

       OBJ文件是Wavefront公司爲它的一套基於工作站的3D建模和動畫軟件"Advanced Visualizer"開發的一種文件格式,這種格式同樣也以通過Maya讀寫。
    要想知道一個文件是不是OBJ文件,通常根據這個文件名的後綴來判斷,OBJ文件的後綴是".obj"OBJ文件是讓人可讀的文本,你可以直接用寫字板打開對它進行編輯。 
       
另外,有一種與此相關二進制文件格式(使用".MOD"後綴),二進制格式作爲專利未公開,因此在這裏我們不作討論。
    OBJ最近的有文檔的版本是v3.0,代替以前的v2.11版本。
    OBJ3.0格式支持多邊形(Polygon),直線(Lines),表面(Surfaces),和自由形態曲線(Free-form Curves)
      
直線和多角形通過它們的點來描述,曲線和表面則根據於它們的控制點和依附於曲線類型的額外信息來定義。這些信息支持規則和不規則的曲線,包括那些基於貝塞爾(Bezier)曲線,B樣條(B-spline),基數(Cardinal/Catmull-Rom樣條),和泰勒方程(Taylor equations)的曲線。
OBJ
文件 -- 特點
  (1)OBJ是一種3D模型文件,因此不包含動畫、材質特性、貼圖路徑、動力學、粒子等信息。
  (2)OBJ文件主要支持多邊形(Polygons)模型。雖然OBJ文件也支持曲線(Curves)、表面(Surfaces)、點組材質(Point Group Materials),但Maya導出的OBJ文件並不包括這些信息。
  (3)OBJ文件支持三個點以上的面,這一點很有用。很多其它的模型文件格式只支持三個點的面,所以我們導入Maya的模型經常被三角化了,這對於我們對模型的再加工甚爲不利。

        (4)OBJ文件支持法線和貼圖座標。在其它軟件中調整好貼圖後,貼圖座標信息可以存入OBJ文件中,這樣文件導入Maya後只需指定一下貼圖文件路徑就行了,不需要再調整貼圖座標了。

OBJ文件 --基本結構

        OBJ文件不需要任何種文件頭(File Header),儘管經常使用幾行文件信息的註釋作爲文件的開頭。
        OBJ
文件由一行行文本組成,註釋行以一個(#)爲開頭,空格和空行可以隨意加到文件中以增加文件的可讀性。有字的行都由一兩個標記字母也就是關鍵字(Keyword)開頭,關鍵字可以說明這一行是什麼樣的數據。多行可以邏輯地連接在一起表示一行,方法是在每一行最後添加一個連接符(\)。注意連接符(\)後面不能出現空格或tab格,否則將導致文件出錯。

        下列關鍵字可以在OBJ文件使用 
        在這個列表中, 關鍵字根據數據類型排列,每個關鍵字有一段簡短描述。
  

        頂點數據(Vertex data)
   v 幾何體頂點 (Geometric vertices)
  vt  貼圖座標點 (Texture vertices)
  vn 頂點法線 (Vertex normals)
  vp 參數空格頂點 (Parameter space vertices)
  

        自由形態曲線(Free-form curve)/表面屬性(surface attributes):
  deg (Degree)
  bmat 基礎矩陣 (Basis matrix)
  step 步尺寸 (Step size)
  cstype 曲線或表面類型 (Curve or surface type)
  

        元素(Elements):
  p (Point)
  l (Line)
  f (Face)
  curv 曲線 (Curve)
  curv2 2D曲線 (2D curve)
  surf 表面 (Surface)
  

        自由形態曲線(Free-form curve)/表面主體陳述(surface body statements):

        parm 參數值 (Parameter values )
  trim 外部修剪循環 (Outer trimming loop)
  hole 內部整修循環 (Inner trimming loop)
  scrv 特殊曲線 (Special curve)
  sp 特殊的點 (Special point)
  end 結束陳述 (End statement)
  

        自由形態表面之間的連接(Connectivity between free-form surfaces):

        con 連接 (Connect)


       - 成組(Grouping):
  g 組名稱 (Group name)
  s 光滑組 (Smoothing group)
  mg 合併組 (Merging group)
  o 對象名稱 (Object name)


       - 顯示(Display)/渲染屬性(render attributes):

        bevel 導角插值 (Bevel interpolation)
  c_interp 顏色插值 (Color interpolation)
  d_interp 溶解插值 (Dissolve interpolation)
  lod 細節層次 (Level of detail)
  usemtl 材質名稱 (Material name)
  mtllib 材質庫 (Material library)
  shadow_obj 投射陰影 (Shadow casting)
  trace_obj 光線跟蹤 (Ray tracing)
  ctech 曲線近似技術 (Curve approximation technique)
  stech 表面近似技術 (Surface approximation technique)

的確挺難理解,所以要用實例來說明。

OBJ文件 --實例
  下面通過實例來具體講解。
  OBJ文件記錄一個四邊形的代碼:
  v -0.58 0.84 0
  v 2.68 1.17 0
  v 2.84 -2.03 0
  v -1.92 -2.89 0
  f 1 2 3 4

  讓我們來創建一個OBJ文件,不過這一回我們不用3D軟件,而是用寫字板來創建。
  打開寫字板,把上面的5行代碼寫上去,可以適當加一點註釋。
  保存文件爲文本格式,文件名爲"myObj.obj",如圖。

  注意:代碼最後一定要按一下回車把光標切換到下一行,就是說加一個換行符(\n)。否則會看到如下錯誤信息:
  // Error: line 1: OBJ file line 5: index out of range. //
  // Error: line 1: Error reading file. //


點擊放大

  在Maya中導入"myObj.obj"文件,看見了吧,導入了一個四邊形。這個四邊形的形狀是完全由前面的那5行代碼決定的,下面我們來分析一個這些代碼。
  v -0.58 0.84 0
  畫一個四邊形需要四個頂點,這是第一個頂點,"v"表示頂點(vertex)"-0.58"爲這個頂點的X軸座標值,"-0.84"Y軸座標值,"0"Z軸座標值。這是第一個頂點,它的索引號是1。索引號是畫面時要用到的。
  v 2.68 1.17 0
  v 2.84 -2.03 0
  v -1.92 -2.89 0
  這分別是第二、三、四個頂點,它們的索引號分別是234

  f 1 2 3 4
  現在開始畫面,"f"表示面(face)1234是前面那四個頂點的索引號。請注意畫這個面連接點的順序,是從第一個點出發,依次連接第二、三、四個點。如果連接的順序不同所生成的面也會截然不同,例如"f 1 2 4 3"會產生一個交迭的面,如圖。面的連接點是按順時針排列或逆時針排列,將決定面的法線方向(面的反正)。例如:"f 1 2 3 4"面的法線向外,"f 4 3 2 1"面的法線向裏。面的連接點順序錯誤,是導致導入模型產生碎面的一個重要原因。

  一個面不能出現兩個以上相同的頂點,這也是檢查OBJ文件出錯的一個要點。
  例如:"f 1 2 3 4 3",有兩個相同的頂點,索引號是3。一個面出現兩個相同頂點,可能造成程序的內存分配錯誤。

  下面來研究一下Maya導出的OBJ文件。
  在Maya中創建一個多邊形立方體,選中這個立方體,選擇菜單"File -> Export Selection..."導出格式爲OBJ,文件名爲"cube.obj",如果沒有此格式,請在Plug-in Manager中載入"objExport.mll"。用寫字板打開"cube.obj",可以看到如下代碼:
  # The units used in this file are centimeters.
  g default
  v -0.500000 -0.500000 0.500000
  v 0.500000 -0.500000 0.500000
  v -0.500000 0.500000 0.500000
  v 0.500000 0.500000 0.500000
  v -0.500000 0.500000 -0.500000
  v 0.500000 0.500000 -0.500000
  v -0.500000 -0.500000 -0.500000
  v 0.500000 -0.500000 -0.500000
  vt 0.000000 0.000000
  vt 1.000000 0.000000
  vt 0.000000 1.000000
  vt 1.000000 1.000000
  vt 0.000000 2.000000
  vt 1.000000 2.000000
  vt 0.000000 3.000000
  vt 1.000000 3.000000
  vt 0.000000 4.000000
  vt 1.000000 4.000000
  vt 2.000000 0.000000
  vt 2.000000 1.000000
  vt -1.000000 0.000000
  vt -1.000000 1.000000
  vn 0.000000 0.000000 1.000000
  vn 0.000000 0.000000 1.000000
  vn 0.000000 0.000000 1.000000
  vn 0.000000 0.000000 1.000000
  vn 0.000000 1.000000 0.000000
  vn 0.000000 1.000000 0.000000
  vn 0.000000 1.000000 0.000000
  vn 0.000000 1.000000 0.000000
  vn 0.000000 0.000000 -1.000000
  vn 0.000000 0.000000 -1.000000
  vn 0.000000 0.000000 -1.000000
  vn 0.000000 0.000000 -1.000000
  vn 0.000000 -1.000000 0.000000
  vn 0.000000 -1.000000 0.000000
  vn 0.000000 -1.000000 0.000000
  vn 0.000000 -1.000000 0.000000
  vn 1.000000 0.000000 0.000000
  vn 1.000000 0.000000 0.000000
  vn 1.000000 0.000000 0.000000
  vn 1.000000 0.000000 0.000000
  vn -1.000000 0.000000 0.000000
  vn -1.000000 0.000000 0.000000
  vn -1.000000 0.000000 0.000000
  vn -1.000000 0.000000 0.000000
  s off
  g pCube1
  usemtl initialShadingGroup
  f 1/1/1 2/2/2 4/4/3 3/3/4
  f 3/3/5 4/4/6 6/6/7 5/5/8
  f 5/5/9 6/6/10 8/8/11 7/7/12
  f 7/7/13 8/8/14 2/10/15 1/9/16
  f 2/2/17 8/11/18 6/12/19 4/4/20
  f 7/13/21 1/1/22 3/3/23 5/14/24
  這個文件看起來稍複雜一些,用到了許多關鍵詞,你可以對照前面的列表查看一下每個關鍵詞的意思。
  我來解釋一下。
  "vt 1.000000 0.000000"這句"vt"代表點的貼圖座標。
  "vn 0.000000 0.000000 -1.000000"這句"vn"代表點的法線。

  "s off"表示關閉光滑組。
  "usemtl initialShadingGroup"表示使用的材質。
   "f 7/13/21"這時在面的數據中多了貼圖座標uv點和法線的索引號,索引號分別用左斜線(/)隔開。
  格式:"f 頂點索引/uv點索引/法線索引"
   "g pCube1"表示組,這裏的成組與Maya中的成組不一樣,這裏的成組是指把"g pCube1"後出現的面都結合到一起,組成一個整的多邊形幾何體。

  把"cube.obj"文件修改一下就知道成組的意思了。把"s off"這句後面的代碼替換成以下代碼:
  usemtl initialShadingGroup
  g pCube_Face1
  f 1/1/1 2/2/2 4/4/3 3/3/4
  g pCube_Face2
  f 3/3/5 4/4/6 6/6/7 5/5/8
  g pCube_Face3
  f 5/5/9 6/6/10 8/8/11 7/7/12
  g pCube_Face4
  f 7/7/13 8/8/14 2/10/15 1/9/16
  g pCube_Face5
  f 2/2/17 8/11/18 6/12/19 4/4/20
  g pCube_Face6
  f 7/13/21 1/1/22 3/3/23 5/14/24
  導入Maya後可以看到,立方體的每個面是分離的,每個面的名稱分別是"pCube_Face(1~6)",可見組的名稱其實就是單獨幾何體的名稱。

  可不可以用中文命名幾何體()呢?試試就知道了,把前面的代碼改成:
  usemtl initialShadingGroup
  g 立方體面1
  f 1/1/1 2/2/2 4/4/3 3/3/4
  g 立方體面2
  f 3/3/5 4/4/6 6/6/7 5/5/8
  g 立方體面3
  f 5/5/9 6/6/10 8/8/11 7/7/12
  g 立方體面4
  f 7/7/13 8/8/14 2/10/15 1/9/16
  g 立方體面5
  f 2/2/17 8/11/18 6/12/19 4/4/20
  g 立方體面6
  f 7/13/21 1/1/22 3/3/23 5/14/24

  試一下,會發現模型順利的導入了。雖然物體的名稱都變亂碼了,可這並不是很嚴重的事。
  不過使用中文名並不總是這麼順利,把"g 立方體面1"這行改爲"g選擇"再試試看,這回導入時模型根本無法出現,只會出現如下的錯誤信息:
  // Error: line 1: Your OBJ file contains a line which is too long to be parsed. Please edit your obj file. //
  // Error: line 1: Error reading file. //
  由此可見,物體命名的不規範也是導致OBJ文件出錯的原因之一。
  關於Maya的物體命名,英文名是很保險的,標點符號中只有下劃線(_)可用,數字不能用放到名稱的開頭,儘量不要用中、日、韓等雙字節文字。

  OBJ文件不支持有孔的多邊形面。
  舉個例子說明一下:

  選擇Maya的創建多邊形工具(Polygons -> Create Polyon Tool),在視圖中畫一個四邊形,不要按回車,按Ctrl在四邊形中間點一下,可以繼續在四邊形中挖一個洞。把這個有孔的多邊形存成OBJ格式,在導入Maya時,會發現多邊形少了一塊。如果你把這也看成錯誤,現在至少你已經知道錯誤的原因了,就是OBJ文件不支持有孔的多邊形面。

OBJ文件 --實際問題
  現在來討論一點比較實際的問題吧,就是一旦你遇到了一個出錯的OBJ文件,倒底該怎麼辦?
  當你打開OBJ文件後,往往會看到有幾萬行的代碼,你恐怕還沒本事情一眼看出錯誤所在行,除非程序的錯誤信息中已經告訴你錯誤行。如果你不知道錯誤在哪裏,可以用排除法,弄清楚肯定正確的代碼範圍,通過縮減錯誤代碼範圍定位錯誤。例如,你先新建一個空的OBJ文件,把有錯的OBJ文件代碼粘貼一半過來,然後把這個只有一半代碼的新OBJ文件導入Maya。如果這時沒有錯誤信息,說明錯誤行是在另一半代碼中,可以從另一半代碼中再粘貼一部分代碼試試看;如果這時出現錯誤,說明錯誤行就在粘貼的代碼中,可以把粘貼過來的代碼刪去一部分再試試看。就這樣,逐步縮減範圍直到找到錯誤行爲止。
  這種方法雖然很麻煩,不過頗爲有效。如果你不會編程,又遇到非常緊急的情況,這種方法還是值得一試的。

OBJ文件 --細節

  掌握了這麼多差不多也夠用了,不過由於網上詳細講解OBJ文件的中文文檔很少,我還是再講一些例子,給大家提供多一點的信息吧。

  簡單的OBJ格式寫法。
  # Simple Wavefront file
  v 0.0 0.0 0.0
  v 0.0 1.0 0.0
  v 1.0 0.0 0.0
  f 1 2 3

  面可以使用負值索引,有時用負值索引描述面更爲簡便。
  "f -4 -3 -2 -1"這句索引值"-3"表示從"f"這行往上數第3個頂點,就是"v -0.500000 0.000000 -0.800000",其它的索引值以此類推。因此與這一行等效的正值索引寫法爲:"f 1 2 3 4"
  v -0.500000 0.000000 0.400000
  v -0.500000 0.000000 -0.800000
  v -0.500000 1.000000 -0.800000
  v -0.500000 1.000000 0.400000
  f -4 -3 -2 -1

  OBJ文件不包含面的顏色定義信息,不過可以引用材質庫,材質庫信息儲存在一個後綴是".mtl"的獨立文件中。關鍵字"mtllib"即材質庫的意思。
  材質庫中包含材質的漫射(diffuse),環境(ambient),光澤(specular)RGB(紅綠藍)的定義值,以及反射(specularity),折射(refraction),透明度(transparency)等其它特徵。
   "usemtl"指定了材質之後,以後的面都是使用這一材質,直到遇到下一個"usemtl"來指定新的材質。
  下面的例子說明了指定材質的方法。
  Cube with Materials
  # This cube has a different material
  # applied to each of its faces.
  mtllib master.mtl
  v 0.000000 2.000000 2.000000
  v 0.000000 0.000000 2.000000
  v 2.000000 0.000000 2.000000
  v 2.000000 2.000000 2.000000
  v 0.000000 2.000000 0.000000
  v 0.000000 0.000000 0.000000
  v 2.000000 0.000000 0.000000
  v 2.000000 2.000000 0.000000
  # 8 vertices
  g front
  usemtl red
  f 1 2 3 4
  g back
  usemtl blue
  f 8 7 6 5
  g right
  usemtl green
  f 4 3 7 8
  g top
  usemtl gold
  f 5 1 4 8
  g left
  usemtl orange
  f 5 6 2 1
  g bottom
  usemtl purple
  f 2 6 7 3
  # 6 elements

  貝塞爾片面(Bezier Patch)

  Maya不能導出OBJ格式的貝塞爾片面,卻能夠導入它。導入的貝塞爾片面自動轉換爲Nurbs表面。
  # 3.0 Bezier patch
  v -5.000000 -5.000000 0.000000
  v -5.000000 -1.666667 0.000000
  v -5.000000 1.666667 0.000000
  v -5.000000 5.000000 0.000000
  v -1.666667 -5.000000 0.000000
  v -1.666667 -1.666667 0.000000
  v -1.666667 1.666667 0.000000
  v -1.666667 5.000000 0.000000
  v 1.666667 -5.000000 0.000000
  v 1.666667 -1.666667 0.000000
  v 1.666667 1.666667 0.000000
  v 1.666667 5.000000 0.000000
  v 5.000000 -5.000000 0.000000
  v 5.000000 -1.666667 0.000000
  v 5.000000 1.666667 0.000000
  v 5.000000 5.000000 0.000000
  # 16 vertices
  cstype bezier
  deg 3 3
  # Example of line continuation
  surf 0.000000 1.000000 0.000000 1.000000 13 14 \
  15 16 9 10 11 12 5 6 7 8 1 2 3 4
  parm u 0.000000 1.000000
  parm v 0.000000 1.000000
  end  
  # 1 element

    基數曲線(Cardinal Curve)
  Maya好像不支持OBJ格式的曲線,導入時不會出現錯誤信息,卻也不會出現曲線。
  # 3.0 Cardinal curve
  v 0.940000 1.340000 0.000000
  v -0.670000 0.820000 0.000000
  v -0.770000 -0.940000 0.000000
  v 1.030000 -1.350000 0.000000
  v 3.070000 -1.310000 0.000000
  # 6 vertices
  cstype cardinal
  deg 3
  curv 0.000000 3.000000 1 2 3 4 5 6
  parm u 0.000000 1.000000 2.000000 3.000000 end
  # 1 element

  貼圖映射(Texture-Mapped)
  # A 2 x 2 square mapped with a 1 x 1 square
  # texture stretched to fit the square exactly.
  mtllib master.mtl
  v 0.000000 2.000000 0.000000
  v 0.000000 0.000000 0.000000
  v 2.000000 0.000000 0.000000
  v 2.000000 2.000000 0.000000
  vt 0.000000 1.000000 0.000000
  vt 0.000000 0.000000 0.000000
  vt 1.000000 0.000000 0.000000
  vt 1.000000 1.000000 0.000000
  # 4 vertices
  usemtl wood
  # The first number is the point,
  # then the slash,
  # and the second is the texture point
  f 1/1 2/2 3/3 4/4
  # 1 element

  fixLWObj_v1.0
  最後,我再提供一個自己編寫的專門修復重複頂點錯誤的mel程序,可以修復LightWave 3D OBJ Export v2.1輸出的某些*.obj文件無法導入Maya的錯誤。

  使用方法:
  新建一個文件夾,把你要修復的*.obj文件都放到這個文件夾裏,把fixLWObj.mel也放到這個文件夾裏,
  然後把fixLWObj.mel拖放到Maya視窗中,耐心地等一兩分種,就可以完成修復。
  可以在Output視窗看到修復的進度。
  修復完後你會發現文件夾中多個一個名爲fix的文件夾,修復過的*.obj文件就存放在fix文件夾中。
  文件夾中的Output.txt文件記錄修復信息。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章