原創。轉載請規範註明出處:http://www.javashuo.com/article/p-hcrvzhto-nh.html
個人git地址:github.com/onsummerhtml
B3dm,Batched 3D Model,成批量的三維模型的意思。git
傾斜攝影數據(例如osgb)、BIM數據(如rvt)、傳統三維模型(如obj、dae、3dMax製做的模型等),都可建立此類瓦片。github
位於b3dm文件最開頭的28個字節,是7個屬性數據:json
屬性的官方名稱 | 字節長 | 類型 | 含義 |
---|---|---|---|
magic |
4 | string(或char[4]) | 該瓦片文件的類型,在b3dm中是 "b3dm" |
version |
4 | uint32 | 該瓦片的版本,目前限定是 1. |
byteLength |
4 | uint32 | 該瓦片文件的文件大小,單位:byte |
featureTableJSONByteLength |
4 | uint32 | 要素表的JSON文本(二進制形式)長度 |
featureTableBinaryByteLength |
4 | uint32 | 要素表的二進制數據長度 |
batchTableJSONByteLength |
4 | uint32 | 批量表的JSON文本(二進制形式)長度 |
batchTableBinaryByteLength |
4 | uint32 | 批量表的二進制數據長度 |
其中,數組
byteLength
= 28 + featureTableJSONByteLength
+ featureTableBinaryByteLength
+ batchTableJSONByteLength
+ batchTableBinaryByteLength
佈局
回顧上篇,我說的是大數據
要素表,記錄的是整個瓦片渲染相關的數據,而不是渲染所需的數據。ui
那麼,b3dm瓦片中的要素表會記錄哪些數據呢?編碼
什麼是全局屬性?即對於瓦片每個三維模型(或BATCH、要素)或者直接對當前瓦片有效的數據,在b3dm中,要素表有如下全局屬性:3d
屬性名 | 屬性數據類型 | 屬性描述 | 是否必須存在 |
---|---|---|---|
BATCH_LENGTH |
uint32 | 當前瓦片文件內三維模型(BATCH、要素)的個數 | yes |
RTC_CENTER |
float32[3] | 若是模型的座標是相對座標,那麼相對座標的中心即此 | no |
注意,若是glb模型並不須要屬性數據,即要素表和批量表有多是空表,那麼 BATCH_LENGTH
的值應設爲 0 .
對於每一個模型(BATCH、要素)各自獨立的數據。在b3dm中沒有。
咱們回憶一下要素表的定義:與渲染相關的數據。
b3dm瓦片與渲染相關的數據都在glb中了,因此b3dm並不須要存儲每一個模型各自獨立的數據,即不存在要素屬性。
在i3dm、pnts兩種瓦片中,要素屬性會很是多。
全局屬性存儲在 要素表的JSON中,見下文:
由上圖可知,文件頭28字節數據以後是要素表,要素表前部是 長達 featureTableJSONByteLength
字節的二進制JSON文本,利用各類語言內置的API能夠將這段二進制數據轉換爲字符串,而後解析爲JSON對象。
例如,這裏解析了一個b3dm文件的 要素表JSON:
{ "BATCH_LENGTH": 4 }
那麼,此b3dm瓦片就有4個模型(4個要素,或4個BATCH),其 batchId
是0、一、二、3.
無。
注:
當要素表的 JSON 數據以引用二進制體的方式出現時,數據纔會記錄在要素表的二進制本體數據中,此時JSON記錄的是字節偏移量等信息。
可是在b3dm瓦片中,要素表只須要JSON就能夠了,不須要自找麻煩再引用二進制數據,由於
BATCH_LENGTH
和RTC_CENTER
都相對好記錄,一個是數值,一個是3元素的數組。在下面的要介紹批量表中,就會出現 JSON 數據引用二進制體的狀況了。在 i3dm 和 pnts 瓦片中,要素表 JSON就會大量引用其二進制體。
批量表記錄的是每一個模型的屬性數據,以及擴展數據(擴展數據之後再談)。
要素表和批量表惟一的聯繫就是 BATCH_LENGTH
,在 i3dm 中叫 INSTANCE_LENGTH
,在 pnts 中叫 POINTS_LENGTH
。
這很好理解,要素表記錄了有多少個模型(BATCH、要素),那麼批量表每一個屬性就有多少個值。
先上一份批量表的JSON看看:
{ "height" : { "byteOffset" : 0, "componentType" : "FLOAT", "type" : "SCALAR" }, "geographic" : { "byteOffset" : 40, "componentType" : "DOUBLE", "type" : "VEC3" }, }
這個批量表的JSON有兩個屬性:height
、geographic
,字面義即模型的高度值、地理座標值。
height
屬性經過其 componentType
指定數據的值類型爲 FLOAT
,經過其 type
指定數據的元素類型爲 SCALAR
(即標量)。
geographic
屬性經過其 componentType
指定數據的的值類型是 DOUBLE
,經過其 type
指定數據的元素類型爲 VEC3
(即3個double數字構成的三維向量)。
byteOffset
,即這個屬性值在 二進制本體數據 中從哪一個字節開始存儲。
從上表能夠看出,height 屬性跨越 0 ~ 39 字節,一共40個字節。
經過 FeatureTableJSON 能夠獲取 BATCH_LENGTH 爲10,那麼就有10個模型,對應的,這 40 個字節就存儲了10個 height 值,查相關資料得知,FLOAT類型的數據字節長度爲 4,恰好 4 byte × 10 = 40 byte,即 height 屬性的所有數據的總長。
geographic 屬性也同理,VEC3 表明一個 geographic 有3個 DOUBLE 類型的數字,一個 DOUBLE 數值佔 8byte,那麼 geographic 一共數據總長是:
type × componentType × BATCH_LENGTH = 3 × 8byte × 10 = 240 byte.
事實上,兩個屬性的總長是 40 + 240 = 280 byte,與 b3dm 文件頭中的第七個屬性 batchTableBinaryByteLength
= 280 是一致的。
二進制本體數據即批量表中每一個屬性的順次存儲。
能夠。若是你以爲數據量比較小,能夠直接把數據寫在 BatchTableJSON
中,仍是以上述兩個數據爲例:
{ "height": [10.0, 20.0, 15.0, ...], // 太長了不寫那麼多,一共10個 "geographic": [ [113.42, 23.10, 102.1], [111.08, 22.98, 24.94], // 太長不寫 ] }
可是,讀者請必定注意這一點:一樣是一個數字,二進制的JSON文本大多數時候體積會比二進制數據大。由於JSON文本還包括括號、逗號、冒號等JSON文本必須的符號。對於屬性數據至關大的狀況,建議使用 JSON引用二進制本體數據的組織形式,此時JSON充當的角色是元數據。
注意:對於屬性的值類型是 JSON 中的 object、string、bool 類型,則必須存於 JSON 中,由於二進制體只能存 標量、234維向量四種類型的數字數據。
本部分略,對glb數據感興趣的讀者可自行查閱 glTF 數據規範。
關於兩大數據表如何與glb每個頂點進行關聯的,在前篇也有簡略介紹。能夠參考官方的說明:
FeatureTableJSON、BatchTableJSON的二進制文本,最後一個字節相對於整個b3dm文件來講,偏移量必須是8的倍數。
若是不對齊,必須用二進制空格(即 0x20
)填夠。
你問我爲啥不對起始偏移量也要求 8byte 對齊?由於 FeatureTableJSON 以前是28byte的 文件頭,爲了湊齊8倍數對齊,文件頭和 FeatureTableJSON 還要塞4個字節填滿,那就有點多餘了。
末尾對齊,即 (28 + ftJSON長)能整除8,(28 + ftTable長 + btJSON長)能整除8.
二進制數據體,不管是要素表、批量表,首個字節相對於b3dm文件的字節偏移量,必須是8的倍數,結束字節的字節偏移量,也必須是8的倍數。
若是不知足,能夠填充任意數據字節知足此要求。
特別的,二進制數據體中,每個屬性值的第一個數值的第一個字節的偏移量,相對於整個b3dm文件,必須是其 componentType
的倍數,若是不知足,則必須用空白字節填滿。
例如,上述 height 屬性所在的批量表二進制數據體,理所固然位於批量表JSON以後,而批量表的JSON又是8byte對齊的,假設批量表的數據體起始字節是800,那麼 height 的第一個值起始字節就是 800,因爲 height 屬性的 componentType 是 FLOAT,即 4字節,800 ÷ 4 能整除,因此沒有問題。
可是,假如 換一個屬性,其 componentType 是 BYTE
,即 1字節,那麼假設第二個屬性的 componentType 是 DOUBLE,即 8字節,就會出現 第二個屬性的第一個值起始偏移量是810,810 ÷ 8 並不能整除,必須補齊 6個空白字節,以知足第二個屬性第一個值的起始偏移量是 810+6 = 816字節。
要素表、批量表的二進制數據,不管是JSON仍是數據體,均使用小端序編碼(LittleEndian)。
其實,不管是要素表,仍是批量表,都容許在JSON中存在擴展數據,以擴充當前瓦片模型的功能,而並非單一的一個一個模型順次存儲在瓦片文件、glb中。
有關擴展數據,在之後會專門出一篇博客介紹。