3DS檔案結構的初步認識

2021-08-24 17:37:08 字數 3139 閱讀 6618

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...