数据格式
b3dm包含一个28B的头部和两个数据table和外部的GLTF文件。
b3dm:
|----header(28 B)--------|--feature table---|--batch table---|---------GLB-----------|
header:
magic | version | byteLength | featureTableJsonByteLength | featureTableBinaryLength | batchTableJsonByteLength | batchTableBinaryLength
feature table:
json | binary
batch table:
json | binary
其中 byteLength = 28 + featureTableJSONByteLength + featureTableBinaryByteLength + batchTableJSONByteLength + batchTableBinaryByteLength + glb的字节长度
magic 是固定的b3dm
featureTableBinaryLength 和 batchTableBinaryLength 在没数据的话,可以为0
feature table 的json 一般直接一个{"BATCH_LENGTH":1}就行了。
然后是batch table的json,
{"batchId":[0],"maxPoint":[[{},{},{}]],"minPoint":[[{},{},{}]],"name":["default"]}
每个字段都是一个数组,上边的batch length 有多少个,每个字段就有多少个数据。
batchId 指的是 glb 文件里 meshes[].primitives[] 的第几个。链接:STL文件解析及转换到GLTF
maxPoint和minPoint是glb的最大最小顶点。
把文件头、featTableJson、batchTableJson写入文件后,需要使用空格来padding到8的倍数.
featureTableJsonByteLength = featureTableJsonByteLength + paddingLength
(28 + featureTableJsonByteLength) % 8 == 0
batchTableJsonByteLength = batchTableJsonByteLength + paddingLength
(28 + batchTableJsonByteLength) % 8 == 0
while (buf.size() < 28 + featureJsonLength) {
// add b'20'
for (byte b : " ".getBytes()) {
buf.add(b);
}
}
...
GLB的处理
写入头部和批量表等数据后,需要处理GLB的内容来配合头部。
batchTableJson描述了怎么找到GLB文件里primitive的位置。
下一步需要改造glb,在primitive加上_BATCHID属性,指明accessor,用来读取glb 文件buffer的内容。
"meshes" : [{"primitives" : [ {"attributes" : {"POSITION" : 1,"_BATCHID":2},"indices" : 0} ]}]
这里就会去找到第三个accessor
{"bufferView" : 2,"byteOffset" : 0,"componentType" : 5125,"count" : %d,"type" : "SCALAR","max" : [ 0 ],"min" : [ 0 ], "name":"_batchId"}
然后是他对应的bufferview
{"buffer" : 0,"byteOffset" : %d,"byteLength" : %d,"target" : 34963}
那么写入buffer的是什么数据呢?
int[] _batches = new int[顶点数];
for (int x = 0; x < _batches.length; x++) {
_batches[x] = 0;
}
这些写就好了, 把_batches写道buffer里
最后把这个glb文件写入到b3dm里即可。