Skip to content

Commit

Permalink
add geographic limit rectangle
Browse files Browse the repository at this point in the history
  • Loading branch information
likangning93 committed Aug 31, 2018
1 parent c8cf473 commit c94c510
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 7 deletions.
88 changes: 88 additions & 0 deletions Apps/Sandcastle/gallery/Geographic Limit Rectangle.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<!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="Use Viewer to start building new applications or easily embed Cesium into existing applications.">
<meta name="cesium-sandcastle-labels" content="Showcases">
<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', {
terrainProvider: Cesium.createWorldTerrain()
});

// Tropics of Cancer and Capricorn
var coffeeBeltRectangle = Cesium.Rectangle.fromDegrees(-180, -23.43687, 180, 23.43687);

viewer.scene.globe.geographicLimitRectangle = coffeeBeltRectangle;
viewer.scene.skyAtmosphere.show = false;

// Add rectangles to show bounds
var rectangles = [];

for (var i = 0; i < 10; i++) {
rectangles.push(viewer.entities.add({
name : 'EPSG 2093 bounds',
rectangle : {
coordinates : coffeeBeltRectangle,
material : Cesium.Color.WHITE.withAlpha(0.0),
height : i * 5000.0,
outline : true,
outlineWidth : 4.0,
outlineColor : Cesium.Color.WHITE
}
}));
}

Sandcastle.addToolbarButton('Show/Hide Bounds', function() {
var rectanglesLength = rectangles.length;
for (var i = 0; i < rectanglesLength; i++) {
var rectangleEntity = rectangles[i];
rectangleEntity.show = !rectangleEntity.show;
}
});

var limited = true;
Sandcastle.addToolbarButton('enable/disable limiter', function() {
if (limited) {
viewer.scene.globe.geographicLimitRectangle = Cesium.Rectangle.MAX_VALUE;
limited = false;
} else {
viewer.scene.globe.geographicLimitRectangle = coffeeBeltRectangle;
limited = true;
}
});

//Sandcastle_End
Sandcastle.finishedLoading();
}
if (typeof Cesium !== 'undefined') {
startup(Cesium);
} else if (typeof require === 'function') {
require(['Cesium'], startup);
}
</script>
</body>
</html>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions Source/Scene/Globe.js
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,14 @@ define([
this._surface.tileProvider.clippingPlanes = value;
}
},
geographicLimitRectangle : {
get : function() {
return this._surface.tileProvider.geographicLimitRectangle;
},
set : function(value) {
this._surface.tileProvider.geographicLimitRectangle = value;
}
},
/**
* The normal map to use for rendering waves in the ocean. Setting this property will
* only have an effect if the configured terrain provider includes a water mask.
Expand Down
14 changes: 11 additions & 3 deletions Source/Scene/GlobeSurfaceShaderSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ define([
return useWebMercatorProjection ? get2DYPositionFractionMercatorProjection : get2DYPositionFractionGeographicProjection;
}

GlobeSurfaceShaderSet.prototype.getShaderProgram = function(frameState, surfaceTile, numberOfDayTextures, applyBrightness, applyContrast, applyHue, applySaturation, applyGamma, applyAlpha, applySplit, showReflectiveOcean, showOceanWaves, enableLighting, hasVertexNormals, useWebMercatorProjection, enableFog, enableClippingPlanes, clippingPlanes) {
GlobeSurfaceShaderSet.prototype.getShaderProgram = function(frameState, surfaceTile, numberOfDayTextures, applyBrightness, applyContrast, applyHue, applySaturation, applyGamma, applyAlpha, applySplit, showReflectiveOcean, showOceanWaves, enableLighting, hasVertexNormals, useWebMercatorProjection, enableFog, enableClippingPlanes, clippingPlanes, clippedByBoundaries) {
var quantization = 0;
var quantizationDefine = '';

Expand All @@ -84,6 +84,13 @@ define([
vertexLogDepthDefine = 'DISABLE_GL_POSITION_LOG_DEPTH';
}

var geographicLimitRectangleFlag = 0;
var geographicLimitRectangleDefine = '';
if (clippedByBoundaries) {//} && frameState.mode !== SceneMode.SCENE3D) {
geographicLimitRectangleFlag = 1;
geographicLimitRectangleDefine = 'TILE_LIMIT_RECTANGLE';
}

var sceneMode = frameState.mode;
var flags = sceneMode |
(applyBrightness << 2) |
Expand All @@ -101,7 +108,8 @@ define([
(quantization << 14) |
(applySplit << 15) |
(enableClippingPlanes << 16) |
(vertexLogDepth << 17);
(vertexLogDepth << 17) |
(geographicLimitRectangleFlag << 18);

var currentClippingShaderState = 0;
if (defined(clippingPlanes)) {
Expand Down Expand Up @@ -134,7 +142,7 @@ define([
}

vs.defines.push(quantizationDefine, vertexLogDepthDefine);
fs.defines.push('TEXTURE_UNITS ' + numberOfDayTextures);
fs.defines.push('TEXTURE_UNITS ' + numberOfDayTextures, geographicLimitRectangleDefine);

if (applyBrightness) {
fs.defines.push('APPLY_BRIGHTNESS');
Expand Down
2 changes: 2 additions & 0 deletions Source/Scene/GlobeSurfaceTile.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ define([

this.surfaceShader = undefined;
this.isClipped = true;

this.clippedByBoundaries = false;
}

defineProperties(GlobeSurfaceTile.prototype, {
Expand Down
42 changes: 40 additions & 2 deletions Source/Scene/GlobeSurfaceTileProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,13 @@ define([
* @private
*/
this._clippingPlanes = undefined;

