From 0be69edbfda8b3478244184ea8d81e5aec8eb99d Mon Sep 17 00:00:00 2001 From: Tom Fili Date: Tue, 7 Jun 2016 14:21:33 -0400 Subject: [PATCH 001/191] Added ability to set domains to use xhr.withCredentials. --- Source/Core/loadWithXhr.js | 25 ++++++++++++++++++++++++- Specs/Core/loadWithXhrSpec.js | 21 +++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/Source/Core/loadWithXhr.js b/Source/Core/loadWithXhr.js index 415093c27601..4e3d2d8588f6 100644 --- a/Source/Core/loadWithXhr.js +++ b/Source/Core/loadWithXhr.js @@ -43,7 +43,7 @@ define([ * }).otherwise(function(error) { * // an error occurred * }); - * + * * @see loadArrayBuffer * @see loadBlob * @see loadJson @@ -122,6 +122,20 @@ define([ } } + loadWithXhr._withCredentialsRegexes = []; + loadWithXhr.addWithCredentials = function(re) { + //>>includeStart('debug', pragmas.debug); + if (!defined(re)) { + throw new DeveloperError('re is required.'); + } + //>>includeEnd('debug'); + + if (!(re instanceof RegExp)) { + re = new RegExp(re); + } + loadWithXhr._withCredentialsRegexes.push(re); + }; + // This is broken out into a separate function so that it can be mocked for testing purposes. loadWithXhr.load = function(url, responseType, method, data, headers, deferred, overrideMimeType) { var dataUriRegexResult = dataUriRegex.exec(url); @@ -132,6 +146,15 @@ define([ var xhr = new XMLHttpRequest(); + var withCredentialsRegexes = loadWithXhr._withCredentialsRegexes; + var withCredentialsLength = withCredentialsRegexes.length; + for (var i = 0; i < withCredentialsLength; ++i) { + if (url.search(withCredentialsRegexes[i])) { + xhr.withCredentials = true; + break; + } + } + if (defined(overrideMimeType) && defined(xhr.overrideMimeType)) { xhr.overrideMimeType(overrideMimeType); } diff --git a/Specs/Core/loadWithXhrSpec.js b/Specs/Core/loadWithXhrSpec.js index 0576effca5e5..3ee06630be83 100644 --- a/Specs/Core/loadWithXhrSpec.js +++ b/Specs/Core/loadWithXhrSpec.js @@ -133,6 +133,27 @@ defineSuite([ }); }); + it('add string with addWithCredentials', function() { + loadWithXhr.addWithCredentials('cesiumjs.org'); + var a = loadWithXhr._withCredentialsRegexes; + expect(a.length).toEqual(1); + expect(a[0] instanceof RegExp).toEqual(true); + expect(a[0].source).toEqual('cesiumjs.org'); + + loadWithXhr._withCredentialsRegexes = []; + }); + + it('add regex with addWithCredentials', function() { + loadWithXhr.addWithCredentials(/cesiumjs.org/i); + var a = loadWithXhr._withCredentialsRegexes; + expect(a.length).toEqual(1); + expect(a[0] instanceof RegExp).toEqual(true); + expect(a[0].source).toEqual('cesiumjs.org'); + expect(a[0].ignoreCase).toEqual(true); + + loadWithXhr._withCredentialsRegexes = []; + }); + xit('can support 2xx HTTP status (other than 200)', function(){ return loadWithXhr({ method: 'POST', From 2ad6330ef68b7b04e2283e01aef2ddd230062e98 Mon Sep 17 00:00:00 2001 From: Tom Fili Date: Tue, 7 Jun 2016 14:28:51 -0400 Subject: [PATCH 002/191] Fixed compare. --- Source/Core/loadWithXhr.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/loadWithXhr.js b/Source/Core/loadWithXhr.js index 4e3d2d8588f6..518beffaf0e1 100644 --- a/Source/Core/loadWithXhr.js +++ b/Source/Core/loadWithXhr.js @@ -149,7 +149,7 @@ define([ var withCredentialsRegexes = loadWithXhr._withCredentialsRegexes; var withCredentialsLength = withCredentialsRegexes.length; for (var i = 0; i < withCredentialsLength; ++i) { - if (url.search(withCredentialsRegexes[i])) { + if (url.search(withCredentialsRegexes[i]) !== -1) { xhr.withCredentials = true; break; } From 7cde6b8f421402a09c19d68dadb8262a9e67fd5b Mon Sep 17 00:00:00 2001 From: Tom Fili Date: Tue, 7 Jun 2016 16:44:00 -0400 Subject: [PATCH 003/191] Added CredentialsRegsitry. --- Source/Core/CredentialsRegistry.js | 133 ++++++++++++++++++++++++++ Source/Core/loadImage.js | 8 +- Source/Core/loadWithXhr.js | 25 +---- Specs/Core/CredentialsRegistrySpec.js | 73 ++++++++++++++ Specs/Core/loadWithXhrSpec.js | 21 ---- 5 files changed, 217 insertions(+), 43 deletions(-) create mode 100644 Source/Core/CredentialsRegistry.js create mode 100644 Specs/Core/CredentialsRegistrySpec.js diff --git a/Source/Core/CredentialsRegistry.js b/Source/Core/CredentialsRegistry.js new file mode 100644 index 000000000000..8f5226c81750 --- /dev/null +++ b/Source/Core/CredentialsRegistry.js @@ -0,0 +1,133 @@ +/*global define*/ +define([ + './defined', + './defineProperties', + './DeveloperError', + '../ThirdParty/Uri' +], function( + defined, + defineProperties, + DeveloperError, + Uri) { + 'use strict'; + + /** + * A singleton that contains all of the servers that are trusted. Credentials will be sent with + * any requests to these servers. + * + * @exports CredentialsRegistry + * + * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing} + */ + var CredentialsRegistry = {}; + var _credentials = {}; + + /** + * Adds a trusted server to the registry + * + * @param {String} authority The server that is trusted. Can include a port if it is needed. (eg. my.server.com or my.server.com:8080) + * + * @example + * // Add a trusted server + * CredentialsRegistry.addTrustedServer('my.server.com:81'); + */ + CredentialsRegistry.addTrustedServer = function(authority) { + //>>includeStart('debug', pragmas.debug); + if (!defined(authority)) { + throw new DeveloperError('authority is required.'); + } + //>>includeEnd('debug'); + + authority = authority.toLowerCase(); + if (!defined(_credentials[authority])) { + _credentials[authority] = true; + } + }; + + /** + * Removes a trusted server from the registry + * + * @param {String} authority The server that is trusted. Should be exact authority that was added. (eg. my.server.com or my.server.com:8080) + * + * @example + * // Remove a trusted server + * CredentialsRegistry.removeTrustedServer('my.server.com:81'); + */ + CredentialsRegistry.removeTrustedServer = function(authority) { + //>>includeStart('debug', pragmas.debug); + if (!defined(authority)) { + throw new DeveloperError('authority is required.'); + } + //>>includeEnd('debug'); + + authority = authority.toLowerCase(); + if (defined(_credentials[authority])) { + delete _credentials[authority]; + } + }; + + /** + * Tests whether a server is trusted or not. The server must have been added with the port if it is included in the url. + * + * @param {String} url The url to be tested against the trusted list + * + * @returns {boolean} Returns true if url is trusted, false otherwise. + * + * @example + * // Add server + * CredentialsRegistry.removeTrustedServer('my.server.com:81'); + * + * // Check if server is trusted + * if (CredentialsRegistry.isTrusted('https://my.server.com:81/path/to/file.png')) { + * // my.server.com:81 is trusted + * } + * if (CredentialsRegistry.isTrusted('https://my.server.com/path/to/file.png')) { + * // my.server.com isn't trusted + * } + */ + CredentialsRegistry.isTrusted = function(url) { + //>>includeStart('debug', pragmas.debug); + if (!defined(url)) { + throw new DeveloperError('url is required.'); + } + //>>includeEnd('debug'); + var uri = new Uri(url); + uri.normalize(); + var authority = uri.getAuthority(); + if (!defined(authority)) { + return false; + } + + if (defined(_credentials[authority])) { + return true; + } + + if (authority.indexOf(':') === -1) { + var scheme = uri.getScheme(); + if (scheme === 'http') { + authority += ':80'; + } else if (scheme === 'https') { + authority += ':443'; + } + + if (defined(_credentials[authority])) { + return true; + } + } + + return false; + }; + + /** + * Clears the registry + * + * @example + * // Remove a trusted server + * CredentialsRegistry.clear(); + */ + CredentialsRegistry.clear = function() { + _credentials = []; + } + + return CredentialsRegistry; +}); \ No newline at end of file diff --git a/Source/Core/loadImage.js b/Source/Core/loadImage.js index 3178cf5f393f..75c049b06084 100644 --- a/Source/Core/loadImage.js +++ b/Source/Core/loadImage.js @@ -1,12 +1,14 @@ /*global define*/ define([ '../ThirdParty/when', + './CredentialsRegistry', './defaultValue', './defined', './DeveloperError', './isCrossOriginUrl' ], function( when, + CredentialsRegistry, defaultValue, defined, DeveloperError, @@ -84,7 +86,11 @@ define([ }; if (crossOrigin) { - image.crossOrigin = ''; + if (CredentialsRegistry.isTrusted(url)) { + image.crossOrigin = 'use-credentials'; + } else { + image.crossOrigin = ''; + } } image.src = url; diff --git a/Source/Core/loadWithXhr.js b/Source/Core/loadWithXhr.js index 518beffaf0e1..db539ae1908d 100644 --- a/Source/Core/loadWithXhr.js +++ b/Source/Core/loadWithXhr.js @@ -1,6 +1,7 @@ /*global define*/ define([ '../ThirdParty/when', + './CredentialsRegistry', './defaultValue', './defined', './DeveloperError', @@ -8,6 +9,7 @@ define([ './RuntimeError' ], function( when, + CredentialsRegistry, defaultValue, defined, DeveloperError, @@ -122,20 +124,6 @@ define([ } } - loadWithXhr._withCredentialsRegexes = []; - loadWithXhr.addWithCredentials = function(re) { - //>>includeStart('debug', pragmas.debug); - if (!defined(re)) { - throw new DeveloperError('re is required.'); - } - //>>includeEnd('debug'); - - if (!(re instanceof RegExp)) { - re = new RegExp(re); - } - loadWithXhr._withCredentialsRegexes.push(re); - }; - // This is broken out into a separate function so that it can be mocked for testing purposes. loadWithXhr.load = function(url, responseType, method, data, headers, deferred, overrideMimeType) { var dataUriRegexResult = dataUriRegex.exec(url); @@ -146,13 +134,8 @@ define([ var xhr = new XMLHttpRequest(); - var withCredentialsRegexes = loadWithXhr._withCredentialsRegexes; - var withCredentialsLength = withCredentialsRegexes.length; - for (var i = 0; i < withCredentialsLength; ++i) { - if (url.search(withCredentialsRegexes[i]) !== -1) { - xhr.withCredentials = true; - break; - } + if (CredentialsRegistry.isTrusted(url)) { + xhr.withCredentials = true; } if (defined(overrideMimeType) && defined(xhr.overrideMimeType)) { diff --git a/Specs/Core/CredentialsRegistrySpec.js b/Specs/Core/CredentialsRegistrySpec.js new file mode 100644 index 000000000000..8968f159b16a --- /dev/null +++ b/Specs/Core/CredentialsRegistrySpec.js @@ -0,0 +1,73 @@ +/*global defineSuite*/ +defineSuite([ + 'Core/CredentialsRegistry' +], function( + CredentialsRegistry) { + 'use strict'; + + afterEach(function() { + CredentialsRegistry.clear(); + }); + + it('addTrustedServer without argument throws', function() { + expect(function() { + CredentialsRegistry.addTrustedServer(); + }).toThrowDeveloperError(); + }); + + it('removeTrustedServer without argument throws', function() { + expect(function() { + CredentialsRegistry.removeTrustedServer(); + }).toThrowDeveloperError(); + }); + + it('isTrusted without argument throws', function() { + expect(function() { + CredentialsRegistry.isTrusted(); + }).toThrowDeveloperError(); + }); + + it('without a port', function() { + CredentialsRegistry.addTrustedServer('cesiumjs.org'); + expect(CredentialsRegistry.isTrusted('http://cesiumjs.org/index.html')).toBe(true); + }); + + it('with a port', function() { + CredentialsRegistry.addTrustedServer('cesiumjs.org:81'); + expect(CredentialsRegistry.isTrusted('http://cesiumjs.org/index.html')).toBe(false); + expect(CredentialsRegistry.isTrusted('http://cesiumjs.org:81/index.html')).toBe(true); + }); + + it('using default http port', function() { + CredentialsRegistry.addTrustedServer('cesiumjs.org:80'); + expect(CredentialsRegistry.isTrusted('http://cesiumjs.org/index.html')).toBe(true); + }); + + it('using default https port', function() { + CredentialsRegistry.addTrustedServer('cesiumjs.org:443'); + expect(CredentialsRegistry.isTrusted('https://cesiumjs.org/index.html')).toBe(true); + }); + + it('remove without a port', function() { + CredentialsRegistry.addTrustedServer('cesiumjs.org'); + expect(CredentialsRegistry.isTrusted('http://cesiumjs.org/index.html')).toBe(true); + CredentialsRegistry.removeTrustedServer('cesiumjs.org'); + expect(CredentialsRegistry.isTrusted('http://cesiumjs.org/index.html')).toBe(false); + }); + + it('remove with a port', function() { + CredentialsRegistry.addTrustedServer('cesiumjs.org:81'); + expect(CredentialsRegistry.isTrusted('http://cesiumjs.org:81/index.html')).toBe(true); + CredentialsRegistry.removeTrustedServer('cesiumjs.org'); + expect(CredentialsRegistry.isTrusted('http://cesiumjs.org:81/index.html')).toBe(true); + CredentialsRegistry.removeTrustedServer('cesiumjs.org:81'); + expect(CredentialsRegistry.isTrusted('http://cesiumjs.org:81/index.html')).toBe(false); + }); + + it('clear', function() { + CredentialsRegistry.addTrustedServer('cesiumjs.org'); + expect(CredentialsRegistry.isTrusted('http://cesiumjs.org/index.html')).toBe(true); + CredentialsRegistry.clear(); + expect(CredentialsRegistry.isTrusted('http://cesiumjs.org/index.html')).toBe(false); + }); +}); diff --git a/Specs/Core/loadWithXhrSpec.js b/Specs/Core/loadWithXhrSpec.js index 3ee06630be83..0576effca5e5 100644 --- a/Specs/Core/loadWithXhrSpec.js +++ b/Specs/Core/loadWithXhrSpec.js @@ -133,27 +133,6 @@ defineSuite([ }); }); - it('add string with addWithCredentials', function() { - loadWithXhr.addWithCredentials('cesiumjs.org'); - var a = loadWithXhr._withCredentialsRegexes; - expect(a.length).toEqual(1); - expect(a[0] instanceof RegExp).toEqual(true); - expect(a[0].source).toEqual('cesiumjs.org'); - - loadWithXhr._withCredentialsRegexes = []; - }); - - it('add regex with addWithCredentials', function() { - loadWithXhr.addWithCredentials(/cesiumjs.org/i); - var a = loadWithXhr._withCredentialsRegexes; - expect(a.length).toEqual(1); - expect(a[0] instanceof RegExp).toEqual(true); - expect(a[0].source).toEqual('cesiumjs.org'); - expect(a[0].ignoreCase).toEqual(true); - - loadWithXhr._withCredentialsRegexes = []; - }); - xit('can support 2xx HTTP status (other than 200)', function(){ return loadWithXhr({ method: 'POST', From 3d2f0c594125944ae3e8dcecc0a04f724153fc02 Mon Sep 17 00:00:00 2001 From: Tom Fili Date: Tue, 7 Jun 2016 16:55:24 -0400 Subject: [PATCH 004/191] Cleanup. --- Source/Core/CredentialsRegistry.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Core/CredentialsRegistry.js b/Source/Core/CredentialsRegistry.js index 8f5226c81750..69e5140cc439 100644 --- a/Source/Core/CredentialsRegistry.js +++ b/Source/Core/CredentialsRegistry.js @@ -108,6 +108,8 @@ define([ authority += ':80'; } else if (scheme === 'https') { authority += ':443'; + } else { + return false; } if (defined(_credentials[authority])) { From ce7b6b45423e7f9fbbe086b421b014daefcd8b89 Mon Sep 17 00:00:00 2001 From: Chris Cooper Date: Mon, 11 Jul 2016 14:55:22 +1000 Subject: [PATCH 005/191] guard against negative height samples --- Source/Core/HeightmapTerrainData.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/HeightmapTerrainData.js b/Source/Core/HeightmapTerrainData.js index 567727abe11f..aeb3bf042cd2 100644 --- a/Source/Core/HeightmapTerrainData.js +++ b/Source/Core/HeightmapTerrainData.js @@ -350,7 +350,7 @@ define([ for (var i = 0; i < width; ++i) { var longitude = CesiumMath.lerp(destinationRectangle.west, destinationRectangle.east, i / (width - 1)); var heightSample = interpolateMeshHeight(buffer, encoding, heightOffset, heightScale, skirtHeight, sourceRectangle, width, height, longitude, latitude, exaggeration); - setHeight(heights, elementsPerHeight, elementMultiplier, divisor, stride, isBigEndian, j * width + i, heightSample); + setHeight(heights, elementsPerHeight, elementMultiplier, divisor, stride, isBigEndian, j * width + i, Math.max(heightSample, 0)); } } From f742e6255e3bb8acf06ae1ca0f83dde5a1a3f136 Mon Sep 17 00:00:00 2001 From: Chris Cooper Date: Mon, 11 Jul 2016 15:40:12 +1000 Subject: [PATCH 006/191] Add spec for heightmap issue --- Specs/Core/HeightmapTerrainDataSpec.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Specs/Core/HeightmapTerrainDataSpec.js b/Specs/Core/HeightmapTerrainDataSpec.js index f67827de3459..3253759b5608 100644 --- a/Specs/Core/HeightmapTerrainDataSpec.js +++ b/Specs/Core/HeightmapTerrainDataSpec.js @@ -246,6 +246,23 @@ defineSuite([ expect(upsampled._buffer).toEqual([2, 1, 0, 3, 1, 0, 3, 1, 0, 4, 1, 0, 4, 1, 0, 5, 1, 0, 5, 1, 0, 6, 1, 0, 6, 1, 0, 7, 1, 0, 7, 1, 0, 8, 1, 0, 8, 1, 0, 9, 1, 0, 9, 1, 0, 10, 1, 0]); }); }); + + it('upsample clamps negative data', function() { + data = new HeightmapTerrainData({ + buffer : new Float32Array([-1.0, -2.0, -3.0, -4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0]), + width : 4, + height : 4 + }); + + return data.createMesh(tilingScheme, 0, 0, 0, 1).then(function() { + return data.upsample(tilingScheme, 0, 0, 0, 0, 0, 1); + }).then(function(upsampled) { + expect(upsampled.wasCreatedByUpsampling()).toBe(true); + expect(upsampled._width).toBe(4); + expect(upsampled._height).toBe(4); + expect(upsampled._buffer).toEqual([0, 0, 0, 0, 2, 1.5, 2, 1.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5]); + }); + }); }); describe('isChildAvailable', function() { From 1c83762ccaa9cd18ec27ea619a15e4edd7d084fd Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 18 Aug 2016 17:35:53 -0400 Subject: [PATCH 007/191] Label clustering WIP. --- .../gallery/development/Labels.html | 165 +++---------- Source/Scene/Billboard.js | 3 + Source/Scene/LabelCollectionDeclutter.js | 217 ++++++++++++++++++ Source/ThirdParty/kdbush.js | 205 +++++++++++++++++ 4 files changed, 454 insertions(+), 136 deletions(-) create mode 100644 Source/Scene/LabelCollectionDeclutter.js create mode 100644 Source/ThirdParty/kdbush.js diff --git a/Apps/Sandcastle/gallery/development/Labels.html b/Apps/Sandcastle/gallery/development/Labels.html index f865fccc0f1a..0b70b90ee8d8 100644 --- a/Apps/Sandcastle/gallery/development/Labels.html +++ b/Apps/Sandcastle/gallery/development/Labels.html @@ -27,150 +27,43 @@ function startup(Cesium) { 'use strict'; //Sandcastle_Begin -var viewer = new Cesium.Viewer('cesiumContainer'); -var scene = viewer.scene; + var viewer = new Cesium.Viewer('cesiumContainer'); + var scene = viewer.scene; -function addLabel() { - Sandcastle.declare(addLabel); - scene.primitives.removeAll(); - var labels = scene.primitives.add(new Cesium.LabelCollection()); - labels.add({ - position : Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222), - text : 'Philadelphia' - }); -} + var minLat = 22.0; + var maxLat = 51.0; + var minLon = -127.0; + var maxLon = -71.0; -function setFont() { - Sandcastle.declare(setFont); - scene.primitives.removeAll(); - var labels = scene.primitives.add(new Cesium.LabelCollection()); - labels.add({ - position : Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222), - text : 'Philadelphia', - // CSS font-family - font : '24px Helvetica', - fillColor : new Cesium.Color(0.6, 0.9, 1.0), - outlineColor : Cesium.Color.BLACK, - outlineWidth : 2, - style : Cesium.LabelStyle.FILL_AND_OUTLINE - }); -} + var lonIncrement = 0.5; + var latIncrement = 0.5; -function setProperties() { - Sandcastle.declare(setProperties); - scene.primitives.removeAll(); - var labels = scene.primitives.add(new Cesium.LabelCollection()); - var l = labels.add({ - position : Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222), - text : 'Philadelphia' - }); + var minWordLength = 4; + var maxWordLength = 9; - l.position = Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222, 300000.0); - l.scale = 2.0; -} + var labels = new Cesium.LabelCollection(); -function inReferenceFrame() { - Sandcastle.declare(inReferenceFrame); - scene.primitives.removeAll(); - var center = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883); - var labels = scene.primitives.add(new Cesium.LabelCollection()); - labels.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center); - labels.add({ - position : new Cesium.Cartesian3(0.0, 0.0, 0.0), - text : 'Center' - }); - labels.add({ - position : new Cesium.Cartesian3(1000000.0, 0.0, 0.0), - text : 'East' - }); - labels.add({ - position : new Cesium.Cartesian3(0.0, 1000000.0, 0.0), - text : 'North' - }); - labels.add({ - position : new Cesium.Cartesian3(0.0, 0.0, 1000000.0), - text : 'Up' - }); -} + for(var i = minLat; i < maxLat; i += latIncrement) { + for (var j = minLon; j < maxLon; j += lonIncrement) { + var position = Cesium.Cartesian3.fromDegrees(j, i); -function offsetByDistance() { - Sandcastle.declare(offsetByDistance); - scene.primitives.removeAll(); - var image = new Image(); - image.onload = function() { - var billboards = scene.primitives.add(new Cesium.BillboardCollection()); - billboards.add({ - position : Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222), - scaleByDistance : new Cesium.NearFarScalar(1.5e2, 5.0, 1.5e7, 0.5), - image : image - }); + var text = ''; + var textLength = Math.random() * (maxWordLength - minWordLength) + minWordLength; + for (var k = 0; k < textLength; ++k) { + text += String.fromCharCode(Math.floor((Math.random() * 25.0 + 65.0))); + } - var labels = scene.primitives.add(new Cesium.LabelCollection()); - labels.add({ - position : Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222), - text : 'Label on top of scaling billboard', - font : '20px sans-serif', - horizontalOrigin : Cesium.HorizontalOrigin.CENTER, - pixelOffset : new Cesium.Cartesian2(0.0, -image.height), - pixelOffsetScaleByDistance : new Cesium.NearFarScalar(1.5e2, 3.0, 1.5e7, 0.5) - }); - }; - image.src = '../images/facility.gif'; -} - -function fadeByDistance() { - Sandcastle.declare(fadeByDistance); - scene.primitives.removeAll(); - var labels = scene.primitives.add(new Cesium.LabelCollection()); - labels.add({ - position : Cesium.Cartesian3.fromDegrees(-73.94, 40.67), - text : 'New York', - translucencyByDistance : new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e8, 0.0) - }); - labels.add({ - position : Cesium.Cartesian3.fromDegrees(-84.39, 33.75), - text : 'Atlanta', - translucencyByDistance : new Cesium.NearFarScalar(1.5e5, 1.0, 1.5e7, 0.0) - }); -} - -Sandcastle.addToolbarMenu([{ - text : 'Add label', - onselect : function() { - addLabel(); - Sandcastle.highlight(addLabel); - } -}, { - text : 'Set font', - onselect : function() { - setFont(); - Sandcastle.highlight(setFont); + labels.add({ + position : position, + text : text + }); + } } -}, { - text : 'Set properties', - onselect : function() { - setProperties(); - Sandcastle.highlight(setProperties); - } -}, { - text : 'Add labels in reference frame', - onselect : function() { - inReferenceFrame(); - Sandcastle.highlight(inReferenceFrame); - } -}, { - text : 'Offset label by distance', - onselect : function() { - offsetByDistance(); - Sandcastle.highlight(offsetByDistance); - } -}, { - text : 'Fade label by distance', - onselect : function() { - fadeByDistance(); - Sandcastle.highlight(fadeByDistance); - } -}]); + + scene.primitives.add(new Cesium.LabelCollectionDeclutter({ + labelCollection : labels, + scene : scene + })); //Sandcastle_End Sandcastle.finishedLoading(); } diff --git a/Source/Scene/Billboard.js b/Source/Scene/Billboard.js index e875a1dd68fa..84f4e39e34b4 100644 --- a/Source/Scene/Billboard.js +++ b/Source/Scene/Billboard.js @@ -1092,6 +1092,9 @@ define([ // World to window coordinates var positionWC = SceneTransforms.wgs84WithEyeOffsetToWindowCoordinates(scene, positionWorld, eyeOffset, result); + if (!defined(positionWC)) { + return undefined; + } // Apply pixel offset pixelOffset = Cartesian2.clone(pixelOffset, scratchComputePixelOffset); diff --git a/Source/Scene/LabelCollectionDeclutter.js b/Source/Scene/LabelCollectionDeclutter.js new file mode 100644 index 000000000000..ffdf5ff40ae9 --- /dev/null +++ b/Source/Scene/LabelCollectionDeclutter.js @@ -0,0 +1,217 @@ +/*global define*/ +define([ + '../Core/BoundingRectangle', + '../Core/Cartesian3', + '../Core/defaultValue', + '../Core/defined', + '../Core/destroyObject', + '../Core/EllipsoidalOccluder', + '../ThirdParty/kdbush', + './HorizontalOrigin', + './LabelCollection', + './SceneTransforms', + './VerticalOrigin' +], function( + BoundingRectangle, + Cartesian3, + defaultValue, + defined, + destroyObject, + EllipsoidalOccluder, + kdbush, + HorizontalOrigin, + LabelCollection, + SceneTransforms, + VerticalOrigin) { + 'use strict'; + + function getX(point) { + return point.coord.x; + } + + function getY(point) { + return point.coord.y; + } + + function getBBox(label, coord) { + // TODO: create this at label creation time + var width = 0; + var height = Number.NEGATIVE_INFINITY; + + var glyphs = label._glyphs; + var length = glyphs.length; + for (var i = 0; i < length; ++i) { + var glyph = glyphs[i]; + var billboard = glyph.billboard; + width += billboard.width; + height = Math.max(height, billboard.height); + } + + var scale = label.scale; + width *= scale; + height *= scale; + + var x = coord.x; + if (label.horizontalOrigin === HorizontalOrigin.RIGHT) { + x -= width; + } else if (label.horizontalOrigin === HorizontalOrigin.CENTER) { + x -= width * 0.5; + } + + var y = coord.y; + if (label.verticalOrigin === VerticalOrigin.TOP) { + y -= height; + } else if (label.verticalOrigin === VerticalOrigin.CENTER) { + y -= height * 0.5; + } + + return new BoundingRectangle(x, y, width, height); + } + + function createDeclutterCallback(labelCollectionDeclutter) { + return function() { + var labelCollection = labelCollectionDeclutter._labelCollection; + var renderCollection = labelCollectionDeclutter._renderCollection; + var scene = labelCollectionDeclutter._scene; + var pixelRange = labelCollectionDeclutter._pixelRange; + + if (defined(renderCollection)) { + renderCollection.removeAll(); + } else { + renderCollection = new LabelCollection(); + } + + var ellipsoid = scene.mapProjection.ellipsoid; + var cameraPosition = scene.camera.positionWC; + var occluder = new EllipsoidalOccluder(ellipsoid, cameraPosition); + + var i; + var label; + var length = labelCollection.length; + var points = []; + + for (i = 0; i < length; ++i) { + label = labelCollection.get(i); + if (!occluder.isPointVisible(label.position)) { + continue; + } + + var coord = label.computeScreenSpacePosition(scene); + if (!defined(coord) || coord.x < 0.0 || coord.x > scene.drawingBufferWidth || coord.y < 0.0 || coord.y > scene.drawingBufferHeight) { + continue; + } + + points.push({ + labelIndex : i, + clustered : false, + coord : coord + }); + } + + var index = kdbush(points, getX, getY, 64, Int32Array); + length = points.length; + + for (i = 0; i < length; ++i) { + var point = points[i]; + if (point.clustered) { + continue; + } + + point.clustered = true; + + label = labelCollection.get(point.labelIndex); + var bbox = getBBox(label, point.coord); + + bbox.x += pixelRange; + bbox.y += pixelRange; + bbox.width += pixelRange * 0.5; + bbox.height += pixelRange * 0.5; + + var neighbors = index.within(bbox.x, bbox.y, bbox.width); + + var neighborsFound = false; + var clusterPosition = new Cartesian3(); + var numPoints = 0; + + var neighborLength = neighbors.length; + for (var j = 0; j < neighborLength; ++j) { + var neighborIndex = neighbors[j]; + var neighborPoint = points[neighborIndex]; + if (!neighborPoint.clustered) { + neighborPoint.clustered = true; + neighborsFound = true; + + Cartesian3.add(clusterPosition, labelCollection.get(neighborPoint.labelIndex).position, clusterPosition); + ++numPoints; + } + } + + if (!neighborsFound) { + var clone = { + text : label.text, + show : label.show, + font : label.font, + fillColor : label.fillColor, + outlineColor : label.outlineColor, + outlineWidth : label.outlineWidth, + style : label.outlineStyle, + verticalOrigin : label.verticalOrigin, + horizontalOrigin : label.horizontalOrigin, + pixelOffset : label.pixelOffset, + eyeOffset : label.eyeOffset, + position : label.position, + scale : label.scale, + id : label.id, + translucencyByDistance : label.translucencyByDistance, + pixelOffsetScaleByDistance : label.pixelOffsetScaleByDistance, + heightReference : label.heightReference + }; + renderCollection.add(clone); + } else { + var position = Cartesian3.multiplyByScalar(clusterPosition, 1.0 / numPoints, clusterPosition); + renderCollection.add({ + text : '' + (numPoints + 1), + position : position + }); + } + } + + if (renderCollection.length === 0) { + renderCollection.destroy(); + renderCollection = undefined; + } + + labelCollectionDeclutter._renderCollection = renderCollection; + }; + } + + function LabelCollectionDeclutter(options) { + this._scene = options.scene; + this._labelCollection = options.labelCollection; + this._renderCollection = undefined; + + this._pixelRange = defaultValue(options.pixelRange, 5); + + this._removeEventListener = this._scene.camera.moveEnd.addEventListener(createDeclutterCallback(this)); + } + + LabelCollectionDeclutter.prototype.update = function(frameState) { + if (!defined(this._renderCollection)) { + this._labelCollection.update(frameState); + } else { + this._renderCollection.update(frameState); + } + }; + + LabelCollectionDeclutter.prototype.isDestroyed = function() { + return false; + }; + + LabelCollectionDeclutter.prototype.destroy = function() { + this._labelCollection = this._labelCollection && this._labelCollection.destroy(); + this._removeEventListener(); + return destroyObject(this); + }; + + return LabelCollectionDeclutter; +}); \ No newline at end of file diff --git a/Source/ThirdParty/kdbush.js b/Source/ThirdParty/kdbush.js new file mode 100644 index 000000000000..afaba5a6ca88 --- /dev/null +++ b/Source/ThirdParty/kdbush.js @@ -0,0 +1,205 @@ +/*global define*/ +define([], function() { + 'use strict'; + + function kdbush(points, getX, getY, nodeSize, ArrayType) { + return new KDBush(points, getX, getY, nodeSize, ArrayType); + } + + function KDBush(points, getX, getY, nodeSize, ArrayType) { + getX = getX || defaultGetX; + getY = getY || defaultGetY; + ArrayType = ArrayType || Array; + + this.nodeSize = nodeSize || 64; + this.points = points; + + this.ids = new ArrayType(points.length); + this.coords = new ArrayType(points.length * 2); + + for (var i = 0; i < points.length; i++) { + this.ids[i] = i; + this.coords[2 * i] = getX(points[i]); + this.coords[2 * i + 1] = getY(points[i]); + } + + sort(this.ids, this.coords, this.nodeSize, 0, this.ids.length - 1, 0); + } + + KDBush.prototype = { + range : function(minX, minY, maxX, maxY) { + return range(this.ids, this.coords, minX, minY, maxX, maxY, this.nodeSize); + }, + + within : function(x, y, r) { + return within(this.ids, this.coords, x, y, r, this.nodeSize); + } + }; + + function defaultGetX(p) { + return p[0]; + } + + function defaultGetY(p) { + return p[1]; + } + + function range(ids, coords, minX, minY, maxX, maxY, nodeSize) { + var stack = [0, ids.length - 1, 0]; + var result = []; + var x, y; + + while (stack.length) { + var axis = stack.pop(); + var right = stack.pop(); + var left = stack.pop(); + + if (right - left <= nodeSize) { + for (var i = left; i <= right; i++) { + x = coords[2 * i]; + y = coords[2 * i + 1]; + if (x >= minX && x <= maxX && y >= minY && y <= maxY) result.push(ids[i]); + } + continue; + } + + var m = Math.floor((left + right) / 2); + + x = coords[2 * m]; + y = coords[2 * m + 1]; + + if (x >= minX && x <= maxX && y >= minY && y <= maxY) result.push(ids[m]); + + var nextAxis = (axis + 1) % 2; + + if (axis === 0 ? minX <= x : minY <= y) { + stack.push(left); + stack.push(m - 1); + stack.push(nextAxis); + } + if (axis === 0 ? maxX >= x : maxY >= y) { + stack.push(m + 1); + stack.push(right); + stack.push(nextAxis); + } + } + + return result; + } + + function sort(ids, coords, nodeSize, left, right, depth) { + return sortKD(ids, coords, nodeSize, left, right, depth); + } + + function sortKD(ids, coords, nodeSize, left, right, depth) { + if (right - left <= nodeSize) return; + + var m = Math.floor((left + right) / 2); + + select(ids, coords, m, left, right, depth % 2); + + sortKD(ids, coords, nodeSize, left, m - 1, depth + 1); + sortKD(ids, coords, nodeSize, m + 1, right, depth + 1); + } + + function select(ids, coords, k, left, right, inc) { + + while (right > left) { + if (right - left > 600) { + var n = right - left + 1; + var m = k - left + 1; + var z = Math.log(n); + var s = 0.5 * Math.exp(2 * z / 3); + var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1); + var newLeft = Math.max(left, Math.floor(k - m * s / n + sd)); + var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd)); + select(ids, coords, k, newLeft, newRight, inc); + } + + var t = coords[2 * k + inc]; + var i = left; + var j = right; + + swapItem(ids, coords, left, k); + if (coords[2 * right + inc] > t) swapItem(ids, coords, left, right); + + while (i < j) { + swapItem(ids, coords, i, j); + i++; + j--; + while (coords[2 * i + inc] < t) i++; + while (coords[2 * j + inc] > t) j--; + } + + if (coords[2 * left + inc] === t) swapItem(ids, coords, left, j); + else { + j++; + swapItem(ids, coords, j, right); + } + + if (j <= k) left = j + 1; + if (k <= j) right = j - 1; + } + } + + function swapItem(ids, coords, i, j) { + swap(ids, i, j); + swap(coords, 2 * i, 2 * j); + swap(coords, 2 * i + 1, 2 * j + 1); + } + + function swap(arr, i, j) { + var tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + + function within(ids, coords, qx, qy, r, nodeSize) { + var stack = [0, ids.length - 1, 0]; + var result = []; + var r2 = r * r; + + while (stack.length) { + var axis = stack.pop(); + var right = stack.pop(); + var left = stack.pop(); + + if (right - left <= nodeSize) { + for (var i = left; i <= right; i++) { + if (sqDist(coords[2 * i], coords[2 * i + 1], qx, qy) <= r2) result.push(ids[i]); + } + continue; + } + + var m = Math.floor((left + right) / 2); + + var x = coords[2 * m]; + var y = coords[2 * m + 1]; + + if (sqDist(x, y, qx, qy) <= r2) result.push(ids[m]); + + var nextAxis = (axis + 1) % 2; + + if (axis === 0 ? qx - r <= x : qy - r <= y) { + stack.push(left); + stack.push(m - 1); + stack.push(nextAxis); + } + if (axis === 0 ? qx + r >= x : qy + r >= y) { + stack.push(m + 1); + stack.push(right); + stack.push(nextAxis); + } + } + + return result; + } + + function sqDist(ax, ay, bx, by) { + var dx = ax - bx; + var dy = ay - by; + return dx * dx + dy * dy; + } + + return kdbush; +}); From 41974df140aee009a889270db82f93490a10d394 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 18 Aug 2016 18:49:05 -0400 Subject: [PATCH 008/191] Use browserify to create a UMD for kdbush instead of creating it manually. --- Source/ThirdParty/kdbush.js | 329 +++++++++++++++++++----------------- 1 file changed, 170 insertions(+), 159 deletions(-) diff --git a/Source/ThirdParty/kdbush.js b/Source/ThirdParty/kdbush.js index afaba5a6ca88..bdcf198311a7 100644 --- a/Source/ThirdParty/kdbush.js +++ b/Source/ThirdParty/kdbush.js @@ -1,205 +1,216 @@ -/*global define*/ -define([], function() { - 'use strict'; +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.kdbush = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= minX && x <= maxX && y >= minY && y <= maxY) result.push(ids[i]); - } - continue; - } - - var m = Math.floor((left + right) / 2); +},{"./range":2,"./sort":3,"./within":4}],2:[function(require,module,exports){ +'use strict'; - x = coords[2 * m]; - y = coords[2 * m + 1]; +module.exports = range; - if (x >= minX && x <= maxX && y >= minY && y <= maxY) result.push(ids[m]); +function range(ids, coords, minX, minY, maxX, maxY, nodeSize) { + var stack = [0, ids.length - 1, 0]; + var result = []; + var x, y; - var nextAxis = (axis + 1) % 2; + while (stack.length) { + var axis = stack.pop(); + var right = stack.pop(); + var left = stack.pop(); - if (axis === 0 ? minX <= x : minY <= y) { - stack.push(left); - stack.push(m - 1); - stack.push(nextAxis); - } - if (axis === 0 ? maxX >= x : maxY >= y) { - stack.push(m + 1); - stack.push(right); - stack.push(nextAxis); + if (right - left <= nodeSize) { + for (var i = left; i <= right; i++) { + x = coords[2 * i]; + y = coords[2 * i + 1]; + if (x >= minX && x <= maxX && y >= minY && y <= maxY) result.push(ids[i]); } + continue; } - return result; - } + var m = Math.floor((left + right) / 2); + + x = coords[2 * m]; + y = coords[2 * m + 1]; + + if (x >= minX && x <= maxX && y >= minY && y <= maxY) result.push(ids[m]); - function sort(ids, coords, nodeSize, left, right, depth) { - return sortKD(ids, coords, nodeSize, left, right, depth); + var nextAxis = (axis + 1) % 2; + + if (axis === 0 ? minX <= x : minY <= y) { + stack.push(left); + stack.push(m - 1); + stack.push(nextAxis); + } + if (axis === 0 ? maxX >= x : maxY >= y) { + stack.push(m + 1); + stack.push(right); + stack.push(nextAxis); + } } - function sortKD(ids, coords, nodeSize, left, right, depth) { - if (right - left <= nodeSize) return; + return result; +} - var m = Math.floor((left + right) / 2); +},{}],3:[function(require,module,exports){ +'use strict'; - select(ids, coords, m, left, right, depth % 2); +module.exports = sortKD; - sortKD(ids, coords, nodeSize, left, m - 1, depth + 1); - sortKD(ids, coords, nodeSize, m + 1, right, depth + 1); - } +function sortKD(ids, coords, nodeSize, left, right, depth) { + if (right - left <= nodeSize) return; - function select(ids, coords, k, left, right, inc) { - - while (right > left) { - if (right - left > 600) { - var n = right - left + 1; - var m = k - left + 1; - var z = Math.log(n); - var s = 0.5 * Math.exp(2 * z / 3); - var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1); - var newLeft = Math.max(left, Math.floor(k - m * s / n + sd)); - var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd)); - select(ids, coords, k, newLeft, newRight, inc); - } + var m = Math.floor((left + right) / 2); - var t = coords[2 * k + inc]; - var i = left; - var j = right; + select(ids, coords, m, left, right, depth % 2); - swapItem(ids, coords, left, k); - if (coords[2 * right + inc] > t) swapItem(ids, coords, left, right); + sortKD(ids, coords, nodeSize, left, m - 1, depth + 1); + sortKD(ids, coords, nodeSize, m + 1, right, depth + 1); +} - while (i < j) { - swapItem(ids, coords, i, j); - i++; - j--; - while (coords[2 * i + inc] < t) i++; - while (coords[2 * j + inc] > t) j--; - } +function select(ids, coords, k, left, right, inc) { - if (coords[2 * left + inc] === t) swapItem(ids, coords, left, j); - else { - j++; - swapItem(ids, coords, j, right); - } + while (right > left) { + if (right - left > 600) { + var n = right - left + 1; + var m = k - left + 1; + var z = Math.log(n); + var s = 0.5 * Math.exp(2 * z / 3); + var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1); + var newLeft = Math.max(left, Math.floor(k - m * s / n + sd)); + var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd)); + select(ids, coords, k, newLeft, newRight, inc); + } + + var t = coords[2 * k + inc]; + var i = left; + var j = right; + + swapItem(ids, coords, left, k); + if (coords[2 * right + inc] > t) swapItem(ids, coords, left, right); - if (j <= k) left = j + 1; - if (k <= j) right = j - 1; + while (i < j) { + swapItem(ids, coords, i, j); + i++; + j--; + while (coords[2 * i + inc] < t) i++; + while (coords[2 * j + inc] > t) j--; } - } - function swapItem(ids, coords, i, j) { - swap(ids, i, j); - swap(coords, 2 * i, 2 * j); - swap(coords, 2 * i + 1, 2 * j + 1); - } + if (coords[2 * left + inc] === t) swapItem(ids, coords, left, j); + else { + j++; + swapItem(ids, coords, j, right); + } - function swap(arr, i, j) { - var tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; + if (j <= k) left = j + 1; + if (k <= j) right = j - 1; } - - function within(ids, coords, qx, qy, r, nodeSize) { - var stack = [0, ids.length - 1, 0]; - var result = []; - var r2 = r * r; - - while (stack.length) { - var axis = stack.pop(); - var right = stack.pop(); - var left = stack.pop(); - - if (right - left <= nodeSize) { - for (var i = left; i <= right; i++) { - if (sqDist(coords[2 * i], coords[2 * i + 1], qx, qy) <= r2) result.push(ids[i]); - } - continue; +} + +function swapItem(ids, coords, i, j) { + swap(ids, i, j); + swap(coords, 2 * i, 2 * j); + swap(coords, 2 * i + 1, 2 * j + 1); +} + +function swap(arr, i, j) { + var tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; +} + +},{}],4:[function(require,module,exports){ +'use strict'; + +module.exports = within; + +function within(ids, coords, qx, qy, r, nodeSize) { + var stack = [0, ids.length - 1, 0]; + var result = []; + var r2 = r * r; + + while (stack.length) { + var axis = stack.pop(); + var right = stack.pop(); + var left = stack.pop(); + + if (right - left <= nodeSize) { + for (var i = left; i <= right; i++) { + if (sqDist(coords[2 * i], coords[2 * i + 1], qx, qy) <= r2) result.push(ids[i]); } + continue; + } - var m = Math.floor((left + right) / 2); + var m = Math.floor((left + right) / 2); - var x = coords[2 * m]; - var y = coords[2 * m + 1]; + var x = coords[2 * m]; + var y = coords[2 * m + 1]; - if (sqDist(x, y, qx, qy) <= r2) result.push(ids[m]); + if (sqDist(x, y, qx, qy) <= r2) result.push(ids[m]); - var nextAxis = (axis + 1) % 2; + var nextAxis = (axis + 1) % 2; - if (axis === 0 ? qx - r <= x : qy - r <= y) { - stack.push(left); - stack.push(m - 1); - stack.push(nextAxis); - } - if (axis === 0 ? qx + r >= x : qy + r >= y) { - stack.push(m + 1); - stack.push(right); - stack.push(nextAxis); - } + if (axis === 0 ? qx - r <= x : qy - r <= y) { + stack.push(left); + stack.push(m - 1); + stack.push(nextAxis); + } + if (axis === 0 ? qx + r >= x : qy + r >= y) { + stack.push(m + 1); + stack.push(right); + stack.push(nextAxis); } - - return result; } - function sqDist(ax, ay, bx, by) { - var dx = ax - bx; - var dy = ay - by; - return dx * dx + dy * dy; - } + return result; +} + +function sqDist(ax, ay, bx, by) { + var dx = ax - bx; + var dy = ay - by; + return dx * dx + dy * dy; +} - return kdbush; -}); +},{}]},{},[1])(1) +}); \ No newline at end of file From 63fef4f435a83ea8a2416d0b1b7de0a999fbce51 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 19 Aug 2016 15:03:23 -0400 Subject: [PATCH 009/191] Keep current clusters when possible. --- Source/Scene/LabelCollectionDeclutter.js | 156 +++++++++++++++++------ 1 file changed, 114 insertions(+), 42 deletions(-) diff --git a/Source/Scene/LabelCollectionDeclutter.js b/Source/Scene/LabelCollectionDeclutter.js index ffdf5ff40ae9..3c521267c942 100644 --- a/Source/Scene/LabelCollectionDeclutter.js +++ b/Source/Scene/LabelCollectionDeclutter.js @@ -1,24 +1,30 @@ /*global define*/ define([ '../Core/BoundingRectangle', + '../Core/Cartesian2', '../Core/Cartesian3', '../Core/defaultValue', '../Core/defined', '../Core/destroyObject', '../Core/EllipsoidalOccluder', + '../Core/Matrix4', '../ThirdParty/kdbush', + './Billboard', './HorizontalOrigin', './LabelCollection', './SceneTransforms', './VerticalOrigin' ], function( BoundingRectangle, + Cartesian2, Cartesian3, defaultValue, defined, destroyObject, EllipsoidalOccluder, + Matrix4, kdbush, + Billboard, HorizontalOrigin, LabelCollection, SceneTransforms, @@ -33,7 +39,7 @@ define([ return point.coord.y; } - function getBBox(label, coord) { + function getLabelBoundingBox(label, coord, pixelRange) { // TODO: create this at label creation time var width = 0; var height = Number.NEGATIVE_INFINITY; @@ -65,16 +71,51 @@ define([ y -= height * 0.5; } + x += pixelRange; + y += pixelRange; + width += pixelRange * 0.5; + height += pixelRange * 0.5; + return new BoundingRectangle(x, y, width, height); } + function cloneLabel(label) { + return { + text : label.text, + show : label.show, + font : label.font, + fillColor : label.fillColor, + outlineColor : label.outlineColor, + outlineWidth : label.outlineWidth, + style : label.outlineStyle, + verticalOrigin : label.verticalOrigin, + horizontalOrigin : label.horizontalOrigin, + pixelOffset : label.pixelOffset, + eyeOffset : label.eyeOffset, + position : label.position, + scale : label.scale, + id : label.id, + translucencyByDistance : label.translucencyByDistance, + pixelOffsetScaleByDistance : label.pixelOffsetScaleByDistance, + heightReference : label.heightReference + }; + } + function createDeclutterCallback(labelCollectionDeclutter) { return function() { + var scene = labelCollectionDeclutter._scene; + var labelCollection = labelCollectionDeclutter._labelCollection; var renderCollection = labelCollectionDeclutter._renderCollection; - var scene = labelCollectionDeclutter._scene; + var pixelRange = labelCollectionDeclutter._pixelRange; + var clusters = labelCollectionDeclutter._previousClusters; + var newClusters = []; + + var previousHeight = labelCollectionDeclutter._previousHeight; + var currentHeight = scene.camera.positionCartographic.height; + if (defined(renderCollection)) { renderCollection.removeAll(); } else { @@ -87,6 +128,7 @@ define([ var i; var label; + var coord; var length = labelCollection.length; var points = []; @@ -96,7 +138,7 @@ define([ continue; } - var coord = label.computeScreenSpacePosition(scene); + coord = label.computeScreenSpacePosition(scene); if (!defined(coord) || coord.x < 0.0 || coord.x > scene.drawingBufferWidth || coord.y < 0.0 || coord.y > scene.drawingBufferHeight) { continue; } @@ -108,9 +150,53 @@ define([ }); } + var j; + var bbox; + var neighbors; + var neighborLength; + var neighborIndex; + var neighborPoint; + var index = kdbush(points, getX, getY, 64, Int32Array); - length = points.length; + if (currentHeight <= previousHeight) { + length = clusters.length; + for (i = 0; i < length; ++i) { + var cluster = clusters[i]; + + if (!occluder.isPointVisible(cluster.position)) { + continue; + } + + coord = Billboard._computeScreenSpacePosition(Matrix4.IDENTITY, cluster.position, Cartesian3.ZERO, Cartesian2.ZERO, scene); + if (!defined(coord) || coord.x < 0.0 || coord.x > scene.drawingBufferWidth || coord.y < 0.0 || coord.y > scene.drawingBufferHeight) { + continue; + } + + neighbors = index.within(coord.x, coord.y, cluster.radius); + neighborLength = neighbors.length; + numPoints = 0; + + for (j = 0; j < neighborLength; ++j) { + neighborIndex = neighbors[j]; + neighborPoint = points[neighborIndex]; + if (!neighborPoint.clustered) { + neighborPoint.clustered = true; + ++numPoints; + } + } + + if (numPoints > 1) { + newClusters.push(cluster); + renderCollection.add({ + text : '' + numPoints, + position : cluster.position + }); + } + } + } + + length = points.length; for (i = 0; i < length; ++i) { var point = points[i]; if (point.clustered) { @@ -120,59 +206,40 @@ define([ point.clustered = true; label = labelCollection.get(point.labelIndex); - var bbox = getBBox(label, point.coord); - - bbox.x += pixelRange; - bbox.y += pixelRange; - bbox.width += pixelRange * 0.5; - bbox.height += pixelRange * 0.5; + bbox = getLabelBoundingBox(label, point.coord, pixelRange); - var neighbors = index.within(bbox.x, bbox.y, bbox.width); + neighbors = index.within(bbox.x, bbox.y, bbox.width); + neighborLength = neighbors.length; - var neighborsFound = false; - var clusterPosition = new Cartesian3(); - var numPoints = 0; + var clusterPosition = Cartesian3.clone(label.position); + var numPoints = 1; - var neighborLength = neighbors.length; - for (var j = 0; j < neighborLength; ++j) { - var neighborIndex = neighbors[j]; - var neighborPoint = points[neighborIndex]; + for (j = 0; j < neighborLength; ++j) { + neighborIndex = neighbors[j]; + neighborPoint = points[neighborIndex]; if (!neighborPoint.clustered) { neighborPoint.clustered = true; - neighborsFound = true; - Cartesian3.add(clusterPosition, labelCollection.get(neighborPoint.labelIndex).position, clusterPosition); + var neighborLabel = labelCollection.get(neighborPoint.labelIndex); + Cartesian3.add(clusterPosition, neighborLabel.position, clusterPosition); + BoundingRectangle.union(bbox, getLabelBoundingBox(neighborLabel, neighborPoint.coord, pixelRange), bbox); ++numPoints; } } - if (!neighborsFound) { - var clone = { - text : label.text, - show : label.show, - font : label.font, - fillColor : label.fillColor, - outlineColor : label.outlineColor, - outlineWidth : label.outlineWidth, - style : label.outlineStyle, - verticalOrigin : label.verticalOrigin, - horizontalOrigin : label.horizontalOrigin, - pixelOffset : label.pixelOffset, - eyeOffset : label.eyeOffset, - position : label.position, - scale : label.scale, - id : label.id, - translucencyByDistance : label.translucencyByDistance, - pixelOffsetScaleByDistance : label.pixelOffsetScaleByDistance, - heightReference : label.heightReference - }; - renderCollection.add(clone); + if (numPoints === 1) { + renderCollection.add(cloneLabel(label)); } else { var position = Cartesian3.multiplyByScalar(clusterPosition, 1.0 / numPoints, clusterPosition); renderCollection.add({ - text : '' + (numPoints + 1), + text : '' + numPoints, position : position }); + + newClusters.push({ + position : position, + radius : Math.max(bbox.width, bbox.height) * 0.5 + }); } } @@ -182,6 +249,8 @@ define([ } labelCollectionDeclutter._renderCollection = renderCollection; + labelCollectionDeclutter._previousClusters = newClusters; + labelCollectionDeclutter._previousHeight = currentHeight; }; } @@ -192,6 +261,9 @@ define([ this._pixelRange = defaultValue(options.pixelRange, 5); + this._previousClusters = []; + this._previousHeight = undefined; + this._removeEventListener = this._scene.camera.moveEnd.addEventListener(createDeclutterCallback(this)); } From 7ff5b7fb2529b26f58796daa91d5326a91acefef Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 22 Aug 2016 14:22:13 -0400 Subject: [PATCH 010/191] Add semi-continuous clustering and fix labels clamped to the ground. --- Source/Scene/LabelCollectionDeclutter.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Source/Scene/LabelCollectionDeclutter.js b/Source/Scene/LabelCollectionDeclutter.js index 3c521267c942..c5c99329b20b 100644 --- a/Source/Scene/LabelCollectionDeclutter.js +++ b/Source/Scene/LabelCollectionDeclutter.js @@ -49,6 +49,10 @@ define([ for (var i = 0; i < length; ++i) { var glyph = glyphs[i]; var billboard = glyph.billboard; + if (!defined(billboard)) { + continue; + } + width += billboard.width; height = Math.max(height, billboard.height); } @@ -102,7 +106,11 @@ define([ } function createDeclutterCallback(labelCollectionDeclutter) { - return function() { + return function(amount) { + if (defined(amount) && amount < 0.05) { + return; + } + var scene = labelCollectionDeclutter._scene; var labelCollection = labelCollectionDeclutter._labelCollection; @@ -119,7 +127,9 @@ define([ if (defined(renderCollection)) { renderCollection.removeAll(); } else { - renderCollection = new LabelCollection(); + renderCollection = new LabelCollection({ + scene : scene + }); } var ellipsoid = scene.mapProjection.ellipsoid; @@ -264,7 +274,8 @@ define([ this._previousClusters = []; this._previousHeight = undefined; - this._removeEventListener = this._scene.camera.moveEnd.addEventListener(createDeclutterCallback(this)); + //this._removeEventListener = this._scene.camera.moveEnd.addEventListener(createDeclutterCallback(this)); + this._removeEventListener = this._scene.camera.changed.addEventListener(createDeclutterCallback(this)); } LabelCollectionDeclutter.prototype.update = function(frameState) { From 89785c765907c45d499efa2c5af9a4615ff7d7ef Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 22 Aug 2016 15:11:22 -0400 Subject: [PATCH 011/191] Picking a cluster returns all clustered items. --- Apps/Sandcastle/gallery/development/Labels.html | 13 +++++++++++++ Source/Scene/LabelCollectionDeclutter.js | 16 +++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/Apps/Sandcastle/gallery/development/Labels.html b/Apps/Sandcastle/gallery/development/Labels.html index 0b70b90ee8d8..7dbe524638a2 100644 --- a/Apps/Sandcastle/gallery/development/Labels.html +++ b/Apps/Sandcastle/gallery/development/Labels.html @@ -64,6 +64,19 @@ labelCollection : labels, scene : scene })); + + var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas); + handler.setInputAction(function(movement) { + var pickedLabel = scene.pick(movement.position); + if (Cesium.defined(pickedLabel)) { + var ids = pickedLabel.id; + if (Cesium.isArray(ids)) { + for (var i = 0; i < ids.length; ++i) { + ids[i].fillColor = Cesium.Color.RED; + } + } + } + }, Cesium.ScreenSpaceEventType.LEFT_CLICK); //Sandcastle_End Sandcastle.finishedLoading(); } diff --git a/Source/Scene/LabelCollectionDeclutter.js b/Source/Scene/LabelCollectionDeclutter.js index c5c99329b20b..69440a19f659 100644 --- a/Source/Scene/LabelCollectionDeclutter.js +++ b/Source/Scene/LabelCollectionDeclutter.js @@ -166,6 +166,8 @@ define([ var neighborLength; var neighborIndex; var neighborPoint; + var ids; + var numPoints; var index = kdbush(points, getX, getY, 64, Int32Array); @@ -186,6 +188,7 @@ define([ neighbors = index.within(coord.x, coord.y, cluster.radius); neighborLength = neighbors.length; numPoints = 0; + ids = []; for (j = 0; j < neighborLength; ++j) { neighborIndex = neighbors[j]; @@ -193,6 +196,8 @@ define([ if (!neighborPoint.clustered) { neighborPoint.clustered = true; ++numPoints; + + ids.push(labelCollection.get(neighborPoint.labelIndex)); } } @@ -200,7 +205,8 @@ define([ newClusters.push(cluster); renderCollection.add({ text : '' + numPoints, - position : cluster.position + position : cluster.position, + id : ids }); } } @@ -222,7 +228,8 @@ define([ neighborLength = neighbors.length; var clusterPosition = Cartesian3.clone(label.position); - var numPoints = 1; + numPoints = 1; + ids = []; for (j = 0; j < neighborLength; ++j) { neighborIndex = neighbors[j]; @@ -234,6 +241,8 @@ define([ Cartesian3.add(clusterPosition, neighborLabel.position, clusterPosition); BoundingRectangle.union(bbox, getLabelBoundingBox(neighborLabel, neighborPoint.coord, pixelRange), bbox); ++numPoints; + + ids.push(labelCollection.get(neighborPoint.labelIndex)); } } @@ -243,7 +252,8 @@ define([ var position = Cartesian3.multiplyByScalar(clusterPosition, 1.0 / numPoints, clusterPosition); renderCollection.add({ text : '' + numPoints, - position : position + position : position, + id : ids }); newClusters.push({ From 93d3c7641f330c483b4d964fc2003055dcd5a49f Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 23 Aug 2016 15:53:14 -0400 Subject: [PATCH 012/191] Add label clustering to the entity layer. --- .../gallery/development/Labels.html | 16 +- Source/DataSources/DataSourceDisplay.js | 10 + Source/DataSources/EntityCluster.js | 342 ++++++++++++++++++ Source/DataSources/EntityCollection.js | 1 + Source/DataSources/LabelVisualizer.js | 50 +-- 5 files changed, 366 insertions(+), 53 deletions(-) create mode 100644 Source/DataSources/EntityCluster.js diff --git a/Apps/Sandcastle/gallery/development/Labels.html b/Apps/Sandcastle/gallery/development/Labels.html index 7dbe524638a2..5ac286b87c74 100644 --- a/Apps/Sandcastle/gallery/development/Labels.html +++ b/Apps/Sandcastle/gallery/development/Labels.html @@ -28,7 +28,6 @@ 'use strict'; //Sandcastle_Begin var viewer = new Cesium.Viewer('cesiumContainer'); - var scene = viewer.scene; var minLat = 22.0; var maxLat = 51.0; @@ -41,8 +40,6 @@ var minWordLength = 4; var maxWordLength = 9; - var labels = new Cesium.LabelCollection(); - for(var i = minLat; i < maxLat; i += latIncrement) { for (var j = minLon; j < maxLon; j += lonIncrement) { var position = Cesium.Cartesian3.fromDegrees(j, i); @@ -53,18 +50,16 @@ text += String.fromCharCode(Math.floor((Math.random() * 25.0 + 65.0))); } - labels.add({ + viewer.entities.add({ position : position, - text : text + label : { + text : text + } }); } } - scene.primitives.add(new Cesium.LabelCollectionDeclutter({ - labelCollection : labels, - scene : scene - })); - + /* var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas); handler.setInputAction(function(movement) { var pickedLabel = scene.pick(movement.position); @@ -77,6 +72,7 @@ } } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); + */ //Sandcastle_End Sandcastle.finishedLoading(); } diff --git a/Source/DataSources/DataSourceDisplay.js b/Source/DataSources/DataSourceDisplay.js index f28bb9dde0e4..4ac21bc4e619 100644 --- a/Source/DataSources/DataSourceDisplay.js +++ b/Source/DataSources/DataSourceDisplay.js @@ -16,6 +16,7 @@ define([ './CylinderGeometryUpdater', './EllipseGeometryUpdater', './EllipsoidGeometryUpdater', + './EntityCluster', './GeometryVisualizer', './LabelVisualizer', './ModelVisualizer', @@ -43,6 +44,7 @@ define([ CylinderGeometryUpdater, EllipseGeometryUpdater, EllipsoidGeometryUpdater, + EntityCluster, GeometryVisualizer, LabelVisualizer, ModelVisualizer, @@ -354,6 +356,11 @@ define([ DataSourceDisplay.prototype._onDataSourceAdded = function(dataSourceCollection, dataSource) { var visualizers = this._visualizersCallback(this._scene, dataSource); dataSource._visualizers = visualizers; + + var cluster = this._scene.primitives.add(new EntityCluster({ + scene : this._scene + })); + dataSource.entities._cluster = cluster; }; DataSourceDisplay.prototype._onDataSourceRemoved = function(dataSourceCollection, dataSource) { @@ -363,6 +370,9 @@ define([ visualizers[i].destroy(); dataSource._visualizers = undefined; } + + this._scene.primitives.remove(dataSource.entities._cluster); + dataSource.entities._cluster = undefined; }; /** diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js new file mode 100644 index 000000000000..9476019e86dd --- /dev/null +++ b/Source/DataSources/EntityCluster.js @@ -0,0 +1,342 @@ +/*global define*/ +define([ + '../Core/BoundingRectangle', + '../Core/Cartesian2', + '../Core/Cartesian3', + '../Core/defaultValue', + '../Core/defined', + '../Core/destroyObject', + '../Core/EllipsoidalOccluder', + '../Core/Matrix4', + '../Scene/Billboard', + '../Scene/HorizontalOrigin', + '../Scene/LabelCollection', + '../Scene/SceneTransforms', + '../Scene/VerticalOrigin', + '../ThirdParty/kdbush' +], function( + BoundingRectangle, + Cartesian2, + Cartesian3, + defaultValue, + defined, + destroyObject, + EllipsoidalOccluder, + Matrix4, + Billboard, + HorizontalOrigin, + LabelCollection, + SceneTransforms, + VerticalOrigin, + kdbush) { + 'use strict'; + + function getX(point) { + return point.coord.x; + } + + function getY(point) { + return point.coord.y; + } + + function getLabelBoundingBox(label, coord, pixelRange) { + // TODO: create this at label creation time + var width = 0; + var height = Number.NEGATIVE_INFINITY; + + var glyphs = label._glyphs; + var length = glyphs.length; + for (var i = 0; i < length; ++i) { + var glyph = glyphs[i]; + var billboard = glyph.billboard; + if (!defined(billboard)) { + continue; + } + + width += billboard.width; + height = Math.max(height, billboard.height); + } + + var scale = label.scale; + width *= scale; + height *= scale; + + var x = coord.x; + if (label.horizontalOrigin === HorizontalOrigin.RIGHT) { + x -= width; + } else if (label.horizontalOrigin === HorizontalOrigin.CENTER) { + x -= width * 0.5; + } + + var y = coord.y; + if (label.verticalOrigin === VerticalOrigin.TOP) { + y -= height; + } else if (label.verticalOrigin === VerticalOrigin.CENTER) { + y -= height * 0.5; + } + + x += pixelRange; + y += pixelRange; + width += pixelRange * 0.5; + height += pixelRange * 0.5; + + return new BoundingRectangle(x, y, width, height); + } + + function cloneLabel(label) { + return { + text : label.text, + show : label.show, + font : label.font, + fillColor : label.fillColor, + outlineColor : label.outlineColor, + outlineWidth : label.outlineWidth, + style : label.outlineStyle, + verticalOrigin : label.verticalOrigin, + horizontalOrigin : label.horizontalOrigin, + pixelOffset : label.pixelOffset, + eyeOffset : label.eyeOffset, + position : label.position, + scale : label.scale, + id : label.id, + translucencyByDistance : label.translucencyByDistance, + pixelOffsetScaleByDistance : label.pixelOffsetScaleByDistance, + heightReference : label.heightReference + }; + } + + function createDeclutterCallback(entityCluster) { + return function(amount) { + if (defined(amount) && amount < 0.05) { + return; + } + + var scene = entityCluster._scene; + + var labelCollection = entityCluster._labelCollection; + var renderCollection = entityCluster._renderCollection; + + if (!defined(labelCollection)) { + return; + } + + var pixelRange = entityCluster._pixelRange; + + var clusters = entityCluster._previousClusters; + var newClusters = []; + + var previousHeight = entityCluster._previousHeight; + var currentHeight = scene.camera.positionCartographic.height; + + if (defined(renderCollection)) { + renderCollection.removeAll(); + } else { + renderCollection = new LabelCollection({ + scene : scene + }); + } + + var ellipsoid = scene.mapProjection.ellipsoid; + var cameraPosition = scene.camera.positionWC; + var occluder = new EllipsoidalOccluder(ellipsoid, cameraPosition); + + var i; + var label; + var coord; + var length = labelCollection.length; + var points = []; + + for (i = 0; i < length; ++i) { + label = labelCollection.get(i); + if (!occluder.isPointVisible(label.position)) { + continue; + } + + coord = label.computeScreenSpacePosition(scene); + if (!defined(coord) || coord.x < 0.0 || coord.x > scene.drawingBufferWidth || coord.y < 0.0 || coord.y > scene.drawingBufferHeight) { + continue; + } + + points.push({ + labelIndex : i, + clustered : false, + coord : coord + }); + } + + var j; + var bbox; + var neighbors; + var neighborLength; + var neighborIndex; + var neighborPoint; + var ids; + var numPoints; + + var index = kdbush(points, getX, getY, 64, Int32Array); + + if (currentHeight <= previousHeight) { + length = clusters.length; + for (i = 0; i < length; ++i) { + var cluster = clusters[i]; + + if (!occluder.isPointVisible(cluster.position)) { + continue; + } + + coord = Billboard._computeScreenSpacePosition(Matrix4.IDENTITY, cluster.position, Cartesian3.ZERO, Cartesian2.ZERO, scene); + if (!defined(coord) || coord.x < 0.0 || coord.x > scene.drawingBufferWidth || coord.y < 0.0 || coord.y > scene.drawingBufferHeight) { + continue; + } + + neighbors = index.within(coord.x, coord.y, cluster.radius); + neighborLength = neighbors.length; + numPoints = 0; + ids = []; + + for (j = 0; j < neighborLength; ++j) { + neighborIndex = neighbors[j]; + neighborPoint = points[neighborIndex]; + if (!neighborPoint.clustered) { + neighborPoint.clustered = true; + ++numPoints; + + ids.push(labelCollection.get(neighborPoint.labelIndex)); + } + } + + if (numPoints > 1) { + newClusters.push(cluster); + renderCollection.add({ + text : '' + numPoints, + position : cluster.position, + id : ids + }); + } + } + } + + length = points.length; + for (i = 0; i < length; ++i) { + var point = points[i]; + if (point.clustered) { + continue; + } + + point.clustered = true; + + label = labelCollection.get(point.labelIndex); + bbox = getLabelBoundingBox(label, point.coord, pixelRange); + + neighbors = index.within(bbox.x, bbox.y, bbox.width); + neighborLength = neighbors.length; + + var clusterPosition = Cartesian3.clone(label.position); + numPoints = 1; + ids = []; + + for (j = 0; j < neighborLength; ++j) { + neighborIndex = neighbors[j]; + neighborPoint = points[neighborIndex]; + if (!neighborPoint.clustered) { + neighborPoint.clustered = true; + + var neighborLabel = labelCollection.get(neighborPoint.labelIndex); + Cartesian3.add(clusterPosition, neighborLabel.position, clusterPosition); + BoundingRectangle.union(bbox, getLabelBoundingBox(neighborLabel, neighborPoint.coord, pixelRange), bbox); + ++numPoints; + + ids.push(labelCollection.get(neighborPoint.labelIndex)); + } + } + + if (numPoints === 1) { + renderCollection.add(cloneLabel(label)); + } else { + var position = Cartesian3.multiplyByScalar(clusterPosition, 1.0 / numPoints, clusterPosition); + renderCollection.add({ + text : '' + numPoints, + position : position, + id : ids + }); + + newClusters.push({ + position : position, + radius : Math.max(bbox.width, bbox.height) * 0.5 + }); + } + } + + if (renderCollection.length === 0) { + renderCollection.destroy(); + renderCollection = undefined; + } + + entityCluster._renderCollection = renderCollection; + entityCluster._previousClusters = newClusters; + entityCluster._previousHeight = currentHeight; + }; + } + + function EntityCluster(options) { + this._scene = options.scene; + this._pixelRange = defaultValue(options.pixelRange, 5); + + this._labelCollection = undefined; + this._renderCollection = undefined; + + this._previousClusters = []; + this._previousHeight = undefined; + + this._removeEventListener = this._scene.camera.changed.addEventListener(createDeclutterCallback(this)); + } + + EntityCluster.prototype.getLabel = function(entity) { + if (defined(this._labelCollection) && defined(entity._labelIndex)) { + return this._labelCollection.get(entity._labelIndex); + } + + if (!defined(this._labelCollection)) { + this._labelCollection = new LabelCollection({ + scene : this._scene + }); + } + + var label = this._labelCollection.add(); + entity._labelIndex = this._labelCollection.length - 1; + return label; + }; + + EntityCluster.prototype.remove = function(entity) { + if (!defined(this._labelCollection) || !defined(entity._labelIndex)) { + return; + } + + var label = this._labelCollection.get(entity._labelIndex); + label.show = false; + }; + + EntityCluster.prototype.update = function(frameState) { + if (!defined(this._labelCollection)) { + return; + } + + if (!defined(this._renderCollection)) { + this._labelCollection.update(frameState); + } else { + this._renderCollection.update(frameState); + } + }; + + EntityCluster.prototype.isDestroyed = function() { + return false; + }; + + EntityCluster.prototype.destroy = function() { + this._labelCollection = this._labelCollection && this._labelCollection.destroy(); + this._removeEventListener(); + return destroyObject(this); + }; + + return EntityCluster; +}); \ No newline at end of file diff --git a/Source/DataSources/EntityCollection.js b/Source/DataSources/EntityCollection.js index d25b41c5fc1e..f7d060233ba9 100644 --- a/Source/DataSources/EntityCollection.js +++ b/Source/DataSources/EntityCollection.js @@ -76,6 +76,7 @@ define([ this._show = true; this._firing = false; this._refire = false; + this._cluster = undefined; } /** diff --git a/Source/DataSources/LabelVisualizer.js b/Source/DataSources/LabelVisualizer.js index 34183d2b2c94..fb0ebeeac2b9 100644 --- a/Source/DataSources/LabelVisualizer.js +++ b/Source/DataSources/LabelVisualizer.js @@ -11,7 +11,6 @@ define([ '../Core/NearFarScalar', '../Scene/HeightReference', '../Scene/HorizontalOrigin', - '../Scene/LabelCollection', '../Scene/LabelStyle', '../Scene/VerticalOrigin', './BoundingSphereState', @@ -28,7 +27,6 @@ define([ NearFarScalar, HeightReference, HorizontalOrigin, - LabelCollection, LabelStyle, VerticalOrigin, BoundingSphereState, @@ -82,9 +80,6 @@ define([ entityCollection.collectionChanged.addEventListener(LabelVisualizer.prototype._onCollectionChanged, this); - this._scene = scene; - this._unusedIndexes = []; - this._labelCollection = undefined; this._entityCollection = entityCollection; this._items = new AssociativeArray(); @@ -106,7 +101,8 @@ define([ //>>includeEnd('debug'); var items = this._items.values; - var unusedIndexes = this._unusedIndexes; + var cluster = this._entityCollection._cluster; + for (var i = 0, len = items.length; i < len; i++) { var item = items[i]; var entity = item.entity; @@ -123,28 +119,12 @@ define([ if (!show) { //don't bother creating or updating anything else - returnLabel(item, unusedIndexes); + cluster.removeLabel(entity); continue; } if (!defined(label)) { - var labelCollection = this._labelCollection; - if (!defined(labelCollection)) { - labelCollection = this._scene.primitives.add(new LabelCollection({ - scene : this._scene - })); - this._labelCollection = labelCollection; - } - - var length = unusedIndexes.length; - if (length > 0) { - var index = unusedIndexes.pop(); - item.index = index; - label = labelCollection.get(index); - } else { - label = labelCollection.add(); - item.index = labelCollection.length - 1; - } + label = cluster.getLabel(entity); label.id = entity; item.label = label; } @@ -215,17 +195,14 @@ define([ */ LabelVisualizer.prototype.destroy = function() { this._entityCollection.collectionChanged.removeEventListener(LabelVisualizer.prototype._onCollectionChanged, this); - if (defined(this._labelCollection)) { - this._scene.primitives.remove(this._labelCollection); - } return destroyObject(this); }; LabelVisualizer.prototype._onCollectionChanged = function(entityCollection, added, removed, changed) { var i; var entity; - var unusedIndexes = this._unusedIndexes; var items = this._items; + var cluster = this._entityCollection._cluster; for (i = added.length - 1; i > -1; i--) { entity = added[i]; @@ -241,30 +218,17 @@ define([ items.set(entity.id, new EntityData(entity)); } } else { - returnLabel(items.get(entity.id), unusedIndexes); + cluster.removeLabel(entity); items.remove(entity.id); } } for (i = removed.length - 1; i > -1; i--) { entity = removed[i]; - returnLabel(items.get(entity.id), unusedIndexes); + cluster.removeLabel(entity); items.remove(entity.id); } }; - function returnLabel(item, unusedIndexes) { - if (defined(item)) { - var label = item.label; - if (defined(label)) { - unusedIndexes.push(item.index); - label.id = undefined; - label.show = false; - item.label = undefined; - item.index = -1; - } - } - } - return LabelVisualizer; }); From 91b3a13abb351f280a8bf6b7d0e69276f823ec8e Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 23 Aug 2016 15:55:42 -0400 Subject: [PATCH 013/191] Remove lower level, label only clustering. --- Source/Scene/LabelCollectionDeclutter.js | 310 ----------------------- 1 file changed, 310 deletions(-) delete mode 100644 Source/Scene/LabelCollectionDeclutter.js diff --git a/Source/Scene/LabelCollectionDeclutter.js b/Source/Scene/LabelCollectionDeclutter.js deleted file mode 100644 index 69440a19f659..000000000000 --- a/Source/Scene/LabelCollectionDeclutter.js +++ /dev/null @@ -1,310 +0,0 @@ -/*global define*/ -define([ - '../Core/BoundingRectangle', - '../Core/Cartesian2', - '../Core/Cartesian3', - '../Core/defaultValue', - '../Core/defined', - '../Core/destroyObject', - '../Core/EllipsoidalOccluder', - '../Core/Matrix4', - '../ThirdParty/kdbush', - './Billboard', - './HorizontalOrigin', - './LabelCollection', - './SceneTransforms', - './VerticalOrigin' -], function( - BoundingRectangle, - Cartesian2, - Cartesian3, - defaultValue, - defined, - destroyObject, - EllipsoidalOccluder, - Matrix4, - kdbush, - Billboard, - HorizontalOrigin, - LabelCollection, - SceneTransforms, - VerticalOrigin) { - 'use strict'; - - function getX(point) { - return point.coord.x; - } - - function getY(point) { - return point.coord.y; - } - - function getLabelBoundingBox(label, coord, pixelRange) { - // TODO: create this at label creation time - var width = 0; - var height = Number.NEGATIVE_INFINITY; - - var glyphs = label._glyphs; - var length = glyphs.length; - for (var i = 0; i < length; ++i) { - var glyph = glyphs[i]; - var billboard = glyph.billboard; - if (!defined(billboard)) { - continue; - } - - width += billboard.width; - height = Math.max(height, billboard.height); - } - - var scale = label.scale; - width *= scale; - height *= scale; - - var x = coord.x; - if (label.horizontalOrigin === HorizontalOrigin.RIGHT) { - x -= width; - } else if (label.horizontalOrigin === HorizontalOrigin.CENTER) { - x -= width * 0.5; - } - - var y = coord.y; - if (label.verticalOrigin === VerticalOrigin.TOP) { - y -= height; - } else if (label.verticalOrigin === VerticalOrigin.CENTER) { - y -= height * 0.5; - } - - x += pixelRange; - y += pixelRange; - width += pixelRange * 0.5; - height += pixelRange * 0.5; - - return new BoundingRectangle(x, y, width, height); - } - - function cloneLabel(label) { - return { - text : label.text, - show : label.show, - font : label.font, - fillColor : label.fillColor, - outlineColor : label.outlineColor, - outlineWidth : label.outlineWidth, - style : label.outlineStyle, - verticalOrigin : label.verticalOrigin, - horizontalOrigin : label.horizontalOrigin, - pixelOffset : label.pixelOffset, - eyeOffset : label.eyeOffset, - position : label.position, - scale : label.scale, - id : label.id, - translucencyByDistance : label.translucencyByDistance, - pixelOffsetScaleByDistance : label.pixelOffsetScaleByDistance, - heightReference : label.heightReference - }; - } - - function createDeclutterCallback(labelCollectionDeclutter) { - return function(amount) { - if (defined(amount) && amount < 0.05) { - return; - } - - var scene = labelCollectionDeclutter._scene; - - var labelCollection = labelCollectionDeclutter._labelCollection; - var renderCollection = labelCollectionDeclutter._renderCollection; - - var pixelRange = labelCollectionDeclutter._pixelRange; - - var clusters = labelCollectionDeclutter._previousClusters; - var newClusters = []; - - var previousHeight = labelCollectionDeclutter._previousHeight; - var currentHeight = scene.camera.positionCartographic.height; - - if (defined(renderCollection)) { - renderCollection.removeAll(); - } else { - renderCollection = new LabelCollection({ - scene : scene - }); - } - - var ellipsoid = scene.mapProjection.ellipsoid; - var cameraPosition = scene.camera.positionWC; - var occluder = new EllipsoidalOccluder(ellipsoid, cameraPosition); - - var i; - var label; - var coord; - var length = labelCollection.length; - var points = []; - - for (i = 0; i < length; ++i) { - label = labelCollection.get(i); - if (!occluder.isPointVisible(label.position)) { - continue; - } - - coord = label.computeScreenSpacePosition(scene); - if (!defined(coord) || coord.x < 0.0 || coord.x > scene.drawingBufferWidth || coord.y < 0.0 || coord.y > scene.drawingBufferHeight) { - continue; - } - - points.push({ - labelIndex : i, - clustered : false, - coord : coord - }); - } - - var j; - var bbox; - var neighbors; - var neighborLength; - var neighborIndex; - var neighborPoint; - var ids; - var numPoints; - - var index = kdbush(points, getX, getY, 64, Int32Array); - - if (currentHeight <= previousHeight) { - length = clusters.length; - for (i = 0; i < length; ++i) { - var cluster = clusters[i]; - - if (!occluder.isPointVisible(cluster.position)) { - continue; - } - - coord = Billboard._computeScreenSpacePosition(Matrix4.IDENTITY, cluster.position, Cartesian3.ZERO, Cartesian2.ZERO, scene); - if (!defined(coord) || coord.x < 0.0 || coord.x > scene.drawingBufferWidth || coord.y < 0.0 || coord.y > scene.drawingBufferHeight) { - continue; - } - - neighbors = index.within(coord.x, coord.y, cluster.radius); - neighborLength = neighbors.length; - numPoints = 0; - ids = []; - - for (j = 0; j < neighborLength; ++j) { - neighborIndex = neighbors[j]; - neighborPoint = points[neighborIndex]; - if (!neighborPoint.clustered) { - neighborPoint.clustered = true; - ++numPoints; - - ids.push(labelCollection.get(neighborPoint.labelIndex)); - } - } - - if (numPoints > 1) { - newClusters.push(cluster); - renderCollection.add({ - text : '' + numPoints, - position : cluster.position, - id : ids - }); - } - } - } - - length = points.length; - for (i = 0; i < length; ++i) { - var point = points[i]; - if (point.clustered) { - continue; - } - - point.clustered = true; - - label = labelCollection.get(point.labelIndex); - bbox = getLabelBoundingBox(label, point.coord, pixelRange); - - neighbors = index.within(bbox.x, bbox.y, bbox.width); - neighborLength = neighbors.length; - - var clusterPosition = Cartesian3.clone(label.position); - numPoints = 1; - ids = []; - - for (j = 0; j < neighborLength; ++j) { - neighborIndex = neighbors[j]; - neighborPoint = points[neighborIndex]; - if (!neighborPoint.clustered) { - neighborPoint.clustered = true; - - var neighborLabel = labelCollection.get(neighborPoint.labelIndex); - Cartesian3.add(clusterPosition, neighborLabel.position, clusterPosition); - BoundingRectangle.union(bbox, getLabelBoundingBox(neighborLabel, neighborPoint.coord, pixelRange), bbox); - ++numPoints; - - ids.push(labelCollection.get(neighborPoint.labelIndex)); - } - } - - if (numPoints === 1) { - renderCollection.add(cloneLabel(label)); - } else { - var position = Cartesian3.multiplyByScalar(clusterPosition, 1.0 / numPoints, clusterPosition); - renderCollection.add({ - text : '' + numPoints, - position : position, - id : ids - }); - - newClusters.push({ - position : position, - radius : Math.max(bbox.width, bbox.height) * 0.5 - }); - } - } - - if (renderCollection.length === 0) { - renderCollection.destroy(); - renderCollection = undefined; - } - - labelCollectionDeclutter._renderCollection = renderCollection; - labelCollectionDeclutter._previousClusters = newClusters; - labelCollectionDeclutter._previousHeight = currentHeight; - }; - } - - function LabelCollectionDeclutter(options) { - this._scene = options.scene; - this._labelCollection = options.labelCollection; - this._renderCollection = undefined; - - this._pixelRange = defaultValue(options.pixelRange, 5); - - this._previousClusters = []; - this._previousHeight = undefined; - - //this._removeEventListener = this._scene.camera.moveEnd.addEventListener(createDeclutterCallback(this)); - this._removeEventListener = this._scene.camera.changed.addEventListener(createDeclutterCallback(this)); - } - - LabelCollectionDeclutter.prototype.update = function(frameState) { - if (!defined(this._renderCollection)) { - this._labelCollection.update(frameState); - } else { - this._renderCollection.update(frameState); - } - }; - - LabelCollectionDeclutter.prototype.isDestroyed = function() { - return false; - }; - - LabelCollectionDeclutter.prototype.destroy = function() { - this._labelCollection = this._labelCollection && this._labelCollection.destroy(); - this._removeEventListener(); - return destroyObject(this); - }; - - return LabelCollectionDeclutter; -}); \ No newline at end of file From 938a7fe2f000b2dde6a93efaff7c9e995fd17fba Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 23 Aug 2016 16:28:21 -0400 Subject: [PATCH 014/191] Billboards are managed by the cluster but not yet actually clustered. --- .../gallery/development/Labels.html | 5 ++ Source/DataSources/BillboardVisualizer.js | 49 ++---------- Source/DataSources/EntityCluster.js | 79 ++++++++++++++----- 3 files changed, 71 insertions(+), 62 deletions(-) diff --git a/Apps/Sandcastle/gallery/development/Labels.html b/Apps/Sandcastle/gallery/development/Labels.html index 5ac286b87c74..be0d6a4abb0e 100644 --- a/Apps/Sandcastle/gallery/development/Labels.html +++ b/Apps/Sandcastle/gallery/development/Labels.html @@ -52,8 +52,13 @@ viewer.entities.add({ position : position, + /* label : { text : text + }, + */ + billboard : { + image : '../images/facility.gif' } }); } diff --git a/Source/DataSources/BillboardVisualizer.js b/Source/DataSources/BillboardVisualizer.js index 51b252e79970..b00e395ea3e3 100644 --- a/Source/DataSources/BillboardVisualizer.js +++ b/Source/DataSources/BillboardVisualizer.js @@ -10,7 +10,6 @@ define([ '../Core/destroyObject', '../Core/DeveloperError', '../Core/NearFarScalar', - '../Scene/BillboardCollection', '../Scene/HeightReference', '../Scene/HorizontalOrigin', '../Scene/VerticalOrigin', @@ -27,7 +26,6 @@ define([ destroyObject, DeveloperError, NearFarScalar, - BillboardCollection, HeightReference, HorizontalOrigin, VerticalOrigin, @@ -81,9 +79,6 @@ define([ entityCollection.collectionChanged.addEventListener(BillboardVisualizer.prototype._onCollectionChanged, this); - this._scene = scene; - this._unusedIndexes = []; - this._billboardCollection = undefined; this._entityCollection = entityCollection; this._items = new AssociativeArray(); this._onCollectionChanged(entityCollection, entityCollection.values, [], []); @@ -104,7 +99,8 @@ define([ //>>includeEnd('debug'); var items = this._items.values; - var unusedIndexes = this._unusedIndexes; + var cluster = this._entityCollection._cluster; + for (var i = 0, len = items.length; i < len; i++) { var item = items[i]; var entity = item.entity; @@ -121,26 +117,12 @@ define([ if (!show) { //don't bother creating or updating anything else - returnBillboard(item, unusedIndexes); + cluster.removeBillboard(entity); continue; } if (!defined(billboard)) { - var billboardCollection = this._billboardCollection; - if (!defined(billboardCollection)) { - billboardCollection = this._scene.primitives.add(new BillboardCollection({ - scene : this._scene - })); - this._billboardCollection = billboardCollection; - } - - var length = unusedIndexes.length; - if (length > 0) { - billboard = billboardCollection.get(unusedIndexes.pop()); - } else { - billboard = billboardCollection.add(); - } - + billboard = cluster.getBillboard(entity); billboard.id = entity; billboard.image = undefined; item.billboard = billboard; @@ -229,17 +211,14 @@ define([ */ BillboardVisualizer.prototype.destroy = function() { this._entityCollection.collectionChanged.removeEventListener(BillboardVisualizer.prototype._onCollectionChanged, this); - if (defined(this._billboardCollection)) { - this._scene.primitives.remove(this._billboardCollection); - } return destroyObject(this); }; BillboardVisualizer.prototype._onCollectionChanged = function(entityCollection, added, removed, changed) { var i; var entity; - var unusedIndexes = this._unusedIndexes; var items = this._items; + var cluster = this._entityCollection._cluster; for (i = added.length - 1; i > -1; i--) { entity = added[i]; @@ -255,31 +234,17 @@ define([ items.set(entity.id, new EntityData(entity)); } } else { - returnBillboard(items.get(entity.id), unusedIndexes); + cluster.removeBillboard(entity); items.remove(entity.id); } } for (i = removed.length - 1; i > -1; i--) { entity = removed[i]; - returnBillboard(items.get(entity.id), unusedIndexes); + cluster.removeBillboard(entity); items.remove(entity.id); } }; - function returnBillboard(item, unusedIndexes) { - if (defined(item)) { - var billboard = item.billboard; - if (defined(billboard)) { - item.textureValue = undefined; - item.billboard = undefined; - billboard.id = undefined; - billboard.show = false; - billboard.image = undefined; - unusedIndexes.push(billboard._index); - } - } - } - return BillboardVisualizer; }); diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index 9476019e86dd..9f6ed2e3ae1b 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -9,6 +9,7 @@ define([ '../Core/EllipsoidalOccluder', '../Core/Matrix4', '../Scene/Billboard', + '../Scene/BillboardCollection', '../Scene/HorizontalOrigin', '../Scene/LabelCollection', '../Scene/SceneTransforms', @@ -24,6 +25,7 @@ define([ EllipsoidalOccluder, Matrix4, Billboard, + BillboardCollection, HorizontalOrigin, LabelCollection, SceneTransforms, @@ -114,7 +116,7 @@ define([ var scene = entityCluster._scene; var labelCollection = entityCluster._labelCollection; - var renderCollection = entityCluster._renderCollection; + var clusteredLabelCollection = entityCluster._clusteredLabelCollection; if (!defined(labelCollection)) { return; @@ -128,10 +130,10 @@ define([ var previousHeight = entityCluster._previousHeight; var currentHeight = scene.camera.positionCartographic.height; - if (defined(renderCollection)) { - renderCollection.removeAll(); + if (defined(clusteredLabelCollection)) { + clusteredLabelCollection.removeAll(); } else { - renderCollection = new LabelCollection({ + clusteredLabelCollection = new LabelCollection({ scene : scene }); } @@ -148,7 +150,7 @@ define([ for (i = 0; i < length; ++i) { label = labelCollection.get(i); - if (!occluder.isPointVisible(label.position)) { + if (!label.show || !occluder.isPointVisible(label.position)) { continue; } @@ -207,7 +209,7 @@ define([ if (numPoints > 1) { newClusters.push(cluster); - renderCollection.add({ + clusteredLabelCollection.add({ text : '' + numPoints, position : cluster.position, id : ids @@ -251,10 +253,10 @@ define([ } if (numPoints === 1) { - renderCollection.add(cloneLabel(label)); + clusteredLabelCollection.add(cloneLabel(label)); } else { var position = Cartesian3.multiplyByScalar(clusterPosition, 1.0 / numPoints, clusterPosition); - renderCollection.add({ + clusteredLabelCollection.add({ text : '' + numPoints, position : position, id : ids @@ -267,12 +269,12 @@ define([ } } - if (renderCollection.length === 0) { - renderCollection.destroy(); - renderCollection = undefined; + if (clusteredLabelCollection.length === 0) { + clusteredLabelCollection.destroy(); + clusteredLabelCollection = undefined; } - entityCluster._renderCollection = renderCollection; + entityCluster._clusteredLabelCollection = clusteredLabelCollection; entityCluster._previousClusters = newClusters; entityCluster._previousHeight = currentHeight; }; @@ -283,7 +285,10 @@ define([ this._pixelRange = defaultValue(options.pixelRange, 5); this._labelCollection = undefined; - this._renderCollection = undefined; + this._clusteredLabelCollection = undefined; + + this._billboardCollection = undefined; + this._clusteredBillboardCollection = undefined; this._previousClusters = []; this._previousHeight = undefined; @@ -307,7 +312,7 @@ define([ return label; }; - EntityCluster.prototype.remove = function(entity) { + EntityCluster.prototype.removeLabel = function(entity) { if (!defined(this._labelCollection) || !defined(entity._labelIndex)) { return; } @@ -316,15 +321,46 @@ define([ label.show = false; }; - EntityCluster.prototype.update = function(frameState) { - if (!defined(this._labelCollection)) { + EntityCluster.prototype.getBillboard = function(entity) { + if (defined(this._billboardCollection) && defined(entity._billboardIndex)) { + return this._billboardCollection.get(entity._billboardIndex); + } + + if (!defined(this._billboardCollection)) { + this._billboardCollection = new BillboardCollection({ + scene : this._scene + }); + } + + var billboard = this._billboardCollection.add(); + entity._billboardIndex = this._billboardCollection.length - 1; + return billboard; + }; + + EntityCluster.prototype.removeBillboard = function(entity) { + if (!defined(this._billboardCollection) || !defined(entity._billboardIndex)) { return; } - if (!defined(this._renderCollection)) { - this._labelCollection.update(frameState); - } else { - this._renderCollection.update(frameState); + var billboard = this._billboardCollection.get(entity._billboardIndex); + billboard.show = false; + }; + + EntityCluster.prototype.update = function(frameState) { + if (defined(this._labelCollection)) { + if (!defined(this._clusteredLabelCollection)) { + this._labelCollection.update(frameState); + } else { + this._clusteredLabelCollection.update(frameState); + } + } + + if (defined(this._billboardCollection)) { + if (!defined(this._clusteredBillboardCollection)) { + this._billboardCollection.update(frameState); + } else { + this._clusteredBillboardCollection.update(frameState); + } } }; @@ -334,6 +370,9 @@ define([ EntityCluster.prototype.destroy = function() { this._labelCollection = this._labelCollection && this._labelCollection.destroy(); + this._clusteredLabelCollection = this._clusteredLabelCollection && this._clusteredLabelCollection.destroy(); + this._billboardCollection = this._billboardCollection && this._billboardCollection.destroy(); + this._clusteredBillboardCollection = this._clusteredBillboardCollection && this._clusteredBillboardCollection.destroy(); this._removeEventListener(); return destroyObject(this); }; From 13e0eaa39adec155e6fe75d2b215ea433f82fde2 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 23 Aug 2016 17:32:35 -0400 Subject: [PATCH 015/191] Re-add functionality to reuse billboards and labels. --- Source/DataSources/EntityCluster.js | 65 ++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index 9f6ed2e3ae1b..3abd45e403e6 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -290,6 +290,9 @@ define([ this._billboardCollection = undefined; this._clusteredBillboardCollection = undefined; + this._unusedLabelIndices = []; + this._unusedBillboardIndices = []; + this._previousClusters = []; this._previousHeight = undefined; @@ -297,18 +300,30 @@ define([ } EntityCluster.prototype.getLabel = function(entity) { - if (defined(this._labelCollection) && defined(entity._labelIndex)) { - return this._labelCollection.get(entity._labelIndex); + var labelCollection = this._labelCollection; + if (defined(labelCollection) && defined(entity._labelIndex)) { + return labelCollection.get(entity._labelIndex); } - if (!defined(this._labelCollection)) { - this._labelCollection = new LabelCollection({ + if (!defined(labelCollection)) { + labelCollection = this._labelCollection = new LabelCollection({ scene : this._scene }); } - var label = this._labelCollection.add(); - entity._labelIndex = this._labelCollection.length - 1; + var index; + var label; + + var unusedIndices = this._unusedLabelIndices; + if (unusedIndices.length > 0) { + index = unusedIndices.pop(); + label = labelCollection.get(index); + } else { + label = labelCollection.add(); + index = labelCollection.length - 1; + } + + entity._labelIndex = index; return label; }; @@ -317,23 +332,40 @@ define([ return; } - var label = this._labelCollection.get(entity._labelIndex); + var index = entity._labelIndex; + entity._labelIndex = undefined; + + var label = this._labelCollection.get(index); label.show = false; + + this._unusedLabelIndices.push(index); }; EntityCluster.prototype.getBillboard = function(entity) { - if (defined(this._billboardCollection) && defined(entity._billboardIndex)) { - return this._billboardCollection.get(entity._billboardIndex); + var billboardCollection = this._billboardCollection; + if (defined(billboardCollection) && defined(entity._billboardIndex)) { + return billboardCollection.get(entity._billboardIndex); } - if (!defined(this._billboardCollection)) { - this._billboardCollection = new BillboardCollection({ + if (!defined(billboardCollection)) { + billboardCollection = this._billboardCollection = new BillboardCollection({ scene : this._scene }); } - var billboard = this._billboardCollection.add(); - entity._billboardIndex = this._billboardCollection.length - 1; + var index; + var billboard; + + var unusedIndices = this._unusedBillboardIndices; + if (unusedIndices.length > 0) { + index = unusedIndices.pop(); + billboard = billboardCollection.get(index); + } else { + billboard = billboardCollection.add(); + index = billboardCollection.length - 1; + } + + entity._billboardIndex = index; return billboard; }; @@ -342,8 +374,13 @@ define([ return; } - var billboard = this._billboardCollection.get(entity._billboardIndex); + var index = entity._billboardIndex; + entity._billboardIndex = undefined; + + var billboard = this._billboardCollection.get(index); billboard.show = false; + + this._unusedBillboardIndices.push(index); }; EntityCluster.prototype.update = function(frameState) { From b89e35258cb8893efba92b22f6c7b338a9f8290f Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 24 Aug 2016 11:43:35 -0400 Subject: [PATCH 016/191] Add billboard clustering. --- Source/DataSources/EntityCluster.js | 256 ++++++++++++++++++++-------- 1 file changed, 181 insertions(+), 75 deletions(-) diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index 3abd45e403e6..52faf8f92827 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -42,7 +42,6 @@ define([ } function getLabelBoundingBox(label, coord, pixelRange) { - // TODO: create this at label creation time var width = 0; var height = Number.NEGATIVE_INFINITY; @@ -85,6 +84,44 @@ define([ return new BoundingRectangle(x, y, width, height); } + function getBillboardBoundingBox(billboard, coord, pixelRange) { + var width = billboard.width; + var height = billboard.height; + + var scale = billboard.scale; + width *= scale; + height *= scale; + + var x = coord.x; + if (billboard.horizontalOrigin === HorizontalOrigin.RIGHT) { + x += width * 0.5; + } else if (billboard.horizontalOrigin === HorizontalOrigin.LEFT) { + x -= width * 0.5; + } + + var y = coord.y; + if (billboard.verticalOrigin === VerticalOrigin.TOP) { + y -= height; + } else if (billboard.verticalOrigin === VerticalOrigin.CENTER) { + y -= height * 0.5; + } + + x -= pixelRange; + y -= pixelRange; + width += pixelRange * 0.5; + height += pixelRange * 0.5; + + return new BoundingRectangle(x, y, width, height); + } + + function getBoundingBox(item, coord, pixelRange) { + if (defined(item._glyphs)) { + return getLabelBoundingBox(item, coord, pixelRange); + } + + return getBillboardBoundingBox(item, coord, pixelRange); + } + function cloneLabel(label) { return { text : label.text, @@ -107,6 +144,73 @@ define([ }; } + function cloneBillboard(billboard) { + return { + show : billboard.show, + position : billboard.position, + heightReference : billboard.heightReference, + pixelOffset : billboard.pixelOffset, + scaleByDistance : billboard.scaleByDistance, + translucencyByDistance : billboard.translucencyByDistance, + pixelOffsetScaleByDistance : billboard.pixelOffsetScaleByDistance, + eyeOffset : billboard.eyeOffset, + horizontalOrigin : billboard.horizontalOrigin, + verticalOrigin : billboard.verticalOrigin, + scale : billboard.scale, + color : billboard.color, + rotation : billboard.rotation, + alignedAxis : billboard.alignedAxis, + width : billboard.width, + height : billboard.height, + sizeInMeters : billboard.sizeInMeters, + id : billboard.id, + pickPrimitive : billboard.pickPrimitive, + image : billboard.image + }; + } + + function addNonClusteredItem(item, entityCluster) { + if (item._glyphs) { + entityCluster._clusterLabelCollection.add(cloneLabel(item)); + } else { + entityCluster._clusterBillboardCollection.add(cloneBillboard(item)); + } + } + + function addCluster(position, numPoints, ids, entityCluster) { + entityCluster._clusterLabelCollection.add({ + text : '' + numPoints, + position : position, + id : ids + }); + } + + function getScreenSpacePositions(collection, points, scene, occluder) { + if (!defined(collection)) { + return; + } + + var length = collection.length; + for (var i = 0; i < length; ++i) { + var item = collection.get(i); + if (!item.show || !occluder.isPointVisible(item.position)) { + continue; + } + + var coord = item.computeScreenSpacePosition(scene); + if (!defined(coord) || coord.x < 0.0 || coord.x > scene.drawingBufferWidth || coord.y < 0.0 || coord.y > scene.drawingBufferHeight) { + continue; + } + + points.push({ + index : i, + collection : collection, + clustered : false, + coord : coord + }); + } + } + function createDeclutterCallback(entityCluster) { return function(amount) { if (defined(amount) && amount < 0.05) { @@ -116,57 +220,50 @@ define([ var scene = entityCluster._scene; var labelCollection = entityCluster._labelCollection; - var clusteredLabelCollection = entityCluster._clusteredLabelCollection; + var billboardCollection = entityCluster._billboardCollection; - if (!defined(labelCollection)) { + if (!defined(labelCollection) && !defined(billboardCollection)) { return; } - var pixelRange = entityCluster._pixelRange; - - var clusters = entityCluster._previousClusters; - var newClusters = []; - - var previousHeight = entityCluster._previousHeight; - var currentHeight = scene.camera.positionCartographic.height; + var clusteredLabelCollection = entityCluster._clusterLabelCollection; + var clusteredBillboardCollection = entityCluster._clusterBillboardCollection; if (defined(clusteredLabelCollection)) { clusteredLabelCollection.removeAll(); } else { - clusteredLabelCollection = new LabelCollection({ + clusteredLabelCollection = entityCluster._clusterLabelCollection = new LabelCollection({ + scene : scene + }); + } + + if (defined(clusteredBillboardCollection)) { + clusteredBillboardCollection.removeAll(); + } else { + clusteredBillboardCollection = entityCluster._clusterBillboardCollection = new BillboardCollection({ scene : scene }); } + var pixelRange = entityCluster._pixelRange; + + var clusters = entityCluster._previousClusters; + var newClusters = []; + + var previousHeight = entityCluster._previousHeight; + var currentHeight = scene.camera.positionCartographic.height; + var ellipsoid = scene.mapProjection.ellipsoid; var cameraPosition = scene.camera.positionWC; var occluder = new EllipsoidalOccluder(ellipsoid, cameraPosition); - var i; - var label; - var coord; - var length = labelCollection.length; var points = []; + getScreenSpacePositions(labelCollection, points, scene, occluder); + getScreenSpacePositions(billboardCollection, points, scene, occluder); - for (i = 0; i < length; ++i) { - label = labelCollection.get(i); - if (!label.show || !occluder.isPointVisible(label.position)) { - continue; - } - - coord = label.computeScreenSpacePosition(scene); - if (!defined(coord) || coord.x < 0.0 || coord.x > scene.drawingBufferWidth || coord.y < 0.0 || coord.y > scene.drawingBufferHeight) { - continue; - } - - points.push({ - labelIndex : i, - clustered : false, - coord : coord - }); - } - + var i; var j; + var length; var bbox; var neighbors; var neighborLength; @@ -175,6 +272,9 @@ define([ var ids; var numPoints; + var collection; + var collectionIndex; + var index = kdbush(points, getX, getY, 64, Int32Array); if (currentHeight <= previousHeight) { @@ -186,7 +286,7 @@ define([ continue; } - coord = Billboard._computeScreenSpacePosition(Matrix4.IDENTITY, cluster.position, Cartesian3.ZERO, Cartesian2.ZERO, scene); + var coord = Billboard._computeScreenSpacePosition(Matrix4.IDENTITY, cluster.position, Cartesian3.ZERO, Cartesian2.ZERO, scene); if (!defined(coord) || coord.x < 0.0 || coord.x > scene.drawingBufferWidth || coord.y < 0.0 || coord.y > scene.drawingBufferHeight) { continue; } @@ -203,17 +303,15 @@ define([ neighborPoint.clustered = true; ++numPoints; - ids.push(labelCollection.get(neighborPoint.labelIndex)); + collection = neighborPoint.collection; + collectionIndex = neighborPoint.index; + ids.push(collection.get(collectionIndex)); } } if (numPoints > 1) { + addCluster(cluster.position, numPoints, ids, entityCluster); newClusters.push(cluster); - clusteredLabelCollection.add({ - text : '' + numPoints, - position : cluster.position, - id : ids - }); } } } @@ -227,13 +325,20 @@ define([ point.clustered = true; - label = labelCollection.get(point.labelIndex); - bbox = getLabelBoundingBox(label, point.coord, pixelRange); + collection = point.collection; + collectionIndex = point.index; + + var item = collection.get(collectionIndex); + bbox = getBoundingBox(item, point.coord, pixelRange); + + var x = bbox.x + bbox.width * 0.5; + var y = bbox.y + bbox.height * 0.5; + var radius = Math.max(bbox.width, bbox.height) * 0.5; - neighbors = index.within(bbox.x, bbox.y, bbox.width); + neighbors = index.within(x, y, radius); neighborLength = neighbors.length; - var clusterPosition = Cartesian3.clone(label.position); + var clusterPosition = Cartesian3.clone(item.position); numPoints = 1; ids = []; @@ -243,25 +348,23 @@ define([ if (!neighborPoint.clustered) { neighborPoint.clustered = true; - var neighborLabel = labelCollection.get(neighborPoint.labelIndex); - Cartesian3.add(clusterPosition, neighborLabel.position, clusterPosition); - BoundingRectangle.union(bbox, getLabelBoundingBox(neighborLabel, neighborPoint.coord, pixelRange), bbox); + var neighborItem = neighborPoint.collection.get(neighborPoint.index); + var neighborBBox = getBoundingBox(neighborItem, neighborPoint.coord, pixelRange); + + Cartesian3.add(neighborItem.position, clusterPosition, clusterPosition); + + BoundingRectangle.union(bbox, neighborBBox, bbox); ++numPoints; - ids.push(labelCollection.get(neighborPoint.labelIndex)); + ids.push(neighborItem); } } if (numPoints === 1) { - clusteredLabelCollection.add(cloneLabel(label)); + addNonClusteredItem(item, entityCluster); } else { var position = Cartesian3.multiplyByScalar(clusterPosition, 1.0 / numPoints, clusterPosition); - clusteredLabelCollection.add({ - text : '' + numPoints, - position : position, - id : ids - }); - + addCluster(position, numPoints, ids, entityCluster); newClusters.push({ position : position, radius : Math.max(bbox.width, bbox.height) * 0.5 @@ -271,10 +374,14 @@ define([ if (clusteredLabelCollection.length === 0) { clusteredLabelCollection.destroy(); - clusteredLabelCollection = undefined; + entityCluster._clusterLabelCollection = undefined; + } + + if (clusteredBillboardCollection.length === 0) { + clusteredBillboardCollection.destroy(); + entityCluster._clusterBillboardCollection = undefined; } - entityCluster._clusteredLabelCollection = clusteredLabelCollection; entityCluster._previousClusters = newClusters; entityCluster._previousHeight = currentHeight; }; @@ -282,13 +389,14 @@ define([ function EntityCluster(options) { this._scene = options.scene; - this._pixelRange = defaultValue(options.pixelRange, 5); + this._pixelRange = defaultValue(options.pixelRange, 80); this._labelCollection = undefined; - this._clusteredLabelCollection = undefined; - this._billboardCollection = undefined; - this._clusteredBillboardCollection = undefined; + + this._clusterBillboardCollection = undefined; + this._clusterLabelCollection = undefined; + //this._clusterPointCollection = undefined; this._unusedLabelIndices = []; this._unusedBillboardIndices = []; @@ -384,20 +492,16 @@ define([ }; EntityCluster.prototype.update = function(frameState) { - if (defined(this._labelCollection)) { - if (!defined(this._clusteredLabelCollection)) { - this._labelCollection.update(frameState); - } else { - this._clusteredLabelCollection.update(frameState); - } + if (defined(this._clusterLabelCollection)) { + this._clusterLabelCollection.update(frameState); + } else if (defined(this._labelCollection)) { + this._labelCollection.update(frameState); } - if (defined(this._billboardCollection)) { - if (!defined(this._clusteredBillboardCollection)) { - this._billboardCollection.update(frameState); - } else { - this._clusteredBillboardCollection.update(frameState); - } + if (defined(this._clusterBillboardCollection)) { + this._clusterBillboardCollection.update(frameState); + } else if (defined(this._billboardCollection)) { + this._billboardCollection.update(frameState); } }; @@ -407,9 +511,11 @@ define([ EntityCluster.prototype.destroy = function() { this._labelCollection = this._labelCollection && this._labelCollection.destroy(); - this._clusteredLabelCollection = this._clusteredLabelCollection && this._clusteredLabelCollection.destroy(); this._billboardCollection = this._billboardCollection && this._billboardCollection.destroy(); - this._clusteredBillboardCollection = this._clusteredBillboardCollection && this._clusteredBillboardCollection.destroy(); + + this._clusterLabelCollection = this._clusterLabelCollection && this._clusterLabelCollection.destroy(); + this._clusterBillboardCollection = this._clusterBillboardCollection && this._clusterBillboardCollection.destroy(); + this._removeEventListener(); return destroyObject(this); }; From 9c33907ae0c350de04840a6eb940ecd9bb611203 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 24 Aug 2016 13:15:49 -0400 Subject: [PATCH 017/191] Move point collection management to the cluster. --- .../gallery/development/Labels.html | 9 ++- Source/DataSources/EntityCluster.js | 53 +++++++++++++- Source/DataSources/PointVisualizer.js | 72 ++++--------------- 3 files changed, 71 insertions(+), 63 deletions(-) diff --git a/Apps/Sandcastle/gallery/development/Labels.html b/Apps/Sandcastle/gallery/development/Labels.html index be0d6a4abb0e..8b5e83232952 100644 --- a/Apps/Sandcastle/gallery/development/Labels.html +++ b/Apps/Sandcastle/gallery/development/Labels.html @@ -56,9 +56,14 @@ label : { text : text }, - */ billboard : { - image : '../images/facility.gif' + image : '../images/facility.gif', + scale : 2.0 + } + */ + point : { + pixelSize : 10, + color : Cesium.Color.YELLOW } }); } diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index 52faf8f92827..f4766364a803 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -12,6 +12,7 @@ define([ '../Scene/BillboardCollection', '../Scene/HorizontalOrigin', '../Scene/LabelCollection', + '../Scene/PointPrimitiveCollection', '../Scene/SceneTransforms', '../Scene/VerticalOrigin', '../ThirdParty/kdbush' @@ -28,6 +29,7 @@ define([ BillboardCollection, HorizontalOrigin, LabelCollection, + PointPrimitiveCollection, SceneTransforms, VerticalOrigin, kdbush) { @@ -389,17 +391,20 @@ define([ function EntityCluster(options) { this._scene = options.scene; + this._enabled = defaultValue(options.enabled, false); this._pixelRange = defaultValue(options.pixelRange, 80); this._labelCollection = undefined; this._billboardCollection = undefined; + this._pointCollection = undefined; this._clusterBillboardCollection = undefined; this._clusterLabelCollection = undefined; - //this._clusterPointCollection = undefined; + this._clusterPointCollection = undefined; this._unusedLabelIndices = []; this._unusedBillboardIndices = []; + this._unusedPointIndices = []; this._previousClusters = []; this._previousHeight = undefined; @@ -491,6 +496,46 @@ define([ this._unusedBillboardIndices.push(index); }; + EntityCluster.prototype.getPoint = function(entity) { + var pointCollection = this._pointCollection; + if (defined(pointCollection) && defined(entity._pointIndex)) { + return pointCollection.get(entity._pointIndex); + } + + if (!defined(pointCollection)) { + pointCollection = this._pointCollection = new PointPrimitiveCollection(); + } + + var index; + var point; + + var unusedIndices = this._unusedPointIndices; + if (unusedIndices.length > 0) { + index = unusedIndices.pop(); + point = pointCollection.get(index); + } else { + point = pointCollection.add(); + index = pointCollection.length - 1; + } + + entity._pointIndex = index; + return point; + }; + + EntityCluster.prototype.removePoint = function(entity) { + if (!defined(this._pointCollection) || !defined(entity._pointIndex)) { + return; + } + + var index = entity._billboardIndex; + entity._pointIndex = undefined; + + var point = this._pointCollection.get(index); + point.show = false; + + this._unusedPointIndices.push(index); + }; + EntityCluster.prototype.update = function(frameState) { if (defined(this._clusterLabelCollection)) { this._clusterLabelCollection.update(frameState); @@ -503,6 +548,12 @@ define([ } else if (defined(this._billboardCollection)) { this._billboardCollection.update(frameState); } + + if (defined(this.__clusterPointCollection)) { + this._clusterPointCollection.update(frameState); + } else if (defined(this._pointCollection)) { + this._pointCollection.update(frameState); + } }; EntityCluster.prototype.isDestroyed = function() { diff --git a/Source/DataSources/PointVisualizer.js b/Source/DataSources/PointVisualizer.js index b7bbe52fb024..1655b088923d 100644 --- a/Source/DataSources/PointVisualizer.js +++ b/Source/DataSources/PointVisualizer.js @@ -8,9 +8,7 @@ define([ '../Core/destroyObject', '../Core/DeveloperError', '../Core/NearFarScalar', - '../Scene/BillboardCollection', '../Scene/HeightReference', - '../Scene/PointPrimitiveCollection', './BoundingSphereState', './Property' ], function( @@ -22,9 +20,7 @@ define([ destroyObject, DeveloperError, NearFarScalar, - BillboardCollection, HeightReference, - PointPrimitiveCollection, BoundingSphereState, Property) { 'use strict'; @@ -70,12 +66,7 @@ define([ entityCollection.collectionChanged.addEventListener(PointVisualizer.prototype._onCollectionChanged, this); - this._scene = scene; - this._unusedPointIndexes = []; - this._unusedBillboardIndexes = []; this._entityCollection = entityCollection; - this._pointPrimitiveCollection = undefined; - this._billboardCollection = undefined; this._items = new AssociativeArray(); this._onCollectionChanged(entityCollection, entityCollection.values, [], []); } @@ -94,10 +85,8 @@ define([ } //>>includeEnd('debug'); - var scene = this._scene; var items = this._items.values; - var unusedPointIndexes = this._unusedPointIndexes; - var unusedBillboardIndexes = this._unusedBillboardIndexes; + var cluster = this._entityCollection._cluster; for (var i = 0, len = items.length; i < len; i++) { var item = items[i]; var entity = item.entity; @@ -111,53 +100,29 @@ define([ show = defined(position); } if (!show) { - returnPrimitive(item, unusedPointIndexes, unusedBillboardIndexes); + returnPrimitive(item, entity, cluster); continue; } var needsRedraw = false; if ((heightReference !== HeightReference.NONE) && !defined(billboard)) { if (defined(pointPrimitive)) { - returnPrimitive(item, unusedPointIndexes, unusedBillboardIndexes); + returnPrimitive(item, entity, cluster); pointPrimitive = undefined; } - var billboardCollection = this._billboardCollection; - if (!defined(billboardCollection)) { - billboardCollection = new BillboardCollection({scene: scene}); - this._billboardCollection = billboardCollection; - scene.primitives.add(billboardCollection); - } - - if (unusedBillboardIndexes.length > 0) { - billboard = billboardCollection.get(unusedBillboardIndexes.pop()); - } else { - billboard = billboardCollection.add(); - } - + billboard = cluster.getBillboard(entity); billboard.id = entity; billboard.image = undefined; item.billboard = billboard; needsRedraw = true; } else if ((heightReference === HeightReference.NONE) && !defined(pointPrimitive)) { if (defined(billboard)) { - returnPrimitive(item, unusedPointIndexes, unusedBillboardIndexes); + returnPrimitive(item, entity, cluster); billboard = undefined; } - var pointPrimitiveCollection = this._pointPrimitiveCollection; - if (!defined(pointPrimitiveCollection)) { - pointPrimitiveCollection = new PointPrimitiveCollection(); - this._pointPrimitiveCollection = pointPrimitiveCollection; - scene.primitives.add(pointPrimitiveCollection); - } - - if (unusedPointIndexes.length > 0) { - pointPrimitive = pointPrimitiveCollection.get(unusedPointIndexes.pop()); - } else { - pointPrimitive = pointPrimitiveCollection.add(); - } - + pointPrimitive = cluster.getPoint(entity); pointPrimitive.id = entity; item.pointPrimitive = pointPrimitive; } @@ -271,21 +236,14 @@ define([ */ PointVisualizer.prototype.destroy = function() { this._entityCollection.collectionChanged.removeEventListener(PointVisualizer.prototype._onCollectionChanged, this); - if (defined(this._pointPrimitiveCollection)) { - this._scene.primitives.remove(this._pointPrimitiveCollection); - } - if (defined(this._billboardCollection)) { - this._scene.primitives.remove(this._billboardCollection); - } return destroyObject(this); }; PointVisualizer.prototype._onCollectionChanged = function(entityCollection, added, removed, changed) { var i; var entity; - var unusedPointIndexes = this._unusedPointIndexes; - var unusedBillboardIndexes = this._unusedBillboardIndexes; var items = this._items; + var cluster = this._entityCollection._cluster; for (i = added.length - 1; i > -1; i--) { entity = added[i]; @@ -301,34 +259,28 @@ define([ items.set(entity.id, new EntityData(entity)); } } else { - returnPrimitive(items.get(entity.id), unusedPointIndexes, unusedBillboardIndexes); + returnPrimitive(items.get(entity.id), entity, cluster); items.remove(entity.id); } } for (i = removed.length - 1; i > -1; i--) { entity = removed[i]; - returnPrimitive(items.get(entity.id), unusedPointIndexes, unusedBillboardIndexes); + returnPrimitive(items.get(entity.id), entity, cluster); items.remove(entity.id); } }; - function returnPrimitive(item, unusedPointIndexes, unusedBillboardIndexes) { + function returnPrimitive(item, entity, cluster) { if (defined(item)) { var pointPrimitive = item.pointPrimitive; if (defined(pointPrimitive)) { - item.pointPrimitive = undefined; - pointPrimitive.id = undefined; - pointPrimitive.show = false; - unusedPointIndexes.push(pointPrimitive._index); + cluster.removePoint(entity); return; } var billboard = item.billboard; if (defined(billboard)) { - item.billboard = undefined; - billboard.id = undefined; - billboard.show = false; - unusedBillboardIndexes.push(billboard._index); + cluster.removeBillboard(entity); } } } From 9c32a4e4f4000e298a7dbca81a22916b65b947dd Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 24 Aug 2016 13:52:43 -0400 Subject: [PATCH 018/191] Add point clustering. --- Source/DataSources/EntityCluster.js | 98 ++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 9 deletions(-) diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index f4766364a803..b41428a09b8e 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -5,6 +5,7 @@ define([ '../Core/Cartesian3', '../Core/defaultValue', '../Core/defined', + '../Core/defineProperties', '../Core/destroyObject', '../Core/EllipsoidalOccluder', '../Core/Matrix4', @@ -22,6 +23,7 @@ define([ Cartesian3, defaultValue, defined, + defineProperties, destroyObject, EllipsoidalOccluder, Matrix4, @@ -116,12 +118,26 @@ define([ return new BoundingRectangle(x, y, width, height); } + function getPointBoundingBox(point, coord, pixelRange) { + var size = point.pixelSize; + var halfSize = size * 0.5; + + var x = coord.x - halfSize - pixelRange * 0.5; + var y = coord.y - halfSize - pixelRange * 0.5; + var width = size + pixelRange; + var height = size + pixelRange; + + return new BoundingRectangle(x, y, width, height); + } + function getBoundingBox(item, coord, pixelRange) { - if (defined(item._glyphs)) { + if (defined(item._labelCollection)) { return getLabelBoundingBox(item, coord, pixelRange); + } else if (defined(item._billboardCollection)) { + return getBillboardBoundingBox(item, coord, pixelRange); + } else if (defined(item._pointPrimitiveCollection)) { + return getPointBoundingBox(item, coord, pixelRange); } - - return getBillboardBoundingBox(item, coord, pixelRange); } function cloneLabel(label) { @@ -171,11 +187,27 @@ define([ }; } + function clonePoint(point) { + return { + show : point.show, + position : point.position, + scaleByDistance : point.scaleByDistance, + translucencyByDistance : point.translucencyByDistance, + pixelSize : point.pixelSize, + color : point.color, + outlineColor : point.outlineColor, + outlineWidth : point.outlineWidth, + id : point.id + }; + } + function addNonClusteredItem(item, entityCluster) { - if (item._glyphs) { + if (defined(item._labelCollection)) { entityCluster._clusterLabelCollection.add(cloneLabel(item)); - } else { + } else if (defined(item._billboardCollection)) { entityCluster._clusterBillboardCollection.add(cloneBillboard(item)); + } else if (defined(item._pointPrimitiveCollection)) { + entityCluster._clusterPointCollection.add(clonePoint(item)); } } @@ -215,7 +247,7 @@ define([ function createDeclutterCallback(entityCluster) { return function(amount) { - if (defined(amount) && amount < 0.05) { + if ((defined(amount) && amount < 0.05) || !entityCluster.enabled) { return; } @@ -223,13 +255,15 @@ define([ var labelCollection = entityCluster._labelCollection; var billboardCollection = entityCluster._billboardCollection; + var pointCollection = entityCluster._pointCollection; - if (!defined(labelCollection) && !defined(billboardCollection)) { + if (!defined(labelCollection) && !defined(billboardCollection) && !defined(pointCollection)) { return; } var clusteredLabelCollection = entityCluster._clusterLabelCollection; var clusteredBillboardCollection = entityCluster._clusterBillboardCollection; + var clusteredPointCollection = entityCluster._clusterPointCollection; if (defined(clusteredLabelCollection)) { clusteredLabelCollection.removeAll(); @@ -247,6 +281,12 @@ define([ }); } + if (defined(clusteredPointCollection)) { + clusteredPointCollection.removeAll(); + } else { + clusteredPointCollection = entityCluster._clusterPointCollection = new PointPrimitiveCollection(); + } + var pixelRange = entityCluster._pixelRange; var clusters = entityCluster._previousClusters; @@ -262,6 +302,7 @@ define([ var points = []; getScreenSpacePositions(labelCollection, points, scene, occluder); getScreenSpacePositions(billboardCollection, points, scene, occluder); + getScreenSpacePositions(pointCollection, points, scene, occluder); var i; var j; @@ -384,6 +425,11 @@ define([ entityCluster._clusterBillboardCollection = undefined; } + if (clusteredPointCollection.length === 0) { + clusteredPointCollection.destroy(); + entityCluster._clusterPointCollection = undefined; + } + entityCluster._previousClusters = newClusters; entityCluster._previousHeight = currentHeight; }; @@ -391,7 +437,7 @@ define([ function EntityCluster(options) { this._scene = options.scene; - this._enabled = defaultValue(options.enabled, false); + this._enabled = true;//defaultValue(options.enabled, false); this._pixelRange = defaultValue(options.pixelRange, 80); this._labelCollection = undefined; @@ -409,9 +455,23 @@ define([ this._previousClusters = []; this._previousHeight = undefined; + this._enabledDirty = false; + this._removeEventListener = this._scene.camera.changed.addEventListener(createDeclutterCallback(this)); } + defineProperties(EntityCluster.prototype, { + enabled : { + get : function() { + return this._enabled; + }, + set : function(value) { + this._enabledDirty = value !== this._enabled; + this._enabled = value; + } + } + }); + EntityCluster.prototype.getLabel = function(entity) { var labelCollection = this._labelCollection; if (defined(labelCollection) && defined(entity._labelIndex)) { @@ -537,6 +597,24 @@ define([ }; EntityCluster.prototype.update = function(frameState) { + if (this._enabledDirty) { + this._enabledDirty = false; + + if (defined(this._clusterLabelCollection)) { + this._clusterLabelCollection.destroy(); + } + if (defined(this._clusterBillboardCollection)) { + this._clusterBillboardCollection.destroy(); + } + if (defined(this.__clusterPointCollection)) { + this._clusterPointCollection.destroy(); + } + + this._clusterLabelCollection = undefined; + this._clusterBillboardCollection = undefined; + this._clusterPointCollection = undefined; + } + if (defined(this._clusterLabelCollection)) { this._clusterLabelCollection.update(frameState); } else if (defined(this._labelCollection)) { @@ -549,7 +627,7 @@ define([ this._billboardCollection.update(frameState); } - if (defined(this.__clusterPointCollection)) { + if (defined(this._clusterPointCollection)) { this._clusterPointCollection.update(frameState); } else if (defined(this._pointCollection)) { this._pointCollection.update(frameState); @@ -563,9 +641,11 @@ define([ EntityCluster.prototype.destroy = function() { this._labelCollection = this._labelCollection && this._labelCollection.destroy(); this._billboardCollection = this._billboardCollection && this._billboardCollection.destroy(); + this._pointCollection = this._pointCollection && this._pointCollection.destroy(); this._clusterLabelCollection = this._clusterLabelCollection && this._clusterLabelCollection.destroy(); this._clusterBillboardCollection = this._clusterBillboardCollection && this._clusterBillboardCollection.destroy(); + this._clusterPointCollection = this._clusterPointCollection && this._clusterPointCollection.destroy(); this._removeEventListener(); return destroyObject(this); From 77bdd4779ade159e37576bf6dd95088ca918c853 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 24 Aug 2016 14:51:22 -0400 Subject: [PATCH 019/191] Cluster entities with either a billboard or point and a label as one object. --- Source/DataSources/EntityCluster.js | 34 +++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index b41428a09b8e..74e690b84ea8 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -130,14 +130,24 @@ define([ return new BoundingRectangle(x, y, width, height); } - function getBoundingBox(item, coord, pixelRange) { + function getBoundingBox(item, coord, pixelRange, entityCluster) { + var bbox; + if (defined(item._labelCollection)) { - return getLabelBoundingBox(item, coord, pixelRange); + bbox = getLabelBoundingBox(item, coord, pixelRange); } else if (defined(item._billboardCollection)) { - return getBillboardBoundingBox(item, coord, pixelRange); + bbox = getBillboardBoundingBox(item, coord, pixelRange); } else if (defined(item._pointPrimitiveCollection)) { - return getPointBoundingBox(item, coord, pixelRange); + bbox = getPointBoundingBox(item, coord, pixelRange); + } + + if (!defined(item._labelCollection) && defined(item.id._label)) { + var labelIndex = item.id._labelIndex; + var label = entityCluster._labelCollection.get(labelIndex); + bbox = BoundingRectangle.union(bbox, getLabelBoundingBox(label, coord, pixelRange), bbox); } + + return bbox; } function cloneLabel(label) { @@ -209,6 +219,12 @@ define([ } else if (defined(item._pointPrimitiveCollection)) { entityCluster._clusterPointCollection.add(clonePoint(item)); } + + if (!defined(item._labelCollection) && defined(item.id._label)) { + var labelIndex = item.id._labelIndex; + var label = entityCluster._labelCollection.get(labelIndex); + entityCluster._clusterLabelCollection.add(cloneLabel(label)); + } } function addCluster(position, numPoints, ids, entityCluster) { @@ -231,6 +247,10 @@ define([ continue; } + if (defined(item._labelCollection) && (defined(item.id._billboard) || defined(item.id._point))) { + continue; + } + var coord = item.computeScreenSpacePosition(scene); if (!defined(coord) || coord.x < 0.0 || coord.x > scene.drawingBufferWidth || coord.y < 0.0 || coord.y > scene.drawingBufferHeight) { continue; @@ -372,7 +392,7 @@ define([ collectionIndex = point.index; var item = collection.get(collectionIndex); - bbox = getBoundingBox(item, point.coord, pixelRange); + bbox = getBoundingBox(item, point.coord, pixelRange, entityCluster); var x = bbox.x + bbox.width * 0.5; var y = bbox.y + bbox.height * 0.5; @@ -392,7 +412,7 @@ define([ neighborPoint.clustered = true; var neighborItem = neighborPoint.collection.get(neighborPoint.index); - var neighborBBox = getBoundingBox(neighborItem, neighborPoint.coord, pixelRange); + var neighborBBox = getBoundingBox(neighborItem, neighborPoint.coord, pixelRange, entityCluster); Cartesian3.add(neighborItem.position, clusterPosition, clusterPosition); @@ -606,7 +626,7 @@ define([ if (defined(this._clusterBillboardCollection)) { this._clusterBillboardCollection.destroy(); } - if (defined(this.__clusterPointCollection)) { + if (defined(this._clusterPointCollection)) { this._clusterPointCollection.destroy(); } From 40a08959d3565805b6c55cf71688aa16c96b91c0 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 24 Aug 2016 15:06:53 -0400 Subject: [PATCH 020/191] Fix issue with combined labels and billboards where if all billboards were clustered all of the billboards would be rendered. --- .../gallery/development/Labels.html | 4 +-- Source/DataSources/EntityCluster.js | 32 +++++++++++-------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/Apps/Sandcastle/gallery/development/Labels.html b/Apps/Sandcastle/gallery/development/Labels.html index 8b5e83232952..5d3a5f7cb2a1 100644 --- a/Apps/Sandcastle/gallery/development/Labels.html +++ b/Apps/Sandcastle/gallery/development/Labels.html @@ -52,7 +52,6 @@ viewer.entities.add({ position : position, - /* label : { text : text }, @@ -60,11 +59,12 @@ image : '../images/facility.gif', scale : 2.0 } - */ + /* point : { pixelSize : 10, color : Cesium.Color.YELLOW } + */ }); } } diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index 74e690b84ea8..a4ecc46a0781 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -11,6 +11,7 @@ define([ '../Core/Matrix4', '../Scene/Billboard', '../Scene/BillboardCollection', + '../Scene/HeightReference', '../Scene/HorizontalOrigin', '../Scene/LabelCollection', '../Scene/PointPrimitiveCollection', @@ -29,6 +30,7 @@ define([ Matrix4, Billboard, BillboardCollection, + HeightReference, HorizontalOrigin, LabelCollection, PointPrimitiveCollection, @@ -620,19 +622,21 @@ define([ if (this._enabledDirty) { this._enabledDirty = false; - if (defined(this._clusterLabelCollection)) { - this._clusterLabelCollection.destroy(); - } - if (defined(this._clusterBillboardCollection)) { - this._clusterBillboardCollection.destroy(); - } - if (defined(this._clusterPointCollection)) { - this._clusterPointCollection.destroy(); - } + if (!this._enabled) { + if (defined(this._clusterLabelCollection)) { + this._clusterLabelCollection.destroy(); + } + if (defined(this._clusterBillboardCollection)) { + this._clusterBillboardCollection.destroy(); + } + if (defined(this._clusterPointCollection)) { + this._clusterPointCollection.destroy(); + } - this._clusterLabelCollection = undefined; - this._clusterBillboardCollection = undefined; - this._clusterPointCollection = undefined; + this._clusterLabelCollection = undefined; + this._clusterBillboardCollection = undefined; + this._clusterPointCollection = undefined; + } } if (defined(this._clusterLabelCollection)) { @@ -643,13 +647,13 @@ define([ if (defined(this._clusterBillboardCollection)) { this._clusterBillboardCollection.update(frameState); - } else if (defined(this._billboardCollection)) { + } else if (defined(this._billboardCollection) && !defined(this._clusterLabelCollection)) { this._billboardCollection.update(frameState); } if (defined(this._clusterPointCollection)) { this._clusterPointCollection.update(frameState); - } else if (defined(this._pointCollection)) { + } else if (defined(this._pointCollection) && defined(this._clusterLabelCollection)) { this._pointCollection.update(frameState); } }; From 84c798785e4b3819aa87a4e5f53fe529e91ae588 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 24 Aug 2016 17:01:26 -0400 Subject: [PATCH 021/191] Use a better search range for the cluster. --- Source/DataSources/EntityCluster.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index a4ecc46a0781..6af2ea9cbaeb 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -356,7 +356,12 @@ define([ continue; } - neighbors = index.within(coord.x, coord.y, cluster.radius); + var minX = coord.x - cluster.width * 0.5; + var minY = coord.y - cluster.height * 0.5; + var maxX = coord.x + cluster.width; + var maxY = coord.y + cluster.height; + + neighbors = index.range(minX, minY, maxX, maxY); neighborLength = neighbors.length; numPoints = 0; ids = []; @@ -396,11 +401,7 @@ define([ var item = collection.get(collectionIndex); bbox = getBoundingBox(item, point.coord, pixelRange, entityCluster); - var x = bbox.x + bbox.width * 0.5; - var y = bbox.y + bbox.height * 0.5; - var radius = Math.max(bbox.width, bbox.height) * 0.5; - - neighbors = index.within(x, y, radius); + neighbors = index.range(bbox.x, bbox.y, bbox.x + bbox.width, bbox.y + bbox.height); neighborLength = neighbors.length; var clusterPosition = Cartesian3.clone(item.position); @@ -432,7 +433,8 @@ define([ addCluster(position, numPoints, ids, entityCluster); newClusters.push({ position : position, - radius : Math.max(bbox.width, bbox.height) * 0.5 + width : bbox.width, + height : bbox.height }); } } From 8be01837acb871504ec05335c75d85debb549763 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 25 Aug 2016 13:47:21 -0400 Subject: [PATCH 022/191] Add minimum cluster size and slightly improve clusters when zooming in. --- Source/DataSources/EntityCluster.js | 36 +++++++++++++++++++---------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index 6af2ea9cbaeb..9ea4441b3381 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -310,6 +310,7 @@ define([ } var pixelRange = entityCluster._pixelRange; + var minimumClusterSize = entityCluster._minimumClusterSize; var clusters = entityCluster._previousClusters; var newClusters = []; @@ -356,10 +357,17 @@ define([ continue; } - var minX = coord.x - cluster.width * 0.5; - var minY = coord.y - cluster.height * 0.5; - var maxX = coord.x + cluster.width; - var maxY = coord.y + cluster.height; + var factor = 1.0 - currentHeight / previousHeight; + var width = cluster.width = cluster.width * factor; + var height = cluster.height = cluster.height * factor; + + width = Math.max(width, cluster.minimumWidth); + height = Math.max(height, cluster.minimumHeight); + + var minX = coord.x - width * 0.5; + var minY = coord.y - height * 0.5; + var maxX = coord.x + width; + var maxY = coord.y + height; neighbors = index.range(minX, minY, maxX, maxY); neighborLength = neighbors.length; @@ -379,7 +387,7 @@ define([ } } - if (numPoints > 1) { + if (numPoints >= minimumClusterSize) { addCluster(cluster.position, numPoints, ids, entityCluster); newClusters.push(cluster); } @@ -400,6 +408,7 @@ define([ var item = collection.get(collectionIndex); bbox = getBoundingBox(item, point.coord, pixelRange, entityCluster); + var totalBBox = BoundingRectangle.clone(bbox); neighbors = index.range(bbox.x, bbox.y, bbox.x + bbox.width, bbox.y + bbox.height); neighborLength = neighbors.length; @@ -419,23 +428,25 @@ define([ Cartesian3.add(neighborItem.position, clusterPosition, clusterPosition); - BoundingRectangle.union(bbox, neighborBBox, bbox); + BoundingRectangle.union(totalBBox, neighborBBox, totalBBox); ++numPoints; ids.push(neighborItem); } } - if (numPoints === 1) { - addNonClusteredItem(item, entityCluster); - } else { + if (numPoints >= minimumClusterSize) { var position = Cartesian3.multiplyByScalar(clusterPosition, 1.0 / numPoints, clusterPosition); addCluster(position, numPoints, ids, entityCluster); newClusters.push({ position : position, - width : bbox.width, - height : bbox.height + width : totalBBox.width, + height : totalBBox.height, + minimumWidth : bbox.width, + minimumHeight : bbox.height }); + } else { + addNonClusteredItem(item, entityCluster); } } @@ -463,6 +474,7 @@ define([ this._scene = options.scene; this._enabled = true;//defaultValue(options.enabled, false); this._pixelRange = defaultValue(options.pixelRange, 80); + this._minimumClusterSize = defaultValue(options.minimumClusterSize, 2); this._labelCollection = undefined; this._billboardCollection = undefined; @@ -655,7 +667,7 @@ define([ if (defined(this._clusterPointCollection)) { this._clusterPointCollection.update(frameState); - } else if (defined(this._pointCollection) && defined(this._clusterLabelCollection)) { + } else if (defined(this._pointCollection) && !defined(this._clusterLabelCollection)) { this._pointCollection.update(frameState); } }; From dac90cbb89e6162f7d410e59913f3d49c560c2bd Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 25 Aug 2016 14:28:39 -0400 Subject: [PATCH 023/191] Use original billboard/label/point instead of trying to clone them. Billboard images are impossible to clone without reading from the texture atlas. --- Source/DataSources/EntityCluster.js | 73 ++---------------------- Source/Scene/Billboard.js | 14 +++++ Source/Scene/BillboardCollection.js | 2 +- Source/Scene/Label.js | 23 ++++++++ Source/Scene/PointPrimitive.js | 14 +++++ Source/Scene/PointPrimitiveCollection.js | 2 +- 6 files changed, 57 insertions(+), 71 deletions(-) diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index 9ea4441b3381..24020cb73294 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -152,80 +152,13 @@ define([ return bbox; } - function cloneLabel(label) { - return { - text : label.text, - show : label.show, - font : label.font, - fillColor : label.fillColor, - outlineColor : label.outlineColor, - outlineWidth : label.outlineWidth, - style : label.outlineStyle, - verticalOrigin : label.verticalOrigin, - horizontalOrigin : label.horizontalOrigin, - pixelOffset : label.pixelOffset, - eyeOffset : label.eyeOffset, - position : label.position, - scale : label.scale, - id : label.id, - translucencyByDistance : label.translucencyByDistance, - pixelOffsetScaleByDistance : label.pixelOffsetScaleByDistance, - heightReference : label.heightReference - }; - } - - function cloneBillboard(billboard) { - return { - show : billboard.show, - position : billboard.position, - heightReference : billboard.heightReference, - pixelOffset : billboard.pixelOffset, - scaleByDistance : billboard.scaleByDistance, - translucencyByDistance : billboard.translucencyByDistance, - pixelOffsetScaleByDistance : billboard.pixelOffsetScaleByDistance, - eyeOffset : billboard.eyeOffset, - horizontalOrigin : billboard.horizontalOrigin, - verticalOrigin : billboard.verticalOrigin, - scale : billboard.scale, - color : billboard.color, - rotation : billboard.rotation, - alignedAxis : billboard.alignedAxis, - width : billboard.width, - height : billboard.height, - sizeInMeters : billboard.sizeInMeters, - id : billboard.id, - pickPrimitive : billboard.pickPrimitive, - image : billboard.image - }; - } - - function clonePoint(point) { - return { - show : point.show, - position : point.position, - scaleByDistance : point.scaleByDistance, - translucencyByDistance : point.translucencyByDistance, - pixelSize : point.pixelSize, - color : point.color, - outlineColor : point.outlineColor, - outlineWidth : point.outlineWidth, - id : point.id - }; - } - function addNonClusteredItem(item, entityCluster) { - if (defined(item._labelCollection)) { - entityCluster._clusterLabelCollection.add(cloneLabel(item)); - } else if (defined(item._billboardCollection)) { - entityCluster._clusterBillboardCollection.add(cloneBillboard(item)); - } else if (defined(item._pointPrimitiveCollection)) { - entityCluster._clusterPointCollection.add(clonePoint(item)); - } + item._clusterRender = true; if (!defined(item._labelCollection) && defined(item.id._label)) { var labelIndex = item.id._labelIndex; var label = entityCluster._labelCollection.get(labelIndex); - entityCluster._clusterLabelCollection.add(cloneLabel(label)); + label._clusterRender = true; } } @@ -245,6 +178,8 @@ define([ var length = collection.length; for (var i = 0; i < length; ++i) { var item = collection.get(i); + item._clusterRender = false; + if (!item.show || !occluder.isPointVisible(item.position)) { continue; } diff --git a/Source/Scene/Billboard.js b/Source/Scene/Billboard.js index 84f4e39e34b4..535f572785bb 100644 --- a/Source/Scene/Billboard.js +++ b/Source/Scene/Billboard.js @@ -151,6 +151,8 @@ define([ this._removeCallbackFunc = undefined; this._mode = SceneMode.SCENE3D; + this._clusterShow = true; + this._updateClamping(); } @@ -821,6 +823,18 @@ define([ this._actualClampedPosition = Cartesian3.clone(value, this._actualClampedPosition); makeDirty(this, POSITION_INDEX); } + }, + + _clusterRender : { + get : function() { + return this._clusterShow; + }, + set : function(value) { + if (this._clusterShow !== value) { + this._clusterShow = value; + makeDirty(this, SHOW_INDEX); + } + } } }); diff --git a/Source/Scene/BillboardCollection.js b/Source/Scene/BillboardCollection.js index 3e101a01a023..396802a7d54f 100644 --- a/Source/Scene/BillboardCollection.js +++ b/Source/Scene/BillboardCollection.js @@ -791,7 +791,7 @@ define([ var horizontalOrigin = billboard.horizontalOrigin; var heightReference = billboard._heightReference; var verticalOrigin = (heightReference === HeightReference.NONE) ? billboard._verticalOrigin : VerticalOrigin.BOTTOM; - var show = billboard.show; + var show = billboard.show && billboard._clusterRender; // If the color alpha is zero, do not show this billboard. This lets us avoid providing // color during the pick pass and also eliminates a discard in the fragment shader. diff --git a/Source/Scene/Label.js b/Source/Scene/Label.js index 7bf979ef1936..a43259b6a73d 100644 --- a/Source/Scene/Label.js +++ b/Source/Scene/Label.js @@ -100,6 +100,8 @@ define([ this._removeCallbackFunc = undefined; this._mode = undefined; + this._clusterShow = true; + this._updateClamping(); } @@ -701,6 +703,27 @@ define([ } } } + }, + + _clusterRender : { + get : function() { + return this._clusterShow; + }, + set : function(value) { + if (this._clusterShow !== value) { + this._clusterShow = value; + + var glyphs = this._glyphs; + for (var i = 0, len = glyphs.length; i < len; i++) { + var glyph = glyphs[i]; + if (defined(glyph.billboard)) { + // Set all the private values here, because we already clamped to ground + // so we don't want to do it again for every glyph + glyph.billboard._clusterRender = value; + } + } + } + } } }); diff --git a/Source/Scene/PointPrimitive.js b/Source/Scene/PointPrimitive.js index bead41db9798..d3ed11811e61 100644 --- a/Source/Scene/PointPrimitive.js +++ b/Source/Scene/PointPrimitive.js @@ -75,6 +75,8 @@ define([ this._id = options.id; this._collection = defaultValue(options.collection, pointPrimitiveCollection); + this._clusterShow = true; + this._pickId = undefined; this._pointPrimitiveCollection = pointPrimitiveCollection; this._dirty = false; @@ -354,6 +356,18 @@ define([ this._pickId.object.id = value; } } + }, + + _clusterRender : { + get : function() { + return this._clusterShow; + }, + set : function(value) { + if (this._clusterShow !== value) { + this._clusterShow = value; + makeDirty(this, SHOW_INDEX); + } + } } }); diff --git a/Source/Scene/PointPrimitiveCollection.js b/Source/Scene/PointPrimitiveCollection.js index eb9c513e6f89..286d9d3aa70e 100644 --- a/Source/Scene/PointPrimitiveCollection.js +++ b/Source/Scene/PointPrimitiveCollection.js @@ -555,7 +555,7 @@ define([ } } - var show = pointPrimitive.show; + var show = pointPrimitive.show && pointPrimitive._clusterRender; // If the color alphas are zero, do not show this pointPrimitive. This lets us avoid providing // color during the pick pass and also eliminates a discard in the fragment shader. From 6f9bd2ea84c0169a570277bc2b9f204fe0e0c9d6 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 25 Aug 2016 14:39:41 -0400 Subject: [PATCH 024/191] Fix disappearing billboards. --- Source/DataSources/EntityCluster.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index 24020cb73294..1d35b0940d17 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -590,19 +590,21 @@ define([ if (defined(this._clusterLabelCollection)) { this._clusterLabelCollection.update(frameState); - } else if (defined(this._labelCollection)) { - this._labelCollection.update(frameState); } - if (defined(this._clusterBillboardCollection)) { this._clusterBillboardCollection.update(frameState); - } else if (defined(this._billboardCollection) && !defined(this._clusterLabelCollection)) { - this._billboardCollection.update(frameState); } - if (defined(this._clusterPointCollection)) { this._clusterPointCollection.update(frameState); - } else if (defined(this._pointCollection) && !defined(this._clusterLabelCollection)) { + } + + if (defined(this._labelCollection)) { + this._labelCollection.update(frameState); + } + if (defined(this._billboardCollection)) { + this._billboardCollection.update(frameState); + } + if (defined(this._pointCollection)) { this._pointCollection.update(frameState); } }; From 3668914a844ee110019635ad3ce5b7e73c383598 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 25 Aug 2016 15:17:25 -0400 Subject: [PATCH 025/191] Expose properties for pixel range and minimum cluster size. Fix enabling/disabling clustering. --- .../gallery/development/Labels.html | 68 +++++++++++++-- Source/DataSources/EntityCluster.js | 83 +++++++++++++++---- 2 files changed, 127 insertions(+), 24 deletions(-) diff --git a/Apps/Sandcastle/gallery/development/Labels.html b/Apps/Sandcastle/gallery/development/Labels.html index 5d3a5f7cb2a1..2e45610270c6 100644 --- a/Apps/Sandcastle/gallery/development/Labels.html +++ b/Apps/Sandcastle/gallery/development/Labels.html @@ -19,10 +19,39 @@

Loading...

-
+
+ + + + + + + + + + +
pixel range + + +
minimum cluster size + + +
+
+
+ + + + + +
+

Loading...

+
+ + + + + + + + + + +
pixel range + + +
minimum cluster size + + +
+
+
+
+ + + diff --git a/Apps/Sandcastle/gallery/development/Labels.html b/Apps/Sandcastle/gallery/development/Labels.html index b5aadc42a504..99239fe28d34 100644 --- a/Apps/Sandcastle/gallery/development/Labels.html +++ b/Apps/Sandcastle/gallery/development/Labels.html @@ -10,159 +10,167 @@

Loading...

-
- - - - - - - - - - -
pixel range - - -
minimum cluster size - - -
-
-
-
+
- + \ No newline at end of file diff --git a/Source/DataSources/EntityCollection.js b/Source/DataSources/EntityCollection.js index f7d060233ba9..d25b41c5fc1e 100644 --- a/Source/DataSources/EntityCollection.js +++ b/Source/DataSources/EntityCollection.js @@ -76,7 +76,6 @@ define([ this._show = true; this._firing = false; this._refire = false; - this._cluster = undefined; } /** diff --git a/Source/DataSources/KmlDataSource.js b/Source/DataSources/KmlDataSource.js index e7331a059c23..82cdba288fb6 100644 --- a/Source/DataSources/KmlDataSource.js +++ b/Source/DataSources/KmlDataSource.js @@ -2230,9 +2230,7 @@ define([ this._pinBuilder = new PinBuilder(); this._promises = []; this._networkLinks = new AssociativeArray(); - this._entityCluster = new EntityCluster({ - enabled : true - }); + this._entityCluster = new EntityCluster(); this._canvas = canvas; this._camera = camera; From b5eba317177a9fa56924b25ada3ffe36c8acd177 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 26 Aug 2016 17:06:07 -0400 Subject: [PATCH 032/191] Update new Sandcastle example image. --- Apps/Sandcastle/gallery/Clustering.jpg | Bin 0 -> 19881 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Apps/Sandcastle/gallery/Clustering.jpg diff --git a/Apps/Sandcastle/gallery/Clustering.jpg b/Apps/Sandcastle/gallery/Clustering.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9c5a1ab68bbcc178b2307f80faf3eb79eebf515e GIT binary patch literal 19881 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 U0H)-h_L+eBRcNAwO!V0Q*^+JJHvj+t literal 0 HcmV?d00001 From 2eacbb231163a9c1c4cc931422e48fbba923fb17 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Thu, 1 Sep 2016 01:12:19 -0400 Subject: [PATCH 033/191] chore(package): update almond to version 0.3.3 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d526f2887fa0..d95b3a58a782 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "requirejs": "2.2.0" }, "devDependencies": { - "almond": "0.3.2", + "almond": "0.3.3", "aws-sdk": "2.5.4", "bluebird": "3.4.5", "compressible": "2.0.8", From c62bef9dd222878f15e262e02732caaf06618bb3 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 1 Sep 2016 14:46:36 -0400 Subject: [PATCH 034/191] Fix billboard/label/point visualizer tests. --- Source/DataSources/EntityCluster.js | 11 +++- Specs/DataSources/BillboardVisualizerSpec.js | 56 ++++++++++++-------- Specs/DataSources/LabelVisualizerSpec.js | 43 +++++++++------ Specs/DataSources/PointVisualizerSpec.js | 49 ++++++++++------- 4 files changed, 97 insertions(+), 62 deletions(-) diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index 551a66c62e43..bbfed14b4cd0 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -579,6 +579,7 @@ define([ var label = this._labelCollection.get(index); label.show = false; + label.id = undefined; this._unusedLabelIndices.push(index); }; @@ -620,7 +621,9 @@ define([ entity._billboardIndex = undefined; var billboard = this._billboardCollection.get(index); + billboard.id = undefined; billboard.show = false; + billboard.image = undefined; this._unusedBillboardIndices.push(index); }; @@ -656,11 +659,12 @@ define([ return; } - var index = entity._billboardIndex; + var index = entity._pointIndex; entity._pointIndex = undefined; var point = this._pointCollection.get(index); point.show = false; + point.id = undefined; this._unusedPointIndices.push(index); }; @@ -747,7 +751,10 @@ define([ this._clusterBillboardCollection = this._clusterBillboardCollection && this._clusterBillboardCollection.destroy(); this._clusterPointCollection = this._clusterPointCollection && this._clusterPointCollection.destroy(); - this._removeEventListener(); + if (defined(this._removeEventListener)) { + this._removeEventListener(); + this._removeEventListener = undefined; + } this._labelCollection = undefined; this._billboardCollection = undefined; diff --git a/Specs/DataSources/BillboardVisualizerSpec.js b/Specs/DataSources/BillboardVisualizerSpec.js index 10b032f27d04..6d3b96481671 100644 --- a/Specs/DataSources/BillboardVisualizerSpec.js +++ b/Specs/DataSources/BillboardVisualizerSpec.js @@ -11,6 +11,7 @@ defineSuite([ 'DataSources/BillboardGraphics', 'DataSources/BoundingSphereState', 'DataSources/ConstantProperty', + 'DataSources/EntityCluster', 'DataSources/EntityCollection', 'Scene/BillboardCollection', 'Scene/HeightReference', @@ -31,6 +32,7 @@ defineSuite([ BillboardGraphics, BoundingSphereState, ConstantProperty, + EntityCluster, EntityCollection, BillboardCollection, HeightReference, @@ -42,6 +44,7 @@ defineSuite([ 'use strict'; var scene; + var entityCluster; var visualizer; beforeAll(function() { @@ -50,14 +53,21 @@ defineSuite([ }); afterAll(function() { + entityCluster.destroy(); scene.destroyForSpecs(); }); + beforeEach(function() { + entityCluster = new EntityCluster(); + entityCluster._initialize(scene); + }); + afterEach(function() { visualizer = visualizer && visualizer.destroy(); + entityCluster.destroy(); }); - it('constructor throws if no scene is passed.', function() { + it('constructor throws if no entityCluster is passed.', function() { expect(function() { return new BillboardVisualizer(); }).toThrowDeveloperError(); @@ -65,7 +75,7 @@ defineSuite([ it('update throws if no time specified.', function() { var entityCollection = new EntityCollection(); - visualizer = new BillboardVisualizer(scene, entityCollection); + visualizer = new BillboardVisualizer(entityCluster, entityCollection); expect(function() { visualizer.update(); }).toThrowDeveloperError(); @@ -73,7 +83,7 @@ defineSuite([ it('isDestroy returns false until destroyed.', function() { var entityCollection = new EntityCollection(); - visualizer = new BillboardVisualizer(scene, entityCollection); + visualizer = new BillboardVisualizer(entityCluster, entityCollection); expect(visualizer.isDestroyed()).toEqual(false); visualizer.destroy(); expect(visualizer.isDestroyed()).toEqual(true); @@ -82,25 +92,25 @@ defineSuite([ it('removes the listener from the entity collection when destroyed', function() { var entityCollection = new EntityCollection(); - var visualizer = new BillboardVisualizer(scene, entityCollection); + var visualizer = new BillboardVisualizer(entityCluster, entityCollection); expect(entityCollection.collectionChanged.numberOfListeners).toEqual(1); - visualizer = visualizer.destroy(); + visualizer.destroy(); expect(entityCollection.collectionChanged.numberOfListeners).toEqual(0); }); it('object with no billboard does not create a billboard.', function() { var entityCollection = new EntityCollection(); - visualizer = new BillboardVisualizer(scene, entityCollection); + visualizer = new BillboardVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); testObject.position = new ConstantProperty(new Cartesian3(1234, 5678, 9101112)); visualizer.update(JulianDate.now()); - expect(scene.primitives.length).toEqual(0); + expect(entityCluster._billboardCollection).not.toBeDefined(); }); it('object with no position does not create a billboard.', function() { var entityCollection = new EntityCollection(); - visualizer = new BillboardVisualizer(scene, entityCollection); + visualizer = new BillboardVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); var billboard = testObject.billboard = new BillboardGraphics(); @@ -108,12 +118,12 @@ defineSuite([ billboard.image = new ConstantProperty('Data/Images/Blue.png'); visualizer.update(JulianDate.now()); - expect(scene.primitives.length).toEqual(0); + expect(entityCluster._billboardCollection).not.toBeDefined(); }); it('object with no image does not create a billboard.', function() { var entityCollection = new EntityCollection(); - visualizer = new BillboardVisualizer(scene, entityCollection); + visualizer = new BillboardVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); testObject.position = new ConstantProperty(new Cartesian3(1234, 5678, 9101112)); @@ -121,12 +131,12 @@ defineSuite([ billboard.show = new ConstantProperty(true); visualizer.update(JulianDate.now()); - expect(scene.primitives.length).toEqual(0); + expect(entityCluster._billboardCollection).not.toBeDefined(); }); it('A BillboardGraphics causes a Billboard to be created and updated.', function() { var entityCollection = new EntityCollection(); - visualizer = new BillboardVisualizer(scene, entityCollection); + visualizer = new BillboardVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); @@ -156,7 +166,7 @@ defineSuite([ visualizer.update(time); - var billboardCollection = scene.primitives.get(0); + var billboardCollection = entityCluster._billboardCollection; expect(billboardCollection.length).toEqual(1); bb = billboardCollection.get(0); @@ -194,7 +204,7 @@ defineSuite([ it('Reuses primitives when hiding one and showing another', function() { var time = JulianDate.now(); var entityCollection = new EntityCollection(); - visualizer = new BillboardVisualizer(scene, entityCollection); + visualizer = new BillboardVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); testObject.position = new ConstantProperty(new Cartesian3(1234, 5678, 9101112)); @@ -204,7 +214,7 @@ defineSuite([ visualizer.update(time); - var billboardCollection = scene.primitives.get(0); + var billboardCollection = entityCluster._billboardCollection; expect(billboardCollection.length).toEqual(1); testObject.billboard.show = new ConstantProperty(false); @@ -225,7 +235,7 @@ defineSuite([ it('clear hides billboards.', function() { var entityCollection = new EntityCollection(); - visualizer = new BillboardVisualizer(scene, entityCollection); + visualizer = new BillboardVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); @@ -237,7 +247,7 @@ defineSuite([ billboard.image = new ConstantProperty('Data/Images/Blue.png'); visualizer.update(time); - var billboardCollection = scene.primitives.get(0); + var billboardCollection = entityCluster._billboardCollection; expect(billboardCollection.length).toEqual(1); var bb = billboardCollection.get(0); @@ -255,7 +265,7 @@ defineSuite([ it('Visualizer sets entity property.', function() { var entityCollection = new EntityCollection(); - visualizer = new BillboardVisualizer(scene, entityCollection); + visualizer = new BillboardVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); var time = JulianDate.now(); @@ -266,7 +276,7 @@ defineSuite([ billboard.image = new ConstantProperty('Data/Images/Blue.png'); visualizer.update(time); - var billboardCollection = scene.primitives.get(0); + var billboardCollection = entityCluster._billboardCollection; expect(billboardCollection.length).toEqual(1); var bb = billboardCollection.get(0); expect(bb.id).toEqual(testObject); @@ -274,7 +284,7 @@ defineSuite([ it('Computes bounding sphere.', function() { var entityCollection = new EntityCollection(); - visualizer = new BillboardVisualizer(scene, entityCollection); + visualizer = new BillboardVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); var time = JulianDate.now(); @@ -296,7 +306,7 @@ defineSuite([ it('Fails bounding sphere for entity without billboard.', function() { var entityCollection = new EntityCollection(); var testObject = entityCollection.getOrCreateEntity('test'); - visualizer = new BillboardVisualizer(scene, entityCollection); + visualizer = new BillboardVisualizer(entityCluster, entityCollection); visualizer.update(JulianDate.now()); var result = new BoundingSphere(); var state = visualizer.getBoundingSphere(testObject, result); @@ -305,7 +315,7 @@ defineSuite([ it('Compute bounding sphere throws without entity.', function() { var entityCollection = new EntityCollection(); - visualizer = new BillboardVisualizer(scene, entityCollection); + visualizer = new BillboardVisualizer(entityCluster, entityCollection); var result = new BoundingSphere(); expect(function() { visualizer.getBoundingSphere(undefined, result); @@ -315,7 +325,7 @@ defineSuite([ it('Compute bounding sphere throws without result.', function() { var entityCollection = new EntityCollection(); var testObject = entityCollection.getOrCreateEntity('test'); - visualizer = new BillboardVisualizer(scene, entityCollection); + visualizer = new BillboardVisualizer(entityCluster, entityCollection); expect(function() { visualizer.getBoundingSphere(testObject, undefined); }).toThrowDeveloperError(); diff --git a/Specs/DataSources/LabelVisualizerSpec.js b/Specs/DataSources/LabelVisualizerSpec.js index 1d689388a59e..18fbb7c56f02 100644 --- a/Specs/DataSources/LabelVisualizerSpec.js +++ b/Specs/DataSources/LabelVisualizerSpec.js @@ -9,6 +9,7 @@ defineSuite([ 'Core/NearFarScalar', 'DataSources/BoundingSphereState', 'DataSources/ConstantProperty', + 'DataSources/EntityCluster', 'DataSources/EntityCollection', 'DataSources/LabelGraphics', 'Scene/HorizontalOrigin', @@ -27,6 +28,7 @@ defineSuite([ NearFarScalar, BoundingSphereState, ConstantProperty, + EntityCluster, EntityCollection, LabelGraphics, HorizontalOrigin, @@ -38,6 +40,7 @@ defineSuite([ 'use strict'; var scene; + var entityCluster; var visualizer; beforeAll(function() { @@ -49,8 +52,14 @@ defineSuite([ scene.destroyForSpecs(); }); + beforeEach(function() { + entityCluster = new EntityCluster(); + entityCluster._initialize(scene); + }); + afterEach(function() { visualizer = visualizer && visualizer.destroy(); + entityCluster.destroy(); }); it('constructor throws if no scene is passed.', function() { @@ -61,7 +70,7 @@ defineSuite([ it('update throws if no time specified.', function() { var entityCollection = new EntityCollection(); - visualizer = new LabelVisualizer(scene, entityCollection); + visualizer = new LabelVisualizer(entityCluster, entityCollection); expect(function() { visualizer.update(); }).toThrowDeveloperError(); @@ -69,7 +78,7 @@ defineSuite([ it('isDestroy returns false until destroyed.', function() { var entityCollection = new EntityCollection(); - visualizer = new LabelVisualizer(scene, entityCollection); + visualizer = new LabelVisualizer(entityCluster, entityCollection); expect(visualizer.isDestroyed()).toEqual(false); visualizer.destroy(); expect(visualizer.isDestroyed()).toEqual(true); @@ -78,7 +87,7 @@ defineSuite([ it('removes the listener from the entity collection when destroyed', function() { var entityCollection = new EntityCollection(); - var visualizer = new LabelVisualizer(scene, entityCollection); + var visualizer = new LabelVisualizer(entityCluster, entityCollection); expect(entityCollection.collectionChanged.numberOfListeners).toEqual(1); visualizer = visualizer.destroy(); expect(entityCollection.collectionChanged.numberOfListeners).toEqual(0); @@ -86,7 +95,7 @@ defineSuite([ it('object with no label does not create a label.', function() { var entityCollection = new EntityCollection(); - visualizer = new LabelVisualizer(scene, entityCollection); + visualizer = new LabelVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); testObject.position = new ConstantProperty(new Cartesian3(1234, 5678, 9101112)); @@ -96,7 +105,7 @@ defineSuite([ it('object with no position does not create a label.', function() { var entityCollection = new EntityCollection(); - visualizer = new LabelVisualizer(scene, entityCollection); + visualizer = new LabelVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); var label = testObject.label = new LabelGraphics(); @@ -109,7 +118,7 @@ defineSuite([ it('object with no text does not create a label.', function() { var entityCollection = new EntityCollection(); - visualizer = new LabelVisualizer(scene, entityCollection); + visualizer = new LabelVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); testObject.position = new ConstantProperty(new Cartesian3(1234, 5678, 9101112)); @@ -122,7 +131,7 @@ defineSuite([ it('A LabelGraphics causes a label to be created and updated.', function() { var entityCollection = new EntityCollection(); - visualizer = new LabelVisualizer(scene, entityCollection); + visualizer = new LabelVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); @@ -148,7 +157,7 @@ defineSuite([ visualizer.update(time); - var labelCollection = scene.primitives.get(0); + var labelCollection = entityCluster._labelCollection; expect(labelCollection.length).toEqual(1); l = labelCollection.get(0); @@ -210,7 +219,7 @@ defineSuite([ it('Reuses primitives when hiding one and showing another', function() { var time = JulianDate.now(); var entityCollection = new EntityCollection(); - visualizer = new LabelVisualizer(scene, entityCollection); + visualizer = new LabelVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); testObject.position = new ConstantProperty(new Cartesian3(1234, 5678, 9101112)); @@ -220,7 +229,7 @@ defineSuite([ visualizer.update(time); - var labelCollection = scene.primitives.get(0); + var labelCollection = entityCluster._labelCollection; expect(labelCollection.length).toEqual(1); testObject.label.show = new ConstantProperty(false); @@ -241,7 +250,7 @@ defineSuite([ it('clear hides labels.', function() { var entityCollection = new EntityCollection(); - visualizer = new LabelVisualizer(scene, entityCollection); + visualizer = new LabelVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); var time = JulianDate.now(); @@ -252,7 +261,7 @@ defineSuite([ label.text = new ConstantProperty('lorum ipsum'); visualizer.update(time); - var labelCollection = scene.primitives.get(0); + var labelCollection = entityCluster._labelCollection; expect(labelCollection.length).toEqual(1); var l = labelCollection.get(0); expect(l.show).toEqual(true); @@ -267,7 +276,7 @@ defineSuite([ it('Visualizer sets entity property.', function() { var entityCollection = new EntityCollection(); - visualizer = new LabelVisualizer(scene, entityCollection); + visualizer = new LabelVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); var time = JulianDate.now(); @@ -278,7 +287,7 @@ defineSuite([ label.text = new ConstantProperty('lorum ipsum'); visualizer.update(time); - var labelCollection = scene.primitives.get(0); + var labelCollection = entityCluster._labelCollection; expect(labelCollection.length).toEqual(1); var l = labelCollection.get(0); expect(l.id).toEqual(testObject); @@ -286,7 +295,7 @@ defineSuite([ it('Computes bounding sphere.', function() { var entityCollection = new EntityCollection(); - visualizer = new LabelVisualizer(scene, entityCollection); + visualizer = new LabelVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); var time = JulianDate.now(); @@ -317,7 +326,7 @@ defineSuite([ it('Compute bounding sphere throws without entity.', function() { var entityCollection = new EntityCollection(); - visualizer = new LabelVisualizer(scene, entityCollection); + visualizer = new LabelVisualizer(entityCluster, entityCollection); var result = new BoundingSphere(); expect(function() { visualizer.getBoundingSphere(undefined, result); @@ -327,7 +336,7 @@ defineSuite([ it('Compute bounding sphere throws without result.', function() { var entityCollection = new EntityCollection(); var testObject = entityCollection.getOrCreateEntity('test'); - visualizer = new LabelVisualizer(scene, entityCollection); + visualizer = new LabelVisualizer(entityCluster, entityCollection); expect(function() { visualizer.getBoundingSphere(testObject, undefined); }).toThrowDeveloperError(); diff --git a/Specs/DataSources/PointVisualizerSpec.js b/Specs/DataSources/PointVisualizerSpec.js index 593d1dc0c137..b2d40e999174 100644 --- a/Specs/DataSources/PointVisualizerSpec.js +++ b/Specs/DataSources/PointVisualizerSpec.js @@ -11,6 +11,7 @@ defineSuite([ 'Core/NearFarScalar', 'DataSources/BoundingSphereState', 'DataSources/ConstantProperty', + 'DataSources/EntityCluster', 'DataSources/EntityCollection', 'DataSources/PointGraphics', 'Scene/BillboardCollection', @@ -29,6 +30,7 @@ defineSuite([ NearFarScalar, BoundingSphereState, ConstantProperty, + EntityCluster, EntityCollection, PointGraphics, BillboardCollection, @@ -38,6 +40,7 @@ defineSuite([ 'use strict'; var scene; + var entityCluster; var visualizer; beforeAll(function() { @@ -71,8 +74,14 @@ defineSuite([ scene.destroyForSpecs(); }); + beforeEach(function() { + entityCluster = new EntityCluster(); + entityCluster._initialize(scene); + }); + afterEach(function() { visualizer = visualizer && visualizer.destroy(); + entityCluster.destroy(); }); it('constructor throws if no scene is passed.', function() { @@ -84,13 +93,13 @@ defineSuite([ it('constructor throws if no entityCollection is passed.', function() { expect(function() { - return new PointVisualizer(scene, undefined); + return new PointVisualizer(entityCluster, undefined); }).toThrowDeveloperError(); }); it('update throws if no time specified.', function() { var entityCollection = new EntityCollection(); - visualizer = new PointVisualizer(scene, entityCollection); + visualizer = new PointVisualizer(entityCluster, entityCollection); expect(function() { visualizer.update(); }).toThrowDeveloperError(); @@ -98,7 +107,7 @@ defineSuite([ it('isDestroy returns false until destroyed.', function() { var entityCollection = new EntityCollection(); - visualizer = new PointVisualizer(scene, entityCollection); + visualizer = new PointVisualizer(entityCluster, entityCollection); expect(visualizer.isDestroyed()).toEqual(false); visualizer.destroy(); expect(visualizer.isDestroyed()).toEqual(true); @@ -107,7 +116,7 @@ defineSuite([ it('removes the listener from the entity collection when destroyed', function() { var entityCollection = new EntityCollection(); - var visualizer = new PointVisualizer(scene, entityCollection); + var visualizer = new PointVisualizer(entityCluster, entityCollection); expect(entityCollection.collectionChanged.numberOfListeners).toEqual(1); visualizer = visualizer.destroy(); expect(entityCollection.collectionChanged.numberOfListeners).toEqual(0); @@ -115,7 +124,7 @@ defineSuite([ it('object with no point does not create a pointPrimitive.', function() { var entityCollection = new EntityCollection(); - visualizer = new PointVisualizer(scene, entityCollection); + visualizer = new PointVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); testObject.position = new ConstantProperty(new Cartesian3(1234, 5678, 9101112)); @@ -125,7 +134,7 @@ defineSuite([ it('object with no position does not create a pointPrimitive.', function() { var entityCollection = new EntityCollection(); - visualizer = new PointVisualizer(scene, entityCollection); + visualizer = new PointVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); var point = testObject.point = new PointGraphics(); @@ -139,7 +148,7 @@ defineSuite([ var time = JulianDate.now(); var entityCollection = new EntityCollection(); - visualizer = new PointVisualizer(scene, entityCollection); + visualizer = new PointVisualizer(entityCluster, entityCollection); var entity = entityCollection.add({ position : new Cartesian3(1234, 5678, 9101112), @@ -156,7 +165,7 @@ defineSuite([ visualizer.update(time); - var pointPrimitiveCollection = scene.primitives.get(0); + var pointPrimitiveCollection = entityCluster._pointCollection; expect(pointPrimitiveCollection instanceof PointPrimitiveCollection).toBe(true); expect(pointPrimitiveCollection.length).toEqual(1); var pointPrimitive = pointPrimitiveCollection.get(0); @@ -192,7 +201,7 @@ defineSuite([ var time = JulianDate.now(); var entityCollection = new EntityCollection(); - visualizer = new PointVisualizer(scene, entityCollection); + visualizer = new PointVisualizer(entityCluster, entityCollection); var entity = entityCollection.add({ position : new Cartesian3(1234, 5678, 9101112), @@ -210,7 +219,7 @@ defineSuite([ visualizer.update(time); - var billboardCollection = scene.primitives.get(0); + var billboardCollection = entityCluster._billboardCollection; expect(billboardCollection instanceof BillboardCollection).toBe(true); expect(billboardCollection.length).toEqual(1); var billboard = billboardCollection.get(0); @@ -245,7 +254,7 @@ defineSuite([ it('Reuses primitives when hiding one and showing another', function() { var time = JulianDate.now(); var entityCollection = new EntityCollection(); - visualizer = new PointVisualizer(scene, entityCollection); + visualizer = new PointVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); testObject.position = new ConstantProperty(new Cartesian3(1234, 5678, 9101112)); @@ -254,7 +263,7 @@ defineSuite([ visualizer.update(time); - var pointPrimitiveCollection = scene.primitives.get(0); + var pointPrimitiveCollection = entityCluster._pointCollection; expect(pointPrimitiveCollection.length).toEqual(1); testObject.point.show = new ConstantProperty(false); @@ -274,7 +283,7 @@ defineSuite([ it('clear hides pointPrimitives.', function() { var entityCollection = new EntityCollection(); - visualizer = new PointVisualizer(scene, entityCollection); + visualizer = new PointVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); var time = JulianDate.now(); @@ -283,7 +292,7 @@ defineSuite([ point.show = new ConstantProperty(true); visualizer.update(time); - var pointPrimitiveCollection = scene.primitives.get(0); + var pointPrimitiveCollection = entityCluster._pointCollection; expect(pointPrimitiveCollection.length).toEqual(1); var bb = pointPrimitiveCollection.get(0); @@ -297,7 +306,7 @@ defineSuite([ it('Visualizer sets entity property.', function() { var entityCollection = new EntityCollection(); - visualizer = new PointVisualizer(scene, entityCollection); + visualizer = new PointVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); var time = JulianDate.now(); @@ -308,7 +317,7 @@ defineSuite([ visualizer.update(time); - var pointPrimitiveCollection = scene.primitives.get(0); + var pointPrimitiveCollection = entityCluster._pointCollection; expect(pointPrimitiveCollection.length).toEqual(1); var bb = pointPrimitiveCollection.get(0); expect(bb.id).toEqual(testObject); @@ -316,7 +325,7 @@ defineSuite([ it('Computes bounding sphere.', function() { var entityCollection = new EntityCollection(); - visualizer = new PointVisualizer(scene, entityCollection); + visualizer = new PointVisualizer(entityCluster, entityCollection); var testObject = entityCollection.getOrCreateEntity('test'); var time = JulianDate.now(); @@ -338,7 +347,7 @@ defineSuite([ it('Fails bounding sphere for entity without pointPrimitive.', function() { var entityCollection = new EntityCollection(); var testObject = entityCollection.getOrCreateEntity('test'); - visualizer = new PointVisualizer(scene, entityCollection); + visualizer = new PointVisualizer(entityCluster, entityCollection); visualizer.update(JulianDate.now()); var result = new BoundingSphere(); var state = visualizer.getBoundingSphere(testObject, result); @@ -347,7 +356,7 @@ defineSuite([ it('Compute bounding sphere throws without entity.', function() { var entityCollection = new EntityCollection(); - visualizer = new PointVisualizer(scene, entityCollection); + visualizer = new PointVisualizer(entityCluster, entityCollection); var result = new BoundingSphere(); expect(function() { visualizer.getBoundingSphere(undefined, result); @@ -357,7 +366,7 @@ defineSuite([ it('Compute bounding sphere throws without result.', function() { var entityCollection = new EntityCollection(); var testObject = entityCollection.getOrCreateEntity('test'); - visualizer = new PointVisualizer(scene, entityCollection); + visualizer = new PointVisualizer(entityCluster, entityCollection); expect(function() { visualizer.getBoundingSphere(testObject, undefined); }).toThrowDeveloperError(); From 4428886f0ba78b2110c89403f626861f749d14e8 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 1 Sep 2016 15:03:05 -0400 Subject: [PATCH 035/191] Fix DataSourceDisplay tests. --- Specs/MockDataSource.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Specs/MockDataSource.js b/Specs/MockDataSource.js index 3c34659d9fdc..d79fd26d5dce 100644 --- a/Specs/MockDataSource.js +++ b/Specs/MockDataSource.js @@ -1,9 +1,11 @@ /*global define*/ define([ 'Core/Event', + 'DataSources/EntityCluster', 'DataSources/EntityCollection' ], function( Event, + EntityCluster, EntityCollection) { 'use strict'; @@ -18,6 +20,7 @@ define([ this.isLoading = false; this.loadingEvent = new Event(); this.destroyed = false; + this.clustering = new EntityCluster(); } MockDataSource.prototype.update = function() { return true; From e4f7d125ceb9c4bed959d26a6f10fb2a75070e56 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Thu, 1 Sep 2016 17:01:26 -0400 Subject: [PATCH 036/191] chore(package): update bluebird to version 3.4.6 https://greenkeeper.io/ --- package.json | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 77221d7424a8..84e92c3ecbce 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,12 @@ "name": "Analytical Graphics, Inc.", "url": "http://www.agi.com" }, - "contributors": [{ - "name": "Cesium community", - "url": "https://github.com/AnalyticalGraphicsInc/cesium/blob/master/CONTRIBUTORS.md" - }], + "contributors": [ + { + "name": "Cesium community", + "url": "https://github.com/AnalyticalGraphicsInc/cesium/blob/master/CONTRIBUTORS.md" + } + ], "keywords": [ "3D", "webgl", @@ -33,7 +35,7 @@ "devDependencies": { "almond": "0.3.2", "aws-sdk": "2.5.4", - "bluebird": "3.4.5", + "bluebird": "3.4.6", "compressible": "2.0.8", "compression": "1.6.2", "electron-prebuilt": "1.3.4", From da84e507c382691adf292e50b6c6bf2d308cb772 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 1 Sep 2016 19:14:51 -0400 Subject: [PATCH 037/191] Some fixes and added tests for clustering billboards. --- Source/DataSources/EntityCluster.js | 6 +- Specs/DataSources/BillboardVisualizerSpec.js | 1 - Specs/DataSources/EntityClusterSpec.js | 238 +++++++++++++++++++ 3 files changed, 241 insertions(+), 4 deletions(-) create mode 100644 Specs/DataSources/EntityClusterSpec.js diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index bbfed14b4cd0..31c74d581de8 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -124,8 +124,8 @@ define([ x -= pixelRange; y -= pixelRange; - width += pixelRange * 0.5; - height += pixelRange * 0.5; + width += pixelRange * 2.0; + height += pixelRange * 2.0; return new BoundingRectangle(x, y, width, height); } @@ -333,7 +333,7 @@ define([ var index = kdbush(points, getX, getY, 64, Int32Array); - if (currentHeight <= previousHeight) { + if (currentHeight < previousHeight) { length = clusters.length; for (i = 0; i < length; ++i) { var cluster = clusters[i]; diff --git a/Specs/DataSources/BillboardVisualizerSpec.js b/Specs/DataSources/BillboardVisualizerSpec.js index 6d3b96481671..fd8d884c5392 100644 --- a/Specs/DataSources/BillboardVisualizerSpec.js +++ b/Specs/DataSources/BillboardVisualizerSpec.js @@ -53,7 +53,6 @@ defineSuite([ }); afterAll(function() { - entityCluster.destroy(); scene.destroyForSpecs(); }); diff --git a/Specs/DataSources/EntityClusterSpec.js b/Specs/DataSources/EntityClusterSpec.js new file mode 100644 index 000000000000..d413fc1da63c --- /dev/null +++ b/Specs/DataSources/EntityClusterSpec.js @@ -0,0 +1,238 @@ +/*global defineSuite*/ +defineSuite([ + 'DataSources/EntityCluster', + 'Core/Cartesian2', + 'Core/Cartesian3', + 'Core/defineProperties', + 'Core/Ellipsoid', + 'Core/Event', + 'DataSources/Entity', + 'Scene/SceneTransforms', + 'Specs/createCanvas', + 'Specs/createGlobe', + 'Specs/createScene', + ], function( + EntityCluster, + Cartesian2, + Cartesian3, + defineProperties, + Ellipsoid, + Event, + Entity, + SceneTransforms, + createCanvas, + createGlobe, + createScene) { + 'use strict'; + + var scene; + var cluster; + + beforeAll(function() { + scene = createScene({ + canvas : createCanvas(10, 10) + }); + scene.globe = { + ellipsoid : Ellipsoid.WGS84, + _surface : { + tileProvider : { + ready : true + }, + _tileLoadQueue : {}, + _debug : { + tilesWaitingForChildren : 0 + } + }, + beginFrame : function() {}, + update : function() {}, + endFrame : function() {} + + }; + + scene.globe.getHeight = function() { + return 0.0; + }; + + scene.globe.destroy = function() { + }; + + scene.globe._surface.updateHeight = function() { + }; + + scene.globe.terrainProviderChanged = new Event(); + defineProperties(scene.globe, { + terrainProvider : { + set : function(value) { + this.terrainProviderChanged.raiseEvent(value); + } + } + }); + + var camera = scene.camera; + camera.setView({ + destination : Cartesian3.fromDegrees(0.0, 0.0, 10000.0) + }); + + scene.initializeFrame(); + scene.render(); + }); + + afterAll(function() { + scene.destroyForSpecs(); + }); + + afterEach(function() { + cluster = cluster && cluster.destroy(); + }); + + it('constructor sets default properties', function() { + cluster = new EntityCluster(); + expect(cluster.enabled).toEqual(false); + expect(cluster.pixelRange).toEqual(80); + expect(cluster.minimumClusterSize).toEqual(2); + + cluster.enabled = true; + expect(cluster.enabled).toEqual(true); + + cluster.pixelRange = 30; + expect(cluster.pixelRange).toEqual(30); + + cluster.minimumClusterSize = 5; + expect(cluster.minimumClusterSize).toEqual(5); + }); + + it('constructor sets expected properties', function() { + var options = { + enabled : true, + pixelRange : 30, + minimumClusterSize : 5 + }; + cluster = new EntityCluster(options); + expect(cluster.enabled).toEqual(options.enabled); + expect(cluster.pixelRange).toEqual(options.pixelRange); + expect(cluster.minimumClusterSize).toEqual(options.minimumClusterSize); + }); + + function createBillboardImage() { + var canvas = document.createElement('canvas'); + canvas.height = canvas.width = 1; + + var context2D = canvas.getContext('2d'); + context2D.clearRect(0, 0, length, length); + context2D.fillStyle="#FF0000"; + context2D.fillRect(0, 0, length, length); + + return canvas; + } + + it('clusters billboards', function() { + cluster = new EntityCluster(); + cluster._initialize(scene); + + var entity = new Entity(); + var billboard = cluster.getBillboard(entity); + billboard.id = entity; + billboard.image = createBillboardImage(); + billboard.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(0.0, 0.0), 0.5); + + entity = new Entity(); + billboard = cluster.getBillboard(entity); + billboard.id = entity; + billboard.image = createBillboardImage(); + billboard.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(scene.canvas.clientWidth, scene.canvas.clientHeight), 0.5); + + var frameState = scene.frameState; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).not.toBeDefined(); + + cluster.enabled = true; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).toBeDefined(); + expect(cluster._clusterLabelCollection.length).toEqual(1); + + cluster.enabled = false; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).not.toBeDefined(); + }); + + it('pixel range', function() { + cluster = new EntityCluster(); + cluster._initialize(scene); + + var entity = new Entity(); + var billboard = cluster.getBillboard(entity); + billboard.id = entity; + billboard.image = createBillboardImage(); + billboard.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(0.0, 0.0), 0.5); + + entity = new Entity(); + billboard = cluster.getBillboard(entity); + billboard.id = entity; + billboard.image = createBillboardImage(); + billboard.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(scene.canvas.clientWidth, scene.canvas.clientHeight), 0.5); + + var frameState = scene.frameState; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).not.toBeDefined(); + + cluster.enabled = true; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).toBeDefined(); + expect(cluster._clusterLabelCollection.length).toEqual(1); + + cluster.pixelRange = 1; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).not.toBeDefined(); + }); + + it('minimum cluster size', function() { + cluster = new EntityCluster(); + cluster._initialize(scene); + + var entity = new Entity(); + var billboard = cluster.getBillboard(entity); + billboard.id = entity; + billboard.image = createBillboardImage(); + billboard.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(0.0, 0.0), 0.5); + + entity = new Entity(); + billboard = cluster.getBillboard(entity); + billboard.id = entity; + billboard.image = createBillboardImage(); + billboard.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(scene.canvas.clientWidth, 0), 0.5); + + entity = new Entity(); + billboard = cluster.getBillboard(entity); + billboard.id = entity; + billboard.image = createBillboardImage(); + billboard.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(0, scene.canvas.clientHeight), 0.5); + + entity = new Entity(); + billboard = cluster.getBillboard(entity); + billboard.id = entity; + billboard.image = createBillboardImage(); + billboard.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(scene.canvas.clientWidth, scene.canvas.clientHeight), 0.5); + + var frameState = scene.frameState; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).not.toBeDefined(); + + cluster.enabled = true; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).toBeDefined(); + expect(cluster._clusterLabelCollection.length).toEqual(1); + + cluster.minimumClusterSize = 5; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).not.toBeDefined(); + }); +}); \ No newline at end of file From 94b5f5d41664b17713182ad548631ef0c60ea8b9 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Fri, 2 Sep 2016 04:01:48 -0400 Subject: [PATCH 038/191] chore(package): update electron-prebuilt to version 1.3.5 https://greenkeeper.io/ --- package.json | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 77221d7424a8..2061b85d093a 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,12 @@ "name": "Analytical Graphics, Inc.", "url": "http://www.agi.com" }, - "contributors": [{ - "name": "Cesium community", - "url": "https://github.com/AnalyticalGraphicsInc/cesium/blob/master/CONTRIBUTORS.md" - }], + "contributors": [ + { + "name": "Cesium community", + "url": "https://github.com/AnalyticalGraphicsInc/cesium/blob/master/CONTRIBUTORS.md" + } + ], "keywords": [ "3D", "webgl", @@ -36,7 +38,7 @@ "bluebird": "3.4.5", "compressible": "2.0.8", "compression": "1.6.2", - "electron-prebuilt": "1.3.4", + "electron-prebuilt": "1.3.5", "event-stream": "3.3.4", "express": "4.14.0", "globby": "6.0.0", From 81cabec12571d2bddc8440a38aa8accf3e952f4c Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Fri, 2 Sep 2016 09:20:27 -0400 Subject: [PATCH 039/191] chore(package): update aws-sdk to version 2.5.5 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8539a2268770..9f1e57b010ea 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ }, "devDependencies": { "almond": "0.3.3", - "aws-sdk": "2.5.4", + "aws-sdk": "2.5.5", "bluebird": "3.4.6", "compressible": "2.0.8", "compression": "1.6.2", From ec1e31f0fd9e69f38917ef0fa4ef4d6b8e58e528 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 2 Sep 2016 14:08:44 -0400 Subject: [PATCH 040/191] Add more tests and fix issue with label bounds. --- Source/DataSources/EntityCluster.js | 8 +- Specs/DataSources/EntityClusterSpec.js | 104 +++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 4 deletions(-) diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index 31c74d581de8..31a931ba3f77 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -92,10 +92,10 @@ define([ y -= height * 0.5; } - x += pixelRange; - y += pixelRange; - width += pixelRange * 0.5; - height += pixelRange * 0.5; + x -= pixelRange; + y -= pixelRange; + width += pixelRange * 2.0; + height += pixelRange * 2.0; return new BoundingRectangle(x, y, width, height); } diff --git a/Specs/DataSources/EntityClusterSpec.js b/Specs/DataSources/EntityClusterSpec.js index d413fc1da63c..892019d7543a 100644 --- a/Specs/DataSources/EntityClusterSpec.js +++ b/Specs/DataSources/EntityClusterSpec.js @@ -158,6 +158,72 @@ defineSuite([ expect(cluster._clusterLabelCollection).not.toBeDefined(); }); + it('clusters labels', function() { + cluster = new EntityCluster(); + cluster._initialize(scene); + + var entity = new Entity(); + var label = cluster.getLabel(entity); + label.id = entity; + label.text = 'a'; + label.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(0.0, 0.0), 0.5); + + entity = new Entity(); + label = cluster.getLabel(entity); + label.id = entity; + label.text = 'b'; + label.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(scene.canvas.clientWidth, scene.canvas.clientHeight), 0.5); + + var frameState = scene.frameState; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).not.toBeDefined(); + + cluster.enabled = true; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).toBeDefined(); + expect(cluster._clusterLabelCollection.length).toEqual(1); + + cluster.enabled = false; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).not.toBeDefined(); + }); + + it('clusters points', function() { + cluster = new EntityCluster(); + cluster._initialize(scene); + + var entity = new Entity(); + var point = cluster.getPoint(entity); + point.id = entity; + point.pixelSize = 1; + point.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(0.0, 0.0), 0.5); + + entity = new Entity(); + point = cluster.getPoint(entity); + point.id = entity; + point.pixelSize = 1; + point.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(scene.canvas.clientWidth, scene.canvas.clientHeight), 0.5); + + var frameState = scene.frameState; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).not.toBeDefined(); + + cluster.enabled = true; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).toBeDefined(); + expect(cluster._clusterLabelCollection.length).toEqual(1); + + cluster.enabled = false; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).not.toBeDefined(); + }); + it('pixel range', function() { cluster = new EntityCluster(); cluster._initialize(scene); @@ -235,4 +301,42 @@ defineSuite([ expect(cluster._clusterLabelCollection).not.toBeDefined(); }); + + it('clusters around the same point', function() { + cluster = new EntityCluster(); + cluster._initialize(scene); + + var entity = new Entity(); + var billboard = cluster.getBillboard(entity); + billboard.id = entity; + billboard.image = createBillboardImage(); + billboard.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(0.0, 0.0), 0.9); + + entity = new Entity(); + billboard = cluster.getBillboard(entity); + billboard.id = entity; + billboard.image = createBillboardImage(); + billboard.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(scene.canvas.clientWidth, scene.canvas.clientHeight), 0.9); + + var frameState = scene.frameState; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).not.toBeDefined(); + + cluster.enabled = true; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).toBeDefined(); + expect(cluster._clusterLabelCollection.length).toEqual(1); + + var position = Cartesian3.clone(cluster._clusterLabelCollection.get(0).position); + + scene.camera.moveForward(1.0e-6); + cluster.pixelRange = cluster.pixelRange - 1; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).toBeDefined(); + expect(cluster._clusterLabelCollection.length).toEqual(1); + expect(cluster._clusterLabelCollection.get(0).position).toEqual(position); + }); }); \ No newline at end of file From dcb270a7a076afd45c7da1e207dedabbe3e120e2 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 2 Sep 2016 14:20:49 -0400 Subject: [PATCH 041/191] Add custom cluster styling test. --- Source/DataSources/EntityCluster.js | 4 +-- Specs/DataSources/EntityClusterSpec.js | 42 ++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index 31a931ba3f77..43b9825b2747 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -136,8 +136,8 @@ define([ var x = coord.x - halfSize - pixelRange * 0.5; var y = coord.y - halfSize - pixelRange * 0.5; - var width = size + pixelRange; - var height = size + pixelRange; + var width = size + pixelRange * 2.0; + var height = size + pixelRange * 2.0; return new BoundingRectangle(x, y, width, height); } diff --git a/Specs/DataSources/EntityClusterSpec.js b/Specs/DataSources/EntityClusterSpec.js index 892019d7543a..f924f5a2da36 100644 --- a/Specs/DataSources/EntityClusterSpec.js +++ b/Specs/DataSources/EntityClusterSpec.js @@ -339,4 +339,46 @@ defineSuite([ expect(cluster._clusterLabelCollection.length).toEqual(1); expect(cluster._clusterLabelCollection.get(0).position).toEqual(position); }); + + it('custom cluster styling', function() { + cluster = new EntityCluster(); + cluster._initialize(scene); + + cluster.clusterEvent.addEventListener(function(cluster, entity) { + entity.billboard = { + image : createBillboardImage() + }; + entity.label = { + text : 'cluster' + }; + }); + + var entity = new Entity(); + var point = cluster.getPoint(entity); + point.id = entity; + point.pixelSize = 1; + point.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(0.0, 0.0), 0.9); + + entity = new Entity(); + point = cluster.getPoint(entity); + point.id = entity; + point.pixelSize = 1; + point.position = SceneTransforms.drawingBufferToWgs84Coordinates(scene, new Cartesian2(scene.canvas.clientWidth, scene.canvas.clientHeight), 0.9); + + var frameState = scene.frameState; + cluster.update(frameState); + + expect(cluster._clusterBillboardCollection).not.toBeDefined(); + expect(cluster._clusterLabelCollection).not.toBeDefined(); + + cluster.enabled = true; + cluster.update(frameState); + + expect(cluster._clusterLabelCollection).toBeDefined(); + expect(cluster._clusterLabelCollection.length).toEqual(1); + expect(cluster._clusterLabelCollection.get(0).text).toEqual('cluster'); + + expect(cluster._clusterBillboardCollection).toBeDefined(); + expect(cluster._clusterBillboardCollection.length).toEqual(1); + }); }); \ No newline at end of file From ffba07c95594d5edc93afcdd0a41e29e7f9489f6 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 2 Sep 2016 14:23:46 -0400 Subject: [PATCH 042/191] Mark new tests as using WebGL. --- Specs/DataSources/EntityClusterSpec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Specs/DataSources/EntityClusterSpec.js b/Specs/DataSources/EntityClusterSpec.js index f924f5a2da36..984b8e00b80c 100644 --- a/Specs/DataSources/EntityClusterSpec.js +++ b/Specs/DataSources/EntityClusterSpec.js @@ -381,4 +381,4 @@ defineSuite([ expect(cluster._clusterBillboardCollection).toBeDefined(); expect(cluster._clusterBillboardCollection.length).toEqual(1); }); -}); \ No newline at end of file +}, 'WebGL'); From 768d7d16e51998ce47b0f6eb89cbc76368e7f8be Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 2 Sep 2016 15:19:32 -0400 Subject: [PATCH 043/191] Update documentation. --- .../gallery/development/Labels.html | 8 +- Source/DataSources/CustomDataSource.js | 6 + Source/DataSources/CzmlDataSource.js | 6 + Source/DataSources/DataSource.js | 6 + Source/DataSources/EntityCluster.js | 107 +++++++++++++++++- Source/DataSources/GeoJsonDataSource.js | 6 + Source/DataSources/KmlDataSource.js | 6 + 7 files changed, 136 insertions(+), 9 deletions(-) diff --git a/Apps/Sandcastle/gallery/development/Labels.html b/Apps/Sandcastle/gallery/development/Labels.html index 99239fe28d34..f419ca8d1a92 100644 --- a/Apps/Sandcastle/gallery/development/Labels.html +++ b/Apps/Sandcastle/gallery/development/Labels.html @@ -10,10 +10,10 @@ diff --git a/Source/DataSources/CustomDataSource.js b/Source/DataSources/CustomDataSource.js index 69ffed9d8770..da9be5220fa3 100644 --- a/Source/DataSources/CustomDataSource.js +++ b/Source/DataSources/CustomDataSource.js @@ -148,6 +148,12 @@ define([ } }, + /** + * Gets or sets the clustering options for this data source. This object can be shared between multiple data sources. + * + * @memberof CustomDataSource.prototype + * @type {EntityCluster} + */ clustering : { get : function() { return this._entityCluster; diff --git a/Source/DataSources/CzmlDataSource.js b/Source/DataSources/CzmlDataSource.js index e69f430631a4..4f279aaa11ae 100644 --- a/Source/DataSources/CzmlDataSource.js +++ b/Source/DataSources/CzmlDataSource.js @@ -1938,6 +1938,12 @@ define([ } }, + /** + * Gets or sets the clustering options for this data source. This object can be shared between multiple data sources. + * + * @memberof CzmlDataSource.prototype + * @type {EntityCluster} + */ clustering : { get : function() { return this._entityCluster; diff --git a/Source/DataSources/DataSource.js b/Source/DataSources/DataSource.js index 63fb5e54cc5c..a2afc6f7eb64 100644 --- a/Source/DataSources/DataSource.js +++ b/Source/DataSources/DataSource.js @@ -87,6 +87,12 @@ define([ get : DeveloperError.throwInstantiationError }, + /** + * Gets or sets the clustering options for this data source. This object can be shared between multiple data sources. + * + * @memberof DataSource.prototype + * @type {EntityCluster} + */ clustering : { get : DeveloperError.throwInstantiationError } diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index 43b9825b2747..f0fa179aa87f 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -465,10 +465,22 @@ define([ }; } + /** + * Defines how screen space objects (billboards, points, labels) are clustered. + * + * @param {Object} [options] An object with the following properties: + * @param {Boolean} [options.enabled=false] Whether or not to enable clustering. + * @param {Number} [options.pixelRange=80] The pixel range to extend the screen space bounding box. + * @param {Number} [options.minimumClusterSize=2] The minimum number of screen space objects that can be clustered. + * + * @alias EntityCluster + * @constructor + * + * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Clustering.html|Cesium Sandcastle Clustering Demo} + */ function EntityCluster(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); - this._scene = options.scene; this._enabled = defaultValue(options.enabled, false); this._pixelRange = defaultValue(options.pixelRange, 80); this._minimumClusterSize = defaultValue(options.minimumClusterSize, 2); @@ -507,6 +519,11 @@ define([ }; defineProperties(EntityCluster.prototype, { + /** + * Gets or sets whether clustering is enabled. + * @memberof EntityCluster.prototype + * @type {Boolean} + */ enabled : { get : function() { return this._enabled; @@ -516,6 +533,11 @@ define([ this._enabled = value; } }, + /** + * Gets or sets the pixel range to extend the screen space bounding box. + * @memberof EntityCluster.prototype + * @type {Number} + */ pixelRange : { get : function() { return this._pixelRange; @@ -525,6 +547,11 @@ define([ this._pixelRange = value; } }, + /** + * Gets or sets the minimum number of screen space objects that can be clustered. + * @memberof EntityCluster.prototype + * @type {Number} + */ minimumClusterSize : { get : function() { return this._minimumClusterSize; @@ -534,6 +561,11 @@ define([ this._minimumClusterSize = value; } }, + /** + * Gets the event that will be raised when a new cluster will be displayed. The signature of the event listener is {@link EntityCluster~newClusterCallback}. + * @memberof EntityCluster.prototype + * @type {Event} + */ clusterEvent : { get : function() { return this._clusterEvent; @@ -541,6 +573,13 @@ define([ } }); + /** + * Returns a new {@link Label}. + * @param {Entity} entity The entity that will use the returned {@link Label} for visualization. + * @returns {Label} The label that will be used to visualize an entity. + * + * @private + */ EntityCluster.prototype.getLabel = function(entity) { var labelCollection = this._labelCollection; if (defined(labelCollection) && defined(entity._labelIndex)) { @@ -569,6 +608,12 @@ define([ return label; }; + /** + * Removes the {@link Label} associated with an entity so it can be reused by another entity. + * @param {Entity} entity The entity that will uses the returned {@link Label} for visualization. + * + * @private + */ EntityCluster.prototype.removeLabel = function(entity) { if (!defined(this._labelCollection) || !defined(entity._labelIndex)) { return; @@ -584,6 +629,13 @@ define([ this._unusedLabelIndices.push(index); }; + /** + * Returns a new {@link Billboard}. + * @param {Entity} entity The entity that will use the returned {@link Billboard} for visualization. + * @returns {Billboard} The label that will be used to visualize an entity. + * + * @private + */ EntityCluster.prototype.getBillboard = function(entity) { var billboardCollection = this._billboardCollection; if (defined(billboardCollection) && defined(entity._billboardIndex)) { @@ -612,6 +664,12 @@ define([ return billboard; }; + /** + * Removes the {@link Billboard} associated with an entity so it can be reused by another entity. + * @param {Entity} entity The entity that will uses the returned {@link Billboard} for visualization. + * + * @private + */ EntityCluster.prototype.removeBillboard = function(entity) { if (!defined(this._billboardCollection) || !defined(entity._billboardIndex)) { return; @@ -628,6 +686,13 @@ define([ this._unusedBillboardIndices.push(index); }; + /** + * Returns a new {@link Point}. + * @param {Entity} entity The entity that will use the returned {@link Point} for visualization. + * @returns {Point} The label that will be used to visualize an entity. + * + * @private + */ EntityCluster.prototype.getPoint = function(entity) { var pointCollection = this._pointCollection; if (defined(pointCollection) && defined(entity._pointIndex)) { @@ -654,6 +719,12 @@ define([ return point; }; + /** + * Removes the {@link Point} associated with an entity so it can be reused by another entity. + * @param {Entity} entity The entity that will uses the returned {@link Point} for visualization. + * + * @private + */ EntityCluster.prototype.removePoint = function(entity) { if (!defined(this._pointCollection) || !defined(entity._pointIndex)) { return; @@ -705,6 +776,11 @@ define([ disableCollectionClustering(entityCluster._pointCollection); } + /** + * Gets the draw commands for the clustered billboards/points/labels if enabled, otherwise, + * queues the draw commands for billboards/points/labels created for entities. + * @private + */ EntityCluster.prototype.update = function(frameState) { if (this._enabledDirty) { this._enabledDirty = false; @@ -738,10 +814,16 @@ define([ } }; - EntityCluster.prototype.isDestroyed = function() { - return false; - }; - + /** + * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic + * release of WebGL resources, instead of relying on the garbage collector to destroy this object. + *

+ * Unlike other objects that use WebGL resources, this object can be reused. For example, if a data source is removed + * from a data source collection and added to another. + *

+ * + * @returns {undefined} + */ EntityCluster.prototype.destroy = function() { this._labelCollection = this._labelCollection && this._labelCollection.destroy(); this._billboardCollection = this._billboardCollection && this._billboardCollection.destroy(); @@ -778,5 +860,20 @@ define([ return undefined; }; + /** + * A event listener function used to style clusters. + * @callback EntityCluster~newClusterCallback + * + * @param {Entity[]} clusteredEntities An array of the entities contained in the cluster. + * @param {Entity} entity The entity that will be display for the cluster. + * + * @example + * dataSource.clustering.clusterEvent.addEventListener(function(entities, entity) { + * entity.label = { + * text : '' + entities.length + * }; + * }); + */ + return EntityCluster; }); \ No newline at end of file diff --git a/Source/DataSources/GeoJsonDataSource.js b/Source/DataSources/GeoJsonDataSource.js index f37a7a211916..a06d5ac60e21 100644 --- a/Source/DataSources/GeoJsonDataSource.js +++ b/Source/DataSources/GeoJsonDataSource.js @@ -769,6 +769,12 @@ define([ } }, + /** + * Gets or sets the clustering options for this data source. This object can be shared between multiple data sources. + * + * @memberof GeoJsonDataSource.prototype + * @type {EntityCluster} + */ clustering : { get : function() { return this._entityCluster; diff --git a/Source/DataSources/KmlDataSource.js b/Source/DataSources/KmlDataSource.js index 45bd80af9fee..d80403b9fde9 100644 --- a/Source/DataSources/KmlDataSource.js +++ b/Source/DataSources/KmlDataSource.js @@ -2370,6 +2370,12 @@ define([ } }, + /** + * Gets or sets the clustering options for this data source. This object can be shared between multiple data sources. + * + * @memberof KmlDataSource.prototype + * @type {EntityCluster} + */ clustering : { get : function() { return this._entityCluster; From 76b23a87ade615f5eec78285cf96f4cef70bb682 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 2 Sep 2016 15:36:03 -0400 Subject: [PATCH 044/191] Update CHANGES.md and LICENSE.md. --- CHANGES.md | 7 +++++++ LICENSE.md | 18 ++++++++++++++++++ Source/DataSources/BillboardVisualizer.js | 2 +- Source/DataSources/LabelVisualizer.js | 2 +- Source/DataSources/PointVisualizer.js | 2 +- 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 11419cea0918..e43bdfa8e621 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,14 @@ Change Log ========== +### 1.26 - 2016-10-03 + +* Deprecated + * The `scene` parameter for creating `BillboardVisualizer`, `LabelVisualizer`, and `PointVisualizer` has been deprecated and will be removed in 1.28. Instead, pass an instance of `EntityCluster`. +* Added support for clustering `Billboard`, `Label` and `Point` entities. [#4240](https://github.com/AnalyticalGraphicsInc/cesium/pull/4240) + ### 1.25 - 2016-09-01 + * Breaking changes * The number and order of arguments passed to `KmlDataSource` `unsupportedNodeEvent` listeners have changed to allow better handling of unsupported KML Features. * Changed billboards and labels that are clamped to terrain to have the `verticalOrigin` set to `CENTER` by default instead of `BOTTOM`. diff --git a/LICENSE.md b/LICENSE.md index 21d694470418..4fe332029945 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -270,6 +270,24 @@ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +### kdbush + +https://github.com/mourner/kdbush + +> Copyright (c) 2016, Vladimir Agafonkin +> +>Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. +> +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + Tests ===== diff --git a/Source/DataSources/BillboardVisualizer.js b/Source/DataSources/BillboardVisualizer.js index d121bb184b34..61fe1a4dce3f 100644 --- a/Source/DataSources/BillboardVisualizer.js +++ b/Source/DataSources/BillboardVisualizer.js @@ -81,7 +81,7 @@ define([ } //>>includeEnd('debug'); - if (!entityCluster.minimumClusterSize) { + if (!defined(entityCluster.minimumClusterSize)) { deprecationWarning('BillboardVisualizer scene constructor parameter', 'The scene is no longer a parameter the BillboardVisualizer. An EntityCluster is required.'); entityCluster = new EntityCluster({ enabled : false diff --git a/Source/DataSources/LabelVisualizer.js b/Source/DataSources/LabelVisualizer.js index c022fb7c713c..41e2b80f9ecb 100644 --- a/Source/DataSources/LabelVisualizer.js +++ b/Source/DataSources/LabelVisualizer.js @@ -82,7 +82,7 @@ define([ } //>>includeEnd('debug'); - if (!entityCluster.minimumClusterSize) { + if (!defined(entityCluster.minimumClusterSize)) { deprecationWarning('BillboardVisualizer scene constructor parameter', 'The scene is no longer a parameter the BillboardVisualizer. An EntityCluster is required.'); entityCluster = new EntityCluster({ enabled : false diff --git a/Source/DataSources/PointVisualizer.js b/Source/DataSources/PointVisualizer.js index 6b9e30a39efb..5b1ae3599b27 100644 --- a/Source/DataSources/PointVisualizer.js +++ b/Source/DataSources/PointVisualizer.js @@ -68,7 +68,7 @@ define([ } //>>includeEnd('debug'); - if (!entityCluster.minimumClusterSize) { + if (!defined(entityCluster.minimumClusterSize)) { deprecationWarning('BillboardVisualizer scene constructor parameter', 'The scene is no longer a parameter the BillboardVisualizer. An EntityCluster is required.'); entityCluster = new EntityCluster({ enabled : false From 396dab40ab2a6a859ebe5f153b90160e025ac9da Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 2 Sep 2016 15:54:43 -0400 Subject: [PATCH 045/191] Enable clustering by default and force a re-cluster when styling in the Sandcastle example. Add commas to default cluster labels. --- Apps/Sandcastle/gallery/Clustering.html | 6 ++++++ Source/DataSources/EntityCluster.js | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Apps/Sandcastle/gallery/Clustering.html b/Apps/Sandcastle/gallery/Clustering.html index 18b115124a76..65ca5616ea5b 100644 --- a/Apps/Sandcastle/gallery/Clustering.html +++ b/Apps/Sandcastle/gallery/Clustering.html @@ -68,6 +68,7 @@ var pixelRange = 15; var minimumClusterSize = 3; + dataSource.clustering.enabled = true; dataSource.clustering.pixelRange = pixelRange; dataSource.clustering.minimumClusterSize = minimumClusterSize; @@ -125,6 +126,11 @@ entity.billboard.image = singleDigitPins[cluster.length - 2]; } }); + + // force a re-cluster with the new styling + var pixelRange = dataSource.clustering.pixelRange; + dataSource.clustering.pixelRange = 0; + dataSource.clustering.pixelRange = pixelRange; }, 'customStyling'); var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index f0fa179aa87f..c43bc66b5d1d 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -182,7 +182,7 @@ define([ var entity = new Entity({ position : position, label : { - text : '' + numPoints + text : numPoints.toLocaleString() } }); From e70b63d823c9c9a59f52fa9c9cbc11f738abd6b9 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 2 Sep 2016 15:55:42 -0400 Subject: [PATCH 046/191] Fix toggling styling in the last commit. --- Apps/Sandcastle/gallery/Clustering.html | 27 ++++++++++++------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/Apps/Sandcastle/gallery/Clustering.html b/Apps/Sandcastle/gallery/Clustering.html index 65ca5616ea5b..f2393f0c9256 100644 --- a/Apps/Sandcastle/gallery/Clustering.html +++ b/Apps/Sandcastle/gallery/Clustering.html @@ -111,21 +111,20 @@ if (Cesium.defined(removeListener)) { removeListener(); removeListener = undefined; - return; - } - - removeListener = dataSource.clustering.clusterEvent.addEventListener(function(cluster, entity) { - entity.label = undefined; - entity.billboard = {}; + } else { + removeListener = dataSource.clustering.clusterEvent.addEventListener(function(cluster, entity) { + entity.label = undefined; + entity.billboard = {}; - if (cluster.length >= 20) { - entity.billboard.image = pin20; - } else if (cluster.length >= 10) { - entity.billboard.image = pin10; - } else { - entity.billboard.image = singleDigitPins[cluster.length - 2]; - } - }); + if (cluster.length >= 20) { + entity.billboard.image = pin20; + } else if (cluster.length >= 10) { + entity.billboard.image = pin10; + } else { + entity.billboard.image = singleDigitPins[cluster.length - 2]; + } + }); + } // force a re-cluster with the new styling var pixelRange = dataSource.clustering.pixelRange; From 0758daa9b7e2f6811827b49d3cd97421b84c4c68 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 2 Sep 2016 16:33:01 -0400 Subject: [PATCH 047/191] Reorganize code based on review. --- Source/DataSources/EntityCluster.js | 200 ++++++++++------------------ Source/Scene/Billboard.js | 43 ++++++ Source/Scene/Label.js | 58 ++++++++ Source/Scene/PointPrimitive.js | 32 +++++ 4 files changed, 200 insertions(+), 133 deletions(-) diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index c43bc66b5d1d..71921688bb22 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -15,8 +15,10 @@ define([ '../Scene/BillboardCollection', '../Scene/HeightReference', '../Scene/HorizontalOrigin', + '../Scene/Label', '../Scene/LabelCollection', '../Scene/LabelStyle', + '../Scene/PointPrimitive', '../Scene/PointPrimitiveCollection', '../Scene/SceneTransforms', '../Scene/VerticalOrigin', @@ -39,8 +41,10 @@ define([ BillboardCollection, HeightReference, HorizontalOrigin, + Label, LabelCollection, LabelStyle, + PointPrimitive, PointPrimitiveCollection, SceneTransforms, VerticalOrigin, @@ -49,117 +53,88 @@ define([ Property) { 'use strict'; - function getX(point) { - return point.coord.x; - } - - function getY(point) { - return point.coord.y; - } + /** + * Defines how screen space objects (billboards, points, labels) are clustered. + * + * @param {Object} [options] An object with the following properties: + * @param {Boolean} [options.enabled=false] Whether or not to enable clustering. + * @param {Number} [options.pixelRange=80] The pixel range to extend the screen space bounding box. + * @param {Number} [options.minimumClusterSize=2] The minimum number of screen space objects that can be clustered. + * + * @alias EntityCluster + * @constructor + * + * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Clustering.html|Cesium Sandcastle Clustering Demo} + */ + function EntityCluster(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); - function getLabelBoundingBox(label, coord, pixelRange) { - var width = 0; - var height = Number.NEGATIVE_INFINITY; + this._enabled = defaultValue(options.enabled, false); + this._pixelRange = defaultValue(options.pixelRange, 80); + this._minimumClusterSize = defaultValue(options.minimumClusterSize, 2); - var glyphs = label._glyphs; - var length = glyphs.length; - for (var i = 0; i < length; ++i) { - var glyph = glyphs[i]; - var billboard = glyph.billboard; - if (!defined(billboard)) { - continue; - } + this._labelCollection = undefined; + this._billboardCollection = undefined; + this._pointCollection = undefined; - width += billboard.width; - height = Math.max(height, billboard.height); - } + this._clusterBillboardCollection = undefined; + this._clusterLabelCollection = undefined; + this._clusterPointCollection = undefined; - var scale = label.scale; - width *= scale; - height *= scale; + this._unusedLabelIndices = []; + this._unusedBillboardIndices = []; + this._unusedPointIndices = []; - var x = coord.x; - if (label.horizontalOrigin === HorizontalOrigin.RIGHT) { - x -= width; - } else if (label.horizontalOrigin === HorizontalOrigin.CENTER) { - x -= width * 0.5; - } + this._previousClusters = []; + this._previousHeight = undefined; - var y = coord.y; - if (label.verticalOrigin === VerticalOrigin.TOP) { - y -= height; - } else if (label.verticalOrigin === VerticalOrigin.CENTER) { - y -= height * 0.5; - } + this._enabledDirty = false; + this._pixelRangeDirty = false; + this._minimumClusterSizeDirty = false; - x -= pixelRange; - y -= pixelRange; - width += pixelRange * 2.0; - height += pixelRange * 2.0; + this._cluster = undefined; + this._removeEventListener = undefined; - return new BoundingRectangle(x, y, width, height); + this._clusterEvent = new Event(); } - function getBillboardBoundingBox(billboard, coord, pixelRange) { - var width = billboard.width; - var height = billboard.height; - - var scale = billboard.scale; - width *= scale; - height *= scale; - - var x = coord.x; - if (billboard.horizontalOrigin === HorizontalOrigin.RIGHT) { - x += width * 0.5; - } else if (billboard.horizontalOrigin === HorizontalOrigin.LEFT) { - x -= width * 0.5; - } - - var y = coord.y; - if (billboard.verticalOrigin === VerticalOrigin.TOP) { - y -= height; - } else if (billboard.verticalOrigin === VerticalOrigin.CENTER) { - y -= height * 0.5; - } - - x -= pixelRange; - y -= pixelRange; - width += pixelRange * 2.0; - height += pixelRange * 2.0; - - return new BoundingRectangle(x, y, width, height); + function getX(point) { + return point.coord.x; } - function getPointBoundingBox(point, coord, pixelRange) { - var size = point.pixelSize; - var halfSize = size * 0.5; - - var x = coord.x - halfSize - pixelRange * 0.5; - var y = coord.y - halfSize - pixelRange * 0.5; - var width = size + pixelRange * 2.0; - var height = size + pixelRange * 2.0; + function getY(point) { + return point.coord.y; + } - return new BoundingRectangle(x, y, width, height); + function expandBoundingBox(bbox, pixelRange) { + bbox.x -= pixelRange; + bbox.y -= pixelRange; + bbox.width += pixelRange * 2.0; + bbox.height += pixelRange * 2.0; } - function getBoundingBox(item, coord, pixelRange, entityCluster) { - var bbox; + var labelBoundingBoxScratch = new BoundingRectangle(); + function getBoundingBox(item, coord, pixelRange, entityCluster, result) { if (defined(item._labelCollection)) { - bbox = getLabelBoundingBox(item, coord, pixelRange); + result = Label.getScreenSpaceBoundingBox(item, coord, result); } else if (defined(item._billboardCollection)) { - bbox = getBillboardBoundingBox(item, coord, pixelRange); + result = Billboard.getScreenSpaceBoundingBox(item, coord, result); } else if (defined(item._pointPrimitiveCollection)) { - bbox = getPointBoundingBox(item, coord, pixelRange); + result = PointPrimitive.getScreenSpaceBoundingBox(item, coord, result); } + expandBoundingBox(result, pixelRange); + if (!defined(item._labelCollection) && defined(item.id._label)) { var labelIndex = item.id._labelIndex; var label = entityCluster._labelCollection.get(labelIndex); - bbox = BoundingRectangle.union(bbox, getLabelBoundingBox(label, coord, pixelRange), bbox); + var labelBBox = Label.getScreenSpaceBoundingBox(label, coord, labelBoundingBoxScratch); + expandBoundingBox(labelBBox, pixelRange); + result = BoundingRectangle.union(result, labelBBox, result); } - return bbox; + return result; } function addNonClusteredItem(item, entityCluster) { @@ -257,6 +232,10 @@ define([ } } + var pointBoundinRectangleScratch = new BoundingRectangle(); + var totalBoundingRectangleScratch = new BoundingRectangle(); + var neighborBoundingRectangleScratch = new BoundingRectangle(); + function createDeclutterCallback(entityCluster) { return function(amount) { if ((defined(amount) && amount < 0.05) || !entityCluster.enabled) { @@ -400,8 +379,8 @@ define([ collectionIndex = point.index; var item = collection.get(collectionIndex); - bbox = getBoundingBox(item, point.coord, pixelRange, entityCluster); - var totalBBox = BoundingRectangle.clone(bbox); + bbox = getBoundingBox(item, point.coord, pixelRange, entityCluster, pointBoundinRectangleScratch); + var totalBBox = BoundingRectangle.clone(bbox, totalBoundingRectangleScratch); neighbors = index.range(bbox.x, bbox.y, bbox.x + bbox.width, bbox.y + bbox.height); neighborLength = neighbors.length; @@ -415,7 +394,7 @@ define([ neighborPoint = points[neighborIndex]; if (!neighborPoint.clustered) { var neighborItem = neighborPoint.collection.get(neighborPoint.index); - var neighborBBox = getBoundingBox(neighborItem, neighborPoint.coord, pixelRange, entityCluster); + var neighborBBox = getBoundingBox(neighborItem, neighborPoint.coord, pixelRange, entityCluster, neighborBoundingRectangleScratch); Cartesian3.add(neighborItem.position, clusterPosition, clusterPosition); @@ -465,51 +444,6 @@ define([ }; } - /** - * Defines how screen space objects (billboards, points, labels) are clustered. - * - * @param {Object} [options] An object with the following properties: - * @param {Boolean} [options.enabled=false] Whether or not to enable clustering. - * @param {Number} [options.pixelRange=80] The pixel range to extend the screen space bounding box. - * @param {Number} [options.minimumClusterSize=2] The minimum number of screen space objects that can be clustered. - * - * @alias EntityCluster - * @constructor - * - * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Clustering.html|Cesium Sandcastle Clustering Demo} - */ - function EntityCluster(options) { - options = defaultValue(options, defaultValue.EMPTY_OBJECT); - - this._enabled = defaultValue(options.enabled, false); - this._pixelRange = defaultValue(options.pixelRange, 80); - this._minimumClusterSize = defaultValue(options.minimumClusterSize, 2); - - this._labelCollection = undefined; - this._billboardCollection = undefined; - this._pointCollection = undefined; - - this._clusterBillboardCollection = undefined; - this._clusterLabelCollection = undefined; - this._clusterPointCollection = undefined; - - this._unusedLabelIndices = []; - this._unusedBillboardIndices = []; - this._unusedPointIndices = []; - - this._previousClusters = []; - this._previousHeight = undefined; - - this._enabledDirty = false; - this._pixelRangeDirty = false; - this._minimumClusterSizeDirty = false; - - this._cluster = undefined; - this._removeEventListener = undefined; - - this._clusterEvent = new Event(); - } - EntityCluster.prototype._initialize = function(scene) { this._scene = scene; diff --git a/Source/Scene/Billboard.js b/Source/Scene/Billboard.js index 535f572785bb..c08bde490af8 100644 --- a/Source/Scene/Billboard.js +++ b/Source/Scene/Billboard.js @@ -1165,6 +1165,49 @@ define([ return windowCoordinates; }; + /** + * Gets a billboard's screen space bounding box centered around screenSpacePosition. + * @param {Billboard} billboard The billboard to get the screen space bounding box for. + * @param {Cartesian2} screenSpacePosition The screen space center of the label. + * @param {BoundingRectangle} [result] The object onto which to store the result. + * @returns {BoundingRectangle} The screen space bounding box. + * + * @private + */ + Billboard.getScreenSpaceBoundingBox = function(billboard, screenSpacePosition, result) { + var width = billboard.width; + var height = billboard.height; + + var scale = billboard.scale; + width *= scale; + height *= scale; + + var x = screenSpacePosition.x; + if (billboard.horizontalOrigin === HorizontalOrigin.RIGHT) { + x += width * 0.5; + } else if (billboard.horizontalOrigin === HorizontalOrigin.LEFT) { + x -= width * 0.5; + } + + var y = screenSpacePosition.y; + if (billboard.verticalOrigin === VerticalOrigin.TOP) { + y -= height; + } else if (billboard.verticalOrigin === VerticalOrigin.CENTER) { + y -= height * 0.5; + } + + if (!defined(result)) { + result = new BoundingRectangle(); + } + + result.x = x; + result.y = y; + result.width = width; + result.height = height; + + return result; + } + /** * Determines if this billboard equals another billboard. Billboards are equal if all their properties * are equal. Billboards in different collections can be equal. diff --git a/Source/Scene/Label.js b/Source/Scene/Label.js index a43259b6a73d..31159cb447b1 100644 --- a/Source/Scene/Label.js +++ b/Source/Scene/Label.js @@ -1,5 +1,6 @@ /*global define*/ define([ + '../Core/BoundingRectangle', '../Core/Cartesian2', '../Core/Cartesian3', '../Core/Color', @@ -14,6 +15,7 @@ define([ './LabelStyle', './VerticalOrigin' ], function( + BoundingRectangle, Cartesian2, Cartesian3, Color, @@ -767,6 +769,62 @@ define([ return windowCoordinates; }; + /** + * Gets a label's screen space bounding box centered around screenSpacePosition. + * @param {Label} label The label to get the screen space bounding box for. + * @param {Cartesian2} screenSpacePosition The screen space center of the label. + * @param {BoundingRectangle} [result] The object onto which to store the result. + * @returns {BoundingRectangle} The screen space bounding box. + * + * @private + */ + Label.getScreenSpaceBoundingBox = function(label, screenSpacePosition, result) { + var width = 0; + var height = Number.NEGATIVE_INFINITY; + + var glyphs = label._glyphs; + var length = glyphs.length; + for (var i = 0; i < length; ++i) { + var glyph = glyphs[i]; + var billboard = glyph.billboard; + if (!defined(billboard)) { + continue; + } + + width += billboard.width; + height = Math.max(height, billboard.height); + } + + var scale = label.scale; + width *= scale; + height *= scale; + + var x = screenSpacePosition.x; + if (label.horizontalOrigin === HorizontalOrigin.RIGHT) { + x -= width; + } else if (label.horizontalOrigin === HorizontalOrigin.CENTER) { + x -= width * 0.5; + } + + var y = screenSpacePosition.y; + if (label.verticalOrigin === VerticalOrigin.TOP) { + y -= height; + } else if (label.verticalOrigin === VerticalOrigin.CENTER) { + y -= height * 0.5; + } + + if (!defined(result)) { + result = new BoundingRectangle(); + } + + result.x = x; + result.y = y; + result.width = width; + result.height = height; + + return result; + } + /** * Determines if this label equals another label. Labels are equal if all their properties * are equal. Labels in different collections can be equal. diff --git a/Source/Scene/PointPrimitive.js b/Source/Scene/PointPrimitive.js index d3ed11811e61..0e4a226cd11e 100644 --- a/Source/Scene/PointPrimitive.js +++ b/Source/Scene/PointPrimitive.js @@ -1,5 +1,6 @@ /*global define*/ define([ + '../Core/BoundingRectangle', '../Core/Cartesian2', '../Core/Cartesian3', '../Core/Cartesian4', @@ -13,6 +14,7 @@ define([ './SceneMode', './SceneTransforms' ], function( + BoundingRectangle, Cartesian2, Cartesian3, Cartesian4, @@ -447,6 +449,36 @@ define([ return windowCoordinates; }; + /** + * Gets a point's screen space bounding box centered around screenSpacePosition. + * @param {PointPrimitive} point The point to get the screen space bounding box for. + * @param {Cartesian2} screenSpacePosition The screen space center of the label. + * @param {BoundingRectangle} [result] The object onto which to store the result. + * @returns {BoundingRectangle} The screen space bounding box. + * + * @private + */ + PointPrimitive.getScreenSpaceBoundingBox = function(point, screenSpacePosition, result) { + var size = point.pixelSize; + var halfSize = size * 0.5; + + var x = screenSpacePosition.x - halfSize; + var y = screenSpacePosition.y - halfSize; + var width = size; + var height = size; + + if (!defined(result)) { + result = new BoundingRectangle(); + } + + result.x = x; + result.y = y; + result.width = width; + result.height = height; + + return result; + } + /** * Determines if this point equals another point. Points are equal if all their properties * are equal. Points in different collections can be equal. From 8a3613dce475e113efdd7bf153d168789493ca48 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 2 Sep 2016 16:48:29 -0400 Subject: [PATCH 048/191] Rename based on review. --- Source/DataSources/EntityCluster.js | 8 ++++---- Source/Scene/Billboard.js | 8 +++++++- Source/Scene/BillboardCollection.js | 2 +- Source/Scene/Label.js | 10 ++++++++-- Source/Scene/PointPrimitive.js | 8 +++++++- Source/Scene/PointPrimitiveCollection.js | 2 +- 6 files changed, 28 insertions(+), 10 deletions(-) diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index 71921688bb22..02250ca9bfaa 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -138,12 +138,12 @@ define([ } function addNonClusteredItem(item, entityCluster) { - item._clusterRender = true; + item.clusterShow = true; if (!defined(item._labelCollection) && defined(item.id._label)) { var labelIndex = item.id._labelIndex; var label = entityCluster._labelCollection.get(labelIndex); - label._clusterRender = true; + label.clusterShow = true; } } @@ -208,7 +208,7 @@ define([ var length = collection.length; for (var i = 0; i < length; ++i) { var item = collection.get(i); - item._clusterRender = false; + item.clusterShow = false; if (!item.show || !occluder.isPointVisible(item.position)) { continue; @@ -681,7 +681,7 @@ define([ var length = collection.length; for (var i = 0; i < length; ++i) { - collection.get(i)._clusterRender = true; + collection.get(i).clusterShow = true; } } diff --git a/Source/Scene/Billboard.js b/Source/Scene/Billboard.js index c08bde490af8..5add819b5556 100644 --- a/Source/Scene/Billboard.js +++ b/Source/Scene/Billboard.js @@ -825,7 +825,13 @@ define([ } }, - _clusterRender : { + /** + * Determines whether or not this billboard will be shown or hidden because it was clustered. + * @memberof Billboard.prototype + * @type {Boolean} + * @private + */ + clusterShow : { get : function() { return this._clusterShow; }, diff --git a/Source/Scene/BillboardCollection.js b/Source/Scene/BillboardCollection.js index 3f513aedf103..24beeac4007d 100644 --- a/Source/Scene/BillboardCollection.js +++ b/Source/Scene/BillboardCollection.js @@ -790,7 +790,7 @@ define([ var horizontalOrigin = billboard.horizontalOrigin; var verticalOrigin = billboard._verticalOrigin; - var show = billboard.show && billboard._clusterRender; + var show = billboard.show && billboard.clusterShow; // If the color alpha is zero, do not show this billboard. This lets us avoid providing // color during the pick pass and also eliminates a discard in the fragment shader. diff --git a/Source/Scene/Label.js b/Source/Scene/Label.js index 31159cb447b1..6d6e1895aca6 100644 --- a/Source/Scene/Label.js +++ b/Source/Scene/Label.js @@ -707,7 +707,13 @@ define([ } }, - _clusterRender : { + /** + * Determines whether or not this label will be shown or hidden because it was clustered. + * @memberof Label.prototype + * @type {Boolean} + * @private + */ + clusterShow : { get : function() { return this._clusterShow; }, @@ -721,7 +727,7 @@ define([ if (defined(glyph.billboard)) { // Set all the private values here, because we already clamped to ground // so we don't want to do it again for every glyph - glyph.billboard._clusterRender = value; + glyph.billboard.clusterShow = value; } } } diff --git a/Source/Scene/PointPrimitive.js b/Source/Scene/PointPrimitive.js index 0e4a226cd11e..0186a5407a5d 100644 --- a/Source/Scene/PointPrimitive.js +++ b/Source/Scene/PointPrimitive.js @@ -360,7 +360,13 @@ define([ } }, - _clusterRender : { + /** + * Determines whether or not this point will be shown or hidden because it was clustered. + * @memberof PointPrimitive.prototype + * @type {Boolean} + * @private + */ + clusterShow : { get : function() { return this._clusterShow; }, diff --git a/Source/Scene/PointPrimitiveCollection.js b/Source/Scene/PointPrimitiveCollection.js index 286d9d3aa70e..82a61cc7e9a7 100644 --- a/Source/Scene/PointPrimitiveCollection.js +++ b/Source/Scene/PointPrimitiveCollection.js @@ -555,7 +555,7 @@ define([ } } - var show = pointPrimitive.show && pointPrimitive._clusterRender; + var show = pointPrimitive.show && pointPrimitive.clusterShow; // If the color alphas are zero, do not show this pointPrimitive. This lets us avoid providing // color during the pick pass and also eliminates a discard in the fragment shader. From 9a942d24409d0a066ca7bf8eb41d34a75fc64bf6 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 2 Sep 2016 16:52:30 -0400 Subject: [PATCH 049/191] Fix jsHint errors. --- Source/Scene/Billboard.js | 2 +- Source/Scene/Label.js | 2 +- Source/Scene/PointPrimitive.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Scene/Billboard.js b/Source/Scene/Billboard.js index 5add819b5556..4b607d843747 100644 --- a/Source/Scene/Billboard.js +++ b/Source/Scene/Billboard.js @@ -1212,7 +1212,7 @@ define([ result.height = height; return result; - } + }; /** * Determines if this billboard equals another billboard. Billboards are equal if all their properties diff --git a/Source/Scene/Label.js b/Source/Scene/Label.js index 6d6e1895aca6..0350c855565b 100644 --- a/Source/Scene/Label.js +++ b/Source/Scene/Label.js @@ -829,7 +829,7 @@ define([ result.height = height; return result; - } + }; /** * Determines if this label equals another label. Labels are equal if all their properties diff --git a/Source/Scene/PointPrimitive.js b/Source/Scene/PointPrimitive.js index 0186a5407a5d..5b73f00998bd 100644 --- a/Source/Scene/PointPrimitive.js +++ b/Source/Scene/PointPrimitive.js @@ -483,7 +483,7 @@ define([ result.height = height; return result; - } + }; /** * Determines if this point equals another point. Points are equal if all their properties From 82ea36830b2b5aef4b8a0a0d106c30f4c9c4488d Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Mon, 5 Sep 2016 13:18:06 -0400 Subject: [PATCH 050/191] chore(package): update requirejs to version 2.3.1 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8539a2268770..50be4adf2f5e 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "email": "cesium-dev@googlegroups.com" }, "dependencies": { - "requirejs": "2.2.0" + "requirejs": "2.3.1" }, "devDependencies": { "almond": "0.3.3", From 80830bc436fa0a0240b72d79e3207b3a9a6f93de Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 6 Sep 2016 14:38:03 -0400 Subject: [PATCH 051/191] Fix clustering when enabled before the first render and more updates from review. --- Apps/Sandcastle/gallery/Clustering.html | 30 ++++++++++++++++++------- Source/DataSources/EntityCluster.js | 16 ++++++++++++- Source/Scene/Label.js | 27 +++++++++++++--------- 3 files changed, 53 insertions(+), 20 deletions(-) diff --git a/Apps/Sandcastle/gallery/Clustering.html b/Apps/Sandcastle/gallery/Clustering.html index f2393f0c9256..fe2d95a22716 100644 --- a/Apps/Sandcastle/gallery/Clustering.html +++ b/Apps/Sandcastle/gallery/Clustering.html @@ -83,9 +83,9 @@ function subscribeParameter(name) { Cesium.knockout.getObservable(viewModel, name).subscribe( - function(newValue) { - dataSource.clustering[name] = newValue; - } + function(newValue) { + dataSource.clustering[name] = newValue; + } ); } @@ -99,15 +99,18 @@ var removeListener; var pinBuilder = new Cesium.PinBuilder(); - var pin20 = pinBuilder.fromText('20+', Cesium.Color.RED, 48).toDataURL(); + var pin50 = pinBuilder.fromText('50+', Cesium.Color.RED, 48).toDataURL(); + var pin40 = pinBuilder.fromText('40+', Cesium.Color.ORANGE, 48).toDataURL(); + var pin30 = pinBuilder.fromText('30+', Cesium.Color.YELLOW, 48).toDataURL(); + var pin20 = pinBuilder.fromText('20+', Cesium.Color.GREEN, 48).toDataURL(); var pin10 = pinBuilder.fromText('10+', Cesium.Color.BLUE, 48).toDataURL(); var singleDigitPins = new Array(8); for (var i = 0; i < singleDigitPins.length; ++i) { - singleDigitPins[i] = pinBuilder.fromText('' + (i + 2), Cesium.Color.GREEN, 48).toDataURL(); + singleDigitPins[i] = pinBuilder.fromText('' + (i + 2), Cesium.Color.VIOLET, 48).toDataURL(); } - Sandcastle.addToolbarButton('Toggle Custom Styling', function() { + function customStyle() { if (Cesium.defined(removeListener)) { removeListener(); removeListener = undefined; @@ -116,7 +119,13 @@ entity.label = undefined; entity.billboard = {}; - if (cluster.length >= 20) { + if (cluster.length >= 50) { + entity.billboard.image = pin50; + } else if (cluster.length >= 40) { + entity.billboard.image = pin40; + } else if (cluster.length >= 30) { + entity.billboard.image = pin30; + } else if (cluster.length >= 20) { entity.billboard.image = pin20; } else if (cluster.length >= 10) { entity.billboard.image = pin10; @@ -130,7 +139,12 @@ var pixelRange = dataSource.clustering.pixelRange; dataSource.clustering.pixelRange = 0; dataSource.clustering.pixelRange = pixelRange; - }, 'customStyling'); + } + + // start with custom style + customStyle(); + + Sandcastle.addToolbarButton('Toggle Custom Styling', customStyle, 'customStyling'); var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); handler.setInputAction(function(movement) { diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index 02250ca9bfaa..d10f42007023 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -716,15 +716,29 @@ define([ * @private */ EntityCluster.prototype.update = function(frameState) { + // If clustering is enabled before the label collection is updated, + // the glyphs haven't been created so the screen space bounding boxes + // are incorrect. + if (defined(this._labelCollection) && this._labelCollection.length > 0 && this._labelCollection.get(0)._glyphs.length === 0) { + var commandList = frameState.commandList; + frameState.commandList = []; + this._labelCollection.update(frameState); + frameState.commandList = commandList; + } + + var clustered = false; if (this._enabledDirty) { this._enabledDirty = false; updateEnable(this); + clustered = this._enabled; } if (this._pixelRangeDirty || this._minimumClusterSizeDirty) { this._pixelRangeDirty = false; this._minimumClusterSizeDirty = false; - this._cluster(); + if (!clustered) { + this._cluster(); + } } if (defined(this._clusterLabelCollection)) { diff --git a/Source/Scene/Label.js b/Source/Scene/Label.js index 0350c855565b..1662cab36b48 100644 --- a/Source/Scene/Label.js +++ b/Source/Scene/Label.js @@ -790,21 +790,26 @@ define([ var glyphs = label._glyphs; var length = glyphs.length; - for (var i = 0; i < length; ++i) { - var glyph = glyphs[i]; - var billboard = glyph.billboard; - if (!defined(billboard)) { - continue; + if (length > 0) { + for (var i = 0; i < length; ++i) { + var glyph = glyphs[i]; + var billboard = glyph.billboard; + if (!defined(billboard)) { + continue; + } + + width += billboard.width; + height = Math.max(height, billboard.height); } - width += billboard.width; - height = Math.max(height, billboard.height); + var scale = label.scale; + width *= scale; + height *= scale; + } else { + width = 0.0; + height = 0.0; } - var scale = label.scale; - width *= scale; - height *= scale; - var x = screenSpacePosition.x; if (label.horizontalOrigin === HorizontalOrigin.RIGHT) { x -= width; From eec32187df1d73ed28d0f47435fbd92b241328cf Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 6 Sep 2016 15:45:57 -0400 Subject: [PATCH 052/191] Add tests for getScreenSpaceBoundingBox for points, billboards, and labels. --- Source/Scene/Billboard.js | 4 +- Source/Scene/Label.js | 29 ++-- Specs/Scene/BillboardCollectionSpec.js | 110 +++++++++++++ Specs/Scene/LabelCollectionSpec.js | 166 ++++++++++++++++++++ Specs/Scene/PointPrimitiveCollectionSpec.js | 40 +++++ 5 files changed, 330 insertions(+), 19 deletions(-) diff --git a/Source/Scene/Billboard.js b/Source/Scene/Billboard.js index 4b607d843747..960d068a84a8 100644 --- a/Source/Scene/Billboard.js +++ b/Source/Scene/Billboard.js @@ -1190,8 +1190,8 @@ define([ var x = screenSpacePosition.x; if (billboard.horizontalOrigin === HorizontalOrigin.RIGHT) { - x += width * 0.5; - } else if (billboard.horizontalOrigin === HorizontalOrigin.LEFT) { + x -= width; + } else if (billboard.horizontalOrigin === HorizontalOrigin.CENTER) { x -= width * 0.5; } diff --git a/Source/Scene/Label.js b/Source/Scene/Label.js index 1662cab36b48..7f423e7b9c42 100644 --- a/Source/Scene/Label.js +++ b/Source/Scene/Label.js @@ -786,30 +786,25 @@ define([ */ Label.getScreenSpaceBoundingBox = function(label, screenSpacePosition, result) { var width = 0; - var height = Number.NEGATIVE_INFINITY; + var height = 0; var glyphs = label._glyphs; var length = glyphs.length; - if (length > 0) { - for (var i = 0; i < length; ++i) { - var glyph = glyphs[i]; - var billboard = glyph.billboard; - if (!defined(billboard)) { - continue; - } - - width += billboard.width; - height = Math.max(height, billboard.height); + for (var i = 0; i < length; ++i) { + var glyph = glyphs[i]; + var billboard = glyph.billboard; + if (!defined(billboard)) { + continue; } - var scale = label.scale; - width *= scale; - height *= scale; - } else { - width = 0.0; - height = 0.0; + width += billboard.width; + height = Math.max(height, billboard.height); } + var scale = label.scale; + width *= scale; + height *= scale; + var x = screenSpacePosition.x; if (label.horizontalOrigin === HorizontalOrigin.RIGHT) { x -= width; diff --git a/Specs/Scene/BillboardCollectionSpec.js b/Specs/Scene/BillboardCollectionSpec.js index d6deef4ad98c..5d1d326bf96a 100644 --- a/Specs/Scene/BillboardCollectionSpec.js +++ b/Specs/Scene/BillboardCollectionSpec.js @@ -16,6 +16,7 @@ defineSuite([ 'Core/NearFarScalar', 'Core/Rectangle', 'Renderer/ContextLimits', + 'Scene/Billboard', 'Scene/HeightReference', 'Scene/HorizontalOrigin', 'Scene/OrthographicFrustum', @@ -42,6 +43,7 @@ defineSuite([ NearFarScalar, Rectangle, ContextLimits, + Billboard, HeightReference, HorizontalOrigin, OrthographicFrustum, @@ -1055,6 +1057,114 @@ defineSuite([ }).toThrowDeveloperError(); }); + it('computes screen space bounding box', function() { + var width = 10; + var height = 15; + var scale = 1.5; + + var b = billboards.add({ + width : width, + height : height, + scale : scale + }); + + var halfWidth = width * scale * 0.5; + var halfHeight = height * scale * 0.5; + width = width * scale; + height = height * scale; + + var bbox = Billboard.getScreenSpaceBoundingBox(b, Cartesian2.ZERO); + expect(bbox.x).toEqual(-halfWidth); + expect(bbox.y).toEqual(-halfHeight); + expect(bbox.width).toEqual(width); + expect(bbox.height).toEqual(height); + }); + + it('computes screen space bounding box with result', function() { + var width = 10; + var height = 15; + var scale = 1.5; + + var b = billboards.add({ + width : width, + height : height, + scale : scale + }); + + var halfWidth = width * scale * 0.5; + var halfHeight = height * scale * 0.5; + width = width * scale; + height = height * scale; + + var result = new BoundingRectangle(); + var bbox = Billboard.getScreenSpaceBoundingBox(b, Cartesian2.ZERO, result); + expect(bbox.x).toEqual(-halfWidth); + expect(bbox.y).toEqual(-halfHeight); + expect(bbox.width).toEqual(width); + expect(bbox.height).toEqual(height); + expect(bbox).toBe(result); + }); + + it('computes screen space bounding box with vertical origin', function() { + var width = 10; + var height = 15; + var scale = 1.5; + + var b = billboards.add({ + width : width, + height : height, + scale : scale, + verticalOrigin : VerticalOrigin.BOTTOM + }); + + var halfWidth = width * scale * 0.5; + width = width * scale; + height = height * scale; + + var bbox = Billboard.getScreenSpaceBoundingBox(b, Cartesian2.ZERO); + expect(bbox.x).toEqual(-halfWidth); + expect(bbox.y).toEqual(0); + expect(bbox.width).toEqual(width); + expect(bbox.height).toEqual(height); + + b.verticalOrigin = VerticalOrigin.TOP; + bbox = Billboard.getScreenSpaceBoundingBox(b, Cartesian2.ZERO); + expect(bbox.x).toEqual(-halfWidth); + expect(bbox.y).toEqual(-height); + expect(bbox.width).toEqual(width); + expect(bbox.height).toEqual(height); + }); + + it('computes screen space bounding box with horizontal origin', function() { + var width = 10; + var height = 15; + var scale = 1.5; + + var b = billboards.add({ + width : width, + height : height, + scale : scale, + horizontalOrigin : HorizontalOrigin.LEFT + }); + + var halfHeight = height * scale * 0.5; + height = height * scale; + width = width * scale; + + var bbox = Billboard.getScreenSpaceBoundingBox(b, Cartesian2.ZERO); + expect(bbox.x).toEqual(0); + expect(bbox.y).toEqual(-halfHeight); + expect(bbox.width).toEqual(width); + expect(bbox.height).toEqual(height); + + b.horizontalOrigin = HorizontalOrigin.RIGHT; + bbox = Billboard.getScreenSpaceBoundingBox(b, Cartesian2.ZERO); + expect(bbox.x).toEqual(-width); + expect(bbox.y).toEqual(-halfHeight); + expect(bbox.width).toEqual(width); + expect(bbox.height).toEqual(height); + }); + it('equals another billboard', function() { var b = billboards.add({ position : new Cartesian3(1.0, 2.0, 3.0), diff --git a/Specs/Scene/LabelCollectionSpec.js b/Specs/Scene/LabelCollectionSpec.js index ccf0b59de6f6..b79ce7eacede 100644 --- a/Specs/Scene/LabelCollectionSpec.js +++ b/Specs/Scene/LabelCollectionSpec.js @@ -1,6 +1,7 @@ /*global defineSuite*/ defineSuite([ 'Scene/LabelCollection', + 'Core/BoundingRectangle', 'Core/BoundingSphere', 'Core/Cartesian2', 'Core/Cartesian3', @@ -13,6 +14,7 @@ defineSuite([ 'Renderer/ContextLimits', 'Scene/HeightReference', 'Scene/HorizontalOrigin', + 'Scene/Label', 'Scene/LabelStyle', 'Scene/OrthographicFrustum', 'Scene/VerticalOrigin', @@ -20,6 +22,7 @@ defineSuite([ 'Specs/createScene' ], function( LabelCollection, + BoundingRectangle, BoundingSphere, Cartesian2, Cartesian3, @@ -32,6 +35,7 @@ defineSuite([ ContextLimits, HeightReference, HorizontalOrigin, + Label, LabelStyle, OrthographicFrustum, VerticalOrigin, @@ -810,6 +814,168 @@ defineSuite([ expect(label.computeScreenSpacePosition(scene)).toEqualEpsilon(new Cartesian2(0.5, 0.5), CesiumMath.EPSILON1); }); + it('computes screen space bounding box', function() { + var scale = 1.5; + + var label = labels.add({ + text : 'abc', + scale : scale + }); + scene.renderForSpecs(); + + var width = 0; + var height = 0; + + var glyphs = label._glyphs; + var length = glyphs.length; + for (var i = 0; i < length; ++i) { + var glyph = glyphs[i]; + var billboard = glyph.billboard; + if (!defined(billboard)) { + continue; + } + + width += billboard.width; + height = Math.max(height, billboard.height); + } + + width *= scale; + height *= scale; + + var bbox = Label.getScreenSpaceBoundingBox(label, Cartesian2.ZERO); + expect(bbox.x).toEqual(0); + expect(bbox.y).toEqual(0); + expect(bbox.width).toEqual(width); + expect(bbox.height).toEqual(height); + }); + + it('computes screen space bounding box with result', function() { + var scale = 1.5; + + var label = labels.add({ + text : 'abc', + scale : scale + }); + scene.renderForSpecs(); + + var width = 0; + var height = 0; + + var glyphs = label._glyphs; + var length = glyphs.length; + for (var i = 0; i < length; ++i) { + var glyph = glyphs[i]; + var billboard = glyph.billboard; + if (!defined(billboard)) { + continue; + } + + width += billboard.width; + height = Math.max(height, billboard.height); + } + + width *= scale; + height *= scale; + + var result = new BoundingRectangle(); + var bbox = Label.getScreenSpaceBoundingBox(label, Cartesian2.ZERO, result); + expect(bbox.x).toEqual(0); + expect(bbox.y).toEqual(0); + expect(bbox.width).toEqual(width); + expect(bbox.height).toEqual(height); + expect(bbox).toBe(result); + }); + + it('computes screen space bounding box with vertical origin', function() { + var scale = 1.5; + + var label = labels.add({ + text : 'abc', + scale : scale, + verticalOrigin : VerticalOrigin.CENTER + }); + scene.renderForSpecs(); + + var width = 0; + var height = 0; + + var glyphs = label._glyphs; + var length = glyphs.length; + for (var i = 0; i < length; ++i) { + var glyph = glyphs[i]; + var billboard = glyph.billboard; + if (!defined(billboard)) { + continue; + } + + width += billboard.width; + height = Math.max(height, billboard.height); + } + + width *= scale; + height *= scale; + + var halfHeight = height * 0.5; + + var bbox = Label.getScreenSpaceBoundingBox(label, Cartesian2.ZERO); + expect(bbox.x).toEqual(0); + expect(bbox.y).toEqual(-halfHeight); + expect(bbox.width).toEqual(width); + expect(bbox.height).toEqual(height); + + label.verticalOrigin = VerticalOrigin.TOP; + bbox = Label.getScreenSpaceBoundingBox(label, Cartesian2.ZERO); + expect(bbox.x).toEqual(0); + expect(bbox.y).toEqual(-height); + expect(bbox.width).toEqual(width); + expect(bbox.height).toEqual(height); + }); + + it('computes screen space bounding box with horizontal origin', function() { + var scale = 1.5; + + var label = labels.add({ + text : 'abc', + scale : scale, + horizontalOrigin : HorizontalOrigin.CENTER + }); + scene.renderForSpecs(); + + var width = 0; + var height = 0; + + var glyphs = label._glyphs; + var length = glyphs.length; + for (var i = 0; i < length; ++i) { + var glyph = glyphs[i]; + var billboard = glyph.billboard; + if (!defined(billboard)) { + continue; + } + + width += billboard.width; + height = Math.max(height, billboard.height); + } + + width *= scale; + height *= scale; + + var halfWidth = width * 0.5; + + var bbox = Label.getScreenSpaceBoundingBox(label, Cartesian2.ZERO); + expect(bbox.x).toEqual(-halfWidth); + expect(bbox.y).toEqual(0); + expect(bbox.width).toEqual(width); + expect(bbox.height).toEqual(height); + + label.horizontalOrigin = HorizontalOrigin.RIGHT; + bbox = Label.getScreenSpaceBoundingBox(label, Cartesian2.ZERO); + expect(bbox.x).toEqual(-width); + expect(bbox.y).toEqual(0); + expect(bbox.width).toEqual(width); + expect(bbox.height).toEqual(height); + }); + it('can equal another label', function() { var label = labels.add({ position : new Cartesian3(1.0, 2.0, 3.0), diff --git a/Specs/Scene/PointPrimitiveCollectionSpec.js b/Specs/Scene/PointPrimitiveCollectionSpec.js index fc66dabb553e..b6061cc9e9c1 100644 --- a/Specs/Scene/PointPrimitiveCollectionSpec.js +++ b/Specs/Scene/PointPrimitiveCollectionSpec.js @@ -1,6 +1,7 @@ /*global defineSuite*/ defineSuite([ 'Scene/PointPrimitiveCollection', + 'Core/BoundingRectangle', 'Core/BoundingSphere', 'Core/Cartesian2', 'Core/Cartesian3', @@ -9,9 +10,11 @@ defineSuite([ 'Core/NearFarScalar', 'Core/Rectangle', 'Scene/OrthographicFrustum', + 'Scene/PointPrimitive', 'Specs/createScene' ], function( PointPrimitiveCollection, + BoundingRectangle, BoundingSphere, Cartesian2, Cartesian3, @@ -20,6 +23,7 @@ defineSuite([ NearFarScalar, Rectangle, OrthographicFrustum, + PointPrimitive, createScene) { 'use strict'; @@ -679,6 +683,42 @@ defineSuite([ }).toThrowDeveloperError(); }); + it('computes screen space bounding box', function() { + var size = 10; + + var p = pointPrimitives.add({ + size : size + }); + + var halfWidth = size * 0.5; + var halfHeight = halfWidth; + + var bbox = PointPrimitive.getScreenSpaceBoundingBox(p, Cartesian2.ZERO); + expect(bbox.x).toEqual(-halfWidth); + expect(bbox.y).toEqual(-halfHeight); + expect(bbox.width).toEqual(size); + expect(bbox.height).toEqual(size); + }); + + it('computes screen space bounding box with result', function() { + var size = 10; + + var p = pointPrimitives.add({ + size : size + }); + + var halfWidth = size * 0.5; + var halfHeight = halfWidth; + + var result = new BoundingRectangle(); + var bbox = PointPrimitive.getScreenSpaceBoundingBox(p, Cartesian2.ZERO, result); + expect(bbox.x).toEqual(-halfWidth); + expect(bbox.y).toEqual(-halfHeight); + expect(bbox.width).toEqual(size); + expect(bbox.height).toEqual(size); + expect(bbox).toBe(result); + }); + it('equals another pointPrimitive', function() { var p = pointPrimitives.add({ position : new Cartesian3(1.0, 2.0, 3.0), From 244ed41e5bc76a9cc23050d9d55e6818f891fa22 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Tue, 6 Sep 2016 20:34:24 -0400 Subject: [PATCH 053/191] chore(package): update aws-sdk to version 2.5.6 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d084c851b6dd..4dfb23faa8d6 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ }, "devDependencies": { "almond": "0.3.3", - "aws-sdk": "2.5.5", + "aws-sdk": "2.5.6", "bluebird": "3.4.6", "compressible": "2.0.8", "compression": "1.6.2", From 7208298f275865e9ad234d3a365089031cfef40c Mon Sep 17 00:00:00 2001 From: Denver Pierce Date: Tue, 6 Sep 2016 22:44:47 -0500 Subject: [PATCH 054/191] Remove polylineGlow from CZML Path Sandcastle. --- Apps/Sandcastle/gallery/CZML Path.html | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Apps/Sandcastle/gallery/CZML Path.html b/Apps/Sandcastle/gallery/CZML Path.html index 3ec59c233939..e6cc7e21ad9d 100644 --- a/Apps/Sandcastle/gallery/CZML Path.html +++ b/Apps/Sandcastle/gallery/CZML Path.html @@ -51,13 +51,7 @@ "outlineColor" : { "rgba" : [0, 255, 255, 255] }, - "outlineWidth" : 5, - "polylineGlow" : { - "color" : { - "rgba" : [255, 255, 0, 255] - }, - "glowPower" : 3 - } + "outlineWidth" : 5 } }, "width" : 8, @@ -67,7 +61,10 @@ }, "billboard" : { "image" : "data:image/png;base64,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", - "scale" : 1.5 + "scale" : 1.5, + "eyeOffset": { + "cartesian": [ 0.0, 0.0, -10.0 ] + } }, "position" : { "epoch" : "2012-08-04T10:00:00Z", From 35ea94cb37e9163e89d10ca8a1119cdb42f2e3e1 Mon Sep 17 00:00:00 2001 From: Denver Pierce Date: Tue, 6 Sep 2016 22:54:42 -0500 Subject: [PATCH 055/191] Spaces > tabs --- Apps/Sandcastle/gallery/CZML Path.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/Sandcastle/gallery/CZML Path.html b/Apps/Sandcastle/gallery/CZML Path.html index e6cc7e21ad9d..763d1dba9aae 100644 --- a/Apps/Sandcastle/gallery/CZML Path.html +++ b/Apps/Sandcastle/gallery/CZML Path.html @@ -62,7 +62,7 @@ "billboard" : { "image" : "data:image/png;base64,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", "scale" : 1.5, - "eyeOffset": { + "eyeOffset": { "cartesian": [ 0.0, 0.0, -10.0 ] } }, From 4c94289c3fa5b337e37d673dafdec4af17d84348 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 7 Sep 2016 10:51:05 -0400 Subject: [PATCH 056/191] Fix billboard rotation when sized in meters. --- Source/Shaders/BillboardCollectionVS.glsl | 33 +++++++++++------------ 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/Source/Shaders/BillboardCollectionVS.glsl b/Source/Shaders/BillboardCollectionVS.glsl index 9ceae522f107..a2ad3e45ac94 100644 --- a/Source/Shaders/BillboardCollectionVS.glsl +++ b/Source/Shaders/BillboardCollectionVS.glsl @@ -39,22 +39,8 @@ vec4 computePositionWindowCoordinates(vec4 positionEC, vec2 imageSize, float sca { vec2 halfSize = imageSize * scale * czm_resolutionScale; halfSize *= ((direction * 2.0) - 1.0); - - if (sizeInMeters) - { - positionEC.xy += halfSize; - } - - vec4 positionWC = czm_eyeToWindowCoordinates(positionEC); - - if (sizeInMeters) - { - positionWC.xy += (origin * abs(halfSize)) / czm_metersPerPixel(positionEC); - } - else - { - positionWC.xy += (origin * abs(halfSize)); - } + + vec2 originTranslate = origin * abs(halfSize); #if defined(ROTATION) || defined(ALIGNED_AXIS) if (validAlignedAxis || rotation != 0.0) @@ -75,7 +61,20 @@ vec4 computePositionWindowCoordinates(vec4 positionEC, vec2 imageSize, float sca halfSize = rotationMatrix * halfSize; } #endif - + + if (sizeInMeters) + { + positionEC.xy += halfSize; + } + + vec4 positionWC = czm_eyeToWindowCoordinates(positionEC); + + if (sizeInMeters) + { + originTranslate += originTranslate / czm_metersPerPixel(positionEC); + } + + positionWC.xy += originTranslate; if (!sizeInMeters) { positionWC.xy += halfSize; From 9465b416f9fb64cac4dec2b175c4f397a62a514f Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 7 Sep 2016 10:53:50 -0400 Subject: [PATCH 057/191] Update CHANGES.md. --- CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 11419cea0918..c31c364f9d88 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,12 @@ Change Log ========== +### 1.26 - 2016-10-03 + +* Fixed billboard rotation when sized in meters. [#3979](https://github.com/AnalyticalGraphicsInc/cesium/issues/3979) + ### 1.25 - 2016-09-01 + * Breaking changes * The number and order of arguments passed to `KmlDataSource` `unsupportedNodeEvent` listeners have changed to allow better handling of unsupported KML Features. * Changed billboards and labels that are clamped to terrain to have the `verticalOrigin` set to `CENTER` by default instead of `BOTTOM`. From 5d59a75b2d37627c8402738d201606b42969f1dd Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 7 Sep 2016 17:50:47 -0400 Subject: [PATCH 058/191] Added DebugCameraPrimitive --- Source/Scene/DebugCameraPrimitive.js | 215 +++++++++++++++++++ Source/Scene/ShadowMap.js | 74 ++----- Specs/Scene/DebugCameraPrimitiveSpec.js | 124 +++++++++++ Specs/Scene/DebugModelMatrixPrimitiveSpec.js | 6 +- 4 files changed, 364 insertions(+), 55 deletions(-) create mode 100644 Source/Scene/DebugCameraPrimitive.js create mode 100644 Specs/Scene/DebugCameraPrimitiveSpec.js diff --git a/Source/Scene/DebugCameraPrimitive.js b/Source/Scene/DebugCameraPrimitive.js new file mode 100644 index 000000000000..393d2ce4550e --- /dev/null +++ b/Source/Scene/DebugCameraPrimitive.js @@ -0,0 +1,215 @@ +/*global define*/ +define([ + '../Core/BoundingSphere', + '../Core/Cartesian3', + '../Core/Cartesian4', + '../Core/Color', + '../Core/ColorGeometryInstanceAttribute', + '../Core/ComponentDatatype', + '../Core/defaultValue', + '../Core/defined', + '../Core/destroyObject', + '../Core/DeveloperError', + '../Core/Geometry', + '../Core/GeometryAttribute', + '../Core/GeometryAttributes', + '../Core/GeometryInstance', + '../Core/Matrix4', + '../Core/PrimitiveType', + './PerInstanceColorAppearance', + './Primitive' + ], function( + BoundingSphere, + Cartesian3, + Cartesian4, + Color, + ColorGeometryInstanceAttribute, + ComponentDatatype, + defaultValue, + defined, + destroyObject, + DeveloperError, + Geometry, + GeometryAttribute, + GeometryAttributes, + GeometryInstance, + Matrix4, + PrimitiveType, + PerInstanceColorAppearance, + Primitive) { + 'use strict'; + + /** + * Draws the outline of the camera's view frustum. + * + * @alias DebugCameraPrimitive + * @constructor + * + * @param {Object} options Object with the following properties: + * @param {Camera} options.camera The camera. + * @param {Color} [options.color=Color.CYAN] The color of the debug outline. + * @param {Boolean} [options.updateOnChange=true] Whether the primitive updates when the underlying camera changes. + * @param {Boolean} [options.show=true] Determines if this primitive will be shown. + * @param {Object} [options.id] A user-defined object to return when the instance is picked with {@link Scene#pick}. + * + * @example + * primitives.add(new Cesium.DebugCameraPrimitive({ + * camera : camera, + * color : Cesium.Color.YELLOW + * })); + */ + function DebugCameraPrimitive(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + //>>includeStart('debug', pragmas.debug); + if (!defined(options.camera)) { + throw new DeveloperError('options.camera is required.'); + } + //>>includeEnd('debug'); + + this._camera = options.camera; + this._color = defaultValue(options.color, Color.CYAN); + this._updateOnChange = defaultValue(options.updateOnChange, true); + + /** + * Determines if this primitive will be shown. + * + * @type Boolean + * @default true + */ + this.show = defaultValue(options.show, true); + + /** + * User-defined object returned when the primitive is picked. + * + * @type {Object} + * @default undefined + * + * @see Scene#pick + */ + this.id = options.id; + this._id = undefined; + + this._primitive = undefined; + } + + var frustumCornersNDC = new Array(8); + frustumCornersNDC[0] = new Cartesian4(-1.0, -1.0, -1.0, 1.0); + frustumCornersNDC[1] = new Cartesian4(1.0, -1.0, -1.0, 1.0); + frustumCornersNDC[2] = new Cartesian4(1.0, 1.0, -1.0, 1.0); + frustumCornersNDC[3] = new Cartesian4(-1.0, 1.0, -1.0, 1.0); + frustumCornersNDC[4] = new Cartesian4(-1.0, -1.0, 1.0, 1.0); + frustumCornersNDC[5] = new Cartesian4(1.0, -1.0, 1.0, 1.0); + frustumCornersNDC[6] = new Cartesian4(1.0, 1.0, 1.0, 1.0); + frustumCornersNDC[7] = new Cartesian4(-1.0, 1.0, 1.0, 1.0); + + var scratchMatrix = new Matrix4(); + var scratchFrustumCorners = new Array(8); + for (var i = 0; i < 8; ++i) { + scratchFrustumCorners[i] = new Cartesian4(); + } + + /** + * @private + */ + DebugCameraPrimitive.prototype.update = function(frameState) { + if (!this.show) { + return; + } + + if (this._updateOnChange) { + // Recreate the primitive every frame + this._primitive = this._primitive && this._primitive.destroy(); + } + + if (!defined(this._primitive)) { + var view = this._camera.viewMatrix; + var projection = this._camera.frustum.projectionMatrix; + var viewProjection = Matrix4.multiply(projection, view, scratchMatrix); + var inverseViewProjection = Matrix4.inverse(viewProjection, scratchMatrix); + + var positions = new Float64Array(8 * 3); + for (var i = 0; i < 8; ++i) { + var corner = Cartesian4.clone(frustumCornersNDC[i], scratchFrustumCorners[i]); + Matrix4.multiplyByVector(inverseViewProjection, corner, corner); + Cartesian3.divideByScalar(corner, corner.w, corner); // Handle the perspective divide + positions[i * 3] = corner.x; + positions[i * 3 + 1] = corner.y; + positions[i * 3 + 2] = corner.z; + } + + var attributes = new GeometryAttributes(); + attributes.position = new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + values : positions + }); + + var indices = new Uint16Array([0,1,1,2,2,3,3,0,0,4,4,7,7,3,7,6,6,2,2,1,1,5,5,4,5,6]); + var geometry = new Geometry({ + attributes : attributes, + indices : indices, + primitiveType : PrimitiveType.LINES, + boundingSphere : new BoundingSphere.fromVertices(positions) + }); + + this._primitive = new Primitive({ + geometryInstances : new GeometryInstance({ + geometry : geometry, + attributes : { + color : ColorGeometryInstanceAttribute.fromColor(this._color) + }, + id : this.id, + pickPrimitive : this + }), + appearance : new PerInstanceColorAppearance({ + translucent : false, + flat : true + }), + asynchronous : false + }); + } + + this._primitive.update(frameState); + }; + + /** + * Returns true if this object was destroyed; otherwise, false. + *

+ * If this object was destroyed, it should not be used; calling any function other than + * isDestroyed will result in a {@link DeveloperError} exception. + *

+ * + * @returns {Boolean} true if this object was destroyed; otherwise, false. + * + * @see DebugModelMatrixPrimitive#destroy + */ + DebugCameraPrimitive.prototype.isDestroyed = function() { + return false; + }; + + /** + * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic + * release of WebGL resources, instead of relying on the garbage collector to destroy this object. + *

+ * Once an object is destroyed, it should not be used; calling any function other than + * isDestroyed will result in a {@link DeveloperError} exception. Therefore, + * assign the return value (undefined) to the object as done in the example. + *

+ * + * @returns {undefined} + * + * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called. + * + * @example + * p = p && p.destroy(); + * + * @see DebugModelMatrixPrimitive#isDestroyed + */ + DebugCameraPrimitive.prototype.destroy = function() { + this._primitive = this._primitive && this._primitive.destroy(); + return destroyObject(this); + }; + + return DebugCameraPrimitive; +}); diff --git a/Source/Scene/ShadowMap.js b/Source/Scene/ShadowMap.js index 6007e8c2059d..6db116f50696 100644 --- a/Source/Scene/ShadowMap.js +++ b/Source/Scene/ShadowMap.js @@ -50,6 +50,7 @@ define([ './Camera', './CullFace', './CullingVolume', + './DebugCameraPrimitive', './OrthographicFrustum', './Pass', './PerInstanceColorAppearance', @@ -107,6 +108,7 @@ define([ Camera, CullFace, CullingVolume, + DebugCameraPrimitive, OrthographicFrustum, Pass, PerInstanceColorAppearance, @@ -877,54 +879,6 @@ define([ }); } - function createDebugFrustum(camera, color) { - var view = camera.viewMatrix; - var projection = camera.frustum.projectionMatrix; - var viewProjection = Matrix4.multiply(projection, view, scratchMatrix); - var inverseViewProjection = Matrix4.inverse(viewProjection, scratchMatrix); - - var positions = new Float64Array(8 * 3); - for (var i = 0; i < 8; ++i) { - var corner = Cartesian4.clone(frustumCornersNDC[i], scratchFrustumCorners[i]); - Matrix4.multiplyByVector(inverseViewProjection, corner, corner); - Cartesian3.divideByScalar(corner, corner.w, corner); // Handle the perspective divide - positions[i * 3 + 0] = corner.x; - positions[i * 3 + 1] = corner.y; - positions[i * 3 + 2] = corner.z; - } - - var attributes = new GeometryAttributes(); - attributes.position = new GeometryAttribute({ - componentDatatype : ComponentDatatype.DOUBLE, - componentsPerAttribute : 3, - values : positions - }); - - var indices = new Uint16Array([0,1,1,2,2,3,3,0,0,4,4,7,7,3,7,6,6,2,2,1,1,5,5,4,5,6]); - var geometry = new Geometry({ - attributes : attributes, - indices : indices, - primitiveType : PrimitiveType.LINES, - boundingSphere : new BoundingSphere.fromVertices(positions) - }); - - var debugFrustum = new Primitive({ - geometryInstances : new GeometryInstance({ - geometry : geometry, - attributes : { - color : ColorGeometryInstanceAttribute.fromColor(color) - } - }), - appearance : new PerInstanceColorAppearance({ - translucent : false, - flat : true - }), - asynchronous : false - }); - - return debugFrustum; - } - var debugOutlineColors = [Color.RED, Color.GREEN, Color.BLUE, Color.MAGENTA]; var scratchScale = new Cartesian3(); @@ -939,7 +893,11 @@ define([ if (enterFreezeFrame) { // Recreate debug camera when entering freeze frame mode shadowMap._debugCameraFrustum = shadowMap._debugCameraFrustum && shadowMap._debugCameraFrustum.destroy(); - shadowMap._debugCameraFrustum = createDebugFrustum(shadowMap._sceneCamera, Color.CYAN); + shadowMap._debugCameraFrustum = new DebugCameraPrimitive({ + camera : shadowMap._sceneCamera, + color : Color.CYAN, + updateOnChange : false + }); } shadowMap._debugCameraFrustum.update(frameState); } @@ -950,7 +908,11 @@ define([ if (enterFreezeFrame) { // Recreate debug frustum when entering freeze frame mode shadowMap._debugLightFrustum = shadowMap._debugLightFrustum && shadowMap._debugLightFrustum.destroy(); - shadowMap._debugLightFrustum = createDebugFrustum(shadowMap._shadowMapCamera, Color.YELLOW); + shadowMap._debugLightFrustum = new DebugCameraPrimitive({ + camera : shadowMap._shadowMapCamera, + color : Color.YELLOW, + updateOnChange : false + }); } shadowMap._debugLightFrustum.update(frameState); @@ -958,7 +920,11 @@ define([ if (enterFreezeFrame) { // Recreate debug frustum when entering freeze frame mode shadowMap._debugCascadeFrustums[i] = shadowMap._debugCascadeFrustums[i] && shadowMap._debugCascadeFrustums[i].destroy(); - shadowMap._debugCascadeFrustums[i] = createDebugFrustum(shadowMap._passes[i].camera, debugOutlineColors[i]); + shadowMap._debugCascadeFrustums[i] = new DebugCameraPrimitive({ + camera : shadowMap._passes[i].camera, + color : debugOutlineColors[i], + updateOnChange : false + }); } shadowMap._debugCascadeFrustums[i].update(frameState); } @@ -977,7 +943,11 @@ define([ shadowMap._debugLightFrustum.update(frameState); } else { if (!defined(shadowMap._debugLightFrustum) || shadowMap._needsUpdate) { - shadowMap._debugLightFrustum = createDebugFrustum(shadowMap._shadowMapCamera, Color.YELLOW); + shadowMap._debugLightFrustum = new DebugCameraPrimitive({ + camera : shadowMap._shadowMapCamera, + color : Color.YELLOW, + updateOnChange : false + }); } shadowMap._debugLightFrustum.update(frameState); } diff --git a/Specs/Scene/DebugCameraPrimitiveSpec.js b/Specs/Scene/DebugCameraPrimitiveSpec.js new file mode 100644 index 000000000000..ca8fa84cf54f --- /dev/null +++ b/Specs/Scene/DebugCameraPrimitiveSpec.js @@ -0,0 +1,124 @@ +/*global defineSuite*/ +defineSuite([ + 'Scene/DebugCameraPrimitive', + 'Core/Cartesian3', + 'Core/Color', + 'Scene/Camera', + 'Specs/createScene' + ], function( + DebugCameraPrimitive, + Cartesian3, + Color, + Camera, + createScene) { + 'use strict'; + + var scene; + var camera; + + beforeAll(function() { + scene = createScene(); + + camera = new Camera(scene); + camera.position = new Cartesian3(0.0, 0.0, 0.0); + camera.direction = Cartesian3.negate(Cartesian3.UNIT_X, new Cartesian3()); + camera.up = Cartesian3.clone(Cartesian3.UNIT_Z); + + scene.camera.position = new Cartesian3(0.0, 0.0, 0.0); + scene.camera.direction = Cartesian3.negate(Cartesian3.UNIT_X, new Cartesian3()); + scene.camera.up = Cartesian3.clone(Cartesian3.UNIT_Z); + scene.camera.zoomOut(1.0); + }); + + afterAll(function() { + scene.destroyForSpecs(); + }); + + afterEach(function() { + scene.primitives.removeAll(); + }); + + it('throws if options.camera is undefined', function() { + expect(function() { + return new DebugCameraPrimitive(); + }).toThrowDeveloperError(); + }); + + it('gets the default properties', function() { + var p = new DebugCameraPrimitive({ + camera : camera + }); + expect(p.show).toEqual(true); + expect(p.id).not.toBeDefined(); + p.destroy(); + }); + + it('constructs with options', function() { + var p = new DebugCameraPrimitive({ + camera : camera, + color : Color.YELLOW, + updateOnChange : false, + show : false, + id : 'id' + }); + expect(p.show).toEqual(false); + expect(p.id).toEqual('id'); + p.destroy(); + }); + + it('renders', function() { + var p = scene.primitives.add(new DebugCameraPrimitive({ + camera : camera + })); + expect(scene.renderForSpecs()).not.toEqual([0, 0, 0, 255]); + }); + + it('does not render when show is false', function() { + scene.primitives.add(new DebugCameraPrimitive({ + camera : camera, + show : false + })); + expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]); + }); + + it('updates when underlying camera changes', function() { + var p = scene.primitives.add(new DebugCameraPrimitive({ + camera : camera + })); + scene.renderForSpecs(); + var primitive = p._primitive; + scene.renderForSpecs(); + expect(p._primitive).not.toBe(primitive); + }); + + it('does not update when updateOnChange is false', function() { + var p = scene.primitives.add(new DebugCameraPrimitive({ + camera : camera, + updateOnChange : false + })); + scene.renderForSpecs(); + var primitive = p._primitive; + scene.renderForSpecs(); + expect(p._primitive).toBe(primitive); + }); + + it('is picked', function() { + var p = scene.primitives.add(new DebugCameraPrimitive({ + camera : camera, + id : 'id' + })); + + var pick = scene.pickForSpecs(); + expect(pick.primitive).toBe(p); + expect(pick.id).toBe('id'); + }); + + it('isDestroyed', function() { + var p = scene.primitives.add(new DebugCameraPrimitive({ + camera : camera + })); + expect(p.isDestroyed()).toEqual(false); + scene.primitives.remove(p); + expect(p.isDestroyed()).toEqual(true); + }); +}, 'WebGL'); diff --git a/Specs/Scene/DebugModelMatrixPrimitiveSpec.js b/Specs/Scene/DebugModelMatrixPrimitiveSpec.js index 535f038deec5..8f95c8f24a4d 100644 --- a/Specs/Scene/DebugModelMatrixPrimitiveSpec.js +++ b/Specs/Scene/DebugModelMatrixPrimitiveSpec.js @@ -78,9 +78,9 @@ defineSuite([ id : 'id' })); - var pick = scene.pick(new Cartesian2(0, 0)); - expect(pick.primitive).toEqual(p); - expect(pick.id).toEqual('id'); + var pick = scene.pickForSpecs(); + expect(pick.primitive).toBe(p); + expect(pick.id).toBe('id'); }); it('isDestroyed', function() { From 87c49c69f8bd448cc21abe1b30d5a860ccdb383c Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 7 Sep 2016 18:03:09 -0400 Subject: [PATCH 059/191] Fix links --- Source/Scene/DebugCameraPrimitive.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Scene/DebugCameraPrimitive.js b/Source/Scene/DebugCameraPrimitive.js index 393d2ce4550e..f26aae3aaf01 100644 --- a/Source/Scene/DebugCameraPrimitive.js +++ b/Source/Scene/DebugCameraPrimitive.js @@ -182,7 +182,7 @@ define([ * * @returns {Boolean} true if this object was destroyed; otherwise, false. * - * @see DebugModelMatrixPrimitive#destroy + * @see DebugCameraPrimitive#destroy */ DebugCameraPrimitive.prototype.isDestroyed = function() { return false; @@ -204,7 +204,7 @@ define([ * @example * p = p && p.destroy(); * - * @see DebugModelMatrixPrimitive#isDestroyed + * @see DebugCameraPrimitive#isDestroyed */ DebugCameraPrimitive.prototype.destroy = function() { this._primitive = this._primitive && this._primitive.destroy(); From b93b80cf35ecd2871919f2d307398d34fbe115ad Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 8 Sep 2016 10:00:39 -0400 Subject: [PATCH 060/191] Fix jshint --- Specs/Scene/DebugCameraPrimitiveSpec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Specs/Scene/DebugCameraPrimitiveSpec.js b/Specs/Scene/DebugCameraPrimitiveSpec.js index ca8fa84cf54f..c8e1b9522f3b 100644 --- a/Specs/Scene/DebugCameraPrimitiveSpec.js +++ b/Specs/Scene/DebugCameraPrimitiveSpec.js @@ -67,7 +67,7 @@ defineSuite([ }); it('renders', function() { - var p = scene.primitives.add(new DebugCameraPrimitive({ + scene.primitives.add(new DebugCameraPrimitive({ camera : camera })); expect(scene.renderForSpecs()).not.toEqual([0, 0, 0, 255]); From 4e443bf62dcd8b88cdac5dccb5aafc3884a89a37 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Thu, 8 Sep 2016 10:42:46 -0400 Subject: [PATCH 061/191] viewerDragDropMixin use flyToOnDrop option --- Source/Widgets/Viewer/viewerDragDropMixin.js | 2 +- Specs/Widgets/Viewer/viewerDragDropMixinSpec.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Source/Widgets/Viewer/viewerDragDropMixin.js b/Source/Widgets/Viewer/viewerDragDropMixin.js index f5c0d28a34e1..bfb21466cda1 100644 --- a/Source/Widgets/Viewer/viewerDragDropMixin.js +++ b/Source/Widgets/Viewer/viewerDragDropMixin.js @@ -79,7 +79,7 @@ define([ //Local variables to be closed over by defineProperties. var dropEnabled = true; - var flyToOnDrop = true; + var flyToOnDrop = defaultValue(options.flyToOnDrop, true); var dropError = new Event(); var clearOnDrop = defaultValue(options.clearOnDrop, true); var dropTarget = defaultValue(options.dropTarget, viewer.container); diff --git a/Specs/Widgets/Viewer/viewerDragDropMixinSpec.js b/Specs/Widgets/Viewer/viewerDragDropMixinSpec.js index 3a2b9e3ec7a5..7e3f1c5ecb82 100644 --- a/Specs/Widgets/Viewer/viewerDragDropMixinSpec.js +++ b/Specs/Widgets/Viewer/viewerDragDropMixinSpec.js @@ -58,6 +58,7 @@ defineSuite([ expect(viewer.dropEnabled).toEqual(true); expect(viewer.clearOnDrop).toEqual(true); expect(viewer.clampToGround).toEqual(true); + expect(viewer.flyToOnDrop).toEqual(true); }); it('clearOnDrop defaults to true when dataSourceBrowser is not used', function() { @@ -73,12 +74,14 @@ defineSuite([ viewer.extend(viewerDragDropMixin, { dropTarget : document.body, clearOnDrop : false, - clampToGround : false + clampToGround : false, + flyToOnDrop: false }); expect(viewer.dropTarget).toBe(document.body); expect(viewer.dropEnabled).toEqual(true); expect(viewer.clearOnDrop).toEqual(false); expect(viewer.clampToGround).toEqual(false); + expect(viewer.flyToOnDrop).toEqual(false); }); it('mixin works with dropTarget id string', function() { From b2b1b088e9ed467f839d1975967fdff85a31f8c4 Mon Sep 17 00:00:00 2001 From: Tom Fili Date: Thu, 8 Sep 2016 12:29:35 -0400 Subject: [PATCH 062/191] jshint error. --- Source/Core/CredentialsRegistry.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/CredentialsRegistry.js b/Source/Core/CredentialsRegistry.js index 69e5140cc439..2a36c8ec1078 100644 --- a/Source/Core/CredentialsRegistry.js +++ b/Source/Core/CredentialsRegistry.js @@ -129,7 +129,7 @@ define([ */ CredentialsRegistry.clear = function() { _credentials = []; - } + }; return CredentialsRegistry; -}); \ No newline at end of file +}); From eba20d6664d3f2447fc9d9fb232a409ef9b15a4d Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 8 Sep 2016 13:26:27 -0400 Subject: [PATCH 063/191] Update CHANGES.md and removed unneeded includes --- CHANGES.md | 1 + Source/Scene/ShadowMap.js | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index c31c364f9d88..96bdf204acb0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,7 @@ Change Log ### 1.26 - 2016-10-03 * Fixed billboard rotation when sized in meters. [#3979](https://github.com/AnalyticalGraphicsInc/cesium/issues/3979) +* Added `DebugCameraPrimitive` to visualize the view frustum of a camera. ### 1.25 - 2016-09-01 diff --git a/Source/Scene/ShadowMap.js b/Source/Scene/ShadowMap.js index 6db116f50696..b26b03f516ff 100644 --- a/Source/Scene/ShadowMap.js +++ b/Source/Scene/ShadowMap.js @@ -11,16 +11,12 @@ define([ '../Core/Color', '../Core/ColorGeometryInstanceAttribute', '../Core/combine', - '../Core/ComponentDatatype', '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', '../Core/destroyObject', '../Core/DeveloperError', '../Core/FeatureDetection', - '../Core/Geometry', - '../Core/GeometryAttribute', - '../Core/GeometryAttributes', '../Core/GeometryInstance', '../Core/Intersect', '../Core/Math', @@ -69,16 +65,12 @@ define([ Color, ColorGeometryInstanceAttribute, combine, - ComponentDatatype, defaultValue, defined, defineProperties, destroyObject, DeveloperError, FeatureDetection, - Geometry, - GeometryAttribute, - GeometryAttributes, GeometryInstance, Intersect, CesiumMath, From 960234fc0cfa282c6ca3d8eaa08de3f0c2d93aa2 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 8 Sep 2016 15:54:13 -0400 Subject: [PATCH 064/191] Add distance display conditions to geometry primitives. --- Source/Core/DistanceDisplayCondition.js | 76 +++++++++ ...splayConditionGeometryInstanceAttribute.js | 161 ++++++++++++++++++ Source/Core/GeometryInstanceAttribute.js | 1 + Source/Scene/Primitive.js | 30 +++- Source/Scene/PrimitivePipeline.js | 36 ++++ 5 files changed, 302 insertions(+), 2 deletions(-) create mode 100644 Source/Core/DistanceDisplayCondition.js create mode 100644 Source/Core/DistanceDisplayConditionGeometryInstanceAttribute.js diff --git a/Source/Core/DistanceDisplayCondition.js b/Source/Core/DistanceDisplayCondition.js new file mode 100644 index 000000000000..05b74cbe2114 --- /dev/null +++ b/Source/Core/DistanceDisplayCondition.js @@ -0,0 +1,76 @@ +/*global define*/ +define([ + './Cartesian3', + './defaultValue', + './defineProperties', + './Matrix4' +], function( + Cartesian3, + defaultValue, + defineProperties, + Matrix4) { + 'use strict'; + + /** + * DOC_TBA + * + * @alias DistanceDisplayCondition + * @constructor + */ + function DistanceDisplayCondition(near, far) { + near = defaultValue(near, 0.0); + this._near = near; + this._near2 = near * near; + + far = defaultValue(far, Number.MAX_VALUE); + this._far = far; + this._far2 = far * far; + } + + defineProperties(DistanceDisplayCondition.prototype, { + /** + * DOC_TBA + * @memberof DistanceDisplayCondition.prototype + * @type {Number} + */ + near : { + get : function() { + return this._near; + }, + set : function(value) { + this._near = value; + this._near2 = value * value; + } + }, + /** + * DOC_TBA + * @memberof DistanceDisplayCondition.prototype + * @type {Number} + */ + far : { + get : function() { + return this._far; + }, + set : function(value) { + this._far = value; + this._far2 = value * value; + } + } + }); + + var scratchPosition = new Cartesian3(); + + /** + * DOC_TBA + */ + DistanceDisplayCondition.prototype.isVisible = function(primitive, frameState) { + // TODO: need to consider positions, e.g., for a polyline + + // Distance to center of primitive's reference frame + var position = Matrix4.getTranslation(primitive.modelMatrix, scratchPosition); + var distance2 = Cartesian3.distanceSquared(position, frameState.camera.positionWC); + return (distance2 >= this._near2) && (distance2 <= this._far2); + }; + + return DistanceDisplayCondition; +}); \ No newline at end of file diff --git a/Source/Core/DistanceDisplayConditionGeometryInstanceAttribute.js b/Source/Core/DistanceDisplayConditionGeometryInstanceAttribute.js new file mode 100644 index 000000000000..e49e2765fdc8 --- /dev/null +++ b/Source/Core/DistanceDisplayConditionGeometryInstanceAttribute.js @@ -0,0 +1,161 @@ +/*global define*/ +define([ + './ComponentDatatype', + './defaultValue', + './defined', + './defineProperties', + './DeveloperError' +], function( + ComponentDatatype, + defaultValue, + defined, + defineProperties, + DeveloperError) { + 'use strict'; + + /** + * Value and type information for per-instance geometry attribute that determines if the geometry instance has a distance display condition. + * + * @alias DistanceDisplayConditionGeometryInstanceAttribute + * @constructor + * + * @param {Number} [near=0.0] The near distance. + * @param {Number} [far=Number.MAX_VALUE] The far distance. + * + * @example + * var instance = new Cesium.GeometryInstance({ + * geometry : new Cesium.BoxGeometry({ + * vertexFormat : Cesium.VertexFormat.POSITION_AND_NORMAL, + * minimum : new Cesium.Cartesian3(-250000.0, -250000.0, -250000.0), + * maximum : new Cesium.Cartesian3(250000.0, 250000.0, 250000.0) + * }), + * modelMatrix : Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame( + * Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883)), new Cesium.Cartesian3(0.0, 0.0, 1000000.0), new Cesium.Matrix4()), + * id : 'box', + * attributes : { + * show : new Cesium.DistanceDisplayConditionGeometryInstanceAttribute(100.0, 10000.0) + * } + * }); + * + * @see GeometryInstance + * @see GeometryInstanceAttribute + */ + function DistanceDisplayConditionGeometryInstanceAttribute(near, far) { + near = defaultValue(near, 0.0); + far = defaultValue(far, Number.MAX_VALUE); + + /** + * The values for the attributes stored in a typed array. + * + * @type Float32Array + * + * @default [0.0, 0.0, Number.MAX_VALUE] + */ + this.value = new Float32Array([near, far]); + } + + defineProperties(DistanceDisplayConditionGeometryInstanceAttribute.prototype, { + /** + * The datatype of each component in the attribute, e.g., individual elements in + * {@link DistanceDisplayConditionGeometryInstanceAttribute#value}. + * + * @memberof DistanceDisplayConditionGeometryInstanceAttribute.prototype + * + * @type {ComponentDatatype} + * @readonly + * + * @default {@link ComponentDatatype.FLOAT} + */ + componentDatatype : { + get : function() { + return ComponentDatatype.FLOAT; + } + }, + + /** + * The number of components in the attributes, i.e., {@link DistanceDisplayConditionGeometryInstanceAttribute#value}. + * + * @memberof DistanceDisplayConditionGeometryInstanceAttribute.prototype + * + * @type {Number} + * @readonly + * + * @default 3 + */ + componentsPerAttribute : { + get : function() { + return 2; + } + }, + + /** + * When true and componentDatatype is an integer format, + * indicate that the components should be mapped to the range [0, 1] (unsigned) + * or [-1, 1] (signed) when they are accessed as floating-point for rendering. + * + * @memberof DistanceDisplayConditionGeometryInstanceAttribute.prototype + * + * @type {Boolean} + * @readonly + * + * @default false + */ + normalize : { + get : function() { + return false; + } + } + }); + + /** + * Creates a new {@link DistanceDisplayConditionGeometryInstanceAttribute} instance given the provided an enabled flag and {@link DistanceDisplayCondition}. + * + * @param {DistanceDisplayCondition} distanceDisplayCondition The distance display condition. + * @returns {DistanceDisplayConditionGeometryInstanceAttribute} The new {@link DistanceDisplayConditionGeometryInstanceAttribute} instance. + * + * @example + * var instance = new Cesium.GeometryInstance({ + * geometry : geometry, + * attributes : { + * color : Cesium.DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition), + * } + * }); + */ + DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition = function(distanceDisplayCondition) { + //>>includeStart('debug', pragmas.debug); + if (!defined(distanceDisplayCondition)) { + throw new DeveloperError('distanceDisplayCondition is required.'); + } + //>>includeEnd('debug'); + + return new DistanceDisplayConditionGeometryInstanceAttribute(distanceDisplayCondition.near, distanceDisplayCondition.far); + }; + + /** + * Converts a distance display condition to a typed array that can be used to assign a distance display condition attribute. + * + * @param {DistanceDisplayCondition} distanceDisplayCondition The distance display condition value. + * @param {Float32Array} [result] The array to store the result in, if undefined a new instance will be created. + * @returns {Float32Array} The modified result parameter or a new instance if result was undefined. + * + * @example + * var attributes = primitive.getGeometryInstanceAttributes('an id'); + * attributes.distanceDisplayCondition = Cesium.DistanceDisplayConditionGeometryInstanceAttribute.toValue(distanceDisplayCondition, attributes.distanceDisplayCondition); + */ + DistanceDisplayConditionGeometryInstanceAttribute.toValue = function(distanceDisplayCondition, result) { + //>>includeStart('debug', pragmas.debug); + if (!defined(distanceDisplayCondition)) { + throw new DeveloperError('distanceDisplayCondition is required.'); + } + //>>includeEnd('debug'); + + if (!defined(result)) { + return new Float32Array([distanceDisplayCondition.near, distanceDisplayCondition.far]); + } + result[0] = distanceDisplayCondition.near; + result[1] = distanceDisplayCondition.far; + return result; + }; + + return DistanceDisplayConditionGeometryInstanceAttribute; +}); diff --git a/Source/Core/GeometryInstanceAttribute.js b/Source/Core/GeometryInstanceAttribute.js index 539d3a929d3b..ff8a578e120d 100644 --- a/Source/Core/GeometryInstanceAttribute.js +++ b/Source/Core/GeometryInstanceAttribute.js @@ -44,6 +44,7 @@ define([ * * @see ColorGeometryInstanceAttribute * @see ShowGeometryInstanceAttribute + * @see DistanceDisplayConditionGeometryInstanceAttribute */ function GeometryInstanceAttribute(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 995078d0fe1b..46f70ca719b2 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -683,6 +683,30 @@ define([ return renamedVS + '\n' + showMain; }; + Primitive._appendDistanceDisplayConditionToShader = function(primitive, vertexShaderSource) { + if (!defined(primitive._attributeLocations.distanceDisplayCondition)) { + return vertexShaderSource; + } + + var renamedVS = ShaderSource.replaceMain(vertexShaderSource, 'czm_non_distanceDisplayCondition_main'); + var distanceDisplayConditionMain = + 'attribute vec3 boundingSphereCenter3DHigh; \n' + + 'attribute vec3 boundingSphereCenter3DLow; \n' + + 'attribute float boundingSphereRadius; \n' + + 'attribute vec2 distanceDisplayCondition; \n' + + 'void main() \n' + + '{ \n' + + ' czm_non_distanceDisplayCondition_main(); \n' + + ' vec4 centerRTE = czm_computeBoundingSphereCenter(); \n' + + ' float distance = length(centerRTE) - boundingSphereRadius; \n' + + ' float near = distanceDisplayCondition.x; \n' + + ' float far = distanceDisplayCondition.y; \n' + + ' float show = (distance >= near && distance <= far) ? 1.0 : 0.0; \n' + + ' gl_Position *= show; \n' + + '}'; + return renamedVS + '\n' + distanceDisplayConditionMain; + }; + function modifyForEncodedNormals(primitive, vertexShaderSource) { if (!primitive.compressVertices) { return vertexShaderSource; @@ -1149,9 +1173,10 @@ define([ var attributeLocations = primitive._attributeLocations; - var vs = Primitive._modifyShaderPosition(primitive, appearance.vertexShaderSource, frameState.scene3DOnly); - vs = Primitive._appendShowToShader(primitive, vs); + var vs = Primitive._appendShowToShader(primitive, appearance.vertexShaderSource); + vs = Primitive._appendDistanceDisplayConditionToShader(primitive, vs); vs = modifyForEncodedNormals(primitive, vs); + vs = Primitive._modifyShaderPosition(primitive, vs, frameState.scene3DOnly); var fs = appearance.getFragmentShaderSource(); // Create pick program @@ -1535,6 +1560,7 @@ define([ * var attributes = primitive.getGeometryInstanceAttributes('an id'); * attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(Cesium.Color.AQUA); * attributes.show = Cesium.ShowGeometryInstanceAttribute.toValue(true); + * attributes.distanceDisplayCondition = Cesium.DistanceDisplayConditionGeometryInstanceAttribute.toValue(100.0, 10000.0); */ Primitive.prototype.getGeometryInstanceAttributes = function(id) { //>>includeStart('debug', pragmas.debug); diff --git a/Source/Scene/PrimitivePipeline.js b/Source/Scene/PrimitivePipeline.js index c4986f352daa..d5bf12d9bccc 100644 --- a/Source/Scene/PrimitivePipeline.js +++ b/Source/Scene/PrimitivePipeline.js @@ -1,6 +1,7 @@ /*global define*/ define([ '../Core/BoundingSphere', + '../Core/Cartesian3', '../Core/Color', '../Core/ComponentDatatype', '../Core/defaultValue', @@ -18,6 +19,7 @@ define([ '../Core/WebMercatorProjection' ], function( BoundingSphere, + Cartesian3, Color, ComponentDatatype, defaultValue, @@ -144,6 +146,9 @@ define([ return attributesInAllInstances; } + var centerValuesScratch = new Array(3); + var radiusValuesScratch = new Array(1); + function addPerInstanceAttributesToGeometry(instanceAttributes, geometry, names) { var numberOfVertices = Geometry.computeNumberOfVertices(geometry); @@ -167,6 +172,37 @@ define([ values : buffer }); } + + if (defined(geometry.attributes.distanceDisplayCondition)) { + var boundingSphere = geometry.boundingSphere; + var center = boundingSphere.center; + var radius = boundingSphere.radius; + + var centerValues = Cartesian3.pack(center, centerValuesScratch); + var radiusValues = radiusValuesScratch; + radiusValues[0] = radius; + + var centerBuffer = new Float64Array(numberOfVertices * 3); + var radiusBuffer = new Float32Array(numberOfVertices); + + for (var i = 0; i < numberOfVertices; ++i) { + centerBuffer.set(centerValues, i * 3); + radiusBuffer.set(radiusValues, i); + } + + geometry.attributes.boundingSphereCenter = new GeometryAttribute({ + componentDatatype : ComponentDatatype.DOUBLE, + componentsPerAttribute : 3, + normalize : false, + values : centerBuffer + }); + geometry.attributes.boundingSphereRadius = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 1, + normalize : false, + values : radiusBuffer + }); + } } function addPerInstanceAttributes(instances, names) { From 28bf84cdc5c254480440a6b0251c878fcb5cd403 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 8 Sep 2016 17:21:39 -0400 Subject: [PATCH 065/191] Add distance display conditions to billboards. --- Source/Core/DistanceDisplayCondition.js | 13 +++++ Source/Scene/Billboard.js | 24 ++++++++- Source/Scene/BillboardCollection.js | 61 +++++++++++++++++++++-- Source/Scene/Primitive.js | 8 +-- Source/Shaders/BillboardCollectionVS.glsl | 12 ++++- 5 files changed, 108 insertions(+), 10 deletions(-) diff --git a/Source/Core/DistanceDisplayCondition.js b/Source/Core/DistanceDisplayCondition.js index 05b74cbe2114..4bfc2ddb4ab3 100644 --- a/Source/Core/DistanceDisplayCondition.js +++ b/Source/Core/DistanceDisplayCondition.js @@ -2,11 +2,13 @@ define([ './Cartesian3', './defaultValue', + './defined', './defineProperties', './Matrix4' ], function( Cartesian3, defaultValue, + defined, defineProperties, Matrix4) { 'use strict'; @@ -72,5 +74,16 @@ define([ return (distance2 >= this._near2) && (distance2 <= this._far2); }; + /** + * DOC_TBA + */ + DistanceDisplayCondition.equals = function(left, right) { + return left === right || + (defined(left) && + defined(right) && + left.near === right.near && + left.far === right.far); + }; + return DistanceDisplayCondition; }); \ No newline at end of file diff --git a/Source/Scene/Billboard.js b/Source/Scene/Billboard.js index e875a1dd68fa..40e29f3a1003 100644 --- a/Source/Scene/Billboard.js +++ b/Source/Scene/Billboard.js @@ -11,6 +11,7 @@ define([ '../Core/defined', '../Core/defineProperties', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', '../Core/Matrix4', '../Core/NearFarScalar', './HeightReference', @@ -30,6 +31,7 @@ define([ defined, defineProperties, DeveloperError, + DistanceDisplayCondition, Matrix4, NearFarScalar, HeightReference, @@ -104,6 +106,7 @@ define([ this._translucencyByDistance = options.translucencyByDistance; this._pixelOffsetScaleByDistance = options.pixelOffsetScaleByDistance; this._sizeInMeters = defaultValue(options.sizeInMeters, false); + this._distanceDisplayCondition = options.distanceDisplayCondition; this._id = options.id; this._collection = defaultValue(options.collection, billboardCollection); @@ -168,7 +171,8 @@ define([ var SCALE_BY_DISTANCE_INDEX = Billboard.SCALE_BY_DISTANCE_INDEX = 11; var TRANSLUCENCY_BY_DISTANCE_INDEX = Billboard.TRANSLUCENCY_BY_DISTANCE_INDEX = 12; var PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX = Billboard.PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX = 13; - Billboard.NUMBER_OF_PROPERTIES = 14; + var DISTANCE_DISPLAY_CONDITION = Billboard.DISTANCE_DISPLAY_CONDITION = 14; + Billboard.NUMBER_OF_PROPERTIES = 15; function makeDirty(billboard, propertyChanged) { var billboardCollection = billboard._billboardCollection; @@ -714,6 +718,24 @@ define([ } }, + /** + * DOC_TBA + * @memberof Billboard.prototype + * @type {DistanceDisplayCondition} + * @default undefined + */ + distanceDisplayCondition : { + get : function() { + return this._distanceDisplayCondition; + }, + set : function(value) { + if (DistanceDisplayCondition.equals(value, this._distanceDisplayCondition)) { + this._distanceDisplayCondition = value; + makeDirty(this, DISTANCE_DISPLAY_CONDITION); + } + } + }, + /** * Gets or sets the user-defined object returned when the billboard is picked. * @memberof Billboard.prototype diff --git a/Source/Scene/BillboardCollection.js b/Source/Scene/BillboardCollection.js index f31b0cde817e..a1e651cea0ca 100644 --- a/Source/Scene/BillboardCollection.js +++ b/Source/Scene/BillboardCollection.js @@ -81,6 +81,7 @@ define([ var SCALE_BY_DISTANCE_INDEX = Billboard.SCALE_BY_DISTANCE_INDEX; var TRANSLUCENCY_BY_DISTANCE_INDEX = Billboard.TRANSLUCENCY_BY_DISTANCE_INDEX; var PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX = Billboard.PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX; + var DISTANCE_DISPLAY_CONDITION_INDEX = Billboard.DISTANCE_DISPLAY_CONDITION_INDEX; var NUMBER_OF_PROPERTIES = Billboard.NUMBER_OF_PROPERTIES; var attributeLocations; @@ -93,7 +94,8 @@ define([ compressedAttribute2 : 4, // image height, color, pick color, size in meters, valid aligned axis, 13 bits free eyeOffset : 5, // 4 bytes free scaleByDistance : 6, - pixelOffsetScaleByDistance : 7 + pixelOffsetScaleByDistance : 7, + distanceDisplayCondition : 8 }; var attributeLocationsInstanced = { @@ -105,7 +107,8 @@ define([ compressedAttribute2 : 5, eyeOffset : 6, // texture range in w scaleByDistance : 7, - pixelOffsetScaleByDistance : 8 + pixelOffsetScaleByDistance : 8, + distanceDisplayCondition : 9 }; /** @@ -193,6 +196,10 @@ define([ this._compiledShaderPixelOffsetScaleByDistance = false; this._compiledShaderPixelOffsetScaleByDistancePick = false; + this._shaderDistanceDisplayCondition = false; + this._compiledShaderDistanceDisplayCondition = false; + this._compiledShaderDistanceDisplayConditionPick = false; + this._propertiesChanged = new Uint32Array(NUMBER_OF_PROPERTIES); this._maxSize = 0.0; @@ -689,6 +696,11 @@ define([ componentsPerAttribute : 4, componentDatatype : ComponentDatatype.FLOAT, usage : buffersUsage[PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX] + }, { + index : attributeLocations.distanceDisplayCondition, + componentsPerAttribute : 2, + componentDatatype : ComponentDatatype.FLOAT, + usage : buffersUsage[DISTANCE_DISPLAY_CONDITION_INDEX] }]; // Instancing requires one non-instanced attribute. @@ -1097,6 +1109,32 @@ define([ } } + function writeDistanceDisplayCondition(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard) { + var i; + var writer = vafWriters[attributeLocations.distanceDisplayCondition]; + var near = 0.0; + var far = Number.MAX_VALUE; + + var distanceDisplayCondition = billboard.distanceDisplayCondition; + if (defined(distanceDisplayCondition)) { + near = distanceDisplayCondition.near; + far = distanceDisplayCondition.far; + + billboardCollection._shaderDistanceDisplayCondition = true; + } + + if (billboardCollection._instanced) { + i = billboard._index; + writer(i, near, far); + } else { + i = billboard._index * 4; + writer(i + 0, near, far); + writer(i + 1, near, far); + writer(i + 2, near, far); + writer(i + 3, near, far); + } + } + function writeBillboard(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard) { writePositionScaleAndRotation(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard); writeCompressedAttrib0(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard); @@ -1105,6 +1143,7 @@ define([ writeEyeOffset(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard); writeScaleByDistance(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard); writePixelOffsetScaleByDistance(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard); + writeDistanceDisplayCondition(billboardCollection, context, textureAtlasCoordinates, vafWriters, billboard); } function recomputeActualPositions(billboardCollection, billboards, length, frameState, modelMatrix, recomputeBoundingVolume) { @@ -1300,6 +1339,10 @@ define([ writers.push(writePixelOffsetScaleByDistance); } + if (properties[DISTANCE_DISPLAY_CONDITION_INDEX]) { + writers.push(writeDistanceDisplayCondition); + } + var numWriters = writers.length; vafWriters = this._vaf.writers; @@ -1391,7 +1434,8 @@ define([ (this._shaderAlignedAxis !== this._compiledShaderAlignedAxis) || (this._shaderScaleByDistance !== this._compiledShaderScaleByDistance) || (this._shaderTranslucencyByDistance !== this._compiledShaderTranslucencyByDistance) || - (this._shaderPixelOffsetScaleByDistance !== this._compiledShaderPixelOffsetScaleByDistance)) { + (this._shaderPixelOffsetScaleByDistance !== this._compiledShaderPixelOffsetScaleByDistance) || + (this._shaderDistanceDisplayCondition !== this._compiledShaderDistanceDisplayCondition)) { vs = new ShaderSource({ sources : [BillboardCollectionVS] @@ -1414,6 +1458,9 @@ define([ if (this._shaderPixelOffsetScaleByDistance) { vs.defines.push('EYE_DISTANCE_PIXEL_OFFSET'); } + if (this._shaderDistanceDisplayCondition) { + vs.defines.push('DISTANCE_DISPLAY_CONDITION'); + } this._sp = ShaderProgram.replaceCache({ context : context, @@ -1428,6 +1475,7 @@ define([ this._compiledShaderScaleByDistance = this._shaderScaleByDistance; this._compiledShaderTranslucencyByDistance = this._shaderTranslucencyByDistance; this._compiledShaderPixelOffsetScaleByDistance = this._shaderPixelOffsetScaleByDistance; + this._compiledShaderDistanceDisplayCondition = this._shaderDistanceDisplayCondition; } va = this._vaf.va; @@ -1469,7 +1517,8 @@ define([ (this._shaderAlignedAxis !== this._compiledShaderAlignedAxisPick) || (this._shaderScaleByDistance !== this._compiledShaderScaleByDistancePick) || (this._shaderTranslucencyByDistance !== this._compiledShaderTranslucencyByDistancePick) || - (this._shaderPixelOffsetScaleByDistance !== this._compiledShaderPixelOffsetScaleByDistancePick)) { + (this._shaderPixelOffsetScaleByDistance !== this._compiledShaderPixelOffsetScaleByDistancePick) || + (this._shaderDistanceDisplayCondition !== this._compiledShaderDistanceDisplayConditionPick)) { vs = new ShaderSource({ defines : ['RENDER_FOR_PICK'], @@ -1494,6 +1543,9 @@ define([ if (this._shaderPixelOffsetScaleByDistance) { vs.defines.push('EYE_DISTANCE_PIXEL_OFFSET'); } + if (this._shaderDistanceDisplayCondition) { + vs.defines.push('DISTANCE_DISPLAY_CONDITION'); + } fs = new ShaderSource({ defines : ['RENDER_FOR_PICK'], @@ -1512,6 +1564,7 @@ define([ this._compiledShaderScaleByDistancePick = this._shaderScaleByDistance; this._compiledShaderTranslucencyByDistancePick = this._shaderTranslucencyByDistance; this._compiledShaderPixelOffsetScaleByDistancePick = this._shaderPixelOffsetScaleByDistance; + this._compiledShaderDistanceDisplayConditionPick = this._shaderDistanceDisplayCondition; } va = this._vaf.va; diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 46f70ca719b2..9e06badb43ff 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -698,10 +698,10 @@ define([ '{ \n' + ' czm_non_distanceDisplayCondition_main(); \n' + ' vec4 centerRTE = czm_computeBoundingSphereCenter(); \n' + - ' float distance = length(centerRTE) - boundingSphereRadius; \n' + - ' float near = distanceDisplayCondition.x; \n' + - ' float far = distanceDisplayCondition.y; \n' + - ' float show = (distance >= near && distance <= far) ? 1.0 : 0.0; \n' + + ' float distanceSq = dot(centerRTE.xyz, centerRTE.xyz) - boundingSphereRadius * boundingSphereRadius; \n' + + ' float nearSq = distanceDisplayCondition.x * distanceDisplayCondition.x; \n' + + ' float farSq = distanceDisplayCondition.y * distanceDisplayCondition.y; \n' + + ' float show = (distanceSq >= nearSq && distanceSq <= farSq) ? 1.0 : 0.0; \n' + ' gl_Position *= show; \n' + '}'; return renamedVS + '\n' + distanceDisplayConditionMain; diff --git a/Source/Shaders/BillboardCollectionVS.glsl b/Source/Shaders/BillboardCollectionVS.glsl index 9ceae522f107..126b70786abb 100644 --- a/Source/Shaders/BillboardCollectionVS.glsl +++ b/Source/Shaders/BillboardCollectionVS.glsl @@ -9,6 +9,7 @@ attribute vec4 compressedAttribute2; // image height, color, pick color, attribute vec4 eyeOffset; // eye offset in meters, 4 bytes free (texture range) attribute vec4 scaleByDistance; // near, nearScale, far, farScale attribute vec4 pixelOffsetScaleByDistance; // near, nearScale, far, farScale +attribute vec2 distanceDisplayCondition; // near, far varying vec2 v_textureCoordinates; @@ -203,7 +204,7 @@ void main() /////////////////////////////////////////////////////////////////////////// -#if defined(EYE_DISTANCE_SCALING) || defined(EYE_DISTANCE_TRANSLUCENCY) || defined(EYE_DISTANCE_PIXEL_OFFSET) +#if defined(EYE_DISTANCE_SCALING) || defined(EYE_DISTANCE_TRANSLUCENCY) || defined(EYE_DISTANCE_PIXEL_OFFSET) || defined(DISTANCE_DISPLAY_CONDITION) float lengthSq; if (czm_sceneMode == czm_sceneMode2D) { @@ -241,6 +242,15 @@ void main() pixelOffset *= pixelOffsetScale; #endif +#ifdef DISTANCE_DISPLAY_CONDITION + float nearSq = distanceDisplayCondition.x * distanceDisplayCondition.x; + float farSq = distanceDisplayCondition.y * distanceDisplayCondition.y; + if (lengthSq < nearSq || lengthSq > farSq) + { + positionEC.xyz = vec3(0.0); + } +#endif + vec4 positionWC = computePositionWindowCoordinates(positionEC, imageSize, scale, direction, origin, translate, pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters); gl_Position = czm_viewportOrthographic * vec4(positionWC.xy, -positionWC.z, 1.0); v_textureCoordinates = textureCoordinates; From 0e9894f3d1335303b99c13363574ec0643f19166 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 8 Sep 2016 17:25:44 -0400 Subject: [PATCH 066/191] Change // to https:// --- Apps/Sandcastle/gallery/Cardboard.html | 2 +- Apps/Sandcastle/gallery/Shadows.html | 2 +- Apps/Sandcastle/gallery/development/Multiple Shadows.html | 2 +- Apps/Sandcastle/gallery/development/Shadows.html | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Apps/Sandcastle/gallery/Cardboard.html b/Apps/Sandcastle/gallery/Cardboard.html index cb0d07dfd594..3c0c199e3201 100644 --- a/Apps/Sandcastle/gallery/Cardboard.html +++ b/Apps/Sandcastle/gallery/Cardboard.html @@ -35,7 +35,7 @@ viewer.scene.globe.enableLighting = true; viewer.terrainProvider = new Cesium.CesiumTerrainProvider({ - url : '//assets.agi.com/stk-terrain/world', + url : 'https://assets.agi.com/stk-terrain/world', requestVertexNormals : true }); diff --git a/Apps/Sandcastle/gallery/Shadows.html b/Apps/Sandcastle/gallery/Shadows.html index af0faaac9463..0f524d53ee76 100644 --- a/Apps/Sandcastle/gallery/Shadows.html +++ b/Apps/Sandcastle/gallery/Shadows.html @@ -37,7 +37,7 @@ }); viewer.terrainProvider = new Cesium.CesiumTerrainProvider({ - url : '//assets.agi.com/stk-terrain/world', + url : 'https://assets.agi.com/stk-terrain/world', requestWaterMask : true, requestVertexNormals : true }); diff --git a/Apps/Sandcastle/gallery/development/Multiple Shadows.html b/Apps/Sandcastle/gallery/development/Multiple Shadows.html index 3ef885c19f1d..3794a9b205d0 100644 --- a/Apps/Sandcastle/gallery/development/Multiple Shadows.html +++ b/Apps/Sandcastle/gallery/development/Multiple Shadows.html @@ -44,7 +44,7 @@ timeline : false }); viewer.terrainProvider = new Cesium.CesiumTerrainProvider({ - url : '//assets.agi.com/stk-terrain/world', + url : 'https://assets.agi.com/stk-terrain/world', requestWaterMask : true, requestVertexNormals : true }); diff --git a/Apps/Sandcastle/gallery/development/Shadows.html b/Apps/Sandcastle/gallery/development/Shadows.html index 2bd2f4c3a484..91d9640a257d 100644 --- a/Apps/Sandcastle/gallery/development/Shadows.html +++ b/Apps/Sandcastle/gallery/development/Shadows.html @@ -482,7 +482,7 @@ var spotLightCamera = new Cesium.Camera(scene); var cesiumTerrainProvider = new Cesium.CesiumTerrainProvider({ - url : '//assets.agi.com/stk-terrain/world', + url : 'https://assets.agi.com/stk-terrain/world', requestWaterMask : true, requestVertexNormals : true }); From 396548a2263e41d4e87025921bb03cc1e257335a Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 8 Sep 2016 17:30:52 -0400 Subject: [PATCH 067/191] Add distance display conditions to labels. --- Source/Scene/Billboard.js | 5 +++-- Source/Scene/Label.js | 23 +++++++++++++++++++++++ Source/Scene/LabelCollection.js | 1 + 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Source/Scene/Billboard.js b/Source/Scene/Billboard.js index 40e29f3a1003..95bfca74761e 100644 --- a/Source/Scene/Billboard.js +++ b/Source/Scene/Billboard.js @@ -729,7 +729,7 @@ define([ return this._distanceDisplayCondition; }, set : function(value) { - if (DistanceDisplayCondition.equals(value, this._distanceDisplayCondition)) { + if (!DistanceDisplayCondition.equals(value, this._distanceDisplayCondition)) { this._distanceDisplayCondition = value; makeDirty(this, DISTANCE_DISPLAY_CONDITION); } @@ -1195,7 +1195,8 @@ define([ Cartesian3.equals(this._eyeOffset, other._eyeOffset) && NearFarScalar.equals(this._scaleByDistance, other._scaleByDistance) && NearFarScalar.equals(this._translucencyByDistance, other._translucencyByDistance) && - NearFarScalar.equals(this._pixelOffsetScaleByDistance, other._pixelOffsetScaleByDistance); + NearFarScalar.equals(this._pixelOffsetScaleByDistance, other._pixelOffsetScaleByDistance) && + DistanceDisplayCondition.equals(this._distanceDisplayCondition, other._distanceDisplayCondition); }; Billboard.prototype._destroy = function() { diff --git a/Source/Scene/Label.js b/Source/Scene/Label.js index 7bf979ef1936..e409b36c0680 100644 --- a/Source/Scene/Label.js +++ b/Source/Scene/Label.js @@ -7,6 +7,7 @@ define([ '../Core/defined', '../Core/defineProperties', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', '../Core/NearFarScalar', './Billboard', './HeightReference', @@ -21,6 +22,7 @@ define([ defined, defineProperties, DeveloperError, + DistanceDisplayCondition, NearFarScalar, Billboard, HeightReference, @@ -89,6 +91,7 @@ define([ this._translucencyByDistance = options.translucencyByDistance; this._pixelOffsetScaleByDistance = options.pixelOffsetScaleByDistance; this._heightReference = defaultValue(options.heightReference, HeightReference.NONE); + this._distanceDisplayCondition = options.distanceDisplayCondition; this._labelCollection = labelCollection; this._glyphs = []; @@ -652,6 +655,25 @@ define([ } }, + distanceDisplayCondition : { + get : function() { + return this._distanceDisplayCondition; + }, + set : function(value) { + if (!DistanceDisplayCondition.equals(value, this._distanceDisplayCondition)) { + this._distanceDisplayCondition = value; + + var glyphs = this._glyphs; + for (var i = 0, len = glyphs.length; i < len; i++) { + var glyph = glyphs[i]; + if (defined(glyph.billboard)) { + glyph.billboard.distanceDisplayCondition = value; + } + } + } + } + }, + /** * Gets or sets the user-defined object returned when the label is picked. * @memberof Label.prototype @@ -769,6 +791,7 @@ define([ Cartesian3.equals(this._eyeOffset, other._eyeOffset) && NearFarScalar.equals(this._translucencyByDistance, other._translucencyByDistance) && NearFarScalar.equals(this._pixelOffsetScaleByDistance, other._pixelOffsetScaleByDistance) && + DistanceDisplayCondition.equals(this._distanceDisplayCondition, other._distanceDisplayCondition) && this._id === other._id; }; diff --git a/Source/Scene/LabelCollection.js b/Source/Scene/LabelCollection.js index 6b28307d8c66..bbaa96c887a8 100644 --- a/Source/Scene/LabelCollection.js +++ b/Source/Scene/LabelCollection.js @@ -203,6 +203,7 @@ define([ billboard.image = id; billboard.translucencyByDistance = label._translucencyByDistance; billboard.pixelOffsetScaleByDistance = label._pixelOffsetScaleByDistance; + billboard.distanceDisplayCondition = label._distanceDisplayCondition; } } From f19aa4d47ee3912e63db248cecc1e806e69d2021 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 8 Sep 2016 18:57:28 -0400 Subject: [PATCH 068/191] Add distance display condition to point primitives. --- Source/Scene/BillboardCollection.js | 3 +- Source/Scene/PointPrimitive.js | 21 +++++++- Source/Scene/PointPrimitiveCollection.js | 51 +++++++++++++++++-- .../Shaders/PointPrimitiveCollectionVS.glsl | 11 +++- 4 files changed, 78 insertions(+), 8 deletions(-) diff --git a/Source/Scene/BillboardCollection.js b/Source/Scene/BillboardCollection.js index a1e651cea0ca..ca88717870bf 100644 --- a/Source/Scene/BillboardCollection.js +++ b/Source/Scene/BillboardCollection.js @@ -283,7 +283,8 @@ define([ BufferUsage.STATIC_DRAW, // ALIGNED_AXIS_INDEX BufferUsage.STATIC_DRAW, // SCALE_BY_DISTANCE_INDEX BufferUsage.STATIC_DRAW, // TRANSLUCENCY_BY_DISTANCE_INDEX - BufferUsage.STATIC_DRAW // PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX + BufferUsage.STATIC_DRAW, // PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX + BufferUsage.STATIC_DRAW // DISTANCE_DISPLAY_CONDITION_INDEX ]; var that = this; diff --git a/Source/Scene/PointPrimitive.js b/Source/Scene/PointPrimitive.js index bead41db9798..b17fcb977459 100644 --- a/Source/Scene/PointPrimitive.js +++ b/Source/Scene/PointPrimitive.js @@ -8,6 +8,7 @@ define([ '../Core/defined', '../Core/defineProperties', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', '../Core/Matrix4', '../Core/NearFarScalar', './SceneMode', @@ -21,6 +22,7 @@ define([ defined, defineProperties, DeveloperError, + DistanceDisplayCondition, Matrix4, NearFarScalar, SceneMode, @@ -72,6 +74,7 @@ define([ this._pixelSize = defaultValue(options.pixelSize, 10.0); this._scaleByDistance = options.scaleByDistance; this._translucencyByDistance = options.translucencyByDistance; + this._distanceDisplayCondition = options.distanceDisplayCondition; this._id = options.id; this._collection = defaultValue(options.collection, pointPrimitiveCollection); @@ -89,7 +92,8 @@ define([ var PIXEL_SIZE_INDEX = PointPrimitive.PIXEL_SIZE_INDEX = 5; var SCALE_BY_DISTANCE_INDEX = PointPrimitive.SCALE_BY_DISTANCE_INDEX = 6; var TRANSLUCENCY_BY_DISTANCE_INDEX = PointPrimitive.TRANSLUCENCY_BY_DISTANCE_INDEX = 7; - PointPrimitive.NUMBER_OF_PROPERTIES = 8; + var DISTANCE_DISPLAY_CONDITION_INDEX = PointPrimitive.DISTANCE_DISPLAY_CONDITION = 8; + PointPrimitive.NUMBER_OF_PROPERTIES = 9; function makeDirty(pointPrimitive, propertyChanged) { var pointPrimitiveCollection = pointPrimitive._pointPrimitiveCollection; @@ -339,6 +343,18 @@ define([ } }, + distanceDisplayCondition : { + get : function() { + return this._distanceDisplayCondition; + }, + set : function(value) { + if (!DistanceDisplayCondition.equals(this._distanceDisplayCondition, value)) { + this._distanceDisplayCondition = value; + makeDirty(this, DISTANCE_DISPLAY_CONDITION_INDEX); + } + } + }, + /** * Gets or sets the user-defined object returned when the point is picked. * @memberof PointPrimitive.prototype @@ -451,7 +467,8 @@ define([ this._show === other._show && Color.equals(this._outlineColor, other._outlineColor) && NearFarScalar.equals(this._scaleByDistance, other._scaleByDistance) && - NearFarScalar.equals(this._translucencyByDistance, other._translucencyByDistance); + NearFarScalar.equals(this._translucencyByDistance, other._translucencyByDistance) && + DistanceDisplayCondition.equals(this._distanceDisplayCondition, other._distanceDisplayCondition); }; PointPrimitive.prototype._destroy = function() { diff --git a/Source/Scene/PointPrimitiveCollection.js b/Source/Scene/PointPrimitiveCollection.js index eb9c513e6f89..ca72253b6b65 100644 --- a/Source/Scene/PointPrimitiveCollection.js +++ b/Source/Scene/PointPrimitiveCollection.js @@ -65,6 +65,7 @@ define([ var PIXEL_SIZE_INDEX = PointPrimitive.PIXEL_SIZE_INDEX; var SCALE_BY_DISTANCE_INDEX = PointPrimitive.SCALE_BY_DISTANCE_INDEX; var TRANSLUCENCY_BY_DISTANCE_INDEX = PointPrimitive.TRANSLUCENCY_BY_DISTANCE_INDEX; + var DISTANCE_DISPLAY_CONDITION_INDEX = PointPrimitive.DISTANCE_DISPLAY_CONDITION_INDEX; var NUMBER_OF_PROPERTIES = PointPrimitive.NUMBER_OF_PROPERTIES; var attributeLocations = { @@ -72,7 +73,8 @@ define([ positionLowAndOutline : 1, compressedAttribute0 : 2, // color, outlineColor, pick color compressedAttribute1 : 3, // show, translucency by distance, some free space - scaleByDistance : 4 + scaleByDistance : 4, + distanceDisplayCondition : 5 }; /** @@ -133,6 +135,10 @@ define([ this._compiledShaderTranslucencyByDistance = false; this._compiledShaderTranslucencyByDistancePick = false; + this._shaderDistanceDisplayCondition = false; + this._compiledShaderDistanceDisplayCondition = false; + this._compiledShaderDistanceDisplayConditionPick = false; + this._propertiesChanged = new Uint32Array(NUMBER_OF_PROPERTIES); this._maxPixelSize = 1.0; @@ -205,7 +211,8 @@ define([ BufferUsage.STATIC_DRAW, // OUTLINE_WIDTH_INDEX BufferUsage.STATIC_DRAW, // PIXEL_SIZE_INDEX BufferUsage.STATIC_DRAW, // SCALE_BY_DISTANCE_INDEX - BufferUsage.STATIC_DRAW // TRANSLUCENCY_BY_DISTANCE_INDEX + BufferUsage.STATIC_DRAW, // TRANSLUCENCY_BY_DISTANCE_INDEX + BufferUsage.STATIC_DRAW // DISTANCE_DISPLAY_CONDITION_INDEX ]; var that = this; @@ -465,6 +472,11 @@ define([ componentsPerAttribute : 4, componentDatatype : ComponentDatatype.FLOAT, usage : buffersUsage[SCALE_BY_DISTANCE_INDEX] + }, { + index : attributeLocations.distanceDisplayCondition, + componentsPerAttribute : 2, + componentDatatype : ComponentDatatype.FLOAT, + usage : buffersUsage[DISTANCE_DISPLAY_CONDITION_INDEX] }], numberOfPointPrimitives); // 1 vertex per pointPrimitive } @@ -600,11 +612,28 @@ define([ writer(i, near, nearValue, far, farValue); } + function writeDistanceDisplayCondition(pointPrimitiveCollection, context, vafWriters, pointPrimitive) { + var i = pointPrimitive._index; + var writer = vafWriters[attributeLocations.distanceDisplayCondition]; + var near = 0.0; + var far = Number.MAX_VALUE; + + var distanceDisplayCondition = pointPrimitive.distanceDisplayCondition; + if (defined(distanceDisplayCondition)) { + near = distanceDisplayCondition.near; + far = distanceDisplayCondition.far; + pointPrimitiveCollection._shaderDistanceDisplayCondition = true; + } + + writer(i, near, far); + } + function writePointPrimitive(pointPrimitiveCollection, context, vafWriters, pointPrimitive) { writePositionSizeAndOutline(pointPrimitiveCollection, context, vafWriters, pointPrimitive); writeCompressedAttrib0(pointPrimitiveCollection, context, vafWriters, pointPrimitive); writeCompressedAttrib1(pointPrimitiveCollection, context, vafWriters, pointPrimitive); writeScaleByDistance(pointPrimitiveCollection, context, vafWriters, pointPrimitive); + writeDistanceDisplayCondition(pointPrimitiveCollection, context, vafWriters, pointPrimitive); } function recomputeActualPositions(pointPrimitiveCollection, pointPrimitives, length, frameState, modelMatrix, recomputeBoundingVolume) { @@ -743,6 +772,10 @@ define([ writers.push(writeScaleByDistance); } + if (properties[DISTANCE_DISPLAY_CONDITION_INDEX]) { + writers.push(writeDistanceDisplayCondition); + } + var numWriters = writers.length; vafWriters = this._vaf.writers; @@ -827,7 +860,8 @@ define([ if (!defined(this._sp) || (this._shaderScaleByDistance && !this._compiledShaderScaleByDistance) || - (this._shaderTranslucencyByDistance && !this._compiledShaderTranslucencyByDistance)) { + (this._shaderTranslucencyByDistance && !this._compiledShaderTranslucencyByDistance) || + (this._shaderDistanceDisplayCondition && !this._compiledShaderDistanceDisplayCondition)) { vs = new ShaderSource({ sources : [PointPrimitiveCollectionVS] @@ -838,6 +872,9 @@ define([ if (this._shaderTranslucencyByDistance) { vs.defines.push('EYE_DISTANCE_TRANSLUCENCY'); } + if (this._shaderDistanceDisplayCondition) { + vs.defines.push('DISTANCE_DISPLAY_CONDITION'); + } this._sp = ShaderProgram.replaceCache({ context : context, @@ -849,6 +886,7 @@ define([ this._compiledShaderScaleByDistance = this._shaderScaleByDistance; this._compiledShaderTranslucencyByDistance = this._shaderTranslucencyByDistance; + this._compiledShaderDistanceDisplayCondition = this._shaderDistanceDisplayCondition; } va = this._vaf.va; @@ -882,7 +920,8 @@ define([ if (!defined(this._spPick) || (this._shaderScaleByDistance && !this._compiledShaderScaleByDistancePick) || - (this._shaderTranslucencyByDistance && !this._compiledShaderTranslucencyByDistancePick)) { + (this._shaderTranslucencyByDistance && !this._compiledShaderTranslucencyByDistancePick) || + (this._shaderDistanceDisplayCondition && !this._compiledShaderDistanceDisplayConditionPick)) { vs = new ShaderSource({ defines : ['RENDER_FOR_PICK'], @@ -895,6 +934,9 @@ define([ if (this._shaderTranslucencyByDistance) { vs.defines.push('EYE_DISTANCE_TRANSLUCENCY'); } + if (this._shaderDistanceDisplayCondition) { + vs.defines.push('DISTANCE_DISPLAY_CONDITION'); + } fs = new ShaderSource({ defines : ['RENDER_FOR_PICK'], @@ -911,6 +953,7 @@ define([ this._compiledShaderScaleByDistancePick = this._shaderScaleByDistance; this._compiledShaderTranslucencyByDistancePick = this._shaderTranslucencyByDistance; + this._compiledShaderDistanceDisplayConditionPick = this._shaderDistanceDisplayCondition; } va = this._vaf.va; diff --git a/Source/Shaders/PointPrimitiveCollectionVS.glsl b/Source/Shaders/PointPrimitiveCollectionVS.glsl index 629c8693f210..a11ea4b95f6b 100644 --- a/Source/Shaders/PointPrimitiveCollectionVS.glsl +++ b/Source/Shaders/PointPrimitiveCollectionVS.glsl @@ -5,6 +5,7 @@ attribute vec4 positionLowAndOutline; attribute vec4 compressedAttribute0; // color, outlineColor, pick color attribute vec4 compressedAttribute1; // show, translucency by distance, some free space attribute vec4 scaleByDistance; // near, nearScale, far, farScale +attribute vec2 distanceDisplayCondition; // near, far varying vec4 v_color; varying vec4 v_outlineColor; @@ -101,7 +102,7 @@ void main() /////////////////////////////////////////////////////////////////////////// -#if defined(EYE_DISTANCE_SCALING) || defined(EYE_DISTANCE_TRANSLUCENCY) +#if defined(EYE_DISTANCE_SCALING) || defined(EYE_DISTANCE_TRANSLUCENCY) || defined(DISTANCE_DISPLAY_CONDITION) float lengthSq; if (czm_sceneMode == czm_sceneMode2D) { @@ -138,6 +139,14 @@ void main() } #endif +#ifdef DISTANCE_DISPLAY_CONDITION + float nearSq = distanceDisplayCondition.x * distanceDisplayCondition.x; + float farSq = distanceDisplayCondition.y * distanceDisplayCondition.y; + if (lengthSq < nearSq || lengthSq > farSq) { + positionEC.xyz = vec3(0.0); + } +#endif + vec4 positionWC = czm_eyeToWindowCoordinates(positionEC); gl_Position = czm_viewportOrthographic * vec4(positionWC.xy, -positionWC.z, 1.0); From 4f52184ef7cc7d6703e145b3afdc5f6b14b93cb1 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Fri, 9 Sep 2016 11:40:52 -0400 Subject: [PATCH 069/191] fix timeline touch --- Source/Widgets/Timeline/Timeline.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Widgets/Timeline/Timeline.js b/Source/Widgets/Timeline/Timeline.js index 32eef7c42fca..4521a69d65a4 100644 --- a/Source/Widgets/Timeline/Timeline.js +++ b/Source/Widgets/Timeline/Timeline.js @@ -702,9 +702,9 @@ define([ var len = e.touches.length, leftX = timeline._topDiv.getBoundingClientRect().left; if (timeline._touchMode === timelineTouchMode.singleTap) { timeline._touchMode = timelineTouchMode.scrub; - timeline._handleTouchMove(e); + timeline._onTouchMove(e); } else if (timeline._touchMode === timelineTouchMode.scrub) { - timeline._handleTouchMove(e); + timeline._onTouchMove(e); } timeline._mouseMode = timelineMouseMode.touchOnly; if (len !== 1) { @@ -790,4 +790,4 @@ define([ }; return Timeline; -}); +}); \ No newline at end of file From 108cdcfd02a36465a059b6037d18c0a2387f2f34 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 9 Sep 2016 15:07:28 -0400 Subject: [PATCH 070/191] Add development Sandcastle example. --- .../development/Display Conditions.html | 108 ++++++++++++++++++ Source/Scene/Model.js | 5 +- 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 Apps/Sandcastle/gallery/development/Display Conditions.html diff --git a/Apps/Sandcastle/gallery/development/Display Conditions.html b/Apps/Sandcastle/gallery/development/Display Conditions.html new file mode 100644 index 000000000000..59ee264b88c6 --- /dev/null +++ b/Apps/Sandcastle/gallery/development/Display Conditions.html @@ -0,0 +1,108 @@ + + + + + + + + + Cesium Demo + + + + + + +
+

Loading...

+
+ + + diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js index 5644c433eb83..30036e2a8eb3 100644 --- a/Source/Scene/Model.js +++ b/Source/Scene/Model.js @@ -399,6 +399,8 @@ define([ */ this.show = defaultValue(options.show, true); + this.distanceDisplayCondition = options.distanceDisplayCondition; + /** * The 4x4 transformation matrix that transforms the model from model to world coordinates. * When this is the identity matrix, the model is drawn in world coordinates, i.e., Earth's WGS84 coordinates. @@ -3719,7 +3721,8 @@ define([ } } - var show = this.show && (this.scale !== 0.0); + var displayConditionPassed = defined(this.distanceDisplayCondition) ? this.distanceDisplayCondition.isVisible(this, frameState) : true; + var show = this.show && (this.scale !== 0.0) && displayConditionPassed; if ((show && this._state === ModelState.LOADED) || justLoaded) { var animated = this.activeAnimations.update(frameState) || this._cesiumAnimationsDirty; From b7a3997921676e98b8f3d2e95bad8f7c9cb7719e Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 9 Sep 2016 16:30:08 -0400 Subject: [PATCH 071/191] Add DistanceDisplayCondition and DistanceDisplayConditionGeometryInstanceAttribute tests. --- Source/Core/DistanceDisplayCondition.js | 22 +++---- ...splayConditionGeometryInstanceAttribute.js | 22 +++---- ...yConditionGeometryInstanceAttributeSpec.js | 59 +++++++++++++++++ Specs/Core/DistanceDisplayConditionSpec.js | 65 +++++++++++++++++++ 4 files changed, 146 insertions(+), 22 deletions(-) create mode 100644 Specs/Core/DistanceDisplayConditionGeometryInstanceAttributeSpec.js create mode 100644 Specs/Core/DistanceDisplayConditionSpec.js diff --git a/Source/Core/DistanceDisplayCondition.js b/Source/Core/DistanceDisplayCondition.js index 4bfc2ddb4ab3..78ddac662bf5 100644 --- a/Source/Core/DistanceDisplayCondition.js +++ b/Source/Core/DistanceDisplayCondition.js @@ -1,16 +1,16 @@ /*global define*/ define([ - './Cartesian3', - './defaultValue', - './defined', - './defineProperties', - './Matrix4' -], function( - Cartesian3, - defaultValue, - defined, - defineProperties, - Matrix4) { + './Cartesian3', + './defaultValue', + './defined', + './defineProperties', + './Matrix4' + ], function( + Cartesian3, + defaultValue, + defined, + defineProperties, + Matrix4) { 'use strict'; /** diff --git a/Source/Core/DistanceDisplayConditionGeometryInstanceAttribute.js b/Source/Core/DistanceDisplayConditionGeometryInstanceAttribute.js index e49e2765fdc8..375d7081261c 100644 --- a/Source/Core/DistanceDisplayConditionGeometryInstanceAttribute.js +++ b/Source/Core/DistanceDisplayConditionGeometryInstanceAttribute.js @@ -1,16 +1,16 @@ /*global define*/ define([ - './ComponentDatatype', - './defaultValue', - './defined', - './defineProperties', - './DeveloperError' -], function( - ComponentDatatype, - defaultValue, - defined, - defineProperties, - DeveloperError) { + './ComponentDatatype', + './defaultValue', + './defined', + './defineProperties', + './DeveloperError' + ], function( + ComponentDatatype, + defaultValue, + defined, + defineProperties, + DeveloperError) { 'use strict'; /** diff --git a/Specs/Core/DistanceDisplayConditionGeometryInstanceAttributeSpec.js b/Specs/Core/DistanceDisplayConditionGeometryInstanceAttributeSpec.js new file mode 100644 index 000000000000..6850a428ee70 --- /dev/null +++ b/Specs/Core/DistanceDisplayConditionGeometryInstanceAttributeSpec.js @@ -0,0 +1,59 @@ +/*global defineSuite*/ +defineSuite([ + 'Core/DistanceDisplayConditionGeometryInstanceAttribute', + 'Core/ComponentDatatype', + 'Core/DistanceDisplayCondition' + ], function( + DistanceDisplayConditionGeometryInstanceAttribute, + ComponentDatatype, + DistanceDisplayCondition) { + 'use strict'; + + it('constructor', function() { + var attribute = new DistanceDisplayConditionGeometryInstanceAttribute(10.0, 100.0); + expect(attribute.componentDatatype).toEqual(ComponentDatatype.FLOAT); + expect(attribute.componentsPerAttribute).toEqual(2); + expect(attribute.normalize).toEqual(false); + + var value = new Float32Array([10.0, 100.0]); + expect(attribute.value).toEqual(value); + }); + + it('fromDistanceDisplayCondition', function() { + var dc = new DistanceDisplayCondition(10.0, 100.0); + var attribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(dc); + expect(attribute.componentDatatype).toEqual(ComponentDatatype.FLOAT); + expect(attribute.componentsPerAttribute).toEqual(2); + expect(attribute.normalize).toEqual(false); + + var value = new Float32Array([dc.near, dc.far]); + expect(attribute.value).toEqual(value); + }); + + it('fromDistanceDisplayCondition throws without distanceDisplayCondition', function() { + expect(function() { + DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(); + }).toThrowDeveloperError(); + }); + + it('toValue', function() { + var dc = new DistanceDisplayCondition(10.0, 200.0); + var expectedResult = new Float32Array([dc.near, dc.far]); + expect(DistanceDisplayConditionGeometryInstanceAttribute.toValue(dc)).toEqual(expectedResult); + }); + + it('toValue works with result parameter', function() { + var dc = new DistanceDisplayCondition(10.0, 200.0); + var expectedResult = new Float32Array([dc.near, dc.far]); + var result = new Float32Array(2); + var returnedResult = DistanceDisplayConditionGeometryInstanceAttribute.toValue(dc, result); + expect(returnedResult).toBe(result); + expect(returnedResult).toEqual(expectedResult); + }); + + it('toValue throws without a distanceDisplayCondition', function() { + expect(function() { + DistanceDisplayConditionGeometryInstanceAttribute.toValue(); + }).toThrowDeveloperError(); + }); +}); diff --git a/Specs/Core/DistanceDisplayConditionSpec.js b/Specs/Core/DistanceDisplayConditionSpec.js new file mode 100644 index 000000000000..a6d7f14e9168 --- /dev/null +++ b/Specs/Core/DistanceDisplayConditionSpec.js @@ -0,0 +1,65 @@ +/*global definedSuite*/ +defineSuite([ + 'Core/DistanceDisplayCondition', + 'Core/Cartesian3', + 'Core/Matrix4' + ], function( + DistanceDisplayCondition, + Cartesian3, + Matrix4) { + 'use strict'; + + it('default constructs', function() { + var dc = new DistanceDisplayCondition(); + expect(dc.near).toEqual(0.0); + expect(dc.far).toEqual(Number.MAX_VALUE); + }); + + it('constructs with parameters', function() { + var near = 10.0; + var far = 100.0; + var dc = new DistanceDisplayCondition(near, far); + expect(dc.near).toEqual(near); + expect(dc.far).toEqual(far); + }); + + it('gets and sets properties', function() { + var dc = new DistanceDisplayCondition(); + + var near = 10.0; + var far = 100.0; + dc.near = near; + dc.far = far; + + expect(dc.near).toEqual(near); + expect(dc.far).toEqual(far); + }); + + it('determines if a primitive is visible', function() { + var mockPrimitive = { + modelMatrix : Matrix4.IDENTITY + }; + var mockFrameState = { + camera : { + positionWC : new Cartesian3(0.0, 0.0, 200.0) + } + }; + + var dc = new DistanceDisplayCondition(10.0, 100.0); + expect(dc.isVisible(mockPrimitive, mockFrameState)).toEqual(false); + + mockFrameState.camera.positionWC.z = 50.0; + expect(dc.isVisible(mockPrimitive, mockFrameState)).toEqual(true); + + mockFrameState.camera.positionWC.z = 5.0; + expect(dc.isVisible(mockPrimitive, mockFrameState)).toEqual(false); + }); + + it('determines equality', function() { + var dc = new DistanceDisplayCondition(10.0, 100.0); + expect(DistanceDisplayCondition.equals(dc, new DistanceDisplayCondition(10.0, 100.0))).toEqual(true); + expect(DistanceDisplayCondition.equals(dc, new DistanceDisplayCondition(11.0, 100.0))).toEqual(false); + expect(DistanceDisplayCondition.equals(dc, new DistanceDisplayCondition(10.0, 101.0))).toEqual(false); + expect(DistanceDisplayCondition.equals(dc, undefined)).toEqual(false); + }); +}); \ No newline at end of file From 9efeb5a4d1ef96fbdbb9c42477db6d1da79e131b Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 9 Sep 2016 17:13:31 -0400 Subject: [PATCH 072/191] Add distance display condition tests for billboards, points and labels. --- ...splayConditionGeometryInstanceAttribute.js | 13 ++++++ Source/Scene/Billboard.js | 9 ++++ Source/Scene/Label.js | 9 ++++ Source/Scene/PointPrimitive.js | 9 ++++ ...yConditionGeometryInstanceAttributeSpec.js | 12 +++++ Specs/Scene/BillboardCollectionSpec.js | 41 +++++++++++++++++ Specs/Scene/LabelCollectionSpec.js | 46 ++++++++++++++++++- Specs/Scene/PointPrimitiveCollectionSpec.js | 41 +++++++++++++++++ 8 files changed, 179 insertions(+), 1 deletion(-) diff --git a/Source/Core/DistanceDisplayConditionGeometryInstanceAttribute.js b/Source/Core/DistanceDisplayConditionGeometryInstanceAttribute.js index 375d7081261c..9d039fa3298f 100644 --- a/Source/Core/DistanceDisplayConditionGeometryInstanceAttribute.js +++ b/Source/Core/DistanceDisplayConditionGeometryInstanceAttribute.js @@ -22,6 +22,8 @@ define([ * @param {Number} [near=0.0] The near distance. * @param {Number} [far=Number.MAX_VALUE] The far distance. * + * @exception {DeveloperError} far must be greater than near. + * * @example * var instance = new Cesium.GeometryInstance({ * geometry : new Cesium.BoxGeometry({ @@ -44,6 +46,12 @@ define([ near = defaultValue(near, 0.0); far = defaultValue(far, Number.MAX_VALUE); + //>>includeStart('debug', pragmas.debug); + if (far <= near) { + throw new DeveloperError('far distance must be greater than near distance.'); + } + //>>includeEnd('debug'); + /** * The values for the attributes stored in a typed array. * @@ -113,6 +121,8 @@ define([ * @param {DistanceDisplayCondition} distanceDisplayCondition The distance display condition. * @returns {DistanceDisplayConditionGeometryInstanceAttribute} The new {@link DistanceDisplayConditionGeometryInstanceAttribute} instance. * + * @exception {DeveloperError} distanceDisplayCondition.far must be greater than distanceDisplayCondition.near + * * @example * var instance = new Cesium.GeometryInstance({ * geometry : geometry, @@ -126,6 +136,9 @@ define([ if (!defined(distanceDisplayCondition)) { throw new DeveloperError('distanceDisplayCondition is required.'); } + if (distanceDisplayCondition.far <= distanceDisplayCondition.near) { + throw new DeveloperError('distanceDisplayCondition.far distance must be greater than distanceDisplayCondition.near distance.'); + } //>>includeEnd('debug'); return new DistanceDisplayConditionGeometryInstanceAttribute(distanceDisplayCondition.near, distanceDisplayCondition.far); diff --git a/Source/Scene/Billboard.js b/Source/Scene/Billboard.js index 95bfca74761e..1d286d9d445d 100644 --- a/Source/Scene/Billboard.js +++ b/Source/Scene/Billboard.js @@ -63,6 +63,7 @@ define([ * @exception {DeveloperError} scaleByDistance.far must be greater than scaleByDistance.near * @exception {DeveloperError} translucencyByDistance.far must be greater than translucencyByDistance.near * @exception {DeveloperError} pixelOffsetScaleByDistance.far must be greater than pixelOffsetScaleByDistance.near + * @exception {DeveloperError} distanceDisplayCondition.far must be greater than distanceDisplayCondition.near * * @see BillboardCollection * @see BillboardCollection#add @@ -85,6 +86,9 @@ define([ if (defined(options.pixelOffsetScaleByDistance) && options.pixelOffsetScaleByDistance.far <= options.pixelOffsetScaleByDistance.near) { throw new DeveloperError('pixelOffsetScaleByDistance.far must be greater than pixelOffsetScaleByDistance.near.'); } + if (defined(options.distanceDisplayCondition) && options.distanceDisplayCondition.far <= options.distanceDisplayCondition.near) { + throw new DeveloperError('distanceDisplayCondition.far must be greater than distanceDisplayCondition.near'); + } //>>includeEnd('debug'); this._show = defaultValue(options.show, true); @@ -730,6 +734,11 @@ define([ }, set : function(value) { if (!DistanceDisplayCondition.equals(value, this._distanceDisplayCondition)) { + //>>includeStart('debug', pragmas.debug); + if (defined(value) && value.far <= value.near) { + throw new DeveloperError('far distance must be greater than near distance.'); + } + //>>includeEnd('debug'); this._distanceDisplayCondition = value; makeDirty(this, DISTANCE_DISPLAY_CONDITION); } diff --git a/Source/Scene/Label.js b/Source/Scene/Label.js index e409b36c0680..0d296573db64 100644 --- a/Source/Scene/Label.js +++ b/Source/Scene/Label.js @@ -56,6 +56,7 @@ define([ * * @exception {DeveloperError} translucencyByDistance.far must be greater than translucencyByDistance.near * @exception {DeveloperError} pixelOffsetScaleByDistance.far must be greater than pixelOffsetScaleByDistance.near + * @exception {DeveloperError} distanceDisplayCondition.far must be greater than distanceDisplayCondition.near * * @see LabelCollection * @see LabelCollection#add @@ -72,6 +73,9 @@ define([ if (defined(options.pixelOffsetScaleByDistance) && options.pixelOffsetScaleByDistance.far <= options.pixelOffsetScaleByDistance.near) { throw new DeveloperError('pixelOffsetScaleByDistance.far must be greater than pixelOffsetScaleByDistance.near.'); } + if (defined(options.distanceDisplayCondition) && options.distanceDisplayCondition.far <= options.distanceDisplayCondition.near) { + throw new DeveloperError('distanceDisplayCondition.far must be greater than distanceDisplayCondition.near'); + } //>>includeEnd('debug'); this._text = defaultValue(options.text, ''); @@ -660,6 +664,11 @@ define([ return this._distanceDisplayCondition; }, set : function(value) { + //>>includeStart('debug', pragmas.debug); + if (defined(value) && value.far <= value.near) { + throw new DeveloperError('far must be greater than near'); + } + //>>includeEnd('debug'); if (!DistanceDisplayCondition.equals(value, this._distanceDisplayCondition)) { this._distanceDisplayCondition = value; diff --git a/Source/Scene/PointPrimitive.js b/Source/Scene/PointPrimitive.js index b17fcb977459..b01f8ea7c036 100644 --- a/Source/Scene/PointPrimitive.js +++ b/Source/Scene/PointPrimitive.js @@ -45,6 +45,7 @@ define([ * * @exception {DeveloperError} scaleByDistance.far must be greater than scaleByDistance.near * @exception {DeveloperError} translucencyByDistance.far must be greater than translucencyByDistance.near + * @exception {DeveloperError} distanceDisplayCondition.far must be greater than distanceDisplayCondition.near * * @see PointPrimitiveCollection * @see PointPrimitiveCollection#add @@ -63,6 +64,9 @@ define([ if (defined(options.translucencyByDistance) && options.translucencyByDistance.far <= options.translucencyByDistance.near) { throw new DeveloperError('translucencyByDistance.far must be greater than translucencyByDistance.near.'); } + if (defined(options.distanceDisplayCondition) && options.distanceDisplayCondition.far <= options.distanceDisplayCondition.near) { + throw new DeveloperError('distanceDisplayCondition.far must be greater than distanceDisplayCondition.near'); + } //>>includeEnd('debug'); this._show = defaultValue(options.show, true); @@ -348,6 +352,11 @@ define([ return this._distanceDisplayCondition; }, set : function(value) { + //>>includeStart('debug', pragmas.debug); + if (defined(value) && value.far <= value.near) { + throw new DeveloperError('far must be greater than near'); + } + //>>includeEnd('debug'); if (!DistanceDisplayCondition.equals(this._distanceDisplayCondition, value)) { this._distanceDisplayCondition = value; makeDirty(this, DISTANCE_DISPLAY_CONDITION_INDEX); diff --git a/Specs/Core/DistanceDisplayConditionGeometryInstanceAttributeSpec.js b/Specs/Core/DistanceDisplayConditionGeometryInstanceAttributeSpec.js index 6850a428ee70..ee16c16be984 100644 --- a/Specs/Core/DistanceDisplayConditionGeometryInstanceAttributeSpec.js +++ b/Specs/Core/DistanceDisplayConditionGeometryInstanceAttributeSpec.js @@ -19,6 +19,12 @@ defineSuite([ expect(attribute.value).toEqual(value); }); + it('constructor throws with far > near', function() { + expect(function() { + return new DistanceDisplayConditionGeometryInstanceAttribute(100.0, 10.0); + }).toThrowDeveloperError(); + }); + it('fromDistanceDisplayCondition', function() { var dc = new DistanceDisplayCondition(10.0, 100.0); var attribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(dc); @@ -36,6 +42,12 @@ defineSuite([ }).toThrowDeveloperError(); }); + it('fromDistanceDisplayCondition throws with far >= near', function() { + expect(function() { + DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(new DistanceDisplayCondition(100.0, 10.0)); + }).toThrowDeveloperError(); + }); + it('toValue', function() { var dc = new DistanceDisplayCondition(10.0, 200.0); var expectedResult = new Float32Array([dc.near, dc.far]); diff --git a/Specs/Scene/BillboardCollectionSpec.js b/Specs/Scene/BillboardCollectionSpec.js index d6deef4ad98c..54d714aa6c19 100644 --- a/Specs/Scene/BillboardCollectionSpec.js +++ b/Specs/Scene/BillboardCollectionSpec.js @@ -9,6 +9,7 @@ defineSuite([ 'Core/Color', 'Core/defined', 'Core/defineProperties', + 'Core/DistanceDisplayCondition', 'Core/Ellipsoid', 'Core/Event', 'Core/loadImage', @@ -35,6 +36,7 @@ defineSuite([ Color, defined, defineProperties, + DistanceDisplayCondition, Ellipsoid, Event, loadImage, @@ -127,6 +129,7 @@ defineSuite([ expect(b.id).not.toBeDefined(); expect(b.heightReference).toEqual(HeightReference.NONE); expect(b.sizeInMeters).toEqual(false); + expect(b.distanceDisplayCondition).not.toBeDefined(); }); it('can add and remove before first update.', function() { @@ -159,6 +162,7 @@ defineSuite([ width : 300.0, height : 200.0, sizeInMeters : true, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0), id : 'id' }); @@ -182,6 +186,7 @@ defineSuite([ expect(b.width).toEqual(300.0); expect(b.height).toEqual(200.0); expect(b.sizeInMeters).toEqual(true); + expect(b.distanceDisplayCondition).toEqual(new DistanceDisplayCondition(10.0, 100.0)); expect(b.id).toEqual('id'); }); @@ -204,6 +209,7 @@ defineSuite([ b.translucencyByDistance = new NearFarScalar(1.0e6, 1.0, 1.0e8, 0.0); b.pixelOffsetScaleByDistance = new NearFarScalar(1.0e6, 3.0, 1.0e8, 0.0); b.sizeInMeters = true; + b.distanceDisplayCondition = new DistanceDisplayCondition(10.0, 100.0); expect(b.show).toEqual(false); expect(b.position).toEqual(new Cartesian3(1.0, 2.0, 3.0)); @@ -225,6 +231,7 @@ defineSuite([ expect(b.width).toEqual(300.0); expect(b.height).toEqual(200.0); expect(b.sizeInMeters).toEqual(true); + expect(b.distanceDisplayCondition).toEqual(new DistanceDisplayCondition(10.0, 100.0)); }); it('is not destroyed', function() { @@ -389,6 +396,40 @@ defineSuite([ }).toThrowDeveloperError(); }); + it('renders billboard with distanceDisplayCondition', function() { + billboards.add({ + position : Cartesian3.ZERO, + image : greenImage, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) + }); + + camera.position = new Cartesian3(200.0, 0.0, 0.0); + expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]); + + camera.position = new Cartesian3(50.0, 0.0, 0.0); + expect(scene.renderForSpecs()).toEqual([0, 255, 0, 255]); + + camera.position = new Cartesian3(5.0, 0.0, 0.0); + expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]); + }); + + it('throws new billboard with invalid distanceDisplayCondition (near >= far)', function() { + var dc = new DistanceDisplayCondition(100.0, 10.0); + expect(function() { + billboards.add({ + distanceDisplayCondition : dc + }); + }).toThrowDeveloperError(); + }); + + it('throws distanceDisplayCondition with near >= far', function() { + var b = billboards.add(); + var dc = new DistanceDisplayCondition(100.0, 10.0); + expect(function() { + b.distanceDisplayCondition = dc; + }).toThrowDeveloperError(); + }); + it('sets a removed billboard property', function() { var b = billboards.add(); billboards.remove(b); diff --git a/Specs/Scene/LabelCollectionSpec.js b/Specs/Scene/LabelCollectionSpec.js index ccf0b59de6f6..8000c113173f 100644 --- a/Specs/Scene/LabelCollectionSpec.js +++ b/Specs/Scene/LabelCollectionSpec.js @@ -6,6 +6,7 @@ defineSuite([ 'Core/Cartesian3', 'Core/Color', 'Core/defined', + 'Core/DistanceDisplayCondition', 'Core/Ellipsoid', 'Core/Math', 'Core/NearFarScalar', @@ -25,6 +26,7 @@ defineSuite([ Cartesian3, Color, defined, + DistanceDisplayCondition, Ellipsoid, CesiumMath, NearFarScalar, @@ -89,6 +91,7 @@ defineSuite([ expect(label.id).not.toBeDefined(); expect(label.translucencyByDistance).not.toBeDefined(); expect(label.pixelOffsetScaleByDistance).not.toBeDefined(); + expect(label.distanceDisplayCondition).not.toBeDefined(); }); it('can add a label with specified values', function() { @@ -118,6 +121,7 @@ defineSuite([ var scale = 2.0; var translucency = new NearFarScalar(1.0e4, 1.0, 1.0e6, 0.0); var pixelOffsetScale = new NearFarScalar(1.0e4, 1.0, 1.0e6, 0.0); + var distanceDisplayCondition = new DistanceDisplayCondition(10.0, 100.0); var label = labels.add({ show : show, position : position, @@ -134,7 +138,8 @@ defineSuite([ scale : scale, id : 'id', translucencyByDistance : translucency, - pixelOffsetScaleByDistance : pixelOffsetScale + pixelOffsetScaleByDistance : pixelOffsetScale, + distanceDisplayCondition : distanceDisplayCondition }); expect(label.show).toEqual(show); @@ -153,6 +158,7 @@ defineSuite([ expect(label.id).toEqual('id'); expect(label.translucencyByDistance).toEqual(translucency); expect(label.pixelOffsetScaleByDistance).toEqual(pixelOffsetScale); + expect(label.distanceDisplayCondition).toEqual(distanceDisplayCondition); }); it('can specify font using units other than pixels', function() { @@ -502,6 +508,44 @@ defineSuite([ expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]); }); + it('renders label with distanceDisplayCondition', function() { + labels.add({ + position : Cartesian3.ZERO, + text : 'm', + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0), + horizontalOrigin : HorizontalOrigin.CENTER, + verticalOrigin : VerticalOrigin.CENTER + }); + + camera.position = new Cartesian3(200.0, 0.0, 0.0); + expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]); + + camera.position = new Cartesian3(50.0, 0.0, 0.0); + expect(scene.renderForSpecs()[0]).toBeGreaterThan(200); + expect(scene.renderForSpecs()[1]).toBeGreaterThan(200); + expect(scene.renderForSpecs()[2]).toBeGreaterThan(200); + + camera.position = new Cartesian3(5.0, 0.0, 0.0); + expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]); + }); + + it('throws new label with invalid distanceDisplayCondition (near >= far)', function() { + var dc = new DistanceDisplayCondition(100.0, 10.0); + expect(function() { + labels.add({ + distanceDisplayCondition : dc + }); + }).toThrowDeveloperError(); + }); + + it('throws distanceDisplayCondition with near >= far', function() { + var l = labels.add(); + var dc = new DistanceDisplayCondition(100.0, 10.0); + expect(function() { + l.distanceDisplayCondition = dc; + }).toThrowDeveloperError(); + }); + it('can pick a label', function() { var label = labels.add({ position : Cartesian3.ZERO, diff --git a/Specs/Scene/PointPrimitiveCollectionSpec.js b/Specs/Scene/PointPrimitiveCollectionSpec.js index fc66dabb553e..a610065aa8b7 100644 --- a/Specs/Scene/PointPrimitiveCollectionSpec.js +++ b/Specs/Scene/PointPrimitiveCollectionSpec.js @@ -5,6 +5,7 @@ defineSuite([ 'Core/Cartesian2', 'Core/Cartesian3', 'Core/Color', + 'Core/DistanceDisplayCondition', 'Core/Math', 'Core/NearFarScalar', 'Core/Rectangle', @@ -16,6 +17,7 @@ defineSuite([ Cartesian2, Cartesian3, Color, + DistanceDisplayCondition, CesiumMath, NearFarScalar, Rectangle, @@ -66,6 +68,7 @@ defineSuite([ expect(p.outlineWidth).toEqual(0.0); expect(p.scaleByDistance).not.toBeDefined(); expect(p.translucencyByDistance).not.toBeDefined(); + expect(p.distanceDisplayCondition).not.toBeDefined(); expect(p.id).not.toBeDefined(); }); @@ -95,6 +98,7 @@ defineSuite([ outlineWidth : 4.0, scaleByDistance : new NearFarScalar(1.0, 3.0, 1.0e6, 0.0), translucencyByDistance : new NearFarScalar(1.0, 1.0, 1.0e6, 0.0), + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0), id : 'id' }); @@ -112,6 +116,7 @@ defineSuite([ expect(p.outlineWidth).toEqual(4.0); expect(p.scaleByDistance).toEqual(new NearFarScalar(1.0, 3.0, 1.0e6, 0.0)); expect(p.translucencyByDistance).toEqual(new NearFarScalar(1.0, 1.0, 1.0e6, 0.0)); + expect(p.distanceDisplayCondition).toEqual(new DistanceDisplayCondition(10.0, 100.0)); expect(p.id).toEqual('id'); }); @@ -125,6 +130,7 @@ defineSuite([ p.outlineWidth = 4.0; p.scaleByDistance = new NearFarScalar(1.0e6, 3.0, 1.0e8, 0.0); p.translucencyByDistance = new NearFarScalar(1.0e6, 1.0, 1.0e8, 0.0); + p.distanceDisplayCondition = new DistanceDisplayCondition(10.0, 100.0); expect(p.show).toEqual(false); expect(p.position).toEqual(new Cartesian3(1.0, 2.0, 3.0)); @@ -140,6 +146,7 @@ defineSuite([ expect(p.outlineWidth).toEqual(4.0); expect(p.scaleByDistance).toEqual(new NearFarScalar(1.0e6, 3.0, 1.0e8, 0.0)); expect(p.translucencyByDistance).toEqual(new NearFarScalar(1.0e6, 1.0, 1.0e8, 0.0)); + expect(p.distanceDisplayCondition).toEqual(new DistanceDisplayCondition(10.0, 100.0)); }); it('is not destroyed', function() { @@ -240,6 +247,40 @@ defineSuite([ }).toThrowDeveloperError(); }); + it('renders pointPrimitive with distanceDisplayCondition', function() { + pointPrimitives.add({ + position : Cartesian3.ZERO, + color : Color.LIME, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) + }); + + camera.position = new Cartesian3(200.0, 0.0, 0.0); + expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]); + + camera.position = new Cartesian3(50.0, 0.0, 0.0); + expect(scene.renderForSpecs()).toEqual([0, 255, 0, 255]); + + camera.position = new Cartesian3(5.0, 0.0, 0.0); + expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]); + }); + + it('throws new pointPrimitive with invalid distanceDisplayCondition (near >= far)', function() { + var dc = new DistanceDisplayCondition(100.0, 10.0); + expect(function() { + pointPrimitives.add({ + distanceDisplayCondition : dc + }); + }).toThrowDeveloperError(); + }); + + it('throws distanceDisplayCondition with near >= far', function() { + var p = pointPrimitives.add(); + var dc = new DistanceDisplayCondition(100.0, 10.0); + expect(function() { + p.distanceDisplayCondition = dc; + }).toThrowDeveloperError(); + }); + it('set a removed pointPrimitive property', function() { var p = pointPrimitives.add(); pointPrimitives.remove(p); From d324e149fbd3472f167c0716d8c1d3f9aea5573f Mon Sep 17 00:00:00 2001 From: Hannah Date: Mon, 12 Sep 2016 11:28:55 -0400 Subject: [PATCH 073/191] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 96bdf204acb0..c796e5d85259 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,7 @@ Change Log * Fixed billboard rotation when sized in meters. [#3979](https://github.com/AnalyticalGraphicsInc/cesium/issues/3979) * Added `DebugCameraPrimitive` to visualize the view frustum of a camera. +* Fixed touch events for the timeline [#4305](https://github.com/AnalyticalGraphicsInc/cesium/pull/4305) ### 1.25 - 2016-09-01 From 00a2e1037dde000bfa85ee31047d7f64c269c806 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 12 Sep 2016 14:37:34 -0400 Subject: [PATCH 074/191] Add model distance display condition tests. --- Source/Scene/Model.js | 24 ++++++- Specs/Core/DistanceDisplayConditionSpec.js | 2 +- Specs/Scene/ModelSpec.js | 77 +++++++++++++++++----- 3 files changed, 83 insertions(+), 20 deletions(-) diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js index 30036e2a8eb3..efb2118a61cb 100644 --- a/Source/Scene/Model.js +++ b/Source/Scene/Model.js @@ -14,6 +14,7 @@ define([ '../Core/deprecationWarning', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', '../Core/FeatureDetection', '../Core/getAbsoluteUri', '../Core/getBaseUri', @@ -74,6 +75,7 @@ define([ deprecationWarning, destroyObject, DeveloperError, + DistanceDisplayCondition, FeatureDetection, getAbsoluteUri, getBaseUri, @@ -399,8 +401,6 @@ define([ */ this.show = defaultValue(options.show, true); - this.distanceDisplayCondition = options.distanceDisplayCondition; - /** * The 4x4 transformation matrix that transforms the model from model to world coordinates. * When this is the identity matrix, the model is drawn in world coordinates, i.e., Earth's WGS84 coordinates. @@ -550,6 +550,8 @@ define([ this.debugWireframe = defaultValue(options.debugWireframe, false); this._debugWireframe = false; + this._distanceDisplayCondition = options.distanceDisplayCondition; + // Undocumented options this._precreatedAttributes = options.precreatedAttributes; this._vertexShaderLoaded = options.vertexShaderLoaded; @@ -913,6 +915,22 @@ define([ var receiveShadows = value; this.shadows = ShadowMode.fromCastReceive(castShadows, receiveShadows); } + }, + + distanceDisplayCondition : { + get : function() { + return this._distanceDisplayCondition; + }, + set : function(value) { + //>>includeStart('debug', pragmas.debug); + if (defined(value) && value.far <= value.near) { + throw new DeveloperError('far must be greater than near'); + } + //>>includeEnd('debug'); + if (!DistanceDisplayCondition.equals(value, this._distanceDisplayCondition)) { + this._distanceDisplayCondition = value; + } + } } }); @@ -3722,7 +3740,7 @@ define([ } var displayConditionPassed = defined(this.distanceDisplayCondition) ? this.distanceDisplayCondition.isVisible(this, frameState) : true; - var show = this.show && (this.scale !== 0.0) && displayConditionPassed; + var show = this.show && displayConditionPassed && (this.scale !== 0.0); if ((show && this._state === ModelState.LOADED) || justLoaded) { var animated = this.activeAnimations.update(frameState) || this._cesiumAnimationsDirty; diff --git a/Specs/Core/DistanceDisplayConditionSpec.js b/Specs/Core/DistanceDisplayConditionSpec.js index a6d7f14e9168..471139bdd73f 100644 --- a/Specs/Core/DistanceDisplayConditionSpec.js +++ b/Specs/Core/DistanceDisplayConditionSpec.js @@ -1,4 +1,4 @@ -/*global definedSuite*/ +/*global defineSuite*/ defineSuite([ 'Core/DistanceDisplayCondition', 'Core/Cartesian3', diff --git a/Specs/Scene/ModelSpec.js b/Specs/Scene/ModelSpec.js index 6378a68a6bdd..2699f497616c 100644 --- a/Specs/Scene/ModelSpec.js +++ b/Specs/Scene/ModelSpec.js @@ -10,6 +10,7 @@ defineSuite([ 'Core/defaultValue', 'Core/defined', 'Core/defineProperties', + 'Core/DistanceDisplayCondition', 'Core/Ellipsoid', 'Core/Event', 'Core/FeatureDetection', @@ -41,6 +42,7 @@ defineSuite([ defaultValue, defined, defineProperties, + DistanceDisplayCondition, Ellipsoid, Event, FeatureDetection, @@ -214,22 +216,23 @@ defineSuite([ it('sets model properties', function() { var modelMatrix = Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(0.0, 0.0, 100.0)); - expect(texturedBoxModel.gltf).toBeDefined(); - expect(texturedBoxModel.basePath).toEqual('./Data/Models/Box-Textured/'); - expect(texturedBoxModel.show).toEqual(false); - expect(texturedBoxModel.modelMatrix).toEqual(modelMatrix); - expect(texturedBoxModel.scale).toEqual(1.0); - expect(texturedBoxModel.minimumPixelSize).toEqual(0.0); - expect(texturedBoxModel.maximumScale).toBeUndefined(); - expect(texturedBoxModel.id).toEqual(texturedBoxUrl); - expect(texturedBoxModel.allowPicking).toEqual(true); - expect(texturedBoxModel.activeAnimations).toBeDefined(); - expect(texturedBoxModel.ready).toEqual(true); - expect(texturedBoxModel.asynchronous).toEqual(true); - expect(texturedBoxModel.releaseGltfJson).toEqual(false); - expect(texturedBoxModel.cacheKey).toEndWith('Data/Models/Box-Textured/CesiumTexturedBoxTest.gltf'); - expect(texturedBoxModel.debugShowBoundingVolume).toEqual(false); - expect(texturedBoxModel.debugWireframe).toEqual(false); + expect(texturedBoxModel.gltf).toBeDefined(); + expect(texturedBoxModel.basePath).toEqual('./Data/Models/Box-Textured/'); + expect(texturedBoxModel.show).toEqual(false); + expect(texturedBoxModel.modelMatrix).toEqual(modelMatrix); + expect(texturedBoxModel.scale).toEqual(1.0); + expect(texturedBoxModel.minimumPixelSize).toEqual(0.0); + expect(texturedBoxModel.maximumScale).toBeUndefined(); + expect(texturedBoxModel.id).toEqual(texturedBoxUrl); + expect(texturedBoxModel.allowPicking).toEqual(true); + expect(texturedBoxModel.activeAnimations).toBeDefined(); + expect(texturedBoxModel.ready).toEqual(true); + expect(texturedBoxModel.asynchronous).toEqual(true); + expect(texturedBoxModel.releaseGltfJson).toEqual(false); + expect(texturedBoxModel.cacheKey).toEndWith('Data/Models/Box-Textured/CesiumTexturedBoxTest.gltf'); + expect(texturedBoxModel.debugShowBoundingVolume).toEqual(false); + expect(texturedBoxModel.debugWireframe).toEqual(false); + expect(texturedBoxModel.distanceDisplayCondition).toBeUndefined(); }); it('renders', function() { @@ -373,6 +376,48 @@ defineSuite([ texturedBoxModel.debugWireframe = false; }); + it('renders with distance display condition', function() { + expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]); + + var center = Matrix4.getTranslation(texturedBoxModel.modelMatrix, new Cartesian3()); + var near = 10.0; + var far = 100.0; + + texturedBoxModel.show = true; + texturedBoxModel.distanceDisplayCondition = new DistanceDisplayCondition(near, far); + + var frameState = scene.frameState; + var commands = frameState.commandList; + + frameState.camera.lookAt(center, new HeadingPitchRange(0.0, 0.0, far + 10.0)); + frameState.camera.lookAtTransform(Matrix4.IDENTITY); + frameState.commandList = []; + texturedBoxModel.update(frameState); + expect(frameState.commandList.length).toEqual(0); + + frameState.camera.lookAt(center, new HeadingPitchRange(0.0, 0.0, (far + near) * 0.5)); + frameState.camera.lookAtTransform(Matrix4.IDENTITY); + frameState.commandList = []; + texturedBoxModel.update(frameState); + expect(frameState.commandList.length).toBeGreaterThan(0); + + frameState.camera.lookAt(center, new HeadingPitchRange(0.0, 0.0, near - 1.0)); + frameState.camera.lookAtTransform(Matrix4.IDENTITY); + frameState.commandList = []; + texturedBoxModel.update(frameState); + expect(frameState.commandList.length).toEqual(0); + + scene.frameState.commandList = commands; + texturedBoxModel.show = false; + texturedBoxModel.distanceDisplayCondition = undefined; + }); + + it('distanceDisplayCondition throws when ner >= far', function() { + expect(function() { + texturedBoxModel.distanceDisplayCondition = new DistanceDisplayCondition(100.0, 10.0); + }).toThrowDeveloperError(); + }); + it('getNode throws when model is not loaded', function() { var m = new Model(); expect(function() { From 366522b98ace69001c48b4c64bf8a56a06c75413 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 12 Sep 2016 14:49:29 -0400 Subject: [PATCH 075/191] Fix distance display conditions for primitives in 2D. --- Source/Scene/Primitive.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 9e06badb43ff..b0542ba0f41f 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -698,7 +698,16 @@ define([ '{ \n' + ' czm_non_distanceDisplayCondition_main(); \n' + ' vec4 centerRTE = czm_computeBoundingSphereCenter(); \n' + - ' float distanceSq = dot(centerRTE.xyz, centerRTE.xyz) - boundingSphereRadius * boundingSphereRadius; \n' + + ' float radiusSq = boundingSphereRadius * boundingSphereRadius; \n' + + ' float distanceSq; \n' + + ' if (czm_sceneMode == czm_sceneMode2D) \n' + + ' { \n' + + ' distanceSq = czm_eyeHeight2D.y - radiusSq; \n' + + ' } \n' + + ' else \n' + + ' { \n' + + ' distanceSq = dot(centerRTE.xyz, centerRTE.xyz) - radiusSq; \n' + + ' } \n' + ' float nearSq = distanceDisplayCondition.x * distanceDisplayCondition.x; \n' + ' float farSq = distanceDisplayCondition.y * distanceDisplayCondition.y; \n' + ' float show = (distanceSq >= nearSq && distanceSq <= farSq) ? 1.0 : 0.0; \n' + From 91d56c1df1f824a54786e0568e9321d71d1811dc Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 12 Sep 2016 16:11:52 -0400 Subject: [PATCH 076/191] Add tests for primitives with distance display conditions. --- Source/Scene/Primitive.js | 1 + Specs/Scene/PrimitiveSpec.js | 49 ++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index b0542ba0f41f..d5943931c751 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -708,6 +708,7 @@ define([ ' { \n' + ' distanceSq = dot(centerRTE.xyz, centerRTE.xyz) - radiusSq; \n' + ' } \n' + + ' distanceSq = max(distanceSq, 0.0); \n' + ' float nearSq = distanceDisplayCondition.x * distanceDisplayCondition.x; \n' + ' float farSq = distanceDisplayCondition.y * distanceDisplayCondition.y; \n' + ' float show = (distanceSq >= nearSq && distanceSq <= farSq) ? 1.0 : 0.0; \n' + diff --git a/Specs/Scene/PrimitiveSpec.js b/Specs/Scene/PrimitiveSpec.js index 36a4aafc0916..2731adb01b92 100644 --- a/Specs/Scene/PrimitiveSpec.js +++ b/Specs/Scene/PrimitiveSpec.js @@ -7,11 +7,14 @@ defineSuite([ 'Core/ColorGeometryInstanceAttribute', 'Core/ComponentDatatype', 'Core/defined', + 'Core/DistanceDisplayConditionGeometryInstanceAttribute', 'Core/Ellipsoid', 'Core/Geometry', 'Core/GeometryAttribute', 'Core/GeometryInstance', 'Core/GeometryInstanceAttribute', + 'Core/HeadingPitchRange', + 'Core/Math', 'Core/Matrix4', 'Core/PolygonGeometry', 'Core/PrimitiveType', @@ -36,11 +39,14 @@ defineSuite([ ColorGeometryInstanceAttribute, ComponentDatatype, defined, + DistanceDisplayConditionGeometryInstanceAttribute, Ellipsoid, Geometry, GeometryAttribute, GeometryInstance, GeometryInstanceAttribute, + HeadingPitchRange, + CesiumMath, Matrix4, PolygonGeometry, PrimitiveType, @@ -712,6 +718,49 @@ defineSuite([ expect(attributes.boundingSphere).toBeDefined(); }); + it('renders with distance display condition per instance attribute', function() { + var near = 10000.0; + var far = 1000000.0; + var rect = Rectangle.fromDegrees(-1.0, -1.0, 1.0, 1.0); + var translation = Cartesian3.multiplyByScalar(Cartesian3.normalize(ellipsoid.cartographicToCartesian(Rectangle.center(rect)), new Cartesian3()), 2.0, new Cartesian3()); + var rectInstance = new GeometryInstance({ + geometry : new RectangleGeometry({ + vertexFormat : PerInstanceColorAppearance.VERTEX_FORMAT, + ellipsoid : ellipsoid, + rectangle : rect + }), + modelMatrix : Matrix4.fromTranslation(translation, new Matrix4()), + id : 'rect', + attributes : { + color : new ColorGeometryInstanceAttribute(1.0, 1.0, 0.0, 1.0), + distanceDisplayCondition : new DistanceDisplayConditionGeometryInstanceAttribute(near, far) + } + }); + + primitive = new Primitive({ + geometryInstances : rectInstance, + appearance : new PerInstanceColorAppearance(), + asynchronous : false + }); + + scene.primitives.add(primitive); + scene.camera.setView({ destination : rect }); + scene.renderForSpecs(); + + var boundingSphere = primitive.getGeometryInstanceAttributes('rect').boundingSphere; + var center = boundingSphere.center; + var radius = boundingSphere.radius; + + scene.camera.lookAt(center, new HeadingPitchRange(0.0, -CesiumMath.PI_OVER_TWO, radius)); + expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]); + + scene.camera.lookAt(center, new HeadingPitchRange(0.0, -CesiumMath.PI_OVER_TWO, radius + near + 1.0)); + expect(scene.renderForSpecs()).not.toEqual([0, 0, 0, 255]); + + scene.camera.lookAt(center, new HeadingPitchRange(0.0, -CesiumMath.PI_OVER_TWO, radius + far + 1.0)); + expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]); + }); + it('getGeometryInstanceAttributes returns same object each time', function() { primitive = new Primitive({ geometryInstances : rectangleInstance1, From 0035a66a6c089e2451305bd8dac53855479aa208 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 12 Sep 2016 16:57:48 -0400 Subject: [PATCH 077/191] Add DistanceDisplayCondition.clone and have models, billboards, points, and labels clone the set display condition. --- Source/Core/DistanceDisplayCondition.js | 17 +++++++++++++++++ Source/Scene/Billboard.js | 2 +- Source/Scene/Label.js | 2 +- Source/Scene/Model.js | 2 +- Source/Scene/PointPrimitive.js | 2 +- Specs/Core/DistanceDisplayConditionSpec.js | 21 +++++++++++++++++++++ 6 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Source/Core/DistanceDisplayCondition.js b/Source/Core/DistanceDisplayCondition.js index 78ddac662bf5..8554235272c6 100644 --- a/Source/Core/DistanceDisplayCondition.js +++ b/Source/Core/DistanceDisplayCondition.js @@ -85,5 +85,22 @@ define([ left.far === right.far); }; + /** + * DOC_TBA + */ + DistanceDisplayCondition.clone = function(value, result) { + if (!defined(value)) { + return undefined; + } + + if (!defined(result)) { + result = new DistanceDisplayCondition(); + } + + result.near = value.near; + result.far = value.far; + return result; + }; + return DistanceDisplayCondition; }); \ No newline at end of file diff --git a/Source/Scene/Billboard.js b/Source/Scene/Billboard.js index 1d286d9d445d..042e2912f063 100644 --- a/Source/Scene/Billboard.js +++ b/Source/Scene/Billboard.js @@ -739,7 +739,7 @@ define([ throw new DeveloperError('far distance must be greater than near distance.'); } //>>includeEnd('debug'); - this._distanceDisplayCondition = value; + this._distanceDisplayCondition = DistanceDisplayCondition.clone(value, this._distanceDisplayCondition); makeDirty(this, DISTANCE_DISPLAY_CONDITION); } } diff --git a/Source/Scene/Label.js b/Source/Scene/Label.js index 0d296573db64..2a09aaaf719a 100644 --- a/Source/Scene/Label.js +++ b/Source/Scene/Label.js @@ -670,7 +670,7 @@ define([ } //>>includeEnd('debug'); if (!DistanceDisplayCondition.equals(value, this._distanceDisplayCondition)) { - this._distanceDisplayCondition = value; + this._distanceDisplayCondition = DistanceDisplayCondition.clone(value, this._distanceDisplayCondition); var glyphs = this._glyphs; for (var i = 0, len = glyphs.length; i < len; i++) { diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js index efb2118a61cb..6aa4eccfbdde 100644 --- a/Source/Scene/Model.js +++ b/Source/Scene/Model.js @@ -928,7 +928,7 @@ define([ } //>>includeEnd('debug'); if (!DistanceDisplayCondition.equals(value, this._distanceDisplayCondition)) { - this._distanceDisplayCondition = value; + this._distanceDisplayCondition = DistanceDisplayCondition.clone(value, this._distanceDisplayCondition); } } } diff --git a/Source/Scene/PointPrimitive.js b/Source/Scene/PointPrimitive.js index b01f8ea7c036..3873d28b1bce 100644 --- a/Source/Scene/PointPrimitive.js +++ b/Source/Scene/PointPrimitive.js @@ -358,7 +358,7 @@ define([ } //>>includeEnd('debug'); if (!DistanceDisplayCondition.equals(this._distanceDisplayCondition, value)) { - this._distanceDisplayCondition = value; + this._distanceDisplayCondition = DistanceDisplayCondition.clone(value, this._distanceDisplayCondition); makeDirty(this, DISTANCE_DISPLAY_CONDITION_INDEX); } } diff --git a/Specs/Core/DistanceDisplayConditionSpec.js b/Specs/Core/DistanceDisplayConditionSpec.js index 471139bdd73f..a268b13645db 100644 --- a/Specs/Core/DistanceDisplayConditionSpec.js +++ b/Specs/Core/DistanceDisplayConditionSpec.js @@ -62,4 +62,25 @@ defineSuite([ expect(DistanceDisplayCondition.equals(dc, new DistanceDisplayCondition(10.0, 101.0))).toEqual(false); expect(DistanceDisplayCondition.equals(dc, undefined)).toEqual(false); }); + + it('clones', function() { + var dc = new DistanceDisplayCondition(10.0, 100.0); + var result = DistanceDisplayCondition.clone(dc); + expect(dc).toEqual(result); + }); + + it('clone with a result parameter', function() { + var dc = new DistanceDisplayCondition(10.0, 100.0); + var result = new DistanceDisplayCondition(); + var returnedResult = DistanceDisplayCondition.clone(dc, result); + expect(dc).not.toBe(result); + expect(result).toBe(returnedResult); + expect(dc).toEqual(result); + }); + + it('clone works with a result parameter that is an input parameter', function() { + var dc = new DistanceDisplayCondition(10.0, 100.0); + var returnedResult = Cartesian3.clone(dc, dc); + expect(dc).toBe(returnedResult); + }); }); \ No newline at end of file From e1ee9fe4d7ad666a629826aab033d15b046d6a69 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 12 Sep 2016 18:56:24 -0400 Subject: [PATCH 078/191] Add entity support for distance display conditions to labels, billboards and points. --- Source/DataSources/BillboardGraphics.js | 8 +++++++- Source/DataSources/BillboardVisualizer.js | 4 ++++ Source/DataSources/LabelGraphics.js | 8 +++++++- Source/DataSources/LabelVisualizer.js | 4 ++++ Source/DataSources/PointGraphics.js | 8 +++++++- Source/DataSources/PointVisualizer.js | 5 +++++ Specs/DataSources/BillboardGraphicsSpec.js | 15 ++++++++++++++- Specs/DataSources/BillboardVisualizerSpec.js | 4 ++++ Specs/DataSources/LabelGraphicsSpec.js | 15 ++++++++++++++- Specs/DataSources/LabelVisualizerSpec.js | 6 ++++++ Specs/DataSources/PointGraphicsSpec.js | 15 ++++++++++++++- Specs/DataSources/PointVisualizerSpec.js | 12 +++++++++++- 12 files changed, 97 insertions(+), 7 deletions(-) diff --git a/Source/DataSources/BillboardGraphics.js b/Source/DataSources/BillboardGraphics.js index 9613c1ffb9b9..d5174d3ab1c8 100644 --- a/Source/DataSources/BillboardGraphics.js +++ b/Source/DataSources/BillboardGraphics.js @@ -86,6 +86,8 @@ define([ this._pixelOffsetScaleByDistanceSubscription = undefined; this._sizeInMeters = undefined; this._sizeInMetersSubscription = undefined; + this._distanceDisplayCondition = undefined; + this._distanceDisplayConditionSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -306,7 +308,9 @@ define([ * @type {Property} * @default false */ - sizeInMeters : createPropertyDescriptor('sizeInMeters') + sizeInMeters : createPropertyDescriptor('sizeInMeters'), + + distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition') }); /** @@ -337,6 +341,7 @@ define([ result.translucencyByDistance = this._translucencyByDistance; result.pixelOffsetScaleByDistance = this._pixelOffsetScaleByDistance; result.sizeInMeters = this._sizeInMeters; + result.distanceDisplayCondition = this._distanceDisplayCondition; return result; }; @@ -371,6 +376,7 @@ define([ this.translucencyByDistance = defaultValue(this._translucencyByDistance, source.translucencyByDistance); this.pixelOffsetScaleByDistance = defaultValue(this._pixelOffsetScaleByDistance, source.pixelOffsetScaleByDistance); this.sizeInMeters = defaultValue(this._sizeInMeters, source.sizeInMeters); + this.distanceDisplayCondition = defaultValue(this._distanceDisplayCondition, source.distanceDisplayCondition); }; return BillboardGraphics; diff --git a/Source/DataSources/BillboardVisualizer.js b/Source/DataSources/BillboardVisualizer.js index 51b252e79970..bd6d3402a432 100644 --- a/Source/DataSources/BillboardVisualizer.js +++ b/Source/DataSources/BillboardVisualizer.js @@ -9,6 +9,7 @@ define([ '../Core/defined', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', '../Core/NearFarScalar', '../Scene/BillboardCollection', '../Scene/HeightReference', @@ -26,6 +27,7 @@ define([ defined, destroyObject, DeveloperError, + DistanceDisplayCondition, NearFarScalar, BillboardCollection, HeightReference, @@ -54,6 +56,7 @@ define([ var translucencyByDistance = new NearFarScalar(); var pixelOffsetScaleByDistance = new NearFarScalar(); var boundingRectangle = new BoundingRectangle(); + var distanceDisplayCondition = new DistanceDisplayCondition(); function EntityData(entity) { this.entity = entity; @@ -167,6 +170,7 @@ define([ billboard.translucencyByDistance = Property.getValueOrUndefined(billboardGraphics._translucencyByDistance, time, translucencyByDistance); billboard.pixelOffsetScaleByDistance = Property.getValueOrUndefined(billboardGraphics._pixelOffsetScaleByDistance, time, pixelOffsetScaleByDistance); billboard.sizeInMeters = Property.getValueOrDefault(billboardGraphics._sizeInMeters, defaultSizeInMeters); + billboard.distanceDisplayCondition = Property.getValueOrUndefined(billboardGraphics._distanceDisplayCondition, time, distanceDisplayCondition); var subRegion = Property.getValueOrUndefined(billboardGraphics._imageSubRegion, time, boundingRectangle); if (defined(subRegion)) { diff --git a/Source/DataSources/LabelGraphics.js b/Source/DataSources/LabelGraphics.js index 6cc1ca46b1a6..ae8c58c809b4 100644 --- a/Source/DataSources/LabelGraphics.js +++ b/Source/DataSources/LabelGraphics.js @@ -77,6 +77,8 @@ define([ this._translucencyByDistanceSubscription = undefined; this._pixelOffsetScaleByDistance = undefined; this._pixelOffsetScaleByDistanceSubscription = undefined; + this._distanceDisplayCondition = undefined; + this._distanceDisplayConditionSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -249,7 +251,9 @@ define([ * @memberof LabelGraphics.prototype * @type {Property} */ - pixelOffsetScaleByDistance : createPropertyDescriptor('pixelOffsetScaleByDistance') + pixelOffsetScaleByDistance : createPropertyDescriptor('pixelOffsetScaleByDistance'), + + distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition') }); @@ -278,6 +282,7 @@ define([ result.pixelOffset = this.pixelOffset; result.translucencyByDistance = this.translucencyByDistance; result.pixelOffsetScaleByDistance = this.pixelOffsetScaleByDistance; + result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; @@ -309,6 +314,7 @@ define([ this.pixelOffset = defaultValue(this.pixelOffset, source.pixelOffset); this.translucencyByDistance = defaultValue(this._translucencyByDistance, source.translucencyByDistance); this.pixelOffsetScaleByDistance = defaultValue(this._pixelOffsetScaleByDistance, source.pixelOffsetScaleByDistance); + this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); }; return LabelGraphics; diff --git a/Source/DataSources/LabelVisualizer.js b/Source/DataSources/LabelVisualizer.js index 34183d2b2c94..e4f1679b5622 100644 --- a/Source/DataSources/LabelVisualizer.js +++ b/Source/DataSources/LabelVisualizer.js @@ -8,6 +8,7 @@ define([ '../Core/defined', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', '../Core/NearFarScalar', '../Scene/HeightReference', '../Scene/HorizontalOrigin', @@ -25,6 +26,7 @@ define([ defined, destroyObject, DeveloperError, + DistanceDisplayCondition, NearFarScalar, HeightReference, HorizontalOrigin, @@ -54,6 +56,7 @@ define([ var pixelOffset = new Cartesian2(); var translucencyByDistance = new NearFarScalar(); var pixelOffsetScaleByDistance = new NearFarScalar(); + var distanceDisplayCondition = new DistanceDisplayCondition(); function EntityData(entity) { this.entity = entity; @@ -165,6 +168,7 @@ define([ label.verticalOrigin = Property.getValueOrDefault(labelGraphics._verticalOrigin, time, defaultVerticalOrigin); label.translucencyByDistance = Property.getValueOrUndefined(labelGraphics._translucencyByDistance, time, translucencyByDistance); label.pixelOffsetScaleByDistance = Property.getValueOrUndefined(labelGraphics._pixelOffsetScaleByDistance, time, pixelOffsetScaleByDistance); + label.distanceDisplayCondition = Property.getValueOrUndefined(labelGraphics._distanceDisplayCondition, time, distanceDisplayCondition); } return true; }; diff --git a/Source/DataSources/PointGraphics.js b/Source/DataSources/PointGraphics.js index 55ebc5fc676e..a0869371aaea 100644 --- a/Source/DataSources/PointGraphics.js +++ b/Source/DataSources/PointGraphics.js @@ -47,6 +47,8 @@ define([ this._translucencyByDistanceSubscription = undefined; this._heightReference = undefined; this._heightReferenceSubscription = undefined; + this._distanceDisplayCondition = undefined; + this._distanceDisplayConditionSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -131,7 +133,9 @@ define([ * @type {Property} * @default HeightReference.NONE */ - heightReference : createPropertyDescriptor('heightReference') + heightReference : createPropertyDescriptor('heightReference'), + + distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition') }); /** @@ -152,6 +156,7 @@ define([ result.scaleByDistance = this.scaleByDistance; result.translucencyByDistance = this._translucencyByDistance; result.heightReference = this.heightReference; + result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; @@ -176,6 +181,7 @@ define([ this.scaleByDistance = defaultValue(this.scaleByDistance, source.scaleByDistance); this.translucencyByDistance = defaultValue(this._translucencyByDistance, source.translucencyByDistance); this.heightReference = defaultValue(this.heightReference, source.heightReference); + this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); }; return PointGraphics; diff --git a/Source/DataSources/PointVisualizer.js b/Source/DataSources/PointVisualizer.js index b7bbe52fb024..cb459e30d550 100644 --- a/Source/DataSources/PointVisualizer.js +++ b/Source/DataSources/PointVisualizer.js @@ -7,6 +7,7 @@ define([ '../Core/defined', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', '../Core/NearFarScalar', '../Scene/BillboardCollection', '../Scene/HeightReference', @@ -21,6 +22,7 @@ define([ defined, destroyObject, DeveloperError, + DistanceDisplayCondition, NearFarScalar, BillboardCollection, HeightReference, @@ -39,6 +41,7 @@ define([ var outlineColor = new Color(); var scaleByDistance = new NearFarScalar(); var translucencyByDistance = new NearFarScalar(); + var distanceDisplayCondition = new DistanceDisplayCondition(); function EntityData(entity) { this.entity = entity; @@ -171,11 +174,13 @@ define([ pointPrimitive.outlineColor = Property.getValueOrDefault(pointGraphics._outlineColor, time, defaultOutlineColor, outlineColor); pointPrimitive.outlineWidth = Property.getValueOrDefault(pointGraphics._outlineWidth, time, defaultOutlineWidth); pointPrimitive.pixelSize = Property.getValueOrDefault(pointGraphics._pixelSize, time, defaultPixelSize); + pointPrimitive.distanceDisplayCondition = Property.getValueOrUndefined(pointGraphics._distanceDisplayCondition, time, distanceDisplayCondition); } else { // billboard billboard.show = true; billboard.position = position; billboard.scaleByDistance = Property.getValueOrUndefined(pointGraphics._scaleByDistance, time, scaleByDistance); billboard.translucencyByDistance = Property.getValueOrUndefined(pointGraphics._translucencyByDistance, time, translucencyByDistance); + billboard.distanceDisplayCondition = Property.getValueOrUndefined(pointGraphics._distanceDisplayCondition, time, distanceDisplayCondition); billboard.heightReference = heightReference; var newColor = Property.getValueOrDefault(pointGraphics._color, time, defaultColor, color); diff --git a/Specs/DataSources/BillboardGraphicsSpec.js b/Specs/DataSources/BillboardGraphicsSpec.js index 123bdba159a4..efdbb17cb80d 100644 --- a/Specs/DataSources/BillboardGraphicsSpec.js +++ b/Specs/DataSources/BillboardGraphicsSpec.js @@ -4,6 +4,7 @@ defineSuite([ 'Core/Cartesian2', 'Core/Cartesian3', 'Core/Color', + 'Core/DistanceDisplayCondition', 'Core/NearFarScalar', 'DataSources/ConstantProperty', 'Scene/HeightReference', @@ -14,6 +15,7 @@ defineSuite([ Cartesian2, Cartesian3, Color, + DistanceDisplayCondition, NearFarScalar, ConstantProperty, HeightReference, @@ -39,7 +41,8 @@ defineSuite([ scaleByDistance : new NearFarScalar(13, 14, 15, 16), translucencyByDistance : new NearFarScalar(17, 18, 19, 20), pixelOffsetScaleByDistance : new NearFarScalar(21, 22, 23, 24), - sizeInMeters : true + sizeInMeters : true, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) }; var billboard = new BillboardGraphics(options); @@ -59,6 +62,7 @@ defineSuite([ expect(billboard.translucencyByDistance).toBeInstanceOf(ConstantProperty); expect(billboard.pixelOffsetScaleByDistance).toBeInstanceOf(ConstantProperty); expect(billboard.sizeInMeters).toBeInstanceOf(ConstantProperty); + expect(billboard.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(billboard.image.getValue()).toEqual(options.image); expect(billboard.rotation.getValue()).toEqual(options.rotation); @@ -76,6 +80,7 @@ defineSuite([ expect(billboard.translucencyByDistance.getValue()).toEqual(options.translucencyByDistance); expect(billboard.pixelOffsetScaleByDistance.getValue()).toEqual(options.pixelOffsetScaleByDistance); expect(billboard.sizeInMeters.getValue()).toEqual(options.sizeInMeters); + expect(billboard.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); }); it('merge assigns unassigned properties', function() { @@ -98,6 +103,7 @@ defineSuite([ source.translucencyByDistance = new ConstantProperty(new NearFarScalar()); source.pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar(1.0, 0.0, 3.0e9, 0.0)); source.sizeInMeters = new ConstantProperty(true); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var target = new BillboardGraphics(); target.merge(source); @@ -120,6 +126,7 @@ defineSuite([ expect(target.translucencyByDistance).toBe(source.translucencyByDistance); expect(target.pixelOffsetScaleByDistance).toBe(source.pixelOffsetScaleByDistance); expect(target.sizeInMeters).toBe(source.sizeInMeters); + expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge does not assign assigned properties', function() { @@ -142,6 +149,7 @@ defineSuite([ source.translucencyByDistance = new ConstantProperty(new NearFarScalar()); source.pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar(1.0, 0.0, 3.0e9, 0.0)); source.sizeInMeters = new ConstantProperty(true); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var image = new ConstantProperty(''); var imageSubRegion = new ConstantProperty(); @@ -161,6 +169,7 @@ defineSuite([ var translucencyByDistance = new ConstantProperty(new NearFarScalar()); var pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar()); var sizeInMeters = new ConstantProperty(true); + var distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var target = new BillboardGraphics(); target.image = image; @@ -181,6 +190,7 @@ defineSuite([ target.translucencyByDistance = translucencyByDistance; target.pixelOffsetScaleByDistance = pixelOffsetScaleByDistance; target.sizeInMeters = sizeInMeters; + target.distanceDisplayCondition = distanceDisplayCondition; target.merge(source); @@ -202,6 +212,7 @@ defineSuite([ expect(target.translucencyByDistance).toBe(translucencyByDistance); expect(target.pixelOffsetScaleByDistance).toBe(pixelOffsetScaleByDistance); expect(target.sizeInMeters).toBe(sizeInMeters); + expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); }); it('clone works', function() { @@ -224,6 +235,7 @@ defineSuite([ source.translucencyByDistance = new ConstantProperty(new NearFarScalar()); source.pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar(1.0, 0.0, 3.0e9, 0.0)); source.sizeInMeters = new ConstantProperty(true); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var result = source.clone(); expect(result.image).toBe(source.image); @@ -244,6 +256,7 @@ defineSuite([ expect(result.translucencyByDistance).toBe(source.translucencyByDistance); expect(result.pixelOffsetScaleByDistance).toBe(source.pixelOffsetScaleByDistance); expect(result.sizeInMeters).toBe(source.sizeInMeters); + expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge throws if source undefined', function() { diff --git a/Specs/DataSources/BillboardVisualizerSpec.js b/Specs/DataSources/BillboardVisualizerSpec.js index 10b032f27d04..5a41a1379c30 100644 --- a/Specs/DataSources/BillboardVisualizerSpec.js +++ b/Specs/DataSources/BillboardVisualizerSpec.js @@ -6,6 +6,7 @@ defineSuite([ 'Core/Cartesian2', 'Core/Cartesian3', 'Core/Color', + 'Core/DistanceDisplayCondition', 'Core/JulianDate', 'Core/NearFarScalar', 'DataSources/BillboardGraphics', @@ -26,6 +27,7 @@ defineSuite([ Cartesian2, Cartesian3, Color, + DistanceDisplayCondition, JulianDate, NearFarScalar, BillboardGraphics, @@ -153,6 +155,7 @@ defineSuite([ billboard.translucencyByDistance = new ConstantProperty(new NearFarScalar()); billboard.pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar(1.0, 0.0, 3.0e9, 0.0)); billboard.sizeInMeters = new ConstantProperty(true); + billboard.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); visualizer.update(time); @@ -180,6 +183,7 @@ defineSuite([ expect(bb.translucencyByDistance).toEqual(testObject.billboard.translucencyByDistance.getValue(time)); expect(bb.pixelOffsetScaleByDistance).toEqual(testObject.billboard.pixelOffsetScaleByDistance.getValue(time)); expect(bb.sizeInMeters).toEqual(testObject.billboard.sizeInMeters.getValue(time)); + expect(bb.distanceDisplayCondition).toEqual(testObject.billboard.distanceDisplayCondition.getValue(time)); expect(bb._imageSubRegion).toEqual(testObject.billboard.imageSubRegion.getValue(time)); billboard.show = new ConstantProperty(false); diff --git a/Specs/DataSources/LabelGraphicsSpec.js b/Specs/DataSources/LabelGraphicsSpec.js index 98a386da06ff..1575a6057bd2 100644 --- a/Specs/DataSources/LabelGraphicsSpec.js +++ b/Specs/DataSources/LabelGraphicsSpec.js @@ -4,6 +4,7 @@ defineSuite([ 'Core/Cartesian2', 'Core/Cartesian3', 'Core/Color', + 'Core/DistanceDisplayCondition', 'Core/NearFarScalar', 'DataSources/ConstantProperty', 'Scene/HorizontalOrigin', @@ -14,6 +15,7 @@ defineSuite([ Cartesian2, Cartesian3, Color, + DistanceDisplayCondition, NearFarScalar, ConstantProperty, HorizontalOrigin, @@ -36,7 +38,8 @@ defineSuite([ scale : 8, show : true, translucencyByDistance : new NearFarScalar(9, 10, 11, 12), - pixelOffsetScaleByDistance : new NearFarScalar(13, 14, 15, 16) + pixelOffsetScaleByDistance : new NearFarScalar(13, 14, 15, 16), + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) }; var label = new LabelGraphics(options); @@ -53,6 +56,7 @@ defineSuite([ expect(label.show).toBeInstanceOf(ConstantProperty); expect(label.translucencyByDistance).toBeInstanceOf(ConstantProperty); expect(label.pixelOffsetScaleByDistance).toBeInstanceOf(ConstantProperty); + expect(label.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(label.text.getValue()).toEqual(options.text); expect(label.font.getValue()).toEqual(options.font); @@ -67,6 +71,7 @@ defineSuite([ expect(label.show.getValue()).toEqual(options.show); expect(label.translucencyByDistance.getValue()).toEqual(options.translucencyByDistance); expect(label.pixelOffsetScaleByDistance.getValue()).toEqual(options.pixelOffsetScaleByDistance); + expect(label.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); }); it('merge assigns unassigned properties', function() { @@ -85,6 +90,7 @@ defineSuite([ source.show = new ConstantProperty(false); source.translucencyByDistance = new ConstantProperty(new NearFarScalar()); source.pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar(1.0, 0.0, 3.0e9, 0.0)); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var target = new LabelGraphics(); target.merge(source); @@ -103,6 +109,7 @@ defineSuite([ expect(target.show).toBe(source.show); expect(target.translucencyByDistance).toBe(source.translucencyByDistance); expect(target.pixelOffsetScaleByDistance).toBe(source.pixelOffsetScaleByDistance); + expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge does not assign assigned properties', function() { @@ -121,6 +128,7 @@ defineSuite([ source.show = new ConstantProperty(false); source.translucencyByDistance = new ConstantProperty(new NearFarScalar()); source.pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar(1.0, 0.0, 3.0e9, 0.0)); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var text = new ConstantProperty('my text'); var font = new ConstantProperty('10px serif'); @@ -136,6 +144,7 @@ defineSuite([ var show = new ConstantProperty(true); var translucencyByDistance = new ConstantProperty(new NearFarScalar()); var pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar()); + var distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var target = new LabelGraphics(); target.text = text; @@ -152,6 +161,7 @@ defineSuite([ target.show = show; target.translucencyByDistance = translucencyByDistance; target.pixelOffsetScaleByDistance = pixelOffsetScaleByDistance; + target.distanceDisplayCondition = distanceDisplayCondition; target.merge(source); @@ -169,6 +179,7 @@ defineSuite([ expect(target.show).toBe(show); expect(target.translucencyByDistance).toBe(translucencyByDistance); expect(target.pixelOffsetScaleByDistance).toBe(pixelOffsetScaleByDistance); + expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); }); it('clone works', function() { @@ -187,6 +198,7 @@ defineSuite([ source.show = new ConstantProperty(false); source.translucencyByDistance = new ConstantProperty(new NearFarScalar()); source.pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar(1.0, 0.0, 3.0e9, 0.0)); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var result = source.clone(); expect(result.text).toBe(source.text); @@ -203,6 +215,7 @@ defineSuite([ expect(result.show).toBe(source.show); expect(result.translucencyByDistance).toBe(source.translucencyByDistance); expect(result.pixelOffsetScaleByDistance).toBe(source.pixelOffsetScaleByDistance); + expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge throws if source undefined', function() { diff --git a/Specs/DataSources/LabelVisualizerSpec.js b/Specs/DataSources/LabelVisualizerSpec.js index 1d689388a59e..c3fd7636c439 100644 --- a/Specs/DataSources/LabelVisualizerSpec.js +++ b/Specs/DataSources/LabelVisualizerSpec.js @@ -5,6 +5,7 @@ defineSuite([ 'Core/Cartesian2', 'Core/Cartesian3', 'Core/Color', + 'Core/DistanceDisplayCondition', 'Core/JulianDate', 'Core/NearFarScalar', 'DataSources/BoundingSphereState', @@ -23,6 +24,7 @@ defineSuite([ Cartesian2, Cartesian3, Color, + DistanceDisplayCondition, JulianDate, NearFarScalar, BoundingSphereState, @@ -145,6 +147,7 @@ defineSuite([ label.show = new ConstantProperty(true); label.translucencyByDistance = new ConstantProperty(new NearFarScalar()); label.pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar()); + label.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); visualizer.update(time); @@ -169,6 +172,7 @@ defineSuite([ expect(l.show).toEqual(testObject.label.show.getValue(time)); expect(l.translucencyByDistance).toEqual(testObject.label.translucencyByDistance.getValue(time)); expect(l.pixelOffsetScaleByDistance).toEqual(testObject.label.pixelOffsetScaleByDistance.getValue(time)); + expect(l.distanceDisplayCondition).toEqual(testObject.label.distanceDisplayCondition.getValue(time)); testObject.position = new ConstantProperty(new Cartesian3(5678, 1234, 1293434)); label.text = new ConstantProperty('b'); @@ -185,6 +189,7 @@ defineSuite([ label.show = new ConstantProperty(true); label.translucencyByDistance = new ConstantProperty(new NearFarScalar()); label.pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar()); + label.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); visualizer.update(time); expect(l.position).toEqual(testObject.position.getValue(time)); @@ -202,6 +207,7 @@ defineSuite([ expect(l.show).toEqual(testObject.label.show.getValue(time)); expect(l.translucencyByDistance).toEqual(testObject.label.translucencyByDistance.getValue(time)); expect(l.pixelOffsetScaleByDistance).toEqual(testObject.label.pixelOffsetScaleByDistance.getValue(time)); + expect(l.distanceDisplayCondition).toEqual(testObject.label.distanceDisplayCondition.getValue(time)); label.show = new ConstantProperty(false); visualizer.update(time); diff --git a/Specs/DataSources/PointGraphicsSpec.js b/Specs/DataSources/PointGraphicsSpec.js index 9273a4a75c7f..912a67f2586c 100644 --- a/Specs/DataSources/PointGraphicsSpec.js +++ b/Specs/DataSources/PointGraphicsSpec.js @@ -2,12 +2,14 @@ defineSuite([ 'DataSources/PointGraphics', 'Core/Color', + 'Core/DistanceDisplayCondition', 'Core/NearFarScalar', 'DataSources/ConstantProperty', 'Scene/HeightReference' ], function( PointGraphics, Color, + DistanceDisplayCondition, NearFarScalar, ConstantProperty, HeightReference) { @@ -21,7 +23,8 @@ defineSuite([ outlineWidth : 2, show : false, scaleByDistance : new NearFarScalar(3, 4, 5, 6), - heightReference : HeightReference.RELATIVE_TO_GROUND + heightReference : HeightReference.RELATIVE_TO_GROUND, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) }; var point = new PointGraphics(options); @@ -32,6 +35,7 @@ defineSuite([ expect(point.show).toBeInstanceOf(ConstantProperty); expect(point.scaleByDistance).toBeInstanceOf(ConstantProperty); expect(point.heightReference).toBeInstanceOf(ConstantProperty); + expect(point.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(point.color.getValue()).toEqual(options.color); expect(point.pixelSize.getValue()).toEqual(options.pixelSize); @@ -40,6 +44,7 @@ defineSuite([ expect(point.show.getValue()).toEqual(options.show); expect(point.scaleByDistance.getValue()).toEqual(options.scaleByDistance); expect(point.heightReference.getValue()).toEqual(options.heightReference); + expect(point.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); }); it('merge assigns unassigned properties', function() { @@ -51,6 +56,7 @@ defineSuite([ source.show = new ConstantProperty(true); source.scaleByDistance = new ConstantProperty(new NearFarScalar()); source.heightReference = new ConstantProperty(HeightReference.RELATIVE_TO_GROUND); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var target = new PointGraphics(); target.merge(source); @@ -61,6 +67,7 @@ defineSuite([ expect(target.show).toBe(source.show); expect(target.scaleByDistance).toBe(source.scaleByDistance); expect(target.heightReference).toBe(source.heightReference); + expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge does not assign assigned properties', function() { @@ -72,6 +79,7 @@ defineSuite([ source.show = new ConstantProperty(true); source.scaleByDistance = new ConstantProperty(new NearFarScalar()); source.heightReference = new ConstantProperty(HeightReference.RELATIVE_TO_GROUND); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var color = new ConstantProperty(Color.WHITE); var pixelSize = new ConstantProperty(1); @@ -79,6 +87,7 @@ defineSuite([ var outlineWidth = new ConstantProperty(1); var show = new ConstantProperty(true); var heightReference = new ConstantProperty(HeightReference.CLAMP_TO_GROUND); + var distanDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var target = new PointGraphics(); target.color = color; @@ -88,6 +97,7 @@ defineSuite([ target.show = show; target.scaleByDistance = show; target.heightReference = heightReference; + target.distanceDisplayCondition = distanDisplayCondition; target.merge(source); expect(target.color).toBe(color); @@ -97,6 +107,7 @@ defineSuite([ expect(target.show).toBe(show); expect(target.scaleByDistance).toBe(show); expect(target.heightReference).toBe(heightReference); + expect(target.distanceDisplayCondition).toBe(distanDisplayCondition); }); it('clone works', function() { @@ -108,6 +119,7 @@ defineSuite([ source.show = new ConstantProperty(true); source.scaleByDistance = new ConstantProperty(new NearFarScalar()); source.heightReference = new ConstantProperty(HeightReference.RELATIVE_TO_GROUND); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var result = source.clone(); expect(result.color).toBe(source.color); @@ -117,6 +129,7 @@ defineSuite([ expect(result.show).toBe(source.show); expect(result.scaleByDistance).toBe(source.scaleByDistance); expect(result.heightReference).toBe(source.heightReference); + expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge throws if source undefined', function() { diff --git a/Specs/DataSources/PointVisualizerSpec.js b/Specs/DataSources/PointVisualizerSpec.js index 593d1dc0c137..5dd75114017c 100644 --- a/Specs/DataSources/PointVisualizerSpec.js +++ b/Specs/DataSources/PointVisualizerSpec.js @@ -5,6 +5,7 @@ defineSuite([ 'Core/Cartesian3', 'Core/Color', 'Core/defineProperties', + 'Core/DistanceDisplayCondition', 'Core/Ellipsoid', 'Core/Event', 'Core/JulianDate', @@ -23,6 +24,7 @@ defineSuite([ Cartesian3, Color, defineProperties, + DistanceDisplayCondition, Ellipsoid, Event, JulianDate, @@ -149,7 +151,8 @@ defineSuite([ outlineColor : new Color(0.5, 0.6, 0.7, 0.8), outlineWidth : 9, pixelSize : 10, - scaleByDistance : new NearFarScalar(11, 12, 13, 14) + scaleByDistance : new NearFarScalar(11, 12, 13, 14), + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) } }); var point = entity.point; @@ -167,12 +170,14 @@ defineSuite([ expect(pointPrimitive.color).toEqual(point.color.getValue(time)); expect(pointPrimitive.outlineColor).toEqual(point.outlineColor.getValue(time)); expect(pointPrimitive.outlineWidth).toEqual(point.outlineWidth.getValue(time)); + expect(pointPrimitive.distanceDisplayCondition).toEqual(point.distanceDisplayCondition.getValue(time)); point.color = new Color(0.15, 0.16, 0.17, 0.18); point.outlineColor = new Color(0.19, 0.20, 0.21, 0.22); point.pixelSize = 23; point.outlineWidth = 24; point.scaleByDistance = new NearFarScalar(25, 26, 27, 28); + point.distanceDisplayCondition = new DistanceDisplayCondition(1000.0, 1000000.0); visualizer.update(time); @@ -182,6 +187,7 @@ defineSuite([ expect(pointPrimitive.color).toEqual(point.color.getValue(time)); expect(pointPrimitive.outlineColor).toEqual(point.outlineColor.getValue(time)); expect(pointPrimitive.outlineWidth).toEqual(point.outlineWidth.getValue(time)); + expect(pointPrimitive.distanceDisplayCondition).toEqual(point.distanceDisplayCondition.getValue(time)); point.show = false; visualizer.update(time); @@ -203,6 +209,7 @@ defineSuite([ outlineWidth : 9, pixelSize : 10, scaleByDistance : new NearFarScalar(11, 12, 13, 14), + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0), heightReference : HeightReference.CLAMP_TO_GROUND } }); @@ -218,6 +225,7 @@ defineSuite([ expect(billboard.show).toEqual(point.show.getValue(time)); expect(billboard.position).toEqual(entity.position.getValue(time)); expect(billboard.scaleByDistance).toEqual(point.scaleByDistance.getValue(time)); + expect(billboard.distanceDisplayCondition).toEqual(point.distanceDisplayCondition.getValue(time)); //expect(billboard.color).toEqual(point.color.getValue(time)); //expect(billboard.outlineColor).toEqual(point.outlineColor.getValue(time)); //expect(billboard.outlineWidth).toEqual(point.outlineWidth.getValue(time)); @@ -227,12 +235,14 @@ defineSuite([ point.pixelSize = 23; point.outlineWidth = 24; point.scaleByDistance = new NearFarScalar(25, 26, 27, 28); + point.distanceDisplayCondition = new DistanceDisplayCondition(1000.0, 1000000.0); visualizer.update(time); expect(billboard.show).toEqual(point.show.getValue(time)); expect(billboard.position).toEqual(entity.position.getValue(time)); expect(billboard.scaleByDistance).toEqual(point.scaleByDistance.getValue(time)); + expect(billboard.distanceDisplayCondition).toEqual(point.distanceDisplayCondition.getValue(time)); //expect(billboard.color).toEqual(point.color.getValue(time)); //expect(billboard.outlineColor).toEqual(point.outlineColor.getValue(time)); //expect(billboard.outlineWidth).toEqual(point.outlineWidth.getValue(time)); From d71c3b032690f18d47990359b5a0851de7ea87c7 Mon Sep 17 00:00:00 2001 From: Dave Whipps Date: Tue, 13 Sep 2016 09:03:11 -0400 Subject: [PATCH 079/191] Added important documentation. This was missing so it was impossible to know that one could set the height reference of a Point, without digging into the source. --- Source/DataSources/PointGraphics.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/DataSources/PointGraphics.js b/Source/DataSources/PointGraphics.js index 55ebc5fc676e..2371939c611f 100644 --- a/Source/DataSources/PointGraphics.js +++ b/Source/DataSources/PointGraphics.js @@ -29,6 +29,7 @@ define([ * @param {Property} [options.show=true] A boolean Property specifying the visibility of the point. * @param {Property} [options.scaleByDistance] A {@link NearFarScalar} Property used to scale the point based on distance. * @param {Property} [options.translucencyByDistance] A {@link NearFarScalar} Property used to set translucency based on distance from the camera. + * @param {Property} [options.heightReference=HeightReference.NONE] A Property specifying what the height is relative to. */ function PointGraphics(options) { this._color = undefined; From 9ed2ab0c5b7bd6acc9c1f67ed861edeaeed0b01f Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 13 Sep 2016 16:00:40 -0400 Subject: [PATCH 080/191] Modify GroundPrimitive shader to support distance display conditions and add tests. --- Source/Scene/GroundPrimitive.js | 4 +- Source/Scene/Primitive.js | 2 +- Specs/Scene/GroundPrimitiveSpec.js | 70 ++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index b60a7d8213df..a96af37afa1a 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -739,9 +739,9 @@ define([ var context = frameState.context; - var vs = ShadowVolumeVS; + var vs = Primitive._appendShowToShader(primitive._primitive, ShadowVolumeVS); + vs = Primitive._appendDistanceDisplayConditionToShader(primitive._primitive, vs); vs = Primitive._modifyShaderPosition(primitive, vs, frameState.scene3DOnly); - vs = Primitive._appendShowToShader(primitive._primitive, vs); var fs = ShadowVolumeFS; var attributeLocations = primitive._primitive._attributeLocations; diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index d5943931c751..173862775fac 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -575,7 +575,7 @@ define([ var attributes = instance.attributes; var newAttributes = {}; for (var property in attributes) { - if (attributes.hasOwnProperty(property)) { + if (attributes.hasOwnProperty(property) && defined(attributes[property])) { newAttributes[property] = cloneGeometryInstanceAttribute(attributes[property]); } } diff --git a/Specs/Scene/GroundPrimitiveSpec.js b/Specs/Scene/GroundPrimitiveSpec.js index 470bbfc27578..3626ad3acd62 100644 --- a/Specs/Scene/GroundPrimitiveSpec.js +++ b/Specs/Scene/GroundPrimitiveSpec.js @@ -6,11 +6,14 @@ defineSuite([ 'Core/ColorGeometryInstanceAttribute', 'Core/ComponentDatatype', 'Core/destroyObject', + 'Core/DistanceDisplayConditionGeometryInstanceAttribute', 'Core/Ellipsoid', 'Core/Geometry', 'Core/GeometryAttribute', 'Core/GeometryInstance', 'Core/GeometryInstanceAttribute', + 'Core/HeadingPitchRange', + 'Core/Math', 'Core/PolygonGeometry', 'Core/PrimitiveType', 'Core/Rectangle', @@ -34,11 +37,14 @@ defineSuite([ ColorGeometryInstanceAttribute, ComponentDatatype, destroyObject, + DistanceDisplayConditionGeometryInstanceAttribute, Ellipsoid, Geometry, GeometryAttribute, GeometryInstance, GeometryInstanceAttribute, + HeadingPitchRange, + CesiumMath, PolygonGeometry, PrimitiveType, Rectangle, @@ -507,6 +513,70 @@ defineSuite([ verifyGroundPrimitiveRender(primitive, depthColor); }); + it('renders with distance display condition per instance attribute', function() { + var near = 10000.0; + var far = 1000000.0; + var rect = Rectangle.fromDegrees(-1.0, -1.0, 1.0, 1.0); + var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(0.0, 0.0, 1.0, 1.0)); + depthColor = depthColorAttribute.value; + var primitive = new Primitive({ + geometryInstances : new GeometryInstance({ + geometry : new RectangleGeometry({ + ellipsoid : ellipsoid, + rectangle : rectangle + }), + id : 'depth rectangle', + attributes : { + color : depthColorAttribute + } + }), + appearance : new PerInstanceColorAppearance({ + translucent : false + }), + asynchronous : false + }); + + // wrap rectangle primitive so it gets executed during the globe pass to lay down depth + depthPrimitive = new MockGlobePrimitive(primitive); + + var rectColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(1.0, 1.0, 0.0, 1.0)); + var rectColor = rectColorAttribute.value; + var rectInstance = new GeometryInstance({ + geometry : new RectangleGeometry({ + ellipsoid : ellipsoid, + rectangle : rectangle + }), + id : 'rect', + attributes : { + color : rectColorAttribute, + distanceDisplayCondition : new DistanceDisplayConditionGeometryInstanceAttribute(near, far) + } + }); + + primitive = new GroundPrimitive({ + geometryInstances : rectInstance, + asynchronous : false + }); + + scene.groundPrimitives.add(depthPrimitive); + scene.groundPrimitives.add(primitive); + scene.camera.setView({ destination : rect }); + scene.renderForSpecs(); + + var boundingSphere = primitive.getGeometryInstanceAttributes('rect').boundingSphere; + var center = boundingSphere.center; + var radius = boundingSphere.radius; + + scene.camera.lookAt(center, new HeadingPitchRange(0.0, -CesiumMath.PI_OVER_TWO, radius)); + expect(scene.renderForSpecs()).toEqual([0, 0, 255, 255]); + + scene.camera.lookAt(center, new HeadingPitchRange(0.0, -CesiumMath.PI_OVER_TWO, radius + near + 1.0)); + expect(scene.renderForSpecs()).not.toEqual([0, 0, 255, 255]); + + scene.camera.lookAt(center, new HeadingPitchRange(0.0, -CesiumMath.PI_OVER_TWO, radius + far + 1.0)); + expect(scene.renderForSpecs()).toEqual([0, 0, 255, 255]); + }); + it('get bounding sphere from per instance attribute', function() { if (!GroundPrimitive.isSupported(scene)) { return; From 5a8068ce8a66f9220da6f0f2c8686daf87720071 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 14 Sep 2016 16:07:14 -0400 Subject: [PATCH 081/191] Add distance display condition support to all entity geometries but polylines and paths. --- Source/Core/DistanceDisplayCondition.js | 7 ++ Source/DataSources/BoxGeometryUpdater.js | 36 ++++++++- Source/DataSources/BoxGraphics.js | 8 +- Source/DataSources/CorridorGeometryUpdater.js | 35 +++++++-- Source/DataSources/CorridorGraphics.js | 8 +- Source/DataSources/CylinderGeometryUpdater.js | 34 +++++++- Source/DataSources/CylinderGraphics.js | 8 +- Source/DataSources/EllipseGeometryUpdater.js | 35 ++++++++- Source/DataSources/EllipseGraphics.js | 8 +- .../DataSources/EllipsoidGeometryUpdater.js | 32 +++++++- Source/DataSources/EllipsoidGraphics.js | 9 ++- Source/DataSources/ModelGraphics.js | 8 +- Source/DataSources/ModelVisualizer.js | 1 + Source/DataSources/PolygonGeometryUpdater.js | 24 +++++- Source/DataSources/PolygonGraphics.js | 8 +- .../PolylineVolumeGeometryUpdater.js | 24 +++++- Source/DataSources/PolylineVolumeGraphics.js | 8 +- .../DataSources/RectangleGeometryUpdater.js | 24 +++++- Source/DataSources/RectangleGraphics.js | 8 +- Source/DataSources/WallGeometryUpdater.js | 24 +++++- Source/DataSources/WallGraphics.js | 8 +- Specs/Core/DistanceDisplayConditionSpec.js | 10 ++- Specs/DataSources/BoxGeometryUpdaterSpec.js | 25 ++++++ Specs/DataSources/BoxGraphicsSpec.js | 15 +++- .../CorridorGeometryUpdaterSpec.js | 30 +++++++- Specs/DataSources/CorridorGraphicsSpec.js | 15 +++- .../CylinderGeometryUpdaterSpec.js | 31 +++++++- Specs/DataSources/CylinderGraphicsSpec.js | 15 +++- .../DataSources/EllipseGeometryUpdaterSpec.js | 33 ++++++++ Specs/DataSources/EllipseGraphicsSpec.js | 15 +++- .../EllipsoidGeometryUpdaterSpec.js | 30 ++++++++ Specs/DataSources/EllipsoidGraphicsSpec.js | 15 +++- Specs/DataSources/ModelGraphicsSpec.js | 12 +++ Specs/DataSources/ModelVisualizerSpec.js | 4 + .../DataSources/PolygonGeometryUpdaterSpec.js | 31 ++++++++ Specs/DataSources/PolygonGraphicsSpec.js | 15 +++- .../PolylineVolumeGeometryUpdaterSpec.js | 27 +++++++ .../DataSources/PolylineVolumeGraphicsSpec.js | 15 +++- .../RectangleGeometryUpdaterSpec.js | 31 ++++++++ Specs/DataSources/RectangleGraphicsSpec.js | 77 +++++++++++-------- Specs/DataSources/WallGeometryUpdaterSpec.js | 27 +++++++ Specs/DataSources/WallGraphicsSpec.js | 15 +++- 42 files changed, 763 insertions(+), 82 deletions(-) diff --git a/Source/Core/DistanceDisplayCondition.js b/Source/Core/DistanceDisplayCondition.js index 8554235272c6..cf1ecba74faa 100644 --- a/Source/Core/DistanceDisplayCondition.js +++ b/Source/Core/DistanceDisplayCondition.js @@ -102,5 +102,12 @@ define([ return result; }; + /** + * DOC_TBA + */ + DistanceDisplayCondition.prototype.equals = function(other) { + return DistanceDisplayCondition.equals(this, other); + }; + return DistanceDisplayCondition; }); \ No newline at end of file diff --git a/Source/DataSources/BoxGeometryUpdater.js b/Source/DataSources/BoxGeometryUpdater.js index 63d3a9e8e5a1..96566533a383 100644 --- a/Source/DataSources/BoxGeometryUpdater.js +++ b/Source/DataSources/BoxGeometryUpdater.js @@ -9,6 +9,8 @@ define([ '../Core/defineProperties', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', + '../Core/DistanceDisplayConditionGeometryInstanceAttribute', '../Core/Event', '../Core/GeometryInstance', '../Core/Iso8601', @@ -32,6 +34,8 @@ define([ defineProperties, destroyObject, DeveloperError, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, Event, GeometryInstance, Iso8601, @@ -53,6 +57,7 @@ define([ var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); + var defaultDistanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var scratchColor = new Color(); function GeometryOptions(entity) { @@ -94,6 +99,7 @@ define([ this._outlineColorProperty = undefined; this._outlineWidth = 1.0; this._shadowsProperty = undefined; + this._distanceDisplayConditionProperty = undefined; this._options = new GeometryOptions(entity); this._onEntityPropertyChanged(entity, 'box', entity.box, undefined); } @@ -234,6 +240,13 @@ define([ return this._shadowsProperty; } }, + + distanceDisplayConditionProperty : { + get : function() { + return this._distanceDisplayConditionProperty; + } + }, + /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -322,6 +335,8 @@ define([ var color; var show = new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); + var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition); if (this._materialProperty instanceof ColorMaterialProperty) { var currentColor = Color.WHITE; if (defined(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) { @@ -330,11 +345,13 @@ define([ color = ColorGeometryInstanceAttribute.fromColor(currentColor); attributes = { show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute, color : color }; } else { attributes = { - show : show + show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute }; } @@ -368,6 +385,7 @@ define([ var entity = this._entity; var isAvailable = entity.isAvailable(time); var outlineColor = Property.getValueOrDefault(this._outlineColorProperty, time, Color.BLACK); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); return new GeometryInstance({ id : entity, @@ -375,7 +393,8 @@ define([ modelMatrix : entity._getModelMatrix(Iso8601.MINIMUM_VALUE), attributes : { show : new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)), - color : ColorGeometryInstanceAttribute.fromColor(outlineColor) + color : ColorGeometryInstanceAttribute.fromColor(outlineColor), + distanceDisplayCondition : DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition) } }); }; @@ -454,6 +473,7 @@ define([ this._showOutlineProperty = defaultValue(box.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(box.outlineColor, defaultOutlineColor) : undefined; this._shadowsProperty = defaultValue(box.shadows, defaultShadows); + this._distanceDisplayConditionProperty = defaultValue(box.distanceDisplayCondition, defaultDistanceDisplayCondition); var outlineWidth = box.outlineWidth; @@ -541,6 +561,10 @@ define([ var shadows = this._geometryUpdater.shadowsProperty.getValue(time); + var distanceDisplayConditionProperty = this._geometryUpdater.distanceDisplayConditionProperty; + var distanceDisplayCondition = distanceDisplayConditionProperty.getValue(time); + var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition); + if (Property.getValueOrDefault(box.fill, time, true)) { var material = MaterialProperty.getValue(time, geometryUpdater.fillMaterialProperty, this._material); this._material = material; @@ -556,7 +580,10 @@ define([ geometryInstances : new GeometryInstance({ id : entity, geometry : BoxGeometry.fromDimensions(options), - modelMatrix : modelMatrix + modelMatrix : modelMatrix, + attributes : { + distanceDisplayCondition : distanceDisplayConditionAttribute + } }), appearance : appearance, asynchronous : false, @@ -577,7 +604,8 @@ define([ geometry : BoxOutlineGeometry.fromDimensions(options), modelMatrix : modelMatrix, attributes : { - color : ColorGeometryInstanceAttribute.fromColor(outlineColor) + color : ColorGeometryInstanceAttribute.fromColor(outlineColor), + distanceDisplayCondition : distanceDisplayConditionAttribute } }), appearance : new PerInstanceColorAppearance({ diff --git a/Source/DataSources/BoxGraphics.js b/Source/DataSources/BoxGraphics.js index a9e4be26f6eb..703e07132b81 100644 --- a/Source/DataSources/BoxGraphics.js +++ b/Source/DataSources/BoxGraphics.js @@ -52,6 +52,8 @@ define([ this._outlineWidthSubscription = undefined; this._shadows = undefined; this._shadowsSubscription = undefined; + this._distanceDisplayCondition = undefined; + this._distanceDisplayConditionSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -132,7 +134,9 @@ define([ * @type {Property} * @default ShadowMode.DISABLED */ - shadows : createPropertyDescriptor('shadows') + shadows : createPropertyDescriptor('shadows'), + + distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition') }); /** @@ -153,6 +157,7 @@ define([ result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.shadows = this.shadows; + result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; @@ -177,6 +182,7 @@ define([ this.outlineColor = defaultValue(this.outlineColor, source.outlineColor); this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth); this.shadows = defaultValue(this.shadows, source.shadows); + this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); }; return BoxGraphics; diff --git a/Source/DataSources/CorridorGeometryUpdater.js b/Source/DataSources/CorridorGeometryUpdater.js index 29f9374f73e7..68eb4805ba07 100644 --- a/Source/DataSources/CorridorGeometryUpdater.js +++ b/Source/DataSources/CorridorGeometryUpdater.js @@ -9,6 +9,8 @@ define([ '../Core/defineProperties', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', + '../Core/DistanceDisplayConditionGeometryInstanceAttribute', '../Core/Event', '../Core/GeometryInstance', '../Core/Iso8601', @@ -34,6 +36,8 @@ define([ defineProperties, destroyObject, DeveloperError, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, Event, GeometryInstance, Iso8601, @@ -57,6 +61,7 @@ define([ var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); + var defaultDistanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var scratchColor = new Color(); function GeometryOptions(entity) { @@ -104,6 +109,7 @@ define([ this._outlineColorProperty = undefined; this._outlineWidth = 1.0; this._shadowsProperty = undefined; + this._distanceDisplayConditionProperty = undefined; this._onTerrain = false; this._options = new GeometryOptions(entity); @@ -246,6 +252,13 @@ define([ return this._shadowsProperty; } }, + + distanceDisplayConditionProperty : { + get : function() { + return this._distanceDisplayCondition; + } + }, + /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -348,6 +361,7 @@ define([ var color; var show = new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)); + var distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(this._distanceDisplayCondition.getValue(time)); if (this._materialProperty instanceof ColorMaterialProperty) { var currentColor = Color.WHITE; if (defined(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) { @@ -356,11 +370,13 @@ define([ color = ColorGeometryInstanceAttribute.fromColor(currentColor); attributes = { show : show, + distanceDisplayCondition : distanceDisplayCondition, color : color }; } else { attributes = { - show : show + show : show, + distanceDisplayCondition : distanceDisplayCondition }; } @@ -399,7 +415,8 @@ define([ geometry : new CorridorOutlineGeometry(this._options), attributes : { show : new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)), - color : ColorGeometryInstanceAttribute.fromColor(outlineColor) + color : ColorGeometryInstanceAttribute.fromColor(outlineColor), + distanceDisplayCondition : DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(this._distanceDisplayCondition.getValue(time)) } }); }; @@ -478,6 +495,7 @@ define([ this._showOutlineProperty = defaultValue(corridor.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(corridor.outlineColor, defaultOutlineColor) : undefined; this._shadowsProperty = defaultValue(corridor.shadows, defaultShadows); + this._distanceDisplayCondition = defaultValue(corridor.distanceDisplayCondition, defaultDistanceDisplayCondition); var height = corridor.height; var extrudedHeight = corridor.extrudedHeight; @@ -599,6 +617,8 @@ define([ options.cornerType = Property.getValueOrUndefined(corridor.cornerType, time); var shadows = this._geometryUpdater.shadowsProperty.getValue(time); + var distanceDisplayCondition = this._geometryUpdater.distanceDisplayConditionProperty.getValue(time); + var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition); if (!defined(corridor.fill) || corridor.fill.getValue(time)) { var fillMaterialProperty = geometryUpdater.fillMaterialProperty; @@ -616,7 +636,8 @@ define([ id : entity, geometry : new CorridorGeometry(options), attributes: { - color: ColorGeometryInstanceAttribute.fromColor(currentColor) + color: ColorGeometryInstanceAttribute.fromColor(currentColor), + distanceDisplayCondition : distanceDisplayConditionAttribute } }), asynchronous : false, @@ -633,7 +654,10 @@ define([ this._primitive = primitives.add(new Primitive({ geometryInstances : new GeometryInstance({ id : entity, - geometry : new CorridorGeometry(options) + geometry : new CorridorGeometry(options), + attributes : { + distanceDisplayCondition : distanceDisplayConditionAttribute + } }), appearance : appearance, asynchronous : false, @@ -654,7 +678,8 @@ define([ id : entity, geometry : new CorridorOutlineGeometry(options), attributes : { - color : ColorGeometryInstanceAttribute.fromColor(outlineColor) + color : ColorGeometryInstanceAttribute.fromColor(outlineColor), + distanceDisplayCondition : distanceDisplayConditionAttribute } }), appearance : new PerInstanceColorAppearance({ diff --git a/Source/DataSources/CorridorGraphics.js b/Source/DataSources/CorridorGraphics.js index 98161c48e343..17a37a7398af 100644 --- a/Source/DataSources/CorridorGraphics.js +++ b/Source/DataSources/CorridorGraphics.js @@ -70,6 +70,8 @@ define([ this._outlineWidthSubscription = undefined; this._shadows = undefined; this._shadowsSubscription = undefined; + this._distanceDisplayCondition = undefined; + this._distanceDisplayConditionSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -190,7 +192,9 @@ define([ * @type {Property} * @default ShadowMode.DISABLED */ - shadows : createPropertyDescriptor('shadows') + shadows : createPropertyDescriptor('shadows'), + + distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition') }); /** @@ -216,6 +220,7 @@ define([ result.outlineWidth = this.outlineWidth; result.cornerType = this.cornerType; result.shadows = this.shadows; + result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; @@ -245,6 +250,7 @@ define([ this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth); this.cornerType = defaultValue(this.cornerType, source.cornerType); this.shadows = defaultValue(this.shadows, source.shadows); + this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); }; return CorridorGraphics; diff --git a/Source/DataSources/CylinderGeometryUpdater.js b/Source/DataSources/CylinderGeometryUpdater.js index 86881bb9eec7..b4d4918055ae 100644 --- a/Source/DataSources/CylinderGeometryUpdater.js +++ b/Source/DataSources/CylinderGeometryUpdater.js @@ -10,6 +10,8 @@ define([ '../Core/defineProperties', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', + '../Core/DistanceDisplayConditionGeometryInstanceAttribute', '../Core/Event', '../Core/GeometryInstance', '../Core/Iso8601', @@ -34,6 +36,8 @@ define([ defineProperties, destroyObject, DeveloperError, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, Event, GeometryInstance, Iso8601, @@ -55,6 +59,7 @@ define([ var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); + var defaultDistanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var scratchColor = new Color(); @@ -101,6 +106,7 @@ define([ this._outlineColorProperty = undefined; this._outlineWidth = 1.0; this._shadowsProperty = undefined; + this._distanceDisplayConditionProperty = undefined; this._options = new GeometryOptions(entity); this._onEntityPropertyChanged(entity, 'cylinder', entity.cylinder, undefined); } @@ -241,6 +247,11 @@ define([ return this._shadowsProperty; } }, + distanceDisplayConditionProperty : { + get : function() { + return this._distanceDisplayConditionProperty; + } + }, /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -329,6 +340,8 @@ define([ var color; var show = new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); + var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition); if (this._materialProperty instanceof ColorMaterialProperty) { var currentColor = Color.WHITE; if (defined(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) { @@ -337,11 +350,13 @@ define([ color = ColorGeometryInstanceAttribute.fromColor(currentColor); attributes = { show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute, color : color }; } else { attributes = { - show : show + show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute }; } @@ -375,6 +390,7 @@ define([ var entity = this._entity; var isAvailable = entity.isAvailable(time); var outlineColor = Property.getValueOrDefault(this._outlineColorProperty, time, Color.BLACK); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); return new GeometryInstance({ id : entity, @@ -382,7 +398,8 @@ define([ modelMatrix : entity._getModelMatrix(Iso8601.MINIMUM_VALUE), attributes : { show : new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)), - color : ColorGeometryInstanceAttribute.fromColor(outlineColor) + color : ColorGeometryInstanceAttribute.fromColor(outlineColor), + distanceDisplayCondition : DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition) } }); }; @@ -464,6 +481,7 @@ define([ this._showOutlineProperty = defaultValue(cylinder.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(cylinder.outlineColor, defaultOutlineColor) : undefined; this._shadowsProperty = defaultValue(cylinder.shadows, defaultShadows); + this._distanceDisplayConditionProperty = defaultValue(cylinder.distanceDisplayCondition, defaultDistanceDisplayCondition); var slices = cylinder.slices; var outlineWidth = cylinder.outlineWidth; @@ -566,6 +584,10 @@ define([ options.numberOfVerticalLines = Property.getValueOrUndefined(cylinder.numberOfVerticalLines, time); var shadows = this._geometryUpdater.shadowsProperty.getValue(time); + + var distanceDisplayConditionProperty = this._geometryUpdater.distanceDisplayConditionProperty; + var distanceDisplayCondition = distanceDisplayConditionProperty.getValue(time); + var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition); if (Property.getValueOrDefault(cylinder.fill, time, true)) { var material = MaterialProperty.getValue(time, geometryUpdater.fillMaterialProperty, this._material); @@ -582,7 +604,10 @@ define([ geometryInstances : new GeometryInstance({ id : entity, geometry : new CylinderGeometry(options), - modelMatrix : modelMatrix + modelMatrix : modelMatrix, + attributes : { + distanceDisplayCondition : distanceDisplayConditionAttribute + } }), appearance : appearance, asynchronous : false, @@ -603,7 +628,8 @@ define([ geometry : new CylinderOutlineGeometry(options), modelMatrix : modelMatrix, attributes : { - color : ColorGeometryInstanceAttribute.fromColor(outlineColor) + color : ColorGeometryInstanceAttribute.fromColor(outlineColor), + distanceDisplayCondition : distanceDisplayConditionAttribute } }), appearance : new PerInstanceColorAppearance({ diff --git a/Source/DataSources/CylinderGraphics.js b/Source/DataSources/CylinderGraphics.js index d2f4196519d9..c7f80b893020 100644 --- a/Source/DataSources/CylinderGraphics.js +++ b/Source/DataSources/CylinderGraphics.js @@ -63,6 +63,8 @@ define([ this._outlineWidthSubscription = undefined; this._shadows = undefined; this._shadowsSubscription = undefined; + this._distanceDisplayCondition = undefined; + this._distanceDisplayConditionSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -174,7 +176,9 @@ define([ * @type {Property} * @default ShadowMode.DISABLED */ - shadows : createPropertyDescriptor('shadows') + shadows : createPropertyDescriptor('shadows'), + + distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition') }); /** @@ -199,6 +203,7 @@ define([ result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.shadows = this.shadows; + result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; @@ -227,6 +232,7 @@ define([ this.outlineColor = defaultValue(this.outlineColor, source.outlineColor); this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth); this.shadows = defaultValue(this.shadows, source.shadows); + this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); }; return CylinderGraphics; diff --git a/Source/DataSources/EllipseGeometryUpdater.js b/Source/DataSources/EllipseGeometryUpdater.js index a9e13c630672..c478a9c99ee1 100644 --- a/Source/DataSources/EllipseGeometryUpdater.js +++ b/Source/DataSources/EllipseGeometryUpdater.js @@ -7,6 +7,8 @@ define([ '../Core/defineProperties', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', + '../Core/DistanceDisplayConditionGeometryInstanceAttribute', '../Core/EllipseGeometry', '../Core/EllipseOutlineGeometry', '../Core/Event', @@ -32,6 +34,8 @@ define([ defineProperties, destroyObject, DeveloperError, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, EllipseGeometry, EllipseOutlineGeometry, Event, @@ -57,6 +61,7 @@ define([ var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); + var defaultDistanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var scratchColor = new Color(); function GeometryOptions(entity) { @@ -107,6 +112,7 @@ define([ this._outlineColorProperty = undefined; this._outlineWidth = 1.0; this._shadowsProperty = undefined; + this._distanceDisplayConditionProperty = undefined; this._onTerrain = false; this._options = new GeometryOptions(entity); @@ -249,6 +255,11 @@ define([ return this._shadowsProperty; } }, + distanceDisplayConditionProperty : { + get : function() { + return this._distanceDisplayConditionProperty; + } + }, /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -351,6 +362,8 @@ define([ var color; var show = new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); + var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition); if (this._materialProperty instanceof ColorMaterialProperty) { var currentColor = Color.WHITE; if (defined(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) { @@ -359,11 +372,13 @@ define([ color = ColorGeometryInstanceAttribute.fromColor(currentColor); attributes = { show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute, color : color }; } else { attributes = { - show : show + show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute }; } @@ -396,13 +411,15 @@ define([ var entity = this._entity; var isAvailable = entity.isAvailable(time); var outlineColor = Property.getValueOrDefault(this._outlineColorProperty, time, Color.BLACK); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); return new GeometryInstance({ id : entity, geometry : new EllipseOutlineGeometry(this._options), attributes : { show : new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)), - color : ColorGeometryInstanceAttribute.fromColor(outlineColor) + color : ColorGeometryInstanceAttribute.fromColor(outlineColor), + distanceDisplayCondition : DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition) } }); }; @@ -483,6 +500,7 @@ define([ this._showOutlineProperty = defaultValue(ellipse.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(ellipse.outlineColor, defaultOutlineColor) : undefined; this._shadowsProperty = defaultValue(ellipse.shadows, defaultShadows); + this._distanceDisplayConditionProperty = defaultValue(ellipse.distanceDisplayCondition, defaultDistanceDisplayCondition); var rotation = ellipse.rotation; var height = ellipse.height; @@ -617,6 +635,10 @@ define([ var shadows = this._geometryUpdater.shadowsProperty.getValue(time); + var distanceDisplayConditionProperty = this._geometryUpdater.distanceDisplayConditionProperty; + var distanceDisplayCondition = distanceDisplayConditionProperty.getValue(time); + var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition); + if (Property.getValueOrDefault(ellipse.fill, time, true)) { var fillMaterialProperty = geometryUpdater.fillMaterialProperty; var material = MaterialProperty.getValue(time, fillMaterialProperty, this._material); @@ -633,7 +655,8 @@ define([ id : entity, geometry : new EllipseGeometry(options), attributes: { - color: ColorGeometryInstanceAttribute.fromColor(currentColor) + color: ColorGeometryInstanceAttribute.fromColor(currentColor), + distanceDisplayCondition : distanceDisplayConditionAttribute } }), asynchronous : false, @@ -652,6 +675,9 @@ define([ id : entity, geometry : new EllipseGeometry(options) }), + attributes : { + distanceDisplayCondition : distanceDisplayConditionAttribute + }, appearance : appearance, asynchronous : false, shadows : shadows @@ -671,7 +697,8 @@ define([ id : entity, geometry : new EllipseOutlineGeometry(options), attributes : { - color : ColorGeometryInstanceAttribute.fromColor(outlineColor) + color : ColorGeometryInstanceAttribute.fromColor(outlineColor), + distanceDisplayCondition : distanceDisplayConditionAttribute } }), appearance : new PerInstanceColorAppearance({ diff --git a/Source/DataSources/EllipseGraphics.js b/Source/DataSources/EllipseGraphics.js index 39e64d17671d..693db8eb0f3e 100644 --- a/Source/DataSources/EllipseGraphics.js +++ b/Source/DataSources/EllipseGraphics.js @@ -76,6 +76,8 @@ define([ this._numberOfVerticalLinesSubscription = undefined; this._shadows = undefined; this._shadowsSubscription = undefined; + this._distanceDisplayCondition = undefined; + this._distanceDisplayConditionSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -212,7 +214,9 @@ define([ * @type {Property} * @default ShadowMode.DISABLED */ - shadows : createPropertyDescriptor('shadows') + shadows : createPropertyDescriptor('shadows'), + + distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition') }); /** @@ -240,6 +244,7 @@ define([ result.outlineWidth = this.outlineWidth; result.numberOfVerticalLines = this.numberOfVerticalLines; result.shadows = this.shadows; + result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; @@ -271,6 +276,7 @@ define([ this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth); this.numberOfVerticalLines = defaultValue(this.numberOfVerticalLines, source.numberOfVerticalLines); this.shadows = defaultValue(this.shadows, source.shadows); + this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); }; return EllipseGraphics; diff --git a/Source/DataSources/EllipsoidGeometryUpdater.js b/Source/DataSources/EllipsoidGeometryUpdater.js index 04662eb305ff..445da07c885c 100644 --- a/Source/DataSources/EllipsoidGeometryUpdater.js +++ b/Source/DataSources/EllipsoidGeometryUpdater.js @@ -8,6 +8,8 @@ define([ '../Core/defineProperties', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', + '../Core/DistanceDisplayConditionGeometryInstanceAttribute', '../Core/EllipsoidGeometry', '../Core/EllipsoidOutlineGeometry', '../Core/Event', @@ -34,6 +36,8 @@ define([ defineProperties, destroyObject, DeveloperError, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, EllipsoidGeometry, EllipsoidOutlineGeometry, Event, @@ -59,6 +63,7 @@ define([ var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); + var defaultDistanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var radiiScratch = new Cartesian3(); var scratchColor = new Color(); @@ -106,6 +111,7 @@ define([ this._outlineColorProperty = undefined; this._outlineWidth = 1.0; this._shadowsProperty = undefined; + this._distanceDisplayConditionProperty = undefined; this._options = new GeometryOptions(entity); this._onEntityPropertyChanged(entity, 'ellipsoid', entity.ellipsoid, undefined); } @@ -246,6 +252,11 @@ define([ return this._shadowsProperty; } }, + distanceDisplayConditionProperty : { + get : function() { + return this._distanceDisplayConditionProperty; + } + }, /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -334,6 +345,8 @@ define([ var color; var show = new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); + var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition); if (this._materialProperty instanceof ColorMaterialProperty) { var currentColor = Color.WHITE; if (defined(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) { @@ -342,11 +355,13 @@ define([ color = ColorGeometryInstanceAttribute.fromColor(currentColor); attributes = { show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute, color : color }; } else { attributes = { - show : show + show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute }; } @@ -381,6 +396,7 @@ define([ var isAvailable = entity.isAvailable(time); var outlineColor = Property.getValueOrDefault(this._outlineColorProperty, time, Color.BLACK); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); return new GeometryInstance({ id : entity, @@ -388,7 +404,8 @@ define([ modelMatrix : entity._getModelMatrix(Iso8601.MINIMUM_VALUE), attributes : { show : new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)), - color : ColorGeometryInstanceAttribute.fromColor(outlineColor) + color : ColorGeometryInstanceAttribute.fromColor(outlineColor), + distanceDisplayCondition : DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition) } }); }; @@ -468,6 +485,7 @@ define([ this._showOutlineProperty = defaultValue(ellipsoid.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(ellipsoid.outlineColor, defaultOutlineColor) : undefined; this._shadowsProperty = defaultValue(ellipsoid.shadows, defaultShadows); + this._distanceDisplayConditionProperty = defaultValue(ellipsoid.distanceDisplayCondition, defaultDistanceDisplayCondition); this._fillEnabled = fillEnabled; this._outlineEnabled = outlineEnabled; @@ -598,6 +616,10 @@ define([ var options = this._options; var shadows = this._geometryUpdater.shadowsProperty.getValue(time); + + var distanceDisplayConditionProperty = this._geometryUpdater.distanceDisplayConditionProperty; + var distanceDisplayCondition = distanceDisplayConditionProperty.getValue(time); + var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition); //We only rebuild the primitive if something other than the radii has changed //For the radii, we use unit sphere and then deform it with a scale matrix. @@ -632,7 +654,8 @@ define([ geometry : new EllipsoidGeometry(options), modelMatrix : !in3D ? modelMatrix : undefined, attributes : { - show : new ShowGeometryInstanceAttribute(showFill) + show : new ShowGeometryInstanceAttribute(showFill), + distanceDisplayCondition : distanceDisplayConditionAttribute } }), appearance : appearance, @@ -649,7 +672,8 @@ define([ modelMatrix : !in3D ? modelMatrix : undefined, attributes : { show : new ShowGeometryInstanceAttribute(showOutline), - color : ColorGeometryInstanceAttribute.fromColor(outlineColor) + color : ColorGeometryInstanceAttribute.fromColor(outlineColor), + distanceDisplayCondition : distanceDisplayConditionAttribute } }), appearance : new PerInstanceColorAppearance({ diff --git a/Source/DataSources/EllipsoidGraphics.js b/Source/DataSources/EllipsoidGraphics.js index efa7d92247cb..849a57c3c229 100644 --- a/Source/DataSources/EllipsoidGraphics.js +++ b/Source/DataSources/EllipsoidGraphics.js @@ -60,6 +60,9 @@ define([ this._outlineWidth = undefined; this._outlineWidthSubscription = undefined; this._shadows = undefined; + this._shadowsSubscription = undefined; + this._distanceDisplayCondition = undefined; + this._distanceDisplayConditionSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -165,7 +168,9 @@ define([ * @type {Property} * @default ShadowMode.DISABLED */ - shadows : createPropertyDescriptor('shadows') + shadows : createPropertyDescriptor('shadows'), + + distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition') }); /** @@ -189,6 +194,7 @@ define([ result.slicePartitions = this.slicePartitions; result.subdivisions = this.subdivisions; result.shadows = this.shadows; + result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; @@ -217,6 +223,7 @@ define([ this.slicePartitions = defaultValue(this.slicePartitions, source.slicePartitions); this.subdivisions = defaultValue(this.subdivisions, source.subdivisions); this.shadows = defaultValue(this.shadows, source.shadows); + this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); }; return EllipsoidGraphics; diff --git a/Source/DataSources/ModelGraphics.js b/Source/DataSources/ModelGraphics.js index e0b5ceb10794..681bc1907750 100644 --- a/Source/DataSources/ModelGraphics.js +++ b/Source/DataSources/ModelGraphics.js @@ -80,6 +80,8 @@ define([ this._nodeTransformationsSubscription = undefined; this._heightReference = undefined; this._heightReferenceSubscription = undefined; + this._distanceDisplayCondition = undefined; + this._distanceDisplayConditionSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -200,7 +202,9 @@ define([ * @type {Property} * @default HeightReference.NONE */ - heightReference : createPropertyDescriptor('heightReference') + heightReference : createPropertyDescriptor('heightReference'), + + distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition') }); /** @@ -225,6 +229,7 @@ define([ result.runAnimations = this.runAnimations; result.nodeTransformations = this.nodeTransformations; result.heightReference = this._heightReference; + result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; @@ -253,6 +258,7 @@ define([ this.uri = defaultValue(this.uri, source.uri); this.runAnimations = defaultValue(this.runAnimations, source.runAnimations); this.heightReference = defaultValue(this.heightReference, source.heightReference); + this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); var sourceNodeTransformations = source.nodeTransformations; if (defined(sourceNodeTransformations)) { diff --git a/Source/DataSources/ModelVisualizer.js b/Source/DataSources/ModelVisualizer.js index fde2fedcb7f8..ff5ad8ac6b08 100644 --- a/Source/DataSources/ModelVisualizer.js +++ b/Source/DataSources/ModelVisualizer.js @@ -147,6 +147,7 @@ define([ model.modelMatrix = Matrix4.clone(modelMatrix, model.modelMatrix); model.shadows = shadows; model.heightReference = Property.getValueOrDefault(modelGraphics._heightReference, time, defaultHeightReference); + model.distanceDisplayCondition = Property.getValueOrUndefined(modelGraphics._distanceDisplayCondition, time); if (model.ready) { var runAnimations = Property.getValueOrDefault(modelGraphics._runAnimations, time, true); diff --git a/Source/DataSources/PolygonGeometryUpdater.js b/Source/DataSources/PolygonGeometryUpdater.js index 6c2aafd06577..dd061ce348a9 100644 --- a/Source/DataSources/PolygonGeometryUpdater.js +++ b/Source/DataSources/PolygonGeometryUpdater.js @@ -7,6 +7,8 @@ define([ '../Core/defineProperties', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', + '../Core/DistanceDisplayConditionGeometryInstanceAttribute', '../Core/Event', '../Core/GeometryInstance', '../Core/isArray', @@ -34,6 +36,8 @@ define([ defineProperties, destroyObject, DeveloperError, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, Event, GeometryInstance, isArray, @@ -61,6 +65,7 @@ define([ var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); + var defaultDistanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var scratchColor = new Color(); function GeometryOptions(entity) { @@ -110,6 +115,7 @@ define([ this._outlineColorProperty = undefined; this._outlineWidth = 1.0; this._shadowsProperty = undefined; + this._distanceDisplayConditionProperty = undefined; this._onTerrain = false; this._options = new GeometryOptions(entity); this._onEntityPropertyChanged(entity, 'polygon', entity.polygon, undefined); @@ -251,6 +257,13 @@ define([ return this._shadowsProperty; } }, + + distanceDisplayConditionProperty : { + get : function() { + return this._distanceDisplayConditionProperty; + } + }, + /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -353,6 +366,8 @@ define([ var color; var show = new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); + var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition); if (this._materialProperty instanceof ColorMaterialProperty) { var currentColor = Color.WHITE; if (defined(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) { @@ -361,11 +376,13 @@ define([ color = ColorGeometryInstanceAttribute.fromColor(currentColor); attributes = { show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute, color : color }; } else { attributes = { - show : show + show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute }; } @@ -398,13 +415,15 @@ define([ var entity = this._entity; var isAvailable = entity.isAvailable(time); var outlineColor = Property.getValueOrDefault(this._outlineColorProperty, time, Color.BLACK); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); return new GeometryInstance({ id : entity, geometry : new PolygonOutlineGeometry(this._options), attributes : { show : new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)), - color : ColorGeometryInstanceAttribute.fromColor(outlineColor) + color : ColorGeometryInstanceAttribute.fromColor(outlineColor), + distanceDisplayCondition : DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition) } }); }; @@ -486,6 +505,7 @@ define([ this._showOutlineProperty = defaultValue(polygon.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(polygon.outlineColor, defaultOutlineColor) : undefined; this._shadowsProperty = defaultValue(polygon.shadows, defaultShadows); + this._distanceDisplayConditionProperty = defaultValue(polygon.distanceDisplayCondition, defaultDistanceDisplayCondition); var height = polygon.height; var extrudedHeight = polygon.extrudedHeight; diff --git a/Source/DataSources/PolygonGraphics.js b/Source/DataSources/PolygonGraphics.js index cdd0b39f6bfa..36951813947c 100644 --- a/Source/DataSources/PolygonGraphics.js +++ b/Source/DataSources/PolygonGraphics.js @@ -77,6 +77,8 @@ define([ this._closeBottomSubscription = undefined; this._shadows = undefined; this._shadowsSubscription = undefined; + this._distanceDisplayCondition = undefined; + this._distanceDisplayConditionSubscription = undefined; this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); } @@ -213,7 +215,9 @@ define([ * @type {Property} * @default ShadowMode.DISABLED */ - shadows : createPropertyDescriptor('shadows') + shadows : createPropertyDescriptor('shadows'), + + distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition') }); /** @@ -241,6 +245,7 @@ define([ result.closeTop = this.closeTop; result.closeBottom = this.closeBottom; result.shadows = this.shadows; + result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; @@ -272,6 +277,7 @@ define([ this.closeTop = defaultValue(this.closeTop, source.closeTop); this.closeBottom = defaultValue(this.closeBottom, source.closeBottom); this.shadows = defaultValue(this.shadows, source.shadows); + this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); }; return PolygonGraphics; diff --git a/Source/DataSources/PolylineVolumeGeometryUpdater.js b/Source/DataSources/PolylineVolumeGeometryUpdater.js index 9252f9374c6f..d939b7da9919 100644 --- a/Source/DataSources/PolylineVolumeGeometryUpdater.js +++ b/Source/DataSources/PolylineVolumeGeometryUpdater.js @@ -7,6 +7,8 @@ define([ '../Core/defineProperties', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', + '../Core/DistanceDisplayConditionGeometryInstanceAttribute', '../Core/Event', '../Core/GeometryInstance', '../Core/Iso8601', @@ -30,6 +32,8 @@ define([ defineProperties, destroyObject, DeveloperError, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, Event, GeometryInstance, Iso8601, @@ -53,6 +57,7 @@ define([ var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); + var defaultDistanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var scratchColor = new Color(); function GeometryOptions(entity) { @@ -97,6 +102,7 @@ define([ this._outlineColorProperty = undefined; this._outlineWidth = 1.0; this._shadowsProperty = undefined; + this._distanceDisplayConditionProperty = undefined; this._options = new GeometryOptions(entity); this._onEntityPropertyChanged(entity, 'polylineVolume', entity.polylineVolume, undefined); } @@ -237,6 +243,13 @@ define([ return this._shadowsProperty; } }, + + distanceDisplayConditionProperty : { + get : function() { + return this._distanceDisplayConditionProperty; + } + }, + /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -325,6 +338,8 @@ define([ var color; var show = new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); + var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition); if (this._materialProperty instanceof ColorMaterialProperty) { var currentColor = Color.WHITE; if (defined(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) { @@ -333,11 +348,13 @@ define([ color = ColorGeometryInstanceAttribute.fromColor(currentColor); attributes = { show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute, color : color }; } else { attributes = { - show : show + show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute, }; } @@ -370,13 +387,15 @@ define([ var entity = this._entity; var isAvailable = entity.isAvailable(time); var outlineColor = Property.getValueOrDefault(this._outlineColorProperty, time, Color.BLACK); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); return new GeometryInstance({ id : entity, geometry : new PolylineVolumeOutlineGeometry(this._options), attributes : { show : new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)), - color : ColorGeometryInstanceAttribute.fromColor(outlineColor) + color : ColorGeometryInstanceAttribute.fromColor(outlineColor), + distanceDisplayCondition : DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition) } }); }; @@ -455,6 +474,7 @@ define([ this._showOutlineProperty = defaultValue(polylineVolume.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(polylineVolume.outlineColor, defaultOutlineColor) : undefined; this._shadowsProperty = defaultValue(polylineVolume.shadows, defaultShadows); + this._distanceDisplayConditionProperty = defaultValue(polylineVolume.distanceDisplayCondition, defaultDistanceDisplayCondition); var granularity = polylineVolume.granularity; var outlineWidth = polylineVolume.outlineWidth; diff --git a/Source/DataSources/PolylineVolumeGraphics.js b/Source/DataSources/PolylineVolumeGraphics.js index 824a97a9b7ea..65f1ecc8cd17 100644 --- a/Source/DataSources/PolylineVolumeGraphics.js +++ b/Source/DataSources/PolylineVolumeGraphics.js @@ -63,6 +63,8 @@ define([ this._outlineWidthSubscription = undefined; this._shadows = undefined; this._shadowsSubscription = undefined; + this._distanceDisplayCondition = undefined; + this._distanceDisplayConditionSubsription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -167,7 +169,9 @@ define([ * @type {Property} * @default ShadowMode.DISABLED */ - shadows : createPropertyDescriptor('shadows') + shadows : createPropertyDescriptor('shadows'), + + distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition') }); /** @@ -191,6 +195,7 @@ define([ result.outlineWidth = this.outlineWidth; result.cornerType = this.cornerType; result.shadows = this.shadows; + result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; @@ -218,6 +223,7 @@ define([ this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth); this.cornerType = defaultValue(this.cornerType, source.cornerType); this.shadows = defaultValue(this.shadows, source.shadows); + this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); }; return PolylineVolumeGraphics; diff --git a/Source/DataSources/RectangleGeometryUpdater.js b/Source/DataSources/RectangleGeometryUpdater.js index 27a25798c18c..e372c94361db 100644 --- a/Source/DataSources/RectangleGeometryUpdater.js +++ b/Source/DataSources/RectangleGeometryUpdater.js @@ -7,6 +7,8 @@ define([ '../Core/defineProperties', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', + '../Core/DistanceDisplayConditionGeometryInstanceAttribute', '../Core/Event', '../Core/GeometryInstance', '../Core/Iso8601', @@ -32,6 +34,8 @@ define([ defineProperties, destroyObject, DeveloperError, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, Event, GeometryInstance, Iso8601, @@ -57,6 +61,7 @@ define([ var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); + var defaultDistanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var scratchColor = new Color(); function GeometryOptions(entity) { @@ -106,6 +111,7 @@ define([ this._outlineColorProperty = undefined; this._outlineWidth = 1.0; this._shadowsProperty = undefined; + this._distanceDisplayConditionProperty = undefined; this._onTerrain = false; this._options = new GeometryOptions(entity); @@ -248,6 +254,13 @@ define([ return this._shadowsProperty; } }, + + distanceDisplayConditionProperty : { + get : function() { + return this._distanceDisplayConditionProperty; + } + }, + /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -350,6 +363,8 @@ define([ var color; var show = new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); + var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition); if (this._materialProperty instanceof ColorMaterialProperty) { var currentColor = Color.WHITE; if (defined(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) { @@ -358,11 +373,13 @@ define([ color = ColorGeometryInstanceAttribute.fromColor(currentColor); attributes = { show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute, color : color }; } else { attributes = { - show : show + show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute }; } @@ -395,13 +412,15 @@ define([ var entity = this._entity; var isAvailable = entity.isAvailable(time); var outlineColor = Property.getValueOrDefault(this._outlineColorProperty, time, Color.BLACK); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); return new GeometryInstance({ id : entity, geometry : new RectangleOutlineGeometry(this._options), attributes : { show : new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)), - color : ColorGeometryInstanceAttribute.fromColor(outlineColor) + color : ColorGeometryInstanceAttribute.fromColor(outlineColor), + distanceDisplayCondition : DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition) } }); }; @@ -480,6 +499,7 @@ define([ this._showOutlineProperty = defaultValue(rectangle.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(rectangle.outlineColor, defaultOutlineColor) : undefined; this._shadowsProperty = defaultValue(rectangle.shadows, defaultShadows); + this._distanceDisplayConditionProperty = defaultValue(rectangle.distanceDisplayCondition, defaultDistanceDisplayCondition); var height = rectangle.height; var extrudedHeight = rectangle.extrudedHeight; diff --git a/Source/DataSources/RectangleGraphics.js b/Source/DataSources/RectangleGraphics.js index f0e22a2029e4..b0d38cbc52a0 100644 --- a/Source/DataSources/RectangleGraphics.js +++ b/Source/DataSources/RectangleGraphics.js @@ -76,6 +76,8 @@ define([ this._outlineWidthSubscription = undefined; this._shadows = undefined; this._shadowsSubscription = undefined; + this._distanceDisplayCondition = undefined; + this._distancedisplayConditionSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -213,7 +215,9 @@ define([ * @type {Property} * @default ShadowMode.DISABLED */ - shadows : createPropertyDescriptor('shadows') + shadows : createPropertyDescriptor('shadows'), + + distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition') }); /** @@ -241,6 +245,7 @@ define([ result.closeTop = this.closeTop; result.closeBottom = this.closeBottom; result.shadows = this.shadows; + result.distanceDisplayCondition = this.distanceDisplayCondition return result; }; @@ -272,6 +277,7 @@ define([ this.closeTop = defaultValue(this.closeTop, source.closeTop); this.closeBottom = defaultValue(this.closeBottom, source.closeBottom); this.shadows = defaultValue(this.shadows, source.shadows); + this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); }; return RectangleGraphics; diff --git a/Source/DataSources/WallGeometryUpdater.js b/Source/DataSources/WallGeometryUpdater.js index 27cd6ed42d6b..eedeea0cb56e 100644 --- a/Source/DataSources/WallGeometryUpdater.js +++ b/Source/DataSources/WallGeometryUpdater.js @@ -7,6 +7,8 @@ define([ '../Core/defineProperties', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', + '../Core/DistanceDisplayConditionGeometryInstanceAttribute', '../Core/Event', '../Core/GeometryInstance', '../Core/Iso8601', @@ -30,6 +32,8 @@ define([ defineProperties, destroyObject, DeveloperError, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, Event, GeometryInstance, Iso8601, @@ -53,6 +57,7 @@ define([ var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); + var defaultDistanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var scratchColor = new Color(); function GeometryOptions(entity) { @@ -97,6 +102,7 @@ define([ this._outlineColorProperty = undefined; this._outlineWidth = 1.0; this._shadowsProperty = undefined; + this._distanceDisplayConditionProperty = undefined; this._options = new GeometryOptions(entity); this._onEntityPropertyChanged(entity, 'wall', entity.wall, undefined); } @@ -237,6 +243,13 @@ define([ return this._shadowsProperty; } }, + + distanceDisplayConditionProperty : { + get : function() { + return this._distanceDisplayConditionProperty; + } + }, + /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -327,6 +340,8 @@ define([ var color; var show = new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); + var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition); if (this._materialProperty instanceof ColorMaterialProperty) { var currentColor = Color.WHITE; if (defined(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) { @@ -335,11 +350,13 @@ define([ color = ColorGeometryInstanceAttribute.fromColor(currentColor); attributes = { show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute, color : color }; } else { attributes = { - show : show + show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute, }; } @@ -372,13 +389,15 @@ define([ var entity = this._entity; var isAvailable = entity.isAvailable(time); var outlineColor = Property.getValueOrDefault(this._outlineColorProperty, time, Color.BLACK); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); return new GeometryInstance({ id : entity, geometry : new WallOutlineGeometry(this._options), attributes : { show : new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)), - color : ColorGeometryInstanceAttribute.fromColor(outlineColor) + color : ColorGeometryInstanceAttribute.fromColor(outlineColor), + distanceDisplayCondition : DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition) } }); }; @@ -457,6 +476,7 @@ define([ this._showOutlineProperty = defaultValue(wall.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(wall.outlineColor, defaultOutlineColor) : undefined; this._shadowsProperty = defaultValue(wall.shadows, defaultShadows); + this._distanceDisplayConditionProperty = defaultValue(wall.distanceDisplayCondition, defaultDistanceDisplayCondition); var minimumHeights = wall.minimumHeights; var maximumHeights = wall.maximumHeights; diff --git a/Source/DataSources/WallGraphics.js b/Source/DataSources/WallGraphics.js index f0a8e25f89b3..15ed7c37e353 100644 --- a/Source/DataSources/WallGraphics.js +++ b/Source/DataSources/WallGraphics.js @@ -63,6 +63,8 @@ define([ this._outlineWidthSubscription = undefined; this._shadows = undefined; this._shadowsSubscription = undefined; + this._distanceDisplayCondition = undefined; + this._distanceDisplayConditionSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -168,7 +170,9 @@ define([ * @type {Property} * @default ShadowMode.DISABLED */ - shadows : createPropertyDescriptor('shadows') + shadows : createPropertyDescriptor('shadows'), + + distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition') }); /** @@ -192,6 +196,7 @@ define([ result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.shadows = this.shadows; + result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; @@ -219,6 +224,7 @@ define([ this.outlineColor = defaultValue(this.outlineColor, source.outlineColor); this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth); this.shadows = defaultValue(this.shadows, source.shadows); + this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); }; return WallGraphics; diff --git a/Specs/Core/DistanceDisplayConditionSpec.js b/Specs/Core/DistanceDisplayConditionSpec.js index a268b13645db..81ef29f26d81 100644 --- a/Specs/Core/DistanceDisplayConditionSpec.js +++ b/Specs/Core/DistanceDisplayConditionSpec.js @@ -55,7 +55,7 @@ defineSuite([ expect(dc.isVisible(mockPrimitive, mockFrameState)).toEqual(false); }); - it('determines equality', function() { + it('determines equality with static function', function() { var dc = new DistanceDisplayCondition(10.0, 100.0); expect(DistanceDisplayCondition.equals(dc, new DistanceDisplayCondition(10.0, 100.0))).toEqual(true); expect(DistanceDisplayCondition.equals(dc, new DistanceDisplayCondition(11.0, 100.0))).toEqual(false); @@ -63,6 +63,14 @@ defineSuite([ expect(DistanceDisplayCondition.equals(dc, undefined)).toEqual(false); }); + it('determines equality with prototype function', function() { + var dc = new DistanceDisplayCondition(10.0, 100.0); + expect(dc.equals(new DistanceDisplayCondition(10.0, 100.0))).toEqual(true); + expect(dc.equals(new DistanceDisplayCondition(11.0, 100.0))).toEqual(false); + expect(dc.equals(new DistanceDisplayCondition(10.0, 101.0))).toEqual(false); + expect(dc.equals(undefined)).toEqual(false); + }); + it('clones', function() { var dc = new DistanceDisplayCondition(10.0, 100.0); var result = DistanceDisplayCondition.clone(dc); diff --git a/Specs/DataSources/BoxGeometryUpdaterSpec.js b/Specs/DataSources/BoxGeometryUpdaterSpec.js index 288dd3f064bc..65a0a343f7ea 100644 --- a/Specs/DataSources/BoxGeometryUpdaterSpec.js +++ b/Specs/DataSources/BoxGeometryUpdaterSpec.js @@ -4,6 +4,8 @@ defineSuite([ 'Core/Cartesian3', 'Core/Color', 'Core/ColorGeometryInstanceAttribute', + 'Core/DistanceDisplayCondition', + 'Core/DistanceDisplayConditionGeometryInstanceAttribute', 'Core/JulianDate', 'Core/ShowGeometryInstanceAttribute', 'Core/TimeInterval', @@ -26,6 +28,8 @@ defineSuite([ Cartesian3, Color, ColorGeometryInstanceAttribute, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, JulianDate, ShowGeometryInstanceAttribute, TimeInterval, @@ -81,6 +85,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toBe(undefined); + expect(updater.distanceDisplayConditionProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -122,6 +127,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); + expect(updater.distanceDisplayConditionProperty).toEqual(new ConstantProperty(new DistanceDisplayCondition())); expect(updater.isDynamic).toBe(false); }); @@ -157,6 +163,7 @@ defineSuite([ box.outline = new ConstantProperty(options.outline); box.outlineColor = new ConstantProperty(options.outlineColor); box.dimensions = new ConstantProperty(options.dimensions); + box.distanceDisplayCondition = options.distanceDisplayCondition; var updater = new BoxGeometryUpdater(entity, scene); @@ -175,6 +182,9 @@ defineSuite([ expect(attributes.color).toBeUndefined(); } expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } if (options.outline) { @@ -185,6 +195,9 @@ defineSuite([ attributes = instance.attributes; expect(attributes.color.value).toEqual(ColorGeometryInstanceAttribute.toValue(options.outlineColor)); expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } } @@ -210,6 +223,18 @@ defineSuite([ }); }); + it('Creates expected distance display condition geometry', function() { + validateGeometryInstance({ + show : true, + material : new ColorMaterialProperty(Color.RED), + fill : true, + outline : true, + outlineColor : Color.BLUE, + dimensions : new Cartesian3(1, 2, 3), + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) + }); + }); + it('Correctly exposes outlineWidth', function() { var entity = createBasicBox(); entity.box.outlineWidth = new ConstantProperty(8); diff --git a/Specs/DataSources/BoxGraphicsSpec.js b/Specs/DataSources/BoxGraphicsSpec.js index 70c4ec7d55d1..5ef15e8b12a0 100644 --- a/Specs/DataSources/BoxGraphicsSpec.js +++ b/Specs/DataSources/BoxGraphicsSpec.js @@ -3,6 +3,7 @@ defineSuite([ 'DataSources/BoxGraphics', 'Core/Cartesian3', 'Core/Color', + 'Core/DistanceDisplayCondition', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', 'Scene/ShadowMode', @@ -12,6 +13,7 @@ defineSuite([ BoxGraphics, Cartesian3, Color, + DistanceDisplayCondition, ColorMaterialProperty, ConstantProperty, ShadowMode, @@ -28,7 +30,8 @@ defineSuite([ outlineColor : Color.RED, outlineWidth : 1, dimensions : new Cartesian3(2, 3, 4), - shadows : ShadowMode.DISABLED + shadows : ShadowMode.DISABLED, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) }; var box = new BoxGraphics(options); @@ -40,6 +43,7 @@ defineSuite([ expect(box.outlineWidth).toBeInstanceOf(ConstantProperty); expect(box.dimensions).toBeInstanceOf(ConstantProperty); expect(box.shadows).toBeInstanceOf(ConstantProperty); + expect(box.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(box.material.color.getValue()).toEqual(options.material); expect(box.show.getValue()).toEqual(options.show); @@ -49,6 +53,7 @@ defineSuite([ expect(box.outlineWidth.getValue()).toEqual(options.outlineWidth); expect(box.dimensions.getValue()).toEqual(options.dimensions); expect(box.shadows.getValue()).toEqual(options.shadows); + expect(box.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); }); it('merge assigns unassigned properties', function() { @@ -61,6 +66,7 @@ defineSuite([ source.outlineWidth = new ConstantProperty(); source.dimensions = new ConstantProperty(); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var target = new BoxGraphics(); target.merge(source); @@ -73,6 +79,7 @@ defineSuite([ expect(target.outlineWidth).toBe(source.outlineWidth); expect(target.dimensions).toBe(source.dimensions); expect(target.shadows).toBe(source.shadows); + expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge does not assign assigned properties', function() { @@ -86,6 +93,7 @@ defineSuite([ var outlineWidth = new ConstantProperty(); var dimensions = new ConstantProperty(); var shadows = new ConstantProperty(); + var distanceDisplayCondition = new ConstantProperty(); var target = new BoxGraphics(); target.material = material; @@ -96,6 +104,7 @@ defineSuite([ target.outlineWidth = outlineWidth; target.dimensions = dimensions; target.shadows = shadows; + target.distanceDisplayCondition = distanceDisplayCondition; target.merge(source); @@ -107,6 +116,7 @@ defineSuite([ expect(target.outlineWidth).toBe(outlineWidth); expect(target.dimensions).toBe(dimensions); expect(target.shadows).toBe(shadows); + expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); }); it('clone works', function() { @@ -119,6 +129,7 @@ defineSuite([ source.outlineWidth = new ConstantProperty(); source.dimensions = new ConstantProperty(); source.shadows = new ConstantProperty(); + source.distanceDisplayCondition = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -129,6 +140,7 @@ defineSuite([ expect(result.outlineWidth).toBe(source.outlineWidth); expect(result.dimensions).toBe(source.dimensions); expect(result.shadows).toBe(source.shadows); + expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge throws if source undefined', function() { @@ -148,5 +160,6 @@ defineSuite([ testDefinitionChanged(property, 'outlineWidth', 2, 3); testDefinitionChanged(property, 'dimensions', new Cartesian3(0, 0, 0), new Cartesian3(1, 1, 1)); testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); + testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 100.0)); }); }); diff --git a/Specs/DataSources/CorridorGeometryUpdaterSpec.js b/Specs/DataSources/CorridorGeometryUpdaterSpec.js index 792933e5f7cc..4ca42465d2d5 100644 --- a/Specs/DataSources/CorridorGeometryUpdaterSpec.js +++ b/Specs/DataSources/CorridorGeometryUpdaterSpec.js @@ -5,6 +5,8 @@ defineSuite([ 'Core/Color', 'Core/ColorGeometryInstanceAttribute', 'Core/CornerType', + 'Core/DistanceDisplayCondition', + 'Core/DistanceDisplayConditionGeometryInstanceAttribute', 'Core/JulianDate', 'Core/ShowGeometryInstanceAttribute', 'Core/TimeInterval', @@ -31,6 +33,8 @@ defineSuite([ Color, ColorGeometryInstanceAttribute, CornerType, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, JulianDate, ShowGeometryInstanceAttribute, TimeInterval, @@ -111,6 +115,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toBe(undefined); + expect(updater.distanceDisplayConditionProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -152,6 +157,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); + expect(updater.distanceDisplayConditionProperty).toEqual(new ConstantProperty(new DistanceDisplayCondition())); expect(updater.isDynamic).toBe(false); }); @@ -246,11 +252,11 @@ defineSuite([ corridor.outline = new ConstantProperty(options.outline); corridor.outlineColor = new ConstantProperty(options.outlineColor); corridor.cornerType = new ConstantProperty(options.cornerType); - corridor.width = new ConstantProperty(options.width); corridor.height = new ConstantProperty(options.height); corridor.extrudedHeight = new ConstantProperty(options.extrudedHeight); corridor.granularity = new ConstantProperty(options.granularity); + corridor.distanceDisplayCondition = options.distanceDisplayCondition; var updater = new CorridorGeometryUpdater(entity, scene); @@ -272,6 +278,9 @@ defineSuite([ expect(attributes.color).toBeUndefined(); } expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } if (options.outline) { @@ -285,6 +294,9 @@ defineSuite([ attributes = instance.attributes; expect(attributes.color.value).toEqual(ColorGeometryInstanceAttribute.toValue(options.outlineColor)); expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } } @@ -318,6 +330,22 @@ defineSuite([ }); }); + it('Creates expected distance display condition geometry', function() { + validateGeometryInstance({ + show : true, + material : new ColorMaterialProperty(Color.RED), + height : 431, + extrudedHeight : 123, + granularity : 0.97, + width : 12, + fill : true, + outline : true, + outlineColor : Color.BLUE, + cornerType : CornerType.MITERED, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) + }); + }); + it('Correctly exposes outlineWidth', function() { var entity = createBasicCorridor(); entity.corridor.outlineWidth = new ConstantProperty(8); diff --git a/Specs/DataSources/CorridorGraphicsSpec.js b/Specs/DataSources/CorridorGraphicsSpec.js index 2fd38a6e6052..bdbbc4434a9b 100644 --- a/Specs/DataSources/CorridorGraphicsSpec.js +++ b/Specs/DataSources/CorridorGraphicsSpec.js @@ -3,6 +3,7 @@ defineSuite([ 'DataSources/CorridorGraphics', 'Core/Color', 'Core/CornerType', + 'Core/DistanceDisplayCondition', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', 'Scene/ShadowMode', @@ -12,6 +13,7 @@ defineSuite([ CorridorGraphics, Color, CornerType, + DistanceDisplayCondition, ColorMaterialProperty, ConstantProperty, ShadowMode, @@ -33,7 +35,8 @@ defineSuite([ outlineColor : Color.RED, outlineWidth : 5, cornerType : CornerType.BEVELED, - shadows : ShadowMode.DISABLED + shadows : ShadowMode.DISABLED, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) }; var corridor = new CorridorGraphics(options); @@ -50,6 +53,7 @@ defineSuite([ expect(corridor.outlineWidth).toBeInstanceOf(ConstantProperty); expect(corridor.cornerType).toBeInstanceOf(ConstantProperty); expect(corridor.shadows).toBeInstanceOf(ConstantProperty); + expect(corridor.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(corridor.material.color.getValue()).toEqual(options.material); expect(corridor.positions.getValue()).toEqual(options.positions); @@ -64,6 +68,7 @@ defineSuite([ expect(corridor.outlineWidth.getValue()).toEqual(options.outlineWidth); expect(corridor.cornerType.getValue()).toEqual(options.cornerType); expect(corridor.shadows.getValue()).toEqual(options.shadows); + expect(corridor.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); }); it('merge assigns unassigned properties', function() { @@ -81,6 +86,7 @@ defineSuite([ source.outlineWidth = new ConstantProperty(); source.cornerType = new ConstantProperty(); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var target = new CorridorGraphics(); target.merge(source); @@ -98,6 +104,7 @@ defineSuite([ expect(target.outlineWidth).toBe(source.outlineWidth); expect(target.cornerType).toBe(source.cornerType); expect(target.shadows).toBe(source.shadows); + expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge does not assign assigned properties', function() { @@ -116,6 +123,7 @@ defineSuite([ var outlineWidth = new ConstantProperty(); var cornerType = new ConstantProperty(); var shadows = new ConstantProperty(); + var distanceDisplayCondition = new ConstantProperty(); var target = new CorridorGraphics(); target.material = material; @@ -131,6 +139,7 @@ defineSuite([ target.outlineWidth = outlineWidth; target.cornerType = cornerType; target.shadows = shadows; + target.distanceDisplayCondition = distanceDisplayCondition; target.merge(source); @@ -147,6 +156,7 @@ defineSuite([ expect(target.outlineWidth).toBe(outlineWidth); expect(target.cornerType).toBe(cornerType); expect(target.shadows).toBe(shadows); + expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); }); it('clone works', function() { @@ -164,6 +174,7 @@ defineSuite([ source.outlineWidth = new ConstantProperty(); source.cornerType = new ConstantProperty(); source.shadows = new ConstantProperty(); + source.distanceDisplayCondition = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -179,6 +190,7 @@ defineSuite([ expect(result.outlineWidth).toBe(source.outlineWidth); expect(result.cornerType).toBe(source.cornerType); expect(result.shadows).toBe(source.shadows); + expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge throws if source undefined', function() { @@ -203,5 +215,6 @@ defineSuite([ testDefinitionChanged(property, 'outlineWidth', 2, 3); testDefinitionChanged(property, 'cornerType', CornerType.BEVELED, CornerType.MITERED); testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); + testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 100.0)); }); }); diff --git a/Specs/DataSources/CylinderGeometryUpdaterSpec.js b/Specs/DataSources/CylinderGeometryUpdaterSpec.js index 21411b2ae099..3f43262cd991 100644 --- a/Specs/DataSources/CylinderGeometryUpdaterSpec.js +++ b/Specs/DataSources/CylinderGeometryUpdaterSpec.js @@ -4,6 +4,8 @@ defineSuite([ 'Core/Cartesian3', 'Core/Color', 'Core/ColorGeometryInstanceAttribute', + 'Core/DistanceDisplayCondition', + 'Core/DistanceDisplayConditionGeometryInstanceAttribute', 'Core/JulianDate', 'Core/Quaternion', 'Core/ShowGeometryInstanceAttribute', @@ -28,6 +30,8 @@ defineSuite([ Cartesian3, Color, ColorGeometryInstanceAttribute, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, JulianDate, Quaternion, ShowGeometryInstanceAttribute, @@ -88,6 +92,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toBe(undefined); + expect(updater.distanceDisplayConditionProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -149,6 +154,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); + expect(updater.distanceDisplayConditionProperty).toEqual(new ConstantProperty(new DistanceDisplayCondition())); expect(updater.isDynamic).toBe(false); }); @@ -219,10 +225,10 @@ defineSuite([ cylinder.outline = new ConstantProperty(options.outline); cylinder.outlineColor = new ConstantProperty(options.outlineColor); cylinder.numberOfVerticalLines = new ConstantProperty(options.numberOfVerticalLines); - cylinder.length = new ConstantProperty(options.length); cylinder.topRadius = new ConstantProperty(options.topRadius); cylinder.bottomRadius = new ConstantProperty(options.bottomRadius); + cylinder.distanceDisplayCondition = options.distanceDisplayCondition; entity.cylinder = cylinder; var updater = new CylinderGeometryUpdater(entity, scene); @@ -244,6 +250,9 @@ defineSuite([ expect(attributes.color).toBeUndefined(); } expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } if (options.outline) { @@ -257,6 +266,9 @@ defineSuite([ attributes = instance.attributes; expect(attributes.color.value).toEqual(ColorGeometryInstanceAttribute.toValue(options.outlineColor)); expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } } @@ -292,6 +304,23 @@ defineSuite([ }); }); + it('Creates expected distance display condition geometry', function() { + validateGeometryInstance({ + position : new Cartesian3(4, 5, 6), + orientation : Quaternion.IDENTITY, + length : 1, + topRadius : 3, + bottomRadius : 2, + show : true, + material : new ColorMaterialProperty(Color.RED), + fill : true, + outline : true, + outlineColor : Color.BLUE, + numberOfVerticalLines : 15, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) + }); + }); + it('Correctly exposes outlineWidth', function() { var entity = createBasicCylinder(); entity.cylinder.outlineWidth = new ConstantProperty(8); diff --git a/Specs/DataSources/CylinderGraphicsSpec.js b/Specs/DataSources/CylinderGraphicsSpec.js index 5a30f2c1bf6c..8e6c99d065f5 100644 --- a/Specs/DataSources/CylinderGraphicsSpec.js +++ b/Specs/DataSources/CylinderGraphicsSpec.js @@ -2,6 +2,7 @@ defineSuite([ 'DataSources/CylinderGraphics', 'Core/Color', + 'Core/DistanceDisplayCondition', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', 'Scene/ShadowMode', @@ -10,6 +11,7 @@ defineSuite([ ], function( CylinderGraphics, Color, + DistanceDisplayCondition, ColorMaterialProperty, ConstantProperty, ShadowMode, @@ -30,7 +32,8 @@ defineSuite([ outline : false, outlineColor : Color.RED, outlineWidth : 6, - shadows : ShadowMode.DISABLED + shadows : ShadowMode.DISABLED, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) }; var cylinder = new CylinderGraphics(options); @@ -46,6 +49,7 @@ defineSuite([ expect(cylinder.outlineColor).toBeInstanceOf(ConstantProperty); expect(cylinder.outlineWidth).toBeInstanceOf(ConstantProperty); expect(cylinder.shadows).toBeInstanceOf(ConstantProperty); + expect(cylinder.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(cylinder.material.color.getValue()).toEqual(options.material); expect(cylinder.show.getValue()).toEqual(options.show); @@ -59,6 +63,7 @@ defineSuite([ expect(cylinder.outlineColor.getValue()).toEqual(options.outlineColor); expect(cylinder.outlineWidth.getValue()).toEqual(options.outlineWidth); expect(cylinder.shadows.getValue()).toEqual(options.shadows); + expect(cylinder.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); }); it('merge assigns unassigned properties', function() { @@ -74,6 +79,7 @@ defineSuite([ source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.distanceDisplayCondition = new ConstantProperty(); var target = new CylinderGraphics(); target.merge(source); @@ -89,6 +95,7 @@ defineSuite([ expect(target.outlineColor).toBe(source.outlineColor); expect(target.outlineWidth).toBe(source.outlineWidth); expect(target.shadows).toBe(source.shadows); + expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge does not assign assigned properties', function() { @@ -105,6 +112,7 @@ defineSuite([ var outlineColor = new ConstantProperty(); var outlineWidth = new ConstantProperty(); var shadows = new ConstantProperty(); + var distanceDisplayCondition = new ConstantProperty(); var target = new CylinderGraphics(); target.material = material; @@ -118,6 +126,7 @@ defineSuite([ target.outlineColor = outlineColor; target.outlineWidth = outlineWidth; target.shadows = shadows; + target.distanceDisplayCondition = distanceDisplayCondition; target.merge(source); @@ -132,6 +141,7 @@ defineSuite([ expect(target.outlineColor).toBe(outlineColor); expect(target.outlineWidth).toBe(outlineWidth); expect(target.shadows).toBe(shadows); + expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); }); it('clone works', function() { @@ -147,6 +157,7 @@ defineSuite([ source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); source.shadows = new ConstantProperty(); + source.distanceDisplayCondition = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -160,6 +171,7 @@ defineSuite([ expect(result.outlineColor).toBe(source.outlineColor); expect(result.outlineWidth).toBe(source.outlineWidth); expect(result.shadows).toBe(source.shadows); + expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge throws if source undefined', function() { @@ -182,5 +194,6 @@ defineSuite([ testDefinitionChanged(property, 'outlineColor', Color.RED, Color.BLUE); testDefinitionChanged(property, 'outlineWidth', 2, 3); testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); + testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 100.0)); }); }); diff --git a/Specs/DataSources/EllipseGeometryUpdaterSpec.js b/Specs/DataSources/EllipseGeometryUpdaterSpec.js index 4df887e1a075..6b2068239e6e 100644 --- a/Specs/DataSources/EllipseGeometryUpdaterSpec.js +++ b/Specs/DataSources/EllipseGeometryUpdaterSpec.js @@ -4,6 +4,8 @@ defineSuite([ 'Core/Cartesian3', 'Core/Color', 'Core/ColorGeometryInstanceAttribute', + 'Core/DistanceDisplayCondition', + 'Core/DistanceDisplayConditionGeometryInstanceAttribute', 'Core/JulianDate', 'Core/ShowGeometryInstanceAttribute', 'Core/TimeInterval', @@ -29,6 +31,8 @@ defineSuite([ Cartesian3, Color, ColorGeometryInstanceAttribute, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, JulianDate, ShowGeometryInstanceAttribute, TimeInterval, @@ -103,6 +107,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.distanceDisplayConditionProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -166,6 +171,7 @@ defineSuite([ expect(updater.outlineWidth).toBe(1.0); expect(updater.isDynamic).toBe(false); expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); + expect(updater.distanceDisplayConditionProperty).toEqual(new ConstantProperty(new DistanceDisplayCondition())); }); it('Ellipse material is correctly exposed.', function() { @@ -281,6 +287,7 @@ defineSuite([ ellipse.height = new ConstantProperty(options.height); ellipse.extrudedHeight = new ConstantProperty(options.extrudedHeight); ellipse.granularity = new ConstantProperty(options.granularity); + ellipse.distanceDisplayCondition = options.distanceDisplayCondition; entity.ellipse = ellipse; var updater = new EllipseGeometryUpdater(entity, scene); @@ -307,6 +314,9 @@ defineSuite([ expect(attributes.color).toBeUndefined(); } expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } if (options.outline) { @@ -324,6 +334,9 @@ defineSuite([ attributes = instance.attributes; expect(attributes.color.value).toEqual(ColorGeometryInstanceAttribute.toValue(options.outlineColor)); expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } } @@ -365,6 +378,26 @@ defineSuite([ }); }); + it('Creates expected distance display condition geometry', function() { + validateGeometryInstance({ + center : new Cartesian3(4, 5, 6), + rotation : 1, + semiMajorAxis : 3, + semiMinorAxis : 2, + show : true, + material : new ColorMaterialProperty(Color.RED), + height : 123, + extrudedHeight : 431, + granularity : 0.97, + stRotation : 12, + fill : true, + outline : true, + outlineColor : Color.BLUE, + numberOfVerticalLines : 15, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) + }); + }); + it('Correctly exposes outlineWidth', function() { var entity = createBasicEllipse(); entity.ellipse.outlineWidth = new ConstantProperty(8); diff --git a/Specs/DataSources/EllipseGraphicsSpec.js b/Specs/DataSources/EllipseGraphicsSpec.js index 48a3d1d019b5..e32f7345cebe 100644 --- a/Specs/DataSources/EllipseGraphicsSpec.js +++ b/Specs/DataSources/EllipseGraphicsSpec.js @@ -2,6 +2,7 @@ defineSuite([ 'DataSources/EllipseGraphics', 'Core/Color', + 'Core/DistanceDisplayCondition', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', 'Scene/ShadowMode', @@ -10,6 +11,7 @@ defineSuite([ ], function( EllipseGraphics, Color, + DistanceDisplayCondition, ColorMaterialProperty, ConstantProperty, ShadowMode, @@ -33,7 +35,8 @@ defineSuite([ outline : false, outlineColor : Color.RED, outlineWidth : 9, - shadows : ShadowMode.DISABLED + shadows : ShadowMode.DISABLED, + distanceDisplayCondition : new DistanceDisplayCondition() }; var ellipse = new EllipseGraphics(options); @@ -52,6 +55,7 @@ defineSuite([ expect(ellipse.outlineColor).toBeInstanceOf(ConstantProperty); expect(ellipse.outlineWidth).toBeInstanceOf(ConstantProperty); expect(ellipse.shadows).toBeInstanceOf(ConstantProperty); + expect(ellipse.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(ellipse.material.color.getValue()).toEqual(options.material); expect(ellipse.show.getValue()).toEqual(options.show); @@ -68,6 +72,7 @@ defineSuite([ expect(ellipse.outlineColor.getValue()).toEqual(options.outlineColor); expect(ellipse.outlineWidth.getValue()).toEqual(options.outlineWidth); expect(ellipse.shadows.getValue()).toEqual(options.shadows); + expect(ellipse.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); }); it('merge assigns unassigned properties', function() { @@ -87,6 +92,7 @@ defineSuite([ source.outlineWidth = new ConstantProperty(); source.numberOfVerticalLines = new ConstantProperty(); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var target = new EllipseGraphics(); target.merge(source); @@ -106,6 +112,7 @@ defineSuite([ expect(target.outlineWidth).toBe(source.outlineWidth); expect(target.numberOfVerticalLines).toBe(source.numberOfVerticalLines); expect(target.shadows).toBe(source.shadows); + expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge does not assign assigned properties', function() { @@ -126,6 +133,7 @@ defineSuite([ var outlineWidth = new ConstantProperty(); var numberOfVerticalLines = new ConstantProperty(); var shadows = new ConstantProperty(); + var distanceDisplayCondition = new ConstantProperty(); var target = new EllipseGraphics(); target.material = material; @@ -143,6 +151,7 @@ defineSuite([ target.outlineWidth = outlineWidth; target.numberOfVerticalLines = numberOfVerticalLines; target.shadows = shadows; + target.distanceDisplayCondition = distanceDisplayCondition; target.merge(source); @@ -161,6 +170,7 @@ defineSuite([ expect(target.outlineWidth).toBe(outlineWidth); expect(target.numberOfVerticalLines).toBe(numberOfVerticalLines); expect(target.shadows).toBe(shadows); + expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); }); it('clone works', function() { @@ -180,6 +190,7 @@ defineSuite([ source.outlineWidth = new ConstantProperty(); source.numberOfVerticalLines = new ConstantProperty(); source.shadows = new ConstantProperty(); + source.distanceDisplayCondition = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -197,6 +208,7 @@ defineSuite([ expect(result.outlineWidth).toBe(source.outlineWidth); expect(result.numberOfVerticalLines).toBe(source.numberOfVerticalLines); expect(result.shadows).toBe(source.shadows); + expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge throws if source undefined', function() { @@ -223,5 +235,6 @@ defineSuite([ testDefinitionChanged(property, 'outlineWidth', 2, 3); testDefinitionChanged(property, 'numberOfVerticalLines', 16, 32); testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); + testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 100.0)); }); }); diff --git a/Specs/DataSources/EllipsoidGeometryUpdaterSpec.js b/Specs/DataSources/EllipsoidGeometryUpdaterSpec.js index 5df189f584dc..15c4d4c5d840 100644 --- a/Specs/DataSources/EllipsoidGeometryUpdaterSpec.js +++ b/Specs/DataSources/EllipsoidGeometryUpdaterSpec.js @@ -4,6 +4,8 @@ defineSuite([ 'Core/Cartesian3', 'Core/Color', 'Core/ColorGeometryInstanceAttribute', + 'Core/DistanceDisplayCondition', + 'Core/DistanceDisplayConditionGeometryInstanceAttribute', 'Core/JulianDate', 'Core/Quaternion', 'Core/ShowGeometryInstanceAttribute', @@ -28,6 +30,8 @@ defineSuite([ Cartesian3, Color, ColorGeometryInstanceAttribute, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, JulianDate, Quaternion, ShowGeometryInstanceAttribute, @@ -85,6 +89,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toBe(undefined); + expect(updater.distanceDisplayConditionProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -135,6 +140,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); + expect(updater.distanceDisplayConditionProperty).toEqual(new ConstantProperty(new DistanceDisplayCondition())); expect(updater.isDynamic).toBe(false); }); @@ -209,6 +215,7 @@ defineSuite([ ellipsoid.stackPartitions = new ConstantProperty(options.stackPartitions); ellipsoid.slicePartitions = new ConstantProperty(options.slicePartitions); ellipsoid.subdivisions = new ConstantProperty(options.subdivisions); + ellipsoid.distanceDisplayCondition = options.distanceDisplayCondition; entity.ellipsoid = ellipsoid; var updater = new EllipsoidGeometryUpdater(entity, scene); @@ -231,6 +238,9 @@ defineSuite([ expect(attributes.color).toBeUndefined(); } expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } if (options.outline) { @@ -245,6 +255,9 @@ defineSuite([ attributes = instance.attributes; expect(attributes.color.value).toEqual(ColorGeometryInstanceAttribute.toValue(options.outlineColor)); expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } } @@ -280,6 +293,23 @@ defineSuite([ }); }); + it('Creates expected distance display condition geometry', function() { + validateGeometryInstance({ + position : new Cartesian3(4, 5, 6), + orientation : Quaternion.IDENTITY, + radii : new Cartesian3(1, 2, 3), + show : true, + material : new ColorMaterialProperty(Color.RED), + fill : true, + outline : true, + outlineColor : Color.BLUE, + stackPartitions : 32, + slicePartitions : 64, + subdivisions : 15, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) + }); + }); + it('Correctly exposes outlineWidth', function() { var entity = createBasicEllipsoid(); entity.ellipsoid.outlineWidth = new ConstantProperty(8); diff --git a/Specs/DataSources/EllipsoidGraphicsSpec.js b/Specs/DataSources/EllipsoidGraphicsSpec.js index aac4cc2bc0b9..d42c8a7c03e5 100644 --- a/Specs/DataSources/EllipsoidGraphicsSpec.js +++ b/Specs/DataSources/EllipsoidGraphicsSpec.js @@ -3,6 +3,7 @@ defineSuite([ 'DataSources/EllipsoidGraphics', 'Core/Cartesian3', 'Core/Color', + 'Core/DistanceDisplayCondition', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', 'Scene/ShadowMode', @@ -12,6 +13,7 @@ defineSuite([ EllipsoidGraphics, Cartesian3, Color, + DistanceDisplayCondition, ColorMaterialProperty, ConstantProperty, ShadowMode, @@ -30,7 +32,8 @@ defineSuite([ outline : false, outlineColor : Color.RED, outlineWidth : 4, - shadows : ShadowMode.DISABLED + shadows : ShadowMode.DISABLED, + distanceDisplayCondition : new DistanceDisplayCondition() }; var ellipsoid = new EllipsoidGraphics(options); @@ -44,6 +47,7 @@ defineSuite([ expect(ellipsoid.outlineColor).toBeInstanceOf(ConstantProperty); expect(ellipsoid.outlineWidth).toBeInstanceOf(ConstantProperty); expect(ellipsoid.shadows).toBeInstanceOf(ConstantProperty); + expect(ellipsoid.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(ellipsoid.material.color.getValue()).toEqual(options.material); expect(ellipsoid.show.getValue()).toEqual(options.show); @@ -55,6 +59,7 @@ defineSuite([ expect(ellipsoid.outlineColor.getValue()).toEqual(options.outlineColor); expect(ellipsoid.outlineWidth.getValue()).toEqual(options.outlineWidth); expect(ellipsoid.shadows.getValue()).toEqual(options.shadows); + expect(ellipsoid.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); }); it('merge assigns unassigned properties', function() { @@ -70,6 +75,7 @@ defineSuite([ source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var target = new EllipsoidGraphics(); target.merge(source); @@ -85,6 +91,7 @@ defineSuite([ expect(target.outlineColor).toBe(source.outlineColor); expect(target.outlineWidth).toBe(source.outlineWidth); expect(target.shadows).toBe(source.shadows); + expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge does not assign assigned properties', function() { @@ -101,6 +108,7 @@ defineSuite([ var outlineColor = new ConstantProperty(); var outlineWidth = new ConstantProperty(); var shadows = new ConstantProperty(); + var distanecDisplayCondition = new ConstantProperty(); var target = new EllipsoidGraphics(); target.material = material; @@ -110,6 +118,7 @@ defineSuite([ target.slicePartitions = slicePartitions; target.subdivisions = subdivisions; target.shadows = shadows; + target.distanceDisplayCondition = distanecDisplayCondition; source.fill = fill; source.outline = outline; @@ -129,6 +138,7 @@ defineSuite([ expect(target.outlineColor).toBe(outlineColor); expect(target.outlineWidth).toBe(outlineWidth); expect(target.shadows).toBe(shadows); + expect(target.distanceDisplayCondition).toBe(distanecDisplayCondition); }); it('clone works', function() { @@ -144,6 +154,7 @@ defineSuite([ source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); source.shadows = new ConstantProperty(); + source.distanceDisplayCondition = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -157,6 +168,7 @@ defineSuite([ expect(result.outlineColor).toBe(source.outlineColor); expect(result.outlineWidth).toBe(source.outlineWidth); expect(result.shadows).toBe(source.shadows); + expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge throws if source undefined', function() { @@ -179,5 +191,6 @@ defineSuite([ testDefinitionChanged(property, 'outlineColor', Color.RED, Color.BLUE); testDefinitionChanged(property, 'outlineWidth', 2, 3); testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); + testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 100.0)); }); }); diff --git a/Specs/DataSources/ModelGraphicsSpec.js b/Specs/DataSources/ModelGraphicsSpec.js index 2e24688d577c..c2c18f2965df 100644 --- a/Specs/DataSources/ModelGraphicsSpec.js +++ b/Specs/DataSources/ModelGraphicsSpec.js @@ -2,6 +2,7 @@ defineSuite([ 'DataSources/ModelGraphics', 'Core/Cartesian3', + 'Core/DistanceDisplayCondition', 'Core/JulianDate', 'Core/Quaternion', 'DataSources/ConstantProperty', @@ -11,6 +12,7 @@ defineSuite([ ], function( ModelGraphics, Cartesian3, + DistanceDisplayCondition, JulianDate, Quaternion, ConstantProperty, @@ -29,6 +31,7 @@ defineSuite([ incrementallyLoadTextures : false, runAnimations : false, shadows : ShadowMode.DISABLED, + distanceDisplayCondition : new DistanceDisplayCondition(), nodeTransformations : { node1 : { translation : Cartesian3.UNIT_Y, @@ -57,6 +60,7 @@ defineSuite([ expect(model.maximumScale.getValue()).toEqual(options.maximumScale); expect(model.incrementallyLoadTextures.getValue()).toEqual(options.incrementallyLoadTextures); expect(model.shadows.getValue()).toEqual(options.shadows); + expect(model.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); expect(model.runAnimations.getValue()).toEqual(options.runAnimations); var actualNodeTransformations = model.nodeTransformations.getValue(new JulianDate()); @@ -77,6 +81,7 @@ defineSuite([ source.maximumScale = new ConstantProperty(200.0); source.incrementallyLoadTextures = new ConstantProperty(true); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); source.runAnimations = new ConstantProperty(true); source.nodeTransformations = { node1 : new NodeTransformationProperty({ @@ -99,6 +104,7 @@ defineSuite([ expect(target.maximumScale).toBe(source.maximumScale); expect(target.incrementallyLoadTextures).toBe(source.incrementallyLoadTextures); expect(target.shadows).toBe(source.shadows); + expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); expect(target.runAnimations).toBe(source.runAnimations); expect(target.nodeTransformations).toEqual(source.nodeTransformations); }); @@ -112,6 +118,7 @@ defineSuite([ source.maximumScale = new ConstantProperty(200.0); source.incrementallyLoadTextures = new ConstantProperty(true); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); source.runAnimations = new ConstantProperty(true); source.nodeTransformations = { transform : new NodeTransformationProperty() @@ -124,6 +131,7 @@ defineSuite([ var maximumScale = new ConstantProperty(200.0); var incrementallyLoadTextures = new ConstantProperty(true); var shadows = new ConstantProperty(ShadowMode.ENABLED); + var distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var runAnimations = new ConstantProperty(true); var nodeTransformations = new PropertyBag({ transform : new NodeTransformationProperty() @@ -137,6 +145,7 @@ defineSuite([ target.maximumScale = maximumScale; target.incrementallyLoadTextures = incrementallyLoadTextures; target.shadows = shadows; + target.distanceDisplayCondition = distanceDisplayCondition; target.runAnimations = runAnimations; target.nodeTransformations = nodeTransformations; @@ -149,6 +158,7 @@ defineSuite([ expect(target.maximumScale).toBe(maximumScale); expect(target.incrementallyLoadTextures).toBe(incrementallyLoadTextures); expect(target.shadows).toBe(shadows); + expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); expect(target.runAnimations).toBe(runAnimations); expect(target.nodeTransformations).toBe(nodeTransformations); }); @@ -162,6 +172,7 @@ defineSuite([ source.maximumScale = new ConstantProperty(200.0); source.incrementallyLoadTextures = new ConstantProperty(true); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); source.runAnimations = new ConstantProperty(true); source.nodeTransformations = { node1 : new NodeTransformationProperty(), @@ -176,6 +187,7 @@ defineSuite([ expect(result.maximumScale).toBe(source.maximumScale); expect(result.incrementallyLoadTextures).toBe(source.incrementallyLoadTextures); expect(result.shadows).toBe(source.shadows); + expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); expect(result.runAnimations).toBe(source.runAnimations); expect(result.nodeTransformations).toEqual(source.nodeTransformations); }); diff --git a/Specs/DataSources/ModelVisualizerSpec.js b/Specs/DataSources/ModelVisualizerSpec.js index c5c17c842cf7..dc27918c2727 100644 --- a/Specs/DataSources/ModelVisualizerSpec.js +++ b/Specs/DataSources/ModelVisualizerSpec.js @@ -3,6 +3,7 @@ defineSuite([ 'DataSources/ModelVisualizer', 'Core/BoundingSphere', 'Core/Cartesian3', + 'Core/DistanceDisplayCondition', 'Core/JulianDate', 'Core/Matrix4', 'Core/Quaternion', @@ -20,6 +21,7 @@ defineSuite([ ModelVisualizer, BoundingSphere, Cartesian3, + DistanceDisplayCondition, JulianDate, Matrix4, Quaternion, @@ -116,6 +118,7 @@ defineSuite([ model.scale = new ConstantProperty(2); model.minimumPixelSize = new ConstantProperty(24.0); model.uri = new ConstantProperty(boxUrl); + model.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var translation = new Cartesian3(1.0, 2.0, 3.0); var rotation = new Quaternion(0.0, 0.707, 0.0, 0.707); @@ -143,6 +146,7 @@ defineSuite([ expect(primitive.scale).toEqual(2); expect(primitive.minimumPixelSize).toEqual(24.0); expect(primitive.modelMatrix).toEqual(Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(1, 2, 3), scene.globe.ellipsoid)); + expect(primitive.distanceDisplayCondition).toEqual(new DistanceDisplayCondition(10.0, 100.0)); // wait till the model is loaded before we can check node transformations return pollToPromise(function() { diff --git a/Specs/DataSources/PolygonGeometryUpdaterSpec.js b/Specs/DataSources/PolygonGeometryUpdaterSpec.js index 211152007aeb..6f8efe50d750 100644 --- a/Specs/DataSources/PolygonGeometryUpdaterSpec.js +++ b/Specs/DataSources/PolygonGeometryUpdaterSpec.js @@ -4,6 +4,8 @@ defineSuite([ 'Core/Cartesian3', 'Core/Color', 'Core/ColorGeometryInstanceAttribute', + 'Core/DistanceDisplayCondition', + 'Core/DistanceDisplayConditionGeometryInstanceAttribute', 'Core/JulianDate', 'Core/PolygonHierarchy', 'Core/ShowGeometryInstanceAttribute', @@ -30,6 +32,8 @@ defineSuite([ Cartesian3, Color, ColorGeometryInstanceAttribute, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, JulianDate, PolygonHierarchy, ShowGeometryInstanceAttribute, @@ -109,6 +113,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toBe(undefined); + expect(updater.distanceDisplayConditionProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.onTerrain).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); @@ -151,6 +156,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); + expect(updater.distanceDisplayConditionProperty).toEqual(new ConstantProperty(new DistanceDisplayCondition())); expect(updater.isDynamic).toBe(false); }); @@ -264,6 +270,7 @@ defineSuite([ polygon.height = new ConstantProperty(options.height); polygon.extrudedHeight = new ConstantProperty(options.extrudedHeight); polygon.granularity = new ConstantProperty(options.granularity); + polygon.distanceDisplayCondition = options.distanceDisplayCondition; var updater = new PolygonGeometryUpdater(entity, scene); @@ -287,6 +294,9 @@ defineSuite([ expect(attributes.color).toBeUndefined(); } expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } if (options.outline) { @@ -300,6 +310,9 @@ defineSuite([ attributes = instance.attributes; expect(attributes.color.value).toEqual(ColorGeometryInstanceAttribute.toValue(options.outlineColor)); expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } } @@ -337,6 +350,24 @@ defineSuite([ }); }); + it('Creates expected distance display condition geometry', function() { + validateGeometryInstance({ + show : true, + material : new ColorMaterialProperty(Color.RED), + height : 431, + extrudedHeight : 123, + granularity : 0.97, + stRotation : 12, + fill : true, + outline : true, + outlineColor : Color.BLUE, + perPositionHeight : false, + closeTop: true, + closeBottom: false, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) + }); + }); + it('Correctly exposes outlineWidth', function() { var entity = createBasicPolygon(); entity.polygon.outlineWidth = new ConstantProperty(8); diff --git a/Specs/DataSources/PolygonGraphicsSpec.js b/Specs/DataSources/PolygonGraphicsSpec.js index 0d28ea67981e..56d353d60d6e 100644 --- a/Specs/DataSources/PolygonGraphicsSpec.js +++ b/Specs/DataSources/PolygonGraphicsSpec.js @@ -2,6 +2,7 @@ defineSuite([ 'DataSources/PolygonGraphics', 'Core/Color', + 'Core/DistanceDisplayCondition', 'Core/PolygonHierarchy', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', @@ -11,6 +12,7 @@ defineSuite([ ], function( PolygonGraphics, Color, + DistanceDisplayCondition, PolygonHierarchy, ColorMaterialProperty, ConstantProperty, @@ -35,7 +37,8 @@ defineSuite([ outlineWidth : 7, closeTop : true, closeBottom : true, - shadows : ShadowMode.DISABLED + shadows : ShadowMode.DISABLED, + distanceDisplayCondition : new DistanceDisplayCondition }; var polygon = new PolygonGraphics(options); @@ -54,6 +57,7 @@ defineSuite([ expect(polygon.closeTop).toBeInstanceOf(ConstantProperty); expect(polygon.closeBottom).toBeInstanceOf(ConstantProperty); expect(polygon.shadows).toBeInstanceOf(ConstantProperty); + expect(polygon.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(polygon.material.color.getValue()).toEqual(options.material); expect(polygon.show.getValue()).toEqual(options.show); @@ -70,6 +74,7 @@ defineSuite([ expect(polygon.closeTop.getValue()).toEqual(options.closeTop); expect(polygon.closeBottom.getValue()).toEqual(options.closeBottom); expect(polygon.shadows.getValue()).toEqual(options.shadows); + expect(polygon.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); }); it('merge assigns unassigned properties', function() { @@ -89,6 +94,7 @@ defineSuite([ source.closeTop = new ConstantProperty(); source.closeBottom = new ConstantProperty(); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var target = new PolygonGraphics(); target.merge(source); @@ -108,6 +114,7 @@ defineSuite([ expect(target.closeTop).toBe(source.closeTop); expect(target.closeBottom).toBe(source.closeBottom); expect(target.shadows).toBe(source.shadows); + expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge does not assign assigned properties', function() { @@ -128,6 +135,7 @@ defineSuite([ var closeTop = new ConstantProperty(); var closeBottom = new ConstantProperty(); var shadows = new ConstantProperty(); + var distanceDisplayCondition = new ConstantProperty(); var target = new PolygonGraphics(); target.material = material; @@ -145,6 +153,7 @@ defineSuite([ target.closeTop = closeTop; target.closeBottom = closeBottom; target.shadows = shadows; + target.distanceDisplayCondition = distanceDisplayCondition; target.merge(source); @@ -163,6 +172,7 @@ defineSuite([ expect(target.closeTop).toBe(closeTop); expect(target.closeBottom).toBe(closeBottom); expect(target.shadows).toBe(shadows); + expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); }); it('clone works', function() { @@ -182,6 +192,7 @@ defineSuite([ source.closeTop = new ConstantProperty(); source.closeBottom = new ConstantProperty(); source.shadows = new ConstantProperty(); + source.distanceDisplayCondition = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -199,6 +210,7 @@ defineSuite([ expect(result.closeTop).toBe(source.closeTop); expect(result.closeBottom).toBe(source.closeBottom); expect(result.shadows).toBe(source.shadows); + expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge throws if source undefined', function() { @@ -225,5 +237,6 @@ defineSuite([ testDefinitionChanged(property, 'closeTop', true, false); testDefinitionChanged(property, 'closeBottom', true, false); testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); + testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 100.0)); }); }); diff --git a/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js b/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js index fca67522f11f..9752be442f2e 100644 --- a/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js +++ b/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js @@ -5,6 +5,8 @@ defineSuite([ 'Core/Cartesian3', 'Core/Color', 'Core/ColorGeometryInstanceAttribute', + 'Core/DistanceDisplayCondition', + 'Core/DistanceDisplayConditionGeometryInstanceAttribute', 'Core/CornerType', 'Core/JulianDate', 'Core/ShowGeometryInstanceAttribute', @@ -29,6 +31,8 @@ defineSuite([ Cartesian3, Color, ColorGeometryInstanceAttribute, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, CornerType, JulianDate, ShowGeometryInstanceAttribute, @@ -92,6 +96,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toBe(undefined); + expect(updater.distanceDisplayConditionProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -132,6 +137,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); + expect(updater.distanceDisplayConditionProperty).toEqual(new ConstantProperty(new DistanceDisplayCondition())); expect(updater.isDynamic).toBe(false); }); @@ -195,6 +201,7 @@ defineSuite([ polylineVolume.shape = new ConstantProperty(options.shape); polylineVolume.granularity = new ConstantProperty(options.granularity); + polylineVolume.distanceDisplayCondition = options.distanceDisplayCondition; var updater = new PolylineVolumeGeometryUpdater(entity, scene); @@ -214,6 +221,9 @@ defineSuite([ expect(attributes.color).toBeUndefined(); } expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } if (options.outline) { @@ -226,6 +236,9 @@ defineSuite([ attributes = instance.attributes; expect(attributes.color.value).toEqual(ColorGeometryInstanceAttribute.toValue(options.outlineColor)); expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } } @@ -255,6 +268,20 @@ defineSuite([ }); }); + it('Creates expected distance display condition geometry', function() { + validateGeometryInstance({ + show : true, + material : new ColorMaterialProperty(Color.RED), + shape : shape, + granularity : 0.97, + fill : true, + outline : true, + outlineColor : Color.BLUE, + cornerType : CornerType.MITERED, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) + }); + }); + it('Correctly exposes outlineWidth', function() { var entity = createBasicPolylineVolume(); entity.polylineVolume.outlineWidth = new ConstantProperty(8); diff --git a/Specs/DataSources/PolylineVolumeGraphicsSpec.js b/Specs/DataSources/PolylineVolumeGraphicsSpec.js index 5db295890dda..06dca21d368d 100644 --- a/Specs/DataSources/PolylineVolumeGraphicsSpec.js +++ b/Specs/DataSources/PolylineVolumeGraphicsSpec.js @@ -3,6 +3,7 @@ defineSuite([ 'DataSources/PolylineVolumeGraphics', 'Core/Color', 'Core/CornerType', + 'Core/DistanceDisplayCondition', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', 'Scene/ShadowMode', @@ -12,6 +13,7 @@ defineSuite([ PolylineVolumeGraphics, Color, CornerType, + DistanceDisplayCondition, ColorMaterialProperty, ConstantProperty, ShadowMode, @@ -31,7 +33,8 @@ defineSuite([ outlineColor : Color.RED, outlineWidth : 2, cornerType : CornerType.BEVELED, - shadows : ShadowMode.DISABLED + shadows : ShadowMode.DISABLED, + distanceDisplayCondition : new DistanceDisplayCondition() }; var polylineVolume = new PolylineVolumeGraphics(options); @@ -46,6 +49,7 @@ defineSuite([ expect(polylineVolume.outlineWidth).toBeInstanceOf(ConstantProperty); expect(polylineVolume.cornerType).toBeInstanceOf(ConstantProperty); expect(polylineVolume.shadows).toBeInstanceOf(ConstantProperty); + expect(polylineVolume.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(polylineVolume.material.color.getValue()).toEqual(options.material); expect(polylineVolume.positions.getValue()).toEqual(options.positions); @@ -58,6 +62,7 @@ defineSuite([ expect(polylineVolume.outlineWidth.getValue()).toEqual(options.outlineWidth); expect(polylineVolume.cornerType.getValue()).toEqual(options.cornerType); expect(polylineVolume.shadows.getValue()).toEqual(options.shadows); + expect(polylineVolume.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); }); it('merge assigns unassigned properties', function() { @@ -73,6 +78,7 @@ defineSuite([ source.outlineWidth = new ConstantProperty(); source.cornerType = new ConstantProperty(); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var target = new PolylineVolumeGraphics(); target.merge(source); @@ -88,6 +94,7 @@ defineSuite([ expect(target.outlineWidth).toBe(source.outlineWidth); expect(target.cornerType).toBe(source.cornerType); expect(target.shadows).toBe(source.shadows); + expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge does not assign assigned properties', function() { @@ -104,6 +111,7 @@ defineSuite([ var outlineWidth = new ConstantProperty(); var cornerType = new ConstantProperty(); var shadows = new ConstantProperty(); + var distanceDisplayCondition = new ConstantProperty(); var target = new PolylineVolumeGraphics(); target.material = material; @@ -117,6 +125,7 @@ defineSuite([ target.outlineWidth = outlineWidth; target.cornerType = cornerType; target.shadows = shadows; + target.distanceDisplayCondition = distanceDisplayCondition; target.merge(source); @@ -131,6 +140,7 @@ defineSuite([ expect(target.outlineWidth).toBe(outlineWidth); expect(target.cornerType).toBe(cornerType); expect(target.shadows).toBe(shadows); + expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); }); it('clone works', function() { @@ -146,6 +156,7 @@ defineSuite([ source.outlineWidth = new ConstantProperty(); source.cornerType = new ConstantProperty(); source.shadows = new ConstantProperty(); + source.distanceDisplayCondition = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -159,6 +170,7 @@ defineSuite([ expect(result.outlineWidth).toBe(source.outlineWidth); expect(result.cornerType).toBe(source.cornerType); expect(result.shadows).toBe(source.shadows); + expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge throws if source undefined', function() { @@ -181,5 +193,6 @@ defineSuite([ testDefinitionChanged(property, 'outlineWidth', 2, 3); testDefinitionChanged(property, 'cornerType', CornerType.BEVELED, CornerType.MITERED); testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); + testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 100.0)); }); }); diff --git a/Specs/DataSources/RectangleGeometryUpdaterSpec.js b/Specs/DataSources/RectangleGeometryUpdaterSpec.js index 63ecba106986..155924ff19f1 100644 --- a/Specs/DataSources/RectangleGeometryUpdaterSpec.js +++ b/Specs/DataSources/RectangleGeometryUpdaterSpec.js @@ -4,6 +4,8 @@ defineSuite([ 'Core/Cartesian3', 'Core/Color', 'Core/ColorGeometryInstanceAttribute', + 'Core/DistanceDisplayCondition', + 'Core/DistanceDisplayConditionGeometryInstanceAttribute', 'Core/JulianDate', 'Core/Rectangle', 'Core/ShowGeometryInstanceAttribute', @@ -28,6 +30,8 @@ defineSuite([ Cartesian3, Color, ColorGeometryInstanceAttribute, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, JulianDate, Rectangle, ShowGeometryInstanceAttribute, @@ -99,6 +103,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toBe(undefined); + expect(updater.distanceDisplayCondition).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -140,6 +145,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); + expect(updater.distanceDisplayConditionProperty).toEqual(new ConstantProperty(new DistanceDisplayCondition())); expect(updater.isDynamic).toBe(false); }); @@ -249,6 +255,7 @@ defineSuite([ rectangle.granularity = new ConstantProperty(options.granularity); rectangle.closeTop = new ConstantProperty(options.closeTop); rectangle.closeBottom = new ConstantProperty(options.closeBottom); + rectangle.distanceDisplayCondition = options.distanceDisplayCondition; var updater = new RectangleGeometryUpdater(entity, scene); @@ -273,6 +280,9 @@ defineSuite([ expect(attributes.color).toBeUndefined(); } expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } if (options.outline) { @@ -285,6 +295,9 @@ defineSuite([ attributes = instance.attributes; expect(attributes.color.value).toEqual(ColorGeometryInstanceAttribute.toValue(options.outlineColor)); expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } } @@ -322,6 +335,24 @@ defineSuite([ }); }); + it('Creates expected distance display condition geometry', function() { + validateGeometryInstance({ + show : true, + material : new ColorMaterialProperty(Color.RED), + height : 431, + extrudedHeight : 123, + granularity : 0.97, + rotation : 1, + stRotation : 12, + fill : true, + outline : true, + outlineColor : Color.BLUE, + closeTop : false, + closeBottom : true, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) + }); + }); + it('Correctly exposes outlineWidth', function() { var entity = createBasicRectangle(); entity.rectangle.outlineWidth = new ConstantProperty(8); diff --git a/Specs/DataSources/RectangleGraphicsSpec.js b/Specs/DataSources/RectangleGraphicsSpec.js index f8311886d30d..4f27b9874144 100644 --- a/Specs/DataSources/RectangleGraphicsSpec.js +++ b/Specs/DataSources/RectangleGraphicsSpec.js @@ -2,6 +2,7 @@ defineSuite([ 'DataSources/RectangleGraphics', 'Core/Color', + 'Core/DistanceDisplayCondition', 'Core/Rectangle', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', @@ -11,6 +12,7 @@ defineSuite([ ], function( RectangleGraphics, Color, + DistanceDisplayCondition, Rectangle, ColorMaterialProperty, ConstantProperty, @@ -35,41 +37,44 @@ defineSuite([ outlineWidth : 10, closeTop : false, closeBottom : false, - shadows : ShadowMode.DISABLED + shadows : ShadowMode.DISABLED, + distanceDisplayCondition : new DistanceDisplayCondition() }; - var ellipse = new RectangleGraphics(options); - expect(ellipse.material).toBeInstanceOf(ColorMaterialProperty); - expect(ellipse.show).toBeInstanceOf(ConstantProperty); - expect(ellipse.coordinates).toBeInstanceOf(ConstantProperty); - expect(ellipse.height).toBeInstanceOf(ConstantProperty); - expect(ellipse.extrudedHeight).toBeInstanceOf(ConstantProperty); - expect(ellipse.granularity).toBeInstanceOf(ConstantProperty); - expect(ellipse.rotation).toBeInstanceOf(ConstantProperty); - expect(ellipse.stRotation).toBeInstanceOf(ConstantProperty); - expect(ellipse.fill).toBeInstanceOf(ConstantProperty); - expect(ellipse.outline).toBeInstanceOf(ConstantProperty); - expect(ellipse.outlineColor).toBeInstanceOf(ConstantProperty); - expect(ellipse.outlineWidth).toBeInstanceOf(ConstantProperty); - expect(ellipse.closeTop).toBeInstanceOf(ConstantProperty); - expect(ellipse.closeBottom).toBeInstanceOf(ConstantProperty); - expect(ellipse.shadows).toBeInstanceOf(ConstantProperty); + var rectangle = new RectangleGraphics(options); + expect(rectangle.material).toBeInstanceOf(ColorMaterialProperty); + expect(rectangle.show).toBeInstanceOf(ConstantProperty); + expect(rectangle.coordinates).toBeInstanceOf(ConstantProperty); + expect(rectangle.height).toBeInstanceOf(ConstantProperty); + expect(rectangle.extrudedHeight).toBeInstanceOf(ConstantProperty); + expect(rectangle.granularity).toBeInstanceOf(ConstantProperty); + expect(rectangle.rotation).toBeInstanceOf(ConstantProperty); + expect(rectangle.stRotation).toBeInstanceOf(ConstantProperty); + expect(rectangle.fill).toBeInstanceOf(ConstantProperty); + expect(rectangle.outline).toBeInstanceOf(ConstantProperty); + expect(rectangle.outlineColor).toBeInstanceOf(ConstantProperty); + expect(rectangle.outlineWidth).toBeInstanceOf(ConstantProperty); + expect(rectangle.closeTop).toBeInstanceOf(ConstantProperty); + expect(rectangle.closeBottom).toBeInstanceOf(ConstantProperty); + expect(rectangle.shadows).toBeInstanceOf(ConstantProperty); + expect(rectangle.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); - expect(ellipse.material.color.getValue()).toEqual(options.material); - expect(ellipse.show.getValue()).toEqual(options.show); - expect(ellipse.coordinates.getValue()).toEqual(options.coordinates); - expect(ellipse.height.getValue()).toEqual(options.height); - expect(ellipse.extrudedHeight.getValue()).toEqual(options.extrudedHeight); - expect(ellipse.granularity.getValue()).toEqual(options.granularity); - expect(ellipse.rotation.getValue()).toEqual(options.rotation); - expect(ellipse.stRotation.getValue()).toEqual(options.stRotation); - expect(ellipse.fill.getValue()).toEqual(options.fill); - expect(ellipse.outline.getValue()).toEqual(options.outline); - expect(ellipse.outlineColor.getValue()).toEqual(options.outlineColor); - expect(ellipse.outlineWidth.getValue()).toEqual(options.outlineWidth); - expect(ellipse.closeTop.getValue()).toEqual(options.closeTop); - expect(ellipse.closeBottom.getValue()).toEqual(options.closeBottom); - expect(ellipse.shadows.getValue()).toEqual(options.shadows); + expect(rectangle.material.color.getValue()).toEqual(options.material); + expect(rectangle.show.getValue()).toEqual(options.show); + expect(rectangle.coordinates.getValue()).toEqual(options.coordinates); + expect(rectangle.height.getValue()).toEqual(options.height); + expect(rectangle.extrudedHeight.getValue()).toEqual(options.extrudedHeight); + expect(rectangle.granularity.getValue()).toEqual(options.granularity); + expect(rectangle.rotation.getValue()).toEqual(options.rotation); + expect(rectangle.stRotation.getValue()).toEqual(options.stRotation); + expect(rectangle.fill.getValue()).toEqual(options.fill); + expect(rectangle.outline.getValue()).toEqual(options.outline); + expect(rectangle.outlineColor.getValue()).toEqual(options.outlineColor); + expect(rectangle.outlineWidth.getValue()).toEqual(options.outlineWidth); + expect(rectangle.closeTop.getValue()).toEqual(options.closeTop); + expect(rectangle.closeBottom.getValue()).toEqual(options.closeBottom); + expect(rectangle.shadows.getValue()).toEqual(options.shadows); + expect(rectangle.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); }); it('merge assigns unassigned properties', function() { @@ -89,6 +94,7 @@ defineSuite([ source.closeTop = new ConstantProperty(); source.closeBottom = new ConstantProperty(); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.distanceDisplayCondition = new ConstantProperty(); var target = new RectangleGraphics(); target.merge(source); @@ -108,6 +114,7 @@ defineSuite([ expect(target.closeTop).toBe(source.closeTop); expect(target.closeBottom).toBe(source.closeBottom); expect(target.shadows).toBe(source.shadows); + expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge does not assign assigned properties', function() { @@ -128,6 +135,7 @@ defineSuite([ var closeTop = new ConstantProperty(); var closeBottom = new ConstantProperty(); var shadows = new ConstantProperty(); + var distanceDisplayCondition = new ConstantProperty(); var target = new RectangleGraphics(); target.material = material; @@ -145,6 +153,7 @@ defineSuite([ target.closeTop = closeTop; target.closeBottom = closeBottom; target.shadows = shadows; + target.distanceDisplayCondition = distanceDisplayCondition; target.merge(source); @@ -163,6 +172,7 @@ defineSuite([ expect(target.closeTop).toBe(closeTop); expect(target.closeBottom).toBe(closeBottom); expect(target.shadows).toBe(shadows); + expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); }); it('clone works', function() { @@ -182,6 +192,7 @@ defineSuite([ source.closeTop = new ConstantProperty(); source.closeBottom = new ConstantProperty(); source.shadows = new ConstantProperty(); + source.distanceDisplayCondition = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -199,6 +210,7 @@ defineSuite([ expect(result.closeTop).toBe(source.closeTop); expect(result.closeBottom).toBe(source.closeBottom); expect(result.shadows).toBe(source.shadows); + expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge throws if source undefined', function() { @@ -225,5 +237,6 @@ defineSuite([ testDefinitionChanged(property, 'closeTop', false, true); testDefinitionChanged(property, 'closeBottom', false, true); testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); + testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 100.0)); }); }); diff --git a/Specs/DataSources/WallGeometryUpdaterSpec.js b/Specs/DataSources/WallGeometryUpdaterSpec.js index c1f36d599764..154d0dbdce8e 100644 --- a/Specs/DataSources/WallGeometryUpdaterSpec.js +++ b/Specs/DataSources/WallGeometryUpdaterSpec.js @@ -4,6 +4,8 @@ defineSuite([ 'Core/Cartesian3', 'Core/Color', 'Core/ColorGeometryInstanceAttribute', + 'Core/DistanceDisplayCondition', + 'Core/DistanceDisplayConditionGeometryInstanceAttribute', 'Core/JulianDate', 'Core/ShowGeometryInstanceAttribute', 'Core/TimeInterval', @@ -27,6 +29,8 @@ defineSuite([ Cartesian3, Color, ColorGeometryInstanceAttribute, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, JulianDate, ShowGeometryInstanceAttribute, TimeInterval, @@ -91,6 +95,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toBe(undefined); + expect(updater.distanceDisplayConditionProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -132,6 +137,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); + expect(updater.distanceDisplayConditionProperty).toEqual(new ConstantProperty(new DistanceDisplayCondition())); expect(updater.isDynamic).toBe(false); }); @@ -209,6 +215,7 @@ defineSuite([ wall.outline = new ConstantProperty(options.outline); wall.outlineColor = new ConstantProperty(options.outlineColor); wall.granularity = new ConstantProperty(options.granularity); + wall.distanceDisplayCondition = options.distanceDisplayCondition; var updater = new WallGeometryUpdater(entity, scene); @@ -229,6 +236,9 @@ defineSuite([ expect(attributes.color).toBeUndefined(); } expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } if (options.outline) { @@ -241,6 +251,9 @@ defineSuite([ attributes = instance.attributes; expect(attributes.color.value).toEqual(ColorGeometryInstanceAttribute.toValue(options.outlineColor)); expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.fill)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } } @@ -270,6 +283,20 @@ defineSuite([ }); }); + it('Creates expected distance display condition geometry', function() { + validateGeometryInstance({ + show : true, + material : new ColorMaterialProperty(Color.RED), + minimumHeights : [0, 1, 2, 3], + maximumHeights : [4, 5, 6, 7], + granularity : 0.97, + fill : true, + outline : true, + outlineColor : Color.BLUE, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) + }); + }); + it('Correctly exposes outlineWidth', function() { var entity = createBasicWall(); entity.wall.outlineWidth = new ConstantProperty(8); diff --git a/Specs/DataSources/WallGraphicsSpec.js b/Specs/DataSources/WallGraphicsSpec.js index 6a1fd2eab8ac..43f1e09e168f 100644 --- a/Specs/DataSources/WallGraphicsSpec.js +++ b/Specs/DataSources/WallGraphicsSpec.js @@ -2,6 +2,7 @@ defineSuite([ 'DataSources/WallGraphics', 'Core/Color', + 'Core/DistanceDisplayCondition', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', 'Scene/ShadowMode', @@ -10,6 +11,7 @@ defineSuite([ ], function( WallGraphics, Color, + DistanceDisplayCondition, ColorMaterialProperty, ConstantProperty, ShadowMode, @@ -29,7 +31,8 @@ defineSuite([ outlineWidth : 2, minimumHeights : [3, 4, 5], maximumHeights : [6, 7, 8], - shadows : ShadowMode.DISABLED + shadows : ShadowMode.DISABLED, + distanceDisplayCondition : new DistanceDisplayCondition() }; var wall = new WallGraphics(options); @@ -45,6 +48,7 @@ defineSuite([ expect(wall.minimumHeights).toBeInstanceOf(ConstantProperty); expect(wall.maximumHeights).toBeInstanceOf(ConstantProperty); expect(wall.shadows).toBeInstanceOf(ConstantProperty); + expect(wall.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(wall.material.color.getValue()).toEqual(options.material); expect(wall.positions.getValue()).toEqual(options.positions); @@ -58,6 +62,7 @@ defineSuite([ expect(wall.minimumHeights.getValue()).toEqual(options.minimumHeights); expect(wall.maximumHeights.getValue()).toEqual(options.maximumHeights); expect(wall.shadows.getValue()).toEqual(options.shadows); + expect(wall.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); }); it('merge assigns unassigned properties', function() { @@ -73,6 +78,7 @@ defineSuite([ source.minimumHeights = new ConstantProperty(); source.maximumHeights = new ConstantProperty(); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.distanceDisplayCondition = new ConstantProperty(); var target = new WallGraphics(); target.merge(source); @@ -88,6 +94,7 @@ defineSuite([ expect(target.minimumHeights).toBe(source.minimumHeights); expect(target.maximumHeights).toBe(source.maximumHeights); expect(target.shadows).toBe(source.shadows); + expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge does not assign assigned properties', function() { @@ -104,6 +111,7 @@ defineSuite([ var minimumHeights = new ConstantProperty(); var maximumHeights = new ConstantProperty(); var shadows = new ConstantProperty(); + var distanceDisplayCondition = new ConstantProperty(); var target = new WallGraphics(); target.material = material; @@ -117,6 +125,7 @@ defineSuite([ target.minimumHeights = minimumHeights; target.maximumHeights = maximumHeights; target.shadows = shadows; + target.distanceDisplayCondition = distanceDisplayCondition; target.merge(source); @@ -131,6 +140,7 @@ defineSuite([ expect(target.minimumHeights).toBe(minimumHeights); expect(target.maximumHeights).toBe(maximumHeights); expect(target.shadows).toBe(shadows); + expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); }); it('clone works', function() { @@ -146,6 +156,7 @@ defineSuite([ source.minimumHeights = new ConstantProperty(); source.maximumHeights = new ConstantProperty(); source.shadows = new ConstantProperty(); + source.distanceDisplayCondition = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -159,6 +170,7 @@ defineSuite([ expect(result.minimumHeights).toBe(source.minimumHeights); expect(result.maximumHeights).toBe(source.maximumHeights); expect(result.shadows).toBe(source.shadows); + expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge throws if source undefined', function() { @@ -181,5 +193,6 @@ defineSuite([ testDefinitionChanged(property, 'minimumHeights', [0, 1], [2, 3]); testDefinitionChanged(property, 'maximumHeights', [3, 5], [7, 8]); testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); + testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 100.0)); }); }); From 090f57e3bbbb7010fad102996e89031bdda596c1 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 14 Sep 2016 16:13:29 -0400 Subject: [PATCH 082/191] Fix jsHint errors. --- Source/DataSources/RectangleGraphics.js | 2 +- Specs/DataSources/PolygonGraphicsSpec.js | 2 +- Specs/Scene/GroundPrimitiveSpec.js | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/DataSources/RectangleGraphics.js b/Source/DataSources/RectangleGraphics.js index b0d38cbc52a0..ccae9a4dabe6 100644 --- a/Source/DataSources/RectangleGraphics.js +++ b/Source/DataSources/RectangleGraphics.js @@ -245,7 +245,7 @@ define([ result.closeTop = this.closeTop; result.closeBottom = this.closeBottom; result.shadows = this.shadows; - result.distanceDisplayCondition = this.distanceDisplayCondition + result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; diff --git a/Specs/DataSources/PolygonGraphicsSpec.js b/Specs/DataSources/PolygonGraphicsSpec.js index 56d353d60d6e..4aa9310a0a36 100644 --- a/Specs/DataSources/PolygonGraphicsSpec.js +++ b/Specs/DataSources/PolygonGraphicsSpec.js @@ -38,7 +38,7 @@ defineSuite([ closeTop : true, closeBottom : true, shadows : ShadowMode.DISABLED, - distanceDisplayCondition : new DistanceDisplayCondition + distanceDisplayCondition : new DistanceDisplayCondition() }; var polygon = new PolygonGraphics(options); diff --git a/Specs/Scene/GroundPrimitiveSpec.js b/Specs/Scene/GroundPrimitiveSpec.js index 3626ad3acd62..1ea1c99bef7b 100644 --- a/Specs/Scene/GroundPrimitiveSpec.js +++ b/Specs/Scene/GroundPrimitiveSpec.js @@ -540,7 +540,6 @@ defineSuite([ depthPrimitive = new MockGlobePrimitive(primitive); var rectColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(1.0, 1.0, 0.0, 1.0)); - var rectColor = rectColorAttribute.value; var rectInstance = new GeometryInstance({ geometry : new RectangleGeometry({ ellipsoid : ellipsoid, From 108ce2d201b70a3cb5fc672163dc9cbfe9cf23e7 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 16 Sep 2016 16:05:10 -0400 Subject: [PATCH 083/191] Add batch table and hook it up to polyline collection. Polylines are still a WIP. --- Source/Scene/BatchTable.js | 313 +++++++++++++++++++++++++++++ Source/Scene/Polyline.js | 6 +- Source/Scene/PolylineCollection.js | 150 +++++++++----- Source/Shaders/PolylineVS.glsl | 18 +- 4 files changed, 425 insertions(+), 62 deletions(-) create mode 100644 Source/Scene/BatchTable.js diff --git a/Source/Scene/BatchTable.js b/Source/Scene/BatchTable.js new file mode 100644 index 000000000000..f402665a4473 --- /dev/null +++ b/Source/Scene/BatchTable.js @@ -0,0 +1,313 @@ +/*global define*/ +define([ + '../Core/Cartesian2', + '../Core/Cartesian3', + '../Core/Cartesian4', + '../Core/combine', + '../Core/ComponentDatatype', + '../Core/defined', + '../Core/destroyObject', + '../Core/DeveloperError', + '../Core/PixelFormat', + '../Core/RuntimeError', + '../Renderer/ContextLimits', + '../Renderer/PixelDatatype', + '../Renderer/Sampler', + '../Renderer/Texture', + '../Renderer/TextureMagnificationFilter', + '../Renderer/TextureMinificationFilter' + ], function( + Cartesian2, + Cartesian3, + Cartesian4, + combine, + ComponentDatatype, + defined, + destroyObject, + DeveloperError, + PixelFormat, + RuntimeError, + ContextLimits, + PixelDatatype, + Sampler, + Texture, + TextureMagnificationFilter, + TextureMinificationFilter) { + 'use strict'; + + function BatchTable(attributes, numberOfInstances) { + //>>includeStart('debug', pragmas.debug); + if (!defined(attributes)) { + throw new DeveloperError('attributes is required'); + } + if (!defined(numberOfInstances)) { + throw new DeveloperError('numberOfInstances is required'); + } + //>>includeEnd('debug'); + + this._attributes = attributes; + this._numberOfInstances = numberOfInstances; + + var pixelDatatype = getDatatype(attributes); + + var numberOfAttributes = attributes.length; + var maxNumberOfInstancesPerRow = Math.floor(ContextLimits.maximumTextureSize / numberOfAttributes); + + var instancesPerWidth = Math.min(numberOfInstances, maxNumberOfInstancesPerRow); + var width = numberOfAttributes * instancesPerWidth; + var height = Math.ceil(numberOfInstances / instancesPerWidth); + + var stepX = 1.0 / width; + var centerX = stepX * 0.5; + var stepY = 1.0 / height; + var centerY = stepY * 0.5; + + this._textureDimensions = new Cartesian2(width, height); + this._textureStep = new Cartesian4(stepX, centerX, stepY, centerY); + this._pixelDatatype = pixelDatatype; + this._texture = undefined; + + var batchLength = width * height * 4; + this._batchValues = pixelDatatype === PixelDatatype.FLOAT ? new Float32Array(batchLength) : new Uint8Array(batchLength); + this._batchValuesDirty = false; + } + + function getDatatype(attributes) { + var foundFloatDatatype = false; + var length = attributes.length; + for (var i = 0; i < length; ++i) { + if (attributes[i].componentDatatype !== ComponentDatatype.UNSIGNED_BYTE) { + foundFloatDatatype = true; + } + } + return foundFloatDatatype ? PixelDatatype.FLOAT : PixelDatatype.UNSIGNED_BYTE; + } + + function getEntryType(attributes, attributeIndex) { + var componentsPerAttribute = attributes[attributeIndex].componentsPerAttribute; + if (componentsPerAttribute === 2) { + return Cartesian2; + } else if (componentsPerAttribute === 3) { + return Cartesian3; + } else if (componentsPerAttribute === 4) { + return Cartesian4; + } + return Number; + } + + var scratchgetEntryCartesian4 = new Cartesian4(); + + BatchTable.prototype.getEntry = function(instanceIndex, attributeIndex, result) { + //>>includeStart('debug', pragmas.debug); + if (instanceIndex < 0 || instanceIndex >= this._numberOfInstances) { + throw new DeveloperError('instanceIndex is out of range.'); + } + if (attributeIndex < 0 || attributeIndex >= this._attributes.length) { + throw new DeveloperError('attributeIndex is out of range'); + } + //>>includeEnd('debug'); + + var attributes = this._attributes; + var index = 4 * attributes.length * instanceIndex + 4 * attributeIndex; + var value = Cartesian4.unpack(this._batchValues, index, scratchgetEntryCartesian4); + + var entryType = getEntryType(attributes, attributeIndex); + if (defined(entryType.fromCartesian4)) { + return entryType.fromCartesian4(value, result); + } else if (defined(entryType.clone)) { + return entryType.clone(value, result); + } + + return value.x; + }; + + var setEntryScratchValues = [undefined, undefined, new Cartesian2(), new Cartesian3(), new Cartesian4()]; + var setEntryScratchCartesian4 = new Cartesian4(); + + BatchTable.prototype.setEntry = function(instanceIndex, attributeIndex, value) { + //>>includeStart('debug', pragmas.debug); + if (instanceIndex < 0 || instanceIndex >= this._numberOfInstances) { + throw new DeveloperError('instanceIndex is out of range.'); + } + if (attributeIndex < 0 || attributeIndex >= this._attributes.length) { + throw new DeveloperError('attributeIndex is out of range'); + } + //>>includeEnd('debug'); + + var attributes = this._attributes; + var result = setEntryScratchValues[attributes[attributeIndex].componentsPerAttribute]; + var currentEntry = this.getEntry(instanceIndex, attributeIndex, result); + var entryType = getEntryType(this._attributes, attributeIndex); + var entriesEqual = defined(entryType.equals) ? entryType.equals(currentEntry, value) : currentEntry === value; + if (entriesEqual) { + return; + } + + var entryValue = setEntryScratchCartesian4; + entryValue.x = defined(value.x) ? value.x : value; + entryValue.y = defined(value.y) ? value.y : 0.0; + entryValue.z = defined(value.z) ? value.z : 0.0; + entryValue.w = defined(value.w) ? value.w : 0.0; + + var index = 4 * attributes.length * instanceIndex + 4 * attributeIndex; + Cartesian4.pack(entryValue, this._batchValues, index); + + this._batchValuesDirty = true; + }; + + function createTexture(batchTable, context) { + var dimensions = batchTable._textureDimensions; + batchTable._texture = new Texture({ + context : context, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : batchTable._pixelDatatype, + width : dimensions.x, + height : dimensions.y, + sampler : new Sampler({ + minificationFilter : TextureMinificationFilter.NEAREST, + magnificationFilter : TextureMagnificationFilter.NEAREST + }) + }); + } + + function updateTexture(batchTable) { + var dimensions = batchTable._textureDimensions; + batchTable._texture.copyFrom({ + width : dimensions.x, + height : dimensions.y, + arrayBufferView : batchTable._batchValues + }); + } + + BatchTable.prototype.update = function(frameState) { + var context = frameState.context; + if (this._pixelDatatype === PixelDatatype.FLOAT && !context.floatingPointTexture) { + // TODO: We could probably pack the floats to RGBA unsigned bytes but that would add a lot CPU and memory overhead. + throw new RuntimeError('The floating point texture extension is required but not supported.'); + } + + if (defined(this._texture) && !this._batchValuesDirty) { + return; + } + + this._batchValuesDirty = false; + + if (!defined(this._texture)) { + createTexture(this, context); + } + updateTexture(this); + }; + + BatchTable.prototype.getUniformMapCallback = function() { + var that = this; + return function(uniformMap) { + var batchUniformMap = { + batchTexture : function() { + return that._texture; + }, + batchTextureDimensions : function() { + return that._textureDimensions; + }, + batchTextureStep : function() { + return that._textureStep; + } + }; + + return combine(uniformMap, batchUniformMap); + }; + }; + + function getGlslComputeSt(batchTable) { + var numberOfAttributes = batchTable._attributes.length; + + // GLSL batchId is zero-based: [0, numberOfInstances - 1] + if (batchTable._textureDimensions.y === 1) { + return 'uniform vec4 batchTextureStep; \n' + + 'vec2 computeSt(float batchId) \n' + + '{ \n' + + ' float stepX = batchTextureStep.x; \n' + + ' float centerX = batchTextureStep.y; \n' + + ' float numberOfAttributes = float('+ numberOfAttributes + '); \n' + + ' return vec2(centerX + (batchId * numberOfAttributes * stepX), 0.5); \n' + + '} \n'; + } + + return 'uniform vec4 batchTextureStep; \n' + + 'uniform vec2 batchTextureDimensions; \n' + + 'vec2 computeSt(float batchId) \n' + + '{ \n' + + ' float stepX = batchTextureStep.x; \n' + + ' float centerX = batchTextureStep.y; \n' + + ' float stepY = batchTextureStep.z; \n' + + ' float centerY = batchTextureStep.w; \n' + + ' float numberOfAttributes = float('+ numberOfAttributes + '); \n' + + ' float xId = mod(batchId * numberOfAttributes, batchTextureDimensions.x); \n' + + ' float yId = floor(batchId * numberOfAttributes / batchTextureDimensions.x); \n' + + ' return vec2(centerX + (xId * stepX), 1.0 - (centerY + (yId * stepY))); \n' + + '} \n'; + } + + function getComponentType(componentsPerAttribute) { + if (componentsPerAttribute === 1) { + return 'float'; + } + return 'vec' + componentsPerAttribute; + } + + function getComponentSwizzle(componentsPerAttribute) { + if (componentsPerAttribute === 1) { + return '.x'; + } else if (componentsPerAttribute === 2) { + return '.xy'; + } else if (componentsPerAttribute === 3) { + return '.xyz'; + } + return ''; + } + + function getGlslAttributeFunction(batchTable, attributeIndex) { + var attributes = batchTable._attributes; + var attribute = attributes[attributeIndex]; + var componentsPerAttribute = attribute.componentsPerAttribute; + var functionName = attribute.functionName; + var functionReturnType = getComponentType(componentsPerAttribute); + var functionReturnValue = getComponentSwizzle(componentsPerAttribute); + + return functionReturnType + ' ' + functionName + '(float batchId) \n' + + '{ \n' + + ' vec2 st = computeSt(batchId); \n' + + ' st.x += batchTextureStep.x * float(' + attributeIndex + '); \n' + + ' vec4 value = texture2D(batchTexture, st); \n' + + ' return value' + functionReturnValue + '; \n' + + '} \n'; + } + + BatchTable.prototype.getVertexShaderCallback = function() { + var batchTableShader = 'uniform sampler2D batchTexture; \n'; + batchTableShader += getGlslComputeSt(this) + '\n'; + + var attributes = this._attributes; + var length = attributes.length; + for (var i = 0; i < length; ++i) { + batchTableShader += getGlslAttributeFunction(this, i); + } + + return function(source) { + var mainIndex = source.indexOf('void main'); + var beforeMain = source.substring(0, mainIndex); + var afterMain = source.substring(mainIndex); + return beforeMain + '\n' + batchTableShader + '\n' + afterMain; + }; + }; + + BatchTable.prototype.isDestroyed = function() { + return false; + }; + + BatchTable.prototype.destroy = function() { + this._texture = this._texture && this._texture.destroy(); + return destroyObject(this); + }; + + return BatchTable; +}); \ No newline at end of file diff --git a/Source/Scene/Polyline.js b/Source/Scene/Polyline.js index 7e2032296b99..3e9e747429a2 100644 --- a/Source/Scene/Polyline.js +++ b/Source/Scene/Polyline.js @@ -93,9 +93,9 @@ define([ this._boundingVolume2D = new BoundingSphere(); // modified in PolylineCollection } - var SHOW_INDEX = Polyline.SHOW_INDEX = 0; - var WIDTH_INDEX = Polyline.WIDTH_INDEX = 1; - var POSITION_INDEX = Polyline.POSITION_INDEX = 2; + var POSITION_INDEX = Polyline.POSITION_INDEX = 0; + var SHOW_INDEX = Polyline.SHOW_INDEX = 1; + var WIDTH_INDEX = Polyline.WIDTH_INDEX = 2; var MATERIAL_INDEX = Polyline.MATERIAL_INDEX = 3; var POSITION_SIZE_INDEX = Polyline.POSITION_SIZE_INDEX = 4; var NUMBER_OF_PROPERTIES = Polyline.NUMBER_OF_PROPERTIES = 5; diff --git a/Source/Scene/PolylineCollection.js b/Source/Scene/PolylineCollection.js index b6efa5504bbc..42fcca12ce0d 100644 --- a/Source/Scene/PolylineCollection.js +++ b/Source/Scene/PolylineCollection.js @@ -1,6 +1,7 @@ /*global define*/ define([ '../Core/BoundingSphere', + '../Core/Cartesian2', '../Core/Cartesian3', '../Core/Cartesian4', '../Core/Cartographic', @@ -27,6 +28,7 @@ define([ '../Shaders/PolylineCommon', '../Shaders/PolylineFS', '../Shaders/PolylineVS', + './BatchTable', './BlendingState', './Material', './Pass', @@ -34,6 +36,7 @@ define([ './SceneMode' ], function( BoundingSphere, + Cartesian2, Cartesian3, Cartesian4, Cartographic, @@ -60,6 +63,7 @@ define([ PolylineCommon, PolylineFS, PolylineVS, + BatchTable, BlendingState, Material, Pass, @@ -77,7 +81,7 @@ define([ var NUMBER_OF_PROPERTIES = Polyline.NUMBER_OF_PROPERTIES; var attributeLocations = { - texCoordExpandWidthAndShow : 0, + texCoordAndExpand : 0, position3DHigh : 1, position3DLow : 2, position2DHigh : 3, @@ -90,7 +94,7 @@ define([ nextPosition3DLow : 10, nextPosition2DHigh : 11, nextPosition2DLow : 12, - pickColor : 13 + batchTableIndex : 13 }; /** @@ -184,11 +188,7 @@ define([ this._polylineBuckets = {}; // The buffer usage for each attribute is determined based on the usage of the attribute over time. - this._buffersUsage = [ - {bufferUsage: BufferUsage.STATIC_DRAW, frameCount:0}, // SHOW_INDEX - {bufferUsage: BufferUsage.STATIC_DRAW, frameCount:0}, // WIDTH_INDEX - {bufferUsage: BufferUsage.STATIC_DRAW, frameCount:0} // POSITION_INDEX - ]; + this._buffersUsage = [{bufferUsage: BufferUsage.STATIC_DRAW, frameCount:0}]; // POSITION_INDEX this._mode = undefined; @@ -197,6 +197,9 @@ define([ this._positionBuffer = undefined; this._pickColorBuffer = undefined; this._texCoordExpandWidthAndShowBuffer = undefined; + + this._batchTable = undefined; + this._createBatchTable = false; } defineProperties(PolylineCollection.prototype, { @@ -248,6 +251,7 @@ define([ p._index = this._polylines.length; this._polylines.push(p); this._createVertexArray = true; + this._createBatchTable = true; return p; }; @@ -280,6 +284,7 @@ define([ this._polylines[polyline._index] = undefined; // Removed later this._polylinesRemoved = true; this._createVertexArray = true; + this._createBatchTable = true; if (defined(polyline._bucket)) { var bucket = polyline._bucket; bucket.shaderProgram = bucket.shaderProgram && bucket.shaderProgram.destroy(); @@ -369,6 +374,25 @@ define([ return this._polylines[index]; }; + function createBatchTable(collection, context) { + if (defined(collection._batchTable)) { + collection._batchTable.destroy(); + } + + var attributes = [{ + functionName : 'batchTable_getWidthAndShow', + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 2 + }, { + functionName : 'batchTable_getPickColor', + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4, + normalize : true + }]; + + collection._batchTable = new BatchTable(attributes, collection._polylines.length); + } + /** * @private */ @@ -386,6 +410,11 @@ define([ var polyline; var properties = this._propertiesChanged; + if (this._createBatchTable) { + createBatchTable(this, context); + this._createBatchTable = false; + } + if (this._createVertexArray || computeNewBuffersUsage(this)) { createVertexArrays(this, context, projection); } else if (this._polylinesUpdated) { @@ -461,6 +490,8 @@ define([ }); } + this._batchTable.update(frameState); + if (pass.render) { var colorList = this._colorCommands; createCommandLists(this, frameState, colorList, modelMatrix, true); @@ -486,6 +517,9 @@ define([ var vertexArrays = polylineCollection._vertexArrays; var debugShowBoundingVolume = polylineCollection.debugShowBoundingVolume; + var batchTable = polylineCollection._batchTable; + var uniformCallback = batchTable.getUniformMapCallback(); + var length = vertexArrays.length; for ( var m = 0; m < length; ++m) { var va = vertexArrays[m]; @@ -531,7 +565,7 @@ define([ command.pass = translucent ? Pass.TRANSLUCENT : Pass.OPAQUE; command.debugShowBoundingVolume = renderPass ? debugShowBoundingVolume : false; - command.uniformMap = currentMaterial._uniforms; + command.uniformMap = uniformCallback(currentMaterial._uniforms); command.count = count; command.offset = offset; @@ -598,7 +632,7 @@ define([ command.pass = currentMaterial.isTranslucent() ? Pass.TRANSLUCENT : Pass.OPAQUE; command.debugShowBoundingVolume = renderPass ? debugShowBoundingVolume : false; - command.uniformMap = currentMaterial._uniforms; + command.uniformMap = uniformCallback(currentMaterial._uniforms); command.count = count; command.offset = offset; @@ -654,6 +688,8 @@ define([ }; function computeNewBuffersUsage(collection) { + return false; + var buffersUsage = collection._buffersUsage; var usageChanged = false; @@ -695,6 +731,8 @@ define([ var totalIndices = [[]]; var indices = totalIndices[0]; + var batchTable = collection._batchTable; + //used to determine the vertexBuffer offset if the indicesArray goes over 64k. //if it's the same polyline while it goes over 64k, the offset needs to backtrack componentsPerAttribute * componentDatatype bytes //so that the polyline looks contiguous. @@ -709,7 +747,7 @@ define([ for (x in polylineBuckets) { if (polylineBuckets.hasOwnProperty(x)) { bucket = polylineBuckets[x]; - bucket.updateShader(context); + bucket.updateShader(context, batchTable); totalLength += bucket.lengthOfPositions; } } @@ -718,17 +756,18 @@ define([ var mode = collection._mode; var positionArray = new Float32Array(6 * totalLength * 3); - var pickColorArray = new Uint8Array(totalLength * 4); - var texCoordExpandWidthAndShowArray = new Float32Array(totalLength * 4); + var texCoordAndExpandArray = new Float32Array(totalLength * 3); + var batchTableIndexArray = new Float32Array(totalLength); var position3DArray; var positionIndex = 0; var colorIndex = 0; - var texCoordExpandWidthAndShowIndex = 0; + var texCoordAndExpandIndex = 0; + var batchTableIndex = 0; for (x in polylineBuckets) { if (polylineBuckets.hasOwnProperty(x)) { bucket = polylineBuckets[x]; - bucket.write(positionArray, pickColorArray, texCoordExpandWidthAndShowArray, positionIndex, colorIndex, texCoordExpandWidthAndShowIndex, context, projection); + bucket.write(positionArray, texCoordAndExpandArray, batchTableIndexArray, positionIndex, colorIndex, texCoordAndExpandIndex, batchTableIndex, batchTable, context, projection); if (mode === SceneMode.MORPHING) { if (!defined(position3DArray)) { @@ -740,15 +779,15 @@ define([ var bucketLength = bucket.lengthOfPositions; positionIndex += 6 * bucketLength * 3; colorIndex += bucketLength * 4; - texCoordExpandWidthAndShowIndex += bucketLength * 4; + texCoordAndExpandIndex += bucketLength * 3; + batchTableIndex += bucketLength; offset = bucket.updateIndices(totalIndices, vertexBufferOffset, vertexArrayBuckets, offset); } } var positionBufferUsage = collection._buffersUsage[POSITION_INDEX].bufferUsage; - var showBufferUsage = collection._buffersUsage[SHOW_INDEX].bufferUsage; - var widthBufferUsage = collection._buffersUsage[WIDTH_INDEX].bufferUsage; - var texCoordExpandWidthAndShowBufferUsage = (showBufferUsage === BufferUsage.STREAM_DRAW || widthBufferUsage === BufferUsage.STREAM_DRAW) ? BufferUsage.STREAM_DRAW : BufferUsage.STATIC_DRAW; + var texCoordAndExpandBufferUsage = BufferUsage.STATIC_DRAW; + var batchTableIndexBufferUsage = BufferUsage.STATIC_DRAW; collection._positionBuffer = Buffer.createVertexBuffer({ context : context, @@ -763,20 +802,20 @@ define([ usage : positionBufferUsage }); } - collection._pickColorBuffer = Buffer.createVertexBuffer({ + collection._texCoordAndExpandBuffer = Buffer.createVertexBuffer({ context : context, - typedArray : pickColorArray, - usage : BufferUsage.STATIC_DRAW + typedArray : texCoordAndExpandArray, + usage : texCoordAndExpandBufferUsage }); - collection._texCoordExpandWidthAndShowBuffer = Buffer.createVertexBuffer({ + collection._batchTableIndexBuffer = Buffer.createVertexBuffer({ context : context, - typedArray : texCoordExpandWidthAndShowArray, - usage : texCoordExpandWidthAndShowBufferUsage + typedArray : batchTableIndexArray, + usage : batchTableIndexBufferUsage }); - var pickColorSizeInBytes = 4 * Uint8Array.BYTES_PER_ELEMENT; var positionSizeInBytes = 3 * Float32Array.BYTES_PER_ELEMENT; - var texCoordExpandWidthAndShowSizeInBytes = 4 * Float32Array.BYTES_PER_ELEMENT; + var texCoordAndExpandSizeInBytes = 3 * Float32Array.BYTES_PER_ELEMENT; + var batchTableIndexSizeInBytes = 3 * Float32Array.BYTES_PER_ELEMENT; var vbo = 0; var numberOfIndicesArrays = totalIndices.length; @@ -800,8 +839,8 @@ define([ var prevPositionLowOffset = positionSizeInBytes + prevPositionHighOffset; var nextPositionHighOffset = positionSizeInBytes + prevPositionLowOffset; var nextPositionLowOffset = positionSizeInBytes + nextPositionHighOffset; - var vertexPickColorBufferOffset = k * (pickColorSizeInBytes * CesiumMath.SIXTY_FOUR_KILOBYTES) - vbo * pickColorSizeInBytes; - var vertexTexCoordExpandWidthAndShowBufferOffset = k * (texCoordExpandWidthAndShowSizeInBytes * CesiumMath.SIXTY_FOUR_KILOBYTES) - vbo * texCoordExpandWidthAndShowSizeInBytes; + var vertexTexCoordAndExpandBufferOffset = k * (texCoordAndExpandSizeInBytes * CesiumMath.SIXTY_FOUR_KILOBYTES) - vbo * texCoordAndExpandSizeInBytes; + var vertexBatchTableIndexBufferOffset = k * (batchTableIndexSizeInBytes * CesiumMath.SIXTY_FOUR_KILOBYTES) - vbo * batchTableIndexSizeInBytes; var attributes = [{ index : attributeLocations.position3DHigh, @@ -876,18 +915,17 @@ define([ offsetInBytes : nextPositionLowOffset, strideInBytes : 6 * positionSizeInBytes }, { - index : attributeLocations.texCoordExpandWidthAndShow, - componentsPerAttribute : 4, + index : attributeLocations.texCoordAndExpand, + componentsPerAttribute : 3, componentDatatype : ComponentDatatype.FLOAT, - vertexBuffer : collection._texCoordExpandWidthAndShowBuffer, - offsetInBytes : vertexTexCoordExpandWidthAndShowBufferOffset + vertexBuffer : collection._texCoordAndExpandBuffer, + offsetInBytes : vertexTexCoordAndExpandBufferOffset }, { - index : attributeLocations.pickColor, - componentsPerAttribute : 4, - componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - vertexBuffer : collection._pickColorBuffer, - offsetInBytes : vertexPickColorBufferOffset, - normalize : true + index : attributeLocations.batchTableIndex, + componentsPerAttribute : 1, + componentDatatype : ComponentDatatype.FLOAT, + vertexBuffer : collection._batchTableIndexBuffer, + offsetInBytes : vertexBatchTableIndexBufferOffset }]; var buffer3D; @@ -1058,6 +1096,7 @@ define([ this.mode = mode; this.modelMatrix = modelMatrix; } + PolylineBucket.prototype.addPolyline = function(p) { var polylines = this.polylines; polylines.push(p); @@ -1066,13 +1105,14 @@ define([ p._bucket = this; }; - PolylineBucket.prototype.updateShader = function(context) { + PolylineBucket.prototype.updateShader = function(context, batchTable) { if (defined(this.shaderProgram)) { return; } + var vsSource = batchTable.getVertexShaderCallback()(PolylineVS); var vs = new ShaderSource({ - sources : [PolylineCommon, PolylineVS] + sources : [PolylineCommon, vsSource] }); var fs = new ShaderSource({ sources : [this.material.shaderSource, PolylineFS] @@ -1124,7 +1164,7 @@ define([ var scratchWriteNextPosition = new Cartesian3(); var scratchWriteVector = new Cartesian3(); - PolylineBucket.prototype.write = function(positionArray, pickColorArray, texCoordExpandWidthAndShowArray, positionIndex, colorIndex, texCoordExpandWidthAndShowIndex, context, projection) { + PolylineBucket.prototype.write = function(positionArray, texCoordAndExpand, batchTableIndexArray, positionIndex, colorIndex, texCoordAndExpandIndex, batchTableIndex, batchTable, context, projection) { var mode = this.mode; var maxLon = projection.ellipsoid.maximumRadius * CesiumMath.PI; @@ -1134,6 +1174,7 @@ define([ var polyline = polylines[i]; var width = polyline.width; var show = polyline.show && width > 0.0; + var polylineBatchIndex = polyline._index; var segments = this.getSegments(polyline, projection); var positions = segments.positions; var lengths = segments.lengths; @@ -1212,22 +1253,27 @@ define([ EncodedCartesian3.writeElements(scratchWritePrevPosition, positionArray, positionIndex + 6); EncodedCartesian3.writeElements(scratchWriteNextPosition, positionArray, positionIndex + 12); - pickColorArray[colorIndex] = Color.floatToByte(pickColor.red); - pickColorArray[colorIndex + 1] = Color.floatToByte(pickColor.green); - pickColorArray[colorIndex + 2] = Color.floatToByte(pickColor.blue); - pickColorArray[colorIndex + 3] = Color.floatToByte(pickColor.alpha); - var direction = (k - 2 < 0) ? -1.0 : 1.0; - texCoordExpandWidthAndShowArray[texCoordExpandWidthAndShowIndex] = j / (positionsLength - 1); // s tex coord - texCoordExpandWidthAndShowArray[texCoordExpandWidthAndShowIndex + 1] = 2 * (k % 2) - 1; // expand direction - texCoordExpandWidthAndShowArray[texCoordExpandWidthAndShowIndex + 2] = direction * width; - texCoordExpandWidthAndShowArray[texCoordExpandWidthAndShowIndex + 3] = show; + texCoordAndExpand[texCoordAndExpandIndex] = j / (positionsLength - 1); // s tex coord + texCoordAndExpand[texCoordAndExpandIndex + 1] = 2 * (k % 2) - 1; // expand direction + texCoordAndExpand[texCoordAndExpandIndex + 2] = direction; + + batchTableIndexArray[batchTableIndex++] = polylineBatchIndex; positionIndex += 6 * 3; - colorIndex += 4; - texCoordExpandWidthAndShowIndex += 4; + texCoordAndExpandIndex += 3; } } + + // TODO: add support for color from the batch table + var colorCartesian = new Cartesian4(); + colorCartesian.x = Color.floatToByte(pickColor.red); + colorCartesian.y = Color.floatToByte(pickColor.green); + colorCartesian.z = Color.floatToByte(pickColor.blue); + colorCartesian.w = Color.floatToByte(pickColor.alpha); + + batchTable.setEntry(polylineBatchIndex, 0, new Cartesian2(width, show ? 1.0 : 0.0)); + batchTable.setEntry(polylineBatchIndex, 1, colorCartesian); } }; diff --git a/Source/Shaders/PolylineVS.glsl b/Source/Shaders/PolylineVS.glsl index 50c6b9d2e8e3..2aa1d268ece8 100644 --- a/Source/Shaders/PolylineVS.glsl +++ b/Source/Shaders/PolylineVS.glsl @@ -10,8 +10,8 @@ attribute vec3 nextPosition3DHigh; attribute vec3 nextPosition3DLow; attribute vec3 nextPosition2DHigh; attribute vec3 nextPosition2DLow; -attribute vec4 texCoordExpandWidthAndShow; -attribute vec4 pickColor; +attribute vec4 texCoordAndExpand; +attribute float batchTableIndex; varying vec2 v_st; varying float v_width; @@ -19,11 +19,15 @@ varying vec4 czm_pickColor; void main() { - float texCoord = texCoordExpandWidthAndShow.x; - float expandDir = texCoordExpandWidthAndShow.y; - float width = abs(texCoordExpandWidthAndShow.z) + 0.5; - bool usePrev = texCoordExpandWidthAndShow.z < 0.0; - float show = texCoordExpandWidthAndShow.w; + float texCoord = texCoordAndExpand.x; + float expandDir = texCoordAndExpand.y; + bool usePrev = texCoordAndExpand.z < 0.0; + + vec2 widthAndShow = batchTable_getWidthAndShow(batchTableIndex); + float width = widthAndShow.x * 255.0; + float show = widthAndShow.y * 255.0; + + vec4 pickColor = batchTable_getPickColor(batchTableIndex); vec4 p, prev, next; if (czm_morphTime == 1.0) From 74f4417ec3f80c04dba8f4956242a9f8263677bb Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 16 Sep 2016 16:16:29 -0400 Subject: [PATCH 084/191] Add normalize option for unsigned byte data. --- Source/Scene/BatchTable.js | 23 ++++++++++++++++------- Source/Shaders/PolylineVS.glsl | 4 ++-- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/Source/Scene/BatchTable.js b/Source/Scene/BatchTable.js index f402665a4473..ed9ab728b1d8 100644 --- a/Source/Scene/BatchTable.js +++ b/Source/Scene/BatchTable.js @@ -273,13 +273,22 @@ define([ var functionReturnType = getComponentType(componentsPerAttribute); var functionReturnValue = getComponentSwizzle(componentsPerAttribute); - return functionReturnType + ' ' + functionName + '(float batchId) \n' + - '{ \n' + - ' vec2 st = computeSt(batchId); \n' + - ' st.x += batchTextureStep.x * float(' + attributeIndex + '); \n' + - ' vec4 value = texture2D(batchTexture, st); \n' + - ' return value' + functionReturnValue + '; \n' + - '} \n'; + var glslFunction = + functionReturnType + ' ' + functionName + '(float batchId) \n' + + '{ \n' + + ' vec2 st = computeSt(batchId); \n' + + ' st.x += batchTextureStep.x * float(' + attributeIndex + '); \n' + + ' vec4 textureValue = texture2D(batchTexture, st); \n' + + ' ' + functionReturnType + ' value = textureValue' + functionReturnValue + '; \n'; + + if (batchTable._pixelDatatype === PixelDatatype.UNSIGNED_BYTE && !attribute.normalize) { + glslFunction += 'value *= 255.0; \n'; + } + + glslFunction += + ' return value; \n' + + '} \n'; + return glslFunction; } BatchTable.prototype.getVertexShaderCallback = function() { diff --git a/Source/Shaders/PolylineVS.glsl b/Source/Shaders/PolylineVS.glsl index 2aa1d268ece8..18b3749e6dc0 100644 --- a/Source/Shaders/PolylineVS.glsl +++ b/Source/Shaders/PolylineVS.glsl @@ -24,8 +24,8 @@ void main() bool usePrev = texCoordAndExpand.z < 0.0; vec2 widthAndShow = batchTable_getWidthAndShow(batchTableIndex); - float width = widthAndShow.x * 255.0; - float show = widthAndShow.y * 255.0; + float width = widthAndShow.x; + float show = widthAndShow.y; vec4 pickColor = batchTable_getPickColor(batchTableIndex); From 17186638a32a8c87ec0d3c6eaf34294264785d63 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 16 Sep 2016 16:54:13 -0400 Subject: [PATCH 085/191] Properly update changed polyline width of show properties. Fix buffer usage changed code. --- Source/Scene/PolylineCollection.js | 88 ++++++++++++------------------ 1 file changed, 34 insertions(+), 54 deletions(-) diff --git a/Source/Scene/PolylineCollection.js b/Source/Scene/PolylineCollection.js index 42fcca12ce0d..85d63d754304 100644 --- a/Source/Scene/PolylineCollection.js +++ b/Source/Scene/PolylineCollection.js @@ -187,16 +187,16 @@ define([ this._polylines = []; this._polylineBuckets = {}; - // The buffer usage for each attribute is determined based on the usage of the attribute over time. - this._buffersUsage = [{bufferUsage: BufferUsage.STATIC_DRAW, frameCount:0}]; // POSITION_INDEX + // The buffer usage is determined based on the usage of the attribute over time. + this._positionBufferUsage = { bufferUsage : BufferUsage.STATIC_DRAW, frameCount : 0 }; this._mode = undefined; this._polylinesToUpdate = []; this._vertexArrays = []; this._positionBuffer = undefined; - this._pickColorBuffer = undefined; - this._texCoordExpandWidthAndShowBuffer = undefined; + this._texCoordAndExpandBuffer = undefined; + this._batchTableIndexBuffer = undefined; this._batchTable = undefined; this._createBatchTable = false; @@ -374,7 +374,7 @@ define([ return this._polylines[index]; }; - function createBatchTable(collection, context) { + function createBatchTable(collection) { if (defined(collection._batchTable)) { collection._batchTable.destroy(); } @@ -396,7 +396,7 @@ define([ /** * @private */ - PolylineCollection.prototype.update = function(frameState, commandList) { + PolylineCollection.prototype.update = function(frameState) { removePolylines(this); if (this._polylines.length === 0) { @@ -429,7 +429,7 @@ define([ } // if a polyline's positions size changes, we need to recreate the vertex arrays and vertex buffers because the indices will be different. - // if a polyline's material changes, we need to recreate the VAOs and VBOs because they will be batched differenty. + // if a polyline's material changes, we need to recreate the VAOs and VBOs because they will be batched differently. if (properties[POSITION_SIZE_INDEX] || properties[MATERIAL_INDEX]) { createVertexArrays(this, context, projection); } else { @@ -440,17 +440,22 @@ define([ properties = polyline._propertiesChanged; var bucket = polyline._bucket; var index = 0; - for ( var x in polylineBuckets) { + for (var x in polylineBuckets) { if (polylineBuckets.hasOwnProperty(x)) { if (polylineBuckets[x] === bucket) { - if (properties[POSITION_INDEX] || properties[SHOW_INDEX] || properties[WIDTH_INDEX]) { - bucket.writeUpdate(index, polyline, this._positionBuffer, this._texCoordExpandWidthAndShowBuffer, projection); + if (properties[POSITION_INDEX]) { + bucket.writeUpdate(index, polyline, this._positionBuffer, projection); } break; } index += polylineBuckets[x].lengthOfPositions; } } + + if (properties[SHOW_INDEX] || properties[WIDTH_INDEX]) { + this._batchTable.setEntry(polyline._index, 0, new Cartesian2(polyline._width, polyline._show)); + } + polyline._clean(); } } @@ -688,34 +693,28 @@ define([ }; function computeNewBuffersUsage(collection) { - return false; - - var buffersUsage = collection._buffersUsage; var usageChanged = false; - var properties = collection._propertiesChanged; - //subtract 2 from NUMBER_OF_PROPERTIES because we don't care about POSITION_SIZE_INDEX or MATERIAL_INDEX property change. - for ( var k = 0; k < NUMBER_OF_PROPERTIES - 2; ++k) { - var bufferUsage = buffersUsage[k]; - if (properties[k]) { - if (bufferUsage.bufferUsage !== BufferUsage.STREAM_DRAW) { + var bufferUsage = collection._positionBufferUsage; + if (properties[POSITION_INDEX]) { + if (bufferUsage.bufferUsage !== BufferUsage.STREAM_DRAW) { + usageChanged = true; + bufferUsage.bufferUsage = BufferUsage.STREAM_DRAW; + bufferUsage.frameCount = 100; + } else { + bufferUsage.frameCount = 100; + } + } else { + if (bufferUsage.bufferUsage !== BufferUsage.STATIC_DRAW) { + if (bufferUsage.frameCount === 0) { usageChanged = true; - bufferUsage.bufferUsage = BufferUsage.STREAM_DRAW; - bufferUsage.frameCount = 100; + bufferUsage.bufferUsage = BufferUsage.STATIC_DRAW; } else { - bufferUsage.frameCount = 100; - } - } else { - if (bufferUsage.bufferUsage !== BufferUsage.STATIC_DRAW) { - if (bufferUsage.frameCount === 0) { - usageChanged = true; - bufferUsage.bufferUsage = BufferUsage.STATIC_DRAW; - } else { - bufferUsage.frameCount--; - } + bufferUsage.frameCount--; } } } + return usageChanged; } @@ -785,7 +784,7 @@ define([ } } - var positionBufferUsage = collection._buffersUsage[POSITION_INDEX].bufferUsage; + var positionBufferUsage = collection._positionBufferUsage.bufferUsage; var texCoordAndExpandBufferUsage = BufferUsage.STATIC_DRAW; var batchTableIndexBufferUsage = BufferUsage.STATIC_DRAW; @@ -1265,7 +1264,7 @@ define([ } } - // TODO: add support for color from the batch table + // TODO: add support for color from the batch table? var colorCartesian = new Cartesian4(); colorCartesian.x = Color.floatToByte(pickColor.red); colorCartesian.y = Color.floatToByte(pickColor.green); @@ -1500,9 +1499,8 @@ define([ }; var scratchPositionsArray; - var scratchTexCoordArray; - PolylineBucket.prototype.writeUpdate = function(index, polyline, positionBuffer, texCoordExpandWidthAndShowBuffer, projection) { + PolylineBucket.prototype.writeUpdate = function(index, polyline, positionBuffer, projection) { var mode = this.mode; var maxLon = projection.ellipsoid.maximumRadius * CesiumMath.PI; @@ -1511,32 +1509,23 @@ define([ index += this.getPolylineStartIndex(polyline); var positionArray = scratchPositionsArray; - var texCoordExpandWidthAndShowArray = scratchTexCoordArray; - var positionsArrayLength = 6 * positionsLength * 3; if (!defined(positionArray) || positionArray.length < positionsArrayLength) { positionArray = scratchPositionsArray = new Float32Array(positionsArrayLength); - texCoordExpandWidthAndShowArray = scratchTexCoordArray = new Float32Array(positionsLength * 4); } else if (positionArray.length > positionsArrayLength) { positionArray = new Float32Array(positionArray.buffer, 0, positionsArrayLength); - texCoordExpandWidthAndShowArray = new Float32Array(texCoordExpandWidthAndShowArray.buffer, 0, positionsLength * 4); } - var positionIndex = 0; - var texCoordExpandWidthAndShowIndex = 0; - var segments = this.getSegments(polyline, projection); var positions = segments.positions; var lengths = segments.lengths; + var positionIndex = 0; var segmentIndex = 0; var count = 0; var position; - var width = polyline.width; - var show = polyline.show && width > 0.0; - positionsLength = positions.length; for ( var i = 0; i < positionsLength; ++i) { if (i === 0) { @@ -1604,20 +1593,11 @@ define([ EncodedCartesian3.writeElements(scratchWritePosition, positionArray, positionIndex); EncodedCartesian3.writeElements(scratchWritePrevPosition, positionArray, positionIndex + 6); EncodedCartesian3.writeElements(scratchWriteNextPosition, positionArray, positionIndex + 12); - - var direction = (j - 2 < 0) ? -1.0 : 1.0; - texCoordExpandWidthAndShowArray[texCoordExpandWidthAndShowIndex] = i / (positionsLength - 1); // s tex coord - texCoordExpandWidthAndShowArray[texCoordExpandWidthAndShowIndex + 1] = 2 * (j % 2) - 1; // expand direction - texCoordExpandWidthAndShowArray[texCoordExpandWidthAndShowIndex + 2] = direction * width; - texCoordExpandWidthAndShowArray[texCoordExpandWidthAndShowIndex + 3] = show; - positionIndex += 6 * 3; - texCoordExpandWidthAndShowIndex += 4; } } positionBuffer.copyFromArrayView(positionArray, 6 * 3 * Float32Array.BYTES_PER_ELEMENT * index); - texCoordExpandWidthAndShowBuffer.copyFromArrayView(texCoordExpandWidthAndShowArray, 4 * Float32Array.BYTES_PER_ELEMENT * index); } }; From 013409095da08fbccfd56c5a0f154f853a14186b Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 16 Sep 2016 17:11:21 -0400 Subject: [PATCH 086/191] Minor cleanup. --- Source/Scene/PolylineCollection.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Source/Scene/PolylineCollection.js b/Source/Scene/PolylineCollection.js index 85d63d754304..3b73500eaeb8 100644 --- a/Source/Scene/PolylineCollection.js +++ b/Source/Scene/PolylineCollection.js @@ -689,6 +689,7 @@ define([ destroyVertexArrays(this); releaseShaders(this); destroyPolylines(this); + this._batchTable = this._batchTable && this._batchTable.destroy(); return destroyObject(this); }; @@ -1162,6 +1163,8 @@ define([ var scratchWritePrevPosition = new Cartesian3(); var scratchWriteNextPosition = new Cartesian3(); var scratchWriteVector = new Cartesian3(); + var scratchPickColorCartesian = new Cartesian4(); + var scratchWidthShowCartesian = new Cartesian2(); PolylineBucket.prototype.write = function(positionArray, texCoordAndExpand, batchTableIndexArray, positionIndex, colorIndex, texCoordAndExpandIndex, batchTableIndex, batchTable, context, projection) { var mode = this.mode; @@ -1265,13 +1268,17 @@ define([ } // TODO: add support for color from the batch table? - var colorCartesian = new Cartesian4(); + var colorCartesian = scratchPickColorCartesian; colorCartesian.x = Color.floatToByte(pickColor.red); colorCartesian.y = Color.floatToByte(pickColor.green); colorCartesian.z = Color.floatToByte(pickColor.blue); colorCartesian.w = Color.floatToByte(pickColor.alpha); - batchTable.setEntry(polylineBatchIndex, 0, new Cartesian2(width, show ? 1.0 : 0.0)); + var widthShowCartesian = scratchWidthShowCartesian; + widthShowCartesian.x = width; + widthShowCartesian.y = show ? 1.0 : 0.0; + + batchTable.setEntry(polylineBatchIndex, 0, widthShowCartesian); batchTable.setEntry(polylineBatchIndex, 1, colorCartesian); } }; From 66abc5a4a5c683c958a4d5f45bb59cd81d4c0e9b Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 16 Sep 2016 17:26:29 -0400 Subject: [PATCH 087/191] Pack the batch index with the texture coordinates and expand direction attribute which brings polylines down to 13 vertex attributes. Fix failing test. --- Source/Scene/PolylineCollection.js | 66 +++++++++++------------------- Source/Shaders/PolylineVS.glsl | 10 ++--- 2 files changed, 28 insertions(+), 48 deletions(-) diff --git a/Source/Scene/PolylineCollection.js b/Source/Scene/PolylineCollection.js index 3b73500eaeb8..cca1e4d26566 100644 --- a/Source/Scene/PolylineCollection.js +++ b/Source/Scene/PolylineCollection.js @@ -81,7 +81,7 @@ define([ var NUMBER_OF_PROPERTIES = Polyline.NUMBER_OF_PROPERTIES; var attributeLocations = { - texCoordAndExpand : 0, + texCoordExpandAndBatchIndex : 0, position3DHigh : 1, position3DLow : 2, position2DHigh : 3, @@ -93,8 +93,7 @@ define([ nextPosition3DHigh : 9, nextPosition3DLow : 10, nextPosition2DHigh : 11, - nextPosition2DLow : 12, - batchTableIndex : 13 + nextPosition2DLow : 12 }; /** @@ -195,8 +194,7 @@ define([ this._polylinesToUpdate = []; this._vertexArrays = []; this._positionBuffer = undefined; - this._texCoordAndExpandBuffer = undefined; - this._batchTableIndexBuffer = undefined; + this._texCoordExpandAndBatchIndexBuffer = undefined; this._batchTable = undefined; this._createBatchTable = false; @@ -756,18 +754,16 @@ define([ var mode = collection._mode; var positionArray = new Float32Array(6 * totalLength * 3); - var texCoordAndExpandArray = new Float32Array(totalLength * 3); - var batchTableIndexArray = new Float32Array(totalLength); + var texCoordExpandAndBatchIndexArray = new Float32Array(totalLength * 4); var position3DArray; var positionIndex = 0; var colorIndex = 0; - var texCoordAndExpandIndex = 0; - var batchTableIndex = 0; + var texCoordExpandAndBatchIndexIndex = 0; for (x in polylineBuckets) { if (polylineBuckets.hasOwnProperty(x)) { bucket = polylineBuckets[x]; - bucket.write(positionArray, texCoordAndExpandArray, batchTableIndexArray, positionIndex, colorIndex, texCoordAndExpandIndex, batchTableIndex, batchTable, context, projection); + bucket.write(positionArray, texCoordExpandAndBatchIndexArray, positionIndex, colorIndex, texCoordExpandAndBatchIndexIndex, batchTable, context, projection); if (mode === SceneMode.MORPHING) { if (!defined(position3DArray)) { @@ -779,15 +775,13 @@ define([ var bucketLength = bucket.lengthOfPositions; positionIndex += 6 * bucketLength * 3; colorIndex += bucketLength * 4; - texCoordAndExpandIndex += bucketLength * 3; - batchTableIndex += bucketLength; + texCoordExpandAndBatchIndexIndex += bucketLength * 4; offset = bucket.updateIndices(totalIndices, vertexBufferOffset, vertexArrayBuckets, offset); } } var positionBufferUsage = collection._positionBufferUsage.bufferUsage; - var texCoordAndExpandBufferUsage = BufferUsage.STATIC_DRAW; - var batchTableIndexBufferUsage = BufferUsage.STATIC_DRAW; + var texCoordExpandAndBatchIndexBufferUsage = BufferUsage.STATIC_DRAW; collection._positionBuffer = Buffer.createVertexBuffer({ context : context, @@ -802,20 +796,14 @@ define([ usage : positionBufferUsage }); } - collection._texCoordAndExpandBuffer = Buffer.createVertexBuffer({ + collection._texCoordExpandAndBatchIndexBuffer = Buffer.createVertexBuffer({ context : context, - typedArray : texCoordAndExpandArray, - usage : texCoordAndExpandBufferUsage - }); - collection._batchTableIndexBuffer = Buffer.createVertexBuffer({ - context : context, - typedArray : batchTableIndexArray, - usage : batchTableIndexBufferUsage + typedArray : texCoordExpandAndBatchIndexArray, + usage : texCoordExpandAndBatchIndexBufferUsage }); var positionSizeInBytes = 3 * Float32Array.BYTES_PER_ELEMENT; - var texCoordAndExpandSizeInBytes = 3 * Float32Array.BYTES_PER_ELEMENT; - var batchTableIndexSizeInBytes = 3 * Float32Array.BYTES_PER_ELEMENT; + var texCoordExpandAndBatchIndexSizeInBytes = 4 * Float32Array.BYTES_PER_ELEMENT; var vbo = 0; var numberOfIndicesArrays = totalIndices.length; @@ -839,8 +827,7 @@ define([ var prevPositionLowOffset = positionSizeInBytes + prevPositionHighOffset; var nextPositionHighOffset = positionSizeInBytes + prevPositionLowOffset; var nextPositionLowOffset = positionSizeInBytes + nextPositionHighOffset; - var vertexTexCoordAndExpandBufferOffset = k * (texCoordAndExpandSizeInBytes * CesiumMath.SIXTY_FOUR_KILOBYTES) - vbo * texCoordAndExpandSizeInBytes; - var vertexBatchTableIndexBufferOffset = k * (batchTableIndexSizeInBytes * CesiumMath.SIXTY_FOUR_KILOBYTES) - vbo * batchTableIndexSizeInBytes; + var vertexTexCoordExpandAndBatchIndexBufferOffset = k * (texCoordExpandAndBatchIndexSizeInBytes * CesiumMath.SIXTY_FOUR_KILOBYTES) - vbo * texCoordExpandAndBatchIndexSizeInBytes; var attributes = [{ index : attributeLocations.position3DHigh, @@ -915,17 +902,11 @@ define([ offsetInBytes : nextPositionLowOffset, strideInBytes : 6 * positionSizeInBytes }, { - index : attributeLocations.texCoordAndExpand, - componentsPerAttribute : 3, - componentDatatype : ComponentDatatype.FLOAT, - vertexBuffer : collection._texCoordAndExpandBuffer, - offsetInBytes : vertexTexCoordAndExpandBufferOffset - }, { - index : attributeLocations.batchTableIndex, - componentsPerAttribute : 1, + index : attributeLocations.texCoordExpandAndBatchIndex, + componentsPerAttribute : 4, componentDatatype : ComponentDatatype.FLOAT, - vertexBuffer : collection._batchTableIndexBuffer, - offsetInBytes : vertexBatchTableIndexBufferOffset + vertexBuffer : collection._texCoordExpandAndBatchIndexBuffer, + offsetInBytes : vertexTexCoordExpandAndBatchIndexBufferOffset }]; var buffer3D; @@ -1166,7 +1147,7 @@ define([ var scratchPickColorCartesian = new Cartesian4(); var scratchWidthShowCartesian = new Cartesian2(); - PolylineBucket.prototype.write = function(positionArray, texCoordAndExpand, batchTableIndexArray, positionIndex, colorIndex, texCoordAndExpandIndex, batchTableIndex, batchTable, context, projection) { + PolylineBucket.prototype.write = function(positionArray, texCoordExpandAndBatchIndexArray, positionIndex, colorIndex, texCoordExpandAndBatchIndexIndex, batchTable, context, projection) { var mode = this.mode; var maxLon = projection.ellipsoid.maximumRadius * CesiumMath.PI; @@ -1256,14 +1237,13 @@ define([ EncodedCartesian3.writeElements(scratchWriteNextPosition, positionArray, positionIndex + 12); var direction = (k - 2 < 0) ? -1.0 : 1.0; - texCoordAndExpand[texCoordAndExpandIndex] = j / (positionsLength - 1); // s tex coord - texCoordAndExpand[texCoordAndExpandIndex + 1] = 2 * (k % 2) - 1; // expand direction - texCoordAndExpand[texCoordAndExpandIndex + 2] = direction; - - batchTableIndexArray[batchTableIndex++] = polylineBatchIndex; + texCoordExpandAndBatchIndexArray[texCoordExpandAndBatchIndexIndex] = j / (positionsLength - 1); // s tex coord + texCoordExpandAndBatchIndexArray[texCoordExpandAndBatchIndexIndex + 1] = 2 * (k % 2) - 1; // expand direction + texCoordExpandAndBatchIndexArray[texCoordExpandAndBatchIndexIndex + 2] = direction; + texCoordExpandAndBatchIndexArray[texCoordExpandAndBatchIndexIndex + 3] = polylineBatchIndex; positionIndex += 6 * 3; - texCoordAndExpandIndex += 3; + texCoordExpandAndBatchIndexIndex += 4; } } diff --git a/Source/Shaders/PolylineVS.glsl b/Source/Shaders/PolylineVS.glsl index 18b3749e6dc0..67b0bfffb2da 100644 --- a/Source/Shaders/PolylineVS.glsl +++ b/Source/Shaders/PolylineVS.glsl @@ -10,8 +10,7 @@ attribute vec3 nextPosition3DHigh; attribute vec3 nextPosition3DLow; attribute vec3 nextPosition2DHigh; attribute vec3 nextPosition2DLow; -attribute vec4 texCoordAndExpand; -attribute float batchTableIndex; +attribute vec4 texCoordExpandAndBatchIndex; varying vec2 v_st; varying float v_width; @@ -19,9 +18,10 @@ varying vec4 czm_pickColor; void main() { - float texCoord = texCoordAndExpand.x; - float expandDir = texCoordAndExpand.y; - bool usePrev = texCoordAndExpand.z < 0.0; + float texCoord = texCoordExpandAndBatchIndex.x; + float expandDir = texCoordExpandAndBatchIndex.y; + bool usePrev = texCoordExpandAndBatchIndex.z < 0.0; + float batchTableIndex = texCoordExpandAndBatchIndex.w; vec2 widthAndShow = batchTable_getWidthAndShow(batchTableIndex); float width = widthAndShow.x; From ea6422cfbf35800c11cd1a54de9b4e5fcd08880f Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Fri, 16 Sep 2016 17:34:23 -0400 Subject: [PATCH 088/191] Fix width with pixel size 1. --- Source/Shaders/PolylineVS.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Shaders/PolylineVS.glsl b/Source/Shaders/PolylineVS.glsl index 67b0bfffb2da..06eaf8caf73f 100644 --- a/Source/Shaders/PolylineVS.glsl +++ b/Source/Shaders/PolylineVS.glsl @@ -24,7 +24,7 @@ void main() float batchTableIndex = texCoordExpandAndBatchIndex.w; vec2 widthAndShow = batchTable_getWidthAndShow(batchTableIndex); - float width = widthAndShow.x; + float width = widthAndShow.x + 0.5; float show = widthAndShow.y; vec4 pickColor = batchTable_getPickColor(batchTableIndex); From 42cabaa1207e8a5ac34e4831fb98cdcfd8bb931c Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Sat, 17 Sep 2016 13:03:57 -0400 Subject: [PATCH 089/191] chore(package): update requirejs to version 2.3.2 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4dfb23faa8d6..c243c8bc66b1 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "email": "cesium-dev@googlegroups.com" }, "dependencies": { - "requirejs": "2.3.1" + "requirejs": "2.3.2" }, "devDependencies": { "almond": "0.3.3", From ca37d97e30f4c410f6a828eb95ccf2d3752fa60d Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Sat, 17 Sep 2016 18:44:52 -0400 Subject: [PATCH 090/191] chore(package): update request to version 2.75.0 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4dfb23faa8d6..1a16f47b825e 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "karma-spec-reporter": "0.0.26", "mime": "1.3.4", "mkdirp": "0.5.1", - "request": "2.74.0", + "request": "2.75.0", "rimraf": "2.5.3", "strip-comments": "0.3.2", "yargs": "5.0.0" From b671ee9d5c5cf23c98e90240d9b32c82d5d6b337 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Sun, 18 Sep 2016 19:43:59 -0400 Subject: [PATCH 091/191] chore(package): update aws-sdk to version 2.6.3 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 11c9d2e01ef8..d2f1806a0325 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ }, "devDependencies": { "almond": "0.3.3", - "aws-sdk": "2.5.6", + "aws-sdk": "2.6.3", "bluebird": "3.4.6", "compressible": "2.0.8", "compression": "1.6.2", From 72961f8c93ef59a1ba8b3ba44ed6091e3bc5b81c Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Sun, 18 Sep 2016 19:48:10 -0400 Subject: [PATCH 092/191] chore(package): update jsdoc to version 3.4.1 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d2f1806a0325..767fc48aede7 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "gulp-replace": "0.5.4", "gulp-zip": "3.0.2", "jasmine-core": "2.4.1", - "jsdoc": "3.4.0", + "jsdoc": "3.4.1", "jshint": "2.9.3", "jshint-stylish": "2.2.1", "karma": "1.2.0", From 8caced2ba103e1d32b60fcbcb941a78277c4c5c8 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Sun, 18 Sep 2016 19:48:10 -0400 Subject: [PATCH 093/191] chore(package): update karma to version 1.3.0 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d2f1806a0325..7fdb7a2c5545 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "jsdoc": "3.4.0", "jshint": "2.9.3", "jshint-stylish": "2.2.1", - "karma": "1.2.0", + "karma": "1.3.0", "karma-chrome-launcher": "2.0.0", "karma-detect-browsers": "2.1.0", "karma-electron-launcher": "0.1.0", From f606ef60bcbb7615c423f545bc5bca3526408817 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Sun, 18 Sep 2016 19:48:10 -0400 Subject: [PATCH 094/191] chore(package): update electron-prebuilt to version 1.4.0 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d2f1806a0325..4dc3e75743da 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "bluebird": "3.4.6", "compressible": "2.0.8", "compression": "1.6.2", - "electron-prebuilt": "1.3.5", + "electron-prebuilt": "1.4.0", "event-stream": "3.3.4", "express": "4.14.0", "globby": "6.0.0", From 4da75d8594ef2dd67a0d3de233d2bc2060560793 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Sun, 18 Sep 2016 19:48:10 -0400 Subject: [PATCH 095/191] chore(package): update karma-requirejs to version 1.1.0 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d2f1806a0325..5b3164a2a48d 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "karma-firefox-launcher": "1.0.0", "karma-ie-launcher": "1.0.0", "karma-jasmine": "1.0.2", - "karma-requirejs": "1.0.0", + "karma-requirejs": "1.1.0", "karma-safari-launcher": "1.0.0", "karma-spec-reporter": "0.0.26", "mime": "1.3.4", From 491fe3dc566619dc85e45ce13e1217cf2dd9f8c8 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Tue, 13 Sep 2016 15:44:29 -0400 Subject: [PATCH 096/191] Draw planes for debug camera --- Source/Scene/DebugCameraPrimitive.js | 60 +++++++++++++++++++++------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/Source/Scene/DebugCameraPrimitive.js b/Source/Scene/DebugCameraPrimitive.js index f26aae3aaf01..12df3e1ddb1b 100644 --- a/Source/Scene/DebugCameraPrimitive.js +++ b/Source/Scene/DebugCameraPrimitive.js @@ -90,7 +90,8 @@ define([ this.id = options.id; this._id = undefined; - this._primitive = undefined; + this._outlinePrimitive = undefined; + this._planesPrimitive = undefined; } var frustumCornersNDC = new Array(8); @@ -109,6 +110,8 @@ define([ scratchFrustumCorners[i] = new Cartesian4(); } + var scratchColor = new Color(); + /** * @private */ @@ -119,10 +122,11 @@ define([ if (this._updateOnChange) { // Recreate the primitive every frame - this._primitive = this._primitive && this._primitive.destroy(); + this._outlinePrimitive = this._outlinePrimitive && this._outlinePrimitive.destroy(); + this._planesPrimitive = this._planesPrimitive && this._planesPrimitive.destroy(); } - if (!defined(this._primitive)) { + if (!defined(this._outlinePrimitive)) { var view = this._camera.viewMatrix; var projection = this._camera.frustum.projectionMatrix; var viewProjection = Matrix4.multiply(projection, view, scratchMatrix); @@ -138,6 +142,8 @@ define([ positions[i * 3 + 2] = corner.z; } + var boundingSphere = new BoundingSphere.fromVertices(positions); + var attributes = new GeometryAttributes(); attributes.position = new GeometryAttribute({ componentDatatype : ComponentDatatype.DOUBLE, @@ -145,17 +151,17 @@ define([ values : positions }); - var indices = new Uint16Array([0,1,1,2,2,3,3,0,0,4,4,7,7,3,7,6,6,2,2,1,1,5,5,4,5,6]); - var geometry = new Geometry({ - attributes : attributes, - indices : indices, - primitiveType : PrimitiveType.LINES, - boundingSphere : new BoundingSphere.fromVertices(positions) - }); + // Create the outline primitive + var outlineIndices = new Uint16Array([0,1,1,2,2,3,3,0,0,4,4,7,7,3,7,6,6,2,2,1,1,5,5,4,5,6]); - this._primitive = new Primitive({ + this._outlinePrimitive = new Primitive({ geometryInstances : new GeometryInstance({ - geometry : geometry, + geometry : { + attributes : attributes, + indices : outlineIndices, + primitiveType : PrimitiveType.LINES, + boundingSphere : boundingSphere + }, attributes : { color : ColorGeometryInstanceAttribute.fromColor(this._color) }, @@ -168,9 +174,34 @@ define([ }), asynchronous : false }); + + // Create the planes primitive + var planesIndices = new Uint16Array([4,5,6,4,6,7,5,1,2,5,2,6,7,6,2,7,2,3,0,1,5,0,5,4,0,4,7,0,7,3,1,0,3,1,3,2]); + + this._planesPrimitive = new Primitive({ + geometryInstances : new GeometryInstance({ + geometry : { + attributes : attributes, + indices : planesIndices, + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : boundingSphere + }, + attributes : { + color : ColorGeometryInstanceAttribute.fromColor(Color.fromAlpha(this._color, 0.1, scratchColor)) + }, + id : this.id, + pickPrimitive : this + }), + appearance : new PerInstanceColorAppearance({ + translucent : true, + flat : true + }), + asynchronous : false + }); } - this._primitive.update(frameState); + this._outlinePrimitive.update(frameState); + this._planesPrimitive.update(frameState); }; /** @@ -207,7 +238,8 @@ define([ * @see DebugCameraPrimitive#isDestroyed */ DebugCameraPrimitive.prototype.destroy = function() { - this._primitive = this._primitive && this._primitive.destroy(); + this._outlinePrimitive = this._outlinePrimitive && this._outlinePrimitive.destroy(); + this._planesPrimitive = this._planesPrimitive && this._planesPrimitive.destroy(); return destroyObject(this); }; From 25e39ea0391c8d4bab8e105864e7b3739b8a93ad Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Mon, 19 Sep 2016 13:18:46 +1000 Subject: [PATCH 097/191] Remove default gamma correction for Bing Maps. This used to look good, but these days Bing Maps aerial imagery looks much better without the gamma correction. --- Source/Scene/BingMapsImageryProvider.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Source/Scene/BingMapsImageryProvider.js b/Source/Scene/BingMapsImageryProvider.js index cf98c7a7be1d..fb2ea3096e40 100644 --- a/Source/Scene/BingMapsImageryProvider.js +++ b/Source/Scene/BingMapsImageryProvider.js @@ -117,17 +117,13 @@ define([ /** * The default {@link ImageryLayer#gamma} to use for imagery layers created for this provider. - * By default, this is set to 1.3 for the "aerial" and "aerial with labels" map styles and 1.0 for - * all others. Changing this value after creating an {@link ImageryLayer} for this provider will have + * Changing this value after creating an {@link ImageryLayer} for this provider will have * no effect. Instead, set the layer's {@link ImageryLayer#gamma} property. * * @type {Number} * @default 1.0 */ this.defaultGamma = 1.0; - if (this._mapStyle === BingMapsStyle.AERIAL || this._mapStyle === BingMapsStyle.AERIAL_WITH_LABELS) { - this.defaultGamma = 1.3; - } this._tilingScheme = new WebMercatorTilingScheme({ numberOfLevelZeroTilesX : 2, From 75b58fbcbc80780f230892dcb15a0be4ffb1636f Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Mon, 19 Sep 2016 13:22:52 +1000 Subject: [PATCH 098/191] Update CHANGES.md. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index c796e5d85259..97d99752bf35 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,7 @@ Change Log * Fixed billboard rotation when sized in meters. [#3979](https://github.com/AnalyticalGraphicsInc/cesium/issues/3979) * Added `DebugCameraPrimitive` to visualize the view frustum of a camera. * Fixed touch events for the timeline [#4305](https://github.com/AnalyticalGraphicsInc/cesium/pull/4305) +* Removed the default gamma correction for Bing Maps aerial imagery, because we no longer think it is an improvement in current versions of the tiles. To restore the previous look, set the `defaultGamma` property of your `BingMapsImageryProvider` instance to 1.3. ### 1.25 - 2016-09-01 From eb06803c85d8f593148e4f7b0db2dd7513c4ae69 Mon Sep 17 00:00:00 2001 From: Chris Cooper Date: Mon, 19 Sep 2016 15:42:33 +1000 Subject: [PATCH 099/191] change clamping based on review --- Source/Core/HeightmapTerrainData.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/HeightmapTerrainData.js b/Source/Core/HeightmapTerrainData.js index aeb3bf042cd2..4079c054ca14 100644 --- a/Source/Core/HeightmapTerrainData.js +++ b/Source/Core/HeightmapTerrainData.js @@ -89,7 +89,7 @@ define([ * childTileMask : childTileMask, * waterMask : waterMask * }); - * + * * @see TerrainData * @see QuantizedMeshTerrainData */ @@ -350,7 +350,7 @@ define([ for (var i = 0; i < width; ++i) { var longitude = CesiumMath.lerp(destinationRectangle.west, destinationRectangle.east, i / (width - 1)); var heightSample = interpolateMeshHeight(buffer, encoding, heightOffset, heightScale, skirtHeight, sourceRectangle, width, height, longitude, latitude, exaggeration); - setHeight(heights, elementsPerHeight, elementMultiplier, divisor, stride, isBigEndian, j * width + i, Math.max(heightSample, 0)); + setHeight(heights, elementsPerHeight, elementMultiplier, divisor, stride, isBigEndian, j * width + i, heightSample); } } @@ -536,7 +536,7 @@ define([ divisor /= elementMultiplier; } } - heights[index + i] = height; + heights[index + i] = Math.max(0, height); } return HeightmapTerrainData; From 30eb4effcf3c284e272ef96f03a9bbb498d8327f Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Mon, 19 Sep 2016 16:58:17 +1000 Subject: [PATCH 100/191] Fix off by one error in compressing/decompressing texture coordinates. --- Source/Core/AttributeCompression.js | 22 ++++++++++--------- .../decompressTextureCoordinates.glsl | 5 +++-- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Source/Core/AttributeCompression.js b/Source/Core/AttributeCompression.js index f4a41c5da943..d5e6973d29cf 100644 --- a/Source/Core/AttributeCompression.js +++ b/Source/Core/AttributeCompression.js @@ -75,9 +75,9 @@ define([ * @param {Cartesian3} vector The normalized vector to be compressed into 2 byte 'oct' encoding. * @param {Cartesian2} result The 2 byte oct-encoded unit length vector. * @returns {Cartesian2} The 2 byte oct-encoded unit length vector. - * + * * @exception {DeveloperError} vector must be normalized. - * + * * @see AttributeCompression.octEncodeInRange * @see AttributeCompression.octDecode */ @@ -124,14 +124,14 @@ define([ /** * Decodes a unit-length vector in 2 byte 'oct' encoding to a normalized 3-component vector. - * + * * @param {Number} x The x component of the oct-encoded unit length vector. * @param {Number} y The y component of the oct-encoded unit length vector. * @param {Cartesian3} result The decoded and normalized vector. * @returns {Cartesian3} The decoded and normalized vector. - * + * * @exception {DeveloperError} x and y must be an unsigned normalized integer between 0 and 255. - * + * * @see AttributeCompression.octDecodeInRange */ AttributeCompression.octDecode = function(x, y, result) { @@ -268,7 +268,7 @@ define([ /** * Pack texture coordinates into a single float. The texture coordinates will only preserve 12 bits of precision. * - * @param {Cartesian2} textureCoordinates The texture coordinates to compress + * @param {Cartesian2} textureCoordinates The texture coordinates to compress. Both coordinates must be in the range 0.0-1.0. * @returns {Number} The packed texture coordinates. * */ @@ -279,8 +279,9 @@ define([ } //>>includeEnd('debug'); - var x = textureCoordinates.x === 1.0 ? 4095.0 : (textureCoordinates.x * 4096.0) | 0; - var y = textureCoordinates.y === 1.0 ? 4095.0 : (textureCoordinates.y * 4096.0) | 0; + // Move x and y to the range 0-4095; + var x = (textureCoordinates.x * 4095.0) | 0; + var y = (textureCoordinates.y * 4095.0) | 0; return 4096.0 * x + y; }; @@ -303,8 +304,9 @@ define([ //>>includeEnd('debug'); var temp = compressed / 4096.0; - result.x = Math.floor(temp) / 4096.0; - result.y = temp - Math.floor(temp); + var xZeroTo4095 = Math.floor(temp); + result.x = xZeroTo4095 / 4095.0; + result.y = (compressed - xZeroTo4095 * 4096) / 4095; return result; }; diff --git a/Source/Shaders/Builtin/Functions/decompressTextureCoordinates.glsl b/Source/Shaders/Builtin/Functions/decompressTextureCoordinates.glsl index c91a5e87473c..fa2a6814382c 100644 --- a/Source/Shaders/Builtin/Functions/decompressTextureCoordinates.glsl +++ b/Source/Shaders/Builtin/Functions/decompressTextureCoordinates.glsl @@ -10,7 +10,8 @@ vec2 czm_decompressTextureCoordinates(float encoded) { float temp = encoded / 4096.0; - float stx = floor(temp) / 4096.0; - float sty = temp - floor(temp); + float xZeroTo4095 = floor(temp); + float stx = xZeroTo4095 / 4095.0; + float sty = (encoded - xZeroTo4095 * 4096.0) / 4095.0; return vec2(stx, sty); } From 28e12792d5b641dd80c74e727c30ef7124c67b21 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Mon, 19 Sep 2016 09:59:41 -0400 Subject: [PATCH 101/191] chore(package): update jasmine-core to version 2.5.2 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2990110ecd8c..441ccced29f6 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "gulp-rename": "1.2.2", "gulp-replace": "0.5.4", "gulp-zip": "3.0.2", - "jasmine-core": "2.4.1", + "jasmine-core": "2.5.2", "jsdoc": "3.4.1", "jshint": "2.9.3", "jshint-stylish": "2.2.1", From a6b81784e8f35232fee6dff8313e44b6a79289c3 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 19 Sep 2016 15:12:32 -0400 Subject: [PATCH 102/191] Add batch table tests. --- Source/Scene/BatchTable.js | 19 +++ Specs/Scene/BatchTableSpec.js | 211 ++++++++++++++++++++++++++++++++++ 2 files changed, 230 insertions(+) create mode 100644 Specs/Scene/BatchTableSpec.js diff --git a/Source/Scene/BatchTable.js b/Source/Scene/BatchTable.js index ed9ab728b1d8..fd5650bfd9f2 100644 --- a/Source/Scene/BatchTable.js +++ b/Source/Scene/BatchTable.js @@ -6,6 +6,7 @@ define([ '../Core/combine', '../Core/ComponentDatatype', '../Core/defined', + '../Core/defineProperties', '../Core/destroyObject', '../Core/DeveloperError', '../Core/PixelFormat', @@ -23,6 +24,7 @@ define([ combine, ComponentDatatype, defined, + defineProperties, destroyObject, DeveloperError, PixelFormat, @@ -72,6 +74,20 @@ define([ this._batchValuesDirty = false; } + defineProperties(BatchTable.prototype, { + attributes : { + get : function() { + return this._attributes; + } + }, + + numberOfInstances : { + get : function () { + return this._numberOfInstances; + } + } + }); + function getDatatype(attributes) { var foundFloatDatatype = false; var length = attributes.length; @@ -132,6 +148,9 @@ define([ if (attributeIndex < 0 || attributeIndex >= this._attributes.length) { throw new DeveloperError('attributeIndex is out of range'); } + if (!defined(value)) { + throw new DeveloperError('value is required.'); + } //>>includeEnd('debug'); var attributes = this._attributes; diff --git a/Specs/Scene/BatchTableSpec.js b/Specs/Scene/BatchTableSpec.js new file mode 100644 index 000000000000..e0c050fc8f52 --- /dev/null +++ b/Specs/Scene/BatchTableSpec.js @@ -0,0 +1,211 @@ +/*global defineSuite*/ +defineSuite([ + 'Scene/BatchTable', + 'Core/Cartesian4', + 'Core/ComponentDatatype', + 'Renderer/PixelDatatype', + 'Renderer/Texture', + 'Specs/createScene' +], function( + BatchTable, + Cartesian4, + ComponentDatatype, + PixelDatatype, + Texture, + createScene) { + 'use strict'; + + var unsignedByteAttributes = [{ + functionName : 'batchTable_getShow', + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 1 + }, { + functionName : 'batchTable_getPickColor', + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4, + normalize : true + }]; + + var floatAttributes = [{ + functionName : 'batchTable_getShow', + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 1 + }, { + functionName : 'batchTable_getCenter', + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3 + }]; + + var batchTable; + var scene; + + beforeAll(function() { + scene = createScene(); + }); + + afterAll(function() { + scene.destroyForSpecs(); + }); + + afterEach(function() { + batchTable = batchTable && !batchTable.isDestroyed() && batchTable.destroy(); + }); + + it('constructor', function() { + batchTable = new BatchTable(unsignedByteAttributes, 2); + expect(batchTable.attributes).toBe(unsignedByteAttributes); + expect(batchTable.numberOfInstances).toEqual(2); + }); + + it('constructior throws without attributes', function() { + expect(function() { + batchTable = new BatchTable(undefined, 5); + }).toThrowDeveloperError(); + }); + + it('constructor throws without number of instances', function() { + expect(function() { + batchTable = new BatchTable(unsignedByteAttributes, undefined); + }).toThrowDeveloperError(); + }); + + it('sets and gets entries in the table', function() { + batchTable = new BatchTable(unsignedByteAttributes, 5); + + var i; + var color = new Cartesian4(0, 1, 2, 3); + + for (i = 0; i < batchTable.numberOfInstances; ++i) { + batchTable.setEntry(i, 0, 1); + batchTable.setEntry(i, 1, color); + } + + for (i = 0; i < batchTable.numberOfInstances; ++i) { + expect(batchTable.getEntry(3, 0)).toEqual(1); + expect(batchTable.getEntry(3, 1)).toEqual(color); + } + + color = new Cartesian4(4, 5, 6, 7); + batchTable.setEntry(3, 0, 0); + batchTable.setEntry(3, 1, color); + expect(batchTable.getEntry(3, 0)).toEqual(0); + expect(batchTable.getEntry(3, 1)).toEqual(color); + }); + + it('gets with result parameter', function() { + batchTable = new BatchTable(unsignedByteAttributes, 5); + var color = new Cartesian4(0, 1, 2, 3); + batchTable.setEntry(0, 1, color); + + var result = new Cartesian4(); + var returndValue = batchTable.getEntry(0, 1, result); + expect(returndValue).toBe(result); + expect(result).toEqual(color); + }); + + it('get entry throws when instance index is out of range', function() { + batchTable = new BatchTable(unsignedByteAttributes, 5); + expect(function() { + batchTable.getEntry(-1, 0); + }).toThrowDeveloperError(); + expect(function() { + batchTable.getEntry(100, 0); + }).toThrowDeveloperError(); + }); + + it('get entry throws when attribute index is out of range', function() { + batchTable = new BatchTable(unsignedByteAttributes, 5); + expect(function() { + batchTable.getEntry(0, -1); + }).toThrowDeveloperError(); + expect(function() { + batchTable.getEntry(0, 100); + }).toThrowDeveloperError(); + }); + + it('set entry throws when instance index is out of range', function() { + batchTable = new BatchTable(unsignedByteAttributes, 5); + expect(function() { + batchTable.setEntry(-1, 0, 0); + }).toThrowDeveloperError(); + expect(function() { + batchTable.setEntry(100, 0, 1); + }).toThrowDeveloperError(); + }); + + it('set entry throws when attribute index is out of range', function() { + batchTable = new BatchTable(unsignedByteAttributes, 5); + expect(function() { + batchTable.setEntry(0, -1, 1); + }).toThrowDeveloperError(); + expect(function() { + batchTable.setEntry(0, 100, 1); + }).toThrowDeveloperError(); + }); + + it('set entry throws when value is undefined', function() { + batchTable = new BatchTable(unsignedByteAttributes, 5); + expect(function() { + batchTable.setEntry(0, 0, undefined); + }).toThrowDeveloperError(); + }); + + it('creates a uniform callback with unsigned byte texture', function() { + batchTable = new BatchTable(unsignedByteAttributes, 5); + batchTable.update(scene.frameState); + + var uniforms = batchTable.getUniformMapCallback()({}); + expect(uniforms.batchTexture).toBeDefined(); + expect(uniforms.batchTexture()).toBeInstanceOf(Texture); + expect(uniforms.batchTexture().pixelDatatype).toEqual(PixelDatatype.UNSIGNED_BYTE); + expect(uniforms.batchTextureDimensions).toBeDefined(); + expect(uniforms.batchTextureDimensions().x).toBeGreaterThan(0); + expect(uniforms.batchTextureDimensions().y).toBeGreaterThan(0); + expect(uniforms.batchTextureStep).toBeDefined(); + expect(uniforms.batchTextureStep().x).toBeGreaterThan(0); + expect(uniforms.batchTextureStep().y).toBeGreaterThan(0); + expect(uniforms.batchTextureStep().z).toBeGreaterThan(0); + expect(uniforms.batchTextureStep().w).toBeGreaterThan(0); + }); + + it('creates a uniform callback with unsigned byte texture', function() { + batchTable = new BatchTable(floatAttributes, 5); + + if (scene.context.floatingPointTexture) { + batchTable.update(scene.frameState); + + var uniforms = batchTable.getUniformMapCallback()({}); + expect(uniforms.batchTexture).toBeDefined(); + expect(uniforms.batchTexture()).toBeInstanceOf(Texture); + expect(uniforms.batchTexture().pixelDatatype).toEqual(PixelDatatype.FLOAT); + expect(uniforms.batchTextureDimensions).toBeDefined(); + expect(uniforms.batchTextureDimensions().x).toBeGreaterThan(0); + expect(uniforms.batchTextureDimensions().y).toBeGreaterThan(0); + expect(uniforms.batchTextureStep).toBeDefined(); + expect(uniforms.batchTextureStep().x).toBeGreaterThan(0); + expect(uniforms.batchTextureStep().y).toBeGreaterThan(0); + expect(uniforms.batchTextureStep().z).toBeGreaterThan(0); + expect(uniforms.batchTextureStep().w).toBeGreaterThan(0); + } else { + expect(function() { + batchTable.update(scene.frameState); + }).toThrowRuntimeError(); + } + }); + + it('create shader functions', function() { + batchTable = new BatchTable(unsignedByteAttributes, 5); + + var shader = 'void main() { gl_Position = vec4(0.0); }'; + var modifiedShader = batchTable.getVertexShaderCallback()(shader); + expect(modifiedShader.indexOf(batchTable.attributes[0].functionName)).not.toEqual(-1); + expect(modifiedShader.indexOf(batchTable.attributes[1].functionName)).not.toEqual(-1); + }); + + it('isDestroyed', function() { + batchTable = new BatchTable(unsignedByteAttributes, 5); + expect(batchTable.isDestroyed()).toEqual(false); + batchTable.destroy(); + expect(batchTable.isDestroyed()).toEqual(true); + }); +}); \ No newline at end of file From 87b01fab6f98f04ab8f438d25fb01f60bc84753f Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 19 Sep 2016 15:46:38 -0400 Subject: [PATCH 103/191] Add doc. --- Source/Scene/BatchTable.js | 136 ++++++++++++++++++++++++++++++++++++- 1 file changed, 135 insertions(+), 1 deletion(-) diff --git a/Source/Scene/BatchTable.js b/Source/Scene/BatchTable.js index fd5650bfd9f2..a96459a5a4c8 100644 --- a/Source/Scene/BatchTable.js +++ b/Source/Scene/BatchTable.js @@ -37,6 +37,52 @@ define([ TextureMinificationFilter) { 'use strict'; + /** + * Creates a texture to look up per instance attributes for batched primitives. For example, store each primitive's pick color in the texture. + * + * @alias BatchTable + * @constructor + * @private + * + * @param {Object[]} attributes An array of objects describing a per instance attribute. Each object contains a datatype, components per attributes, whether it is normalized and a function name + * to retrieve the value in the vertex shader. + * @param {Number} numberOfInstances The number of instances in a batch table. + * + * @example + * // create the batch table + * var attributes = [{ + * functionName : 'getShow()', + * componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + * componentsPerAttribute : 1 + * }, { + * functionName : 'getPickColor', + * componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + * componentsPerAttribute : 4, + * normalize : true + * }]; + * var batchTable = new BatchTable(attributes, 5); + * + * // when creating the draw commands, update the uniform map and the vertex shader + * vertexShaderSource = batchTable.getVertexShaderCallback()(vertexShaderSource); + * var shaderProgram = ShaderProgram.fromCache({ + * // ... + * vertexShaderSource : vertexShaderSource, + * }); + * + * drawCommand.shaderProgram = shaderProgram; + * drawCommand.uniformMap = batchTable.getUniformMapCallback()(uniformMap); + * + * // use the attribute function names in the shader to retrieve the instance values + * // ... + * attribute float batchId; + * + * void main() { + * // ... + * float show = getShow(batchId); + * vec3 pickColor = getPickColor(batchId); + * // ... + * } + */ function BatchTable(attributes, numberOfInstances) { //>>includeStart('debug', pragmas.debug); if (!defined(attributes)) { @@ -75,12 +121,23 @@ define([ } defineProperties(BatchTable.prototype, { + /** + * The attribute descriptions. + * @memberOf BatchTable.prototype + * @type {Object[]} + * @readonly + */ attributes : { get : function() { return this._attributes; } }, - + /** + * The number of instances. + * @memberOf BatchTable.prototype + * @type {Number} + * @readonly + */ numberOfInstances : { get : function () { return this._numberOfInstances; @@ -113,6 +170,17 @@ define([ var scratchgetEntryCartesian4 = new Cartesian4(); + /** + * Gets the value of an entry in the table. + * + * @param {Number} instanceIndex The index of the instance. + * @param {Number} attributeIndex The index of the attribute. + * @param {undefined|Cartesian2|Cartesian3|Cartesian4} [result] The object onto which to store the result. The type is dependent on the attribute's number of components. + * @returns {Number|Cartesian2|Cartesian3|Cartesian4} The attribute value stored for the instance. + * + * @exception {DeveloperError} instanceIndex is out of range. + * @exception {DeveloperError} attributeIndex is out of range. + */ BatchTable.prototype.getEntry = function(instanceIndex, attributeIndex, result) { //>>includeStart('debug', pragmas.debug); if (instanceIndex < 0 || instanceIndex >= this._numberOfInstances) { @@ -140,6 +208,16 @@ define([ var setEntryScratchValues = [undefined, undefined, new Cartesian2(), new Cartesian3(), new Cartesian4()]; var setEntryScratchCartesian4 = new Cartesian4(); + /** + * Sets the value of an entry in the table. + * + * @param {Number} instanceIndex The index of the instance. + * @param {Number} attributeIndex The index of the attribute. + * @param {Number|Cartesian2|Cartesian3|Cartesian4} value The value to be stored in the table. The type of value will depend on the number of components of the attribute. + * + * @exception {DeveloperError} instanceIndex is out of range. + * @exception {DeveloperError} attributeIndex is out of range. + */ BatchTable.prototype.setEntry = function(instanceIndex, attributeIndex, value) { //>>includeStart('debug', pragmas.debug); if (instanceIndex < 0 || instanceIndex >= this._numberOfInstances) { @@ -198,6 +276,12 @@ define([ }); } + /** + * Creates/updates the batch table texture. + * @param {FrameState} frameState The frame state. + * + * @exception {RuntimeError} The floating point texture extension is required but not supported. + */ BatchTable.prototype.update = function(frameState) { var context = frameState.context; if (this._pixelDatatype === PixelDatatype.FLOAT && !context.floatingPointTexture) { @@ -217,6 +301,11 @@ define([ updateTexture(this); }; + /** + * Gets a function that will update a uniform map to contain values for looking up values in the batch table. + * + * @returns {BatchTable~updateUniformMapCallback} A callback for updating uniform maps. + */ BatchTable.prototype.getUniformMapCallback = function() { var that = this; return function(uniformMap) { @@ -310,6 +399,11 @@ define([ return glslFunction; } + /** + * Gets a function that will update a vertex shader to contain functions for looking up values in the batch table. + * + * @returns {BatchTable~updateVertexShaderSourceCallback} A callback for updating a vertex shader source. + */ BatchTable.prototype.getVertexShaderCallback = function() { var batchTableShader = 'uniform sampler2D batchTexture; \n'; batchTableShader += getGlslComputeSt(this) + '\n'; @@ -328,14 +422,54 @@ define([ }; }; + /** + * Returns true if this object was destroyed; otherwise, false. + *

+ * If this object was destroyed, it should not be used; calling any function other than + * isDestroyed will result in a {@link DeveloperError} exception. + * + * @returns {Boolean} true if this object was destroyed; otherwise, false. + * + * @see BatchTable#destroy + */ BatchTable.prototype.isDestroyed = function() { return false; }; + /** + * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic + * release of WebGL resources, instead of relying on the garbage collector to destroy this object. + *

+ * Once an object is destroyed, it should not be used; calling any function other than + * isDestroyed will result in a {@link DeveloperError} exception. Therefore, + * assign the return value (undefined) to the object as done in the example. + * + * @returns {undefined} + * + * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called. + * + * @see BatchTable#isDestroyed + */ BatchTable.prototype.destroy = function() { this._texture = this._texture && this._texture.destroy(); return destroyObject(this); }; + /** + * A callback for updating uniform maps. + * @callback BatchTable~updateUniformMapCallback + * + * @param {Object} uniformMap The uniform map. + * @returns {Object} The new uniform map with properties for retrieving values from the batch table. + */ + + /** + * A callback for updating a vertex shader source. + * @callback BatchTable~updateVertexShaderSourceCallback + * + * @param {String} vertexShaderSource The vertex shader source. + * @returns {String} The new vertex shader source with the functions for retrieving batch table values injected. + */ + return BatchTable; }); \ No newline at end of file From dc1966b11e8506641f4c01b543d277122042b612 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 19 Sep 2016 15:47:41 -0400 Subject: [PATCH 104/191] Tag tests as requiring WebGL. --- Specs/Scene/BatchTableSpec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Specs/Scene/BatchTableSpec.js b/Specs/Scene/BatchTableSpec.js index e0c050fc8f52..5d049282e280 100644 --- a/Specs/Scene/BatchTableSpec.js +++ b/Specs/Scene/BatchTableSpec.js @@ -208,4 +208,4 @@ defineSuite([ batchTable.destroy(); expect(batchTable.isDestroyed()).toEqual(true); }); -}); \ No newline at end of file +}, 'WebGL'); \ No newline at end of file From dbd21f9b8133993378ee0c67cb387889c171929f Mon Sep 17 00:00:00 2001 From: Ed Mackey Date: Tue, 20 Sep 2016 10:09:51 -0400 Subject: [PATCH 105/191] Fix some demo links. --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a038b06112cc..981de97c4833 100644 --- a/README.md +++ b/README.md @@ -33,12 +33,12 @@ We appreciate attribution by including the Cesium logo and link in your app. ### Featured Demos ###

-  +          -  +     

@@ -82,7 +82,6 @@ We appreciate attribution by including the Cesium logo and link in your app.       -        @@ -132,6 +131,5 @@ We appreciate attribution by including the Cesium logo and link in your app.       - 

From 93d8d4b3d103caeeb9d085678c7032f2de7024e0 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 20 Sep 2016 14:00:58 -0400 Subject: [PATCH 106/191] Add distance display conditions to polylines. --- Source/Scene/Polyline.js | 23 ++++++++- Source/Scene/PolylineCollection.js | 75 +++++++++++++++++++++++++++++- Source/Shaders/PolylineVS.glsl | 27 +++++++++++ 3 files changed, 122 insertions(+), 3 deletions(-) diff --git a/Source/Scene/Polyline.js b/Source/Scene/Polyline.js index 3e9e747429a2..a27a7c451601 100644 --- a/Source/Scene/Polyline.js +++ b/Source/Scene/Polyline.js @@ -8,6 +8,7 @@ define([ '../Core/defined', '../Core/defineProperties', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', '../Core/Matrix4', '../Core/PolylinePipeline', './Material' @@ -20,6 +21,7 @@ define([ defined, defineProperties, DeveloperError, + DistanceDisplayCondition, Matrix4, PolylinePipeline, Material) { @@ -48,6 +50,7 @@ define([ this._show = defaultValue(options.show, true); this._width = defaultValue(options.width, 1.0); this._loop = defaultValue(options.loop, false); + this._distanceDisplayCondition = options.distanceDisplayCondition; this._material = options.material; if (!defined(this._material)) { @@ -98,7 +101,8 @@ define([ var WIDTH_INDEX = Polyline.WIDTH_INDEX = 2; var MATERIAL_INDEX = Polyline.MATERIAL_INDEX = 3; var POSITION_SIZE_INDEX = Polyline.POSITION_SIZE_INDEX = 4; - var NUMBER_OF_PROPERTIES = Polyline.NUMBER_OF_PROPERTIES = 5; + var DISTANCE_DISPLAY_CONDITION = Polyline.DISTANCE_DISPLAY_CONDITION = 5; + var NUMBER_OF_PROPERTIES = Polyline.NUMBER_OF_PROPERTIES = 6; function makeDirty(polyline, propertyChanged) { ++polyline._propertiesChanged[propertyChanged]; @@ -285,6 +289,23 @@ define([ this._pickId.object.id = value; } } + }, + + distanceDisplayCondition : { + get : function() { + return this._distanceDisplayCondition; + }, + set : function(value) { + if (!DistanceDisplayCondition.equals(value, this._distanceDisplayCondition)) { + //>>includeStart('debug', pragmas.debug); + if (defined(value) && value.far <= value.near) { + throw new DeveloperError('far distance must be greater than near distance.'); + } + //>>includeEnd('debug'); + this._distanceDisplayCondition = DistanceDisplayCondition.clone(value, this._distanceDisplayCondition); + makeDirty(this, DISTANCE_DISPLAY_CONDITION); + } + } } }); diff --git a/Source/Scene/PolylineCollection.js b/Source/Scene/PolylineCollection.js index cca1e4d26566..59d20e7127a3 100644 --- a/Source/Scene/PolylineCollection.js +++ b/Source/Scene/PolylineCollection.js @@ -78,6 +78,7 @@ define([ //POSITION_SIZE_INDEX is needed for when the polyline's position array changes size. //When it does, we need to recreate the indicesBuffer. var POSITION_SIZE_INDEX = Polyline.POSITION_SIZE_INDEX; + var DISTANCE_DISPLAY_CONDITION = Polyline.DISTANCE_DISPLAY_CONDITION; var NUMBER_OF_PROPERTIES = Polyline.NUMBER_OF_PROPERTIES; var attributeLocations = { @@ -372,7 +373,7 @@ define([ return this._polylines[index]; }; - function createBatchTable(collection) { + function createBatchTable(collection, context) { if (defined(collection._batchTable)) { collection._batchTable.destroy(); } @@ -388,9 +389,29 @@ define([ normalize : true }]; + if (defined(context.floatingPointTexture)) { + attributes.push({ + functionName : 'batchTable_getCenterHigh', + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3 + }, { + functionName : 'batchTable_getCenterLowAndRadius', + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 4 + }, { + functionName : 'batchTable_getDistanceDisplayCondition', + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 2 + }); + } + collection._batchTable = new BatchTable(attributes, collection._polylines.length); } + var scratchUpdatePolylineEncodedCartesian = new EncodedCartesian3(); + var scratchUpdatePolylineCartesian4 = new Cartesian4(); + var scratchNearFarCartesian2 = new Cartesian2(); + /** * @private */ @@ -454,6 +475,30 @@ define([ this._batchTable.setEntry(polyline._index, 0, new Cartesian2(polyline._width, polyline._show)); } + if (this._batchTable.attributes.length > 2) { + if (properties[POSITION_INDEX] || properties[POSITION_SIZE_INDEX]) { + var boundingSphere = frameState.mode === SceneMode.SCENE2D ? polyline._boundingVolume2D : polyline._boundingVolumeWC; + var encodedCenter = EncodedCartesian3.fromCartesian(boundingSphere.center, scratchUpdatePolylineEncodedCartesian); + var low = Cartesian4.fromElements(encodedCenter.low.x, encodedCenter.low.y, encodedCenter.low.z, boundingSphere.radius, scratchUpdatePolylineCartesian4); + this._batchTable.setEntry(polyline._index, 2, encodedCenter.high); + this._batchTable.setEntry(polyline._index, 3, low); + } + + if (properties[DISTANCE_DISPLAY_CONDITION]) { + var nearFarCartesian = scratchNearFarCartesian2; + nearFarCartesian.x = 0.0; + nearFarCartesian.y = Number.MAX_VALUE; + + var distanceDisplayCondition = polyline.distanceDisplayCondition; + if (defined(distanceDisplayCondition)) { + nearFarCartesian.x = distanceDisplayCondition.near; + nearFarCartesian.x = distanceDisplayCondition.far; + } + + this._batchTable.setEntry(polyline._index, 4, nearFarCartesian); + } + } + polyline._clean(); } } @@ -1091,8 +1136,14 @@ define([ return; } + var defines = []; + if (context.floatingPointTexture) { + defines.push('DISTANCE_DISPLAY_CONDITION'); + } + var vsSource = batchTable.getVertexShaderCallback()(PolylineVS); var vs = new ShaderSource({ + defines : defines, sources : [PolylineCommon, vsSource] }); var fs = new ShaderSource({ @@ -1247,7 +1298,6 @@ define([ } } - // TODO: add support for color from the batch table? var colorCartesian = scratchPickColorCartesian; colorCartesian.x = Color.floatToByte(pickColor.red); colorCartesian.y = Color.floatToByte(pickColor.green); @@ -1258,8 +1308,29 @@ define([ widthShowCartesian.x = width; widthShowCartesian.y = show ? 1.0 : 0.0; + var boundingSphere = mode === SceneMode.SCENE2D ? polyline._boundingVolume2D : polyline._boundingVolumeWC; + var encodedCenter = EncodedCartesian3.fromCartesian(boundingSphere.center, scratchUpdatePolylineEncodedCartesian); + var high = encodedCenter.high; + var low = Cartesian4.fromElements(encodedCenter.low.x, encodedCenter.low.y, encodedCenter.low.z, boundingSphere.radius, scratchUpdatePolylineCartesian4); + + var nearFarCartesian = scratchNearFarCartesian2; + nearFarCartesian.x = 0.0; + nearFarCartesian.y = Number.MAX_VALUE; + + var distanceDisplayCondition = polyline.distanceDisplayCondition; + if (defined(distanceDisplayCondition)) { + nearFarCartesian.x = distanceDisplayCondition.near; + nearFarCartesian.y = distanceDisplayCondition.far; + } + batchTable.setEntry(polylineBatchIndex, 0, widthShowCartesian); batchTable.setEntry(polylineBatchIndex, 1, colorCartesian); + + if (batchTable.attributes.length > 2) { + batchTable.setEntry(polylineBatchIndex, 2, high); + batchTable.setEntry(polylineBatchIndex, 3, low); + batchTable.setEntry(polylineBatchIndex, 4, nearFarCartesian); + } } }; diff --git a/Source/Shaders/PolylineVS.glsl b/Source/Shaders/PolylineVS.glsl index 06eaf8caf73f..1e9bb899eabc 100644 --- a/Source/Shaders/PolylineVS.glsl +++ b/Source/Shaders/PolylineVS.glsl @@ -57,6 +57,33 @@ void main() czm_translateRelativeToEye(nextPosition3DHigh.xyz, nextPosition3DLow.xyz), czm_morphTime); } + + #ifdef DISTANCE_DISPLAY_CONDITION + vec3 centerHigh = batchTable_getCenterHigh(batchTableIndex); + vec4 centerLowAndRadius = batchTable_getCenterLowAndRadius(batchTableIndex); + vec3 centerLow = centerLowAndRadius.xyz; + float radius = centerLowAndRadius.w; + vec2 distanceDisplayCondition = batchTable_getDistanceDisplayCondition(batchTableIndex); + + float lengthSq; + if (czm_sceneMode == czm_sceneMode2D) + { + lengthSq = czm_eyeHeight2D.y; + } + else + { + vec4 center = czm_translateRelativeToEye(centerHigh.xyz, centerLow.xyz); + lengthSq = max(0.0, dot(center.xyz, center.xyz) - radius * radius); + } + + float nearSq = distanceDisplayCondition.x * distanceDisplayCondition.x; + float farSq = distanceDisplayCondition.y * distanceDisplayCondition.y; + //show = show == 1.0 && (lengthSq >= nearSq || lengthSq <= farSq) ? 1.0 : 0.0; + if (lengthSq < nearSq || lengthSq > farSq) + { + show = 0.0; + } + #endif vec4 positionWC = getPolylineWindowCoordinates(p, prev, next, expandDir, width, usePrev); gl_Position = czm_viewportOrthographic * positionWC * show; From 93e6e2f9839fb9fba50d1c0a398b289b9e620cbe Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 20 Sep 2016 14:16:28 -0400 Subject: [PATCH 107/191] Rename get/setEntry to get/setBatchedAttribute. --- Source/Scene/BatchTable.js | 52 +++++++++++++++--------------- Source/Scene/PolylineCollection.js | 6 ++-- Specs/Scene/BatchTableSpec.js | 38 +++++++++++----------- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/Source/Scene/BatchTable.js b/Source/Scene/BatchTable.js index a96459a5a4c8..0ee8ac58c74a 100644 --- a/Source/Scene/BatchTable.js +++ b/Source/Scene/BatchTable.js @@ -51,7 +51,7 @@ define([ * @example * // create the batch table * var attributes = [{ - * functionName : 'getShow()', + * functionName : 'getShow', * componentDatatype : ComponentDatatype.UNSIGNED_BYTE, * componentsPerAttribute : 1 * }, { @@ -156,7 +156,7 @@ define([ return foundFloatDatatype ? PixelDatatype.FLOAT : PixelDatatype.UNSIGNED_BYTE; } - function getEntryType(attributes, attributeIndex) { + function getAttributeType(attributes, attributeIndex) { var componentsPerAttribute = attributes[attributeIndex].componentsPerAttribute; if (componentsPerAttribute === 2) { return Cartesian2; @@ -168,10 +168,10 @@ define([ return Number; } - var scratchgetEntryCartesian4 = new Cartesian4(); + var scratchGetAttributeCartesian4 = new Cartesian4(); /** - * Gets the value of an entry in the table. + * Gets the value of an attribute in the table. * * @param {Number} instanceIndex The index of the instance. * @param {Number} attributeIndex The index of the attribute. @@ -181,7 +181,7 @@ define([ * @exception {DeveloperError} instanceIndex is out of range. * @exception {DeveloperError} attributeIndex is out of range. */ - BatchTable.prototype.getEntry = function(instanceIndex, attributeIndex, result) { + BatchTable.prototype.getBatchedAttribute = function(instanceIndex, attributeIndex, result) { //>>includeStart('debug', pragmas.debug); if (instanceIndex < 0 || instanceIndex >= this._numberOfInstances) { throw new DeveloperError('instanceIndex is out of range.'); @@ -193,23 +193,23 @@ define([ var attributes = this._attributes; var index = 4 * attributes.length * instanceIndex + 4 * attributeIndex; - var value = Cartesian4.unpack(this._batchValues, index, scratchgetEntryCartesian4); + var value = Cartesian4.unpack(this._batchValues, index, scratchGetAttributeCartesian4); - var entryType = getEntryType(attributes, attributeIndex); - if (defined(entryType.fromCartesian4)) { - return entryType.fromCartesian4(value, result); - } else if (defined(entryType.clone)) { - return entryType.clone(value, result); + var attributeType = getAttributeType(attributes, attributeIndex); + if (defined(attributeType.fromCartesian4)) { + return attributeType.fromCartesian4(value, result); + } else if (defined(attributeType.clone)) { + return attributeType.clone(value, result); } return value.x; }; - var setEntryScratchValues = [undefined, undefined, new Cartesian2(), new Cartesian3(), new Cartesian4()]; - var setEntryScratchCartesian4 = new Cartesian4(); + var setAttributeScratchValues = [undefined, undefined, new Cartesian2(), new Cartesian3(), new Cartesian4()]; + var setAttributeScratchCartesian4 = new Cartesian4(); /** - * Sets the value of an entry in the table. + * Sets the value of an attribute in the table. * * @param {Number} instanceIndex The index of the instance. * @param {Number} attributeIndex The index of the attribute. @@ -218,7 +218,7 @@ define([ * @exception {DeveloperError} instanceIndex is out of range. * @exception {DeveloperError} attributeIndex is out of range. */ - BatchTable.prototype.setEntry = function(instanceIndex, attributeIndex, value) { + BatchTable.prototype.setBatchedAttribute = function(instanceIndex, attributeIndex, value) { //>>includeStart('debug', pragmas.debug); if (instanceIndex < 0 || instanceIndex >= this._numberOfInstances) { throw new DeveloperError('instanceIndex is out of range.'); @@ -232,22 +232,22 @@ define([ //>>includeEnd('debug'); var attributes = this._attributes; - var result = setEntryScratchValues[attributes[attributeIndex].componentsPerAttribute]; - var currentEntry = this.getEntry(instanceIndex, attributeIndex, result); - var entryType = getEntryType(this._attributes, attributeIndex); - var entriesEqual = defined(entryType.equals) ? entryType.equals(currentEntry, value) : currentEntry === value; + var result = setAttributeScratchValues[attributes[attributeIndex].componentsPerAttribute]; + var currentAttribute = this.getBatchedAttribute(instanceIndex, attributeIndex, result); + var attributeType = getAttributeType(this._attributes, attributeIndex); + var entriesEqual = defined(attributeType.equals) ? attributeType.equals(currentAttribute, value) : currentAttribute === value; if (entriesEqual) { return; } - var entryValue = setEntryScratchCartesian4; - entryValue.x = defined(value.x) ? value.x : value; - entryValue.y = defined(value.y) ? value.y : 0.0; - entryValue.z = defined(value.z) ? value.z : 0.0; - entryValue.w = defined(value.w) ? value.w : 0.0; + var attributeValue = setAttributeScratchCartesian4; + attributeValue.x = defined(value.x) ? value.x : value; + attributeValue.y = defined(value.y) ? value.y : 0.0; + attributeValue.z = defined(value.z) ? value.z : 0.0; + attributeValue.w = defined(value.w) ? value.w : 0.0; var index = 4 * attributes.length * instanceIndex + 4 * attributeIndex; - Cartesian4.pack(entryValue, this._batchValues, index); + Cartesian4.pack(attributeValue, this._batchValues, index); this._batchValuesDirty = true; }; @@ -285,7 +285,7 @@ define([ BatchTable.prototype.update = function(frameState) { var context = frameState.context; if (this._pixelDatatype === PixelDatatype.FLOAT && !context.floatingPointTexture) { - // TODO: We could probably pack the floats to RGBA unsigned bytes but that would add a lot CPU and memory overhead. + // We could probably pack the floats to RGBA unsigned bytes but that would add a lot CPU and memory overhead. throw new RuntimeError('The floating point texture extension is required but not supported.'); } diff --git a/Source/Scene/PolylineCollection.js b/Source/Scene/PolylineCollection.js index cca1e4d26566..a254c9d55847 100644 --- a/Source/Scene/PolylineCollection.js +++ b/Source/Scene/PolylineCollection.js @@ -451,7 +451,7 @@ define([ } if (properties[SHOW_INDEX] || properties[WIDTH_INDEX]) { - this._batchTable.setEntry(polyline._index, 0, new Cartesian2(polyline._width, polyline._show)); + this._batchTable.setBatchedAttribute(polyline._index, 0, new Cartesian2(polyline._width, polyline._show)); } polyline._clean(); @@ -1258,8 +1258,8 @@ define([ widthShowCartesian.x = width; widthShowCartesian.y = show ? 1.0 : 0.0; - batchTable.setEntry(polylineBatchIndex, 0, widthShowCartesian); - batchTable.setEntry(polylineBatchIndex, 1, colorCartesian); + batchTable.setBatchedAttribute(polylineBatchIndex, 0, widthShowCartesian); + batchTable.setBatchedAttribute(polylineBatchIndex, 1, colorCartesian); } }; diff --git a/Specs/Scene/BatchTableSpec.js b/Specs/Scene/BatchTableSpec.js index 5d049282e280..5237321ebd81 100644 --- a/Specs/Scene/BatchTableSpec.js +++ b/Specs/Scene/BatchTableSpec.js @@ -76,29 +76,29 @@ defineSuite([ var color = new Cartesian4(0, 1, 2, 3); for (i = 0; i < batchTable.numberOfInstances; ++i) { - batchTable.setEntry(i, 0, 1); - batchTable.setEntry(i, 1, color); + batchTable.setBatchedAttribute(i, 0, 1); + batchTable.setBatchedAttribute(i, 1, color); } for (i = 0; i < batchTable.numberOfInstances; ++i) { - expect(batchTable.getEntry(3, 0)).toEqual(1); - expect(batchTable.getEntry(3, 1)).toEqual(color); + expect(batchTable.getBatchedAttribute(3, 0)).toEqual(1); + expect(batchTable.getBatchedAttribute(3, 1)).toEqual(color); } color = new Cartesian4(4, 5, 6, 7); - batchTable.setEntry(3, 0, 0); - batchTable.setEntry(3, 1, color); - expect(batchTable.getEntry(3, 0)).toEqual(0); - expect(batchTable.getEntry(3, 1)).toEqual(color); + batchTable.setBatchedAttribute(3, 0, 0); + batchTable.setBatchedAttribute(3, 1, color); + expect(batchTable.getBatchedAttribute(3, 0)).toEqual(0); + expect(batchTable.getBatchedAttribute(3, 1)).toEqual(color); }); it('gets with result parameter', function() { batchTable = new BatchTable(unsignedByteAttributes, 5); var color = new Cartesian4(0, 1, 2, 3); - batchTable.setEntry(0, 1, color); + batchTable.setBatchedAttribute(0, 1, color); var result = new Cartesian4(); - var returndValue = batchTable.getEntry(0, 1, result); + var returndValue = batchTable.getBatchedAttribute(0, 1, result); expect(returndValue).toBe(result); expect(result).toEqual(color); }); @@ -106,47 +106,47 @@ defineSuite([ it('get entry throws when instance index is out of range', function() { batchTable = new BatchTable(unsignedByteAttributes, 5); expect(function() { - batchTable.getEntry(-1, 0); + batchTable.getBatchedAttribute(-1, 0); }).toThrowDeveloperError(); expect(function() { - batchTable.getEntry(100, 0); + batchTable.getBatchedAttribute(100, 0); }).toThrowDeveloperError(); }); it('get entry throws when attribute index is out of range', function() { batchTable = new BatchTable(unsignedByteAttributes, 5); expect(function() { - batchTable.getEntry(0, -1); + batchTable.getBatchedAttribute(0, -1); }).toThrowDeveloperError(); expect(function() { - batchTable.getEntry(0, 100); + batchTable.getBatchedAttribute(0, 100); }).toThrowDeveloperError(); }); it('set entry throws when instance index is out of range', function() { batchTable = new BatchTable(unsignedByteAttributes, 5); expect(function() { - batchTable.setEntry(-1, 0, 0); + batchTable.setBatchedAttribute(-1, 0, 0); }).toThrowDeveloperError(); expect(function() { - batchTable.setEntry(100, 0, 1); + batchTable.setBatchedAttribute(100, 0, 1); }).toThrowDeveloperError(); }); it('set entry throws when attribute index is out of range', function() { batchTable = new BatchTable(unsignedByteAttributes, 5); expect(function() { - batchTable.setEntry(0, -1, 1); + batchTable.setBatchedAttribute(0, -1, 1); }).toThrowDeveloperError(); expect(function() { - batchTable.setEntry(0, 100, 1); + batchTable.setBatchedAttribute(0, 100, 1); }).toThrowDeveloperError(); }); it('set entry throws when value is undefined', function() { batchTable = new BatchTable(unsignedByteAttributes, 5); expect(function() { - batchTable.setEntry(0, 0, undefined); + batchTable.setBatchedAttribute(0, 0, undefined); }).toThrowDeveloperError(); }); From 96ebfabe67766a3a8a612fb4c239a5dc815e2180 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 20 Sep 2016 14:19:33 -0400 Subject: [PATCH 108/191] Remove unneeded TODO comment. --- Source/Scene/PolylineCollection.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Scene/PolylineCollection.js b/Source/Scene/PolylineCollection.js index a254c9d55847..10869066594e 100644 --- a/Source/Scene/PolylineCollection.js +++ b/Source/Scene/PolylineCollection.js @@ -1247,7 +1247,6 @@ define([ } } - // TODO: add support for color from the batch table? var colorCartesian = scratchPickColorCartesian; colorCartesian.x = Color.floatToByte(pickColor.red); colorCartesian.y = Color.floatToByte(pickColor.green); From 71df48c600a2cfe07232183b6b69545d9ca80685 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 20 Sep 2016 14:34:10 -0400 Subject: [PATCH 109/191] Fixes after merge. --- Source/Scene/PolylineCollection.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Scene/PolylineCollection.js b/Source/Scene/PolylineCollection.js index aaaecb1dd256..ba8805cebf7a 100644 --- a/Source/Scene/PolylineCollection.js +++ b/Source/Scene/PolylineCollection.js @@ -480,8 +480,8 @@ define([ var boundingSphere = frameState.mode === SceneMode.SCENE2D ? polyline._boundingVolume2D : polyline._boundingVolumeWC; var encodedCenter = EncodedCartesian3.fromCartesian(boundingSphere.center, scratchUpdatePolylineEncodedCartesian); var low = Cartesian4.fromElements(encodedCenter.low.x, encodedCenter.low.y, encodedCenter.low.z, boundingSphere.radius, scratchUpdatePolylineCartesian4); - this._batchTable.setEntry(polyline._index, 2, encodedCenter.high); - this._batchTable.setEntry(polyline._index, 3, low); + this._batchTable.setBatchedAttribute(polyline._index, 2, encodedCenter.high); + this._batchTable.setBatchedAttribute(polyline._index, 3, low); } if (properties[DISTANCE_DISPLAY_CONDITION]) { @@ -495,7 +495,7 @@ define([ nearFarCartesian.x = distanceDisplayCondition.far; } - this._batchTable.setEntry(polyline._index, 4, nearFarCartesian); + this._batchTable.setBatchedAttribute(polyline._index, 4, nearFarCartesian); } } From 500c400495b6bd53b0380f96ba35a2577cdfa144 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 20 Sep 2016 14:56:57 -0400 Subject: [PATCH 110/191] Fix normalized unsigned byte attributes when using a floating point texture. --- Source/Scene/BatchTable.js | 2 ++ Source/Shaders/PolylineVS.glsl | 9 +++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Source/Scene/BatchTable.js b/Source/Scene/BatchTable.js index 0ee8ac58c74a..2462bd7637cd 100644 --- a/Source/Scene/BatchTable.js +++ b/Source/Scene/BatchTable.js @@ -391,6 +391,8 @@ define([ if (batchTable._pixelDatatype === PixelDatatype.UNSIGNED_BYTE && !attribute.normalize) { glslFunction += 'value *= 255.0; \n'; + } else if (batchTable._pixelDatatype === PixelDatatype.FLOAT && attribute.componentDatatype === ComponentDatatype.UNSIGNED_BYTE && attribute.normalize) { + glslFunction += 'value /= 255.0; \n'; } glslFunction += diff --git a/Source/Shaders/PolylineVS.glsl b/Source/Shaders/PolylineVS.glsl index 1e9bb899eabc..a8bb5b3b167c 100644 --- a/Source/Shaders/PolylineVS.glsl +++ b/Source/Shaders/PolylineVS.glsl @@ -27,7 +27,9 @@ void main() float width = widthAndShow.x + 0.5; float show = widthAndShow.y; - vec4 pickColor = batchTable_getPickColor(batchTableIndex); + v_st = vec2(texCoord, clamp(expandDir, 0.0, 1.0)); + v_width = width; + czm_pickColor = batchTable_getPickColor(batchTableIndex); vec4 p, prev, next; if (czm_morphTime == 1.0) @@ -78,7 +80,6 @@ void main() float nearSq = distanceDisplayCondition.x * distanceDisplayCondition.x; float farSq = distanceDisplayCondition.y * distanceDisplayCondition.y; - //show = show == 1.0 && (lengthSq >= nearSq || lengthSq <= farSq) ? 1.0 : 0.0; if (lengthSq < nearSq || lengthSq > farSq) { show = 0.0; @@ -87,8 +88,4 @@ void main() vec4 positionWC = getPolylineWindowCoordinates(p, prev, next, expandDir, width, usePrev); gl_Position = czm_viewportOrthographic * positionWC * show; - - v_st = vec2(texCoord, clamp(expandDir, 0.0, 1.0)); - v_width = width; - czm_pickColor = pickColor; } From 953b96306abc9c6066eb67c272af7bb0260b6e68 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 20 Sep 2016 15:36:18 -0400 Subject: [PATCH 111/191] Add polyline distance display condition test. --- Specs/Scene/PolylineCollectionSpec.js | 43 +++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/Specs/Scene/PolylineCollectionSpec.js b/Specs/Scene/PolylineCollectionSpec.js index 40d071037716..6a2cb9753638 100644 --- a/Specs/Scene/PolylineCollectionSpec.js +++ b/Specs/Scene/PolylineCollectionSpec.js @@ -4,6 +4,8 @@ defineSuite([ 'Core/BoundingSphere', 'Core/Cartesian3', 'Core/Color', + 'Core/DistanceDisplayCondition', + 'Core/HeadingPitchRange', 'Core/Math', 'Scene/Camera', 'Scene/Material', @@ -14,6 +16,8 @@ defineSuite([ BoundingSphere, Cartesian3, Color, + DistanceDisplayCondition, + HeadingPitchRange, CesiumMath, Camera, Material, @@ -1222,6 +1226,45 @@ defineSuite([ expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]); }); + it('renders with a distance display condition', function() { + if (!scene.context.floatingPointTexture) { + return; + } + + var near = 100.0; + var far = 10000.0; + + var line = polylines.add({ + positions : [{ + x : 10.0, + y : -10.0, + z : 0.0 + }, { + x : 10.0, + y : 10.0, + z : 0.0 + }], + width : 7, + distanceDisplayCondition : new DistanceDisplayCondition(near, far) + }); + + scene.primitives.add(polylines); + scene.renderForSpecs(); + + var boundingSphere = line._boundingVolumeWC; + var center = boundingSphere.center; + var radius = boundingSphere.radius; + + scene.camera.lookAt(center, new HeadingPitchRange(0.0, -CesiumMath.PI_OVER_TWO, radius + near - 10.0)); + expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]); + + scene.camera.lookAt(center, new HeadingPitchRange(0.0, -CesiumMath.PI_OVER_TWO, radius + near + 1.0)); + expect(scene.renderForSpecs()).not.toEqual([0, 0, 0, 255]); + + scene.camera.lookAt(center, new HeadingPitchRange(0.0, -CesiumMath.PI_OVER_TWO, radius + far + 10.0)); + expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]); + }); + it('changes polyline position size recreates vertex arrays', function() { var positions = []; for(var i = 0; i < 20; ++i){ From 017db411e41e579ba7e72e79fd8a58ae677245c7 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 20 Sep 2016 16:21:57 -0400 Subject: [PATCH 112/191] Add distance display condition support to path and polyline entities. --- Source/DataSources/PathGraphics.js | 8 ++++++- Source/DataSources/PathVisualizer.js | 2 ++ Source/DataSources/PolylineGeometryUpdater.js | 21 ++++++++++++++++++- Source/DataSources/PolylineGraphics.js | 8 ++++++- Specs/DataSources/PathGraphicsSpec.js | 15 ++++++++++++- Specs/DataSources/PathVisualizerSpec.js | 4 ++++ .../PolylineGeometryUpdaterSpec.js | 21 +++++++++++++++++++ Specs/DataSources/PolylineGraphicsSpec.js | 16 +++++++++++++- 8 files changed, 90 insertions(+), 5 deletions(-) diff --git a/Source/DataSources/PathGraphics.js b/Source/DataSources/PathGraphics.js index 818a82edfa8b..f083f535bdb6 100644 --- a/Source/DataSources/PathGraphics.js +++ b/Source/DataSources/PathGraphics.js @@ -44,6 +44,8 @@ define([ this._leadTimeSubscription = undefined; this._trailTime = undefined; this._trailTimeSubscription = undefined; + this._distanceDisplayCondition = undefined; + this._distanceDisplayConditionSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -106,7 +108,9 @@ define([ * @memberof PathGraphics.prototype * @type {Property} */ - trailTime : createPropertyDescriptor('trailTime') + trailTime : createPropertyDescriptor('trailTime'), + + distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition') }); /** @@ -125,6 +129,7 @@ define([ result.show = this.show; result.leadTime = this.leadTime; result.trailTime = this.trailTime; + result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; @@ -147,6 +152,7 @@ define([ this.show = defaultValue(this.show, source.show); this.leadTime = defaultValue(this.leadTime, source.leadTime); this.trailTime = defaultValue(this.trailTime, source.trailTime); + this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); }; return PathGraphics; diff --git a/Source/DataSources/PathVisualizer.js b/Source/DataSources/PathVisualizer.js index 8c39644abf93..e80a388bb5e2 100644 --- a/Source/DataSources/PathVisualizer.js +++ b/Source/DataSources/PathVisualizer.js @@ -273,6 +273,7 @@ define([ this._referenceFrame = referenceFrame; scene.primitives.add(this._polylineCollection); } + PolylineUpdater.prototype.update = function(time) { if (this._referenceFrame === ReferenceFrame.INERTIAL) { var toFixed = Transforms.computeIcrfToFixedMatrix(time, toFixedScratch); @@ -368,6 +369,7 @@ define([ polyline.positions = subSample(positionProperty, sampleStart, sampleStop, time, this._referenceFrame, resolution, polyline.positions.slice()); polyline.material = MaterialProperty.getValue(time, pathGraphics._material, polyline.material); polyline.width = Property.getValueOrDefault(pathGraphics._width, time, defaultWidth); + polyline.distanceDisplayCondition = Property.getValueOrUndefined(pathGraphics._distanceDisplayCondition, time, polyline.distanceDisplayCondition); }; PolylineUpdater.prototype.removeObject = function(item) { diff --git a/Source/DataSources/PolylineGeometryUpdater.js b/Source/DataSources/PolylineGeometryUpdater.js index 174248e04ba7..b7ba5af695f7 100644 --- a/Source/DataSources/PolylineGeometryUpdater.js +++ b/Source/DataSources/PolylineGeometryUpdater.js @@ -8,6 +8,8 @@ define([ '../Core/defineProperties', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/DistanceDisplayCondition', + '../Core/DistanceDisplayConditionGeometryInstanceAttribute', '../Core/Ellipsoid', '../Core/Event', '../Core/GeometryInstance', @@ -33,6 +35,8 @@ define([ defineProperties, destroyObject, DeveloperError, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, Ellipsoid, Event, GeometryInstance, @@ -57,6 +61,7 @@ define([ var defaultMaterial = new ColorMaterialProperty(Color.WHITE); var defaultShow = new ConstantProperty(true); var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); + var defaultDistanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); function GeometryOptions(entity) { this.id = entity; @@ -95,6 +100,7 @@ define([ this._showProperty = undefined; this._materialProperty = undefined; this._shadowsProperty = undefined; + this._distanceDisplayConditionProperty = undefined; this._options = new GeometryOptions(entity); this._onEntityPropertyChanged(entity, 'polyline', entity.polyline, undefined); } @@ -210,6 +216,13 @@ define([ return this._shadowsProperty; } }, + + distanceDisplayConditionProperty : { + get : function() { + return this._distanceDisplayConditionProperty; + } + }, + /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -295,6 +308,8 @@ define([ var entity = this._entity; var isAvailable = entity.isAvailable(time); var show = new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time)); + var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); + var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition); if (this._materialProperty instanceof ColorMaterialProperty) { var currentColor = Color.WHITE; @@ -304,11 +319,13 @@ define([ color = ColorGeometryInstanceAttribute.fromColor(currentColor); attributes = { show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute, color : color }; } else { attributes = { - show : show + show : show, + distanceDisplayCondition : distanceDisplayConditionAttribute }; } @@ -384,6 +401,7 @@ define([ this._materialProperty = material; this._showProperty = defaultValue(show, defaultShow); this._shadowsProperty = defaultValue(polyline.shadows, defaultShadows); + this._distanceDisplayConditionProperty = defaultValue(polyline.distanceDisplayCondition, defaultDistanceDisplayCondition); this._fillEnabled = true; var width = polyline.width; @@ -504,6 +522,7 @@ define([ line.positions = positions.slice(); line.material = MaterialProperty.getValue(time, geometryUpdater.fillMaterialProperty, line.material); line.width = Property.getValueOrDefault(polyline._width, time, 1); + line.distanceDisplayCondition = Property.getValueOrUndefined(polyline._distanceDisplayCondition, time, line.distanceDisplayCondition); }; DynamicGeometryUpdater.prototype.getBoundingSphere = function(entity, result) { diff --git a/Source/DataSources/PolylineGraphics.js b/Source/DataSources/PolylineGraphics.js index c1416aed104f..0c3664acee5d 100644 --- a/Source/DataSources/PolylineGraphics.js +++ b/Source/DataSources/PolylineGraphics.js @@ -53,6 +53,8 @@ define([ this._widthSubscription = undefined; this._shadows = undefined; this._shadowsSubscription = undefined; + this._distanceDisplayCondition = undefined; + this._distanceDisplayConditionSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -128,7 +130,9 @@ define([ * @type {Property} * @default ShadowMode.DISABLED */ - shadows : createPropertyDescriptor('shadows') + shadows : createPropertyDescriptor('shadows'), + + distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition') }); /** @@ -148,6 +152,7 @@ define([ result.followSurface = this.followSurface; result.granularity = this.granularity; result.shadows = this.shadows; + result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; @@ -171,6 +176,7 @@ define([ this.followSurface = defaultValue(this.followSurface, source.followSurface); this.granularity = defaultValue(this.granularity, source.granularity); this.shadows = defaultValue(this.shadows, source.shadows); + this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); }; return PolylineGraphics; diff --git a/Specs/DataSources/PathGraphicsSpec.js b/Specs/DataSources/PathGraphicsSpec.js index 9b24542b9715..f7add5e01e98 100644 --- a/Specs/DataSources/PathGraphicsSpec.js +++ b/Specs/DataSources/PathGraphicsSpec.js @@ -2,11 +2,13 @@ defineSuite([ 'DataSources/PathGraphics', 'Core/Color', + 'Core/DistanceDisplayCondition', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty' ], function( PathGraphics, Color, + DistanceDisplayCondition, ColorMaterialProperty, ConstantProperty) { 'use strict'; @@ -18,7 +20,8 @@ defineSuite([ show : false, leadTime : 2, trailTime : 3, - resolution : 4 + resolution : 4, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 20.0) }; var path = new PathGraphics(options); @@ -28,6 +31,7 @@ defineSuite([ expect(path.leadTime).toBeInstanceOf(ConstantProperty); expect(path.trailTime).toBeInstanceOf(ConstantProperty); expect(path.resolution).toBeInstanceOf(ConstantProperty); + expect(path.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(path.material.color.getValue()).toEqual(options.material); expect(path.width.getValue()).toEqual(options.width); @@ -35,6 +39,7 @@ defineSuite([ expect(path.leadTime.getValue()).toEqual(options.leadTime); expect(path.trailTime.getValue()).toEqual(options.trailTime); expect(path.resolution.getValue()).toEqual(options.resolution); + expect(path.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); }); it('merge assigns unassigned properties', function() { @@ -45,6 +50,7 @@ defineSuite([ source.leadTime = new ConstantProperty(1); source.trailTime = new ConstantProperty(1); source.resolution = new ConstantProperty(1); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 20.0)); var target = new PathGraphics(); target.merge(source); @@ -54,6 +60,7 @@ defineSuite([ expect(target.leadTime).toBe(source.leadTime); expect(target.trailTime).toBe(source.trailTime); expect(target.resolution).toBe(source.resolution); + expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge does not assign assigned properties', function() { @@ -64,6 +71,7 @@ defineSuite([ source.leadTime = new ConstantProperty(1); source.trailTime = new ConstantProperty(1); source.resolution = new ConstantProperty(1); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var color = new ColorMaterialProperty(); var width = new ConstantProperty(1); @@ -71,6 +79,7 @@ defineSuite([ var leadTime = new ConstantProperty(1); var trailTime = new ConstantProperty(1); var resolution = new ConstantProperty(1); + var distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var target = new PathGraphics(); target.material = color; @@ -79,6 +88,7 @@ defineSuite([ target.leadTime = leadTime; target.trailTime = trailTime; target.resolution = resolution; + target.distanceDisplayCondition = distanceDisplayCondition; target.merge(source); expect(target.material).toBe(color); @@ -87,6 +97,7 @@ defineSuite([ expect(target.leadTime).toBe(leadTime); expect(target.trailTime).toBe(trailTime); expect(target.resolution).toBe(resolution); + expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); }); it('clone works', function() { @@ -97,6 +108,7 @@ defineSuite([ source.leadTime = new ConstantProperty(1); source.trailTime = new ConstantProperty(1); source.resolution = new ConstantProperty(1); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var result = source.clone(); expect(result.material).toBe(source.material); @@ -105,6 +117,7 @@ defineSuite([ expect(result.leadTime).toBe(source.leadTime); expect(result.trailTime).toBe(source.trailTime); expect(result.resolution).toBe(source.resolution); + expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge throws if source undefined', function() { diff --git a/Specs/DataSources/PathVisualizerSpec.js b/Specs/DataSources/PathVisualizerSpec.js index b3e089e6fdf0..b08d9f3af72d 100644 --- a/Specs/DataSources/PathVisualizerSpec.js +++ b/Specs/DataSources/PathVisualizerSpec.js @@ -3,6 +3,7 @@ defineSuite([ 'DataSources/PathVisualizer', 'Core/Cartesian3', 'Core/Color', + 'Core/DistanceDisplayCondition', 'Core/JulianDate', 'Core/Matrix4', 'Core/ReferenceFrame', @@ -24,6 +25,7 @@ defineSuite([ PathVisualizer, Cartesian3, Color, + DistanceDisplayCondition, JulianDate, Matrix4, ReferenceFrame, @@ -152,6 +154,7 @@ defineSuite([ path.material.outlineColor = new ConstantProperty(new Color(0.1, 0.2, 0.3, 0.4)); path.material.outlineWidth = new ConstantProperty(2.5); path.width = new ConstantProperty(12.5); + path.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 20.0)); path.leadTime = new ConstantProperty(25); path.trailTime = new ConstantProperty(10); @@ -166,6 +169,7 @@ defineSuite([ expect(primitive.positions[2]).toEqual(testObject.position.getValue(JulianDate.addSeconds(updateTime, path.leadTime.getValue(), new JulianDate()))); expect(primitive.show).toEqual(testObject.path.show.getValue(updateTime)); expect(primitive.width).toEqual(testObject.path.width.getValue(updateTime)); + expect(primitive.distanceDisplayCondition).toEqual(testObject.path.distanceDisplayCondition.getValue(updateTime)); var material = primitive.material; expect(material.uniforms.color).toEqual(testObject.path.material.color.getValue(updateTime)); diff --git a/Specs/DataSources/PolylineGeometryUpdaterSpec.js b/Specs/DataSources/PolylineGeometryUpdaterSpec.js index cdb905c5c655..080f71c3cbd5 100644 --- a/Specs/DataSources/PolylineGeometryUpdaterSpec.js +++ b/Specs/DataSources/PolylineGeometryUpdaterSpec.js @@ -5,6 +5,8 @@ defineSuite([ 'Core/Cartesian3', 'Core/Color', 'Core/ColorGeometryInstanceAttribute', + 'Core/DistanceDisplayCondition', + 'Core/DistanceDisplayConditionGeometryInstanceAttribute', 'Core/JulianDate', 'Core/ShowGeometryInstanceAttribute', 'Core/TimeInterval', @@ -30,6 +32,8 @@ defineSuite([ Cartesian3, Color, ColorGeometryInstanceAttribute, + DistanceDisplayCondition, + DistanceDisplayConditionGeometryInstanceAttribute, JulianDate, ShowGeometryInstanceAttribute, TimeInterval, @@ -94,6 +98,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.shadowsProperty).toBe(undefined); + expect(updater.distanceDisplayConditionProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -133,6 +138,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); + expect(updater.distanceDisplayConditionProperty).toEqual(new ConstantProperty(new DistanceDisplayCondition())); expect(updater.isDynamic).toBe(false); }); @@ -198,6 +204,7 @@ defineSuite([ polyline.width = new ConstantProperty(options.width); polyline.followSurface = new ConstantProperty(options.followSurface); polyline.granularity = new ConstantProperty(options.granularity); + polyline.distanceDisplayCondition = options.distanceDisplayCondition; var updater = new PolylineGeometryUpdater(entity, scene); @@ -217,6 +224,9 @@ defineSuite([ expect(attributes.color).toBeUndefined(); } expect(attributes.show.value).toEqual(ShowGeometryInstanceAttribute.toValue(options.show)); + if (options.distanceDisplayCondition) { + expect(attributes.distanceDisplayCondition.value).toEqual(DistanceDisplayConditionGeometryInstanceAttribute.toValue(options.distanceDisplayCondition)); + } } it('Creates expected per-color geometry', function() { @@ -239,6 +249,17 @@ defineSuite([ }); }); + it('Creates expected distance display condition geometry', function() { + validateGeometryInstance({ + show : true, + material : new ColorMaterialProperty(Color.RED), + width : 3, + followSurface : false, + granularity : 1.0, + distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) + }); + }); + it('Attributes have expected values at creation time', function() { var time1 = new JulianDate(0, 0); var time2 = new JulianDate(10, 0); diff --git a/Specs/DataSources/PolylineGraphicsSpec.js b/Specs/DataSources/PolylineGraphicsSpec.js index 73e41c2f5e3d..4e303b179e35 100644 --- a/Specs/DataSources/PolylineGraphicsSpec.js +++ b/Specs/DataSources/PolylineGraphicsSpec.js @@ -2,6 +2,7 @@ defineSuite([ 'DataSources/PolylineGraphics', 'Core/Color', + 'Core/DistanceDisplayCondition', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', 'Scene/ShadowMode', @@ -10,6 +11,7 @@ defineSuite([ ], function( PolylineGraphics, Color, + DistanceDisplayCondition, ColorMaterialProperty, ConstantProperty, ShadowMode, @@ -25,7 +27,8 @@ defineSuite([ width : 1, followSurface : false, granularity : 2, - shadows : ShadowMode.DISABLED + shadows : ShadowMode.DISABLED, + distanceDisplayCondition : new DistanceDisplayCondition() }; var polyline = new PolylineGraphics(options); @@ -36,6 +39,7 @@ defineSuite([ expect(polyline.followSurface).toBeInstanceOf(ConstantProperty); expect(polyline.granularity).toBeInstanceOf(ConstantProperty); expect(polyline.shadows).toBeInstanceOf(ConstantProperty); + expect(polyline.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(polyline.material.color.getValue()).toEqual(options.material); expect(polyline.positions.getValue()).toEqual(options.positions); @@ -44,6 +48,7 @@ defineSuite([ expect(polyline.followSurface.getValue()).toEqual(options.followSurface); expect(polyline.granularity.getValue()).toEqual(options.granularity); expect(polyline.shadows.getValue()).toEqual(options.shadows); + expect(polyline.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); }); it('merge assigns unassigned properties', function() { @@ -55,6 +60,7 @@ defineSuite([ source.followSurface = new ConstantProperty(); source.granularity = new ConstantProperty(); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var target = new PolylineGraphics(); target.merge(source); @@ -65,6 +71,7 @@ defineSuite([ expect(target.followSurface).toBe(source.followSurface); expect(target.granularity).toBe(source.granularity); expect(target.shadows).toBe(source.shadows); + expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge does not assign assigned properties', function() { @@ -76,6 +83,7 @@ defineSuite([ source.followSurface = new ConstantProperty(); source.granularity = new ConstantProperty(); source.shadows = new ConstantProperty(); + source.distanceDisplayCondition = new ConstantProperty(); var color = new ColorMaterialProperty(); var positions = new ConstantProperty(); @@ -84,6 +92,7 @@ defineSuite([ var followSurface = new ConstantProperty(); var granularity = new ConstantProperty(); var shadows = new ConstantProperty(); + var distanceDisplayCondition = new ConstantProperty(); var target = new PolylineGraphics(); target.material = color; @@ -93,6 +102,7 @@ defineSuite([ target.followSurface = followSurface; target.granularity = granularity; target.shadows = shadows; + target.distanceDisplayCondition = distanceDisplayCondition; target.merge(source); expect(target.material).toBe(color); @@ -102,6 +112,7 @@ defineSuite([ expect(target.followSurface).toBe(followSurface); expect(target.granularity).toBe(granularity); expect(target.shadows).toBe(shadows); + expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); }); it('clone works', function() { @@ -113,6 +124,7 @@ defineSuite([ source.followSurface = new ConstantProperty(); source.granularity = new ConstantProperty(); source.shadows = new ConstantProperty(); + source.distanceDisplayCondition = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -122,6 +134,7 @@ defineSuite([ expect(result.followSurface).toBe(source.followSurface); expect(result.granularity).toBe(source.granularity); expect(result.shadows).toBe(source.shadows); + expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); it('merge throws if source undefined', function() { @@ -140,5 +153,6 @@ defineSuite([ testDefinitionChanged(property, 'followSurface', false, true); testDefinitionChanged(property, 'granularity', 2, 1); testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); + testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 20.0)); }); }); From 52e072dc88af5a42971666992d8e6bde06819183 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Sun, 18 Sep 2016 19:48:10 -0400 Subject: [PATCH 113/191] chore(package): update jsdoc to version 3.4.1 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d2f1806a0325..767fc48aede7 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "gulp-replace": "0.5.4", "gulp-zip": "3.0.2", "jasmine-core": "2.4.1", - "jsdoc": "3.4.0", + "jsdoc": "3.4.1", "jshint": "2.9.3", "jshint-stylish": "2.2.1", "karma": "1.2.0", From eff9a99a496af3768b56c2710f25e82255e4d2c0 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Sun, 18 Sep 2016 19:48:10 -0400 Subject: [PATCH 114/191] chore(package): update karma to version 1.3.0 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 767fc48aede7..9944af3afddd 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "jsdoc": "3.4.1", "jshint": "2.9.3", "jshint-stylish": "2.2.1", - "karma": "1.2.0", + "karma": "1.3.0", "karma-chrome-launcher": "2.0.0", "karma-detect-browsers": "2.1.0", "karma-electron-launcher": "0.1.0", From 4e43b996eda316e5925ee5538914f31c1b9b5cbb Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Sun, 18 Sep 2016 19:48:10 -0400 Subject: [PATCH 115/191] chore(package): update electron-prebuilt to version 1.4.0 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9944af3afddd..a1f973c33ecf 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "bluebird": "3.4.6", "compressible": "2.0.8", "compression": "1.6.2", - "electron-prebuilt": "1.3.5", + "electron-prebuilt": "1.4.0", "event-stream": "3.3.4", "express": "4.14.0", "globby": "6.0.0", From eabd0c6269084124e6ec4e6c799a15dd58cbafcd Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Sun, 18 Sep 2016 19:48:10 -0400 Subject: [PATCH 116/191] chore(package): update karma-requirejs to version 1.1.0 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a1f973c33ecf..2990110ecd8c 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "karma-firefox-launcher": "1.0.0", "karma-ie-launcher": "1.0.0", "karma-jasmine": "1.0.2", - "karma-requirejs": "1.0.0", + "karma-requirejs": "1.1.0", "karma-safari-launcher": "1.0.0", "karma-spec-reporter": "0.0.26", "mime": "1.3.4", From ec30679e11300873bffcbd89ae8e0feefae17854 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Tue, 13 Sep 2016 15:44:29 -0400 Subject: [PATCH 117/191] Draw planes for debug camera --- Source/Scene/DebugCameraPrimitive.js | 60 +++++++++++++++++++++------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/Source/Scene/DebugCameraPrimitive.js b/Source/Scene/DebugCameraPrimitive.js index f26aae3aaf01..12df3e1ddb1b 100644 --- a/Source/Scene/DebugCameraPrimitive.js +++ b/Source/Scene/DebugCameraPrimitive.js @@ -90,7 +90,8 @@ define([ this.id = options.id; this._id = undefined; - this._primitive = undefined; + this._outlinePrimitive = undefined; + this._planesPrimitive = undefined; } var frustumCornersNDC = new Array(8); @@ -109,6 +110,8 @@ define([ scratchFrustumCorners[i] = new Cartesian4(); } + var scratchColor = new Color(); + /** * @private */ @@ -119,10 +122,11 @@ define([ if (this._updateOnChange) { // Recreate the primitive every frame - this._primitive = this._primitive && this._primitive.destroy(); + this._outlinePrimitive = this._outlinePrimitive && this._outlinePrimitive.destroy(); + this._planesPrimitive = this._planesPrimitive && this._planesPrimitive.destroy(); } - if (!defined(this._primitive)) { + if (!defined(this._outlinePrimitive)) { var view = this._camera.viewMatrix; var projection = this._camera.frustum.projectionMatrix; var viewProjection = Matrix4.multiply(projection, view, scratchMatrix); @@ -138,6 +142,8 @@ define([ positions[i * 3 + 2] = corner.z; } + var boundingSphere = new BoundingSphere.fromVertices(positions); + var attributes = new GeometryAttributes(); attributes.position = new GeometryAttribute({ componentDatatype : ComponentDatatype.DOUBLE, @@ -145,17 +151,17 @@ define([ values : positions }); - var indices = new Uint16Array([0,1,1,2,2,3,3,0,0,4,4,7,7,3,7,6,6,2,2,1,1,5,5,4,5,6]); - var geometry = new Geometry({ - attributes : attributes, - indices : indices, - primitiveType : PrimitiveType.LINES, - boundingSphere : new BoundingSphere.fromVertices(positions) - }); + // Create the outline primitive + var outlineIndices = new Uint16Array([0,1,1,2,2,3,3,0,0,4,4,7,7,3,7,6,6,2,2,1,1,5,5,4,5,6]); - this._primitive = new Primitive({ + this._outlinePrimitive = new Primitive({ geometryInstances : new GeometryInstance({ - geometry : geometry, + geometry : { + attributes : attributes, + indices : outlineIndices, + primitiveType : PrimitiveType.LINES, + boundingSphere : boundingSphere + }, attributes : { color : ColorGeometryInstanceAttribute.fromColor(this._color) }, @@ -168,9 +174,34 @@ define([ }), asynchronous : false }); + + // Create the planes primitive + var planesIndices = new Uint16Array([4,5,6,4,6,7,5,1,2,5,2,6,7,6,2,7,2,3,0,1,5,0,5,4,0,4,7,0,7,3,1,0,3,1,3,2]); + + this._planesPrimitive = new Primitive({ + geometryInstances : new GeometryInstance({ + geometry : { + attributes : attributes, + indices : planesIndices, + primitiveType : PrimitiveType.TRIANGLES, + boundingSphere : boundingSphere + }, + attributes : { + color : ColorGeometryInstanceAttribute.fromColor(Color.fromAlpha(this._color, 0.1, scratchColor)) + }, + id : this.id, + pickPrimitive : this + }), + appearance : new PerInstanceColorAppearance({ + translucent : true, + flat : true + }), + asynchronous : false + }); } - this._primitive.update(frameState); + this._outlinePrimitive.update(frameState); + this._planesPrimitive.update(frameState); }; /** @@ -207,7 +238,8 @@ define([ * @see DebugCameraPrimitive#isDestroyed */ DebugCameraPrimitive.prototype.destroy = function() { - this._primitive = this._primitive && this._primitive.destroy(); + this._outlinePrimitive = this._outlinePrimitive && this._outlinePrimitive.destroy(); + this._planesPrimitive = this._planesPrimitive && this._planesPrimitive.destroy(); return destroyObject(this); }; From 274bdcc485bb1772f3fcda179f09ad42bb45080d Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Mon, 19 Sep 2016 13:18:46 +1000 Subject: [PATCH 118/191] Remove default gamma correction for Bing Maps. This used to look good, but these days Bing Maps aerial imagery looks much better without the gamma correction. --- Source/Scene/BingMapsImageryProvider.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Source/Scene/BingMapsImageryProvider.js b/Source/Scene/BingMapsImageryProvider.js index cf98c7a7be1d..fb2ea3096e40 100644 --- a/Source/Scene/BingMapsImageryProvider.js +++ b/Source/Scene/BingMapsImageryProvider.js @@ -117,17 +117,13 @@ define([ /** * The default {@link ImageryLayer#gamma} to use for imagery layers created for this provider. - * By default, this is set to 1.3 for the "aerial" and "aerial with labels" map styles and 1.0 for - * all others. Changing this value after creating an {@link ImageryLayer} for this provider will have + * Changing this value after creating an {@link ImageryLayer} for this provider will have * no effect. Instead, set the layer's {@link ImageryLayer#gamma} property. * * @type {Number} * @default 1.0 */ this.defaultGamma = 1.0; - if (this._mapStyle === BingMapsStyle.AERIAL || this._mapStyle === BingMapsStyle.AERIAL_WITH_LABELS) { - this.defaultGamma = 1.3; - } this._tilingScheme = new WebMercatorTilingScheme({ numberOfLevelZeroTilesX : 2, From aed2661968fdd65c8822f288a6c37608c573f32b Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Mon, 19 Sep 2016 13:22:52 +1000 Subject: [PATCH 119/191] Update CHANGES.md. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index c796e5d85259..97d99752bf35 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,7 @@ Change Log * Fixed billboard rotation when sized in meters. [#3979](https://github.com/AnalyticalGraphicsInc/cesium/issues/3979) * Added `DebugCameraPrimitive` to visualize the view frustum of a camera. * Fixed touch events for the timeline [#4305](https://github.com/AnalyticalGraphicsInc/cesium/pull/4305) +* Removed the default gamma correction for Bing Maps aerial imagery, because we no longer think it is an improvement in current versions of the tiles. To restore the previous look, set the `defaultGamma` property of your `BingMapsImageryProvider` instance to 1.3. ### 1.25 - 2016-09-01 From 982d23de5bd31c6f1d45410b171ea6156b039deb Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Mon, 19 Sep 2016 09:59:41 -0400 Subject: [PATCH 120/191] chore(package): update jasmine-core to version 2.5.2 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2990110ecd8c..441ccced29f6 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "gulp-rename": "1.2.2", "gulp-replace": "0.5.4", "gulp-zip": "3.0.2", - "jasmine-core": "2.4.1", + "jasmine-core": "2.5.2", "jsdoc": "3.4.1", "jshint": "2.9.3", "jshint-stylish": "2.2.1", From 199a0bfbf485748fa1c63d414901b15e8f1e72fc Mon Sep 17 00:00:00 2001 From: Ed Mackey Date: Tue, 20 Sep 2016 10:09:51 -0400 Subject: [PATCH 121/191] Fix some demo links. --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a038b06112cc..981de97c4833 100644 --- a/README.md +++ b/README.md @@ -33,12 +33,12 @@ We appreciate attribution by including the Cesium logo and link in your app. ### Featured Demos ###

-  +          -  +     

@@ -82,7 +82,6 @@ We appreciate attribution by including the Cesium logo and link in your app.       -        @@ -132,6 +131,5 @@ We appreciate attribution by including the Cesium logo and link in your app.       - 

From 694e11d77f757d9fe625130c180ec649a0a77e2d Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Wed, 21 Sep 2016 18:17:54 +1000 Subject: [PATCH 122/191] Add min/max encoded values to heightmap structure. --- Source/Core/CesiumTerrainProvider.js | 8 +++++--- Source/Core/HeightmapTerrainData.js | 9 ++++++++- Source/Core/VRTheWorldTerrainProvider.js | 6 ++++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Source/Core/CesiumTerrainProvider.js b/Source/Core/CesiumTerrainProvider.js index a36abdc07a5b..0db08a0da84c 100644 --- a/Source/Core/CesiumTerrainProvider.js +++ b/Source/Core/CesiumTerrainProvider.js @@ -75,7 +75,7 @@ define([ * url : 'https://assets.agi.com/stk-terrain/world', * requestVertexNormals : true * }); - * + * * // Terrain geometry near the surface of the globe is difficult to view when using NaturalEarthII imagery, * // unless the TerrainProvider provides additional lighting information to shade the terrain (as shown above). * var imageryProvider = Cesium.createTileMapServiceImageryProvider({ @@ -91,7 +91,7 @@ define([ * * // The globe must enable lighting to make use of the terrain's vertex normals * viewer.scene.globe.enableLighting = true; - * + * * @see TerrainProvider */ function CesiumTerrainProvider(options) { @@ -180,7 +180,9 @@ define([ elementsPerHeight : 1, stride : 1, elementMultiplier : 256.0, - isBigEndian : false + isBigEndian : false, + lowestEncodedHeight : 0, + highestEncodedHeight : 256 * 256 }; that._hasWaterMask = true; that._requestWaterMask = true; diff --git a/Source/Core/HeightmapTerrainData.js b/Source/Core/HeightmapTerrainData.js index 4079c054ca14..8d8a541bac13 100644 --- a/Source/Core/HeightmapTerrainData.js +++ b/Source/Core/HeightmapTerrainData.js @@ -350,6 +350,12 @@ define([ for (var i = 0; i < width; ++i) { var longitude = CesiumMath.lerp(destinationRectangle.west, destinationRectangle.east, i / (width - 1)); var heightSample = interpolateMeshHeight(buffer, encoding, heightOffset, heightScale, skirtHeight, sourceRectangle, width, height, longitude, latitude, exaggeration); + + // Use conditionals here instead of Math.min and Math.max so that an undefined + // lowestEncodedHeight or highestEncodedHeight has no effect. + heightSample = heightSample < structure.lowestEncodedHeight ? structure.lowestEncodedHeight : heightSample; + heightSample = heightSample > structure.highestEncodedHeight ? structure.highestEncodedHeight : heightSample; + setHeight(heights, elementsPerHeight, elementMultiplier, divisor, stride, isBigEndian, j * width + i, heightSample); } } @@ -448,6 +454,7 @@ define([ } function interpolateMeshHeight(buffer, encoding, heightOffset, heightScale, skirtHeight, sourceRectangle, width, height, longitude, latitude, exaggeration) { + // returns a height encoded according to the structure's heightScale and heightOffset. var fromWest = (longitude - sourceRectangle.west) * (width - 1) / (sourceRectangle.east - sourceRectangle.west); var fromSouth = (latitude - sourceRectangle.south) * (height - 1) / (sourceRectangle.north - sourceRectangle.south); @@ -536,7 +543,7 @@ define([ divisor /= elementMultiplier; } } - heights[index + i] = Math.max(0, height); + heights[index + i] = height; } return HeightmapTerrainData; diff --git a/Source/Core/VRTheWorldTerrainProvider.js b/Source/Core/VRTheWorldTerrainProvider.js index edfcbfe5de5b..b2d86e6b47f3 100644 --- a/Source/Core/VRTheWorldTerrainProvider.js +++ b/Source/Core/VRTheWorldTerrainProvider.js @@ -64,7 +64,7 @@ define([ * url : 'https://www.vr-theworld.com/vr-theworld/tiles1.0.0/73/' * }); * viewer.terrainProvider = terrainProvider; - * + * * @see TerrainProvider */ function VRTheWorldTerrainProvider(options) { @@ -90,7 +90,9 @@ define([ elementsPerHeight : 3, stride : 4, elementMultiplier : 256.0, - isBigEndian : true + isBigEndian : true, + lowestEncodedHeight : 0, + highestEncodedHeight : 256 * 256 * 256 }; var credit = options.credit; From 8621305fea5283f670d8c660f93da56cd3bd3be8 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Wed, 21 Sep 2016 18:23:01 +1000 Subject: [PATCH 123/191] Add new fields to ArcGIS terrain provider, too. --- Source/Core/ArcGisImageServerTerrainProvider.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Core/ArcGisImageServerTerrainProvider.js b/Source/Core/ArcGisImageServerTerrainProvider.js index 6236c4d7365c..356d54ea0ad2 100644 --- a/Source/Core/ArcGisImageServerTerrainProvider.js +++ b/Source/Core/ArcGisImageServerTerrainProvider.js @@ -60,7 +60,7 @@ define([ * proxy : new Cesium.DefaultProxy('/terrain/') * }); * viewer.terrainProvider = terrainProvider; - * + * * @see TerrainProvider */ function ArcGisImageServerTerrainProvider(options) { @@ -91,7 +91,9 @@ define([ elementsPerHeight : 3, stride : 4, elementMultiplier : 256.0, - isBigEndian : true + isBigEndian : true, + lowestEncodedHeight : 0, + highestEncodedHeight : 256 * 256 * 256 }; this._errorEvent = new Event(); From 0ca80b25e7e489b3ad0db732087bcdad9a4f3085 Mon Sep 17 00:00:00 2001 From: HeercoGrond Date: Wed, 21 Sep 2016 11:27:14 +0200 Subject: [PATCH 124/191] Update with credentials (see #4340 and #4341) Per Request - Added our Organization details and my name to Contributors.md --- CONTRIBUTORS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index d322dd58bd41..2408f5478bf0 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -62,6 +62,8 @@ * [Dave Whipps](https://github.com/dwhipps) * [Geoscan](https://www.geoscan.aero) * [Andrey Orlov](https://github.com/AndreyOrlov) +* [The Imagineers](https://www.theimagineers.com/) + * [Heerco Grond](https://github.com/HeercoGrond) ## [Individual CLA](http://www.agi.com/licenses/individual-cla-agi-v1.0.txt) * [Victor Berchet](https://github.com/vicb) From 2e0b103c28f1b2ee2defbf7dfa4f15e24538979a Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 21 Sep 2016 14:18:53 -0400 Subject: [PATCH 125/191] Fix failing polyline test and update CHANGES.md. --- CHANGES.md | 2 ++ Source/Scene/BatchTable.js | 1 + Source/Shaders/PolylineVS.glsl | 5 +++++ 3 files changed, 8 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 97d99752bf35..e2124ba1d132 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,8 @@ Change Log ### 1.26 - 2016-10-03 +* Breaking changes + * Vertex texture fetch is now required to be supported to render polylines. Maximum vertex texture image units must be greater than zero. * Fixed billboard rotation when sized in meters. [#3979](https://github.com/AnalyticalGraphicsInc/cesium/issues/3979) * Added `DebugCameraPrimitive` to visualize the view frustum of a camera. * Fixed touch events for the timeline [#4305](https://github.com/AnalyticalGraphicsInc/cesium/pull/4305) diff --git a/Source/Scene/BatchTable.js b/Source/Scene/BatchTable.js index 0ee8ac58c74a..01c8b77ecaaa 100644 --- a/Source/Scene/BatchTable.js +++ b/Source/Scene/BatchTable.js @@ -151,6 +151,7 @@ define([ for (var i = 0; i < length; ++i) { if (attributes[i].componentDatatype !== ComponentDatatype.UNSIGNED_BYTE) { foundFloatDatatype = true; + break; } } return foundFloatDatatype ? PixelDatatype.FLOAT : PixelDatatype.UNSIGNED_BYTE; diff --git a/Source/Shaders/PolylineVS.glsl b/Source/Shaders/PolylineVS.glsl index 06eaf8caf73f..7f0664b2c3f8 100644 --- a/Source/Shaders/PolylineVS.glsl +++ b/Source/Shaders/PolylineVS.glsl @@ -27,6 +27,11 @@ void main() float width = widthAndShow.x + 0.5; float show = widthAndShow.y; + if (width < 1.0) + { + show = 0.0; + } + vec4 pickColor = batchTable_getPickColor(batchTableIndex); vec4 p, prev, next; From 48a4a5d7e0c79ced1daf1b37ab78cadc35dae230 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 21 Sep 2016 16:03:58 -0400 Subject: [PATCH 126/191] Use batch table for per instance geometry attributes. --- Source/Scene/Primitive.js | 187 +++++++++++++++++- Source/Scene/PrimitivePipeline.js | 33 ++++ .../Appearances/AllMaterialAppearanceVS.glsl | 1 + .../BasicMaterialAppearanceVS.glsl | 1 + .../EllipsoidSurfaceAppearanceVS.glsl | 1 + .../PerInstanceColorAppearanceVS.glsl | 1 + .../PerInstanceFlatColorAppearanceVS.glsl | 1 + .../Appearances/PointAppearanceVS.glsl | 1 + .../PolylineColorAppearanceVS.glsl | 1 + .../PolylineMaterialAppearanceVS.glsl | 1 + .../TexturedMaterialAppearanceVS.glsl | 1 + 11 files changed, 224 insertions(+), 5 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 995078d0fe1b..2b7750eb75f8 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -3,7 +3,9 @@ define([ '../Core/BoundingSphere', '../Core/Cartesian2', '../Core/Cartesian3', + '../Core/Cartesian4', '../Core/clone', + '../Core/Color', '../Core/combine', '../Core/ComponentDatatype', '../Core/defaultValue', @@ -30,6 +32,7 @@ define([ '../Renderer/ShaderSource', '../Renderer/VertexArray', '../ThirdParty/when', + './BatchTable', './CullFace', './Pass', './PrimitivePipeline', @@ -40,7 +43,9 @@ define([ BoundingSphere, Cartesian2, Cartesian3, + Cartesian4, clone, + Color, combine, ComponentDatatype, defaultValue, @@ -67,6 +72,7 @@ define([ ShaderSource, VertexArray, when, + BatchTable, CullFace, Pass, PrimitivePipeline, @@ -350,6 +356,9 @@ define([ this._createGeometryResults = undefined; this._ready = false; this._readyPromise = when.defer(); + + this._batchTable = undefined; + this._batchTableAttributeIndices = undefined; } defineProperties(Primitive.prototype, { @@ -518,6 +527,145 @@ define([ } }); + function getCommonPerInstanceAttributeNames(instances) { + var length = instances.length; + + var attributesInAllInstances = []; + var attributes0 = instances[0].attributes; + var name; + + for (name in attributes0) { + if (attributes0.hasOwnProperty(name)) { + var attribute = attributes0[name]; + var inAllInstances = true; + + // Does this same attribute exist in all instances? + for (var i = 1; i < length; ++i) { + var otherAttribute = instances[i].attributes[name]; + + if (!defined(otherAttribute) || + (attribute.componentDatatype !== otherAttribute.componentDatatype) || + (attribute.componentsPerAttribute !== otherAttribute.componentsPerAttribute) || + (attribute.normalize !== otherAttribute.normalize)) { + + inAllInstances = false; + break; + } + } + + if (inAllInstances) { + attributesInAllInstances.push(name); + } + } + } + + return attributesInAllInstances; + } + + var scratchGetAttributeCartesian2 = new Cartesian2(); + var scratchGetAttributeCartesian3 = new Cartesian3(); + var scratchGetAttributeCartesian4 = new Cartesian4(); + + function getAttributeValue(attribute) { + var componentsPerAttribute = attribute.componentsPerAttribute; + var value = attribute.value; + if (componentsPerAttribute === 1) { + return value[0]; + } else if (componentsPerAttribute === 2) { + return Cartesian2.unpack(value, 0, scratchGetAttributeCartesian2); + } else if (componentsPerAttribute === 3) { + return Cartesian3.unpack(value, 0, scratchGetAttributeCartesian3); + } else if (componentsPerAttribute === 4) { + return Cartesian4.unpack(value, 0, scratchGetAttributeCartesian4); + } + } + + function createBatchTable(primitive, context) { + var geometryInstances = primitive.geometryInstances; + var instances = (isArray(geometryInstances)) ? geometryInstances : [geometryInstances]; + var numberOfInstances = instances.length; + if (numberOfInstances === 0) { + return; + } + + var names = getCommonPerInstanceAttributeNames(instances); + var length = names.length; + + var allowPicking = primitive.allowPicking; + var attributesLength = allowPicking ? length + 1 : length; + var attributes = new Array(attributesLength); + var attributeIndices = {}; + + var firstInstance = instances[0]; + var instanceAttributes = firstInstance.attributes; + + var i; + var name; + var attribute; + + for (i = 0; i < length; ++i) { + name = names[i]; + attribute = instanceAttributes[name]; + + attributeIndices[name] = i; + attributes[i] = { + functionName : 'czm_batchTable_' + name, + componentDatatype : attribute.componentDatatype, + componentsPerAttribute : attribute.componentsPerAttribute, + normalize : attribute.normalize + }; + } + + if (allowPicking) { + attributes[attributesLength - 1] = { + functionName : 'czm_batchTable_pickColor', + componentDatatype : ComponentDatatype.UNSIGNED_BYTE, + componentsPerAttribute : 4, + normalize : true + }; + } + + var batchTable = new BatchTable(attributes, numberOfInstances); + + for (i = 0; i < numberOfInstances; ++i) { + var instance = instances[i]; + instanceAttributes = instance.attributes; + + for (var j = 0; j < length; ++j) { + name = names[j]; + attribute = instanceAttributes[name]; + var value = getAttributeValue(attribute); + var attributeIndex = attributeIndices[name]; + batchTable.setBatchedAttribute(i, attributeIndex, value); + } + + if (allowPicking) { + var pickObject = { + primitive : defaultValue(instance.pickPrimitive, primitive) + }; + + if (defined(instance.id)) { + pickObject.id = instance.id; + } + + var pickId = context.createPickId(pickObject); + primitive._pickIds.push(pickId); + + var pickColor = pickId.color; + var color = scratchGetAttributeCartesian4; + color.x = Color.floatToByte(pickColor.red); + color.y = Color.floatToByte(pickColor.green); + color.z = Color.floatToByte(pickColor.blue); + color.w = Color.floatToByte(pickColor.alpha); + + batchTable.setBatchedAttribute(i, attributesLength - 1, color); + } + } + + primitive._batchTable = batchTable; + primitive._batchTableAttributeIndices = attributeIndices; + } + function cloneAttribute(attribute) { var clonedValues; if (isArray(attribute.values)) { @@ -667,22 +815,38 @@ define([ }; Primitive._appendShowToShader = function(primitive, vertexShaderSource) { - if (!defined(primitive._attributeLocations.show)) { + if (!defined(primitive._batchTableAttributeIndices.show)) { return vertexShaderSource; } var renamedVS = ShaderSource.replaceMain(vertexShaderSource, 'czm_non_show_main'); var showMain = - 'attribute float show;\n' + 'void main() \n' + '{ \n' + ' czm_non_show_main(); \n' + - ' gl_Position *= show; \n' + + ' gl_Position *= czm_batchTable_show; \n' + '}'; return renamedVS + '\n' + showMain; }; + function updateColorAttribute(primitive, vertexShaderSource) { + // some appearances have a color attribute for per vertex color. + // only remove if color is a per instance attribute. + if (!defined(primitive._batchTableAttributeIndices.color)) { + return vertexShaderSource; + } + + if (vertexShaderSource.search(/attribute\s+vec4\s+color;/g) === -1) { + return vertexShaderSource; + } + + var modifiedVS = vertexShaderSource; + modifiedVS = modifiedVS.replace(/attribute\s+vec4\s+color;/g, ''); + modifiedVS = modifiedVS.replace(/(\b)color(\b)/g, '$1czm_batchTable_color(batchId)$2'); + return modifiedVS; + } + function modifyForEncodedNormals(primitive, vertexShaderSource) { if (!primitive.compressVertices) { return vertexShaderSource; @@ -1149,17 +1313,24 @@ define([ var attributeLocations = primitive._attributeLocations; - var vs = Primitive._modifyShaderPosition(primitive, appearance.vertexShaderSource, frameState.scene3DOnly); + var vs = primitive._batchTable.getVertexShaderCallback()(appearance.vertexShaderSource); + vs = Primitive._modifyShaderPosition(primitive, vs, frameState.scene3DOnly); vs = Primitive._appendShowToShader(primitive, vs); + vs = updateColorAttribute(primitive, vs); vs = modifyForEncodedNormals(primitive, vs); var fs = appearance.getFragmentShaderSource(); // Create pick program if (primitive.allowPicking) { + var vsPick = ShaderSource.createPickVertexShaderSource(vs); + + vsPick = vsPick.replace(/attribute\s+vec4\s+pickColor;/g, ''); + vsPick = vsPick.replace(/(\b)pickColor(\b)/g, '$1czm_batchTable_pickColor(batchId)$2'); + primitive._pickSP = ShaderProgram.replaceCache({ context : context, shaderProgram : primitive._pickSP, - vertexShaderSource : ShaderSource.createPickVertexShaderSource(vs), + vertexShaderSource : vsPick, fragmentShaderSource : ShaderSource.createPickFragmentShaderSource(fs, 'varying'), attributeLocations : attributeLocations }); @@ -1205,6 +1376,7 @@ define([ } } var uniforms = combine(appearanceUniformMap, materialUniformMap); + uniforms = primitive._batchTable.getUniformMapCallback()(uniforms); if (defined(primitive.rtcCenter)) { uniforms.u_modifiedModelView = function() { @@ -1440,6 +1612,11 @@ define([ createVertexArray(this, frameState); } + if (!defined(this._batchTable)) { + createBatchTable(this, frameState.context); + } + this._batchTable.update(frameState); + if (!this.show || this._state !== PrimitiveState.COMPLETE) { return; } diff --git a/Source/Scene/PrimitivePipeline.js b/Source/Scene/PrimitivePipeline.js index c4986f352daa..6e6201f83b15 100644 --- a/Source/Scene/PrimitivePipeline.js +++ b/Source/Scene/PrimitivePipeline.js @@ -109,6 +109,37 @@ define([ } } + function addGeometryBatchId(geometry, batchId) { + var attributes = geometry.attributes; + var positionAttr = attributes.position; + var numberOfComponents = positionAttr.values.length / positionAttr.componentsPerAttribute; + + attributes.batchId = new GeometryAttribute({ + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 1, + values : new Float32Array(numberOfComponents) + }); + + var values = attributes.batchId.values; + for (var j = 0; j < numberOfComponents; ++j) { + values[j] = batchId; + } + } + + function addBatchIds(instances) { + var length = instances.length; + + for (var i = 0; i < length; ++i) { + var instance = instances[i]; + if (defined(instance.geometry)) { + addGeometryBatchId(instance.geometry, i); + } else { + addGeometryBatchId(instance.westHemisphereGeometry, i); + addGeometryBatchId(instance.eastHemisphereGeometry, i); + } + } + } + function getCommonPerInstanceAttributeNames(instances) { var length = instances.length; @@ -218,6 +249,8 @@ define([ } } + addBatchIds(instances); + // Add pickColor attribute for picking individual instances if (allowPicking) { addPickColorAttribute(instances, pickIds); diff --git a/Source/Shaders/Appearances/AllMaterialAppearanceVS.glsl b/Source/Shaders/Appearances/AllMaterialAppearanceVS.glsl index 59d74a27b25a..72e2081604ef 100644 --- a/Source/Shaders/Appearances/AllMaterialAppearanceVS.glsl +++ b/Source/Shaders/Appearances/AllMaterialAppearanceVS.glsl @@ -4,6 +4,7 @@ attribute vec3 normal; attribute vec3 tangent; attribute vec3 binormal; attribute vec2 st; +attribute float batchId; varying vec3 v_positionEC; varying vec3 v_normalEC; diff --git a/Source/Shaders/Appearances/BasicMaterialAppearanceVS.glsl b/Source/Shaders/Appearances/BasicMaterialAppearanceVS.glsl index 6fe9772ba516..0d496a877e7c 100644 --- a/Source/Shaders/Appearances/BasicMaterialAppearanceVS.glsl +++ b/Source/Shaders/Appearances/BasicMaterialAppearanceVS.glsl @@ -1,6 +1,7 @@ attribute vec3 position3DHigh; attribute vec3 position3DLow; attribute vec3 normal; +attribute float batchId; varying vec3 v_positionEC; varying vec3 v_normalEC; diff --git a/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl b/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl index 61f12dcb32e2..1bd13c9a5382 100644 --- a/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl +++ b/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.glsl @@ -1,6 +1,7 @@ attribute vec3 position3DHigh; attribute vec3 position3DLow; attribute vec2 st; +attribute float batchId; varying vec3 v_positionMC; varying vec3 v_positionEC; diff --git a/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl b/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl index aa8de58a0ba9..b429e64c6896 100644 --- a/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl +++ b/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.glsl @@ -2,6 +2,7 @@ attribute vec3 position3DHigh; attribute vec3 position3DLow; attribute vec3 normal; attribute vec4 color; +attribute float batchId; varying vec3 v_positionEC; varying vec3 v_normalEC; diff --git a/Source/Shaders/Appearances/PerInstanceFlatColorAppearanceVS.glsl b/Source/Shaders/Appearances/PerInstanceFlatColorAppearanceVS.glsl index 44c759da268e..ce015c678423 100644 --- a/Source/Shaders/Appearances/PerInstanceFlatColorAppearanceVS.glsl +++ b/Source/Shaders/Appearances/PerInstanceFlatColorAppearanceVS.glsl @@ -1,6 +1,7 @@ attribute vec3 position3DHigh; attribute vec3 position3DLow; attribute vec4 color; +attribute float batchId; varying vec4 v_color; diff --git a/Source/Shaders/Appearances/PointAppearanceVS.glsl b/Source/Shaders/Appearances/PointAppearanceVS.glsl index dd4a639ea7fa..4d41d523be98 100644 --- a/Source/Shaders/Appearances/PointAppearanceVS.glsl +++ b/Source/Shaders/Appearances/PointAppearanceVS.glsl @@ -1,6 +1,7 @@ attribute vec3 position3DHigh; attribute vec3 position3DLow; attribute vec3 color; +attribute float batchId; uniform float pointSize; diff --git a/Source/Shaders/Appearances/PolylineColorAppearanceVS.glsl b/Source/Shaders/Appearances/PolylineColorAppearanceVS.glsl index f096e4a0d676..db7c610d10d6 100644 --- a/Source/Shaders/Appearances/PolylineColorAppearanceVS.glsl +++ b/Source/Shaders/Appearances/PolylineColorAppearanceVS.glsl @@ -6,6 +6,7 @@ attribute vec3 nextPosition3DHigh; attribute vec3 nextPosition3DLow; attribute vec2 expandAndWidth; attribute vec4 color; +attribute float batchId; varying vec4 v_color; diff --git a/Source/Shaders/Appearances/PolylineMaterialAppearanceVS.glsl b/Source/Shaders/Appearances/PolylineMaterialAppearanceVS.glsl index 9148abc52bce..dcb40b5ad322 100644 --- a/Source/Shaders/Appearances/PolylineMaterialAppearanceVS.glsl +++ b/Source/Shaders/Appearances/PolylineMaterialAppearanceVS.glsl @@ -6,6 +6,7 @@ attribute vec3 nextPosition3DHigh; attribute vec3 nextPosition3DLow; attribute vec2 expandAndWidth; attribute vec2 st; +attribute float batchId; varying float v_width; varying vec2 v_st; diff --git a/Source/Shaders/Appearances/TexturedMaterialAppearanceVS.glsl b/Source/Shaders/Appearances/TexturedMaterialAppearanceVS.glsl index b606f12a0ef1..19c102bba321 100644 --- a/Source/Shaders/Appearances/TexturedMaterialAppearanceVS.glsl +++ b/Source/Shaders/Appearances/TexturedMaterialAppearanceVS.glsl @@ -2,6 +2,7 @@ attribute vec3 position3DHigh; attribute vec3 position3DLow; attribute vec3 normal; attribute vec2 st; +attribute float batchId; varying vec3 v_positionEC; varying vec3 v_normalEC; From a9c607f43ffe8c95b486d33f9cc8cfb411b78ee7 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 21 Sep 2016 17:02:04 -0400 Subject: [PATCH 127/191] Update getting and setting per instance geometry attributes to use batch table. --- Source/Scene/Primitive.js | 113 +++++++++++--------------------------- 1 file changed, 33 insertions(+), 80 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 2b7750eb75f8..aa56b78e2ea2 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -566,9 +566,8 @@ define([ var scratchGetAttributeCartesian3 = new Cartesian3(); var scratchGetAttributeCartesian4 = new Cartesian4(); - function getAttributeValue(attribute) { - var componentsPerAttribute = attribute.componentsPerAttribute; - var value = attribute.value; + function getAttributeValue(value) { + var componentsPerAttribute = value.length; if (componentsPerAttribute === 1) { return value[0]; } else if (componentsPerAttribute === 2) { @@ -634,7 +633,7 @@ define([ for (var j = 0; j < length; ++j) { name = names[j]; attribute = instanceAttributes[name]; - var value = getAttributeValue(attribute); + var value = getAttributeValue(attribute.value); var attributeIndex = attributeIndices[name]; batchTable.setBatchedAttribute(i, attributeIndex, value); } @@ -1197,7 +1196,6 @@ define([ function createVertexArray(primitive, frameState) { var attributeLocations = primitive._attributeLocations; var geometries = primitive._geometries; - var vaAttributes = primitive._vaAttributes; var scene3DOnly = frameState.scene3DOnly; var context = frameState.context; @@ -1206,24 +1204,12 @@ define([ for (var i = 0; i < length; ++i) { var geometry = geometries[i]; - var attributes = vaAttributes[i]; - var vaLength = attributes.length; - for (var j = 0; j < vaLength; ++j) { - var attribute = attributes[j]; - attribute.vertexBuffer = Buffer.createVertexBuffer({ - context : context, - typedArray : attribute.values, - usage : BufferUsage.DYNAMIC_DRAW}); - delete attribute.values; - } - va.push(VertexArray.fromGeometry({ context : context, geometry : geometry, attributeLocations : attributeLocations, bufferUsage : BufferUsage.STATIC_DRAW, - interleave : primitive._interleave, - vertexArrayAttributes : attributes + interleave : primitive._interleave })); if (defined(primitive._createBoundingVolumeFunction)) { @@ -1447,41 +1433,6 @@ define([ } } - function updatePerInstanceAttributes(primitive) { - if (primitive._dirtyAttributes.length === 0) { - return; - } - - var attributes = primitive._dirtyAttributes; - var length = attributes.length; - for (var i = 0; i < length; ++i) { - var attribute = attributes[i]; - var value = attribute.value; - var indices = attribute.indices; - var indicesLength = indices.length; - for (var j = 0; j < indicesLength; ++j) { - var index = indices[j]; - var offset = index.offset; - var count = index.count; - - var vaAttribute = index.attribute; - var componentDatatype = vaAttribute.componentDatatype; - var componentsPerAttribute = vaAttribute.componentsPerAttribute; - - var typedArray = ComponentDatatype.createTypedArray(componentDatatype, count * componentsPerAttribute); - for (var k = 0; k < count; ++k) { - typedArray.set(value, k * componentsPerAttribute); - } - - var offsetInBytes = offset * componentsPerAttribute * ComponentDatatype.getSizeInBytes(componentDatatype); - vaAttribute.vertexBuffer.copyFromArrayView(typedArray, offsetInBytes); - } - attribute.dirty = false; - } - - attributes.length = 0; - } - function updateBoundingVolumes(primitive, frameState) { // Update bounding volumes for primitives that are sized in pixels. // The pixel size in meters varies based on the distance from the camera. @@ -1600,6 +1551,11 @@ define([ return; } + if (!defined(this._batchTable)) { + createBatchTable(this, frameState.context); + } + this._batchTable.update(frameState); + if (this._state !== PrimitiveState.COMPLETE && this._state !== PrimitiveState.COMBINED) { if (this.asynchronous) { loadAsynchronous(this, frameState); @@ -1612,11 +1568,6 @@ define([ createVertexArray(this, frameState); } - if (!defined(this._batchTable)) { - createBatchTable(this, frameState.context); - } - this._batchTable.update(frameState); - if (!this.show || this._state !== PrimitiveState.COMPLETE) { return; } @@ -1665,36 +1616,34 @@ define([ commandFunc(this, appearance, material, translucent, twoPasses, this._colorCommands, this._pickCommands, frameState); } - updatePerInstanceAttributes(this); - var updateAndQueueCommandsFunc = defaultValue(this._updateAndQueueCommandsFunction, updateAndQueueCommands); updateAndQueueCommandsFunc(this, frameState, this._colorCommands, this._pickCommands, this.modelMatrix, this.cull, this.debugShowBoundingVolume, twoPasses); }; - function createGetFunction(name, perInstanceAttributes) { - var attribute = perInstanceAttributes[name]; + function createGetFunction(batchTable, instanceIndex, attributeIndex) { return function() { - if (defined(attribute) && defined(attribute.value)) { - return perInstanceAttributes[name].value; + var attributeValue = batchTable.getBatchedAttribute(instanceIndex, attributeIndex); + var attribute = batchTable.attributes[attributeIndex]; + var componentsPerAttribute = attribute.componentsPerAttribute; + var value = ComponentDatatype.createTypedArray(attribute.componentDatatype, componentsPerAttribute); + if (defined(attributeValue.constructor.pack)) { + attributeValue.constructor.pack(attributeValue, value, 0); + } else { + value[0] = attributeValue; } - return attribute; + return value; }; } - function createSetFunction(name, perInstanceAttributes, dirtyList) { - return function (value) { + function createSetFunction(batchTable, instanceIndex, attributeIndex) { + return function(value) { //>>includeStart('debug', pragmas.debug); if (!defined(value) || !defined(value.length) || value.length < 1 || value.length > 4) { throw new DeveloperError('value must be and array with length between 1 and 4.'); } //>>includeEnd('debug'); - - var attribute = perInstanceAttributes[name]; - attribute.value = value; - if (!attribute.dirty && attribute.valid) { - dirtyList.push(attribute); - attribute.dirty = true; - } + var attributeValue = getAttributeValue(value); + batchTable.setBatchedAttribute(instanceIndex, attributeIndex, attributeValue); }; } @@ -1718,7 +1667,7 @@ define([ if (!defined(id)) { throw new DeveloperError('id is required'); } - if (!defined(this._perInstanceAttributeLocations)) { + if (!defined(this._batchTable)) { throw new DeveloperError('must call update before calling getGeometryInstanceAttributes'); } //>>includeEnd('debug'); @@ -1738,21 +1687,25 @@ define([ if (index === -1) { return undefined; } + var attributes = this._perInstanceAttributeCache[index]; if (defined(attributes)) { return attributes; } - var perInstanceAttributes = this._perInstanceAttributeLocations[index]; + var batchTable = this._batchTable; + var perInstanceAttributeIndices = this._batchTableAttributeIndices; attributes = {}; var properties = {}; var hasProperties = false; - for (var name in perInstanceAttributes) { - if (perInstanceAttributes.hasOwnProperty(name)) { + for (var name in perInstanceAttributeIndices) { + if (perInstanceAttributeIndices.hasOwnProperty(name)) { + var attributeIndex = perInstanceAttributeIndices[name]; + hasProperties = true; properties[name] = { - get : createGetFunction(name, perInstanceAttributes) + get : createGetFunction(batchTable, index, attributeIndex) }; var createSetter = true; @@ -1777,7 +1730,7 @@ define([ } if (createSetter) { - properties[name].set = createSetFunction(name, perInstanceAttributes, this._dirtyAttributes); + properties[name].set = createSetFunction(batchTable, index, attributeIndex); } } } From 28aa9bbb5c92b7f610dd89b7cf989a11665d2be2 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 21 Sep 2016 17:19:04 -0400 Subject: [PATCH 128/191] Fix primitives with show per instance attribute. --- Source/Scene/Primitive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index aa56b78e2ea2..583f249c60f2 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -823,7 +823,7 @@ define([ 'void main() \n' + '{ \n' + ' czm_non_show_main(); \n' + - ' gl_Position *= czm_batchTable_show; \n' + + ' gl_Position *= czm_batchTable_show(batchId); \n' + '}'; return renamedVS + '\n' + showMain; From 6a4e4f2d58de808d394b4c3e6d6c732f444cea8c Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 21 Sep 2016 17:27:54 -0400 Subject: [PATCH 129/191] Remove pick color attribute that is now in the batch table. Remove packing/unpacking pick ids for transfer to/from web workers. --- Source/Scene/Primitive.js | 27 ---------- Source/Scene/PrimitivePipeline.js | 83 ------------------------------- 2 files changed, 110 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 583f249c60f2..ec9c78a99c3c 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -940,27 +940,6 @@ define([ //>>includeEnd('debug'); } - function createPickIds(context, primitive, instances) { - var pickColors = []; - var length = instances.length; - - for (var i = 0; i < length; ++i) { - var pickObject = { - primitive : defaultValue(instances[i].pickPrimitive, primitive) - }; - - if (defined(instances[i].id)) { - pickObject.id = instances[i].id; - } - - var pickId = context.createPickId(pickObject); - primitive._pickIds.push(pickId); - pickColors.push(pickId.color); - } - - return pickColors; - } - function getUniformFunction(uniforms, name) { return function() { return uniforms[name]; @@ -1057,19 +1036,16 @@ define([ var transferableObjects = []; instances = (isArray(primitive.geometryInstances)) ? primitive.geometryInstances : [primitive.geometryInstances]; - var allowPicking = primitive.allowPicking; var scene3DOnly = frameState.scene3DOnly; var projection = frameState.mapProjection; var promise = combineGeometryTaskProcessor.scheduleTask(PrimitivePipeline.packCombineGeometryParameters({ createGeometryResults : primitive._createGeometryResults, instances : instances, - pickIds : allowPicking ? createPickIds(frameState.context, primitive, instances) : undefined, ellipsoid : projection.ellipsoid, projection : projection, elementIndexUintSupported : frameState.context.elementIndexUint, scene3DOnly : scene3DOnly, - allowPicking : allowPicking, vertexCacheOptimize : primitive.vertexCacheOptimize, compressVertices : primitive.compressVertices, modelMatrix : primitive.modelMatrix, @@ -1154,19 +1130,16 @@ define([ geometries.length = geometryIndex; clonedInstances.length = geometryIndex; - var allowPicking = primitive.allowPicking; var scene3DOnly = frameState.scene3DOnly; var projection = frameState.mapProjection; var result = PrimitivePipeline.combineGeometry({ instances : clonedInstances, invalidInstances : invalidInstances, - pickIds : allowPicking ? createPickIds(frameState.context, primitive, clonedInstances) : undefined, ellipsoid : projection.ellipsoid, projection : projection, elementIndexUintSupported : frameState.context.elementIndexUint, scene3DOnly : scene3DOnly, - allowPicking : allowPicking, vertexCacheOptimize : primitive.vertexCacheOptimize, compressVertices : primitive.compressVertices, modelMatrix : primitive.modelMatrix, diff --git a/Source/Scene/PrimitivePipeline.js b/Source/Scene/PrimitivePipeline.js index 6e6201f83b15..6eb2249a955a 100644 --- a/Source/Scene/PrimitivePipeline.js +++ b/Source/Scene/PrimitivePipeline.js @@ -67,48 +67,6 @@ define([ } } - function addGeometryPickColor(geometry, pickColor) { - var attributes = geometry.attributes; - var positionAttr = attributes.position; - var numberOfComponents = 4 * (positionAttr.values.length / positionAttr.componentsPerAttribute); - - attributes.pickColor = new GeometryAttribute({ - componentDatatype : ComponentDatatype.UNSIGNED_BYTE, - componentsPerAttribute : 4, - normalize : true, - values : new Uint8Array(numberOfComponents) - }); - - var red = Color.floatToByte(pickColor.red); - var green = Color.floatToByte(pickColor.green); - var blue = Color.floatToByte(pickColor.blue); - var alpha = Color.floatToByte(pickColor.alpha); - var values = attributes.pickColor.values; - - for (var j = 0; j < numberOfComponents; j += 4) { - values[j] = red; - values[j + 1] = green; - values[j + 2] = blue; - values[j + 3] = alpha; - } - } - - function addPickColorAttribute(instances, pickIds) { - var length = instances.length; - - for (var i = 0; i < length; ++i) { - var instance = instances[i]; - var pickColor = pickIds[i]; - - if (defined(instance.geometry)) { - addGeometryPickColor(instance.geometry, pickColor); - } else { - addGeometryPickColor(instance.westHemisphereGeometry, pickColor); - addGeometryPickColor(instance.eastHemisphereGeometry, pickColor); - } - } - } - function addGeometryBatchId(geometry, batchId) { var attributes = geometry.attributes; var positionAttr = attributes.position; @@ -217,11 +175,9 @@ define([ function geometryPipeline(parameters) { var instances = parameters.instances; - var pickIds = parameters.pickIds; var projection = parameters.projection; var uintIndexSupport = parameters.elementIndexUintSupported; var scene3DOnly = parameters.scene3DOnly; - var allowPicking = parameters.allowPicking; var vertexCacheOptimize = parameters.vertexCacheOptimize; var compressVertices = parameters.compressVertices; var modelMatrix = parameters.modelMatrix; @@ -251,11 +207,6 @@ define([ addBatchIds(instances); - // Add pickColor attribute for picking individual instances - if (allowPicking) { - addPickColorAttribute(instances, pickIds); - } - // add attributes to the geometry for each per-instance attribute var perInstanceAttributeNames = getCommonPerInstanceAttributeNames(instances); addPerInstanceAttributes(instances, perInstanceAttributeNames); @@ -820,25 +771,6 @@ define([ return result; }; - function packPickIds(pickIds, transferableObjects) { - var length = pickIds.length; - var packedPickIds = new Uint32Array(pickIds.length); - for (var i = 0; i < length; ++i) { - packedPickIds[i] = pickIds[i].toRgba(); - } - transferableObjects.push(packedPickIds.buffer); - return packedPickIds; - } - - function unpackPickIds(packedPickIds) { - var length = packedPickIds.length; - var pickIds = new Array(length); - for (var i = 0; i < length; i++) { - pickIds[i] = Color.fromRgba(packedPickIds[i]); - } - return pickIds; - } - // This function was created by simplifying packInstancesForCombine into a count-only operation. function countInstancesForCombine(instances) { var length = instances.length; @@ -1111,20 +1043,13 @@ define([ transferableObjects.push(createGeometryResults[i].packedData.buffer); } - var packedPickIds; - if (parameters.allowPicking) { - packedPickIds = packPickIds(parameters.pickIds, transferableObjects); - } - return { createGeometryResults : parameters.createGeometryResults, packedInstances : packInstancesForCombine(parameters.instances, transferableObjects), - packedPickIds : packedPickIds, ellipsoid : parameters.ellipsoid, isGeographic : parameters.projection instanceof GeographicProjection, elementIndexUintSupported : parameters.elementIndexUintSupported, scene3DOnly : parameters.scene3DOnly, - allowPicking : parameters.allowPicking, vertexCacheOptimize : parameters.vertexCacheOptimize, compressVertices : parameters.compressVertices, modelMatrix : parameters.modelMatrix, @@ -1137,8 +1062,6 @@ define([ */ PrimitivePipeline.unpackCombineGeometryParameters = function(packedParameters) { var instances = unpackInstancesForCombine(packedParameters.packedInstances); - var allowPicking = packedParameters.allowPicking; - var pickIds = allowPicking ? unpackPickIds(packedParameters.packedPickIds) : undefined; var createGeometryResults = packedParameters.createGeometryResults; var length = createGeometryResults.length; var instanceIndex = 0; @@ -1147,7 +1070,6 @@ define([ var invalidInstances = []; var validInstancesIndices = []; var invalidInstancesIndices = []; - var validPickIds = []; for (var resultIndex = 0; resultIndex < length; resultIndex++) { var geometries = PrimitivePipeline.unpackCreateGeometryResults(createGeometryResults[resultIndex]); @@ -1160,9 +1082,6 @@ define([ instance.geometry = geometry; validInstances.push(instance); validInstancesIndices.push(instanceIndex); - if (allowPicking) { - validPickIds.push(pickIds[instanceIndex]); - } } else { invalidInstances.push(instance); invalidInstancesIndices.push(instanceIndex); @@ -1180,12 +1099,10 @@ define([ invalidInstances : invalidInstances, validInstancesIndices : validInstancesIndices, invalidInstancesIndices : invalidInstancesIndices, - pickIds : validPickIds, ellipsoid : ellipsoid, projection : projection, elementIndexUintSupported : packedParameters.elementIndexUintSupported, scene3DOnly : packedParameters.scene3DOnly, - allowPicking : packedParameters.allowPicking, vertexCacheOptimize : packedParameters.vertexCacheOptimize, compressVertices : packedParameters.compressVertices, modelMatrix : Matrix4.clone(packedParameters.modelMatrix), From f975f289746addc989ad252dd6001da4b78d4bd2 Mon Sep 17 00:00:00 2001 From: Chris Cooper Date: Thu, 22 Sep 2016 09:13:05 +1000 Subject: [PATCH 130/191] fix upsample clamping spec --- Specs/Core/HeightmapTerrainDataSpec.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Specs/Core/HeightmapTerrainDataSpec.js b/Specs/Core/HeightmapTerrainDataSpec.js index 3253759b5608..809ba6b61585 100644 --- a/Specs/Core/HeightmapTerrainDataSpec.js +++ b/Specs/Core/HeightmapTerrainDataSpec.js @@ -247,11 +247,17 @@ defineSuite([ }); }); - it('upsample clamps negative data', function() { + it('upsample clamps out of range data', function() { data = new HeightmapTerrainData({ buffer : new Float32Array([-1.0, -2.0, -3.0, -4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0]), width : 4, - height : 4 + height : 4, + structure : { + stride: 1, + elementsPerHeight: 1, + lowestEncodedHeight : 1, + highestEncodedHeight : 7 + } }); return data.createMesh(tilingScheme, 0, 0, 0, 1).then(function() { @@ -260,7 +266,7 @@ defineSuite([ expect(upsampled.wasCreatedByUpsampling()).toBe(true); expect(upsampled._width).toBe(4); expect(upsampled._height).toBe(4); - expect(upsampled._buffer).toEqual([0, 0, 0, 0, 2, 1.5, 2, 1.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5]); + expect(upsampled._buffer).toEqual([1, 1, 1, 1, 2, 1.5, 2, 1.5, 5, 5.5, 6, 6.5, 7, 7, 7, 7]); }); }); }); From 49a834df70fe591302a601b69862979818aa681e Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Thu, 22 Sep 2016 11:04:22 +1000 Subject: [PATCH 131/191] Add doc for new structure options, fix off-by-one. --- Source/Core/ArcGisImageServerTerrainProvider.js | 2 +- Source/Core/CesiumTerrainProvider.js | 2 +- Source/Core/HeightmapTerrainData.js | 8 ++++++++ Source/Core/HeightmapTessellator.js | 8 ++++++++ Source/Core/VRTheWorldTerrainProvider.js | 2 +- 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Source/Core/ArcGisImageServerTerrainProvider.js b/Source/Core/ArcGisImageServerTerrainProvider.js index 356d54ea0ad2..8354bcacc8e4 100644 --- a/Source/Core/ArcGisImageServerTerrainProvider.js +++ b/Source/Core/ArcGisImageServerTerrainProvider.js @@ -93,7 +93,7 @@ define([ elementMultiplier : 256.0, isBigEndian : true, lowestEncodedHeight : 0, - highestEncodedHeight : 256 * 256 * 256 + highestEncodedHeight : 256 * 256 * 256 - 1 }; this._errorEvent = new Event(); diff --git a/Source/Core/CesiumTerrainProvider.js b/Source/Core/CesiumTerrainProvider.js index 0db08a0da84c..61955ae9bd01 100644 --- a/Source/Core/CesiumTerrainProvider.js +++ b/Source/Core/CesiumTerrainProvider.js @@ -182,7 +182,7 @@ define([ elementMultiplier : 256.0, isBigEndian : false, lowestEncodedHeight : 0, - highestEncodedHeight : 256 * 256 + highestEncodedHeight : 256 * 256 - 1 }; that._hasWaterMask = true; that._requestWaterMask = true; diff --git a/Source/Core/HeightmapTerrainData.js b/Source/Core/HeightmapTerrainData.js index 8d8a541bac13..1dad3a8a2632 100644 --- a/Source/Core/HeightmapTerrainData.js +++ b/Source/Core/HeightmapTerrainData.js @@ -73,6 +73,14 @@ define([ * @param {Boolean} [options.structure.isBigEndian=false] Indicates endianness of the elements in the buffer when the * stride property is greater than 1. If this property is false, the first element is the * low-order element. If it is true, the first element is the high-order element. + * @param {Number} [options.structure.lowestEncodedHeight] The lowest value that can be stored in the height buffer. Any heights that are lower + * than this value after encoding with the `heightScale` and `heightOffset` are clamped to this value. For example, if the height + * buffer is a `Uint16Array`, this value should be 0 because a `Uint16Array` cannot store negative numbers. If this parameter is + * not specified, no minimum value is enforced. + * @param {Number} [options.structure.highestEncodedHeight] The highest value that can be stored in the height buffer. Any heights that are higher + * than this value after encoding with the `heightScale` and `heightOffset` are clamped to this value. For example, if the height + * buffer is a `Uint16Array`, this value should be `256 * 256 - 1` or 65535 because a `Uint16Array` cannot store numbers larger + * than 65535. If this parameter is not specified, no maximum value is enforced. * @param {Boolean} [options.createdByUpsampling=false] True if this instance was created by upsampling another instance; * otherwise, false. * diff --git a/Source/Core/HeightmapTessellator.js b/Source/Core/HeightmapTessellator.js index fbb28c43ebb7..fc478f62a2b8 100644 --- a/Source/Core/HeightmapTessellator.js +++ b/Source/Core/HeightmapTessellator.js @@ -101,6 +101,14 @@ define([ * `height = buffer[index] + buffer[index + 1] * 256 + buffer[index + 2] * 256 * 256 + buffer[index + 3] * 256 * 256 * 256` * This is assuming that the isBigEndian property is false. If it is true, the order of the * elements is reversed. + * @param {Number} [options.structure.lowestEncodedHeight] The lowest value that can be stored in the height buffer. Any heights that are lower + * than this value after encoding with the `heightScale` and `heightOffset` are clamped to this value. For example, if the height + * buffer is a `Uint16Array`, this value should be 0 because a `Uint16Array` cannot store negative numbers. If this parameter is + * not specified, no minimum value is enforced. + * @param {Number} [options.structure.highestEncodedHeight] The highest value that can be stored in the height buffer. Any heights that are higher + * than this value after encoding with the `heightScale` and `heightOffset` are clamped to this value. For example, if the height + * buffer is a `Uint16Array`, this value should be `256 * 256 - 1` or 65535 because a `Uint16Array` cannot store numbers larger + * than 65535. If this parameter is not specified, no maximum value is enforced. * @param {Boolean} [options.structure.isBigEndian=false] Indicates endianness of the elements in the buffer when the * stride property is greater than 1. If this property is false, the first element is the * low-order element. If it is true, the first element is the high-order element. diff --git a/Source/Core/VRTheWorldTerrainProvider.js b/Source/Core/VRTheWorldTerrainProvider.js index b2d86e6b47f3..f7b27be75a37 100644 --- a/Source/Core/VRTheWorldTerrainProvider.js +++ b/Source/Core/VRTheWorldTerrainProvider.js @@ -92,7 +92,7 @@ define([ elementMultiplier : 256.0, isBigEndian : true, lowestEncodedHeight : 0, - highestEncodedHeight : 256 * 256 * 256 + highestEncodedHeight : 256 * 256 * 256 - 1 }; var credit = options.credit; From 81a857b07857f5458c2650d96a8f86c33f073d4c Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Thu, 22 Sep 2016 11:04:22 +1000 Subject: [PATCH 132/191] Add doc for new structure options, fix off-by-one. --- Source/Core/ArcGisImageServerTerrainProvider.js | 2 +- Source/Core/CesiumTerrainProvider.js | 2 +- Source/Core/HeightmapTerrainData.js | 8 ++++++++ Source/Core/HeightmapTessellator.js | 8 ++++++++ Source/Core/VRTheWorldTerrainProvider.js | 2 +- 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Source/Core/ArcGisImageServerTerrainProvider.js b/Source/Core/ArcGisImageServerTerrainProvider.js index 356d54ea0ad2..8354bcacc8e4 100644 --- a/Source/Core/ArcGisImageServerTerrainProvider.js +++ b/Source/Core/ArcGisImageServerTerrainProvider.js @@ -93,7 +93,7 @@ define([ elementMultiplier : 256.0, isBigEndian : true, lowestEncodedHeight : 0, - highestEncodedHeight : 256 * 256 * 256 + highestEncodedHeight : 256 * 256 * 256 - 1 }; this._errorEvent = new Event(); diff --git a/Source/Core/CesiumTerrainProvider.js b/Source/Core/CesiumTerrainProvider.js index 0db08a0da84c..61955ae9bd01 100644 --- a/Source/Core/CesiumTerrainProvider.js +++ b/Source/Core/CesiumTerrainProvider.js @@ -182,7 +182,7 @@ define([ elementMultiplier : 256.0, isBigEndian : false, lowestEncodedHeight : 0, - highestEncodedHeight : 256 * 256 + highestEncodedHeight : 256 * 256 - 1 }; that._hasWaterMask = true; that._requestWaterMask = true; diff --git a/Source/Core/HeightmapTerrainData.js b/Source/Core/HeightmapTerrainData.js index 8d8a541bac13..1dad3a8a2632 100644 --- a/Source/Core/HeightmapTerrainData.js +++ b/Source/Core/HeightmapTerrainData.js @@ -73,6 +73,14 @@ define([ * @param {Boolean} [options.structure.isBigEndian=false] Indicates endianness of the elements in the buffer when the * stride property is greater than 1. If this property is false, the first element is the * low-order element. If it is true, the first element is the high-order element. + * @param {Number} [options.structure.lowestEncodedHeight] The lowest value that can be stored in the height buffer. Any heights that are lower + * than this value after encoding with the `heightScale` and `heightOffset` are clamped to this value. For example, if the height + * buffer is a `Uint16Array`, this value should be 0 because a `Uint16Array` cannot store negative numbers. If this parameter is + * not specified, no minimum value is enforced. + * @param {Number} [options.structure.highestEncodedHeight] The highest value that can be stored in the height buffer. Any heights that are higher + * than this value after encoding with the `heightScale` and `heightOffset` are clamped to this value. For example, if the height + * buffer is a `Uint16Array`, this value should be `256 * 256 - 1` or 65535 because a `Uint16Array` cannot store numbers larger + * than 65535. If this parameter is not specified, no maximum value is enforced. * @param {Boolean} [options.createdByUpsampling=false] True if this instance was created by upsampling another instance; * otherwise, false. * diff --git a/Source/Core/HeightmapTessellator.js b/Source/Core/HeightmapTessellator.js index fbb28c43ebb7..fc478f62a2b8 100644 --- a/Source/Core/HeightmapTessellator.js +++ b/Source/Core/HeightmapTessellator.js @@ -101,6 +101,14 @@ define([ * `height = buffer[index] + buffer[index + 1] * 256 + buffer[index + 2] * 256 * 256 + buffer[index + 3] * 256 * 256 * 256` * This is assuming that the isBigEndian property is false. If it is true, the order of the * elements is reversed. + * @param {Number} [options.structure.lowestEncodedHeight] The lowest value that can be stored in the height buffer. Any heights that are lower + * than this value after encoding with the `heightScale` and `heightOffset` are clamped to this value. For example, if the height + * buffer is a `Uint16Array`, this value should be 0 because a `Uint16Array` cannot store negative numbers. If this parameter is + * not specified, no minimum value is enforced. + * @param {Number} [options.structure.highestEncodedHeight] The highest value that can be stored in the height buffer. Any heights that are higher + * than this value after encoding with the `heightScale` and `heightOffset` are clamped to this value. For example, if the height + * buffer is a `Uint16Array`, this value should be `256 * 256 - 1` or 65535 because a `Uint16Array` cannot store numbers larger + * than 65535. If this parameter is not specified, no maximum value is enforced. * @param {Boolean} [options.structure.isBigEndian=false] Indicates endianness of the elements in the buffer when the * stride property is greater than 1. If this property is false, the first element is the * low-order element. If it is true, the first element is the high-order element. diff --git a/Source/Core/VRTheWorldTerrainProvider.js b/Source/Core/VRTheWorldTerrainProvider.js index b2d86e6b47f3..f7b27be75a37 100644 --- a/Source/Core/VRTheWorldTerrainProvider.js +++ b/Source/Core/VRTheWorldTerrainProvider.js @@ -92,7 +92,7 @@ define([ elementMultiplier : 256.0, isBigEndian : true, lowestEncodedHeight : 0, - highestEncodedHeight : 256 * 256 * 256 + highestEncodedHeight : 256 * 256 * 256 - 1 }; var credit = options.credit; From 684475923fe51b5e4d1b6e5cd242da451664b633 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Thu, 22 Sep 2016 11:11:11 +1000 Subject: [PATCH 133/191] Update CHANGES.md. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index e2124ba1d132..e036ffa28de2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ Change Log * Added `DebugCameraPrimitive` to visualize the view frustum of a camera. * Fixed touch events for the timeline [#4305](https://github.com/AnalyticalGraphicsInc/cesium/pull/4305) * Removed the default gamma correction for Bing Maps aerial imagery, because we no longer think it is an improvement in current versions of the tiles. To restore the previous look, set the `defaultGamma` property of your `BingMapsImageryProvider` instance to 1.3. +* Fixed a bug in `AttributeCompression.compressTextureCoordinates` and `decompressTextureCoordinates` that could cause a small inaccuracy in the encoded texture coordinates. ### 1.25 - 2016-09-01 From 66b347e896f0f2e2f1d863ca918a5a67faae09a7 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Thu, 22 Sep 2016 11:42:10 +1000 Subject: [PATCH 134/191] Add specs. --- Specs/Core/AttributeCompressionSpec.js | 33 ++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/Specs/Core/AttributeCompressionSpec.js b/Specs/Core/AttributeCompressionSpec.js index 1a37151f3380..574bda8995bf 100644 --- a/Specs/Core/AttributeCompressionSpec.js +++ b/Specs/Core/AttributeCompressionSpec.js @@ -490,24 +490,49 @@ defineSuite([ it('compresses texture coordinates', function() { var coords = new Cartesian2(0.5, 0.5); - expect(AttributeCompression.decompressTextureCoordinates(AttributeCompression.compressTextureCoordinates(coords), new Cartesian2())).toEqual(coords); + expect(AttributeCompression.decompressTextureCoordinates(AttributeCompression.compressTextureCoordinates(coords), new Cartesian2())).toEqualEpsilon(coords, 1.0 / 4096.0); }); - + it('compress texture coordinates throws without texture coordinates', function() { expect(function() { AttributeCompression.compressTextureCoordinates(undefined); }).toThrowDeveloperError(); }); - + it('decompress texture coordinates throws without encoded texture coordinates', function() { expect(function() { AttributeCompression.decompressTextureCoordinates(undefined, new Cartesian2()); }).toThrowDeveloperError(); }); - + it('decompress texture coordinates throws without result', function() { expect(function() { AttributeCompression.decompressTextureCoordinates(0.0, undefined); }).toThrowDeveloperError(); }); + + it('compresses/decompresses 1.0', function() { + var coords = new Cartesian2(1.0, 1.0); + expect(AttributeCompression.decompressTextureCoordinates(AttributeCompression.compressTextureCoordinates(coords), new Cartesian2())).toEqual(coords); + }); + + it('compresses/decompresses 0.0', function() { + var coords = new Cartesian2(1.0, 1.0); + expect(AttributeCompression.decompressTextureCoordinates(AttributeCompression.compressTextureCoordinates(coords), new Cartesian2())).toEqual(coords); + }); + + it('compresses/decompresses 0.5 / 1.0', function() { + var coords = new Cartesian2(0.5, 1.0); + expect(AttributeCompression.decompressTextureCoordinates(AttributeCompression.compressTextureCoordinates(coords), new Cartesian2())).toEqualEpsilon(coords, 1.0 / 4095.0); + }); + + it('compresses/decompresses 1.0 / 0.5', function() { + var coords = new Cartesian2(1.0, 0.5); + expect(AttributeCompression.decompressTextureCoordinates(AttributeCompression.compressTextureCoordinates(coords), new Cartesian2())).toEqualEpsilon(coords, 1.0 / 4095.0); + }); + + it('compresses/decompresses values very close but not equal to 1.0', function() { + var coords = new Cartesian2(0.99999999999999, 0.99999999999999); + expect(AttributeCompression.decompressTextureCoordinates(AttributeCompression.compressTextureCoordinates(coords), new Cartesian2())).toEqualEpsilon(coords, 1.0 / 4095.0); + }); }); From 02524f0dfd21c3c3de379014fa9382a9af4607c1 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Thu, 22 Sep 2016 12:05:08 +1000 Subject: [PATCH 135/191] Fix test failures. --- Specs/Core/TerrainEncodingSpec.js | 8 ++++---- Specs/Renderer/BuiltinFunctionsSpec.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Specs/Core/TerrainEncodingSpec.js b/Specs/Core/TerrainEncodingSpec.js index e2f4b3195bf0..9928217ae848 100644 --- a/Specs/Core/TerrainEncodingSpec.js +++ b/Specs/Core/TerrainEncodingSpec.js @@ -183,7 +183,7 @@ defineSuite([ expect(encoding.getStride()).toEqual(3); expect(buffer.length).toEqual(encoding.getStride()); - expect(encoding.decodeTextureCoordinates(buffer, 0)).toEqualEpsilon(texCoords, CesiumMath.EPSILON14); + expect(encoding.decodeTextureCoordinates(buffer, 0)).toEqualEpsilon(texCoords, 1.0 / 4095.0); }); it('encodes textureCoordinates with quantization and normals', function() { @@ -198,7 +198,7 @@ defineSuite([ expect(encoding.getStride()).toEqual(4); expect(buffer.length).toEqual(encoding.getStride()); - expect(encoding.decodeTextureCoordinates(buffer, 0)).toEqualEpsilon(texCoords, CesiumMath.EPSILON14); + expect(encoding.decodeTextureCoordinates(buffer, 0)).toEqualEpsilon(texCoords, 1.0 / 4095.0); }); it('encodes height with quantization and without normals', function() { @@ -214,7 +214,7 @@ defineSuite([ expect(encoding.getStride()).toEqual(3); expect(buffer.length).toEqual(encoding.getStride()); - expect(encoding.decodeHeight(buffer, 0)).toEqualEpsilon(height, CesiumMath.EPSILON14); + expect(encoding.decodeHeight(buffer, 0)).toEqualEpsilon(height, 200.0 / 4095.0); }); it('encodes height with quantization and normals', function() { @@ -230,7 +230,7 @@ defineSuite([ expect(encoding.getStride()).toEqual(4); expect(buffer.length).toEqual(encoding.getStride()); - expect(encoding.decodeHeight(buffer, 0)).toEqualEpsilon(height, CesiumMath.EPSILON14); + expect(encoding.decodeHeight(buffer, 0)).toEqualEpsilon(height, 200.0 / 4095.0); }); it('gets oct-encoded normal', function() { diff --git a/Specs/Renderer/BuiltinFunctionsSpec.js b/Specs/Renderer/BuiltinFunctionsSpec.js index 9ff5c55e04d3..24387af25124 100644 --- a/Specs/Renderer/BuiltinFunctionsSpec.js +++ b/Specs/Renderer/BuiltinFunctionsSpec.js @@ -219,7 +219,7 @@ defineSuite([ it('has czm_decompressTextureCoordinates', function() { var fs = 'void main() { ' + - ' gl_FragColor = vec4(czm_decompressTextureCoordinates(8390656.0) == vec2(0.5, 0.5)); ' + + ' gl_FragColor = vec4(czm_decompressTextureCoordinates(8386559.0) == vec2(0.4998779, 0.4998779)); ' + '}'; context.verifyDrawForSpecs(fs); }); From b2f64b244536c6618ec75f9f50165e7a32bf946f Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Thu, 22 Sep 2016 12:15:35 +1000 Subject: [PATCH 136/191] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index e2124ba1d132..8d1c21265b6b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ Change Log * Added `DebugCameraPrimitive` to visualize the view frustum of a camera. * Fixed touch events for the timeline [#4305](https://github.com/AnalyticalGraphicsInc/cesium/pull/4305) * Removed the default gamma correction for Bing Maps aerial imagery, because we no longer think it is an improvement in current versions of the tiles. To restore the previous look, set the `defaultGamma` property of your `BingMapsImageryProvider` instance to 1.3. +* Fixed a bug that could lead to incorrect terrain heights when using `HeightmapTerrainData` with an encoding in which actual heights were equal to the minimum representable height. ### 1.25 - 2016-09-01 From 13a32ca4a0c6fdc025c63cf4f1ed79bb8bef68a0 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Thu, 22 Sep 2016 07:30:28 -0400 Subject: [PATCH 137/191] chore(package): update electron-prebuilt to version 1.4.1 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 441ccced29f6..2b00af309247 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "bluebird": "3.4.6", "compressible": "2.0.8", "compression": "1.6.2", - "electron-prebuilt": "1.4.0", + "electron-prebuilt": "1.4.1", "event-stream": "3.3.4", "express": "4.14.0", "globby": "6.0.0", From f2eb439c660c7eb2db78a2918186f96f064a1327 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 22 Sep 2016 10:18:00 -0400 Subject: [PATCH 138/191] Remove per instance vertex attribute packing/unpacking. --- Source/Scene/Primitive.js | 69 +---- Source/Scene/PrimitivePipeline.js | 440 +----------------------------- 2 files changed, 5 insertions(+), 504 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index ec9c78a99c3c..77438ec61efb 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -311,21 +311,17 @@ define([ this._state = PrimitiveState.READY; this._geometries = []; - this._vaAttributes = undefined; this._error = undefined; this._numberOfInstances = 0; - this._validModelMatrix = false; this._boundingSpheres = []; this._boundingSphereWC = []; this._boundingSphereCV = []; this._boundingSphere2D = []; this._boundingSphereMorph = []; - this._perInstanceAttributeLocations = undefined; this._perInstanceAttributeCache = []; this._instanceIds = []; this._lastPerInstanceAttributeIndex = 0; - this._dirtyAttributes = []; this._va = []; this._attributeLocations = undefined; @@ -703,34 +699,10 @@ define([ }); } - function cloneGeometryInstanceAttribute(attribute) { - var clonedValue; - if (isArray(attribute.value)) { - clonedValue = attribute.value.slice(0); - } else { - clonedValue = new attribute.value.constructor(attribute.value); - } - return new GeometryInstanceAttribute({ - componentDatatype : attribute.componentDatatype, - componentsPerAttribute : attribute.componentsPerAttribute, - normalize : attribute.normalize, - value : clonedValue - }); - } - function cloneInstance(instance, geometry) { - var attributes = instance.attributes; - var newAttributes = {}; - for (var property in attributes) { - if (attributes.hasOwnProperty(property)) { - newAttributes[property] = cloneGeometryInstanceAttribute(attributes[property]); - } - } - return new GeometryInstance({ geometry : geometry, modelMatrix : Matrix4.clone(instance.modelMatrix), - attributes : newAttributes, pickPrimitive : instance.pickPrimitive, id : instance.id }); @@ -1059,28 +1031,11 @@ define([ var result = PrimitivePipeline.unpackCombineGeometryResults(packedResult); primitive._geometries = result.geometries; primitive._attributeLocations = result.attributeLocations; - primitive._vaAttributes = result.vaAttributes; - primitive._perInstanceAttributeLocations = result.perInstanceAttributeLocations; primitive.modelMatrix = Matrix4.clone(result.modelMatrix, primitive.modelMatrix); - primitive._validModelMatrix = !Matrix4.equals(primitive.modelMatrix, Matrix4.IDENTITY); primitive._pickOffsets = result.pickOffsets; - var validInstancesIndices = packedResult.validInstancesIndices; - var invalidInstancesIndices = packedResult.invalidInstancesIndices; - var instanceIds = primitive._instanceIds; - var reorderedInstanceIds = new Array(instanceIds.length); - - var validLength = validInstancesIndices.length; - for (var i = 0; i < validLength; ++i) { - reorderedInstanceIds[i] = instanceIds[validInstancesIndices[i]]; - } - - var invalidLength = invalidInstancesIndices.length; - for (var j = 0; j < invalidLength; ++j) { - reorderedInstanceIds[validLength + j] = instanceIds[invalidInstancesIndices[j]]; - } - - primitive._instanceIds = reorderedInstanceIds; + // TODO + //var invalidInstancesIndices = packedResult.invalidInstancesIndices; if (defined(primitive._geometries)) { primitive._state = PrimitiveState.COMBINED; @@ -1096,11 +1051,7 @@ define([ function loadSynchronous(primitive, frameState) { var instances = (isArray(primitive.geometryInstances)) ? primitive.geometryInstances : [primitive.geometryInstances]; var length = primitive._numberOfInstances = instances.length; - - var geometries = new Array(length); var clonedInstances = new Array(length); - - var invalidInstances = []; var instanceIds = primitive._instanceIds; var instance; @@ -1119,15 +1070,12 @@ define([ } if (defined(createdGeometry)) { - geometries[geometryIndex] = createdGeometry; clonedInstances[geometryIndex++] = cloneInstance(instance, createdGeometry); - instanceIds.push(instance.id); - } else { - invalidInstances.push(instance); } + + instanceIds.push(instance.id); } - geometries.length = geometryIndex; clonedInstances.length = geometryIndex; var scene3DOnly = frameState.scene3DOnly; @@ -1135,7 +1083,6 @@ define([ var result = PrimitivePipeline.combineGeometry({ instances : clonedInstances, - invalidInstances : invalidInstances, ellipsoid : projection.ellipsoid, projection : projection, elementIndexUintSupported : frameState.context.elementIndexUint, @@ -1148,17 +1095,9 @@ define([ primitive._geometries = result.geometries; primitive._attributeLocations = result.attributeLocations; - primitive._vaAttributes = result.vaAttributes; - primitive._perInstanceAttributeLocations = result.vaAttributeLocations; primitive.modelMatrix = Matrix4.clone(result.modelMatrix, primitive.modelMatrix); - primitive._validModelMatrix = !Matrix4.equals(primitive.modelMatrix, Matrix4.IDENTITY); primitive._pickOffsets = result.pickOffsets; - for (i = 0; i < invalidInstances.length; ++i) { - instance = invalidInstances[i]; - instanceIds.push(instance.id); - } - if (defined(primitive._geometries)) { primitive._state = PrimitiveState.COMBINED; } else { diff --git a/Source/Scene/PrimitivePipeline.js b/Source/Scene/PrimitivePipeline.js index 6eb2249a955a..ed4e31a014a2 100644 --- a/Source/Scene/PrimitivePipeline.js +++ b/Source/Scene/PrimitivePipeline.js @@ -98,81 +98,6 @@ define([ } } - function getCommonPerInstanceAttributeNames(instances) { - var length = instances.length; - - var attributesInAllInstances = []; - var attributes0 = instances[0].attributes; - var name; - - for (name in attributes0) { - if (attributes0.hasOwnProperty(name)) { - var attribute = attributes0[name]; - var inAllInstances = true; - - // Does this same attribute exist in all instances? - for (var i = 1; i < length; ++i) { - var otherAttribute = instances[i].attributes[name]; - - if (!defined(otherAttribute) || - (attribute.componentDatatype !== otherAttribute.componentDatatype) || - (attribute.componentsPerAttribute !== otherAttribute.componentsPerAttribute) || - (attribute.normalize !== otherAttribute.normalize)) { - - inAllInstances = false; - break; - } - } - - if (inAllInstances) { - attributesInAllInstances.push(name); - } - } - } - - return attributesInAllInstances; - } - - function addPerInstanceAttributesToGeometry(instanceAttributes, geometry, names) { - var numberOfVertices = Geometry.computeNumberOfVertices(geometry); - - var namesLength = names.length; - for (var j = 0; j < namesLength; ++j) { - var name = names[j]; - var attribute = instanceAttributes[name]; - var componentDatatype = attribute.componentDatatype; - var value = attribute.value; - var componentsPerAttribute = attribute.componentsPerAttribute; - - var buffer = ComponentDatatype.createTypedArray(componentDatatype, numberOfVertices * componentsPerAttribute); - for (var k = 0; k < numberOfVertices; ++k) { - buffer.set(value, k * componentsPerAttribute); - } - - geometry.attributes[name] = new GeometryAttribute({ - componentDatatype : componentDatatype, - componentsPerAttribute : componentsPerAttribute, - normalize : attribute.normalize, - values : buffer - }); - } - } - - function addPerInstanceAttributes(instances, names) { - var length = instances.length; - for (var i = 0; i < length; ++i) { - var instance = instances[i]; - var instanceAttributes = instance.attributes; - - if (defined(instance.geometry)) { - addPerInstanceAttributesToGeometry(instanceAttributes, instance.geometry, names); - } else { - addPerInstanceAttributesToGeometry(instanceAttributes, instance.westHemisphereGeometry, names); - addPerInstanceAttributesToGeometry(instanceAttributes, instance.eastHemisphereGeometry, names); - } - } - } - function geometryPipeline(parameters) { var instances = parameters.instances; var projection = parameters.projection; @@ -207,10 +132,6 @@ define([ addBatchIds(instances); - // add attributes to the geometry for each per-instance attribute - var perInstanceAttributeNames = getCommonPerInstanceAttributeNames(instances); - addPerInstanceAttributes(instances, perInstanceAttributeNames); - // Optimize for vertex shader caches if (vertexCacheOptimize) { for (i = 0; i < length; ++i) { @@ -283,159 +204,6 @@ define([ return geometries; } - function createPerInstanceVAAttributes(geometry, attributeLocations, names) { - var vaAttributes = []; - var attributes = geometry.attributes; - - var length = names.length; - for (var i = 0; i < length; ++i) { - var name = names[i]; - var attribute = attributes[name]; - - var componentDatatype = attribute.componentDatatype; - if (componentDatatype === ComponentDatatype.DOUBLE) { - componentDatatype = ComponentDatatype.FLOAT; - } - - var typedArray = ComponentDatatype.createTypedArray(componentDatatype, attribute.values); - vaAttributes.push({ - index : attributeLocations[name], - componentDatatype : componentDatatype, - componentsPerAttribute : attribute.componentsPerAttribute, - normalize : attribute.normalize, - values : typedArray - }); - - delete attributes[name]; - } - - return vaAttributes; - } - - function computePerInstanceAttributeLocationsForGeometry(instanceIndex, geometry, instanceAttributes, names, attributeLocations, vertexArrays, indices, offsets, vaIndices) { - var numberOfVertices = Geometry.computeNumberOfVertices(geometry); - - if (!defined(indices[instanceIndex])) { - indices[instanceIndex] = { - boundingSphere : geometry.boundingSphere, - boundingSphereCV : geometry.boundingSphereCV - }; - } - - var namesLength = names.length; - for (var j = 0; j < namesLength; ++j) { - var name = names[j]; - var index = attributeLocations[name]; - - var tempVertexCount = numberOfVertices; - while (tempVertexCount > 0) { - var vaIndex = defaultValue(vaIndices[name], 0); - var va = vertexArrays[vaIndex]; - var vaLength = va.length; - - var attribute; - for (var k = 0; k < vaLength; ++k) { - attribute = va[k]; - if (attribute.index === index) { - break; - } - } - - if (!defined(indices[instanceIndex][name])) { - indices[instanceIndex][name] = { - dirty : false, - valid : true, - value : instanceAttributes[name].value, - indices : [] - }; - } - - var size = attribute.values.length / attribute.componentsPerAttribute; - var offset = defaultValue(offsets[name], 0); - - var count; - if (offset + tempVertexCount < size) { - count = tempVertexCount; - indices[instanceIndex][name].indices.push({ - attribute : attribute, - offset : offset, - count : count - }); - offsets[name] = offset + tempVertexCount; - } else { - count = size - offset; - indices[instanceIndex][name].indices.push({ - attribute : attribute, - offset : offset, - count : count - }); - offsets[name] = 0; - vaIndices[name] = vaIndex + 1; - } - - tempVertexCount -= count; - } - } - } - - function computePerInstanceAttributeLocations(instances, invalidInstances, vertexArrays, attributeLocations, names) { - var indices = []; - - var length = instances.length; - var offsets = {}; - var vaIndices = {}; - - var i; - var instance; - var attributes; - - for (i = 0; i < length; ++i) { - instance = instances[i]; - attributes = instance.attributes; - if (defined(instance.geometry)) { - computePerInstanceAttributeLocationsForGeometry(i, instance.geometry, attributes, names, attributeLocations, vertexArrays, indices, offsets, vaIndices); - } - } - - for (i = 0; i < length; ++i) { - instance = instances[i]; - attributes = instance.attributes; - if (defined(instance.westHemisphereGeometry)) { - computePerInstanceAttributeLocationsForGeometry(i, instance.westHemisphereGeometry, attributes, names, attributeLocations, vertexArrays, indices, offsets, vaIndices); - } - } - - for (i = 0; i < length; ++i) { - instance = instances[i]; - attributes = instance.attributes; - if (defined(instance.eastHemisphereGeometry)) { - computePerInstanceAttributeLocationsForGeometry(i, instance.eastHemisphereGeometry, attributes, names, attributeLocations, vertexArrays, indices, offsets, vaIndices); - } - } - - length = invalidInstances.length; - for (i = 0; i < length; ++i) { - instance = invalidInstances[i]; - attributes = instance.attributes; - - var instanceAttributes = {}; - indices.push(instanceAttributes); - - var namesLength = names.length; - for (var j = 0; j < namesLength; ++j) { - var name = names[j]; - instanceAttributes[name] = { - dirty : false, - valid : false, - value : attributes[name].value, - indices : [] - }; - } - } - - return indices; - } - function createPickOffsets(instances, geometryName, geometries, pickOffsets) { var offset; var indexCount; @@ -496,30 +264,13 @@ define([ PrimitivePipeline.combineGeometry = function(parameters) { var geometries; var attributeLocations; - var perInstanceAttributes; - var perInstanceAttributeNames; - var length; - var instances = parameters.instances; - var invalidInstances = parameters.invalidInstances; if (instances.length > 0) { geometries = geometryPipeline(parameters); attributeLocations = GeometryPipeline.createAttributeLocations(geometries[0]); - - perInstanceAttributeNames = getCommonPerInstanceAttributeNames(instances); - - perInstanceAttributes = []; - length = geometries.length; - for (var i = 0; i < length; ++i) { - var geometry = geometries[i]; - perInstanceAttributes.push(createPerInstanceVAAttributes(geometry, attributeLocations, perInstanceAttributeNames)); - } } - perInstanceAttributeNames = defined(perInstanceAttributeNames) ? perInstanceAttributeNames : getCommonPerInstanceAttributeNames(invalidInstances); - var indices = computePerInstanceAttributeLocations(instances, invalidInstances, perInstanceAttributes, attributeLocations, perInstanceAttributeNames); - var pickOffsets; if (parameters.createPickOffsets && defined(geometries)) { pickOffsets = createInstancePickOffsets(instances, geometries); @@ -529,9 +280,6 @@ define([ geometries : geometries, modelMatrix : parameters.modelMatrix, attributeLocations : attributeLocations, - vaAttributes : perInstanceAttributes, - vaAttributeLocations : indices, - validInstancesIndices : parameters.validInstancesIndices, invalidInstancesIndices : parameters.invalidInstancesIndices, pickOffsets : pickOffsets }; @@ -561,20 +309,6 @@ define([ } } - /** - * @private - */ - function transferPerInstanceAttributes(perInstanceAttributes, transferableObjects) { - var length = perInstanceAttributes.length; - for (var i = 0; i < length; ++i) { - var vaAttributes = perInstanceAttributes[i]; - var vaLength = vaAttributes.length; - for (var j = 0; j < vaLength; ++j) { - transferableObjects.push(vaAttributes[j].values.buffer); - } - } - } - // This function was created by simplifying packCreateGeometryResults into a count-only operation. function countCreateGeometryResults(items) { var count = 1; @@ -875,163 +609,6 @@ define([ return result; } - // This function was created by simplifying packAttributeLocations into a count-only operation. - function countAttributeLocations(attributeLocations) { - var length = attributeLocations.length; - var count = 1 + length; - for (var i = 0; i < length; i++) { - var instance = attributeLocations[i]; - - count += 2; - count += defined(instance.boundingSphere) ? BoundingSphere.packedLength : 0.0; - count += defined(instance.boundingSphereCV) ? BoundingSphere.packedLength : 0.0; - - for ( var propertyName in instance) { - if (instance.hasOwnProperty(propertyName) && defined(instance[propertyName]) && - propertyName !== 'boundingSphere' && propertyName !== 'boundingSphereCV') { - var property = instance[propertyName]; - count += 4 + (property.indices.length * 3) + property.value.length; - } - } - } - return count; - } - - function packAttributeLocations(attributeLocations, transferableObjects) { - var packedData = new Float64Array(countAttributeLocations(attributeLocations)); - var stringTable = []; - var attributeTable = []; - - var stringHash = {}; - var length = attributeLocations.length; - var count = 0; - packedData[count++] = length; - for (var i = 0; i < length; i++) { - var instance = attributeLocations[i]; - - var boundingSphere = instance.boundingSphere; - var hasBoundingSphere = defined(boundingSphere); - packedData[count++] = hasBoundingSphere ? 1.0 : 0.0; - if (hasBoundingSphere) { - BoundingSphere.pack(boundingSphere, packedData, count); - count += BoundingSphere.packedLength; - } - - boundingSphere = instance.boundingSphereCV; - hasBoundingSphere = defined(boundingSphere); - packedData[count++] = hasBoundingSphere ? 1.0 : 0.0; - if (hasBoundingSphere) { - BoundingSphere.pack(boundingSphere, packedData, count); - count += BoundingSphere.packedLength; - } - - var propertiesToWrite = []; - for ( var propertyName in instance) { - if (instance.hasOwnProperty(propertyName) && defined(instance[propertyName]) && - propertyName !== 'boundingSphere' && propertyName !== 'boundingSphereCV') { - propertiesToWrite.push(propertyName); - if (!defined(stringHash[propertyName])) { - stringHash[propertyName] = stringTable.length; - stringTable.push(propertyName); - } - } - } - - packedData[count++] = propertiesToWrite.length; - for (var q = 0; q < propertiesToWrite.length; q++) { - var name = propertiesToWrite[q]; - var property = instance[name]; - packedData[count++] = stringHash[name]; - packedData[count++] = property.valid ? 1.0 : 0.0; - - var indices = property.indices; - var indicesLength = indices.length; - packedData[count++] = indicesLength; - for (var x = 0; x < indicesLength; x++) { - var index = indices[x]; - packedData[count++] = index.count; - packedData[count++] = index.offset; - var tableIndex = attributeTable.indexOf(index.attribute); - if (tableIndex === -1) { - tableIndex = attributeTable.length; - attributeTable.push(index.attribute); - } - packedData[count++] = tableIndex; - } - - packedData[count++] = property.value.length; - packedData.set(property.value, count); - count += property.value.length; - } - } - - transferableObjects.push(packedData.buffer); - - return { - stringTable : stringTable, - packedData : packedData, - attributeTable : attributeTable - }; - } - - function unpackAttributeLocations(packedAttributeLocations, vaAttributes) { - var stringTable = packedAttributeLocations.stringTable; - var attributeTable = packedAttributeLocations.attributeTable; - var packedData = packedAttributeLocations.packedData; - - var attributeLocations = new Array(packedData[0]); - var attributeLocationsIndex = 0; - var i = 1; - var packedDataLength = packedData.length; - while (i < packedDataLength) { - var instance = {}; - - var hasBoundingSphere = packedData[i++] === 1.0; - if (hasBoundingSphere) { - instance.boundingSphere = BoundingSphere.unpack(packedData, i); - i += BoundingSphere.packedLength; - } - - hasBoundingSphere = packedData[i++] === 1.0; - if (hasBoundingSphere) { - instance.boundingSphereCV = BoundingSphere.unpack(packedData, i); - i += BoundingSphere.packedLength; - } - - var numAttributes = packedData[i++]; - for (var x = 0; x < numAttributes; x++) { - var name = stringTable[packedData[i++]]; - var valid = packedData[i++] === 1.0; - - var indicesLength = packedData[i++]; - var indices = indicesLength > 0 ? new Array(indicesLength) : undefined; - for (var indicesIndex = 0; indicesIndex < indicesLength; indicesIndex++) { - var index = {}; - index.count = packedData[i++]; - index.offset = packedData[i++]; - index.attribute = attributeTable[packedData[i++]]; - indices[indicesIndex] = index; - } - - var valueLength = packedData[i++]; - var value = valid ? ComponentDatatype.createTypedArray(indices[0].attribute.componentDatatype, valueLength) : new Array(valueLength); - for (var valueIndex = 0; valueIndex < valueLength; valueIndex++) { - value[valueIndex] = packedData[i++]; - } - - instance[name] = { - dirty : false, - valid : valid, - indices : indices, - value : value - }; - } - attributeLocations[attributeLocationsIndex++] = instance; - } - - return attributeLocations; - } - /** * @private */ @@ -1065,10 +642,6 @@ define([ var createGeometryResults = packedParameters.createGeometryResults; var length = createGeometryResults.length; var instanceIndex = 0; - - var validInstances = []; - var invalidInstances = []; - var validInstancesIndices = []; var invalidInstancesIndices = []; for (var resultIndex = 0; resultIndex < length; resultIndex++) { @@ -1080,10 +653,7 @@ define([ if (defined(geometry)) { instance.geometry = geometry; - validInstances.push(instance); - validInstancesIndices.push(instanceIndex); } else { - invalidInstances.push(instance); invalidInstancesIndices.push(instanceIndex); } @@ -1095,9 +665,7 @@ define([ var projection = packedParameters.isGeographic ? new GeographicProjection(ellipsoid) : new WebMercatorProjection(ellipsoid); return { - instances : validInstances, - invalidInstances : invalidInstances, - validInstancesIndices : validInstancesIndices, + instances : instances, invalidInstancesIndices : invalidInstancesIndices, ellipsoid : ellipsoid, projection : projection, @@ -1116,16 +684,12 @@ define([ PrimitivePipeline.packCombineGeometryResults = function(results, transferableObjects) { if (defined(results.geometries)) { transferGeometries(results.geometries, transferableObjects); - transferPerInstanceAttributes(results.vaAttributes, transferableObjects); } return { geometries : results.geometries, attributeLocations : results.attributeLocations, - vaAttributes : results.vaAttributes, - packedVaAttributeLocations : packAttributeLocations(results.vaAttributeLocations, transferableObjects), modelMatrix : results.modelMatrix, - validInstancesIndices : results.validInstancesIndices, invalidInstancesIndices : results.invalidInstancesIndices, pickOffsets : results.pickOffsets }; @@ -1138,8 +702,6 @@ define([ return { geometries : packedResult.geometries, attributeLocations : packedResult.attributeLocations, - vaAttributes : packedResult.vaAttributes, - perInstanceAttributeLocations : unpackAttributeLocations(packedResult.packedVaAttributeLocations, packedResult.vaAttributes), modelMatrix : packedResult.modelMatrix, pickOffsets : packedResult.pickOffsets }; From 16ee94657e90227be25615171138bd58c6582edf Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 22 Sep 2016 11:32:45 -0400 Subject: [PATCH 139/191] Cluster on add. Update Sandcastle example. --- Apps/Sandcastle/gallery/Clustering.html | 4 +++- Source/DataSources/EntityCluster.js | 31 +++++++++++++++++++------ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/Apps/Sandcastle/gallery/Clustering.html b/Apps/Sandcastle/gallery/Clustering.html index fe2d95a22716..63b9537239ea 100644 --- a/Apps/Sandcastle/gallery/Clustering.html +++ b/Apps/Sandcastle/gallery/Clustering.html @@ -117,7 +117,9 @@ } else { removeListener = dataSource.clustering.clusterEvent.addEventListener(function(cluster, entity) { entity.label = undefined; - entity.billboard = {}; + entity.billboard = { + verticalOrigin : Cesium.VerticalOrigin.BOTTOM + }; if (cluster.length >= 50) { entity.billboard.image = pin50; diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index d10f42007023..00485930f2ee 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -91,6 +91,7 @@ define([ this._enabledDirty = false; this._pixelRangeDirty = false; this._minimumClusterSizeDirty = false; + this._clusterDirty = false; this._cluster = undefined; this._removeEventListener = undefined; @@ -126,7 +127,7 @@ define([ expandBoundingBox(result, pixelRange); - if (!defined(item._labelCollection) && defined(item.id._label)) { + if (!defined(item._labelCollection) && defined(item.id._label) && defined(entityCluster._labelCollection)) { var labelIndex = item.id._labelIndex; var label = entityCluster._labelCollection.get(labelIndex); var labelBBox = Label.getScreenSpaceBoundingBox(label, coord, labelBoundingBoxScratch); @@ -539,6 +540,9 @@ define([ } entity._labelIndex = index; + + this._clusterDirty = true; + return label; }; @@ -561,6 +565,8 @@ define([ label.id = undefined; this._unusedLabelIndices.push(index); + + this._clusterDirty = true; }; /** @@ -595,6 +601,9 @@ define([ } entity._billboardIndex = index; + + this._clusterDirty = true; + return billboard; }; @@ -618,6 +627,8 @@ define([ billboard.image = undefined; this._unusedBillboardIndices.push(index); + + this._clusterDirty = true; }; /** @@ -650,6 +661,9 @@ define([ } entity._pointIndex = index; + + this._clusterDirty = true; + return point; }; @@ -672,6 +686,8 @@ define([ point.id = undefined; this._unusedPointIndices.push(index); + + this._clusterDirty = true; }; function disableCollectionClustering(collection) { @@ -687,7 +703,6 @@ define([ function updateEnable(entityCluster) { if (entityCluster.enabled) { - entityCluster._cluster(); return; } @@ -726,19 +741,21 @@ define([ frameState.commandList = commandList; } - var clustered = false; if (this._enabledDirty) { this._enabledDirty = false; updateEnable(this); - clustered = this._enabled; + this._clusterDirty = true; } if (this._pixelRangeDirty || this._minimumClusterSizeDirty) { this._pixelRangeDirty = false; this._minimumClusterSizeDirty = false; - if (!clustered) { - this._cluster(); - } + this._clusterDirty = true; + } + + if (this._clusterDirty) { + this._clusterDirty = false; + this._cluster(); } if (defined(this._clusterLabelCollection)) { From 127d1c806f8fe09cef605fdb18a1d9e98df6dcfc Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 22 Sep 2016 15:35:41 -0400 Subject: [PATCH 140/191] Remove more pack/unpack per instance attribute code. --- Source/Scene/Primitive.js | 3 -- Source/Scene/PrimitivePipeline.js | 76 ++----------------------------- 2 files changed, 3 insertions(+), 76 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 77438ec61efb..6e988b24262b 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -1034,9 +1034,6 @@ define([ primitive.modelMatrix = Matrix4.clone(result.modelMatrix, primitive.modelMatrix); primitive._pickOffsets = result.pickOffsets; - // TODO - //var invalidInstancesIndices = packedResult.invalidInstancesIndices; - if (defined(primitive._geometries)) { primitive._state = PrimitiveState.COMBINED; } else { diff --git a/Source/Scene/PrimitivePipeline.js b/Source/Scene/PrimitivePipeline.js index ed4e31a014a2..66b81cdbb58b 100644 --- a/Source/Scene/PrimitivePipeline.js +++ b/Source/Scene/PrimitivePipeline.js @@ -505,28 +505,9 @@ define([ return result; }; - // This function was created by simplifying packInstancesForCombine into a count-only operation. - function countInstancesForCombine(instances) { - var length = instances.length; - var count = 1 + (length * 17); - for (var i = 0; i < length; i++) { - var attributes = instances[i].attributes; - for ( var property in attributes) { - if (attributes.hasOwnProperty(property) && defined(attributes[property])) { - var attribute = attributes[property]; - count += 5 + attribute.value.length; - } - } - } - return count; - } - function packInstancesForCombine(instances, transferableObjects) { - var packedData = new Float64Array(countInstancesForCombine(instances)); - var stringHash = {}; - var stringTable = []; - var length = instances.length; + var packedData = new Float64Array(1 + (length * 16)); var count = 0; packedData[count++] = length; for (var i = 0; i < length; i++) { @@ -534,43 +515,14 @@ define([ Matrix4.pack(instance.modelMatrix, packedData, count); count += Matrix4.packedLength; - - var attributes = instance.attributes; - var attributesToWrite = []; - for ( var property in attributes) { - if (attributes.hasOwnProperty(property) && defined(attributes[property])) { - attributesToWrite.push(property); - if (!defined(stringHash[property])) { - stringHash[property] = stringTable.length; - stringTable.push(property); - } - } - } - - packedData[count++] = attributesToWrite.length; - for (var q = 0; q < attributesToWrite.length; q++) { - var name = attributesToWrite[q]; - var attribute = attributes[name]; - packedData[count++] = stringHash[name]; - packedData[count++] = attribute.componentDatatype; - packedData[count++] = attribute.componentsPerAttribute; - packedData[count++] = attribute.normalize; - packedData[count++] = attribute.value.length; - packedData.set(attribute.value, count); - count += attribute.value.length; - } } transferableObjects.push(packedData.buffer); - return { - stringTable : stringTable, - packedData : packedData - }; + return packedData; } function unpackInstancesForCombine(data) { - var packedInstances = data.packedData; - var stringTable = data.stringTable; + var packedInstances = data; var result = new Array(packedInstances[0]); var count = 0; @@ -579,29 +531,7 @@ define([ var modelMatrix = Matrix4.unpack(packedInstances, i); i += Matrix4.packedLength; - var attributes = {}; - var numAttributes = packedInstances[i++]; - for (var x = 0; x < numAttributes; x++) { - var name = stringTable[packedInstances[i++]]; - var componentDatatype = packedInstances[i++]; - var componentsPerAttribute = packedInstances[i++]; - var normalize = packedInstances[i++] !== 0; - var length = packedInstances[i++]; - var value = ComponentDatatype.createTypedArray(componentDatatype, length); - for (var valueIndex = 0; valueIndex < length; valueIndex++) { - value[valueIndex] = packedInstances[i++]; - } - - attributes[name] = { - componentDatatype : componentDatatype, - componentsPerAttribute : componentsPerAttribute, - normalize : normalize, - value : value - }; - } - result[count++] = { - attributes : attributes, modelMatrix : modelMatrix }; } From 3c3febc0014dacb725ae259f9a9fe226687c0480 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 22 Sep 2016 15:57:36 -0400 Subject: [PATCH 141/191] Fix handling invalid geometry. --- Source/Core/GeometryPipeline.js | 2 +- Source/Scene/Primitive.js | 13 ++++------- Source/Scene/PrimitivePipeline.js | 39 +++++++++++++++++-------------- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js index ad9079d35a72..95b1027baef9 100644 --- a/Source/Core/GeometryPipeline.js +++ b/Source/Core/GeometryPipeline.js @@ -1033,7 +1033,7 @@ define([ var instance = instances[i]; if (defined(instance.geometry)) { instanceGeometry.push(instance); - } else { + } else if (defined(instance.westHemisphereGeometry) && defined(instance.eastHemisphereGeometry)) { instanceSplitGeometry.push(instance); } } diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 6e988b24262b..0d75bf49d143 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -700,12 +700,12 @@ define([ } function cloneInstance(instance, geometry) { - return new GeometryInstance({ + return { geometry : geometry, modelMatrix : Matrix4.clone(instance.modelMatrix), pickPrimitive : instance.pickPrimitive, id : instance.id - }); + }; } var positionRegex = /attribute\s+vec(?:3|4)\s+(.*)3DHigh;/g; @@ -1034,7 +1034,7 @@ define([ primitive.modelMatrix = Matrix4.clone(result.modelMatrix, primitive.modelMatrix); primitive._pickOffsets = result.pickOffsets; - if (defined(primitive._geometries)) { + if (defined(primitive._geometries) && primitive._geometries.length > 0) { primitive._state = PrimitiveState.COMBINED; } else { setReady(primitive, frameState, PrimitiveState.FAILED, undefined); @@ -1066,10 +1066,7 @@ define([ createdGeometry = geometry.constructor.createGeometry(geometry); } - if (defined(createdGeometry)) { - clonedInstances[geometryIndex++] = cloneInstance(instance, createdGeometry); - } - + clonedInstances[geometryIndex++] = cloneInstance(instance, createdGeometry); instanceIds.push(instance.id); } @@ -1095,7 +1092,7 @@ define([ primitive.modelMatrix = Matrix4.clone(result.modelMatrix, primitive.modelMatrix); primitive._pickOffsets = result.pickOffsets; - if (defined(primitive._geometries)) { + if (defined(primitive._geometries) && primitive._geometries.length > 0) { primitive._state = PrimitiveState.COMBINED; } else { setReady(primitive, frameState, PrimitiveState.FAILED, undefined); diff --git a/Source/Scene/PrimitivePipeline.js b/Source/Scene/PrimitivePipeline.js index 66b81cdbb58b..eb3e92ce6ac0 100644 --- a/Source/Scene/PrimitivePipeline.js +++ b/Source/Scene/PrimitivePipeline.js @@ -59,6 +59,9 @@ define([ if (toWorld) { for (i = 0; i < length; ++i) { + if (!defined(instances[i].geometry)) { + continue; + } GeometryPipeline.transformToWorldCoordinates(instances[i]); } } else { @@ -91,7 +94,7 @@ define([ var instance = instances[i]; if (defined(instance.geometry)) { addGeometryBatchId(instance.geometry, i); - } else { + } else if (defined(instance.westHemisphereGeometry) && defined(instance.eastHemisphereGeometry)) { addGeometryBatchId(instance.westHemisphereGeometry, i); addGeometryBatchId(instance.eastHemisphereGeometry, i); } @@ -109,12 +112,19 @@ define([ var i; var geometry; + var primitiveType; var length = instances.length; - var primitiveType = instances[0].geometry.primitiveType; + + for (i = 0 ; i < length; ++i) { + if (defined(instances[i].geometry)) { + primitiveType = instances[i].geometry.primitiveType; + break; + } + } //>>includeStart('debug', pragmas.debug); for (i = 1; i < length; ++i) { - if (instances[i].geometry.primitiveType !== primitiveType) { + if (defined(instances[i].geometry) && instances[i].geometry.primitiveType !== primitiveType) { throw new DeveloperError('All instance geometries must have the same primitiveType.'); } } @@ -126,6 +136,9 @@ define([ // Clip to IDL if (!scene3DOnly) { for (i = 0; i < length; ++i) { + if (!defined(instances[i].geometry)) { + continue; + } GeometryPipeline.splitLongitude(instances[i]); } } @@ -139,7 +152,7 @@ define([ if (defined(instance.geometry)) { GeometryPipeline.reorderForPostVertexCache(instance.geometry); GeometryPipeline.reorderForPreVertexCache(instance.geometry); - } else { + } else if (defined(instance.westHemisphereGeometry) && defined(instance.eastHemisphereGeometry)) { GeometryPipeline.reorderForPostVertexCache(instance.westHemisphereGeometry); GeometryPipeline.reorderForPreVertexCache(instance.westHemisphereGeometry); @@ -268,11 +281,13 @@ define([ if (instances.length > 0) { geometries = geometryPipeline(parameters); - attributeLocations = GeometryPipeline.createAttributeLocations(geometries[0]); + if (geometries.length > 0) { + attributeLocations = GeometryPipeline.createAttributeLocations(geometries[0]); + } } var pickOffsets; - if (parameters.createPickOffsets && defined(geometries)) { + if (parameters.createPickOffsets && geometries.length > 0) { pickOffsets = createInstancePickOffsets(instances, geometries); } @@ -280,7 +295,6 @@ define([ geometries : geometries, modelMatrix : parameters.modelMatrix, attributeLocations : attributeLocations, - invalidInstancesIndices : parameters.invalidInstancesIndices, pickOffsets : pickOffsets }; }; @@ -572,7 +586,6 @@ define([ var createGeometryResults = packedParameters.createGeometryResults; var length = createGeometryResults.length; var instanceIndex = 0; - var invalidInstancesIndices = []; for (var resultIndex = 0; resultIndex < length; resultIndex++) { var geometries = PrimitivePipeline.unpackCreateGeometryResults(createGeometryResults[resultIndex]); @@ -580,13 +593,7 @@ define([ for (var geometryIndex = 0; geometryIndex < geometriesLength; geometryIndex++) { var geometry = geometries[geometryIndex]; var instance = instances[instanceIndex]; - - if (defined(geometry)) { - instance.geometry = geometry; - } else { - invalidInstancesIndices.push(instanceIndex); - } - + instance.geometry = geometry; ++instanceIndex; } } @@ -596,7 +603,6 @@ define([ return { instances : instances, - invalidInstancesIndices : invalidInstancesIndices, ellipsoid : ellipsoid, projection : projection, elementIndexUintSupported : packedParameters.elementIndexUintSupported, @@ -620,7 +626,6 @@ define([ geometries : results.geometries, attributeLocations : results.attributeLocations, modelMatrix : results.modelMatrix, - invalidInstancesIndices : results.invalidInstancesIndices, pickOffsets : results.pickOffsets }; }; From 9d7f49f66f14205ee2b62e63be0a8a07723731d8 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 22 Sep 2016 16:54:38 -0400 Subject: [PATCH 142/191] Re-add per instance bounding spheres. --- Source/Core/Geometry.js | 2 +- Source/Scene/Primitive.js | 42 ++++++++-------- Source/Scene/PrimitivePipeline.js | 79 +++++++++++++++++++++++++++++-- 3 files changed, 99 insertions(+), 24 deletions(-) diff --git a/Source/Core/Geometry.js b/Source/Core/Geometry.js index 55dd903af05c..c10078c250ef 100644 --- a/Source/Core/Geometry.js +++ b/Source/Core/Geometry.js @@ -158,7 +158,7 @@ define([ /** * @private */ - this.boundingSphereCV = undefined; + this.boundingSphereCV = options.boundingSphereCV; } /** diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 0d75bf49d143..3ecbd1e31ba1 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -355,6 +355,8 @@ define([ this._batchTable = undefined; this._batchTableAttributeIndices = undefined; + this._instanceBoundingSpheres = undefined; + this._instanceBoundingSpheresCV = undefined; } defineProperties(Primitive.prototype, { @@ -1033,6 +1035,8 @@ define([ primitive._attributeLocations = result.attributeLocations; primitive.modelMatrix = Matrix4.clone(result.modelMatrix, primitive.modelMatrix); primitive._pickOffsets = result.pickOffsets; + primitive._instanceBoundingSpheres = result.boundingSpheres; + primitive._instanceBoundingSpheresCV = result.boundingSpheresCV; if (defined(primitive._geometries) && primitive._geometries.length > 0) { primitive._state = PrimitiveState.COMBINED; @@ -1091,6 +1095,8 @@ define([ primitive._attributeLocations = result.attributeLocations; primitive.modelMatrix = Matrix4.clone(result.modelMatrix, primitive.modelMatrix); primitive._pickOffsets = result.pickOffsets; + primitive._instanceBoundingSpheres = result.boundingSpheres; + primitive._instanceBoundingSpheresCV = result.boundingSpheresCV; if (defined(primitive._geometries) && primitive._geometries.length > 0) { primitive._state = PrimitiveState.COMBINED; @@ -1553,7 +1559,18 @@ define([ }; } - var readOnlyInstanceAttributesScratch = ['boundingSphere', 'boundingSphereCV']; + function createBoundingSphereProperties(primitive, properties, index) { + properties.boundingSphere = { + get : function() { + return primitive._instanceBoundingSpheres[index]; + } + }; + properties.boundingSphereCV = { + get : function() { + return primitive._instanceBoundingSpheresCV[index]; + } + }; + } /** * Returns the modifiable per-instance attributes for a {@link GeometryInstance}. @@ -1603,28 +1620,16 @@ define([ var perInstanceAttributeIndices = this._batchTableAttributeIndices; attributes = {}; var properties = {}; - var hasProperties = false; for (var name in perInstanceAttributeIndices) { if (perInstanceAttributeIndices.hasOwnProperty(name)) { var attributeIndex = perInstanceAttributeIndices[name]; - - hasProperties = true; properties[name] = { get : createGetFunction(batchTable, index, attributeIndex) }; var createSetter = true; - var readOnlyAttributes = readOnlyInstanceAttributesScratch; - length = readOnlyAttributes.length; - for (var j = 0; j < length; ++j) { - if (name === readOnlyInstanceAttributesScratch[j]) { - createSetter = false; - break; - } - } - - readOnlyAttributes = this._readOnlyInstanceAttributes; + var readOnlyAttributes = this._readOnlyInstanceAttributes; if (createSetter && defined(readOnlyAttributes)) { length = readOnlyAttributes.length; for (var k = 0; k < length; ++k) { @@ -1641,9 +1646,8 @@ define([ } } - if (hasProperties) { - defineProperties(attributes, properties); - } + createBoundingSphereProperties(this, properties, index); + defineProperties(attributes, properties); this._lastPerInstanceAttributeIndex = index; this._perInstanceAttributeCache[index] = attributes; @@ -1705,14 +1709,14 @@ define([ } this._pickIds = undefined; + this._batchTable = this._batchTable && this._batchTable.destroy(); + //These objects may be fairly large and reference other large objects (like Entities) //We explicitly set them to undefined here so that the memory can be freed //even if a reference to the destroyed Primitive has been kept around. this._instanceIds = undefined; this._perInstanceAttributeCache = undefined; - this._perInstanceAttributeLocations = undefined; this._attributeLocations = undefined; - this._dirtyAttributes = undefined; return destroyObject(this); }; diff --git a/Source/Scene/PrimitivePipeline.js b/Source/Scene/PrimitivePipeline.js index eb3e92ce6ac0..b48aa3d2e239 100644 --- a/Source/Scene/PrimitivePipeline.js +++ b/Source/Scene/PrimitivePipeline.js @@ -278,8 +278,9 @@ define([ var geometries; var attributeLocations; var instances = parameters.instances; + var length = instances.length; - if (instances.length > 0) { + if (length > 0) { geometries = geometryPipeline(parameters); if (geometries.length > 0) { attributeLocations = GeometryPipeline.createAttributeLocations(geometries[0]); @@ -291,11 +292,35 @@ define([ pickOffsets = createInstancePickOffsets(instances, geometries); } + var boundingSpheres = new Array(length); + var boundingSpheresCV = new Array(length); + for (var i = 0; i < length; ++i) { + var instance = instances[i]; + var geometry = instance.geometry; + if (defined(geometry)) { + boundingSpheres[i] = geometry.boundingSphere; + boundingSpheresCV[i] = geometry.boundingSphereCV; + } + + var eastHemisphereGeometry = instance.eastHemisphereGeometry; + var westHemisphereGeometry = instance.westHemisphereGeometry; + if (defined(eastHemisphereGeometry) && defined(westHemisphereGeometry)) { + if (defined(eastHemisphereGeometry.boundingSphere) && defined(westHemisphereGeometry.boundingSphere)) { + boundingSpheres[i] = BoundingSphere.union(eastHemisphereGeometry.boundingSphere, westHemisphereGeometry.boundingSphere); + } + if (defined(eastHemisphereGeometry.boundingSphereCV) && defined(westHemisphereGeometry.boundingSphereCV)) { + boundingSpheresCV[i] = BoundingSphere.union(eastHemisphereGeometry.boundingSphereCV, westHemisphereGeometry.boundingSphereCV); + } + } + } + return { geometries : geometries, modelMatrix : parameters.modelMatrix, attributeLocations : attributeLocations, - pickOffsets : pickOffsets + pickOffsets : pickOffsets, + boundingSpheres : boundingSpheres, + boundingSpheresCV : boundingSpheresCV }; }; @@ -511,6 +536,7 @@ define([ primitiveType : primitiveType, geometryType : geometryType, boundingSphere : boundingSphere, + boundingSphereCV : boundingSphereCV, indices : indices, attributes : attributes }); @@ -614,6 +640,43 @@ define([ }; }; + function packBoundingSpheres(boundingSpheres) { + var length = boundingSpheres.length; + var bufferLength = 1 + (BoundingSphere.packedLength + 1) * length; + var buffer = new Float32Array(bufferLength); + + var bufferIndex = 0; + buffer[bufferIndex++] = length; + + for (var i = 0; i < length; ++i) { + var bs = boundingSpheres[i]; + if (!defined(bs)) { + buffer[bufferIndex++] = 0.0; + } else { + buffer[bufferIndex++] = 1.0; + BoundingSphere.pack(boundingSpheres[i], buffer, bufferIndex); + } + bufferIndex += BoundingSphere.packedLength; + } + + return buffer; + } + + function unpackBoundingSpheres(buffer) { + var result = new Array(buffer[0]); + var count = 0; + + var i = 1; + while (i < buffer.length) { + if(buffer[i++] === 1.0) { + result[count++] = BoundingSphere.unpack(buffer, i); + } + i += BoundingSphere.packedLength; + } + + return result; + } + /** * @private */ @@ -622,11 +685,17 @@ define([ transferGeometries(results.geometries, transferableObjects); } + var packedBoundingSpheres = packBoundingSpheres(results.boundingSpheres); + var packedBoundingSpheresCV = packBoundingSpheres(results.boundingSpheresCV); + transferableObjects.push(packedBoundingSpheres.buffer, packedBoundingSpheresCV.buffer); + return { geometries : results.geometries, attributeLocations : results.attributeLocations, modelMatrix : results.modelMatrix, - pickOffsets : results.pickOffsets + pickOffsets : results.pickOffsets, + boundingSpheres : packedBoundingSpheres, + boundingSpheresCV : packedBoundingSpheresCV }; }; @@ -638,7 +707,9 @@ define([ geometries : packedResult.geometries, attributeLocations : packedResult.attributeLocations, modelMatrix : packedResult.modelMatrix, - pickOffsets : packedResult.pickOffsets + pickOffsets : packedResult.pickOffsets, + boundingSpheres : unpackBoundingSpheres(packedResult.boundingSpheres), + boundingSpheresCV : unpackBoundingSpheres(packedResult.boundingSpheresCV) }; }; From 28f3b986b710d3e0ba63356f3b36dc3273700fde Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 22 Sep 2016 17:06:32 -0400 Subject: [PATCH 143/191] Fix GroundPrimitives. --- Source/Scene/GroundPrimitive.js | 21 ++++++++++++++------- Source/Scene/Primitive.js | 16 ++++++++++------ Source/Shaders/ShadowVolumeVS.glsl | 1 + 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index b60a7d8213df..99cd3548d4e2 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -740,8 +740,10 @@ define([ var context = frameState.context; var vs = ShadowVolumeVS; + vs = primitive._primitive._batchTable.getVertexShaderCallback()(vs); vs = Primitive._modifyShaderPosition(primitive, vs, frameState.scene3DOnly); vs = Primitive._appendShowToShader(primitive._primitive, vs); + vs = Primitive._updateColorAttribute(primitive._primitive, vs); var fs = ShadowVolumeFS; var attributeLocations = primitive._primitive._attributeLocations; @@ -755,6 +757,9 @@ define([ }); if (primitive._primitive.allowPicking) { + var vsPick = ShaderSource.createPickVertexShaderSource(vs); + vsPick = Primitive._updatePickColorAttribute(vsPick); + var pickFS = new ShaderSource({ sources : [fs], pickColorQualifier : 'varying' @@ -762,7 +767,7 @@ define([ primitive._spPick = ShaderProgram.replaceCache({ context : context, shaderProgram : primitive._spPick, - vertexShaderSource : ShaderSource.createPickVertexShaderSource(vs), + vertexShaderSource : vsPick, fragmentShaderSource : pickFS, attributeLocations : attributeLocations }); @@ -782,6 +787,7 @@ define([ colorCommands.length = length; var vaIndex = 0; + var uniformMap = primitive._batchTable.getUniformMapCallback()(groundPrimitive._uniformMap); for (var i = 0; i < length; i += 3) { var vertexArray = primitive._va[vaIndex++]; @@ -798,7 +804,7 @@ define([ command.vertexArray = vertexArray; command.renderState = groundPrimitive._rsStencilPreloadPass; command.shaderProgram = groundPrimitive._sp; - command.uniformMap = groundPrimitive._uniformMap; + command.uniformMap = uniformMap; command.pass = Pass.GROUND; // stencil depth command @@ -813,7 +819,7 @@ define([ command.vertexArray = vertexArray; command.renderState = groundPrimitive._rsStencilDepthPass; command.shaderProgram = groundPrimitive._sp; - command.uniformMap = groundPrimitive._uniformMap; + command.uniformMap = uniformMap; command.pass = Pass.GROUND; // color command @@ -828,7 +834,7 @@ define([ command.vertexArray = vertexArray; command.renderState = groundPrimitive._rsColorPass; command.shaderProgram = groundPrimitive._sp; - command.uniformMap = groundPrimitive._uniformMap; + command.uniformMap = uniformMap; command.pass = Pass.GROUND; } } @@ -840,6 +846,7 @@ define([ pickCommands.length = length; var pickIndex = 0; + var uniformMap = primitive._batchTable.getUniformMapCallback()(groundPrimitive._uniformMap); for (var j = 0; j < length; j += 3) { var pickOffset = pickOffsets[pickIndex++]; @@ -862,7 +869,7 @@ define([ command.count = count; command.renderState = groundPrimitive._rsStencilPreloadPass; command.shaderProgram = groundPrimitive._sp; - command.uniformMap = groundPrimitive._uniformMap; + command.uniformMap = uniformMap; command.pass = Pass.GROUND; // stencil depth command @@ -879,7 +886,7 @@ define([ command.count = count; command.renderState = groundPrimitive._rsStencilDepthPass; command.shaderProgram = groundPrimitive._sp; - command.uniformMap = groundPrimitive._uniformMap; + command.uniformMap = uniformMap; command.pass = Pass.GROUND; // color command @@ -896,7 +903,7 @@ define([ command.count = count; command.renderState = groundPrimitive._rsPickPass; command.shaderProgram = groundPrimitive._spPick; - command.uniformMap = groundPrimitive._uniformMap; + command.uniformMap = uniformMap; command.pass = Pass.GROUND; } } diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 3ecbd1e31ba1..8955e6e6795a 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -803,7 +803,7 @@ define([ return renamedVS + '\n' + showMain; }; - function updateColorAttribute(primitive, vertexShaderSource) { + Primitive._updateColorAttribute = function(primitive, vertexShaderSource) { // some appearances have a color attribute for per vertex color. // only remove if color is a per instance attribute. if (!defined(primitive._batchTableAttributeIndices.color)) { @@ -818,7 +818,13 @@ define([ modifiedVS = modifiedVS.replace(/attribute\s+vec4\s+color;/g, ''); modifiedVS = modifiedVS.replace(/(\b)color(\b)/g, '$1czm_batchTable_color(batchId)$2'); return modifiedVS; - } + }; + + Primitive._updatePickColorAttribute = function(source) { + var vsPick = source.replace(/attribute\s+vec4\s+pickColor;/g, ''); + vsPick = vsPick.replace(/(\b)pickColor(\b)/g, '$1czm_batchTable_pickColor(batchId)$2'); + return vsPick; + }; function modifyForEncodedNormals(primitive, vertexShaderSource) { if (!primitive.compressVertices) { @@ -1214,16 +1220,14 @@ define([ var vs = primitive._batchTable.getVertexShaderCallback()(appearance.vertexShaderSource); vs = Primitive._modifyShaderPosition(primitive, vs, frameState.scene3DOnly); vs = Primitive._appendShowToShader(primitive, vs); - vs = updateColorAttribute(primitive, vs); + vs = Primitive._updateColorAttribute(primitive, vs); vs = modifyForEncodedNormals(primitive, vs); var fs = appearance.getFragmentShaderSource(); // Create pick program if (primitive.allowPicking) { var vsPick = ShaderSource.createPickVertexShaderSource(vs); - - vsPick = vsPick.replace(/attribute\s+vec4\s+pickColor;/g, ''); - vsPick = vsPick.replace(/(\b)pickColor(\b)/g, '$1czm_batchTable_pickColor(batchId)$2'); + vsPick = Primitive._updatePickColorAttribute(vsPick); primitive._pickSP = ShaderProgram.replaceCache({ context : context, diff --git a/Source/Shaders/ShadowVolumeVS.glsl b/Source/Shaders/ShadowVolumeVS.glsl index 81b3c90294c6..a97b96c1752b 100644 --- a/Source/Shaders/ShadowVolumeVS.glsl +++ b/Source/Shaders/ShadowVolumeVS.glsl @@ -1,6 +1,7 @@ attribute vec3 position3DHigh; attribute vec3 position3DLow; attribute vec4 color; +attribute float batchId; // emulated noperspective varying float v_WindowZ; From 7579b43256062b55868f96706f2ee94890a03894 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 22 Sep 2016 17:27:08 -0400 Subject: [PATCH 144/191] Fix DebugAppearance and its tests. --- Source/Scene/DebugAppearance.js | 12 +++++++-- Specs/Scene/DebugAppearanceSpec.js | 42 ++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/Source/Scene/DebugAppearance.js b/Source/Scene/DebugAppearance.js index 5de436b25ac4..70047a7fd72a 100644 --- a/Source/Scene/DebugAppearance.js +++ b/Source/Scene/DebugAppearance.js @@ -26,6 +26,7 @@ define([ * * @param {Object} options Object with the following properties: * @param {String} options.attributeName The name of the attribute to visualize. + * @param {Boolean} options.perInstanceAttribute Boolean that determines whether this attribute is a per-instance geometry attribute. * @param {String} [options.glslDatatype='vec3'] The GLSL datatype of the attribute. Supported datatypes are float, vec2, vec3, and vec4. * @param {String} [options.vertexShaderSource] Optional GLSL vertex shader source to override the default vertex shader. * @param {String} [options.fragmentShaderSource] Optional GLSL fragment shader source to override the default fragment shader. @@ -44,11 +45,15 @@ define([ function DebugAppearance(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); var attributeName = options.attributeName; + var perInstanceAttribute = options.perInstanceAttribute; //>>includeStart('debug', pragmas.debug); if (!defined(attributeName)) { throw new DeveloperError('options.attributeName is required.'); } + if (!defined(perInstanceAttribute)) { + throw new DeveloperError('options.perInstanceAttribute is required.'); + } //>>includeEnd('debug'); var glslDatatype = defaultValue(options.glslDatatype, 'vec3'); @@ -85,12 +90,15 @@ define([ var vs = 'attribute vec3 position3DHigh;\n' + 'attribute vec3 position3DLow;\n' + - 'attribute ' + glslDatatype + ' ' + attributeName + ';\n' + + 'attribute float batchId;\n' + + (perInstanceAttribute ? '' : 'attribute ' + glslDatatype + ' ' + attributeName + ';\n') + 'varying ' + glslDatatype + ' ' + varyingName + ';\n' + 'void main()\n' + '{\n' + 'vec4 p = czm_translateRelativeToEye(position3DHigh, position3DLow);\n' + - varyingName + ' = ' + attributeName + ';\n' + + (perInstanceAttribute ? + varyingName + ' = czm_batchTable_' + attributeName + '(batchId);\n' : + varyingName + ' = ' + attributeName + ';\n') + 'gl_Position = czm_modelViewProjectionRelativeToEye * p;\n' + '}'; var fs = diff --git a/Specs/Scene/DebugAppearanceSpec.js b/Specs/Scene/DebugAppearanceSpec.js index 591fa791a495..229e31d72582 100644 --- a/Specs/Scene/DebugAppearanceSpec.js +++ b/Specs/Scene/DebugAppearanceSpec.js @@ -67,7 +67,8 @@ defineSuite([ it('default construct with normal, binormal, or tangent attribute name', function() { var a = new DebugAppearance({ - attributeName : 'normal' + attributeName : 'normal', + perInstanceAttribute : false }); expect(a.vertexShaderSource).toBeDefined(); @@ -87,7 +88,8 @@ defineSuite([ it('default construct with st attribute name', function() { var a = new DebugAppearance({ - attributeName : 'st' + attributeName : 'st', + perInstanceAttribute : false }); expect(a.vertexShaderSource).toBeDefined(); @@ -108,7 +110,8 @@ defineSuite([ it('debug appearance with float attribute name', function() { var a = new DebugAppearance({ attributeName : 'rotation', - glslDatatype : 'float' + glslDatatype : 'float', + perInstanceAttribute : true }); expect(a.vertexShaderSource).toBeDefined(); @@ -129,7 +132,8 @@ defineSuite([ it('debug appearance with vec3 attribute name', function() { var a = new DebugAppearance({ attributeName : 'str', - glslDatatype : 'vec3' + glslDatatype : 'vec3', + perInstanceAttribute : false }); expect(a.vertexShaderSource).toBeDefined(); @@ -150,7 +154,8 @@ defineSuite([ it('debug appearance with vec4 attribute name', function() { var a = new DebugAppearance({ attributeName : 'quaternion', - glslDatatype : 'vec4' + glslDatatype : 'vec4', + perInstanceAttribute : true }); expect(a.vertexShaderSource).toBeDefined(); @@ -172,7 +177,8 @@ defineSuite([ expect(function() { return new DebugAppearance({ attributeName : 'invalid_datatype', - glslDatatype : 'invalid' + glslDatatype : 'invalid', + perInstanceAttribute : true }); }).toThrowDeveloperError(); }); @@ -185,7 +191,8 @@ defineSuite([ primitive = new Primitive({ geometryInstances : createInstance(vertexFormat), appearance : new DebugAppearance({ - attributeName : 'normal' + attributeName : 'normal', + perInstanceAttribute : false }), asynchronous : false, compressVertices : false @@ -206,7 +213,8 @@ defineSuite([ primitive = new Primitive({ geometryInstances : createInstance(vertexFormat), appearance : new DebugAppearance({ - attributeName : 'binormal' + attributeName : 'binormal', + perInstanceAttribute : false }), asynchronous : false, compressVertices : false @@ -227,7 +235,8 @@ defineSuite([ primitive = new Primitive({ geometryInstances : createInstance(vertexFormat), appearance : new DebugAppearance({ - attributeName : 'tangent' + attributeName : 'tangent', + perInstanceAttribute : false }), asynchronous : false, compressVertices : false @@ -247,7 +256,8 @@ defineSuite([ primitive = new Primitive({ geometryInstances : createInstance(vertexFormat), appearance : new DebugAppearance({ - attributeName : 'st' + attributeName : 'st', + perInstanceAttribute : false }), asynchronous : false, compressVertices : false @@ -272,7 +282,8 @@ defineSuite([ geometryInstances : rectangleInstance, appearance : new DebugAppearance({ attributeName : 'debug', - glslDatatype : 'float' + glslDatatype : 'float', + perInstanceAttribute : true }), asynchronous : false }); @@ -296,7 +307,8 @@ defineSuite([ geometryInstances : rectangleInstance, appearance : new DebugAppearance({ attributeName : 'debug', - glslDatatype : 'vec2' + glslDatatype : 'vec2', + perInstanceAttribute : true }), asynchronous : false }); @@ -320,7 +332,8 @@ defineSuite([ geometryInstances : rectangleInstance, appearance : new DebugAppearance({ attributeName : 'debug', - glslDatatype : 'vec3' + glslDatatype : 'vec3', + perInstanceAttribute : true }), asynchronous : false }); @@ -344,7 +357,8 @@ defineSuite([ geometryInstances : rectangleInstance, appearance : new DebugAppearance({ attributeName : 'debug', - glslDatatype : 'vec4' + glslDatatype : 'vec4', + perInstanceAttribute : true }), asynchronous : false }); From c6b7c56038d3cf588646d23f48f983e3da19e8d2 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 22 Sep 2016 20:03:09 -0400 Subject: [PATCH 145/191] Fix debug camera primitive tests --- Specs/Scene/DebugCameraPrimitiveSpec.js | 4 ++-- Specs/Scene/ShadowMapSpec.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Specs/Scene/DebugCameraPrimitiveSpec.js b/Specs/Scene/DebugCameraPrimitiveSpec.js index c8e1b9522f3b..2d3d9b00c5d9 100644 --- a/Specs/Scene/DebugCameraPrimitiveSpec.js +++ b/Specs/Scene/DebugCameraPrimitiveSpec.js @@ -86,9 +86,9 @@ defineSuite([ camera : camera })); scene.renderForSpecs(); - var primitive = p._primitive; + var primitive = p._outlinePrimitive; scene.renderForSpecs(); - expect(p._primitive).not.toBe(primitive); + expect(p._outlinePrimitive).not.toBe(primitive); }); it('does not update when updateOnChange is false', function() { diff --git a/Specs/Scene/ShadowMapSpec.js b/Specs/Scene/ShadowMapSpec.js index bf20df19a9a6..dfd14519819c 100644 --- a/Specs/Scene/ShadowMapSpec.js +++ b/Specs/Scene/ShadowMapSpec.js @@ -861,11 +861,11 @@ defineSuite([ it('enable debugShow for cascaded shadow map', function() { createCascadedShadowMap(); - // Shadow overlay command, shadow volume outline, camera outline, and four cascade outlines + // Shadow overlay command, shadow volume outline, camera outline, four cascade outlines, four cascade planes scene.shadowMap.debugShow = true; scene.shadowMap.debugFreezeFrame = true; render(); - expect(scene.frameState.commandList.length).toBe(7); + expect(scene.frameState.commandList.length).toBe(13); scene.shadowMap.debugShow = false; render(); @@ -875,10 +875,10 @@ defineSuite([ it('enable debugShow for fixed shadow map', function() { createShadowMapForDirectionalLight(); - // Overlay command and shadow volume outline + // Overlay command, shadow volume outline, shadow volume planes scene.shadowMap.debugShow = true; render(); - expect(scene.frameState.commandList.length).toBe(2); + expect(scene.frameState.commandList.length).toBe(3); scene.shadowMap.debugShow = false; render(); From 72c7f4af1c0f4fdb2e5daec941b920be513a3078 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 22 Sep 2016 21:01:31 -0400 Subject: [PATCH 146/191] Removed deprecated castShadows and receiveShadows --- CHANGES.md | 2 + Source/DataSources/CzmlDataSource.js | 2 - Source/DataSources/ModelGraphics.js | 28 ----------- Source/DataSources/ModelVisualizer.js | 11 +---- Source/Scene/Globe.js | 42 ---------------- Source/Scene/Model.js | 54 +-------------------- Source/Scene/Primitive.js | 50 +------------------ Source/Widgets/CesiumWidget/CesiumWidget.js | 10 +--- Source/Widgets/Viewer/Viewer.js | 9 +--- 9 files changed, 7 insertions(+), 201 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 8d1c21265b6b..83e1e22f0fc3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,8 @@ Change Log * Breaking changes * Vertex texture fetch is now required to be supported to render polylines. Maximum vertex texture image units must be greater than zero. + * Removed `castShadows` and `receiveShadows` properties from `Model`, `Primitive`, and `Globe`. Use `shadows` instead with the `ShadowMode` enum, e.g. `model.shadows = ShadowMode.ENABLED`. + * `Viewer.terrainShadows` now uses the `ShadowMode` enum instead of a Boolean, e.g. `viewer.terrainShadows = ShadowMode.RECEIVE_ONLY`. * Fixed billboard rotation when sized in meters. [#3979](https://github.com/AnalyticalGraphicsInc/cesium/issues/3979) * Added `DebugCameraPrimitive` to visualize the view frustum of a camera. * Fixed touch events for the timeline [#4305](https://github.com/AnalyticalGraphicsInc/cesium/pull/4305) diff --git a/Source/DataSources/CzmlDataSource.js b/Source/DataSources/CzmlDataSource.js index 706049c9fc25..c0e24b9180d8 100644 --- a/Source/DataSources/CzmlDataSource.js +++ b/Source/DataSources/CzmlDataSource.js @@ -1409,8 +1409,6 @@ define([ processPacketData(Number, model, 'maximumScale', modelData.maximumScale, interval, sourceUri, entityCollection); processPacketData(Boolean, model, 'incrementallyLoadTextures', modelData.incrementallyLoadTextures, interval, sourceUri, entityCollection); processPacketData(Boolean, model, 'runAnimations', modelData.runAnimations, interval, sourceUri, entityCollection); - processPacketData(Boolean, model, 'castShadows', modelData.castShadows, interval, sourceUri, entityCollection); - processPacketData(Boolean, model, 'receiveShadows', modelData.receiveShadows, interval, sourceUri, entityCollection); processPacketData(ShadowMode, model, 'shadows', modelData.shadows, interval, sourceUri, entityCollection); processPacketData(HeightReference, model, 'heightReference', modelData.heightReference, interval, sourceUri, entityCollection); diff --git a/Source/DataSources/ModelGraphics.js b/Source/DataSources/ModelGraphics.js index e0b5ceb10794..992cebf0c09e 100644 --- a/Source/DataSources/ModelGraphics.js +++ b/Source/DataSources/ModelGraphics.js @@ -47,8 +47,6 @@ define([ * @param {Property} [options.incrementallyLoadTextures=true] Determine if textures may continue to stream in after the model is loaded. * @param {Property} [options.runAnimations=true] A boolean Property specifying if glTF animations specified in the model should be started. * @param {Property} [options.nodeTransformations] An object, where keys are names of nodes, and values are {@link TranslationRotationScale} Properties describing the transformation to apply to that node. - * @param {Property} [options.castShadows=true] Deprecated, use options.shadows instead. A boolean Property specifying whether the model casts shadows from each light source. - * @param {Property} [options.receiveShadows=true] Deprecated, use options.shadows instead. A boolean Property specifying whether the model receives shadows from shadow casters in the scene. * @param {Property} [options.shadows=ShadowMode.ENABLED] An enum Property specifying whether the model casts or receives shadows from each light source. * @param {Property} [options.heightReference=HeightReference.NONE] A Property specifying what the height is relative to. * @@ -66,10 +64,6 @@ define([ this._maximumScaleSubscription = undefined; this._incrementallyLoadTextures = undefined; this._incrementallyLoadTexturesSubscription = undefined; - this._castShadows = undefined; - this._castShadowsSubscription = undefined; - this._receiveShadows = undefined; - this._receiveShadowsSubscription = undefined; this._shadows = undefined; this._shadowsSubscription = undefined; this._uri = undefined; @@ -144,24 +138,6 @@ define([ */ incrementallyLoadTextures : createPropertyDescriptor('incrementallyLoadTextures'), - /** - * Get or sets the boolean Property specifying whether the model - * casts shadows from each light source. - * @memberof ModelGraphics.prototype - * @type {Property} - * @deprecated - */ - castShadows : createPropertyDescriptor('castShadows'), - - /** - * Get or sets the boolean Property specifying whether the model - * receives shadows from shadow casters in the scene. - * @memberof ModelGraphics.prototype - * @type {Property} - * @deprecated - */ - receiveShadows : createPropertyDescriptor('receiveShadows'), - /** * Get or sets the enum Property specifying whether the model * casts or receives shadows from each light source. @@ -218,8 +194,6 @@ define([ result.minimumPixelSize = this.minimumPixelSize; result.maximumScale = this.maximumScale; result.incrementallyLoadTextures = this.incrementallyLoadTextures; - result.castShadows = this.castShadows; - result.receiveShadows = this.receiveShadows; result.shadows = this.shadows; result.uri = this.uri; result.runAnimations = this.runAnimations; @@ -247,8 +221,6 @@ define([ this.minimumPixelSize = defaultValue(this.minimumPixelSize, source.minimumPixelSize); this.maximumScale = defaultValue(this.maximumScale, source.maximumScale); this.incrementallyLoadTextures = defaultValue(this.incrementallyLoadTextures, source.incrementallyLoadTextures); - this.castShadows = defaultValue(this.castShadows, source.castShadows); - this.receiveShadows = defaultValue(this.receiveShadows, source.receiveShadows); this.shadows = defaultValue(this.shadows, source.shadows); this.uri = defaultValue(this.uri, source.uri); this.runAnimations = defaultValue(this.runAnimations, source.runAnimations); diff --git a/Source/DataSources/ModelVisualizer.js b/Source/DataSources/ModelVisualizer.js index fde2fedcb7f8..1f8487eb12b6 100644 --- a/Source/DataSources/ModelVisualizer.js +++ b/Source/DataSources/ModelVisualizer.js @@ -131,21 +131,12 @@ define([ modelHash[entity.id] = modelData; } - var shadows = defaultShadows; - if (defined(modelGraphics._shadows)) { - shadows = Property.getValueOrDefault(modelGraphics._shadows, time, defaultShadows); - } else if (defined(modelGraphics._castShadows) || defined(modelGraphics._receiveShadows)) { - var castShadows = Property.getValueOrDefault(modelGraphics._castShadows, time, true); - var receiveShadows = Property.getValueOrDefault(modelGraphics.receiveShadows, time, true); - shadows = ShadowMode.fromCastReceive(castShadows, receiveShadows); - } - model.show = true; model.scale = Property.getValueOrDefault(modelGraphics._scale, time, defaultScale); model.minimumPixelSize = Property.getValueOrDefault(modelGraphics._minimumPixelSize, time, defaultMinimumPixelSize); model.maximumScale = Property.getValueOrUndefined(modelGraphics._maximumScale, time); model.modelMatrix = Matrix4.clone(modelMatrix, model.modelMatrix); - model.shadows = shadows; + model.shadows = Property.getValueOrDefault(modelGraphics._shadows, time, defaultShadows); model.heightReference = Property.getValueOrDefault(modelGraphics._heightReference, time, defaultHeightReference); if (model.ready) { diff --git a/Source/Scene/Globe.js b/Source/Scene/Globe.js index e16b87fba3bc..e84b483997b0 100644 --- a/Source/Scene/Globe.js +++ b/Source/Scene/Globe.js @@ -7,7 +7,6 @@ define([ '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', - '../Core/deprecationWarning', '../Core/destroyObject', '../Core/DeveloperError', '../Core/Ellipsoid', @@ -38,7 +37,6 @@ define([ defaultValue, defined, defineProperties, - deprecationWarning, destroyObject, DeveloperError, Ellipsoid, @@ -281,46 +279,6 @@ define([ get: function() { return this._surface.tileLoadProgressEvent; } - }, - - /** - * Determines whether the globe casts shadows from each light source. - * - * @memberof Globe.prototype - * @type {Boolean} - * @deprecated - */ - castShadows : { - get : function() { - deprecationWarning('Globe.castShadows', 'Globe.castShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Globe.shadows instead.'); - return ShadowMode.castShadows(this.shadows); - }, - set : function(value) { - deprecationWarning('Globe.castShadows', 'Globe.castShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Globe.shadows instead.'); - var castShadows = value; - var receiveShadows = ShadowMode.receiveShadows(this.shadows); - this.shadows = ShadowMode.fromCastReceive(castShadows, receiveShadows); - } - }, - - /** - * Determines whether the globe receives shadows from shadow casters in the scene. - * - * @memberof Globe.prototype - * @type {Boolean} - * @deprecated - */ - receiveShadows : { - get : function() { - deprecationWarning('Globe.receiveShadows', 'Globe.receiveShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Globe.shadows instead.'); - return ShadowMode.receiveShadows(this.shadows); - }, - set : function(value) { - deprecationWarning('Globe.receiveShadows', 'Globe.receiveShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Globe.shadows instead.'); - var castShadows = ShadowMode.castShadows(this.shadows); - var receiveShadows = value; - this.shadows = ShadowMode.fromCastReceive(castShadows, receiveShadows); - } } }); diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js index 5644c433eb83..e0f77da3afda 100644 --- a/Source/Scene/Model.js +++ b/Source/Scene/Model.js @@ -11,7 +11,6 @@ define([ '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', - '../Core/deprecationWarning', '../Core/destroyObject', '../Core/DeveloperError', '../Core/FeatureDetection', @@ -71,7 +70,6 @@ define([ defaultValue, defined, defineProperties, - deprecationWarning, destroyObject, DeveloperError, FeatureDetection, @@ -315,8 +313,6 @@ define([ * @param {Boolean} [options.allowPicking=true] When true, each glTF mesh and primitive is pickable with {@link Scene#pick}. * @param {Boolean} [options.incrementallyLoadTextures=true] Determine if textures may continue to stream in after the model is loaded. * @param {Boolean} [options.asynchronous=true] Determines if model WebGL resource creation will be spread out over several frames or block until completion once all glTF files are loaded. - * @param {Boolean} [options.castShadows=true] Deprecated, use options.shadows instead. Determines whether the model casts shadows from each light source. - * @param {Boolean} [options.receiveShadows=true] Deprecated, use options.shadows instead. Determines whether the model receives shadows from shadow casters in the scene. * @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the model casts or receives shadows from each light source. * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Draws the bounding sphere for each draw command in the model. * @param {Boolean} [options.debugWireframe=false] For debugging only. Draws the model in wireframe. @@ -507,10 +503,6 @@ define([ this._incrementallyLoadTextures = defaultValue(options.incrementallyLoadTextures, true); this._asynchronous = defaultValue(options.asynchronous, true); - // Deprecated options - var castShadows = defaultValue(options.castShadows, true); - var receiveShadows = defaultValue(options.receiveShadows, true); - /** * Determines whether the model casts or receives shadows from each light source. * @@ -518,7 +510,7 @@ define([ * * @default ShadowMode.ENABLED */ - this.shadows = defaultValue(options.shadows, ShadowMode.fromCastReceive(castShadows, receiveShadows)); + this.shadows = defaultValue(options.shadows, ShadowMode.ENABLED); this._shadows = this.shadows; /** @@ -867,50 +859,6 @@ define([ get : function() { return this._dirty; } - }, - - /** - * Determines whether the model casts shadows from each light source. - * - * @memberof Model.prototype - * - * @type {Boolean} - * - * @deprecated - */ - castShadows : { - get : function() { - deprecationWarning('Model.castShadows', 'Model.castShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Model.shadows instead.'); - return ShadowMode.castShadows(this.shadows); - }, - set : function(value) { - deprecationWarning('Model.castShadows', 'Model.castShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Model.shadows instead.'); - var castShadows = value; - var receiveShadows = ShadowMode.receiveShadows(this.shadows); - this.shadows = ShadowMode.fromCastReceive(castShadows, receiveShadows); - } - }, - - /** - * Determines whether the model receives shadows from shadow casters in the scene. - * - * @memberof Model.prototype - * - * @type {Boolean} - * - * @deprecated - */ - receiveShadows : { - get : function() { - deprecationWarning('Model.receiveShadows', 'Model.receiveShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Model.shadows instead.'); - return ShadowMode.receiveShadows(this.shadows); - }, - set : function(value) { - deprecationWarning('Model.receiveShadows', 'Model.receiveShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Model.shadows instead.'); - var castShadows = ShadowMode.castShadows(this.shadows); - var receiveShadows = value; - this.shadows = ShadowMode.fromCastReceive(castShadows, receiveShadows); - } } }); diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 995078d0fe1b..b939397d79c0 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -9,7 +9,6 @@ define([ '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', - '../Core/deprecationWarning', '../Core/destroyObject', '../Core/DeveloperError', '../Core/FeatureDetection', @@ -46,7 +45,6 @@ define([ defaultValue, defined, defineProperties, - deprecationWarning, destroyObject, DeveloperError, FeatureDetection, @@ -112,8 +110,6 @@ define([ * @param {Boolean} [options.cull=true] When true, the renderer frustum culls and horizon culls the primitive's commands based on their bounding volume. Set this to false for a small performance gain if you are manually culling the primitive. * @param {Boolean} [options.asynchronous=true] Determines if the primitive will be created asynchronously or block until ready. * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if this primitive's commands' bounding spheres are shown. - * @param {Boolean} [options.castShadows=true] Deprecated, use options.shadows instead. Determines whether the primitive casts shadows from each light source. - * @param {Boolean} [options.receiveShadows=true] Deprecated, use options.shadows instead. Determines whether the primitive receives shadows from shadow casters in the scene. * @param {ShadowMode} [options.shadows=ShadowMode.DISABLED] Determines whether this primitive casts or receives shadows from each light source. * * @example @@ -288,10 +284,6 @@ define([ } //>>includeEnd('debug'); - // Deprecated options - var castShadows = defaultValue(options.castShadows, false); - var receiveShadows = defaultValue(options.receiveShadows, false); - /** * Determines whether this primitive casts or receives shadows from each light source. * @@ -299,7 +291,7 @@ define([ * * @default ShadowMode.DISABLED */ - this.shadows = defaultValue(options.shadows, ShadowMode.fromCastReceive(castShadows, receiveShadows)); + this.shadows = defaultValue(options.shadows, ShadowMode.DISABLED); this._translucent = undefined; @@ -475,46 +467,6 @@ define([ get : function() { return this._readyPromise.promise; } - }, - - /** - * Determines whether the primitive casts shadows from each light source. - * - * @memberof Primitive.prototype - * @type {Boolean} - * @deprecated - */ - castShadows : { - get : function() { - deprecationWarning('Primitive.castShadows', 'Primitive.castShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Primitive.shadows instead.'); - return ShadowMode.castShadows(this.shadows); - }, - set : function(value) { - deprecationWarning('Primitive.castShadows', 'Primitive.castShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Primitive.shadows instead.'); - var castShadows = value; - var receiveShadows = ShadowMode.receiveShadows(this.shadows); - this.shadows = ShadowMode.fromCastReceive(castShadows, receiveShadows); - } - }, - - /** - * Determines whether the primitive receives shadows from shadow casters in the scene. - * - * @memberof Primitive.prototype - * @type {Boolean} - * @deprecated - */ - receiveShadows : { - get : function() { - deprecationWarning('Primitive.receiveShadows', 'Primitive.receiveShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Primitive.shadows instead.'); - return ShadowMode.receiveShadows(this.shadows); - }, - set : function(value) { - deprecationWarning('Primitive.receiveShadows', 'Primitive.receiveShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Primitive.shadows instead.'); - var castShadows = ShadowMode.castShadows(this.shadows); - var receiveShadows = value; - this.shadows = ShadowMode.fromCastReceive(castShadows, receiveShadows); - } } }); diff --git a/Source/Widgets/CesiumWidget/CesiumWidget.js b/Source/Widgets/CesiumWidget/CesiumWidget.js index 2e6c6f6e38ff..8e2da0c334a3 100644 --- a/Source/Widgets/CesiumWidget/CesiumWidget.js +++ b/Source/Widgets/CesiumWidget/CesiumWidget.js @@ -282,15 +282,7 @@ define([ } if (globe !== false) { scene.globe = globe; - // If the passed in value is a boolean, convert to the ShadowMode enum. - var terrainShadows = options.terrainShadows; - if (terrainShadows === true) { - scene.globe.shadows = ShadowMode.ENABLED; - } else if (terrainShadows === false) { - scene.globe.shadows = ShadowMode.RECEIVE_ONLY; - } else { - scene.globe.shadows = defaultValue(terrainShadows, ShadowMode.RECEIVE_ONLY); - } + scene.globe.shadows = defaultValue(options.terrainShadows, ShadowMode.RECEIVE_ONLY); } var skyBox = options.skyBox; diff --git a/Source/Widgets/Viewer/Viewer.js b/Source/Widgets/Viewer/Viewer.js index 8bf59948fc4f..3b780eae4d53 100644 --- a/Source/Widgets/Viewer/Viewer.js +++ b/Source/Widgets/Viewer/Viewer.js @@ -974,14 +974,7 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to return this.scene.globe.shadows; }, set : function(value) { - // If the passed in value is a boolean, convert to the ShadowMode enum. - if (value === true) { - this.scene.globe.shadows = ShadowMode.ENABLED; - } else if (value === false) { - this.scene.globe.shadows = ShadowMode.RECEIVE_ONLY; - } else { - this.scene.globe.shadows = value; - } + this.scene.globe.shadows = value; } }, From 9b5856cb7107214593509aa1d1a7fb4b49599b1d Mon Sep 17 00:00:00 2001 From: Tom Fili Date: Fri, 23 Sep 2016 12:10:26 -0400 Subject: [PATCH 147/191] Added options for background color and border color to writeTextToCanvas. --- Source/Core/writeTextToCanvas.js | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/Source/Core/writeTextToCanvas.js b/Source/Core/writeTextToCanvas.js index 8669aa6d0e32..9e1a44b22b0a 100644 --- a/Source/Core/writeTextToCanvas.js +++ b/Source/Core/writeTextToCanvas.js @@ -27,7 +27,10 @@ define([ * @param {Boolean} [options.stroke=false] Whether to stroke the text. * @param {Color} [options.fillColor=Color.WHITE] The fill color. * @param {Color} [options.strokeColor=Color.BLACK] The stroke color. - * @param {Color} [options.strokeWidth=1] The stroke width. + * @param {Number} [options.strokeWidth=1] The stroke width. + * @param {Color} [options.backgroundColor=Color.TRANSPARENT] The background color of the canvas. + * @param {Number} [options.borderWidth=0] The pixel size of the border to add around the text. + * @param {Number} [options.borderColor=Color.BLACK] The color of the border. * @returns {Canvas} A new canvas with the given text drawn into it. The dimensions object * from measureText will also be added to the returned canvas. If text is * blank, returns undefined. @@ -47,6 +50,9 @@ define([ var stroke = defaultValue(options.stroke, false); var fill = defaultValue(options.fill, true); var strokeWidth = defaultValue(options.strokeWidth, 1); + var backgroundColor = defaultValue(options.backgroundColor, Color.TRANSPARENT); + var borderWidth = defaultValue(options.borderWidth, 0); + var halfBorderWidth = borderWidth * 0.5; var canvas = document.createElement('canvas'); canvas.width = 1; @@ -88,11 +94,24 @@ define([ document.body.removeChild(canvas); canvas.style.visibility = ''; - var baseline = dimensions.height - dimensions.ascent; - canvas.width = dimensions.computedWidth; - canvas.height = dimensions.height; + var baseline = dimensions.height - dimensions.ascent + halfBorderWidth; + canvas.width = dimensions.computedWidth + borderWidth; + canvas.height = dimensions.height + borderWidth; var y = canvas.height - baseline; + // Draw border color to whole canvas + if (borderWidth > 0) { + var borderColor = defaultValue(options.borderColor, Color.BLACK); + context2D.fillStyle = borderColor.toCssColorString(); + context2D.fillRect(0, 0, canvas.width, canvas.height); + } + + // Draw background except to the border area + if (backgroundColor !== Color.TRANSPARENT) { + context2D.fillStyle = backgroundColor.toCssColorString(); + context2D.fillRect(halfBorderWidth, halfBorderWidth, canvas.width-borderWidth, canvas.height-borderWidth); + } + // Properties must be explicitly set again after changing width and height context2D.font = font; context2D.lineJoin = 'round'; @@ -102,13 +121,13 @@ define([ if (stroke) { var strokeColor = defaultValue(options.strokeColor, Color.BLACK); context2D.strokeStyle = strokeColor.toCssColorString(); - context2D.strokeText(text, 0, y); + context2D.strokeText(text, halfBorderWidth, y); } if (fill) { var fillColor = defaultValue(options.fillColor, Color.WHITE); context2D.fillStyle = fillColor.toCssColorString(); - context2D.fillText(text, 0, y); + context2D.fillText(text, halfBorderWidth, y); } return canvas; From eeaf9b330782c2c6001b8ac8f41b66da81e107c1 Mon Sep 17 00:00:00 2001 From: Tom Fili Date: Fri, 23 Sep 2016 14:27:22 -0400 Subject: [PATCH 148/191] Added tests. --- Source/Core/writeTextToCanvas.js | 32 ++++++++++--------------- Specs/Core/writeTextToCanvasSpec.js | 37 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/Source/Core/writeTextToCanvas.js b/Source/Core/writeTextToCanvas.js index 9e1a44b22b0a..017fa16bd390 100644 --- a/Source/Core/writeTextToCanvas.js +++ b/Source/Core/writeTextToCanvas.js @@ -30,7 +30,6 @@ define([ * @param {Number} [options.strokeWidth=1] The stroke width. * @param {Color} [options.backgroundColor=Color.TRANSPARENT] The background color of the canvas. * @param {Number} [options.borderWidth=0] The pixel size of the border to add around the text. - * @param {Number} [options.borderColor=Color.BLACK] The color of the border. * @returns {Canvas} A new canvas with the given text drawn into it. The dimensions object * from measureText will also be added to the returned canvas. If text is * blank, returns undefined. @@ -52,7 +51,7 @@ define([ var strokeWidth = defaultValue(options.strokeWidth, 1); var backgroundColor = defaultValue(options.backgroundColor, Color.TRANSPARENT); var borderWidth = defaultValue(options.borderWidth, 0); - var halfBorderWidth = borderWidth * 0.5; + var doubleBorderWidth = borderWidth * 2.0; var canvas = document.createElement('canvas'); canvas.width = 1; @@ -94,40 +93,33 @@ define([ document.body.removeChild(canvas); canvas.style.visibility = ''; - var baseline = dimensions.height - dimensions.ascent + halfBorderWidth; - canvas.width = dimensions.computedWidth + borderWidth; - canvas.height = dimensions.height + borderWidth; + var baseline = dimensions.height - dimensions.ascent + borderWidth; + canvas.width = dimensions.computedWidth + doubleBorderWidth; + canvas.height = dimensions.height + doubleBorderWidth; var y = canvas.height - baseline; - // Draw border color to whole canvas - if (borderWidth > 0) { - var borderColor = defaultValue(options.borderColor, Color.BLACK); - context2D.fillStyle = borderColor.toCssColorString(); - context2D.fillRect(0, 0, canvas.width, canvas.height); - } - - // Draw background except to the border area - if (backgroundColor !== Color.TRANSPARENT) { - context2D.fillStyle = backgroundColor.toCssColorString(); - context2D.fillRect(halfBorderWidth, halfBorderWidth, canvas.width-borderWidth, canvas.height-borderWidth); - } - // Properties must be explicitly set again after changing width and height context2D.font = font; context2D.lineJoin = 'round'; context2D.lineWidth = strokeWidth; context2D[imageSmoothingEnabledName] = false; + // Draw background except to the border area + if (backgroundColor !== Color.TRANSPARENT) { + context2D.fillStyle = backgroundColor.toCssColorString(); + context2D.fillRect(0, 0, canvas.width, canvas.height); + } + if (stroke) { var strokeColor = defaultValue(options.strokeColor, Color.BLACK); context2D.strokeStyle = strokeColor.toCssColorString(); - context2D.strokeText(text, halfBorderWidth, y); + context2D.strokeText(text, borderWidth, y); } if (fill) { var fillColor = defaultValue(options.fillColor, Color.WHITE); context2D.fillStyle = fillColor.toCssColorString(); - context2D.fillText(text, halfBorderWidth, y); + context2D.fillText(text, borderWidth, y); } return canvas; diff --git a/Specs/Core/writeTextToCanvasSpec.js b/Specs/Core/writeTextToCanvasSpec.js index 56136f872066..3b5a0790d88b 100644 --- a/Specs/Core/writeTextToCanvasSpec.js +++ b/Specs/Core/writeTextToCanvasSpec.js @@ -93,4 +93,41 @@ defineSuite([ // canvas2 is stroked, so there should be four "edges" expect(getColorChangeCount(canvas2)).toEqual(4); }); + + it('background color defaults to transparent', function() { + var canvas = writeTextToCanvas('a', { + font : '90px "Open Sans"' + }); + + var context = canvas.getContext('2d'); + var pixel = context.getImageData(0, 0, 1, 1).data; + expect(pixel).toEqual([0,0,0,0]); + }); + + it('background can be set', function() { + var canvas = writeTextToCanvas('a', { + font : '90px "Open Sans"', + backgroundColor : Color.RED + }); + + var context = canvas.getContext('2d'); + var pixel = context.getImageData(0, 0, 1, 1).data; + expect(pixel).toEqual([255,0,0,255]); + }); + + it('border can be set', function() { + var canvas1 = writeTextToCanvas('a', { + font : '90px "Open Sans"', + backgroundColor : Color.RED + }); + + var canvas2 = writeTextToCanvas('a', { + font : '90px "Open Sans"', + backgroundColor : Color.RED, + borderWidth : 2 + }); + + expect(canvas2.width).toEqual(canvas1.width+4); + expect(canvas2.height).toEqual(canvas1.height+4); + }); }); From d4b47f0c253100b54e4973676574a43640c147ec Mon Sep 17 00:00:00 2001 From: Tom Fili Date: Fri, 23 Sep 2016 14:29:10 -0400 Subject: [PATCH 149/191] Tweak --- Source/Core/writeTextToCanvas.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/writeTextToCanvas.js b/Source/Core/writeTextToCanvas.js index 017fa16bd390..c1927b86aacb 100644 --- a/Source/Core/writeTextToCanvas.js +++ b/Source/Core/writeTextToCanvas.js @@ -104,7 +104,7 @@ define([ context2D.lineWidth = strokeWidth; context2D[imageSmoothingEnabledName] = false; - // Draw background except to the border area + // Draw background if (backgroundColor !== Color.TRANSPARENT) { context2D.fillStyle = backgroundColor.toCssColorString(); context2D.fillRect(0, 0, canvas.width, canvas.height); From d70805a80f41abfd7a9c52c6f83bebd98e57d094 Mon Sep 17 00:00:00 2001 From: Tom Fili Date: Fri, 23 Sep 2016 14:41:58 -0400 Subject: [PATCH 150/191] Updated CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 8d1c21265b6b..a5f368e25552 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ Change Log * Added `DebugCameraPrimitive` to visualize the view frustum of a camera. * Fixed touch events for the timeline [#4305](https://github.com/AnalyticalGraphicsInc/cesium/pull/4305) * Removed the default gamma correction for Bing Maps aerial imagery, because we no longer think it is an improvement in current versions of the tiles. To restore the previous look, set the `defaultGamma` property of your `BingMapsImageryProvider` instance to 1.3. +* Added `backgroundColor` and `borderWidth` properties to `writeTextToCanvas`. * Fixed a bug that could lead to incorrect terrain heights when using `HeightmapTerrainData` with an encoding in which actual heights were equal to the minimum representable height. ### 1.25 - 2016-09-01 From aad9a76f2e35beeac049a3ade17956837aa324ff Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 26 Sep 2016 13:45:49 -0400 Subject: [PATCH 151/191] Do not update batch table if there are no per instance attributes. --- Source/Scene/Primitive.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index dba68d57d381..9ed02fb1606f 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -1422,7 +1422,9 @@ define([ if (!defined(this._batchTable)) { createBatchTable(this, frameState.context); } - this._batchTable.update(frameState); + if (this._batchTable.attributes.length > 0) { + this._batchTable.update(frameState); + } if (this._state !== PrimitiveState.COMPLETE && this._state !== PrimitiveState.COMBINED) { if (this.asynchronous) { From 86db25105f0c010e244136e607d1d89d87c6b433 Mon Sep 17 00:00:00 2001 From: Dave Whipps Date: Mon, 26 Sep 2016 14:42:03 -0400 Subject: [PATCH 152/191] Fixed latutude range clamping. Was incorrectly wrapping to 0..PI and 0..-PI when should have been to PI/2 in both cases. --- Source/Core/Math.js | 21 +++++++++++++++++++++ Source/DataSources/KmlDataSource.js | 4 ++-- Specs/DataSources/KmlDataSourceSpec.js | 18 ++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Source/Core/Math.js b/Source/Core/Math.js index 7ca053d20e57..7c9952c522b5 100644 --- a/Source/Core/Math.js +++ b/Source/Core/Math.js @@ -469,6 +469,27 @@ define([ return simplified; }; + /** + * Convenience function that clamps a latitude value, in radians, to the range [-Math.PI/2, Math.PI/2). + * Useful for sanitizing data before use in objects requiring correct range. + * + * @param {Number} angle The latitude value, in radians, to clamp to the range [-Math.PI/2, Math.PI/2). + * @returns {Number} The latitude value clamped to the range [-Math.PI/2, Math.PI/2). + * + * @example + * // Clamp 108 degrees latitude to 90 degrees latitude + * var latitude = Cesium.Math.clampToLatitudeRange(Cesium.Math.toRadians(108.0)); + */ + CesiumMath.clampToLatitudeRange = function(angle) { + //>>includeStart('debug', pragmas.debug); + if (!defined(angle)) { + throw new DeveloperError('angle is required.'); + } + //>>includeEnd('debug'); + + return CesiumMath.clamp(angle, -1*CesiumMath.PI_OVER_TWO, CesiumMath.PI_OVER_TWO); + }; + /** * Produces an angle in the range -Pi <= angle <= Pi which is equivalent to the provided angle. * diff --git a/Source/DataSources/KmlDataSource.js b/Source/DataSources/KmlDataSource.js index 88dec7dc5868..40e2b4d18f9a 100644 --- a/Source/DataSources/KmlDataSource.js +++ b/Source/DataSources/KmlDataSource.js @@ -1664,13 +1664,13 @@ define([ west = CesiumMath.negativePiToPi(CesiumMath.toRadians(west)); } if (defined(south)) { - south = CesiumMath.negativePiToPi(CesiumMath.toRadians(south)); + south = CesiumMath.clampToLatitudeRange(CesiumMath.toRadians(south)); } if (defined(east)) { east = CesiumMath.negativePiToPi(CesiumMath.toRadians(east)); } if (defined(north)) { - north = CesiumMath.negativePiToPi(CesiumMath.toRadians(north)); + north = CesiumMath.clampToLatitudeRange(CesiumMath.toRadians(north)); } geometry.coordinates = new Rectangle(west, south, east, north); diff --git a/Specs/DataSources/KmlDataSourceSpec.js b/Specs/DataSources/KmlDataSourceSpec.js index 8b5c304c592a..2502124ecf28 100644 --- a/Specs/DataSources/KmlDataSourceSpec.js +++ b/Specs/DataSources/KmlDataSourceSpec.js @@ -786,6 +786,24 @@ defineSuite([ }); }); + it('GroundOverlay: Handles out-of-range latitudes.', function() { + var kml = '\ + \ + \ + -180\ + -100\ + 180\ + 100\ + \ + '; + + return KmlDataSource.load(parser.parseFromString(kml, "text/xml"), options).then(function(dataSource) { + var entity = dataSource.entities.values[0]; + expect(entity.polygon).toBeUndefined(); + expect(entity.rectangle.coordinates.getValue()).toEqual(Rectangle.fromDegrees(-180, -90, 180, 90)); + }); + }); + it('GroundOverlay: Sets polygon coordinates for gx:LatLonQuad', function() { var kml = '\ Date: Mon, 26 Sep 2016 14:54:57 -0400 Subject: [PATCH 153/191] Updated CHANGES to reflect bug fix. --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 83e1e22f0fc3..9f780d8ddc67 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,8 @@ Change Log * Fixed touch events for the timeline [#4305](https://github.com/AnalyticalGraphicsInc/cesium/pull/4305) * Removed the default gamma correction for Bing Maps aerial imagery, because we no longer think it is an improvement in current versions of the tiles. To restore the previous look, set the `defaultGamma` property of your `BingMapsImageryProvider` instance to 1.3. * Fixed a bug that could lead to incorrect terrain heights when using `HeightmapTerrainData` with an encoding in which actual heights were equal to the minimum representable height. +* Fixed a bug that was incorrectly clamping Latitudes in KML (s) to the range -PI..PI. Now correctly clamps to -PI/2..PI/2. + ### 1.25 - 2016-09-01 From 29905a0f7d97df1aef9c2229da372d2a28ea89ca Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 26 Sep 2016 15:06:16 -0400 Subject: [PATCH 154/191] Update after merge and make distance display conditions use the batch table. --- Source/Scene/Primitive.js | 135 ++++++++++++++++++++++++++---- Source/Scene/PrimitivePipeline.js | 31 ------- 2 files changed, 121 insertions(+), 45 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 765fd69cfa65..8470778583a3 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -4,6 +4,7 @@ define([ '../Core/Cartesian2', '../Core/Cartesian3', '../Core/Cartesian4', + '../Core/Cartographic', '../Core/clone', '../Core/Color', '../Core/combine', @@ -13,6 +14,7 @@ define([ '../Core/defineProperties', '../Core/destroyObject', '../Core/DeveloperError', + '../Core/EncodedCartesian3', '../Core/FeatureDetection', '../Core/Geometry', '../Core/GeometryAttribute', @@ -43,6 +45,7 @@ define([ Cartesian2, Cartesian3, Cartesian4, + Cartographic, clone, Color, combine, @@ -52,6 +55,7 @@ define([ defineProperties, destroyObject, DeveloperError, + EncodedCartesian3, FeatureDetection, Geometry, GeometryAttribute, @@ -349,6 +353,8 @@ define([ this._batchTableAttributeIndices = undefined; this._instanceBoundingSpheres = undefined; this._instanceBoundingSpheresCV = undefined; + this._batchTableBoundingSpheresUpdated = false; + this._batchTableBoundingSphereAttributeIndices = undefined; } defineProperties(Primitive.prototype, { @@ -541,9 +547,9 @@ define([ var length = names.length; var allowPicking = primitive.allowPicking; - var attributesLength = allowPicking ? length + 1 : length; - var attributes = new Array(attributesLength); + var attributes = []; var attributeIndices = {}; + var boundingSphereAttributeIndices = {}; var firstInstance = instances[0]; var instanceAttributes = firstInstance.attributes; @@ -557,23 +563,53 @@ define([ attribute = instanceAttributes[name]; attributeIndices[name] = i; - attributes[i] = { + attributes.push({ functionName : 'czm_batchTable_' + name, componentDatatype : attribute.componentDatatype, componentsPerAttribute : attribute.componentsPerAttribute, normalize : attribute.normalize - }; + }); + } + + if (names.indexOf('distanceDisplayCondition') !== -1) { + attributes.push({ + functionName : 'czm_batchTable_boundingSphereCenter3DHigh', + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3 + },{ + functionName : 'czm_batchTable_boundingSphereCenter3DLow', + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3 + },{ + functionName : 'czm_batchTable_boundingSphereCenter2DHigh', + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3 + },{ + functionName : 'czm_batchTable_boundingSphereCenter2DLow', + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 3 + },{ + functionName : 'czm_batchTable_boundingSphereRadius', + componentDatatype : ComponentDatatype.FLOAT, + componentsPerAttribute : 1 + }); + boundingSphereAttributeIndices.center3DHigh = attributes.length - 5; + boundingSphereAttributeIndices.center3DLow = attributes.length - 4; + boundingSphereAttributeIndices.center2DHigh = attributes.length - 3; + boundingSphereAttributeIndices.center2DLow = attributes.length - 2; + boundingSphereAttributeIndices.radius = attributes.length - 1; } if (allowPicking) { - attributes[attributesLength - 1] = { + attributes.push({ functionName : 'czm_batchTable_pickColor', componentDatatype : ComponentDatatype.UNSIGNED_BYTE, componentsPerAttribute : 4, normalize : true - }; + }); } + var attributesLength = attributes.length; var batchTable = new BatchTable(attributes, numberOfInstances); for (i = 0; i < numberOfInstances; ++i) { @@ -613,6 +649,7 @@ define([ primitive._batchTable = batchTable; primitive._batchTableAttributeIndices = attributeIndices; + primitive._batchTableBoundingSphereAttributeIndices = boundingSphereAttributeIndices; } function cloneAttribute(attribute) { @@ -778,21 +815,47 @@ define([ return vsPick; }; - Primitive._appendDistanceDisplayConditionToShader = function(primitive, vertexShaderSource) { - if (!defined(primitive._attributeLocations.distanceDisplayCondition)) { + Primitive._appendDistanceDisplayConditionToShader = function(primitive, vertexShaderSource, scene3DOnly) { + if (!defined(primitive._batchTableAttributeIndices.distanceDisplayCondition)) { return vertexShaderSource; } var renamedVS = ShaderSource.replaceMain(vertexShaderSource, 'czm_non_distanceDisplayCondition_main'); var distanceDisplayConditionMain = - 'attribute vec3 boundingSphereCenter3DHigh; \n' + - 'attribute vec3 boundingSphereCenter3DLow; \n' + - 'attribute float boundingSphereRadius; \n' + - 'attribute vec2 distanceDisplayCondition; \n' + 'void main() \n' + '{ \n' + ' czm_non_distanceDisplayCondition_main(); \n' + - ' vec4 centerRTE = czm_computeBoundingSphereCenter(); \n' + + ' vec2 distanceDisplayCondition = czm_batchTable_distanceDisplayCondition(batchId);\n' + + ' vec3 boundingSphereCenter3DHigh = czm_batchTable_boundingSphereCenter3DHigh(batchId);\n' + + ' vec3 boundingSphereCenter3DLow = czm_batchTable_boundingSphereCenter3DLow(batchId);\n' + + ' vec3 boundingSphereCenter2DHigh = czm_batchTable_boundingSphereCenter2DHigh(batchId);\n' + + ' vec3 boundingSphereCenter2DLow = czm_batchTable_boundingSphereCenter2DLow(batchId);\n' + + ' float boundingSphereRadius = czm_batchTable_boundingSphereRadius(batchId);\n'; + + if (!scene3DOnly) { + distanceDisplayConditionMain += + ' vec4 centerRTE;\n' + + ' if (czm_morphTime == 1.0)\n' + + ' {\n' + + ' centerRTE = czm_translateRelativeToEye(boundingSphereCenter3DHigh, boundingSphereCenter3DLow);\n' + + ' }\n' + + ' else if (czm_morphTime == 0.0)\n' + + ' {\n' + + ' centerRTE = czm_translateRelativeToEye(boundingSphereCenter2DHigh.zxy, boundingSphereCenter2DLow.zxy);\n' + + ' }\n' + + ' else\n' + + ' {\n' + + ' centerRTE = czm_columbusViewMorph(\n' + + ' czm_translateRelativeToEye(boundingSphereCenter2DHigh.zxy, boundingSphereCenter2DLow.zxy),\n' + + ' czm_translateRelativeToEye(boundingSphereCenter3DHigh, boundingSphereCenter3DLow),\n' + + ' czm_morphTime);\n' + + ' }\n'; + } else { + distanceDisplayConditionMain += + ' vec4 centerRTE = czm_translateRelativeToEye(boundingSphereCenter3DHigh, boundingSphereCenter3DLow);\n'; + } + + distanceDisplayConditionMain += ' float radiusSq = boundingSphereRadius * boundingSphereRadius; \n' + ' float distanceSq; \n' + ' if (czm_sceneMode == czm_sceneMode2D) \n' + @@ -1097,6 +1160,50 @@ define([ } } + var scratchBoundingSphereCenterEncoded = new EncodedCartesian3(); + var scratchBoundingSphereCartographic = new Cartographic(); + var scratchBoundingSphereCenter2D = new Cartesian3(); + + function updateBatchTableBoundingSpheres(primitive, frameState) { + if (!defined(primitive._batchTableAttributeIndices.distanceDisplayCondition) || primitive._batchTableBoundingSpheresUpdated) { + return; + } + + var indices = primitive._batchTableBoundingSphereAttributeIndices; + var center3DHighIndex = indices.center3DHigh; + var center3DLowIndex = indices.center3DLow; + var center2DHighIndex = indices.center2DHigh; + var center2DLowIndex = indices.center2DLow; + var radiusIndex = indices.radius; + + var projection = frameState.mapProjection; + var ellipsoid = projection.ellipsoid; + + var batchTable = primitive._batchTable; + var boundingSpheres = primitive._instanceBoundingSpheres; + var length = boundingSpheres.length; + + for (var i = 0; i < length; ++i) { + var boundingSphere = boundingSpheres[i]; + var center = boundingSphere.center; + var radius = boundingSphere.radius; + + var encodedCenter = EncodedCartesian3.fromCartesian(center, scratchBoundingSphereCenterEncoded); + batchTable.setBatchedAttribute(i, center3DHighIndex, encodedCenter.high); + batchTable.setBatchedAttribute(i, center3DLowIndex, encodedCenter.low); + + var cartographic = ellipsoid.cartesianToCartographic(center, scratchBoundingSphereCartographic); + var center2D = projection.project(cartographic, scratchBoundingSphereCenter2D); + encodedCenter = EncodedCartesian3.fromCartesian(center2D, scratchBoundingSphereCenterEncoded); + batchTable.setBatchedAttribute(i, center2DHighIndex, encodedCenter.high); + batchTable.setBatchedAttribute(i, center2DLowIndex, encodedCenter.low); + + batchTable.setBatchedAttribute(i, radiusIndex, radius); + } + + primitive._batchTableBoundingSpheresUpdated = true; + } + function createVertexArray(primitive, frameState) { var attributeLocations = primitive._attributeLocations; var geometries = primitive._geometries; @@ -1206,7 +1313,6 @@ define([ var vs = primitive._batchTable.getVertexShaderCallback()(appearance.vertexShaderSource); vs = Primitive._appendShowToShader(primitive, vs); vs = Primitive._appendDistanceDisplayConditionToShader(primitive, vs); - vs = Primitive._modifyShaderPosition(primitive, vs, frameState.scene3DOnly); vs = Primitive._updateColorAttribute(primitive, vs); vs = modifyForEncodedNormals(primitive, vs); vs = Primitive._modifyShaderPosition(primitive, vs, frameState.scene3DOnly); @@ -1471,6 +1577,7 @@ define([ } if (this._state === PrimitiveState.COMBINED) { + updateBatchTableBoundingSpheres(this, frameState); createVertexArray(this, frameState); } diff --git a/Source/Scene/PrimitivePipeline.js b/Source/Scene/PrimitivePipeline.js index c171d6acfc59..95ee4bccd290 100644 --- a/Source/Scene/PrimitivePipeline.js +++ b/Source/Scene/PrimitivePipeline.js @@ -101,37 +101,6 @@ define([ addGeometryBatchId(instance.eastHemisphereGeometry, i); } } - - if (defined(geometry.attributes.distanceDisplayCondition)) { - var boundingSphere = geometry.boundingSphere; - var center = boundingSphere.center; - var radius = boundingSphere.radius; - - var centerValues = Cartesian3.pack(center, centerValuesScratch); - var radiusValues = radiusValuesScratch; - radiusValues[0] = radius; - - var centerBuffer = new Float64Array(numberOfVertices * 3); - var radiusBuffer = new Float32Array(numberOfVertices); - - for (var i = 0; i < numberOfVertices; ++i) { - centerBuffer.set(centerValues, i * 3); - radiusBuffer.set(radiusValues, i); - } - - geometry.attributes.boundingSphereCenter = new GeometryAttribute({ - componentDatatype : ComponentDatatype.DOUBLE, - componentsPerAttribute : 3, - normalize : false, - values : centerBuffer - }); - geometry.attributes.boundingSphereRadius = new GeometryAttribute({ - componentDatatype : ComponentDatatype.FLOAT, - componentsPerAttribute : 1, - normalize : false, - values : radiusBuffer - }); - } } function geometryPipeline(parameters) { From 14d50211dbc27c5f3dffe70a1fad0c1550a86920 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 26 Sep 2016 15:23:00 -0400 Subject: [PATCH 155/191] Updates from review. --- Source/Scene/PrimitivePipeline.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Source/Scene/PrimitivePipeline.js b/Source/Scene/PrimitivePipeline.js index b48aa3d2e239..a09a764f06e2 100644 --- a/Source/Scene/PrimitivePipeline.js +++ b/Source/Scene/PrimitivePipeline.js @@ -59,10 +59,9 @@ define([ if (toWorld) { for (i = 0; i < length; ++i) { - if (!defined(instances[i].geometry)) { - continue; + if (defined(instances[i].geometry)) { + GeometryPipeline.transformToWorldCoordinates(instances[i]); } - GeometryPipeline.transformToWorldCoordinates(instances[i]); } } else { // Leave geometry in local coordinate system; auto update model-matrix. @@ -136,10 +135,9 @@ define([ // Clip to IDL if (!scene3DOnly) { for (i = 0; i < length; ++i) { - if (!defined(instances[i].geometry)) { - continue; + if (defined(instances[i].geometry)) { + GeometryPipeline.splitLongitude(instances[i]); } - GeometryPipeline.splitLongitude(instances[i]); } } @@ -668,7 +666,7 @@ define([ var i = 1; while (i < buffer.length) { - if(buffer[i++] === 1.0) { + if (buffer[i++] === 1.0) { result[count++] = BoundingSphere.unpack(buffer, i); } i += BoundingSphere.packedLength; From 74f73a5ab781d13de8218b07273da0fe2bf1a5d4 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 26 Sep 2016 15:54:47 -0400 Subject: [PATCH 156/191] Check for 3D only when generating the shader function for getting the bounding sphere center. --- Source/Scene/Primitive.js | 2 +- Source/Scene/PrimitivePipeline.js | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index 8470778583a3..aa39d4a7b216 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -1312,7 +1312,7 @@ define([ var vs = primitive._batchTable.getVertexShaderCallback()(appearance.vertexShaderSource); vs = Primitive._appendShowToShader(primitive, vs); - vs = Primitive._appendDistanceDisplayConditionToShader(primitive, vs); + vs = Primitive._appendDistanceDisplayConditionToShader(primitive, vs, frameState.scene3DOnly); vs = Primitive._updateColorAttribute(primitive, vs); vs = modifyForEncodedNormals(primitive, vs); vs = Primitive._modifyShaderPosition(primitive, vs, frameState.scene3DOnly); diff --git a/Source/Scene/PrimitivePipeline.js b/Source/Scene/PrimitivePipeline.js index 95ee4bccd290..b48aa3d2e239 100644 --- a/Source/Scene/PrimitivePipeline.js +++ b/Source/Scene/PrimitivePipeline.js @@ -1,7 +1,6 @@ /*global define*/ define([ '../Core/BoundingSphere', - '../Core/Cartesian3', '../Core/Color', '../Core/ComponentDatatype', '../Core/defaultValue', @@ -19,7 +18,6 @@ define([ '../Core/WebMercatorProjection' ], function( BoundingSphere, - Cartesian3, Color, ComponentDatatype, defaultValue, From 0138c83b088ee6cb32558c71983057d2c88e0020 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 26 Sep 2016 16:33:32 -0400 Subject: [PATCH 157/191] Add distance display condition Sandcastle example that uses entities. --- .../gallery/Distance Display Conditions.html | 103 +++++++++++++++ .../gallery/Distance Display Conditions.jpg | Bin 0 -> 15097 bytes .../development/Display Conditions.html | 118 +++++++++--------- 3 files changed, 162 insertions(+), 59 deletions(-) create mode 100644 Apps/Sandcastle/gallery/Distance Display Conditions.html create mode 100644 Apps/Sandcastle/gallery/Distance Display Conditions.jpg diff --git a/Apps/Sandcastle/gallery/Distance Display Conditions.html b/Apps/Sandcastle/gallery/Distance Display Conditions.html new file mode 100644 index 000000000000..988e9eb62a3c --- /dev/null +++ b/Apps/Sandcastle/gallery/Distance Display Conditions.html @@ -0,0 +1,103 @@ + + + + + + + + + Cesium Demo + + + + + + +
+

Loading...

+
+ + + diff --git a/Apps/Sandcastle/gallery/Distance Display Conditions.jpg b/Apps/Sandcastle/gallery/Distance Display Conditions.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0e9d7551f88bbb73aba7da794a6b98895b830d9f GIT binary patch literal 15097 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 R)(1P0tK{wi9tDq!{{si{-rN8H literal 0 HcmV?d00001 diff --git a/Apps/Sandcastle/gallery/development/Display Conditions.html b/Apps/Sandcastle/gallery/development/Display Conditions.html index 59ee264b88c6..a4c304c7cb2f 100644 --- a/Apps/Sandcastle/gallery/development/Display Conditions.html +++ b/Apps/Sandcastle/gallery/development/Display Conditions.html @@ -25,78 +25,78 @@