From 0e80848be8444ec9dd952084fc9ccbb78e8ff489 Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Mon, 27 Oct 2014 17:34:40 -0400 Subject: [PATCH 01/10] Added support for loading a watermask for Quantized-Mesh terrain tiles. --- CHANGES.md | 1 + Source/Core/CesiumTerrainProvider.js | 89 +++++--- Source/Core/QuantizedMeshTerrainData.js | 1 + Specs/Core/CesiumTerrainProviderSpec.js | 200 +++++------------- .../CesiumTerrainTileJson/WaterMask.tile.json | 31 +++ .../tile.vertexnormals.watermask.terrain | Bin 0 -> 69718 bytes .../tile.watermask.terrain | Bin 0 -> 69293 bytes 7 files changed, 150 insertions(+), 172 deletions(-) create mode 100644 Specs/Data/CesiumTerrainTileJson/WaterMask.tile.json create mode 100644 Specs/Data/CesiumTerrainTileJson/tile.vertexnormals.watermask.terrain create mode 100644 Specs/Data/CesiumTerrainTileJson/tile.watermask.terrain diff --git a/CHANGES.md b/CHANGES.md index 42faf0fb92b..1703feea6f0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ Change Log * Fixed a bug that caused non-base imagery layers with a limited `rectangle` to be stretched to the edges of imagery tiles. [#416](https://github.com/AnalyticalGraphicsInc/cesium/issues/416) * Fixed rendering polylines with duplicate positions. [#898](https://github.com/AnalyticalGraphicsInc/cesium/issues/898) * Fixed a bug in `Globe.pick` that caused it to return incorrect results when using terrain data with vertex normals. The bug manifested itself as strange behavior when navigating around the surface with the mouse as well as incorrect results when using `Camera.viewRectangle`. +* Added support for loading a watermask for Quantized-Mesh terrain tiles. * Fixed a bug in `sampleTerrain` that could cause it to produce undefined heights when sampling for a position very near the edge of a tile. * `ReferenceProperty` instances now retain their last value if the entity being referenced is removed from the target collection. The reference will be automatically reattached if the target is reintroduced. * Upgraded topojson from 1.6.8 to 1.6.18. diff --git a/Source/Core/CesiumTerrainProvider.js b/Source/Core/CesiumTerrainProvider.js index 2a2ef7111d8..ca4330e3eae 100644 --- a/Source/Core/CesiumTerrainProvider.js +++ b/Source/Core/CesiumTerrainProvider.js @@ -121,6 +121,13 @@ define([ * @private */ this._requestVertexNormals = defaultValue(options.requestVertexNormals, false); + /** + * Boolean flag that indicates if the client should request tile watermasks from the server. + * @type {Boolean} + * @default false + * @private + */ + this._requestWaterMask = defaultValue(options.requestWaterMask, false); this._errorEvent = new Event(); @@ -165,9 +172,8 @@ define([ isBigEndian : false }; that._hasWaterMask = true; - } else if (data.format.indexOf('quantized-mesh-1.') === 0) { - that._hasWaterMask = false; - } else { + that._requestWaterMask = true; + } else if (data.format.indexOf('quantized-mesh-1.') !== 0) { message = 'The tile format "' + data.format + '" is invalid or not supported.'; metadataError = TileProviderError.handleError(metadataError, that, that._errorEvent, message, undefined, undefined, undefined, requestMetadata); return; @@ -189,6 +195,9 @@ define([ if (defined(data.extensions) && data.extensions.indexOf('vertexnormals') !== -1) { that._hasVertexNormals = true; } + if (defined(data.extensions) && data.extensions.indexOf('watermask') !== -1) { + that._hasWaterMask = true; + } that._ready = true; } @@ -236,26 +245,30 @@ define([ * @constant * @default 1 */ - OCT_VERTEX_NORMALS: 1 - }; - - var requestHeadersVertexNormals = { - // prefer quantized-mesh media-type - // only request vertex normals if Lighting is enabled on the CesiumTerrainProvider - Accept : 'application/vnd.quantized-mesh;extensions=vertexnormals,application/octet-stream;q=0.9,*/*;q=0.01' - }; - - function loadTileVertexNormals(url) { - return loadArrayBuffer(url, requestHeadersVertexNormals); - } - - var requestHeadersDefault = { - // prefer quantized-mesh media-type - Accept : 'application/vnd.quantized-mesh,application/octet-stream;q=0.9,*/*;q=0.01' + OCT_VERTEX_NORMALS: 1, + /** + * A watermask is included as an extension to the tile mesh + * + * @type {Number} + * @constant + * @default 2 + */ + WATER_MASK: 2 }; - function loadTile(url) { - return loadArrayBuffer(url, requestHeadersDefault); + function getRequestHeader(extensionsList) { + if (!defined(extensionsList) || extensionsList.length === 0) { + return { + // prefer quantized-mesh media-type + Accept : 'application/vnd.quantized-mesh,application/octet-stream;q=0.9,*/*;q=0.01' + }; + } else { + var extensions = extensionsList.join(':'); + return { + // prefer quantized-mesh media-type + Accept : 'application/vnd.quantized-mesh;extensions=' + extensions + ',application/octet-stream;q=0.9,*/*;q=0.01' + }; + } } function createHeightmapTerrainData(provider, buffer, level, x, y, tmsY) { @@ -377,6 +390,7 @@ define([ pos += northVertexCount * bytesPerIndex; var encodedNormalBuffer; + var waterMaskBuffer; while (pos < view.byteLength) { var extensionId = view.getUint8(pos); pos += Uint8Array.BYTES_PER_ELEMENT; @@ -385,6 +399,8 @@ define([ if (extensionId === QuantizedMeshExtensionIds.OCT_VERTEX_NORMALS) { encodedNormalBuffer = new Uint8Array(buffer, pos, vertexCount * 2); + } else if (extensionId === QuantizedMeshExtensionIds.WATER_MASK) { + waterMaskBuffer = new Uint8Array(buffer, pos, extensionLength); } pos += extensionLength; } @@ -408,7 +424,8 @@ define([ southSkirtHeight : skirtHeight, eastSkirtHeight : skirtHeight, northSkirtHeight : skirtHeight, - childTileMask: getChildMaskForTile(provider, level, x, tmsY) + childTileMask: getChildMaskForTile(provider, level, x, tmsY), + waterMask: waterMaskBuffer }); } @@ -456,10 +473,16 @@ define([ var promise; - var tileLoader = loadTile; + var extensionList = []; if (this._requestVertexNormals && this._hasVertexNormals) { - tileLoader = loadTileVertexNormals; + extensionList.push("vertexnormals"); + } + if (this._requestWaterMask && this._hasWaterMask) { + extensionList.push("watermask"); } + var tileLoader = function(tileUrl) { + return loadArrayBuffer(tileUrl, getRequestHeader(extensionList)); + }; throttleRequests = defaultValue(throttleRequests, true); if (throttleRequests) { @@ -559,7 +582,7 @@ define([ } //>>includeEnd('debug'); - return this._hasWaterMask; + return this._hasWaterMask && this._requestWaterMask; } }, @@ -597,6 +620,22 @@ define([ get : function() { return this._requestVertexNormals; } + }, + + /** + * Boolean flag that indicates if the client should request a watermask from the server. + * Watermask data is appended to the standard tile mesh data only if the client requests the watermask and + * if the server provides a watermask. + * + * This property is read only. To change this value, a new CesiumTerrainProvider must be constructed that requests + * a watermask to ensure that all existing tiles are requested that includes/excludes watermask extension data. + * @memberof CesiumTerrainProvider.prototype + * @type {Boolean} + */ + requestWaterMask : { + get : function() { + return this._requestWaterMask; + } } }); diff --git a/Source/Core/QuantizedMeshTerrainData.js b/Source/Core/QuantizedMeshTerrainData.js index 7cd473d99d7..6b302587017 100644 --- a/Source/Core/QuantizedMeshTerrainData.js +++ b/Source/Core/QuantizedMeshTerrainData.js @@ -69,6 +69,7 @@ define([ * * @param {Boolean} [options.createdByUpsampling=false] True if this instance was created by upsampling another instance; * otherwise, false. + * @param {Uint8Array} options.waterMask The buffer containing the watermask. * * @see TerrainData * @see HeightmapTerrainData diff --git a/Specs/Core/CesiumTerrainProviderSpec.js b/Specs/Core/CesiumTerrainProviderSpec.js index 852ea919d8e..0524a03b85d 100644 --- a/Specs/Core/CesiumTerrainProviderSpec.js +++ b/Specs/Core/CesiumTerrainProviderSpec.js @@ -59,10 +59,34 @@ defineSuite([ return returnTileJson('Data/CesiumTerrainTileJson/VertexNormals.tile.json'); } + function returnWaterMaskTileJson() { + return returnTileJson('Data/CesiumTerrainTileJson/WaterMask.tile.json'); + } + function returnPartialAvailabilityTileJson() { return returnTileJson('Data/CesiumTerrainTileJson/PartialAvailability.tile.json'); } + function waitForTile(level, x, y, requestNormals, requestWaterMask, f) { + var terrainProvider = new CesiumTerrainProvider({ + url : 'made/up/url', + requestVertexNormals : requestNormals, + requestWaterMask: requestWaterMask + }); + + waitsFor(function() { + return terrainProvider.ready; + }); + + runs(function() { + var promise = terrainProvider.requestTileGeometry(0, 0, 0); + + when(promise, f, function(error) { + expect('requestTileGeometry').toBe('returning a tile.'); // test failure + }); + }); + } + it('conforms to TerrainProvider interface', function() { expect(CesiumTerrainProvider).toConformToInterface(TerrainProvider); }); @@ -387,29 +411,7 @@ defineSuite([ returnHeightmapTileJson(); - var terrainProvider = new CesiumTerrainProvider({ - url : baseUrl - }); - - waitsFor(function() { - return terrainProvider.ready; - }); - - var loadedData; - - runs(function() { - var promise = terrainProvider.requestTileGeometry(0, 0, 0); - - when(promise, function(terrainData) { - loadedData = terrainData; - }); - }); - - waitsFor(function() { - return defined(loadedData); - }, 'request to complete'); - - runs(function() { + waitForTile(0, 0, 0, false, false, function(loadedData) { expect(loadedData).toBeInstanceOf(HeightmapTerrainData); }); }); @@ -423,29 +425,7 @@ defineSuite([ returnQuantizedMeshTileJson(); - var terrainProvider = new CesiumTerrainProvider({ - url : baseUrl - }); - - waitsFor(function() { - return terrainProvider.ready; - }); - - var loadedData; - - runs(function() { - var promise = terrainProvider.requestTileGeometry(0, 0, 0); - - when(promise, function(terrainData) { - loadedData = terrainData; - }); - }); - - waitsFor(function() { - return defined(loadedData); - }, 'request to complete'); - - runs(function() { + waitForTile(0, 0, 0, false, false, function(loadedData) { expect(loadedData).toBeInstanceOf(QuantizedMeshTerrainData); }); }); @@ -459,29 +439,7 @@ defineSuite([ returnQuantizedMeshTileJson(); - var terrainProvider = new CesiumTerrainProvider({ - url : baseUrl - }); - - waitsFor(function() { - return terrainProvider.ready; - }); - - var loadedData; - - runs(function() { - var promise = terrainProvider.requestTileGeometry(0, 0, 0); - - when(promise, function(terrainData) { - loadedData = terrainData; - }); - }); - - waitsFor(function() { - return defined(loadedData); - }, 'request to complete'); - - runs(function() { + waitForTile(0, 0, 0, false, false, function(loadedData) { expect(loadedData).toBeInstanceOf(QuantizedMeshTerrainData); expect(loadedData._indices.BYTES_PER_ELEMENT).toBe(4); }); @@ -496,32 +454,40 @@ defineSuite([ returnVertexNormalTileJson(); - var terrainProvider = new CesiumTerrainProvider({ - url : baseUrl, - requestVertexNormals : true + waitForTile(0, 0, 0, true, false, function(loadedData) { + expect(loadedData).toBeInstanceOf(QuantizedMeshTerrainData); + expect(loadedData._encodedNormals).toBeDefined(); }); + }); - waitsFor(function() { - return terrainProvider.ready; - }); + it('provides QuantizedMeshTerrainData with WaterMask', function() { + var baseUrl = 'made/up/url'; - var loadedData; + loadWithXhr.load = function(url, responseType, method, data, headers, deferred, overrideMimeType) { + loadWithXhr.defaultLoad('Data/CesiumTerrainTileJson/tile.watermask.terrain', responseType, method, data, headers, deferred); + }; - runs(function() { - var promise = terrainProvider.requestTileGeometry(0, 0, 0); + returnWaterMaskTileJson(); - when(promise, function(terrainData) { - loadedData = terrainData; - }); + waitForTile(0, 0, 0, false, true, function(loadedData) { + expect(loadedData).toBeInstanceOf(QuantizedMeshTerrainData); + expect(loadedData._waterMask).toBeDefined(); }); + }); - waitsFor(function() { - return defined(loadedData); - }, 'request to complete'); + it('provides QuantizedMeshTerrainData with VertexNormals and WaterMask', function() { + var baseUrl = 'made/up/url'; - runs(function() { + loadWithXhr.load = function(url, responseType, method, data, headers, deferred, overrideMimeType) { + loadWithXhr.defaultLoad('Data/CesiumTerrainTileJson/tile.vertexnormals.watermask.terrain', responseType, method, data, headers, deferred); + }; + + returnWaterMaskTileJson(); + + waitForTile(0, 0, 0, false, true, function(loadedData) { expect(loadedData).toBeInstanceOf(QuantizedMeshTerrainData); expect(loadedData._encodedNormals).toBeDefined(); + expect(loadedData._waterMask).toBeDefined(); }); }); @@ -534,30 +500,7 @@ defineSuite([ returnVertexNormalTileJson(); - var terrainProvider = new CesiumTerrainProvider({ - url : baseUrl, - requestVertexNormals : true - }); - - waitsFor(function() { - return terrainProvider.ready; - }); - - var loadedData; - - runs(function() { - var promise = terrainProvider.requestTileGeometry(0, 0, 0); - - when(promise, function(terrainData) { - loadedData = terrainData; - }); - }); - - waitsFor(function() { - return defined(loadedData); - }, 'request to complete'); - - runs(function() { + waitForTile(0, 0, 0, true, false, function(loadedData) { expect(loadedData).toBeInstanceOf(QuantizedMeshTerrainData); expect(loadedData._encodedNormals).toBeDefined(); }); @@ -572,30 +515,7 @@ defineSuite([ returnVertexNormalTileJson(); - var terrainProvider = new CesiumTerrainProvider({ - url : baseUrl, - requestVertexNormals : true - }); - - waitsFor(function() { - return terrainProvider.ready; - }); - - var loadedData; - - runs(function() { - var promise = terrainProvider.requestTileGeometry(0, 0, 0); - - when(promise, function(terrainData) { - loadedData = terrainData; - }); - }); - - waitsFor(function() { - return defined(loadedData); - }, 'request to complete'); - - runs(function() { + waitForTile(0, 0, 0, true, false, function(loadedData) { expect(loadedData).toBeInstanceOf(QuantizedMeshTerrainData); }); }); @@ -655,20 +575,6 @@ defineSuite([ return terrainProvider.ready; }); - var loadedData; - - runs(function() { - var promise = terrainProvider.requestTileGeometry(0, 0, 0); - - when(promise, function(terrainData) { - loadedData = terrainData; - }); - }); - - waitsFor(function() { - return defined(loadedData); - }, 'request to complete'); - runs(function() { expect(terrainProvider.getTileDataAvailable(0, 0, 0)).toBe(true); expect(terrainProvider.getTileDataAvailable(0, 0, 2)).toBe(false); diff --git a/Specs/Data/CesiumTerrainTileJson/WaterMask.tile.json b/Specs/Data/CesiumTerrainTileJson/WaterMask.tile.json new file mode 100644 index 00000000000..c4d01b2352f --- /dev/null +++ b/Specs/Data/CesiumTerrainTileJson/WaterMask.tile.json @@ -0,0 +1,31 @@ +{ + "tilejson": "2.1.0", + "format" : "quantized-mesh-1.0", + "version" : "1.0.0", + "scheme" : "tms", + "tiles" : [ + "{z}/{x}/{y}.terrain?v={version}" + ], + "extensions" : [ + "vertexnormals", + "watermask" + ], + "available" : [ + [ + { + "startX" : 0, + "startY" : 0, + "endX" : 1, + "endY" : 0 + } + ], + [ + { + "startX" : 0, + "startY" : 0, + "endX" : 3, + "endY" : 1 + } + ] + ] +} diff --git a/Specs/Data/CesiumTerrainTileJson/tile.vertexnormals.watermask.terrain b/Specs/Data/CesiumTerrainTileJson/tile.vertexnormals.watermask.terrain new file mode 100644 index 0000000000000000000000000000000000000000..9e634f80cdaec72d7c56d4dfafa101229e03f3d3 GIT binary patch literal 69718 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%0A)b%YZ`nmGq(EZ15q-LZ&);hOl-95ZV z{2053@hFlvylE8Qm)@JZXyK~8cmb7sPk1uy+(hB*LDw`D4=5B~szg+&vgImPuOHXE z=j2KMi!1Lq1u-QmZ!39JDPPb^yu+g^)NR%{FmJJ+p*^#}GYdSkz%vUxv%oV8JhQ+v Y3p}&HGYdSkz%vUxv%oV8JQ)`FKN8O#-~a#s literal 0 HcmV?d00001 From 08254e4cd307eb3226f9ccaa94380828e5f481e5 Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Mon, 27 Oct 2014 23:08:42 -0400 Subject: [PATCH 02/10] Updated documentation to note that waterMask and encodedNormals were optional. --- Source/Core/QuantizedMeshTerrainData.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/QuantizedMeshTerrainData.js b/Source/Core/QuantizedMeshTerrainData.js index 6b302587017..b67b155229e 100644 --- a/Source/Core/QuantizedMeshTerrainData.js +++ b/Source/Core/QuantizedMeshTerrainData.js @@ -41,7 +41,6 @@ define([ * @param {Uint16Array} options.quantizedVertices The buffer containing the quantized mesh. * @param {Uint16Array|Uint32Array} options.indices The indices specifying how the quantized vertices are linked * together into triangles. Each three indices specifies one triangle. - * @param {Uint8Array} options.encodedNormals The buffer containing per vertex normals, encoded using 'oct' encoding * @param {Number} options.minimumHeight The minimum terrain height within the tile, in meters above the ellipsoid. * @param {Number} options.maximumHeight The maximum terrain height within the tile, in meters above the ellipsoid. * @param {BoundingSphere} options.boundingSphere A sphere bounding all of the vertices in the mesh. @@ -69,7 +68,8 @@ define([ * * @param {Boolean} [options.createdByUpsampling=false] True if this instance was created by upsampling another instance; * otherwise, false. - * @param {Uint8Array} options.waterMask The buffer containing the watermask. + * @param {Uint8Array} [options.encodedNormals] The buffer containing per vertex normals, encoded using 'oct' encoding + * @param {Uint8Array} [options.waterMask] The buffer containing the watermask. * * @see TerrainData * @see HeightmapTerrainData From 0330bc81a6dbafae1ba4c3f7c88130f15019998b Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Tue, 28 Oct 2014 13:49:51 -0400 Subject: [PATCH 03/10] Minor updates from PR comments. --- CHANGES.md | 1 - Source/Core/CesiumTerrainProvider.js | 6 ------ 2 files changed, 7 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 1703feea6f0..42faf0fb92b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,7 +9,6 @@ Change Log * Fixed a bug that caused non-base imagery layers with a limited `rectangle` to be stretched to the edges of imagery tiles. [#416](https://github.com/AnalyticalGraphicsInc/cesium/issues/416) * Fixed rendering polylines with duplicate positions. [#898](https://github.com/AnalyticalGraphicsInc/cesium/issues/898) * Fixed a bug in `Globe.pick` that caused it to return incorrect results when using terrain data with vertex normals. The bug manifested itself as strange behavior when navigating around the surface with the mouse as well as incorrect results when using `Camera.viewRectangle`. -* Added support for loading a watermask for Quantized-Mesh terrain tiles. * Fixed a bug in `sampleTerrain` that could cause it to produce undefined heights when sampling for a position very near the edge of a tile. * `ReferenceProperty` instances now retain their last value if the entity being referenced is removed from the target collection. The reference will be automatically reattached if the target is reintroduced. * Upgraded topojson from 1.6.8 to 1.6.18. diff --git a/Source/Core/CesiumTerrainProvider.js b/Source/Core/CesiumTerrainProvider.js index ca4330e3eae..99c74c7c83a 100644 --- a/Source/Core/CesiumTerrainProvider.js +++ b/Source/Core/CesiumTerrainProvider.js @@ -610,9 +610,6 @@ define([ * Boolean flag that indicates if the client should request vertex normals from the server. * Vertex normals data is appended to the standard tile mesh data only if the client requests the vertex normals and * if the server provides vertex normals. - * - * This property is read only. To change this value, a new CesiumTerrainProvider must be constructed that requests - * vertex normals to ensure that all existing tiles are requested that includes/excludes vertex normal extension data. * @memberof CesiumTerrainProvider.prototype * @type {Boolean} */ @@ -626,9 +623,6 @@ define([ * Boolean flag that indicates if the client should request a watermask from the server. * Watermask data is appended to the standard tile mesh data only if the client requests the watermask and * if the server provides a watermask. - * - * This property is read only. To change this value, a new CesiumTerrainProvider must be constructed that requests - * a watermask to ensure that all existing tiles are requested that includes/excludes watermask extension data. * @memberof CesiumTerrainProvider.prototype * @type {Boolean} */ From 216e7346c0f0add17012893ad7b0a76265fa2d11 Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Thu, 30 Oct 2014 15:17:02 -0400 Subject: [PATCH 04/10] Applying mask value to waterMask diffuseIntensity. --- Source/Core/CesiumTerrainProvider.js | 1 + Source/Shaders/GlobeFS.glsl | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/Core/CesiumTerrainProvider.js b/Source/Core/CesiumTerrainProvider.js index 99c74c7c83a..81c0db09eab 100644 --- a/Source/Core/CesiumTerrainProvider.js +++ b/Source/Core/CesiumTerrainProvider.js @@ -55,6 +55,7 @@ define([ * @param {String} options.url The URL of the Cesium terrain server. * @param {Proxy} [options.proxy] A proxy to use for requests. This object is expected to have a getURL function which returns the proxied URL, if needed. * @param {Boolean} [options.requestVertexNormals=false] Flag that indicates if the client should request additional lighting information from the server, in the form of per vertex normals if available. + * @param {Boolean} [options.requestWaterMask=false] Flag that indicates if the client should request per tile water masks from the server, if available. * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas. * * @see TerrainProvider diff --git a/Source/Shaders/GlobeFS.glsl b/Source/Shaders/GlobeFS.glsl index d886fc9ac83..8a423970fed 100644 --- a/Source/Shaders/GlobeFS.glsl +++ b/Source/Shaders/GlobeFS.glsl @@ -202,7 +202,7 @@ const float oceanFrequencyHighAltitude = 125000.0; const float oceanAnimationSpeedHighAltitude = 0.008; const float oceanOneOverAmplitudeHighAltitude = 1.0 / 2.0; -vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat3 enuToEye, vec4 imageryColor, float specularMapValue) +vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat3 enuToEye, vec4 imageryColor, float maskValue) { vec3 positionToEyeEC = -positionEyeCoordinates; float positionToEyeECLength = length(positionToEyeEC); @@ -244,7 +244,7 @@ vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat const vec3 waveHighlightColor = vec3(0.3, 0.45, 0.6); // Use diffuse light to highlight the waves - float diffuseIntensity = czm_getLambertDiffuse(czm_sunDirectionEC, normalEC); + float diffuseIntensity = czm_getLambertDiffuse(czm_sunDirectionEC, normalEC) * maskValue; vec3 diffuseHighlight = waveHighlightColor * diffuseIntensity; #ifdef SHOW_OCEAN_WAVES @@ -258,7 +258,7 @@ vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat // Add specular highlights in 3D, and in all modes when zoomed in. float specularIntensity = czm_getSpecular(czm_sunDirectionEC, normalizedpositionToEyeEC, normalEC, 10.0) + 0.25 * czm_getSpecular(czm_moonDirectionEC, normalizedpositionToEyeEC, normalEC, 10.0); - float surfaceReflectance = mix(0.0, mix(u_zoomedOutOceanSpecularIntensity, oceanSpecularIntensity, waveIntensity), specularMapValue); + float surfaceReflectance = mix(0.0, mix(u_zoomedOutOceanSpecularIntensity, oceanSpecularIntensity, waveIntensity), maskValue); float specular = specularIntensity * surfaceReflectance; return vec4(imageryColor.rgb + diffuseHighlight + nonDiffuseHighlight + specular, imageryColor.a); From b2bf34f0234a324ed6ebfb6a87f91e8b73e1c9d5 Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Mon, 1 Dec 2014 17:38:16 -0500 Subject: [PATCH 05/10] Fixed and updated unit tests. New terrain files needed with correct endian extensionLength. --- Specs/Core/CesiumTerrainProviderSpec.js | 58 ++---------------- .../CesiumTerrainTileJson/WaterMask.tile.json | 2 +- .../tile.octvertexnormals.watermask.terrain | Bin 0 -> 69878 bytes .../tile.vertexnormals.watermask.terrain | Bin 69718 -> 0 bytes .../tile.watermask.terrain | Bin 69293 -> 69437 bytes 5 files changed, 7 insertions(+), 53 deletions(-) create mode 100644 Specs/Data/CesiumTerrainTileJson/tile.octvertexnormals.watermask.terrain delete mode 100644 Specs/Data/CesiumTerrainTileJson/tile.vertexnormals.watermask.terrain diff --git a/Specs/Core/CesiumTerrainProviderSpec.js b/Specs/Core/CesiumTerrainProviderSpec.js index fd78bfb428b..b29b1a7217b 100644 --- a/Specs/Core/CesiumTerrainProviderSpec.js +++ b/Specs/Core/CesiumTerrainProviderSpec.js @@ -83,7 +83,7 @@ defineSuite([ }); runs(function() { - var promise = terrainProvider.requestTileGeometry(0, 0, 0); + var promise = terrainProvider.requestTileGeometry(level, x, y); when(promise, f, function(error) { expect('requestTileGeometry').toBe('returning a tile.'); // test failure @@ -483,12 +483,12 @@ defineSuite([ var baseUrl = 'made/up/url'; loadWithXhr.load = function(url, responseType, method, data, headers, deferred, overrideMimeType) { - loadWithXhr.defaultLoad('Data/CesiumTerrainTileJson/tile.vertexnormals.watermask.terrain', responseType, method, data, headers, deferred); + loadWithXhr.defaultLoad('Data/CesiumTerrainTileJson/tile.octvertexnormals.watermask.terrain', responseType, method, data, headers, deferred); }; returnWaterMaskTileJson(); - waitForTile(0, 0, 0, false, true, function(loadedData) { + waitForTile(0, 0, 0, true, true, function(loadedData) { expect(loadedData).toBeInstanceOf(QuantizedMeshTerrainData); expect(loadedData._encodedNormals).toBeDefined(); expect(loadedData._waterMask).toBeDefined(); @@ -504,30 +504,7 @@ defineSuite([ returnOctVertexNormalTileJson(); - var terrainProvider = new CesiumTerrainProvider({ - url : baseUrl, - requestVertexNormals : true - }); - - waitsFor(function() { - return terrainProvider.ready; - }); - - var loadedData; - - runs(function() { - var promise = terrainProvider.requestTileGeometry(0, 0, 0); - - when(promise, function(terrainData) { - loadedData = terrainData; - }); - }); - - waitsFor(function() { - return defined(loadedData); - }, 'request to complete'); - - runs(function() { + waitForTile(0, 0, 0, true, false, function(loadedData) { expect(loadedData).toBeInstanceOf(QuantizedMeshTerrainData); expect(loadedData._encodedNormals).toBeDefined(); }); @@ -557,30 +534,7 @@ defineSuite([ returnOctVertexNormalTileJson(); - var terrainProvider = new CesiumTerrainProvider({ - url : baseUrl, - requestVertexNormals : true - }); - - waitsFor(function() { - return terrainProvider.ready; - }); - - var loadedData; - - runs(function() { - var promise = terrainProvider.requestTileGeometry(0, 0, 0); - - when(promise, function(terrainData) { - loadedData = terrainData; - }); - }); - - waitsFor(function() { - return defined(loadedData); - }, 'request to complete'); - - runs(function() { + waitForTile(0, 0, 0, true, false, function(loadedData) { expect(loadedData).toBeInstanceOf(QuantizedMeshTerrainData); expect(loadedData._encodedNormals).toBeDefined(); }); @@ -595,7 +549,7 @@ defineSuite([ returnOctVertexNormalTileJson(); - waitForTile(0, 0, 0, true, false, function(loadedData) { + waitForTile(0, 0, 0, false, false, function(loadedData) { expect(loadedData).toBeInstanceOf(QuantizedMeshTerrainData); }); }); diff --git a/Specs/Data/CesiumTerrainTileJson/WaterMask.tile.json b/Specs/Data/CesiumTerrainTileJson/WaterMask.tile.json index c4d01b2352f..aecfa3604c1 100644 --- a/Specs/Data/CesiumTerrainTileJson/WaterMask.tile.json +++ b/Specs/Data/CesiumTerrainTileJson/WaterMask.tile.json @@ -7,7 +7,7 @@ "{z}/{x}/{y}.terrain?v={version}" ], "extensions" : [ - "vertexnormals", + "octvertexnormals", "watermask" ], "available" : [ diff --git a/Specs/Data/CesiumTerrainTileJson/tile.octvertexnormals.watermask.terrain b/Specs/Data/CesiumTerrainTileJson/tile.octvertexnormals.watermask.terrain new file mode 100644 index 0000000000000000000000000000000000000000..3433ee2202f479660ae9c0360e402a255578efab GIT binary patch literal 69878 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 AP5=M^ literal 0 HcmV?d00001 diff --git a/Specs/Data/CesiumTerrainTileJson/tile.vertexnormals.watermask.terrain b/Specs/Data/CesiumTerrainTileJson/tile.vertexnormals.watermask.terrain deleted file mode 100644 index 9e634f80cdaec72d7c56d4dfafa101229e03f3d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69718 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%0A)b%YZ`nmGq(EZ15q-LZ&);hOl-95ZV z{2053@hFlvylE8Qm)@JZXyK~8cmb7sPk1uy+(hB*LDw`D4=5B~szg+&vgImPuOHXE z=j2KMi!1Lq1u-QmZ!39JDPPb^yu+g^)NR%{FmJJ+p*^#}GYdSkz%vUxv%oV8JhQ+v Y3p}&HGYdSkz%vUxv%oV8JQ)`FKN8O#-~a#s From 0adf8f5130e261a662ec67db033d4aa112a56f94 Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Mon, 19 Jan 2015 17:30:40 -0500 Subject: [PATCH 06/10] Shader fixes for rendering terrain with both watermask and vertex lighting. --- Source/Shaders/GlobeFS.glsl | 5 +---- Source/Shaders/GlobeVS.glsl | 10 +++++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Source/Shaders/GlobeFS.glsl b/Source/Shaders/GlobeFS.glsl index 8a423970fed..2de37e752e1 100644 --- a/Source/Shaders/GlobeFS.glsl +++ b/Source/Shaders/GlobeFS.glsl @@ -134,9 +134,6 @@ void main() #if defined(SHOW_REFLECTIVE_OCEAN) || defined(ENABLE_DAYNIGHT_SHADING) vec3 normalMC = normalize(czm_geodeticSurfaceNormal(v_positionMC, vec3(0.0), vec3(1.0))); // normalized surface normal in model coordinates vec3 normalEC = normalize(czm_normal3D * normalMC); // normalized surface normal in eye coordiantes -#elif defined(ENABLE_VERTEX_LIGHTING) - vec3 normalMC = normalize(v_normalMC); // normalized surface normal in model coordinates - vec3 normalEC = normalize(v_normalEC); // normalized surface normal in eye coordiantes #endif #ifdef SHOW_REFLECTIVE_OCEAN @@ -160,7 +157,7 @@ void main() #endif #ifdef ENABLE_VERTEX_LIGHTING - float diffuseIntensity = clamp(czm_getLambertDiffuse(czm_sunDirectionEC, normalEC) * 0.9 + 0.3, 0.0, 1.0); + float diffuseIntensity = clamp(czm_getLambertDiffuse(czm_sunDirectionEC, normalize(v_normalEC)) * 0.9 + 0.3, 0.0, 1.0); gl_FragColor = vec4(color.rgb * diffuseIntensity, color.a); #elif defined(ENABLE_DAYNIGHT_SHADING) float diffuseIntensity = clamp(czm_getLambertDiffuse(czm_sunDirectionEC, normalEC) * 5.0 + 0.3, 0.0, 1.0); diff --git a/Source/Shaders/GlobeVS.glsl b/Source/Shaders/GlobeVS.glsl index c41856fa4c8..47a65adacec 100644 --- a/Source/Shaders/GlobeVS.glsl +++ b/Source/Shaders/GlobeVS.glsl @@ -1,5 +1,5 @@ attribute vec4 position3DAndHeight; -attribute vec4 textureCoordAndEncodedNormals; +attribute vec3 textureCoordAndEncodedNormals; uniform vec3 u_center3D; uniform mat4 u_modifiedModelView; @@ -87,15 +87,15 @@ void main() gl_Position = getPosition(position3DWC); -#if defined(SHOW_REFLECTIVE_OCEAN) || defined(ENABLE_DAYNIGHT_SHADING) - v_positionEC = (czm_modelView3D * vec4(position3DWC, 1.0)).xyz; - v_positionMC = position3DWC; // position in model coordinates -#elif defined(ENABLE_VERTEX_LIGHTING) +#if defined(ENABLE_VERTEX_LIGHTING) v_positionEC = (czm_modelView3D * vec4(position3DWC, 1.0)).xyz; v_positionMC = position3DWC; // position in model coordinates float encodedNormal = textureCoordAndEncodedNormals.z; v_normalMC = czm_octDecode(encodedNormal); v_normalEC = czm_normal3D * v_normalMC; +#elif defined(SHOW_REFLECTIVE_OCEAN) || defined(ENABLE_DAYNIGHT_SHADING) + v_positionEC = (czm_modelView3D * vec4(position3DWC, 1.0)).xyz; + v_positionMC = position3DWC; // position in model coordinates #endif v_textureCoordinates = textureCoordAndEncodedNormals.xy; From 92fca3975c526fbf27dd4e85877e477282e5a41d Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Mon, 2 Feb 2015 13:54:03 -0500 Subject: [PATCH 07/10] Added guard to only use an extension if the client requests the extension. --- Source/Core/CesiumTerrainProvider.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/CesiumTerrainProvider.js b/Source/Core/CesiumTerrainProvider.js index 7d760a2dd82..09ba92b9834 100644 --- a/Source/Core/CesiumTerrainProvider.js +++ b/Source/Core/CesiumTerrainProvider.js @@ -405,9 +405,9 @@ define([ var extensionLength = view.getUint32(pos, provider._littleEndianExtensionSize); pos += Uint32Array.BYTES_PER_ELEMENT; - if (extensionId === QuantizedMeshExtensionIds.OCT_VERTEX_NORMALS) { + if (extensionId === QuantizedMeshExtensionIds.OCT_VERTEX_NORMALS && provider._requestVertexNormals) { encodedNormalBuffer = new Uint8Array(buffer, pos, vertexCount * 2); - } else if (extensionId === QuantizedMeshExtensionIds.WATER_MASK) { + } else if (extensionId === QuantizedMeshExtensionIds.WATER_MASK && provider._requestWaterMask) { waterMaskBuffer = new Uint8Array(buffer, pos, extensionLength); } pos += extensionLength; From ebee0a092e004aef2e548607dd87b7addcde3881 Mon Sep 17 00:00:00 2001 From: Alex Wood Date: Wed, 11 Feb 2015 10:27:24 -0500 Subject: [PATCH 08/10] Updated sandcastle to showcase watermask and terrain lighting. Minor cleanup in terrain sandcastle ui. --- Apps/Sandcastle/gallery/Cesium Inspector.html | 5 +- Apps/Sandcastle/gallery/Terrain.html | 110 ++++++++++++------ 2 files changed, 77 insertions(+), 38 deletions(-) diff --git a/Apps/Sandcastle/gallery/Cesium Inspector.html b/Apps/Sandcastle/gallery/Cesium Inspector.html index ca499667a79..3c8e286cee5 100644 --- a/Apps/Sandcastle/gallery/Cesium Inspector.html +++ b/Apps/Sandcastle/gallery/Cesium Inspector.html @@ -38,8 +38,9 @@ var ellipsoid = globe.ellipsoid; var cesiumTerrainProviderHeightmaps = new Cesium.CesiumTerrainProvider({ - url : '//cesiumjs.org/smallterrain', - credit : 'Terrain data courtesy Analytical Graphics, Inc.' + url : '//assets.agi.com/stk-terrain/world', + requestWaterMask: true, + requestVertexNormals: true }); viewer.terrainProvider = cesiumTerrainProviderHeightmaps; diff --git a/Apps/Sandcastle/gallery/Terrain.html b/Apps/Sandcastle/gallery/Terrain.html index ba0224f04d9..774ea614bc6 100644 --- a/Apps/Sandcastle/gallery/Terrain.html +++ b/Apps/Sandcastle/gallery/Terrain.html @@ -25,6 +25,7 @@
+