@loaders.gl/3d-tiles
Version:
3D Tiles, an open standard for streaming massive heterogeneous 3D geospatial datasets.
1,279 lines (1,258 loc) • 98.9 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// dist/index.js
var dist_exports = {};
__export(dist_exports, {
CesiumIonLoader: () => CesiumIonLoader,
TILE3D_TYPE: () => TILE3D_TYPE,
Tile3DBatchTable: () => Tile3DBatchTableParser,
Tile3DFeatureTable: () => Tile3DFeatureTable,
Tile3DSubtreeLoader: () => Tile3DSubtreeLoader,
Tile3DWriter: () => Tile3DWriter,
Tiles3DArchive: () => Tiles3DArchive,
Tiles3DArchiveFileLoader: () => Tiles3DArchiveFileLoader,
Tiles3DLoader: () => Tiles3DLoader,
_getIonTilesetMetadata: () => getIonTilesetMetadata
});
module.exports = __toCommonJS(dist_exports);
// dist/tiles-3d-loader.js
var import_loader_utils8 = require("@loaders.gl/loader-utils");
var import_tiles2 = require("@loaders.gl/tiles");
// dist/lib/utils/version.js
var VERSION = true ? "4.3.2" : "latest";
// dist/lib/constants.js
var TILE3D_TYPE = {
COMPOSITE: "cmpt",
POINT_CLOUD: "pnts",
BATCHED_3D_MODEL: "b3dm",
INSTANCED_3D_MODEL: "i3dm",
GEOMETRY: "geom",
VECTOR: "vect",
GLTF: "glTF"
};
var TILE3D_TYPES = Object.keys(TILE3D_TYPE);
var MAGIC_ARRAY = {
BATCHED_MODEL: [98, 51, 100, 109],
INSTANCED_MODEL: [105, 51, 100, 109],
POINT_CLOUD: [112, 110, 116, 115],
COMPOSITE: [99, 109, 112, 116]
};
// dist/lib/parsers/helpers/parse-utils.js
var import_loader_utils = require("@loaders.gl/loader-utils");
function getStringFromArrayBuffer(arrayBuffer, byteOffset, byteLength) {
(0, import_loader_utils.assert)(arrayBuffer instanceof ArrayBuffer);
const textDecoder = new TextDecoder("utf8");
const typedArray = new Uint8Array(arrayBuffer, byteOffset, byteLength);
const string = textDecoder.decode(typedArray);
return string;
}
function getMagicString(arrayBuffer, byteOffset = 0) {
const dataView = new DataView(arrayBuffer);
return `${String.fromCharCode(dataView.getUint8(byteOffset + 0))}${String.fromCharCode(dataView.getUint8(byteOffset + 1))}${String.fromCharCode(dataView.getUint8(byteOffset + 2))}${String.fromCharCode(dataView.getUint8(byteOffset + 3))}`;
}
// dist/lib/parsers/parse-3d-tile-point-cloud.js
var import_draco = require("@loaders.gl/draco");
var import_loader_utils4 = require("@loaders.gl/loader-utils");
var import_math6 = require("@loaders.gl/math");
var import_core3 = require("@math.gl/core");
// dist/lib/classes/tile-3d-feature-table.js
var import_math = require("@loaders.gl/math");
var Tile3DFeatureTable = class {
json;
buffer;
featuresLength = 0;
_cachedTypedArrays = {};
constructor(featureTableJson, featureTableBinary) {
this.json = featureTableJson;
this.buffer = featureTableBinary;
}
getExtension(extensionName) {
return this.json.extensions && this.json.extensions[extensionName];
}
hasProperty(propertyName) {
return Boolean(this.json[propertyName]);
}
getGlobalProperty(propertyName, componentType = import_math.GL.UNSIGNED_INT, componentLength = 1) {
const jsonValue = this.json[propertyName];
if (jsonValue && Number.isFinite(jsonValue.byteOffset)) {
return this._getTypedArrayFromBinary(propertyName, componentType, componentLength, 1, jsonValue.byteOffset);
}
return jsonValue;
}
getPropertyArray(propertyName, componentType, componentLength) {
const jsonValue = this.json[propertyName];
if (jsonValue && Number.isFinite(jsonValue.byteOffset)) {
if ("componentType" in jsonValue) {
componentType = import_math.GLType.fromName(jsonValue.componentType);
}
return this._getTypedArrayFromBinary(propertyName, componentType, componentLength, this.featuresLength, jsonValue.byteOffset);
}
return this._getTypedArrayFromArray(propertyName, componentType, jsonValue);
}
getProperty(propertyName, componentType, componentLength, featureId, result) {
const jsonValue = this.json[propertyName];
if (!jsonValue) {
return jsonValue;
}
const typedArray = this.getPropertyArray(propertyName, componentType, componentLength);
if (componentLength === 1) {
return typedArray[featureId];
}
for (let i = 0; i < componentLength; ++i) {
result[i] = typedArray[componentLength * featureId + i];
}
return result;
}
// HELPERS
_getTypedArrayFromBinary(propertyName, componentType, componentLength, count, byteOffset) {
const cachedTypedArrays = this._cachedTypedArrays;
let typedArray = cachedTypedArrays[propertyName];
if (!typedArray) {
typedArray = import_math.GLType.createTypedArray(componentType, this.buffer.buffer, this.buffer.byteOffset + byteOffset, count * componentLength);
cachedTypedArrays[propertyName] = typedArray;
}
return typedArray;
}
_getTypedArrayFromArray(propertyName, componentType, array) {
const cachedTypedArrays = this._cachedTypedArrays;
let typedArray = cachedTypedArrays[propertyName];
if (!typedArray) {
typedArray = import_math.GLType.createTypedArray(componentType, array);
cachedTypedArrays[propertyName] = typedArray;
}
return typedArray;
}
};
// dist/lib/classes/tile-3d-batch-table.js
var import_loader_utils3 = require("@loaders.gl/loader-utils");
// dist/lib/classes/helpers/tile-3d-accessor-utils.js
var import_math2 = require("@loaders.gl/math");
var import_loader_utils2 = require("@loaders.gl/loader-utils");
var COMPONENTS_PER_ATTRIBUTE = {
SCALAR: 1,
VEC2: 2,
VEC3: 3,
VEC4: 4,
MAT2: 4,
MAT3: 9,
MAT4: 16
};
var UNPACKER = {
SCALAR: (values, i) => values[i],
VEC2: (values, i) => [values[2 * i + 0], values[2 * i + 1]],
VEC3: (values, i) => [values[3 * i + 0], values[3 * i + 1], values[3 * i + 2]],
VEC4: (values, i) => [values[4 * i + 0], values[4 * i + 1], values[4 * i + 2], values[4 * i + 3]],
// TODO: check column major
MAT2: (values, i) => [
values[4 * i + 0],
values[4 * i + 1],
values[4 * i + 2],
values[4 * i + 3]
],
MAT3: (values, i) => [
values[9 * i + 0],
values[9 * i + 1],
values[9 * i + 2],
values[9 * i + 3],
values[9 * i + 4],
values[9 * i + 5],
values[9 * i + 6],
values[9 * i + 7],
values[9 * i + 8]
],
MAT4: (values, i) => [
values[16 * i + 0],
values[16 * i + 1],
values[16 * i + 2],
values[16 * i + 3],
values[16 * i + 4],
values[16 * i + 5],
values[16 * i + 6],
values[16 * i + 7],
values[16 * i + 8],
values[16 * i + 9],
values[16 * i + 10],
values[16 * i + 11],
values[16 * i + 12],
values[16 * i + 13],
values[16 * i + 14],
values[16 * i + 15]
]
};
var PACKER = {
SCALAR: (x, values, i) => {
values[i] = x;
},
VEC2: (x, values, i) => {
values[2 * i + 0] = x[0];
values[2 * i + 1] = x[1];
},
VEC3: (x, values, i) => {
values[3 * i + 0] = x[0];
values[3 * i + 1] = x[1];
values[3 * i + 2] = x[2];
},
VEC4: (x, values, i) => {
values[4 * i + 0] = x[0];
values[4 * i + 1] = x[1];
values[4 * i + 2] = x[2];
values[4 * i + 3] = x[3];
},
// TODO: check column major correctness
MAT2: (x, values, i) => {
values[4 * i + 0] = x[0];
values[4 * i + 1] = x[1];
values[4 * i + 2] = x[2];
values[4 * i + 3] = x[3];
},
MAT3: (x, values, i) => {
values[9 * i + 0] = x[0];
values[9 * i + 1] = x[1];
values[9 * i + 2] = x[2];
values[9 * i + 3] = x[3];
values[9 * i + 4] = x[4];
values[9 * i + 5] = x[5];
values[9 * i + 6] = x[6];
values[9 * i + 7] = x[7];
values[9 * i + 8] = x[8];
values[9 * i + 9] = x[9];
},
MAT4: (x, values, i) => {
values[16 * i + 0] = x[0];
values[16 * i + 1] = x[1];
values[16 * i + 2] = x[2];
values[16 * i + 3] = x[3];
values[16 * i + 4] = x[4];
values[16 * i + 5] = x[5];
values[16 * i + 6] = x[6];
values[16 * i + 7] = x[7];
values[16 * i + 8] = x[8];
values[16 * i + 9] = x[9];
values[16 * i + 10] = x[10];
values[16 * i + 11] = x[11];
values[16 * i + 12] = x[12];
values[16 * i + 13] = x[13];
values[16 * i + 14] = x[14];
values[16 * i + 15] = x[15];
}
};
function createTypedArrayFromAccessor(tile3DAccessor, buffer, byteOffset, length) {
const { componentType } = tile3DAccessor;
(0, import_loader_utils2.assert)(tile3DAccessor.componentType);
const type = typeof componentType === "string" ? import_math2.GLType.fromName(componentType) : componentType;
const size = COMPONENTS_PER_ATTRIBUTE[tile3DAccessor.type];
const unpacker = UNPACKER[tile3DAccessor.type];
const packer = PACKER[tile3DAccessor.type];
byteOffset += tile3DAccessor.byteOffset;
const values = import_math2.GLType.createTypedArray(type, buffer, byteOffset, size * length);
return {
values,
type,
size,
unpacker,
packer
};
}
// dist/lib/classes/tile-3d-batch-table-hierarchy.js
var defined = (x) => x !== void 0;
function initializeHierarchy(batchTable, jsonHeader, binaryBody) {
if (!jsonHeader) {
return null;
}
let hierarchy = batchTable.getExtension("3DTILES_batch_table_hierarchy");
const legacyHierarchy = jsonHeader.HIERARCHY;
if (legacyHierarchy) {
console.warn("3D Tile Parser: HIERARCHY is deprecated. Use 3DTILES_batch_table_hierarchy.");
jsonHeader.extensions = jsonHeader.extensions || {};
jsonHeader.extensions["3DTILES_batch_table_hierarchy"] = legacyHierarchy;
hierarchy = legacyHierarchy;
}
if (!hierarchy) {
return null;
}
return initializeHierarchyValues(hierarchy, binaryBody);
}
function initializeHierarchyValues(hierarchyJson, binaryBody) {
let i;
let classId;
let binaryAccessor;
const instancesLength = hierarchyJson.instancesLength;
const classes = hierarchyJson.classes;
let classIds = hierarchyJson.classIds;
let parentCounts = hierarchyJson.parentCounts;
let parentIds = hierarchyJson.parentIds;
let parentIdsLength = instancesLength;
if (defined(classIds.byteOffset)) {
classIds.componentType = defaultValue(classIds.componentType, GL.UNSIGNED_SHORT);
classIds.type = AttributeType.SCALAR;
binaryAccessor = getBinaryAccessor(classIds);
classIds = binaryAccessor.createArrayBufferView(binaryBody.buffer, binaryBody.byteOffset + classIds.byteOffset, instancesLength);
}
let parentIndexes;
if (defined(parentCounts)) {
if (defined(parentCounts.byteOffset)) {
parentCounts.componentType = defaultValue(parentCounts.componentType, GL.UNSIGNED_SHORT);
parentCounts.type = AttributeType.SCALAR;
binaryAccessor = getBinaryAccessor(parentCounts);
parentCounts = binaryAccessor.createArrayBufferView(binaryBody.buffer, binaryBody.byteOffset + parentCounts.byteOffset, instancesLength);
}
parentIndexes = new Uint16Array(instancesLength);
parentIdsLength = 0;
for (i = 0; i < instancesLength; ++i) {
parentIndexes[i] = parentIdsLength;
parentIdsLength += parentCounts[i];
}
}
if (defined(parentIds) && defined(parentIds.byteOffset)) {
parentIds.componentType = defaultValue(parentIds.componentType, GL.UNSIGNED_SHORT);
parentIds.type = AttributeType.SCALAR;
binaryAccessor = getBinaryAccessor(parentIds);
parentIds = binaryAccessor.createArrayBufferView(binaryBody.buffer, binaryBody.byteOffset + parentIds.byteOffset, parentIdsLength);
}
const classesLength = classes.length;
for (i = 0; i < classesLength; ++i) {
const classInstancesLength = classes[i].length;
const properties = classes[i].instances;
const binaryProperties = getBinaryProperties(classInstancesLength, properties, binaryBody);
classes[i].instances = combine(binaryProperties, properties);
}
const classCounts = new Array(classesLength).fill(0);
const classIndexes = new Uint16Array(instancesLength);
for (i = 0; i < instancesLength; ++i) {
classId = classIds[i];
classIndexes[i] = classCounts[classId];
++classCounts[classId];
}
const hierarchy = {
classes,
classIds,
classIndexes,
parentCounts,
parentIndexes,
parentIds
};
validateHierarchy(hierarchy);
return hierarchy;
}
function traverseHierarchy(hierarchy, instanceIndex, endConditionCallback) {
if (!hierarchy) {
return;
}
const parentCounts = hierarchy.parentCounts;
const parentIds = hierarchy.parentIds;
if (parentIds) {
return endConditionCallback(hierarchy, instanceIndex);
}
if (parentCounts > 0) {
return traverseHierarchyMultipleParents(hierarchy, instanceIndex, endConditionCallback);
}
return traverseHierarchySingleParent(hierarchy, instanceIndex, endConditionCallback);
}
function traverseHierarchyMultipleParents(hierarchy, instanceIndex, endConditionCallback) {
const classIds = hierarchy.classIds;
const parentCounts = hierarchy.parentCounts;
const parentIds = hierarchy.parentIds;
const parentIndexes = hierarchy.parentIndexes;
const instancesLength = classIds.length;
const visited = scratchVisited;
visited.length = Math.max(visited.length, instancesLength);
const visitedMarker = ++marker;
const stack2 = scratchStack;
stack2.length = 0;
stack2.push(instanceIndex);
while (stack2.length > 0) {
instanceIndex = stack2.pop();
if (visited[instanceIndex] === visitedMarker) {
continue;
}
visited[instanceIndex] = visitedMarker;
const result = endConditionCallback(hierarchy, instanceIndex);
if (defined(result)) {
return result;
}
const parentCount = parentCounts[instanceIndex];
const parentIndex = parentIndexes[instanceIndex];
for (let i = 0; i < parentCount; ++i) {
const parentId = parentIds[parentIndex + i];
if (parentId !== instanceIndex) {
stack2.push(parentId);
}
}
}
return null;
}
function traverseHierarchySingleParent(hierarchy, instanceIndex, endConditionCallback) {
let hasParent = true;
while (hasParent) {
const result = endConditionCallback(hierarchy, instanceIndex);
if (defined(result)) {
return result;
}
const parentId = hierarchy.parentIds[instanceIndex];
hasParent = parentId !== instanceIndex;
instanceIndex = parentId;
}
throw new Error("traverseHierarchySingleParent");
}
function validateHierarchy(hierarchy) {
const scratchValidateStack = [];
const classIds = hierarchy.classIds;
const instancesLength = classIds.length;
for (let i = 0; i < instancesLength; ++i) {
validateInstance(hierarchy, i, stack);
}
}
function validateInstance(hierarchy, instanceIndex, stack2) {
const parentCounts = hierarchy.parentCounts;
const parentIds = hierarchy.parentIds;
const parentIndexes = hierarchy.parentIndexes;
const classIds = hierarchy.classIds;
const instancesLength = classIds.length;
if (!defined(parentIds)) {
return;
}
assert(instanceIndex < instancesLength, `Parent index ${instanceIndex} exceeds the total number of instances: ${instancesLength}`);
assert(stack2.indexOf(instanceIndex) === -1, "Circular dependency detected in the batch table hierarchy.");
stack2.push(instanceIndex);
const parentCount = defined(parentCounts) ? parentCounts[instanceIndex] : 1;
const parentIndex = defined(parentCounts) ? parentIndexes[instanceIndex] : instanceIndex;
for (let i = 0; i < parentCount; ++i) {
const parentId = parentIds[parentIndex + i];
if (parentId !== instanceIndex) {
validateInstance(hierarchy, parentId, stack2);
}
}
stack2.pop(instanceIndex);
}
// dist/lib/classes/tile-3d-batch-table.js
function defined2(x) {
return x !== void 0 && x !== null;
}
var clone = (x, y) => x;
var IGNORED_PROPERTY_FIELDS = {
HIERARCHY: true,
// Deprecated HIERARCHY property
extensions: true,
extras: true
};
var Tile3DBatchTableParser = class {
json;
binary;
featureCount;
_extensions;
// Copy all top-level property fields from the json object, ignoring special fields
_properties;
_binaryProperties;
// TODO: hierarchy support is only partially implemented and not tested
_hierarchy;
constructor(json, binary, featureCount, options = {}) {
var _a;
(0, import_loader_utils3.assert)(featureCount >= 0);
this.json = json || {};
this.binary = binary;
this.featureCount = featureCount;
this._extensions = ((_a = this.json) == null ? void 0 : _a.extensions) || {};
this._properties = {};
for (const propertyName in this.json) {
if (!IGNORED_PROPERTY_FIELDS[propertyName]) {
this._properties[propertyName] = this.json[propertyName];
}
}
this._binaryProperties = this._initializeBinaryProperties();
if (options["3DTILES_batch_table_hierarchy"]) {
this._hierarchy = initializeHierarchy(this, this.json, this.binary);
}
}
getExtension(extensionName) {
return this.json && this.json.extensions && this.json.extensions[extensionName];
}
memorySizeInBytes() {
return 0;
}
isClass(batchId, className) {
this._checkBatchId(batchId);
(0, import_loader_utils3.assert)(typeof className === "string", className);
if (this._hierarchy) {
const result = traverseHierarchy(this._hierarchy, batchId, (hierarchy, instanceIndex) => {
const classId = hierarchy.classIds[instanceIndex];
const instanceClass = hierarchy.classes[classId];
return instanceClass.name === className;
});
return defined2(result);
}
return false;
}
isExactClass(batchId, className) {
(0, import_loader_utils3.assert)(typeof className === "string", className);
return this.getExactClassName(batchId) === className;
}
getExactClassName(batchId) {
this._checkBatchId(batchId);
if (this._hierarchy) {
const classId = this._hierarchy.classIds[batchId];
const instanceClass = this._hierarchy.classes[classId];
return instanceClass.name;
}
return void 0;
}
hasProperty(batchId, name) {
this._checkBatchId(batchId);
(0, import_loader_utils3.assert)(typeof name === "string", name);
return defined2(this._properties[name]) || this._hasPropertyInHierarchy(batchId, name);
}
getPropertyNames(batchId, results) {
this._checkBatchId(batchId);
results = defined2(results) ? results : [];
results.length = 0;
const propertyNames = Object.keys(this._properties);
results.push(...propertyNames);
if (this._hierarchy) {
this._getPropertyNamesInHierarchy(batchId, results);
}
return results;
}
getProperty(batchId, name) {
this._checkBatchId(batchId);
(0, import_loader_utils3.assert)(typeof name === "string", name);
if (this._binaryProperties) {
const binaryProperty = this._binaryProperties[name];
if (defined2(binaryProperty)) {
return this._getBinaryProperty(binaryProperty, batchId);
}
}
const propertyValues = this._properties[name];
if (defined2(propertyValues)) {
return clone(propertyValues[batchId], true);
}
if (this._hierarchy) {
const hierarchyProperty = this._getHierarchyProperty(batchId, name);
if (defined2(hierarchyProperty)) {
return hierarchyProperty;
}
}
return void 0;
}
setProperty(batchId, name, value) {
const featureCount = this.featureCount;
this._checkBatchId(batchId);
(0, import_loader_utils3.assert)(typeof name === "string", name);
if (this._binaryProperties) {
const binaryProperty = this._binaryProperties[name];
if (binaryProperty) {
this._setBinaryProperty(binaryProperty, batchId, value);
return;
}
}
if (this._hierarchy) {
if (this._setHierarchyProperty(this, batchId, name, value)) {
return;
}
}
let propertyValues = this._properties[name];
if (!defined2(propertyValues)) {
this._properties[name] = new Array(featureCount);
propertyValues = this._properties[name];
}
propertyValues[batchId] = clone(value, true);
}
// PRIVATE METHODS
_checkBatchId(batchId) {
const valid = batchId >= 0 && batchId < this.featureCount;
if (!valid) {
throw new Error("batchId not in range [0, featureCount - 1].");
}
}
_getBinaryProperty(binaryProperty, index) {
return binaryProperty.unpack(binaryProperty.typedArray, index);
}
_setBinaryProperty(binaryProperty, index, value) {
binaryProperty.pack(value, binaryProperty.typedArray, index);
}
_initializeBinaryProperties() {
let binaryProperties = null;
for (const name in this._properties) {
const property = this._properties[name];
const binaryProperty = this._initializeBinaryProperty(name, property);
if (binaryProperty) {
binaryProperties = binaryProperties || {};
binaryProperties[name] = binaryProperty;
}
}
return binaryProperties;
}
_initializeBinaryProperty(name, property) {
if ("byteOffset" in property) {
const tile3DAccessor = property;
(0, import_loader_utils3.assert)(this.binary, `Property ${name} requires a batch table binary.`);
(0, import_loader_utils3.assert)(tile3DAccessor.type, `Property ${name} requires a type.`);
const accessor = createTypedArrayFromAccessor(tile3DAccessor, this.binary.buffer, this.binary.byteOffset | 0, this.featureCount);
return {
typedArray: accessor.values,
componentCount: accessor.size,
unpack: accessor.unpacker,
pack: accessor.packer
};
}
return null;
}
// EXTENSION SUPPORT: 3DTILES_batch_table_hierarchy
_hasPropertyInHierarchy(batchId, name) {
if (!this._hierarchy) {
return false;
}
const result = traverseHierarchy(this._hierarchy, batchId, (hierarchy, instanceIndex) => {
const classId = hierarchy.classIds[instanceIndex];
const instances = hierarchy.classes[classId].instances;
return defined2(instances[name]);
});
return defined2(result);
}
_getPropertyNamesInHierarchy(batchId, results) {
traverseHierarchy(this._hierarchy, batchId, (hierarchy, instanceIndex) => {
const classId = hierarchy.classIds[instanceIndex];
const instances = hierarchy.classes[classId].instances;
for (const name in instances) {
if (instances.hasOwnProperty(name)) {
if (results.indexOf(name) === -1) {
results.push(name);
}
}
}
});
}
_getHierarchyProperty(batchId, name) {
return traverseHierarchy(this._hierarchy, batchId, (hierarchy, instanceIndex) => {
const classId = hierarchy.classIds[instanceIndex];
const instanceClass = hierarchy.classes[classId];
const indexInClass = hierarchy.classIndexes[instanceIndex];
const propertyValues = instanceClass.instances[name];
if (defined2(propertyValues)) {
if (defined2(propertyValues.typedArray)) {
return this._getBinaryProperty(propertyValues, indexInClass);
}
return clone(propertyValues[indexInClass], true);
}
return null;
});
}
_setHierarchyProperty(batchTable, batchId, name, value) {
const result = traverseHierarchy(this._hierarchy, batchId, (hierarchy, instanceIndex) => {
const classId = hierarchy.classIds[instanceIndex];
const instanceClass = hierarchy.classes[classId];
const indexInClass = hierarchy.classIndexes[instanceIndex];
const propertyValues = instanceClass.instances[name];
if (defined2(propertyValues)) {
(0, import_loader_utils3.assert)(instanceIndex === batchId, `Inherited property "${name}" is read-only.`);
if (defined2(propertyValues.typedArray)) {
this._setBinaryProperty(propertyValues, indexInClass, value);
} else {
propertyValues[indexInClass] = clone(value, true);
}
return true;
}
return false;
});
return defined2(result);
}
};
// dist/lib/parsers/helpers/parse-3d-tile-header.js
var SIZEOF_UINT32 = 4;
function parse3DTileHeaderSync(tile, arrayBuffer, byteOffset = 0) {
const view = new DataView(arrayBuffer);
tile.magic = view.getUint32(byteOffset, true);
byteOffset += SIZEOF_UINT32;
tile.version = view.getUint32(byteOffset, true);
byteOffset += SIZEOF_UINT32;
tile.byteLength = view.getUint32(byteOffset, true);
byteOffset += SIZEOF_UINT32;
if (tile.version !== 1) {
throw new Error(`3D Tile Version ${tile.version} not supported`);
}
return byteOffset;
}
// dist/lib/parsers/helpers/parse-3d-tile-tables.js
var SIZEOF_UINT322 = 4;
var DEPRECATION_WARNING = "b3dm tile in legacy format.";
function parse3DTileTablesHeaderSync(tile, arrayBuffer, byteOffset) {
const view = new DataView(arrayBuffer);
let batchLength;
tile.header = tile.header || {};
let featureTableJsonByteLength = view.getUint32(byteOffset, true);
byteOffset += SIZEOF_UINT322;
let featureTableBinaryByteLength = view.getUint32(byteOffset, true);
byteOffset += SIZEOF_UINT322;
let batchTableJsonByteLength = view.getUint32(byteOffset, true);
byteOffset += SIZEOF_UINT322;
let batchTableBinaryByteLength = view.getUint32(byteOffset, true);
byteOffset += SIZEOF_UINT322;
if (batchTableJsonByteLength >= 570425344) {
byteOffset -= SIZEOF_UINT322 * 2;
batchLength = featureTableJsonByteLength;
batchTableJsonByteLength = featureTableBinaryByteLength;
batchTableBinaryByteLength = 0;
featureTableJsonByteLength = 0;
featureTableBinaryByteLength = 0;
console.warn(DEPRECATION_WARNING);
} else if (batchTableBinaryByteLength >= 570425344) {
byteOffset -= SIZEOF_UINT322;
batchLength = batchTableJsonByteLength;
batchTableJsonByteLength = featureTableJsonByteLength;
batchTableBinaryByteLength = featureTableBinaryByteLength;
featureTableJsonByteLength = 0;
featureTableBinaryByteLength = 0;
console.warn(DEPRECATION_WARNING);
}
tile.header.featureTableJsonByteLength = featureTableJsonByteLength;
tile.header.featureTableBinaryByteLength = featureTableBinaryByteLength;
tile.header.batchTableJsonByteLength = batchTableJsonByteLength;
tile.header.batchTableBinaryByteLength = batchTableBinaryByteLength;
tile.header.batchLength = batchLength;
return byteOffset;
}
function parse3DTileTablesSync(tile, arrayBuffer, byteOffset, options) {
byteOffset = parse3DTileFeatureTable(tile, arrayBuffer, byteOffset, options);
byteOffset = parse3DTileBatchTable(tile, arrayBuffer, byteOffset, options);
return byteOffset;
}
function parse3DTileFeatureTable(tile, arrayBuffer, byteOffset, options) {
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;
return byteOffset;
}
function parse3DTileBatchTable(tile, arrayBuffer, byteOffset, options) {
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) {
tile.batchTableBinary = new Uint8Array(arrayBuffer, byteOffset, batchTableBinaryByteLength);
tile.batchTableBinary = new Uint8Array(tile.batchTableBinary);
byteOffset += batchTableBinaryByteLength;
}
}
return byteOffset;
}
// dist/lib/parsers/helpers/normalize-3d-tile-colors.js
var import_math3 = require("@loaders.gl/math");
function normalize3DTileColorAttribute(tile, colors, batchTable) {
if (!colors && (!tile || !tile.batchIds || !batchTable)) {
return null;
}
const { batchIds, isRGB565, pointCount = 0 } = tile;
if (batchIds && batchTable) {
const colorArray = new Uint8ClampedArray(pointCount * 3);
for (let i = 0; i < pointCount; i++) {
const batchId = batchIds[i];
const dimensions = batchTable.getProperty(batchId, "dimensions");
const color = dimensions.map((d) => d * 255);
colorArray[i * 3] = color[0];
colorArray[i * 3 + 1] = color[1];
colorArray[i * 3 + 2] = color[2];
}
return {
type: import_math3.GL.UNSIGNED_BYTE,
value: colorArray,
size: 3,
normalized: true
};
}
if (colors && isRGB565) {
const colorArray = new Uint8ClampedArray(pointCount * 3);
for (let i = 0; i < pointCount; i++) {
const color = (0, import_math3.decodeRGB565)(colors[i]);
colorArray[i * 3] = color[0];
colorArray[i * 3 + 1] = color[1];
colorArray[i * 3 + 2] = color[2];
}
return {
type: import_math3.GL.UNSIGNED_BYTE,
value: colorArray,
size: 3,
normalized: true
};
}
if (colors && colors.length === pointCount * 3) {
return {
type: import_math3.GL.UNSIGNED_BYTE,
value: colors,
size: 3,
normalized: true
};
}
return {
type: import_math3.GL.UNSIGNED_BYTE,
value: colors || new Uint8ClampedArray(),
size: 4,
normalized: true
};
}
// dist/lib/parsers/helpers/normalize-3d-tile-normals.js
var import_core = require("@math.gl/core");
var import_math4 = require("@loaders.gl/math");
var scratchNormal = new import_core.Vector3();
function normalize3DTileNormalAttribute(tile, normals) {
if (!normals) {
return null;
}
if (tile.isOctEncoded16P) {
const decodedArray = new Float32Array((tile.pointsLength || 0) * 3);
for (let i = 0; i < (tile.pointsLength || 0); i++) {
(0, import_math4.octDecode)(normals[i * 2], normals[i * 2 + 1], scratchNormal);
scratchNormal.toArray(decodedArray, i * 3);
}
return {
type: import_math4.GL.FLOAT,
size: 2,
value: decodedArray
};
}
return {
type: import_math4.GL.FLOAT,
size: 2,
value: normals
};
}
// dist/lib/parsers/helpers/normalize-3d-tile-positions.js
var import_core2 = require("@math.gl/core");
var import_math5 = require("@loaders.gl/math");
function normalize3DTilePositionAttribute(tile, positions, options) {
if (!tile.isQuantized) {
return positions;
}
if (options["3d-tiles"] && options["3d-tiles"].decodeQuantizedPositions) {
tile.isQuantized = false;
return decodeQuantizedPositions(tile, positions);
}
return {
type: import_math5.GL.UNSIGNED_SHORT,
value: positions,
size: 3,
normalized: true
};
}
function decodeQuantizedPositions(tile, positions) {
const scratchPosition = new import_core2.Vector3();
const decodedArray = new Float32Array(tile.pointCount * 3);
for (let i = 0; i < tile.pointCount; i++) {
scratchPosition.set(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]).scale(1 / tile.quantizedRange).multiply(tile.quantizedVolumeScale).add(tile.quantizedVolumeOffset).toArray(decodedArray, i * 3);
}
return decodedArray;
}
// dist/lib/parsers/parse-3d-tile-point-cloud.js
async function parsePointCloud3DTile(tile, arrayBuffer, byteOffset, options, context) {
byteOffset = parse3DTileHeaderSync(tile, arrayBuffer, byteOffset);
byteOffset = parse3DTileTablesHeaderSync(tile, arrayBuffer, byteOffset);
byteOffset = parse3DTileTablesSync(tile, arrayBuffer, byteOffset, options);
initializeTile(tile);
const { featureTable, batchTable } = parsePointCloudTables(tile);
await parseDraco(tile, featureTable, batchTable, options, context);
parsePositions(tile, featureTable, options);
parseColors(tile, featureTable, batchTable);
parseNormals(tile, featureTable);
return byteOffset;
}
function initializeTile(tile) {
tile.attributes = {
positions: null,
colors: null,
normals: null,
batchIds: null
};
tile.isQuantized = false;
tile.isTranslucent = false;
tile.isRGB565 = false;
tile.isOctEncoded16P = false;
}
function parsePointCloudTables(tile) {
const featureTable = new Tile3DFeatureTable(tile.featureTableJson, tile.featureTableBinary);
const pointsLength = featureTable.getGlobalProperty("POINTS_LENGTH");
if (!Number.isFinite(pointsLength)) {
throw new Error("POINTS_LENGTH must be defined");
}
featureTable.featuresLength = pointsLength;
tile.featuresLength = pointsLength;
tile.pointsLength = pointsLength;
tile.pointCount = pointsLength;
tile.rtcCenter = featureTable.getGlobalProperty("RTC_CENTER", import_math6.GL.FLOAT, 3);
const batchTable = parseBatchIds(tile, featureTable);
return { featureTable, batchTable };
}
function parsePositions(tile, featureTable, options) {
tile.attributes = tile.attributes || {
positions: null,
colors: null,
normals: null,
batchIds: null
};
if (!tile.attributes.positions) {
if (featureTable.hasProperty("POSITION")) {
tile.attributes.positions = featureTable.getPropertyArray("POSITION", import_math6.GL.FLOAT, 3);
} else if (featureTable.hasProperty("POSITION_QUANTIZED")) {
const positions = featureTable.getPropertyArray("POSITION_QUANTIZED", import_math6.GL.UNSIGNED_SHORT, 3);
tile.isQuantized = true;
tile.quantizedRange = (1 << 16) - 1;
tile.quantizedVolumeScale = featureTable.getGlobalProperty("QUANTIZED_VOLUME_SCALE", import_math6.GL.FLOAT, 3);
if (!tile.quantizedVolumeScale) {
throw new Error("QUANTIZED_VOLUME_SCALE must be defined for quantized positions.");
}
tile.quantizedVolumeOffset = featureTable.getGlobalProperty("QUANTIZED_VOLUME_OFFSET", import_math6.GL.FLOAT, 3);
if (!tile.quantizedVolumeOffset) {
throw new Error("QUANTIZED_VOLUME_OFFSET must be defined for quantized positions.");
}
tile.attributes.positions = normalize3DTilePositionAttribute(tile, positions, options);
}
}
if (!tile.attributes.positions) {
throw new Error("Either POSITION or POSITION_QUANTIZED must be defined.");
}
}
function parseColors(tile, featureTable, batchTable) {
tile.attributes = tile.attributes || {
positions: null,
colors: null,
normals: null,
batchIds: null
};
if (!tile.attributes.colors) {
let colors = null;
if (featureTable.hasProperty("RGBA")) {
colors = featureTable.getPropertyArray("RGBA", import_math6.GL.UNSIGNED_BYTE, 4);
tile.isTranslucent = true;
} else if (featureTable.hasProperty("RGB")) {
colors = featureTable.getPropertyArray("RGB", import_math6.GL.UNSIGNED_BYTE, 3);
} else if (featureTable.hasProperty("RGB565")) {
colors = featureTable.getPropertyArray("RGB565", import_math6.GL.UNSIGNED_SHORT, 1);
tile.isRGB565 = true;
}
tile.attributes.colors = normalize3DTileColorAttribute(tile, colors, batchTable);
}
if (featureTable.hasProperty("CONSTANT_RGBA")) {
tile.constantRGBA = featureTable.getGlobalProperty("CONSTANT_RGBA", import_math6.GL.UNSIGNED_BYTE, 4);
}
}
function parseNormals(tile, featureTable) {
tile.attributes = tile.attributes || {
positions: null,
colors: null,
normals: null,
batchIds: null
};
if (!tile.attributes.normals) {
let normals = null;
if (featureTable.hasProperty("NORMAL")) {
normals = featureTable.getPropertyArray("NORMAL", import_math6.GL.FLOAT, 3);
} else if (featureTable.hasProperty("NORMAL_OCT16P")) {
normals = featureTable.getPropertyArray("NORMAL_OCT16P", import_math6.GL.UNSIGNED_BYTE, 2);
tile.isOctEncoded16P = true;
}
tile.attributes.normals = normalize3DTileNormalAttribute(tile, normals);
}
}
function parseBatchIds(tile, featureTable) {
let batchTable = null;
if (!tile.batchIds && featureTable.hasProperty("BATCH_ID")) {
tile.batchIds = featureTable.getPropertyArray("BATCH_ID", import_math6.GL.UNSIGNED_SHORT, 1);
if (tile.batchIds) {
const batchFeatureLength = featureTable.getGlobalProperty("BATCH_LENGTH");
if (!batchFeatureLength) {
throw new Error("Global property: BATCH_LENGTH must be defined when BATCH_ID is defined.");
}
const { batchTableJson, batchTableBinary } = tile;
batchTable = new Tile3DBatchTableParser(batchTableJson, batchTableBinary, batchFeatureLength);
}
}
return batchTable;
}
async function parseDraco(tile, featureTable, batchTable, options, context) {
let dracoBuffer;
let dracoFeatureTableProperties;
let dracoBatchTableProperties;
const batchTableDraco = tile.batchTableJson && tile.batchTableJson.extensions && tile.batchTableJson.extensions["3DTILES_draco_point_compression"];
if (batchTableDraco) {
dracoBatchTableProperties = batchTableDraco.properties;
}
const featureTableDraco = featureTable.getExtension("3DTILES_draco_point_compression");
if (featureTableDraco) {
dracoFeatureTableProperties = featureTableDraco.properties;
const dracoByteOffset = featureTableDraco.byteOffset;
const dracoByteLength = featureTableDraco.byteLength;
if (!dracoFeatureTableProperties || !Number.isFinite(dracoByteOffset) || !dracoByteLength) {
throw new Error("Draco properties, byteOffset, and byteLength must be defined");
}
dracoBuffer = (tile.featureTableBinary || []).slice(dracoByteOffset, dracoByteOffset + dracoByteLength);
tile.hasPositions = Number.isFinite(dracoFeatureTableProperties.POSITION);
tile.hasColors = Number.isFinite(dracoFeatureTableProperties.RGB) || Number.isFinite(dracoFeatureTableProperties.RGBA);
tile.hasNormals = Number.isFinite(dracoFeatureTableProperties.NORMAL);
tile.hasBatchIds = Number.isFinite(dracoFeatureTableProperties.BATCH_ID);
tile.isTranslucent = Number.isFinite(dracoFeatureTableProperties.RGBA);
}
if (!dracoBuffer) {
return true;
}
const dracoData = {
buffer: dracoBuffer,
properties: { ...dracoFeatureTableProperties, ...dracoBatchTableProperties },
featureTableProperties: dracoFeatureTableProperties,
batchTableProperties: dracoBatchTableProperties,
dequantizeInShader: false
};
return await loadDraco(tile, dracoData, options, context);
}
async function loadDraco(tile, dracoData, options, context) {
if (!context) {
return;
}
const dracoOptions = {
...options,
draco: {
...options == null ? void 0 : options.draco,
extraAttributes: dracoData.batchTableProperties || {}
}
};
delete dracoOptions["3d-tiles"];
const data = await (0, import_loader_utils4.parseFromContext)(dracoData.buffer, import_draco.DracoLoader, dracoOptions, context);
const decodedPositions = data.attributes.POSITION && data.attributes.POSITION.value;
const decodedColors = data.attributes.COLOR_0 && data.attributes.COLOR_0.value;
const decodedNormals = data.attributes.NORMAL && data.attributes.NORMAL.value;
const decodedBatchIds = data.attributes.BATCH_ID && data.attributes.BATCH_ID.value;
const isQuantizedDraco = decodedPositions && data.attributes.POSITION.value.quantization;
const isOctEncodedDraco = decodedNormals && data.attributes.NORMAL.value.quantization;
if (isQuantizedDraco) {
const quantization = data.POSITION.data.quantization;
const range = quantization.range;
tile.quantizedVolumeScale = new import_core3.Vector3(range, range, range);
tile.quantizedVolumeOffset = new import_core3.Vector3(quantization.minValues);
tile.quantizedRange = (1 << quantization.quantizationBits) - 1;
tile.isQuantizedDraco = true;
}
if (isOctEncodedDraco) {
tile.octEncodedRange = (1 << data.NORMAL.data.quantization.quantizationBits) - 1;
tile.isOctEncodedDraco = true;
}
const batchTableAttributes = {};
if (dracoData.batchTableProperties) {
for (const attributeName of Object.keys(dracoData.batchTableProperties)) {
if (data.attributes[attributeName] && data.attributes[attributeName].value) {
batchTableAttributes[attributeName.toLowerCase()] = data.attributes[attributeName].value;
}
}
}
tile.attributes = {
// @ts-expect-error
positions: decodedPositions,
// @ts-expect-error
colors: normalize3DTileColorAttribute(tile, decodedColors, void 0),
// @ts-expect-error
normals: decodedNormals,
// @ts-expect-error
batchIds: decodedBatchIds,
...batchTableAttributes
};
}
// dist/lib/parsers/parse-3d-tile-batched-model.js
var import_math7 = require("@loaders.gl/math");
// dist/lib/parsers/helpers/parse-3d-tile-gltf-view.js
var import_gltf = require("@loaders.gl/gltf");
var import_loader_utils5 = require("@loaders.gl/loader-utils");
var GLTF_FORMAT = {
URI: 0,
EMBEDDED: 1
};
function parse3DTileGLTFViewSync(tile, arrayBuffer, byteOffset, options) {
tile.rotateYtoZ = true;
const gltfByteLength = (tile.byteOffset || 0) + (tile.byteLength || 0) - byteOffset;
if (gltfByteLength === 0) {
throw new Error("glTF byte length must be greater than 0.");
}
tile.gltfUpAxis = (options == null ? void 0 : options["3d-tiles"]) && options["3d-tiles"].assetGltfUpAxis ? options["3d-tiles"].assetGltfUpAxis : "Y";
tile.gltfArrayBuffer = (0, import_loader_utils5.sliceArrayBuffer)(arrayBuffer, byteOffset, gltfByteLength);
tile.gltfByteOffset = 0;
tile.gltfByteLength = gltfByteLength;
if (byteOffset % 4 === 0) {
} else {
console.warn(`${tile.type}: embedded glb is not aligned to a 4-byte boundary.`);
}
return (tile.byteOffset || 0) + (tile.byteLength || 0);
}
async function extractGLTF(tile, gltfFormat, options, context) {
const tile3DOptions = (options == null ? void 0 : options["3d-tiles"]) || {};
extractGLTFBufferOrURL(tile, gltfFormat, options);
if (tile3DOptions.loadGLTF) {
if (!context) {
return;
}
if (tile.gltfUrl) {
const { fetch } = context;
const response = await fetch(tile.gltfUrl, options);
tile.gltfArrayBuffer = await response.arrayBuffer();
tile.gltfByteOffset = 0;
}
if (tile.gltfArrayBuffer) {
const gltfWithBuffers = await (0, import_loader_utils5.parseFromContext)(tile.gltfArrayBuffer, import_gltf.GLTFLoader, options, context);
tile.gltf = (0, import_gltf.postProcessGLTF)(gltfWithBuffers);
tile.gpuMemoryUsageInBytes = (0, import_gltf._getMemoryUsageGLTF)(tile.gltf);
delete tile.gltfArrayBuffer;
delete tile.gltfByteOffset;
delete tile.gltfByteLength;
}
}
}
function extractGLTFBufferOrURL(tile, gltfFormat, options) {
switch (gltfFormat) {
case GLTF_FORMAT.URI:
if (tile.gltfArrayBuffer) {
const gltfUrlBytes = new Uint8Array(tile.gltfArrayBuffer, tile.gltfByteOffset);
const textDecoder = new TextDecoder();
const gltfUrl = textDecoder.decode(gltfUrlBytes);
tile.gltfUrl = gltfUrl.replace(/[\s\0]+$/, "");
}
delete tile.gltfArrayBuffer;
delete tile.gltfByteOffset;
delete tile.gltfByteLength;
break;
case GLTF_FORMAT.EMBEDDED:
break;
default:
throw new Error("b3dm: Illegal glTF format field");
}
}
// dist/lib/parsers/parse-3d-tile-batched-model.js
async function parseBatchedModel3DTile(tile, arrayBuffer, byteOffset, options, context) {
var _a;
byteOffset = parseBatchedModel(tile, arrayBuffer, byteOffset, options, context);
await extractGLTF(tile, GLTF_FORMAT.EMBEDDED, options, context);
const extensions = (_a = tile == null ? void 0 : tile.gltf) == null ? void 0 : _a.extensions;
if (extensions && extensions.CESIUM_RTC) {
tile.rtcCenter = extensions.CESIUM_RTC.center;
}
return byteOffset;
}
function parseBatchedModel(tile, arrayBuffer, byteOffset, options, context) {
byteOffset = parse3DTileHeaderSync(tile, arrayBuffer, byteOffset);
byteOffset = parse3DTileTablesHeaderSync(tile, arrayBuffer, byteOffset);
byteOffset = parse3DTileTablesSync(tile, arrayBuffer, byteOffset, options);
byteOffset = parse3DTileGLTFViewSync(tile, arrayBuffer, byteOffset, options);
const featureTable = new Tile3DFeatureTable(tile.featureTableJson, tile.featureTableBinary);
tile.rtcCenter = featureTable.getGlobalProperty("RTC_CENTER", import_math7.GL.FLOAT, 3);
return byteOffset;
}
// dist/lib/parsers/parse-3d-tile-instanced-model.js
var import_core4 = require("@math.gl/core");
var import_geospatial = require("@math.gl/geospatial");
var import_math8 = require("@loaders.gl/math");
async function parseInstancedModel3DTile(tile, arrayBuffer, byteOffset, options, context) {
byteOffset = parseInstancedModel(tile, arrayBuffer, byteOffset, options, context);
await extractGLTF(tile, tile.gltfFormat || 0, options, context);
return byteOffset;
}
function parseInstancedModel(tile, arrayBuffer, byteOffset, options, context) {
var _a;
byteOffset = parse3DTileHeaderSync(tile, arrayBuffer, byteOffset);
if (tile.version !== 1) {
throw new Error(`Instanced 3D Model version ${tile.version} is not supported`);
}
byteOffset = parse3DTileTablesHeaderSync(tile, arrayBuffer, byteOffset);
const view = new DataView(arrayBuffer);
tile.gltfFormat = view.getUint32(byteOffset, true);
byteOffset += 4;
byteOffset = parse3DTileTablesSync(tile, arrayBuffer, byteOffset, options);
byteOffset = parse3DTileGLTFViewSync(tile, arrayBuffer, byteOffset, options);
if (!((_a = tile == null ? void 0 : tile.header) == null ? void 0 : _a.featureTableJsonByteLength) || tile.header.featureTableJsonByteLength === 0) {
throw new Error("i3dm parser: featureTableJsonByteLength is zero.");
}
const featureTable = new Tile3DFeatureTable(tile.featureTableJson, tile.featureTableBinary);
const instancesLength = featureTable.getGlobalProperty("INSTANCES_LENGTH");
featureTable.featuresLength = instancesLength;
if (!Number.isFinite(instancesLength)) {
throw new Error("i3dm parser: INSTANCES_LENGTH must be defined");
}
tile.eastNorthUp = featureTable.getGlobalProperty("EAST_NORTH_UP");
tile.rtcCenter = featureTable.getGlobalProperty("RTC_CENTER", import_math8.GL.FLOAT, 3);
const batchTable = new Tile3DBatchTableParser(tile.batchTableJson, tile.batchTableBinary, instancesLength);
extractInstancedAttributes(tile, featureTable, batchTable, instancesLength);
return byteOffset;
}
function extractInstancedAttributes(tile, featureTable, batchTable, instancesLength) {
const instances = new Array(instancesLength);
const instancePosition = new import_core4.Vector3();
const instanceNormalRight = new import_core4.Vector3();
const instanceNormalUp = new import_core4.Vector3();
const instanceNormalForward = new import_core4.Vector3();
const instanceRotation = new import_core4.Matrix3();
const instanceQuaternion = new import_core4.Quaternion();
const instanceScale = new import_core4.Vector3();
const instanceTranslationRotationScale = {};
const instanceTransform = new import_core4.Matrix4();
const scratch1 = [];
const scratch2 = [];
const scratch3 = [];
const scratch4 = [];
for (let i = 0; i < instancesLength; i++) {
let position;
if (featureTable.hasProperty("POSITION")) {
position = featureTable.getProperty("POSITION", import_math8.GL.FLOAT, 3, i, instancePosition);
} else if (featureTable.hasProperty("POSITION_QUANTIZED")) {
position = featureTable.getProperty("POSITION_QUANTIZED", import_math8.GL.UNSIGNED_SHORT, 3, i, instancePosition);
const quantizedVolumeOffset = featureTable.getGlobalProperty("QUANTIZED_VOLUME_OFFSET", import_math8.GL.FLOAT, 3);
if (!quantizedVolumeOffset) {
throw new Error("i3dm parser: QUANTIZED_VOLUME_OFFSET must be defined for quantized positions.");
}
const quantizedVolumeScale = featureTable.getGlobalProperty("QUANTIZED_VOLUME_SCALE", import_math8.GL.FLOAT, 3);
if (!quantizedVolumeScale) {
throw new Error("i3dm parser: QUANTIZED_VOLUME_SCALE must be defined for quantized positions.");
}
const MAX_UNSIGNED_SHORT = 65535;
for (let j = 0; j < 3; j++) {
position[j] = position[j] / MAX_UNSIGNED_SHORT * quantizedVolumeScale[j] + quantizedVolumeOffset[j];
}
}
if (!position) {
throw new Error("i3dm: POSITION or POSITION_QUANTIZED must be defined for each instance.");
}
instancePosition.copy(position);
instanceTranslationRotationScale.translation = instancePosition;
tile.normalUp = featureTable.getProperty("NORMAL_UP", import_math8.GL.FLOAT, 3, i, scratch1);
tile.normalRight = featureTable.getProperty("NORMAL_RIGHT", import_math8.GL.FLOAT, 3, i, scratch2);
const hasCustomOrientation = false;
if (tile.normalUp) {
if (!tile.normalRight) {
throw new Error("i3dm: Custom orientation requires both NORMAL_UP and NORMAL_RIGHT.");
}
tile.hasCustomOrientation = true;
} else