-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add geographic limit rectangle #6987
Changes from 4 commits
c94c510
569094f
9fe6b02
6cb3753
5bae8b3
6e84ef5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be called "cartographicLimitRectangle" given Cesium's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's go with |
||
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> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 = ''; | ||
|
||
|
@@ -84,6 +84,13 @@ define([ | |
vertexLogDepthDefine = 'DISABLE_GL_POSITION_LOG_DEPTH'; | ||
} | ||
|
||
var geographicLimitRectangleFlag = 0; | ||
var geographicLimitRectangleDefine = ''; | ||
if (clippedByBoundaries) {//} && frameState.mode !== SceneMode.SCENE3D) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove commented out code. |
||
geographicLimitRectangleFlag = 1; | ||
geographicLimitRectangleDefine = 'TILE_LIMIT_RECTANGLE'; | ||
} | ||
|
||
var sceneMode = frameState.mode; | ||
var flags = sceneMode | | ||
(applyBrightness << 2) | | ||
|
@@ -101,7 +108,8 @@ define([ | |
(quantization << 14) | | ||
(applySplit << 15) | | ||
(enableClippingPlanes << 16) | | ||
(vertexLogDepth << 17); | ||
(vertexLogDepth << 17) | | ||
(geographicLimitRectangleFlag << 18); | ||
|
||
var currentClippingShaderState = 0; | ||
if (defined(clippingPlanes)) { | ||
|
@@ -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'); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ define([ | |
'../Core/Cartesian2', | ||
'../Core/Cartesian3', | ||
'../Core/Cartesian4', | ||
'../Core/Cartographic', | ||
'../Core/Color', | ||
'../Core/ColorGeometryInstanceAttribute', | ||
'../Core/combine', | ||
|
@@ -50,6 +51,7 @@ define([ | |
Cartesian2, | ||
Cartesian3, | ||
Cartesian4, | ||
Cartographic, | ||
Color, | ||
ColorGeometryInstanceAttribute, | ||
combine, | ||
|
@@ -168,6 +170,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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would remove the line about custom projections since this would likely get merged before support is added for them and that is not the only use case. Prevents tiles from loading and also clips tiles on the boundary? |
||
* @type {Rectangle} | ||
*/ | ||
this.geographicLimitRectangle = Rectangle.clone(Rectangle.MAX_VALUE); | ||
} | ||
|
||
defineProperties(GlobeSurfaceTileProvider.prototype, { | ||
|
@@ -509,6 +518,24 @@ define([ | |
}; | ||
|
||
var boundingSphereScratch = new BoundingSphere(); | ||
var rectangleIntersectionScratch = new Rectangle(); | ||
var splitGeographicLimitRectangleScratch = new Rectangle(); | ||
var rectangleCenterScratch = new Cartographic(); | ||
|
||
// geographicLimitRectangle may span the IDL, but tiles never will. | ||
function clipRectangleAntimeridian(tileRectangle, geographicLimitRectangle) { | ||
if (geographicLimitRectangle.west < geographicLimitRectangle.east) { | ||
return geographicLimitRectangle; | ||
} | ||
var splitRectangle = Rectangle.clone(geographicLimitRectangle, splitGeographicLimitRectangleScratch); | ||
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 | ||
|
@@ -536,6 +563,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 clippedGeographicLimitRectangle = clipRectangleAntimeridian(tile.rectangle, this.geographicLimitRectangle); | ||
var areaLimitIntersection = Rectangle.simpleIntersection(clippedGeographicLimitRectangle, 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); | ||
|
@@ -580,6 +618,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(); | ||
|
@@ -921,6 +960,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; | ||
|
@@ -969,7 +1011,9 @@ define([ | |
minMaxHeight : new Cartesian2(), | ||
scaleAndBias : new Matrix4(), | ||
clippingPlanesEdgeColor : Color.clone(Color.WHITE), | ||
clippingPlanesEdgeWidth : 0.0 | ||
clippingPlanesEdgeWidth : 0.0, | ||
|
||
localizedGeographicLimitRectangle : new Cartesian4() | ||
} | ||
}; | ||
|
||
|
@@ -1255,6 +1299,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 = clipRectangleAntimeridian(tile.rectangle, 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; | ||
|
||
|
@@ -1357,7 +1415,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; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
|
@@ -155,6 +159,15 @@ vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat | |
|
||
void main() | ||
{ | ||
|
||
#ifdef TILE_LIMIT_RECTANGLE | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a way to add a fast reject case to the vertex shader so that if the entire tile is outside the region, the vertex is moved beyond the camera like we do for billboards, etc.? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It shouldn't be necessary, the limiter is tied into tileset visibility computation. Tiles completely outside bounds won't get drawn and tiles completely inside bounds won't receive shader modification. |
||
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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Append
.0
when the intention is floating point.Throughout.