OpenGL日記——3ds文件結構


 
   

本文來源於ZwqXin http://www.zwqxin.com/ , 轉載請註明
原文地址:http://www.zwqxin.com/archives/opengl/3ds-structure-simple.html

3DS文件的結構比想象中複雜,也可以說我之前想得太簡單了.它跟可以直接查看的obj文件的複雜度完全不同。保存的信息很多很多(若這些信息在模型中存在)。雖然是一種老字號的通用格式,但是文件結構從來沒被髮布過,只是網路上很多高手不吝麻煩,一一嘗試測試,找出其紛亂二進制下的含義,並公開讓建模者和程序員得以應用3DS模型文件。

3DS文件格式,對數據的組織跟內存很相像。它分成很多的“chunk”(塊),按順序排列。每個chunk都包含着一些信息,比如頂點啊材質啊燈光啊等等,相應地,就被稱爲頂點chunk材質chunk燈光chunk等等,每個chunk都有其功用。每個chunk有其ID也有其長度和數據。如果把ID所在位置作爲一個chunk的地址的話,把該“chunk地址+chunk長度”就可以找到下一個chunk的地址(ID所在位置)了。具體描述如下:

因此只要知道入口地址(ID0x4D4D,稱爲基本塊,標識3DS文件)和所需要的chunk對於它的偏移量就能找到你想要的數據了。Chunk-length就是一個chunk的容量。Data是主數據,Sub-chunks是子塊。當然,與內存的最大區別是3DS文件不依賴於硬件。內存的話總容量是固定的,地址爲0長度爲8的內存分配來存儲某數據,如果該數據僅僅佔用了開頭的4個內存格子,其餘4個格子什麼也沒有(或者說無意義)等於浪費了,但它們還是“被使用”了,沒法用來幹別的事。而3DS文件,哪怕一個chunk的長度多麼長而被填充的數據多麼少,或者根本沒有相應數據,多餘的那些“虛擬的數據地址”不會佔用整個文件的大小。這是符合實際的:一個模型的數據量可大可小,因此對應3DS文件也跟着可大可小。至於數據量超過了長度所允許怎麼辦呢?據說某些chunk,如描述頂點數的chunk的“長度”也是varying,也就是說長度也跟隨數據量變化,望有心人指教。另一個區別在於ID非一定按順序的,譬如基本塊ID0x4D4D,設其地址爲0,有一個chunkID0x0001,明顯小於0x4D4D,但其地址可能很大。所以說ID是名字,ID所在3DS文件結構種的“位置”纔是地址。

順帶一提的是,3DS文件中塊的內部組織更像是一種樹結構(The chunk tree),因此就有了父塊和子塊這種概念,父塊包含子塊。其中ID0x4D4D的塊就是樹幹,其長度是“0 + sub-chunks”,而ID0x3D3D3D editor chunk(描述對象信息)和EDITKEYFRAME(關鍵幀信息)等等就是樹幹上的大樹枝,Object block (描述對象的點與面總的信息)等等就是大樹枝上的小樹枝,然後還有小小樹枝,小小小樹枝……較小的樹枝都是比它大一點的樹枝的“子塊sub-chunk”,且較大樹枝的“長度length”上標示的是其屬下所有小樹枝的“長度”總和(想起你電腦上的文件夾了嗎呵呵)。資料上的樹關係(其中一部分如下,左邊空格的多少突顯出父子關係):

 

0x4D4D            Main chunk

  0x3D3D          3D editor chunk

    0x4000        Object block (with name of your object)

     0x4100       Triangular mesh

       0x4110     Your vertices

       0x4120     Your faces

在實際應用中,因爲某種chunk的長度固定,故偏移確定,也就能直接計算得某個塊的ID所在位置了。衆多高手們已經幫我們算好了(雖然還沒有全部解析),給出一個chunkID和它存儲的數據的作用和格式,也就是說我們應用的可以通過其ID訪問該chunk,按照數據存儲格式把數據讀出來,爲我們所用。例如ID號爲0x4110chunk就是用來描述對象頂點的,按照其存儲數據的方式可以遍歷之,保存到一種容器(實際內存)中,使用的時候就能直接從此容器中把模型頂點拿出來了。

 

譬如我用到的一個3DS文件讀取類就用到了以下IDchunk

// 基本塊(Primary Chunk),位於文件的開始

#define PRIMARY            0x4D4D

  // 主塊(Main Chunks)

#define OBJECTINFO         0x3D3D        // 網格對象的版本號

#define VERSION            0x0002        // .3ds文件的版本

#define EDITKEYFRAME       0xB000        // 所有關鍵幀信息的頭部   

// 對象的次級定義(包括對象的材質和對象)

#define MATERIAL           0xAFFF        // 保存紋理信息

#define OBJECT             0x4000        // 保存對象的面、頂點等信息   

// 材質的次級定義

#define MATNAME            0xA000        // 保存材質名稱

#define MATDIFFUSE         0xA020        // 對象/材質的顏色

#define MATMAP             0xA200        // 新材質的頭部

#define MATMAPFILE         0xA300        // 保存紋理的文件名   

#define OBJECT_MESH        0x4100        // 新的網格對象   

// OBJECT_MESH的次級定義

#define OBJECT_VERTICES    0x4110      // 對象頂點

#define OBJECT_FACES       0x4120      // 對象的面

#define OBJECT_MATERIAL    0x4130      // 對象的材質

#define OBJECT_UV          0x4140      // 對象的UV紋理座標


明顯這個類只用到了3DS文件中的一小部分(chunk):頂點信息,面信息,紋理信息,材質信息,和一些標誌信息。事實上一個複雜模型對應的3DS文件中有更多的chunks。可以參看以下文檔:

 

本文來源於ZwqXin http://www.zwqxin.com/ , 轉載請註明
原文地址:http://www.zwqxin.com/archives/opengl/3ds-structure-simple.html

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