123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566 |
- import Cartesian3 from "../Core/Cartesian3.js";
- import defaultValue from "../Core/defaultValue.js";
- import defined from "../Core/defined.js";
- import deprecationWarning from "../Core/deprecationWarning.js";
- import destroyObject from "../Core/destroyObject.js";
- import DeveloperError from "../Core/DeveloperError.js";
- import getJsonFromTypedArray from "../Core/getJsonFromTypedArray.js";
- import Matrix4 from "../Core/Matrix4.js";
- import RuntimeError from "../Core/RuntimeError.js";
- import Cesium3DTileBatchTable from "./Cesium3DTileBatchTable.js";
- import Vector3DTileGeometry from "./Vector3DTileGeometry.js";
- /**
- * <p>
- * Implements the {@link Cesium3DTileContent} interface.
- * </p>
- *
- * @alias Geometry3DTileContent
- * @constructor
- *
- * @private
- */
- function Geometry3DTileContent(
- tileset,
- tile,
- resource,
- arrayBuffer,
- byteOffset
- ) {
- this._tileset = tileset;
- this._tile = tile;
- this._resource = resource;
- this._geometries = undefined;
- this._metadata = undefined;
- this._batchTable = undefined;
- this._features = undefined;
- /**
- * Part of the {@link Cesium3DTileContent} interface.
- */
- this.featurePropertiesDirty = false;
- this._group = undefined;
- this._ready = false;
- // This is for backwards compatibility. It can be removed once readyPromise is removed.
- this._resolveContent = undefined;
- this._readyPromise = new Promise((resolve) => {
- this._resolveContent = resolve;
- });
- initialize(this, arrayBuffer, byteOffset);
- }
- Object.defineProperties(Geometry3DTileContent.prototype, {
- featuresLength: {
- get: function () {
- return defined(this._batchTable) ? this._batchTable.featuresLength : 0;
- },
- },
- pointsLength: {
- get: function () {
- return 0;
- },
- },
- trianglesLength: {
- get: function () {
- if (defined(this._geometries)) {
- return this._geometries.trianglesLength;
- }
- return 0;
- },
- },
- geometryByteLength: {
- get: function () {
- if (defined(this._geometries)) {
- return this._geometries.geometryByteLength;
- }
- return 0;
- },
- },
- texturesByteLength: {
- get: function () {
- return 0;
- },
- },
- batchTableByteLength: {
- get: function () {
- return defined(this._batchTable)
- ? this._batchTable.batchTableByteLength
- : 0;
- },
- },
- innerContents: {
- get: function () {
- return undefined;
- },
- },
- /**
- * Returns true when the tile's content is ready to render; otherwise false
- *
- * @memberof Geometry3DTileContent.prototype
- *
- * @type {boolean}
- * @readonly
- * @private
- */
- ready: {
- get: function () {
- return this._ready;
- },
- },
- /**
- * Gets the promise that will be resolved when the tile's content is ready to render.
- *
- * @memberof Geometry3DTileContent.prototype
- *
- * @type {Promise<Geometry3DTileContent>}
- * @readonly
- * @deprecated
- * @private
- */
- readyPromise: {
- get: function () {
- deprecationWarning(
- "Geometry3DTileContent.readyPromise",
- "Geometry3DTileContent.readyPromise was deprecated in CesiumJS 1.104. It will be removed in 1.107. Wait for Geometry3DTileContent.ready to return true instead."
- );
- return this._readyPromise;
- },
- },
- tileset: {
- get: function () {
- return this._tileset;
- },
- },
- tile: {
- get: function () {
- return this._tile;
- },
- },
- url: {
- get: function () {
- return this._resource.getUrlComponent(true);
- },
- },
- metadata: {
- get: function () {
- return this._metadata;
- },
- set: function (value) {
- this._metadata = value;
- },
- },
- batchTable: {
- get: function () {
- return this._batchTable;
- },
- },
- group: {
- get: function () {
- return this._group;
- },
- set: function (value) {
- this._group = value;
- },
- },
- });
- function createColorChangedCallback(content) {
- return function (batchId, color) {
- if (defined(content._geometries)) {
- content._geometries.updateCommands(batchId, color);
- }
- };
- }
- function getBatchIds(featureTableJson, featureTableBinary) {
- let boxBatchIds;
- let cylinderBatchIds;
- let ellipsoidBatchIds;
- let sphereBatchIds;
- let i;
- const numberOfBoxes = defaultValue(featureTableJson.BOXES_LENGTH, 0);
- const numberOfCylinders = defaultValue(featureTableJson.CYLINDERS_LENGTH, 0);
- const numberOfEllipsoids = defaultValue(
- featureTableJson.ELLIPSOIDS_LENGTH,
- 0
- );
- const numberOfSpheres = defaultValue(featureTableJson.SPHERES_LENGTH, 0);
- if (numberOfBoxes > 0 && defined(featureTableJson.BOX_BATCH_IDS)) {
- const boxBatchIdsByteOffset =
- featureTableBinary.byteOffset + featureTableJson.BOX_BATCH_IDS.byteOffset;
- boxBatchIds = new Uint16Array(
- featureTableBinary.buffer,
- boxBatchIdsByteOffset,
- numberOfBoxes
- );
- }
- if (numberOfCylinders > 0 && defined(featureTableJson.CYLINDER_BATCH_IDS)) {
- const cylinderBatchIdsByteOffset =
- featureTableBinary.byteOffset +
- featureTableJson.CYLINDER_BATCH_IDS.byteOffset;
- cylinderBatchIds = new Uint16Array(
- featureTableBinary.buffer,
- cylinderBatchIdsByteOffset,
- numberOfCylinders
- );
- }
- if (numberOfEllipsoids > 0 && defined(featureTableJson.ELLIPSOID_BATCH_IDS)) {
- const ellipsoidBatchIdsByteOffset =
- featureTableBinary.byteOffset +
- featureTableJson.ELLIPSOID_BATCH_IDS.byteOffset;
- ellipsoidBatchIds = new Uint16Array(
- featureTableBinary.buffer,
- ellipsoidBatchIdsByteOffset,
- numberOfEllipsoids
- );
- }
- if (numberOfSpheres > 0 && defined(featureTableJson.SPHERE_BATCH_IDS)) {
- const sphereBatchIdsByteOffset =
- featureTableBinary.byteOffset +
- featureTableJson.SPHERE_BATCH_IDS.byteOffset;
- sphereBatchIds = new Uint16Array(
- featureTableBinary.buffer,
- sphereBatchIdsByteOffset,
- numberOfSpheres
- );
- }
- const atLeastOneDefined =
- defined(boxBatchIds) ||
- defined(cylinderBatchIds) ||
- defined(ellipsoidBatchIds) ||
- defined(sphereBatchIds);
- const atLeastOneUndefined =
- (numberOfBoxes > 0 && !defined(boxBatchIds)) ||
- (numberOfCylinders > 0 && !defined(cylinderBatchIds)) ||
- (numberOfEllipsoids > 0 && !defined(ellipsoidBatchIds)) ||
- (numberOfSpheres > 0 && !defined(sphereBatchIds));
- if (atLeastOneDefined && atLeastOneUndefined) {
- throw new RuntimeError(
- "If one group of batch ids is defined, then all batch ids must be defined"
- );
- }
- const allUndefinedBatchIds =
- !defined(boxBatchIds) &&
- !defined(cylinderBatchIds) &&
- !defined(ellipsoidBatchIds) &&
- !defined(sphereBatchIds);
- if (allUndefinedBatchIds) {
- let id = 0;
- if (!defined(boxBatchIds) && numberOfBoxes > 0) {
- boxBatchIds = new Uint16Array(numberOfBoxes);
- for (i = 0; i < numberOfBoxes; ++i) {
- boxBatchIds[i] = id++;
- }
- }
- if (!defined(cylinderBatchIds) && numberOfCylinders > 0) {
- cylinderBatchIds = new Uint16Array(numberOfCylinders);
- for (i = 0; i < numberOfCylinders; ++i) {
- cylinderBatchIds[i] = id++;
- }
- }
- if (!defined(ellipsoidBatchIds) && numberOfEllipsoids > 0) {
- ellipsoidBatchIds = new Uint16Array(numberOfEllipsoids);
- for (i = 0; i < numberOfEllipsoids; ++i) {
- ellipsoidBatchIds[i] = id++;
- }
- }
- if (!defined(sphereBatchIds) && numberOfSpheres > 0) {
- sphereBatchIds = new Uint16Array(numberOfSpheres);
- for (i = 0; i < numberOfSpheres; ++i) {
- sphereBatchIds[i] = id++;
- }
- }
- }
- return {
- boxes: boxBatchIds,
- cylinders: cylinderBatchIds,
- ellipsoids: ellipsoidBatchIds,
- spheres: sphereBatchIds,
- };
- }
- const sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT;
- function initialize(content, arrayBuffer, byteOffset) {
- byteOffset = defaultValue(byteOffset, 0);
- const uint8Array = new Uint8Array(arrayBuffer);
- const view = new DataView(arrayBuffer);
- byteOffset += sizeOfUint32; // Skip magic number
- const version = view.getUint32(byteOffset, true);
- if (version !== 1) {
- throw new RuntimeError(
- `Only Geometry tile version 1 is supported. Version ${version} is not.`
- );
- }
- byteOffset += sizeOfUint32;
- const byteLength = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- if (byteLength === 0) {
- content._ready = true;
- content._resolveContent(content);
- return;
- }
- const featureTableJSONByteLength = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- if (featureTableJSONByteLength === 0) {
- throw new RuntimeError(
- "Feature table must have a byte length greater than zero"
- );
- }
- const featureTableBinaryByteLength = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- const batchTableJSONByteLength = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- const batchTableBinaryByteLength = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- const featureTableJson = getJsonFromTypedArray(
- uint8Array,
- byteOffset,
- featureTableJSONByteLength
- );
- byteOffset += featureTableJSONByteLength;
- const featureTableBinary = new Uint8Array(
- arrayBuffer,
- byteOffset,
- featureTableBinaryByteLength
- );
- byteOffset += featureTableBinaryByteLength;
- let batchTableJson;
- let batchTableBinary;
- if (batchTableJSONByteLength > 0) {
- // PERFORMANCE_IDEA: is it possible to allocate this on-demand? Perhaps keep the
- // arraybuffer/string compressed in memory and then decompress it when it is first accessed.
- //
- // We could also make another request for it, but that would make the property set/get
- // API async, and would double the number of numbers in some cases.
- batchTableJson = getJsonFromTypedArray(
- uint8Array,
- byteOffset,
- batchTableJSONByteLength
- );
- byteOffset += batchTableJSONByteLength;
- if (batchTableBinaryByteLength > 0) {
- // Has a batch table binary
- batchTableBinary = new Uint8Array(
- arrayBuffer,
- byteOffset,
- batchTableBinaryByteLength
- );
- // Copy the batchTableBinary section and let the underlying ArrayBuffer be freed
- batchTableBinary = new Uint8Array(batchTableBinary);
- }
- }
- const numberOfBoxes = defaultValue(featureTableJson.BOXES_LENGTH, 0);
- const numberOfCylinders = defaultValue(featureTableJson.CYLINDERS_LENGTH, 0);
- const numberOfEllipsoids = defaultValue(
- featureTableJson.ELLIPSOIDS_LENGTH,
- 0
- );
- const numberOfSpheres = defaultValue(featureTableJson.SPHERES_LENGTH, 0);
- const totalPrimitives =
- numberOfBoxes + numberOfCylinders + numberOfEllipsoids + numberOfSpheres;
- const batchTable = new Cesium3DTileBatchTable(
- content,
- totalPrimitives,
- batchTableJson,
- batchTableBinary,
- createColorChangedCallback(content)
- );
- content._batchTable = batchTable;
- if (totalPrimitives === 0) {
- return;
- }
- const modelMatrix = content.tile.computedTransform;
- let center;
- if (defined(featureTableJson.RTC_CENTER)) {
- center = Cartesian3.unpack(featureTableJson.RTC_CENTER);
- Matrix4.multiplyByPoint(modelMatrix, center, center);
- }
- const batchIds = getBatchIds(featureTableJson, featureTableBinary);
- if (
- numberOfBoxes > 0 ||
- numberOfCylinders > 0 ||
- numberOfEllipsoids > 0 ||
- numberOfSpheres > 0
- ) {
- let boxes;
- let cylinders;
- let ellipsoids;
- let spheres;
- if (numberOfBoxes > 0) {
- const boxesByteOffset =
- featureTableBinary.byteOffset + featureTableJson.BOXES.byteOffset;
- boxes = new Float32Array(
- featureTableBinary.buffer,
- boxesByteOffset,
- Vector3DTileGeometry.packedBoxLength * numberOfBoxes
- );
- }
- if (numberOfCylinders > 0) {
- const cylindersByteOffset =
- featureTableBinary.byteOffset + featureTableJson.CYLINDERS.byteOffset;
- cylinders = new Float32Array(
- featureTableBinary.buffer,
- cylindersByteOffset,
- Vector3DTileGeometry.packedCylinderLength * numberOfCylinders
- );
- }
- if (numberOfEllipsoids > 0) {
- const ellipsoidsByteOffset =
- featureTableBinary.byteOffset + featureTableJson.ELLIPSOIDS.byteOffset;
- ellipsoids = new Float32Array(
- featureTableBinary.buffer,
- ellipsoidsByteOffset,
- Vector3DTileGeometry.packedEllipsoidLength * numberOfEllipsoids
- );
- }
- if (numberOfSpheres > 0) {
- const spheresByteOffset =
- featureTableBinary.byteOffset + featureTableJson.SPHERES.byteOffset;
- spheres = new Float32Array(
- featureTableBinary.buffer,
- spheresByteOffset,
- Vector3DTileGeometry.packedSphereLength * numberOfSpheres
- );
- }
- content._geometries = new Vector3DTileGeometry({
- boxes: boxes,
- boxBatchIds: batchIds.boxes,
- cylinders: cylinders,
- cylinderBatchIds: batchIds.cylinders,
- ellipsoids: ellipsoids,
- ellipsoidBatchIds: batchIds.ellipsoids,
- spheres: spheres,
- sphereBatchIds: batchIds.spheres,
- center: center,
- modelMatrix: modelMatrix,
- batchTable: batchTable,
- boundingVolume: content.tile.boundingVolume.boundingVolume,
- });
- return content;
- }
- return Promise.resolve(content);
- }
- function createFeatures(content) {
- const featuresLength = content.featuresLength;
- if (!defined(content._features) && featuresLength > 0) {
- const features = new Array(featuresLength);
- if (defined(content._geometries)) {
- content._geometries.createFeatures(content, features);
- }
- content._features = features;
- }
- }
- Geometry3DTileContent.prototype.hasProperty = function (batchId, name) {
- return this._batchTable.hasProperty(batchId, name);
- };
- Geometry3DTileContent.prototype.getFeature = function (batchId) {
- //>>includeStart('debug', pragmas.debug);
- const featuresLength = this.featuresLength;
- if (!defined(batchId) || batchId < 0 || batchId >= featuresLength) {
- throw new DeveloperError(
- `batchId is required and between zero and featuresLength - 1 (${
- featuresLength - 1
- }).`
- );
- }
- //>>includeEnd('debug');
- createFeatures(this);
- return this._features[batchId];
- };
- Geometry3DTileContent.prototype.applyDebugSettings = function (enabled, color) {
- if (defined(this._geometries)) {
- this._geometries.applyDebugSettings(enabled, color);
- }
- };
- Geometry3DTileContent.prototype.applyStyle = function (style) {
- createFeatures(this);
- if (defined(this._geometries)) {
- this._geometries.applyStyle(style, this._features);
- }
- };
- Geometry3DTileContent.prototype.update = function (tileset, frameState) {
- if (defined(this._geometries)) {
- this._geometries.classificationType = this._tileset.classificationType;
- this._geometries.debugWireframe = this._tileset.debugWireframe;
- this._geometries.update(frameState);
- }
- if (defined(this._batchTable) && this._geometries.ready) {
- this._batchTable.update(tileset, frameState);
- this._ready = true;
- this._resolveContent(this);
- }
- };
- Geometry3DTileContent.prototype.isDestroyed = function () {
- return false;
- };
- Geometry3DTileContent.prototype.destroy = function () {
- this._geometries = this._geometries && this._geometries.destroy();
- this._batchTable = this._batchTable && this._batchTable.destroy();
- return destroyObject(this);
- };
- export default Geometry3DTileContent;
|