Skip to content

Commit

Permalink
Merge pull request #7061 from AnalyticalGraphicsInc/fill-tiles
Browse files Browse the repository at this point in the history
Terrain / imagery rendering overhaul
  • Loading branch information
mramato authored Feb 12, 2019
2 parents f87fbad + 96b3f26 commit 6f152be
Show file tree
Hide file tree
Showing 53 changed files with 6,487 additions and 1,821 deletions.
189 changes: 189 additions & 0 deletions Apps/Sandcastle/gallery/development/Terrain Performance.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="Measure terrain loading and rendering performance.">
<meta name="cesium-sandcastle-labels" content="Development">
<title>Cesium Demo</title>
<script type="text/javascript" src="../Sandcastle-header.js"></script>
<script type="text/javascript" src="../../../ThirdParty/requirejs-2.1.20/require.js"></script>
<script type="text/javascript">
if(typeof require === "function") {
require.config({
baseUrl : '../../../Source',
waitSeconds : 120
});
}
</script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
@import url(../templates/bucket.css);
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar"></div>
<script id="cesium_sandcastle_script">
function startup(Cesium) {
'use strict';
//Sandcastle_Begin
var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;
var camera = scene.camera;
var globe = scene.globe;
var statistics = Cesium.RequestScheduler.statistics;

viewer.terrainProvider = Cesium.createWorldTerrain();

var startTime;
var flightComplete;
var monitor;
var minFrameRate = 1000;
var maxFrameRate = 0;
var sumFrameRate = 0.0;
var frameRateSamples = 0;

function startTest() {
flightComplete = false;
statistics.numberOfActiveRequestsEver = 0;
monitor = new Cesium.FrameRateMonitor({
scene: scene,
samplingWindow: 1.0,
quietPeriod: 0.0,
warmupPeriod: 0.0,
minimumFrameRateDuringWarmup: 0,
minimumFrameRateAfterWarmup: 0
});
scene.preUpdate.addEventListener(measureFrameRate);
startTime = window.performance.now();
window.setTimeout(function() {
scene.postRender.addEventListener(viewReady);
}, 500);
}

function measureFrameRate() {
var frameRate = monitor.lastFramesPerSecond;
if (frameRate === undefined || frameRate !== frameRate) {
return;
}

++frameRateSamples;
sumFrameRate += frameRate;
minFrameRate = Math.min(minFrameRate, frameRate);
maxFrameRate = Math.max(maxFrameRate, frameRate);
}

function viewReady(scene, time) {
var ready = globe._surface.tileProvider.ready && globe._surface._tileLoadQueueHigh.length === 0 && globe._surface._tileLoadQueueMedium.length === 0 && globe._surface._tileLoadQueueLow.length === 0 && globe._surface._debug.tilesWaitingForChildren === 0;
if (flightComplete && ready) {
var endTime = window.performance.now();
var duration = endTime - startTime;
alert((duration / 1000).toFixed(2) + ' seconds ' + statistics.numberOfActiveRequestsEver + ' requests, min/max/avg frame FPS ' + minFrameRate + '/' + maxFrameRate + '/' + (sumFrameRate / frameRateSamples));
scene.postRender.removeEventListener(viewReady);
}
}

function goToEverestHorizontal() {
camera.position = new Cesium.Cartesian3(302950.1757410969, 5637093.359233209, 2976894.491577989);
camera.direction = new Cesium.Cartesian3(-0.9648960658153797, -0.24110066659365145, -0.10414437451009724);
camera.right = new Cesium.Cartesian3(-0.02152846103178338, 0.46781654381873394, -0.8835633574877908);
camera.up = new Cesium.Cartesian3(-0.26174817580950865, 0.8503047394302772, 0.456584868959543);
flightComplete = true;
}

function goToEverestTopDown() {
camera.position = new Cesium.Cartesian3(301989.1870802739, 5637745.915399717, 2977153.0443453398);
camera.direction = new Cesium.Cartesian3(0.021398841015326783, -0.8909524564021135, -0.45359211857597476);
camera.right = new Cesium.Cartesian3(0.21237352569072232, 0.4473925820246778, -0.8687562161705573);
camera.up = new Cesium.Cartesian3(-0.9769542339275126, 0.07774058129659328, -0.19878839712310903);
flightComplete = true;
}

function goToEverest45Degrees() {
camera.position = new Cesium.Cartesian3(302760.41072832496, 5637092.977453635, 2977284.6758398763);
camera.direction = new Cesium.Cartesian3(-0.7254568510163212, -0.3330925403210976, -0.6022970337764594);
camera.right = new Cesium.Cartesian3(0.4750641658993092, 0.39087207931336604, -0.7883736778277414);
camera.up = new Cesium.Cartesian3(-0.49802248502640617, 0.8580608237157107, 0.12532049797395203);
flightComplete = true;
}

function zoomToEverest() {
var position = new Cesium.Cartesian3(302955.90876054496, 5639614.4908250235, 2981096.1048591887);
camera.flyTo({
destination : position,
easingFunction : Cesium.EasingFunction.QUADRATIC_OUT,
complete : function() {
flightComplete = true;
}
});
}

function panAroundEverest() {
camera.position = new Cesium.Cartesian3(302950.1757410969, 5637093.359233209, 2976894.491577989);
camera.direction = new Cesium.Cartesian3(-0.9648960658153797, -0.24110066659365145, -0.10414437451009724);
camera.right = new Cesium.Cartesian3(-0.02152846103178338, 0.46781654381873394, -0.8835633574877908);
camera.up = new Cesium.Cartesian3(-0.26174817580950865, 0.8503047394302772, 0.456584868959543);

var startCartographic = Cesium.Cartographic.fromCartesian(camera.position);
var longitude = startCartographic.longitude;
var endLongitude = longitude + 0.01;
var latitude = startCartographic.latitude;
var height = startCartographic.height;
var startTime = window.performance.now();
var removeCallback = scene.preRender.addEventListener(function(scene, time) {
var endTime = window.performance.now();
var delta = endTime - startTime;
startTime = endTime;
longitude += delta * 0.000001;
if (longitude >= endLongitude) {
flightComplete = true;
removeCallback();
}
camera.position = Cesium.Cartesian3.fromRadians(longitude, latitude, height);
});
}

Sandcastle.addToolbarButton('Timer Static Horizontal', function() {
startTest();
goToEverestHorizontal();
});

Sandcastle.addToolbarButton('Timer Static Top Down', function() {
startTest();
goToEverestTopDown();
});

Sandcastle.addToolbarButton('Timer Static 45 degrees', function() {
startTest();
goToEverest45Degrees();
});

Sandcastle.addToolbarButton('Timer Zoom', function() {
startTest();
zoomToEverest();
});

Sandcastle.addToolbarButton('Timer Pan', function() {
startTest();
panAroundEverest();
});

Sandcastle.addToolbarButton('Save camera', function() {
var cameraString = 'camera.position = new Cesium.Cartesian3(' + camera.positionWC.x + ', ' + camera.positionWC.y + ', ' + camera.positionWC.z + ');\n'+
'camera.direction = new Cesium.Cartesian3(' + camera.directionWC.x + ', ' + camera.directionWC.y + ', ' + camera.directionWC.z + ');\n'+
'camera.right = new Cesium.Cartesian3(' + camera.rightWC.x + ', ' + camera.rightWC.y + ', ' + camera.rightWC.z + ');\n'+
'camera.up = new Cesium.Cartesian3(' + camera.upWC.x + ', ' + camera.upWC.y + ', ' + camera.upWC.z + ');\n';
console.log(cameraString);
});//Sandcastle_End
Sandcastle.finishedLoading();
}
if (typeof Cesium !== "undefined") {
startup(Cesium);
} else if (typeof require === "function") {
require(["Cesium"], startup);
}
</script>
</body>
</html>
122 changes: 122 additions & 0 deletions Apps/Sandcastle/gallery/development/Terrain Tweaks.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="Tweak various terrain tweakables.">
<meta name="cesium-sandcastle-labels" content="Development">
<title>Cesium Demo</title>
<script type="text/javascript" src="../Sandcastle-header.js"></script>
<script type="text/javascript" src="../../../ThirdParty/requirejs-2.1.20/require.js"></script>
<script type="text/javascript">
if(typeof require === 'function') {
require.config({
baseUrl : '../../../Source',
waitSeconds : 120
});
}
</script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
@import url(../templates/bucket.css);
#toolbar {
background: rgba(42, 42, 42, 0.8);
padding: 4px;
border-radius: 4px;
}
#toolbar input {
vertical-align: middle;
padding-top: 2px;
padding-bottom: 2px;
}
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
<table>
<tbody>
<tr>
<td>Loading Descendant Limit</td>
<td>
<input type="text" size="5" data-bind="value: loadingDescendantLimit" title="The number of loading descendant tiles that is considered 'too many'. If a tile has too many loading descendants, that tile will be loaded and rendered before any of its descendants are loaded and rendered. This means more feedback for the user that something is happening at the cost of a longer overall load time. Setting this to 0 will cause each tile level to be loaded successively, significantly increasing load time. Setting it to a large number (e.g. 100000) will minimize the number of tiles that are loaded but tend to make detail appear all at once after a long wait." />
</td>
</tr>
<tr>
<td>Preload Ancestors</td>
<td>
<input type="checkbox" data-bind="checked: preloadAncestors" title="Indicating whether the ancestors of rendered tiles should be preloaded. Setting this to true optimizes the zoom-out experience and provides more detail in newly-exposed areas when panning. The down side is that it requires loading more tiles." />
</td>
</tr>
<tr>
<td>Preload Siblings</td>
<td>
<input type="checkbox" data-bind="checked: preloadSiblings" title="Gets or sets a value indicating whether the siblings of rendered tiles should be preloaded. Setting this to true causes tiles with the same parent as a rendered tile to be loaded, even if they are culled. Setting this to true may provide a better panning experience at the cost of loading more tiles." />
</td>
</tr>
<tr>
<td>Fill Tile Highlight</td>
<td>
<input type="checkbox" data-bind="checked: fillHighlightEnabled" title="Highlights generated fill tiles." />
<input type="text" size="25" data-bind="value: fillHighlightColor" title="The color to use to highlight fill tiles. If undefined, fill tiles are not highlighted at all. The alpha value is used to alpha blend with the tile's actual color." />
</td>
</tr>
</tbody>
</table>
</div>
<script id="cesium_sandcastle_script">
function startup(Cesium) {
'use strict';
//Sandcastle_Begin
var viewer = new Cesium.Viewer('cesiumContainer');

var viewModel = {
loadingDescendantLimit: viewer.scene.globe.loadingDescendantLimit,
preloadAncestors: viewer.scene.globe.preloadAncestors,
preloadSiblings: viewer.scene.globe.preloadSiblings,
fillHighlightColor: Cesium.defined(viewer.scene.globe.fillHighlightColor) ? viewer.scene.globe.fillHighlightColor.toCssColorString() : 'rgba(255, 255, 0, 0.5)',
fillHighlightEnabled: Cesium.defined(viewer.scene.globe.fillHighlightColor)
};

Cesium.knockout.track(viewModel);

var toolbar = document.getElementById('toolbar');
Cesium.knockout.applyBindings(viewModel, toolbar);

Cesium.knockout.getObservable(viewModel, 'loadingDescendantLimit').subscribe(function(newValue) {
viewer.scene.globe.loadingDescendantLimit = parseInt(newValue, 10);
});
Cesium.knockout.getObservable(viewModel, 'preloadAncestors').subscribe(function(newValue) {
viewer.scene.globe.preloadAncestors = newValue;
});
Cesium.knockout.getObservable(viewModel, 'preloadSiblings').subscribe(function(newValue) {
viewer.scene.globe.preloadSiblings = newValue;
});

function updateFillHighlight() {
if (viewModel.fillHighlightEnabled) {
viewer.scene.globe.fillHighlightColor = Cesium.Color.fromCssColorString(viewModel.fillHighlightColor);
} else {
viewer.scene.globe.fillHighlightColor = undefined;
}
}

Cesium.knockout.getObservable(viewModel, 'fillHighlightEnabled').subscribe(function(newValue) {
updateFillHighlight();
});
Cesium.knockout.getObservable(viewModel, 'fillHighlightColor').subscribe(function(newValue) {
updateFillHighlight();
});

//Sandcastle_End
Sandcastle.finishedLoading();
}
if (typeof Cesium !== 'undefined') {
startup(Cesium);
} else if (typeof require === 'function') {
require(['Cesium'], startup);
}
</script>
</body>
</html>
7 changes: 5 additions & 2 deletions Source/Core/CesiumTerrainProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -904,7 +904,10 @@ define([
* Gets an object that can be used to determine availability of terrain from this provider, such as
* at points and in rectangles. This function should not be called before
* {@link CesiumTerrainProvider#ready} returns true. This property may be undefined if availability
* information is not available.
* information is not available. Note that this reflects tiles that are known to be available currently.
* Additional tiles may be discovered to be available in the future, e.g. if availability information
* exists deeper in the tree rather than it all being discoverable at the root. However, a tile that
* is available now will not become unavailable in the future.
* @memberof CesiumTerrainProvider.prototype
* @type {TileAvailability}
*/
Expand Down Expand Up @@ -936,7 +939,7 @@ define([
* @param {Number} x The X coordinate of the tile for which to request geometry.
* @param {Number} y The Y coordinate of the tile for which to request geometry.
* @param {Number} level The level of the tile for which to request geometry.
* @returns {Boolean} Undefined if not supported, otherwise true or false.
* @returns {Boolean} Undefined if not supported or availability is unknown, otherwise true or false.
*/
CesiumTerrainProvider.prototype.getTileDataAvailable = function(x, y, level) {
if (!defined(this._availability)) {
Expand Down
6 changes: 5 additions & 1 deletion Source/Core/GoogleEarthEnterpriseTerrainData.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,11 @@ define([
result.numberOfAttributes,
result.orientedBoundingBox,
TerrainEncoding.clone(result.encoding),
exaggeration);
exaggeration,
result.westIndicesSouthToNorth,
result.southIndicesEastToWest,
result.eastIndicesNorthToSouth,
result.northIndicesWestToEast);

that._vertexCountWithoutSkirts = result.vertexCountWithoutSkirts;
that._skirtIndex = result.skirtIndex;
Expand Down
Loading

0 comments on commit 6f152be

Please sign in to comment.