532 lines
20 KiB
JavaScript
532 lines
20 KiB
JavaScript
|
|
defineSuite([
|
||
|
|
'Scene/QuadtreePrimitive',
|
||
|
|
'Core/Cartesian3',
|
||
|
|
'Core/Cartographic',
|
||
|
|
'Core/defineProperties',
|
||
|
|
'Core/EventHelper',
|
||
|
|
'Core/GeographicTilingScheme',
|
||
|
|
'Core/Visibility',
|
||
|
|
'Scene/QuadtreeTileLoadState',
|
||
|
|
'Specs/createScene',
|
||
|
|
'Specs/pollToPromise'
|
||
|
|
], function(
|
||
|
|
QuadtreePrimitive,
|
||
|
|
Cartesian3,
|
||
|
|
Cartographic,
|
||
|
|
defineProperties,
|
||
|
|
EventHelper,
|
||
|
|
GeographicTilingScheme,
|
||
|
|
Visibility,
|
||
|
|
QuadtreeTileLoadState,
|
||
|
|
createScene,
|
||
|
|
pollToPromise) {
|
||
|
|
'use strict';
|
||
|
|
|
||
|
|
var scene;
|
||
|
|
|
||
|
|
beforeAll(function() {
|
||
|
|
scene = createScene();
|
||
|
|
scene.render();
|
||
|
|
});
|
||
|
|
|
||
|
|
afterAll(function() {
|
||
|
|
scene.destroyForSpecs();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('must be constructed with a tileProvider', function() {
|
||
|
|
expect(function() {
|
||
|
|
return new QuadtreePrimitive();
|
||
|
|
}).toThrowDeveloperError();
|
||
|
|
|
||
|
|
expect(function() {
|
||
|
|
return new QuadtreePrimitive({});
|
||
|
|
}).toThrowDeveloperError();
|
||
|
|
});
|
||
|
|
|
||
|
|
function createSpyTileProvider() {
|
||
|
|
var result = jasmine.createSpyObj('tileProvider', [
|
||
|
|
'getQuadtree', 'setQuadtree', 'getReady', 'getTilingScheme', 'getErrorEvent',
|
||
|
|
'initialize', 'updateImagery', 'beginUpdate', 'endUpdate', 'getLevelMaximumGeometricError', 'loadTile',
|
||
|
|
'computeTileVisibility', 'showTileThisFrame', 'computeDistanceToTile', 'isDestroyed', 'destroy']);
|
||
|
|
|
||
|
|
defineProperties(result, {
|
||
|
|
quadtree : {
|
||
|
|
get : result.getQuadtree,
|
||
|
|
set : result.setQuadtree
|
||
|
|
},
|
||
|
|
ready : {
|
||
|
|
get : result.getReady
|
||
|
|
},
|
||
|
|
tilingScheme : {
|
||
|
|
get : result.getTilingScheme
|
||
|
|
},
|
||
|
|
errorEvent : {
|
||
|
|
get : result.getErrorEvent
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
var tilingScheme = new GeographicTilingScheme();
|
||
|
|
result.getTilingScheme.and.returnValue(tilingScheme);
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
it('calls initialize, beginUpdate, loadTile, and endUpdate', function() {
|
||
|
|
var tileProvider = createSpyTileProvider();
|
||
|
|
tileProvider.getReady.and.returnValue(true);
|
||
|
|
|
||
|
|
var quadtree = new QuadtreePrimitive({
|
||
|
|
tileProvider : tileProvider
|
||
|
|
});
|
||
|
|
|
||
|
|
// determine what tiles to load
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
// load tiles
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
expect(tileProvider.initialize).toHaveBeenCalled();
|
||
|
|
expect(tileProvider.beginUpdate).toHaveBeenCalled();
|
||
|
|
expect(tileProvider.loadTile).toHaveBeenCalled();
|
||
|
|
expect(tileProvider.endUpdate).toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('shows the root tiles when they are ready and visible', function() {
|
||
|
|
var tileProvider = createSpyTileProvider();
|
||
|
|
tileProvider.getReady.and.returnValue(true);
|
||
|
|
tileProvider.computeTileVisibility.and.returnValue(Visibility.FULL);
|
||
|
|
tileProvider.loadTile.and.callFake(function(frameState, tile) {
|
||
|
|
tile.renderable = true;
|
||
|
|
});
|
||
|
|
|
||
|
|
var quadtree = new QuadtreePrimitive({
|
||
|
|
tileProvider : tileProvider
|
||
|
|
});
|
||
|
|
|
||
|
|
// determine what tiles to load
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
// load tiles
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
expect(tileProvider.showTileThisFrame).toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('stops loading a tile that moves to the DONE state', function() {
|
||
|
|
var tileProvider = createSpyTileProvider();
|
||
|
|
tileProvider.getReady.and.returnValue(true);
|
||
|
|
tileProvider.computeTileVisibility.and.returnValue(Visibility.FULL);
|
||
|
|
|
||
|
|
var calls = 0;
|
||
|
|
tileProvider.loadTile.and.callFake(function(frameState, tile) {
|
||
|
|
++calls;
|
||
|
|
tile.state = QuadtreeTileLoadState.DONE;
|
||
|
|
});
|
||
|
|
|
||
|
|
var quadtree = new QuadtreePrimitive({
|
||
|
|
tileProvider : tileProvider
|
||
|
|
});
|
||
|
|
|
||
|
|
// determine what tiles to load
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
// load tiles
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
expect(calls).toBe(2);
|
||
|
|
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
expect(calls).toBe(2);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('tileLoadProgressEvent is raised when tile loaded and when new children discovered', function() {
|
||
|
|
var eventHelper = new EventHelper();
|
||
|
|
|
||
|
|
var tileProvider = createSpyTileProvider();
|
||
|
|
tileProvider.getReady.and.returnValue(true);
|
||
|
|
tileProvider.computeTileVisibility.and.returnValue(Visibility.FULL);
|
||
|
|
|
||
|
|
var quadtree = new QuadtreePrimitive({
|
||
|
|
tileProvider : tileProvider
|
||
|
|
});
|
||
|
|
|
||
|
|
var progressEventSpy = jasmine.createSpy('progressEventSpy');
|
||
|
|
eventHelper.add(quadtree.tileLoadProgressEvent, progressEventSpy);
|
||
|
|
|
||
|
|
// Initial update to get the zero-level tiles set up.
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
// load zero-level tiles
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
// There will now be two zero-level tiles in the load queue.
|
||
|
|
expect(progressEventSpy.calls.mostRecent().args[0]).toEqual(2);
|
||
|
|
|
||
|
|
// Change one to loaded and update again
|
||
|
|
quadtree._levelZeroTiles[0].state = QuadtreeTileLoadState.DONE;
|
||
|
|
quadtree._levelZeroTiles[1].state = QuadtreeTileLoadState.LOADING;
|
||
|
|
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
// Now there should only be one left in the update queue
|
||
|
|
expect(progressEventSpy.calls.mostRecent().args[0]).toEqual(1);
|
||
|
|
|
||
|
|
// Simulate the second zero-level child having loaded with two children.
|
||
|
|
quadtree._levelZeroTiles[1].state = QuadtreeTileLoadState.DONE;
|
||
|
|
quadtree._levelZeroTiles[1].renderable = true;
|
||
|
|
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
|
||
|
|
scene.renderForSpecs();
|
||
|
|
|
||
|
|
// Now that tile's four children should be in the load queue.
|
||
|
|
expect(progressEventSpy.calls.mostRecent().args[0]).toEqual(4);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('forEachLoadedTile does not enumerate tiles in the START state', function() {
|
||
|
|
var tileProvider = createSpyTileProvider();
|
||
|
|
tileProvider.getReady.and.returnValue(true);
|
||
|
|
tileProvider.computeTileVisibility.and.returnValue(Visibility.FULL);
|
||
|
|
tileProvider.computeDistanceToTile.and.returnValue(1e-15);
|
||
|
|
|
||
|
|
// Load the root tiles.
|
||
|
|
tileProvider.loadTile.and.callFake(function(frameState, tile) {
|
||
|
|
tile.state = QuadtreeTileLoadState.DONE;
|
||
|
|
tile.renderable = true;
|
||
|
|
});
|
||
|
|
|
||
|
|
var quadtree = new QuadtreePrimitive({
|
||
|
|
tileProvider : tileProvider
|
||
|
|
});
|
||
|
|
|
||
|
|
// determine what tiles to load
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
// load tiles
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
// Don't load further tiles.
|
||
|
|
tileProvider.loadTile.and.callFake(function(frameState, tile) {
|
||
|
|
tile.state = QuadtreeTileLoadState.START;
|
||
|
|
});
|
||
|
|
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
quadtree.forEachLoadedTile(function(tile) {
|
||
|
|
expect(tile.state).not.toBe(QuadtreeTileLoadState.START);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('add and remove callbacks to tiles', function() {
|
||
|
|
var tileProvider = createSpyTileProvider();
|
||
|
|
tileProvider.getReady.and.returnValue(true);
|
||
|
|
tileProvider.computeTileVisibility.and.returnValue(Visibility.FULL);
|
||
|
|
tileProvider.computeDistanceToTile.and.returnValue(1e-15);
|
||
|
|
|
||
|
|
// Load the root tiles.
|
||
|
|
tileProvider.loadTile.and.callFake(function(frameState, tile) {
|
||
|
|
tile.state = QuadtreeTileLoadState.DONE;
|
||
|
|
tile.renderable = true;
|
||
|
|
tile.data = {
|
||
|
|
pick : function() {
|
||
|
|
return undefined;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
});
|
||
|
|
|
||
|
|
var quadtree = new QuadtreePrimitive({
|
||
|
|
tileProvider : tileProvider
|
||
|
|
});
|
||
|
|
|
||
|
|
var removeFunc = quadtree.updateHeight(Cartographic.fromDegrees(-72.0, 40.0), function(position) {
|
||
|
|
});
|
||
|
|
|
||
|
|
// determine what tiles to load
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
// load tiles
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
var addedCallback = false;
|
||
|
|
quadtree.forEachLoadedTile(function(tile) {
|
||
|
|
addedCallback = addedCallback || tile.customData.length > 0;
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(addedCallback).toEqual(true);
|
||
|
|
|
||
|
|
removeFunc();
|
||
|
|
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
var removedCallback = true;
|
||
|
|
quadtree.forEachLoadedTile(function(tile) {
|
||
|
|
removedCallback = removedCallback && tile.customData.length === 0;
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(removedCallback).toEqual(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('updates heights', function() {
|
||
|
|
var tileProvider = createSpyTileProvider();
|
||
|
|
tileProvider.getReady.and.returnValue(true);
|
||
|
|
tileProvider.computeTileVisibility.and.returnValue(Visibility.FULL);
|
||
|
|
tileProvider.computeDistanceToTile.and.returnValue(1e-15);
|
||
|
|
|
||
|
|
tileProvider.terrainProvider = {
|
||
|
|
getTileDataAvailable : function() {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
var position = Cartesian3.clone(Cartesian3.ZERO);
|
||
|
|
var updatedPosition = Cartesian3.clone(Cartesian3.UNIT_X);
|
||
|
|
var currentPosition = position;
|
||
|
|
|
||
|
|
// Load the root tiles.
|
||
|
|
tileProvider.loadTile.and.callFake(function(frameState, tile) {
|
||
|
|
tile.state = QuadtreeTileLoadState.DONE;
|
||
|
|
tile.renderable = true;
|
||
|
|
tile.data = {
|
||
|
|
pick : function() {
|
||
|
|
return currentPosition;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
});
|
||
|
|
|
||
|
|
var quadtree = new QuadtreePrimitive({
|
||
|
|
tileProvider : tileProvider
|
||
|
|
});
|
||
|
|
|
||
|
|
quadtree.updateHeight(Cartographic.fromDegrees(-72.0, 40.0), function(p) {
|
||
|
|
Cartesian3.clone(p, position);
|
||
|
|
});
|
||
|
|
|
||
|
|
// determine what tiles to load
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
// load tiles
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
expect(position).toEqual(Cartesian3.ZERO);
|
||
|
|
|
||
|
|
currentPosition = updatedPosition;
|
||
|
|
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
expect(position).toEqual(updatedPosition);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('gives correct priority to tile loads', function() {
|
||
|
|
var tileProvider = createSpyTileProvider();
|
||
|
|
tileProvider.getReady.and.returnValue(true);
|
||
|
|
tileProvider.computeTileVisibility.and.returnValue(Visibility.FULL);
|
||
|
|
|
||
|
|
var quadtree = new QuadtreePrimitive({
|
||
|
|
tileProvider : tileProvider
|
||
|
|
});
|
||
|
|
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
// The root tiles should be in the high priority load queue
|
||
|
|
expect(quadtree._tileLoadQueueHigh.length).toBe(2);
|
||
|
|
expect(quadtree._tileLoadQueueHigh).toContain(quadtree._levelZeroTiles[0]);
|
||
|
|
expect(quadtree._tileLoadQueueHigh).toContain(quadtree._levelZeroTiles[1]);
|
||
|
|
expect(quadtree._tileLoadQueueMedium.length).toBe(0);
|
||
|
|
expect(quadtree._tileLoadQueueLow.length).toBe(0);
|
||
|
|
|
||
|
|
// Mark the first root tile renderable (but not done loading)
|
||
|
|
quadtree._levelZeroTiles[0].renderable = true;
|
||
|
|
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
// That root tile should now load with low priority while its children should load with high.
|
||
|
|
expect(quadtree._tileLoadQueueHigh.length).toBe(5);
|
||
|
|
expect(quadtree._tileLoadQueueHigh).toContain(quadtree._levelZeroTiles[1]);
|
||
|
|
expect(quadtree._tileLoadQueueHigh).toContain(quadtree._levelZeroTiles[0].children[0]);
|
||
|
|
expect(quadtree._tileLoadQueueHigh).toContain(quadtree._levelZeroTiles[0].children[1]);
|
||
|
|
expect(quadtree._tileLoadQueueHigh).toContain(quadtree._levelZeroTiles[0].children[2]);
|
||
|
|
expect(quadtree._tileLoadQueueHigh).toContain(quadtree._levelZeroTiles[0].children[3]);
|
||
|
|
expect(quadtree._tileLoadQueueMedium.length).toBe(0);
|
||
|
|
expect(quadtree._tileLoadQueueLow.length).toBe(1);
|
||
|
|
expect(quadtree._tileLoadQueueLow).toContain(quadtree._levelZeroTiles[0]);
|
||
|
|
|
||
|
|
// Mark the children of that root tile renderable too, so we can refine it
|
||
|
|
quadtree._levelZeroTiles[0].children[0].renderable = true;
|
||
|
|
quadtree._levelZeroTiles[0].children[1].renderable = true;
|
||
|
|
quadtree._levelZeroTiles[0].children[2].renderable = true;
|
||
|
|
quadtree._levelZeroTiles[0].children[3].renderable = true;
|
||
|
|
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
expect(quadtree._tileLoadQueueHigh.length).toBe(17); // levelZeroTiles[1] plus levelZeroTiles[0]'s 16 grandchildren
|
||
|
|
expect(quadtree._tileLoadQueueHigh).toContain(quadtree._levelZeroTiles[1]);
|
||
|
|
expect(quadtree._tileLoadQueueHigh).toContain(quadtree._levelZeroTiles[0].children[0].children[0]);
|
||
|
|
expect(quadtree._tileLoadQueueHigh).toContain(quadtree._levelZeroTiles[0].children[0].children[1]);
|
||
|
|
expect(quadtree._tileLoadQueueHigh).toContain(quadtree._levelZeroTiles[0].children[0].children[2]);
|
||
|
|
expect(quadtree._tileLoadQueueHigh).toContain(quadtree._levelZeroTiles[0].children[0].children[3]);
|
||
|
|
expect(quadtree._tileLoadQueueMedium.length).toBe(0);
|
||
|
|
expect(quadtree._tileLoadQueueLow.length).toBe(5);
|
||
|
|
expect(quadtree._tileLoadQueueLow).toContain(quadtree._levelZeroTiles[0]);
|
||
|
|
expect(quadtree._tileLoadQueueLow).toContain(quadtree._levelZeroTiles[0].children[0]);
|
||
|
|
expect(quadtree._tileLoadQueueLow).toContain(quadtree._levelZeroTiles[0].children[1]);
|
||
|
|
expect(quadtree._tileLoadQueueLow).toContain(quadtree._levelZeroTiles[0].children[2]);
|
||
|
|
expect(quadtree._tileLoadQueueLow).toContain(quadtree._levelZeroTiles[0].children[3]);
|
||
|
|
|
||
|
|
// Mark the children of levelZeroTiles[0] upsampled
|
||
|
|
quadtree._levelZeroTiles[0].children[0].upsampledFromParent = true;
|
||
|
|
quadtree._levelZeroTiles[0].children[1].upsampledFromParent = true;
|
||
|
|
quadtree._levelZeroTiles[0].children[2].upsampledFromParent = true;
|
||
|
|
quadtree._levelZeroTiles[0].children[3].upsampledFromParent = true;
|
||
|
|
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
// levelZeroTiles[0] should move to medium priority.
|
||
|
|
// Its descendents should continue loading, so they have a chance to decide they're not upsampled later.
|
||
|
|
expect(quadtree._tileLoadQueueHigh.length).toBe(1);
|
||
|
|
expect(quadtree._tileLoadQueueHigh).toContain(quadtree._levelZeroTiles[1]);
|
||
|
|
expect(quadtree._tileLoadQueueMedium.length).toBe(1);
|
||
|
|
expect(quadtree._tileLoadQueueMedium).toContain(quadtree._levelZeroTiles[0]);
|
||
|
|
expect(quadtree._tileLoadQueueLow.length).toBe(4);
|
||
|
|
expect(quadtree._tileLoadQueueLow).toContain(quadtree._levelZeroTiles[0].children[0]);
|
||
|
|
expect(quadtree._tileLoadQueueLow).toContain(quadtree._levelZeroTiles[0].children[1]);
|
||
|
|
expect(quadtree._tileLoadQueueLow).toContain(quadtree._levelZeroTiles[0].children[2]);
|
||
|
|
expect(quadtree._tileLoadQueueLow).toContain(quadtree._levelZeroTiles[0].children[3]);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders tiles in approximate near-to-far order', function() {
|
||
|
|
var tileProvider = createSpyTileProvider();
|
||
|
|
tileProvider.getReady.and.returnValue(true);
|
||
|
|
tileProvider.computeTileVisibility.and.returnValue(Visibility.FULL);
|
||
|
|
|
||
|
|
var quadtree = new QuadtreePrimitive({
|
||
|
|
tileProvider : tileProvider
|
||
|
|
});
|
||
|
|
|
||
|
|
tileProvider.loadTile.and.callFake(function(frameState, tile) {
|
||
|
|
if (tile.level <= 1) {
|
||
|
|
tile.state = QuadtreeTileLoadState.DONE;
|
||
|
|
tile.renderable = true;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
scene.camera.setView({
|
||
|
|
destination : Cartesian3.fromDegrees(1.0, 1.0, 15000.0)
|
||
|
|
});
|
||
|
|
scene.camera.update(scene.mode);
|
||
|
|
|
||
|
|
return pollToPromise(function() {
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
return quadtree._tilesToRender.filter(function(tile) { return tile.level === 1; }).length === 8;
|
||
|
|
}).then(function() {
|
||
|
|
quadtree.update(scene.frameState);
|
||
|
|
quadtree.beginFrame(scene.frameState);
|
||
|
|
quadtree.render(scene.frameState);
|
||
|
|
quadtree.endFrame(scene.frameState);
|
||
|
|
|
||
|
|
// Rendered tiles:
|
||
|
|
// +----+----+----+----+
|
||
|
|
// |w.nw|w.ne|e.nw|e.ne|
|
||
|
|
// +----+----+----+----+
|
||
|
|
// |w.sw|w.se|e.sw|e.se|
|
||
|
|
// +----+----+----+----+
|
||
|
|
// camera is located in e.nw (east.northwestChild)
|
||
|
|
|
||
|
|
var west = quadtree._levelZeroTiles.filter(function(tile) { return tile.x === 0; })[0];
|
||
|
|
var east = quadtree._levelZeroTiles.filter(function(tile) { return tile.x === 1; })[0];
|
||
|
|
expect(quadtree._tilesToRender[0]).toBe(east.northwestChild);
|
||
|
|
expect(quadtree._tilesToRender[1] === east.southwestChild || quadtree._tilesToRender[1] === east.northeastChild).toBe(true);
|
||
|
|
expect(quadtree._tilesToRender[2] === east.southwestChild || quadtree._tilesToRender[2] === east.northeastChild).toBe(true);
|
||
|
|
expect(quadtree._tilesToRender[3]).toBe(east.southeastChild);
|
||
|
|
expect(quadtree._tilesToRender[4]).toBe(west.northeastChild);
|
||
|
|
expect(quadtree._tilesToRender[5] === west.northwestChild || quadtree._tilesToRender[5] === west.southeastChild).toBe(true);
|
||
|
|
expect(quadtree._tilesToRender[6] === west.northwestChild || quadtree._tilesToRender[6] === west.southeastChild).toBe(true);
|
||
|
|
expect(quadtree._tilesToRender[7]).toBe(west.southwestChild);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}, 'WebGL');
|