Skip to content

Commit

Permalink
Merge pull request #6987 from AnalyticalGraphicsInc/globeLimiterRecta…
Browse files Browse the repository at this point in the history
…ngle

Add geographic limit rectangle
  • Loading branch information
bagnell authored Sep 10, 2018
2 parents 5e28dfb + 6e84ef5 commit d6ad77b
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 7 deletions.
87 changes: 87 additions & 0 deletions Apps/Sandcastle/gallery/Cartographic Limit Rectangle.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<!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="Limit terrain and imagery to a cartographic Rectangle area.">
<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.0, -23.43687, 180.0, 23.43687);

viewer.scene.globe.cartographicLimitRectangle = 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({
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.cartographicLimitRectangle = Cesium.Rectangle.MAX_VALUE;
limited = false;
} else {
viewer.scene.globe.cartographicLimitRectangle = 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.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Change Log
==========

### 1.50 - 2018-10-01

##### Additions :tada:
* Added `cartographicLimitRectangle` to `Globe`. Use this to limit terrain and imagery to a specific `Rectangle` area. [#6987](https://github.com/AnalyticalGraphicsInc/cesium/pull/6987)

### 1.49 - 2018-09-04

##### Breaking Changes :mega:
Expand Down
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;
}
},
cartographicLimitRectangle : {
get : function() {
return this._surface.tileProvider.cartographicLimitRectangle;
},
set : function(value) {
this._surface.tileProvider.cartographicLimitRectangle = 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 cartographicLimitRectangleFlag = 0;
var cartographicLimitRectangleDefine = '';
if (clippedByBoundaries) {
cartographicLimitRectangleFlag = 1;
cartographicLimitRectangleDefine = '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) |
(cartographicLimitRectangleFlag << 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, cartographicLimitRectangleDefine);

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
61 changes: 59 additions & 2 deletions Source/Scene/GlobeSurfaceTileProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ define([
'../Core/Cartesian2',
'../Core/Cartesian3',
'../Core/Cartesian4',
'../Core/Cartographic',
'../Core/Color',
'../Core/ColorGeometryInstanceAttribute',
'../Core/combine',
Expand Down Expand Up @@ -50,6 +51,7 @@ define([
Cartesian2,
Cartesian3,
Cartesian4,
Cartographic,
Color,
ColorGeometryInstanceAttribute,
combine,
Expand Down Expand Up @@ -168,6 +170,12 @@ define([
* @private
*/
this._clippingPlanes = undefined;

/**
* A property specifying a {@link Rectangle} used to selectively limit terrain and imagery rendering.
* @type {Rectangle}
*/
this.cartographicLimitRectangle = Rectangle.clone(Rectangle.MAX_VALUE);
}

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

var boundingSphereScratch = new BoundingSphere();
var rectangleIntersectionScratch = new Rectangle();
var splitCartographicLimitRectangleScratch = new Rectangle();
var rectangleCenterScratch = new Cartographic();

// cartographicLimitRectangle may span the IDL, but tiles never will.
function clipRectangleAntimeridian(tileRectangle, cartographicLimitRectangle) {
if (cartographicLimitRectangle.west < cartographicLimitRectangle.east) {
return cartographicLimitRectangle;
}
var splitRectangle = Rectangle.clone(cartographicLimitRectangle, splitCartographicLimitRectangleScratch);
var tileCenter = Rectangle.center(tileRectangle, rectangleCenterScratch);
if (tileCenter.longitude > 0.0) {
splitRectangle.east = CesiumMath.PI;
} else {
splitRectangle.west = -CesiumMath.PI;
}
return splitRectangle;
}

/**
* Determines the visibility of a given tile. The tile may be fully visible, partially visible, or not
Expand Down Expand Up @@ -536,6 +562,17 @@ 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 clippedCartographicLimitRectangle = clipRectangleAntimeridian(tile.rectangle, this.cartographicLimitRectangle);
var areaLimitIntersection = Rectangle.simpleIntersection(clippedCartographicLimitRectangle, 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 +617,7 @@ define([
var modifiedModelViewScratch = new Matrix4();
var modifiedModelViewProjectionScratch = new Matrix4();
var tileRectangleScratch = new Cartesian4();
var localizedCartographicLimitRectangleScratch = new Cartesian4();
var rtcScratch = new Cartesian3();
var centerEyeScratch = new Cartesian3();
var southwestScratch = new Cartesian3();
Expand Down Expand Up @@ -921,6 +959,9 @@ define([
}
return frameState.context.defaultTexture;
},
u_cartographicLimitRectangle : function() {
return this.properties.localizedCartographicLimitRectangle;
},
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 +1010,9 @@ define([
minMaxHeight : new Cartesian2(),
scaleAndBias : new Matrix4(),
clippingPlanesEdgeColor : Color.clone(Color.WHITE),
clippingPlanesEdgeWidth : 0.0
clippingPlanesEdgeWidth : 0.0,

localizedCartographicLimitRectangle : new Cartesian4()
}
};

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

// Convert tile limiter rectangle from cartographic to texture space using the tileRectangle.
var localizedCartographicLimitRectangle = localizedCartographicLimitRectangleScratch;
var cartographicLimitRectangle = clipRectangleAntimeridian(tile.rectangle, tileProvider.cartographicLimitRectangle);

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

Cartesian4.clone(localizedCartographicLimitRectangle, uniformMapProperties.localizedCartographicLimitRectangle);

// 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 +1414,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_cartographicLimitRectangle;
#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_cartographicLimitRectangle.x || u_cartographicLimitRectangle.z < v_textureCoordinates.x ||
v_textureCoordinates.y < u_cartographicLimitRectangle.y || u_cartographicLimitRectangle.w < v_textureCoordinates.y)
{
discard;
}
#endif

#ifdef ENABLE_CLIPPING_PLANES
float clipDistance = clip(gl_FragCoord, u_clippingPlanes, u_clippingPlanesMatrix);
#endif
Expand Down
Loading

0 comments on commit d6ad77b

Please sign in to comment.