From bd5514478dcb1e3de31896634edb8d739b41cd66 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Thu, 22 Mar 2018 14:44:31 -0400 Subject: [PATCH 01/11] working z-indexing [ci skip] --- Source/Core/oneTimeWarning.js | 2 + Source/DataSources/BoxGeometryUpdater.js | 2 + Source/DataSources/CorridorGeometryUpdater.js | 8 +- Source/DataSources/CorridorGraphics.js | 15 ++- Source/DataSources/CylinderGeometryUpdater.js | 2 + Source/DataSources/EllipseGeometryUpdater.js | 8 +- Source/DataSources/EllipseGraphics.js | 15 ++- .../DataSources/EllipsoidGeometryUpdater.js | 2 +- Source/DataSources/GeometryUpdater.js | 5 +- Source/DataSources/GeometryVisualizer.js | 98 ++++++++++++++++--- Source/DataSources/GroundGeometryUpdater.js | 72 ++++++++++++++ Source/DataSources/PlaneGeometryUpdater.js | 2 + Source/DataSources/PolygonGeometryUpdater.js | 8 +- Source/DataSources/PolygonGraphics.js | 16 ++- .../PolylineVolumeGeometryUpdater.js | 2 + .../DataSources/RectangleGeometryUpdater.js | 8 +- Source/DataSources/RectangleGraphics.js | 17 +++- Source/DataSources/WallGeometryUpdater.js | 2 + Specs/DataSources/GeometryVisualizerSpec.js | 2 +- 19 files changed, 256 insertions(+), 30 deletions(-) create mode 100644 Source/DataSources/GroundGeometryUpdater.js diff --git a/Source/Core/oneTimeWarning.js b/Source/Core/oneTimeWarning.js index 2973c4f82404..23634642c4ca 100644 --- a/Source/Core/oneTimeWarning.js +++ b/Source/Core/oneTimeWarning.js @@ -47,5 +47,7 @@ define([ oneTimeWarning.geometryOutlines = 'Entity geometry outlines are unsupported on terrain. Outlines will be disabled. To enable outlines, disable geometry terrain clamping by explicitly setting height to 0.'; + oneTimeWarning.geometryZIndex = 'Entity geometry with zIndex are unsupported when the entity is dynamic, or height or extrudedHeight are defined. zIndex will be ignored'; + return oneTimeWarning; }); diff --git a/Source/DataSources/BoxGeometryUpdater.js b/Source/DataSources/BoxGeometryUpdater.js index bd29108ea4a3..65fc33687cb0 100644 --- a/Source/DataSources/BoxGeometryUpdater.js +++ b/Source/DataSources/BoxGeometryUpdater.js @@ -64,6 +64,8 @@ define([ geometryPropertyName : 'box', observedPropertyNames : ['availability', 'position', 'orientation', 'box'] }); + + this._onEntityPropertyChanged(entity, 'box', entity.box, undefined); } if (defined(Object.create)) { diff --git a/Source/DataSources/CorridorGeometryUpdater.js b/Source/DataSources/CorridorGeometryUpdater.js index 338a33baeccd..e08457d6776c 100644 --- a/Source/DataSources/CorridorGeometryUpdater.js +++ b/Source/DataSources/CorridorGeometryUpdater.js @@ -16,6 +16,7 @@ define([ './ColorMaterialProperty', './DynamicGeometryUpdater', './GeometryUpdater', + './GroundGeometryUpdater', './Property' ], function( Check, @@ -35,6 +36,7 @@ define([ ColorMaterialProperty, DynamicGeometryUpdater, GeometryUpdater, + GroundGeometryUpdater, Property) { 'use strict'; @@ -61,17 +63,19 @@ define([ * @param {Scene} scene The scene where visualization is taking place. */ function CorridorGeometryUpdater(entity, scene) { - GeometryUpdater.call(this, { + GroundGeometryUpdater.call(this, { entity : entity, scene : scene, geometryOptions : new CorridorGeometryOptions(entity), geometryPropertyName : 'corridor', observedPropertyNames : ['availability', 'corridor'] }); + + this._onEntityPropertyChanged(entity, 'corridor', entity.corridor, undefined); } if (defined(Object.create)) { - CorridorGeometryUpdater.prototype = Object.create(GeometryUpdater.prototype); + CorridorGeometryUpdater.prototype = Object.create(GroundGeometryUpdater.prototype); CorridorGeometryUpdater.prototype.constructor = CorridorGeometryUpdater; } diff --git a/Source/DataSources/CorridorGraphics.js b/Source/DataSources/CorridorGraphics.js index d9da02617177..f42ff4c6a082 100644 --- a/Source/DataSources/CorridorGraphics.js +++ b/Source/DataSources/CorridorGraphics.js @@ -39,6 +39,7 @@ define([ * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the distance between each latitude and longitude. * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the corridor casts or receives shadows from each light source. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this corridor will be displayed. + * @param {ConstantProperty} [options.zIndex] A Property specifying the zIndex of the corridor, used for ordering. Only has an effect if height and extrudedHeight are undefined, and if the corridor is static. * * @see Entity * @demo {@link https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Corridor.html|Cesium Sandcastle Corridor Demo} @@ -74,6 +75,8 @@ define([ this._distanceDisplayConditionSubscription = undefined; this._classificationType = undefined; this._classificationTypeSubscription = undefined; + this._zIndex = undefined; + this._zIndexSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -209,7 +212,15 @@ define([ * @type {Property} * @default ClassificationType.BOTH */ - classificationType : createPropertyDescriptor('classificationType') + classificationType : createPropertyDescriptor('classificationType'), + + /** + * Gets or sets the zIndex Property specifying the ordering of the corridor. Only has an effect if the coridor is static and neither height or exturdedHeight are specified. + * @memberof CorridorGraphics.prototype + * @type {ConstantProperty} + * @default 0 + */ + zIndex: createPropertyDescriptor('zIndex') }); /** @@ -237,6 +248,7 @@ define([ result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; result.classificationType = this.classificationType; + result.zIndex = this.zIndex; return result; }; @@ -268,6 +280,7 @@ define([ this.shadows = defaultValue(this.shadows, source.shadows); this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); this.classificationType = defaultValue(this.classificationType, source.classificationType); + this.zIndex = defaultValue(this.zIndex, source.zIndex); }; return CorridorGraphics; diff --git a/Source/DataSources/CylinderGeometryUpdater.js b/Source/DataSources/CylinderGeometryUpdater.js index 8216266e1ee3..90c863049ce3 100644 --- a/Source/DataSources/CylinderGeometryUpdater.js +++ b/Source/DataSources/CylinderGeometryUpdater.js @@ -68,6 +68,8 @@ define([ geometryPropertyName: 'cylinder', observedPropertyNames: ['availability', 'position', 'orientation', 'cylinder'] }); + + this._onEntityPropertyChanged(entity, 'cylinder', entity.cylinder, undefined); } if (defined(Object.create)) { diff --git a/Source/DataSources/EllipseGeometryUpdater.js b/Source/DataSources/EllipseGeometryUpdater.js index 45c1eec20ee9..d6cc26277e3e 100644 --- a/Source/DataSources/EllipseGeometryUpdater.js +++ b/Source/DataSources/EllipseGeometryUpdater.js @@ -16,6 +16,7 @@ define([ './ColorMaterialProperty', './DynamicGeometryUpdater', './GeometryUpdater', + './GroundGeometryUpdater', './Property' ], function( Check, @@ -35,6 +36,7 @@ define([ ColorMaterialProperty, DynamicGeometryUpdater, GeometryUpdater, + GroundGeometryUpdater, Property) { 'use strict'; @@ -64,17 +66,19 @@ define([ * @param {Scene} scene The scene where visualization is taking place. */ function EllipseGeometryUpdater(entity, scene) { - GeometryUpdater.call(this, { + GroundGeometryUpdater.call(this, { entity : entity, scene : scene, geometryOptions : new EllipseGeometryOptions(entity), geometryPropertyName : 'ellipse', observedPropertyNames : ['availability', 'position', 'ellipse'] }); + + this._onEntityPropertyChanged(entity, 'ellipse', entity.ellipse, undefined); } if (defined(Object.create)) { - EllipseGeometryUpdater.prototype = Object.create(GeometryUpdater.prototype); + EllipseGeometryUpdater.prototype = Object.create(GroundGeometryUpdater.prototype); EllipseGeometryUpdater.prototype.constructor = EllipseGeometryUpdater; } diff --git a/Source/DataSources/EllipseGraphics.js b/Source/DataSources/EllipseGraphics.js index 066040239541..afce93014cf0 100644 --- a/Source/DataSources/EllipseGraphics.js +++ b/Source/DataSources/EllipseGraphics.js @@ -42,6 +42,7 @@ define([ * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between points on the ellipse. * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the ellipse casts or receives shadows from each light source. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this ellipse will be displayed. + * @param {ConstantProperty} [options.zIndex=0] A property specifying the zIndex of the Ellipse. Used for ordering ground geometry. Only has an effect if the ellipse is constant and neither height or exturdedHeight are specified. * * @demo {@link https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Circles and Ellipses.html|Cesium Sandcastle Circles and Ellipses Demo} */ @@ -80,6 +81,8 @@ define([ this._distanceDisplayConditionSubscription = undefined; this._classificationType = undefined; this._classificationTypeSubscription = undefined; + this._zIndex = undefined; + this._zIndexSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -231,7 +234,15 @@ define([ * @type {Property} * @default ClassificationType.BOTH */ - classificationType : createPropertyDescriptor('classificationType') + classificationType : createPropertyDescriptor('classificationType'), + + /** + * Gets or sets the zIndex Property specifying the ellipse ordering. Only has an effect if the ellipse is constant and neither height or extrudedHeight are specified + * @memberof EllipseGraphics.prototype + * @type {ConstantProperty} + * @default 0 + */ + zIndex : createPropertyDescriptor('zIndex') }); /** @@ -261,6 +272,7 @@ define([ result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; result.classificationType = this.classificationType; + result.zIndex = this.zIndex; return result; }; @@ -294,6 +306,7 @@ define([ this.shadows = defaultValue(this.shadows, source.shadows); this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); this.classificationType = defaultValue(this.classificationType, source.classificationType); + this.zIndex = defaultValue(this.zIndex, source.zIndex); }; return EllipseGraphics; diff --git a/Source/DataSources/EllipsoidGeometryUpdater.js b/Source/DataSources/EllipsoidGeometryUpdater.js index 34ecddc475b0..41f6b4052e27 100644 --- a/Source/DataSources/EllipsoidGeometryUpdater.js +++ b/Source/DataSources/EllipsoidGeometryUpdater.js @@ -81,7 +81,7 @@ define([ observedPropertyNames : ['availability', 'position', 'orientation', 'ellipsoid'] }); - this._isClosed = true; + this._onEntityPropertyChanged(entity, 'ellipsoid', entity.ellipsoid, undefined); } if (defined(Object.create)) { diff --git a/Source/DataSources/GeometryUpdater.js b/Source/DataSources/GeometryUpdater.js index 0846738c42fc..a5ade1ad4f7f 100644 --- a/Source/DataSources/GeometryUpdater.js +++ b/Source/DataSources/GeometryUpdater.js @@ -44,8 +44,7 @@ define([ var defaultClassificationType = new ConstantProperty(ClassificationType.BOTH); /** - * A {@link GeometryUpdater} for boxes. - * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}. + * An abstract class for updating geometry entites. * @alias GeometryUpdater * @constructor * @@ -88,8 +87,6 @@ define([ this._geometryPropertyName = geometryPropertyName; this._id = geometryPropertyName + '-' + entity.id; this._observedPropertyNames = options.observedPropertyNames; - - this._onEntityPropertyChanged(entity, geometryPropertyName, entity[geometryPropertyName], undefined); } defineProperties(GeometryUpdater.prototype, { diff --git a/Source/DataSources/GeometryVisualizer.js b/Source/DataSources/GeometryVisualizer.js index 72ed71a89100..51be3f4769cb 100644 --- a/Source/DataSources/GeometryVisualizer.js +++ b/Source/DataSources/GeometryVisualizer.js @@ -11,6 +11,7 @@ define([ '../Scene/ClassificationType', '../Scene/MaterialAppearance', '../Scene/PerInstanceColorAppearance', + '../Scene/PrimitiveCollection', '../Scene/ShadowMode', './BoundingSphereState', './BoxGeometryUpdater', @@ -42,6 +43,7 @@ define([ ClassificationType, MaterialAppearance, PerInstanceColorAppearance, + PrimitiveCollection, ShadowMode, BoundingSphereState, BoxGeometryUpdater, @@ -112,6 +114,17 @@ define([ destroyObject(this); }; + function createGroundColorBatch(groundPrimitives) { + var numberOfClassificationTypes = ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES; + var batches = new Array(numberOfClassificationTypes); + + for (var i = 0; i < numberOfClassificationTypes; ++i) { + batches[i] = new StaticGroundGeometryColorBatch(groundPrimitives, i); + } + batches._primitives = groundPrimitives; + return batches; + } + /** * A general purpose visualizer for geometry represented by {@link Primitive} instances. * @alias GeometryVisualizer @@ -134,6 +147,7 @@ define([ this._scene = scene; this._primitives = primitives; this._groundPrimitives = groundPrimitives; + this._orderedGroundPrimitives = groundPrimitives.add(new PrimitiveCollection()); this._entityCollection = undefined; this._addedObjects = new AssociativeArray(); this._removedObjects = new AssociativeArray(); @@ -146,8 +160,7 @@ define([ this._openColorBatches = new Array(numberOfShadowModes); this._openMaterialBatches = new Array(numberOfShadowModes); - var i; - for (i = 0; i < numberOfShadowModes; ++i) { + for (var i = 0; i < numberOfShadowModes; ++i) { this._outlineBatches[i] = new StaticOutlineGeometryBatch(primitives, scene, i); this._closedColorBatches[i] = new StaticGeometryColorBatch(primitives, PerInstanceColorAppearance, undefined, true, i); @@ -156,16 +169,12 @@ define([ this._openMaterialBatches[i] = new StaticGeometryPerMaterialBatch(primitives, MaterialAppearance, undefined, false, i); } - var numberOfClassificationTypes = ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES; - this._groundColorBatches = new Array(numberOfClassificationTypes); - - for (i = 0; i < numberOfClassificationTypes; ++i) { - this._groundColorBatches[i] = new StaticGroundGeometryColorBatch(groundPrimitives, i); - } + this._groundColorBatches = {}; + this._reorderGroundPrimitives = false; this._dynamicBatch = new DynamicGeometryBatch(primitives, groundPrimitives); - this._batches = this._outlineBatches.concat(this._closedColorBatches, this._closedMaterialBatches, this._openColorBatches, this._openMaterialBatches, this._groundColorBatches, this._dynamicBatch); + this._batches = this._outlineBatches.concat(this._closedColorBatches, this._closedMaterialBatches, this._openColorBatches, this._openMaterialBatches, this._dynamicBatch); this._subscriptions = new AssociativeArray(); this._updaterSets = new AssociativeArray(); @@ -255,6 +264,25 @@ define([ isUpdated = batches[i].update(time) && isUpdated; } + var orderedGroundPrimitives = this._orderedGroundPrimitives; + var groundBatches = this._groundColorBatches; + var groundBatchIndexes = Object.keys(groundBatches); + groundBatchIndexes = groundBatchIndexes.sort(); + + if (this._reorderGroundPrimitives) { + for (i = 0; i < groundBatchIndexes.length; i++) { + orderedGroundPrimitives.raiseToTop(groundBatches[groundBatchIndexes[i]]._primitives); + } + this._reorderGroundPrimitives = false; + } + + var numberOfClassificationTypes = ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES; + for (i = 0; i < groundBatchIndexes.length; i++) { + for (var j = 0; j < numberOfClassificationTypes; j++) { + isUpdated = groundBatches[groundBatchIndexes[i]][j].update(time) && isUpdated; + } + } + return isUpdated; }; @@ -291,7 +319,8 @@ define([ for (var j = 0; j < updaters.length; j++) { var updater = updaters[j]; - for (var i = 0; i < batchesLength; i++) { + var i; + for (i = 0; i < batchesLength; i++) { state = batches[i].getBoundingSphere(updater, tmp); if (state === BoundingSphereState.PENDING) { return BoundingSphereState.PENDING; @@ -300,6 +329,21 @@ define([ count++; } } + + var groundBatches = this._groundColorBatches; + var groundBatchIndexes = Object.keys(groundBatches); + var numberOfClassificationTypes = ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES; + for (i = 0; i < groundBatchIndexes.length; i++) { + for (var k = 0; k < numberOfClassificationTypes; k++) { + state = groundBatches[groundBatchIndexes[i]][k].getBoundingSphere(updater, tmp); + if (state === BoundingSphereState.PENDING) { + return BoundingSphereState.PENDING; + } else if (state === BoundingSphereState.DONE) { + boundingSpheres[count] = BoundingSphere.clone(tmp, boundingSpheres[count]); + count++; + } + } + } } if (count === 0) { @@ -335,12 +379,23 @@ define([ batches[i].removeAllPrimitives(); } + var groundBatches = this._groundColorBatches; + var groundBatchIndexes = Object.keys(groundBatches); + var numberOfClassificationTypes = ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES; + for (i = 0; i < groundBatchIndexes.length; i++) { + for (var k = 0; k < numberOfClassificationTypes; k++) { + groundBatches[groundBatchIndexes[i]][k].removeAllPrimitives(); + } + } + var subscriptions = this._subscriptions.values; length = subscriptions.length; for (i = 0; i < length; i++) { subscriptions[i](); } this._subscriptions.removeAll(); + + this._groundPrimitives.remove(this._orderedGroundPrimitives); return destroyObject(this); }; @@ -351,9 +406,19 @@ define([ //We don't keep track of which batch an updater is in, so just remove it from all of them. var batches = this._batches; var length = batches.length; - for (var i = 0; i < length; i++) { + var i; + for (i = 0; i < length; i++) { batches[i].remove(updater); } + + var groundBatches = this._groundColorBatches; + var groundBatchIndexes = Object.keys(groundBatches); + var numberOfClassificationTypes = ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES; + for (i = 0; i < groundBatchIndexes.length; i++) { + for (var k = 0; k < numberOfClassificationTypes; k++) { + groundBatches[groundBatchIndexes[i]][k].remove(updater); + } + } }; /** @@ -376,8 +441,17 @@ define([ if (updater.fillEnabled) { if (updater.onTerrain) { + var zIndex = updater.zIndex; + var batchArray = this._groundColorBatches[zIndex]; + if (!defined(batchArray)) { + batchArray = createGroundColorBatch(this._orderedGroundPrimitives.add(new PrimitiveCollection())); + this._groundColorBatches[zIndex] = batchArray; + this._reorderGroundPrimitives = true; + } + var classificationType = updater.classificationTypeProperty.getValue(time); - this._groundColorBatches[classificationType].add(time, updater); + var batch = batchArray[classificationType]; + batch.add(time, updater); } else if (updater.isClosed) { if (updater.fillMaterialProperty instanceof ColorMaterialProperty) { this._closedColorBatches[shadows].add(time, updater); diff --git a/Source/DataSources/GroundGeometryUpdater.js b/Source/DataSources/GroundGeometryUpdater.js new file mode 100644 index 000000000000..924354716fa1 --- /dev/null +++ b/Source/DataSources/GroundGeometryUpdater.js @@ -0,0 +1,72 @@ +define([ + '../Core/defined', + '../Core/defineProperties', + '../Core/Iso8601', + '../Core/oneTimeWarning', + './GeometryUpdater', + './Property' +], function( + defined, + defineProperties, + Iso8601, + oneTimeWarning, + GeometryUpdater, + Property) { + 'use strict'; + + /** + * An abstract class for updating ground geometry entities. + * @constructor + * + * @param {Object} options An object with the following properties: + * @param {Entity} options.entity The entity containing the geometry to be visualized. + * @param {Scene} options.scene The scene where visualization is taking place. + * @param {Object} options.geometryOptions Options for the geometry + * @param {String} options.geometryPropertyName The geometry property name + * @param {String[]} options.observedPropertyNames The entity properties this geometry cares about + */ + function GroundGeometryUpdater(options) { + GeometryUpdater.call(this, options); + + this._zIndex = 0; + } + + if (defined(Object.create)) { + GroundGeometryUpdater.prototype = Object.create(GeometryUpdater.prototype); + GroundGeometryUpdater.prototype.constructor = GroundGeometryUpdater; + } + + defineProperties(GroundGeometryUpdater.prototype, { + /** + * Gets the zindex + * @type {Number} + * @memberof GroundGeometryUpdater.prototype + * @readonly + */ + zIndex: { + get: function() { + return this._zIndex; + } + } + }); + + GroundGeometryUpdater.prototype._onEntityPropertyChanged = function(entity, propertyName, newValue, oldValue) { + GeometryUpdater.prototype._onEntityPropertyChanged.call(this, entity, propertyName, newValue, oldValue); + if (this._observedPropertyNames.indexOf(propertyName) === -1) { + return; + } + + var geometry = this._entity[this._geometryPropertyName]; + if (!defined(geometry)) { + return; + } + var zIndex = geometry.zIndex; + if (this._dynamic || !Property.isConstant(geometry.zIndex) || defined(this._options.height) || defined(this._options.extrudedHeight)) { + oneTimeWarning(oneTimeWarning.geometryZIndex); + } + + this._zIndex = Property.getValueOrDefault(zIndex, Iso8601.MINIMUM_VALUE, 0); + }; + + return GroundGeometryUpdater; +}); diff --git a/Source/DataSources/PlaneGeometryUpdater.js b/Source/DataSources/PlaneGeometryUpdater.js index b82289a56337..5c70bd1e38a2 100644 --- a/Source/DataSources/PlaneGeometryUpdater.js +++ b/Source/DataSources/PlaneGeometryUpdater.js @@ -71,6 +71,8 @@ define([ geometryPropertyName : 'plane', observedPropertyNames : ['availability', 'position', 'orientation', 'plane'] }); + + this._onEntityPropertyChanged(entity, 'plane', entity.plane, undefined); } if (defined(Object.create)) { diff --git a/Source/DataSources/PolygonGeometryUpdater.js b/Source/DataSources/PolygonGeometryUpdater.js index 293d463812d3..3bb06bcae2ac 100644 --- a/Source/DataSources/PolygonGeometryUpdater.js +++ b/Source/DataSources/PolygonGeometryUpdater.js @@ -18,6 +18,7 @@ define([ './ColorMaterialProperty', './DynamicGeometryUpdater', './GeometryUpdater', + './GroundGeometryUpdater', './Property' ], function( Check, @@ -39,6 +40,7 @@ define([ ColorMaterialProperty, DynamicGeometryUpdater, GeometryUpdater, + GroundGeometryUpdater, Property) { 'use strict'; @@ -67,17 +69,19 @@ define([ * @param {Scene} scene The scene where visualization is taking place. */ function PolygonGeometryUpdater(entity, scene) { - GeometryUpdater.call(this, { + GroundGeometryUpdater.call(this, { entity : entity, scene : scene, geometryOptions : new PolygonGeometryOptions(entity), geometryPropertyName : 'polygon', observedPropertyNames : ['availability', 'polygon'] }); + + this._onEntityPropertyChanged(entity, 'polygon', entity.polygon, undefined); } if (defined(Object.create)) { - PolygonGeometryUpdater.prototype = Object.create(GeometryUpdater.prototype); + PolygonGeometryUpdater.prototype = Object.create(GroundGeometryUpdater.prototype); PolygonGeometryUpdater.prototype.constructor = PolygonGeometryUpdater; } diff --git a/Source/DataSources/PolygonGraphics.js b/Source/DataSources/PolygonGraphics.js index 92364efb5a71..f66d92a4d005 100644 --- a/Source/DataSources/PolygonGraphics.js +++ b/Source/DataSources/PolygonGraphics.js @@ -41,6 +41,7 @@ define([ * @param {Boolean} [options.closeBottom=true] When false, leaves off the bottom of an extruded polygon open. * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the polygon casts or receives shadows from each light source. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this polygon will be displayed. + * @param {ConstantProperty} [options.zIndex=0] A property specifying the zIndex used for ordering ground geometry. Only has an effect if the polygon is constant and neither height or extrudedHeight are specified. * * @see Entity * @demo {@link https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Polygon.html|Cesium Sandcastle Polygon Demo} @@ -80,6 +81,8 @@ define([ this._distanceDisplayConditionSubscription = undefined; this._classificationType = undefined; this._classificationTypeSubscription = undefined; + this._zIndex = undefined; + this._zIndexSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -232,7 +235,15 @@ define([ * @type {Property} * @default ClassificationType.BOTH */ - classificationType : createPropertyDescriptor('classificationType') + classificationType : createPropertyDescriptor('classificationType'), + + /** + * Gets or sets the zIndex Prperty specifying the ordering of ground geometry. Only has an effect if the polygon is constant and neither height or extrudedHeight are specified. + * @memberof PolygonGraphics.prototype + * @type {ConstantProperty} + * @default 0 + */ + zIndex : createPropertyDescriptor('zIndex') }); /** @@ -262,6 +273,8 @@ define([ result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; result.classificationType = this.classificationType; + result.zIndex = this.zIndex; + return result; }; @@ -295,6 +308,7 @@ define([ this.shadows = defaultValue(this.shadows, source.shadows); this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); this.classificationType = defaultValue(this.classificationType, source.classificationType); + this.zIndex = defaultValue(this.zIndex, source.zIndex); }; return PolygonGraphics; diff --git a/Source/DataSources/PolylineVolumeGeometryUpdater.js b/Source/DataSources/PolylineVolumeGeometryUpdater.js index 899d36d10974..b3fa49ced383 100644 --- a/Source/DataSources/PolylineVolumeGeometryUpdater.js +++ b/Source/DataSources/PolylineVolumeGeometryUpdater.js @@ -64,6 +64,8 @@ define([ geometryPropertyName : 'polylineVolume', observedPropertyNames : ['availability', 'polylineVolume'] }); + + this._onEntityPropertyChanged(entity, 'polylineVolume', entity.polylineVolume, undefined); } if (defined(Object.create)) { diff --git a/Source/DataSources/RectangleGeometryUpdater.js b/Source/DataSources/RectangleGeometryUpdater.js index 5ebe539f5df3..4e1fcb6a8be0 100644 --- a/Source/DataSources/RectangleGeometryUpdater.js +++ b/Source/DataSources/RectangleGeometryUpdater.js @@ -16,6 +16,7 @@ define([ './ColorMaterialProperty', './DynamicGeometryUpdater', './GeometryUpdater', + './GroundGeometryUpdater', './Property' ], function( Check, @@ -35,6 +36,7 @@ define([ ColorMaterialProperty, DynamicGeometryUpdater, GeometryUpdater, + GroundGeometryUpdater, Property) { 'use strict'; @@ -61,17 +63,19 @@ define([ * @param {Scene} scene The scene where visualization is taking place. */ function RectangleGeometryUpdater(entity, scene) { - GeometryUpdater.call(this, { + GroundGeometryUpdater.call(this, { entity : entity, scene : scene, geometryOptions : new RectangleGeometryOptions(entity), geometryPropertyName : 'rectangle', observedPropertyNames : ['availability', 'rectangle'] }); + + this._onEntityPropertyChanged(entity, 'rectangle', entity.rectangle, undefined); } if (defined(Object.create)) { - RectangleGeometryUpdater.prototype = Object.create(GeometryUpdater.prototype); + RectangleGeometryUpdater.prototype = Object.create(GroundGeometryUpdater.prototype); RectangleGeometryUpdater.prototype.constructor = RectangleGeometryUpdater; } diff --git a/Source/DataSources/RectangleGraphics.js b/Source/DataSources/RectangleGraphics.js index fda0edf37a4f..b4880a42fb8d 100644 --- a/Source/DataSources/RectangleGraphics.js +++ b/Source/DataSources/RectangleGraphics.js @@ -39,6 +39,7 @@ define([ * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between points on the rectangle. * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the rectangle casts or receives shadows from each light source. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this rectangle will be displayed. + * @param {Property} [options.zIndex=0] A Property specifying the zIndex used for ordering ground geometry. Only has an effect if the rectangle is constant and neither height or extrudedHeight are specified. * * @see Entity * @demo {@link https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Rectangle.html|Cesium Sandcastle Rectangle Demo} @@ -74,6 +75,9 @@ define([ this._distancedisplayConditionSubscription = undefined; this._classificationType = undefined; this._classificationTypeSubscription = undefined; + this._zIndex = undefined; + this._zIndexSubscription = undefined; + this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -210,7 +214,15 @@ define([ * @type {Property} * @default ClassificationType.BOTH */ - classificationType : createPropertyDescriptor('classificationType') + classificationType : createPropertyDescriptor('classificationType'), + + /** + * Gets or sets the zIndex Property specifying the ordering of the rectangle. Only has an effect if the rectangle is constant and neither height or extrudedHeight are specified. + * @memberof RectangleGraphics.prototype + * @type {ConstantProperty} + * @default 0 + */ + zIndex : createPropertyDescriptor('zIndex') }); /** @@ -238,6 +250,8 @@ define([ result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; result.classificationType = this.classificationType; + result.zIndex = this.zIndex; + return result; }; @@ -269,6 +283,7 @@ define([ this.shadows = defaultValue(this.shadows, source.shadows); this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); this.classificationType = defaultValue(this.classificationType, source.classificationType); + this.zIndex = defaultValue(this.zIndex, source.zIndex); }; return RectangleGraphics; diff --git a/Source/DataSources/WallGeometryUpdater.js b/Source/DataSources/WallGeometryUpdater.js index e66a73b3f35f..07f8ea30b19b 100644 --- a/Source/DataSources/WallGeometryUpdater.js +++ b/Source/DataSources/WallGeometryUpdater.js @@ -64,6 +64,8 @@ define([ geometryPropertyName : 'wall', observedPropertyNames : ['availability', 'wall'] }); + + this._onEntityPropertyChanged(entity, 'wall', entity.wall, undefined); } if (defined(Object.create)) { diff --git a/Specs/DataSources/GeometryVisualizerSpec.js b/Specs/DataSources/GeometryVisualizerSpec.js index 689ea3df8aa8..b1ef59af3615 100644 --- a/Specs/DataSources/GeometryVisualizerSpec.js +++ b/Specs/DataSources/GeometryVisualizerSpec.js @@ -374,7 +374,7 @@ defineSuite([ scene.render(time); return isUpdated; }).then(function() { - var primitive = scene.groundPrimitives.get(0); + var primitive = scene.groundPrimitives.get(0).get(0).get(0); expect(primitive.classificationType).toBe(type); objects.remove(entity); From c970417b35a34867a37e8020d498328b9e2a8336 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Thu, 22 Mar 2018 15:08:37 -0400 Subject: [PATCH 02/11] sandcastle example --- .../Sandcastle/gallery/Ordering Geometry.html | 93 +++++++++++++++++++ Source/DataSources/GroundGeometryUpdater.js | 8 +- 2 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 Apps/Sandcastle/gallery/Ordering Geometry.html diff --git a/Apps/Sandcastle/gallery/Ordering Geometry.html b/Apps/Sandcastle/gallery/Ordering Geometry.html new file mode 100644 index 000000000000..2a4c1b2aaca7 --- /dev/null +++ b/Apps/Sandcastle/gallery/Ordering Geometry.html @@ -0,0 +1,93 @@ + + + + + + + + + Cesium Demo + + + + + + +
+

Loading...

+
+ + + diff --git a/Source/DataSources/GroundGeometryUpdater.js b/Source/DataSources/GroundGeometryUpdater.js index 924354716fa1..1dddfe9ce545 100644 --- a/Source/DataSources/GroundGeometryUpdater.js +++ b/Source/DataSources/GroundGeometryUpdater.js @@ -1,4 +1,5 @@ define([ + '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', '../Core/Iso8601', @@ -6,6 +7,7 @@ define([ './GeometryUpdater', './Property' ], function( + defaultValue, defined, defineProperties, Iso8601, @@ -60,12 +62,12 @@ define([ if (!defined(geometry)) { return; } - var zIndex = geometry.zIndex; - if (this._dynamic || !Property.isConstant(geometry.zIndex) || defined(this._options.height) || defined(this._options.extrudedHeight)) { + var zIndex = Property.getValueOrUndefined(geometry.zIndex, Iso8601.MINIMUM_VALUE); + if (defined(zIndex) && (this._dynamic || !Property.isConstant(geometry.zIndex) || defined(this._options.height) || defined(this._options.extrudedHeight))) { oneTimeWarning(oneTimeWarning.geometryZIndex); } - this._zIndex = Property.getValueOrDefault(zIndex, Iso8601.MINIMUM_VALUE, 0); + this._zIndex = defaultValue(zIndex, 0); }; return GroundGeometryUpdater; From ce145b5cfebd90cf0f8f8b416a0281e761779d37 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Thu, 22 Mar 2018 15:57:07 -0400 Subject: [PATCH 03/11] Fix ordering, add to kml --- ...Geometry.html => Z-Indexing Geometry.html} | 0 .../gallery/Z-Indexing Geometry.jpg | Bin 0 -> 15127 bytes Source/DataSources/GeometryVisualizer.js | 8 +++++++- Source/DataSources/KmlDataSource.js | 19 ++++++++++++++---- 4 files changed, 22 insertions(+), 5 deletions(-) rename Apps/Sandcastle/gallery/{Ordering Geometry.html => Z-Indexing Geometry.html} (100%) create mode 100644 Apps/Sandcastle/gallery/Z-Indexing Geometry.jpg diff --git a/Apps/Sandcastle/gallery/Ordering Geometry.html b/Apps/Sandcastle/gallery/Z-Indexing Geometry.html similarity index 100% rename from Apps/Sandcastle/gallery/Ordering Geometry.html rename to Apps/Sandcastle/gallery/Z-Indexing Geometry.html diff --git a/Apps/Sandcastle/gallery/Z-Indexing Geometry.jpg b/Apps/Sandcastle/gallery/Z-Indexing Geometry.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3da960f0ad21237c10e7ad68b3109046a158b912 GIT binary patch literal 15127 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 Date: Thu, 22 Mar 2018 17:26:13 -0400 Subject: [PATCH 04/11] specs and CHANGES.md --- CHANGES.md | 4 +- Source/DataSources/KmlDataSource.js | 2 +- Specs/DataSources/CorridorGraphicsSpec.js | 13 +- Specs/DataSources/EllipseGraphicsSpec.js | 13 +- Specs/DataSources/GeometryVisualizerSpec.js | 112 ++++++++++++++++++ Specs/DataSources/KmlDataSourceSpec.js | 50 +++++++- Specs/DataSources/PolygonGraphicsSpec.js | 13 +- Specs/DataSources/RectangleGraphicsSpec.js | 13 +- ...reateGeometryUpdaterGroundGeometrySpecs.js | 15 +++ 9 files changed, 227 insertions(+), 8 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index d3276b2cc5f1..8440d5f4a64c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -29,7 +29,8 @@ Change Log * `Credit` has been modified to take an HTML string as the credit content [#6331](https://github.com/AnalyticalGraphicsInc/cesium/pull/6331) * Added support for ordering in `DataSourceCollection` [#6316](https://github.com/AnalyticalGraphicsInc/cesium/pull/6316) * All ground geometry from one `DataSource` will render in front of all ground geometry from another `DataSource` in the same collection with a lower index. - * Use `DataSourceCollection.raise`, `DataSourceCollection.lower`, `DataSourceCollection.raiseToTop` and `DataSourceCollection.lowerToBottom` functions to change the ordering of a `DataSource` in the collection. + * Use `DataSourceCollection.raise`, `DataSourceCollection.lower`, `DataSourceCollection.raiseToTop` and `DataSourceCollection.lowerToBottom` functions to change the ordering of a `DataSource` in the collection. +* Added `zIndex` support for static `Corridor`, `Ellipse`, `Polygon` and `Rectangle` entities [#6362](https://github.com/AnalyticalGraphicsInc/cesium/pull/6362) ##### Fixes :wrench: * Fixed support of glTF-supplied tangent vectors. [#6302](https://github.com/AnalyticalGraphicsInc/cesium/pull/6302) @@ -40,7 +41,6 @@ Change Log * Fixed rendering vector tiles when using `invertClassification`. [#6349](https://github.com/AnalyticalGraphicsInc/cesium/pull/6349) * Fixed animation for glTF models with missing animation targets. [#6351](https://github.com/AnalyticalGraphicsInc/cesium/pull/6351) - ### 1.43 - 2018-03-01 ##### Major Announcements :loudspeaker: diff --git a/Source/DataSources/KmlDataSource.js b/Source/DataSources/KmlDataSource.js index 4daee1ee802d..64b10dbcba06 100644 --- a/Source/DataSources/KmlDataSource.js +++ b/Source/DataSources/KmlDataSource.js @@ -1883,7 +1883,7 @@ define([ var ellipsoid = dataSource._ellipsoid; var positions = readCoordinates(queryFirstNode(groundOverlay, 'LatLonQuad', namespaces.gx), ellipsoid); - var zIndex = queryFirstNode(groundOverlay, 'drawOrder', namespaces.kml); + var zIndex = queryNumericValue(groundOverlay, 'drawOrder', namespaces.kml); if (defined(positions)) { geometry = createDefaultPolygon(); geometry.hierarchy = new PolygonHierarchy(positions); diff --git a/Specs/DataSources/CorridorGraphicsSpec.js b/Specs/DataSources/CorridorGraphicsSpec.js index 141fe8c7a529..cf0baf1ded93 100644 --- a/Specs/DataSources/CorridorGraphicsSpec.js +++ b/Specs/DataSources/CorridorGraphicsSpec.js @@ -38,7 +38,8 @@ defineSuite([ cornerType : CornerType.BEVELED, shadows : ShadowMode.DISABLED, distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0), - classificationType : ClassificationType.TERRAIN + classificationType : ClassificationType.TERRAIN, + zIndex: 3 }; var corridor = new CorridorGraphics(options); @@ -57,6 +58,7 @@ defineSuite([ expect(corridor.shadows).toBeInstanceOf(ConstantProperty); expect(corridor.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(corridor.classificationType).toBeInstanceOf(ConstantProperty); + expect(corridor.zIndex).toBeInstanceOf(ConstantProperty); expect(corridor.material.color.getValue()).toEqual(options.material); expect(corridor.positions.getValue()).toEqual(options.positions); @@ -73,6 +75,7 @@ defineSuite([ expect(corridor.shadows.getValue()).toEqual(options.shadows); expect(corridor.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); expect(corridor.classificationType.getValue()).toEqual(options.classificationType); + expect(corridor.zIndex.getValue()).toEqual(options.zIndex); }); it('merge assigns unassigned properties', function() { @@ -92,6 +95,7 @@ defineSuite([ source.shadows = new ConstantProperty(ShadowMode.ENABLED); source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); source.classificationType = new ConstantProperty(ClassificationType.TERRAIN); + source.zIndex = new ConstantProperty(3); var target = new CorridorGraphics(); target.merge(source); @@ -111,6 +115,7 @@ defineSuite([ expect(target.shadows).toBe(source.shadows); expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); expect(target.classificationType).toBe(source.classificationType); + expect(target.zIndex).toBe(source.zIndex); }); it('merge does not assign assigned properties', function() { @@ -131,6 +136,7 @@ defineSuite([ var shadows = new ConstantProperty(); var distanceDisplayCondition = new ConstantProperty(); var classificationType = new ConstantProperty(); + var zIndex = new ConstantProperty(); var target = new CorridorGraphics(); target.material = material; @@ -148,6 +154,7 @@ defineSuite([ target.shadows = shadows; target.distanceDisplayCondition = distanceDisplayCondition; target.classificationType = classificationType; + target.zIndex = zIndex; target.merge(source); @@ -166,6 +173,7 @@ defineSuite([ expect(target.shadows).toBe(shadows); expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); expect(target.classificationType).toBe(classificationType); + expect(target.zIndex).toBe(zIndex); }); it('clone works', function() { @@ -185,6 +193,7 @@ defineSuite([ source.shadows = new ConstantProperty(); source.distanceDisplayCondition = new ConstantProperty(); source.classificationType = new ConstantProperty(); + source.zIndex = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -202,6 +211,7 @@ defineSuite([ expect(result.shadows).toBe(source.shadows); expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); expect(result.classificationType).toBe(source.classificationType); + expect(result.zIndex).toBe(source.zIndex); }); it('merge throws if source undefined', function() { @@ -228,5 +238,6 @@ defineSuite([ testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 100.0)); testDefinitionChanged(property, 'classificationType', ClassificationType.TERRAIN, ClassificationType.BOTH); + testDefinitionChanged(property, 'zIndex', 3, 0); }); }); diff --git a/Specs/DataSources/EllipseGraphicsSpec.js b/Specs/DataSources/EllipseGraphicsSpec.js index 62324f7aa38d..fdec8f339ca4 100644 --- a/Specs/DataSources/EllipseGraphicsSpec.js +++ b/Specs/DataSources/EllipseGraphicsSpec.js @@ -38,7 +38,8 @@ defineSuite([ outlineWidth : 9, shadows : ShadowMode.DISABLED, distanceDisplayCondition : new DistanceDisplayCondition(), - classificationType : ClassificationType.TERRAIN + classificationType : ClassificationType.TERRAIN, + zIndex: 3 }; var ellipse = new EllipseGraphics(options); @@ -59,6 +60,7 @@ defineSuite([ expect(ellipse.shadows).toBeInstanceOf(ConstantProperty); expect(ellipse.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(ellipse.classificationType).toBeInstanceOf(ConstantProperty); + expect(ellipse.zIndex).toBeInstanceOf(ConstantProperty); expect(ellipse.material.color.getValue()).toEqual(options.material); expect(ellipse.show.getValue()).toEqual(options.show); @@ -77,6 +79,7 @@ defineSuite([ expect(ellipse.shadows.getValue()).toEqual(options.shadows); expect(ellipse.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); expect(ellipse.classificationType.getValue()).toEqual(options.classificationType); + expect(ellipse.zIndex.getValue()).toEqual(options.zIndex); }); it('merge assigns unassigned properties', function() { @@ -98,6 +101,7 @@ defineSuite([ source.shadows = new ConstantProperty(ShadowMode.ENABLED); source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); source.classificationType = new ConstantProperty(ClassificationType.TERRAIN); + source.zIndex = new ConstantProperty(3); var target = new EllipseGraphics(); target.merge(source); @@ -119,6 +123,7 @@ defineSuite([ expect(target.shadows).toBe(source.shadows); expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); expect(target.classificationType).toBe(source.classificationType); + expect(target.zIndex).toBe(source.zIndex); }); it('merge does not assign assigned properties', function() { @@ -141,6 +146,7 @@ defineSuite([ var shadows = new ConstantProperty(); var distanceDisplayCondition = new ConstantProperty(); var classificationType = new ConstantProperty(); + var zIndex = new ConstantProperty(); var target = new EllipseGraphics(); target.material = material; @@ -160,6 +166,7 @@ defineSuite([ target.shadows = shadows; target.distanceDisplayCondition = distanceDisplayCondition; target.classificationType = classificationType; + target.zIndex = zIndex; target.merge(source); @@ -180,6 +187,7 @@ defineSuite([ expect(target.shadows).toBe(shadows); expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); expect(target.classificationType).toBe(classificationType); + expect(target.zIndex).toBe(zIndex); }); it('clone works', function() { @@ -201,6 +209,7 @@ defineSuite([ source.shadows = new ConstantProperty(); source.distanceDisplayCondition = new ConstantProperty(); source.classificationType = new ConstantProperty(); + source.zIndex = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -220,6 +229,7 @@ defineSuite([ expect(result.shadows).toBe(source.shadows); expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); expect(result.classificationType).toBe(source.classificationType); + expect(result.zIndex).toBe(source.zIndex); }); it('merge throws if source undefined', function() { @@ -248,5 +258,6 @@ defineSuite([ testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 100.0)); testDefinitionChanged(property, 'classificationType', ClassificationType.TERRAIN, ClassificationType.BOTH); + testDefinitionChanged(property, 'zIndex', 4, 0); }); }); diff --git a/Specs/DataSources/GeometryVisualizerSpec.js b/Specs/DataSources/GeometryVisualizerSpec.js index b1ef59af3615..36d2b302a2e3 100644 --- a/Specs/DataSources/GeometryVisualizerSpec.js +++ b/Specs/DataSources/GeometryVisualizerSpec.js @@ -554,9 +554,121 @@ defineSuite([ expect(visualizer.update(time)).toBe(true); scene.render(time); expect(scene.primitives.length).toBe(0); + expect(scene.groundPrimitives.length).toBe(1); visualizer.destroy(); }); + it('Creates and removes static color geometry on terrain', function() { + scene.groundPrimitives.removeAll(); + var objects = new EntityCollection(); + var visualizer = new GeometryVisualizer(scene, objects, scene.primitives, scene.groundPrimitives); + + var ellipse = new EllipseGraphics(); + ellipse.semiMajorAxis = new ConstantProperty(2); + ellipse.semiMinorAxis = new ConstantProperty(1); + ellipse.material = new ColorMaterialProperty(); + + var entity = new Entity(); + entity.position = new ConstantPositionProperty(new Cartesian3(1234, 5678, 9101112)); + entity.ellipse = ellipse; + objects.add(entity); + + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }).then(function() { + var primitive = scene.groundPrimitives.get(0).get(0).get(0); + var attributes = primitive.getGeometryInstanceAttributes(entity); + expect(attributes).toBeDefined(); + expect(attributes.show).toEqual(ShowGeometryInstanceAttribute.toValue(true)); + expect(attributes.color).toEqual(ColorGeometryInstanceAttribute.toValue(Color.WHITE)); + + objects.remove(entity); + + return pollToPromise(function() { + scene.initializeFrame(); + expect(visualizer.update(time)).toBe(true); + scene.render(time); + return scene.groundPrimitives.get(0).get(0).length === 0; + }).then(function(){ + visualizer.destroy(); + expect(scene.groundPrimitives.length).toBe(0); + }); + }); + }); + + it('Users zIndex to order static color geometry on terrain', function() { + scene.groundPrimitives.removeAll(); + var objects = new EntityCollection(); + var visualizer = new GeometryVisualizer(scene, objects, scene.primitives, scene.groundPrimitives); + + var ellipse = new EllipseGraphics(); + ellipse.semiMajorAxis = new ConstantProperty(2); + ellipse.semiMinorAxis = new ConstantProperty(1); + ellipse.material = new ColorMaterialProperty(Color.GREEN); + ellipse.zIndex = 0; + var entity1 = new Entity(); + entity1.position = new ConstantPositionProperty(new Cartesian3(1234, 5678, 9101112)); + entity1.ellipse = ellipse; + objects.add(entity1); + + var entity2 = new Entity(); + ellipse = new EllipseGraphics(); + ellipse.semiMajorAxis = new ConstantProperty(2); + ellipse.semiMinorAxis = new ConstantProperty(1); + ellipse.material = new ColorMaterialProperty(Color.RED); + ellipse.zIndex = 3; + entity2.position = new ConstantPositionProperty(new Cartesian3(1234, 5678, 9101112)); + entity2.ellipse = ellipse; + objects.add(entity2); + + var entity3 = new Entity(); + ellipse = new EllipseGraphics(); + ellipse.semiMajorAxis = new ConstantProperty(2); + ellipse.semiMinorAxis = new ConstantProperty(1); + ellipse.material = new ColorMaterialProperty(Color.BLUE); + ellipse.zIndex = 2; + entity3.position = new ConstantPositionProperty(new Cartesian3(1234, 5678, 9101112)); + entity3.ellipse = ellipse; + objects.add(entity3); + + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }).then(function() { + var layer = scene.groundPrimitives.get(0); + expect(layer.length).toBe(3); + var primitive = layer.get(0).get(0); + var attributes = primitive.getGeometryInstanceAttributes(entity1); + expect(attributes).toBeDefined(); + expect(attributes.show).toEqual(ShowGeometryInstanceAttribute.toValue(true)); + expect(attributes.color).toEqual(ColorGeometryInstanceAttribute.toValue(Color.GREEN)); + + primitive = layer.get(1).get(0); + attributes = primitive.getGeometryInstanceAttributes(entity3); + expect(attributes).toBeDefined(); + expect(attributes.show).toEqual(ShowGeometryInstanceAttribute.toValue(true)); + expect(attributes.color).toEqual(ColorGeometryInstanceAttribute.toValue(Color.BLUE)); + + primitive = layer.get(2).get(0); + attributes = primitive.getGeometryInstanceAttributes(entity2); + expect(attributes).toBeDefined(); + expect(attributes.show).toEqual(ShowGeometryInstanceAttribute.toValue(true)); + expect(attributes.color).toEqual(ColorGeometryInstanceAttribute.toValue(Color.RED)); + + objects.remove(entity1); + objects.remove(entity2); + objects.remove(entity3); + + visualizer.destroy(); + expect(scene.groundPrimitives.length).toBe(0); + }); + }); + it('Constructor throws without scene', function() { var objects = new EntityCollection(); expect(function() { diff --git a/Specs/DataSources/KmlDataSourceSpec.js b/Specs/DataSources/KmlDataSourceSpec.js index 202d4da998a0..2e47a176996e 100644 --- a/Specs/DataSources/KmlDataSourceSpec.js +++ b/Specs/DataSources/KmlDataSourceSpec.js @@ -888,7 +888,7 @@ defineSuite([ }); }); - it('GroundOverlay: Sets rectangle coordinates and rotation', function() { + it('GroundOverlay: Sets rectangle coordinates, rotation and zIndex', function() { var kml = '\ \ \ @@ -898,6 +898,7 @@ defineSuite([ 2\ 45\ \ + 3\ '; return KmlDataSource.load(parser.parseFromString(kml, "text/xml"), options).then(function(dataSource) { @@ -906,6 +907,7 @@ defineSuite([ expect(entity.rectangle.coordinates.getValue()).toEqualEpsilon(Rectangle.fromDegrees(3, 1, 4, 2), CesiumMath.EPSILON14); expect(entity.rectangle.rotation.getValue()).toEqual(Math.PI / 4); expect(entity.rectangle.stRotation.getValue()).toEqual(Math.PI / 4); + expect(entity.rectangle.zIndex.getValue()).toEqual(3); }); }); @@ -984,6 +986,24 @@ defineSuite([ }); }); + it('GroundOverlay: Sets polygon zIndex for gx:LatLonQuad', function() { + var kml = '\ + \ + \ + \ + 1,2 3,4 5,6 7,8\ + \ + \ + 3\ + '; + + return KmlDataSource.load(parser.parseFromString(kml, "text/xml"), options).then(function(dataSource) { + var entity = dataSource.entities.values[0]; + expect(entity.polygon.zIndex.getValue()).toEqual(3); + }); + }); + it('GroundOverlay: Sets rectangle absolute height', function() { var kml = '\ \ @@ -4676,4 +4696,32 @@ defineSuite([ expect(entity.corridor.material).toBeInstanceOf(ColorMaterialProperty); }); }); + + it('when a LineString is clamped to ground and tesselated with z draworder, entity has a corridor geometry and ColorProperty', function() { + var kml = '\ + \ + \ + \ + \ + clampToGround\ + true\ + 1,2,3\ + 4,5,6\ + \ + 2\ + \ + \ + '; + var clampToGroundOptions = combine(options, { clampToGround : true }); + return KmlDataSource.load(parser.parseFromString(kml, "text/xml"), clampToGroundOptions).then(function(dataSource) { + var entity = dataSource.entities.values[0]; + expect(entity.corridor).toBeDefined(); + expect(entity.corridor.zIndex.getValue()).toBe(2); + }); + }); }); diff --git a/Specs/DataSources/PolygonGraphicsSpec.js b/Specs/DataSources/PolygonGraphicsSpec.js index ffe11cc487db..a313822e45b6 100644 --- a/Specs/DataSources/PolygonGraphicsSpec.js +++ b/Specs/DataSources/PolygonGraphicsSpec.js @@ -40,7 +40,8 @@ defineSuite([ closeBottom : true, shadows : ShadowMode.DISABLED, distanceDisplayCondition : new DistanceDisplayCondition(), - classificationType : ClassificationType.TERRAIN + classificationType : ClassificationType.TERRAIN, + zIndex: 22 }; var polygon = new PolygonGraphics(options); @@ -61,6 +62,7 @@ defineSuite([ expect(polygon.shadows).toBeInstanceOf(ConstantProperty); expect(polygon.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(polygon.classificationType).toBeInstanceOf(ConstantProperty); + expect(polygon.zIndex).toBeInstanceOf(ConstantProperty); expect(polygon.material.color.getValue()).toEqual(options.material); expect(polygon.show.getValue()).toEqual(options.show); @@ -79,6 +81,7 @@ defineSuite([ expect(polygon.shadows.getValue()).toEqual(options.shadows); expect(polygon.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); expect(polygon.classificationType.getValue()).toEqual(options.classificationType); + expect(polygon.zIndex.getValue()).toEqual(22); }); it('merge assigns unassigned properties', function() { @@ -100,6 +103,7 @@ defineSuite([ source.shadows = new ConstantProperty(ShadowMode.ENABLED); source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); source.classificationType = new ConstantProperty(ClassificationType.TERRAIN); + source.zIndex = new ConstantProperty(30); var target = new PolygonGraphics(); target.merge(source); @@ -121,6 +125,7 @@ defineSuite([ expect(target.shadows).toBe(source.shadows); expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); expect(target.classificationType).toBe(source.classificationType); + expect(target.zIndex).toBe(source.zIndex); }); it('merge does not assign assigned properties', function() { @@ -143,6 +148,7 @@ defineSuite([ var shadows = new ConstantProperty(); var distanceDisplayCondition = new ConstantProperty(); var classificationType = new ConstantProperty(); + var zIndex = new ConstantProperty(); var target = new PolygonGraphics(); target.material = material; @@ -162,6 +168,7 @@ defineSuite([ target.shadows = shadows; target.distanceDisplayCondition = distanceDisplayCondition; target.classificationType = classificationType; + target.zIndex = zIndex; target.merge(source); @@ -182,6 +189,7 @@ defineSuite([ expect(target.shadows).toBe(shadows); expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); expect(target.classificationType).toBe(classificationType); + expect(target.zIndex).toBe(zIndex); }); it('clone works', function() { @@ -203,6 +211,7 @@ defineSuite([ source.shadows = new ConstantProperty(); source.distanceDisplayCondition = new ConstantProperty(); source.classificationType = new ConstantProperty(); + source.zIndex = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -222,6 +231,7 @@ defineSuite([ expect(result.shadows).toBe(source.shadows); expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); expect(result.classificationType).toBe(source.classificationType); + expect(result.zIndex).toBe(source.zIndex); }); it('merge throws if source undefined', function() { @@ -250,5 +260,6 @@ defineSuite([ testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 100.0)); testDefinitionChanged(property, 'classificationType', ClassificationType.TERRAIN, ClassificationType.BOTH); + testDefinitionChanged(property, 'zIndex', 54, 3); }); }); diff --git a/Specs/DataSources/RectangleGraphicsSpec.js b/Specs/DataSources/RectangleGraphicsSpec.js index d543da2e2e41..8b7116042935 100644 --- a/Specs/DataSources/RectangleGraphicsSpec.js +++ b/Specs/DataSources/RectangleGraphicsSpec.js @@ -38,7 +38,8 @@ defineSuite([ outlineWidth : 10, shadows : ShadowMode.DISABLED, distanceDisplayCondition : new DistanceDisplayCondition(), - classificationType : ClassificationType.TERRAIN + classificationType : ClassificationType.TERRAIN, + zIndex: 5 }; var rectangle = new RectangleGraphics(options); @@ -57,6 +58,7 @@ defineSuite([ expect(rectangle.shadows).toBeInstanceOf(ConstantProperty); expect(rectangle.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(rectangle.classificationType).toBeInstanceOf(ConstantProperty); + expect(rectangle.zIndex).toBeInstanceOf(ConstantProperty); expect(rectangle.material.color.getValue()).toEqual(options.material); expect(rectangle.show.getValue()).toEqual(options.show); @@ -73,6 +75,7 @@ defineSuite([ expect(rectangle.shadows.getValue()).toEqual(options.shadows); expect(rectangle.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); expect(rectangle.classificationType.getValue()).toEqual(options.classificationType); + expect(rectangle.zIndex.getValue()).toEqual(options.zIndex); }); it('merge assigns unassigned properties', function() { @@ -92,6 +95,7 @@ defineSuite([ source.shadows = new ConstantProperty(ShadowMode.ENABLED); source.distanceDisplayCondition = new ConstantProperty(); source.classificationType = new ConstantProperty(); + source.zIndex = new ConstantProperty(); var target = new RectangleGraphics(); target.merge(source); @@ -111,6 +115,7 @@ defineSuite([ expect(target.shadows).toBe(source.shadows); expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); expect(target.classificationType).toBe(source.classificationType); + expect(target.zIndex).toBe(source.zIndex); }); it('merge does not assign assigned properties', function() { @@ -131,6 +136,7 @@ defineSuite([ var shadows = new ConstantProperty(); var distanceDisplayCondition = new ConstantProperty(); var classificationType = new ConstantProperty(); + var zIndex = new ConstantProperty(); var target = new RectangleGraphics(); target.material = material; @@ -148,6 +154,7 @@ defineSuite([ target.shadows = shadows; target.distanceDisplayCondition = distanceDisplayCondition; target.classificationType = classificationType; + target.zIndex = zIndex; target.merge(source); @@ -166,6 +173,7 @@ defineSuite([ expect(target.shadows).toBe(shadows); expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); expect(target.classificationType).toBe(classificationType); + expect(target.zIndex).toBe(zIndex); }); it('clone works', function() { @@ -185,6 +193,7 @@ defineSuite([ source.shadows = new ConstantProperty(); source.distanceDisplayCondition = new ConstantProperty(); source.classificationType = new ConstantProperty(); + source.zIndex = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -202,6 +211,7 @@ defineSuite([ expect(result.shadows).toBe(source.shadows); expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); expect(result.classificationType).toBe(source.classificationType); + expect(result.zIndex).toBe(source.zIndex); }); it('merge throws if source undefined', function() { @@ -228,5 +238,6 @@ defineSuite([ testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 100.0)); testDefinitionChanged(property, 'classificationType', ClassificationType.TERRAIN, ClassificationType.BOTH); + testDefinitionChanged(property, 'zIndex', 20, 5); }); }); diff --git a/Specs/createGeometryUpdaterGroundGeometrySpecs.js b/Specs/createGeometryUpdaterGroundGeometrySpecs.js index 79b5268e9340..1cfb53ab4c86 100644 --- a/Specs/createGeometryUpdaterGroundGeometrySpecs.js +++ b/Specs/createGeometryUpdaterGroundGeometrySpecs.js @@ -21,6 +21,21 @@ define([ function createGeometryUpdaterGroundGeometrySpecs(Updater, geometryPropertyName, createEntity, createDynamicEntity, getScene) { var time = JulianDate.now(); + it('has default zIndex of zero', function() { + var entity = createEntity(); + + var updater = new Updater(entity, getScene()); + expect(updater.zIndex).toBe(0); + }); + + it('uses zIndex value', function() { + var entity = createEntity(); + entity[geometryPropertyName].zIndex = 22; + + var updater = new Updater(entity, getScene()); + expect(updater.zIndex).toBe(22); + }); + it('A time-varying color causes ground geometry to be dynamic', function() { var entity = createEntity(); var color = new SampledProperty(Color); From 85df9efe46dcf344f06f3ecbd9afccb1c73d3fb4 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Wed, 9 May 2018 15:12:43 -0400 Subject: [PATCH 05/11] zIndex for static and dynamic geometry --- Source/DataSources/CorridorGeometryUpdater.js | 1 + Source/DataSources/DataSourceDisplay.js | 4 +- Source/DataSources/DynamicGeometryBatch.js | 6 +- Source/DataSources/DynamicGeometryUpdater.js | 18 +- Source/DataSources/EllipseGeometryUpdater.js | 1 + Source/DataSources/GeometryVisualizer.js | 224 ++++++----------- Source/DataSources/GroundGeometryUpdater.js | 15 +- Source/DataSources/PolygonGeometryUpdater.js | 1 + .../DataSources/RectangleGeometryUpdater.js | 1 + .../StaticGroundGeometryColorBatch.js | 14 +- Source/Scene/GroundPrimitive.js | 3 + .../Scene/OrderedGroundPrimitiveCollection.js | 230 ++++++++++++++++++ Source/Scene/PrimitiveCollection.js | 3 + 13 files changed, 344 insertions(+), 177 deletions(-) create mode 100644 Source/Scene/OrderedGroundPrimitiveCollection.js diff --git a/Source/DataSources/CorridorGeometryUpdater.js b/Source/DataSources/CorridorGeometryUpdater.js index e08457d6776c..590af5f02a6e 100644 --- a/Source/DataSources/CorridorGeometryUpdater.js +++ b/Source/DataSources/CorridorGeometryUpdater.js @@ -189,6 +189,7 @@ define([ !Property.isConstant(corridor.width) || // !Property.isConstant(corridor.outlineWidth) || // !Property.isConstant(corridor.cornerType) || // + !Property.isConstant(corridor.zIndex) || // (this._onTerrain && !Property.isConstant(this._materialProperty)); }; diff --git a/Source/DataSources/DataSourceDisplay.js b/Source/DataSources/DataSourceDisplay.js index 0a4a1bc51363..896503d7d71f 100644 --- a/Source/DataSources/DataSourceDisplay.js +++ b/Source/DataSources/DataSourceDisplay.js @@ -7,6 +7,7 @@ define([ '../Core/destroyObject', '../Core/EventHelper', '../Scene/GroundPrimitive', + '../Scene/OrderedGroundPrimitiveCollection', '../Scene/PrimitiveCollection', './BillboardVisualizer', './BoundingSphereState', @@ -26,6 +27,7 @@ define([ destroyObject, EventHelper, GroundPrimitive, + OrderedGroundPrimitiveCollection, PrimitiveCollection, BillboardVisualizer, BoundingSphereState, @@ -362,7 +364,7 @@ define([ var displayGroundPrimitives = this._groundPrimitives; var primitives = displayPrimitives.add(new PrimitiveCollection()); - var groundPrimitives = displayGroundPrimitives.add(new PrimitiveCollection()); + var groundPrimitives = displayGroundPrimitives.add(new OrderedGroundPrimitiveCollection()); dataSource._primitives = primitives; dataSource._groundPrimitives = groundPrimitives; diff --git a/Source/DataSources/DynamicGeometryBatch.js b/Source/DataSources/DynamicGeometryBatch.js index 800577bdd5c5..c46bcd6e6506 100644 --- a/Source/DataSources/DynamicGeometryBatch.js +++ b/Source/DataSources/DynamicGeometryBatch.js @@ -11,14 +11,14 @@ define([ /** * @private */ - function DynamicGeometryBatch(primitives, groundPrimitives) { + function DynamicGeometryBatch(primitives, orderedGroundPrimitives) { this._primitives = primitives; - this._groundPrimitives = groundPrimitives; + this._orderedGroundPrimitives = orderedGroundPrimitives; this._dynamicUpdaters = new AssociativeArray(); } DynamicGeometryBatch.prototype.add = function(time, updater) { - this._dynamicUpdaters.set(updater.id, updater.createDynamicUpdater(this._primitives, this._groundPrimitives)); + this._dynamicUpdaters.set(updater.id, updater.createDynamicUpdater(this._primitives, this._orderedGroundPrimitives)); }; DynamicGeometryBatch.prototype.remove = function(updater) { diff --git a/Source/DataSources/DynamicGeometryUpdater.js b/Source/DataSources/DynamicGeometryUpdater.js index 672a5db01d4d..59e73d262b36 100644 --- a/Source/DataSources/DynamicGeometryUpdater.js +++ b/Source/DataSources/DynamicGeometryUpdater.js @@ -41,15 +41,15 @@ define([ * @constructor * @private */ - function DynamicGeometryUpdater(geometryUpdater, primitives, groundPrimitives) { + function DynamicGeometryUpdater(geometryUpdater, primitives, orderedGroundPrimitives) { //>>includeStart('debug', pragmas.debug); Check.defined('geometryUpdater', geometryUpdater); Check.defined('primitives', primitives); - Check.defined('groundPrimitives', groundPrimitives); + Check.defined('orderedGroundPrimitives', orderedGroundPrimitives); //>>includeEnd('debug'); this._primitives = primitives; - this._groundPrimitives = groundPrimitives; + this._orderedGroundPrimitives = orderedGroundPrimitives; this._primitive = undefined; this._outlinePrimitive = undefined; this._geometryUpdater = geometryUpdater; @@ -80,9 +80,9 @@ define([ var onTerrain = geometryUpdater._onTerrain; var primitives = this._primitives; - var groundPrimitives = this._groundPrimitives; + var orderedGroundPrimitives = this._orderedGroundPrimitives; if (onTerrain) { - groundPrimitives.removeAndDestroy(this._primitive); + orderedGroundPrimitives.remove(this._primitive); } else { primitives.removeAndDestroy(this._primitive); primitives.removeAndDestroy(this._outlinePrimitive); @@ -102,11 +102,11 @@ define([ if (!defined(geometry.fill) || geometry.fill.getValue(time)) { if (onTerrain) { options.vertexFormat = PerInstanceColorAppearance.VERTEX_FORMAT; - this._primitive = groundPrimitives.add(new GroundPrimitive({ + this._primitive = orderedGroundPrimitives.add(new GroundPrimitive({ geometryInstances : this._geometryUpdater.createFillGeometryInstance(time), asynchronous : false, shadows : shadows - })); + }), Property.getValueOrUndefined(this._geometryUpdater.zIndex, time)); } else { var fillMaterialProperty = geometryUpdater.fillMaterialProperty; var isColorAppearance = fillMaterialProperty instanceof ColorMaterialProperty; @@ -229,9 +229,9 @@ define([ */ DynamicGeometryUpdater.prototype.destroy = function() { var primitives = this._primitives; - var groundPrimitives = this._groundPrimitives; + var orderedGroundPrimitives = this._orderedGroundPrimitives; if (this._geometryUpdater._onTerrain) { - groundPrimitives.removeAndDestroy(this._primitive); + orderedGroundPrimitives.remove(this._primitive); } else { primitives.removeAndDestroy(this._primitive); } diff --git a/Source/DataSources/EllipseGeometryUpdater.js b/Source/DataSources/EllipseGeometryUpdater.js index d6cc26277e3e..2478c3198c5e 100644 --- a/Source/DataSources/EllipseGeometryUpdater.js +++ b/Source/DataSources/EllipseGeometryUpdater.js @@ -192,6 +192,7 @@ define([ !Property.isConstant(ellipse.stRotation) || // !Property.isConstant(ellipse.outlineWidth) || // !Property.isConstant(ellipse.numberOfVerticalLines) || // + !Property.isConstant(ellipse.zIndex) || // (this._onTerrain && !Property.isConstant(this._materialProperty)); }; diff --git a/Source/DataSources/GeometryVisualizer.js b/Source/DataSources/GeometryVisualizer.js index b69688ee1146..aaa1816aa723 100644 --- a/Source/DataSources/GeometryVisualizer.js +++ b/Source/DataSources/GeometryVisualizer.js @@ -1,71 +1,69 @@ define([ - '../Core/AssociativeArray', - '../Core/BoundingSphere', - '../Core/Check', - '../Core/defaultValue', - '../Core/defined', - '../Core/destroyObject', - '../Core/Event', - '../Core/EventHelper', - '../Scene/ClassificationType', - '../Scene/MaterialAppearance', - '../Scene/PerInstanceColorAppearance', - '../Scene/PrimitiveCollection', - '../Scene/ShadowMode', - './BoundingSphereState', - './BoxGeometryUpdater', - './ColorMaterialProperty', - './CorridorGeometryUpdater', - './CylinderGeometryUpdater', - './DynamicGeometryBatch', - './EllipseGeometryUpdater', - './EllipsoidGeometryUpdater', - './PlaneGeometryUpdater', - './PolygonGeometryUpdater', - './PolylineVolumeGeometryUpdater', - './RectangleGeometryUpdater', - './StaticGeometryColorBatch', - './StaticGeometryPerMaterialBatch', - './StaticGroundGeometryColorBatch', - './StaticOutlineGeometryBatch', - './WallGeometryUpdater' - ], function( - AssociativeArray, - BoundingSphere, - Check, - defaultValue, - defined, - destroyObject, - Event, - EventHelper, - ClassificationType, - MaterialAppearance, - PerInstanceColorAppearance, - PrimitiveCollection, - ShadowMode, - BoundingSphereState, - BoxGeometryUpdater, - ColorMaterialProperty, - CorridorGeometryUpdater, - CylinderGeometryUpdater, - DynamicGeometryBatch, - EllipseGeometryUpdater, - EllipsoidGeometryUpdater, - PlaneGeometryUpdater, - PolygonGeometryUpdater, - PolylineVolumeGeometryUpdater, - RectangleGeometryUpdater, - StaticGeometryColorBatch, - StaticGeometryPerMaterialBatch, - StaticGroundGeometryColorBatch, - StaticOutlineGeometryBatch, - WallGeometryUpdater) { + '../Core/AssociativeArray', + '../Core/BoundingSphere', + '../Core/Check', + '../Core/defaultValue', + '../Core/defined', + '../Core/destroyObject', + '../Core/Event', + '../Core/EventHelper', + '../Scene/ClassificationType', + '../Scene/MaterialAppearance', + '../Scene/PerInstanceColorAppearance', + '../Scene/ShadowMode', + './BoundingSphereState', + './BoxGeometryUpdater', + './ColorMaterialProperty', + './CorridorGeometryUpdater', + './CylinderGeometryUpdater', + './DynamicGeometryBatch', + './EllipseGeometryUpdater', + './EllipsoidGeometryUpdater', + './PlaneGeometryUpdater', + './PolygonGeometryUpdater', + './PolylineVolumeGeometryUpdater', + './RectangleGeometryUpdater', + './StaticGeometryColorBatch', + './StaticGeometryPerMaterialBatch', + './StaticGroundGeometryColorBatch', + './StaticOutlineGeometryBatch', + './WallGeometryUpdater' +], function( + AssociativeArray, + BoundingSphere, + Check, + defaultValue, + defined, + destroyObject, + Event, + EventHelper, + ClassificationType, + MaterialAppearance, + PerInstanceColorAppearance, + ShadowMode, + BoundingSphereState, + BoxGeometryUpdater, + ColorMaterialProperty, + CorridorGeometryUpdater, + CylinderGeometryUpdater, + DynamicGeometryBatch, + EllipseGeometryUpdater, + EllipsoidGeometryUpdater, + PlaneGeometryUpdater, + PolygonGeometryUpdater, + PolylineVolumeGeometryUpdater, + RectangleGeometryUpdater, + StaticGeometryColorBatch, + StaticGeometryPerMaterialBatch, + StaticGroundGeometryColorBatch, + StaticOutlineGeometryBatch, + WallGeometryUpdater) { 'use strict'; var emptyArray = []; var geometryUpdaters = [BoxGeometryUpdater, CylinderGeometryUpdater, CorridorGeometryUpdater, EllipseGeometryUpdater, EllipsoidGeometryUpdater, PlaneGeometryUpdater, - PolygonGeometryUpdater, PolylineVolumeGeometryUpdater, RectangleGeometryUpdater, WallGeometryUpdater]; + PolygonGeometryUpdater, PolylineVolumeGeometryUpdater, RectangleGeometryUpdater, WallGeometryUpdater]; function GeometryUpdaterSet(entity, scene) { this.entity = entity; @@ -112,23 +110,6 @@ define([ destroyObject(this); }; - function createGroundColorBatch(groundPrimitives) { - var numberOfClassificationTypes = ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES; - var batches = new Array(numberOfClassificationTypes); - - for (var i = 0; i < numberOfClassificationTypes; ++i) { - batches[i] = new StaticGroundGeometryColorBatch(groundPrimitives, i); - } - batches._primitives = groundPrimitives; - return batches; - } - - function sortIndexes(a, b) { - a = Number(a); - b = Number(b); - return a - b; - } - /** * A general purpose visualizer for geometry represented by {@link Primitive} instances. * @alias GeometryVisualizer @@ -151,7 +132,6 @@ define([ this._scene = scene; this._primitives = primitives; this._groundPrimitives = groundPrimitives; - this._orderedGroundPrimitives = groundPrimitives.add(new PrimitiveCollection()); this._entityCollection = undefined; this._addedObjects = new AssociativeArray(); this._removedObjects = new AssociativeArray(); @@ -164,7 +144,8 @@ define([ this._openColorBatches = new Array(numberOfShadowModes); this._openMaterialBatches = new Array(numberOfShadowModes); - for (var i = 0; i < numberOfShadowModes; ++i) { + var i; + for (i = 0; i < numberOfShadowModes; ++i) { this._outlineBatches[i] = new StaticOutlineGeometryBatch(primitives, scene, i); this._closedColorBatches[i] = new StaticGeometryColorBatch(primitives, PerInstanceColorAppearance, undefined, true, i); @@ -173,12 +154,16 @@ define([ this._openMaterialBatches[i] = new StaticGeometryPerMaterialBatch(primitives, MaterialAppearance, undefined, false, i); } - this._groundColorBatches = {}; - this._reorderGroundPrimitives = false; + var numberOfClassificationTypes = ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES; + this._groundColorBatches = new Array(numberOfClassificationTypes); + + for (i = 0; i < numberOfClassificationTypes; ++i) { + this._groundColorBatches[i] = new StaticGroundGeometryColorBatch(groundPrimitives, i); + } this._dynamicBatch = new DynamicGeometryBatch(primitives, groundPrimitives); - this._batches = this._outlineBatches.concat(this._closedColorBatches, this._closedMaterialBatches, this._openColorBatches, this._openMaterialBatches, this._dynamicBatch); + this._batches = this._outlineBatches.concat(this._closedColorBatches, this._closedMaterialBatches, this._openColorBatches, this._openMaterialBatches, this._groundColorBatches, this._dynamicBatch); this._subscriptions = new AssociativeArray(); this._updaterSets = new AssociativeArray(); @@ -268,25 +253,6 @@ define([ isUpdated = batches[i].update(time) && isUpdated; } - var orderedGroundPrimitives = this._orderedGroundPrimitives; - var groundBatches = this._groundColorBatches; - var groundBatchIndexes = Object.keys(groundBatches); - groundBatchIndexes = groundBatchIndexes.sort(sortIndexes); - - if (this._reorderGroundPrimitives) { - for (i = 0; i < groundBatchIndexes.length; i++) { - orderedGroundPrimitives.raiseToTop(groundBatches[groundBatchIndexes[i]]._primitives); - } - this._reorderGroundPrimitives = false; - } - - var numberOfClassificationTypes = ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES; - for (i = 0; i < groundBatchIndexes.length; i++) { - for (var j = 0; j < numberOfClassificationTypes; j++) { - isUpdated = groundBatches[groundBatchIndexes[i]][j].update(time) && isUpdated; - } - } - return isUpdated; }; @@ -323,8 +289,7 @@ define([ for (var j = 0; j < updaters.length; j++) { var updater = updaters[j]; - var i; - for (i = 0; i < batchesLength; i++) { + for (var i = 0; i < batchesLength; i++) { state = batches[i].getBoundingSphere(updater, tmp); if (state === BoundingSphereState.PENDING) { return BoundingSphereState.PENDING; @@ -333,21 +298,6 @@ define([ count++; } } - - var groundBatches = this._groundColorBatches; - var groundBatchIndexes = Object.keys(groundBatches); - var numberOfClassificationTypes = ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES; - for (i = 0; i < groundBatchIndexes.length; i++) { - for (var k = 0; k < numberOfClassificationTypes; k++) { - state = groundBatches[groundBatchIndexes[i]][k].getBoundingSphere(updater, tmp); - if (state === BoundingSphereState.PENDING) { - return BoundingSphereState.PENDING; - } else if (state === BoundingSphereState.DONE) { - boundingSpheres[count] = BoundingSphere.clone(tmp, boundingSpheres[count]); - count++; - } - } - } } if (count === 0) { @@ -383,23 +333,12 @@ define([ batches[i].removeAllPrimitives(); } - var groundBatches = this._groundColorBatches; - var groundBatchIndexes = Object.keys(groundBatches); - var numberOfClassificationTypes = ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES; - for (i = 0; i < groundBatchIndexes.length; i++) { - for (var k = 0; k < numberOfClassificationTypes; k++) { - groundBatches[groundBatchIndexes[i]][k].removeAllPrimitives(); - } - } - var subscriptions = this._subscriptions.values; length = subscriptions.length; for (i = 0; i < length; i++) { subscriptions[i](); } this._subscriptions.removeAll(); - - this._groundPrimitives.remove(this._orderedGroundPrimitives); return destroyObject(this); }; @@ -410,19 +349,9 @@ define([ //We don't keep track of which batch an updater is in, so just remove it from all of them. var batches = this._batches; var length = batches.length; - var i; - for (i = 0; i < length; i++) { + for (var i = 0; i < length; i++) { batches[i].remove(updater); } - - var groundBatches = this._groundColorBatches; - var groundBatchIndexes = Object.keys(groundBatches); - var numberOfClassificationTypes = ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES; - for (i = 0; i < groundBatchIndexes.length; i++) { - for (var k = 0; k < numberOfClassificationTypes; k++) { - groundBatches[groundBatchIndexes[i]][k].remove(updater); - } - } }; /** @@ -445,17 +374,8 @@ define([ if (updater.fillEnabled) { if (updater.onTerrain) { - var zIndex = updater.zIndex; - var batchArray = this._groundColorBatches[zIndex]; - if (!defined(batchArray)) { - batchArray = createGroundColorBatch(this._orderedGroundPrimitives.add(new PrimitiveCollection())); - this._groundColorBatches[zIndex] = batchArray; - this._reorderGroundPrimitives = true; - } - var classificationType = updater.classificationTypeProperty.getValue(time); - var batch = batchArray[classificationType]; - batch.add(time, updater); + this._groundColorBatches[classificationType].add(time, updater); } else if (updater.isClosed) { if (updater.fillMaterialProperty instanceof ColorMaterialProperty) { this._closedColorBatches[shadows].add(time, updater); diff --git a/Source/DataSources/GroundGeometryUpdater.js b/Source/DataSources/GroundGeometryUpdater.js index 1dddfe9ce545..43f2a98afc14 100644 --- a/Source/DataSources/GroundGeometryUpdater.js +++ b/Source/DataSources/GroundGeometryUpdater.js @@ -4,18 +4,20 @@ define([ '../Core/defineProperties', '../Core/Iso8601', '../Core/oneTimeWarning', - './GeometryUpdater', - './Property' + './ConstantProperty', + './GeometryUpdater' ], function( defaultValue, defined, defineProperties, Iso8601, oneTimeWarning, - GeometryUpdater, - Property) { + ConstantProperty, + GeometryUpdater) { 'use strict'; + var defaultZIndex = new ConstantProperty(0); + /** * An abstract class for updating ground geometry entities. * @constructor @@ -62,12 +64,11 @@ define([ if (!defined(geometry)) { return; } - var zIndex = Property.getValueOrUndefined(geometry.zIndex, Iso8601.MINIMUM_VALUE); - if (defined(zIndex) && (this._dynamic || !Property.isConstant(geometry.zIndex) || defined(this._options.height) || defined(this._options.extrudedHeight))) { + if (defined(geometry.zIndex) && (defined(geometry.height) || defined(geometry.extrudedHeight))) { oneTimeWarning(oneTimeWarning.geometryZIndex); } - this._zIndex = defaultValue(zIndex, 0); + this._zIndex = defaultValue(geometry.zIndex, defaultZIndex); }; return GroundGeometryUpdater; diff --git a/Source/DataSources/PolygonGeometryUpdater.js b/Source/DataSources/PolygonGeometryUpdater.js index 3bb06bcae2ac..4bbc3698e03b 100644 --- a/Source/DataSources/PolygonGeometryUpdater.js +++ b/Source/DataSources/PolygonGeometryUpdater.js @@ -194,6 +194,7 @@ define([ !Property.isConstant(polygon.perPositionHeight) || // !Property.isConstant(polygon.closeTop) || // !Property.isConstant(polygon.closeBottom) || // + !Property.isConstant(polygon.zIndex) || // (this._onTerrain && !Property.isConstant(this._materialProperty)); }; diff --git a/Source/DataSources/RectangleGeometryUpdater.js b/Source/DataSources/RectangleGeometryUpdater.js index 4e1fcb6a8be0..f90e4457cb67 100644 --- a/Source/DataSources/RectangleGeometryUpdater.js +++ b/Source/DataSources/RectangleGeometryUpdater.js @@ -184,6 +184,7 @@ define([ !Property.isConstant(rectangle.stRotation) || // !Property.isConstant(rectangle.rotation) || // !Property.isConstant(rectangle.outlineWidth) || // + !Property.isConstant(rectangle.zIndex) || // (this._onTerrain && !Property.isConstant(this._materialProperty)); }; diff --git a/Source/DataSources/StaticGroundGeometryColorBatch.js b/Source/DataSources/StaticGroundGeometryColorBatch.js index 9dcfc20bfde6..0082d0eaf552 100644 --- a/Source/DataSources/StaticGroundGeometryColorBatch.js +++ b/Source/DataSources/StaticGroundGeometryColorBatch.js @@ -6,6 +6,7 @@ define([ '../Core/DistanceDisplayConditionGeometryInstanceAttribute', '../Core/ShowGeometryInstanceAttribute', '../Scene/GroundPrimitive', + '../Scene/OrderedGroundPrimitiveCollection', './BoundingSphereState', './Property' ], function( @@ -16,6 +17,7 @@ define([ DistanceDisplayConditionGeometryInstanceAttribute, ShowGeometryInstanceAttribute, GroundPrimitive, + OrderedGroundPrimitiveCollection, BoundingSphereState, Property) { 'use strict'; @@ -24,8 +26,9 @@ define([ var distanceDisplayConditionScratch = new DistanceDisplayCondition(); var defaultDistanceDisplayCondition = new DistanceDisplayCondition(); - function Batch(primitives, classificationType, color, key) { + function Batch(primitives, classificationType, color, key, zIndex) { this.primitives = primitives; + this.zIndex = zIndex; this.classificationType = classificationType; this.color = color; this.key = key; @@ -116,7 +119,7 @@ define([ geometryInstances : geometries, classificationType : this.classificationType }); - primitives.add(primitive); + primitives.add(primitive, this.zIndex); isUpdated = false; } else { if (defined(primitive)) { @@ -264,13 +267,14 @@ define([ StaticGroundGeometryColorBatch.prototype.add = function(time, updater) { var instance = updater.createFillGeometryInstance(time); var batches = this._batches; - // instance.attributes.color.value is a Uint8Array, so just read it as a Uint32 and make that the key - var batchKey = new Uint32Array(instance.attributes.color.value.buffer)[0]; + // color and zIndex are batch breakers, so we'll use that for the key + var zIndex = Property.getValueOrDefault(updater.zIndex, 0); + var batchKey = new Uint32Array(instance.attributes.color.value.buffer)[0] + ':' + zIndex; var batch; if (batches.contains(batchKey)) { batch = batches.get(batchKey); } else { - batch = new Batch(this._primitives, this._classificationType, instance.attributes.color.value, batchKey); + batch = new Batch(this._primitives, this._classificationType, instance.attributes.color.value, batchKey, zIndex); batches.set(batchKey, batch); } batch.add(updater, instance); diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index 6374117d3126..fca3458f42aa 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -213,6 +213,9 @@ define([ this._boundingSpheresKeys = []; this._boundingSpheres = []; + // Used when inserting in an OrderedPrimitiveCollection + this._zIndex = undefined; + var that = this; this._primitiveOptions = { geometryInstances : undefined, diff --git a/Source/Scene/OrderedGroundPrimitiveCollection.js b/Source/Scene/OrderedGroundPrimitiveCollection.js new file mode 100644 index 000000000000..05f898b21acd --- /dev/null +++ b/Source/Scene/OrderedGroundPrimitiveCollection.js @@ -0,0 +1,230 @@ +define([ + '../Core/defaultValue', + '../Core/defined', + '../Core/defineProperties', + '../Core/destroyObject', + '../Core/Check', + '../Core/DeveloperError', + './PrimitiveCollection' +], function( + defaultValue, + defined, + defineProperties, + destroyObject, + Check, + DeveloperError, + PrimitiveCollection) { + 'use strict'; + + /** + * A primitive collection for helping maintain the order or ground primitives based on a z-index + * + * @private + */ + function OrderedGroundPrimitiveCollection() { + this._length = 0; + this._collections = {}; + this._collectionsArray = []; + + this.show = true; + } + + defineProperties(OrderedGroundPrimitiveCollection.prototype, { + /** + * Gets the number of primitives in the collection. + * + * @memberof OrderedGroundPrimitiveCollection.prototype + * + * @type {Number} + * @readonly + */ + length : { + get : function() { + return this._length; + } + } + }); + + /** + * Adds a primitive to the collection. + * + * @param {GroundPrimitive} primitive The primitive to add. + * @param {Number} [zIndex = 0] The index of the primitive + * @returns {GroundPrimitive} The primitive added to the collection. + */ + OrderedGroundPrimitiveCollection.prototype.add = function(primitive, zIndex) { + //>>includeStart('debug', pragmas.debug); + Check.defined('primitive', primitive); + //>>includeEnd('debug'); + + zIndex = defaultValue(zIndex, 0); + var collection = this._collections[zIndex]; + if (!defined(collection)) { + collection = new PrimitiveCollection({ destroyPrimitives: false }); + collection._zIndex = zIndex; + this._collections[zIndex] = collection; + var array = this._collectionsArray; + var i = 0; + while (i < array.length && array[i]._zIndex < zIndex) { + i++; + } + array.splice(i, 0, collection); + } + + collection.add(primitive); + this._length++; + primitive._zIndex = zIndex; + + return primitive; + }; + + /** + * Adjusts the z-index + * @param {GroundPrimitive} primitive + * @param {Number} zIndex + */ + OrderedGroundPrimitiveCollection.prototype.set = function(primitive, zIndex) { + //>>includeStart('debug', pragmas.debug); + Check.defined('primitive', primitive); + Check.defined('zIndex', zIndex); + //>>includeEnd('debug'); + + if (zIndex === primitive._zIndex) { + return primitive; + } + + this.remove(primitive, true); + this.add(primitive, zIndex); + }; + + /** + * Removes a primitive from the collection. + * + * @param {Object} primitive The primitive to remove. + * @param {Boolean} [doNotDestroy = false] + * @returns {Boolean} true if the primitive was removed; false if the primitive is undefined or was not found in the collection. + */ + OrderedGroundPrimitiveCollection.prototype.remove = function(primitive, doNotDestroy) { + //>>includeStart('debug', pragmas.debug); + Check.defined('primitive', primitive); + //>>includeEnd('debug'); + if (this.contains(primitive)) { + var index = primitive._zIndex; + var collection = this._collections[index]; + var result; + if (doNotDestroy) { + result = collection.remove(primitive); + } else { + result = collection.removeAndDestroy(primitive); + } + + if (result) { + this._length--; + } + + if (collection.length === 0) { + this._collectionsArray.splice(this._collectionsArray.indexOf(collection), 1); + this._collections[index] = undefined; + collection.destroy(); + } + + return result; + } + + return false; + }; + + /** + * Removes all primitives in the collection. + * + * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called. + * + * @see OrderedGroundPrimitiveCollection#destroyPrimitives + */ + OrderedGroundPrimitiveCollection.prototype.removeAll = function() { + var collections = this._collectionsArray; + for (var i = 0; i < collections.length; i++) { + var collection = collections[i]; + collection.destroyPrimitives = true; + collection.destroy(); + } + + this._collections = {}; + this._collectionsArray = []; + }; + + /** + * Determines if this collection contains a primitive. + * + * @param {Object} primitive The primitive to check for. + * @returns {Boolean} true if the primitive is in the collection; false if the primitive is undefined or was not found in the collection. + */ + OrderedGroundPrimitiveCollection.prototype.contains = function(primitive) { + //>>includeStart('debug', pragmas.debug); + Check.defined('primitive', primitive); + //>>includeEnd('debug'); + var collection = this._collections[primitive._zIndex]; + return defined(collection) && collection.contains(primitive); + }; + + OrderedGroundPrimitiveCollection.prototype.get = function() { + //>>includeStart('debug', pragmas.debug); + throw new DeveloperError('get is not supported.'); + //>>includeEnd('debug'); + }; + + /** + * @private + */ + OrderedGroundPrimitiveCollection.prototype.update = function(frameState) { + if (!this.show) { + return; + } + + var collections = this._collectionsArray; + for (var i = 0 ; i < collections.length; i++) { + collections[i].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 OrderedGroundPrimitiveCollection#destroy + */ + OrderedGroundPrimitiveCollection.prototype.isDestroyed = function() { + return false; + }; + + /** + * Destroys the WebGL resources held by each primitive in this collection. Explicitly destroying this + * collection allows for deterministic release of WebGL resources, instead of relying on the garbage + * collector to destroy this collection. + *

+ * Since destroying a collection destroys all the contained primitives, only destroy a collection + * when you are sure no other code is still using any of the contained primitives. + *

+ * Once this collection 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. + * + * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called. + * + * + * @example + * primitives = primitives && primitives.destroy(); + * + * @see OrderedGroundPrimitiveCollection#isDestroyed + */ + OrderedGroundPrimitiveCollection.prototype.destroy = function() { + this.removeAll(); + return destroyObject(this); + }; + + return OrderedGroundPrimitiveCollection; +}); diff --git a/Source/Scene/PrimitiveCollection.js b/Source/Scene/PrimitiveCollection.js index ee4ab3276e53..3141f95079dd 100644 --- a/Source/Scene/PrimitiveCollection.js +++ b/Source/Scene/PrimitiveCollection.js @@ -42,6 +42,9 @@ define([ this._primitives = []; this._guid = createGuid(); + // Used by the OrderedGroundPrimitiveCollection + this._zIndex = undefined; + /** * Determines if primitives in this collection will be shown. * From 423762ab21b44c6c892bf0b08df9b3a5ace4582e Mon Sep 17 00:00:00 2001 From: hpinkos Date: Wed, 9 May 2018 16:44:53 -0400 Subject: [PATCH 06/11] specs --- Source/Core/oneTimeWarning.js | 2 +- Source/DataSources/GeometryVisualizer.js | 118 +++++----- Source/DataSources/KmlDataSource.js | 6 +- .../StaticGroundGeometryColorBatch.js | 2 - .../Scene/OrderedGroundPrimitiveCollection.js | 18 +- Specs/DataSources/GeometryVisualizerSpec.js | 114 +--------- .../StaticGroundGeometryColorBatchSpec.js | 67 +++--- .../OrderedGroundPrimitiveCollectionSpec.js | 215 ++++++++++++++++++ ...reateGeometryUpdaterGroundGeometrySpecs.js | 4 +- 9 files changed, 320 insertions(+), 226 deletions(-) create mode 100644 Specs/Scene/OrderedGroundPrimitiveCollectionSpec.js diff --git a/Source/Core/oneTimeWarning.js b/Source/Core/oneTimeWarning.js index 23634642c4ca..4056713ab345 100644 --- a/Source/Core/oneTimeWarning.js +++ b/Source/Core/oneTimeWarning.js @@ -47,7 +47,7 @@ define([ oneTimeWarning.geometryOutlines = 'Entity geometry outlines are unsupported on terrain. Outlines will be disabled. To enable outlines, disable geometry terrain clamping by explicitly setting height to 0.'; - oneTimeWarning.geometryZIndex = 'Entity geometry with zIndex are unsupported when the entity is dynamic, or height or extrudedHeight are defined. zIndex will be ignored'; + oneTimeWarning.geometryZIndex = 'Entity geometry with zIndex are unsupported when height or extrudedHeight are defined. zIndex will be ignored'; return oneTimeWarning; }); diff --git a/Source/DataSources/GeometryVisualizer.js b/Source/DataSources/GeometryVisualizer.js index aaa1816aa723..e80e34bf3206 100644 --- a/Source/DataSources/GeometryVisualizer.js +++ b/Source/DataSources/GeometryVisualizer.js @@ -1,63 +1,63 @@ define([ - '../Core/AssociativeArray', - '../Core/BoundingSphere', - '../Core/Check', - '../Core/defaultValue', - '../Core/defined', - '../Core/destroyObject', - '../Core/Event', - '../Core/EventHelper', - '../Scene/ClassificationType', - '../Scene/MaterialAppearance', - '../Scene/PerInstanceColorAppearance', - '../Scene/ShadowMode', - './BoundingSphereState', - './BoxGeometryUpdater', - './ColorMaterialProperty', - './CorridorGeometryUpdater', - './CylinderGeometryUpdater', - './DynamicGeometryBatch', - './EllipseGeometryUpdater', - './EllipsoidGeometryUpdater', - './PlaneGeometryUpdater', - './PolygonGeometryUpdater', - './PolylineVolumeGeometryUpdater', - './RectangleGeometryUpdater', - './StaticGeometryColorBatch', - './StaticGeometryPerMaterialBatch', - './StaticGroundGeometryColorBatch', - './StaticOutlineGeometryBatch', - './WallGeometryUpdater' -], function( - AssociativeArray, - BoundingSphere, - Check, - defaultValue, - defined, - destroyObject, - Event, - EventHelper, - ClassificationType, - MaterialAppearance, - PerInstanceColorAppearance, - ShadowMode, - BoundingSphereState, - BoxGeometryUpdater, - ColorMaterialProperty, - CorridorGeometryUpdater, - CylinderGeometryUpdater, - DynamicGeometryBatch, - EllipseGeometryUpdater, - EllipsoidGeometryUpdater, - PlaneGeometryUpdater, - PolygonGeometryUpdater, - PolylineVolumeGeometryUpdater, - RectangleGeometryUpdater, - StaticGeometryColorBatch, - StaticGeometryPerMaterialBatch, - StaticGroundGeometryColorBatch, - StaticOutlineGeometryBatch, - WallGeometryUpdater) { + '../Core/AssociativeArray', + '../Core/BoundingSphere', + '../Core/Check', + '../Core/defaultValue', + '../Core/defined', + '../Core/destroyObject', + '../Core/Event', + '../Core/EventHelper', + '../Scene/ClassificationType', + '../Scene/MaterialAppearance', + '../Scene/PerInstanceColorAppearance', + '../Scene/ShadowMode', + './BoundingSphereState', + './BoxGeometryUpdater', + './ColorMaterialProperty', + './CorridorGeometryUpdater', + './CylinderGeometryUpdater', + './DynamicGeometryBatch', + './EllipseGeometryUpdater', + './EllipsoidGeometryUpdater', + './PlaneGeometryUpdater', + './PolygonGeometryUpdater', + './PolylineVolumeGeometryUpdater', + './RectangleGeometryUpdater', + './StaticGeometryColorBatch', + './StaticGeometryPerMaterialBatch', + './StaticGroundGeometryColorBatch', + './StaticOutlineGeometryBatch', + './WallGeometryUpdater' + ], function( + AssociativeArray, + BoundingSphere, + Check, + defaultValue, + defined, + destroyObject, + Event, + EventHelper, + ClassificationType, + MaterialAppearance, + PerInstanceColorAppearance, + ShadowMode, + BoundingSphereState, + BoxGeometryUpdater, + ColorMaterialProperty, + CorridorGeometryUpdater, + CylinderGeometryUpdater, + DynamicGeometryBatch, + EllipseGeometryUpdater, + EllipsoidGeometryUpdater, + PlaneGeometryUpdater, + PolygonGeometryUpdater, + PolylineVolumeGeometryUpdater, + RectangleGeometryUpdater, + StaticGeometryColorBatch, + StaticGeometryPerMaterialBatch, + StaticGroundGeometryColorBatch, + StaticOutlineGeometryBatch, + WallGeometryUpdater) { 'use strict'; var emptyArray = []; diff --git a/Source/DataSources/KmlDataSource.js b/Source/DataSources/KmlDataSource.js index b00e489b8861..f51d5d25a904 100644 --- a/Source/DataSources/KmlDataSource.js +++ b/Source/DataSources/KmlDataSource.js @@ -1236,10 +1236,6 @@ define([ var coordinates = readCoordinates(coordinatesNode, ellipsoid); var polyline = styleEntity.polyline; if (canExtrude && extrude) { - if (defined(zIndex)) { - oneTimeWarning('kml-gx:drawOrder', 'KML - gx:drawOrder is not supported in LineStrings'); - } - var wall = new WallGraphics(); entity.wall = wall; wall.positions = coordinates; @@ -1272,7 +1268,7 @@ define([ corridor.zIndex = zIndex; } else { if (defined(zIndex)) { - oneTimeWarning('kml-gx:drawOrder', 'KML - gx:drawOrder is not supported in LineStrings'); + oneTimeWarning('kml-gx:drawOrder', 'KML - gx:drawOrder is not supported in LineStrings when clampToGround is false'); } polyline = defined(polyline) ? polyline.clone() : new PolylineGraphics(); diff --git a/Source/DataSources/StaticGroundGeometryColorBatch.js b/Source/DataSources/StaticGroundGeometryColorBatch.js index 0082d0eaf552..8a3cec51b51f 100644 --- a/Source/DataSources/StaticGroundGeometryColorBatch.js +++ b/Source/DataSources/StaticGroundGeometryColorBatch.js @@ -6,7 +6,6 @@ define([ '../Core/DistanceDisplayConditionGeometryInstanceAttribute', '../Core/ShowGeometryInstanceAttribute', '../Scene/GroundPrimitive', - '../Scene/OrderedGroundPrimitiveCollection', './BoundingSphereState', './Property' ], function( @@ -17,7 +16,6 @@ define([ DistanceDisplayConditionGeometryInstanceAttribute, ShowGeometryInstanceAttribute, GroundPrimitive, - OrderedGroundPrimitiveCollection, BoundingSphereState, Property) { 'use strict'; diff --git a/Source/Scene/OrderedGroundPrimitiveCollection.js b/Source/Scene/OrderedGroundPrimitiveCollection.js index 05f898b21acd..c740db242a57 100644 --- a/Source/Scene/OrderedGroundPrimitiveCollection.js +++ b/Source/Scene/OrderedGroundPrimitiveCollection.js @@ -95,6 +95,8 @@ define([ this.remove(primitive, true); this.add(primitive, zIndex); + + return primitive; }; /** @@ -105,9 +107,6 @@ define([ * @returns {Boolean} true if the primitive was removed; false if the primitive is undefined or was not found in the collection. */ OrderedGroundPrimitiveCollection.prototype.remove = function(primitive, doNotDestroy) { - //>>includeStart('debug', pragmas.debug); - Check.defined('primitive', primitive); - //>>includeEnd('debug'); if (this.contains(primitive)) { var index = primitive._zIndex; var collection = this._collections[index]; @@ -151,6 +150,7 @@ define([ this._collections = {}; this._collectionsArray = []; + this._length = 0; }; /** @@ -160,19 +160,13 @@ define([ * @returns {Boolean} true if the primitive is in the collection; false if the primitive is undefined or was not found in the collection. */ OrderedGroundPrimitiveCollection.prototype.contains = function(primitive) { - //>>includeStart('debug', pragmas.debug); - Check.defined('primitive', primitive); - //>>includeEnd('debug'); + if (!defined(primitive)) { + return false; + } var collection = this._collections[primitive._zIndex]; return defined(collection) && collection.contains(primitive); }; - OrderedGroundPrimitiveCollection.prototype.get = function() { - //>>includeStart('debug', pragmas.debug); - throw new DeveloperError('get is not supported.'); - //>>includeEnd('debug'); - }; - /** * @private */ diff --git a/Specs/DataSources/GeometryVisualizerSpec.js b/Specs/DataSources/GeometryVisualizerSpec.js index 36d2b302a2e3..689ea3df8aa8 100644 --- a/Specs/DataSources/GeometryVisualizerSpec.js +++ b/Specs/DataSources/GeometryVisualizerSpec.js @@ -374,7 +374,7 @@ defineSuite([ scene.render(time); return isUpdated; }).then(function() { - var primitive = scene.groundPrimitives.get(0).get(0).get(0); + var primitive = scene.groundPrimitives.get(0); expect(primitive.classificationType).toBe(type); objects.remove(entity); @@ -554,121 +554,9 @@ defineSuite([ expect(visualizer.update(time)).toBe(true); scene.render(time); expect(scene.primitives.length).toBe(0); - expect(scene.groundPrimitives.length).toBe(1); visualizer.destroy(); }); - it('Creates and removes static color geometry on terrain', function() { - scene.groundPrimitives.removeAll(); - var objects = new EntityCollection(); - var visualizer = new GeometryVisualizer(scene, objects, scene.primitives, scene.groundPrimitives); - - var ellipse = new EllipseGraphics(); - ellipse.semiMajorAxis = new ConstantProperty(2); - ellipse.semiMinorAxis = new ConstantProperty(1); - ellipse.material = new ColorMaterialProperty(); - - var entity = new Entity(); - entity.position = new ConstantPositionProperty(new Cartesian3(1234, 5678, 9101112)); - entity.ellipse = ellipse; - objects.add(entity); - - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { - var primitive = scene.groundPrimitives.get(0).get(0).get(0); - var attributes = primitive.getGeometryInstanceAttributes(entity); - expect(attributes).toBeDefined(); - expect(attributes.show).toEqual(ShowGeometryInstanceAttribute.toValue(true)); - expect(attributes.color).toEqual(ColorGeometryInstanceAttribute.toValue(Color.WHITE)); - - objects.remove(entity); - - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.groundPrimitives.get(0).get(0).length === 0; - }).then(function(){ - visualizer.destroy(); - expect(scene.groundPrimitives.length).toBe(0); - }); - }); - }); - - it('Users zIndex to order static color geometry on terrain', function() { - scene.groundPrimitives.removeAll(); - var objects = new EntityCollection(); - var visualizer = new GeometryVisualizer(scene, objects, scene.primitives, scene.groundPrimitives); - - var ellipse = new EllipseGraphics(); - ellipse.semiMajorAxis = new ConstantProperty(2); - ellipse.semiMinorAxis = new ConstantProperty(1); - ellipse.material = new ColorMaterialProperty(Color.GREEN); - ellipse.zIndex = 0; - var entity1 = new Entity(); - entity1.position = new ConstantPositionProperty(new Cartesian3(1234, 5678, 9101112)); - entity1.ellipse = ellipse; - objects.add(entity1); - - var entity2 = new Entity(); - ellipse = new EllipseGraphics(); - ellipse.semiMajorAxis = new ConstantProperty(2); - ellipse.semiMinorAxis = new ConstantProperty(1); - ellipse.material = new ColorMaterialProperty(Color.RED); - ellipse.zIndex = 3; - entity2.position = new ConstantPositionProperty(new Cartesian3(1234, 5678, 9101112)); - entity2.ellipse = ellipse; - objects.add(entity2); - - var entity3 = new Entity(); - ellipse = new EllipseGraphics(); - ellipse.semiMajorAxis = new ConstantProperty(2); - ellipse.semiMinorAxis = new ConstantProperty(1); - ellipse.material = new ColorMaterialProperty(Color.BLUE); - ellipse.zIndex = 2; - entity3.position = new ConstantPositionProperty(new Cartesian3(1234, 5678, 9101112)); - entity3.ellipse = ellipse; - objects.add(entity3); - - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { - var layer = scene.groundPrimitives.get(0); - expect(layer.length).toBe(3); - var primitive = layer.get(0).get(0); - var attributes = primitive.getGeometryInstanceAttributes(entity1); - expect(attributes).toBeDefined(); - expect(attributes.show).toEqual(ShowGeometryInstanceAttribute.toValue(true)); - expect(attributes.color).toEqual(ColorGeometryInstanceAttribute.toValue(Color.GREEN)); - - primitive = layer.get(1).get(0); - attributes = primitive.getGeometryInstanceAttributes(entity3); - expect(attributes).toBeDefined(); - expect(attributes.show).toEqual(ShowGeometryInstanceAttribute.toValue(true)); - expect(attributes.color).toEqual(ColorGeometryInstanceAttribute.toValue(Color.BLUE)); - - primitive = layer.get(2).get(0); - attributes = primitive.getGeometryInstanceAttributes(entity2); - expect(attributes).toBeDefined(); - expect(attributes.show).toEqual(ShowGeometryInstanceAttribute.toValue(true)); - expect(attributes.color).toEqual(ColorGeometryInstanceAttribute.toValue(Color.RED)); - - objects.remove(entity1); - objects.remove(entity2); - objects.remove(entity3); - - visualizer.destroy(); - expect(scene.groundPrimitives.length).toBe(0); - }); - }); - it('Constructor throws without scene', function() { var objects = new EntityCollection(); expect(function() { diff --git a/Specs/DataSources/StaticGroundGeometryColorBatchSpec.js b/Specs/DataSources/StaticGroundGeometryColorBatchSpec.js index 32d95f9f05f6..5ca62376cb9e 100644 --- a/Specs/DataSources/StaticGroundGeometryColorBatchSpec.js +++ b/Specs/DataSources/StaticGroundGeometryColorBatchSpec.js @@ -1,5 +1,6 @@ defineSuite([ 'DataSources/StaticGroundGeometryColorBatch', + 'Core/defaultValue', 'Core/Cartesian3', 'Core/Color', 'Core/DistanceDisplayCondition', @@ -18,6 +19,7 @@ defineSuite([ 'Specs/pollToPromise' ], function( StaticGroundGeometryColorBatch, + defaultValue, Cartesian3, Color, DistanceDisplayCondition, @@ -53,10 +55,11 @@ defineSuite([ GroundPrimitive._terrainHeights = undefined; }); - function computeKey(color) { + function computeKey(color, zIndex) { var ui8 = new Uint8Array(color); var ui32 = new Uint32Array(ui8.buffer); - return ui32[0]; + zIndex = defaultValue(zIndex, 0); + return ui32[0] + ':' + zIndex; } it('updates color attribute after rebuilding primitive', function() { @@ -204,36 +207,36 @@ defineSuite([ batch.add(time, updater1); return pollToPromise(renderScene) - .then(function() { - expect(scene.groundPrimitives.length).toEqual(1); - var primitive = scene.groundPrimitives.get(0); - expect(primitive.show).toBeTruthy(); - }) - .then(function() { - batch.add(time, updater2); - }) - .then(function() { - return pollToPromise(function() { - renderScene(); - return scene.groundPrimitives.length === 2; - }); - }) - .then(function() { - var showCount = 0; - expect(scene.groundPrimitives.length).toEqual(2); - showCount += !!scene.groundPrimitives.get(0).show; - showCount += !!scene.groundPrimitives.get(1).show; - expect(showCount).toEqual(1); - }) - .then(function() { - return pollToPromise(renderScene); - }) - .then(function() { - expect(scene.groundPrimitives.length).toEqual(1); - var primitive = scene.groundPrimitives.get(0); - expect(primitive.show).toBeTruthy(); + .then(function() { + expect(scene.groundPrimitives.length).toEqual(1); + var primitive = scene.groundPrimitives.get(0); + expect(primitive.show).toBeTruthy(); + }) + .then(function() { + batch.add(time, updater2); + }) + .then(function() { + return pollToPromise(function() { + renderScene(); + return scene.groundPrimitives.length === 2; + }); + }) + .then(function() { + var showCount = 0; + expect(scene.groundPrimitives.length).toEqual(2); + showCount += !!scene.groundPrimitives.get(0).show; + showCount += !!scene.groundPrimitives.get(1).show; + expect(showCount).toEqual(1); + }) + .then(function() { + return pollToPromise(renderScene); + }) + .then(function() { + expect(scene.groundPrimitives.length).toEqual(1); + var primitive = scene.groundPrimitives.get(0); + expect(primitive.show).toBeTruthy(); - batch.removeAllPrimitives(); - }); + batch.removeAllPrimitives(); + }); }); }); diff --git a/Specs/Scene/OrderedGroundPrimitiveCollectionSpec.js b/Specs/Scene/OrderedGroundPrimitiveCollectionSpec.js new file mode 100644 index 000000000000..74170933ef73 --- /dev/null +++ b/Specs/Scene/OrderedGroundPrimitiveCollectionSpec.js @@ -0,0 +1,215 @@ +defineSuite([ + 'Scene/OrderedGroundPrimitiveCollection', + 'Core/destroyObject' +], function( + OrderedGroundPrimitiveCollection, + destroyObject) { + 'use strict'; + + var updateCallOrder; + + beforeEach(function() { + updateCallOrder = []; + }); + + function MockPrimitive() {} + + MockPrimitive.prototype.update = function() { + updateCallOrder.push(this); + }; + + MockPrimitive.prototype.isDestroyed = function() { return false; }; + MockPrimitive.prototype.destroy = function() { + return destroyObject(this); + }; + + it('constructs', function() { + var collection = new OrderedGroundPrimitiveCollection(); + expect(collection.length).toBe(0); + expect(collection.show).toBe(true); + }); + + it('add throws without primitive', function() { + expect(function() { + var collection = new OrderedGroundPrimitiveCollection(); + collection.add(); + }).toThrowDeveloperError(); + }); + + it('adds a primitive', function() { + var collection = new OrderedGroundPrimitiveCollection(); + collection.add(new MockPrimitive()); + expect(collection.length).toBe(1); + }); + + it('add handles multiple zIndexes', function() { + var collection = new OrderedGroundPrimitiveCollection(); + var p1 = collection.add(new MockPrimitive()); + var p2 = collection.add(new MockPrimitive(), 0); + var p3 = collection.add(new MockPrimitive(), 2); + var p4 = collection.add(new MockPrimitive(), 1); + expect(collection.length).toBe(4); + + var array = collection._collectionsArray; + expect(array.length).toBe(3); + expect(array[0].length).toBe(2); + expect(array[0].get(0)).toBe(p1); + expect(array[0].get(1)).toBe(p2); + expect(array[1].length).toBe(1); + expect(array[1].get(0)).toBe(p4); + expect(array[2].length).toBe(1); + expect(array[2].get(0)).toBe(p3); + }); + + it('set throws without primitive', function() { + expect(function() { + var collection = new OrderedGroundPrimitiveCollection(); + collection.set(undefined, 3); + }).toThrowDeveloperError(); + }); + + it('set throws without zIndex', function() { + expect(function() { + var collection = new OrderedGroundPrimitiveCollection(); + collection.set(new MockPrimitive(), undefined); + }).toThrowDeveloperError(); + }); + + it('set adds primitive if it is not in the collection', function() { + var collection = new OrderedGroundPrimitiveCollection(); + collection.set(new MockPrimitive(), 3); + expect(collection.length).toBe(1); + }); + + it('set changes a primitives index', function() { + var collection = new OrderedGroundPrimitiveCollection(); + var p1 = collection.add(new MockPrimitive(), 0); + var p2 = collection.add(new MockPrimitive(), 0); + var p3 = collection.add(new MockPrimitive(), 2); + var p4 = collection.add(new MockPrimitive(), 1); + expect(collection.length).toBe(4); + + collection.set(p4, 2); + + expect(collection.length).toBe(4); + + var array = collection._collectionsArray; + expect(array.length).toBe(2); + expect(array[0].length).toBe(2); + expect(array[0].get(0)).toBe(p1); + expect(array[0].get(1)).toBe(p2); + expect(array[1].length).toBe(2); + expect(array[1].get(0)).toBe(p3); + expect(array[1].get(1)).toBe(p4); + }); + + it('set throws without primitive', function() { + expect(function() { + var collection = new OrderedGroundPrimitiveCollection(); + collection.set(undefined, 3); + }).toThrowDeveloperError(); + }); + + it('removes a primitive', function() { + var collection = new OrderedGroundPrimitiveCollection(); + var p = collection.add(new MockPrimitive()); + var result = collection.remove(p); + expect(result).toBe(true); + expect(collection.length).toBe(0); + expect(collection._collectionsArray.length).toBe(0); + expect(p.isDestroyed()).toBe(true); + }); + + it('removes handles multiple zIndexes', function() { + var collection = new OrderedGroundPrimitiveCollection(); + var p1 = collection.add(new MockPrimitive(), 0); + var p2 = collection.add(new MockPrimitive(), 2); + var p3 = collection.add(new MockPrimitive(), 2); + var p4 = collection.add(new MockPrimitive(), 1); + expect(collection.length).toBe(4); + + var array = collection._collectionsArray; + expect(array.length).toBe(3); + collection.remove(p3); + expect(array.length).toBe(3); + collection.remove(p2); + expect(array.length).toBe(2); + expect(array[0].get(0)).toBe(p1); + expect(array[1].get(0)).toBe(p4); + }); + + it('removes null', function() { + var collection = new OrderedGroundPrimitiveCollection(); + expect(collection.remove()).toEqual(false); + }); + + it('removeAll removes and destroys all primitives', function() { + var collection = new OrderedGroundPrimitiveCollection(); + var p1 = collection.add(new MockPrimitive(), 0); + var p2 = collection.add(new MockPrimitive(), 0); + var p3 = collection.add(new MockPrimitive(), 2); + var p4 = collection.add(new MockPrimitive(), 1); + expect(collection.length).toBe(4); + collection.removeAll(); + expect(collection.length).toBe(0); + expect(p1.isDestroyed()).toBe(true); + expect(p2.isDestroyed()).toBe(true); + expect(p3.isDestroyed()).toBe(true); + expect(p4.isDestroyed()).toBe(true); + }); + + it('contains primitive', function() { + var collection = new OrderedGroundPrimitiveCollection(); + var p1 = collection.add(new MockPrimitive()); + + expect(collection.contains(p1)).toBe(true); + }); + + it('does not contain primitive', function() { + var collection = new OrderedGroundPrimitiveCollection(); + var p1 = new MockPrimitive(); + + expect(collection.contains(p1)).toBe(false); + }); + + it('does not contain undefined', function() { + var collection = new OrderedGroundPrimitiveCollection(); + expect(collection.contains()).toEqual(false); + }); + + it('update is called in the correct order', function() { + var collection = new OrderedGroundPrimitiveCollection(); + var p1 = collection.add(new MockPrimitive(), 0); + var p2 = collection.add(new MockPrimitive(), 3); + var p3 = collection.add(new MockPrimitive(), 1); + var p4 = collection.add(new MockPrimitive(), 2); + collection.update(); + expect(updateCallOrder).toEqual([p1, p3, p4, p2]); + + updateCallOrder = []; + collection.set(p1, 4); + collection.update(); + expect(updateCallOrder).toEqual([p3, p4, p2, p1]); + + updateCallOrder = []; + collection.set(p2, 0); + collection.update(); + expect(updateCallOrder).toEqual([p2, p3, p4, p1]); + }); + + it('update is not called when show is false', function() { + var collection = new OrderedGroundPrimitiveCollection(); + collection.add(new MockPrimitive(), 0); + collection.add(new MockPrimitive(), 3); + collection.show = false; + collection.update(); + expect(updateCallOrder).toEqual([]); + }); + + it('destroys', function() { + var collection = new OrderedGroundPrimitiveCollection(); + expect(collection.isDestroyed()).toBe(false); + collection.destroy(); + expect(collection.isDestroyed()).toBe(true); + }); +}); diff --git a/Specs/createGeometryUpdaterGroundGeometrySpecs.js b/Specs/createGeometryUpdaterGroundGeometrySpecs.js index 1cfb53ab4c86..16a31a677d09 100644 --- a/Specs/createGeometryUpdaterGroundGeometrySpecs.js +++ b/Specs/createGeometryUpdaterGroundGeometrySpecs.js @@ -25,7 +25,7 @@ define([ var entity = createEntity(); var updater = new Updater(entity, getScene()); - expect(updater.zIndex).toBe(0); + expect(updater.zIndex.getValue()).toBe(0); }); it('uses zIndex value', function() { @@ -33,7 +33,7 @@ define([ entity[geometryPropertyName].zIndex = 22; var updater = new Updater(entity, getScene()); - expect(updater.zIndex).toBe(22); + expect(updater.zIndex.getValue()).toBe(22); }); it('A time-varying color causes ground geometry to be dynamic', function() { From e04ab018d8fbdb63af72ebb50f2cbc1826b0f1c4 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Thu, 10 May 2018 11:31:41 -0400 Subject: [PATCH 07/11] fix specs --- Specs/DataSources/KmlDataSourceSpec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Specs/DataSources/KmlDataSourceSpec.js b/Specs/DataSources/KmlDataSourceSpec.js index 45b3df9f8050..f0cca59b327a 100644 --- a/Specs/DataSources/KmlDataSourceSpec.js +++ b/Specs/DataSources/KmlDataSourceSpec.js @@ -4100,7 +4100,7 @@ defineSuite([ return KmlDataSource.load(parser.parseFromString(kml, "text/xml"), options).then(function(dataSource) { expect(dataSource.entities.values.length).toEqual(1); expect(console.warn.calls.count()).toEqual(1); - expect(console.warn).toHaveBeenCalledWith('KML - gx:drawOrder is not supported in LineStrings'); + expect(console.warn).toHaveBeenCalledWith('KML - gx:drawOrder is not supported in LineStrings when clampToGround is false'); }); }); From 3f408e4556c026ca17e643e7c296c2532447b938 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Thu, 10 May 2018 12:37:33 -0400 Subject: [PATCH 08/11] type check, negative numbers --- .../Scene/OrderedGroundPrimitiveCollection.js | 5 +- .../OrderedGroundPrimitiveCollectionSpec.js | 54 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/Source/Scene/OrderedGroundPrimitiveCollection.js b/Source/Scene/OrderedGroundPrimitiveCollection.js index c740db242a57..445916cd4fd4 100644 --- a/Source/Scene/OrderedGroundPrimitiveCollection.js +++ b/Source/Scene/OrderedGroundPrimitiveCollection.js @@ -55,6 +55,9 @@ define([ OrderedGroundPrimitiveCollection.prototype.add = function(primitive, zIndex) { //>>includeStart('debug', pragmas.debug); Check.defined('primitive', primitive); + if (defined(zIndex)) { + Check.typeOf.number('zIndex', zIndex); + } //>>includeEnd('debug'); zIndex = defaultValue(zIndex, 0); @@ -86,7 +89,7 @@ define([ OrderedGroundPrimitiveCollection.prototype.set = function(primitive, zIndex) { //>>includeStart('debug', pragmas.debug); Check.defined('primitive', primitive); - Check.defined('zIndex', zIndex); + Check.typeOf.number('zIndex', zIndex); //>>includeEnd('debug'); if (zIndex === primitive._zIndex) { diff --git a/Specs/Scene/OrderedGroundPrimitiveCollectionSpec.js b/Specs/Scene/OrderedGroundPrimitiveCollectionSpec.js index 74170933ef73..036d93cb3d68 100644 --- a/Specs/Scene/OrderedGroundPrimitiveCollectionSpec.js +++ b/Specs/Scene/OrderedGroundPrimitiveCollectionSpec.js @@ -36,6 +36,13 @@ defineSuite([ }).toThrowDeveloperError(); }); + it('add throws if zIndex is not a number', function() { + expect(function() { + var collection = new OrderedGroundPrimitiveCollection(); + collection.add(new MockPrimitive(), '3'); + }).toThrowDeveloperError(); + }); + it('adds a primitive', function() { var collection = new OrderedGroundPrimitiveCollection(); collection.add(new MockPrimitive()); @@ -61,6 +68,25 @@ defineSuite([ expect(array[2].get(0)).toBe(p3); }); + it('add works with negative zIndexes', function() { + var collection = new OrderedGroundPrimitiveCollection(); + var p1 = collection.add(new MockPrimitive(), 0); + var p2 = collection.add(new MockPrimitive(), -3); + var p3 = collection.add(new MockPrimitive(), -1); + var p4 = collection.add(new MockPrimitive(), -3); + expect(collection.length).toBe(4); + + var array = collection._collectionsArray; + expect(array.length).toBe(3); + expect(array[0].length).toBe(2); + expect(array[0].get(0)).toBe(p2); + expect(array[0].get(1)).toBe(p4); + expect(array[1].length).toBe(1); + expect(array[1].get(0)).toBe(p3); + expect(array[2].length).toBe(1); + expect(array[2].get(0)).toBe(p1); + }); + it('set throws without primitive', function() { expect(function() { var collection = new OrderedGroundPrimitiveCollection(); @@ -75,6 +101,13 @@ defineSuite([ }).toThrowDeveloperError(); }); + it('set throws if zIndex is not a number', function() { + expect(function() { + var collection = new OrderedGroundPrimitiveCollection(); + collection.set(new MockPrimitive(), '3'); + }).toThrowDeveloperError(); + }); + it('set adds primitive if it is not in the collection', function() { var collection = new OrderedGroundPrimitiveCollection(); collection.set(new MockPrimitive(), 3); @@ -103,6 +136,22 @@ defineSuite([ expect(array[1].get(1)).toBe(p4); }); + it('set works with negative indexes', function() { + var collection = new OrderedGroundPrimitiveCollection(); + var p1 = collection.add(new MockPrimitive(), 0); + var p2 = collection.add(new MockPrimitive(), 0); + expect(collection.length).toBe(2); + + collection.set(p2, -1); + + var array = collection._collectionsArray; + expect(array.length).toBe(2); + expect(array[0].length).toBe(1); + expect(array[0].get(0)).toBe(p2); + expect(array[1].length).toBe(1); + expect(array[1].get(0)).toBe(p1); + }); + it('set throws without primitive', function() { expect(function() { var collection = new OrderedGroundPrimitiveCollection(); @@ -195,6 +244,11 @@ defineSuite([ collection.set(p2, 0); collection.update(); expect(updateCallOrder).toEqual([p2, p3, p4, p1]); + + updateCallOrder = []; + collection.set(p4, -1); + collection.update(); + expect(updateCallOrder).toEqual([p4, p2, p3, p1]); }); it('update is not called when show is false', function() { From ba34dc83da51f97a825250e4db5dfa40fc44696a Mon Sep 17 00:00:00 2001 From: hpinkos Date: Mon, 21 May 2018 16:07:05 -0400 Subject: [PATCH 09/11] fix merge --- .../gallery/Z-Indexing Geometry.html | 24 ++++++++++++------- Source/DataSources/GeometryVisualizer.js | 8 +++---- .../StaticGroundGeometryPerMaterialBatch.js | 13 ++++++---- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/Apps/Sandcastle/gallery/Z-Indexing Geometry.html b/Apps/Sandcastle/gallery/Z-Indexing Geometry.html index 2a4c1b2aaca7..1ec0d4e8e578 100644 --- a/Apps/Sandcastle/gallery/Z-Indexing Geometry.html +++ b/Apps/Sandcastle/gallery/Z-Indexing Geometry.html @@ -5,7 +5,7 @@ - + Cesium Demo @@ -35,15 +35,17 @@ rectangle : { coordinates : Cesium.Rectangle.fromDegrees(-110.0, 20.0, -100.5, 30.0), material : Cesium.Color.RED, - zIndex: 1 + zIndex: 1, + classificationType : Cesium.ClassificationType.TERRAIN } }); viewer.entities.add({ rectangle : { coordinates : Cesium.Rectangle.fromDegrees(-112.0, 25.0, -102.5, 35.0), - material : Cesium.Color.GREEN, - zIndex: 2 + material : '../images/Cesium_Logo_Color.jpg', + zIndex: 2, + classificationType : Cesium.ClassificationType.TERRAIN } }); @@ -51,15 +53,17 @@ rectangle : { coordinates : Cesium.Rectangle.fromDegrees(-110.0, 31.0, -100.5, 41.0), material : Cesium.Color.BLUE, - zIndex: 3 + zIndex: 3, + classificationType : Cesium.ClassificationType.TERRAIN } }); viewer.entities.add({ rectangle : { coordinates : Cesium.Rectangle.fromDegrees(-99.5, 20.0, -90.0, 30.0), - material : Cesium.Color.RED, - zIndex: 3 + material : '../images/Cesium_Logo_Color.jpg', + zIndex: 3, + classificationType : Cesium.ClassificationType.TERRAIN } }); @@ -67,7 +71,8 @@ rectangle : { coordinates : Cesium.Rectangle.fromDegrees(-97.5, 25.0, -88.0, 35.0), material : Cesium.Color.GREEN, - zIndex: 2 + zIndex: 2, + classificationType : Cesium.ClassificationType.TERRAIN } }); @@ -75,7 +80,8 @@ rectangle : { coordinates : Cesium.Rectangle.fromDegrees(-99.5, 31.0, -90.0, 41.0), material : Cesium.Color.BLUE, - zIndex: 1 + zIndex: 1, + classificationType : Cesium.ClassificationType.TERRAIN } }); diff --git a/Source/DataSources/GeometryVisualizer.js b/Source/DataSources/GeometryVisualizer.js index a561c6f12e0d..9ea93859248f 100644 --- a/Source/DataSources/GeometryVisualizer.js +++ b/Source/DataSources/GeometryVisualizer.js @@ -163,7 +163,7 @@ define([ var numberOfClassificationTypes = ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES; var groundColorBatches = new Array(numberOfClassificationTypes); - var groundmaterialBatches = []; + var groundMaterialBatches = []; if (supportsMaterialsforEntitiesOnTerrain) { // Culling, phong shading only supported for ClassificationType.TERRAIN at the moment because // tileset depth information not yet available. @@ -173,8 +173,8 @@ define([ groundColorBatches[i] = new StaticGroundGeometryColorBatch(groundPrimitives, i); } } - groundmaterialBatches[0] = new StaticGroundGeometryPerMaterialBatch(groundPrimitives, MaterialAppearance); - this._groundTerrainMaterialBatch = groundmaterialBatches[0]; + groundMaterialBatches[0] = new StaticGroundGeometryPerMaterialBatch(groundPrimitives, MaterialAppearance); + this._groundTerrainMaterialBatch = groundMaterialBatches[0]; } else { for (i = 0; i < numberOfClassificationTypes; ++i) { groundColorBatches[i] = new StaticGroundGeometryColorBatch(groundPrimitives, i); @@ -185,7 +185,7 @@ define([ this._dynamicBatch = new DynamicGeometryBatch(primitives, groundPrimitives); - this._batches = this._outlineBatches.concat(this._closedColorBatches, this._closedMaterialBatches, this._openColorBatches, this._openMaterialBatches, this._groundColorBatches, groundmaterialBatches, this._dynamicBatch); + this._batches = this._outlineBatches.concat(this._closedColorBatches, this._closedMaterialBatches, this._openColorBatches, this._openMaterialBatches, this._groundColorBatches, groundMaterialBatches, this._dynamicBatch); this._subscriptions = new AssociativeArray(); this._updaterSets = new AssociativeArray(); diff --git a/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js b/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js index 01eee22b114a..a8f4773f6cc5 100644 --- a/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js +++ b/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js @@ -34,7 +34,7 @@ define([ var defaultDistanceDisplayCondition = new DistanceDisplayCondition(); // Encapsulates a Primitive and all the entities that it represents. - function Batch(primitives, appearanceType, materialProperty, usingSphericalTextureCoordinates) { + function Batch(primitives, appearanceType, materialProperty, usingSphericalTextureCoordinates, zIndex) { this.primitives = primitives; // scene level primitive collection this.appearanceType = appearanceType; this.materialProperty = materialProperty; @@ -51,6 +51,7 @@ define([ this.subscriptions = new AssociativeArray(); this.showsUpdated = new AssociativeArray(); this.usingSphericalTextureCoordinates = usingSphericalTextureCoordinates; + this.zIndex = zIndex; this.rectangleCollisionCheck = new RectangleCollisionChecker(); } @@ -159,7 +160,7 @@ define([ classificationType : ClassificationType.TERRAIN }); - primitives.add(primitive); + primitives.add(primitive, this.zIndex); isUpdated = false; } else { if (defined(primitive)) { @@ -290,6 +291,7 @@ define([ var length = items.length; var geometryInstance = updater.createFillGeometryInstance(time); var usingSphericalTextureCoordinates = ShadowVolumeAppearance.shouldUseSphericalCoordinates(geometryInstance.geometry.rectangle); + var zIndex = Property.getValueOrDefault(updater.zIndex, 0); // Check if the Entity represented by the updater can be placed in an existing batch. Requirements: // * compatible material (same material or same color) // * same type of texture coordinates (spherical vs. planar) @@ -297,14 +299,15 @@ define([ for (var i = 0; i < length; ++i) { var item = items[i]; if (item.isMaterial(updater) && - !item.overlapping(geometryInstance.geometry.rectangle) && - item.usingSphericalTextureCoordinates === usingSphericalTextureCoordinates) { + item.usingSphericalTextureCoordinates === usingSphericalTextureCoordinates && + item.zIndex === zIndex && + !item.overlapping(geometryInstance.geometry.rectangle)) { item.add(time, updater, geometryInstance); return; } } // If a compatible batch wasn't found, create a new batch. - var batch = new Batch(this._primitives, this._appearanceType, updater.fillMaterialProperty, usingSphericalTextureCoordinates); + var batch = new Batch(this._primitives, this._appearanceType, updater.fillMaterialProperty, usingSphericalTextureCoordinates, zIndex); batch.add(time, updater, geometryInstance); items.push(batch); }; From e656a8da514377ea3541db4b4145761d7ceb2764 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Tue, 22 May 2018 12:12:06 -0400 Subject: [PATCH 10/11] fix classification type --- .../gallery/Z-Indexing Geometry.html | 18 ++++++------------ .../gallery/Z-Indexing Geometry.jpg | Bin 15127 -> 18128 bytes CHANGES.md | 2 ++ Source/DataSources/CorridorGraphics.js | 2 +- Source/DataSources/EllipseGraphics.js | 2 +- Source/DataSources/GeometryUpdater.js | 2 +- Source/DataSources/PolygonGraphics.js | 2 +- Source/DataSources/RectangleGraphics.js | 2 +- Source/Scene/GroundPrimitive.js | 6 +++--- Specs/Scene/GroundPrimitiveSpec.js | 6 ++++-- 10 files changed, 20 insertions(+), 22 deletions(-) diff --git a/Apps/Sandcastle/gallery/Z-Indexing Geometry.html b/Apps/Sandcastle/gallery/Z-Indexing Geometry.html index 1ec0d4e8e578..a2c43724c3f5 100644 --- a/Apps/Sandcastle/gallery/Z-Indexing Geometry.html +++ b/Apps/Sandcastle/gallery/Z-Indexing Geometry.html @@ -35,8 +35,7 @@ rectangle : { coordinates : Cesium.Rectangle.fromDegrees(-110.0, 20.0, -100.5, 30.0), material : Cesium.Color.RED, - zIndex: 1, - classificationType : Cesium.ClassificationType.TERRAIN + zIndex: 1 } }); @@ -44,8 +43,7 @@ rectangle : { coordinates : Cesium.Rectangle.fromDegrees(-112.0, 25.0, -102.5, 35.0), material : '../images/Cesium_Logo_Color.jpg', - zIndex: 2, - classificationType : Cesium.ClassificationType.TERRAIN + zIndex: 2 } }); @@ -53,8 +51,7 @@ rectangle : { coordinates : Cesium.Rectangle.fromDegrees(-110.0, 31.0, -100.5, 41.0), material : Cesium.Color.BLUE, - zIndex: 3, - classificationType : Cesium.ClassificationType.TERRAIN + zIndex: 3 } }); @@ -62,8 +59,7 @@ rectangle : { coordinates : Cesium.Rectangle.fromDegrees(-99.5, 20.0, -90.0, 30.0), material : '../images/Cesium_Logo_Color.jpg', - zIndex: 3, - classificationType : Cesium.ClassificationType.TERRAIN + zIndex: 3 } }); @@ -71,8 +67,7 @@ rectangle : { coordinates : Cesium.Rectangle.fromDegrees(-97.5, 25.0, -88.0, 35.0), material : Cesium.Color.GREEN, - zIndex: 2, - classificationType : Cesium.ClassificationType.TERRAIN + zIndex: 2 } }); @@ -80,8 +75,7 @@ rectangle : { coordinates : Cesium.Rectangle.fromDegrees(-99.5, 31.0, -90.0, 41.0), material : Cesium.Color.BLUE, - zIndex: 1, - classificationType : Cesium.ClassificationType.TERRAIN + zIndex: 1 } }); diff --git a/Apps/Sandcastle/gallery/Z-Indexing Geometry.jpg b/Apps/Sandcastle/gallery/Z-Indexing Geometry.jpg index 3da960f0ad21237c10e7ad68b3109046a158b912..caae2ada52e648a428a3f0d2e8ce331172300d2b 100644 GIT binary patch delta 17582 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 CZiWE> delta 14558 zcmV<4I3dT-jRBW-693r$-~bRxMoC5h0RaI3U;to|5={wU000010001Bk!Yp?m$MH6 z%K?8QiE?VxVxfb9Ruko~qKV+tB#Jy5y$XPXnyColr%bEykDHV3YeaI-T@6hSPLo&F zA-9G(B$7u8sDPGYP5=OMNzO1U?LQ3sA-|JK@UMVu?;y9ERgk^ozQgU|zxpF2m}Bz=SMO=0ox ziTp*YYjb8zYS8(DJj1du>9RDFl?ViCo>&0vk}#*HJ}-&!sm?ff{heR0Pq}_)c2|by zmET{>uivpgsp1_w;iivcWuskN-|7}tOxDms&GvbMM9(9zBPyw|9jeUCati_TFExMh zQ^vO*EQZCVw6dR8iWW(3Vz_A9bTO9U9dq*GoVOS(qZ~6H&rR@tm*AfeTwYBzt?b%Q znQ1YSCW;t~NLR~N%eme2kD0oioDkd7#J>Y|O*i6vdV#sIx4L5k!yC$chmJn6e4wt? zaEwC`aezS`ep)hH%VXN9hm`bdOZ|VxFQoUz)c%`1XN%Ikg;>z*Cgd|3K@wuc^}CZMu2T1#hcJowN_B0rawJV({sU=RVz z@HBjT;=K<{@OXye-%@$C2-0h%hC^=A`NIK9g2)+5u{lx)0d|0(d9TAS4C#OR2ad(W zdWD+m6J1DBTj!QTa~TPrFB#b@Dv+fH*2Can3VXM5-zu7fdTx3IzZvx{8scj`8f(Rx zHW6J}y|9XSq(QkNU}FJaa9&a<`N$&xWYq0-4-@M$O?0+%NT|6JPQjdic~!n%HihSo z*~r1YtXW)I{7=+1?OHu0r~7{*+p3GBHrbs624_GHRSE#j)NVN-?ld)f6_V=IdC*!- zB#8O*2Qjn!z_v*|432|2&uS%WSqh|O%kMwXY#L;7#WdF~<_Kc_=$iBby*CrQ3<1#f zr12kyZ!c}_7{w)|mrl zhfow9fU)`a0)B1=0IZwe5=*FBM{Oi`2(hGb$cz{@rUJdGmMj0?qagkwPl!CLf6gaBFMpf)blo$ z%%9yPC-9tQMm}A_1h9X3V3ATaWt9t)ow&wVB!7FU`V7?{3Ch;~B88uSmbb;+qeTgx$H2tUj)gg zX);=A7m>qpb!_n2y~N5}&E2=nROAqYG8F`q<(l+w8_VZ3H%WgRE!;%;ybxYax-piO6{+G*nRRf^6w z5Za?k>KkhuZDN0ql~J$=S+Rh`bziZ)mZk8+_JQ$7gS?x&i)%P$d6MQa3hs_XSZ;Q( zByL#-0Q<`z>HszL7sOkpp4(8fZ9n}DE#~v#*(KMTz9W<S=rw8zVz|j0V_+f9UCcSwcjeVv?smFgDxsuk!HhJ@yw;kay4$PJy z^4rT56uc|@Ku4;0gGsc}JSF4Xwbd@sX4Pl5@+}Rn=2x9t=G+KnAxKfzB=kJinemIp zpAmdO-WT|Pr`vd6!a76|>0jFSwnWVUU%nw$Zg^HzTyDoKV`lk%gTp$F*Mod3_C%9Z z)CQlnIWB+hC3$Wqly#Aqo^sp1QO7}m0)fGZii2{k?@9E&%cbnM`I>uFv|AmQg1=|k zz9M`GzP`|JJVC5#*19$3u-A6lga#NVh4JluT{fsXzGii*Mw}d^^z=H<*~|8P(tJnp-^RWH)Glu|FAC_FEb?iV(iqO5 z(aV43hgATaj0SCkCurvY8efYavVVa575iEEZ$WJ)Njy8OTii_ARM!q>h^NZC$O^y` zHvn>R+}F$2Um5k!1o)8a);hJ`pQw48(&8t?!M%v*JoTYdxZK?R;KM`Dbg8JiJ zO#c9;Je#E?j2?dq`kL5UsxnZOn_rEsbBliuT9nU zm{wD_ux!>^x`XRiwAp;QLv%T-i@ATzQk|90us>uC5?>1VdfZ>Ze9>JYzeKeFF+!Ld zn2-W(UCojPF`OFuBfx$UxAE7AEC!n%p9(`1vnp?mENuvA&i0X?_evSxmmo83!FB-G z8~ZuQK;$5w@x-&5wcj5m4FUM4MF;kTKwtG2sG?ZYwU-D(|6|$z2 zsx%S4u#-U^^%lzuEyJ-YPtIHKG3O+bU5Pl|P5347cgCNzCyXt8FAk$;40=j5mlqSm z<=ZW^XUlSB3Q2c4O`!eY4pe{UtLi==ic`cATiPPL>l84w=^>6o9J`4l_q$MFI;LfZ z?yBuI>OZk&r{XUPTWc2(UFiP+WtPfq78u=Qnk$8nB5rY9 zOWxS@m4XSDqUqX@&CGNV~Tz#O*siYz@SM!zVvM_(6a1BjRLl zr8T|OHt8+Hi>Mt$vKeHCG@Prp8b^(f9ECziA#i>p_{nh%-^K40OK)o(jl7!0+eK|0 zo?=^}naZNK@dX$F_X2;vqrQ&b3E+H4%(1vkZF$gz2u4Z4CwD1Y&zq%_^ZSnv9hgr6 z1vsTHX7@hy)PHC{hI+obbXm1;3tU*qJ=8Z+&3;X|!WWL>GGt{rD4_rdP>=v50{(rf ze$gHY()2j&=hn2Fgk7bX9!cfLa0+e*2a}xSlk1W3MHT&Rhx&g7@WPsSjLQ)y_KK$$ z_qfaQJW8BTR!jJCzs&n9Tm7wk6&{;uZ)f5W`>^>D+g&Vvpb_PQGD+!?jxYu>t$*>e z!@dAbK5cVY`z@}a7@ptDwVb`c+O4}Prx@I$oCEa-9}m~Je$@BE=ixWPi2nf5*`d+0 zUNCoIp|&_<>JESJ#GhLEJ}LSh@OD|mxh7GE#bRA7Z0p9ObEV9^oe9;8gH%#Y$~KoY zWpwnj)Y_jAVkbtV+KuCDX!^9fo}=P_+jqg=X^-skYPS)U^4+1b+`wb+e(~3w`gQy& zq#w7>g=3F%X}%(BgP=Yq#06FC2;R^SU*bl^)T6e^4Yfp)x@-MX0Ge;tV zB$7E4Cp~{h%PfPA4tWN?6UR@Y{{RByULRxgJc9<|i^IkTT6yb z!4+h=9&0SCmSqDZ<+)xuf$Dnq$=B_q)~pt0X-j`M%Mc6?mgfqjjOQF=k;xu|H4lJp zE;aLGZE1ZZUSj!DNpX=Qqi)?JFj1B2I^dNDE1LfRE*COBvR?G<6{kY4i5BBT)Dwl$_>wDo ze;R-4kgV-><;<#GfKo_R5@R5q960UYtw*NY1AC^tYS(ZxsbqHAue9$g=r;u;Cp`@t z9JM6eq`c1KN7S^K*GJMFRNQJa7?ynCM=2*(xmoFx_Q zr!Ka);*K22w-~42^gPz)aHr-wn2x8tWZgFB{{ZXNyXV~XLUsZD>+U3DLN*#WG~R!6 zPAB!DhElWiI)?9}q};#VkMlHByC*^>q@x_ul}V&f=*|eMmYly8O$Rk<2|Te?9n7k1 zefRqYd_uVKKf&bDWSZfu^t+ZZ31={bawL$VjD=(<^D_?F&U)j~z7P0ZXxCmT@cqVZsxF>3SJ~_Lo}O3DD8)ym*Y*8$J3kTI$$1=$YYcYmul9SGwxn>%GD3eQ<{oYu zHh7F`$e^5KhTX)AFC2JJNAVO^J{IvcoVwg9_JUnbCW6tJsuyTZK~c6v^RHGR8M$W>Ry+Y`|_ifvI)x8Cq!icBv+< z;tR{YB6|-bQl8#PFx*QRxnX}0NZ1E5BXnRyd?_bymnlAnxap_m{dtu>75pdFz8>fz zdpqB-O|3z0#U40ubsToGZB&<&zcR{L{MZp9jH@$O<%>4slit5q^)DaT`1ke$)%A@h zP}Q4K@UDj`vzi!1yuqQce9STTqYdT)!x`s1b^M^O^q=Spm(CbG>l}aDwC6$zbzF+9 zoB8`iZ$^Ay7fLJG!abY&?fyYU6j%Bdd}vp;{?J-vS3dy$AKyfmS+%u>-QGYJHZohQ ze4{`d@w0Ko)TiC4V*ce$2N*^9xkvqiNHi30$>4Vz;=gNEb3B%Ukz^TqsJ@Z4X* zbt&%gRU`792}S-5o}PaODbTHc%kw-MinpccH`?Pm*xB9QG^NEBU?!e!H9Trw?ULam_LGXgDj&+Es)(Q&+p@lCrbDy$=$mDvdwl zO)plFgI)gs?6)0@}%06Ugt0QP?;JYzMT{{RXn#b5Lb z{{YFDfB3rTyaVt<#GVxKR*$VDnp}4pUF0{b6q7dK(YSC95RTsU_{WJJICx=-;jDI9 zS3kl_>ojW8N}eK|-RDkG`wo1&=-Rc+Y3JE}8j-0g(b2A{{zueM(%W{S-rB^I`y!^jD&Opb? zGI7(K@pp>9;W5W|Pe{ObppMt^@%sm`G6+P;tHzslx+gG6Ib zT~}7P3vn_PSi%7JP60e1_2iOp26@JEHGDtf1lBAhnrMZ(sR*80{Om_1K;wbXclmkA z>3}>pFNrltt|q!@Z1zN^R(;N^fw@%l#&;e)M{`r!eWO>uX*9w1D6HdA$INA72|G_c zae_}cJo|t3a--9Y(cXAJ?EWXw?=GFO3?Ql#jm)G1PSe3Bo&f&tcp|<-{k#^%HR$D8 zB%4x_C_~93?lOP^oD2=Bp#UDaVhaPf{S*5@d|J}}6nr$cn%2ro<~K`g9A(xs8x(Ib zT$LvWVQ!i2_jx}C_}=zQ^z$W==8>f`Gr7w<9Fl)exv#9@oCLYvFJ-dx@An)S`q6fx zx6!kYx|kz1QO4%nYD=^G-%4odUtzl{F|r$sy-6Z@WtD-*>+Mmo!wQn}&BOj4wrE}o)o>3RCq0(L?(ZG zXO+>LYQlu4$_k^DZN+&`hvO4j-FPbNSkrDTY&<=xX%oJUJ-n+LYUrTEkFe#IIW60A zMh-z>8wYkjG{q^xi>qrZJ3mByUMmpcg{vsF%^0`oWpwO(bMaSFT`S?vu`7aAt(qP^ zWcdf`!oFv(qP{zS$tu-9?T`MBO8I}*ztXSS!+@m@0nBl$$MLBz!?FC~ z!0<~4Id$f@+?V-<6j5L3QTBmfMEr5OlVAOdd=+>V7T(6@&d30m!+oCTb~4$)*^__< z=5K2G+P&w*7I#|D>@B3s%@aXkf9G(8SxA;hKqtQvf1F@{J^0}YbaS2-%qoAoDCQLD z{OZ%Fm*W(^XRVe+%AI(x0jlK)8dMUi#6nxxu{TkZ|=2!J+1P$L-6h}R?MHG3Mit#i%*sU zGAnyc@LsPZa(OUEBFO^J9Fl)b3c3{ej(>*)a0mo_cH;)OqC~RLE$`&r6lIwtGd|ea z0`fs&xAXZAOzf<+k39$)cF&KCDqZxnTEwBB#U*uKr-ifGc z`n+0t+<78qP|mpwF~ICL^v8bZfKEDSye|Y=E!0;G#(g=5l_W9!=G}jixje2xBd8>O zYAXxd9WDswwXu>}WFYS|g-6DAle3MZj+;gXd9H=LHL7^>c=aeX2qe<(u$M5!D#kF9^N{{Usb75H83B>vLS^)Sj zsmY&IpY~OJW~=vegZ}`)9hy3gZ$!267MUfT>?=LA*xrPZoDfGNo}gDZ{{RXn!l(XW zfB7>v{{R`fT*(W!qZuF19eGm-xQg%jal`UU?0W#QQE^c=ZnXqxZ zr%ZZw;MMInK+^m>;U)0-cy6@m@)pWgERF+j$wGeyeqp;g2fqfVPrF?l+A)j3FZ?b*|~zM-xY$qlfPA%%8&NDX->IIsGrf-W%}ko#R^R zdQX4ai0u@x;(md72#cRlL5@UzYnn>=gQtQiSJ0dwT{G;E? z2kL9+DJ#G~Y~3z9ePcquUE<>637~#>+Z!t{>mz=Z`VWS9k7u4jAI}*txpRN*r};PI zj|XMEALCwY!?`>aEIeE}Ar)xFRH06{D%I&1Ca-;M=5pF+jkRqr!}nTUuAy}XpLl=U zrGXrUV~ihhkZ^I0zzpXCy|eZX_{XhizY{FH9@lZn;r(f)-*0foY;GZtuG5jheW!0i za6r#B^6rzZNo{bVMrMt;=bTq*;a?NpcsIm0nx>yGlX+(+nHy(=*n{e%5(w@I9qalZ z8G)yWp*mcvU(cgFx^*W)tY>|{E~tO{TlVSrAa49KY2qszTcx_vqDVCW;0@8Sk++YS z?p17KXut&Ikhvcz{{UoO&!-!x?Ji`tQ-+yiB^33+Ju~fJZTMf}{68B!3mwB>%F;}Y z1?`DV!sM8pS_ftr!!+u500+tkBZcr!gIY(A;n8&sKf<$V@Y=(yeV+1J(O!Q`a)bsi zklSK8RxB4kyZKMw&zHjUs_DxKQ9f#am-Ta_Jd`OViGx;`cV+sYFzXinR;xJZH*V>U zy#AF=WApW|O!&3n&11%v+Ly#3rd!zQI+gK_?cf`J&UOqq7yzRX*kRR`v(G2YWEgyo zhnn_f7ah*bJylW{Pi-Bwv+94oLbB$W^{FYR=4wpdE$k-aML!f$D&Pk-BB$k1gYwj> z{Cv2eiC>_3H7bMC@##&@eKYKMsRHc+sU&A6(9(iN#yH=t0QA>0d(r#l9f$%$_l8ZxL$} zXkTtcwubP;l0y>~97(y;Xe2HeoDNCA%MX>}%&FqC>dy}!-ty^f8|c&Wwa+I$jxN4i zR|kjH&MhT$wSH}+zHWcVx=~rWhPgJI@o!Y{w3e#LrpC-K(oDrWFO|7e5Do{LIX%G` ztxc8u(~ryR;Hvu^OnGHw?R4~eY}!6&Ao?))pPprFImz;w*P!JnsX}z5`J9m`xnY8_+g3B{NS9UR#`DDg&bGxSm z*R{j%_w^$7aFYBF_1inka~!w9&K04V(UlBV3VC!~C2nX=l2o1S+P?4SuVW61D6a(m z)(R-1fExWP#{Yi+Y|SzmJP)N`FmFEI`^ZC{0=#U^`o^`_e$kf~RzC>!E2|re%UjE5 zg`tw#cZI<+q8?O?f~b0mcOvB^EF^?wbxW~L^r zb9hzdROHpIt9Dmcy3whAmOsWHrw0brqvGr{xm8J2!_j||icak(QkzZbYw|w&TjkD! zll-w=HifH4sYJ1s3o87ryX9X@=cQ!ox@IQ|zaoI!*q#6#D_7ya!+mq&Cc3(AhifI} z%!B3%I3MDD0LeVy8vX6m_I~uMEwX2D)BSxNR?IJ5|6$2Oj>tMQt8@ET)2LqsE)i1$6 zhx)F(*IFK>DYUo9S+u=NHu1OtNG~eM-v@@l+;M-AfmmU9g9U}fdu~SC@^)&^O|I{K z4<|6ns$#Hmprxbhb)(YOSMIefd~f(Kr|BOPb!{TgQMl9mJEobnKMrd!+%3eGk;}1# zlP1`MEP0Vh7+;k_@T51&UN87>9n{*kp`u?!sOWlZ@W7W6BHFn#D>^Tf#4$f4fwqQF zRP%q0r2RMXo8j+@?5DSfz|u*p>DLh|0eJD7=wD~dS&GLQK*uUoLFf+P2|qgcgTWfd zg>|Qw#2OBzXQ#tBTd3lT$xWfQl}8}QlY#?sGCzx&)_H~l5eWTJ{F~R)tXM<8^O`+UAGhy*F9A(sh3eT_;&GuAg}&yDh!xh=DJZ)GI+ybepSvgI&y0l$6vEY zi##nfcUqNK{!RI;}K;f5VXah>??Ncs*Mik35x{iw-)2lKzuezimh`!jKC<|{df z;5Jv#=NTg$)ty_$O{ZDM7MBD%9-hU5SlTItRk5BF9)oemT%P3D?0z3-HEb2NjVGT90_>;X6fIL>tc z0BNhc%O4%;8cpKHw-$34iH(Z}91?TWpU(_I^d56#X4jLds{5M#j+~`llwDM{vumew z_?r(x5sx!HLs6aRPqiMQLt>w4bZdTggd(4Yokup{Z&25XT@>9KL*OByOjwo!Q2HMi_P?xp{75vbfr@`HZcCxjS>7{{a1Jjcn%e z4eK*}%aecy%AZXC08&kK)2%o-@;7+xtI)5h(d28DMlXF9r_g_vAGfU9CW&$OO+HJl zYE%~L8Gy2kVtFWAH+;?YgIDK2<7mGeQYZkUQ_qH&{adKJ7TVem*KyMcUpd=$Hkr?wSdV5WUtKp{uO^-?q85&tt>uWMvSFWD_7V2 zyB!?Yw0jWjU+*{PMK+4++q~(-)Q#^@KWutJuq*ANk)yK%fS0ow7KD567=adZCf`QoO8 zWqnCC3~hhvDn)g`=j9z}(1~2w@OO_jZ-=^^x0*HI*zRPA!qRzZE>y52VSyb~bJvRL z7xtp@&>LG^`Ln?mP+13$}w;6X!|Ue#2zWi zF#iBj%Cjs*3RiEEoobMc-tU$&O7E+-r?El%XZU}NYIerz&q!NUaAjCyb!Q#MOExp= z2OjnGf5R^qXrC7}_M1i2Bbr5oPb@C#vs$iHHsmKQfKC}s8L+($;qaBFS`q!z`qj-3 z#9Ehvb*p_tO1P5N>fOYVy7g21uycYAK?H-4Yv=L23zXG|?x@BscKuJcr}TvJ8Z&SE zUblbFOYqZAk@^X5;M>VGYkfguj_%HAeAbrQb#Ek-fUY?z*~rIjt&`UqJ^|J)JS(or zAClT!S4YT8i8kCiH_A6MsuHSL=OZC_=QwKlN8z{a`KtJBKF_FW_Uy7@WSZ7ShEA+Y z?IfXZnU5QJ;~-|fi11hKF{S)NwbRz#eJ6ifYl%z|fYGhA^MimyCWOORniQ_n+{9HmsKH5;)|v zSr#p-K5XsJD$Rq}<~>epdre@lv~WN>y6qQ6hsK)Srm<}=1zkC}QXVhD4d4?QvM{|G2eluR%7wmuH zo9%Vw@dDcE#NT@J|TQd=RO%PEa#Fr8r@WuKz?klMl<+V8>_m%nIki2aM}RKBL_J? zpnx&lXYuwa$_@%p+3e3gQ>i(%P^+ox41ajcSae+T*PrwBtgDII;r{U}oPkr{U3uG6 z94|S~B=i3O)~4H7Np~{Fi@34rQgy~ED(ro&jM|s(XK&fQ^5ekzhNq}l!)~|m{gLLsfrzlScPS;zNs!W9F2boES9W@` zmIK{9Kk%nZ)I0+Pr}lll#)WjzTFCB9&2c5Nt1M2zLpvZ+>~I$xC@6N17a5;n=*y9N z*6sa#j+%H{(@K9y*)!l@_(S9Mlm7Y?SLoN7;D7FGzxT{v{6!V!{{XD({(V2c{sGhd zn^XRN{s+%L7JfeXE8@@WrJ?v&L(rDjQLtM>e|*rYC8&lbS+KxmjPe-U9gJiSrnw&k z{>+z}rkNe|jbowdw-`2(>O}ds2ub8ZyyMe8wPWDFf^C0c)I2w)-a@llL1!n3uOlOi zmRD$?jlI5I-}cq3^ylE$?1Av-;%~t359`|Qiyg;{uPoubY172;#EwbaRKj^&CPvQ1 zK<{3iYK>`gsywleG>?Qlb^9f0J`wl@sOc8=_cz}XCe)+5noF3?x0f^<_`l)%Sw%g?taC5fSVwact|Wo+$Yt%5oF0cBxUc9#Tm7DV2k|$?M^*8a zlzN7vb!!}uT-^AIJSyXABHtg1?yKDX0xW>X*!joY@X8g-Qb=U^ki@uPq7vC2mBM8_K9EEgX8wC zuWP;+ywo(kO4YRg0JgVF$Q;G^CJ_^V0B2bC2NgP+#)=F+3SrmVb(v(0OXk{u7L(Lx2U&>#yUC)hF{J%rT z)}oYdIL>{;POL9_-3 z1^(}9?Ja-co`16$wY834+QV9V$)-;+m*D=mvBsPSMHnp14nRB(I#KNxTm8(hWh8&@ zt@oqi8#A{7zU?|+-(&0Ey@U3i{hhog@Q1{e=RB^YW0*hLUYMjve23i>l0wVSp~fq4 zco$lCWnCXqW{d*BTE187#UuCwUI%}j7gPX^!~GHZdi0^jAsI;MJQe#(`0v0GG&Xwm z#pSCgMz_BI07{6cJp##)xf~L>IPYGGVgCRH5AjZ)plTMs*xG%(myVK_vbvfWoTy+o zqcd*C>T&q)xJ~nX3|bRyih(K_=;&-IP@K2Nfd4%SxA3MjyWS9 zK6u;x99mpF5!(#p1Pa_^j(Io( zB-gV18U3-|`g==16JHWzxbvgd5P5}LJF{^P7)UuEI;e0-C(P(RU7Nw$qPs^XmwXvX zQmt;>AATuqybY~8u(i|mK)`=xyto|TeKAh9Ux%wp*-9$iEu&tBT#ZYb4X5{`^k7*- z;yp&+Tv+t|L2gStxAs@zj;ILW5rsLZ+H?|Yw)a+$#=5j;?FLyS$##tH z1%LzYk{5ylWbh9s;5%I##l|?=Ju_0dP1sZRS2;ZKoOAT8%`?P)IMIK;MALjlZe_$r z$w^eUINEX71GX#YD)7304Ntv)!8#>~o$tt>%=@dx+RTroM=kM=@WXiJHnK^XL}|J? z7+{7{d0v?E`yM>%_%gwDcoa(@z>Rlq87wkLK7e=QJYbHVLGWYZX1}2$+TLh7t@fXF z<~y(199%^0jL46GSm%EnHb*D!lbZGYGG7zjcy{XcZ9dQY3hbMWK6qesxBwHiWmY>u zRc)k(&3QQdp0*xWZ8-FO{{Z0m6Dr=-b4y0LA2)nb*5tnNPN_Z3!x`qC^6k_C z$K(J59)JqqZs%F$Zcf!FY1@qc71(@6@D8>iOXGGTit2;Tmg*tlG{jQivu{|Wtj8|IV6E!p;4($G$QY!OY;7-JlLx?-sce% zd!Hvf*V6w0vDd-f4_5Hi_lPx(-)N5MZEXw0-d(h-vQ=%%lF}Ri6CZRrA%<~@;qTb) zUlh$}{hz2$A~b)>mkTbREG+`=A>8f*fCg~b2M6W`z24_WZwj9c_o zXVdl1wyWI3xZM~Og)TrC9Pxz(%U};q<5SXf-wt?tP}F~}nTqK4^2D}~$|U<)m61|6 zU>h5x%93)qJOv6^lZTKEU?`xLkq>_+uP&JEt2o@C=$nlINA>489=O0 zi5?__QL&3pwTkv+hUE-V`Ar+kI8u9!!(zU0M(xBCkaJ%cp;Btren+iQD5l!G>HU9S ziEsWAOV5A$4zK}(!?Q@X=_!-RR&7LX zIKqGBi0PUrqJvadEEbo)-tH_u0-YFpI(N3ei@)k?PyYY}bN#ioKY;olf^I$p>K5?n zxA!;q62sz;4YNq{&e8%L>LC5uBm@zRs(a&$AMimR+dpZ~!A)~^(~Nk#!??}|{X}|a zKcy5_^2JTN=xZE2QnBuS9sPknZ?6gbHPU}PHEHk?!fRb35RprBsCZgSfK=gsd;O!h z{oyP z00j!x*2nE118ie!DLm9@bsq~OD-wj9{{U$7gS?NT`kWL|?Vn-$HQe(bjQ;@eM_=2A z<9CT|bv;|)uApu$?IN}<2Z=m42J8S^A$1%aGe`mIKwRMG7`_bu0D>F-+MWmTUYo61 z{1w%W_K$fL^{AJ{J{*!GBurg5snmaP%eiC7?hAWlqO0o?T7RGUk@a~009OA1BiuYm z`xSq|KsAj~XNTY}lNh%~iW0Y;7Kx=yoxWgQN0Wq$J#m-EY{RF1#J})RMK(6KKLT{| zrrMa|*%qVWec}<7Wd!Oye6!s3{OF>m+dki)`H$GH@9_TsB5D5sW6$^~W#oUiO((#e zEn50GqnpdV@TkB|zjyv7JRW4{z7y2qte>%8{1h^6dG!zYQMPc;bW~1Z)ch=TK1K)jjs_Gj z9W#+yQ2xZX|MKp%wgXD0K&}8xDDAq+8q7qFnyEX7=9-I0D^q~0Kq{# zU*IdR4_sTmhxs0AzwknT+WJH) zehTY={J~I5ujT$nNATPBAN{|rbvv0aJ`CtOZ|)Qa zn*RX9vI#KAe6SMvzuF@p50qq#n(4Iv0N6A3;JVY5AK{;etnYs>F1KDuE#8FCtWn1g zloM^yZ0`F&>C{D>4a5{ybG)7JVwE(yjPbYZGy8bmE!Cty4E!T|70ih&lG|Qrv7@jA z@xJ9-0ggExK9%S8pYTW@+Uru+hN-H2H`gP+n_Rlpu0F%!KM$mFdA4f?_!QmoDLD)q z3KlfSIiiY)#z`*Unf@Q-DN#+{=aT;b#6G{Z*ZmT8{{X_HM*jfhx+tQq^6&Y7kb5sT I_true, the primitive does not keep a reference to the input geometryInstances to save memory. * @param {Boolean} [options.allowPicking=true] When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved. * @param {Boolean} [options.asynchronous=true] Determines if the primitive will be created asynchronously or block until ready. If false initializeTerrainHeights() must be called first. - * @param {ClassificationType} [options.classificationType=ClassificationType.BOTH] Determines whether terrain, 3D Tiles or both will be classified. + * @param {ClassificationType} [options.classificationType=ClassificationType.TERRAIN] Determines whether terrain, 3D Tiles or both will be classified. * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if this primitive's commands' bounding spheres are shown. * @param {Boolean} [options.debugShowShadowVolume=false] For debugging only. Determines if the shadow volume for each geometry in the primitive is drawn. Must be true on * creation for the volumes to be created before the geometry is released or options.releaseGeometryInstance must be false. @@ -208,9 +208,9 @@ define([ * * @type {ClassificationType} * - * @default ClassificationType.BOTH + * @default ClassificationType.TERRAIN */ - this.classificationType = defaultValue(options.classificationType, ClassificationType.BOTH); + this.classificationType = defaultValue(options.classificationType, ClassificationType.TERRAIN); /** * This property is for debugging only; it is not for production use nor is it optimized. *

diff --git a/Specs/Scene/GroundPrimitiveSpec.js b/Specs/Scene/GroundPrimitiveSpec.js index c1d4b9efafdc..e8ab745fe93a 100644 --- a/Specs/Scene/GroundPrimitiveSpec.js +++ b/Specs/Scene/GroundPrimitiveSpec.js @@ -542,7 +542,8 @@ defineSuite([ primitive = new GroundPrimitive({ geometryInstances : rectangleInstance, - asynchronous : false + asynchronous : false, + classificationType: ClassificationType.BOTH }); scene.camera.setView({ destination : rectangle }); @@ -582,7 +583,8 @@ defineSuite([ primitive = new GroundPrimitive({ geometryInstances : rectangleInstance, - asynchronous : false + asynchronous : false, + classificationType: ClassificationType.BOTH }); scene.camera.setView({ destination : rectangle }); From 30ae47416098d3cccb08e39bf3a0f9e0de669200 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Tue, 22 May 2018 12:13:55 -0400 Subject: [PATCH 11/11] fix CHANGES.md --- CHANGES.md | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 82a7419f2a85..13d2f59195df 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,10 @@ Change Log ### 1.46 - 2018-06-01 +##### Breaking Changes :mega: +* Removed `Scene.copyGlobeDepth`. Globe depth will now be copied by default when supported. [#6393](https://github.com/AnalyticalGraphicsInc/cesium/pull/6393) +* The default `classificationType` for `GroundPrimitive`, `CorridorGraphics`, `EllipseGraphics`, `PolygonGraphics` and `RectangleGraphics` is now `ClassificationType.TERRAIN`. If you wish the geometry to color both terrain and 3D tiles, pass in the option `classificationType: Cesium.ClassificationType.BOTH`. + ##### Deprecated :hourglass_flowing_sand: * The `Scene.fxaa` property has been deprecated and will be removed in Cesium 1.47. Use `Scene.postProcessStages.fxaa.enabled`. @@ -18,6 +22,11 @@ Change Log * Added a new Sandcastle label `Post Processing` to showcase the different built-in post-process stages. * Added `Rectangle.equalsEpsilon` for comparing the equality of two rectangles [#6533](https://github.com/AnalyticalGraphicsInc/cesium/pull/6533) * Added `zIndex` for ground geometry, including corridor, ellipse, polygon and rectangle entities. [#6362](https://github.com/AnalyticalGraphicsInc/cesium/pull/6362) +* Added support for materials on terrain entities (entities with unspecified `height`) and `GroundPrimitives`. [#6393](https://github.com/AnalyticalGraphicsInc/cesium/pull/6393) + * Only available for `ClassificationType.TERRAIN` at this time. Adding a material to a terrain `Entity` will cause it to behave as if it is `ClassificationType.TERRAIN`. + * Requires depth texture support (`WEBGL_depth_texture` or `WEBKIT_WEBGL_depth_texture`), so materials on terrain entities and `GroundPrimitives` are not supported in Internet Explorer. + * Best suited for notational patterns and not intended for precisely mapping textures to terrain - for that use case, use `SingleTileImageryProvider`. +* Added `GroundPrimitive.supportsMaterials` and `Entity.supportsMaterialsforEntitiesOnTerrain`, both of which can be used to check if materials on terrain entities and `GroundPrimitives` is supported. [#6393](https://github.com/AnalyticalGraphicsInc/cesium/pull/6393) ##### Fixes :wrench: * Fixed a bug causing custom TilingScheme classes to not be able to use a GeographicProjection. [#6524](https://github.com/AnalyticalGraphicsInc/cesium/pull/6524) @@ -29,17 +38,6 @@ Change Log * Fixed polygon outline when using `perPositionHeight` and `extrudedHeight`. [#6595](https://github.com/AnalyticalGraphicsInc/cesium/issues/6595) * Fixed broken links in documentation of `createTileMapServiceImageryProvider`. [#5818](https://github.com/AnalyticalGraphicsInc/cesium/issues/5818) -##### Breaking Changes :mega: -* Removed `Scene.copyGlobeDepth`. Globe depth will now be copied by default when supported. [#6393](https://github.com/AnalyticalGraphicsInc/cesium/pull/6393) -* The default `classificationType` for `GroundPrimitive`, `CorridorGraphics`, `EllipseGraphics`, `PolygonGraphics` and `RectangleGraphics` is now `ClassificationType.TERRAIN`. If you wish the geometry to color both terrain and 3D tiles, pass in the option `classificationType: Cesium.ClassificationType.BOTH`. - -##### Additions :tada: -* Added support for materials on terrain entities (entities with unspecified `height`) and `GroundPrimitives`. [#6393](https://github.com/AnalyticalGraphicsInc/cesium/pull/6393) - * Only available for `ClassificationType.TERRAIN` at this time. Adding a material to a terrain `Entity` will cause it to behave as if it is `ClassificationType.TERRAIN`. - * Requires depth texture support (`WEBGL_depth_texture` or `WEBKIT_WEBGL_depth_texture`), so materials on terrain entities and `GroundPrimitives` are not supported in Internet Explorer. - * Best suited for notational patterns and not intended for precisely mapping textures to terrain - for that use case, use `SingleTileImageryProvider`. -* Added `GroundPrimitive.supportsMaterials` and `Entity.supportsMaterialsforEntitiesOnTerrain`, both of which can be used to check if materials on terrain entities and `GroundPrimitives` is supported. [#6393](https://github.com/AnalyticalGraphicsInc/cesium/pull/6393) - ### 1.45 - 2018-05-01 ##### Major Announcements :loudspeaker: