@loaders.gl/3d-tiles
Version:
3D Tiles, an open standard for streaming massive heterogeneous 3D geospatial datasets.
146 lines (118 loc) • 5.22 kB
text/typescript
// loaders.gl
// SPDX-License-Identifier: MIT AND Apache-2.0
// Copyright vis.gl contributors
// This file is derived from the Cesium code base under Apache 2 license
// See LICENSE.md and https://github.com/AnalyticalGraphicsInc/cesium/blob/master/LICENSE.md
import {getStringFromArrayBuffer} from './parse-utils';
import {Tiles3DLoaderOptions} from '../../../tiles-3d-loader';
import {Tiles3DTileContent} from '../../../types';
const SIZEOF_UINT32 = 4;
const DEPRECATION_WARNING = 'b3dm tile in legacy format.';
// eslint-disable-next-line max-statements
export function parse3DTileTablesHeaderSync(
tile: Tiles3DTileContent,
arrayBuffer: ArrayBuffer,
byteOffset: number
) {
const view = new DataView(arrayBuffer);
let batchLength;
tile.header = tile.header || {};
let featureTableJsonByteLength = view.getUint32(byteOffset, true);
byteOffset += SIZEOF_UINT32;
let featureTableBinaryByteLength = view.getUint32(byteOffset, true);
byteOffset += SIZEOF_UINT32;
let batchTableJsonByteLength = view.getUint32(byteOffset, true);
byteOffset += SIZEOF_UINT32;
let batchTableBinaryByteLength = view.getUint32(byteOffset, true);
byteOffset += SIZEOF_UINT32;
// First legacy header format - [batchLength] [batchTableByteLength] ('batchTableJsonByteLength': JSON starts with a quotation mark or the glTF magic)
// Second legacy format - [batchTableJsonByteLength] [batchTableBinaryByteLength] [batchLength] (Second legacy format is similar as first but here we check 'batchTableBinaryByteLength' instead)
// Current header format - [featureTableJsonByteLength] [featureTableBinaryByteLength] [batchTableJsonByteLength] [batchTableBinaryByteLength]
// First byte will be 0x22 or 0x67. The minimum uint32 expected is 0x22000000 = 570425344 = 570MB.
if (batchTableJsonByteLength >= 570425344) {
byteOffset -= SIZEOF_UINT32 * 2;
batchLength = featureTableJsonByteLength;
batchTableJsonByteLength = featureTableBinaryByteLength;
batchTableBinaryByteLength = 0;
featureTableJsonByteLength = 0;
featureTableBinaryByteLength = 0;
console.warn(DEPRECATION_WARNING); // eslint-disable-line
} else if (batchTableBinaryByteLength >= 570425344) {
byteOffset -= SIZEOF_UINT32;
batchLength = batchTableJsonByteLength;
batchTableJsonByteLength = featureTableJsonByteLength;
batchTableBinaryByteLength = featureTableBinaryByteLength;
featureTableJsonByteLength = 0;
featureTableBinaryByteLength = 0;
console.warn(DEPRECATION_WARNING); // eslint-disable-line
}
tile.header.featureTableJsonByteLength = featureTableJsonByteLength;
tile.header.featureTableBinaryByteLength = featureTableBinaryByteLength;
tile.header.batchTableJsonByteLength = batchTableJsonByteLength;
tile.header.batchTableBinaryByteLength = batchTableBinaryByteLength;
tile.header.batchLength = batchLength;
return byteOffset;
}
export function parse3DTileTablesSync(
tile: Tiles3DTileContent,
arrayBuffer: ArrayBuffer,
byteOffset: number,
options?: Tiles3DLoaderOptions
) {
byteOffset = parse3DTileFeatureTable(tile, arrayBuffer, byteOffset, options);
byteOffset = parse3DTileBatchTable(tile, arrayBuffer, byteOffset, options);
return byteOffset;
}
function parse3DTileFeatureTable(
tile: Tiles3DTileContent,
arrayBuffer: ArrayBuffer,
byteOffset: number,
options?: Tiles3DLoaderOptions
) {
const {featureTableJsonByteLength, featureTableBinaryByteLength, batchLength} = tile.header || {};
tile.featureTableJson = {
BATCH_LENGTH: batchLength || 0
};
if (featureTableJsonByteLength && featureTableJsonByteLength > 0) {
const featureTableString = getStringFromArrayBuffer(
arrayBuffer,
byteOffset,
featureTableJsonByteLength
);
tile.featureTableJson = JSON.parse(featureTableString);
}
byteOffset += featureTableJsonByteLength || 0;
tile.featureTableBinary = new Uint8Array(arrayBuffer, byteOffset, featureTableBinaryByteLength);
byteOffset += featureTableBinaryByteLength || 0;
/*
const featureTable = parseFeatureTable(featureTableJson, featureTableBinary);
const batchLength = featureTable.getGlobalProperty('BATCH_LENGTH');
featureTable.featuresLength = batchLength;
*/
return byteOffset;
}
function parse3DTileBatchTable(
tile: Tiles3DTileContent,
arrayBuffer: ArrayBuffer,
byteOffset: number,
options?: Tiles3DLoaderOptions
) {
const {batchTableJsonByteLength, batchTableBinaryByteLength} = tile.header || {};
if (batchTableJsonByteLength && batchTableJsonByteLength > 0) {
const batchTableString = getStringFromArrayBuffer(
arrayBuffer,
byteOffset,
batchTableJsonByteLength
);
tile.batchTableJson = JSON.parse(batchTableString);
byteOffset += batchTableJsonByteLength;
if (batchTableBinaryByteLength && batchTableBinaryByteLength > 0) {
// Has a batch table binary
tile.batchTableBinary = new Uint8Array(arrayBuffer, byteOffset, batchTableBinaryByteLength);
// Copy the batchTableBinary section and let the underlying ArrayBuffer be freed
tile.batchTableBinary = new Uint8Array(tile.batchTableBinary);
byteOffset += batchTableBinaryByteLength;
}
}
return byteOffset;
}