3ds檔案的結構比想象中複雜,也可以說我之前想得太簡單了.它跟可以直接檢視的obj檔案的複雜度完全不同。儲存的資訊很多很多(若這些資訊在模型中存在)。雖然是一種老字型大小的通用格式,但是檔案結構從來沒被發布過,只是網路上很多高手不吝麻煩,一一嘗試測試,找出其紛亂二進位制下的含義,並公開讓建模者和程式設計師得以應用3ds模型檔案。這裡主要記錄一下我的認識(比較膚淺呵呵)。——zwqxin.com
本文**於zwqxin(
其實按我最近的理解,3ds檔案格式,對資料的組織跟記憶體很相像。它分成很多的「chunk」(塊),按順序排列。每個chunk都包含著一些資訊,比如頂點啊材質啊燈光啊等等,相應地,就被稱為頂點chunk材質chunk燈光chunk等等,每個chunk都有其功用。每個chunk有其id也有其長度和資料。如果把id所在位置作為乙個chunk的位址的話,把該「chunk位址+chunk長度」就可以找到下乙個chunk的位址(id所在位置)了。具體描述如下:
offset
length
name02
chunk-id24
chunk-length = 6+n+m6 n
data
6+nm
sub-chunks
因此只要知道入口位址(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。可以參看以下文件:
3dsinfo.zip
3DS檔案的結構
本文 於 zwqxin 其實按我最近的理解,3ds檔案格式,對資料的組織跟記憶體很相像。它分成很多的 chunk 塊 按順序排列。每個chunk都包含著一些資訊,比如頂點啊材質啊燈光啊等等,相應地,就被稱為頂點chunk材質chunk燈光chunk等等,每個chunk都有其功用。每個chunk有其i...
3DS檔案格式
1 讀取規則 3ds檔案的讀取規則如下 位元組 直接讀取 字 先讀低位位元組,後讀高位位元組,如ed 3c讀出後的字為3c ed 雙字 先讀低位字,後讀高位字,如ed 3c 25 43讀出後的雙字為43 25 3c ed 浮點數 直接讀取四個位元組。2 chunk chunk是3ds檔案的基本構成單...
3DS 檔案格式
3ds 檔案格式 1 讀取規則 3ds檔案的讀取規則如下 位元組 直接讀取 字 先讀低位位元組,後讀高位位元組,如ed 3c讀出後的字為3c ed 雙字 先讀低位字,後讀高位字,如ed 3c 25 43讀出後的雙字為43 25 3c ed 浮點數 直接讀取四個位元組。2 chunk chunk是3d...