OK, then from my current understanding, you have a bunch of B3DM files, and they have associated IDs, and you want to do something with the glTF (payload) of these B3DM files based on the ID. There are several assumptions here, about the presence and structure of these IDs, but maybe that can be sorted out later.
However, there are some pointers that could be helpful for accomplishing your goal here.
The implementation example section in the specification shows a basic, low-level approach for reading that data from a batch table. It also links to the implementation of all that in CesiumJS.
Note: The example there handles the case where the data is stored as a Binary Body Reference. Skipping some details: The batch table can contain something like id: [ "id0", "id1" ]
directly in the JSON. But these ID strings could also be stored in binary form. Depending on which assumptions you can make here, the implementation may be trivial and just use the JSON. Or it may be a bit more complex, and have to access the binary data…
Another option for accessing this data could be the 3d-tiles-tools
. The 3d-tiles-tools
currently do NOT offer a public API. Everything there may change arbitrarily in future versions. (Significant changes are unlikely - but the point is: There are no stability guarantees. It is only veryion 0.4.2
).
I’m going out on a limb here, in terms of what you might need or try to accomplish. But the following is implemented against the cloned state of the 3d-tiles-tools
, using internal API, but it shows how to access the data from a B3DM more or less conveniently:
import fs from "fs";
import { TileFormats } from "./src/tilesets";
import { B3dmFeatureTable } from "./src/structure";
import { BatchTable } from "./src/structure";
import { BatchTablePropertyTableModels } from "./src/tools";
import { PropertyTableModel } from "./src/metadata";
import { NodeIO } from "@gltf-transform/core";
// Only for information: Print the contents of the given table
function printPropertyTableModel(propertyTableModel: PropertyTableModel) {
// Print the "column names" of the table (i.e. the property names)
const propertyNames = propertyTableModel.getPropertyNames();
console.log("propertyNames: ", propertyNames);
// Print all rows of the table:
const numRows = propertyTableModel.getCount();
for (let r = 0; r < numRows; r++) {
console.log("Row " + r);
// Each row is an "entity" that has one property
// stored in each column
const entity = propertyTableModel.getMetadataEntityModel(r);
for (const propertyName of propertyNames) {
const value = entity.getPropertyValue(propertyName);
console.log(" " + propertyName + ": " + value);
}
}
}
// Print information about the textures that are contained
// in the given GLB data (using glTF-Transform)
async function printTextures(glbData: Buffer) {
const io = new NodeIO();
const document = await io.readBinary(glbData);
const root = document.getRoot();
const textures = root.listTextures();
console.log("There are " + textures.length + " textures");
for (let i = 0; i < textures.length; i++) {
const texture = textures[i];
const imageData = texture.getImage();
console.log(" texture " + i + " image data: ", imageData);
}
}
async function process(fileName: string) {
// Read the B3DM data from the file, and create
// a "TileData" object
const b3dmBuffer = fs.readFileSync(fileName);
const tileData = TileFormats.readTileData(b3dmBuffer);
// Obtain the batch- and feature table information from the tile data
const batchTable = tileData.batchTable.json as BatchTable;
const batchTableBinary = tileData.batchTable.binary;
const featureTable = tileData.featureTable.json as B3dmFeatureTable;
const numRows = featureTable.BATCH_LENGTH;
// A lot of magic is happening here: Create a "table" object from
// the batch table, that allows accessing the rows (objects)
// and columns (properties)
const propertyTableModel = BatchTablePropertyTableModels.create(
batchTable,
batchTableBinary,
{},
numRows
);
printPropertyTableModel(propertyTableModel);
// Check, for example, row 3 of the table, and see whether
// it contains the expected ID. If it does, print information
// about the textures that are contained in the GLB data.
const row = 3;
const expectedId = 3;
const entity = propertyTableModel.getMetadataEntityModel(row);
const actualId = entity.getPropertyValue("id");
if (actualId === expectedId) {
console.log("Found expected ID in row " + row);
await printTextures(tileData.payload);
}
}
process("batchedWithBatchTable.b3dm");
The crucial part there is the PropertyTableModel
interface. This is described in this image, but since it is an internal API, it is not documented beyond that.
For a given B3DM file, this will print something like
propertyNames: [ 'id', 'Longitude', 'Latitude', 'Height', 'info', 'rooms' ]
Row 0
id: 0
Longitude: -1.31968
Latitude: 0.698874
Height: 6.155801922082901
info: [object Object]
rooms: room0_a,room0_b,room0_c
Row 1
id: 1
Longitude: -1.3196832683949145
Latitude: 0.6988615321420496
Height: 13.410263679921627
info: [object Object]
rooms: room1_a,room1_b,room1_c
...
It then checks a certain row to see whether it has the expected ID. If it does, it prints information about the textures that are contained in the glTF data (using glTF-Transform)