mirror of https://github.com/CesiumGS/cesium.git
503 lines
16 KiB
JavaScript
503 lines
16 KiB
JavaScript
import {
|
|
Cartesian3,
|
|
Color,
|
|
Frozen,
|
|
defined,
|
|
JulianDate,
|
|
ImageBasedLighting,
|
|
Resource,
|
|
Cesium3DTileContentFactory,
|
|
Cesium3DTileset,
|
|
TileBoundingSphere,
|
|
} from "@cesium/engine";
|
|
|
|
import pollToPromise from "./pollToPromise.js";
|
|
|
|
const mockTile = {
|
|
contentBoundingVolume: new TileBoundingSphere(),
|
|
_contentBoundingVolume: new TileBoundingSphere(),
|
|
_header: {
|
|
content: {
|
|
boundingVolume: {
|
|
sphere: [0.0, 0.0, 0.0, 1.0],
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
function Cesium3DTilesTester() {}
|
|
|
|
function padStringToByteAlignment(string, byteAlignment) {
|
|
const length = string.length;
|
|
const paddedLength = Math.ceil(length / byteAlignment) * byteAlignment; // Round up to the required alignment
|
|
const padding = paddedLength - length;
|
|
let whitespace = "";
|
|
for (let i = 0; i < padding; ++i) {
|
|
whitespace += " ";
|
|
}
|
|
return string + whitespace;
|
|
}
|
|
|
|
const time = new JulianDate(2457522.0);
|
|
|
|
Cesium3DTilesTester.expectRender = function (scene, tileset, callback) {
|
|
const renderOptions = {
|
|
scene: scene,
|
|
time: time,
|
|
};
|
|
tileset.show = false;
|
|
expect(renderOptions).toRender([0, 0, 0, 255]);
|
|
tileset.show = true;
|
|
expect(renderOptions).toRenderAndCall(function (rgba) {
|
|
expect(rgba).not.toEqual([0, 0, 0, 255]);
|
|
if (defined(callback)) {
|
|
callback(rgba);
|
|
}
|
|
});
|
|
};
|
|
|
|
Cesium3DTilesTester.expectRenderBlank = function (scene, tileset) {
|
|
const renderOptions = {
|
|
scene: scene,
|
|
time: time,
|
|
};
|
|
tileset.show = false;
|
|
expect(renderOptions).toRender([0, 0, 0, 255]);
|
|
tileset.show = true;
|
|
expect(renderOptions).toRender([0, 0, 0, 255]);
|
|
};
|
|
|
|
Cesium3DTilesTester.expectRenderTileset = function (scene, tileset) {
|
|
// Verify render before being picked
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
|
|
|
// Pick a feature
|
|
expect(scene).toPickAndCall(function (result) {
|
|
expect(result).toBeDefined();
|
|
|
|
// Change the color of the picked feature to yellow
|
|
result.color = Color.clone(Color.YELLOW, result.color);
|
|
|
|
// Expect the pixel color to be some shade of yellow
|
|
Cesium3DTilesTester.expectRender(scene, tileset, function (rgba) {
|
|
expect(rgba[0]).toBeGreaterThan(0);
|
|
expect(rgba[1]).toBeGreaterThan(0);
|
|
expect(rgba[2]).toEqual(0);
|
|
expect(rgba[3]).toEqual(255);
|
|
});
|
|
|
|
// Turn show off and on
|
|
result.show = false;
|
|
Cesium3DTilesTester.expectRenderBlank(scene, tileset);
|
|
result.show = true;
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
|
});
|
|
};
|
|
|
|
Cesium3DTilesTester.waitForTilesLoaded = function (scene, tileset) {
|
|
return pollToPromise(function () {
|
|
scene.renderForSpecs();
|
|
return tileset.tilesLoaded;
|
|
}).then(function () {
|
|
scene.renderForSpecs();
|
|
return tileset;
|
|
});
|
|
};
|
|
|
|
Cesium3DTilesTester.waitForTileContent = function (scene, tile) {
|
|
return pollToPromise(function () {
|
|
scene.renderForSpecs();
|
|
return !tile.contentUnloaded;
|
|
}).then(function () {
|
|
scene.renderForSpecs();
|
|
return tile;
|
|
});
|
|
};
|
|
|
|
Cesium3DTilesTester.waitForTileContentReady = function (scene, tile) {
|
|
return pollToPromise(function () {
|
|
scene.renderForSpecs();
|
|
return tile.contentReady;
|
|
}).then(function () {
|
|
scene.renderForSpecs();
|
|
return tile;
|
|
});
|
|
};
|
|
|
|
// A white ambient light with low intensity
|
|
const defaultIbl = new ImageBasedLighting({
|
|
sphericalHarmonicCoefficients: [
|
|
new Cartesian3(0.4, 0.4, 0.4),
|
|
Cartesian3.ZERO,
|
|
Cartesian3.ZERO,
|
|
Cartesian3.ZERO,
|
|
Cartesian3.ZERO,
|
|
Cartesian3.ZERO,
|
|
Cartesian3.ZERO,
|
|
Cartesian3.ZERO,
|
|
Cartesian3.ZERO,
|
|
],
|
|
});
|
|
|
|
Cesium3DTilesTester.loadTileset = async function (scene, url, options) {
|
|
options = options ?? {};
|
|
options.cullRequestsWhileMoving = options.cullRequestsWhileMoving ?? false;
|
|
options.imageBasedLighting = options.imageBasedLighting ?? defaultIbl;
|
|
options.environmentMapOptions = {
|
|
enabled: false, // disable other diffuse lighting by default
|
|
...options.environmentMapOptions,
|
|
};
|
|
|
|
const tileset = await Cesium3DTileset.fromUrl(url, options);
|
|
|
|
// Load all visible tiles
|
|
scene.primitives.add(tileset);
|
|
await Cesium3DTilesTester.waitForTilesLoaded(scene, tileset);
|
|
return tileset;
|
|
};
|
|
|
|
Cesium3DTilesTester.createContentForMockTile = async function (
|
|
arrayBuffer,
|
|
type,
|
|
) {
|
|
const tileset = {};
|
|
const url = Resource.createIfNeeded("");
|
|
return Cesium3DTileContentFactory[type](
|
|
tileset,
|
|
mockTile,
|
|
url,
|
|
arrayBuffer,
|
|
0,
|
|
);
|
|
};
|
|
|
|
Cesium3DTilesTester.tileDestroys = function (scene, url, options) {
|
|
return Cesium3DTilesTester.loadTileset(scene, url, options).then(
|
|
function (tileset) {
|
|
const content = tileset.root.content;
|
|
expect(content.isDestroyed()).toEqual(false);
|
|
scene.primitives.remove(tileset);
|
|
expect(content.isDestroyed()).toEqual(true);
|
|
},
|
|
);
|
|
};
|
|
|
|
Cesium3DTilesTester.generateBatchedTileBuffer = function (options) {
|
|
// Procedurally generate the tile array buffer for testing purposes
|
|
options = options ?? Frozen.EMPTY_OBJECT;
|
|
const magic = options.magic ?? [98, 51, 100, 109];
|
|
const version = options.version ?? 1;
|
|
const featuresLength = options.featuresLength ?? 1;
|
|
const featureTableJson = {
|
|
BATCH_LENGTH: featuresLength,
|
|
};
|
|
const featureTableJsonString = JSON.stringify(featureTableJson);
|
|
const featureTableJsonByteLength = featureTableJsonString.length;
|
|
|
|
const headerByteLength = 28;
|
|
const byteLength = headerByteLength + featureTableJsonByteLength;
|
|
const buffer = new ArrayBuffer(byteLength);
|
|
const view = new DataView(buffer);
|
|
view.setUint8(0, magic[0]);
|
|
view.setUint8(1, magic[1]);
|
|
view.setUint8(2, magic[2]);
|
|
view.setUint8(3, magic[3]);
|
|
view.setUint32(4, version, true); // version
|
|
view.setUint32(8, byteLength, true); // byteLength
|
|
view.setUint32(12, featureTableJsonByteLength, true); // featureTableJsonByteLength
|
|
view.setUint32(16, 0, true); // featureTableBinaryByteLength
|
|
view.setUint32(20, 0, true); // batchTableJsonByteLength
|
|
view.setUint32(24, 0, true); // batchTableBinaryByteLength
|
|
|
|
let i;
|
|
let byteOffset = headerByteLength;
|
|
for (i = 0; i < featureTableJsonByteLength; i++) {
|
|
view.setUint8(byteOffset, featureTableJsonString.charCodeAt(i));
|
|
byteOffset++;
|
|
}
|
|
|
|
return buffer;
|
|
};
|
|
|
|
Cesium3DTilesTester.generateInstancedTileBuffer = function (options) {
|
|
// Procedurally generate the tile array buffer for testing purposes
|
|
options = options ?? Frozen.EMPTY_OBJECT;
|
|
const magic = options.magic ?? [105, 51, 100, 109];
|
|
const version = options.version ?? 1;
|
|
|
|
const gltfFormat = options.gltfFormat ?? 1;
|
|
const gltfUri = options.gltfUri ?? "model.gltf";
|
|
const gltfUriByteLength = gltfUri.length;
|
|
|
|
const featureTableJson = options.featureTableJson;
|
|
let featureTableJsonString = "";
|
|
if (defined(featureTableJson)) {
|
|
if (Object.keys(featureTableJson).length > 0) {
|
|
featureTableJsonString = JSON.stringify(featureTableJson);
|
|
}
|
|
} else {
|
|
const featuresLength = options.featuresLength ?? 1;
|
|
featureTableJsonString = JSON.stringify({
|
|
INSTANCES_LENGTH: featuresLength,
|
|
POSITION: new Array(featuresLength * 3).fill(0),
|
|
});
|
|
}
|
|
featureTableJsonString = padStringToByteAlignment(featureTableJsonString, 8);
|
|
const featureTableJsonByteLength = featureTableJsonString.length;
|
|
|
|
const featureTableBinary = options.featureTableBinary ?? new Uint8Array(0);
|
|
const featureTableBinaryByteLength = featureTableBinary.length;
|
|
|
|
const batchTableJson = options.batchTableJson;
|
|
let batchTableJsonString = "";
|
|
if (defined(batchTableJson) && Object.keys(batchTableJson).length > 0) {
|
|
batchTableJsonString = JSON.stringify(batchTableJson);
|
|
}
|
|
batchTableJsonString = padStringToByteAlignment(batchTableJsonString, 8);
|
|
const batchTableJsonByteLength = batchTableJsonString.length;
|
|
|
|
const batchTableBinary = options.batchTableBinary ?? new Uint8Array(0);
|
|
const batchTableBinaryByteLength = batchTableBinary.length;
|
|
|
|
const headerByteLength = 32;
|
|
const byteLength =
|
|
headerByteLength +
|
|
featureTableJsonByteLength +
|
|
featureTableBinaryByteLength +
|
|
batchTableJsonByteLength +
|
|
batchTableBinaryByteLength +
|
|
gltfUriByteLength;
|
|
const buffer = new ArrayBuffer(byteLength);
|
|
const view = new DataView(buffer);
|
|
view.setUint8(0, magic[0]);
|
|
view.setUint8(1, magic[1]);
|
|
view.setUint8(2, magic[2]);
|
|
view.setUint8(3, magic[3]);
|
|
view.setUint32(4, version, true);
|
|
view.setUint32(8, byteLength, true);
|
|
view.setUint32(12, featureTableJsonByteLength, true);
|
|
view.setUint32(16, featureTableBinaryByteLength, true);
|
|
view.setUint32(20, batchTableJsonByteLength, true);
|
|
view.setUint32(24, batchTableBinaryByteLength, true);
|
|
view.setUint32(28, gltfFormat, true);
|
|
|
|
let i;
|
|
let byteOffset = headerByteLength;
|
|
for (i = 0; i < featureTableJsonByteLength; i++) {
|
|
view.setUint8(byteOffset, featureTableJsonString.charCodeAt(i));
|
|
byteOffset++;
|
|
}
|
|
for (i = 0; i < featureTableBinaryByteLength; i++) {
|
|
view.setUint8(byteOffset, featureTableBinary[i]);
|
|
byteOffset++;
|
|
}
|
|
for (i = 0; i < batchTableJsonByteLength; i++) {
|
|
view.setUint8(byteOffset, batchTableJsonString.charCodeAt(i));
|
|
byteOffset++;
|
|
}
|
|
for (i = 0; i < batchTableBinaryByteLength; i++) {
|
|
view.setUint8(byteOffset, batchTableBinary[i]);
|
|
byteOffset++;
|
|
}
|
|
for (i = 0; i < gltfUriByteLength; i++) {
|
|
view.setUint8(byteOffset, gltfUri.charCodeAt(i));
|
|
byteOffset++;
|
|
}
|
|
return buffer;
|
|
};
|
|
|
|
Cesium3DTilesTester.generatePointCloudTileBuffer = function (options) {
|
|
// Procedurally generate the tile array buffer for testing purposes
|
|
options = options ?? Frozen.EMPTY_OBJECT;
|
|
const magic = options.magic ?? [112, 110, 116, 115];
|
|
const version = options.version ?? 1;
|
|
let featureTableJson = options.featureTableJson;
|
|
if (!defined(featureTableJson)) {
|
|
featureTableJson = {
|
|
POINTS_LENGTH: 1,
|
|
POSITIONS: {
|
|
byteOffset: 0,
|
|
},
|
|
};
|
|
}
|
|
|
|
let featureTableJsonString = JSON.stringify(featureTableJson);
|
|
featureTableJsonString = padStringToByteAlignment(featureTableJsonString, 4);
|
|
const featureTableJsonByteLength =
|
|
options.featureTableJsonByteLength ?? featureTableJsonString.length;
|
|
|
|
const featureTableBinary = new ArrayBuffer(12); // Enough space to hold 3 floats
|
|
const featureTableBinaryByteLength = featureTableBinary.byteLength;
|
|
|
|
const headerByteLength = 28;
|
|
const byteLength =
|
|
headerByteLength +
|
|
featureTableJsonByteLength +
|
|
featureTableBinaryByteLength;
|
|
const buffer = new ArrayBuffer(byteLength);
|
|
const view = new DataView(buffer);
|
|
view.setUint8(0, magic[0]);
|
|
view.setUint8(1, magic[1]);
|
|
view.setUint8(2, magic[2]);
|
|
view.setUint8(3, magic[3]);
|
|
view.setUint32(4, version, true); // version
|
|
view.setUint32(8, byteLength, true); // byteLength
|
|
view.setUint32(12, featureTableJsonByteLength, true); // featureTableJsonByteLength
|
|
view.setUint32(16, featureTableBinaryByteLength, true); // featureTableBinaryByteLength
|
|
view.setUint32(20, 0, true); // batchTableJsonByteLength
|
|
view.setUint32(24, 0, true); // batchTableBinaryByteLength
|
|
|
|
let i;
|
|
let byteOffset = headerByteLength;
|
|
for (i = 0; i < featureTableJsonByteLength; i++) {
|
|
view.setUint8(byteOffset, featureTableJsonString.charCodeAt(i));
|
|
byteOffset++;
|
|
}
|
|
for (i = 0; i < featureTableBinaryByteLength; i++) {
|
|
view.setUint8(byteOffset, featureTableBinary[i]);
|
|
byteOffset++;
|
|
}
|
|
return buffer;
|
|
};
|
|
|
|
Cesium3DTilesTester.generateCompositeTileBuffer = function (options) {
|
|
// Procedurally generate the tile array buffer for testing purposes
|
|
options = options ?? Frozen.EMPTY_OBJECT;
|
|
const magic = options.magic ?? [99, 109, 112, 116];
|
|
const version = options.version ?? 1;
|
|
const tiles = options.tiles ?? Frozen.EMPTY_ARRAY;
|
|
const tilesLength = tiles.length;
|
|
|
|
let i;
|
|
let tilesByteLength = 0;
|
|
for (i = 0; i < tilesLength; ++i) {
|
|
tilesByteLength += tiles[i].byteLength;
|
|
}
|
|
|
|
const headerByteLength = 16;
|
|
const byteLength = headerByteLength + tilesByteLength;
|
|
const buffer = new ArrayBuffer(byteLength);
|
|
const uint8Array = new Uint8Array(buffer);
|
|
const view = new DataView(buffer);
|
|
view.setUint8(0, magic[0]);
|
|
view.setUint8(1, magic[1]);
|
|
view.setUint8(2, magic[2]);
|
|
view.setUint8(3, magic[3]);
|
|
view.setUint32(4, version, true); // version
|
|
view.setUint32(8, byteLength, true); // byteLength
|
|
view.setUint32(12, tilesLength, true); // tilesLength
|
|
|
|
let byteOffset = headerByteLength;
|
|
for (i = 0; i < tilesLength; ++i) {
|
|
const tile = new Uint8Array(tiles[i]);
|
|
uint8Array.set(tile, byteOffset);
|
|
byteOffset += tile.byteLength;
|
|
}
|
|
|
|
return buffer;
|
|
};
|
|
|
|
Cesium3DTilesTester.generateVectorTileBuffer = function (options) {
|
|
// Procedurally generate the tile array buffer for testing purposes
|
|
options = options ?? Frozen.EMPTY_OBJECT;
|
|
const magic = options.magic ?? [118, 99, 116, 114];
|
|
const version = options.version ?? 1;
|
|
|
|
let featureTableJsonString;
|
|
let featureTableJsonByteLength = 0;
|
|
const defineFeatureTable = options.defineFeatureTable ?? true;
|
|
if (defineFeatureTable) {
|
|
const defineRegion = options.defineRegion ?? true;
|
|
const featureTableJson = {
|
|
REGION: defineRegion ? [-1.0, -1.0, 1.0, 1.0, -1.0, 1.0] : undefined,
|
|
POLYGONS_LENGTH: options.polygonsLength ?? 0,
|
|
POLYLINES_LENGTH: options.polylinesLength ?? 0,
|
|
POINTS_LENGTH: options.pointsLength ?? 0,
|
|
POLYGON_BATCH_IDS: options.polygonBatchIds,
|
|
POLYLINE_BATCH_IDS: options.polylineBatchIds,
|
|
POINT_BATCH_IDS: options.pointBatchIds,
|
|
};
|
|
featureTableJsonString = JSON.stringify(featureTableJson);
|
|
featureTableJsonByteLength = featureTableJsonString.length;
|
|
}
|
|
|
|
const headerByteLength = 44;
|
|
const byteLength = headerByteLength + featureTableJsonByteLength;
|
|
const buffer = new ArrayBuffer(byteLength);
|
|
const view = new DataView(buffer);
|
|
view.setUint8(0, magic[0]);
|
|
view.setUint8(1, magic[1]);
|
|
view.setUint8(2, magic[2]);
|
|
view.setUint8(3, magic[3]);
|
|
view.setUint32(4, version, true); // version
|
|
view.setUint32(8, byteLength, true); // byteLength
|
|
view.setUint32(12, featureTableJsonByteLength, true); // featureTableJsonByteLength
|
|
view.setUint32(16, 0, true); // featureTableBinaryByteLength
|
|
view.setUint32(20, 0, true); // batchTableJsonByteLength
|
|
view.setUint32(24, 0, true); // batchTableBinaryByteLength
|
|
view.setUint32(28, 0, true); // indicesByteLength
|
|
view.setUint32(32, 0, true); // polygonPositionByteLength
|
|
view.setUint32(36, 0, true); // polylinePositionByteLength
|
|
view.setUint32(40, 0, true); // pointsPositionByteLength
|
|
|
|
let i;
|
|
let byteOffset = headerByteLength;
|
|
for (i = 0; i < featureTableJsonByteLength; i++) {
|
|
view.setUint8(byteOffset, featureTableJsonString.charCodeAt(i));
|
|
byteOffset++;
|
|
}
|
|
|
|
return buffer;
|
|
};
|
|
|
|
Cesium3DTilesTester.generateGeometryTileBuffer = function (options) {
|
|
// Procedurally generate the tile array buffer for testing purposes
|
|
options = options ?? Frozen.EMPTY_OBJECT;
|
|
const magic = options.magic ?? [103, 101, 111, 109];
|
|
const version = options.version ?? 1;
|
|
|
|
let featureTableJsonString;
|
|
let featureTableJsonByteLength = 0;
|
|
const defineFeatureTable = options.defineFeatureTable ?? true;
|
|
if (defineFeatureTable) {
|
|
const featureTableJson = {
|
|
BOXES_LENGTH: options.boxesLength ?? 0,
|
|
CYLINDERS_LENGTH: options.cylindersLength ?? 0,
|
|
ELLIPSOIDS_LENGTH: options.ellipsoidsLength ?? 0,
|
|
SPHERES_LENGTH: options.spheresLength ?? 0,
|
|
BOX_BATCH_IDS: options.boxBatchIds,
|
|
CYLINDER_BATCH_IDS: options.cylinderBatchIds,
|
|
ELLIPSOID_BATCH_IDS: options.ellipsoidBatchIds,
|
|
SPHERE_BATCH_IDS: options.sphereBatchIds,
|
|
};
|
|
featureTableJsonString = JSON.stringify(featureTableJson);
|
|
featureTableJsonByteLength = featureTableJsonString.length;
|
|
}
|
|
|
|
const headerByteLength = 28;
|
|
const byteLength = headerByteLength + featureTableJsonByteLength;
|
|
const buffer = new ArrayBuffer(byteLength);
|
|
const view = new DataView(buffer);
|
|
view.setUint8(0, magic[0]);
|
|
view.setUint8(1, magic[1]);
|
|
view.setUint8(2, magic[2]);
|
|
view.setUint8(3, magic[3]);
|
|
view.setUint32(4, version, true); // version
|
|
view.setUint32(8, byteLength, true); // byteLength
|
|
view.setUint32(12, featureTableJsonByteLength, true); // featureTableJsonByteLength
|
|
view.setUint32(16, 0, true); // featureTableBinaryByteLength
|
|
view.setUint32(20, 0, true); // batchTableJsonByteLength
|
|
view.setUint32(24, 0, true); // batchTableBinaryByteLength
|
|
|
|
let i;
|
|
let byteOffset = headerByteLength;
|
|
for (i = 0; i < featureTableJsonByteLength; i++) {
|
|
view.setUint8(byteOffset, featureTableJsonString.charCodeAt(i));
|
|
byteOffset++;
|
|
}
|
|
|
|
return buffer;
|
|
};
|
|
|
|
export default Cesium3DTilesTester;
|