本文來源於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所在位置)了。具體描述如下:
因此只要知道入口地址(ID爲0x4D4D,稱爲基本塊,標識3DS文件)和所需要的chunk對於它的偏移量就能找到你想要的數據了。Chunk-length就是一個chunk的容量。Data是主數據,Sub-chunks是子塊。當然,與內存的最大區別是3DS文件不依賴於硬件。內存的話總容量是固定的,地址爲0長度爲8的內存分配來存儲某數據,如果該數據僅僅佔用了開頭的4個內存格子,其餘4個格子什麼也沒有(或者說無意義)等於浪費了,但它們還是“被使用”了,沒法用來幹別的事。而3DS文件,哪怕一個chunk的長度多麼長而被填充的數據多麼少,或者根本沒有相應數據,多餘的那些“虛擬的數據地址”不會佔用整個文件的大小。這是符合實際的:一個模型的數據量可大可小,因此對應3DS文件也跟着可大可小。至於數據量超過了長度所允許怎麼辦呢?據說某些chunk,如描述頂點數的chunk的“長度”也是varying,也就是說長度也跟隨數據量變化,望有心人指教。另一個區別在於ID非一定按順序的,譬如基本塊ID爲0x4D4D,設其地址爲0,有一個chunk的ID是0x0001,明顯小於0x4D4D,但其地址可能很大。所以說ID是名字,ID所在3DS文件結構種的“位置”纔是地址。
順帶一提的是,3DS文件中塊的內部組織更像是一種樹結構(The chunk tree),因此就有了父塊和子塊這種概念,父塊包含子塊。其中ID號0x4D4D的塊就是樹幹,其長度是“0 + sub-chunks”,而ID爲0x3D3D的3D 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所在位置了。衆多高手們已經幫我們算好了(雖然還沒有全部解析),給出一個chunk的ID和它存儲的數據的作用和格式,也就是說我們應用的可以通過其ID訪問該chunk,按照數據存儲格式把數據讀出來,爲我們所用。例如ID號爲0x4110的chunk就是用來描述對象頂點的,按照其存儲數據的方式可以遍歷之,保存到一種容器(實際內存)中,使用的時候就能直接從此容器中把模型頂點拿出來了。
譬如我用到的一個3DS文件讀取類就用到了以下ID的chunk:
// 基本塊(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