3dTiles 数据规范详解[4.1]b3dm ⽡⽚⼆进制数据⽂件结构
原创。转载请规范注明出处:我的git 地址:⽬录:
B3dm,Batched 3D Model,成批量的三维模型的意思。
倾斜摄影数据(例如osgb)、BIM数据(如rvt)、传统三维模型(如obj、dae、3dMax制作的模型等),均可创建此类⽡⽚。
⽡⽚⽂件⼆进制布局(⽂件结构)
① ⽂件头:占28字节(byte )
位于b3dm⽂件最开头的28个字节,是7个属性数据:
其中,
byteLength = 28 + featureTableJSONByteLength + featureTableBinaryByteLength + batchTableJSONByteLength + batchTableBinaryByteLength + glb 的字节长度
② 要素表
回顾上篇,我说的是
要素表,记录的是整个⽡⽚渲染相关的数据,⽽不是渲染所需的数据。
那么,b3dm⽡⽚中的要素表会记录哪些数据呢?
全局属性
什么是全局属性?即对于⽡⽚每⼀个三维模型(或BATCH、要素)或者直接对当前⽡⽚有效的数据,在b3dm中,要素表有以下全局属性:
注意,如果glb模型并不需要属性数据,即要素表和批量表有可能是空表,那么 BATCH_LENGTH 的值应设为 0 .
*要素属性
对于每个模型(BATCH、要素)各⾃独⽴的数据。在b3dm中没有。我们回忆⼀下要素表的定义:与渲染相关的数据。
属性的官⽅名称字节长类型
含义
magic 4string (或char[4])该⽡⽚⽂件的类型,在b3dm 中是 "b3dm"version 4uint32该⽡⽚的版本,⽬前限定是 1.byteLength
json值的类型有哪些4uint32该⽡⽚⽂件的⽂件⼤⼩,单位:byte featureTableJSONByteLength 4uint32要素表的JSON ⽂本(⼆进制形式)长度featureTableBinaryByteLength 4uint32要素表的⼆进制数据长度
batchTableJSONByteLength 4uint32批量表的JSON ⽂本(⼆进制形式)长度batchTableBinaryByteLength
4
uint32
批量表的⼆进制数据长度
属性名
属性数据类型属性描述
是否必须存在BATCH_LENGTH uint32当前⽡⽚⽂件内三维模型(BATCH 、要素)的个数yes RTC_CENTER
float32[3]
如果模型的坐标是相对坐标,那么相对坐标的中⼼即此
no
b3dm⽡⽚与渲染相关的数据都在glb中了,所以b3dm并不需要存储每个模型各⾃独⽴的数据,即不存在要素属性。
在i3dm、pnts两种⽡⽚中,要素属性会⾮常多。
全局属性存在哪⾥?
全局属性存储在 要素表的JSON中,见下⽂:
JSON头部数据
由上图可知,⽂件头28字节数据之后是要素表,要素表前部是 长达 featureTableJSONByteLength 字节的⼆进制JSON⽂本,利⽤各种语⾔内置的API可以将这段⼆进制数据转换为字符串,然后解析为JSON对象。
例如,这⾥解析了⼀个b3dm⽂件的 要素表JSON:
{
"BATCH_LENGTH": 4
}
那么,此b3dm⽡⽚就有4个模型(4个要素,或4个BATCH),其 batchId 是0、1、2、3.
要素表的⼆进制本体数据
⽆。
注:
当要素表的 JSON 数据以引⽤⼆进制体的⽅式出现时,数据才会记录在要素表的⼆进制本体数据中,此时JSON记录的是字节偏移量等信息。
但是在b3dm⽡⽚中,要素表只需要JSON就可以了,不需要⾃⿇烦再引⽤⼆进制数据,因为BATCH_LENGTH 和 RTC_CENTER 都相对好记录,⼀个是数值,⼀个是3元素的数组。
在下⾯的要介绍批量表中,就会出现 JSON 数据引⽤⼆进制体的情况了。在 i3dm 和 pnts ⽡⽚中,要素表 JSON就会⼤量引⽤其⼆进制体。
③批量表
批量表记录的是每个模型的属性数据,以及扩展数据(扩展数据以后再谈)。
要素表和批量表唯⼀的联系就是 BATCH_LENGTH,在 i3dm 中叫 INSTANCE_LENGTH,在 pnts 中叫 POINTS_LENGTH。
这很好理解,要素表记录了有多少个模型(BATCH、要素),那么批量表每个属性就有多少个值。
JSON头部数据
先上⼀份批量表的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
本部分略,对glb数据感兴趣的读者可⾃⾏查阅 glTF 数据规范。
关于两⼤数据表如何与glb每⼀个顶点进⾏关联的,在前篇也有简略介绍。可以参考官⽅的说明:
⑤字节对齐与编码端序
JSON⼆进制⽂本对齐
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)。
⑥扩展数据(extensions)与额外补充信息(extras)
其实,⽆论是要素表,还是批量表,都允许在JSON中存在扩展数据,以扩充当前⽡⽚模型的功能,⽽并不是单⼀的⼀个⼀个模型顺次存储在⽡⽚⽂件、glb中。
有关扩展数据,在以后会专门出⼀篇博客介绍。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论