/**
* A property specifying a {@link Rectangle} used to selectively prevent tiles outside a region from loading.
* For limiting terrain in scenes that use custom projections or Proj4JS projections that cause overlapping tiles.
* @type {Rectangle}
*/
this.geographicLimitRectangle = Rectangle.clone(Rectangle.MAX_VALUE);
}

defineProperties(GlobeSurfaceTileProvider.prototype, {
Expand Down Expand Up @@ -509,6 +516,7 @@ define([
};

var boundingSphereScratch = new BoundingSphere();
var rectangleIntersectionScratch = new Rectangle();

/**
* Determines the visibility of a given tile. The tile may be fully visible, partially visible, or not
Expand Down Expand Up @@ -536,6 +544,16 @@ define([
var cullingVolume = frameState.cullingVolume;
var boundingVolume = defaultValue(surfaceTile.orientedBoundingBox, surfaceTile.boundingSphere3D);

// Check if the tile is outside the limit area in cartographic space
surfaceTile.clippedByBoundaries = false;
var areaLimitIntersection = Rectangle.simpleIntersection(this.geographicLimitRectangle, tile.rectangle, rectangleIntersectionScratch);
if (!defined(areaLimitIntersection)) {
return Visibility.NONE;
}
if (!Rectangle.equals(areaLimitIntersection, tile.rectangle)) {
surfaceTile.clippedByBoundaries = true;
}

if (frameState.mode !== SceneMode.SCENE3D) {
boundingVolume = boundingSphereScratch;
BoundingSphere.fromRectangleWithHeights2D(tile.rectangle, frameState.mapProjection, surfaceTile.minimumHeight, surfaceTile.maximumHeight, boundingVolume);
Expand Down Expand Up @@ -580,6 +598,7 @@ define([
var modifiedModelViewScratch = new Matrix4();
var modifiedModelViewProjectionScratch = new Matrix4();
var tileRectangleScratch = new Cartesian4();
var localizedGeographicLimitRectangleScratch = new Cartesian4();
var rtcScratch = new Cartesian3();
var centerEyeScratch = new Cartesian3();
var southwestScratch = new Cartesian3();
Expand Down Expand Up @@ -921,6 +940,9 @@ define([
}
return frameState.context.defaultTexture;
},
u_geographicLimitRectangle : function() {
return this.properties.localizedGeographicLimitRectangle;
},
u_clippingPlanesMatrix : function() {
var clippingPlanes = globeSurfaceTileProvider._clippingPlanes;
return defined(clippingPlanes) ? Matrix4.multiply(frameState.context.uniformState.view, clippingPlanes.modelMatrix, scratchClippingPlaneMatrix) : Matrix4.IDENTITY;
Expand Down Expand Up @@ -969,7 +991,9 @@ define([
minMaxHeight : new Cartesian2(),
scaleAndBias : new Matrix4(),
clippingPlanesEdgeColor : Color.clone(Color.WHITE),
clippingPlanesEdgeWidth : 0.0
clippingPlanesEdgeWidth : 0.0,

localizedGeographicLimitRectangle : new Cartesian4()
}
};

Expand Down Expand Up @@ -1255,6 +1279,20 @@ define([
uniformMapProperties.southMercatorYAndOneOverHeight.x = southMercatorY;
uniformMapProperties.southMercatorYAndOneOverHeight.y = oneOverMercatorHeight;

// Convert tile limiter rectangle from cartographic to texture space using the tileRectangle.
var localizedGeographicLimitRectangle = localizedGeographicLimitRectangleScratch;
var geographicLimitRectangle = tileProvider.geographicLimitRectangle;

var cartographicTileRectangle = tile.rectangle;
var inverseTileWidth = 1.0 / cartographicTileRectangle.width;
var inverseTileHeight = 1.0 / cartographicTileRectangle.height;
localizedGeographicLimitRectangle.x = (geographicLimitRectangle.west - cartographicTileRectangle.west) * inverseTileWidth;
localizedGeographicLimitRectangle.y = (geographicLimitRectangle.south - cartographicTileRectangle.south) * inverseTileHeight;
localizedGeographicLimitRectangle.z = (geographicLimitRectangle.east - cartographicTileRectangle.west) * inverseTileWidth;
localizedGeographicLimitRectangle.w = (geographicLimitRectangle.north - cartographicTileRectangle.south) * inverseTileHeight;

Cartesian4.clone(localizedGeographicLimitRectangle, uniformMapProperties.localizedGeographicLimitRectangle);

// For performance, use fog in the shader only when the tile is in fog.
var applyFog = enableFog && CesiumMath.fog(tile._distance, frameState.fog.density) > CesiumMath.EPSILON3;

Expand Down Expand Up @@ -1357,7 +1395,7 @@ define([
uniformMap = combine(uniformMap, tileProvider.uniformMap);
}

command.shaderProgram = tileProvider._surfaceShaderSet.getShaderProgram(frameState, surfaceTile, numberOfDayTextures, applyBrightness, applyContrast, applyHue, applySaturation, applyGamma, applyAlpha, applySplit, showReflectiveOcean, showOceanWaves, tileProvider.enableLighting, hasVertexNormals, useWebMercatorProjection, applyFog, clippingPlanesEnabled, clippingPlanes);
command.shaderProgram = tileProvider._surfaceShaderSet.getShaderProgram(frameState, surfaceTile, numberOfDayTextures, applyBrightness, applyContrast, applyHue, applySaturation, applyGamma, applyAlpha, applySplit, showReflectiveOcean, showOceanWaves, tileProvider.enableLighting, hasVertexNormals, useWebMercatorProjection, applyFog, clippingPlanesEnabled, clippingPlanes, surfaceTile.clippedByBoundaries);
command.castShadows = castShadows;
command.receiveShadows = receiveShadows;
command.renderState = renderState;
Expand Down
13 changes: 13 additions & 0 deletions Source/Shaders/GlobeFS.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ uniform sampler2D u_oceanNormalMap;
uniform vec2 u_lightingFadeDistance;
#endif

#ifdef TILE_LIMIT_RECTANGLE
uniform vec4 u_geographicLimitRectangle;
#endif

#ifdef ENABLE_CLIPPING_PLANES
uniform sampler2D u_clippingPlanes;
uniform mat4 u_clippingPlanesMatrix;
Expand Down Expand Up @@ -155,6 +159,15 @@ vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat

void main()
{

#ifdef TILE_LIMIT_RECTANGLE
if (v_textureCoordinates.x < u_geographicLimitRectangle.x || u_geographicLimitRectangle.z < v_textureCoordinates.x ||
v_textureCoordinates.y < u_geographicLimitRectangle.y || u_geographicLimitRectangle.w < v_textureCoordinates.y)
{
discard;
}
#endif

#ifdef ENABLE_CLIPPING_PLANES
float clipDistance = clip(gl_FragCoord, u_clippingPlanes, u_clippingPlanesMatrix);
#endif
Expand Down
38 changes: 36 additions & 2 deletions Specs/Scene/GlobeSurfaceTileProviderSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ defineSuite([
'Core/Ellipsoid',
'Core/EllipsoidTerrainProvider',
'Core/GeographicProjection',
'Core/Intersect',
'Core/Rectangle',
'Core/WebMercatorProjection',
'Renderer/ContextLimits',
Expand Down Expand Up @@ -39,7 +38,6 @@ defineSuite([
Ellipsoid,
EllipsoidTerrainProvider,
GeographicProjection,
Intersect,
Rectangle,
WebMercatorProjection,
ContextLimits,
Expand Down Expand Up @@ -116,6 +114,7 @@ defineSuite([

afterEach(function() {
scene.imageryLayers.removeAll();
scene.primitives.removeAll();
});

it('conforms to QuadtreeTileProvider interface', function() {
Expand Down Expand Up @@ -939,4 +938,39 @@ defineSuite([
}).toThrowDeveloperError();
});

it('geographicLimitRectangle selectively enables rendering globe surface', function() {
expect(scene).toRender([0, 0, 0, 255]);
switchViewMode(SceneMode.COLUMBUS_VIEW, new GeographicProjection(Ellipsoid.WGS84));
var result;
return updateUntilDone(scene.globe).then(function() {
expect(scene).notToRender([0, 0, 0, 255]);
expect(scene).toRenderAndCall(function(rgba) {
result = rgba;
expect(rgba).not.toEqual([0, 0, 0, 255]);
});
scene.globe.geographicLimitRectangle = Rectangle.fromDegrees(-2, -2, -1, -1);
expect(scene).notToRender(result);
scene.camera.setView({
destination : scene.globe.geographicLimitRectangle
});
return updateUntilDone(scene.globe);
})
.then(function() {
expect(scene).toRender(result);
});
});

it('geographicLimitRectangle culls tiles outside the region', function() {
switchViewMode(SceneMode.COLUMBUS_VIEW, new GeographicProjection(Ellipsoid.WGS84));
var unculledCommandCount;
return updateUntilDone(scene.globe).then(function() {
unculledCommandCount = scene.frameState.commandList.length;
scene.globe.geographicLimitRectangle = Rectangle.fromDegrees(-2, -2, -1, -1);
return updateUntilDone(scene.globe);
})
.then(function() {
expect(unculledCommandCount).toBeGreaterThan(scene.frameState.commandList.length);
});
});

}, 'WebGL');

0 comments on commit c94c510

Please sign in to comment.