3513 lines
150 KiB
JavaScript
3513 lines
150 KiB
JavaScript
|
|
defineSuite([
|
||
|
|
'Scene/Cesium3DTileset',
|
||
|
|
'Core/Cartesian2',
|
||
|
|
'Core/Cartesian3',
|
||
|
|
'Core/Cartographic',
|
||
|
|
'Core/Color',
|
||
|
|
'Core/defined',
|
||
|
|
'Core/CullingVolume',
|
||
|
|
'Core/getAbsoluteUri',
|
||
|
|
'Core/getStringFromTypedArray',
|
||
|
|
'Core/HeadingPitchRange',
|
||
|
|
'Core/Intersect',
|
||
|
|
'Core/JulianDate',
|
||
|
|
'Core/Math',
|
||
|
|
'Core/Matrix4',
|
||
|
|
'Core/PerspectiveFrustum',
|
||
|
|
'Core/PrimitiveType',
|
||
|
|
'Core/Ray',
|
||
|
|
'Core/RequestScheduler',
|
||
|
|
'Core/Resource',
|
||
|
|
'Core/Transforms',
|
||
|
|
'Renderer/ClearCommand',
|
||
|
|
'Renderer/ContextLimits',
|
||
|
|
'Scene/Cesium3DTile',
|
||
|
|
'Scene/Cesium3DTileColorBlendMode',
|
||
|
|
'Scene/Cesium3DTileContentState',
|
||
|
|
'Scene/Cesium3DTileRefine',
|
||
|
|
'Scene/Cesium3DTileStyle',
|
||
|
|
'Scene/ClippingPlane',
|
||
|
|
'Scene/ClippingPlaneCollection',
|
||
|
|
'Scene/CullFace',
|
||
|
|
'Specs/Cesium3DTilesTester',
|
||
|
|
'Specs/createScene',
|
||
|
|
'Specs/pollToPromise',
|
||
|
|
'ThirdParty/when'
|
||
|
|
], function(
|
||
|
|
Cesium3DTileset,
|
||
|
|
Cartesian2,
|
||
|
|
Cartesian3,
|
||
|
|
Cartographic,
|
||
|
|
Color,
|
||
|
|
defined,
|
||
|
|
CullingVolume,
|
||
|
|
getAbsoluteUri,
|
||
|
|
getStringFromTypedArray,
|
||
|
|
HeadingPitchRange,
|
||
|
|
Intersect,
|
||
|
|
JulianDate,
|
||
|
|
CesiumMath,
|
||
|
|
Matrix4,
|
||
|
|
PerspectiveFrustum,
|
||
|
|
PrimitiveType,
|
||
|
|
Ray,
|
||
|
|
RequestScheduler,
|
||
|
|
Resource,
|
||
|
|
Transforms,
|
||
|
|
ClearCommand,
|
||
|
|
ContextLimits,
|
||
|
|
Cesium3DTile,
|
||
|
|
Cesium3DTileColorBlendMode,
|
||
|
|
Cesium3DTileContentState,
|
||
|
|
Cesium3DTileRefine,
|
||
|
|
Cesium3DTileStyle,
|
||
|
|
ClippingPlane,
|
||
|
|
ClippingPlaneCollection,
|
||
|
|
CullFace,
|
||
|
|
Cesium3DTilesTester,
|
||
|
|
createScene,
|
||
|
|
pollToPromise,
|
||
|
|
when) {
|
||
|
|
'use strict';
|
||
|
|
|
||
|
|
// It's not easily possible to mock the asynchronous pick functions
|
||
|
|
// so don't run those tests when using the WebGL stub
|
||
|
|
var webglStub = !!window.webglStub;
|
||
|
|
|
||
|
|
var scene;
|
||
|
|
var centerLongitude = -1.31968;
|
||
|
|
var centerLatitude = 0.698874;
|
||
|
|
|
||
|
|
// Parent tile with content and four child tiles with content
|
||
|
|
var tilesetUrl = 'Data/Cesium3DTiles/Tilesets/Tileset/tileset.json';
|
||
|
|
|
||
|
|
// Parent tile with no content and four child tiles with content
|
||
|
|
var tilesetEmptyRootUrl = 'Data/Cesium3DTiles/Tilesets/TilesetEmptyRoot/tileset.json';
|
||
|
|
|
||
|
|
// Tileset with 3 levels of uniform subdivision
|
||
|
|
var tilesetUniform = 'Data/Cesium3DTiles/Tilesets/TilesetUniform/tileset.json';
|
||
|
|
|
||
|
|
var tilesetReplacement1Url = 'Data/Cesium3DTiles/Tilesets/TilesetReplacement1/tileset.json';
|
||
|
|
var tilesetReplacement2Url = 'Data/Cesium3DTiles/Tilesets/TilesetReplacement2/tileset.json';
|
||
|
|
var tilesetReplacement3Url = 'Data/Cesium3DTiles/Tilesets/TilesetReplacement3/tileset.json';
|
||
|
|
|
||
|
|
// 3 level tree with mix of additive and replacement refinement
|
||
|
|
var tilesetRefinementMix = 'Data/Cesium3DTiles/Tilesets/TilesetRefinementMix/tileset.json';
|
||
|
|
|
||
|
|
// tileset.json : root content points to tiles2.json
|
||
|
|
// tiles2.json: root with b3dm content, three children with b3dm content, one child points to tiles3.json
|
||
|
|
// tiles3.json: root with b3dm content
|
||
|
|
var tilesetOfTilesetsUrl = 'Data/Cesium3DTiles/Tilesets/TilesetOfTilesets/tileset.json';
|
||
|
|
|
||
|
|
var withoutBatchTableUrl = 'Data/Cesium3DTiles/Batched/BatchedWithoutBatchTable/tileset.json';
|
||
|
|
var withBatchTableUrl = 'Data/Cesium3DTiles/Batched/BatchedWithBatchTable/tileset.json';
|
||
|
|
var noBatchIdsUrl = 'Data/Cesium3DTiles/Batched/BatchedNoBatchIds/tileset.json';
|
||
|
|
|
||
|
|
var withBatchTableHierarchyUrl = 'Data/Cesium3DTiles/Hierarchy/BatchTableHierarchy/tileset.json';
|
||
|
|
|
||
|
|
var withTransformBoxUrl = 'Data/Cesium3DTiles/Batched/BatchedWithTransformBox/tileset.json';
|
||
|
|
var withTransformSphereUrl = 'Data/Cesium3DTiles/Batched/BatchedWithTransformSphere/tileset.json';
|
||
|
|
var withTransformRegionUrl = 'Data/Cesium3DTiles/Batched/BatchedWithTransformRegion/tileset.json';
|
||
|
|
var withBoundingSphereUrl = 'Data/Cesium3DTiles/Batched/BatchedWithBoundingSphere/tileset.json';
|
||
|
|
|
||
|
|
var compositeUrl = 'Data/Cesium3DTiles/Composite/Composite/tileset.json';
|
||
|
|
var instancedUrl = 'Data/Cesium3DTiles/Instanced/InstancedWithBatchTable/tileset.json';
|
||
|
|
var instancedRedMaterialUrl = 'Data/Cesium3DTiles/Instanced/InstancedRedMaterial/tileset.json';
|
||
|
|
|
||
|
|
// 1 tile where each feature is a different source color
|
||
|
|
var colorsUrl = 'Data/Cesium3DTiles/Batched/BatchedColors/tileset.json';
|
||
|
|
|
||
|
|
// 1 tile where each feature has a reddish texture
|
||
|
|
var texturedUrl = 'Data/Cesium3DTiles/Batched/BatchedTextured/tileset.json';
|
||
|
|
|
||
|
|
// 1 tile with translucent features
|
||
|
|
var translucentUrl = 'Data/Cesium3DTiles/Batched/BatchedTranslucent/tileset.json';
|
||
|
|
|
||
|
|
// 1 tile with opaque and translucent features
|
||
|
|
var translucentOpaqueMixUrl = 'Data/Cesium3DTiles/Batched/BatchedTranslucentOpaqueMix/tileset.json';
|
||
|
|
|
||
|
|
// Root tile is transformed from local space to wgs84, child tile is rotated, scaled, and translated locally
|
||
|
|
var tilesetWithTransformsUrl = 'Data/Cesium3DTiles/Tilesets/TilesetWithTransforms/tileset.json';
|
||
|
|
|
||
|
|
// Root tile with 4 b3dm children and 1 pnts child with a viewer request volume
|
||
|
|
var tilesetWithViewerRequestVolumeUrl = 'Data/Cesium3DTiles/Tilesets/TilesetWithViewerRequestVolume/tileset.json';
|
||
|
|
|
||
|
|
// Parent tile with content and four child tiles with content with viewer request volume for each child
|
||
|
|
var tilesetReplacementWithViewerRequestVolumeUrl = 'Data/Cesium3DTiles/Tilesets/TilesetReplacementWithViewerRequestVolume/tileset.json';
|
||
|
|
|
||
|
|
var tilesetWithExternalResourcesUrl = 'Data/Cesium3DTiles/Tilesets/TilesetWithExternalResources/tileset.json';
|
||
|
|
var tilesetUrlWithContentUri = 'Data/Cesium3DTiles/Batched/BatchedWithContentDataUri/tileset.json';
|
||
|
|
|
||
|
|
var tilesetSubtreeExpirationUrl = 'Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/tileset.json';
|
||
|
|
var tilesetSubtreeUrl = 'Data/Cesium3DTiles/Tilesets/TilesetSubtreeExpiration/subtree.json';
|
||
|
|
var batchedExpirationUrl = 'Data/Cesium3DTiles/Batched/BatchedExpiration/tileset.json';
|
||
|
|
var batchedColorsB3dmUrl = 'Data/Cesium3DTiles/Batched/BatchedColors/batchedColors.b3dm';
|
||
|
|
var batchedVertexColorsUrl = 'Data/Cesium3DTiles/Batched/BatchedWithVertexColors/tileset.json';
|
||
|
|
|
||
|
|
var styleUrl = 'Data/Cesium3DTiles/Style/style.json';
|
||
|
|
|
||
|
|
var pointCloudUrl = 'Data/Cesium3DTiles/PointCloud/PointCloudRGB/tileset.json';
|
||
|
|
var pointCloudBatchedUrl = 'Data/Cesium3DTiles/PointCloud/PointCloudBatched/tileset.json';
|
||
|
|
|
||
|
|
beforeAll(function() {
|
||
|
|
scene = createScene();
|
||
|
|
});
|
||
|
|
|
||
|
|
afterAll(function() {
|
||
|
|
scene.destroyForSpecs();
|
||
|
|
});
|
||
|
|
|
||
|
|
beforeEach(function() {
|
||
|
|
RequestScheduler.clearForSpecs();
|
||
|
|
scene.morphTo3D(0.0);
|
||
|
|
|
||
|
|
var camera = scene.camera;
|
||
|
|
camera.frustum = new PerspectiveFrustum();
|
||
|
|
camera.frustum.aspectRatio = scene.drawingBufferWidth / scene.drawingBufferHeight;
|
||
|
|
camera.frustum.fov = CesiumMath.toRadians(60.0);
|
||
|
|
|
||
|
|
viewAllTiles();
|
||
|
|
});
|
||
|
|
|
||
|
|
afterEach(function() {
|
||
|
|
scene.primitives.removeAll();
|
||
|
|
});
|
||
|
|
|
||
|
|
function setZoom(distance) {
|
||
|
|
// Bird's eye view
|
||
|
|
var center = Cartesian3.fromRadians(centerLongitude, centerLatitude);
|
||
|
|
scene.camera.lookAt(center, new HeadingPitchRange(0.0, -1.57, distance));
|
||
|
|
}
|
||
|
|
|
||
|
|
function viewAllTiles() {
|
||
|
|
setZoom(15.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
function viewRootOnly() {
|
||
|
|
setZoom(100.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
function viewNothing() {
|
||
|
|
setZoom(200.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
function viewSky() {
|
||
|
|
var center = Cartesian3.fromRadians(centerLongitude, centerLatitude, 100);
|
||
|
|
scene.camera.lookAt(center, new HeadingPitchRange(0.0, 1.57, 10.0));
|
||
|
|
}
|
||
|
|
|
||
|
|
function viewBottomLeft() {
|
||
|
|
viewAllTiles();
|
||
|
|
scene.camera.moveLeft(200.0);
|
||
|
|
scene.camera.moveDown(200.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
function viewInstances() {
|
||
|
|
setZoom(30.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
function viewPointCloud() {
|
||
|
|
setZoom(5.0);
|
||
|
|
}
|
||
|
|
|
||
|
|
function isSelected(tileset, tile) {
|
||
|
|
return tileset._selectedTiles.indexOf(tile) > -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
it('throws with undefined url', function() {
|
||
|
|
expect(function() {
|
||
|
|
return new Cesium3DTileset();
|
||
|
|
}).toThrowDeveloperError();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('rejects readyPromise with invalid tileset JSON fiile', function() {
|
||
|
|
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
|
||
|
|
deferred.reject();
|
||
|
|
});
|
||
|
|
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : 'invalid.json'
|
||
|
|
}));
|
||
|
|
return tileset.readyPromise.then(function() {
|
||
|
|
fail('should not resolve');
|
||
|
|
}).otherwise(function(error) {
|
||
|
|
expect(tileset.ready).toEqual(false);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('loads json with static loadJson method', function() {
|
||
|
|
var tilesetJson = {
|
||
|
|
asset : {
|
||
|
|
version : 2.0
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
var uri = 'data:text/plain;base64,' + btoa(JSON.stringify(tilesetJson));
|
||
|
|
|
||
|
|
Cesium3DTileset.loadJson(uri).then(function(result) {
|
||
|
|
expect(result).toEqual(tilesetJson);
|
||
|
|
}).otherwise(function(error) {
|
||
|
|
fail('should not fail');
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('static method loadJson is used in Cesium3DTileset constructor', function() {
|
||
|
|
var path = 'Data/Cesium3DTiles/Tilesets/TilesetOfTilesets/tileset.json';
|
||
|
|
|
||
|
|
var originalLoadJson = Cesium3DTileset.loadJson;
|
||
|
|
|
||
|
|
// override loadJson and replace incorrect url with correct url
|
||
|
|
Cesium3DTileset.loadJson = function(tilesetUrl) {
|
||
|
|
return originalLoadJson(path);
|
||
|
|
};
|
||
|
|
|
||
|
|
// setup tileset with invalid url (overridden loadJson should replace invalid url with correct url)
|
||
|
|
var tileset = new Cesium3DTileset({
|
||
|
|
url : 'invalid.json'
|
||
|
|
});
|
||
|
|
|
||
|
|
// restore original version
|
||
|
|
Cesium3DTileset.loadJson = originalLoadJson;
|
||
|
|
|
||
|
|
return tileset.readyPromise.then(function() {
|
||
|
|
expect(tileset.ready).toEqual(true);
|
||
|
|
}).otherwise(function(error) {
|
||
|
|
fail('should not fail');
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Constructor works with promise to resource', function() {
|
||
|
|
var resource = new Resource({
|
||
|
|
url: 'Data/Cesium3DTiles/Tilesets/TilesetOfTilesets/tileset.json'
|
||
|
|
});
|
||
|
|
|
||
|
|
// setup tileset with invalid url (overridden loadJson should replace invalid url with correct url)
|
||
|
|
var tileset = new Cesium3DTileset({
|
||
|
|
url : when.resolve(resource)
|
||
|
|
});
|
||
|
|
|
||
|
|
return tileset.readyPromise.then(function() {
|
||
|
|
expect(tileset.ready).toEqual(true);
|
||
|
|
}).otherwise(function(error) {
|
||
|
|
fail('should not fail');
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Constructor works with file resource', function() {
|
||
|
|
var resource = new Resource({
|
||
|
|
url: 'Data/Cesium3DTiles/Tilesets/TilesetOfTilesets/tileset.json'
|
||
|
|
});
|
||
|
|
|
||
|
|
// setup tileset with invalid url (overridden loadJson should replace invalid url with correct url)
|
||
|
|
var tileset = new Cesium3DTileset({
|
||
|
|
url : resource
|
||
|
|
});
|
||
|
|
|
||
|
|
return tileset.readyPromise.then(function() {
|
||
|
|
expect(tileset.ready).toEqual(true);
|
||
|
|
}).otherwise(function(error) {
|
||
|
|
fail('should not fail');
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('rejects readyPromise with invalid tileset version', function() {
|
||
|
|
var tilesetJson = {
|
||
|
|
asset : {
|
||
|
|
version : 2.0
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
var uri = 'data:text/plain;base64,' + btoa(JSON.stringify(tilesetJson));
|
||
|
|
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : uri
|
||
|
|
}));
|
||
|
|
return tileset.readyPromise.then(function() {
|
||
|
|
fail('should not resolve');
|
||
|
|
}).otherwise(function(error) {
|
||
|
|
expect(tileset.ready).toEqual(false);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('url and tilesetUrl set up correctly given tileset JSON filepath', function() {
|
||
|
|
var path = 'Data/Cesium3DTiles/Tilesets/TilesetOfTilesets/tileset.json';
|
||
|
|
var tileset = new Cesium3DTileset({
|
||
|
|
url : path
|
||
|
|
});
|
||
|
|
expect(tileset.url).toEqual(path);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('url and tilesetUrl set up correctly given path with query string', function() {
|
||
|
|
var path = 'Data/Cesium3DTiles/Tilesets/TilesetOfTilesets/tileset.json';
|
||
|
|
var param = '?param1=1¶m2=2';
|
||
|
|
var tileset = new Cesium3DTileset({
|
||
|
|
url : path + param
|
||
|
|
});
|
||
|
|
expect(tileset.url).toEqual(path + param);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('resolves readyPromise', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
return tileset.readyPromise.then(function(tileset) {
|
||
|
|
expect(tileset.ready).toEqual(true);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('loads tileset JSON file', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var asset = tileset.asset;
|
||
|
|
expect(asset).toBeDefined();
|
||
|
|
expect(asset.version).toEqual('1.0');
|
||
|
|
expect(asset.tilesetVersion).toEqual('1.2.3');
|
||
|
|
|
||
|
|
var properties = tileset.properties;
|
||
|
|
expect(properties).toBeDefined();
|
||
|
|
expect(properties.id).toBeDefined();
|
||
|
|
expect(properties.id.minimum).toEqual(0);
|
||
|
|
expect(properties.id.maximum).toEqual(9);
|
||
|
|
|
||
|
|
expect(tileset._geometricError).toEqual(240.0);
|
||
|
|
expect(tileset.root).toBeDefined();
|
||
|
|
expect(tileset.url).toEqual(tilesetUrl);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('loads tileset with extras', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
expect(tileset.extras).toEqual({ 'name': 'Sample Tileset' });
|
||
|
|
expect(tileset.root.extras).toBeUndefined();
|
||
|
|
|
||
|
|
var length = tileset.root.children.length;
|
||
|
|
var taggedChildren = 0;
|
||
|
|
for (var i = 0; i < length; ++i) {
|
||
|
|
if (defined(tileset.root.children[i].extras)) {
|
||
|
|
expect(tileset.root.children[i].extras).toEqual({ 'id': 'Special Tile' });
|
||
|
|
++taggedChildren;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
expect(taggedChildren).toEqual(1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('gets root tile', function() {
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : tilesetUrl
|
||
|
|
}));
|
||
|
|
expect(function() {
|
||
|
|
return tileset.root;
|
||
|
|
}).toThrowDeveloperError();
|
||
|
|
return tileset.readyPromise.then(function() {
|
||
|
|
expect(tileset.root).toBeDefined();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('hasExtension returns true if the tileset JSON file uses the specified extension', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, withBatchTableHierarchyUrl).then(function(tileset) {
|
||
|
|
expect(tileset.hasExtension('3DTILES_batch_table_hierarchy')).toBe(true);
|
||
|
|
expect(tileset.hasExtension('3DTILES_nonexistant_extension')).toBe(false);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('passes version in query string to tiles', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
expect(tileset.root.content._resource.url).toEqual(getAbsoluteUri(tilesetUrl.replace('tileset.json','parent.b3dm?v=1.2.3')));
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('passes version in query string to all external resources', function() {
|
||
|
|
// Spy on loadWithXhr so we can verify requested urls
|
||
|
|
spyOn(Resource._Implementations, 'loadWithXhr').and.callThrough();
|
||
|
|
|
||
|
|
var queryParams = '?a=1&b=boy';
|
||
|
|
var queryParamsWithVersion = '?a=1&b=boy&v=1.2.3';
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetWithExternalResourcesUrl + queryParams).then(function(tileset) {
|
||
|
|
var calls = Resource._Implementations.loadWithXhr.calls.all();
|
||
|
|
var callsLength = calls.length;
|
||
|
|
for (var i = 0; i < callsLength; ++i) {
|
||
|
|
var url = calls[0].args[0];
|
||
|
|
if (url.indexOf(tilesetWithExternalResourcesUrl) >= 0) {
|
||
|
|
var query = url.slice(url.indexOf('?'));
|
||
|
|
if (url.indexOf('tileset.json') >= 0) {
|
||
|
|
// The initial tileset.json does not have a tileset version parameter
|
||
|
|
expect(query).toBe(queryParams);
|
||
|
|
} else {
|
||
|
|
expect(query).toBe(queryParamsWithVersion);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws when getting asset and tileset is not ready', function() {
|
||
|
|
var tileset = new Cesium3DTileset({
|
||
|
|
url : tilesetUrl
|
||
|
|
});
|
||
|
|
expect(function() {
|
||
|
|
return tileset.asset;
|
||
|
|
}).toThrowDeveloperError();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws when getting properties and tileset is not ready', function() {
|
||
|
|
var tileset = new Cesium3DTileset({
|
||
|
|
url : tilesetUrl
|
||
|
|
});
|
||
|
|
expect(function() {
|
||
|
|
return tileset.properties;
|
||
|
|
}).toThrowDeveloperError();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws when getting extras and tileset is not ready', function() {
|
||
|
|
var tileset = new Cesium3DTileset({
|
||
|
|
url : tilesetUrl
|
||
|
|
});
|
||
|
|
expect(function() {
|
||
|
|
return tileset.extras;
|
||
|
|
}).toThrowDeveloperError();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('requests tile with invalid magic', function() {
|
||
|
|
var invalidMagicBuffer = Cesium3DTilesTester.generateBatchedTileBuffer({
|
||
|
|
magic : [120, 120, 120, 120]
|
||
|
|
});
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : tilesetUrl
|
||
|
|
}));
|
||
|
|
return tileset.readyPromise.then(function(tileset) {
|
||
|
|
// Start spying after the tileset json has been loaded
|
||
|
|
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
|
||
|
|
deferred.resolve(invalidMagicBuffer);
|
||
|
|
});
|
||
|
|
scene.renderForSpecs(); // Request root
|
||
|
|
var root = tileset.root;
|
||
|
|
return root.contentReadyPromise.then(function() {
|
||
|
|
fail('should not resolve');
|
||
|
|
}).otherwise(function(error) {
|
||
|
|
expect(error.message).toBe('Invalid tile content.');
|
||
|
|
expect(root._contentState).toEqual(Cesium3DTileContentState.FAILED);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('handles failed tile requests', function() {
|
||
|
|
viewRootOnly();
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : tilesetUrl
|
||
|
|
}));
|
||
|
|
return tileset.readyPromise.then(function(tileset) {
|
||
|
|
// Start spying after the tileset json has been loaded
|
||
|
|
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
|
||
|
|
deferred.reject();
|
||
|
|
});
|
||
|
|
scene.renderForSpecs(); // Request root
|
||
|
|
var root = tileset.root;
|
||
|
|
return root.contentReadyPromise.then(function() {
|
||
|
|
fail('should not resolve');
|
||
|
|
}).otherwise(function(error) {
|
||
|
|
expect(root._contentState).toEqual(Cesium3DTileContentState.FAILED);
|
||
|
|
var statistics = tileset.statistics;
|
||
|
|
expect(statistics.numberOfAttemptedRequests).toBe(0);
|
||
|
|
expect(statistics.numberOfPendingRequests).toBe(0);
|
||
|
|
expect(statistics.numberOfTilesProcessing).toBe(0);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toBe(0);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('handles failed tile processing', function() {
|
||
|
|
viewRootOnly();
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : tilesetUrl
|
||
|
|
}));
|
||
|
|
return tileset.readyPromise.then(function(tileset) {
|
||
|
|
// Start spying after the tileset json has been loaded
|
||
|
|
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
|
||
|
|
deferred.resolve(Cesium3DTilesTester.generateBatchedTileBuffer({
|
||
|
|
version : 0 // Invalid version
|
||
|
|
}));
|
||
|
|
});
|
||
|
|
scene.renderForSpecs(); // Request root
|
||
|
|
var root = tileset.root;
|
||
|
|
return root.contentReadyPromise.then(function() {
|
||
|
|
fail('should not resolve');
|
||
|
|
}).otherwise(function(error) {
|
||
|
|
expect(root._contentState).toEqual(Cesium3DTileContentState.FAILED);
|
||
|
|
var statistics = tileset.statistics;
|
||
|
|
expect(statistics.numberOfAttemptedRequests).toBe(0);
|
||
|
|
expect(statistics.numberOfPendingRequests).toBe(0);
|
||
|
|
expect(statistics.numberOfTilesProcessing).toBe(0);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toBe(0);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders tileset', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(5);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders tileset in CV', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
scene.morphToColumbusView(0.0);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(5);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders tileset in 2D', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
scene.morphTo2D(0.0);
|
||
|
|
tileset.maximumScreenSpaceError = 3;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(5);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(10);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not render during morph', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var commandList = scene.frameState.commandList;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(commandList.length).toBeGreaterThan(0);
|
||
|
|
scene.morphToColumbusView(1.0);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(commandList.length).toBe(0);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders tileset with empty root tile', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetEmptyRootUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(5);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(4); // Empty tile doesn't issue a command
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('verify statistics', function() {
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : tilesetUrl
|
||
|
|
}));
|
||
|
|
|
||
|
|
// Verify initial values
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(0);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(0);
|
||
|
|
expect(statistics.numberOfPendingRequests).toEqual(0);
|
||
|
|
expect(statistics.numberOfTilesProcessing).toEqual(0);
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.waitForReady(scene, tileset).then(function() {
|
||
|
|
// Check that root and children are requested
|
||
|
|
expect(statistics.visited).toEqual(5);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(0);
|
||
|
|
expect(statistics.numberOfPendingRequests).toEqual(5);
|
||
|
|
expect(statistics.numberOfTilesProcessing).toEqual(0);
|
||
|
|
|
||
|
|
// Wait for all tiles to load and check that they are all visited and rendered
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(statistics.visited).toEqual(5);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
expect(statistics.numberOfPendingRequests).toEqual(0);
|
||
|
|
expect(statistics.numberOfTilesProcessing).toEqual(0);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
function checkPointAndFeatureCounts(tileset, features, points, triangles) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
|
||
|
|
expect(statistics.numberOfFeaturesSelected).toEqual(0);
|
||
|
|
expect(statistics.numberOfFeaturesLoaded).toEqual(0);
|
||
|
|
expect(statistics.numberOfPointsSelected).toEqual(0);
|
||
|
|
expect(statistics.numberOfPointsLoaded).toEqual(0);
|
||
|
|
expect(statistics.numberOfTrianglesSelected).toEqual(0);
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(statistics.numberOfFeaturesSelected).toEqual(features);
|
||
|
|
expect(statistics.numberOfFeaturesLoaded).toEqual(features);
|
||
|
|
expect(statistics.numberOfPointsSelected).toEqual(points);
|
||
|
|
expect(statistics.numberOfPointsLoaded).toEqual(points);
|
||
|
|
expect(statistics.numberOfTrianglesSelected).toEqual(triangles);
|
||
|
|
|
||
|
|
viewNothing();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfFeaturesSelected).toEqual(0);
|
||
|
|
expect(statistics.numberOfFeaturesLoaded).toEqual(features);
|
||
|
|
expect(statistics.numberOfPointsSelected).toEqual(0);
|
||
|
|
expect(statistics.numberOfPointsLoaded).toEqual(points);
|
||
|
|
expect(statistics.numberOfTrianglesSelected).toEqual(0);
|
||
|
|
|
||
|
|
tileset.trimLoadedTiles();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfFeaturesSelected).toEqual(0);
|
||
|
|
expect(statistics.numberOfFeaturesLoaded).toEqual(0);
|
||
|
|
expect(statistics.numberOfPointsSelected).toEqual(0);
|
||
|
|
expect(statistics.numberOfPointsLoaded).toEqual(0);
|
||
|
|
expect(statistics.numberOfTrianglesSelected).toEqual(0);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
it('verify batched features statistics', function() {
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : withBatchTableUrl
|
||
|
|
}));
|
||
|
|
|
||
|
|
return checkPointAndFeatureCounts(tileset, 10, 0, 120);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('verify no batch table features statistics', function() {
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : noBatchIdsUrl
|
||
|
|
}));
|
||
|
|
|
||
|
|
return checkPointAndFeatureCounts(tileset, 0, 0, 120);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('verify instanced features statistics', function() {
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : instancedRedMaterialUrl
|
||
|
|
}));
|
||
|
|
|
||
|
|
return checkPointAndFeatureCounts(tileset, 25, 0, 12);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('verify composite features statistics', function() {
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : compositeUrl
|
||
|
|
}));
|
||
|
|
|
||
|
|
return checkPointAndFeatureCounts(tileset, 35, 0, 132);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('verify tileset of tilesets features statistics', function() {
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : tilesetOfTilesetsUrl
|
||
|
|
}));
|
||
|
|
|
||
|
|
return checkPointAndFeatureCounts(tileset, 50, 0, 600);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('verify points statistics', function() {
|
||
|
|
viewPointCloud();
|
||
|
|
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : pointCloudUrl
|
||
|
|
}));
|
||
|
|
|
||
|
|
return checkPointAndFeatureCounts(tileset, 0, 1000, 0);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('verify triangle statistics', function() {
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : tilesetEmptyRootUrl
|
||
|
|
}));
|
||
|
|
|
||
|
|
return checkPointAndFeatureCounts(tileset, 40, 0, 480);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('verify batched points statistics', function() {
|
||
|
|
viewPointCloud();
|
||
|
|
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : pointCloudBatchedUrl
|
||
|
|
}));
|
||
|
|
|
||
|
|
return checkPointAndFeatureCounts(tileset, 8, 1000, 0);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('verify memory usage statistics', function() {
|
||
|
|
// Calculations in Batched3DModel3DTileContentSpec, minus uvs
|
||
|
|
var singleTileGeometryMemory = 7440;
|
||
|
|
var singleTileTextureMemory = 0;
|
||
|
|
var singleTileBatchTextureMemory = 40;
|
||
|
|
var singleTilePickTextureMemory = 40;
|
||
|
|
var tilesLength = 5;
|
||
|
|
|
||
|
|
viewNothing();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
|
||
|
|
// No tiles loaded
|
||
|
|
expect(statistics.geometryByteLength).toEqual(0);
|
||
|
|
expect(statistics.texturesByteLength).toEqual(0);
|
||
|
|
expect(statistics.batchTableByteLength).toEqual(0);
|
||
|
|
|
||
|
|
viewRootOnly();
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
// Root tile loaded
|
||
|
|
expect(statistics.geometryByteLength).toEqual(singleTileGeometryMemory);
|
||
|
|
expect(statistics.texturesByteLength).toEqual(singleTileTextureMemory);
|
||
|
|
expect(statistics.batchTableByteLength).toEqual(0);
|
||
|
|
|
||
|
|
viewAllTiles();
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
// All tiles loaded
|
||
|
|
expect(statistics.geometryByteLength).toEqual(singleTileGeometryMemory * tilesLength);
|
||
|
|
expect(statistics.texturesByteLength).toEqual(singleTileTextureMemory * tilesLength);
|
||
|
|
expect(statistics.batchTableByteLength).toEqual(0);
|
||
|
|
|
||
|
|
// One feature colored, the batch table memory is now higher
|
||
|
|
tileset.root.content.getFeature(0).color = Color.RED;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.geometryByteLength).toEqual(singleTileGeometryMemory * tilesLength);
|
||
|
|
expect(statistics.texturesByteLength).toEqual(singleTileTextureMemory * tilesLength);
|
||
|
|
expect(statistics.batchTableByteLength).toEqual(singleTileBatchTextureMemory);
|
||
|
|
|
||
|
|
// All tiles picked, the texture memory is now higher
|
||
|
|
scene.pickForSpecs();
|
||
|
|
expect(statistics.geometryByteLength).toEqual(singleTileGeometryMemory * tilesLength);
|
||
|
|
expect(statistics.texturesByteLength).toEqual(singleTileTextureMemory * tilesLength);
|
||
|
|
expect(statistics.batchTableByteLength).toEqual(singleTileBatchTextureMemory + singleTilePickTextureMemory * tilesLength);
|
||
|
|
|
||
|
|
// Tiles are still in memory when zoomed out
|
||
|
|
viewNothing();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.geometryByteLength).toEqual(singleTileGeometryMemory * tilesLength);
|
||
|
|
expect(statistics.texturesByteLength).toEqual(singleTileTextureMemory * tilesLength);
|
||
|
|
expect(statistics.batchTableByteLength).toEqual(singleTileBatchTextureMemory + singleTilePickTextureMemory * tilesLength);
|
||
|
|
|
||
|
|
// Trim loaded tiles, expect the memory statistics to be 0
|
||
|
|
tileset.trimLoadedTiles();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.geometryByteLength).toEqual(0);
|
||
|
|
expect(statistics.texturesByteLength).toEqual(0);
|
||
|
|
expect(statistics.batchTableByteLength).toEqual(0);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('verify memory usage statistics for shared resources', function() {
|
||
|
|
// Six tiles total:
|
||
|
|
// * Two b3dm tiles - no shared resources
|
||
|
|
// * Two i3dm tiles with embedded glTF - no shared resources
|
||
|
|
// * Two i3dm tiles with external glTF - shared resources
|
||
|
|
// Expect to see some saving with memory usage since two of the tiles share resources
|
||
|
|
// All tiles reference the same external texture but texture caching is not supported yet
|
||
|
|
// TODO : tweak test when #5051 is in
|
||
|
|
|
||
|
|
var b3dmGeometryMemory = 840; // Only one box in the tile, unlike most other test tiles
|
||
|
|
var i3dmGeometryMemory = 840;
|
||
|
|
|
||
|
|
// Texture is 128x128 RGBA bytes, not mipmapped
|
||
|
|
var texturesByteLength = 65536;
|
||
|
|
|
||
|
|
var expectedGeometryMemory = b3dmGeometryMemory * 2 + i3dmGeometryMemory * 3;
|
||
|
|
var expectedTextureMemory = texturesByteLength * 5;
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetWithExternalResourcesUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.geometryByteLength).toBe(expectedGeometryMemory);
|
||
|
|
expect(statistics.texturesByteLength).toBe(expectedTextureMemory);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not process tileset when screen space error is not met', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(5);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
|
||
|
|
// Set zoom far enough away to not meet sse
|
||
|
|
viewNothing();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.visited).toEqual(0);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(0);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not select tiles when outside of view frustum', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(5);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
|
||
|
|
viewSky();
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.visited).toEqual(0);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(0);
|
||
|
|
expect(tileset.root.visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not load additive tiles that are out of view', function() {
|
||
|
|
viewBottomLeft();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(2);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('culls with content box', function() {
|
||
|
|
// Root tile has a content box that is half the extents of its box
|
||
|
|
// Expect to cull root tile and three child tiles
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(5);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
|
||
|
|
viewBottomLeft();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.visited).toEqual(2); // Visits root, but does not render it
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
expect(tileset._selectedTiles[0]).not.toBe(tileset.root);
|
||
|
|
|
||
|
|
// Set contents box to undefined, and now root won't be culled
|
||
|
|
tileset.root._contentBoundingVolume = undefined;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.visited).toEqual(2);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(2);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
function findTileByUri(tiles, uri) {
|
||
|
|
var length = tiles.length;
|
||
|
|
for (var i = 0; i < length; ++i) {
|
||
|
|
var tile = tiles[i];
|
||
|
|
var contentHeader = tile._header.content;
|
||
|
|
if (defined(contentHeader)) {
|
||
|
|
if (contentHeader.uri.indexOf(uri) >= 0) {
|
||
|
|
return tile;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return undefined;
|
||
|
|
}
|
||
|
|
|
||
|
|
it('selects children in front to back order', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
// After moving the camera left by 1.0 and down by 0.5, the distance from the camera should be in the order:
|
||
|
|
// 1. lower left
|
||
|
|
// 2. upper left
|
||
|
|
// 3. lower right
|
||
|
|
// 4. upper right
|
||
|
|
|
||
|
|
scene.camera.moveLeft(1.0);
|
||
|
|
scene.camera.moveDown(0.5);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
var root = tileset.root;
|
||
|
|
var llTile = findTileByUri(root.children, 'll.b3dm');
|
||
|
|
var lrTile = findTileByUri(root.children, 'lr.b3dm');
|
||
|
|
var urTile = findTileByUri(root.children, 'ur.b3dm');
|
||
|
|
var ulTile = findTileByUri(root.children, 'ul.b3dm');
|
||
|
|
|
||
|
|
var selectedTiles = tileset._selectedTiles;
|
||
|
|
expect(selectedTiles[0]).toBe(root);
|
||
|
|
expect(selectedTiles[1]).toBe(llTile);
|
||
|
|
expect(selectedTiles[2]).toBe(ulTile);
|
||
|
|
expect(selectedTiles[3]).toBe(lrTile);
|
||
|
|
expect(selectedTiles[4]).toBe(urTile);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
function testDynamicScreenSpaceError(url, distance) {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, url).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
|
||
|
|
// Horizon view, only root is visible
|
||
|
|
var center = Cartesian3.fromRadians(centerLongitude, centerLatitude);
|
||
|
|
scene.camera.lookAt(center, new HeadingPitchRange(0.0, 0.0, distance));
|
||
|
|
|
||
|
|
// Set dynamic SSE to false (default)
|
||
|
|
tileset.dynamicScreenSpaceError = false;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.visited).toEqual(1);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
|
||
|
|
// Set dynamic SSE to true, now the root is not rendered
|
||
|
|
tileset.dynamicScreenSpaceError = true;
|
||
|
|
tileset.dynamicScreenSpaceErrorDensity = 1.0;
|
||
|
|
tileset.dynamicScreenSpaceErrorFactor = 10.0;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.visited).toEqual(0);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(0);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function numberOfChildrenWithoutContent(tile) {
|
||
|
|
var children = tile.children;
|
||
|
|
var length = children.length;
|
||
|
|
var count = 0;
|
||
|
|
for (var i = 0; i < length; ++i) {
|
||
|
|
var child = children[i];
|
||
|
|
if (!child.contentReady) {
|
||
|
|
++count;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Adjust distances for each test because the dynamic SSE takes the
|
||
|
|
// bounding volume height into account, which differs for each bounding volume.
|
||
|
|
it('uses dynamic screen space error for tileset with region', function() {
|
||
|
|
return testDynamicScreenSpaceError(withTransformRegionUrl, 103.0);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('uses dynamic screen space error for tileset with bounding sphere', function() {
|
||
|
|
return testDynamicScreenSpaceError(withBoundingSphereUrl, 137.0);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('uses dynamic screen space error for local tileset with box', function() {
|
||
|
|
return testDynamicScreenSpaceError(withTransformBoxUrl, 103.0);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('uses dynamic screen space error for local tileset with sphere', function() {
|
||
|
|
return testDynamicScreenSpaceError(withTransformSphereUrl, 144.0);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('additive refinement - selects root when sse is met', function() {
|
||
|
|
viewRootOnly();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
// Meets screen space error, only root tile is rendered
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(1);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('additive refinement - selects all tiles when sse is not met', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
// Does not meet screen space error, all tiles are visible
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(5);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('additive refinement - use parent\'s geometric error on child\'s box for early refinement', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(5);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
|
||
|
|
// Both right tiles don't meet the SSE anymore
|
||
|
|
scene.camera.moveLeft(50.0);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.visited).toEqual(3);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(3);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('additive refinement - selects tile when inside viewer request volume', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetWithViewerRequestVolumeUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
// Force root tile to always not meet SSE since this is just checking the request volume
|
||
|
|
tileset.maximumScreenSpaceError = 0.0;
|
||
|
|
|
||
|
|
// Renders all 5 tiles
|
||
|
|
setZoom(20.0);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
|
||
|
|
// No longer renders the tile with a request volume
|
||
|
|
setZoom(1500.0);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toEqual(4);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('replacement refinement - selects root when sse is met', function() {
|
||
|
|
viewRootOnly();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
tileset.root.refine = Cesium3DTileRefine.REPLACE;
|
||
|
|
|
||
|
|
// Meets screen space error, only root tile is rendered
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(1);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('replacement refinement - selects children when sse is not met', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
tileset.root.refine = Cesium3DTileRefine.REPLACE;
|
||
|
|
|
||
|
|
// Does not meet screen space error, child tiles replace root tile
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(5); // Visits root, but does not render it
|
||
|
|
expect(statistics.numberOfCommands).toEqual(4);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('replacement refinement - selects root when sse is not met and children are not ready', function() {
|
||
|
|
viewRootOnly();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var root = tileset.root;
|
||
|
|
root.refine = Cesium3DTileRefine.REPLACE;
|
||
|
|
|
||
|
|
// Set zoom to start loading child tiles
|
||
|
|
viewAllTiles();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
// LOD skipping visits all visible
|
||
|
|
expect(statistics.visited).toEqual(5);
|
||
|
|
// no stencil clear command because only the root tile
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
expect(statistics.numberOfPendingRequests).toEqual(4);
|
||
|
|
expect(numberOfChildrenWithoutContent(root)).toEqual(4);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('replacement refinement - selects tile when inside viewer request volume', function() {
|
||
|
|
var options = {
|
||
|
|
skipLevelOfDetail : false
|
||
|
|
};
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetWithViewerRequestVolumeUrl, options).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
|
||
|
|
var root = tileset.root;
|
||
|
|
root.refine = Cesium3DTileRefine.REPLACE;
|
||
|
|
root.hasEmptyContent = false; // mock content
|
||
|
|
tileset.maximumScreenSpaceError = 0.0; // Force root tile to always not meet SSE since this is just checking the request volume
|
||
|
|
|
||
|
|
// Renders all 5 tiles
|
||
|
|
setZoom(20.0);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
expect(isSelected(tileset, root)).toBe(false);
|
||
|
|
|
||
|
|
// No longer renders the tile with a request volume
|
||
|
|
setZoom(1500.0);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toEqual(4);
|
||
|
|
expect(isSelected(tileset, root)).toBe(true); // one child is no longer selected. root is chosen instead
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('replacement refinement - selects upwards when traversal stops at empty tile', function() {
|
||
|
|
// No children have content, but all grandchildren have content
|
||
|
|
//
|
||
|
|
// C
|
||
|
|
// E E
|
||
|
|
// C C C C
|
||
|
|
//
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacement1Url).then(function(tileset) {
|
||
|
|
tileset.root.geometricError = 90;
|
||
|
|
setZoom(80);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.selected).toEqual(1);
|
||
|
|
expect(statistics.visited).toEqual(3);
|
||
|
|
expect(isSelected(tileset, tileset.root)).toBe(true);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('replacement refinement - selects root when sse is not met and subtree is not refinable (1)', function() {
|
||
|
|
// No children have content, but all grandchildren have content
|
||
|
|
//
|
||
|
|
// C
|
||
|
|
// E E
|
||
|
|
// C C C C
|
||
|
|
//
|
||
|
|
viewRootOnly();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacement1Url).then(function(tileset) {
|
||
|
|
tileset.skipLevelOfDetail = false;
|
||
|
|
viewAllTiles();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
var root = tileset.root;
|
||
|
|
|
||
|
|
// Even though root's children are loaded, the grandchildren need to be loaded before it becomes refinable
|
||
|
|
expect(numberOfChildrenWithoutContent(root)).toEqual(0); // Children are loaded
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1); // No stencil or backface commands; no mixed content
|
||
|
|
expect(statistics.numberOfPendingRequests).toEqual(4); // Loading grandchildren
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toEqual(4); // Render children
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('replacement refinement - selects root when sse is not met and subtree is not refinable (2)', function() {
|
||
|
|
// Check that the root is refinable once its child is loaded
|
||
|
|
//
|
||
|
|
// C
|
||
|
|
// E
|
||
|
|
// C E
|
||
|
|
// C (smaller geometric error)
|
||
|
|
//
|
||
|
|
|
||
|
|
viewRootOnly();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacement2Url).then(function(tileset) {
|
||
|
|
tileset.skipLevelOfDetail = false;
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
|
||
|
|
setZoom(5.0); // Zoom into the last tile, when it is ready the root is refinable
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(statistics.numberOfCommands).toEqual(2); // Renders two content tiles
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('replacement refinement - selects root when sse is not met and subtree is not refinable (3)', function() {
|
||
|
|
// Check that the root is refinable once its child is loaded
|
||
|
|
//
|
||
|
|
// C
|
||
|
|
// T (external tileset ref)
|
||
|
|
// E (root of external tileset)
|
||
|
|
// C C C C
|
||
|
|
//
|
||
|
|
|
||
|
|
viewRootOnly();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacement3Url).then(function(tileset) {
|
||
|
|
tileset.skipLevelOfDetail = false;
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
var root = tileset.root;
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
|
||
|
|
viewAllTiles();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
return root.children[0].contentReadyPromise.then(function() {
|
||
|
|
// The external tileset json is loaded, but the external tileset isn't.
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1); // root
|
||
|
|
expect(statistics.numberOfPendingRequests).toEqual(4); // Loading child content tiles
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(isSelected(tileset, root)).toEqual(false);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(4); // Render child content tiles
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('replacement and additive refinement', function() {
|
||
|
|
// A
|
||
|
|
// A R (not rendered)
|
||
|
|
// R A R A
|
||
|
|
//
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetRefinementMix).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(7);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(6);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('children bound union optimization', function() {
|
||
|
|
it('does not select visible tiles with invisible children', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacementWithViewerRequestVolumeUrl).then(function(tileset) {
|
||
|
|
var center = Cartesian3.fromRadians(centerLongitude, centerLatitude, 22.0);
|
||
|
|
scene.camera.lookAt(center, new HeadingPitchRange(0.0, 1.57, 1.0));
|
||
|
|
|
||
|
|
var root = tileset.root;
|
||
|
|
var childRoot = root.children[0];
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(childRoot.visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
|
||
|
|
expect(childRoot.children[0].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(childRoot.children[1].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(childRoot.children[2].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(childRoot.children[3].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
|
||
|
|
expect(tileset._selectedTiles.length).toEqual(0);
|
||
|
|
expect(isSelected(tileset, childRoot)).toBe(false);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not select external tileset whose root has invisible children', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetOfTilesetsUrl).then(function(tileset) {
|
||
|
|
var center = Cartesian3.fromRadians(centerLongitude, centerLatitude, 50.0);
|
||
|
|
scene.camera.lookAt(center, new HeadingPitchRange(0.0, 1.57, 1.0));
|
||
|
|
var root = tileset.root;
|
||
|
|
var externalRoot = root.children[0];
|
||
|
|
externalRoot.refine = Cesium3DTileRefine.REPLACE;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(isSelected(tileset, root)).toBe(false);
|
||
|
|
expect(isSelected(tileset, externalRoot)).toBe(false);
|
||
|
|
expect(root._visible).toBe(false);
|
||
|
|
expect(externalRoot._visible).toBe(false);
|
||
|
|
expect(tileset.statistics.numberOfTilesCulledWithChildrenUnion).toBe(1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not select visible tiles not meeting SSE with visible children', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacementWithViewerRequestVolumeUrl).then(function(tileset) {
|
||
|
|
var root = tileset.root;
|
||
|
|
var childRoot = root.children[0];
|
||
|
|
childRoot.geometricError = 240;
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(childRoot.visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
|
||
|
|
expect(childRoot.children[0].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(childRoot.children[1].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(childRoot.children[2].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(childRoot.children[3].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
|
||
|
|
expect(isSelected(tileset, childRoot)).toBe(false);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does select visible tiles meeting SSE with visible children', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacementWithViewerRequestVolumeUrl).then(function(tileset) {
|
||
|
|
var root = tileset.root;
|
||
|
|
var childRoot = root.children[0];
|
||
|
|
|
||
|
|
childRoot.geometricError = 0; // child root should meet SSE and children should not be drawn
|
||
|
|
scene.renderForSpecs();
|
||
|
|
// wait for load because geometric error has changed
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function(tileset) {
|
||
|
|
expect(childRoot.visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
|
||
|
|
expect(childRoot.children[0].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(childRoot.children[1].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(childRoot.children[2].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(childRoot.children[3].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
|
||
|
|
expect(isSelected(tileset, childRoot)).toBe(true);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does select visible tiles with visible children failing request volumes', function() {
|
||
|
|
var options = {
|
||
|
|
cullWithChildrenBounds : false
|
||
|
|
};
|
||
|
|
viewRootOnly();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacementWithViewerRequestVolumeUrl, options).then(function(tileset) {
|
||
|
|
var root = tileset.root;
|
||
|
|
var childRoot = root.children[0];
|
||
|
|
|
||
|
|
expect(childRoot.visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
|
||
|
|
expect(childRoot.children[0].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(childRoot.children[1].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(childRoot.children[2].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(childRoot.children[3].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
|
||
|
|
expect(tileset._selectedTiles.length).toEqual(1);
|
||
|
|
expect(isSelected(tileset, childRoot)).toBe(true);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does select visible tiles with visible children passing request volumes', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacementWithViewerRequestVolumeUrl).then(function(tileset) {
|
||
|
|
var root = tileset.root;
|
||
|
|
var childRoot = root.children[0];
|
||
|
|
childRoot.geometricError = 0;
|
||
|
|
|
||
|
|
// wait for load because geometric error has changed
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function(tileset) {
|
||
|
|
expect(childRoot.visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
|
||
|
|
expect(childRoot.children[0].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(childRoot.children[1].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(childRoot.children[2].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(childRoot.children[3].visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
|
||
|
|
expect(tileset._selectedTiles.length).toEqual(1);
|
||
|
|
expect(isSelected(tileset, childRoot)).toBe(true);
|
||
|
|
|
||
|
|
childRoot.geometricError = 200;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._selectedTiles.length).toEqual(4);
|
||
|
|
expect(isSelected(tileset, childRoot)).toBe(false);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('loads tileset with external tileset JSON file', function() {
|
||
|
|
// Set view so that no tiles are loaded initially
|
||
|
|
viewNothing();
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetOfTilesetsUrl).then(function(tileset) {
|
||
|
|
// Root points to an external tileset JSON file and has no children until it is requested
|
||
|
|
var root = tileset.root;
|
||
|
|
expect(root.children.length).toEqual(0);
|
||
|
|
|
||
|
|
// Set view so that root's content is requested
|
||
|
|
viewRootOnly();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
return root.contentReadyPromise.then(function() {
|
||
|
|
expect(root.hasTilesetContent).toEqual(true);
|
||
|
|
|
||
|
|
// Root has one child now, the root of the external tileset
|
||
|
|
expect(root.children.length).toEqual(1);
|
||
|
|
|
||
|
|
// Check that headers are equal
|
||
|
|
var subtreeRoot = root.children[0];
|
||
|
|
expect(root.refine).toEqual(subtreeRoot.refine);
|
||
|
|
expect(root.contentBoundingVolume.boundingVolume).toEqual(subtreeRoot.contentBoundingVolume.boundingVolume);
|
||
|
|
|
||
|
|
// Check that subtree root has 4 children
|
||
|
|
expect(subtreeRoot.hasTilesetContent).toEqual(false);
|
||
|
|
expect(subtreeRoot.children.length).toEqual(4);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('preserves query string with external tileset JSON file', function() {
|
||
|
|
// Set view so that no tiles are loaded initially
|
||
|
|
viewNothing();
|
||
|
|
|
||
|
|
//Spy on loadWithXhr so we can verify requested urls
|
||
|
|
spyOn(Resource._Implementations, 'loadWithXhr').and.callThrough();
|
||
|
|
|
||
|
|
var queryParams = 'a=1&b=boy';
|
||
|
|
var expectedUrl = 'Data/Cesium3DTiles/Tilesets/TilesetOfTilesets/tileset.json?' + queryParams;
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetOfTilesetsUrl + '?' + queryParams).then(function(tileset) {
|
||
|
|
//Make sure tileset JSON file was requested with query parameters
|
||
|
|
expect(Resource._Implementations.loadWithXhr.calls.argsFor(0)[0]).toEqual(expectedUrl);
|
||
|
|
|
||
|
|
Resource._Implementations.loadWithXhr.calls.reset();
|
||
|
|
|
||
|
|
// Set view so that root's content is requested
|
||
|
|
viewRootOnly();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
return tileset.root.contentReadyPromise;
|
||
|
|
}).then(function() {
|
||
|
|
//Make sure tileset2.json was requested with query parameters and does not use parent tilesetVersion
|
||
|
|
expectedUrl = getAbsoluteUri('Data/Cesium3DTiles/Tilesets/TilesetOfTilesets/tileset2.json?v=1.2.3&' + queryParams);
|
||
|
|
expect(Resource._Implementations.loadWithXhr.calls.argsFor(0)[0]).toEqual(expectedUrl);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders tileset with external tileset JSON file', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetOfTilesetsUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(7); // Visits two tiles with tileset content, five tiles with b3dm content
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5); // Render the five tiles with b3dm content
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('always visits external tileset root', function() {
|
||
|
|
viewRootOnly();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetOfTilesetsUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(2); // Visits external tileset tile, and external tileset root
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1); // Renders external tileset root
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('set tile color', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, noBatchIdsUrl).then(function(tileset) {
|
||
|
|
// Get initial color
|
||
|
|
var color;
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset, function(rgba) {
|
||
|
|
color = rgba;
|
||
|
|
});
|
||
|
|
|
||
|
|
// Check for color
|
||
|
|
tileset.root.color = Color.RED;
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset, function(rgba) {
|
||
|
|
expect(rgba).not.toEqual(color);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('debugFreezeFrame', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
viewRootOnly();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(1);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
|
||
|
|
tileset.debugFreezeFrame = true;
|
||
|
|
viewAllTiles();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.visited).toEqual(0); // selectTiles returns early, so no tiles are visited
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1); // root tile is still in selectedTiles list
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
function checkDebugColorizeTiles(url) {
|
||
|
|
CesiumMath.setRandomNumberSeed(0);
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, url).then(function(tileset) {
|
||
|
|
// Get initial color
|
||
|
|
var color;
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset, function(rgba) {
|
||
|
|
color = rgba;
|
||
|
|
});
|
||
|
|
|
||
|
|
// Check for debug color
|
||
|
|
tileset.debugColorizeTiles = true;
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset, function(rgba) {
|
||
|
|
expect(rgba).not.toEqual(color);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Check for original color
|
||
|
|
tileset.debugColorizeTiles = false;
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset, function(rgba) {
|
||
|
|
expect(rgba).toEqual(color);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
it('debugColorizeTiles for b3dm with batch table', function() {
|
||
|
|
return checkDebugColorizeTiles(withBatchTableUrl);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('debugColorizeTiles for b3dm without batch table', function() {
|
||
|
|
return checkDebugColorizeTiles(noBatchIdsUrl);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('debugColorizeTiles for i3dm', function() {
|
||
|
|
viewInstances();
|
||
|
|
return checkDebugColorizeTiles(instancedUrl);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('debugColorizeTiles for cmpt', function() {
|
||
|
|
return checkDebugColorizeTiles(compositeUrl);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('debugColorizeTiles for pnts with batch table', function() {
|
||
|
|
viewPointCloud();
|
||
|
|
return checkDebugColorizeTiles(pointCloudBatchedUrl);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('debugColorizeTiles for pnts without batch table', function() {
|
||
|
|
viewPointCloud();
|
||
|
|
return checkDebugColorizeTiles(pointCloudUrl);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('debugWireframe', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
viewRootOnly();
|
||
|
|
tileset.debugWireframe = true;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
var commands = scene.frameState.commandList;
|
||
|
|
var length = commands.length;
|
||
|
|
var i;
|
||
|
|
for (i = 0; i < length; ++i) {
|
||
|
|
expect(commands[i].primitiveType).toEqual(PrimitiveType.LINES);
|
||
|
|
}
|
||
|
|
|
||
|
|
tileset.debugWireframe = false;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
commands = scene.frameState.commandList;
|
||
|
|
for (i = 0; i < length; ++i) {
|
||
|
|
expect(commands[i].primitiveType).toEqual(PrimitiveType.TRIANGLES);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('debugShowBoundingVolume', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
viewRootOnly();
|
||
|
|
tileset.debugShowBoundingVolume = true;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(1);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(2); // Tile command + bounding volume command
|
||
|
|
|
||
|
|
tileset.debugShowBoundingVolume = false;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('debugShowContentBoundingVolume', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
viewRootOnly();
|
||
|
|
tileset.debugShowContentBoundingVolume = true;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(1);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(2); // Tile command + bounding volume command
|
||
|
|
|
||
|
|
tileset.debugShowContentBoundingVolume = false;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('debugShowViewerRequestVolume', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetWithViewerRequestVolumeUrl).then(function(tileset) {
|
||
|
|
tileset.debugShowViewerRequestVolume = true;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(6); // 1 empty root tile + 4 b3dm tiles + 1 pnts tile
|
||
|
|
expect(statistics.numberOfCommands).toEqual(6); // 5 tile commands + viewer request volume command
|
||
|
|
|
||
|
|
tileset.debugShowViewerRequestVolume = false;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('show tile debug labels with regions', function() {
|
||
|
|
// tilesetUrl has bounding regions
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
tileset.debugShowGeometricError = true;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._tileDebugLabels).toBeDefined();
|
||
|
|
expect(tileset._tileDebugLabels.length).toEqual(5);
|
||
|
|
|
||
|
|
var root = tileset.root;
|
||
|
|
expect(tileset._tileDebugLabels._labels[0].text).toEqual('Geometric error: ' + root.geometricError);
|
||
|
|
expect(tileset._tileDebugLabels._labels[1].text).toEqual('Geometric error: ' + root.children[0].geometricError);
|
||
|
|
expect(tileset._tileDebugLabels._labels[2].text).toEqual('Geometric error: ' + root.children[1].geometricError);
|
||
|
|
expect(tileset._tileDebugLabels._labels[3].text).toEqual('Geometric error: ' + root.children[2].geometricError);
|
||
|
|
expect(tileset._tileDebugLabels._labels[4].text).toEqual('Geometric error: ' + root.children[3].geometricError);
|
||
|
|
|
||
|
|
tileset.debugShowGeometricError = false;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._tileDebugLabels).not.toBeDefined();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('show tile debug labels with boxes', function() {
|
||
|
|
// tilesetWithTransformsUrl has bounding boxes
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetWithTransformsUrl).then(function(tileset) {
|
||
|
|
tileset.debugShowGeometricError = true;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._tileDebugLabels).toBeDefined();
|
||
|
|
expect(tileset._tileDebugLabels.length).toEqual(2);
|
||
|
|
|
||
|
|
var root = tileset.root;
|
||
|
|
expect(tileset._tileDebugLabels._labels[0].text).toEqual('Geometric error: ' + root.geometricError);
|
||
|
|
expect(tileset._tileDebugLabels._labels[1].text).toEqual('Geometric error: ' + root.children[0].geometricError);
|
||
|
|
|
||
|
|
tileset.debugShowGeometricError = false;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._tileDebugLabels).not.toBeDefined();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('show tile debug labels with bounding spheres', function() {
|
||
|
|
// tilesetWithViewerRequestVolumeUrl has bounding sphere
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetWithViewerRequestVolumeUrl).then(function(tileset) {
|
||
|
|
tileset.debugShowGeometricError = true;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
var length = tileset._selectedTiles.length;
|
||
|
|
expect(tileset._tileDebugLabels).toBeDefined();
|
||
|
|
expect(tileset._tileDebugLabels.length).toEqual(length);
|
||
|
|
|
||
|
|
for (var i = 0; i < length; ++i) {
|
||
|
|
expect(tileset._tileDebugLabels._labels[i].text).toEqual('Geometric error: ' + tileset._selectedTiles[i].geometricError);
|
||
|
|
}
|
||
|
|
|
||
|
|
tileset.debugShowGeometricError = false;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._tileDebugLabels).not.toBeDefined();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('show tile debug labels with rendering statistics', function() {
|
||
|
|
// tilesetUrl has bounding regions
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
tileset.debugShowRenderingStatistics = true;
|
||
|
|
viewRootOnly();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._tileDebugLabels).toBeDefined();
|
||
|
|
expect(tileset._tileDebugLabels.length).toEqual(1);
|
||
|
|
|
||
|
|
var content = tileset.root.content;
|
||
|
|
var expected = 'Commands: ' + tileset.root.commandsLength + '\n' +
|
||
|
|
'Triangles: ' + content.trianglesLength + '\n' +
|
||
|
|
'Features: ' + content.featuresLength;
|
||
|
|
|
||
|
|
expect(tileset._tileDebugLabels._labels[0].text).toEqual(expected);
|
||
|
|
|
||
|
|
tileset.debugShowRenderingStatistics = false;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._tileDebugLabels).not.toBeDefined();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('show tile debug labels with memory usage', function() {
|
||
|
|
// tilesetUrl has bounding regions
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
tileset.debugShowMemoryUsage = true;
|
||
|
|
viewRootOnly();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._tileDebugLabels).toBeDefined();
|
||
|
|
expect(tileset._tileDebugLabels.length).toEqual(1);
|
||
|
|
|
||
|
|
var expected = 'Texture Memory: 0\n' +
|
||
|
|
'Geometry Memory: 0.007';
|
||
|
|
|
||
|
|
expect(tileset._tileDebugLabels._labels[0].text).toEqual(expected);
|
||
|
|
|
||
|
|
tileset.debugShowMemoryUsage = false;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._tileDebugLabels).not.toBeDefined();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('show tile debug labels with all statistics', function() {
|
||
|
|
// tilesetUrl has bounding regions
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
tileset.debugShowGeometricError = true;
|
||
|
|
tileset.debugShowRenderingStatistics = true;
|
||
|
|
tileset.debugShowMemoryUsage = true;
|
||
|
|
tileset.debugShowUrl = true;
|
||
|
|
viewRootOnly();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._tileDebugLabels).toBeDefined();
|
||
|
|
|
||
|
|
var expected = 'Geometric error: 70\n' +
|
||
|
|
'Commands: 1\n' +
|
||
|
|
'Triangles: 120\n' +
|
||
|
|
'Features: 10\n' +
|
||
|
|
'Texture Memory: 0\n' +
|
||
|
|
'Geometry Memory: 0.007\n' +
|
||
|
|
'Url: parent.b3dm';
|
||
|
|
expect(tileset._tileDebugLabels._labels[0].text).toEqual(expected);
|
||
|
|
|
||
|
|
tileset.debugShowGeometricError = false;
|
||
|
|
tileset.debugShowRenderingStatistics = false;
|
||
|
|
tileset.debugShowMemoryUsage = false;
|
||
|
|
tileset.debugShowUrl = false;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._tileDebugLabels).not.toBeDefined();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('show only picked tile debug label with all stats', function() {
|
||
|
|
// tilesetUrl has bounding regions
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
tileset.debugShowGeometricError = true;
|
||
|
|
tileset.debugShowRenderingStatistics = true;
|
||
|
|
tileset.debugShowMemoryUsage = true;
|
||
|
|
tileset.debugShowUrl = true;
|
||
|
|
tileset.debugPickedTileLabelOnly = true;
|
||
|
|
|
||
|
|
var scratchPosition = new Cartesian3(1.0, 1.0, 1.0);
|
||
|
|
tileset.debugPickedTile = tileset.root;
|
||
|
|
tileset.debugPickPosition = scratchPosition;
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._tileDebugLabels).toBeDefined();
|
||
|
|
|
||
|
|
var expected = 'Geometric error: 70\n' +
|
||
|
|
'Commands: 1\n' +
|
||
|
|
'Triangles: 120\n' +
|
||
|
|
'Features: 10\n' +
|
||
|
|
'Texture Memory: 0\n' +
|
||
|
|
'Geometry Memory: 0.007\n' +
|
||
|
|
'Url: parent.b3dm';
|
||
|
|
expect(tileset._tileDebugLabels.get(0).text).toEqual(expected);
|
||
|
|
expect(tileset._tileDebugLabels.get(0).position).toEqual(scratchPosition);
|
||
|
|
|
||
|
|
tileset.debugPickedTile = undefined;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._tileDebugLabels.length).toEqual(0);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not request tiles when picking', function() {
|
||
|
|
viewNothing();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
viewRootOnly();
|
||
|
|
scene.pickForSpecs();
|
||
|
|
expect(tileset._statistics.numberOfPendingRequests).toEqual(0);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._statistics.numberOfPendingRequests).toEqual(1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not process tiles when picking', function() {
|
||
|
|
var spy = spyOn(Cesium3DTile.prototype, 'process').and.callThrough();
|
||
|
|
|
||
|
|
viewNothing();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
viewRootOnly();
|
||
|
|
scene.renderForSpecs(); // Request root
|
||
|
|
expect(tileset._statistics.numberOfPendingRequests).toEqual(1);
|
||
|
|
return tileset.root.contentReadyToProcessPromise.then(function() {
|
||
|
|
scene.pickForSpecs();
|
||
|
|
expect(spy).not.toHaveBeenCalled();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(spy).toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not request tiles when the request scheduler is full', function() {
|
||
|
|
viewRootOnly(); // Root tiles are loaded initially
|
||
|
|
var options = {
|
||
|
|
skipLevelOfDetail : false
|
||
|
|
};
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl, options).then(function(tileset) {
|
||
|
|
// Try to load 4 children. Only 3 requests will go through, 1 will be attempted.
|
||
|
|
var oldMaximumRequestsPerServer = RequestScheduler.maximumRequestsPerServer;
|
||
|
|
RequestScheduler.maximumRequestsPerServer = 3;
|
||
|
|
|
||
|
|
viewAllTiles();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(tileset._statistics.numberOfPendingRequests).toEqual(3);
|
||
|
|
expect(tileset._statistics.numberOfAttemptedRequests).toEqual(1);
|
||
|
|
|
||
|
|
RequestScheduler.maximumRequestsPerServer = oldMaximumRequestsPerServer;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('load progress events are raised', function() {
|
||
|
|
// [numberOfPendingRequests, numberOfTilesProcessing]
|
||
|
|
var results = [
|
||
|
|
[1, 0],
|
||
|
|
[0, 1],
|
||
|
|
[0, 0]
|
||
|
|
];
|
||
|
|
var spyUpdate = jasmine.createSpy('listener');
|
||
|
|
|
||
|
|
viewNothing();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
tileset.loadProgress.addEventListener(spyUpdate);
|
||
|
|
viewRootOnly();
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(spyUpdate.calls.count()).toEqual(3);
|
||
|
|
expect(spyUpdate.calls.allArgs()).toEqual(results);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('tilesLoaded', function() {
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : tilesetUrl
|
||
|
|
}));
|
||
|
|
expect(tileset.tilesLoaded).toBe(false);
|
||
|
|
tileset.readyPromise.then(function() {
|
||
|
|
expect(tileset.tilesLoaded).toBe(false);
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(tileset.tilesLoaded).toBe(true);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('all tiles loaded event is raised', function() {
|
||
|
|
// Called first when only the root is visible and it becomes loaded, and then again when
|
||
|
|
// the rest of the tileset is visible and all tiles are loaded.
|
||
|
|
var spyUpdate1 = jasmine.createSpy('listener');
|
||
|
|
var spyUpdate2 = jasmine.createSpy('listener');
|
||
|
|
viewRootOnly();
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : tilesetUrl
|
||
|
|
}));
|
||
|
|
tileset.allTilesLoaded.addEventListener(spyUpdate1);
|
||
|
|
tileset.initialTilesLoaded.addEventListener(spyUpdate2);
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
viewAllTiles();
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(spyUpdate1.calls.count()).toEqual(2);
|
||
|
|
expect(spyUpdate2.calls.count()).toEqual(1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('tile visible event is raised', function() {
|
||
|
|
viewRootOnly();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var spyUpdate = jasmine.createSpy('listener');
|
||
|
|
tileset.tileVisible.addEventListener(spyUpdate);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset.root.visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(spyUpdate.calls.count()).toEqual(1);
|
||
|
|
expect(spyUpdate.calls.argsFor(0)[0]).toBe(tileset.root);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('tile load event is raised', function() {
|
||
|
|
viewNothing();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var spyUpdate = jasmine.createSpy('listener');
|
||
|
|
tileset.tileLoad.addEventListener(spyUpdate);
|
||
|
|
tileset.maximumMemoryUsage = 0;
|
||
|
|
viewRootOnly();
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
// Root is loaded
|
||
|
|
expect(spyUpdate.calls.count()).toEqual(1);
|
||
|
|
expect(spyUpdate.calls.argsFor(0)[0]).toBe(tileset.root);
|
||
|
|
spyUpdate.calls.reset();
|
||
|
|
|
||
|
|
// Unload from cache
|
||
|
|
viewNothing();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset.statistics.numberOfTilesWithContentReady).toEqual(0);
|
||
|
|
|
||
|
|
// Look at root again
|
||
|
|
viewRootOnly();
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(spyUpdate.calls.count()).toEqual(1);
|
||
|
|
expect(spyUpdate.calls.argsFor(0)[0]).toBe(tileset.root);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('tile failed event is raised', function() {
|
||
|
|
viewNothing();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
|
||
|
|
deferred.reject('404');
|
||
|
|
});
|
||
|
|
var spyUpdate = jasmine.createSpy('listener');
|
||
|
|
tileset.tileFailed.addEventListener(spyUpdate);
|
||
|
|
tileset.maximumMemoryUsage = 0;
|
||
|
|
viewRootOnly();
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(spyUpdate.calls.count()).toEqual(1);
|
||
|
|
|
||
|
|
var arg = spyUpdate.calls.argsFor(0)[0];
|
||
|
|
expect(arg).toBeDefined();
|
||
|
|
expect(arg.url).toContain('parent.b3dm');
|
||
|
|
expect(arg.message).toBeDefined();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('destroys', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var root = tileset.root;
|
||
|
|
expect(tileset.isDestroyed()).toEqual(false);
|
||
|
|
scene.primitives.remove(tileset);
|
||
|
|
expect(tileset.isDestroyed()).toEqual(true);
|
||
|
|
|
||
|
|
// Check that all tiles are destroyed
|
||
|
|
expect(root.isDestroyed()).toEqual(true);
|
||
|
|
expect(root.children[0].isDestroyed()).toEqual(true);
|
||
|
|
expect(root.children[1].isDestroyed()).toEqual(true);
|
||
|
|
expect(root.children[2].isDestroyed()).toEqual(true);
|
||
|
|
expect(root.children[3].isDestroyed()).toEqual(true);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('destroys before external tileset JSON file finishes loading', function() {
|
||
|
|
viewNothing();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetOfTilesetsUrl).then(function(tileset) {
|
||
|
|
var root = tileset.root;
|
||
|
|
|
||
|
|
viewRootOnly();
|
||
|
|
scene.renderForSpecs(); // Request external tileset JSON file
|
||
|
|
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.numberOfPendingRequests).toEqual(1);
|
||
|
|
scene.primitives.remove(tileset);
|
||
|
|
|
||
|
|
return root.contentReadyPromise.then(function(root) {
|
||
|
|
fail('should not resolve');
|
||
|
|
}).otherwise(function(error) {
|
||
|
|
// Expect the root to not have added any children from the external tileset JSON file
|
||
|
|
expect(root.children.length).toEqual(0);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('destroys before tile finishes loading', function() {
|
||
|
|
viewRootOnly();
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : tilesetUrl
|
||
|
|
}));
|
||
|
|
return tileset.readyPromise.then(function(tileset) {
|
||
|
|
var root = tileset.root;
|
||
|
|
scene.renderForSpecs(); // Request root
|
||
|
|
scene.primitives.remove(tileset);
|
||
|
|
|
||
|
|
return root.contentReadyPromise.then(function(content) {
|
||
|
|
fail('should not resolve');
|
||
|
|
}).otherwise(function(error) {
|
||
|
|
expect(root._contentState).toBe(Cesium3DTileContentState.FAILED);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders with imageBaseLightingFactor', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, withoutBatchTableUrl).then(function(tileset) {
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba).not.toEqual([0, 0, 0, 255]);
|
||
|
|
tileset.imageBasedLightingFactor = new Cartesian2(0.0, 0.0);
|
||
|
|
expect(scene).notToRender(rgba);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders with lightColor', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, withoutBatchTableUrl).then(function(tileset) {
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba).not.toEqual([0, 0, 0, 255]);
|
||
|
|
tileset.imageBasedLightingFactor = new Cartesian2(0.0, 0.0);
|
||
|
|
expect(scene).toRenderAndCall(function(rgba2) {
|
||
|
|
expect(rgba2).not.toEqual(rgba);
|
||
|
|
tileset.lightColor = new Cartesian3(5.0, 5.0, 5.0);
|
||
|
|
expect(scene).notToRender(rgba2);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
///////////////////////////////////////////////////////////////////////////
|
||
|
|
// Styling tests
|
||
|
|
|
||
|
|
it('applies show style to a tileset', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, withoutBatchTableUrl).then(function(tileset) {
|
||
|
|
var hideStyle = new Cesium3DTileStyle({show : 'false'});
|
||
|
|
tileset.style = hideStyle;
|
||
|
|
expect(tileset.style).toBe(hideStyle);
|
||
|
|
expect(scene).toRender([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
tileset.style = new Cesium3DTileStyle({show : 'true'});
|
||
|
|
expect(scene).notToRender([0, 0, 0, 255]);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies show style to a tileset without features', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, noBatchIdsUrl).then(function(tileset) {
|
||
|
|
var hideStyle = new Cesium3DTileStyle({show : 'false'});
|
||
|
|
tileset.style = hideStyle;
|
||
|
|
expect(tileset.style).toBe(hideStyle);
|
||
|
|
expect(scene).toRender([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
tileset.style = new Cesium3DTileStyle({show : 'true'});
|
||
|
|
expect(scene).notToRender([0, 0, 0, 255]);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies style with complex show expression to a tileset', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl).then(function(tileset) {
|
||
|
|
// Each feature in the b3dm file has an id property from 0 to 9
|
||
|
|
// ${id} >= 10 will always evaluate to false
|
||
|
|
tileset.style = new Cesium3DTileStyle({show : '${id} >= 50 * 2'});
|
||
|
|
expect(scene).toRender([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
// ${id} < 10 will always evaluate to true
|
||
|
|
tileset.style = new Cesium3DTileStyle({show : '${id} < 200 / 2'});
|
||
|
|
expect(scene).notToRender([0, 0, 0, 255]);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies show style to a tileset with a composite tile', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, compositeUrl).then(function(tileset) {
|
||
|
|
tileset.style = new Cesium3DTileStyle({show : 'false'});
|
||
|
|
expect(scene).toRender([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
tileset.style = new Cesium3DTileStyle({show : 'true'});
|
||
|
|
expect(scene).notToRender([0, 0, 0, 255]);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
function expectColorStyle(tileset) {
|
||
|
|
var color;
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
color = rgba;
|
||
|
|
});
|
||
|
|
|
||
|
|
tileset.style = new Cesium3DTileStyle({color : 'color("blue")'});
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toEqual(0);
|
||
|
|
expect(rgba[1]).toEqual(0);
|
||
|
|
expect(rgba[2]).toBeGreaterThan(0);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
|
||
|
|
// set color to transparent
|
||
|
|
tileset.style = new Cesium3DTileStyle({color : 'color("blue", 0.0)'});
|
||
|
|
expect(scene).toRender([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
tileset.style = new Cesium3DTileStyle({color : 'color("cyan")'});
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toEqual(0);
|
||
|
|
expect(rgba[1]).toBeGreaterThan(0);
|
||
|
|
expect(rgba[2]).toBeGreaterThan(0);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Remove style
|
||
|
|
tileset.style = undefined;
|
||
|
|
expect(scene).toRender(color);
|
||
|
|
}
|
||
|
|
|
||
|
|
it('applies color style to a tileset', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, withoutBatchTableUrl).then(function(tileset) {
|
||
|
|
expectColorStyle(tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies color style to a tileset with translucent tiles', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, translucentUrl).then(function(tileset) {
|
||
|
|
expectColorStyle(tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies color style to a tileset with translucent and opaque tiles', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, translucentOpaqueMixUrl).then(function(tileset) {
|
||
|
|
expectColorStyle(tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies color style to tileset without features', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, noBatchIdsUrl).then(function(tileset) {
|
||
|
|
expectColorStyle(tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies style when feature properties change', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl).then(function(tileset) {
|
||
|
|
// Initially, all feature ids are less than 10
|
||
|
|
tileset.style = new Cesium3DTileStyle({show : '${id} < 10'});
|
||
|
|
expect(scene).notToRender([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
// Change feature ids so the show expression will evaluate to false
|
||
|
|
var content = tileset.root.content;
|
||
|
|
var length = content.featuresLength;
|
||
|
|
var i;
|
||
|
|
var feature;
|
||
|
|
for (i = 0; i < length; ++i) {
|
||
|
|
feature = content.getFeature(i);
|
||
|
|
feature.setProperty('id', feature.getProperty('id') + 10);
|
||
|
|
}
|
||
|
|
expect(scene).toRender([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
// Change ids back
|
||
|
|
for (i = 0; i < length; ++i) {
|
||
|
|
feature = content.getFeature(i);
|
||
|
|
feature.setProperty('id', feature.getProperty('id') - 10);
|
||
|
|
}
|
||
|
|
expect(scene).notToRender([0, 0, 0, 255]);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies style when tile is selected after new style is applied', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl).then(function(tileset) {
|
||
|
|
var feature = tileset.root.content.getFeature(0);
|
||
|
|
tileset.style = new Cesium3DTileStyle({color: 'color("red")'});
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(feature.color).toEqual(Color.RED);
|
||
|
|
|
||
|
|
tileset.style = new Cesium3DTileStyle({color: 'color("blue")'});
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(feature.color).toEqual(Color.BLUE);
|
||
|
|
|
||
|
|
viewNothing();
|
||
|
|
tileset.style = new Cesium3DTileStyle({color: 'color("lime")'});
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(feature.color).toEqual(Color.BLUE); // Hasn't been selected yet
|
||
|
|
|
||
|
|
viewAllTiles();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(feature.color).toEqual(Color.LIME);
|
||
|
|
|
||
|
|
// Feature's show property is preserved if the style hasn't changed and the feature is newly selected
|
||
|
|
feature.show = false;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(feature.show).toBe(false);
|
||
|
|
viewNothing();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(feature.show).toBe(false);
|
||
|
|
viewAllTiles();
|
||
|
|
expect(feature.show).toBe(false);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not reapply style during pick pass', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl).then(function(tileset) {
|
||
|
|
tileset.style = new Cesium3DTileStyle({color: 'color("red")'});
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tileset._statisticsLastRender.numberOfTilesStyled).toBe(1);
|
||
|
|
scene.pickForSpecs();
|
||
|
|
expect(tileset._statisticsLastPick.numberOfTilesStyled).toBe(0);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies style with complex color expression to a tileset', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl).then(function(tileset) {
|
||
|
|
// Each feature in the b3dm file has an id property from 0 to 9
|
||
|
|
// ${id} >= 10 will always evaluate to false
|
||
|
|
tileset.style = new Cesium3DTileStyle({color : '(${id} >= 50 * 2) ? color("red") : color("blue")'});
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toEqual(0);
|
||
|
|
expect(rgba[1]).toEqual(0);
|
||
|
|
expect(rgba[2]).toBeGreaterThan(0);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
|
||
|
|
// ${id} < 10 will always evaluate to true
|
||
|
|
tileset.style = new Cesium3DTileStyle({color : '(${id} < 50 * 2) ? color("red") : color("blue")'});
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toBeGreaterThan(0);
|
||
|
|
expect(rgba[1]).toEqual(0);
|
||
|
|
expect(rgba[2]).toEqual(0);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies conditional color style to a tileset', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl).then(function(tileset) {
|
||
|
|
// ${id} < 10 will always evaluate to true
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : {
|
||
|
|
conditions : [
|
||
|
|
['${id} < 10', 'color("red")'],
|
||
|
|
['true', 'color("blue")']
|
||
|
|
]
|
||
|
|
}
|
||
|
|
});
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toBeGreaterThan(0);
|
||
|
|
expect(rgba[1]).toEqual(0);
|
||
|
|
expect(rgba[2]).toEqual(0);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
|
||
|
|
// ${id}>= 10 will always evaluate to false
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : {
|
||
|
|
conditions : [
|
||
|
|
['${id} >= 10', 'color("red")'],
|
||
|
|
['true', 'color("blue")']
|
||
|
|
]
|
||
|
|
}
|
||
|
|
});
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toEqual(0);
|
||
|
|
expect(rgba[1]).toEqual(0);
|
||
|
|
expect(rgba[2]).toBeGreaterThan(0);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('loads style from uri', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl).then(function(tileset) {
|
||
|
|
// ${id} < 10 will always evaluate to true
|
||
|
|
tileset.style = new Cesium3DTileStyle(styleUrl);
|
||
|
|
return tileset.style.readyPromise.then(function(style) {
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toBeGreaterThan(0);
|
||
|
|
expect(rgba[1]).toEqual(0);
|
||
|
|
expect(rgba[2]).toEqual(0);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
}).otherwise(function(error) {
|
||
|
|
expect(error).not.toBeDefined();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies custom style to a tileset', function() {
|
||
|
|
var style = new Cesium3DTileStyle();
|
||
|
|
style.show = {
|
||
|
|
evaluate : function(feature) {
|
||
|
|
return this._value;
|
||
|
|
},
|
||
|
|
_value : false
|
||
|
|
};
|
||
|
|
style.color = {
|
||
|
|
evaluateColor : function(feature, result) {
|
||
|
|
return Color.clone(Color.WHITE, result);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, withoutBatchTableUrl).then(function(tileset) {
|
||
|
|
tileset.style = style;
|
||
|
|
expect(tileset.style).toBe(style);
|
||
|
|
expect(scene).toRender([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
style.show._value = true;
|
||
|
|
tileset.makeStyleDirty();
|
||
|
|
expect(scene).notToRender([0, 0, 0, 255]);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
function testColorBlendMode(url) {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, url).then(function(tileset) {
|
||
|
|
tileset.luminanceAtZenith = undefined;
|
||
|
|
|
||
|
|
// Check that the feature is red
|
||
|
|
var sourceRed;
|
||
|
|
var renderOptions = {
|
||
|
|
scene : scene,
|
||
|
|
time : new JulianDate(2457522.154792)
|
||
|
|
};
|
||
|
|
expect(renderOptions).toRenderAndCall(function(rgba) {
|
||
|
|
sourceRed = rgba[0];
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(renderOptions).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toBeGreaterThan(200);
|
||
|
|
expect(rgba[1]).toBeLessThan(25);
|
||
|
|
expect(rgba[2]).toBeLessThan(25);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Use HIGHLIGHT blending
|
||
|
|
tileset.colorBlendMode = Cesium3DTileColorBlendMode.HIGHLIGHT;
|
||
|
|
|
||
|
|
// Style with dark yellow. Expect the red channel to be darker than before.
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'rgb(128, 128, 0)'
|
||
|
|
});
|
||
|
|
expect(renderOptions).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toBeGreaterThan(100);
|
||
|
|
expect(rgba[0]).toBeLessThan(sourceRed);
|
||
|
|
expect(rgba[1]).toBeLessThan(25);
|
||
|
|
expect(rgba[2]).toBeLessThan(25);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Style with yellow + alpha. Expect the red channel to be darker than before.
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'rgba(255, 255, 0, 0.5)'
|
||
|
|
});
|
||
|
|
expect(renderOptions).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toBeGreaterThan(100);
|
||
|
|
expect(rgba[0]).toBeLessThan(sourceRed);
|
||
|
|
expect(rgba[1]).toBeLessThan(25);
|
||
|
|
expect(rgba[2]).toBeLessThan(25);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Use REPLACE blending
|
||
|
|
tileset.colorBlendMode = Cesium3DTileColorBlendMode.REPLACE;
|
||
|
|
|
||
|
|
// Style with dark yellow. Expect the red and green channels to be roughly dark yellow.
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'rgb(128, 128, 0)'
|
||
|
|
});
|
||
|
|
var replaceRed;
|
||
|
|
var replaceGreen;
|
||
|
|
expect(renderOptions).toRenderAndCall(function(rgba) {
|
||
|
|
replaceRed = rgba[0];
|
||
|
|
replaceGreen = rgba[1];
|
||
|
|
expect(rgba[0]).toBeGreaterThan(100);
|
||
|
|
expect(rgba[0]).toBeLessThan(255);
|
||
|
|
expect(rgba[1]).toBeGreaterThan(100);
|
||
|
|
expect(rgba[1]).toBeLessThan(255);
|
||
|
|
expect(rgba[2]).toBeLessThan(25);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Style with yellow + alpha. Expect the red and green channels to be a shade of yellow.
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'rgba(255, 255, 0, 0.5)'
|
||
|
|
});
|
||
|
|
expect(renderOptions).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toBeGreaterThan(100);
|
||
|
|
expect(rgba[0]).toBeLessThan(255);
|
||
|
|
expect(rgba[1]).toBeGreaterThan(100);
|
||
|
|
expect(rgba[1]).toBeLessThan(255);
|
||
|
|
expect(rgba[2]).toBeLessThan(25);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Use MIX blending
|
||
|
|
tileset.colorBlendMode = Cesium3DTileColorBlendMode.MIX;
|
||
|
|
tileset.colorBlendAmount = 0.5;
|
||
|
|
|
||
|
|
// Style with dark yellow. Expect color to be a mix of the source and style colors.
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'rgb(128, 128, 0)'
|
||
|
|
});
|
||
|
|
var mixRed;
|
||
|
|
var mixGreen;
|
||
|
|
expect(renderOptions).toRenderAndCall(function(rgba) {
|
||
|
|
mixRed = rgba[0];
|
||
|
|
mixGreen = rgba[1];
|
||
|
|
expect(rgba[0]).toBeGreaterThan(replaceRed);
|
||
|
|
expect(rgba[0]).toBeLessThan(sourceRed);
|
||
|
|
expect(rgba[1]).toBeGreaterThan(50);
|
||
|
|
expect(rgba[1]).toBeLessThan(replaceGreen);
|
||
|
|
expect(rgba[2]).toBeLessThan(25);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Set colorBlendAmount to 0.25. Expect color to be closer to the source color.
|
||
|
|
tileset.colorBlendAmount = 0.25;
|
||
|
|
expect(renderOptions).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toBeGreaterThan(mixRed);
|
||
|
|
expect(rgba[0]).toBeLessThan(sourceRed);
|
||
|
|
expect(rgba[1]).toBeGreaterThan(0);
|
||
|
|
expect(rgba[1]).toBeLessThan(mixGreen);
|
||
|
|
expect(rgba[2]).toBeLessThan(25);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Set colorBlendAmount to 0.0. Expect color to equal the source color
|
||
|
|
tileset.colorBlendAmount = 0.0;
|
||
|
|
expect(renderOptions).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toEqual(sourceRed);
|
||
|
|
expect(rgba[1]).toBeLessThan(25);
|
||
|
|
expect(rgba[2]).toBeLessThan(25);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Set colorBlendAmount to 1.0. Expect color to equal the style color
|
||
|
|
tileset.colorBlendAmount = 1.0;
|
||
|
|
expect(renderOptions).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toEqual(replaceRed);
|
||
|
|
expect(rgba[1]).toEqual(replaceGreen);
|
||
|
|
expect(rgba[2]).toBeLessThan(25);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Style with yellow + alpha. Expect color to be a mix of the source and style colors.
|
||
|
|
tileset.colorBlendAmount = 0.5;
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'rgba(255, 255, 0, 0.5)'
|
||
|
|
});
|
||
|
|
expect(renderOptions).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toBeGreaterThan(0);
|
||
|
|
expect(rgba[1]).toBeGreaterThan(0);
|
||
|
|
expect(rgba[2]).toBeLessThan(25);
|
||
|
|
expect(rgba[3]).toEqual(255);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
it('sets colorBlendMode', function() {
|
||
|
|
return testColorBlendMode(colorsUrl);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('sets colorBlendMode when vertex texture fetch is not supported', function() {
|
||
|
|
// Disable VTF
|
||
|
|
var maximumVertexTextureImageUnits = ContextLimits.maximumVertexTextureImageUnits;
|
||
|
|
ContextLimits._maximumVertexTextureImageUnits = 0;
|
||
|
|
return testColorBlendMode(colorsUrl).then(function() {
|
||
|
|
// Re-enable VTF
|
||
|
|
ContextLimits._maximumVertexTextureImageUnits = maximumVertexTextureImageUnits;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('sets colorBlendMode for textured tileset', function() {
|
||
|
|
return testColorBlendMode(texturedUrl);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('sets colorBlendMode for instanced tileset', function() {
|
||
|
|
viewInstances();
|
||
|
|
return testColorBlendMode(instancedRedMaterialUrl);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('sets colorBlendMode for vertex color tileset', function() {
|
||
|
|
return testColorBlendMode(batchedVertexColorsUrl);
|
||
|
|
});
|
||
|
|
|
||
|
|
///////////////////////////////////////////////////////////////////////////
|
||
|
|
// Cache replacement tests
|
||
|
|
|
||
|
|
it('Unload all cached tiles not required to meet SSE using maximumMemoryUsage', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
tileset.maximumMemoryUsage = 0;
|
||
|
|
|
||
|
|
// Render parent and four children (using additive refinement)
|
||
|
|
viewAllTiles();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(5); // Five loaded tiles
|
||
|
|
expect(tileset.totalMemoryUsageInBytes).toEqual(37200); // Specific to this tileset
|
||
|
|
|
||
|
|
// Zoom out so only root tile is needed to meet SSE. This unloads
|
||
|
|
// the four children since the maximum memory usage is zero.
|
||
|
|
viewRootOnly();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(1);
|
||
|
|
expect(tileset.totalMemoryUsageInBytes).toEqual(7440); // Specific to this tileset
|
||
|
|
|
||
|
|
// Zoom back in so all four children are re-requested.
|
||
|
|
viewAllTiles();
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(5); // Five loaded tiles
|
||
|
|
expect(tileset.totalMemoryUsageInBytes).toEqual(37200); // Specific to this tileset
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Unload some cached tiles not required to meet SSE using maximumMemoryUsage', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
tileset.maximumMemoryUsage = 0.025; // Just enough memory to allow 3 tiles to remain
|
||
|
|
// Render parent and four children (using additive refinement)
|
||
|
|
viewAllTiles();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(5); // Five loaded tiles
|
||
|
|
|
||
|
|
// Zoom out so only root tile is needed to meet SSE. This unloads
|
||
|
|
// two of the four children so three tiles are still loaded (the
|
||
|
|
// root and two children) since the maximum memory usage is sufficient.
|
||
|
|
viewRootOnly();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(3);
|
||
|
|
|
||
|
|
// Zoom back in so the two children are re-requested.
|
||
|
|
viewAllTiles();
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(5); // Five loaded tiles
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Unloads cached tiles outside of the view frustum using maximumMemoryUsage', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
tileset.maximumMemoryUsage = 0;
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(5);
|
||
|
|
|
||
|
|
viewSky();
|
||
|
|
|
||
|
|
// All tiles are unloaded
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toEqual(0);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(0);
|
||
|
|
|
||
|
|
// Reset camera so all tiles are reloaded
|
||
|
|
viewAllTiles();
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(5);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Unloads cached tiles in a tileset with external tileset JSON file using maximumMemoryUsage', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetOfTilesetsUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
var cacheList = tileset._cache._list;
|
||
|
|
|
||
|
|
tileset.maximumMemoryUsage = 0.02;
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(5);
|
||
|
|
expect(cacheList.length - 1).toEqual(5); // Only tiles with content are on the replacement list. -1 for sentinel.
|
||
|
|
|
||
|
|
// Zoom out so only root tile is needed to meet SSE. This unloads
|
||
|
|
// all tiles except the root and one of the b3dm children
|
||
|
|
viewRootOnly();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(2);
|
||
|
|
expect(cacheList.length - 1).toEqual(2);
|
||
|
|
|
||
|
|
// Reset camera so all tiles are reloaded
|
||
|
|
viewAllTiles();
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(5);
|
||
|
|
|
||
|
|
expect(cacheList.length - 1).toEqual(5);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Unloads cached tiles in a tileset with empty tiles using maximumMemoryUsage', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetEmptyRootUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
|
||
|
|
tileset.maximumMemoryUsage = 0.02;
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toEqual(4);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(4); // 4 children with b3dm content (does not include empty root)
|
||
|
|
|
||
|
|
viewSky();
|
||
|
|
|
||
|
|
// Unload tiles to meet cache size
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toEqual(0);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(2); // 2 children with b3dm content (does not include empty root)
|
||
|
|
|
||
|
|
// Reset camera so all tiles are reloaded
|
||
|
|
viewAllTiles();
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(statistics.numberOfCommands).toEqual(4);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(4);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Unload cached tiles when a tileset uses replacement refinement using maximumMemoryUsage', function() {
|
||
|
|
// No children have content, but all grandchildren have content
|
||
|
|
//
|
||
|
|
// C
|
||
|
|
// E E
|
||
|
|
// C C C C
|
||
|
|
//
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacement1Url).then(function(tileset) {
|
||
|
|
tileset.maximumMemoryUsage = 0; // Only root needs to be visible
|
||
|
|
|
||
|
|
// Render parent and four children (using additive refinement)
|
||
|
|
viewAllTiles();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.numberOfCommands).toEqual(4); // 4 grandchildren. Root is replaced.
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(5); // Root + four grandchildren (does not include empty children)
|
||
|
|
|
||
|
|
// Zoom out so only root tile is needed to meet SSE. This unloads
|
||
|
|
// all grandchildren since the max number of loaded tiles is one.
|
||
|
|
viewRootOnly();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(1);
|
||
|
|
|
||
|
|
// Zoom back in so the four children are re-requested.
|
||
|
|
viewAllTiles();
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function() {
|
||
|
|
expect(statistics.numberOfCommands).toEqual(4);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(5);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Explicitly unloads cached tiles with trimLoadedTiles', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
tileset.maximumMemoryUsage = 0.05;
|
||
|
|
|
||
|
|
// Render parent and four children (using additive refinement)
|
||
|
|
viewAllTiles();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(5); // Five loaded tiles
|
||
|
|
|
||
|
|
// Zoom out so only root tile is needed to meet SSE. The children
|
||
|
|
// are not unloaded since max number of loaded tiles is five.
|
||
|
|
viewRootOnly();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(5);
|
||
|
|
|
||
|
|
tileset.trimLoadedTiles();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('tileUnload event is raised', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
tileset.maximumMemoryUsage = 0;
|
||
|
|
|
||
|
|
// Render parent and four children (using additive refinement)
|
||
|
|
viewAllTiles();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(5); // Five loaded tiles
|
||
|
|
|
||
|
|
// Zoom out so only root tile is needed to meet SSE. All the
|
||
|
|
// children are unloaded since max number of loaded tiles is one.
|
||
|
|
viewRootOnly();
|
||
|
|
var spyUpdate = jasmine.createSpy('listener');
|
||
|
|
tileset.tileUnload.addEventListener(spyUpdate);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(tileset.root.visibility(scene.frameState, CullingVolume.MASK_INDETERMINATE)).not.toEqual(CullingVolume.MASK_OUTSIDE);
|
||
|
|
expect(spyUpdate.calls.count()).toEqual(4);
|
||
|
|
expect(spyUpdate.calls.argsFor(0)[0]).toBe(tileset.root.children[0]);
|
||
|
|
expect(spyUpdate.calls.argsFor(1)[0]).toBe(tileset.root.children[1]);
|
||
|
|
expect(spyUpdate.calls.argsFor(2)[0]).toBe(tileset.root.children[2]);
|
||
|
|
expect(spyUpdate.calls.argsFor(3)[0]).toBe(tileset.root.children[3]);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('maximumMemoryUsage throws when negative', function() {
|
||
|
|
var tileset = new Cesium3DTileset({
|
||
|
|
url : tilesetUrl
|
||
|
|
});
|
||
|
|
expect(function() {
|
||
|
|
tileset.maximumMemoryUsage = -1;
|
||
|
|
}).toThrowDeveloperError();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('maximumScreenSpaceError throws when negative', function() {
|
||
|
|
var tileset = new Cesium3DTileset({
|
||
|
|
url : tilesetUrl
|
||
|
|
});
|
||
|
|
expect(function() {
|
||
|
|
tileset.maximumScreenSpaceError = -1;
|
||
|
|
}).toThrowDeveloperError();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('propagates tile transform down the tree', function() {
|
||
|
|
var b3dmCommands = 1;
|
||
|
|
var i3dmCommands = scene.context.instancedArrays ? 1 : 25; // When instancing is not supported there is one command per instance
|
||
|
|
var totalCommands = b3dmCommands + i3dmCommands;
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetWithTransformsUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
var root = tileset.root;
|
||
|
|
var rootTransform = Matrix4.unpack(root._header.transform);
|
||
|
|
|
||
|
|
var child = root.children[0];
|
||
|
|
var childTransform = Matrix4.unpack(child._header.transform);
|
||
|
|
var computedTransform = Matrix4.multiply(rootTransform, childTransform, new Matrix4());
|
||
|
|
|
||
|
|
expect(statistics.numberOfCommands).toBe(totalCommands);
|
||
|
|
expect(root.computedTransform).toEqual(rootTransform);
|
||
|
|
expect(child.computedTransform).toEqual(computedTransform);
|
||
|
|
|
||
|
|
// Set the tileset's modelMatrix
|
||
|
|
var tilesetTransform = Matrix4.fromTranslation(new Cartesian3(0.0, 1.0, 0.0));
|
||
|
|
tileset.modelMatrix = tilesetTransform;
|
||
|
|
computedTransform = Matrix4.multiply(tilesetTransform, computedTransform, computedTransform);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(child.computedTransform).toEqual(computedTransform);
|
||
|
|
|
||
|
|
// Set the modelMatrix somewhere off screen
|
||
|
|
tileset.modelMatrix = Matrix4.fromTranslation(new Cartesian3(0.0, 100000.0, 0.0));
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toBe(0);
|
||
|
|
|
||
|
|
// Now bring it back
|
||
|
|
tileset.modelMatrix = Matrix4.IDENTITY;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toBe(totalCommands);
|
||
|
|
|
||
|
|
// Do the same steps for a tile transform
|
||
|
|
child.transform = Matrix4.fromTranslation(new Cartesian3(0.0, 100000.0, 0.0));
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toBe(1);
|
||
|
|
child.transform = Matrix4.IDENTITY;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toBe(totalCommands);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not mark tileset as refining when tiles have selection depth 0', function() {
|
||
|
|
viewRootOnly();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
viewAllTiles();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(1);
|
||
|
|
expect(tileset._selectedTiles[0]._selectionDepth).toEqual(0);
|
||
|
|
expect(tileset._hasMixedContent).toBe(false);
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function(tileset) {
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(5);
|
||
|
|
expect(tileset._hasMixedContent).toBe(false);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('marks tileset as mixed when tiles have nonzero selection depth', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacement3Url).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
|
||
|
|
tileset.root.children[0].children[0].children[0].unloadContent();
|
||
|
|
tileset.root.children[0].children[0].children[1].unloadContent();
|
||
|
|
tileset.root.children[0].children[0].children[2].unloadContent();
|
||
|
|
statistics.numberOfTilesWithContentReady -= 3;
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(tileset._hasMixedContent).toBe(true);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(2);
|
||
|
|
expect(tileset.root.children[0].children[0].children[3]._selectionDepth).toEqual(1);
|
||
|
|
expect(tileset.root._selectionDepth).toEqual(0);
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function(tileset) {
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toEqual(5);
|
||
|
|
expect(tileset._hasMixedContent).toBe(false);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('adds stencil clear command first when unresolved', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacement3Url).then(function(tileset) {
|
||
|
|
tileset.root.children[0].children[0].children[0].unloadContent();
|
||
|
|
tileset.root.children[0].children[0].children[1].unloadContent();
|
||
|
|
tileset.root.children[0].children[0].children[2].unloadContent();
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
var commandList = scene.frameState.commandList;
|
||
|
|
expect(commandList[0] instanceof ClearCommand).toBe(true);
|
||
|
|
expect(commandList[0].stencil).toBe(0);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('creates duplicate backface commands', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacement3Url).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
var root = tileset.root;
|
||
|
|
|
||
|
|
tileset.root.children[0].children[0].children[0].unloadContent();
|
||
|
|
tileset.root.children[0].children[0].children[1].unloadContent();
|
||
|
|
tileset.root.children[0].children[0].children[2].unloadContent();
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
// 2 for root tile, 1 for child, 1 for stencil clear
|
||
|
|
// Tiles that are marked as finalResolution, including leaves, do not create back face commands
|
||
|
|
expect(statistics.numberOfCommands).toEqual(4);
|
||
|
|
expect(isSelected(tileset, root)).toBe(true);
|
||
|
|
expect(root._finalResolution).toBe(false);
|
||
|
|
expect(isSelected(tileset, root.children[0].children[0].children[3])).toBe(true);
|
||
|
|
expect(root.children[0].children[0].children[3]._finalResolution).toBe(true);
|
||
|
|
expect(tileset._hasMixedContent).toBe(true);
|
||
|
|
|
||
|
|
var commandList = scene.frameState.commandList;
|
||
|
|
var rs = commandList[1].renderState;
|
||
|
|
expect(rs.cull.enabled).toBe(true);
|
||
|
|
expect(rs.cull.face).toBe(CullFace.FRONT);
|
||
|
|
expect(rs.polygonOffset.enabled).toBe(true);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not create duplicate backface commands if no selected descendants', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacement3Url).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
var root = tileset.root;
|
||
|
|
|
||
|
|
tileset.root.children[0].children[0].children[0].unloadContent();
|
||
|
|
tileset.root.children[0].children[0].children[1].unloadContent();
|
||
|
|
tileset.root.children[0].children[0].children[2].unloadContent();
|
||
|
|
tileset.root.children[0].children[0].children[3].unloadContent();
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
// 2 for root tile, 1 for child, 1 for stencil clear
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
expect(isSelected(tileset, root)).toBe(true);
|
||
|
|
expect(root._finalResolution).toBe(true);
|
||
|
|
expect(isSelected(tileset, root.children[0].children[0].children[0])).toBe(false);
|
||
|
|
expect(isSelected(tileset, root.children[0].children[0].children[1])).toBe(false);
|
||
|
|
expect(isSelected(tileset, root.children[0].children[0].children[2])).toBe(false);
|
||
|
|
expect(isSelected(tileset, root.children[0].children[0].children[3])).toBe(false);
|
||
|
|
expect(tileset._hasMixedContent).toBe(false);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not add commands or stencil clear command with no selected tiles', function() {
|
||
|
|
var tileset = scene.primitives.add(new Cesium3DTileset({
|
||
|
|
url : tilesetUrl
|
||
|
|
}));
|
||
|
|
scene.renderForSpecs();
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(tileset._selectedTiles.length).toEqual(0);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(0);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not add stencil clear command or backface commands when fully resolved', function() {
|
||
|
|
viewAllTiles();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacement3Url).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.numberOfCommands).toEqual(tileset._selectedTiles.length);
|
||
|
|
|
||
|
|
var commandList = scene.frameState.commandList;
|
||
|
|
var length = commandList.length;
|
||
|
|
for (var i = 0; i < length; ++i) {
|
||
|
|
var command = commandList[i];
|
||
|
|
expect(command instanceof ClearCommand).toBe(false);
|
||
|
|
expect(command.renderState.cull.face).not.toBe(CullFace.FRONT);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('loadSiblings', function() {
|
||
|
|
viewBottomLeft();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetReplacement3Url, {
|
||
|
|
loadSiblings : false
|
||
|
|
}).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toBe(2);
|
||
|
|
tileset.loadSiblings = true;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function(tileset) {
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toBe(5);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('immediatelyLoadDesiredLevelOfDetail', function() {
|
||
|
|
viewNothing();
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl, {
|
||
|
|
immediatelyLoadDesiredLevelOfDetail : true
|
||
|
|
}).then(function(tileset) {
|
||
|
|
var root = tileset.root;
|
||
|
|
var child = findTileByUri(root.children, 'll.b3dm');
|
||
|
|
tileset.root.refine = Cesium3DTileRefine.REPLACE;
|
||
|
|
tileset._allTilesAdditive = false;
|
||
|
|
viewBottomLeft();
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function(tileset) {
|
||
|
|
expect(isSelected(tileset, child));
|
||
|
|
expect(!isSelected(tileset, root));
|
||
|
|
expect(root.contentUnloaded).toBe(true);
|
||
|
|
// Renders child while parent loads
|
||
|
|
viewRootOnly();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(isSelected(tileset, child));
|
||
|
|
expect(!isSelected(tileset, root));
|
||
|
|
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset).then(function(tileset) {
|
||
|
|
expect(!isSelected(tileset, child));
|
||
|
|
expect(isSelected(tileset, root));
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('selects children if no ancestors available', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetOfTilesetsUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
var parent = tileset.root.children[0];
|
||
|
|
var child = parent.children[3].children[0];
|
||
|
|
parent.refine = Cesium3DTileRefine.REPLACE;
|
||
|
|
parent.unloadContent();
|
||
|
|
|
||
|
|
viewBottomLeft();
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(child.contentReady).toBe(true);
|
||
|
|
expect(parent.contentReady).toBe(false);
|
||
|
|
expect(isSelected(tileset, child)).toBe(true);
|
||
|
|
expect(isSelected(tileset, parent)).toBe(false);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('tile expires', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, batchedExpirationUrl).then(function(tileset) {
|
||
|
|
// Intercept the request and load content that produces more draw commands, to simulate fetching new content after the original expires
|
||
|
|
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
|
||
|
|
Resource._DefaultImplementations.loadWithXhr(batchedColorsB3dmUrl, responseType, method, data, headers, deferred, overrideMimeType);
|
||
|
|
});
|
||
|
|
var tile = tileset.root;
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
var expiredContent;
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'color("red")'
|
||
|
|
});
|
||
|
|
|
||
|
|
// Check that expireDuration and expireDate are correctly set
|
||
|
|
var expireDate = JulianDate.addSeconds(JulianDate.now(), 5.0, new JulianDate());
|
||
|
|
expect(JulianDate.secondsDifference(tile.expireDate, expireDate)).toEqualEpsilon(0.0, CesiumMath.EPSILON1);
|
||
|
|
expect(tile.expireDuration).toBe(5.0);
|
||
|
|
expect(tile.contentExpired).toBe(false);
|
||
|
|
expect(tile.contentReady).toBe(true);
|
||
|
|
expect(tile.contentAvailable).toBe(true);
|
||
|
|
expect(tile._expiredContent).toBeUndefined();
|
||
|
|
|
||
|
|
// Check statistics
|
||
|
|
expect(statistics.numberOfCommands).toBe(1);
|
||
|
|
expect(statistics.numberOfTilesTotal).toBe(1);
|
||
|
|
|
||
|
|
// Trigger expiration to happen next frame
|
||
|
|
tile.expireDate = JulianDate.addSeconds(JulianDate.now(), -1.0, new JulianDate());
|
||
|
|
|
||
|
|
// Stays in the expired state until the request goes through
|
||
|
|
var originalMaxmimumRequests = RequestScheduler.maximumRequests;
|
||
|
|
RequestScheduler.maximumRequests = 0; // Artificially limit Request Scheduler so the request won't go through
|
||
|
|
scene.renderForSpecs();
|
||
|
|
RequestScheduler.maximumRequests = originalMaxmimumRequests;
|
||
|
|
expiredContent = tile._expiredContent;
|
||
|
|
expect(tile.contentExpired).toBe(true);
|
||
|
|
expect(tile.contentAvailable).toBe(true); // Expired content now exists
|
||
|
|
expect(expiredContent).toBeDefined();
|
||
|
|
|
||
|
|
// Expired content renders while new content loads in
|
||
|
|
expect(statistics.numberOfCommands).toBe(1);
|
||
|
|
expect(statistics.numberOfTilesTotal).toBe(1);
|
||
|
|
|
||
|
|
// Request goes through, now in the LOADING state
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tile.contentExpired).toBe(false);
|
||
|
|
expect(tile.contentReady).toBe(false);
|
||
|
|
expect(tile.contentAvailable).toBe(true);
|
||
|
|
expect(tile._contentState).toBe(Cesium3DTileContentState.LOADING);
|
||
|
|
expect(tile._expiredContent).toBeDefined(); // Still holds onto expired content until the content state is READY
|
||
|
|
|
||
|
|
// Check that url contains a query param with the timestamp
|
||
|
|
var url = Resource._Implementations.loadWithXhr.calls.first().args[0];
|
||
|
|
expect(url.indexOf('expired=') >= 0).toBe(true);
|
||
|
|
|
||
|
|
// statistics are still the same
|
||
|
|
expect(statistics.numberOfCommands).toBe(1);
|
||
|
|
expect(statistics.numberOfTilesTotal).toBe(1);
|
||
|
|
|
||
|
|
return pollToPromise(function() {
|
||
|
|
expect(statistics.numberOfCommands).toBe(1); // Still renders expired content
|
||
|
|
scene.renderForSpecs();
|
||
|
|
return tile.contentReady;
|
||
|
|
}).then(function() {
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
// Expired content is destroyed
|
||
|
|
expect(tile._expiredContent).toBeUndefined();
|
||
|
|
expect(expiredContent.isDestroyed()).toBe(true);
|
||
|
|
|
||
|
|
// Expect the style to be reapplied
|
||
|
|
expect(tile.content.getFeature(0).color).toEqual(Color.RED);
|
||
|
|
|
||
|
|
// statistics for new content
|
||
|
|
expect(statistics.numberOfCommands).toBe(10);
|
||
|
|
expect(statistics.numberOfTilesTotal).toBe(1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
function modifySubtreeBuffer(arrayBuffer) {
|
||
|
|
var uint8Array = new Uint8Array(arrayBuffer);
|
||
|
|
var jsonString = getStringFromTypedArray(uint8Array);
|
||
|
|
var json = JSON.parse(jsonString);
|
||
|
|
json.root.children.splice(0, 1);
|
||
|
|
|
||
|
|
jsonString = JSON.stringify(json);
|
||
|
|
var length = jsonString.length;
|
||
|
|
uint8Array = new Uint8Array(length);
|
||
|
|
for (var i = 0; i < length; i++) {
|
||
|
|
uint8Array[i] = jsonString.charCodeAt(i);
|
||
|
|
}
|
||
|
|
return uint8Array.buffer;
|
||
|
|
}
|
||
|
|
|
||
|
|
it('tile with tileset content expires', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetSubtreeExpirationUrl).then(function(tileset) {
|
||
|
|
// Intercept the request and load a subtree with one less child. Still want to make an actual request to simulate
|
||
|
|
// real use cases instead of immediately returning a pre-created array buffer.
|
||
|
|
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
|
||
|
|
var newDeferred = when.defer();
|
||
|
|
Resource._DefaultImplementations.loadWithXhr(tilesetSubtreeUrl, responseType, method, data, headers, newDeferred, overrideMimeType);
|
||
|
|
newDeferred.promise.then(function(arrayBuffer) {
|
||
|
|
deferred.resolve(modifySubtreeBuffer(arrayBuffer));
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
var subtreeRoot = tileset.root.children[0];
|
||
|
|
var subtreeChildren = subtreeRoot.children[0].children;
|
||
|
|
var childrenLength = subtreeChildren.length;
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
|
||
|
|
// Check statistics
|
||
|
|
expect(statistics.numberOfCommands).toBe(5);
|
||
|
|
expect(statistics.numberOfTilesTotal).toBe(7);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toBe(5);
|
||
|
|
|
||
|
|
// Trigger expiration to happen next frame
|
||
|
|
subtreeRoot.expireDate = JulianDate.addSeconds(JulianDate.now(), -1.0, new JulianDate());
|
||
|
|
|
||
|
|
// Listen to tile unload events
|
||
|
|
var spyUpdate = jasmine.createSpy('listener');
|
||
|
|
tileset.tileUnload.addEventListener(spyUpdate);
|
||
|
|
|
||
|
|
// Tiles in the subtree are removed from the cache and destroyed.
|
||
|
|
scene.renderForSpecs(); // Becomes expired
|
||
|
|
scene.renderForSpecs(); // Makes request
|
||
|
|
expect(subtreeRoot.children).toEqual([]);
|
||
|
|
for (var i = 0; i < childrenLength; ++i) {
|
||
|
|
expect(subtreeChildren[0].isDestroyed()).toBe(true);
|
||
|
|
}
|
||
|
|
expect(spyUpdate.calls.count()).toEqual(4);
|
||
|
|
|
||
|
|
// Remove the spy so new tiles load in normally
|
||
|
|
Resource._Implementations.loadWithXhr = Resource._DefaultImplementations.loadWithXhr;
|
||
|
|
|
||
|
|
// Wait for the new tileset content to come in with one less leaf
|
||
|
|
return pollToPromise(function() {
|
||
|
|
scene.renderForSpecs();
|
||
|
|
return subtreeRoot.contentReady && tileset.tilesLoaded;
|
||
|
|
}).then(function() {
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(statistics.numberOfCommands).toBe(4);
|
||
|
|
expect(statistics.numberOfTilesTotal).toBe(6);
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toBe(4);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('tile expires and request fails', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, batchedExpirationUrl).then(function(tileset) {
|
||
|
|
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
|
||
|
|
deferred.reject();
|
||
|
|
});
|
||
|
|
var tile = tileset.root;
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
|
||
|
|
// Trigger expiration to happen next frame
|
||
|
|
tile.expireDate = JulianDate.addSeconds(JulianDate.now(), -1.0, new JulianDate());
|
||
|
|
|
||
|
|
// After update the tile is expired
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
// Make request (it will fail)
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
// Render scene
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tile._contentState).toBe(Cesium3DTileContentState.FAILED);
|
||
|
|
expect(statistics.numberOfCommands).toBe(0);
|
||
|
|
expect(statistics.numberOfTilesTotal).toBe(1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('tile expiration date', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var tile = tileset.root;
|
||
|
|
|
||
|
|
// Trigger expiration to happen next frame
|
||
|
|
tile.expireDate = JulianDate.addSeconds(JulianDate.now(), -1.0, new JulianDate());
|
||
|
|
|
||
|
|
// Stays in the expired state until the request goes through
|
||
|
|
var originalMaxmimumRequests = RequestScheduler.maximumRequests;
|
||
|
|
RequestScheduler.maximumRequests = 0; // Artificially limit Request Scheduler so the request won't go through
|
||
|
|
scene.renderForSpecs();
|
||
|
|
RequestScheduler.maximumRequests = originalMaxmimumRequests;
|
||
|
|
|
||
|
|
expect(tile.contentExpired).toBe(true);
|
||
|
|
|
||
|
|
return pollToPromise(function() {
|
||
|
|
scene.renderForSpecs();
|
||
|
|
return tile.contentReady;
|
||
|
|
}).then(function() {
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(tile._expiredContent).toBeUndefined();
|
||
|
|
expect(tile.expireDate).toBeUndefined();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('supports content data URIs', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrlWithContentUri).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
expect(statistics.visited).toEqual(1);
|
||
|
|
expect(statistics.numberOfCommands).toEqual(1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('destroys attached ClippingPlaneCollections and ClippingPlaneCollections that have been detached', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var clippingPlaneCollection1 = new ClippingPlaneCollection({
|
||
|
|
planes : [
|
||
|
|
new ClippingPlane(Cartesian3.UNIT_Z, -100000000.0)
|
||
|
|
]
|
||
|
|
});
|
||
|
|
expect(clippingPlaneCollection1.owner).not.toBeDefined();
|
||
|
|
|
||
|
|
tileset.clippingPlanes = clippingPlaneCollection1;
|
||
|
|
var clippingPlaneCollection2 = new ClippingPlaneCollection({
|
||
|
|
planes : [
|
||
|
|
new ClippingPlane(Cartesian3.UNIT_Z, -100000000.0)
|
||
|
|
]
|
||
|
|
});
|
||
|
|
|
||
|
|
tileset.clippingPlanes = clippingPlaneCollection2;
|
||
|
|
expect(clippingPlaneCollection1.isDestroyed()).toBe(true);
|
||
|
|
|
||
|
|
scene.primitives.remove(tileset);
|
||
|
|
expect(clippingPlaneCollection2.isDestroyed()).toBe(true);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws a DeveloperError when given a ClippingPlaneCollection attached to another Tileset', function() {
|
||
|
|
var clippingPlanes;
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset1) {
|
||
|
|
clippingPlanes = new ClippingPlaneCollection({
|
||
|
|
planes : [
|
||
|
|
new ClippingPlane(Cartesian3.UNIT_X, 0.0)
|
||
|
|
]
|
||
|
|
});
|
||
|
|
tileset1.clippingPlanes = clippingPlanes;
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl);
|
||
|
|
})
|
||
|
|
.then(function(tileset2) {
|
||
|
|
expect(function() {
|
||
|
|
tileset2.clippingPlanes = clippingPlanes;
|
||
|
|
}).toThrowDeveloperError();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('clipping planes cull hidden tiles', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var visibility = tileset.root.visibility(scene.frameState, CullingVolume.MASK_INSIDE);
|
||
|
|
|
||
|
|
expect(visibility).not.toBe(CullingVolume.MASK_OUTSIDE);
|
||
|
|
|
||
|
|
var plane = new ClippingPlane(Cartesian3.UNIT_Z, -100000000.0);
|
||
|
|
tileset.clippingPlanes = new ClippingPlaneCollection({
|
||
|
|
planes : [
|
||
|
|
plane
|
||
|
|
]
|
||
|
|
});
|
||
|
|
|
||
|
|
visibility = tileset.root.visibility(scene.frameState, CullingVolume.MASK_INSIDE);
|
||
|
|
|
||
|
|
expect(visibility).toBe(CullingVolume.MASK_OUTSIDE);
|
||
|
|
|
||
|
|
plane.distance = 0.0;
|
||
|
|
visibility = tileset.root.visibility(scene.frameState, CullingVolume.MASK_INSIDE);
|
||
|
|
|
||
|
|
expect(visibility).not.toBe(CullingVolume.MASK_OUTSIDE);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('clipping planes cull hidden content', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var visibility = tileset.root.contentVisibility(scene.frameState);
|
||
|
|
|
||
|
|
expect(visibility).not.toBe(Intersect.OUTSIDE);
|
||
|
|
|
||
|
|
var plane = new ClippingPlane(Cartesian3.UNIT_Z, -100000000.0);
|
||
|
|
tileset.clippingPlanes = new ClippingPlaneCollection({
|
||
|
|
planes : [
|
||
|
|
plane
|
||
|
|
]
|
||
|
|
});
|
||
|
|
|
||
|
|
visibility = tileset.root.contentVisibility(scene.frameState);
|
||
|
|
|
||
|
|
expect(visibility).toBe(Intersect.OUTSIDE);
|
||
|
|
|
||
|
|
plane.distance = 0.0;
|
||
|
|
visibility = tileset.root.contentVisibility(scene.frameState);
|
||
|
|
|
||
|
|
expect(visibility).not.toBe(Intersect.OUTSIDE);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('clipping planes cull tiles completely inside clipping region', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
var root = tileset.root;
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
|
||
|
|
tileset.update(scene.frameState);
|
||
|
|
|
||
|
|
var radius = 287.0736139905632;
|
||
|
|
|
||
|
|
var plane = new ClippingPlane(Cartesian3.UNIT_X, radius);
|
||
|
|
tileset.clippingPlanes = new ClippingPlaneCollection({
|
||
|
|
planes : [
|
||
|
|
plane
|
||
|
|
]
|
||
|
|
});
|
||
|
|
|
||
|
|
tileset.update(scene.frameState);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfCommands).toEqual(5);
|
||
|
|
expect(root._isClipped).toBe(false);
|
||
|
|
|
||
|
|
plane.distance = -1;
|
||
|
|
|
||
|
|
tileset.update(scene.frameState);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfCommands).toEqual(3);
|
||
|
|
expect(root._isClipped).toBe(true);
|
||
|
|
|
||
|
|
plane.distance = -radius;
|
||
|
|
|
||
|
|
tileset.update(scene.frameState);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfCommands).toEqual(0);
|
||
|
|
expect(root._isClipped).toBe(true);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('clipping planes cull tiles completely inside clipping region for i3dm', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetWithExternalResourcesUrl).then(function(tileset) {
|
||
|
|
var statistics = tileset._statistics;
|
||
|
|
var root = tileset.root;
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfCommands).toEqual(6);
|
||
|
|
|
||
|
|
tileset.update(scene.frameState);
|
||
|
|
|
||
|
|
var radius = 142.19001637409772;
|
||
|
|
|
||
|
|
var plane = new ClippingPlane(Cartesian3.UNIT_Z, radius);
|
||
|
|
tileset.clippingPlanes = new ClippingPlaneCollection({
|
||
|
|
planes : [
|
||
|
|
plane
|
||
|
|
]
|
||
|
|
});
|
||
|
|
|
||
|
|
tileset.update(scene.frameState);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfCommands).toEqual(6);
|
||
|
|
expect(root._isClipped).toBe(false);
|
||
|
|
|
||
|
|
plane.distance = 0;
|
||
|
|
|
||
|
|
tileset.update(scene.frameState);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfCommands).toEqual(6);
|
||
|
|
expect(root._isClipped).toBe(true);
|
||
|
|
|
||
|
|
plane.distance = -radius;
|
||
|
|
|
||
|
|
tileset.update(scene.frameState);
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
expect(statistics.numberOfCommands).toEqual(0);
|
||
|
|
expect(root._isClipped).toBe(true);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('clippingPlanesOriginMatrix has correct orientation', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, withTransformBoxUrl).then(function(tileset) {
|
||
|
|
// The bounding volume of this tileset puts it under the surface, so no
|
||
|
|
// east-north-up should be applied. Check that it matches the orientation
|
||
|
|
// of the original transform.
|
||
|
|
var offsetMatrix = tileset.clippingPlanesOriginMatrix;
|
||
|
|
|
||
|
|
expect(Matrix4.equals(offsetMatrix, tileset.root.computedTransform)).toBe(true);
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUrl).then(function(tileset) {
|
||
|
|
// The bounding volume of this tileset puts it on the surface,
|
||
|
|
// so we want to apply east-north-up as our best guess.
|
||
|
|
offsetMatrix = tileset.clippingPlanesOriginMatrix;
|
||
|
|
// The clipping plane matrix is not the same as the original because we applied east-north-up.
|
||
|
|
expect(Matrix4.equals(offsetMatrix, tileset.root.computedTransform)).toBe(false);
|
||
|
|
|
||
|
|
// But they have the same translation.
|
||
|
|
var clippingPlanesOrigin = Matrix4.getTranslation(offsetMatrix, new Cartesian3());
|
||
|
|
expect(Cartesian3.equals(tileset.root.boundingSphere.center, clippingPlanesOrigin)).toBe(true);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('clippingPlanesOriginMatrix matches root tile bounding sphere', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetOfTilesetsUrl).then(function(tileset) {
|
||
|
|
var offsetMatrix = Matrix4.clone(tileset.clippingPlanesOriginMatrix, new Matrix4());
|
||
|
|
var boundingSphereEastNorthUp = Transforms.eastNorthUpToFixedFrame(tileset.root.boundingSphere.center);
|
||
|
|
expect(Matrix4.equals(offsetMatrix, boundingSphereEastNorthUp)).toBe(true);
|
||
|
|
|
||
|
|
// Changing the model matrix should change the clipping planes matrix
|
||
|
|
tileset.modelMatrix = Matrix4.fromTranslation(new Cartesian3(100, 0, 0));
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(Matrix4.equals(offsetMatrix, tileset.clippingPlanesOriginMatrix)).toBe(false);
|
||
|
|
|
||
|
|
boundingSphereEastNorthUp = Transforms.eastNorthUpToFixedFrame(tileset.root.boundingSphere.center);
|
||
|
|
offsetMatrix = tileset.clippingPlanesOriginMatrix;
|
||
|
|
expect(offsetMatrix).toEqualEpsilon(boundingSphereEastNorthUp, CesiumMath.EPSILON3);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
function sampleHeightMostDetailed(cartographics, objectsToExclude) {
|
||
|
|
var result;
|
||
|
|
var completed = false;
|
||
|
|
scene.sampleHeightMostDetailed(cartographics, objectsToExclude).then(function(pickResult) {
|
||
|
|
result = pickResult;
|
||
|
|
completed = true;
|
||
|
|
});
|
||
|
|
return pollToPromise(function() {
|
||
|
|
// Scene requires manual updates in the tests to move along the promise
|
||
|
|
scene.render();
|
||
|
|
return completed;
|
||
|
|
}).then(function() {
|
||
|
|
return result;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function drillPickFromRayMostDetailed(ray, limit, objectsToExclude) {
|
||
|
|
var result;
|
||
|
|
var completed = false;
|
||
|
|
scene.drillPickFromRayMostDetailed(ray, limit, objectsToExclude).then(function(pickResult) {
|
||
|
|
result = pickResult;
|
||
|
|
completed = true;
|
||
|
|
});
|
||
|
|
return pollToPromise(function() {
|
||
|
|
// Scene requires manual updates in the tests to move along the promise
|
||
|
|
scene.render();
|
||
|
|
return completed;
|
||
|
|
}).then(function() {
|
||
|
|
return result;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
describe('most detailed height queries', function() {
|
||
|
|
it('tileset is offscreen', function() {
|
||
|
|
if (webglStub) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
viewNothing();
|
||
|
|
|
||
|
|
// Tileset uses replacement refinement so only one tile should be loaded and selected during most detailed picking
|
||
|
|
var centerCartographic = new Cartographic(-1.3196799798348215, 0.6988740001506679, 2.4683731133709323);
|
||
|
|
var cartographics = [centerCartographic];
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUniform).then(function(tileset) {
|
||
|
|
return sampleHeightMostDetailed(cartographics).then(function() {
|
||
|
|
expect(centerCartographic.height).toEqualEpsilon(2.47, CesiumMath.EPSILON1);
|
||
|
|
var statisticsAsync = tileset._statisticsLastAsync;
|
||
|
|
var statisticsRender = tileset._statisticsLastRender;
|
||
|
|
expect(statisticsAsync.numberOfCommands).toBe(1);
|
||
|
|
expect(statisticsAsync.numberOfTilesWithContentReady).toBe(1);
|
||
|
|
expect(statisticsAsync.selected).toBe(1);
|
||
|
|
expect(statisticsAsync.visited).toBeGreaterThan(1);
|
||
|
|
expect(statisticsAsync.numberOfTilesTotal).toBe(21);
|
||
|
|
expect(statisticsRender.selected).toBe(0);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('tileset is onscreen', function() {
|
||
|
|
if (webglStub) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
viewAllTiles();
|
||
|
|
|
||
|
|
// Tileset uses replacement refinement so only one tile should be loaded and selected during most detailed picking
|
||
|
|
var centerCartographic = new Cartographic(-1.3196799798348215, 0.6988740001506679, 2.4683731133709323);
|
||
|
|
var cartographics = [centerCartographic];
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUniform).then(function(tileset) {
|
||
|
|
return sampleHeightMostDetailed(cartographics).then(function() {
|
||
|
|
expect(centerCartographic.height).toEqualEpsilon(2.47, CesiumMath.EPSILON1);
|
||
|
|
var statisticsAsync = tileset._statisticsLastAsync;
|
||
|
|
var statisticsRender = tileset._statisticsLastRender;
|
||
|
|
expect(statisticsAsync.numberOfCommands).toBe(1);
|
||
|
|
expect(statisticsAsync.numberOfTilesWithContentReady).toBeGreaterThan(1);
|
||
|
|
expect(statisticsAsync.selected).toBe(1);
|
||
|
|
expect(statisticsAsync.visited).toBeGreaterThan(1);
|
||
|
|
expect(statisticsAsync.numberOfTilesTotal).toBe(21);
|
||
|
|
expect(statisticsRender.selected).toBeGreaterThan(0);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('tileset uses additive refinement', function() {
|
||
|
|
if (webglStub) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
viewNothing();
|
||
|
|
|
||
|
|
var originalLoadJson = Cesium3DTileset.loadJson;
|
||
|
|
spyOn(Cesium3DTileset, 'loadJson').and.callFake(function(tilesetUrl) {
|
||
|
|
return originalLoadJson(tilesetUrl).then(function(tilesetJson) {
|
||
|
|
tilesetJson.root.refine = 'ADD';
|
||
|
|
return tilesetJson;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
var offcenterCartographic = new Cartographic(-1.3196754112739246, 0.6988705057695633, 2.467395745774971);
|
||
|
|
var cartographics = [offcenterCartographic];
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUniform).then(function(tileset) {
|
||
|
|
return sampleHeightMostDetailed(cartographics).then(function() {
|
||
|
|
var statistics = tileset._statisticsLastAsync;
|
||
|
|
expect(offcenterCartographic.height).toEqualEpsilon(7.407, CesiumMath.EPSILON1);
|
||
|
|
expect(statistics.numberOfCommands).toBe(3); // One for each level of the tree
|
||
|
|
expect(statistics.numberOfTilesWithContentReady).toBeGreaterThanOrEqualTo(3);
|
||
|
|
expect(statistics.selected).toBe(3);
|
||
|
|
expect(statistics.visited).toBeGreaterThan(3);
|
||
|
|
expect(statistics.numberOfTilesTotal).toBe(21);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('drill picks multiple features when tileset uses additive refinement', function() {
|
||
|
|
if (webglStub) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
viewNothing();
|
||
|
|
var ray = new Ray(scene.camera.positionWC, scene.camera.directionWC);
|
||
|
|
|
||
|
|
var originalLoadJson = Cesium3DTileset.loadJson;
|
||
|
|
spyOn(Cesium3DTileset, 'loadJson').and.callFake(function(tilesetUrl) {
|
||
|
|
return originalLoadJson(tilesetUrl).then(function(tilesetJson) {
|
||
|
|
tilesetJson.root.refine = 'ADD';
|
||
|
|
return tilesetJson;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUniform).then(function(tileset) {
|
||
|
|
return drillPickFromRayMostDetailed(ray).then(function(results) {
|
||
|
|
expect(results.length).toBe(3);
|
||
|
|
expect(results[0].object.content.url.indexOf('0_0_0.b3dm') > -1).toBe(true);
|
||
|
|
expect(results[1].object.content.url.indexOf('1_1_1.b3dm') > -1).toBe(true);
|
||
|
|
expect(results[2].object.content.url.indexOf('2_4_4.b3dm') > -1).toBe(true);
|
||
|
|
console.log(results);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('works when tileset cache is disabled', function() {
|
||
|
|
if (webglStub) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
viewNothing();
|
||
|
|
var centerCartographic = new Cartographic(-1.3196799798348215, 0.6988740001506679, 2.4683731133709323);
|
||
|
|
var cartographics = [centerCartographic];
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUniform).then(function(tileset) {
|
||
|
|
tileset.maximumMemoryUsage = 0;
|
||
|
|
return sampleHeightMostDetailed(cartographics).then(function() {
|
||
|
|
expect(centerCartographic.height).toEqualEpsilon(2.47, CesiumMath.EPSILON1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('multiple samples', function() {
|
||
|
|
if (webglStub) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
viewNothing();
|
||
|
|
|
||
|
|
var centerCartographic = new Cartographic(-1.3196799798348215, 0.6988740001506679);
|
||
|
|
var offcenterCartographic = new Cartographic(-1.3196754112739246, 0.6988705057695633);
|
||
|
|
var missCartographic = new Cartographic(-1.3196096042084076, 0.6988703290845706);
|
||
|
|
var cartographics = [centerCartographic, offcenterCartographic, missCartographic];
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, tilesetUniform).then(function(tileset) {
|
||
|
|
return sampleHeightMostDetailed(cartographics).then(function() {
|
||
|
|
expect(centerCartographic.height).toEqualEpsilon(2.47, CesiumMath.EPSILON1);
|
||
|
|
expect(offcenterCartographic.height).toEqualEpsilon(2.47, CesiumMath.EPSILON1);
|
||
|
|
expect(missCartographic.height).toBeUndefined();
|
||
|
|
expect(tileset._statisticsLastAsync.numberOfTilesWithContentReady).toBe(2);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}, 'WebGL');
|