DSDSServer2024/build/build.20240805/static/js/Cesium-1.53/Specs/Scene/GlobeSurfaceTileSpec.js

567 lines
27 KiB
JavaScript

defineSuite([
'Scene/GlobeSurfaceTile',
'Core/Cartesian3',
'Core/Cartesian4',
'Core/CesiumTerrainProvider',
'Core/createWorldTerrain',
'Core/defined',
'Core/Ellipsoid',
'Core/GeographicTilingScheme',
'Core/Ray',
'Core/Rectangle',
'Core/RequestScheduler',
'Scene/Imagery',
'Scene/ImageryLayer',
'Scene/ImageryLayerCollection',
'Scene/ImageryState',
'Scene/QuadtreeTile',
'Scene/QuadtreeTileLoadState',
'Scene/TerrainState',
'Scene/TileImagery',
'Specs/createScene',
'Specs/pollToPromise',
'ThirdParty/when'
], function(
GlobeSurfaceTile,
Cartesian3,
Cartesian4,
CesiumTerrainProvider,
createWorldTerrain,
defined,
Ellipsoid,
GeographicTilingScheme,
Ray,
Rectangle,
RequestScheduler,
Imagery,
ImageryLayer,
ImageryLayerCollection,
ImageryState,
QuadtreeTile,
QuadtreeTileLoadState,
TerrainState,
TileImagery,
createScene,
pollToPromise,
when) {
'use strict';
describe('processStateMachine', function() {
var scene;
var alwaysDeferTerrainProvider;
var alwaysFailTerrainProvider;
var realTerrainProvider;
var tilingScheme;
var rootTiles;
var rootTile;
var imageryLayerCollection;
beforeAll(function() {
scene = createScene();
alwaysDeferTerrainProvider = {
requestTileGeometry : function(x, y, level) {
return undefined;
},
tilingScheme : tilingScheme,
hasWaterMask : function() {
return true;
},
getTileDataAvailable : function(x, y, level) {
return undefined;
}
};
alwaysFailTerrainProvider = {
requestTileGeometry : function(x, y, level) {
var deferred = when.defer();
deferred.reject();
return deferred.promise;
},
tilingScheme : tilingScheme,
hasWaterMask : function() {
return true;
},
getTileDataAvailable : function(x, y, level) {
return undefined;
}
};
realTerrainProvider = new CesiumTerrainProvider({
url : 'https://s3.amazonaws.com/cesiumjs/smallTerrain'
});
});
afterAll(function() {
scene.destroyForSpecs();
});
beforeEach(function() {
tilingScheme = new GeographicTilingScheme();
alwaysDeferTerrainProvider.tilingScheme = tilingScheme;
alwaysFailTerrainProvider.tilingScheme = tilingScheme;
rootTiles = QuadtreeTile.createLevelZeroTiles(tilingScheme);
rootTile = rootTiles[0];
imageryLayerCollection = new ImageryLayerCollection();
return pollToPromise(function() {
return realTerrainProvider.ready;
});
});
afterEach(function() {
for (var i = 0; i < rootTiles.length; ++i) {
rootTiles[i].freeResources();
}
});
it('starts in the START state', function() {
for (var i = 0; i < rootTiles.length; ++i) {
var tile = rootTiles[i];
expect(tile.state).toBe(QuadtreeTileLoadState.START);
}
});
it('transitions to the LOADING state immediately', function() {
GlobeSurfaceTile.processStateMachine(rootTile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
expect(rootTile.state).toBe(QuadtreeTileLoadState.LOADING);
});
it('creates loadedTerrain but not upsampledTerrain for root tiles', function() {
GlobeSurfaceTile.processStateMachine(rootTile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
expect(rootTile.data.loadedTerrain).toBeDefined();
expect(rootTile.data.upsampledTerrain).toBeUndefined();
});
it('non-root tiles get neither loadedTerrain nor upsampledTerrain when their parent is not loaded nor upsampled', function() {
var children = rootTile.children;
for (var i = 0; i < children.length; ++i) {
GlobeSurfaceTile.processStateMachine(children[i], scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
expect(children[i].data.loadedTerrain).toBeUndefined();
expect(children[i].data.upsampledTerrain).toBeUndefined();
}
});
it('once a root tile is loaded, its children get both loadedTerrain and upsampledTerrain', function() {
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(rootTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
RequestScheduler.update();
return rootTile.state === QuadtreeTileLoadState.DONE;
}).then(function() {
var children = rootTile.children;
for (var i = 0; i < children.length; ++i) {
GlobeSurfaceTile.processStateMachine(children[i], scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
expect(children[i].data.loadedTerrain).toBeDefined();
expect(children[i].data.upsampledTerrain).toBeDefined();
}
});
});
it('loaded terrainData is copied to the tile once it is available', function() {
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(rootTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
RequestScheduler.update();
return rootTile.data.loadedTerrain.state >= TerrainState.RECEIVED;
}).then(function() {
expect(rootTile.data.terrainData).toBeDefined();
});
});
xit('upsampled terrainData is copied to the tile once it is available', function() {
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(rootTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
return rootTile.data.loadedTerrain.state >= TerrainState.RECEIVED;
}).then(function() {
return pollToPromise(function() {
var childTile = rootTile.children[0];
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
return childTile.data.upsampledTerrain.state >= TerrainState.RECEIVED;
}).then(function() {
expect(rootTile.children[0].data.terrainData).toBeDefined();
});
});
});
xit('loaded terrain data replaces upsampled terrain data', function() {
var childTile = rootTile.children[0];
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(rootTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
return rootTile.data.loadedTerrain.state >= TerrainState.RECEIVED;
}).then(function() {
var upsampledTerrainData;
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
return childTile.data.upsampledTerrain.state >= TerrainState.RECEIVED;
}).then(function() {
upsampledTerrainData = childTile.data.terrainData;
expect(upsampledTerrainData).toBeDefined();
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
return childTile.data.loadedTerrain.state >= TerrainState.RECEIVED;
}).then(function() {
expect(childTile.data.terrainData).not.toBe(upsampledTerrainData);
});
});
});
});
xit('loaded terrain replacing upsampled terrain triggers re-upsampling and re-loading of children', function() {
var childTile = rootTile.children[0];
var grandchildTile = childTile.children[0];
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(rootTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
return rootTile.data.loadedTerrain.state >= TerrainState.RECEIVED;
}).then(function() {
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
return childTile.data.upsampledTerrain.state >= TerrainState.RECEIVED;
});
}).then(function() {
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(grandchildTile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
return grandchildTile.data.upsampledTerrain.state >= TerrainState.RECEIVED;
});
}).then(function() {
var grandchildUpsampledTerrain = grandchildTile.data.upsampledTerrain;
expect(grandchildTile.data.loadedTerrain).toBeUndefined();
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
return childTile.data.loadedTerrain.state >= TerrainState.RECEIVED;
}).then(function() {
expect(grandchildTile.data.upsampledTerrain).not.toBe(grandchildUpsampledTerrain);
expect(grandchildTile.data.loadedTerrain).toBeDefined();
});
});
});
xit('improved upsampled terrain triggers re-upsampling of children', function() {
var childTile = rootTile.children[0];
var grandchildTile = childTile.children[0];
var greatGrandchildTile = grandchildTile.children[0];
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(rootTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
return rootTile.data.loadedTerrain.state >= TerrainState.RECEIVED;
}).then(function() {
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
return childTile.data.upsampledTerrain.state >= TerrainState.RECEIVED;
});
}).then(function() {
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(grandchildTile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
return grandchildTile.data.upsampledTerrain.state >= TerrainState.RECEIVED;
});
}).then(function() {
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(greatGrandchildTile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
return greatGrandchildTile.data.upsampledTerrain.state >= TerrainState.RECEIVED;
});
}).then(function() {
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
return childTile.data.loadedTerrain.state >= TerrainState.RECEIVED;
});
}).then(function() {
var greatGrandchildUpsampledTerrain = grandchildTile.data.upsampledTerrain;
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(grandchildTile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
return grandchildTile.data.upsampledTerrain.state >= TerrainState.RECEIVED;
}).then(function() {
expect(greatGrandchildTile.data.upsampledTerrain).toBeDefined();
expect(greatGrandchildTile.data.upsampledTerrain).not.toBe(greatGrandchildUpsampledTerrain);
});
});
});
it('releases previous upsampled water mask when a real one is loaded', function() {
var childTile = rootTile.children[0];
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(rootTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
RequestScheduler.update();
return rootTile.renderable && childTile.renderable;
}).then(function() {
expect(childTile.data.waterMaskTexture).toBeDefined();
var childWaterMaskTexture = childTile.data.waterMaskTexture;
var referenceCount = childWaterMaskTexture.referenceCount;
var vertexArraysToDestroy = [];
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, realTerrainProvider, imageryLayerCollection, vertexArraysToDestroy);
RequestScheduler.update();
return childTile.state === QuadtreeTileLoadState.DONE;
}).then(function() {
expect(childTile.data.waterMaskTexture).toBeDefined();
expect(childTile.data.waterMaskTexture).not.toBe(childWaterMaskTexture);
expect(childWaterMaskTexture.referenceCount + 1).toBe(referenceCount);
expect(vertexArraysToDestroy.length).toEqual(1);
});
});
});
it('upsampled terrain is used when real terrain fails to load', function() {
var childTile = rootTile.children[0];
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(rootTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, alwaysFailTerrainProvider, imageryLayerCollection, []);
RequestScheduler.update();
return rootTile.renderable && childTile.renderable;
}).then(function() {
expect(childTile.data.loadedTerrain).toBeUndefined();
expect(childTile.upsampledFromParent).toBe(true);
});
});
it('child of loaded tile is not re-upsampled or re-loaded if it is already loaded', function() {
var childTile = rootTile.children[0];
var grandchildTile = childTile.children[0];
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(rootTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
RequestScheduler.update();
return defined(rootTile.data.terrainData) && defined(rootTile.data.terrainData._mesh) &&
defined(childTile.data.terrainData);
}).then(function() {
// Mark the grandchild as present even though the child is upsampled.
childTile.data.terrainData._childTileMask = 15;
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(grandchildTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
RequestScheduler.update();
return grandchildTile.state === QuadtreeTileLoadState.DONE;
}).then(function() {
expect(grandchildTile.data.loadedTerrain).toBeUndefined();
expect(grandchildTile.data.upsampledTerrain).toBeUndefined();
var vertexArraysToDestroy = [];
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, realTerrainProvider, imageryLayerCollection, vertexArraysToDestroy);
RequestScheduler.update();
return childTile.state === QuadtreeTileLoadState.DONE;
}).then(function() {
expect(grandchildTile.state).toBe(QuadtreeTileLoadState.DONE);
expect(grandchildTile.data.loadedTerrain).toBeUndefined();
expect(grandchildTile.data.upsampledTerrain).toBeUndefined();
expect(vertexArraysToDestroy.length).toEqual(1);
});
});
});
});
it('child of upsampled tile is not re-upsampled if it is already loaded', function() {
var childTile = rootTile.children[0];
var grandchildTile = childTile.children[0];
var greatGrandchildTile = grandchildTile.children[0];
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(rootTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
GlobeSurfaceTile.processStateMachine(grandchildTile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
RequestScheduler.update();
return defined(rootTile.data.terrainData) && defined(rootTile.data.terrainData._mesh) &&
defined(childTile.data.terrainData) && defined(childTile.data.terrainData._mesh) &&
defined(grandchildTile.data.terrainData);
}).then(function() {
// Mark the great-grandchild as present even though the grandchild is upsampled.
grandchildTile.data.terrainData._childTileMask = 15;
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(greatGrandchildTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
RequestScheduler.update();
return greatGrandchildTile.state === QuadtreeTileLoadState.DONE;
}).then(function() {
expect(greatGrandchildTile.data.loadedTerrain).toBeUndefined();
expect(greatGrandchildTile.data.upsampledTerrain).toBeUndefined();
var vertexArraysToBeDestroyed = [];
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, realTerrainProvider, imageryLayerCollection, vertexArraysToBeDestroyed);
GlobeSurfaceTile.processStateMachine(grandchildTile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, vertexArraysToBeDestroyed);
RequestScheduler.update();
return childTile.state === QuadtreeTileLoadState.DONE &&
!defined(grandchildTile.data.upsampledTerrain);
}).then(function() {
expect(greatGrandchildTile.state).toBe(QuadtreeTileLoadState.DONE);
expect(greatGrandchildTile.data.loadedTerrain).toBeUndefined();
expect(greatGrandchildTile.data.upsampledTerrain).toBeUndefined();
expect(vertexArraysToBeDestroyed.length).toEqual(2);
});
});
});
});
it('entirely upsampled tile is marked as such', function() {
var childTile = rootTile.children[0];
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(rootTile, scene.frameState, realTerrainProvider, imageryLayerCollection, []);
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, alwaysFailTerrainProvider, imageryLayerCollection, []);
RequestScheduler.update();
return rootTile.state >= QuadtreeTileLoadState.DONE &&
childTile.state >= QuadtreeTileLoadState.DONE;
}).then(function() {
expect(rootTile.state).toBe(QuadtreeTileLoadState.DONE);
expect(childTile.upsampledFromParent).toBe(true);
});
});
it('uses shared water mask texture for tiles that are entirely water', function() {
var allWaterTerrainProvider = {
requestTileGeometry : function(x, y, level) {
var real = realTerrainProvider.requestTileGeometry(x, y, level);
if (!defined(real)) {
return real;
}
return when(real, function(terrainData) {
terrainData._waterMask = new Uint8Array([255]);
return terrainData;
});
},
tilingScheme : realTerrainProvider.tilingScheme,
hasWaterMask : function() {
return realTerrainProvider.hasWaterMask();
},
getTileDataAvailable : function(x, y, level) {
return undefined;
}
};
var childTile = rootTile.children[0];
return pollToPromise(function() {
if (rootTile.state !== QuadtreeTileLoadState.DONE) {
GlobeSurfaceTile.processStateMachine(rootTile, scene.frameState, allWaterTerrainProvider, imageryLayerCollection, []);
return false;
}
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, allWaterTerrainProvider, imageryLayerCollection, []);
return childTile.state === QuadtreeTileLoadState.DONE;
}).then(function() {
expect(childTile.data.waterMaskTexture).toBeDefined();
expect(childTile.data.waterMaskTexture).toBe(rootTile.data.waterMaskTexture);
});
});
it('uses undefined water mask texture for tiles that are entirely land', function() {
var allLandTerrainProvider = {
requestTileGeometry : function(x, y, level) {
var real = realTerrainProvider.requestTileGeometry(x, y, level);
if (!defined(real)) {
return real;
}
return when(real, function(terrainData) {
terrainData._waterMask = new Uint8Array([0]);
return terrainData;
});
},
tilingScheme : realTerrainProvider.tilingScheme,
hasWaterMask : function() {
return realTerrainProvider.hasWaterMask();
},
getTileDataAvailable : function(x, y, level) {
return undefined;
}
};
var childTile = rootTile.children[0];
return pollToPromise(function() {
if (rootTile.state !== QuadtreeTileLoadState.DONE) {
GlobeSurfaceTile.processStateMachine(rootTile, scene.frameState, allLandTerrainProvider, imageryLayerCollection, []);
return false;
}
GlobeSurfaceTile.processStateMachine(childTile, scene.frameState, allLandTerrainProvider, imageryLayerCollection, []);
return childTile.state === QuadtreeTileLoadState.DONE;
}).then(function() {
expect(childTile.data.waterMaskTexture).toBeUndefined();
});
});
it('loads parent imagery tile even for root terrain tiles', function() {
var tile = new QuadtreeTile({
tilingScheme : new GeographicTilingScheme(),
level : 0,
x : 1,
y : 0
});
var imageryLayerCollection = new ImageryLayerCollection();
GlobeSurfaceTile.processStateMachine(tile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
var layer = new ImageryLayer({
requestImage : function() {
return when.reject();
}
});
var imagery = new Imagery(layer, 0, 0, 1, Rectangle.MAX_VALUE);
tile.data.imagery.push(new TileImagery(imagery, new Cartesian4()));
expect(imagery.parent.state).toBe(ImageryState.UNLOADED);
return pollToPromise(function() {
GlobeSurfaceTile.processStateMachine(tile, scene.frameState, alwaysDeferTerrainProvider, imageryLayerCollection, []);
return imagery.parent.state !== ImageryState.UNLOADED;
});
});
}, 'WebGL');
describe('pick', function() {
var scene;
beforeAll(function() {
scene = createScene();
});
afterAll(function() {
scene.destroyForSpecs();
});
it('gets correct results even when the mesh includes normals', function() {
var terrainProvider = createWorldTerrain({
requestVertexNormals: true,
requestWaterMask: false
});
var tile = new QuadtreeTile({
tilingScheme : new GeographicTilingScheme(),
level : 11,
x : 3788,
y : 1336
});
var imageryLayerCollection = new ImageryLayerCollection();
return pollToPromise(function() {
if (!terrainProvider.ready) {
return false;
}
GlobeSurfaceTile.processStateMachine(tile, scene.frameState, terrainProvider, imageryLayerCollection, []);
RequestScheduler.update();
return tile.state === QuadtreeTileLoadState.DONE;
}).then(function() {
var ray = new Ray(
new Cartesian3(-5052039.459789615, 2561172.040315167, -2936276.999965875),
new Cartesian3(0.5036332963145244, 0.6648033332898124, 0.5517155343926082));
var pickResult = tile.data.pick(ray, undefined, true);
var cartographic = Ellipsoid.WGS84.cartesianToCartographic(pickResult);
expect(cartographic.height).toBeGreaterThan(-500.0);
});
});
}, 'WebGL');
});