diff --git a/.idea/cesium.iml b/.idea/cesium.iml index 9d1caefa1f83..5ecdb1a3e790 100644 --- a/.idea/cesium.iml +++ b/.idea/cesium.iml @@ -8,6 +8,5 @@ - \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml index 3dd4bfcb6516..d45df048bf58 100644 --- a/.idea/jsLibraryMappings.xml +++ b/.idea/jsLibraryMappings.xml @@ -1,7 +1,7 @@ - + \ No newline at end of file diff --git a/.idea/libraries/cesium_node_modules.xml b/.idea/libraries/cesium_node_modules.xml deleted file mode 100644 index 656d3f8a77eb..000000000000 --- a/.idea/libraries/cesium_node_modules.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/Apps/Sandcastle/gallery/ArcGIS MapServer.html b/Apps/Sandcastle/gallery/ArcGIS MapServer.html index 1e6b7a831b36..b205658d1aee 100644 --- a/Apps/Sandcastle/gallery/ArcGIS MapServer.html +++ b/Apps/Sandcastle/gallery/ArcGIS MapServer.html @@ -32,7 +32,7 @@ // Add an ArcGIS MapServer imagery layer var imageryLayers = viewer.imageryLayers; imageryLayers.addImageryProvider(new Cesium.ArcGisMapServerImageryProvider({ - url : 'https://nationalmap.gov.au/proxy/http://www.ga.gov.au/gis/rest/services/earth_science/GA_Surface_Geology_of_Australia_WM/MapServer' + url : 'https://nationalmap.gov.au/proxy/http://services.ga.gov.au/site_3/rest/services/Electricity_Infrastructure/MapServer' })); // Start off looking at Australia. diff --git a/Apps/Sandcastle/gallery/Shadows.html b/Apps/Sandcastle/gallery/Shadows.html index dfbfeb42a9a1..af0faaac9463 100644 --- a/Apps/Sandcastle/gallery/Shadows.html +++ b/Apps/Sandcastle/gallery/Shadows.html @@ -33,7 +33,7 @@ infoBox : false, selectionIndicator : false, shadows : true, - terrainShadows : true + terrainShadows : Cesium.ShadowMode.ENABLED }); viewer.terrainProvider = new Cesium.CesiumTerrainProvider({ @@ -85,6 +85,46 @@ } }); +var boxEntity = viewer.entities.add({ + name : 'Box', + height : 10.0, + box : { + dimensions : new Cesium.Cartesian3(10.0, 10.0, 10.0), + material : Cesium.Color.RED, + shadows : Cesium.ShadowMode.ENABLED + } +}); + +var checkerMaterial = new Cesium.CheckerboardMaterialProperty({ + evenColor : Cesium.Color.RED.withAlpha(0.5), + oddColor : Cesium.Color.RED.withAlpha(0.0), + repeat : new Cesium.Cartesian2(5.0, 10.0) +}); + +var checkerEntity = viewer.entities.add({ + name : 'Checkered Box', + height : 10.0, + box : { + dimensions : new Cesium.Cartesian3(10.0, 10.0, 10.0), + material : checkerMaterial, + outline : true, + outlineColor : Cesium.Color.RED, + shadows : Cesium.ShadowMode.ENABLED + } +}); + +var sphereEntity = viewer.entities.add({ + name : 'Sphere', + height : 20.0, + ellipsoid : { + radii : new Cesium.Cartesian3(15.0, 15.0, 15.0), + material : Cesium.Color.BLUE.withAlpha(0.5), + slicePartitions : 24, + stackPartitions : 36, + shadows : Cesium.ShadowMode.ENABLED + } +}); + var locations = { Exton : { longitude : -1.31968, @@ -190,8 +230,18 @@ viewer.shadows = !viewer.shadows; }); +var entityShadows = Cesium.ShadowMode.ENABLED; +Sandcastle.addToolbarButton('Toggle Entity Shadows', function() { + entityShadows = (entityShadows === Cesium.ShadowMode.ENABLED) ? Cesium.ShadowMode.DISABLED : Cesium.ShadowMode.ENABLED; + for (i = 0; i < entitiesLength; ++i) { + var entity = entities[i]; + var visual = entity.model || entity.box || entity.ellipsoid; + visual.shadows = entityShadows; + } +}); + Sandcastle.addToolbarButton('Toggle Terrain Shadows', function() { - viewer.terrainShadows = !viewer.terrainShadows; + viewer.terrainShadows = (viewer.terrainShadows === Cesium.ShadowMode.ENABLED) ? Cesium.ShadowMode.DISABLED : Cesium.ShadowMode.ENABLED; }); Sandcastle.addToolbarButton('Soft Shadows', function() { @@ -220,35 +270,6 @@ } }]); -function setShadows(castShadows, receiveShadows) { - for (i = 0; i < entitiesLength; ++i) { - entities[i].model.castShadows = castShadows; - entities[i].model.receiveShadows = receiveShadows; - } -} - -Sandcastle.addToolbarMenu([{ - text : 'Entity Shadows', - onselect : function() { - setShadows(true, true); - } -}, { - text : 'Cast Only', - onselect : function() { - setShadows(true, false); - } -}, { - text : 'Receive Only', - onselect : function() { - setShadows(false, true); - } -}, { - text : 'Off', - onselect : function() { - setShadows(false, false); - } -}]); - setLocation(locations.Exton); setEntity(cesiumAir); diff --git a/Apps/Sandcastle/gallery/development/Shadows.html b/Apps/Sandcastle/gallery/development/Shadows.html index 41a2c2c2912f..2bd2f4c3a484 100644 --- a/Apps/Sandcastle/gallery/development/Shadows.html +++ b/Apps/Sandcastle/gallery/development/Shadows.html @@ -390,8 +390,7 @@ // Force all derived commands to update shadowMap.dirty = true; - globe.castShadows = viewModel.terrainCast; - globe.receiveShadows = viewModel.terrainReceive; + globe.shadows = Cesium.ShadowMode.fromCastReceive(viewModel.terrainCast, viewModel.terrainReceive); globe.show = viewModel.globe; scene.skyAtmosphere.show = viewModel.globe; } @@ -639,8 +638,7 @@ }), asynchronous : false, rtcCenter : boxGeometry.boundingSphere.center, - castShadows : true, - receiveShadows : true + shadows : Cesium.ShadowMode.ENABLED }); scene.primitives.add(box); @@ -665,8 +663,7 @@ closed : true }), asynchronous : false, - castShadows : true, - receiveShadows : true + shadows : Cesium.ShadowMode.ENABLED }); scene.primitives.add(box); @@ -691,8 +688,7 @@ closed : true }), asynchronous : false, - castShadows : true, - receiveShadows : true + shadows : Cesium.ShadowMode.ENABLED }); scene.primitives.add(sphere); @@ -711,7 +707,9 @@ handler.setInputAction(function(movement) { var picked = scene.pick(movement.position); if (Cesium.defined(picked) && Cesium.defined(picked.primitive)) { - picked.primitive.castShadows = !picked.primitive.castShadows; + var castShadows = Cesium.ShadowMode.castShadows(picked.primitive.shadows); + var receiveShadows = Cesium.ShadowMode.receiveShadows(picked.primitive.shadows); + picked.primitive.shadows = Cesium.ShadowMode.fromCastReceive(!castShadows, receiveShadows); } }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); @@ -719,7 +717,9 @@ handler.setInputAction(function(movement) { var picked = scene.pick(movement.position); if (Cesium.defined(picked)) { - picked.primitive.receiveShadows = !picked.primitive.receiveShadows; + var castShadows = Cesium.ShadowMode.castShadows(picked.primitive.shadows); + var receiveShadows = Cesium.ShadowMode.receiveShadows(picked.primitive.shadows); + picked.primitive.shadows = Cesium.ShadowMode.fromCastReceive(castShadows, !receiveShadows); } }, Cesium.ScreenSpaceEventType.MIDDLE_DOUBLE_CLICK); diff --git a/CHANGES.md b/CHANGES.md index 6e44781010c8..11419cea0918 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,28 @@ Change Log ========== +### 1.25 - 2016-09-01 +* Breaking changes + * The number and order of arguments passed to `KmlDataSource` `unsupportedNodeEvent` listeners have changed to allow better handling of unsupported KML Features. + * Changed billboards and labels that are clamped to terrain to have the `verticalOrigin` set to `CENTER` by default instead of `BOTTOM`. +* Deprecated + * Deprecated `castShadows` and `receiveShadows` properties from `Model`, `Primitive`, and `Globe`. They will be removed in 1.26. Use `shadows` instead with the `ShadowMode` enum, e.g. `model.shadows = ShadowMode.ENABLED`. + * `Viewer.terrainShadows` now uses the `ShadowMode` enum instead of a Boolean, e.g. `viewer.terrainShadows = ShadowMode.RECEIVE_ONLY`. Boolean support will be removed in 1.26. +* Updated the online [model converter](http://cesiumjs.org/convertmodel.html) to convert OBJ models to glTF with [obj2gltf](https://github.com/AnalyticalGraphicsInc/OBJ2GLTF), as well as optimize existing glTF models with the [gltf-pipeline](https://github.com/AnalyticalGraphicsInc/gltf-pipeline). Added an option to bake ambient occlusion onto the glTF model. Also added an option to compress geometry using the glTF [WEB3D_quantized_attributes](https://github.com/KhronosGroup/glTF/blob/master/extensions/Vendor/WEB3D_quantized_attributes/README.md) extension. +* Improve label quality for oblique and italic fonts. [#3782](https://github.com/AnalyticalGraphicsInc/cesium/issues/3782) +* Added `shadows` property to the entity API for `Box`, `Corridor`, `Cylinder`, `Ellipse`, `Ellipsoid`, `Polygon`, `Polyline`, `PoylineVolume`, `Rectangle`, and `Wall`. [#4005](https://github.com/AnalyticalGraphicsInc/cesium/pull/4005) +* Added `Camera.cancelFlight` to cancel the existing camera flight if it exists. +* Fix overlapping camera flights by always cancelling the previous flight when a new one is created. +* Camera flights now disable collision with the terrain until all of the terrain in the area has finished loading. This prevents the camera from being moved to be above lower resolution terrain when flying to a position close to higher resolution terrain. [#4075](https://github.com/AnalyticalGraphicsInc/cesium/issues/4075) +* Fixed a crash that would occur if quickly toggling imagery visibility. [#4083](https://github.com/AnalyticalGraphicsInc/cesium/issues/4083) +* Fixed an issue causing an error if KML has a clamped to ground LineString with color. [#4131](https://github.com/AnalyticalGraphicsInc/cesium/issues/4131) +* Added logic to `KmlDataSource` defaulting KML Feature node to hidden unless all ancestors are visible. This better matches the KML specification. +* Fixed position of KML point features with an altitude mode of `relativeToGround` and `clampToGround`. +* Added `GeocoderViewModel.keepExpanded` which when set to true will always keep the Geocoder in its expanded state. +* Added support for `INT` and `UNSIGNED_INT` in `ComponentDatatype`. +* Added `ComponentDatatype.fromName` for getting a `ComponentDatatype` from its name. +* Fixed a crash caused by draping dynamic geometry over terrain. [#4255](https://github.com/AnalyticalGraphicsInc/cesium/pull/4255) + ### 1.24 - 2016-08-01 * Added support in CZML for expressing `BillboardGraphics.alignedAxis` as the velocity vector of an entity, using `velocityReference` syntax. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4f90e68ec7df..110827511c03 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,6 +4,8 @@ Thanks for contributing to Cesium. You rock! Are you * [getting started contributing](#getting-started-contributing), or * [opening a pull request](#opening-a-pull-request)? +To ensure an inclusive community, contributors and users in the Cesium community should follow the [code of conduct](#code-of-conduct). + # Submitting an Issue If you have a question, do not submit an issue; instead, search the [Cesium forum](http://cesiumjs.org/forum.html). The forum is very active and there are years of informative archives, often with answers from the core Cesium team. If you do not find an answer to your question, start a new thread and you'll likely get a quick response. @@ -76,3 +78,9 @@ Our code is our lifeblood so maintaining Cesium's high code quality is important * Include reference documentation with code examples. Follow the [Documentation Guide](Documentation/Contributors/DocumentationGuide/README.md). * If the change is significant, add a new [Sandcastle](http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html) example or extend and existing one. * If you added third-party libraries, including new version of existing libraries, update [LICENSE.md](LICENSE.md). Mention it in [CHANGES.md](CHANGES.md). If you plan to add a third-party library, start a new thread on the [Cesium forum](http://cesiumjs.org/forum.html) first. + +# Code of Conduct + +One of Cesium's strengths is our community. Our contributors and users are pushing the 3D geospatial field to amazing new levels. We rely on an open, friendly, inclusive environment to facilitate this. As such, we follow the [Contributor Covenant](http://contributor-covenant.org/)'s [Code of Conduct](http://contributor-covenant.org/version/1/4/code_of_conduct.md) to ensure a harassment-free experience in the Cesium community. Any unacceptable behavior can be confidentiality sent to the core team at pcozzi@agi.com. + +This applies to the main Cesium repo, forum, twitter, and all channels, including all repos in the [AnalyticalGraphicsInc](https://github.com/AnalyticalGraphicsInc) GitHub organization. diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index ed7369b0a60b..d322dd58bd41 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -60,6 +60,8 @@ * [Erik Andersson](https://github.com/e-andersson) * [Simulation Curriculum](http://www.simulationcurriculum.com/) * [Dave Whipps](https://github.com/dwhipps) +* [Geoscan](https://www.geoscan.aero) + * [Andrey Orlov](https://github.com/AndreyOrlov) ## [Individual CLA](http://www.agi.com/licenses/individual-cla-agi-v1.0.txt) * [Victor Berchet](https://github.com/vicb) @@ -98,3 +100,4 @@ * [Mati Ostrovsky](https://github.com/mati-o) * [Tom Novacek](https://github.com/novacto2) * [Olivier Guyot-Roullot](https://github.com/theOgrable) +* [Andy Fry](https://github.com/andyfry01) diff --git a/Documentation/Contributors/TestingGuide/README.md b/Documentation/Contributors/TestingGuide/README.md index fb8a5fd3b8e6..cd0bac588d75 100644 --- a/Documentation/Contributors/TestingGuide/README.md +++ b/Documentation/Contributors/TestingGuide/README.md @@ -171,9 +171,9 @@ It is also possible for Karma to run all tests against each browser installed on `npm run test-webgl` #### Run Only Non-WebGL Tests with Karma - + `npm run test-non-webgl` - + #### Run All Tests Against the Minified Release Version of Cesium `npm run test-release` @@ -381,7 +381,7 @@ afterAll(function() { context.destroyForSpecs(); }); -it('has czm_tranpose (2x2)', function() { +it('has czm_transpose (2x2)', function() { var fs = 'void main() { ' + ' mat2 m = mat2(1.0, 2.0, 3.0, 4.0); ' + diff --git a/README.md b/README.md index 7c85e33e6942..a038b06112cc 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@

[![Build Status](https://travis-ci.org/AnalyticalGraphicsInc/cesium.svg?branch=master)](https://travis-ci.org/AnalyticalGraphicsInc/cesium)  -[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) [![Docs](https://img.shields.io/badge/docs-online-orange.svg)](http://cesiumjs.org/tutorials.html) Cesium is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin. It uses WebGL for hardware-accelerated graphics, and is cross-platform, cross-browser, and tuned for dynamic-data visualization. @@ -46,6 +46,15 @@ We appreciate attribution by including the Cesium logo and link in your app. ### Demos ###

+  +  +  +  +  +  +  +  +        diff --git a/Source/Core/BingMapsApi.js b/Source/Core/BingMapsApi.js index bd2f03290bc0..2018caa68dc4 100644 --- a/Source/Core/BingMapsApi.js +++ b/Source/Core/BingMapsApi.js @@ -42,7 +42,7 @@ define([ console.log(errorString); printedBingWarning = true; } - return 'AnjT_wAj_juA_MsD8NhcEAVSjCYpV-e50lUypkWm1JPxVu0XyVqabsvD3r2DQpX-'; + return 'AhiQlDaPOwKbStA_3nJIdimUj4PRYkp0yHwcNpvxVlLNPRo5ZJWY5oX_h6B_dMbm'; } return BingMapsApi.defaultKey; diff --git a/Source/Core/ComponentDatatype.js b/Source/Core/ComponentDatatype.js index 5c1a58dc54fe..9d9d94ba08d2 100644 --- a/Source/Core/ComponentDatatype.js +++ b/Source/Core/ComponentDatatype.js @@ -64,6 +64,28 @@ define([ */ UNSIGNED_SHORT : WebGLConstants.UNSIGNED_SHORT, + /** + * 32-bit signed int corresponding to INT and the type + * of an element in Int32Array. + * + * @memberOf ComponentDatatype + * + * @type {Number} + * @constant + */ + INT : WebGLConstants.INT, + + /** + * 32-bit unsigned int corresponding to UNSIGNED_INT and the type + * of an element in Uint32Array. + * + * @memberOf ComponentDatatype + * + * @type {Number} + * @constant + */ + UNSIGNED_INT : WebGLConstants.UNSIGNED_INT, + /** * 32-bit floating-point corresponding to FLOAT and the type * of an element in Float32Array. @@ -115,6 +137,10 @@ define([ return Int16Array.BYTES_PER_ELEMENT; case ComponentDatatype.UNSIGNED_SHORT: return Uint16Array.BYTES_PER_ELEMENT; + case ComponentDatatype.INT: + return Int32Array.BYTES_PER_ELEMENT; + case ComponentDatatype.UNSIGNED_INT: + return Uint32Array.BYTES_PER_ELEMENT; case ComponentDatatype.FLOAT: return Float32Array.BYTES_PER_ELEMENT; case ComponentDatatype.DOUBLE: @@ -125,7 +151,7 @@ define([ }; /** - * Gets the ComponentDatatype for the provided TypedArray instance. + * Gets the {@link ComponentDatatype} for the provided TypedArray instance. * * @param {TypedArray} array The typed array. * @returns {ComponentDatatype} The ComponentDatatype for the provided array, or undefined if the array is not a TypedArray. @@ -143,6 +169,12 @@ define([ if (array instanceof Uint16Array) { return ComponentDatatype.UNSIGNED_SHORT; } + if (array instanceof Int32Array) { + return ComponentDatatype.INT; + } + if (array instanceof Uint32Array) { + return ComponentDatatype.UNSIGNED_INT; + } if (array instanceof Float32Array) { return ComponentDatatype.FLOAT; } @@ -168,6 +200,8 @@ define([ componentDatatype === ComponentDatatype.UNSIGNED_BYTE || componentDatatype === ComponentDatatype.SHORT || componentDatatype === ComponentDatatype.UNSIGNED_SHORT || + componentDatatype === ComponentDatatype.INT || + componentDatatype === ComponentDatatype.UNSIGNED_INT || componentDatatype === ComponentDatatype.FLOAT || componentDatatype === ComponentDatatype.DOUBLE); }; @@ -177,7 +211,7 @@ define([ * * @param {ComponentDatatype} componentDatatype The component data type. * @param {Number|Array} valuesOrLength The length of the array to create or an array. - * @returns {Int8Array|Uint8Array|Int16Array|Uint16Array|Float32Array|Float64Array} A typed array. + * @returns {Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array} A typed array. * * @exception {DeveloperError} componentDatatype is not a valid value. * @@ -204,6 +238,10 @@ define([ return new Int16Array(valuesOrLength); case ComponentDatatype.UNSIGNED_SHORT: return new Uint16Array(valuesOrLength); + case ComponentDatatype.INT: + return new Int32Array(valuesOrLength); + case ComponentDatatype.UNSIGNED_INT: + return new Uint32Array(valuesOrLength); case ComponentDatatype.FLOAT: return new Float32Array(valuesOrLength); case ComponentDatatype.DOUBLE: @@ -220,7 +258,7 @@ define([ * @param {ArrayBuffer} buffer The buffer storage to use for the view. * @param {Number} [byteOffset] The offset, in bytes, to the first element in the view. * @param {Number} [length] The number of elements in the view. - * @returns {Int8Array|Uint8Array|Int16Array|Uint16Array|Float32Array|Float64Array} A typed array view of the buffer. + * @returns {Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array} A typed array view of the buffer. * * @exception {DeveloperError} componentDatatype is not a valid value. */ @@ -246,6 +284,10 @@ define([ return new Int16Array(buffer, byteOffset, length); case ComponentDatatype.UNSIGNED_SHORT: return new Uint16Array(buffer, byteOffset, length); + case ComponentDatatype.INT: + return new Int32Array(buffer, byteOffset, length); + case ComponentDatatype.UNSIGNED_INT: + return new Uint32Array(buffer, byteOffset, length); case ComponentDatatype.FLOAT: return new Float32Array(buffer, byteOffset, length); case ComponentDatatype.DOUBLE: @@ -255,5 +297,36 @@ define([ } }; + /** + * Get the ComponentDatatype from its name. + * + * @param {String} name The name of the ComponentDatatype. + * @returns {ComponentDatatype} The ComponentDatatype. + * + * @exception {DeveloperError} name is not a valid value. + */ + ComponentDatatype.fromName = function(name) { + switch (name) { + case 'BYTE': + return ComponentDatatype.BYTE; + case 'UNSIGNED_BYTE': + return ComponentDatatype.UNSIGNED_BYTE; + case 'SHORT': + return ComponentDatatype.SHORT; + case 'UNSIGNED_SHORT': + return ComponentDatatype.UNSIGNED_SHORT; + case 'INT': + return ComponentDatatype.INT; + case 'UNSIGNED_INT': + return ComponentDatatype.UNSIGNED_INT; + case 'FLOAT': + return ComponentDatatype.FLOAT; + case 'DOUBLE': + return ComponentDatatype.DOUBLE; + default: + throw new DeveloperError('name is not a valid value.'); + } + }; + return freezeObject(ComponentDatatype); }); diff --git a/Source/Core/RectangleGeometryLibrary.js b/Source/Core/RectangleGeometryLibrary.js index 1dd8a01ac4d0..34ac3cbbb40a 100644 --- a/Source/Core/RectangleGeometryLibrary.js +++ b/Source/Core/RectangleGeometryLibrary.js @@ -112,7 +112,7 @@ define([ var granYSin = 0.0; var granXSin = 0.0; - if (defined(rotation)) { // rotation doesn't work when center is on/near IDL + if (defined(rotation) && rotation !== 0) { // rotation doesn't work when center is on/near IDL var cosRotation = Math.cos(rotation); granYCos *= cosRotation; granXCos *= cosRotation; diff --git a/Source/Core/loadWithXhr.js b/Source/Core/loadWithXhr.js index 415093c27601..fe2d42c85846 100644 --- a/Source/Core/loadWithXhr.js +++ b/Source/Core/loadWithXhr.js @@ -43,7 +43,7 @@ define([ * }).otherwise(function(error) { * // an error occurred * }); - * + * * @see loadArrayBuffer * @see loadBlob * @see loadJson @@ -102,23 +102,23 @@ define([ var data = dataUriRegexResult[3]; switch (responseType) { - case '': - case 'text': - return decodeDataUriText(isBase64, data); - case 'arraybuffer': - return decodeDataUriArrayBuffer(isBase64, data); - case 'blob': - var buffer = decodeDataUriArrayBuffer(isBase64, data); - return new Blob([buffer], { - type : mimeType - }); - case 'document': - var parser = new DOMParser(); - return parser.parseFromString(decodeDataUriText(isBase64, data), mimeType); - case 'json': - return JSON.parse(decodeDataUriText(isBase64, data)); - default: - throw new DeveloperError('Unhandled responseType: ' + responseType); + case '': + case 'text': + return decodeDataUriText(isBase64, data); + case 'arraybuffer': + return decodeDataUriArrayBuffer(isBase64, data); + case 'blob': + var buffer = decodeDataUriArrayBuffer(isBase64, data); + return new Blob([buffer], { + type : mimeType + }); + case 'document': + var parser = new DOMParser(); + return parser.parseFromString(decodeDataUriText(isBase64, data), mimeType); + case 'json': + return JSON.parse(decodeDataUriText(isBase64, data)); + default: + throw new DeveloperError('Unhandled responseType: ' + responseType); } } @@ -139,7 +139,7 @@ define([ xhr.open(method, url, true); if (defined(headers)) { - for ( var key in headers) { + for (var key in headers) { if (headers.hasOwnProperty(key)) { xhr.setRequestHeader(key, headers[key]); } @@ -151,21 +151,31 @@ define([ } xhr.onload = function() { - if (xhr.status >= 200 && xhr.status < 300) { - if (defined(xhr.response)) { - deferred.resolve(xhr.response); - } else { - // busted old browsers. - if (defined(xhr.responseXML) && xhr.responseXML.hasChildNodes()) { - deferred.resolve(xhr.responseXML); - } else if (defined(xhr.responseText)) { - deferred.resolve(xhr.responseText); - } else { - deferred.reject(new RuntimeError('unknown XMLHttpRequest response type.')); - } + if (xhr.status < 200 || xhr.status >= 300) { + deferred.reject(new RequestErrorEvent(xhr.status, xhr.response, xhr.getAllResponseHeaders())); + return; + } + + var response = xhr.response; + var browserResponseType = xhr.responseType; + + //All modern browsers will go into either the first if block or last else block. + //Other code paths support older browsers that either do not support the supplied responseType + //or do not support the xhr.response property. + if (defined(response) && (!defined(responseType) || (browserResponseType === responseType))) { + deferred.resolve(response); + } else if ((responseType === 'json') && typeof response === 'string') { + try { + deferred.resolve(JSON.parse(response)); + } catch (e) { + deferred.reject(e); } + } else if ((browserResponseType === '' || browserResponseType === 'document') && defined(xhr.responseXML) && xhr.responseXML.hasChildNodes()) { + deferred.resolve(xhr.responseXML); + } else if ((browserResponseType === '' || browserResponseType === 'text') && defined(xhr.responseText)) { + deferred.resolve(xhr.responseText); } else { - deferred.reject(new RequestErrorEvent(xhr.status, xhr.response, xhr.getAllResponseHeaders())); + deferred.reject(new RuntimeError('Invalid XMLHttpRequest response type.')); } }; diff --git a/Source/DataSources/BoxGeometryUpdater.js b/Source/DataSources/BoxGeometryUpdater.js index 40bc2b9f4ce7..63d3a9e8e5a1 100644 --- a/Source/DataSources/BoxGeometryUpdater.js +++ b/Source/DataSources/BoxGeometryUpdater.js @@ -16,6 +16,7 @@ define([ '../Scene/MaterialAppearance', '../Scene/PerInstanceColorAppearance', '../Scene/Primitive', + '../Scene/ShadowMode', './ColorMaterialProperty', './ConstantProperty', './dynamicGeometryGetBoundingSphere', @@ -38,6 +39,7 @@ define([ MaterialAppearance, PerInstanceColorAppearance, Primitive, + ShadowMode, ColorMaterialProperty, ConstantProperty, dynamicGeometryGetBoundingSphere, @@ -50,6 +52,7 @@ define([ var defaultFill = new ConstantProperty(true); var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); + var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); var scratchColor = new Color(); function GeometryOptions(entity) { @@ -90,6 +93,7 @@ define([ this._showOutlineProperty = undefined; this._outlineColorProperty = undefined; this._outlineWidth = 1.0; + this._shadowsProperty = undefined; this._options = new GeometryOptions(entity); this._onEntityPropertyChanged(entity, 'box', entity.box, undefined); } @@ -217,6 +221,19 @@ define([ return this._outlineWidth; } }, + /** + * Gets the property specifying whether the geometry + * casts or receives shadows from each light source. + * @memberof BoxGeometryUpdater.prototype + * + * @type {Property} + * @readonly + */ + shadowsProperty : { + get : function() { + return this._shadowsProperty; + } + }, /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -436,6 +453,7 @@ define([ this._showProperty = defaultValue(show, defaultShow); this._showOutlineProperty = defaultValue(box.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(box.outlineColor, defaultOutlineColor) : undefined; + this._shadowsProperty = defaultValue(box.shadows, defaultShadows); var outlineWidth = box.outlineWidth; @@ -521,6 +539,8 @@ define([ options.dimensions = dimensions; + var shadows = this._geometryUpdater.shadowsProperty.getValue(time); + if (Property.getValueOrDefault(box.fill, time, true)) { var material = MaterialProperty.getValue(time, geometryUpdater.fillMaterialProperty, this._material); this._material = material; @@ -539,7 +559,8 @@ define([ modelMatrix : modelMatrix }), appearance : appearance, - asynchronous : false + asynchronous : false, + shadows : shadows })); } @@ -566,7 +587,8 @@ define([ lineWidth : geometryUpdater._scene.clampLineWidth(outlineWidth) } }), - asynchronous : false + asynchronous : false, + shadows : shadows })); } }; diff --git a/Source/DataSources/BoxGraphics.js b/Source/DataSources/BoxGraphics.js index c2a7d11ed423..a9e4be26f6eb 100644 --- a/Source/DataSources/BoxGraphics.js +++ b/Source/DataSources/BoxGraphics.js @@ -31,6 +31,7 @@ define([ * @param {Property} [options.outline=false] A boolean Property specifying whether the box is outlined. * @param {Property} [options.outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline. * @param {Property} [options.outlineWidth=1.0] A numeric Property specifying the width of the outline. + * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the box casts or receives shadows from each light source. * * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Box.html|Cesium Sandcastle Box Demo} */ @@ -49,6 +50,8 @@ define([ this._outlineColorSubscription = undefined; this._outlineWidth = undefined; this._outlineWidthSubscription = undefined; + this._shadows = undefined; + this._shadowsSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -120,7 +123,16 @@ define([ * @type {Property} * @default 1.0 */ - outlineWidth : createPropertyDescriptor('outlineWidth') + outlineWidth : createPropertyDescriptor('outlineWidth'), + + /** + * Get or sets the enum Property specifying whether the box + * casts or receives shadows from each light source. + * @memberof BoxGraphics.prototype + * @type {Property} + * @default ShadowMode.DISABLED + */ + shadows : createPropertyDescriptor('shadows') }); /** @@ -140,6 +152,7 @@ define([ result.outline = this.outline; result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; + result.shadows = this.shadows; return result; }; @@ -163,6 +176,7 @@ define([ this.outline = defaultValue(this.outline, source.outline); this.outlineColor = defaultValue(this.outlineColor, source.outlineColor); this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth); + this.shadows = defaultValue(this.shadows, source.shadows); }; return BoxGraphics; diff --git a/Source/DataSources/CorridorGeometryUpdater.js b/Source/DataSources/CorridorGeometryUpdater.js index f1b071a14ba8..29f9374f73e7 100644 --- a/Source/DataSources/CorridorGeometryUpdater.js +++ b/Source/DataSources/CorridorGeometryUpdater.js @@ -18,6 +18,7 @@ define([ '../Scene/MaterialAppearance', '../Scene/PerInstanceColorAppearance', '../Scene/Primitive', + '../Scene/ShadowMode', './ColorMaterialProperty', './ConstantProperty', './dynamicGeometryGetBoundingSphere', @@ -42,6 +43,7 @@ define([ MaterialAppearance, PerInstanceColorAppearance, Primitive, + ShadowMode, ColorMaterialProperty, ConstantProperty, dynamicGeometryGetBoundingSphere, @@ -54,6 +56,7 @@ define([ var defaultFill = new ConstantProperty(true); var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); + var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); var scratchColor = new Color(); function GeometryOptions(entity) { @@ -100,6 +103,7 @@ define([ this._showOutlineProperty = undefined; this._outlineColorProperty = undefined; this._outlineWidth = 1.0; + this._shadowsProperty = undefined; this._onTerrain = false; this._options = new GeometryOptions(entity); @@ -229,6 +233,19 @@ define([ return this._outlineWidth; } }, + /** + * Gets the property specifying whether the geometry + * casts or receives shadows from each light source. + * @memberof CorridorGeometryUpdater.prototype + * + * @type {Property} + * @readonly + */ + shadowsProperty : { + get : function() { + return this._shadowsProperty; + } + }, /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -460,6 +477,7 @@ define([ this._showProperty = defaultValue(show, defaultShow); this._showOutlineProperty = defaultValue(corridor.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(corridor.outlineColor, defaultOutlineColor) : undefined; + this._shadowsProperty = defaultValue(corridor.shadows, defaultShadows); var height = corridor.height; var extrudedHeight = corridor.extrudedHeight; @@ -580,6 +598,8 @@ define([ options.granularity = Property.getValueOrUndefined(corridor.granularity, time); options.cornerType = Property.getValueOrUndefined(corridor.cornerType, time); + var shadows = this._geometryUpdater.shadowsProperty.getValue(time); + if (!defined(corridor.fill) || corridor.fill.getValue(time)) { var fillMaterialProperty = geometryUpdater.fillMaterialProperty; var material = MaterialProperty.getValue(time, fillMaterialProperty, this._material); @@ -592,14 +612,15 @@ define([ } this._primitive = groundPrimitives.add(new GroundPrimitive({ - geometryInstance : new GeometryInstance({ + geometryInstances : new GeometryInstance({ id : entity, geometry : new CorridorGeometry(options), attributes: { color: ColorGeometryInstanceAttribute.fromColor(currentColor) } }), - asynchronous : false + asynchronous : false, + shadows : shadows })); } else { var appearance = new MaterialAppearance({ @@ -615,7 +636,8 @@ define([ geometry : new CorridorGeometry(options) }), appearance : appearance, - asynchronous : false + asynchronous : false, + shadows : shadows })); } } @@ -642,7 +664,8 @@ define([ lineWidth : geometryUpdater._scene.clampLineWidth(outlineWidth) } }), - asynchronous : false + asynchronous : false, + shadows : shadows })); } }; diff --git a/Source/DataSources/CorridorGraphics.js b/Source/DataSources/CorridorGraphics.js index e15ab9b6347a..98161c48e343 100644 --- a/Source/DataSources/CorridorGraphics.js +++ b/Source/DataSources/CorridorGraphics.js @@ -38,6 +38,7 @@ define([ * @param {Property} [options.outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline. * @param {Property} [options.outlineWidth=1.0] A numeric Property specifying the width of the outline. * @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. * * @see Entity * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Corridor.html|Cesium Sandcastle Corridor Demo} @@ -67,6 +68,8 @@ define([ this._outlineColorSubscription = undefined; this._outlineWidth = undefined; this._outlineWidthSubscription = undefined; + this._shadows = undefined; + this._shadowsSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -178,7 +181,16 @@ define([ * @type {Property} * @default CornerType.ROUNDED */ - cornerType : createPropertyDescriptor('cornerType') + cornerType : createPropertyDescriptor('cornerType'), + + /** + * Get or sets the enum Property specifying whether the corridor + * casts or receives shadows from each light source. + * @memberof CorridorGraphics.prototype + * @type {Property} + * @default ShadowMode.DISABLED + */ + shadows : createPropertyDescriptor('shadows') }); /** @@ -203,6 +215,7 @@ define([ result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.cornerType = this.cornerType; + result.shadows = this.shadows; return result; }; @@ -231,6 +244,7 @@ define([ this.outlineColor = defaultValue(this.outlineColor, source.outlineColor); this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth); this.cornerType = defaultValue(this.cornerType, source.cornerType); + this.shadows = defaultValue(this.shadows, source.shadows); }; return CorridorGraphics; diff --git a/Source/DataSources/CylinderGeometryUpdater.js b/Source/DataSources/CylinderGeometryUpdater.js index bd5f7ba199f4..86881bb9eec7 100644 --- a/Source/DataSources/CylinderGeometryUpdater.js +++ b/Source/DataSources/CylinderGeometryUpdater.js @@ -17,6 +17,7 @@ define([ '../Scene/MaterialAppearance', '../Scene/PerInstanceColorAppearance', '../Scene/Primitive', + '../Scene/ShadowMode', './ColorMaterialProperty', './ConstantProperty', './dynamicGeometryGetBoundingSphere', @@ -40,6 +41,7 @@ define([ MaterialAppearance, PerInstanceColorAppearance, Primitive, + ShadowMode, ColorMaterialProperty, ConstantProperty, dynamicGeometryGetBoundingSphere, @@ -52,6 +54,7 @@ define([ var defaultFill = new ConstantProperty(true); var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); + var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); var scratchColor = new Color(); @@ -97,6 +100,7 @@ define([ this._showOutlineProperty = undefined; this._outlineColorProperty = undefined; this._outlineWidth = 1.0; + this._shadowsProperty = undefined; this._options = new GeometryOptions(entity); this._onEntityPropertyChanged(entity, 'cylinder', entity.cylinder, undefined); } @@ -224,6 +228,19 @@ define([ return this._outlineWidth; } }, + /** + * Gets the property specifying whether the geometry + * casts or receives shadows from each light source. + * @memberof CylinderGeometryUpdater.prototype + * + * @type {Property} + * @readonly + */ + shadowsProperty : { + get : function() { + return this._shadowsProperty; + } + }, /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -446,6 +463,7 @@ define([ this._showProperty = defaultValue(show, defaultShow); this._showOutlineProperty = defaultValue(cylinder.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(cylinder.outlineColor, defaultOutlineColor) : undefined; + this._shadowsProperty = defaultValue(cylinder.shadows, defaultShadows); var slices = cylinder.slices; var outlineWidth = cylinder.outlineWidth; @@ -547,6 +565,8 @@ define([ options.slices = Property.getValueOrUndefined(cylinder.slices, time); options.numberOfVerticalLines = Property.getValueOrUndefined(cylinder.numberOfVerticalLines, time); + var shadows = this._geometryUpdater.shadowsProperty.getValue(time); + if (Property.getValueOrDefault(cylinder.fill, time, true)) { var material = MaterialProperty.getValue(time, geometryUpdater.fillMaterialProperty, this._material); this._material = material; @@ -565,7 +585,8 @@ define([ modelMatrix : modelMatrix }), appearance : appearance, - asynchronous : false + asynchronous : false, + shadows : shadows })); } @@ -592,7 +613,8 @@ define([ lineWidth : geometryUpdater._scene.clampLineWidth(outlineWidth) } }), - asynchronous : false + asynchronous : false, + shadows : shadows })); } }; diff --git a/Source/DataSources/CylinderGraphics.js b/Source/DataSources/CylinderGraphics.js index 0640971e8593..d2f4196519d9 100644 --- a/Source/DataSources/CylinderGraphics.js +++ b/Source/DataSources/CylinderGraphics.js @@ -36,6 +36,7 @@ define([ * @param {Property} [options.outlineWidth=1.0] A numeric Property specifying the width of the outline. * @param {Property} [options.numberOfVerticalLines=16] A numeric Property specifying the number of vertical lines to draw along the perimeter for the outline. * @param {Property} [options.slices=128] The number of edges around the perimeter of the cylinder. + * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the cylinder casts or receives shadows from each light source. */ function CylinderGraphics(options) { this._length = undefined; @@ -60,6 +61,8 @@ define([ this._outlineColorSubscription = undefined; this._outlineWidth = undefined; this._outlineWidthSubscription = undefined; + this._shadows = undefined; + this._shadowsSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -162,7 +165,16 @@ define([ * @type {Property} * @default 1.0 */ - outlineWidth : createPropertyDescriptor('outlineWidth') + outlineWidth : createPropertyDescriptor('outlineWidth'), + + /** + * Get or sets the enum Property specifying whether the cylinder + * casts or receives shadows from each light source. + * @memberof CylinderGraphics.prototype + * @type {Property} + * @default ShadowMode.DISABLED + */ + shadows : createPropertyDescriptor('shadows') }); /** @@ -186,6 +198,7 @@ define([ result.outline = this.outline; result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; + result.shadows = this.shadows; return result; }; @@ -213,6 +226,7 @@ define([ this.outline = defaultValue(this.outline, source.outline); this.outlineColor = defaultValue(this.outlineColor, source.outlineColor); this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth); + this.shadows = defaultValue(this.shadows, source.shadows); }; return CylinderGraphics; diff --git a/Source/DataSources/CzmlDataSource.js b/Source/DataSources/CzmlDataSource.js index 00c9b989ce03..706049c9fc25 100644 --- a/Source/DataSources/CzmlDataSource.js +++ b/Source/DataSources/CzmlDataSource.js @@ -37,6 +37,7 @@ define([ '../Scene/HeightReference', '../Scene/HorizontalOrigin', '../Scene/LabelStyle', + '../Scene/ShadowMode', '../Scene/VerticalOrigin', '../ThirdParty/Uri', '../ThirdParty/when', @@ -119,6 +120,7 @@ define([ HeightReference, HorizontalOrigin, LabelStyle, + ShadowMode, VerticalOrigin, Uri, when, @@ -446,6 +448,8 @@ define([ return unwrapQuaternionInterval(czmlInterval); case Rotation: return defaultValue(czmlInterval.number, czmlInterval); + case ShadowMode: + return ShadowMode[defaultValue(czmlInterval.shadows, czmlInterval)]; case String: return defaultValue(czmlInterval.string, czmlInterval); case StripeOrientation: @@ -1166,6 +1170,7 @@ define([ processPacketData(Boolean, box, 'outline', boxData.outline, interval, sourceUri, entityCollection); processPacketData(Color, box, 'outlineColor', boxData.outlineColor, interval, sourceUri, entityCollection); processPacketData(Number, box, 'outlineWidth', boxData.outlineWidth, interval, sourceUri, entityCollection); + processPacketData(ShadowMode, box, 'shadows', boxData.shadows, interval, sourceUri, entityCollection); } function processCorridor(entity, packet, entityCollection, sourceUri) { @@ -1198,6 +1203,7 @@ define([ processPacketData(Boolean, corridor, 'outline', corridorData.outline, interval, sourceUri, entityCollection); processPacketData(Color, corridor, 'outlineColor', corridorData.outlineColor, interval, sourceUri, entityCollection); processPacketData(Number, corridor, 'outlineWidth', corridorData.outlineWidth, interval, sourceUri, entityCollection); + processPacketData(ShadowMode, corridor, 'shadows', corridorData.shadows, interval, sourceUri, entityCollection); } function processCylinder(entity, packet, entityCollection, sourceUri) { @@ -1229,6 +1235,7 @@ define([ processPacketData(Number, cylinder, 'outlineWidth', cylinderData.outlineWidth, interval, sourceUri, entityCollection); processPacketData(Number, cylinder, 'numberOfVerticalLines', cylinderData.numberOfVerticalLines, interval, sourceUri, entityCollection); processPacketData(Number, cylinder, 'slices', cylinderData.slices, interval, sourceUri, entityCollection); + processPacketData(ShadowMode, cylinder, 'shadows', cylinderData.shadows, interval, sourceUri, entityCollection); } function processDocument(packet, dataSource) { @@ -1308,6 +1315,7 @@ define([ processPacketData(Color, ellipse, 'outlineColor', ellipseData.outlineColor, interval, sourceUri, entityCollection); processPacketData(Number, ellipse, 'outlineWidth', ellipseData.outlineWidth, interval, sourceUri, entityCollection); processPacketData(Number, ellipse, 'numberOfVerticalLines', ellipseData.numberOfVerticalLines, interval, sourceUri, entityCollection); + processPacketData(ShadowMode, ellipse, 'shadows', ellipseData.shadows, interval, sourceUri, entityCollection); } function processEllipsoid(entity, packet, entityCollection, sourceUri) { @@ -1338,6 +1346,7 @@ define([ processPacketData(Number, ellipsoid, 'stackPartitions', ellipsoidData.stackPartitions, interval, sourceUri, entityCollection); processPacketData(Number, ellipsoid, 'slicePartitions', ellipsoidData.slicePartitions, interval, sourceUri, entityCollection); processPacketData(Number, ellipsoid, 'subdivisions', ellipsoidData.subdivisions, interval, sourceUri, entityCollection); + processPacketData(ShadowMode, ellipsoid, 'shadows', ellipsoidData.shadows, interval, sourceUri, entityCollection); } function processLabel(entity, packet, entityCollection, sourceUri) { @@ -1399,9 +1408,10 @@ define([ processPacketData(Number, model, 'minimumPixelSize', modelData.minimumPixelSize, interval, sourceUri, entityCollection); processPacketData(Number, model, 'maximumScale', modelData.maximumScale, interval, sourceUri, entityCollection); processPacketData(Boolean, model, 'incrementallyLoadTextures', modelData.incrementallyLoadTextures, interval, sourceUri, entityCollection); + processPacketData(Boolean, model, 'runAnimations', modelData.runAnimations, interval, sourceUri, entityCollection); processPacketData(Boolean, model, 'castShadows', modelData.castShadows, interval, sourceUri, entityCollection); processPacketData(Boolean, model, 'receiveShadows', modelData.receiveShadows, interval, sourceUri, entityCollection); - processPacketData(Boolean, model, 'runAnimations', modelData.runAnimations, interval, sourceUri, entityCollection); + processPacketData(ShadowMode, model, 'shadows', modelData.shadows, interval, sourceUri, entityCollection); processPacketData(HeightReference, model, 'heightReference', modelData.heightReference, interval, sourceUri, entityCollection); var nodeTransformationsData = modelData.nodeTransformations; @@ -1549,6 +1559,7 @@ define([ processPacketData(Boolean, polygon, 'perPositionHeight', polygonData.perPositionHeight, interval, sourceUri, entityCollection); processPacketData(Boolean, polygon, 'closeTop', polygonData.closeTop, interval, sourceUri, entityCollection); processPacketData(Boolean, polygon, 'closeBottom', polygonData.closeBottom, interval, sourceUri, entityCollection); + processPacketData(ShadowMode, polygon, 'shadows', polygonData.shadows, interval, sourceUri, entityCollection); } function processPolyline(entity, packet, entityCollection, sourceUri) { @@ -1575,6 +1586,7 @@ define([ processPacketData(Number, polyline, 'granularity', polylineData.granularity, interval, sourceUri, entityCollection); processMaterialPacketData(polyline, 'material', polylineData.material, interval, sourceUri, entityCollection); processPacketData(Boolean, polyline, 'followSurface', polylineData.followSurface, interval, sourceUri, entityCollection); + processPacketData(ShadowMode, polyline, 'shadows', polylineData.shadows, interval, sourceUri, entityCollection); } function processRectangle(entity, packet, entityCollection, sourceUri) { @@ -1609,6 +1621,7 @@ define([ processPacketData(Number, rectangle, 'outlineWidth', rectangleData.outlineWidth, interval, sourceUri, entityCollection); processPacketData(Boolean, rectangle, 'closeTop', rectangleData.closeTop, interval, sourceUri, entityCollection); processPacketData(Boolean, rectangle, 'closeBottom', rectangleData.closeBottom, interval, sourceUri, entityCollection); + processPacketData(ShadowMode, rectangle, 'shadows', rectangleData.shadows, interval, sourceUri, entityCollection); } function processWall(entity, packet, entityCollection, sourceUri) { @@ -1639,6 +1652,7 @@ define([ processPacketData(Boolean, wall, 'outline', wallData.outline, interval, sourceUri, entityCollection); processPacketData(Color, wall, 'outlineColor', wallData.outlineColor, interval, sourceUri, entityCollection); processPacketData(Number, wall, 'outlineWidth', wallData.outlineWidth, interval, sourceUri, entityCollection); + processPacketData(ShadowMode, wall, 'shadows', wallData.shadows, interval, sourceUri, entityCollection); } function processCzmlPacket(packet, entityCollection, updaterFunctions, sourceUri, dataSource) { diff --git a/Source/DataSources/DataSourceDisplay.js b/Source/DataSources/DataSourceDisplay.js index c7f48feb1255..c5ae516e6ac1 100644 --- a/Source/DataSources/DataSourceDisplay.js +++ b/Source/DataSources/DataSourceDisplay.js @@ -7,6 +7,7 @@ define([ '../Core/destroyObject', '../Core/DeveloperError', '../Core/EventHelper', + '../Scene/GroundPrimitive', './BillboardVisualizer', './BoundingSphereState', './BoxGeometryUpdater', @@ -33,6 +34,7 @@ define([ destroyObject, DeveloperError, EventHelper, + GroundPrimitive, BillboardVisualizer, BoundingSphereState, BoxGeometryUpdater, @@ -77,6 +79,8 @@ define([ throw new DeveloperError('dataSourceCollection is required.'); } //>>includeEnd('debug'); + + GroundPrimitive.initializeTerrainHeights(); var scene = options.scene; var dataSourceCollection = options.dataSourceCollection; @@ -231,6 +235,11 @@ define([ } //>>includeEnd('debug'); + if (!GroundPrimitive._initialized) { + this._ready = false; + return false; + } + var result = true; var i; @@ -292,6 +301,10 @@ define([ } //>>includeEnd('debug'); + if (!this._ready) { + return BoundingSphereState.PENDING; + } + var i; var length; var dataSource = this._defaultDataSource; diff --git a/Source/DataSources/EllipseGeometryUpdater.js b/Source/DataSources/EllipseGeometryUpdater.js index 7f204a09a7a8..a9e13c630672 100644 --- a/Source/DataSources/EllipseGeometryUpdater.js +++ b/Source/DataSources/EllipseGeometryUpdater.js @@ -18,6 +18,7 @@ define([ '../Scene/MaterialAppearance', '../Scene/PerInstanceColorAppearance', '../Scene/Primitive', + '../Scene/ShadowMode', './ColorMaterialProperty', './ConstantProperty', './dynamicGeometryGetBoundingSphere', @@ -42,6 +43,7 @@ define([ MaterialAppearance, PerInstanceColorAppearance, Primitive, + ShadowMode, ColorMaterialProperty, ConstantProperty, dynamicGeometryGetBoundingSphere, @@ -54,6 +56,7 @@ define([ var defaultFill = new ConstantProperty(true); var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); + var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); var scratchColor = new Color(); function GeometryOptions(entity) { @@ -103,6 +106,7 @@ define([ this._showOutlineProperty = undefined; this._outlineColorProperty = undefined; this._outlineWidth = 1.0; + this._shadowsProperty = undefined; this._onTerrain = false; this._options = new GeometryOptions(entity); @@ -232,6 +236,19 @@ define([ return this._outlineWidth; } }, + /** + * Gets the property specifying whether the geometry + * casts or receives shadows from each light source. + * @memberof EllipseGeometryUpdater.prototype + * + * @type {Property} + * @readonly + */ + shadowsProperty : { + get : function() { + return this._shadowsProperty; + } + }, /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -465,6 +482,7 @@ define([ this._showProperty = defaultValue(show, defaultShow); this._showOutlineProperty = defaultValue(ellipse.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(ellipse.outlineColor, defaultOutlineColor) : undefined; + this._shadowsProperty = defaultValue(ellipse.shadows, defaultShadows); var rotation = ellipse.rotation; var height = ellipse.height; @@ -597,6 +615,8 @@ define([ options.stRotation = Property.getValueOrUndefined(ellipse.stRotation, time); options.numberOfVerticalLines = Property.getValueOrUndefined(ellipse.numberOfVerticalLines, time); + var shadows = this._geometryUpdater.shadowsProperty.getValue(time); + if (Property.getValueOrDefault(ellipse.fill, time, true)) { var fillMaterialProperty = geometryUpdater.fillMaterialProperty; var material = MaterialProperty.getValue(time, fillMaterialProperty, this._material); @@ -609,14 +629,15 @@ define([ } this._primitive = groundPrimitives.add(new GroundPrimitive({ - geometryInstance : new GeometryInstance({ + geometryInstances : new GeometryInstance({ id : entity, geometry : new EllipseGeometry(options), attributes: { color: ColorGeometryInstanceAttribute.fromColor(currentColor) } }), - asynchronous : false + asynchronous : false, + shadows : shadows })); } else { var appearance = new MaterialAppearance({ @@ -632,7 +653,8 @@ define([ geometry : new EllipseGeometry(options) }), appearance : appearance, - asynchronous : false + asynchronous : false, + shadows : shadows })); } } @@ -659,7 +681,8 @@ define([ lineWidth : geometryUpdater._scene.clampLineWidth(outlineWidth) } }), - asynchronous : false + asynchronous : false, + shadows : shadows })); } }; diff --git a/Source/DataSources/EllipseGraphics.js b/Source/DataSources/EllipseGraphics.js index 10a365b2a1d4..39e64d17671d 100644 --- a/Source/DataSources/EllipseGraphics.js +++ b/Source/DataSources/EllipseGraphics.js @@ -41,6 +41,7 @@ define([ * @param {Property} [options.rotation=0.0] A numeric property specifying the rotation of the ellipse counter-clockwise from north. * @param {Property} [options.stRotation=0.0] A numeric property specifying the rotation of the ellipse texture counter-clockwise from north. * @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. * * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Circles and Ellipses.html|Cesium Sandcastle Circles and Ellipses Demo} */ @@ -73,6 +74,8 @@ define([ this._outlineWidthSubscription = undefined; this._numberOfVerticalLines = undefined; this._numberOfVerticalLinesSubscription = undefined; + this._shadows = undefined; + this._shadowsSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -200,7 +203,16 @@ define([ * @type {Property} * @default 16 */ - numberOfVerticalLines : createPropertyDescriptor('numberOfVerticalLines') + numberOfVerticalLines : createPropertyDescriptor('numberOfVerticalLines'), + + /** + * Get or sets the enum Property specifying whether the ellipse + * casts or receives shadows from each light source. + * @memberof EllipseGraphics.prototype + * @type {Property} + * @default ShadowMode.DISABLED + */ + shadows : createPropertyDescriptor('shadows') }); /** @@ -227,6 +239,7 @@ define([ result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.numberOfVerticalLines = this.numberOfVerticalLines; + result.shadows = this.shadows; return result; }; @@ -257,6 +270,7 @@ define([ this.outlineColor = defaultValue(this.outlineColor, source.outlineColor); this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth); this.numberOfVerticalLines = defaultValue(this.numberOfVerticalLines, source.numberOfVerticalLines); + this.shadows = defaultValue(this.shadows, source.shadows); }; return EllipseGraphics; diff --git a/Source/DataSources/EllipsoidGeometryUpdater.js b/Source/DataSources/EllipsoidGeometryUpdater.js index 373c3f1ed7bc..04662eb305ff 100644 --- a/Source/DataSources/EllipsoidGeometryUpdater.js +++ b/Source/DataSources/EllipsoidGeometryUpdater.js @@ -19,6 +19,7 @@ define([ '../Scene/PerInstanceColorAppearance', '../Scene/Primitive', '../Scene/SceneMode', + '../Scene/ShadowMode', './ColorMaterialProperty', './ConstantProperty', './dynamicGeometryGetBoundingSphere', @@ -44,6 +45,7 @@ define([ PerInstanceColorAppearance, Primitive, SceneMode, + ShadowMode, ColorMaterialProperty, ConstantProperty, dynamicGeometryGetBoundingSphere, @@ -56,6 +58,7 @@ define([ var defaultFill = new ConstantProperty(true); var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); + var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); var radiiScratch = new Cartesian3(); var scratchColor = new Color(); @@ -102,6 +105,7 @@ define([ this._showOutlineProperty = undefined; this._outlineColorProperty = undefined; this._outlineWidth = 1.0; + this._shadowsProperty = undefined; this._options = new GeometryOptions(entity); this._onEntityPropertyChanged(entity, 'ellipsoid', entity.ellipsoid, undefined); } @@ -229,6 +233,19 @@ define([ return this._outlineWidth; } }, + /** + * Gets the property specifying whether the geometry + * casts or receives shadows from each light source. + * @memberof EllipsoidGeometryUpdater.prototype + * + * @type {Property} + * @readonly + */ + shadowsProperty : { + get : function() { + return this._shadowsProperty; + } + }, /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -450,6 +467,8 @@ define([ this._showProperty = defaultValue(show, defaultShow); this._showOutlineProperty = defaultValue(ellipsoid.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(ellipsoid.outlineColor, defaultOutlineColor) : undefined; + this._shadowsProperty = defaultValue(ellipsoid.shadows, defaultShadows); + this._fillEnabled = fillEnabled; this._outlineEnabled = outlineEnabled; @@ -577,6 +596,9 @@ define([ var in3D = sceneMode === SceneMode.SCENE3D; var options = this._options; + + var shadows = this._geometryUpdater.shadowsProperty.getValue(time); + //We only rebuild the primitive if something other than the radii has changed //For the radii, we use unit sphere and then deform it with a scale matrix. var rebuildPrimitives = !in3D || this._lastSceneMode !== sceneMode || !defined(this._primitive) || // @@ -614,7 +636,8 @@ define([ } }), appearance : appearance, - asynchronous : false + asynchronous : false, + shadows : shadows })); options.vertexFormat = PerInstanceColorAppearance.VERTEX_FORMAT; @@ -636,7 +659,8 @@ define([ lineWidth : this._geometryUpdater._scene.clampLineWidth(outlineWidth) } }), - asynchronous : false + asynchronous : false, + shadows : shadows })); this._lastShow = showFill; diff --git a/Source/DataSources/EllipsoidGraphics.js b/Source/DataSources/EllipsoidGraphics.js index 58f03b6f0b76..efa7d92247cb 100644 --- a/Source/DataSources/EllipsoidGraphics.js +++ b/Source/DataSources/EllipsoidGraphics.js @@ -34,6 +34,7 @@ define([ * @param {Property} [options.subdivisions=128] A Property specifying the number of samples per outline ring, determining the granularity of the curvature. * @param {Property} [options.stackPartitions=64] A Property specifying the number of stacks. * @param {Property} [options.slicePartitions=64] A Property specifying the number of radial slices. + * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the ellipsoid casts or receives shadows from each light source. * * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Spheres%20and%20Ellipsoids.html|Cesium Sandcastle Spheres and Ellipsoids Demo} */ @@ -58,6 +59,7 @@ define([ this._outlineColorSubscription = undefined; this._outlineWidth = undefined; this._outlineWidthSubscription = undefined; + this._shadows = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -154,7 +156,16 @@ define([ * @type {Property} * @default 128 */ - subdivisions : createPropertyDescriptor('subdivisions') + subdivisions : createPropertyDescriptor('subdivisions'), + + /** + * Get or sets the enum Property specifying whether the ellipsoid + * casts or receives shadows from each light source. + * @memberof EllipsoidGraphics.prototype + * @type {Property} + * @default ShadowMode.DISABLED + */ + shadows : createPropertyDescriptor('shadows') }); /** @@ -177,6 +188,7 @@ define([ result.stackPartitions = this.stackPartitions; result.slicePartitions = this.slicePartitions; result.subdivisions = this.subdivisions; + result.shadows = this.shadows; return result; }; @@ -204,6 +216,7 @@ define([ this.stackPartitions = defaultValue(this.stackPartitions, source.stackPartitions); this.slicePartitions = defaultValue(this.slicePartitions, source.slicePartitions); this.subdivisions = defaultValue(this.subdivisions, source.subdivisions); + this.shadows = defaultValue(this.shadows, source.shadows); }; return EllipsoidGraphics; diff --git a/Source/DataSources/GeometryVisualizer.js b/Source/DataSources/GeometryVisualizer.js index bf17f32af4cb..df3cc9e6f5e0 100644 --- a/Source/DataSources/GeometryVisualizer.js +++ b/Source/DataSources/GeometryVisualizer.js @@ -5,6 +5,7 @@ define([ '../Core/defined', '../Core/destroyObject', '../Core/DeveloperError', + '../Scene/ShadowMode', './BoundingSphereState', './ColorMaterialProperty', './StaticGeometryColorBatch', @@ -17,6 +18,7 @@ define([ defined, destroyObject, DeveloperError, + ShadowMode, BoundingSphereState, ColorMaterialProperty, StaticGeometryColorBatch, @@ -84,8 +86,13 @@ define([ return; } + var shadows; + if (updater.outlineEnabled || updater.fillEnabled) { + shadows = updater.shadowsProperty.getValue(time); + } + if (updater.outlineEnabled) { - that._outlineBatch.add(time, updater); + that._outlineBatches[shadows].add(time, updater); } if (updater.fillEnabled) { @@ -94,15 +101,15 @@ define([ } else { if (updater.isClosed) { if (updater.fillMaterialProperty instanceof ColorMaterialProperty) { - that._closedColorBatch.add(time, updater); + that._closedColorBatches[shadows].add(time, updater); } else { - that._closedMaterialBatch.add(time, updater); + that._closedMaterialBatches[shadows].add(time, updater); } } else { if (updater.fillMaterialProperty instanceof ColorMaterialProperty) { - that._openColorBatch.add(time, updater); + that._openColorBatches[shadows].add(time, updater); } else { - that._openMaterialBatch.add(time, updater); + that._openMaterialBatches[shadows].add(time, updater); } } } @@ -143,15 +150,25 @@ define([ this._removedObjects = new AssociativeArray(); this._changedObjects = new AssociativeArray(); - this._outlineBatch = new StaticOutlineGeometryBatch(primitives, scene); - this._closedColorBatch = new StaticGeometryColorBatch(primitives, type.perInstanceColorAppearanceType, true); - this._closedMaterialBatch = new StaticGeometryPerMaterialBatch(primitives, type.materialAppearanceType, true); - this._openColorBatch = new StaticGeometryColorBatch(primitives, type.perInstanceColorAppearanceType, false); - this._openMaterialBatch = new StaticGeometryPerMaterialBatch(primitives, type.materialAppearanceType, false); + var numberOfShadowModes = ShadowMode.NUMBER_OF_SHADOW_MODES; + this._outlineBatches = new Array(numberOfShadowModes); + this._closedColorBatches = new Array(numberOfShadowModes); + this._closedMaterialBatches = new Array(numberOfShadowModes); + this._openColorBatches = new Array(numberOfShadowModes); + this._openMaterialBatches = new Array(numberOfShadowModes); + + for (var i = 0; i < numberOfShadowModes; ++i) { + this._outlineBatches[i] = new StaticOutlineGeometryBatch(primitives, scene, i); + this._closedColorBatches[i] = new StaticGeometryColorBatch(primitives, type.perInstanceColorAppearanceType, true, i); + this._closedMaterialBatches[i] = new StaticGeometryPerMaterialBatch(primitives, type.materialAppearanceType, true, i); + this._openColorBatches[i] = new StaticGeometryColorBatch(primitives, type.perInstanceColorAppearanceType, false, i); + this._openMaterialBatches[i] = new StaticGeometryPerMaterialBatch(primitives, type.materialAppearanceType, false, i); + } + this._groundColorBatch = new StaticGroundGeometryColorBatch(groundPrimitives); this._dynamicBatch = new DynamicGeometryBatch(primitives, groundPrimitives); - this._batches = [this._closedColorBatch, this._closedMaterialBatch, this._openColorBatch, this._openMaterialBatch, - this._groundColorBatch, this._dynamicBatch, this._outlineBatch]; + + this._batches = this._outlineBatches.concat(this._closedColorBatches, this._closedMaterialBatches, this._openColorBatches, this._openMaterialBatches, this._groundColorBatch, this._dynamicBatch); this._subscriptions = new AssociativeArray(); this._updaters = new AssociativeArray(); diff --git a/Source/DataSources/KmlDataSource.js b/Source/DataSources/KmlDataSource.js index 8fa6fe0187ff..88dec7dc5868 100644 --- a/Source/DataSources/KmlDataSource.js +++ b/Source/DataSources/KmlDataSource.js @@ -649,7 +649,6 @@ define([ var heading = queryNumericValue(node, 'heading', namespaces.kml); var color = queryColorValue(node, 'color', namespaces.kml); - var iconNode = queryFirstNode(node, 'Icon', namespaces.kml); var icon = getIconHref(iconNode, dataSource, sourceUri, uriResolver, false); var x = queryNumericValue(iconNode, 'x', namespaces.gx); @@ -698,19 +697,20 @@ define([ } else if (hotSpotXUnit === 'insetPixels') { xOffset = (hotSpotX - BILLBOARD_SIZE) * scale; } else if (hotSpotXUnit === 'fraction') { - xOffset = -BILLBOARD_SIZE * scale * hotSpotX; + xOffset = -hotSpotX * BILLBOARD_SIZE * scale; } xOffset += BILLBOARD_SIZE * 0.5 * scale; } if (defined(hotSpotY)) { if (hotSpotYUnit === 'pixels') { - yOffset = hotSpotY; + yOffset = hotSpotY * scale; } else if (hotSpotYUnit === 'insetPixels') { - yOffset = -hotSpotY; + yOffset = (-hotSpotY + BILLBOARD_SIZE) * scale; } else if (hotSpotYUnit === 'fraction') { - yOffset = hotSpotY * BILLBOARD_SIZE; + yOffset = hotSpotY * BILLBOARD_SIZE * scale; } + yOffset -= BILLBOARD_SIZE * 0.5 * scale; } @@ -1064,8 +1064,9 @@ define([ billboard.image = dataSource._pinBuilder.fromColor(Color.YELLOW, 64); } + var scale = 1.0; if (defined(billboard.scale)) { - var scale = billboard.scale.getValue(); + scale = billboard.scale.getValue(); if (scale !== 0) { label.pixelOffset = new Cartesian2((scale * 16) + 1, 0); } else { @@ -1150,7 +1151,7 @@ define([ entity.corridor = corridor; corridor.positions = coordinates; if (defined(polyline)) { - corridor.material = defined(polyline.material) ? polyline.material.color : Color.WHITE; + corridor.material = defined(polyline.material) ? polyline.material.color.getValue(Iso8601.MINIMUM_VALUE) : Color.WHITE; corridor.width = defaultValue(polyline.width, 1.0); } else { corridor.material = Color.WHITE; @@ -1525,8 +1526,16 @@ define([ } entity.availability = availability; + // Per KML spec "A Feature is visible only if it and all its ancestors are visible." + function ancestryIsVisible(parentEntity) { + if (!parentEntity) { + return true; + } + return parentEntity.show && ancestryIsVisible(parentEntity.parent); + } + var visibility = queryBooleanValue(featureNode, 'visibility', namespaces.kml); - entity.show = defaultValue(visibility, true); + entity.show = ancestryIsVisible(parent) && defaultValue(visibility, true); //var open = queryBooleanValue(featureNode, 'open', namespaces.kml); var authorNode = queryFirstNode(featureNode, 'author', namespaces.atom); @@ -1717,8 +1726,8 @@ define([ } } - function processUnsupported(dataSource, parent, node, entityCollection, styleCollection, sourceUri, uriResolver) { - dataSource._unsupportedNode.raiseEvent(dataSource, node, uriResolver); + function processUnsupportedFeature(dataSource, parent, node, entityCollection, styleCollection, sourceUri, uriResolver) { + dataSource._unsupportedNode.raiseEvent(dataSource, parent, node, entityCollection, styleCollection, sourceUri, uriResolver); console.log('KML - Unsupported feature: ' + node.localName); } @@ -2008,9 +2017,9 @@ define([ Placemark : processPlacemark, NetworkLink : processNetworkLink, GroundOverlay : processGroundOverlay, - PhotoOverlay : processUnsupported, - ScreenOverlay : processUnsupported, - Tour : processUnsupported + PhotoOverlay : processUnsupportedFeature, + ScreenOverlay : processUnsupportedFeature, + Tour : processUnsupportedFeature }; function processFeatureNode(dataSource, node, parent, entityCollection, styleCollection, sourceUri, uriResolver) { @@ -2018,8 +2027,7 @@ define([ if (defined(featureProcessor)) { featureProcessor(dataSource, parent, node, entityCollection, styleCollection, sourceUri, uriResolver); } else { - dataSource._unsupportedNode.raiseEvent(dataSource, node, uriResolver); - console.log('KML - Unsupported feature node: ' + node.localName); + processUnsupportedFeature(dataSource, parent, node, entityCollection, styleCollection, sourceUri, uriResolver); } } diff --git a/Source/DataSources/ModelGraphics.js b/Source/DataSources/ModelGraphics.js index fc947f4fa7e6..e0b5ceb10794 100644 --- a/Source/DataSources/ModelGraphics.js +++ b/Source/DataSources/ModelGraphics.js @@ -45,10 +45,11 @@ define([ * @param {Property} [options.minimumPixelSize=0.0] A numeric Property specifying the approximate minimum pixel size of the model regardless of zoom. * @param {Property} [options.maximumScale] The maximum scale size of a model. An upper limit for minimumPixelSize. * @param {Property} [options.incrementallyLoadTextures=true] Determine if textures may continue to stream in after the model is loaded. - * @param {Property} [options.castShadows=true] A boolean Property specifying whether the model casts shadows from each light source. - * @param {Property} [options.receiveShadows=true] A boolean Property specifying whether the model receives shadows from shadow casters in the scene. * @param {Property} [options.runAnimations=true] A boolean Property specifying if glTF animations specified in the model should be started. * @param {Property} [options.nodeTransformations] An object, where keys are names of nodes, and values are {@link TranslationRotationScale} Properties describing the transformation to apply to that node. + * @param {Property} [options.castShadows=true] Deprecated, use options.shadows instead. A boolean Property specifying whether the model casts shadows from each light source. + * @param {Property} [options.receiveShadows=true] Deprecated, use options.shadows instead. A boolean Property specifying whether the model receives shadows from shadow casters in the scene. + * @param {Property} [options.shadows=ShadowMode.ENABLED] An enum Property specifying whether the model casts or receives shadows from each light source. * @param {Property} [options.heightReference=HeightReference.NONE] A Property specifying what the height is relative to. * * @see {@link http://cesiumjs.org/2014/03/03/Cesium-3D-Models-Tutorial/|3D Models Tutorial} @@ -69,6 +70,8 @@ define([ this._castShadowsSubscription = undefined; this._receiveShadows = undefined; this._receiveShadowsSubscription = undefined; + this._shadows = undefined; + this._shadowsSubscription = undefined; this._uri = undefined; this._uriSubscription = undefined; this._runAnimations = undefined; @@ -146,6 +149,7 @@ define([ * casts shadows from each light source. * @memberof ModelGraphics.prototype * @type {Property} + * @deprecated */ castShadows : createPropertyDescriptor('castShadows'), @@ -154,9 +158,19 @@ define([ * receives shadows from shadow casters in the scene. * @memberof ModelGraphics.prototype * @type {Property} + * @deprecated */ receiveShadows : createPropertyDescriptor('receiveShadows'), + /** + * Get or sets the enum Property specifying whether the model + * casts or receives shadows from each light source. + * @memberof ModelGraphics.prototype + * @type {Property} + * @default ShadowMode.ENABLED + */ + shadows : createPropertyDescriptor('shadows'), + /** * Gets or sets the string Property specifying the URI of the glTF asset. * @memberof ModelGraphics.prototype @@ -206,6 +220,7 @@ define([ result.incrementallyLoadTextures = this.incrementallyLoadTextures; result.castShadows = this.castShadows; result.receiveShadows = this.receiveShadows; + result.shadows = this.shadows; result.uri = this.uri; result.runAnimations = this.runAnimations; result.nodeTransformations = this.nodeTransformations; @@ -234,6 +249,7 @@ define([ this.incrementallyLoadTextures = defaultValue(this.incrementallyLoadTextures, source.incrementallyLoadTextures); this.castShadows = defaultValue(this.castShadows, source.castShadows); this.receiveShadows = defaultValue(this.receiveShadows, source.receiveShadows); + this.shadows = defaultValue(this.shadows, source.shadows); this.uri = defaultValue(this.uri, source.uri); this.runAnimations = defaultValue(this.runAnimations, source.runAnimations); this.heightReference = defaultValue(this.heightReference, source.heightReference); diff --git a/Source/DataSources/ModelVisualizer.js b/Source/DataSources/ModelVisualizer.js index a84ddee5e4fd..fde2fedcb7f8 100644 --- a/Source/DataSources/ModelVisualizer.js +++ b/Source/DataSources/ModelVisualizer.js @@ -9,6 +9,7 @@ define([ '../Scene/HeightReference', '../Scene/Model', '../Scene/ModelAnimationLoop', + '../Scene/ShadowMode', './BoundingSphereState', './Property' ], function( @@ -21,6 +22,7 @@ define([ HeightReference, Model, ModelAnimationLoop, + ShadowMode, BoundingSphereState, Property) { 'use strict'; @@ -28,9 +30,8 @@ define([ var defaultScale = 1.0; var defaultMinimumPixelSize = 0.0; var defaultIncrementallyLoadTextures = true; + var defaultShadows = ShadowMode.ENABLED; var defaultHeightReference = HeightReference.NONE; - var defaultCastShadows = true; - var defaultReceiveShadows = true; var modelMatrixScratch = new Matrix4(); var nodeMatrixScratch = new Matrix4(); @@ -130,13 +131,21 @@ define([ modelHash[entity.id] = modelData; } + var shadows = defaultShadows; + if (defined(modelGraphics._shadows)) { + shadows = Property.getValueOrDefault(modelGraphics._shadows, time, defaultShadows); + } else if (defined(modelGraphics._castShadows) || defined(modelGraphics._receiveShadows)) { + var castShadows = Property.getValueOrDefault(modelGraphics._castShadows, time, true); + var receiveShadows = Property.getValueOrDefault(modelGraphics.receiveShadows, time, true); + shadows = ShadowMode.fromCastReceive(castShadows, receiveShadows); + } + model.show = true; model.scale = Property.getValueOrDefault(modelGraphics._scale, time, defaultScale); model.minimumPixelSize = Property.getValueOrDefault(modelGraphics._minimumPixelSize, time, defaultMinimumPixelSize); model.maximumScale = Property.getValueOrUndefined(modelGraphics._maximumScale, time); - model.castShadows = Property.getValueOrDefault(modelGraphics._castShadows, time, defaultCastShadows); - model.receiveShadows = Property.getValueOrDefault(modelGraphics._receiveShadows, time, defaultReceiveShadows); model.modelMatrix = Matrix4.clone(modelMatrix, model.modelMatrix); + model.shadows = shadows; model.heightReference = Property.getValueOrDefault(modelGraphics._heightReference, time, defaultHeightReference); if (model.ready) { diff --git a/Source/DataSources/PolygonGeometryUpdater.js b/Source/DataSources/PolygonGeometryUpdater.js index 0d88fef25369..6c2aafd06577 100644 --- a/Source/DataSources/PolygonGeometryUpdater.js +++ b/Source/DataSources/PolygonGeometryUpdater.js @@ -20,6 +20,7 @@ define([ '../Scene/MaterialAppearance', '../Scene/PerInstanceColorAppearance', '../Scene/Primitive', + '../Scene/ShadowMode', './ColorMaterialProperty', './ConstantProperty', './dynamicGeometryGetBoundingSphere', @@ -46,6 +47,7 @@ define([ MaterialAppearance, PerInstanceColorAppearance, Primitive, + ShadowMode, ColorMaterialProperty, ConstantProperty, dynamicGeometryGetBoundingSphere, @@ -58,6 +60,7 @@ define([ var defaultFill = new ConstantProperty(true); var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); + var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); var scratchColor = new Color(); function GeometryOptions(entity) { @@ -106,6 +109,7 @@ define([ this._showOutlineProperty = undefined; this._outlineColorProperty = undefined; this._outlineWidth = 1.0; + this._shadowsProperty = undefined; this._onTerrain = false; this._options = new GeometryOptions(entity); this._onEntityPropertyChanged(entity, 'polygon', entity.polygon, undefined); @@ -234,6 +238,19 @@ define([ return this._outlineWidth; } }, + /** + * Gets the property specifying whether the geometry + * casts or receives shadows from each light source. + * @memberof PolygonGeometryUpdater.prototype + * + * @type {Property} + * @readonly + */ + shadowsProperty : { + get : function() { + return this._shadowsProperty; + } + }, /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -468,6 +485,7 @@ define([ this._showProperty = defaultValue(show, defaultShow); this._showOutlineProperty = defaultValue(polygon.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(polygon.outlineColor, defaultOutlineColor) : undefined; + this._shadowsProperty = defaultValue(polygon.shadows, defaultShadows); var height = polygon.height; var extrudedHeight = polygon.extrudedHeight; @@ -618,6 +636,8 @@ define([ options.closeTop = closeTopValue; options.closeBottom = closeBottomValue; + var shadows = this._geometryUpdater.shadowsProperty.getValue(time); + if (Property.getValueOrDefault(polygon.fill, time, true)) { var fillMaterialProperty = geometryUpdater.fillMaterialProperty; var material = MaterialProperty.getValue(time, fillMaterialProperty, this._material); @@ -630,14 +650,15 @@ define([ } this._primitive = groundPrimitives.add(new GroundPrimitive({ - geometryInstance : new GeometryInstance({ + geometryInstances : new GeometryInstance({ id : entity, geometry : new PolygonGeometry(options), attributes: { color: ColorGeometryInstanceAttribute.fromColor(currentColor) } }), - asynchronous : false + asynchronous : false, + shadows : shadows })); } else { var appearance = new MaterialAppearance({ @@ -653,7 +674,8 @@ define([ geometry : new PolygonGeometry(options) }), appearance : appearance, - asynchronous : false + asynchronous : false, + shadows : shadows })); } } @@ -680,7 +702,8 @@ define([ lineWidth : geometryUpdater._scene.clampLineWidth(outlineWidth) } }), - asynchronous : false + asynchronous : false, + shadows : shadows })); } }; diff --git a/Source/DataSources/PolygonGraphics.js b/Source/DataSources/PolygonGraphics.js index 4676b1905973..cdd0b39f6bfa 100644 --- a/Source/DataSources/PolygonGraphics.js +++ b/Source/DataSources/PolygonGraphics.js @@ -40,6 +40,7 @@ define([ * @param {Property} [options.perPositionHeight=false] A boolean specifying whether or not the the height of each position is used. * @param {Boolean} [options.closeTop=true] When false, leaves off the top of an extruded polygon open. * @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. * * @see Entity * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Polygon.html|Cesium Sandcastle Polygon Demo} @@ -74,6 +75,8 @@ define([ this._closeTopSubscription = undefined; this._closeBottom = undefined; this._closeBottomSubscription = undefined; + this._shadows = undefined; + this._shadowsSubscription = undefined; this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); } @@ -201,7 +204,16 @@ define([ * @memberof PolygonGraphics.prototype * @type {Property} */ - closeBottom : createPropertyDescriptor('closeBottom') + closeBottom : createPropertyDescriptor('closeBottom'), + + /** + * Get or sets the enum Property specifying whether the polygon + * casts or receives shadows from each light source. + * @memberof PolygonGraphics.prototype + * @type {Property} + * @default ShadowMode.DISABLED + */ + shadows : createPropertyDescriptor('shadows') }); /** @@ -228,6 +240,7 @@ define([ result.perPositionHeight = this.perPositionHeight; result.closeTop = this.closeTop; result.closeBottom = this.closeBottom; + result.shadows = this.shadows; return result; }; @@ -258,6 +271,7 @@ define([ this.perPositionHeight = defaultValue(this.perPositionHeight, source.perPositionHeight); this.closeTop = defaultValue(this.closeTop, source.closeTop); this.closeBottom = defaultValue(this.closeBottom, source.closeBottom); + this.shadows = defaultValue(this.shadows, source.shadows); }; return PolygonGraphics; diff --git a/Source/DataSources/PolylineGeometryUpdater.js b/Source/DataSources/PolylineGeometryUpdater.js index 0f6e1c499912..174248e04ba7 100644 --- a/Source/DataSources/PolylineGeometryUpdater.js +++ b/Source/DataSources/PolylineGeometryUpdater.js @@ -18,6 +18,7 @@ define([ '../Scene/PolylineCollection', '../Scene/PolylineColorAppearance', '../Scene/PolylineMaterialAppearance', + '../Scene/ShadowMode', './BoundingSphereState', './ColorMaterialProperty', './ConstantProperty', @@ -42,6 +43,7 @@ define([ PolylineCollection, PolylineColorAppearance, PolylineMaterialAppearance, + ShadowMode, BoundingSphereState, ColorMaterialProperty, ConstantProperty, @@ -54,6 +56,7 @@ define([ var defaultMaterial = new ColorMaterialProperty(Color.WHITE); var defaultShow = new ConstantProperty(true); + var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); function GeometryOptions(entity) { this.id = entity; @@ -91,6 +94,7 @@ define([ this._geometryChanged = new Event(); this._showProperty = undefined; this._materialProperty = undefined; + this._shadowsProperty = undefined; this._options = new GeometryOptions(entity); this._onEntityPropertyChanged(entity, 'polyline', entity.polyline, undefined); } @@ -193,6 +197,19 @@ define([ outlineColorProperty : { value : undefined }, + /** + * Gets the property specifying whether the geometry + * casts or receives shadows from each light source. + * @memberof PolylineGeometryUpdater.prototype + * + * @type {Property} + * @readonly + */ + shadowsProperty : { + get : function() { + return this._shadowsProperty; + } + }, /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -366,6 +383,7 @@ define([ var isColorMaterial = material instanceof ColorMaterialProperty; this._materialProperty = material; this._showProperty = defaultValue(show, defaultShow); + this._shadowsProperty = defaultValue(polyline.shadows, defaultShadows); this._fillEnabled = true; var width = polyline.width; diff --git a/Source/DataSources/PolylineGraphics.js b/Source/DataSources/PolylineGraphics.js index a4bc4922ea7b..c1416aed104f 100644 --- a/Source/DataSources/PolylineGraphics.js +++ b/Source/DataSources/PolylineGraphics.js @@ -32,6 +32,7 @@ define([ * @param {Property} [options.show=true] A boolean Property specifying the visibility of the polyline. * @param {MaterialProperty} [options.material=Color.WHITE] A Property specifying the material used to draw the polyline. * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between each latitude and longitude if followSurface is true. + * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the polyline casts or receives shadows from each light source. * * @see Entity * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Polyline.html|Cesium Sandcastle Polyline Demo} @@ -50,6 +51,8 @@ define([ this._widthSubscription = undefined; this._width = undefined; this._widthSubscription = undefined; + this._shadows = undefined; + this._shadowsSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -116,7 +119,16 @@ define([ * @type {Property} * @default Cesium.Math.RADIANS_PER_DEGREE */ - granularity : createPropertyDescriptor('granularity') + granularity : createPropertyDescriptor('granularity'), + + /** + * Get or sets the enum Property specifying whether the polyline + * casts or receives shadows from each light source. + * @memberof PolylineGraphics.prototype + * @type {Property} + * @default ShadowMode.DISABLED + */ + shadows : createPropertyDescriptor('shadows') }); /** @@ -135,6 +147,7 @@ define([ result.width = this.width; result.followSurface = this.followSurface; result.granularity = this.granularity; + result.shadows = this.shadows; return result; }; @@ -157,6 +170,7 @@ define([ this.width = defaultValue(this.width, source.width); this.followSurface = defaultValue(this.followSurface, source.followSurface); this.granularity = defaultValue(this.granularity, source.granularity); + this.shadows = defaultValue(this.shadows, source.shadows); }; return PolylineGraphics; diff --git a/Source/DataSources/PolylineVolumeGeometryUpdater.js b/Source/DataSources/PolylineVolumeGeometryUpdater.js index 525b036f53a8..9252f9374c6f 100644 --- a/Source/DataSources/PolylineVolumeGeometryUpdater.js +++ b/Source/DataSources/PolylineVolumeGeometryUpdater.js @@ -16,6 +16,7 @@ define([ '../Scene/MaterialAppearance', '../Scene/PerInstanceColorAppearance', '../Scene/Primitive', + '../Scene/ShadowMode', './ColorMaterialProperty', './ConstantProperty', './dynamicGeometryGetBoundingSphere', @@ -38,6 +39,7 @@ define([ MaterialAppearance, PerInstanceColorAppearance, Primitive, + ShadowMode, ColorMaterialProperty, ConstantProperty, dynamicGeometryGetBoundingSphere, @@ -50,6 +52,7 @@ define([ var defaultFill = new ConstantProperty(true); var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); + var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); var scratchColor = new Color(); function GeometryOptions(entity) { @@ -93,6 +96,7 @@ define([ this._showOutlineProperty = undefined; this._outlineColorProperty = undefined; this._outlineWidth = 1.0; + this._shadowsProperty = undefined; this._options = new GeometryOptions(entity); this._onEntityPropertyChanged(entity, 'polylineVolume', entity.polylineVolume, undefined); } @@ -220,6 +224,19 @@ define([ return this._outlineWidth; } }, + /** + * Gets the property specifying whether the geometry + * casts or receives shadows from each light source. + * @memberof PolylineVolumeGeometryUpdater.prototype + * + * @type {Property} + * @readonly + */ + shadowsProperty : { + get : function() { + return this._shadowsProperty; + } + }, /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -437,6 +454,7 @@ define([ this._showProperty = defaultValue(show, defaultShow); this._showOutlineProperty = defaultValue(polylineVolume.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(polylineVolume.outlineColor, defaultOutlineColor) : undefined; + this._shadowsProperty = defaultValue(polylineVolume.shadows, defaultShadows); var granularity = polylineVolume.granularity; var outlineWidth = polylineVolume.outlineWidth; @@ -531,6 +549,8 @@ define([ options.granularity = Property.getValueOrUndefined(polylineVolume.granularity, time); options.cornerType = Property.getValueOrUndefined(polylineVolume.cornerType, time); + var shadows = this._geometryUpdater.shadowsProperty.getValue(time); + if (!defined(polylineVolume.fill) || polylineVolume.fill.getValue(time)) { var material = MaterialProperty.getValue(time, geometryUpdater.fillMaterialProperty, this._material); this._material = material; @@ -548,7 +568,8 @@ define([ geometry : new PolylineVolumeGeometry(options) }), appearance : appearance, - asynchronous : false + asynchronous : false, + shadows : shadows })); } @@ -574,7 +595,8 @@ define([ lineWidth : geometryUpdater._scene.clampLineWidth(outlineWidth) } }), - asynchronous : false + asynchronous : false, + shadows : shadows })); } }; diff --git a/Source/DataSources/PolylineVolumeGraphics.js b/Source/DataSources/PolylineVolumeGraphics.js index acf3be4bc9a5..824a97a9b7ea 100644 --- a/Source/DataSources/PolylineVolumeGraphics.js +++ b/Source/DataSources/PolylineVolumeGraphics.js @@ -35,6 +35,7 @@ define([ * @param {Property} [options.outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline. * @param {Property} [options.outlineWidth=1.0] A numeric Property specifying the width of the outline. * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between each latitude and longitude point. + * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the volume casts or receives shadows from each light source. * * @see Entity * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Polyline%20Volume.html|Cesium Sandcastle Polyline Volume Demo} @@ -60,6 +61,8 @@ define([ this._outlineColorSubscription = undefined; this._outlineWidth = undefined; this._outlineWidthSubscription = undefined; + this._shadows = undefined; + this._shadowsSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -155,7 +158,16 @@ define([ * @type {Property} * @default CornerType.ROUNDED */ - cornerType : createPropertyDescriptor('cornerType') + cornerType : createPropertyDescriptor('cornerType'), + + /** + * Get or sets the enum Property specifying whether the volume + * casts or receives shadows from each light source. + * @memberof PolylineVolumeGraphics.prototype + * @type {Property} + * @default ShadowMode.DISABLED + */ + shadows : createPropertyDescriptor('shadows') }); /** @@ -178,6 +190,7 @@ define([ result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.cornerType = this.cornerType; + result.shadows = this.shadows; return result; }; @@ -204,6 +217,7 @@ define([ this.outlineColor = defaultValue(this.outlineColor, source.outlineColor); this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth); this.cornerType = defaultValue(this.cornerType, source.cornerType); + this.shadows = defaultValue(this.shadows, source.shadows); }; return PolylineVolumeGraphics; diff --git a/Source/DataSources/RectangleGeometryUpdater.js b/Source/DataSources/RectangleGeometryUpdater.js index 9a997f42c8c7..27a25798c18c 100644 --- a/Source/DataSources/RectangleGeometryUpdater.js +++ b/Source/DataSources/RectangleGeometryUpdater.js @@ -18,6 +18,7 @@ define([ '../Scene/MaterialAppearance', '../Scene/PerInstanceColorAppearance', '../Scene/Primitive', + '../Scene/ShadowMode', './ColorMaterialProperty', './ConstantProperty', './dynamicGeometryGetBoundingSphere', @@ -42,6 +43,7 @@ define([ MaterialAppearance, PerInstanceColorAppearance, Primitive, + ShadowMode, ColorMaterialProperty, ConstantProperty, dynamicGeometryGetBoundingSphere, @@ -54,6 +56,7 @@ define([ var defaultFill = new ConstantProperty(true); var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); + var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); var scratchColor = new Color(); function GeometryOptions(entity) { @@ -102,6 +105,7 @@ define([ this._showOutlineProperty = undefined; this._outlineColorProperty = undefined; this._outlineWidth = 1.0; + this._shadowsProperty = undefined; this._onTerrain = false; this._options = new GeometryOptions(entity); @@ -231,6 +235,19 @@ define([ return this._outlineWidth; } }, + /** + * Gets the property specifying whether the geometry + * casts or receives shadows from each light source. + * @memberof RectangleGeometryUpdater.prototype + * + * @type {Property} + * @readonly + */ + shadowsProperty : { + get : function() { + return this._shadowsProperty; + } + }, /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -462,6 +479,7 @@ define([ this._showProperty = defaultValue(show, defaultShow); this._showOutlineProperty = defaultValue(rectangle.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(rectangle.outlineColor, defaultOutlineColor) : undefined; + this._shadowsProperty = defaultValue(rectangle.shadows, defaultShadows); var height = rectangle.height; var extrudedHeight = rectangle.extrudedHeight; @@ -590,6 +608,8 @@ define([ options.closeBottom = Property.getValueOrUndefined(rectangle.closeBottom, time); options.closeTop = Property.getValueOrUndefined(rectangle.closeTop, time); + var shadows = this._geometryUpdater.shadowsProperty.getValue(time); + if (Property.getValueOrDefault(rectangle.fill, time, true)) { var fillMaterialProperty = geometryUpdater.fillMaterialProperty; var material = MaterialProperty.getValue(time, fillMaterialProperty, this._material); @@ -602,14 +622,15 @@ define([ } this._primitive = groundPrimitives.add(new GroundPrimitive({ - geometryInstance : new GeometryInstance({ + geometryInstances : new GeometryInstance({ id : entity, geometry : new RectangleGeometry(options), attributes: { color: ColorGeometryInstanceAttribute.fromColor(currentColor) } }), - asynchronous : false + asynchronous : false, + shadows : shadows })); } else { var appearance = new MaterialAppearance({ @@ -626,10 +647,10 @@ define([ geometry : new RectangleGeometry(options) }), appearance : appearance, - asynchronous : false + asynchronous : false, + shadows : shadows })); } - } if (!onTerrain && Property.getValueOrDefault(rectangle.outline, time, false)) { @@ -654,7 +675,8 @@ define([ lineWidth : geometryUpdater._scene.clampLineWidth(outlineWidth) } }), - asynchronous : false + asynchronous : false, + shadows : shadows })); } }; diff --git a/Source/DataSources/RectangleGraphics.js b/Source/DataSources/RectangleGraphics.js index 124bd9da6f38..f0e22a2029e4 100644 --- a/Source/DataSources/RectangleGraphics.js +++ b/Source/DataSources/RectangleGraphics.js @@ -40,6 +40,7 @@ define([ * @param {Property} [options.rotation=0.0] A numeric property specifying the rotation of the rectangle clockwise from north. * @param {Property} [options.stRotation=0.0] A numeric property specifying the rotation of the rectangle texture counter-clockwise from north. * @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. * * @see Entity * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Rectangle.html|Cesium Sandcastle Rectangle Demo} @@ -73,6 +74,8 @@ define([ this._outlineColorSubscription = undefined; this._outlineWidth = undefined; this._outlineWidthSubscription = undefined; + this._shadows = undefined; + this._shadowsSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -201,7 +204,16 @@ define([ * @type {Property} * @default true */ - closeBottom : createPropertyDescriptor('closeBottom') + closeBottom : createPropertyDescriptor('closeBottom'), + + /** + * Get or sets the enum Property specifying whether the rectangle + * casts or receives shadows from each light source. + * @memberof RectangleGraphics.prototype + * @type {Property} + * @default ShadowMode.DISABLED + */ + shadows : createPropertyDescriptor('shadows') }); /** @@ -228,6 +240,7 @@ define([ result.outlineWidth = this.outlineWidth; result.closeTop = this.closeTop; result.closeBottom = this.closeBottom; + result.shadows = this.shadows; return result; }; @@ -258,6 +271,7 @@ define([ this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth); this.closeTop = defaultValue(this.closeTop, source.closeTop); this.closeBottom = defaultValue(this.closeBottom, source.closeBottom); + this.shadows = defaultValue(this.shadows, source.shadows); }; return RectangleGraphics; diff --git a/Source/DataSources/StaticGeometryColorBatch.js b/Source/DataSources/StaticGeometryColorBatch.js index ea56d93ad7d1..e4ce395124b3 100644 --- a/Source/DataSources/StaticGeometryColorBatch.js +++ b/Source/DataSources/StaticGeometryColorBatch.js @@ -19,10 +19,11 @@ define([ var colorScratch = new Color(); - function Batch(primitives, translucent, appearanceType, closed) { + function Batch(primitives, translucent, appearanceType, closed, shadows) { this.translucent = translucent; this.appearanceType = appearanceType; this.closed = closed; + this.shadows = shadows; this.primitives = primitives; this.createPrimitive = false; this.waitingOnCreate = false; @@ -108,7 +109,8 @@ define([ appearance : new this.appearanceType({ translucent : this.translucent, closed : this.closed - }) + }), + shadows : this.shadows }); primitives.add(primitive); isUpdated = false; @@ -235,9 +237,9 @@ define([ /** * @private */ - function StaticGeometryColorBatch(primitives, appearanceType, closed) { - this._solidBatch = new Batch(primitives, false, appearanceType, closed); - this._translucentBatch = new Batch(primitives, true, appearanceType, closed); + function StaticGeometryColorBatch(primitives, appearanceType, closed, shadows) { + this._solidBatch = new Batch(primitives, false, appearanceType, closed, shadows); + this._translucentBatch = new Batch(primitives, true, appearanceType, closed, shadows); } StaticGeometryColorBatch.prototype.add = function(time, updater) { diff --git a/Source/DataSources/StaticGeometryPerMaterialBatch.js b/Source/DataSources/StaticGeometryPerMaterialBatch.js index 817ae04c1421..95d06ab7e421 100644 --- a/Source/DataSources/StaticGeometryPerMaterialBatch.js +++ b/Source/DataSources/StaticGeometryPerMaterialBatch.js @@ -15,11 +15,12 @@ define([ MaterialProperty) { 'use strict'; - function Batch(primitives, appearanceType, materialProperty, closed) { + function Batch(primitives, appearanceType, materialProperty, closed, shadows) { this.primitives = primitives; this.appearanceType = appearanceType; this.materialProperty = materialProperty; this.closed = closed; + this.shadows = shadows; this.updaters = new AssociativeArray(); this.createPrimitive = true; this.primitive = undefined; @@ -122,7 +123,8 @@ define([ material : this.material, translucent : this.material.isTranslucent(), closed : this.closed - }) + }), + shadows : this.shadows }); primitives.add(primitive); @@ -211,7 +213,7 @@ define([ return BoundingSphereState.PENDING; } var attributes = primitive.getGeometryInstanceAttributes(entity); - if (!defined(attributes) || !defined(attributes.boundingSphere) ||// + if (!defined(attributes) || !defined(attributes.boundingSphere) || (defined(attributes.show) && attributes.show[0] === 0)) { return BoundingSphereState.FAILED; } @@ -235,11 +237,12 @@ define([ /** * @private */ - function StaticGeometryPerMaterialBatch(primitives, appearanceType, closed) { + function StaticGeometryPerMaterialBatch(primitives, appearanceType, closed, shadows) { this._items = []; this._primitives = primitives; this._appearanceType = appearanceType; this._closed = closed; + this._shadows = shadows; } StaticGeometryPerMaterialBatch.prototype.add = function(time, updater) { var items = this._items; @@ -251,7 +254,7 @@ define([ return; } } - var batch = new Batch(this._primitives, this._appearanceType, updater.fillMaterialProperty, this._closed); + var batch = new Batch(this._primitives, this._appearanceType, updater.fillMaterialProperty, this._closed, this._shadows); batch.add(time, updater); items.push(batch); }; diff --git a/Source/DataSources/StaticOutlineGeometryBatch.js b/Source/DataSources/StaticOutlineGeometryBatch.js index fbeff43dff86..8266ad021f7a 100644 --- a/Source/DataSources/StaticOutlineGeometryBatch.js +++ b/Source/DataSources/StaticOutlineGeometryBatch.js @@ -19,8 +19,10 @@ define([ BoundingSphereState) { 'use strict'; - function Batch(primitives, translucent, width) { + function Batch(primitives, translucent, width, shadows) { this.translucent = translucent; + this.width = width; + this.shadows = shadows; this.primitives = primitives; this.createPrimitive = false; this.waitingOnCreate = false; @@ -31,7 +33,6 @@ define([ this.updatersWithAttributes = new AssociativeArray(); this.attributes = new AssociativeArray(); this.itemsToRemove = []; - this.width = width; this.subscriptions = new AssociativeArray(); this.showsUpdated = new AssociativeArray(); } @@ -110,7 +111,8 @@ define([ renderState : { lineWidth : this.width } - }) + }), + shadows : this.shadows }); primitives.add(primitive); @@ -240,9 +242,10 @@ define([ /** * @private */ - function StaticOutlineGeometryBatch(primitives, scene) { + function StaticOutlineGeometryBatch(primitives, scene, shadows) { this._primitives = primitives; this._scene = scene; + this._shadows = shadows; this._solidBatches = new AssociativeArray(); this._translucentBatches = new AssociativeArray(); } @@ -255,7 +258,7 @@ define([ batches = this._solidBatches; batch = batches.get(width); if (!defined(batch)) { - batch = new Batch(this._primitives, false, width); + batch = new Batch(this._primitives, false, width, this._shadows); batches.set(width, batch); } batch.add(updater, instance); @@ -263,7 +266,7 @@ define([ batches = this._translucentBatches; batch = batches.get(width); if (!defined(batch)) { - batch = new Batch(this._primitives, true, width); + batch = new Batch(this._primitives, true, width, this._shadows); batches.set(width, batch); } batch.add(updater, instance); diff --git a/Source/DataSources/WallGeometryUpdater.js b/Source/DataSources/WallGeometryUpdater.js index e1dbb2eff1d0..27cd6ed42d6b 100644 --- a/Source/DataSources/WallGeometryUpdater.js +++ b/Source/DataSources/WallGeometryUpdater.js @@ -16,6 +16,7 @@ define([ '../Scene/MaterialAppearance', '../Scene/PerInstanceColorAppearance', '../Scene/Primitive', + '../Scene/ShadowMode', './ColorMaterialProperty', './ConstantProperty', './dynamicGeometryGetBoundingSphere', @@ -38,6 +39,7 @@ define([ MaterialAppearance, PerInstanceColorAppearance, Primitive, + ShadowMode, ColorMaterialProperty, ConstantProperty, dynamicGeometryGetBoundingSphere, @@ -50,6 +52,7 @@ define([ var defaultFill = new ConstantProperty(true); var defaultOutline = new ConstantProperty(false); var defaultOutlineColor = new ConstantProperty(Color.BLACK); + var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); var scratchColor = new Color(); function GeometryOptions(entity) { @@ -93,6 +96,7 @@ define([ this._showOutlineProperty = undefined; this._outlineColorProperty = undefined; this._outlineWidth = 1.0; + this._shadowsProperty = undefined; this._options = new GeometryOptions(entity); this._onEntityPropertyChanged(entity, 'wall', entity.wall, undefined); } @@ -220,6 +224,19 @@ define([ return this._outlineWidth; } }, + /** + * Gets the property specifying whether the geometry + * casts or receives shadows from each light source. + * @memberof WallGeometryUpdater.prototype + * + * @type {Property} + * @readonly + */ + shadowsProperty : { + get : function() { + return this._shadowsProperty; + } + }, /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -439,6 +456,7 @@ define([ this._showProperty = defaultValue(show, defaultShow); this._showOutlineProperty = defaultValue(wall.outline, defaultOutline); this._outlineColorProperty = outlineEnabled ? defaultValue(wall.outlineColor, defaultOutlineColor) : undefined; + this._shadowsProperty = defaultValue(wall.shadows, defaultShadows); var minimumHeights = wall.minimumHeights; var maximumHeights = wall.maximumHeights; @@ -533,6 +551,8 @@ define([ options.maximumHeights = Property.getValueOrUndefined(wall.maximumHeights, time, options.maximumHeights); options.granularity = Property.getValueOrUndefined(wall.granularity, time); + var shadows = this._geometryUpdater.shadowsProperty.getValue(time); + if (Property.getValueOrDefault(wall.fill, time, true)) { var material = MaterialProperty.getValue(time, geometryUpdater.fillMaterialProperty, this._material); this._material = material; @@ -550,7 +570,8 @@ define([ geometry : new WallGeometry(options) }), appearance : appearance, - asynchronous : false + asynchronous : false, + shadows : shadows })); } @@ -576,7 +597,8 @@ define([ lineWidth : geometryUpdater._scene.clampLineWidth(outlineWidth) } }), - asynchronous : false + asynchronous : false, + shadows : shadows })); } }; diff --git a/Source/DataSources/WallGraphics.js b/Source/DataSources/WallGraphics.js index 3bac99635c44..f0a8e25f89b3 100644 --- a/Source/DataSources/WallGraphics.js +++ b/Source/DataSources/WallGraphics.js @@ -35,6 +35,7 @@ define([ * @param {Property} [options.outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline. * @param {Property} [options.outlineWidth=1.0] A numeric Property specifying the width of the outline. * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between each latitude and longitude point. + * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the wall casts or receives shadows from each light source. * * @see Entity * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Wall.html|Cesium Sandcastle Wall Demo} @@ -60,6 +61,8 @@ define([ this._outlineColorSubscription = undefined; this._outlineWidth = undefined; this._outlineWidthSubscription = undefined; + this._shadows = undefined; + this._shadowsSubscription = undefined; this._definitionChanged = new Event(); this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); @@ -156,7 +159,16 @@ define([ * @type {Property} * @default 1.0 */ - outlineWidth : createPropertyDescriptor('outlineWidth') + outlineWidth : createPropertyDescriptor('outlineWidth'), + + /** + * Get or sets the enum Property specifying whether the wall + * casts or receives shadows from each light source. + * @memberof WallGraphics.prototype + * @type {Property} + * @default ShadowMode.DISABLED + */ + shadows : createPropertyDescriptor('shadows') }); /** @@ -179,6 +191,7 @@ define([ result.outline = this.outline; result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; + result.shadows = this.shadows; return result; }; @@ -205,6 +218,7 @@ define([ this.outline = defaultValue(this.outline, source.outline); this.outlineColor = defaultValue(this.outlineColor, source.outlineColor); this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth); + this.shadows = defaultValue(this.shadows, source.shadows); }; return WallGraphics; diff --git a/Source/Renderer/UniformState.js b/Source/Renderer/UniformState.js index 0e138fbec12a..49ddc5cd50dd 100644 --- a/Source/Renderer/UniformState.js +++ b/Source/Renderer/UniformState.js @@ -261,7 +261,7 @@ define([ * @memberof UniformState.prototype * @private */ - inverseTranposeModel : { + inverseTransposeModel : { get : function() { var m = this._inverseTransposeModel; if (this._inverseTransposeModelDirty) { diff --git a/Source/Scene/BillboardCollection.js b/Source/Scene/BillboardCollection.js index 3e101a01a023..f31b0cde817e 100644 --- a/Source/Scene/BillboardCollection.js +++ b/Source/Scene/BillboardCollection.js @@ -789,8 +789,7 @@ define([ billboardCollection._maxPixelOffset = Math.max(billboardCollection._maxPixelOffset, Math.abs(pixelOffsetX + translateX), Math.abs(-pixelOffsetY + translateY)); var horizontalOrigin = billboard.horizontalOrigin; - var heightReference = billboard._heightReference; - var verticalOrigin = (heightReference === HeightReference.NONE) ? billboard._verticalOrigin : VerticalOrigin.BOTTOM; + var verticalOrigin = billboard._verticalOrigin; var show = billboard.show; // If the color alpha is zero, do not show this billboard. This lets us avoid providing diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index b4b8c6361dae..965e29b1417c 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -227,6 +227,7 @@ define([ this._projection = projection; this._maxCoord = projection.project(new Cartographic(Math.PI, CesiumMath.PI_OVER_TWO)); this._max2Dfrustum = undefined; + this._suspendTerrainAdjustment = false; // set default view rectangleCameraPosition3D(this, Camera.DEFAULT_VIEW_RECTANGLE, this.position, true); @@ -346,6 +347,76 @@ define([ } }; + var scratchAdjustHeightTransform = new Matrix4(); + var scratchAdjustHeightCartographic = new Cartographic(); + + Camera.prototype._adjustHeightForTerrain = function() { + var scene = this._scene; + + var screenSpaceCameraController = scene.screenSpaceCameraController; + var enableCollisionDetection = screenSpaceCameraController.enableCollisionDetection; + var minimumCollisionTerrainHeight = screenSpaceCameraController.minimumCollisionTerrainHeight; + var minimumZoomDistance = screenSpaceCameraController.minimumZoomDistance; + + if (this._suspendTerrainAdjustment || !enableCollisionDetection) { + return; + } + + var mode = this._mode; + var globe = scene.globe; + + if (!defined(globe) || mode === SceneMode.SCENE2D || mode === SceneMode.MORPHING) { + return; + } + + var ellipsoid = globe.ellipsoid; + var projection = scene.mapProjection; + + var transform; + var mag; + if (!Matrix4.equals(this.transform, Matrix4.IDENTITY)) { + transform = Matrix4.clone(this.transform, scratchAdjustHeightTransform); + mag = Cartesian3.magnitude(this.position); + this._setTransform(Matrix4.IDENTITY); + } + + var cartographic = scratchAdjustHeightCartographic; + if (mode === SceneMode.SCENE3D) { + ellipsoid.cartesianToCartographic(this.position, cartographic); + } else { + projection.unproject(this.position, cartographic); + } + + var heightUpdated = false; + if (cartographic.height < minimumCollisionTerrainHeight) { + var height = globe.getHeight(cartographic); + if (defined(height)) { + height += minimumZoomDistance; + if (cartographic.height < height) { + cartographic.height = height; + if (mode === SceneMode.SCENE3D) { + ellipsoid.cartographicToCartesian(cartographic, this.position); + } else { + projection.project(cartographic, this.position); + } + heightUpdated = true; + } + } + } + + if (defined(transform)) { + this._setTransform(transform); + if (heightUpdated) { + Cartesian3.normalize(this.position, this.position); + Cartesian3.negate(this.position, this.direction); + Cartesian3.multiplyByScalar(this.position, Math.max(mag, minimumZoomDistance), this.position); + Cartesian3.normalize(this.direction, this.direction); + Cartesian3.cross(this.direction, this.up, this.right); + Cartesian3.cross(this.right, this.direction, this.up); + } + } + }; + function convertTransformForColumbusView(camera) { Transforms.basisTo2D(camera._projection, camera._transform, camera._actualTransform); } @@ -862,6 +933,13 @@ define([ if (this._mode === SceneMode.SCENE2D) { clampMove2D(this, this.position); } + + var globe = this._scene.globe; + var globeFinishedUpdating = !defined(globe) || (globe._surface.tileProvider.ready && !defined(globe._surface._tileLoadQueue.head) && globe._surface._debug.tilesWaitingForChildren === 0); + if (this._suspendTerrainAdjustment) { + this._suspendTerrainAdjustment = !globeFinishedUpdating; + } + this._adjustHeightForTerrain(); }; var setTransformPosition = new Cartesian3(); @@ -1090,6 +1168,8 @@ define([ var pitch = defaultValue(orientation.pitch, -CesiumMath.PI_OVER_TWO); var roll = defaultValue(orientation.roll, 0.0); + this._suspendTerrainAdjustment = true; + if (mode === SceneMode.SCENE3D) { setView3D(this, destination, heading, pitch, roll); } else if (mode === SceneMode.SCENE2D) { @@ -2458,7 +2538,6 @@ define([ }; var scratchFlyToDestination = new Cartesian3(); - var scratchFlyToCarto = new Cartographic(); var newOptions = { destination : undefined, heading : undefined, @@ -2472,6 +2551,17 @@ define([ easingFunction : undefined }; + /** + * Cancels the current camera flight if one is in progress. + * The camera is left at it's current location. + */ + Camera.prototype.cancelFlight = function () { + if (defined(this._currentFlight)) { + this._currentFlight.cancelTween(); + this._currentFlight = undefined; + } + }; + /** * Flies the camera from its current position to a new position. * @@ -2533,6 +2623,8 @@ define([ return; } + this.cancelFlight(); + var orientation = defaultValue(options.orientation, defaultValue.EMPTY_OBJECT); if (defined(orientation.direction)) { orientation = directionUpToHeadingPitchRoll(this, destination, orientation, scratchSetViewOptions.orientation); @@ -2558,45 +2650,22 @@ define([ destination = this.getRectangleCameraCoordinates(destination, scratchFlyToDestination); } - var sscc = this._scene.screenSpaceCameraController; - - if (defined(sscc) || mode === SceneMode.SCENE2D) { - var ellipsoid = this._scene.mapProjection.ellipsoid; - var destinationCartographic = ellipsoid.cartesianToCartographic(destination, scratchFlyToCarto); - var height = destinationCartographic.height; - - // Make sure camera doesn't zoom outside set limits - if (defined(sscc)) { - //The computed height for rectangle in 2D/CV is stored in the 'z' component of Cartesian3 - if (mode !== SceneMode.SCENE3D && isRectangle) { - destination.z = CesiumMath.clamp(destination.z, sscc.minimumZoomDistance, sscc.maximumZoomDistance); - } else { - destinationCartographic.height = CesiumMath.clamp(destinationCartographic.height, sscc.minimumZoomDistance, sscc.maximumZoomDistance); - } - } - - // The max height in 2D might be lower than the max height for sscc. - if (mode === SceneMode.SCENE2D) { - var maxHeight = ellipsoid.maximumRadius * Math.PI * 2.0; - if (isRectangle) { - destination.z = Math.min(destination.z, maxHeight); - } else { - destinationCartographic.height = Math.min(destinationCartographic.height, maxHeight); - } - } - - //Only change if we clamped the height - if (destinationCartographic.height !== height) { - destination = ellipsoid.cartographicToCartesian(destinationCartographic, scratchFlyToDestination); - } - } + var that = this; + var flightTween; newOptions.destination = destination; newOptions.heading = orientation.heading; newOptions.pitch = orientation.pitch; newOptions.roll = orientation.roll; newOptions.duration = options.duration; - newOptions.complete = options.complete; + newOptions.complete = function () { + if(flightTween === that._currentFlight){ + that._currentFlight = undefined; + } + if (defined(options.complete)) { + options.complete(); + } + }; newOptions.cancel = options.cancel; newOptions.endTransform = options.endTransform; newOptions.convert = isRectangle ? false : options.convert; @@ -2604,7 +2673,8 @@ define([ newOptions.easingFunction = options.easingFunction; var scene = this._scene; - scene.tweens.add(CameraFlightPath.createTween(scene, newOptions)); + flightTween = scene.tweens.add(CameraFlightPath.createTween(scene, newOptions)); + this._currentFlight = flightTween; }; function distanceToBoundingSphere3D(camera, radius) { diff --git a/Source/Scene/CameraFlightPath.js b/Source/Scene/CameraFlightPath.js index 4b7b28df3e94..3aacb634f9b1 100644 --- a/Source/Scene/CameraFlightPath.js +++ b/Source/Scene/CameraFlightPath.js @@ -151,10 +151,6 @@ define([ var startRoll = adjustAngleForLERP(camera.roll, roll); var destCart = ellipsoid.cartesianToCartographic(destination, scratchEndCart); - if (destCart.height <= 0.0) { - destCart.height = startCart.height; - } - startCart.longitude = CesiumMath.zeroToTwoPi(startCart.longitude); destCart.longitude = CesiumMath.zeroToTwoPi(destCart.longitude); diff --git a/Source/Scene/FrameState.js b/Source/Scene/FrameState.js index dbd4935771e7..f64149f62758 100644 --- a/Source/Scene/FrameState.js +++ b/Source/Scene/FrameState.js @@ -170,6 +170,23 @@ define([ this.terrainExaggeration = 1.0; this.shadowHints = { + /** + * Whether there are any active shadow maps this frame. + * @type {Boolean} + */ + shadowsEnabled : true, + + /** + * All shadow maps that are enabled this frame. + */ + shadowMaps : [], + + /** + * Shadow maps that originate from light sources. Does not include shadow maps that are used for + * analytical purposes. Only these shadow maps will be used to generate receive shadows shaders. + */ + lightShadowMaps : [], + /** * The near plane of the scene's frustum commands. Used for fitting cascaded shadow maps. * @type {Number} diff --git a/Source/Scene/Globe.js b/Source/Scene/Globe.js index 118b7b96e800..e16b87fba3bc 100644 --- a/Source/Scene/Globe.js +++ b/Source/Scene/Globe.js @@ -7,6 +7,7 @@ define([ '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', + '../Core/deprecationWarning', '../Core/destroyObject', '../Core/DeveloperError', '../Core/Ellipsoid', @@ -27,7 +28,8 @@ define([ './GlobeSurfaceTileProvider', './ImageryLayerCollection', './QuadtreePrimitive', - './SceneMode' + './SceneMode', + './ShadowMode' ], function( BoundingSphere, buildModuleUrl, @@ -36,6 +38,7 @@ define([ defaultValue, defined, defineProperties, + deprecationWarning, destroyObject, DeveloperError, Ellipsoid, @@ -56,7 +59,8 @@ define([ GlobeSurfaceTileProvider, ImageryLayerCollection, QuadtreePrimitive, - SceneMode) { + SceneMode, + ShadowMode) { 'use strict'; /** @@ -188,23 +192,14 @@ define([ this.depthTestAgainstTerrain = false; /** - * Determines whether the globe casts shadows from each light source. Any primitive that has - * receiveShadows set to true will receive shadows that are casted by - * the globe. This may impact performance since the terrain is rendered again from the light's - * perspective. Currently only terrain that is in view casts shadows. + * Determines whether the globe casts or receives shadows from each light source. Setting the globe + * to cast shadows may impact performance since the terrain is rendered again from the light's perspective. + * Currently only terrain that is in view casts shadows. By default the globe does not cast shadows. * - * @type {Boolean} - * @default false - */ - this.castShadows = false; - - /** - * Determines whether the globe receives shadows from shadow casters in the scene. - * - * @type {Boolean} - * @default true + * @type {ShadowMode} + * @default ShadowMode.RECEIVE_ONLY */ - this.receiveShadows = true; + this.shadows = ShadowMode.RECEIVE_ONLY; this._oceanNormalMap = undefined; this._zoomedOutOceanSpecularIntensity = 0.5; @@ -286,6 +281,46 @@ define([ get: function() { return this._surface.tileLoadProgressEvent; } + }, + + /** + * Determines whether the globe casts shadows from each light source. + * + * @memberof Globe.prototype + * @type {Boolean} + * @deprecated + */ + castShadows : { + get : function() { + deprecationWarning('Globe.castShadows', 'Globe.castShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Globe.shadows instead.'); + return ShadowMode.castShadows(this.shadows); + }, + set : function(value) { + deprecationWarning('Globe.castShadows', 'Globe.castShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Globe.shadows instead.'); + var castShadows = value; + var receiveShadows = ShadowMode.receiveShadows(this.shadows); + this.shadows = ShadowMode.fromCastReceive(castShadows, receiveShadows); + } + }, + + /** + * Determines whether the globe receives shadows from shadow casters in the scene. + * + * @memberof Globe.prototype + * @type {Boolean} + * @deprecated + */ + receiveShadows : { + get : function() { + deprecationWarning('Globe.receiveShadows', 'Globe.receiveShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Globe.shadows instead.'); + return ShadowMode.receiveShadows(this.shadows); + }, + set : function(value) { + deprecationWarning('Globe.receiveShadows', 'Globe.receiveShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Globe.shadows instead.'); + var castShadows = ShadowMode.castShadows(this.shadows); + var receiveShadows = value; + this.shadows = ShadowMode.fromCastReceive(castShadows, receiveShadows); + } } }); @@ -505,8 +540,7 @@ define([ tileProvider.hasWaterMask = hasWaterMask; tileProvider.oceanNormalMap = this._oceanNormalMap; tileProvider.enableLighting = this.enableLighting; - tileProvider.castShadows = this.castShadows; - tileProvider.receiveShadows = this.receiveShadows; + tileProvider.shadows = this.shadows; surface.beginFrame(frameState); } diff --git a/Source/Scene/GlobeSurfaceTileProvider.js b/Source/Scene/GlobeSurfaceTileProvider.js index a27a7ba7d1f6..613d72eee6d9 100644 --- a/Source/Scene/GlobeSurfaceTileProvider.js +++ b/Source/Scene/GlobeSurfaceTileProvider.js @@ -43,7 +43,8 @@ define([ './ImageryLayer', './ImageryState', './QuadtreeTileLoadState', - './SceneMode' + './SceneMode', + './ShadowMode' ], function( BoundingSphere, BoxOutlineGeometry, @@ -88,7 +89,8 @@ define([ ImageryLayer, ImageryState, QuadtreeTileLoadState, - SceneMode) { + SceneMode, + ShadowMode) { 'use strict'; /** @@ -125,8 +127,7 @@ define([ this.oceanNormalMap = undefined; this.zoomedOutOceanSpecularIntensity = 0.5; this.enableLighting = false; - this.castShadows = false; - this.receiveShadows = false; + this.shadows = ShadowMode.RECEIVE_ONLY; this._quadtree = undefined; this._terrainProvider = options.terrainProvider; @@ -924,8 +925,8 @@ define([ var showOceanWaves = showReflectiveOcean && defined(oceanNormalMap); var hasVertexNormals = tileProvider.terrainProvider.ready && tileProvider.terrainProvider.hasVertexNormals; var enableFog = frameState.fog.enabled; - var castShadows = tileProvider.castShadows; - var receiveShadows = tileProvider.receiveShadows; + var castShadows = ShadowMode.castShadows(tileProvider.shadows); + var receiveShadows = ShadowMode.receiveShadows(tileProvider.shadows); if (showReflectiveOcean) { --maxTextures; diff --git a/Source/Scene/ImageryLayer.js b/Source/Scene/ImageryLayer.js index b60b22e12030..7b68a411bdb4 100644 --- a/Source/Scene/ImageryLayer.js +++ b/Source/Scene/ImageryLayer.js @@ -761,6 +761,7 @@ define([ if (!(this._imageryProvider.tilingScheme instanceof GeographicTilingScheme) && rectangle.width / texture.width > 1e-5) { var that = this; + imagery.addReference(); var computeCommand = new ComputeCommand({ persists : true, owner : this, @@ -773,6 +774,7 @@ define([ texture.destroy(); imagery.texture = outputTexture; finalizeReprojectTexture(that, context, imagery, outputTexture); + imagery.releaseReference(); } }); this._reprojectComputeCommands.push(computeCommand); diff --git a/Source/Scene/LabelCollection.js b/Source/Scene/LabelCollection.js index 44d8c2ff7759..6b28307d8c66 100644 --- a/Source/Scene/LabelCollection.js +++ b/Source/Scene/LabelCollection.js @@ -242,8 +242,7 @@ define([ glyphPixelOffset.x = widthOffset * resolutionScale; glyphPixelOffset.y = 0; - var heightReference = label._heightReference; - var verticalOrigin = (heightReference === HeightReference.NONE) ? label._verticalOrigin : VerticalOrigin.BOTTOM; + var verticalOrigin = label._verticalOrigin; for (glyphIndex = 0; glyphIndex < glyphLength; ++glyphIndex) { glyph = glyphs[glyphIndex]; dimensions = glyph.dimensions; diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js index 77f7f67fe898..5644c433eb83 100644 --- a/Source/Scene/Model.js +++ b/Source/Scene/Model.js @@ -11,6 +11,7 @@ define([ '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', + '../Core/deprecationWarning', '../Core/destroyObject', '../Core/DeveloperError', '../Core/FeatureDetection', @@ -47,7 +48,7 @@ define([ '../ThirdParty/gltfDefaults', '../ThirdParty/Uri', '../ThirdParty/when', - './getModelAccessor', + './getBinaryAccessor', './HeightReference', './ModelAnimationCache', './ModelAnimationCollection', @@ -56,7 +57,8 @@ define([ './ModelMesh', './ModelNode', './Pass', - './SceneMode' + './SceneMode', + './ShadowMode' ], function( BoundingSphere, Cartesian2, @@ -69,6 +71,7 @@ define([ defaultValue, defined, defineProperties, + deprecationWarning, destroyObject, DeveloperError, FeatureDetection, @@ -105,7 +108,7 @@ define([ gltfDefaults, Uri, when, - getModelAccessor, + getBinaryAccessor, HeightReference, ModelAnimationCache, ModelAnimationCollection, @@ -114,7 +117,8 @@ define([ ModelMesh, ModelNode, Pass, - SceneMode) { + SceneMode, + ShadowMode) { 'use strict'; // Bail out if the browser doesn't support typed arrays, to prevent the setup function @@ -311,8 +315,9 @@ define([ * @param {Boolean} [options.allowPicking=true] When true, each glTF mesh and primitive is pickable with {@link Scene#pick}. * @param {Boolean} [options.incrementallyLoadTextures=true] Determine if textures may continue to stream in after the model is loaded. * @param {Boolean} [options.asynchronous=true] Determines if model WebGL resource creation will be spread out over several frames or block until completion once all glTF files are loaded. - * @param {Boolean} [options.castShadows=true] Determines whether the model casts shadows from each light source. - * @param {Boolean} [options.receiveShadows=true] Determines whether the model receives shadows from shadow casters in the scene. + * @param {Boolean} [options.castShadows=true] Deprecated, use options.shadows instead. Determines whether the model casts shadows from each light source. + * @param {Boolean} [options.receiveShadows=true] Deprecated, use options.shadows instead. Determines whether the model receives shadows from shadow casters in the scene. + * @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the model casts or receives shadows from each light source. * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Draws the bounding sphere for each draw command in the model. * @param {Boolean} [options.debugWireframe=false] For debugging only. Draws the model in wireframe. * @param {HeightReference} [options.heightReference] Determines how the model is drawn relative to terrain. @@ -502,25 +507,19 @@ define([ this._incrementallyLoadTextures = defaultValue(options.incrementallyLoadTextures, true); this._asynchronous = defaultValue(options.asynchronous, true); - /** - * Determines whether the model casts shadows from each light source. - * - * @type {Boolean} - * - * @default true - */ - this.castShadows = defaultValue(options.castShadows, true); - this._castShadows = this.castShadows; + // Deprecated options + var castShadows = defaultValue(options.castShadows, true); + var receiveShadows = defaultValue(options.receiveShadows, true); /** - * Determines whether the model receives shadows from shadow casters in the scene. + * Determines whether the model casts or receives shadows from each light source. * - * @type {Boolean} + * @type {ShadowMode} * - * @default true + * @default ShadowMode.ENABLED */ - this.receiveShadows = defaultValue(options.receiveShadows, true); - this._receiveShadows = this.receiveShadows; + this.shadows = defaultValue(options.shadows, ShadowMode.fromCastReceive(castShadows, receiveShadows)); + this._shadows = this.shadows; /** * This property is for debugging only; it is not for production use nor is it optimized. @@ -868,6 +867,50 @@ define([ get : function() { return this._dirty; } + }, + + /** + * Determines whether the model casts shadows from each light source. + * + * @memberof Model.prototype + * + * @type {Boolean} + * + * @deprecated + */ + castShadows : { + get : function() { + deprecationWarning('Model.castShadows', 'Model.castShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Model.shadows instead.'); + return ShadowMode.castShadows(this.shadows); + }, + set : function(value) { + deprecationWarning('Model.castShadows', 'Model.castShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Model.shadows instead.'); + var castShadows = value; + var receiveShadows = ShadowMode.receiveShadows(this.shadows); + this.shadows = ShadowMode.fromCastReceive(castShadows, receiveShadows); + } + }, + + /** + * Determines whether the model receives shadows from shadow casters in the scene. + * + * @memberof Model.prototype + * + * @type {Boolean} + * + * @deprecated + */ + receiveShadows : { + get : function() { + deprecationWarning('Model.receiveShadows', 'Model.receiveShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Model.shadows instead.'); + return ShadowMode.receiveShadows(this.shadows); + }, + set : function(value) { + deprecationWarning('Model.receiveShadows', 'Model.receiveShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Model.shadows instead.'); + var castShadows = ShadowMode.castShadows(this.shadows); + var receiveShadows = value; + this.shadows = ShadowMode.fromCastReceive(castShadows, receiveShadows); + } } }); @@ -946,8 +989,7 @@ define([ * @param {Boolean} [options.allowPicking=true] When true, each glTF mesh and primitive is pickable with {@link Scene#pick}. * @param {Boolean} [options.incrementallyLoadTextures=true] Determine if textures may continue to stream in after the model is loaded. * @param {Boolean} [options.asynchronous=true] Determines if model WebGL resource creation will be spread out over several frames or block until completion once all glTF files are loaded. - * @param {Boolean} [options.castShadows=true] Determines whether the model casts shadows from each light source. - * @param {Boolean} [options.receiveShadows=true] Determines whether the model receives shadows from shadow casters in the scene. + * @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the model casts or receives shadows from each light source. * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Draws the bounding sphere for each {@link DrawCommand} in the model. * @param {Boolean} [options.debugWireframe=false] For debugging only. Draws the model in wireframe. * @@ -1629,7 +1671,7 @@ define([ } return undefined; } - + function modifyShaderForQuantizedAttributes(shader, programName, model, context) { var quantizedUniforms = {}; model._quantizedUniforms[programName] = quantizedUniforms; @@ -2172,7 +2214,7 @@ define([ attributes.push({ index : attributeLocation, vertexBuffer : rendererBuffers[a.bufferView], - componentsPerAttribute : getModelAccessor(a).componentsPerAttribute, + componentsPerAttribute : getBinaryAccessor(a).componentsPerAttribute, componentDatatype : a.componentType, normalize : false, offsetInBytes : a.byteOffset, @@ -2386,7 +2428,7 @@ define([ }, MODELINVERSETRANSPOSE : function(uniformState, model) { return function() { - return uniformState.inverseTranposeModel; + return uniformState.inverseTransposeModel; }; }, MODELVIEWINVERSETRANSPOSE : function(uniformState, model) { @@ -2880,7 +2922,7 @@ define([ else { var positions = accessors[primitive.attributes.POSITION]; count = positions.count; - var accessorInfo = getModelAccessor(positions); + var accessorInfo = getBinaryAccessor(positions); offset = (positions.byteOffset / (accessorInfo.componentsPerAttribute*ComponentDatatype.getSizeInBytes(positions.componentType))); } @@ -2915,6 +2957,9 @@ define([ mesh : runtimeMeshesByName[mesh.name] }; + var castShadows = ShadowMode.castShadows(model._shadows); + var receiveShadows = ShadowMode.receiveShadows(model._shadows); + var command = new DrawCommand({ boundingVolume : new BoundingSphere(), // updated in update() cull : model.cull, @@ -2924,8 +2969,8 @@ define([ count : count, offset : offset, shaderProgram : rendererPrograms[technique.program], - castShadows : model._castShadows, - receiveShadows : model._receiveShadows, + castShadows : castShadows, + receiveShadows : receiveShadows, uniformMap : uniformMap, renderState : rs, owner : owner, @@ -3353,12 +3398,11 @@ define([ } function updateShadows(model) { - if ((model.castShadows !== model._castShadows) || (model.receiveShadows !== model._receiveShadows)) { - model._castShadows = model.castShadows; - model._receiveShadows = model.receiveShadows; + if (model.shadows !== model._shadows) { + model._shadows = model.shadows; - var castShadows = model.castShadows; - var receiveShadows = model.receiveShadows; + var castShadows = ShadowMode.castShadows(model.shadows); + var receiveShadows = ShadowMode.receiveShadows(model.shadows); var nodeCommands = model._nodeCommands; var length = nodeCommands.length; diff --git a/Source/Scene/ModelAnimationCache.js b/Source/Scene/ModelAnimationCache.js index 9fa635e4c6be..d19ce82e4a52 100644 --- a/Source/Scene/ModelAnimationCache.js +++ b/Source/Scene/ModelAnimationCache.js @@ -8,7 +8,7 @@ define([ '../Core/Quaternion', '../Core/QuaternionSpline', '../Renderer/WebGLConstants', - './getModelAccessor' + './getBinaryAccessor' ], function( Cartesian3, defaultValue, @@ -18,7 +18,7 @@ define([ Quaternion, QuaternionSpline, WebGLConstants, - getModelAccessor) { + getBinaryAccessor) { 'use strict'; /** @@ -36,7 +36,7 @@ define([ var buffer = buffers[bufferView.buffer]; var byteOffset = bufferView.byteOffset + accessor.byteOffset; - var byteLength = accessor.count * getModelAccessor(accessor).componentsPerAttribute; + var byteLength = accessor.count * getBinaryAccessor(accessor).componentsPerAttribute; // buffer.path will be undefined when animations are embedded. return model.cacheKey + '//' + defaultValue(buffer.path, '') + '/' + byteOffset + '/' + byteLength; @@ -67,7 +67,7 @@ define([ // Convert typed array to Cesium types var buffer = loadResources.getBuffer(bufferView); - var typedArray = getModelAccessor(accessor).createArrayBufferView(buffer.buffer, buffer.byteOffset + accessor.byteOffset, count); + var typedArray = getBinaryAccessor(accessor).createArrayBufferView(buffer.buffer, buffer.byteOffset + accessor.byteOffset, count); var i; if ((componentType === WebGLConstants.FLOAT) && (type === 'SCALAR')) { @@ -180,7 +180,7 @@ define([ var type = accessor.type; var count = accessor.count; var buffer = loadResources.getBuffer(bufferView); - var typedArray = getModelAccessor(accessor).createArrayBufferView(buffer.buffer, buffer.byteOffset + accessor.byteOffset, count); + var typedArray = getBinaryAccessor(accessor).createArrayBufferView(buffer.buffer, buffer.byteOffset + accessor.byteOffset, count); matrices = new Array(count); if ((componentType === WebGLConstants.FLOAT) && (type === 'MAT4')) { diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js index a46052f31bea..995078d0fe1b 100644 --- a/Source/Scene/Primitive.js +++ b/Source/Scene/Primitive.js @@ -9,6 +9,7 @@ define([ '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', + '../Core/deprecationWarning', '../Core/destroyObject', '../Core/DeveloperError', '../Core/FeatureDetection', @@ -33,7 +34,8 @@ define([ './Pass', './PrimitivePipeline', './PrimitiveState', - './SceneMode' + './SceneMode', + './ShadowMode' ], function( BoundingSphere, Cartesian2, @@ -44,6 +46,7 @@ define([ defaultValue, defined, defineProperties, + deprecationWarning, destroyObject, DeveloperError, FeatureDetection, @@ -68,7 +71,8 @@ define([ Pass, PrimitivePipeline, PrimitiveState, - SceneMode) { + SceneMode, + ShadowMode) { 'use strict'; /** @@ -108,8 +112,9 @@ define([ * @param {Boolean} [options.cull=true] When true, the renderer frustum culls and horizon culls the primitive's commands based on their bounding volume. Set this to false for a small performance gain if you are manually culling the primitive. * @param {Boolean} [options.asynchronous=true] Determines if the primitive will be created asynchronously or block until ready. * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if this primitive's commands' bounding spheres are shown. - * @param {Boolean} [options.castShadows=false] Determines whether this primitive casts shadows from each light source. - * @param {Boolean} [options.receiveShadows=false] Determines whether this primitive receives shadows from shadow casters in the scene. + * @param {Boolean} [options.castShadows=true] Deprecated, use options.shadows instead. Determines whether the primitive casts shadows from each light source. + * @param {Boolean} [options.receiveShadows=true] Deprecated, use options.shadows instead. Determines whether the primitive receives shadows from shadow casters in the scene. + * @param {ShadowMode} [options.shadows=ShadowMode.DISABLED] Determines whether this primitive casts or receives shadows from each light source. * * @example * // 1. Draw a translucent ellipse on the surface with a checkerboard pattern @@ -283,23 +288,18 @@ define([ } //>>includeEnd('debug'); - /** - * Determines whether this primitive casts shadows from each light source. - * - * @type {Boolean} - * - * @default false - */ - this.castShadows = defaultValue(options.castShadows, false); + // Deprecated options + var castShadows = defaultValue(options.castShadows, false); + var receiveShadows = defaultValue(options.receiveShadows, false); /** - * Determines whether this primitive receives shadows from shadow casters in the scene. + * Determines whether this primitive casts or receives shadows from each light source. * - * @type {Boolean} + * @type {ShadowMode} * - * @default false + * @default ShadowMode.DISABLED */ - this.receiveShadows = defaultValue(options.receiveShadows, false); + this.shadows = defaultValue(options.shadows, ShadowMode.fromCastReceive(castShadows, receiveShadows)); this._translucent = undefined; @@ -475,6 +475,46 @@ define([ get : function() { return this._readyPromise.promise; } + }, + + /** + * Determines whether the primitive casts shadows from each light source. + * + * @memberof Primitive.prototype + * @type {Boolean} + * @deprecated + */ + castShadows : { + get : function() { + deprecationWarning('Primitive.castShadows', 'Primitive.castShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Primitive.shadows instead.'); + return ShadowMode.castShadows(this.shadows); + }, + set : function(value) { + deprecationWarning('Primitive.castShadows', 'Primitive.castShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Primitive.shadows instead.'); + var castShadows = value; + var receiveShadows = ShadowMode.receiveShadows(this.shadows); + this.shadows = ShadowMode.fromCastReceive(castShadows, receiveShadows); + } + }, + + /** + * Determines whether the primitive receives shadows from shadow casters in the scene. + * + * @memberof Primitive.prototype + * @type {Boolean} + * @deprecated + */ + receiveShadows : { + get : function() { + deprecationWarning('Primitive.receiveShadows', 'Primitive.receiveShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Primitive.shadows instead.'); + return ShadowMode.receiveShadows(this.shadows); + }, + set : function(value) { + deprecationWarning('Primitive.receiveShadows', 'Primitive.receiveShadows was deprecated in Cesium 1.25. It will be removed in 1.26. Use Primitive.shadows instead.'); + var castShadows = ShadowMode.castShadows(this.shadows); + var receiveShadows = value; + this.shadows = ShadowMode.fromCastReceive(castShadows, receiveShadows); + } } }); @@ -1325,6 +1365,8 @@ define([ var commandList = frameState.commandList; var passes = frameState.passes; if (passes.render) { + var castShadows = ShadowMode.castShadows(primitive.shadows); + var receiveShadows = ShadowMode.receiveShadows(primitive.shadows); var colorLength = colorCommands.length; for (var j = 0; j < colorLength; ++j) { var sphereIndex = twoPasses ? Math.floor(j / 2) : j; @@ -1333,8 +1375,8 @@ define([ colorCommand.boundingVolume = boundingSpheres[sphereIndex]; colorCommand.cull = cull; colorCommand.debugShowBoundingVolume = debugShowBoundingVolume; - colorCommand.castShadows = primitive.castShadows; - colorCommand.receiveShadows = primitive.receiveShadows; + colorCommand.castShadows = castShadows; + colorCommand.receiveShadows = receiveShadows; commandList.push(colorCommand); } diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index fcfd53fc76d5..d43b448aab00 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -1102,9 +1102,11 @@ define([ function updateDerivedCommands(scene, command) { var frameState = scene.frameState; - var shadowMaps = frameState.shadowMaps; var context = scene._context; var shadowsEnabled = frameState.shadowHints.shadowsEnabled; + var shadowMaps = frameState.shadowHints.shadowMaps; + var lightShadowMaps = frameState.shadowHints.lightShadowMaps; + var lightShadowsEnabled = shadowsEnabled && (lightShadowMaps.length > 0); var shadowsDirty = false; if (shadowsEnabled && (command.receiveShadows || command.castShadows)) { @@ -1123,12 +1125,12 @@ define([ var derivedCommands = command.derivedCommands; if (shadowsEnabled && (command.receiveShadows || command.castShadows)) { - derivedCommands.shadows = ShadowMap.createDerivedCommands(shadowMaps, command, shadowsDirty, context, derivedCommands.shadows); + derivedCommands.shadows = ShadowMap.createDerivedCommands(shadowMaps, lightShadowMaps, command, shadowsDirty, context, derivedCommands.shadows); } var oit = scene._oit; if (command.pass === Pass.TRANSLUCENT && defined(oit) && oit.isSupported()) { - if (shadowsEnabled && command.receiveShadows) { + if (lightShadowsEnabled && command.receiveShadows) { derivedCommands.oit = oit.createDerivedCommands(command.derivedCommands.shadows.receiveCommand, context, derivedCommands.oit); } else { derivedCommands.oit = oit.createDerivedCommands(command, context, derivedCommands.oit); @@ -1485,9 +1487,12 @@ define([ return; } + var shadowsEnabled = scene.frameState.shadowHints.shadowsEnabled; + var lightShadowsEnabled = shadowsEnabled && (scene.frameState.shadowHints.lightShadowMaps.length > 0); + if (scene.debugShowCommands || scene.debugShowFrustums) { executeDebugCommand(command, scene, passState); - } else if (scene.frameState.shadowHints.shadowsEnabled && command.receiveShadows && defined(command.derivedCommands.shadows)) { + } else if (lightShadowsEnabled && command.receiveShadows && defined(command.derivedCommands.shadows)) { // If the command receives shadows, execute the derived shadows command. // Some commands, such as OIT derived commands, do not have derived shadow commands themselves // and instead shadowing is built-in. In this case execute the command regularly below. @@ -1832,14 +1837,13 @@ define([ var command = commandList[i]; updateDerivedCommands(scene, command); - // Don't insert globe commands with the rest of the scene commands since they are handled separately if (command.castShadows && (command.pass === Pass.GLOBE || command.pass === Pass.OPAQUE || command.pass === Pass.TRANSLUCENT)) { if (isVisible(command, shadowVolume)) { if (isPointLight) { for (var k = 0; k < numberOfPasses; ++k) { passes[k].commandList.push(command); } - } else if (numberOfPasses <= 1) { + } else if (numberOfPasses === 1) { passes[0].commandList.push(command); } else { var wasVisible = false; @@ -1863,7 +1867,7 @@ define([ function executeShadowMapCastCommands(scene) { var frameState = scene.frameState; - var shadowMaps = frameState.shadowMaps; + var shadowMaps = frameState.shadowHints.shadowMaps; var shadowMapLength = shadowMaps.length; if (!frameState.shadowHints.shadowsEnabled) { @@ -2145,10 +2149,28 @@ define([ return; } + // Check if the shadow maps are different than the shadow maps last frame. + // If so, the derived commands need to be updated. + for (var j = 0; j < length; ++j) { + if (shadowMaps[j] !== frameState.shadowHints.shadowMaps[j]) { + ++frameState.shadowHints.lastDirtyTime; + break; + } + } + + frameState.shadowHints.shadowMaps.length = 0; + frameState.shadowHints.lightShadowMaps.length = 0; + for (var i = 0; i < length; ++i) { var shadowMap = shadowMaps[i]; shadowMap.update(frameState); + frameState.shadowHints.shadowMaps.push(shadowMap); + + if (shadowMap.fromLightSource) { + frameState.shadowHints.lightShadowMaps.push(shadowMap); + } + if (shadowMap.dirty) { ++frameState.shadowHints.lastDirtyTime; shadowMap.dirty = false; @@ -2303,13 +2325,14 @@ define([ } this._tweens.update(); - this._camera.update(this._mode); - this._camera._updateCameraChanged(); this._screenSpaceCameraController.update(); if (defined(this._deviceOrientationCameraController)) { this._deviceOrientationCameraController.update(); } + + this._camera.update(this._mode); + this._camera._updateCameraChanged(); }; var scratchEyeTranslation = new Cartesian3(); diff --git a/Source/Scene/ScreenSpaceCameraController.js b/Source/Scene/ScreenSpaceCameraController.js index 23af144ee69d..02a98707494e 100644 --- a/Source/Scene/ScreenSpaceCameraController.js +++ b/Source/Scene/ScreenSpaceCameraController.js @@ -991,7 +991,6 @@ define([ } function rotateCVOnTerrain(controller, startPosition, movement) { - var ellipsoid = controller._ellipsoid; var scene = controller._scene; var camera = scene.camera; @@ -1046,7 +1045,7 @@ define([ var verticalCenter = IntersectionTests.rayPlane(ray, plane, rotateCVVerticalCenter); var projection = camera._projection; - ellipsoid = projection.ellipsoid; + var ellipsoid = projection.ellipsoid; Cartesian3.fromElements(center.y, center.z, center.x, center); var cart = projection.unproject(center, rotateCVCart); @@ -1122,7 +1121,7 @@ define([ controller._rotateRateRangeAdjustment = radius; var originalPosition = Cartesian3.clone(camera.positionWC, rotateCVCartesian3); - adjustHeightForTerrain(controller); + camera._adjustHeightForTerrain(); if (!Cartesian3.equals(camera.positionWC, originalPosition)) { camera._setTransform(verticalTransform); @@ -1753,7 +1752,7 @@ define([ controller._rotateRateRangeAdjustment = radius; var originalPosition = Cartesian3.clone(camera.positionWC, tilt3DCartesian3); - adjustHeightForTerrain(controller); + camera._adjustHeightForTerrain(); if (!Cartesian3.equals(camera.positionWC, originalPosition)) { camera._setTransform(verticalTransform); @@ -1866,70 +1865,6 @@ define([ reactToInput(controller, controller.enableLook, controller.lookEventTypes, look3D); } - var scratchAdjustHeightCartographic = new Cartographic(); - - function adjustHeightForTerrain(controller) { - if (!controller.enableCollisionDetection) { - return; - } - - var scene = controller._scene; - var mode = scene.mode; - var globe = scene.globe; - - if (!defined(globe) || mode === SceneMode.SCENE2D || mode === SceneMode.MORPHING) { - return; - } - - var camera = scene.camera; - var ellipsoid = globe.ellipsoid; - var projection = scene.mapProjection; - - var transform; - var mag; - if (!Matrix4.equals(camera.transform, Matrix4.IDENTITY)) { - transform = Matrix4.clone(camera.transform); - mag = Cartesian3.magnitude(camera.position); - camera._setTransform(Matrix4.IDENTITY); - } - - var cartographic = scratchAdjustHeightCartographic; - if (mode === SceneMode.SCENE3D) { - ellipsoid.cartesianToCartographic(camera.position, cartographic); - } else { - projection.unproject(camera.position, cartographic); - } - - var heightUpdated = false; - if (cartographic.height < controller._minimumCollisionTerrainHeight) { - var height = globe.getHeight(cartographic); - if (defined(height)) { - height += controller.minimumZoomDistance; - if (cartographic.height < height) { - cartographic.height = height; - if (mode === SceneMode.SCENE3D) { - ellipsoid.cartographicToCartesian(cartographic, camera.position); - } else { - projection.project(cartographic, camera.position); - } - heightUpdated = true; - } - } - } - - if (defined(transform)) { - camera._setTransform(transform); - if (heightUpdated) { - Cartesian3.normalize(camera.position, camera.position); - Cartesian3.negate(camera.position, camera.direction); - Cartesian3.multiplyByScalar(camera.position, Math.max(mag, controller.minimumZoomDistance), camera.position); - Cartesian3.normalize(camera.direction, camera.direction); - Cartesian3.cross(camera.direction, camera.up, camera.right); - Cartesian3.cross(camera.right, camera.direction, camera.up); - } - } - } - /** * @private */ @@ -1962,8 +1897,6 @@ define([ update3D(this); } - adjustHeightForTerrain(this); - this._aggregator.reset(); }; diff --git a/Source/Scene/ShadowMap.js b/Source/Scene/ShadowMap.js index 22d22a0b673f..6007e8c2059d 100644 --- a/Source/Scene/ShadowMap.js +++ b/Source/Scene/ShadowMap.js @@ -161,6 +161,14 @@ define([ this._softShadows = defaultValue(options.softShadows, false); this.dirty = true; + /** + * Specifies whether the shadow map originates from a light source. Shadow maps that are used for analytical + * purposes should set this to false so as not to affect scene rendering. + * + * @private + */ + this.fromLightSource = defaultValue(options.fromLightSource, true); + /** * Determines the darkness of the shadows. * @@ -1535,11 +1543,12 @@ define([ return result; } - ShadowMap.createDerivedCommands = function(shadowMaps, command, shadowsDirty, context, result) { + ShadowMap.createDerivedCommands = function(shadowMaps, lightShadowMaps, command, shadowsDirty, context, result) { if (!defined(result)) { result = {}; } + var lightShadowMapsEnabled = (lightShadowMaps.length > 0); var shaderProgram = command.shaderProgram; var vertexShaderSource = shaderProgram.vertexShaderSource; var fragmentShaderSource = shaderProgram.fragmentShaderSource; @@ -1568,7 +1577,8 @@ define([ result.castShaderProgramId = command.shaderProgram.id; } - if (command.receiveShadows) { + if (command.receiveShadows && lightShadowMapsEnabled) { + // Only generate a receiveCommand if there is a shadow map originating from a light source. var receiveShader; var receiveUniformMap; if (defined(result.receiveCommand)) { @@ -1591,7 +1601,7 @@ define([ } var receiveVS = ShadowMapShader.createShadowReceiveVertexShader(vertexShaderSource, isTerrain, hasTerrainNormal); - var receiveFS = ShadowMapShader.createShadowReceiveFragmentShader(fragmentShaderSource, shadowMaps[0], command.castShadows, isTerrain, hasTerrainNormal); + var receiveFS = ShadowMapShader.createShadowReceiveFragmentShader(fragmentShaderSource, lightShadowMaps[0], command.castShadows, isTerrain, hasTerrainNormal); receiveShader = ShaderProgram.fromCache({ context : context, @@ -1600,7 +1610,7 @@ define([ attributeLocations : shaderProgram._attributeLocations }); - receiveUniformMap = combineUniforms(shadowMaps[0], command.uniformMap, isTerrain); + receiveUniformMap = combineUniforms(lightShadowMaps[0], command.uniformMap, isTerrain); } result.receiveCommand.shaderProgram = receiveShader; diff --git a/Source/Scene/ShadowMode.js b/Source/Scene/ShadowMode.js new file mode 100644 index 000000000000..68983ad7febd --- /dev/null +++ b/Source/Scene/ShadowMode.js @@ -0,0 +1,83 @@ +/*global define*/ +define([ + '../Core/freezeObject' + ], function( + freezeObject) { + 'use strict'; + + /** + * Specifies whether the object casts or receives shadows from each light source when + * shadows are enabled. + * + * @exports ShadowMode + */ + var ShadowMode = { + /** + * The object does not cast or receive shadows. + * + * @type {Number} + * @constant + */ + DISABLED : 0, + + /** + * The object casts and receives shadows. + * + * @type {Number} + * @constant + */ + ENABLED : 1, + + /** + * The object casts shadows only. + * + * @type {Number} + * @constant + */ + CAST_ONLY : 2, + + /** + * The object receives shadows only. + * + * @type {Number} + * @constant + */ + RECEIVE_ONLY : 3, + + /** + * @private + */ + NUMBER_OF_SHADOW_MODES : 4 + }; + + /** + * @private + */ + ShadowMode.castShadows = function(shadowMode) { + return (shadowMode === ShadowMode.ENABLED) || (shadowMode === ShadowMode.CAST_ONLY); + }; + + /** + * @private + */ + ShadowMode.receiveShadows = function(shadowMode) { + return (shadowMode === ShadowMode.ENABLED) || (shadowMode === ShadowMode.RECEIVE_ONLY); + }; + + /** + * @private + */ + ShadowMode.fromCastReceive = function(castShadows, receiveShadows) { + if (castShadows && receiveShadows) { + return ShadowMode.ENABLED; + } else if (castShadows) { + return ShadowMode.CAST_ONLY; + } else if (receiveShadows) { + return ShadowMode.RECEIVE_ONLY; + } else { + return ShadowMode.DISABLED; + } + }; + + return freezeObject(ShadowMode); +}); diff --git a/Source/Scene/getBinaryAccessor.js b/Source/Scene/getBinaryAccessor.js new file mode 100644 index 000000000000..e4aa0036f26a --- /dev/null +++ b/Source/Scene/getBinaryAccessor.js @@ -0,0 +1,64 @@ +/*global define*/ +define([ + '../Core/Cartesian2', + '../Core/Cartesian3', + '../Core/Cartesian4', + '../Core/ComponentDatatype', + '../Core/Matrix2', + '../Core/Matrix3', + '../Core/Matrix4' + ], function( + Cartesian2, + Cartesian3, + Cartesian4, + ComponentDatatype, + Matrix2, + Matrix3, + Matrix4) { + 'use strict'; + + var ComponentsPerAttribute = { + SCALAR : 1, + VEC2 : 2, + VEC3 : 3, + VEC4 : 4, + MAT2 : 4, + MAT3 : 9, + MAT4 : 16 + }; + + var ClassPerType = { + SCALAR : undefined, + VEC2 : Cartesian2, + VEC3 : Cartesian3, + VEC4 : Cartesian4, + MAT2 : Matrix2, + MAT3 : Matrix3, + MAT4 : Matrix4 + }; + + /** + * @private + */ + function getBinaryAccessor(accessor) { + var componentType = accessor.componentType; + var componentDatatype; + if (typeof componentType === 'string') { + componentDatatype = ComponentDatatype.fromName(componentType); + } else { + componentDatatype = componentType; + } + + var componentsPerAttribute = ComponentsPerAttribute[accessor.type]; + var classType = ClassPerType[accessor.type]; + return { + componentsPerAttribute : componentsPerAttribute, + classType : classType, + createArrayBufferView : function(buffer, byteOffset, length) { + return ComponentDatatype.createArrayBufferView(componentDatatype, buffer, byteOffset, componentsPerAttribute * length); + } + }; + } + + return getBinaryAccessor; +}); diff --git a/Source/Scene/getModelAccessor.js b/Source/Scene/getModelAccessor.js deleted file mode 100644 index 59ba2d6c2472..000000000000 --- a/Source/Scene/getModelAccessor.js +++ /dev/null @@ -1,34 +0,0 @@ -/*global define*/ -define([ - '../Core/ComponentDatatype' - ], function( - ComponentDatatype) { - 'use strict'; - - var ComponentsPerAttribute = { - SCALAR : 1, - VEC2 : 2, - VEC3 : 3, - VEC4 : 4, - MAT2 : 4, - MAT3 : 9, - MAT4 : 16 - }; - - /** - * @private - */ - function getModelAccessor(accessor) { - var componentDatatype = accessor.componentType; - var componentsPerAttribute = ComponentsPerAttribute[accessor.type]; - - return { - componentsPerAttribute : componentsPerAttribute, - createArrayBufferView : function(buffer, byteOffset, length) { - return ComponentDatatype.createArrayBufferView(componentDatatype, buffer, byteOffset, componentsPerAttribute * length); - } - }; - } - - return getModelAccessor; -}); diff --git a/Source/Shaders/Builtin/Functions/transpose.glsl b/Source/Shaders/Builtin/Functions/transpose.glsl index 7c39ca70d69b..8578d4403875 100644 --- a/Source/Shaders/Builtin/Functions/transpose.glsl +++ b/Source/Shaders/Builtin/Functions/transpose.glsl @@ -1,5 +1,5 @@ /** - * Returns the transpose of the matrix. The input matrix can be + * Returns the transpose of the matrix. The input matrix can be * a mat2, mat3, or mat4. * * @name czm_transpose @@ -15,7 +15,7 @@ * mat3 czm_transpose(mat3 matrix); * mat4 czm_transpose(mat4 matrix); * - * // Tranpose a 3x3 rotation matrix to find its inverse. + * // Transpose a 3x3 rotation matrix to find its inverse. * mat3 eastNorthUpToEye = czm_eastNorthUpToEyeCoordinates( * positionMC, normalEC); * mat3 eyeToEastNorthUp = czm_transpose(eastNorthUpToEye); diff --git a/Source/ThirdParty/earcut-2.1.1.js b/Source/ThirdParty/earcut-2.1.1.js index 4ac1683e6f21..be074fec16b9 100644 --- a/Source/ThirdParty/earcut-2.1.1.js +++ b/Source/ThirdParty/earcut-2.1.1.js @@ -1,7 +1,6 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.earcut = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o" + textstring; document.body.appendChild(leadDiv); @@ -125,8 +127,10 @@ define(function() { canvas.style.opacity = 1; canvas.style.fontFamily = fontFamily; canvas.style.fontSize = fontSize; + canvas.style.fontStyle = fontStyle; + canvas.style.fontWeight = fontWeight; var ctx = canvas.getContext("2d"); - ctx.font = fontSize + "px " + fontFamily; + ctx.font = fontStyle + " " + fontWeight + " " + fontSize + "px " + fontFamily; var w = canvas.width, h = canvas.height, diff --git a/Source/Widgets/CesiumWidget/CesiumWidget.js b/Source/Widgets/CesiumWidget/CesiumWidget.js index aab48545dc10..2e6c6f6e38ff 100644 --- a/Source/Widgets/CesiumWidget/CesiumWidget.js +++ b/Source/Widgets/CesiumWidget/CesiumWidget.js @@ -19,6 +19,7 @@ define([ '../../Scene/Moon', '../../Scene/Scene', '../../Scene/SceneMode', + '../../Scene/ShadowMode', '../../Scene/SkyAtmosphere', '../../Scene/SkyBox', '../../Scene/Sun', @@ -43,6 +44,7 @@ define([ Moon, Scene, SceneMode, + ShadowMode, SkyAtmosphere, SkyBox, Sun, @@ -160,7 +162,7 @@ define([ * to the bottom of the widget itself. * @param {Number} [options.terrainExaggeration=1.0] A scalar used to exaggerate the terrain. Note that terrain exaggeration will not modify any other primitive as they are positioned relative to the ellipsoid. * @param {Boolean} [options.shadows=false] Determines if shadows are cast by the sun. - * @param {Boolean} [options.terrainShadows=false] Determines if the terrain casts shadows from the sun. + * @param {ShadowMode} [options.terrainShadows=ShadowMode.RECEIVE_ONLY] Determines if the terrain casts or receives shadows from the sun. * @param {MapMode2D} [options.mapMode2D=MapMode2D.INFINITE_SCROLL] Determines if the 2D map is rotatable or can be scrolled infinitely in the horizontal direction. * * @exception {DeveloperError} Element with id "container" does not exist in the document. @@ -280,7 +282,15 @@ define([ } if (globe !== false) { scene.globe = globe; - scene.globe.castShadows = defaultValue(options.terrainShadows, false); + // If the passed in value is a boolean, convert to the ShadowMode enum. + var terrainShadows = options.terrainShadows; + if (terrainShadows === true) { + scene.globe.shadows = ShadowMode.ENABLED; + } else if (terrainShadows === false) { + scene.globe.shadows = ShadowMode.RECEIVE_ONLY; + } else { + scene.globe.shadows = defaultValue(terrainShadows, ShadowMode.RECEIVE_ONLY); + } } var skyBox = options.skyBox; diff --git a/Source/Widgets/Geocoder/Geocoder.js b/Source/Widgets/Geocoder/Geocoder.js index c189688a2d1e..d697bbb01aa3 100644 --- a/Source/Widgets/Geocoder/Geocoder.js +++ b/Source/Widgets/Geocoder/Geocoder.js @@ -69,7 +69,7 @@ define([ value: searchText,\ valueUpdate: "afterkeydown",\ disable: isSearchInProgress,\ -css: { "cesium-geocoder-input-wide" : searchText.length > 0 }'); +css: { "cesium-geocoder-input-wide" : keepExpanded || searchText.length > 0 }'); form.appendChild(textBox); var searchButton = document.createElement('span'); diff --git a/Source/Widgets/Geocoder/GeocoderViewModel.js b/Source/Widgets/Geocoder/GeocoderViewModel.js index fe9979ed4e1a..c7d13cc633b4 100644 --- a/Source/Widgets/Geocoder/GeocoderViewModel.js +++ b/Source/Widgets/Geocoder/GeocoderViewModel.js @@ -82,7 +82,15 @@ define([ } }); - knockout.track(this, ['_searchText', '_isSearchInProgress']); + /** + * Gets or sets a value indicating if this instance should always show its text input field. + * + * @type {Boolean} + * @default false + */ + this.keepExpanded = false; + + knockout.track(this, ['_searchText', '_isSearchInProgress', 'keepExpanded']); /** * Gets a value indicating whether a search is currently in progress. This property is observable. diff --git a/Source/Widgets/Timeline/Timeline.js b/Source/Widgets/Timeline/Timeline.js index 0ea02619232c..32eef7c42fca 100644 --- a/Source/Widgets/Timeline/Timeline.js +++ b/Source/Widgets/Timeline/Timeline.js @@ -784,6 +784,7 @@ define([ this._trackListEle.height = trackListHeight; this._makeTics(); + this._lastXPos = undefined; this._lastWidth = width; this._lastHeight = height; }; diff --git a/Source/Widgets/Viewer/Viewer.js b/Source/Widgets/Viewer/Viewer.js index d4924d75507c..8bf59948fc4f 100644 --- a/Source/Widgets/Viewer/Viewer.js +++ b/Source/Widgets/Viewer/Viewer.js @@ -22,6 +22,7 @@ define([ '../../DataSources/Property', '../../Scene/ImageryLayer', '../../Scene/SceneMode', + '../../Scene/ShadowMode', '../../ThirdParty/knockout', '../../ThirdParty/when', '../Animation/Animation', @@ -65,6 +66,7 @@ define([ Property, ImageryLayer, SceneMode, + ShadowMode, knockout, when, Animation, @@ -277,7 +279,7 @@ define([ * the instance is assumed to be owned by the caller and will not be destroyed when the viewer is destroyed. * @param {Number} [options.terrainExaggeration=1.0] A scalar used to exaggerate the terrain. Note that terrain exaggeration will not modify any other primitive as they are positioned relative to the ellipsoid. * @param {Boolean} [options.shadows=false] Determines if shadows are cast by the sun. - * @param {Boolean} [options.terrainShadows=false] Determines if the terrain casts shadows from the sun. + * @param {ShadowMode} [options.terrainShadows=ShadowMode.RECEIVE_ONLY] Determines if the terrain casts or receives shadows from the sun. * @param {MapMode2D} [options.mapMode2D=MapMode2D.INFINITE_SCROLL] Determines if the 2D map is rotatable or can be scrolled infinitely in the horizontal direction. * * @exception {DeveloperError} Element with id "container" does not exist in the document. @@ -963,16 +965,23 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to }, /** - * Determines if the terrain casts shadows from the sun. + * Determines if the terrain casts or shadows from the sun. * @memberof Viewer.prototype - * @type {Boolean} + * @type {ShadowMode} */ terrainShadows : { get : function() { - return this.scene.globe.castShadows; + return this.scene.globe.shadows; }, set : function(value) { - this.scene.globe.castShadows = value; + // If the passed in value is a boolean, convert to the ShadowMode enum. + if (value === true) { + this.scene.globe.shadows = ShadowMode.ENABLED; + } else if (value === false) { + this.scene.globe.shadows = ShadowMode.RECEIVE_ONLY; + } else { + this.scene.globe.shadows = value; + } } }, diff --git a/Source/copyrightHeader.js b/Source/copyrightHeader.js index f53f5738a1a6..1bf1b765eef6 100644 --- a/Source/copyrightHeader.js +++ b/Source/copyrightHeader.js @@ -1,7 +1,7 @@ /** * Cesium - https://github.com/AnalyticalGraphicsInc/cesium * - * Copyright 2011-2015 Cesium Contributors + * Copyright 2011-2016 Cesium Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/Specs/Core/ComponentDatatypeSpec.js b/Specs/Core/ComponentDatatypeSpec.js index 55a22c354903..5d65b5e19e61 100644 --- a/Specs/Core/ComponentDatatypeSpec.js +++ b/Specs/Core/ComponentDatatypeSpec.js @@ -10,6 +10,8 @@ defineSuite([ expect(ComponentDatatype.fromTypedArray(new Uint8Array())).toBe(ComponentDatatype.UNSIGNED_BYTE); expect(ComponentDatatype.fromTypedArray(new Int16Array())).toBe(ComponentDatatype.SHORT); expect(ComponentDatatype.fromTypedArray(new Uint16Array())).toBe(ComponentDatatype.UNSIGNED_SHORT); + expect(ComponentDatatype.fromTypedArray(new Int32Array())).toBe(ComponentDatatype.INT); + expect(ComponentDatatype.fromTypedArray(new Uint32Array())).toBe(ComponentDatatype.UNSIGNED_INT); expect(ComponentDatatype.fromTypedArray(new Float32Array())).toBe(ComponentDatatype.FLOAT); expect(ComponentDatatype.fromTypedArray(new Float64Array())).toBe(ComponentDatatype.DOUBLE); }); @@ -19,6 +21,8 @@ defineSuite([ expect(ComponentDatatype.validate(ComponentDatatype.UNSIGNED_BYTE)).toBe(true); expect(ComponentDatatype.validate(ComponentDatatype.SHORT)).toBe(true); expect(ComponentDatatype.validate(ComponentDatatype.UNSIGNED_SHORT)).toBe(true); + expect(ComponentDatatype.validate(ComponentDatatype.INT)).toBe(true); + expect(ComponentDatatype.validate(ComponentDatatype.UNSIGNED_INT)).toBe(true); expect(ComponentDatatype.validate(ComponentDatatype.FLOAT)).toBe(true); expect(ComponentDatatype.validate(ComponentDatatype.DOUBLE)).toBe(true); expect(ComponentDatatype.validate(undefined)).toBe(false); @@ -42,6 +46,14 @@ defineSuite([ expect(typedArray).toBeInstanceOf(Uint16Array); expect(typedArray.length).toBe(3); + typedArray = ComponentDatatype.createTypedArray(ComponentDatatype.INT, 4); + expect(typedArray).toBeInstanceOf(Int32Array); + expect(typedArray.length).toBe(4); + + typedArray = ComponentDatatype.createTypedArray(ComponentDatatype.UNSIGNED_INT, 5); + expect(typedArray).toBeInstanceOf(Uint32Array); + expect(typedArray.length).toBe(5); + typedArray = ComponentDatatype.createTypedArray(ComponentDatatype.FLOAT, 6); expect(typedArray).toBeInstanceOf(Float32Array); expect(typedArray.length).toBe(6); @@ -73,6 +85,16 @@ defineSuite([ expect(typedArray).toEqual(values); expect(typedArray.length).toBe(values.length); + typedArray = ComponentDatatype.createTypedArray(ComponentDatatype.INT, values); + expect(typedArray).toBeInstanceOf(Int32Array); + expect(typedArray).toEqual(values); + expect(typedArray.length).toBe(values.length); + + typedArray = ComponentDatatype.createTypedArray(ComponentDatatype.UNSIGNED_INT, values); + expect(typedArray).toBeInstanceOf(Uint32Array); + expect(typedArray).toEqual(values); + expect(typedArray.length).toBe(values.length); + typedArray = ComponentDatatype.createTypedArray(ComponentDatatype.FLOAT, values); expect(typedArray).toBeInstanceOf(Float32Array); expect(typedArray).toEqual(values); @@ -90,6 +112,8 @@ defineSuite([ expect(ComponentDatatype.createArrayBufferView(ComponentDatatype.UNSIGNED_BYTE, buffer, 0, 1)).toBeInstanceOf(Uint8Array); expect(ComponentDatatype.createArrayBufferView(ComponentDatatype.SHORT, buffer, 0, 1)).toBeInstanceOf(Int16Array); expect(ComponentDatatype.createArrayBufferView(ComponentDatatype.UNSIGNED_SHORT, buffer, 0, 1)).toBeInstanceOf(Uint16Array); + expect(ComponentDatatype.createArrayBufferView(ComponentDatatype.INT, buffer, 0, 1)).toBeInstanceOf(Int32Array); + expect(ComponentDatatype.createArrayBufferView(ComponentDatatype.UNSIGNED_INT, buffer, 0, 1)).toBeInstanceOf(Uint32Array); expect(ComponentDatatype.createArrayBufferView(ComponentDatatype.FLOAT, buffer, 0, 1)).toBeInstanceOf(Float32Array); expect(ComponentDatatype.createArrayBufferView(ComponentDatatype.DOUBLE, buffer, 0, 1)).toBeInstanceOf(Float64Array); }); @@ -125,4 +149,21 @@ defineSuite([ ComponentDatatype.createTypedArray(ComponentDatatype.BYTE, undefined, 0, 1); }).toThrowDeveloperError(); }); + + it('fromName works', function() { + expect(ComponentDatatype.fromName('BYTE')).toEqual(ComponentDatatype.BYTE); + expect(ComponentDatatype.fromName('UNSIGNED_BYTE')).toEqual(ComponentDatatype.UNSIGNED_BYTE); + expect(ComponentDatatype.fromName('SHORT')).toEqual(ComponentDatatype.SHORT); + expect(ComponentDatatype.fromName('UNSIGNED_SHORT')).toEqual(ComponentDatatype.UNSIGNED_SHORT); + expect(ComponentDatatype.fromName('INT')).toEqual(ComponentDatatype.INT); + expect(ComponentDatatype.fromName('UNSIGNED_INT')).toEqual(ComponentDatatype.UNSIGNED_INT); + expect(ComponentDatatype.fromName('FLOAT')).toEqual(ComponentDatatype.FLOAT); + expect(ComponentDatatype.fromName('DOUBLE')).toEqual(ComponentDatatype.DOUBLE); + }); + + it('fromName throws without name', function() { + expect(function() { + ComponentDatatype.fromName(); + }).toThrowDeveloperError(); + }); }); diff --git a/Specs/Core/EllipseGeometrySpec.js b/Specs/Core/EllipseGeometrySpec.js index bc05188d4a5c..98ab696a2e5b 100644 --- a/Specs/Core/EllipseGeometrySpec.js +++ b/Specs/Core/EllipseGeometrySpec.js @@ -247,10 +247,10 @@ defineSuite([ }); var r = ellipse.rectangle; - expect(r.north).toEqual(0.6989665987920752); - expect(r.south).toEqual(0.6986522252554146); - expect(r.east).toEqual(-1.3190209903056758); - expect(r.west).toEqual(-1.3198389970251112); + expect(r.north).toEqualEpsilon(0.6989665987920752, CesiumMath.EPSILON7); + expect(r.south).toEqualEpsilon(0.6986522252554146, CesiumMath.EPSILON7); + expect(r.east).toEqualEpsilon(-1.3190209903056758, CesiumMath.EPSILON7); + expect(r.west).toEqualEpsilon(-1.3198389970251112, CesiumMath.EPSILON7); }); var center = Cartesian3.fromDegrees(0,0); diff --git a/Specs/Core/RectangleGeometrySpec.js b/Specs/Core/RectangleGeometrySpec.js index 146e377cd616..519dfdcb5a68 100644 --- a/Specs/Core/RectangleGeometrySpec.js +++ b/Specs/Core/RectangleGeometrySpec.js @@ -292,6 +292,17 @@ defineSuite([ expect(CesiumMath.toDegrees(r.west)).toEqual(-1.4094456877799821); }); + it('computing rectangle property with zero rotation', function() { + expect(function() { + return RectangleGeometry.createGeometry(new RectangleGeometry({ + vertexFormat : VertexFormat.POSITION_ONLY, + rectangle : Rectangle.MAX_VALUE, + granularity : 1.0, + rotation : 0 + })); + }).not.toThrowDeveloperError(); + }); + var rectangle = new RectangleGeometry({ vertexFormat : VertexFormat.POSITION_ONLY, rectangle : new Rectangle(-2.0, -1.0, 0.0, 1.0), diff --git a/Specs/Core/loadWithXhrSpec.js b/Specs/Core/loadWithXhrSpec.js index 0576effca5e5..44cc1799f33a 100644 --- a/Specs/Core/loadWithXhrSpec.js +++ b/Specs/Core/loadWithXhrSpec.js @@ -1,12 +1,22 @@ /*global defineSuite*/ defineSuite([ 'Core/loadWithXhr', - 'Core/loadImage' + 'Core/loadImage', + 'Core/RequestErrorEvent', + 'Core/RuntimeError' ], function( loadWithXhr, - loadImage) { + loadImage, + RequestErrorEvent, + RuntimeError) { 'use strict'; + it('throws with no url', function() { + expect(function() { + loadWithXhr(); + }).toThrowDeveloperError(); + }); + describe('data URI loading', function() { it('can load URI escaped text with default response type', function() { return loadWithXhr({ @@ -33,7 +43,7 @@ defineSuite([ }); }); - it ('can load Base64 encoded text with responseType=text', function() { + it('can load Base64 encoded text with responseType=text', function() { return loadWithXhr({ url : 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==', responseType : 'text' @@ -133,18 +143,263 @@ defineSuite([ }); }); - xit('can support 2xx HTTP status (other than 200)', function(){ + xit('can support 2xx HTTP status (other than 200)', function() { return loadWithXhr({ - method: 'POST', - url: 'http://jsonplaceholder.typicode.com/posts', - data: { - title: 'foo', - body: 'bar', - userId: 1 + method : 'POST', + url : 'http://jsonplaceholder.typicode.com/posts', + data : { + title : 'foo', + body : 'bar', + userId : 1 } - }).then(function(result){ + }).then(function(result) { expect(JSON.parse(result).id).toEqual(101); }); }); }); + + describe('URL loading using XHR', function() { + describe('returns a promise that rejects when the request', function() { + it('results in an HTTP status code greater than or equal to 300', function() { + return loadWithXhr({ + url : 'http://example.invalid' + }).then(function() { + fail('expected promise to reject'); + }).otherwise(function(err) { + expect(err instanceof RequestErrorEvent).toBe(true); + }); + }); + + it('loads an invalid JSON string response with a json responseType', function() { + return loadWithXhr({ + url : 'Data/htmlString.txt', + responseType : 'json' + }).then(function() { + fail('expected promise to reject'); + }).otherwise(function(err) { + expect(err).toBeDefined(); + expect(err instanceof Error).toBe(true); + }); + }); + }); + + describe('returns a promise that resolves when the request loads', function() { + it('a non-null response with default responseType', function() { + return loadWithXhr({ + url : 'Data/Models/Box/ReadMe.txt' + }).then(function(result) { + expect(result).toBe('CesiumBoxTest-NoTechnique.gltf is a modified glTF that has techniques, shaders & programs removed.'); + }); + }); + + it('a non-null response with a browser-supported responseType', function() { + return loadWithXhr({ + url : 'Data/Models/Box/ReadMe.txt', + responseType : 'text' + }).then(function(result) { + expect(result).toBe('CesiumBoxTest-NoTechnique.gltf is a modified glTF that has techniques, shaders & programs removed.'); + }); + }); + + it('a valid JSON string response as JSON with a json responseType', function() { + return loadWithXhr({ + url : 'Data/jsonString.txt', + responseType : 'json' + }).then(function(result) { + expect(result).toEqual(jasmine.objectContaining({hello : 'world'})); + }); + }); + }); + }); + + describe('URL loading using mocked XHR', function() { + var fakeXHR; + + beforeEach(function() { + fakeXHR = jasmine.createSpyObj('XMLHttpRequest', ['send', 'open', 'setRequestHeader', 'abort', 'getAllResponseHeaders']); + fakeXHR.simulateError = function() { + fakeXHR.response = ''; + if (typeof fakeXHR.onerror === 'function') { + fakeXHR.onerror(); + } + }; + fakeXHR.simulateHttpError = function(statusCode, response) { + fakeXHR.status = statusCode; + fakeXHR.response = response; + if (typeof fakeXHR.onload === 'function') { + fakeXHR.onload(); + } + }; + fakeXHR.simulateResponseXMLLoad = function(responseXML) { + fakeXHR.status = 200; + fakeXHR.responseXML = responseXML; + if (typeof fakeXHR.onload === 'function') { + fakeXHR.onload(); + } + }; + fakeXHR.simulateResponseTextLoad = function(responseText) { + fakeXHR.status = 200; + fakeXHR.responseText = responseText; + if (typeof fakeXHR.onload === 'function') { + fakeXHR.onload(); + } + }; + + spyOn(window, 'XMLHttpRequest').and.returnValue(fakeXHR); + }); + + describe('returns a promise that rejects when the request', function() { + it('errors', function() { + var promise = loadWithXhr({ + url : 'http://example.invalid' + }); + + expect(promise).toBeDefined(); + + var resolvedValue; + var rejectedError; + promise.then(function(value) { + resolvedValue = value; + }).otherwise(function (error) { + rejectedError = error; + }); + + expect(resolvedValue).toBeUndefined(); + expect(rejectedError).toBeUndefined(); + + fakeXHR.simulateError(); + expect(resolvedValue).toBeUndefined(); + expect(rejectedError instanceof RequestErrorEvent).toBe(true); + }); + + it('results in an HTTP status code less than 200', function() { + var promise = loadWithXhr({ + url : 'http://example.invalid' + }); + + expect(promise).toBeDefined(); + + var resolvedValue; + var rejectedError; + promise.then(function(value) { + resolvedValue = value; + }).otherwise(function (error) { + rejectedError = error; + }); + + expect(resolvedValue).toBeUndefined(); + expect(rejectedError).toBeUndefined(); + + fakeXHR.simulateHttpError(199); + expect(resolvedValue).toBeUndefined(); + expect(rejectedError instanceof RequestErrorEvent).toBe(true); + }); + }); + + describe('returns a promise that resolves when the request loads', function() { + it('a null response with a \'\' responseType and non-null responseXML with child nodes', function() { + var promise = loadWithXhr({ + url : 'http://example.invalid', + responseType : '' + }); + + expect(promise).toBeDefined(); + + var resolvedValue; + var rejectedError; + promise.then(function(value) { + resolvedValue = value; + }).otherwise(function (error) { + rejectedError = error; + }); + + expect(resolvedValue).toBeUndefined(); + expect(rejectedError).toBeUndefined(); + + var responseXML = { + hasChildNodes : jasmine.createSpy('hasChildNodes').and.returnValue(true) + }; + fakeXHR.simulateResponseXMLLoad(responseXML); + expect(resolvedValue).toEqual(responseXML); + expect(rejectedError).toBeUndefined(); + }); + + it('a null response with a document responseType and non-null responseXML with child nodes', function() { + var promise = loadWithXhr({ + url : 'http://example.invalid', + responseType : 'document' + }); + + expect(promise).toBeDefined(); + + var resolvedValue; + var rejectedError; + promise.then(function(value) { + resolvedValue = value; + }).otherwise(function (error) { + rejectedError = error; + }); + + expect(resolvedValue).toBeUndefined(); + expect(rejectedError).toBeUndefined(); + + var responseXML = { + hasChildNodes : jasmine.createSpy('hasChildNodes').and.returnValue(true) + }; + fakeXHR.simulateResponseXMLLoad(responseXML); + expect(resolvedValue).toEqual(responseXML); + expect(rejectedError).toBeUndefined(); + }); + + it('a null response with a \'\' responseType and non-null responseText', function() { + var promise = loadWithXhr({ + url : 'http://example.invalid', + responseType : '' + }); + + expect(promise).toBeDefined(); + + var resolvedValue; + var rejectedError; + promise.then(function(value) { + resolvedValue = value; + }).otherwise(function (error) { + rejectedError = error; + }); + + expect(resolvedValue).toBeUndefined(); + expect(rejectedError).toBeUndefined(); + + var responseText = 'hello world'; + fakeXHR.simulateResponseTextLoad(responseText); + expect(resolvedValue).toEqual(responseText); + expect(rejectedError).toBeUndefined(); + }); + + it('a null response with a text responseType and non-null responseText', function() { + var promise = loadWithXhr({ + url : 'http://example.invalid', + responseType : 'text' + }); + + expect(promise).toBeDefined(); + + var resolvedValue; + var rejectedError; + promise.then(function(value) { + resolvedValue = value; + }).otherwise(function (error) { + rejectedError = error; + }); + + expect(resolvedValue).toBeUndefined(); + expect(rejectedError).toBeUndefined(); + + var responseText = 'hello world'; + fakeXHR.simulateResponseTextLoad(responseText); + expect(resolvedValue).toEqual(responseText); + expect(rejectedError).toBeUndefined(); + }); + }); + }); }); diff --git a/Specs/Data/htmlString.txt b/Specs/Data/htmlString.txt new file mode 100644 index 000000000000..b233ed45a241 --- /dev/null +++ b/Specs/Data/htmlString.txt @@ -0,0 +1 @@ +Hello, world! diff --git a/Specs/Data/jsonString.txt b/Specs/Data/jsonString.txt new file mode 100644 index 000000000000..56c8e280338e --- /dev/null +++ b/Specs/Data/jsonString.txt @@ -0,0 +1 @@ +{"hello": "world"} diff --git a/Specs/DataSources/BoxGeometryUpdaterSpec.js b/Specs/DataSources/BoxGeometryUpdaterSpec.js index 315b8c7422fe..288dd3f064bc 100644 --- a/Specs/DataSources/BoxGeometryUpdaterSpec.js +++ b/Specs/DataSources/BoxGeometryUpdaterSpec.js @@ -17,6 +17,7 @@ defineSuite([ 'DataSources/SampledProperty', 'DataSources/TimeIntervalCollectionProperty', 'Scene/PrimitiveCollection', + 'Scene/ShadowMode', 'Specs/createDynamicGeometryBoundingSphereSpecs', 'Specs/createDynamicProperty', 'Specs/createScene' @@ -38,6 +39,7 @@ defineSuite([ SampledProperty, TimeIntervalCollectionProperty, PrimitiveCollection, + ShadowMode, createDynamicGeometryBoundingSphereSpecs, createDynamicProperty, createScene) { @@ -78,6 +80,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -118,6 +121,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); expect(updater.isDynamic).toBe(false); }); diff --git a/Specs/DataSources/BoxGraphicsSpec.js b/Specs/DataSources/BoxGraphicsSpec.js index fd2ee1d65449..70c4ec7d55d1 100644 --- a/Specs/DataSources/BoxGraphicsSpec.js +++ b/Specs/DataSources/BoxGraphicsSpec.js @@ -5,6 +5,7 @@ defineSuite([ 'Core/Color', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', + 'Scene/ShadowMode', 'Specs/testDefinitionChanged', 'Specs/testMaterialDefinitionChanged' ], function( @@ -13,6 +14,7 @@ defineSuite([ Color, ColorMaterialProperty, ConstantProperty, + ShadowMode, testDefinitionChanged, testMaterialDefinitionChanged) { 'use strict'; @@ -25,7 +27,8 @@ defineSuite([ outline : false, outlineColor : Color.RED, outlineWidth : 1, - dimensions : new Cartesian3(2, 3, 4) + dimensions : new Cartesian3(2, 3, 4), + shadows : ShadowMode.DISABLED }; var box = new BoxGraphics(options); @@ -36,6 +39,7 @@ defineSuite([ expect(box.outlineColor).toBeInstanceOf(ConstantProperty); expect(box.outlineWidth).toBeInstanceOf(ConstantProperty); expect(box.dimensions).toBeInstanceOf(ConstantProperty); + expect(box.shadows).toBeInstanceOf(ConstantProperty); expect(box.material.color.getValue()).toEqual(options.material); expect(box.show.getValue()).toEqual(options.show); @@ -44,6 +48,7 @@ defineSuite([ expect(box.outlineColor.getValue()).toEqual(options.outlineColor); expect(box.outlineWidth.getValue()).toEqual(options.outlineWidth); expect(box.dimensions.getValue()).toEqual(options.dimensions); + expect(box.shadows.getValue()).toEqual(options.shadows); }); it('merge assigns unassigned properties', function() { @@ -55,6 +60,7 @@ defineSuite([ source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); source.dimensions = new ConstantProperty(); + source.shadows = new ConstantProperty(ShadowMode.ENABLED); var target = new BoxGraphics(); target.merge(source); @@ -66,6 +72,7 @@ defineSuite([ expect(target.outlineColor).toBe(source.outlineColor); expect(target.outlineWidth).toBe(source.outlineWidth); expect(target.dimensions).toBe(source.dimensions); + expect(target.shadows).toBe(source.shadows); }); it('merge does not assign assigned properties', function() { @@ -78,6 +85,7 @@ defineSuite([ var outlineColor = new ConstantProperty(); var outlineWidth = new ConstantProperty(); var dimensions = new ConstantProperty(); + var shadows = new ConstantProperty(); var target = new BoxGraphics(); target.material = material; @@ -87,6 +95,7 @@ defineSuite([ target.outlineColor = outlineColor; target.outlineWidth = outlineWidth; target.dimensions = dimensions; + target.shadows = shadows; target.merge(source); @@ -97,6 +106,7 @@ defineSuite([ expect(target.outlineColor).toBe(outlineColor); expect(target.outlineWidth).toBe(outlineWidth); expect(target.dimensions).toBe(dimensions); + expect(target.shadows).toBe(shadows); }); it('clone works', function() { @@ -108,6 +118,7 @@ defineSuite([ source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); source.dimensions = new ConstantProperty(); + source.shadows = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -117,6 +128,7 @@ defineSuite([ expect(result.outlineColor).toBe(source.outlineColor); expect(result.outlineWidth).toBe(source.outlineWidth); expect(result.dimensions).toBe(source.dimensions); + expect(result.shadows).toBe(source.shadows); }); it('merge throws if source undefined', function() { @@ -135,5 +147,6 @@ defineSuite([ testDefinitionChanged(property, 'outlineColor', Color.RED, Color.BLUE); testDefinitionChanged(property, 'outlineWidth', 2, 3); testDefinitionChanged(property, 'dimensions', new Cartesian3(0, 0, 0), new Cartesian3(1, 1, 1)); + testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); }); }); diff --git a/Specs/DataSources/CorridorGeometryUpdaterSpec.js b/Specs/DataSources/CorridorGeometryUpdaterSpec.js index cfece3467b95..792933e5f7cc 100644 --- a/Specs/DataSources/CorridorGeometryUpdaterSpec.js +++ b/Specs/DataSources/CorridorGeometryUpdaterSpec.js @@ -19,7 +19,9 @@ defineSuite([ 'DataSources/SampledPositionProperty', 'DataSources/SampledProperty', 'DataSources/TimeIntervalCollectionProperty', + 'Scene/GroundPrimitive', 'Scene/PrimitiveCollection', + 'Scene/ShadowMode', 'Specs/createDynamicGeometryBoundingSphereSpecs', 'Specs/createDynamicProperty', 'Specs/createScene' @@ -43,7 +45,9 @@ defineSuite([ SampledPositionProperty, SampledProperty, TimeIntervalCollectionProperty, + GroundPrimitive, PrimitiveCollection, + ShadowMode, createDynamicGeometryBoundingSphereSpecs, createDynamicProperty, createScene) { @@ -51,10 +55,12 @@ defineSuite([ var scene; var time; + var groundPrimitiveSupported; beforeAll(function() { scene = createScene(); time = JulianDate.now(); + groundPrimitiveSupported = GroundPrimitive.isSupported(scene); }); afterAll(function() { @@ -104,6 +110,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -144,6 +151,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); expect(updater.isDynamic).toBe(false); }); @@ -385,8 +393,13 @@ defineSuite([ var updater = new CorridorGeometryUpdater(entity, scene); - expect(updater.onTerrain).toBe(true); - expect(updater.outlineEnabled).toBe(false); + if (groundPrimitiveSupported) { + expect(updater.onTerrain).toBe(true); + expect(updater.outlineEnabled).toBe(false); + } else { + expect(updater.onTerrain).toBe(false); + expect(updater.outlineEnabled).toBe(true); + } }); it('Checks that an entity with height isn\'t on terrain', function() { @@ -509,11 +522,11 @@ defineSuite([ it('dynamic updater on terrain', function() { var corridor = new CorridorGraphics(); corridor.positions = createDynamicProperty(Cartesian3.fromRadiansArray([ - 0, 0, - 1, 0, - 1, 1, - 0, 1 - ])); + 0, 0, + 1, 0, + 1, 1, + 0, 1 + ])); corridor.show = createDynamicProperty(true); corridor.outline = createDynamicProperty(true); corridor.fill = createDynamicProperty(true); @@ -533,8 +546,14 @@ defineSuite([ expect(groundPrimitives.length).toBe(0); dynamicUpdater.update(time); - expect(primitives.length).toBe(0); - expect(groundPrimitives.length).toBe(1); + + if (groundPrimitiveSupported) { + expect(primitives.length).toBe(0); + expect(groundPrimitives.length).toBe(1); + } else { + expect(primitives.length).toBe(2); + expect(groundPrimitives.length).toBe(0); + } dynamicUpdater.destroy(); updater.destroy(); @@ -646,7 +665,11 @@ defineSuite([ var entity = createBasicCorridorWithoutHeight(); entity.corridor.fill = true; var updater = new CorridorGeometryUpdater(entity, scene); - expect(updater.onTerrain).toBe(true); + if (groundPrimitiveSupported) { + expect(updater.onTerrain).toBe(true); + } else { + expect(updater.onTerrain).toBe(false); + } }); it('fill is false sets onTerrain to false', function() { @@ -677,7 +700,11 @@ defineSuite([ entity.corridor.fill = true; entity.corridor.material = new ColorMaterialProperty(Color.WHITE); var updater = new CorridorGeometryUpdater(entity, scene); - expect(updater.onTerrain).toBe(true); + if (groundPrimitiveSupported) { + expect(updater.onTerrain).toBe(true); + } else { + expect(updater.onTerrain).toBe(false); + } }); it('non-color material sets onTerrain to false', function() { diff --git a/Specs/DataSources/CorridorGraphicsSpec.js b/Specs/DataSources/CorridorGraphicsSpec.js index 7092b6a3900c..2fd38a6e6052 100644 --- a/Specs/DataSources/CorridorGraphicsSpec.js +++ b/Specs/DataSources/CorridorGraphicsSpec.js @@ -5,6 +5,7 @@ defineSuite([ 'Core/CornerType', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', + 'Scene/ShadowMode', 'Specs/testDefinitionChanged', 'Specs/testMaterialDefinitionChanged' ], function( @@ -13,6 +14,7 @@ defineSuite([ CornerType, ColorMaterialProperty, ConstantProperty, + ShadowMode, testDefinitionChanged, testMaterialDefinitionChanged) { 'use strict'; @@ -30,7 +32,8 @@ defineSuite([ outline : false, outlineColor : Color.RED, outlineWidth : 5, - cornerType : CornerType.BEVELED + cornerType : CornerType.BEVELED, + shadows : ShadowMode.DISABLED }; var corridor = new CorridorGraphics(options); @@ -46,6 +49,7 @@ defineSuite([ expect(corridor.outlineColor).toBeInstanceOf(ConstantProperty); expect(corridor.outlineWidth).toBeInstanceOf(ConstantProperty); expect(corridor.cornerType).toBeInstanceOf(ConstantProperty); + expect(corridor.shadows).toBeInstanceOf(ConstantProperty); expect(corridor.material.color.getValue()).toEqual(options.material); expect(corridor.positions.getValue()).toEqual(options.positions); @@ -59,6 +63,7 @@ defineSuite([ expect(corridor.outlineColor.getValue()).toEqual(options.outlineColor); expect(corridor.outlineWidth.getValue()).toEqual(options.outlineWidth); expect(corridor.cornerType.getValue()).toEqual(options.cornerType); + expect(corridor.shadows.getValue()).toEqual(options.shadows); }); it('merge assigns unassigned properties', function() { @@ -75,6 +80,7 @@ defineSuite([ source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); source.cornerType = new ConstantProperty(); + source.shadows = new ConstantProperty(ShadowMode.ENABLED); var target = new CorridorGraphics(); target.merge(source); @@ -91,6 +97,7 @@ defineSuite([ expect(target.outlineColor).toBe(source.outlineColor); expect(target.outlineWidth).toBe(source.outlineWidth); expect(target.cornerType).toBe(source.cornerType); + expect(target.shadows).toBe(source.shadows); }); it('merge does not assign assigned properties', function() { @@ -108,6 +115,7 @@ defineSuite([ var outlineColor = new ConstantProperty(); var outlineWidth = new ConstantProperty(); var cornerType = new ConstantProperty(); + var shadows = new ConstantProperty(); var target = new CorridorGraphics(); target.material = material; @@ -122,6 +130,7 @@ defineSuite([ target.outlineColor = outlineColor; target.outlineWidth = outlineWidth; target.cornerType = cornerType; + target.shadows = shadows; target.merge(source); @@ -137,6 +146,7 @@ defineSuite([ expect(target.outlineColor).toBe(outlineColor); expect(target.outlineWidth).toBe(outlineWidth); expect(target.cornerType).toBe(cornerType); + expect(target.shadows).toBe(shadows); }); it('clone works', function() { @@ -153,6 +163,7 @@ defineSuite([ source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); source.cornerType = new ConstantProperty(); + source.shadows = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -167,6 +178,7 @@ defineSuite([ expect(result.outlineColor).toBe(source.outlineColor); expect(result.outlineWidth).toBe(source.outlineWidth); expect(result.cornerType).toBe(source.cornerType); + expect(result.shadows).toBe(source.shadows); }); it('merge throws if source undefined', function() { @@ -190,5 +202,6 @@ defineSuite([ testDefinitionChanged(property, 'outlineColor', Color.RED, Color.BLUE); testDefinitionChanged(property, 'outlineWidth', 2, 3); testDefinitionChanged(property, 'cornerType', CornerType.BEVELED, CornerType.MITERED); + testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); }); }); diff --git a/Specs/DataSources/CylinderGeometryUpdaterSpec.js b/Specs/DataSources/CylinderGeometryUpdaterSpec.js index b023798d2915..21411b2ae099 100644 --- a/Specs/DataSources/CylinderGeometryUpdaterSpec.js +++ b/Specs/DataSources/CylinderGeometryUpdaterSpec.js @@ -19,6 +19,7 @@ defineSuite([ 'DataSources/SampledProperty', 'DataSources/TimeIntervalCollectionProperty', 'Scene/PrimitiveCollection', + 'Scene/ShadowMode', 'Specs/createDynamicGeometryBoundingSphereSpecs', 'Specs/createDynamicProperty', 'Specs/createScene' @@ -42,6 +43,7 @@ defineSuite([ SampledProperty, TimeIntervalCollectionProperty, PrimitiveCollection, + ShadowMode, createDynamicGeometryBoundingSphereSpecs, createDynamicProperty, createScene) { @@ -85,6 +87,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -145,6 +148,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); expect(updater.isDynamic).toBe(false); }); diff --git a/Specs/DataSources/CylinderGraphicsSpec.js b/Specs/DataSources/CylinderGraphicsSpec.js index 698e7b16f2e3..5a30f2c1bf6c 100644 --- a/Specs/DataSources/CylinderGraphicsSpec.js +++ b/Specs/DataSources/CylinderGraphicsSpec.js @@ -4,6 +4,7 @@ defineSuite([ 'Core/Color', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', + 'Scene/ShadowMode', 'Specs/testDefinitionChanged', 'Specs/testMaterialDefinitionChanged' ], function( @@ -11,6 +12,7 @@ defineSuite([ Color, ColorMaterialProperty, ConstantProperty, + ShadowMode, testDefinitionChanged, testMaterialDefinitionChanged) { 'use strict'; @@ -27,7 +29,8 @@ defineSuite([ fill : false, outline : false, outlineColor : Color.RED, - outlineWidth : 6 + outlineWidth : 6, + shadows : ShadowMode.DISABLED }; var cylinder = new CylinderGraphics(options); @@ -42,6 +45,7 @@ defineSuite([ expect(cylinder.outline).toBeInstanceOf(ConstantProperty); expect(cylinder.outlineColor).toBeInstanceOf(ConstantProperty); expect(cylinder.outlineWidth).toBeInstanceOf(ConstantProperty); + expect(cylinder.shadows).toBeInstanceOf(ConstantProperty); expect(cylinder.material.color.getValue()).toEqual(options.material); expect(cylinder.show.getValue()).toEqual(options.show); @@ -54,6 +58,7 @@ defineSuite([ expect(cylinder.outline.getValue()).toEqual(options.outline); expect(cylinder.outlineColor.getValue()).toEqual(options.outlineColor); expect(cylinder.outlineWidth.getValue()).toEqual(options.outlineWidth); + expect(cylinder.shadows.getValue()).toEqual(options.shadows); }); it('merge assigns unassigned properties', function() { @@ -68,6 +73,7 @@ defineSuite([ source.outline = new ConstantProperty(); source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); + source.shadows = new ConstantProperty(ShadowMode.ENABLED); var target = new CylinderGraphics(); target.merge(source); @@ -82,6 +88,7 @@ defineSuite([ expect(target.outline).toBe(source.outline); expect(target.outlineColor).toBe(source.outlineColor); expect(target.outlineWidth).toBe(source.outlineWidth); + expect(target.shadows).toBe(source.shadows); }); it('merge does not assign assigned properties', function() { @@ -97,6 +104,7 @@ defineSuite([ var outline = new ConstantProperty(); var outlineColor = new ConstantProperty(); var outlineWidth = new ConstantProperty(); + var shadows = new ConstantProperty(); var target = new CylinderGraphics(); target.material = material; @@ -109,6 +117,7 @@ defineSuite([ target.outline = outline; target.outlineColor = outlineColor; target.outlineWidth = outlineWidth; + target.shadows = shadows; target.merge(source); @@ -122,6 +131,7 @@ defineSuite([ expect(target.outline).toBe(outline); expect(target.outlineColor).toBe(outlineColor); expect(target.outlineWidth).toBe(outlineWidth); + expect(target.shadows).toBe(shadows); }); it('clone works', function() { @@ -136,6 +146,7 @@ defineSuite([ source.outline = new ConstantProperty(); source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); + source.shadows = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -148,6 +159,7 @@ defineSuite([ expect(result.outline).toBe(source.outline); expect(result.outlineColor).toBe(source.outlineColor); expect(result.outlineWidth).toBe(source.outlineWidth); + expect(result.shadows).toBe(source.shadows); }); it('merge throws if source undefined', function() { @@ -169,5 +181,6 @@ defineSuite([ testDefinitionChanged(property, 'outline', true, false); testDefinitionChanged(property, 'outlineColor', Color.RED, Color.BLUE); testDefinitionChanged(property, 'outlineWidth', 2, 3); + testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); }); }); diff --git a/Specs/DataSources/CzmlDataSourceSpec.js b/Specs/DataSources/CzmlDataSourceSpec.js index cf61c2dbe799..4e96c76e68fe 100644 --- a/Specs/DataSources/CzmlDataSourceSpec.js +++ b/Specs/DataSources/CzmlDataSourceSpec.js @@ -31,6 +31,7 @@ defineSuite([ 'Scene/HeightReference', 'Scene/HorizontalOrigin', 'Scene/LabelStyle', + 'Scene/ShadowMode', 'Scene/VerticalOrigin', 'Specs/pollToPromise', 'ThirdParty/when' @@ -66,6 +67,7 @@ defineSuite([ HeightReference, HorizontalOrigin, LabelStyle, + ShadowMode, VerticalOrigin, pollToPromise, when) { @@ -1023,7 +1025,8 @@ defineSuite([ outlineColor : { rgbaf : [0.2, 0.2, 0.2, 0.2] }, - outlineWidth : 6 + outlineWidth : 6, + shadows : 'ENABLED' } }; @@ -1038,6 +1041,7 @@ defineSuite([ expect(entity.ellipse.outline.getValue(Iso8601.MINIMUM_VALUE)).toEqual(true); expect(entity.ellipse.outlineColor.getValue(Iso8601.MINIMUM_VALUE)).toEqual(new Color(0.2, 0.2, 0.2, 0.2)); expect(entity.ellipse.outlineWidth.getValue(Iso8601.MINIMUM_VALUE)).toEqual(6); + expect(entity.ellipse.shadows.getValue(Iso8601.MINIMUM_VALUE)).toEqual(ShadowMode.ENABLED); }); it('CZML adds data for constrained ellipse.', function() { @@ -1046,7 +1050,8 @@ defineSuite([ interval : '2000-01-01/2001-01-01', semiMajorAxis : 10, semiMinorAxis : 20, - rotation : 1.0 + rotation : 1.0, + shadows : 'ENABLED' } }; @@ -1063,10 +1068,12 @@ defineSuite([ expect(entity.ellipse.semiMajorAxis.getValue(validTime)).toEqual(ellipsePacketInterval.ellipse.semiMajorAxis); expect(entity.ellipse.semiMinorAxis.getValue(validTime)).toEqual(ellipsePacketInterval.ellipse.semiMinorAxis); expect(entity.ellipse.rotation.getValue(validTime)).toEqual(ellipsePacketInterval.ellipse.rotation); + expect(entity.ellipse.shadows.getValue(validTime)).toEqual(ShadowMode.ENABLED); expect(entity.ellipse.semiMajorAxis.getValue(invalidTime)).toBeUndefined(); expect(entity.ellipse.semiMinorAxis.getValue(invalidTime)).toBeUndefined(); expect(entity.ellipse.rotation.getValue(invalidTime)).toBeUndefined(); + expect(entity.ellipse.shadows.getValue(invalidTime)).toBeUndefined(); }); it('CZML adds data for infinite ellipsoid.', function() { @@ -1092,7 +1099,8 @@ defineSuite([ outlineWidth : 6, stackPartitions : 25, slicePartitions : 26, - subdivisions : 27 + subdivisions : 27, + shadows : 'ENABLED' } }; @@ -1110,6 +1118,7 @@ defineSuite([ expect(entity.ellipsoid.stackPartitions.getValue(Iso8601.MINIMUM_VALUE)).toEqual(25); expect(entity.ellipsoid.slicePartitions.getValue(Iso8601.MINIMUM_VALUE)).toEqual(26); expect(entity.ellipsoid.subdivisions.getValue(Iso8601.MINIMUM_VALUE)).toEqual(27); + expect(entity.ellipsoid.shadows.getValue(Iso8601.MINIMUM_VALUE)).toEqual(ShadowMode.ENABLED); }); it('CZML adds data for constrained ellipsoid.', function() { @@ -1128,7 +1137,8 @@ defineSuite([ rgbaf : [0.1, 0.1, 0.1, 0.1] } } - } + }, + shadows : 'ENABLED' } }; @@ -1145,10 +1155,12 @@ defineSuite([ expect(entity.ellipsoid.radii.getValue(validTime)).toEqual(expectedRadii); expect(entity.ellipsoid.show.getValue(validTime)).toEqual(ellipsoidPacketInterval.ellipsoid.show); expect(entity.ellipsoid.material.getValue(validTime).color).toEqual(new Color(0.1, 0.1, 0.1, 0.1)); + expect(entity.ellipsoid.shadows.getValue(validTime)).toEqual(ShadowMode.ENABLED); expect(entity.ellipsoid.radii.getValue(invalidTime)).toBeUndefined(); expect(entity.ellipsoid.show.getValue(invalidTime)).toBeUndefined(); expect(entity.ellipsoid.material.getValue(invalidTime)).toBeUndefined(); + expect(entity.ellipsoid.shadows.getValue(invalidTime)).toBeUndefined(); }); it('CZML adds data for infinite label.', function() { @@ -1682,7 +1694,8 @@ defineSuite([ }, outlineWidth : 6, closeTop : false, - closeBottom : false + closeBottom : false, + shadows : 'ENABLED' } }; @@ -1702,6 +1715,7 @@ defineSuite([ expect(entity.polygon.outlineWidth.getValue(Iso8601.MINIMUM_VALUE)).toEqual(6); expect(entity.polygon.closeTop.getValue(Iso8601.MINIMUM_VALUE)).toEqual(false); expect(entity.polygon.closeBottom.getValue(Iso8601.MINIMUM_VALUE)).toEqual(false); + expect(entity.polygon.shadows.getValue(Iso8601.MINIMUM_VALUE)).toEqual(ShadowMode.ENABLED); }); it('CZML adds data for constrained polygon.', function() { @@ -1715,7 +1729,8 @@ defineSuite([ } } }, - show : true + show : true, + shadows : 'ENABLED' } }; @@ -1731,9 +1746,12 @@ defineSuite([ expect(entity.polygon).toBeDefined(); expect(entity.polygon.material.getValue(validTime).color).toEqual(new Color(0.1, 0.1, 0.1, 0.1)); expect(entity.polygon.show.getValue(validTime)).toEqual(true); + expect(entity.polygon.shadows.getValue(validTime)).toEqual(ShadowMode.ENABLED); expect(entity.polygon.material.getValue(invalidTime)).toBeUndefined(); expect(entity.polygon.show.getValue(invalidTime)).toBeUndefined(); + expect(entity.polygon.shadows.getValue(invalidTime)).toBeUndefined(); + }); it('CZML adds data for infinite polyline.', function() { @@ -1751,7 +1769,8 @@ defineSuite([ } }, width : 1.0, - show : true + show : true, + shadows : 'ENABLED' } }; @@ -1765,6 +1784,7 @@ defineSuite([ expect(entity.polyline.material.outlineColor.getValue(Iso8601.MINIMUM_VALUE)).toEqual(new Color(0.2, 0.2, 0.2, 0.2)); expect(entity.polyline.material.outlineWidth.getValue(Iso8601.MINIMUM_VALUE)).toEqual(1.0); expect(entity.polyline.show.getValue(Iso8601.MINIMUM_VALUE)).toEqual(true); + expect(entity.polyline.shadows.getValue(Iso8601.MINIMUM_VALUE)).toEqual(ShadowMode.ENABLED); }); it('CZML adds data for constrained polyline.', function() { @@ -1783,7 +1803,8 @@ defineSuite([ } }, width : 1.0, - show : true + show : true, + shadows : 'ENABLED' } }; @@ -1802,10 +1823,12 @@ defineSuite([ expect(entity.polyline.material.getValue(validTime).outlineColor).toEqual(new Color(0.2, 0.2, 0.2, 0.2)); expect(entity.polyline.material.getValue(validTime).outlineWidth).toEqual(1.0); expect(entity.polyline.show.getValue(validTime)).toEqual(true); + expect(entity.polyline.shadows.getValue(validTime)).toEqual(ShadowMode.ENABLED); expect(entity.polyline.material.getValue(invalidTime)).toBeUndefined(); expect(entity.polyline.width.getValue(invalidTime)).toBeUndefined(); expect(entity.polyline.show.getValue(invalidTime)).toBeUndefined(); + expect(entity.polyline.shadows.getValue(invalidTime)).toBeUndefined(); }); it('CZML adds data for infinite model.', function() { @@ -1817,8 +1840,7 @@ defineSuite([ maximumScale : 4.0, gltf : './Data/Models/Box/CesiumBoxTest.gltf', incrementallyLoadTextures : true, - castShadows : true, - receiveShadows : true, + shadows : 'ENABLED', heightReference: 'CLAMP_TO_GROUND', nodeTransformations : { Mesh : { @@ -1847,8 +1869,7 @@ defineSuite([ expect(entity.model.maximumScale.getValue(Iso8601.MINIMUM_VALUE)).toEqual(4.0); expect(entity.model.uri.getValue(Iso8601.MINIMUM_VALUE)).toEqual('./Data/Models/Box/CesiumBoxTest.gltf'); expect(entity.model.incrementallyLoadTextures.getValue(Iso8601.MINIMUM_VALUE)).toEqual(true); - expect(entity.model.castShadows.getValue(Iso8601.MINIMUM_VALUE)).toEqual(true); - expect(entity.model.receiveShadows.getValue(Iso8601.MINIMUM_VALUE)).toEqual(true); + expect(entity.model.shadows.getValue(Iso8601.MINIMUM_VALUE)).toEqual(ShadowMode.ENABLED); expect(entity.model.heightReference.getValue(Iso8601.MINIMUM_VALUE)).toEqual(HeightReference.CLAMP_TO_GROUND); var nodeTransform = entity.model.nodeTransformations.getValue(Iso8601.MINIMUM_VALUE).Mesh; @@ -1874,8 +1895,7 @@ defineSuite([ minimumPixelSize : 5.0, gltf : './Data/Models/Box/CesiumBoxTest.gltf', incrementallyLoadTextures : true, - castShadows : true, - receiveShadows : true, + shadows : 'ENABLED', nodeTransformations : { Mesh : { scale : { @@ -1907,8 +1927,7 @@ defineSuite([ expect(entity.model.minimumPixelSize.getValue(validTime)).toEqual(5.0); expect(entity.model.uri.getValue(validTime)).toEqual('./Data/Models/Box/CesiumBoxTest.gltf'); expect(entity.model.incrementallyLoadTextures.getValue(validTime)).toEqual(true); - expect(entity.model.castShadows.getValue(validTime)).toEqual(true); - expect(entity.model.receiveShadows.getValue(validTime)).toEqual(true); + expect(entity.model.shadows.getValue(validTime)).toEqual(ShadowMode.ENABLED); var nodeTransform = entity.model.nodeTransformations.getValue(validTime).Mesh; expect(nodeTransform).toBeDefined(); @@ -1928,8 +1947,7 @@ defineSuite([ expect(entity.model.minimumPixelSize.getValue(invalidTime)).toBeUndefined(); expect(entity.model.uri.getValue(invalidTime)).toBeUndefined(); expect(entity.model.incrementallyLoadTextures.getValue(invalidTime)).toBeUndefined(); - expect(entity.model.castShadows.getValue(invalidTime)).toBeUndefined(); - expect(entity.model.receiveShadows.getValue(invalidTime)).toBeUndefined(); + expect(entity.model.shadows.getValue(invalidTime)).toBeUndefined(); expect(entity.model.nodeTransformations.Mesh.getValue(invalidTime)).toEqual(new TranslationRotationScale()); expect(entity.model.nodeTransformations.Mesh.scale.getValue(invalidTime)).toBeUndefined(); @@ -2149,7 +2167,8 @@ defineSuite([ outlineColor : { rgbaf : [0.2, 0.2, 0.2, 0.2] }, - outlineWidth : 6 + outlineWidth : 6, + shadows : 'ENABLED' } }; @@ -2173,6 +2192,7 @@ defineSuite([ expect(entity.rectangle.outline.getValue(Iso8601.MINIMUM_VALUE)).toEqual(true); expect(entity.rectangle.outlineColor.getValue(Iso8601.MINIMUM_VALUE)).toEqual(new Color(0.2, 0.2, 0.2, 0.2)); expect(entity.rectangle.outlineWidth.getValue(Iso8601.MINIMUM_VALUE)).toEqual(6); + expect(entity.rectangle.shadows.getValue(Iso8601.MINIMUM_VALUE)).toEqual(ShadowMode.ENABLED); }); it('can handle constant rectangle coordinates in degrees.', function() { @@ -2264,7 +2284,8 @@ defineSuite([ outlineColor : { rgbaf : [0.2, 0.2, 0.2, 0.2] }, - outlineWidth : 6 + outlineWidth : 6, + shadows : 'ENABLED' } }; @@ -2283,6 +2304,7 @@ defineSuite([ expect(entity.wall.outline.getValue(Iso8601.MINIMUM_VALUE)).toEqual(true); expect(entity.wall.outlineColor.getValue(Iso8601.MINIMUM_VALUE)).toEqual(new Color(0.2, 0.2, 0.2, 0.2)); expect(entity.wall.outlineWidth.getValue(Iso8601.MINIMUM_VALUE)).toEqual(6); + expect(entity.wall.shadows.getValue(Iso8601.MINIMUM_VALUE)).toEqual(ShadowMode.ENABLED); }); it('CZML adds data for wall with minimumHeights as references.', function() { @@ -2338,7 +2360,8 @@ defineSuite([ outlineColor : { rgbaf : [0.2, 0.2, 0.2, 0.2] }, - outlineWidth : 6 + outlineWidth : 6, + shadows : 'ENABLED' } }; @@ -2353,6 +2376,7 @@ defineSuite([ expect(entity.box.outline.getValue(Iso8601.MINIMUM_VALUE)).toEqual(true); expect(entity.box.outlineColor.getValue(Iso8601.MINIMUM_VALUE)).toEqual(new Color(0.2, 0.2, 0.2, 0.2)); expect(entity.box.outlineWidth.getValue(Iso8601.MINIMUM_VALUE)).toEqual(6); + expect(entity.box.shadows.getValue(Iso8601.MINIMUM_VALUE)).toEqual(ShadowMode.ENABLED); }); it('CZML adds data for cylinder.', function() { @@ -2375,7 +2399,8 @@ defineSuite([ }, outlineWidth : 6, numberOfVerticalLines : 15, - slices : 100 + slices : 100, + shadows : 'ENABLED' } }; @@ -2394,6 +2419,7 @@ defineSuite([ expect(entity.cylinder.outlineWidth.getValue(Iso8601.MINIMUM_VALUE)).toEqual(6); expect(entity.cylinder.numberOfVerticalLines.getValue(Iso8601.MINIMUM_VALUE)).toEqual(15); expect(entity.cylinder.slices.getValue(Iso8601.MINIMUM_VALUE)).toEqual(100); + expect(entity.cylinder.shadows.getValue(Iso8601.MINIMUM_VALUE)).toEqual(ShadowMode.ENABLED); }); it('CZML adds data for corridor.', function() { @@ -2421,7 +2447,8 @@ defineSuite([ outlineColor : { rgbaf : [0.2, 0.2, 0.2, 0.2] }, - outlineWidth : 6 + outlineWidth : 6, + shadows : 'ENABLED' } }; @@ -2443,6 +2470,7 @@ defineSuite([ expect(entity.corridor.outline.getValue(Iso8601.MINIMUM_VALUE)).toEqual(true); expect(entity.corridor.outlineColor.getValue(Iso8601.MINIMUM_VALUE)).toEqual(new Color(0.2, 0.2, 0.2, 0.2)); expect(entity.corridor.outlineWidth.getValue(Iso8601.MINIMUM_VALUE)).toEqual(6); + expect(entity.corridor.shadows.getValue(Iso8601.MINIMUM_VALUE)).toEqual(ShadowMode.ENABLED); }); it('Has entity collection with link to data source', function() { diff --git a/Specs/DataSources/DataSourceDisplaySpec.js b/Specs/DataSources/DataSourceDisplaySpec.js index 2a8b59a21725..4f33a811f5a1 100644 --- a/Specs/DataSources/DataSourceDisplaySpec.js +++ b/Specs/DataSources/DataSourceDisplaySpec.js @@ -7,6 +7,7 @@ defineSuite([ 'DataSources/BoundingSphereState', 'DataSources/DataSourceCollection', 'DataSources/Entity', + 'Scene/GroundPrimitive', 'Specs/createScene', 'Specs/MockDataSource' ], function( @@ -17,6 +18,7 @@ defineSuite([ BoundingSphereState, DataSourceCollection, Entity, + GroundPrimitive, createScene, MockDataSource) { 'use strict'; @@ -27,10 +29,17 @@ defineSuite([ beforeAll(function() { scene = createScene(); dataSourceCollection = new DataSourceCollection(); + + return GroundPrimitive.initializeTerrainHeights(); }); afterAll(function() { scene.destroyForSpecs(); + + // Leave ground primitive uninitialized + GroundPrimitive._initialized = false; + GroundPrimitive._initPromise = undefined; + GroundPrimitive._terrainHeights = undefined; }); afterEach(function() { @@ -109,6 +118,8 @@ defineSuite([ dataSource.entities.add(entity); display.dataSources.add(dataSource); + display.update(Iso8601.MINIMUM_VALUE); + var result = new BoundingSphere(); var state = display.getBoundingSphere(entity, true, result); @@ -140,6 +151,8 @@ defineSuite([ dataSource.entities.add(entity); display.dataSources.add(dataSource); + display.update(Iso8601.MINIMUM_VALUE); + var result = new BoundingSphere(); var state = display.getBoundingSphere(entity, true, result); @@ -182,6 +195,8 @@ defineSuite([ var dataSource = new MockDataSource(); dataSource.entities.add(entity); display.dataSources.add(dataSource); + display.update(Iso8601.MINIMUM_VALUE); + var result = new BoundingSphere(); var state = display.getBoundingSphere(entity, false, result); expect(state).toBe(BoundingSphereState.FAILED); @@ -193,6 +208,8 @@ defineSuite([ dataSourceCollection : dataSourceCollection, scene : scene }); + display.update(Iso8601.MINIMUM_VALUE); + var entity = new Entity(); var result = new BoundingSphere(); var state = display.getBoundingSphere(entity, false, result); @@ -339,4 +356,28 @@ defineSuite([ return display.update(); }).toThrowDeveloperError(); }); + + it('verify update returns false till terrain heights are initialized', function() { + GroundPrimitive._initialized = false; + GroundPrimitive._initPromise = undefined; + GroundPrimitive._terrainHeights = undefined; + + var source1 = new MockDataSource(); + var source2 = new MockDataSource(); + + display = new DataSourceDisplay({ + scene : scene, + dataSourceCollection : dataSourceCollection, + visualizersCallback : visualizersCallback + }); + dataSourceCollection.add(source1); + dataSourceCollection.add(source2); + display.update(Iso8601.MINIMUM_VALUE); + expect(display.ready).toBe(false); + + return GroundPrimitive.initializeTerrainHeights().then(function() { + display.update(Iso8601.MINIMUM_VALUE); + expect(display.ready).toBe(true); + }); + }); }, 'WebGL'); diff --git a/Specs/DataSources/EllipseGeometryUpdaterSpec.js b/Specs/DataSources/EllipseGeometryUpdaterSpec.js index 1a6b5f9e282a..4df887e1a075 100644 --- a/Specs/DataSources/EllipseGeometryUpdaterSpec.js +++ b/Specs/DataSources/EllipseGeometryUpdaterSpec.js @@ -18,7 +18,9 @@ defineSuite([ 'DataSources/SampledPositionProperty', 'DataSources/SampledProperty', 'DataSources/TimeIntervalCollectionProperty', + 'Scene/GroundPrimitive', 'Scene/PrimitiveCollection', + 'Scene/ShadowMode', 'Specs/createDynamicGeometryBoundingSphereSpecs', 'Specs/createDynamicProperty', 'Specs/createScene' @@ -41,7 +43,9 @@ defineSuite([ SampledPositionProperty, SampledProperty, TimeIntervalCollectionProperty, + GroundPrimitive, PrimitiveCollection, + ShadowMode, createDynamicGeometryBoundingSphereSpecs, createDynamicProperty, createScene) { @@ -49,10 +53,12 @@ defineSuite([ var scene; var time; + var groundPrimitiveSupported; beforeAll(function() { scene = createScene(); time = JulianDate.now(); + groundPrimitiveSupported = GroundPrimitive.isSupported(scene); }); afterAll(function() { @@ -100,6 +106,7 @@ defineSuite([ expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); + expect(updater.shadowsProperty).toBe(undefined); updater.destroy(); expect(updater.isDestroyed()).toBe(true); }); @@ -158,6 +165,7 @@ defineSuite([ expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); expect(updater.isDynamic).toBe(false); + expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); }); it('Ellipse material is correctly exposed.', function() { @@ -432,8 +440,13 @@ defineSuite([ var updater = new EllipseGeometryUpdater(entity, scene); - expect(updater.onTerrain).toBe(true); - expect(updater.outlineEnabled).toBe(false); + if (groundPrimitiveSupported) { + expect(updater.onTerrain).toBe(true); + expect(updater.outlineEnabled).toBe(false); + } else { + expect(updater.onTerrain).toBe(false); + expect(updater.outlineEnabled).toBe(true); + } }); it('Checks that an entity with height isn\'t on terrain', function() { @@ -569,8 +582,14 @@ defineSuite([ expect(groundPrimitives.length).toBe(0); dynamicUpdater.update(time); - expect(primitives.length).toBe(0); - expect(groundPrimitives.length).toBe(1); + + if (groundPrimitiveSupported) { + expect(primitives.length).toBe(0); + expect(groundPrimitives.length).toBe(1); + } else { + expect(primitives.length).toBe(2); + expect(groundPrimitives.length).toBe(0); + } dynamicUpdater.destroy(); updater.destroy(); @@ -684,7 +703,11 @@ defineSuite([ var entity = createBasicEllipseWithoutHeight(); entity.ellipse.fill = true; var updater = new EllipseGeometryUpdater(entity, scene); - expect(updater.onTerrain).toBe(true); + if (groundPrimitiveSupported) { + expect(updater.onTerrain).toBe(true); + } else { + expect(updater.onTerrain).toBe(false); + } }); it('fill is false sets onTerrain to false', function() { @@ -715,7 +738,11 @@ defineSuite([ entity.ellipse.fill = true; entity.ellipse.material = new ColorMaterialProperty(Color.WHITE); var updater = new EllipseGeometryUpdater(entity, scene); - expect(updater.onTerrain).toBe(true); + if (groundPrimitiveSupported) { + expect(updater.onTerrain).toBe(true); + } else { + expect(updater.onTerrain).toBe(false); + } }); it('non-color material sets onTerrain to false', function() { diff --git a/Specs/DataSources/EllipseGraphicsSpec.js b/Specs/DataSources/EllipseGraphicsSpec.js index 7dba5c335213..48a3d1d019b5 100644 --- a/Specs/DataSources/EllipseGraphicsSpec.js +++ b/Specs/DataSources/EllipseGraphicsSpec.js @@ -4,6 +4,7 @@ defineSuite([ 'Core/Color', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', + 'Scene/ShadowMode', 'Specs/testDefinitionChanged', 'Specs/testMaterialDefinitionChanged' ], function( @@ -11,6 +12,7 @@ defineSuite([ Color, ColorMaterialProperty, ConstantProperty, + ShadowMode, testDefinitionChanged, testMaterialDefinitionChanged) { 'use strict'; @@ -30,7 +32,8 @@ defineSuite([ fill : false, outline : false, outlineColor : Color.RED, - outlineWidth : 9 + outlineWidth : 9, + shadows : ShadowMode.DISABLED }; var ellipse = new EllipseGraphics(options); @@ -48,6 +51,7 @@ defineSuite([ expect(ellipse.outline).toBeInstanceOf(ConstantProperty); expect(ellipse.outlineColor).toBeInstanceOf(ConstantProperty); expect(ellipse.outlineWidth).toBeInstanceOf(ConstantProperty); + expect(ellipse.shadows).toBeInstanceOf(ConstantProperty); expect(ellipse.material.color.getValue()).toEqual(options.material); expect(ellipse.show.getValue()).toEqual(options.show); @@ -63,6 +67,7 @@ defineSuite([ expect(ellipse.outline.getValue()).toEqual(options.outline); expect(ellipse.outlineColor.getValue()).toEqual(options.outlineColor); expect(ellipse.outlineWidth.getValue()).toEqual(options.outlineWidth); + expect(ellipse.shadows.getValue()).toEqual(options.shadows); }); it('merge assigns unassigned properties', function() { @@ -81,6 +86,7 @@ defineSuite([ source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); source.numberOfVerticalLines = new ConstantProperty(); + source.shadows = new ConstantProperty(ShadowMode.ENABLED); var target = new EllipseGraphics(); target.merge(source); @@ -99,6 +105,7 @@ defineSuite([ expect(target.outlineColor).toBe(source.outlineColor); expect(target.outlineWidth).toBe(source.outlineWidth); expect(target.numberOfVerticalLines).toBe(source.numberOfVerticalLines); + expect(target.shadows).toBe(source.shadows); }); it('merge does not assign assigned properties', function() { @@ -118,6 +125,7 @@ defineSuite([ var outlineColor = new ConstantProperty(); var outlineWidth = new ConstantProperty(); var numberOfVerticalLines = new ConstantProperty(); + var shadows = new ConstantProperty(); var target = new EllipseGraphics(); target.material = material; @@ -134,6 +142,7 @@ defineSuite([ target.outlineColor = outlineColor; target.outlineWidth = outlineWidth; target.numberOfVerticalLines = numberOfVerticalLines; + target.shadows = shadows; target.merge(source); @@ -151,6 +160,7 @@ defineSuite([ expect(target.outlineColor).toBe(outlineColor); expect(target.outlineWidth).toBe(outlineWidth); expect(target.numberOfVerticalLines).toBe(numberOfVerticalLines); + expect(target.shadows).toBe(shadows); }); it('clone works', function() { @@ -169,6 +179,7 @@ defineSuite([ source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); source.numberOfVerticalLines = new ConstantProperty(); + source.shadows = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -185,6 +196,7 @@ defineSuite([ expect(result.outlineColor).toBe(source.outlineColor); expect(result.outlineWidth).toBe(source.outlineWidth); expect(result.numberOfVerticalLines).toBe(source.numberOfVerticalLines); + expect(result.shadows).toBe(source.shadows); }); it('merge throws if source undefined', function() { @@ -210,5 +222,6 @@ defineSuite([ testDefinitionChanged(property, 'outlineColor', Color.RED, Color.BLUE); testDefinitionChanged(property, 'outlineWidth', 2, 3); testDefinitionChanged(property, 'numberOfVerticalLines', 16, 32); + testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); }); }); diff --git a/Specs/DataSources/EllipsoidGeometryUpdaterSpec.js b/Specs/DataSources/EllipsoidGeometryUpdaterSpec.js index 080fb029a537..5df189f584dc 100644 --- a/Specs/DataSources/EllipsoidGeometryUpdaterSpec.js +++ b/Specs/DataSources/EllipsoidGeometryUpdaterSpec.js @@ -19,6 +19,7 @@ defineSuite([ 'DataSources/SampledProperty', 'DataSources/TimeIntervalCollectionProperty', 'Scene/PrimitiveCollection', + 'Scene/ShadowMode', 'Specs/createDynamicGeometryBoundingSphereSpecs', 'Specs/createDynamicProperty', 'Specs/createScene' @@ -42,6 +43,7 @@ defineSuite([ SampledProperty, TimeIntervalCollectionProperty, PrimitiveCollection, + ShadowMode, createDynamicGeometryBoundingSphereSpecs, createDynamicProperty, createScene) { @@ -82,6 +84,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -131,6 +134,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); expect(updater.isDynamic).toBe(false); }); diff --git a/Specs/DataSources/EllipsoidGraphicsSpec.js b/Specs/DataSources/EllipsoidGraphicsSpec.js index 9e26bab8e4a0..aac4cc2bc0b9 100644 --- a/Specs/DataSources/EllipsoidGraphicsSpec.js +++ b/Specs/DataSources/EllipsoidGraphicsSpec.js @@ -5,6 +5,7 @@ defineSuite([ 'Core/Color', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', + 'Scene/ShadowMode', 'Specs/testDefinitionChanged', 'Specs/testMaterialDefinitionChanged' ], function( @@ -13,6 +14,7 @@ defineSuite([ Color, ColorMaterialProperty, ConstantProperty, + ShadowMode, testDefinitionChanged, testMaterialDefinitionChanged) { 'use strict'; @@ -27,7 +29,8 @@ defineSuite([ fill : false, outline : false, outlineColor : Color.RED, - outlineWidth : 4 + outlineWidth : 4, + shadows : ShadowMode.DISABLED }; var ellipsoid = new EllipsoidGraphics(options); @@ -40,6 +43,7 @@ defineSuite([ expect(ellipsoid.outline).toBeInstanceOf(ConstantProperty); expect(ellipsoid.outlineColor).toBeInstanceOf(ConstantProperty); expect(ellipsoid.outlineWidth).toBeInstanceOf(ConstantProperty); + expect(ellipsoid.shadows).toBeInstanceOf(ConstantProperty); expect(ellipsoid.material.color.getValue()).toEqual(options.material); expect(ellipsoid.show.getValue()).toEqual(options.show); @@ -50,6 +54,7 @@ defineSuite([ expect(ellipsoid.outline.getValue()).toEqual(options.outline); expect(ellipsoid.outlineColor.getValue()).toEqual(options.outlineColor); expect(ellipsoid.outlineWidth.getValue()).toEqual(options.outlineWidth); + expect(ellipsoid.shadows.getValue()).toEqual(options.shadows); }); it('merge assigns unassigned properties', function() { @@ -64,6 +69,7 @@ defineSuite([ source.outline = new ConstantProperty(); source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); + source.shadows = new ConstantProperty(ShadowMode.ENABLED); var target = new EllipsoidGraphics(); target.merge(source); @@ -78,6 +84,7 @@ defineSuite([ expect(target.outline).toBe(source.outline); expect(target.outlineColor).toBe(source.outlineColor); expect(target.outlineWidth).toBe(source.outlineWidth); + expect(target.shadows).toBe(source.shadows); }); it('merge does not assign assigned properties', function() { @@ -93,6 +100,7 @@ defineSuite([ var outline = new ConstantProperty(); var outlineColor = new ConstantProperty(); var outlineWidth = new ConstantProperty(); + var shadows = new ConstantProperty(); var target = new EllipsoidGraphics(); target.material = material; @@ -101,6 +109,8 @@ defineSuite([ target.stackPartitions = stackPartitions; target.slicePartitions = slicePartitions; target.subdivisions = subdivisions; + target.shadows = shadows; + source.fill = fill; source.outline = outline; source.outlineColor = outlineColor; @@ -118,6 +128,7 @@ defineSuite([ expect(target.outline).toBe(outline); expect(target.outlineColor).toBe(outlineColor); expect(target.outlineWidth).toBe(outlineWidth); + expect(target.shadows).toBe(shadows); }); it('clone works', function() { @@ -132,6 +143,7 @@ defineSuite([ source.outline = new ConstantProperty(); source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); + source.shadows = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -144,6 +156,7 @@ defineSuite([ expect(result.outline).toBe(source.outline); expect(result.outlineColor).toBe(source.outlineColor); expect(result.outlineWidth).toBe(source.outlineWidth); + expect(result.shadows).toBe(source.shadows); }); it('merge throws if source undefined', function() { @@ -165,5 +178,6 @@ defineSuite([ testDefinitionChanged(property, 'outline', true, false); testDefinitionChanged(property, 'outlineColor', Color.RED, Color.BLUE); testDefinitionChanged(property, 'outlineWidth', 2, 3); + testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); }); }); diff --git a/Specs/DataSources/GeometryVisualizerSpec.js b/Specs/DataSources/GeometryVisualizerSpec.js index f7b897a052cd..285d295be647 100644 --- a/Specs/DataSources/GeometryVisualizerSpec.js +++ b/Specs/DataSources/GeometryVisualizerSpec.js @@ -22,6 +22,8 @@ defineSuite([ 'DataSources/StaticGeometryPerMaterialBatch', 'DataSources/StaticGroundGeometryColorBatch', 'DataSources/StaticOutlineGeometryBatch', + 'Scene/GroundPrimitive', + 'Scene/ShadowMode', 'Specs/createDynamicProperty', 'Specs/createScene', 'Specs/pollToPromise' @@ -48,6 +50,8 @@ defineSuite([ StaticGeometryPerMaterialBatch, StaticGroundGeometryColorBatch, StaticOutlineGeometryBatch, + GroundPrimitive, + ShadowMode, createDynamicProperty, createScene, pollToPromise) { @@ -58,10 +62,17 @@ defineSuite([ var scene; beforeAll(function() { scene = createScene(); + + return GroundPrimitive.initializeTerrainHeights(); }); afterAll(function() { scene.destroyForSpecs(); + + // Leave ground primitive uninitialized + GroundPrimitive._initialized = false; + GroundPrimitive._initPromise = undefined; + GroundPrimitive._terrainHeights = undefined; }); it('Can create and destroy', function() { @@ -283,6 +294,60 @@ defineSuite([ }); }); + function createAndRemoveGeometryWithShadows(shadows) { + var objects = new EntityCollection(); + var visualizer = new GeometryVisualizer(EllipseGeometryUpdater, scene, objects); + + var ellipse = new EllipseGraphics(); + ellipse.semiMajorAxis = new ConstantProperty(2); + ellipse.semiMinorAxis = new ConstantProperty(1); + ellipse.material = new ColorMaterialProperty(); + ellipse.extrudedHeight = new ConstantProperty(1000); + ellipse.shadows = new ConstantProperty(shadows); + + 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.primitives.get(0); + expect(primitive.shadows).toBe(shadows); + + objects.remove(entity); + + return pollToPromise(function() { + scene.initializeFrame(); + expect(visualizer.update(time)).toBe(true); + scene.render(time); + return scene.primitives.length === 0; + }).then(function(){ + visualizer.destroy(); + }); + }); + } + + it('Creates and removes geometry with shadows disabled', function() { + return createAndRemoveGeometryWithShadows(ShadowMode.DISABLED); + }); + + it('Creates and removes geometry with shadows enabled', function() { + return createAndRemoveGeometryWithShadows(ShadowMode.ENABLED); + }); + + it('Creates and removes geometry with shadow casting only', function() { + return createAndRemoveGeometryWithShadows(ShadowMode.CAST_ONLY); + }); + + it('Creates and removes geometry with shadow receiving only', function() { + return createAndRemoveGeometryWithShadows(ShadowMode.RECEIVE_ONLY); + }); + it('Correctly handles geometry changing batches', function() { var objects = new EntityCollection(); var visualizer = new GeometryVisualizer(EllipseGeometryUpdater, scene, objects); @@ -389,6 +454,33 @@ defineSuite([ var objects = new EntityCollection(); var visualizer = new GeometryVisualizer(EllipseGeometryUpdater, scene, objects); + var ellipse = new EllipseGraphics(); + ellipse.semiMajorAxis = new SampledProperty(Number); + ellipse.semiMajorAxis.addSample(time, 2); + ellipse.semiMinorAxis = new ConstantProperty(1); + ellipse.extrudedHeight = new ConstantProperty(1000); + ellipse.material = new ColorMaterialProperty(); + + var entity = new Entity(); + entity.position = new ConstantPositionProperty(new Cartesian3(1234, 5678, 9101112)); + entity.ellipse = ellipse; + objects.add(entity); + + scene.initializeFrame(); + expect(visualizer.update(time)).toBe(true); + scene.render(time); + objects.remove(entity); + scene.initializeFrame(); + expect(visualizer.update(time)).toBe(true); + scene.render(time); + expect(scene.primitives.length).toBe(0); + visualizer.destroy(); + }); + + it('Creates and removes dynamic geometry on terrain ', function() { + var objects = new EntityCollection(); + var visualizer = new GeometryVisualizer(EllipseGeometryUpdater, scene, objects); + var ellipse = new EllipseGraphics(); ellipse.semiMajorAxis = new SampledProperty(Number); ellipse.semiMajorAxis.addSample(time, 2); @@ -441,7 +533,7 @@ defineSuite([ }); it('StaticGeometryPerMaterialBatch handles shared material being invalidated', function() { - var batch = new StaticGeometryPerMaterialBatch(scene.primitives, EllipseGeometryUpdater.materialAppearanceType, false); + var batch = new StaticGeometryPerMaterialBatch(scene.primitives, EllipseGeometryUpdater.materialAppearanceType, false, ShadowMode.DISABLED); var ellipse = new EllipseGraphics(); ellipse.semiMajorAxis = new ConstantProperty(2); @@ -488,7 +580,7 @@ defineSuite([ }); it('StaticGeometryColorBatch updates color attribute after rebuilding primitive', function() { - var batch = new StaticGeometryColorBatch(scene.primitives, EllipseGeometryUpdater.materialAppearanceType, false); + var batch = new StaticGeometryColorBatch(scene.primitives, EllipseGeometryUpdater.materialAppearanceType, false, ShadowMode.DISABLED); var entity = new Entity({ position : new Cartesian3(1234, 5678, 9101112), @@ -536,6 +628,10 @@ defineSuite([ }); it('StaticGroundGeometryColorBatch updates color attribute after rebuilding primitive', function() { + if (!GroundPrimitive.isSupported(scene)) { + return; + } + var batch = new StaticGroundGeometryColorBatch(scene.groundPrimitives); function computeKey(color) { @@ -604,7 +700,7 @@ defineSuite([ }); it('StaticOutlineGeometryBatch updates color attribute after rebuilding primitive', function() { - var batch = new StaticOutlineGeometryBatch(scene.primitives, scene, false); + var batch = new StaticOutlineGeometryBatch(scene.primitives, scene, false, ShadowMode.DISABLED); var entity = new Entity({ position : new Cartesian3(1234, 5678, 9101112), @@ -774,7 +870,7 @@ defineSuite([ }); }); - it('Sets static geometry primitive show attribute when using dynamic fill color', function() { + it('Sets static geometry primitive show attribute when using dynamic fill color', function() { var entities = new EntityCollection(); var visualizer = new GeometryVisualizer(EllipseGeometryUpdater, scene, entities); @@ -818,7 +914,7 @@ defineSuite([ }); }); - it('Sets static geometry primitive show attribute when using dynamic outline color', function() { + it('Sets static geometry primitive show attribute when using dynamic outline color', function() { var entities = new EntityCollection(); var visualizer = new GeometryVisualizer(EllipseGeometryUpdater, scene, entities); diff --git a/Specs/DataSources/KmlDataSourceSpec.js b/Specs/DataSources/KmlDataSourceSpec.js index 5195426a9b40..8b5c304c592a 100644 --- a/Specs/DataSources/KmlDataSourceSpec.js +++ b/Specs/DataSources/KmlDataSourceSpec.js @@ -7,6 +7,7 @@ defineSuite([ 'Core/ClockRange', 'Core/ClockStep', 'Core/Color', + 'Core/combine', 'Core/DefaultProxy', 'Core/Event', 'Core/Iso8601', @@ -37,6 +38,7 @@ defineSuite([ ClockRange, ClockStep, Color, + combine, DefaultProxy, Event, Iso8601, @@ -102,7 +104,7 @@ defineSuite([ var uberIconColor = Color.fromBytes(0xdd, 0xdd, 0xdd, 0xdd); var uberIconScale = 3; var uberIconHeading = CesiumMath.toRadians(-45); - var uberIconHotspot = new Cartesian2(45, -46); + var uberIconHotspot = new Cartesian2(45, -42); var uberLabelColor = Color.fromBytes(0xee, 0xee, 0xee, 0xee); var uberLabelScale = 4; @@ -336,10 +338,11 @@ defineSuite([ expect(spy.calls.count()).toEqual(3); for (var i = 0; i < nodeNames.length; i++) { var args = spy.calls.argsFor(i); - expect(args.length).toEqual(3); + expect(args.length).toEqual(7); expect(args[0]).toBe(dataSource); - expect(args[1].localName).toEqual(nodeNames[i]); - // args[2] could be undefined, allow for that + expect(args[2].localName).toEqual(nodeNames[i]); + expect(args[3]).toBeInstanceOf(EntityCollection); + expect(args[4]).toBeInstanceOf(EntityCollection); } }); }); @@ -1568,7 +1571,7 @@ defineSuite([ return KmlDataSource.load(parser.parseFromString(kml, "text/xml"), options).then(function(dataSource) { var billboard = dataSource.entities.values[0].billboard; - expect(billboard.pixelOffset.getValue()).toEqual(new Cartesian2(-15, -18)); + expect(billboard.pixelOffset.getValue()).toEqual(new Cartesian2(-15, 14)); }); }); @@ -2183,6 +2186,7 @@ defineSuite([ var entities = dataSource.entities.values; expect(entities.length).toEqual(1); expect(entities[0].position.getValue(Iso8601.MINIMUM_VALUE)).toEqual(Cartesian3.fromDegrees(1, 2, 3)); + expect(entities[0].billboard.pixelOffset).toBeUndefined(); expect(entities[0].polyline).toBeUndefined(); }); }); @@ -2191,7 +2195,7 @@ defineSuite([ var kml = '\ \ \ - absolute\ + relativeToGround\ 1,2,3\ \ '; @@ -2200,6 +2204,7 @@ defineSuite([ var entities = dataSource.entities.values; expect(entities.length).toEqual(1); expect(entities[0].position.getValue(Iso8601.MINIMUM_VALUE)).toEqual(Cartesian3.fromDegrees(1, 2, 3)); + expect(entities[0].billboard.pixelOffset).toBeUndefined(); expect(entities[0].polyline).toBeUndefined(); }); }); @@ -2217,7 +2222,8 @@ defineSuite([ return KmlDataSource.load(parser.parseFromString(kml, "text/xml"), options).then(function(dataSource) { var entities = dataSource.entities.values; expect(entities.length).toEqual(1); - expect(entities[0].position.getValue(Iso8601.MINIMUM_VALUE)).toEqual(Cartesian3.fromDegrees(1, 2)); + expect(entities[0].position.getValue(Iso8601.MINIMUM_VALUE)).toEqual(Cartesian3.fromDegrees(1, 2, 0)); + expect(entities[0].billboard.pixelOffset).toBeUndefined(); expect(entities[0].polyline).toBeUndefined(); }); }); @@ -3827,4 +3833,28 @@ defineSuite([ expect(entity.polygon.height.getValue()).toEqual(0); }); }); + + it('when a LineString is clamped to ground and tesselated, entity has a corridor geometry and ColorProperty', function() { + var kml = '\ + \ + \ + \ + clampToGround\ + true\ + 1,2,3\ + 4,5,6\ + \ + \ + '; + 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.material).toBeInstanceOf(ColorMaterialProperty); + }); + }); }); diff --git a/Specs/DataSources/ModelGraphicsSpec.js b/Specs/DataSources/ModelGraphicsSpec.js index c7a2d6378e7f..2e24688d577c 100644 --- a/Specs/DataSources/ModelGraphicsSpec.js +++ b/Specs/DataSources/ModelGraphicsSpec.js @@ -6,7 +6,8 @@ defineSuite([ 'Core/Quaternion', 'DataSources/ConstantProperty', 'DataSources/NodeTransformationProperty', - 'DataSources/PropertyBag' + 'DataSources/PropertyBag', + 'Scene/ShadowMode' ], function( ModelGraphics, Cartesian3, @@ -14,7 +15,8 @@ defineSuite([ Quaternion, ConstantProperty, NodeTransformationProperty, - PropertyBag) { + PropertyBag, + ShadowMode) { 'use strict'; it('creates expected instance from raw assignment and construction', function() { @@ -25,9 +27,8 @@ defineSuite([ minimumPixelSize : 2, maximumScale : 200, incrementallyLoadTextures : false, - castShadows : false, - receiveShadows : false, runAnimations : false, + shadows : ShadowMode.DISABLED, nodeTransformations : { node1 : { translation : Cartesian3.UNIT_Y, @@ -44,8 +45,7 @@ defineSuite([ expect(model.minimumPixelSize).toBeInstanceOf(ConstantProperty); expect(model.maximumScale).toBeInstanceOf(ConstantProperty); expect(model.incrementallyLoadTextures).toBeInstanceOf(ConstantProperty); - expect(model.castShadows).toBeInstanceOf(ConstantProperty); - expect(model.receiveShadows).toBeInstanceOf(ConstantProperty); + expect(model.shadows).toBeInstanceOf(ConstantProperty); expect(model.runAnimations).toBeInstanceOf(ConstantProperty); expect(model.nodeTransformations).toBeInstanceOf(PropertyBag); @@ -56,8 +56,7 @@ defineSuite([ expect(model.minimumPixelSize.getValue()).toEqual(options.minimumPixelSize); expect(model.maximumScale.getValue()).toEqual(options.maximumScale); expect(model.incrementallyLoadTextures.getValue()).toEqual(options.incrementallyLoadTextures); - expect(model.castShadows.getValue()).toEqual(options.castShadows); - expect(model.receiveShadows.getValue()).toEqual(options.receiveShadows); + expect(model.shadows.getValue()).toEqual(options.shadows); expect(model.runAnimations.getValue()).toEqual(options.runAnimations); var actualNodeTransformations = model.nodeTransformations.getValue(new JulianDate()); @@ -77,8 +76,7 @@ defineSuite([ source.minimumPixelSize = new ConstantProperty(2.0); source.maximumScale = new ConstantProperty(200.0); source.incrementallyLoadTextures = new ConstantProperty(true); - source.castShadows = new ConstantProperty(true); - source.receiveShadows = new ConstantProperty(true); + source.shadows = new ConstantProperty(ShadowMode.ENABLED); source.runAnimations = new ConstantProperty(true); source.nodeTransformations = { node1 : new NodeTransformationProperty({ @@ -100,8 +98,7 @@ defineSuite([ expect(target.minimumPixelSize).toBe(source.minimumPixelSize); expect(target.maximumScale).toBe(source.maximumScale); expect(target.incrementallyLoadTextures).toBe(source.incrementallyLoadTextures); - expect(target.castShadows).toBe(source.castShadows); - expect(target.receiveShadows).toBe(source.receiveShadows); + expect(target.shadows).toBe(source.shadows); expect(target.runAnimations).toBe(source.runAnimations); expect(target.nodeTransformations).toEqual(source.nodeTransformations); }); @@ -114,8 +111,7 @@ defineSuite([ source.minimumPixelSize = new ConstantProperty(2.0); source.maximumScale = new ConstantProperty(200.0); source.incrementallyLoadTextures = new ConstantProperty(true); - source.castShadows = new ConstantProperty(true); - source.receiveShadows = new ConstantProperty(true); + source.shadows = new ConstantProperty(ShadowMode.ENABLED); source.runAnimations = new ConstantProperty(true); source.nodeTransformations = { transform : new NodeTransformationProperty() @@ -127,8 +123,7 @@ defineSuite([ var minimumPixelSize = new ConstantProperty(2.0); var maximumScale = new ConstantProperty(200.0); var incrementallyLoadTextures = new ConstantProperty(true); - var castShadows = new ConstantProperty(true); - var receiveShadows = new ConstantProperty(true); + var shadows = new ConstantProperty(ShadowMode.ENABLED); var runAnimations = new ConstantProperty(true); var nodeTransformations = new PropertyBag({ transform : new NodeTransformationProperty() @@ -141,8 +136,7 @@ defineSuite([ target.minimumPixelSize = minimumPixelSize; target.maximumScale = maximumScale; target.incrementallyLoadTextures = incrementallyLoadTextures; - target.castShadows = castShadows; - target.receiveShadows = receiveShadows; + target.shadows = shadows; target.runAnimations = runAnimations; target.nodeTransformations = nodeTransformations; @@ -154,8 +148,7 @@ defineSuite([ expect(target.minimumPixelSize).toBe(minimumPixelSize); expect(target.maximumScale).toBe(maximumScale); expect(target.incrementallyLoadTextures).toBe(incrementallyLoadTextures); - expect(target.castShadows).toBe(castShadows); - expect(target.receiveShadows).toBe(receiveShadows); + expect(target.shadows).toBe(shadows); expect(target.runAnimations).toBe(runAnimations); expect(target.nodeTransformations).toBe(nodeTransformations); }); @@ -168,8 +161,7 @@ defineSuite([ source.minimumPixelSize = new ConstantProperty(2.0); source.maximumScale = new ConstantProperty(200.0); source.incrementallyLoadTextures = new ConstantProperty(true); - source.castShadows = new ConstantProperty(true); - source.receiveShadows = new ConstantProperty(true); + source.shadows = new ConstantProperty(ShadowMode.ENABLED); source.runAnimations = new ConstantProperty(true); source.nodeTransformations = { node1 : new NodeTransformationProperty(), @@ -183,8 +175,7 @@ defineSuite([ expect(result.minimumPixelSize).toBe(source.minimumPixelSize); expect(result.maximumScale).toBe(source.maximumScale); expect(result.incrementallyLoadTextures).toBe(source.incrementallyLoadTextures); - expect(result.castShadows).toBe(source.castShadows); - expect(result.receiveShadows).toBe(source.receiveShadows); + expect(result.shadows).toBe(source.shadows); expect(result.runAnimations).toBe(source.runAnimations); expect(result.nodeTransformations).toEqual(source.nodeTransformations); }); diff --git a/Specs/DataSources/PolygonGeometryUpdaterSpec.js b/Specs/DataSources/PolygonGeometryUpdaterSpec.js index 5a426dd85fa7..211152007aeb 100644 --- a/Specs/DataSources/PolygonGeometryUpdaterSpec.js +++ b/Specs/DataSources/PolygonGeometryUpdaterSpec.js @@ -19,7 +19,9 @@ defineSuite([ 'DataSources/SampledPositionProperty', 'DataSources/SampledProperty', 'DataSources/TimeIntervalCollectionProperty', + 'Scene/GroundPrimitive', 'Scene/PrimitiveCollection', + 'Scene/ShadowMode', 'Specs/createDynamicGeometryBoundingSphereSpecs', 'Specs/createDynamicProperty', 'Specs/createScene' @@ -43,7 +45,9 @@ defineSuite([ SampledPositionProperty, SampledProperty, TimeIntervalCollectionProperty, + GroundPrimitive, PrimitiveCollection, + ShadowMode, createDynamicGeometryBoundingSphereSpecs, createDynamicProperty, createScene) { @@ -51,10 +55,12 @@ defineSuite([ var scene; var time; + var groundPrimitiveSupported; beforeAll(function() { scene = createScene(); time = JulianDate.now(); + groundPrimitiveSupported = GroundPrimitive.isSupported(scene); }); afterAll(function() { @@ -102,6 +108,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.onTerrain).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); @@ -143,6 +150,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); expect(updater.isDynamic).toBe(false); }); @@ -404,8 +412,13 @@ defineSuite([ var updater = new PolygonGeometryUpdater(entity, scene); - expect(updater.onTerrain).toBe(true); - expect(updater.outlineEnabled).toBe(false); + if (groundPrimitiveSupported) { + expect(updater.onTerrain).toBe(true); + expect(updater.outlineEnabled).toBe(false); + } else { + expect(updater.onTerrain).toBe(false); + expect(updater.outlineEnabled).toBe(true); + } }); it('Checks that an entity with height isn\'t on terrain', function() { @@ -454,7 +467,11 @@ defineSuite([ var updater = new PolygonGeometryUpdater(entity, scene); - expect(updater.onTerrain).toBe(true); + if (groundPrimitiveSupported) { + expect(updater.onTerrain).toBe(true); + } else { + expect(updater.onTerrain).toBe(false); + } }); it('createFillGeometryInstance obeys Entity.show is false.', function() { @@ -480,11 +497,11 @@ defineSuite([ it('dynamic updater sets properties', function() { var polygon = new PolygonGraphics(); polygon.hierarchy = createDynamicProperty(new PolygonHierarchy(Cartesian3.fromRadiansArray([ - 0, 0, - 1, 0, - 1, 1, - 0, 1 - ]))); + 0, 0, + 1, 0, + 1, 1, + 0, 1 + ]))); polygon.show = createDynamicProperty(true); polygon.height = createDynamicProperty(3); polygon.extrudedHeight = createDynamicProperty(2); @@ -552,11 +569,11 @@ defineSuite([ it('dynamic updater on terrain', function() { var polygon = new PolygonGraphics(); polygon.hierarchy = createDynamicProperty(new PolygonHierarchy(Cartesian3.fromRadiansArray([ - 0, 0, - 1, 0, - 1, 1, - 0, 1 - ]))); + 0, 0, + 1, 0, + 1, 1, + 0, 1 + ]))); polygon.show = createDynamicProperty(true); polygon.outline = createDynamicProperty(true); polygon.fill = createDynamicProperty(true); @@ -575,8 +592,14 @@ defineSuite([ expect(groundPrimitives.length).toBe(0); dynamicUpdater.update(time); - expect(primitives.length).toBe(0); - expect(groundPrimitives.length).toBe(1); + + if (groundPrimitiveSupported) { + expect(primitives.length).toBe(0); + expect(groundPrimitives.length).toBe(1); + } else { + expect(primitives.length).toBe(2); + expect(groundPrimitives.length).toBe(0); + } dynamicUpdater.destroy(); updater.destroy(); @@ -688,7 +711,11 @@ defineSuite([ var entity = createBasicPolygonWithoutHeight(); entity.polygon.fill = true; var updater = new PolygonGeometryUpdater(entity, scene); - expect(updater.onTerrain).toBe(true); + if (groundPrimitiveSupported) { + expect(updater.onTerrain).toBe(true); + } else { + expect(updater.onTerrain).toBe(false); + } }); it('fill is false sets onTerrain to false', function() { @@ -727,7 +754,11 @@ defineSuite([ entity.polygon.fill = true; entity.polygon.material = new ColorMaterialProperty(Color.WHITE); var updater = new PolygonGeometryUpdater(entity, scene); - expect(updater.onTerrain).toBe(true); + if (groundPrimitiveSupported) { + expect(updater.onTerrain).toBe(true); + } else { + expect(updater.onTerrain).toBe(false); + } }); it('non-color material sets onTerrain to false', function() { diff --git a/Specs/DataSources/PolygonGraphicsSpec.js b/Specs/DataSources/PolygonGraphicsSpec.js index 1e6632fe2199..0d28ea67981e 100644 --- a/Specs/DataSources/PolygonGraphicsSpec.js +++ b/Specs/DataSources/PolygonGraphicsSpec.js @@ -5,6 +5,7 @@ defineSuite([ 'Core/PolygonHierarchy', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', + 'Scene/ShadowMode', 'Specs/testDefinitionChanged', 'Specs/testMaterialDefinitionChanged' ], function( @@ -13,6 +14,7 @@ defineSuite([ PolygonHierarchy, ColorMaterialProperty, ConstantProperty, + ShadowMode, testDefinitionChanged, testMaterialDefinitionChanged) { 'use strict'; @@ -32,7 +34,8 @@ defineSuite([ outlineColor : Color.RED, outlineWidth : 7, closeTop : true, - closeBottom : true + closeBottom : true, + shadows : ShadowMode.DISABLED }; var polygon = new PolygonGraphics(options); @@ -50,6 +53,7 @@ defineSuite([ expect(polygon.outlineWidth).toBeInstanceOf(ConstantProperty); expect(polygon.closeTop).toBeInstanceOf(ConstantProperty); expect(polygon.closeBottom).toBeInstanceOf(ConstantProperty); + expect(polygon.shadows).toBeInstanceOf(ConstantProperty); expect(polygon.material.color.getValue()).toEqual(options.material); expect(polygon.show.getValue()).toEqual(options.show); @@ -65,6 +69,7 @@ defineSuite([ expect(polygon.outlineWidth.getValue()).toEqual(options.outlineWidth); expect(polygon.closeTop.getValue()).toEqual(options.closeTop); expect(polygon.closeBottom.getValue()).toEqual(options.closeBottom); + expect(polygon.shadows.getValue()).toEqual(options.shadows); }); it('merge assigns unassigned properties', function() { @@ -83,6 +88,7 @@ defineSuite([ source.perPositionHeight = new ConstantProperty(); source.closeTop = new ConstantProperty(); source.closeBottom = new ConstantProperty(); + source.shadows = new ConstantProperty(ShadowMode.ENABLED); var target = new PolygonGraphics(); target.merge(source); @@ -101,6 +107,7 @@ defineSuite([ expect(target.perPositionHeight).toBe(source.perPositionHeight); expect(target.closeTop).toBe(source.closeTop); expect(target.closeBottom).toBe(source.closeBottom); + expect(target.shadows).toBe(source.shadows); }); it('merge does not assign assigned properties', function() { @@ -120,6 +127,7 @@ defineSuite([ var perPositionHeight = new ConstantProperty(); var closeTop = new ConstantProperty(); var closeBottom = new ConstantProperty(); + var shadows = new ConstantProperty(); var target = new PolygonGraphics(); target.material = material; @@ -136,6 +144,7 @@ defineSuite([ target.perPositionHeight = perPositionHeight; target.closeTop = closeTop; target.closeBottom = closeBottom; + target.shadows = shadows; target.merge(source); @@ -153,6 +162,7 @@ defineSuite([ expect(target.perPositionHeight).toBe(perPositionHeight); expect(target.closeTop).toBe(closeTop); expect(target.closeBottom).toBe(closeBottom); + expect(target.shadows).toBe(shadows); }); it('clone works', function() { @@ -171,6 +181,7 @@ defineSuite([ source.perPositionHeight = new ConstantProperty(); source.closeTop = new ConstantProperty(); source.closeBottom = new ConstantProperty(); + source.shadows = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -187,6 +198,7 @@ defineSuite([ expect(result.perPositionHeight).toBe(source.perPositionHeight); expect(result.closeTop).toBe(source.closeTop); expect(result.closeBottom).toBe(source.closeBottom); + expect(result.shadows).toBe(source.shadows); }); it('merge throws if source undefined', function() { @@ -212,5 +224,6 @@ defineSuite([ testDefinitionChanged(property, 'perPositionHeight', false, true); testDefinitionChanged(property, 'closeTop', true, false); testDefinitionChanged(property, 'closeBottom', true, false); + testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); }); }); diff --git a/Specs/DataSources/PolylineGeometryUpdaterSpec.js b/Specs/DataSources/PolylineGeometryUpdaterSpec.js index dd7e5e03a4bc..cdb905c5c655 100644 --- a/Specs/DataSources/PolylineGeometryUpdaterSpec.js +++ b/Specs/DataSources/PolylineGeometryUpdaterSpec.js @@ -21,6 +21,7 @@ defineSuite([ 'DataSources/TimeIntervalCollectionProperty', 'Scene/Globe', 'Scene/PrimitiveCollection', + 'Scene/ShadowMode', 'Specs/createDynamicProperty', 'Specs/createScene' ], function( @@ -45,6 +46,7 @@ defineSuite([ TimeIntervalCollectionProperty, Globe, PrimitiveCollection, + ShadowMode, createDynamicProperty, createScene) { 'use strict'; @@ -91,6 +93,7 @@ defineSuite([ expect(updater.hasConstantFill).toBe(true); expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); + expect(updater.shadowsProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -129,6 +132,7 @@ defineSuite([ expect(updater.hasConstantFill).toBe(true); expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); + expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); expect(updater.isDynamic).toBe(false); }); diff --git a/Specs/DataSources/PolylineGraphicsSpec.js b/Specs/DataSources/PolylineGraphicsSpec.js index 44088e111c0e..73e41c2f5e3d 100644 --- a/Specs/DataSources/PolylineGraphicsSpec.js +++ b/Specs/DataSources/PolylineGraphicsSpec.js @@ -4,6 +4,7 @@ defineSuite([ 'Core/Color', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', + 'Scene/ShadowMode', 'Specs/testDefinitionChanged', 'Specs/testMaterialDefinitionChanged' ], function( @@ -11,6 +12,7 @@ defineSuite([ Color, ColorMaterialProperty, ConstantProperty, + ShadowMode, testDefinitionChanged, testMaterialDefinitionChanged) { 'use strict'; @@ -22,7 +24,8 @@ defineSuite([ show : true, width : 1, followSurface : false, - granularity : 2 + granularity : 2, + shadows : ShadowMode.DISABLED }; var polyline = new PolylineGraphics(options); @@ -32,6 +35,7 @@ defineSuite([ expect(polyline.width).toBeInstanceOf(ConstantProperty); expect(polyline.followSurface).toBeInstanceOf(ConstantProperty); expect(polyline.granularity).toBeInstanceOf(ConstantProperty); + expect(polyline.shadows).toBeInstanceOf(ConstantProperty); expect(polyline.material.color.getValue()).toEqual(options.material); expect(polyline.positions.getValue()).toEqual(options.positions); @@ -39,6 +43,7 @@ defineSuite([ expect(polyline.width.getValue()).toEqual(options.width); expect(polyline.followSurface.getValue()).toEqual(options.followSurface); expect(polyline.granularity.getValue()).toEqual(options.granularity); + expect(polyline.shadows.getValue()).toEqual(options.shadows); }); it('merge assigns unassigned properties', function() { @@ -49,6 +54,7 @@ defineSuite([ source.show = new ConstantProperty(); source.followSurface = new ConstantProperty(); source.granularity = new ConstantProperty(); + source.shadows = new ConstantProperty(ShadowMode.ENABLED); var target = new PolylineGraphics(); target.merge(source); @@ -58,6 +64,7 @@ defineSuite([ expect(target.show).toBe(source.show); expect(target.followSurface).toBe(source.followSurface); expect(target.granularity).toBe(source.granularity); + expect(target.shadows).toBe(source.shadows); }); it('merge does not assign assigned properties', function() { @@ -68,6 +75,7 @@ defineSuite([ source.show = new ConstantProperty(); source.followSurface = new ConstantProperty(); source.granularity = new ConstantProperty(); + source.shadows = new ConstantProperty(); var color = new ColorMaterialProperty(); var positions = new ConstantProperty(); @@ -75,6 +83,7 @@ defineSuite([ var show = new ConstantProperty(); var followSurface = new ConstantProperty(); var granularity = new ConstantProperty(); + var shadows = new ConstantProperty(); var target = new PolylineGraphics(); target.material = color; @@ -83,6 +92,7 @@ defineSuite([ target.show = show; target.followSurface = followSurface; target.granularity = granularity; + target.shadows = shadows; target.merge(source); expect(target.material).toBe(color); @@ -91,6 +101,7 @@ defineSuite([ expect(target.show).toBe(show); expect(target.followSurface).toBe(followSurface); expect(target.granularity).toBe(granularity); + expect(target.shadows).toBe(shadows); }); it('clone works', function() { @@ -101,6 +112,7 @@ defineSuite([ source.show = new ConstantProperty(); source.followSurface = new ConstantProperty(); source.granularity = new ConstantProperty(); + source.shadows = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -109,6 +121,7 @@ defineSuite([ expect(result.show).toBe(source.show); expect(result.followSurface).toBe(source.followSurface); expect(result.granularity).toBe(source.granularity); + expect(result.shadows).toBe(source.shadows); }); it('merge throws if source undefined', function() { @@ -126,5 +139,6 @@ defineSuite([ testDefinitionChanged(property, 'width', 3, 4); testDefinitionChanged(property, 'followSurface', false, true); testDefinitionChanged(property, 'granularity', 2, 1); + testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); }); }); diff --git a/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js b/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js index be9ee8302894..fca67522f11f 100644 --- a/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js +++ b/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js @@ -19,6 +19,7 @@ defineSuite([ 'DataSources/SampledProperty', 'DataSources/TimeIntervalCollectionProperty', 'Scene/PrimitiveCollection', + 'Scene/ShadowMode', 'Specs/createDynamicGeometryBoundingSphereSpecs', 'Specs/createDynamicProperty', 'Specs/createScene' @@ -42,6 +43,7 @@ defineSuite([ SampledProperty, TimeIntervalCollectionProperty, PrimitiveCollection, + ShadowMode, createDynamicGeometryBoundingSphereSpecs, createDynamicProperty, createScene) { @@ -89,6 +91,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -128,6 +131,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); expect(updater.isDynamic).toBe(false); }); diff --git a/Specs/DataSources/PolylineVolumeGraphicsSpec.js b/Specs/DataSources/PolylineVolumeGraphicsSpec.js index 5c451d730b08..5db295890dda 100644 --- a/Specs/DataSources/PolylineVolumeGraphicsSpec.js +++ b/Specs/DataSources/PolylineVolumeGraphicsSpec.js @@ -5,6 +5,7 @@ defineSuite([ 'Core/CornerType', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', + 'Scene/ShadowMode', 'Specs/testDefinitionChanged', 'Specs/testMaterialDefinitionChanged' ], function( @@ -13,6 +14,7 @@ defineSuite([ CornerType, ColorMaterialProperty, ConstantProperty, + ShadowMode, testDefinitionChanged, testMaterialDefinitionChanged) { 'use strict'; @@ -28,7 +30,8 @@ defineSuite([ outline : false, outlineColor : Color.RED, outlineWidth : 2, - cornerType : CornerType.BEVELED + cornerType : CornerType.BEVELED, + shadows : ShadowMode.DISABLED }; var polylineVolume = new PolylineVolumeGraphics(options); @@ -42,6 +45,7 @@ defineSuite([ expect(polylineVolume.outlineColor).toBeInstanceOf(ConstantProperty); expect(polylineVolume.outlineWidth).toBeInstanceOf(ConstantProperty); expect(polylineVolume.cornerType).toBeInstanceOf(ConstantProperty); + expect(polylineVolume.shadows).toBeInstanceOf(ConstantProperty); expect(polylineVolume.material.color.getValue()).toEqual(options.material); expect(polylineVolume.positions.getValue()).toEqual(options.positions); @@ -53,6 +57,7 @@ defineSuite([ expect(polylineVolume.outlineColor.getValue()).toEqual(options.outlineColor); expect(polylineVolume.outlineWidth.getValue()).toEqual(options.outlineWidth); expect(polylineVolume.cornerType.getValue()).toEqual(options.cornerType); + expect(polylineVolume.shadows.getValue()).toEqual(options.shadows); }); it('merge assigns unassigned properties', function() { @@ -67,6 +72,7 @@ defineSuite([ source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); source.cornerType = new ConstantProperty(); + source.shadows = new ConstantProperty(ShadowMode.ENABLED); var target = new PolylineVolumeGraphics(); target.merge(source); @@ -81,6 +87,7 @@ defineSuite([ expect(target.outlineColor).toBe(source.outlineColor); expect(target.outlineWidth).toBe(source.outlineWidth); expect(target.cornerType).toBe(source.cornerType); + expect(target.shadows).toBe(source.shadows); }); it('merge does not assign assigned properties', function() { @@ -96,6 +103,7 @@ defineSuite([ var outlineColor = new ConstantProperty(); var outlineWidth = new ConstantProperty(); var cornerType = new ConstantProperty(); + var shadows = new ConstantProperty(); var target = new PolylineVolumeGraphics(); target.material = material; @@ -108,6 +116,7 @@ defineSuite([ target.outlineColor = outlineColor; target.outlineWidth = outlineWidth; target.cornerType = cornerType; + target.shadows = shadows; target.merge(source); @@ -121,6 +130,7 @@ defineSuite([ expect(target.outlineColor).toBe(outlineColor); expect(target.outlineWidth).toBe(outlineWidth); expect(target.cornerType).toBe(cornerType); + expect(target.shadows).toBe(shadows); }); it('clone works', function() { @@ -135,6 +145,7 @@ defineSuite([ source.outlineColor = new ConstantProperty(); source.outlineWidth = new ConstantProperty(); source.cornerType = new ConstantProperty(); + source.shadows = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -147,6 +158,7 @@ defineSuite([ expect(result.outlineColor).toBe(source.outlineColor); expect(result.outlineWidth).toBe(source.outlineWidth); expect(result.cornerType).toBe(source.cornerType); + expect(result.shadows).toBe(source.shadows); }); it('merge throws if source undefined', function() { @@ -168,5 +180,6 @@ defineSuite([ testDefinitionChanged(property, 'outlineColor', Color.RED, Color.BLUE); testDefinitionChanged(property, 'outlineWidth', 2, 3); testDefinitionChanged(property, 'cornerType', CornerType.BEVELED, CornerType.MITERED); + testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); }); }); diff --git a/Specs/DataSources/RectangleGeometryUpdaterSpec.js b/Specs/DataSources/RectangleGeometryUpdaterSpec.js index 14943ae63e53..63ecba106986 100644 --- a/Specs/DataSources/RectangleGeometryUpdaterSpec.js +++ b/Specs/DataSources/RectangleGeometryUpdaterSpec.js @@ -17,7 +17,9 @@ defineSuite([ 'DataSources/RectangleGraphics', 'DataSources/SampledProperty', 'DataSources/TimeIntervalCollectionProperty', + 'Scene/GroundPrimitive', 'Scene/PrimitiveCollection', + 'Scene/ShadowMode', 'Specs/createDynamicGeometryBoundingSphereSpecs', 'Specs/createDynamicProperty', 'Specs/createScene' @@ -39,7 +41,9 @@ defineSuite([ RectangleGraphics, SampledProperty, TimeIntervalCollectionProperty, + GroundPrimitive, PrimitiveCollection, + ShadowMode, createDynamicGeometryBoundingSphereSpecs, createDynamicProperty, createScene) { @@ -49,12 +53,14 @@ defineSuite([ var time2; var time3; var scene; + var groundPrimitiveSupported; beforeAll(function() { scene = createScene(); time = new JulianDate(0, 0); time2 = new JulianDate(10, 0); time3 = new JulianDate(20, 0); + groundPrimitiveSupported = GroundPrimitive.isSupported(scene); }); afterAll(function() { @@ -92,6 +98,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -132,6 +139,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); expect(updater.isDynamic).toBe(false); }); @@ -385,8 +393,13 @@ defineSuite([ var updater = new RectangleGeometryUpdater(entity, scene); - expect(updater.onTerrain).toBe(true); - expect(updater.outlineEnabled).toBe(false); + if (groundPrimitiveSupported) { + expect(updater.onTerrain).toBe(true); + expect(updater.outlineEnabled).toBe(false); + } else { + expect(updater.onTerrain).toBe(false); + expect(updater.outlineEnabled).toBe(true); + } }); it('Checks that an entity with height isn\'t on terrain', function() { @@ -520,8 +533,14 @@ defineSuite([ expect(groundPrimitives.length).toBe(0); dynamicUpdater.update(time); - expect(primitives.length).toBe(0); - expect(groundPrimitives.length).toBe(1); + + if (groundPrimitiveSupported) { + expect(primitives.length).toBe(0); + expect(groundPrimitives.length).toBe(1); + } else { + expect(primitives.length).toBe(2); + expect(groundPrimitives.length).toBe(0); + } dynamicUpdater.destroy(); updater.destroy(); @@ -630,7 +649,11 @@ defineSuite([ var entity = createBasicRectangleWithoutHeight(); entity.rectangle.fill = true; var updater = new RectangleGeometryUpdater(entity, scene); - expect(updater.onTerrain).toBe(true); + if (groundPrimitiveSupported) { + expect(updater.onTerrain).toBe(true); + } else { + expect(updater.onTerrain).toBe(false); + } }); it('fill is false sets onTerrain to false', function() { @@ -661,7 +684,11 @@ defineSuite([ entity.rectangle.fill = true; entity.rectangle.material = new ColorMaterialProperty(Color.WHITE); var updater = new RectangleGeometryUpdater(entity, scene); - expect(updater.onTerrain).toBe(true); + if (groundPrimitiveSupported) { + expect(updater.onTerrain).toBe(true); + } else { + expect(updater.onTerrain).toBe(false); + } }); it('non-color material sets onTerrain to false', function() { diff --git a/Specs/DataSources/RectangleGraphicsSpec.js b/Specs/DataSources/RectangleGraphicsSpec.js index fa6b177f8611..f8311886d30d 100644 --- a/Specs/DataSources/RectangleGraphicsSpec.js +++ b/Specs/DataSources/RectangleGraphicsSpec.js @@ -5,6 +5,7 @@ defineSuite([ 'Core/Rectangle', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', + 'Scene/ShadowMode', 'Specs/testDefinitionChanged', 'Specs/testMaterialDefinitionChanged' ], function( @@ -13,6 +14,7 @@ defineSuite([ Rectangle, ColorMaterialProperty, ConstantProperty, + ShadowMode, testDefinitionChanged, testMaterialDefinitionChanged) { 'use strict'; @@ -32,7 +34,8 @@ defineSuite([ outlineColor : Color.RED, outlineWidth : 10, closeTop : false, - closeBottom : false + closeBottom : false, + shadows : ShadowMode.DISABLED }; var ellipse = new RectangleGraphics(options); @@ -50,7 +53,8 @@ defineSuite([ expect(ellipse.outlineWidth).toBeInstanceOf(ConstantProperty); expect(ellipse.closeTop).toBeInstanceOf(ConstantProperty); expect(ellipse.closeBottom).toBeInstanceOf(ConstantProperty); - + expect(ellipse.shadows).toBeInstanceOf(ConstantProperty); + expect(ellipse.material.color.getValue()).toEqual(options.material); expect(ellipse.show.getValue()).toEqual(options.show); expect(ellipse.coordinates.getValue()).toEqual(options.coordinates); @@ -65,6 +69,7 @@ defineSuite([ expect(ellipse.outlineWidth.getValue()).toEqual(options.outlineWidth); expect(ellipse.closeTop.getValue()).toEqual(options.closeTop); expect(ellipse.closeBottom.getValue()).toEqual(options.closeBottom); + expect(ellipse.shadows.getValue()).toEqual(options.shadows); }); it('merge assigns unassigned properties', function() { @@ -83,6 +88,7 @@ defineSuite([ source.outlineWidth = new ConstantProperty(); source.closeTop = new ConstantProperty(); source.closeBottom = new ConstantProperty(); + source.shadows = new ConstantProperty(ShadowMode.ENABLED); var target = new RectangleGraphics(); target.merge(source); @@ -101,6 +107,7 @@ defineSuite([ expect(target.outlineWidth).toBe(source.outlineWidth); expect(target.closeTop).toBe(source.closeTop); expect(target.closeBottom).toBe(source.closeBottom); + expect(target.shadows).toBe(source.shadows); }); it('merge does not assign assigned properties', function() { @@ -120,6 +127,7 @@ defineSuite([ var outlineWidth = new ConstantProperty(); var closeTop = new ConstantProperty(); var closeBottom = new ConstantProperty(); + var shadows = new ConstantProperty(); var target = new RectangleGraphics(); target.material = material; @@ -136,6 +144,7 @@ defineSuite([ target.outlineWidth = outlineWidth; target.closeTop = closeTop; target.closeBottom = closeBottom; + target.shadows = shadows; target.merge(source); @@ -153,6 +162,7 @@ defineSuite([ expect(target.outlineWidth).toBe(outlineWidth); expect(target.closeTop).toBe(closeTop); expect(target.closeBottom).toBe(closeBottom); + expect(target.shadows).toBe(shadows); }); it('clone works', function() { @@ -171,6 +181,7 @@ defineSuite([ source.outlineWidth = new ConstantProperty(); source.closeTop = new ConstantProperty(); source.closeBottom = new ConstantProperty(); + source.shadows = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -187,6 +198,7 @@ defineSuite([ expect(result.outlineWidth).toBe(source.outlineWidth); expect(result.closeTop).toBe(source.closeTop); expect(result.closeBottom).toBe(source.closeBottom); + expect(result.shadows).toBe(source.shadows); }); it('merge throws if source undefined', function() { @@ -212,5 +224,6 @@ defineSuite([ testDefinitionChanged(property, 'outlineWidth', 2, 3); testDefinitionChanged(property, 'closeTop', false, true); testDefinitionChanged(property, 'closeBottom', false, true); + testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); }); }); diff --git a/Specs/DataSources/WallGeometryUpdaterSpec.js b/Specs/DataSources/WallGeometryUpdaterSpec.js index 123cfb0c217a..c1f36d599764 100644 --- a/Specs/DataSources/WallGeometryUpdaterSpec.js +++ b/Specs/DataSources/WallGeometryUpdaterSpec.js @@ -18,6 +18,7 @@ defineSuite([ 'DataSources/TimeIntervalCollectionProperty', 'DataSources/WallGraphics', 'Scene/PrimitiveCollection', + 'Scene/ShadowMode', 'Specs/createDynamicGeometryBoundingSphereSpecs', 'Specs/createDynamicProperty', 'Specs/createScene' @@ -40,6 +41,7 @@ defineSuite([ TimeIntervalCollectionProperty, WallGraphics, PrimitiveCollection, + ShadowMode, createDynamicGeometryBoundingSphereSpecs, createDynamicProperty, createScene) { @@ -88,6 +90,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toBe(undefined); expect(updater.isDynamic).toBe(false); expect(updater.isOutlineVisible(time)).toBe(false); expect(updater.isFilled(time)).toBe(false); @@ -128,6 +131,7 @@ defineSuite([ expect(updater.hasConstantOutline).toBe(true); expect(updater.outlineColorProperty).toBe(undefined); expect(updater.outlineWidth).toBe(1.0); + expect(updater.shadowsProperty).toEqual(new ConstantProperty(ShadowMode.DISABLED)); expect(updater.isDynamic).toBe(false); }); diff --git a/Specs/DataSources/WallGraphicsSpec.js b/Specs/DataSources/WallGraphicsSpec.js index 1ea35d4c71c1..6a1fd2eab8ac 100644 --- a/Specs/DataSources/WallGraphicsSpec.js +++ b/Specs/DataSources/WallGraphicsSpec.js @@ -4,6 +4,7 @@ defineSuite([ 'Core/Color', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', + 'Scene/ShadowMode', 'Specs/testDefinitionChanged', 'Specs/testMaterialDefinitionChanged' ], function( @@ -11,6 +12,7 @@ defineSuite([ Color, ColorMaterialProperty, ConstantProperty, + ShadowMode, testDefinitionChanged, testMaterialDefinitionChanged) { 'use strict'; @@ -26,7 +28,8 @@ defineSuite([ outlineColor : Color.RED, outlineWidth : 2, minimumHeights : [3, 4, 5], - maximumHeights : [6, 7, 8] + maximumHeights : [6, 7, 8], + shadows : ShadowMode.DISABLED }; var wall = new WallGraphics(options); @@ -41,6 +44,7 @@ defineSuite([ expect(wall.outlineWidth).toBeInstanceOf(ConstantProperty); expect(wall.minimumHeights).toBeInstanceOf(ConstantProperty); expect(wall.maximumHeights).toBeInstanceOf(ConstantProperty); + expect(wall.shadows).toBeInstanceOf(ConstantProperty); expect(wall.material.color.getValue()).toEqual(options.material); expect(wall.positions.getValue()).toEqual(options.positions); @@ -53,6 +57,7 @@ defineSuite([ expect(wall.outlineWidth.getValue()).toEqual(options.outlineWidth); expect(wall.minimumHeights.getValue()).toEqual(options.minimumHeights); expect(wall.maximumHeights.getValue()).toEqual(options.maximumHeights); + expect(wall.shadows.getValue()).toEqual(options.shadows); }); it('merge assigns unassigned properties', function() { @@ -67,6 +72,7 @@ defineSuite([ source.outlineWidth = new ConstantProperty(); source.minimumHeights = new ConstantProperty(); source.maximumHeights = new ConstantProperty(); + source.shadows = new ConstantProperty(ShadowMode.ENABLED); var target = new WallGraphics(); target.merge(source); @@ -81,6 +87,7 @@ defineSuite([ expect(target.outlineWidth).toBe(source.outlineWidth); expect(target.minimumHeights).toBe(source.minimumHeights); expect(target.maximumHeights).toBe(source.maximumHeights); + expect(target.shadows).toBe(source.shadows); }); it('merge does not assign assigned properties', function() { @@ -96,6 +103,7 @@ defineSuite([ var outlineWidth = new ConstantProperty(); var minimumHeights = new ConstantProperty(); var maximumHeights = new ConstantProperty(); + var shadows = new ConstantProperty(); var target = new WallGraphics(); target.material = material; @@ -108,6 +116,7 @@ defineSuite([ target.outlineWidth = outlineWidth; target.minimumHeights = minimumHeights; target.maximumHeights = maximumHeights; + target.shadows = shadows; target.merge(source); @@ -121,6 +130,7 @@ defineSuite([ expect(target.outlineWidth).toBe(outlineWidth); expect(target.minimumHeights).toBe(minimumHeights); expect(target.maximumHeights).toBe(maximumHeights); + expect(target.shadows).toBe(shadows); }); it('clone works', function() { @@ -135,6 +145,7 @@ defineSuite([ source.outlineWidth = new ConstantProperty(); source.minimumHeights = new ConstantProperty(); source.maximumHeights = new ConstantProperty(); + source.shadows = new ConstantProperty(); var result = source.clone(); expect(result.material).toBe(source.material); @@ -147,6 +158,7 @@ defineSuite([ expect(result.outlineWidth).toBe(source.outlineWidth); expect(result.minimumHeights).toBe(source.minimumHeights); expect(result.maximumHeights).toBe(source.maximumHeights); + expect(result.shadows).toBe(source.shadows); }); it('merge throws if source undefined', function() { @@ -168,5 +180,6 @@ defineSuite([ testDefinitionChanged(property, 'outlineWidth', 2, 3); testDefinitionChanged(property, 'minimumHeights', [0, 1], [2, 3]); testDefinitionChanged(property, 'maximumHeights', [3, 5], [7, 8]); + testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); }); }); diff --git a/Specs/Renderer/BuiltinFunctionsSpec.js b/Specs/Renderer/BuiltinFunctionsSpec.js index b0bb4c9dc532..9ff5c55e04d3 100644 --- a/Specs/Renderer/BuiltinFunctionsSpec.js +++ b/Specs/Renderer/BuiltinFunctionsSpec.js @@ -25,7 +25,7 @@ defineSuite([ context.destroyForSpecs(); }); - it('has czm_tranpose (2x2)', function() { + it('has czm_transpose (2x2)', function() { var fs = 'void main() { ' + ' mat2 m = mat2(1.0, 2.0, 3.0, 4.0); ' + @@ -36,7 +36,7 @@ defineSuite([ context.verifyDrawForSpecs(fs); }); - it('has czm_tranpose (3x3)', function() { + it('has czm_transpose (3x3)', function() { var fs = 'void main() { ' + ' mat3 m = mat3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0); ' + @@ -47,7 +47,7 @@ defineSuite([ context.verifyDrawForSpecs(fs); }); - it('has czm_tranpose (4x4)', function() { + it('has czm_transpose (4x4)', function() { var fs = 'void main() { ' + ' mat4 m = mat4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0);' + diff --git a/Specs/Scene/CameraSpec.js b/Specs/Scene/CameraSpec.js index a15c8ffc8419..87626ef2df70 100644 --- a/Specs/Scene/CameraSpec.js +++ b/Specs/Scene/CameraSpec.js @@ -2103,25 +2103,63 @@ defineSuite([ }); var options = { - destination : Cartesian3.fromDegrees(-117.16, 32.71, 15000.0) + destination : Cartesian3.fromDegrees(-117.16, 32.71, 15000.0), + orientation : { + heading : 0, + pitch : 1, + roll : 2 + }, + duration : 3, + complete : function() { + }, + cancel : function() { + }, + endTransform : new Matrix4(), + convert : true, + maximumHeight : 100, + easingFunction : function() { + } }; camera.flyTo(options); - var expectedOptions = { - destination : options.destination, - heading : undefined, - pitch : undefined, - roll : undefined, - duration : undefined, - complete : undefined, - cancel : undefined, - endTransform : undefined, - convert : undefined, - maximumHeight : undefined, - easingFunction : undefined + var args = CameraFlightPath.createTween.calls.argsFor(0); + var passedOptions = args[1]; + + expect(CameraFlightPath.createTween).toHaveBeenCalled(); + expect(args[0]).toBe(scene); + expect(passedOptions.destination).toBe(options.destination); + expect(passedOptions.heading).toBe(options.orientation.heading); + expect(passedOptions.pitch).toBe(options.orientation.pitch); + expect(passedOptions.roll).toBe(options.orientation.roll); + expect(typeof passedOptions.complete).toBe('function'); //complete function is wrapped by camera. + expect(passedOptions.cancel).toBe(options.cancel); + expect(passedOptions.endTransform).toBe(options.endTransform); + expect(passedOptions.convert).toBe(options.convert); + expect(passedOptions.maximumHeight).toBe(options.maximumHeight); + expect(passedOptions.easingFunction).toBe(options.easingFunction); + }); + + it('can cancel a flight', function() { + spyOn(CameraFlightPath, 'createTween').and.returnValue({ + startObject : {}, + stopObject: {}, + duration : 0.001, + cancelTween: jasmine.createSpy('cancelTween') + }); + + var options = { + destination : Cartesian3.fromDegrees(-117.16, 32.71, 15000.0) }; + camera.flyTo(options); + + expect(camera._currentFlight).toBeDefined(); + + var createdTween = camera._currentFlight; + spyOn(createdTween, 'cancelTween'); + camera.cancelFlight(); - expect(CameraFlightPath.createTween).toHaveBeenCalledWith(scene, expectedOptions); + expect(createdTween.cancelTween).toHaveBeenCalled(); + expect(camera._currentFlight).toBeUndefined(); }); it('flyTo with heading, pitch and roll', function() { diff --git a/Specs/Scene/GroundPrimitiveSpec.js b/Specs/Scene/GroundPrimitiveSpec.js index 0e5e87f4da96..470bbfc27578 100644 --- a/Specs/Scene/GroundPrimitiveSpec.js +++ b/Specs/Scene/GroundPrimitiveSpec.js @@ -70,20 +70,23 @@ defineSuite([ var primitive; var depthPrimitive; - beforeAll(function(done) { + beforeAll(function() { scene = createScene(); scene.fxaa = false; context = scene.context; ellipsoid = Ellipsoid.WGS84; - GroundPrimitive.initializeTerrainHeights().then(function() { - done(); - }); + return GroundPrimitive.initializeTerrainHeights(); }); afterAll(function() { scene.destroyForSpecs(); + + // Leave ground primitive uninitialized + GroundPrimitive._initialized = false; + GroundPrimitive._initPromise = undefined; + GroundPrimitive._terrainHeights = undefined; }); function MockGlobePrimitive(primitive) { @@ -851,10 +854,12 @@ defineSuite([ geometryInstances : rectangleInstance, asynchronous : false }); - - expect(function() { - primitive.update(scene.frameState); - }).toThrowDeveloperError(); + + if (GroundPrimitive.isSupported(scene)) { + expect(function() { + primitive.update(scene.frameState); + }).toThrowDeveloperError(); + } // Set back to initialized state GroundPrimitive._initPromise = initPromise; diff --git a/Specs/Scene/ModelSpec.js b/Specs/Scene/ModelSpec.js index 8756b4e7773f..6378a68a6bdd 100644 --- a/Specs/Scene/ModelSpec.js +++ b/Specs/Scene/ModelSpec.js @@ -18,8 +18,8 @@ defineSuite([ 'Core/loadArrayBuffer', 'Core/loadJson', 'Core/Math', - 'Core/Matrix4', 'Core/Matrix3', + 'Core/Matrix4', 'Core/PrimitiveType', 'Core/Transforms', 'Renderer/RenderState', @@ -49,8 +49,8 @@ defineSuite([ loadArrayBuffer, loadJson, CesiumMath, - Matrix4, Matrix3, + Matrix4, PrimitiveType, Transforms, RenderState, @@ -1834,7 +1834,15 @@ defineSuite([ getHeight : function() { return 0.0; }, - _surface : {}, + _surface : { + tileProvider : { + ready : true + }, + _tileLoadQueue : {}, + _debug : { + tilesWaitingForChildren : 0 + } + }, destroy : function() {} }; diff --git a/Specs/Scene/PrimitiveSpec.js b/Specs/Scene/PrimitiveSpec.js index 84ae16278862..36a4aafc0916 100644 --- a/Specs/Scene/PrimitiveSpec.js +++ b/Specs/Scene/PrimitiveSpec.js @@ -85,6 +85,8 @@ defineSuite([ beforeEach(function() { scene.morphTo3D(0); + scene.frameState.passes.render = true; + scene.frameState.passes.pick = false; rectangle1 = Rectangle.fromDegrees(-80.0, 20.0, -70.0, 30.0); rectangle2 = Rectangle.fromDegrees(70.0, 20.0, 80.0, 30.0); diff --git a/Specs/Scene/ScreenSpaceCameraControllerSpec.js b/Specs/Scene/ScreenSpaceCameraControllerSpec.js index 015875efd384..0bb6a625bbda 100644 --- a/Specs/Scene/ScreenSpaceCameraControllerSpec.js +++ b/Specs/Scene/ScreenSpaceCameraControllerSpec.js @@ -57,6 +57,7 @@ defineSuite([ this.globe = undefined; this.mapProjection = new GeographicProjection(ellipsoid); this.terrainExaggeration = 1.0; + this.screenSpaceCameraController = undefined; } function MockGlobe(ellipsoid) { @@ -64,6 +65,15 @@ defineSuite([ this.getHeight = function(cartographic) { return 0.0; }; + this._surface = { + tileProvider : { + ready : true + }, + _tileLoadQueue : {}, + _debug : { + tilesWaitingForChildren : 0 + } + }; } beforeAll(function() { canvas = createCanvas(1024, 768); @@ -86,6 +96,9 @@ defineSuite([ scene = new MockScene(canvas, camera, Ellipsoid.WGS84); controller = new ScreenSpaceCameraController(scene); + + scene.screenSpaceCameraController = controller; + camera._scene = scene; }); afterEach(function() { diff --git a/Specs/Scene/ShadowMapSpec.js b/Specs/Scene/ShadowMapSpec.js index f91ef0dfa2b6..bf20df19a9a6 100644 --- a/Specs/Scene/ShadowMapSpec.js +++ b/Specs/Scene/ShadowMapSpec.js @@ -27,6 +27,7 @@ defineSuite([ 'Scene/OrthographicFrustum', 'Scene/PerInstanceColorAppearance', 'Scene/Primitive', + 'Scene/ShadowMode', 'Specs/createScene', 'Specs/pollToPromise', 'ThirdParty/when' @@ -58,6 +59,7 @@ defineSuite([ OrthographicFrustum, PerInstanceColorAppearance, Primitive, + ShadowMode, createScene, pollToPromise, when) { @@ -185,8 +187,7 @@ defineSuite([ }), asynchronous : false, show : false, - castShadows : true, - receiveShadows : true + shadows : ShadowMode.ENABLED })); } @@ -222,8 +223,7 @@ defineSuite([ asynchronous : false, rtcCenter : boxGeometry.boundingSphere.center, show : false, - castShadows : true, - receiveShadows : true + shadows : ShadowMode.ENABLED })); } @@ -354,8 +354,8 @@ defineSuite([ } function verifyShadows(caster, receiver) { - caster.castShadows = true; - receiver.receiveShadows = true; + caster.shadows = ShadowMode.ENABLED; + receiver.shadows = ShadowMode.ENABLED; // Render without shadows scene.shadowMap.enabled = false; @@ -369,15 +369,15 @@ defineSuite([ expect(shadowedColor).not.toEqual(unshadowedColor); // Turn shadow casting off/on - caster.castShadows = false; + caster.shadows = ShadowMode.DISABLED; expect(render()).toEqual(unshadowedColor); - caster.castShadows = true; + caster.shadows = ShadowMode.ENABLED; expect(render()).toEqual(shadowedColor); // Turn shadow receiving off/on - receiver.receiveShadows = false; + receiver.shadows = ShadowMode.DISABLED; expect(render()).toEqual(unshadowedColor); - receiver.receiveShadows = true; + receiver.shadows = ShadowMode.ENABLED; expect(render()).toEqual(shadowedColor); // Move the camera away from the shadow @@ -538,11 +538,11 @@ defineSuite([ // Render with globe casting off scene.shadowMap.enabled = true; - scene.globe.castShadows = false; + scene.globe.shadows = ShadowMode.DISABLED; expect(render()).toEqual(unshadowedColor); // Render with globe casting on - scene.globe.castShadows = true; + scene.globe.shadows = ShadowMode.ENABLED; var shadowedColor = render(); expect(shadowedColor).not.toEqual(backgroundColor); expect(shadowedColor).not.toEqual(unshadowedColor); diff --git a/Specs/Widgets/Geocoder/GeocoderViewModelSpec.js b/Specs/Widgets/Geocoder/GeocoderViewModelSpec.js index ba6bcbb143e6..3df6917aad7d 100644 --- a/Specs/Widgets/Geocoder/GeocoderViewModelSpec.js +++ b/Specs/Widgets/Geocoder/GeocoderViewModelSpec.js @@ -38,6 +38,7 @@ defineSuite([ expect(viewModel.flightDuration).toBe(flightDuration); expect(viewModel.url).toBe(url); expect(viewModel.key).toBe(key); + expect(viewModel.keepExpanded).toBe(false); }); it('can get and set flight duration', function() { diff --git a/Specs/Widgets/Viewer/ViewerSpec.js b/Specs/Widgets/Viewer/ViewerSpec.js index 5975bd670773..5fd773162693 100644 --- a/Specs/Widgets/Viewer/ViewerSpec.js +++ b/Specs/Widgets/Viewer/ViewerSpec.js @@ -18,6 +18,7 @@ defineSuite([ 'Scene/CameraFlightPath', 'Scene/ImageryLayerCollection', 'Scene/SceneMode', + 'Scene/ShadowMode', 'Specs/createViewer', 'Specs/DomEventSimulator', 'Specs/MockDataSource', @@ -52,6 +53,7 @@ defineSuite([ CameraFlightPath, ImageryLayerCollection, SceneMode, + ShadowMode, createViewer, DomEventSimulator, MockDataSource, @@ -363,9 +365,9 @@ defineSuite([ it('can set terrain shadows', function() { viewer = createViewer(container, { - terrainShadows : true + terrainShadows : ShadowMode.ENABLED }); - expect(viewer.terrainShadows).toBe(true); + expect(viewer.terrainShadows).toBe(ShadowMode.ENABLED); }); it('can set terrainProvider', function() { diff --git a/gulpfile.js b/gulpfile.js index 50e906f8c27b..2c0d3842a01c 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -21,6 +21,7 @@ var gulpInsert = require('gulp-insert'); var gulpZip = require('gulp-zip'); var gulpRename = require('gulp-rename'); var gulpReplace = require('gulp-replace'); +var os = require('os'); var Promise = require('bluebird'); var requirejs = require('requirejs'); var karma = require('karma').Server; @@ -371,7 +372,8 @@ function deployCesium(bucketName, uploadDirectory, cacheControl, done) { return getCredentials() .then(function() { - return listAll(s3, bucketName, uploadDirectory, existingBlobs) + var prefix = uploadDirectory + '/'; + return listAll(s3, bucketName, prefix, existingBlobs) .then(function() { return globby([ 'Apps/**', @@ -538,11 +540,11 @@ function getMimeType(filename) { } // get all files currently in bucket asynchronously -function listAll(s3, bucketName, directory, files, marker) { +function listAll(s3, bucketName, prefix, files, marker) { return s3.listObjectsAsync({ Bucket : bucketName, MaxKeys : 1000, - Prefix: directory, + Prefix : prefix, Marker : marker }) .then(function(data) { @@ -553,7 +555,7 @@ function listAll(s3, bucketName, directory, files, marker) { if (data.IsTruncated) { // get next page of results - return listAll(s3, bucketName, directory, files, files[files.length - 1]); + return listAll(s3, bucketName, prefix, files, files[files.length - 1]); } }); } @@ -699,19 +701,14 @@ gulp.task('sortRequires', function() { var noModulesRegex = /[\s\S]*?define\(function\(\)/; var requiresRegex = /([\s\S]*?(define|defineSuite|require)\((?:{[\s\S]*}, )?\[)([\S\s]*?)]([\s\S]*?function\s*)\(([\S\s]*?)\) {([\s\S]*)/; var splitRegex = /,\s*/; - var filesChecked = 0; var fsReadFile = Promise.promisify(fs.readFile); var fsWriteFile = Promise.promisify(fs.writeFile); var files = globby.sync(filesToSortRequires); return Promise.map(files, function(file) { - if (filesChecked > 0 && filesChecked % 50 === 0) { - console.log('Sorted requires in ' + filesChecked + ' files'); - } - ++filesChecked; - fsReadFile(file).then(function(contents) { + return fsReadFile(file).then(function(contents) { var result = requiresRegex.exec(contents); @@ -800,15 +797,15 @@ gulp.task('sortRequires', function() { var outputNames = ']'; if (sortedNames.length > 0) { - outputNames = '\r\n ' + - sortedNames.join(',\r\n ') + - '\r\n ]'; + outputNames = os.EOL + ' ' + + sortedNames.join(',' + os.EOL + ' ') + + os.EOL + ' ]'; } var outputIdentifiers = '('; if (sortedIdentifiers.length > 0) { - outputIdentifiers = '(\r\n ' + - sortedIdentifiers.join(',\r\n '); + outputIdentifiers = '(' + os.EOL + ' ' + + sortedIdentifiers.join(',' + os.EOL + ' '); } contents = result[1] + diff --git a/package.json b/package.json index a0b55b5a2ebf..77221d7424a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cesium", - "version": "1.24.0", + "version": "1.25.0", "description": "Cesium is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.", "homepage": "http://cesiumjs.org", "license": "Apache-2.0", @@ -8,10 +8,10 @@ "name": "Analytical Graphics, Inc.", "url": "http://www.agi.com" }, - "contributors": { + "contributors": [{ "name": "Cesium community", "url": "https://github.com/AnalyticalGraphicsInc/cesium/blob/master/CONTRIBUTORS.md" - }, + }], "keywords": [ "3D", "webgl", @@ -32,11 +32,11 @@ }, "devDependencies": { "almond": "0.3.2", - "aws-sdk": "2.4.10", - "bluebird": "3.4.1", + "aws-sdk": "2.5.4", + "bluebird": "3.4.5", "compressible": "2.0.8", "compression": "1.6.2", - "electron-prebuilt": "1.3.1", + "electron-prebuilt": "1.3.4", "event-stream": "3.3.4", "express": "4.14.0", "globby": "6.0.0", @@ -48,10 +48,10 @@ "gulp-zip": "3.0.2", "jasmine-core": "2.4.1", "jsdoc": "3.4.0", - "jshint": "2.9.2", - "jshint-stylish": "2.2.0", - "karma": "1.1.2", - "karma-chrome-launcher": "1.0.1", + "jshint": "2.9.3", + "jshint-stylish": "2.2.1", + "karma": "1.2.0", + "karma-chrome-launcher": "2.0.0", "karma-detect-browsers": "2.1.0", "karma-electron-launcher": "0.1.0", "karma-firefox-launcher": "1.0.0", @@ -65,7 +65,7 @@ "request": "2.74.0", "rimraf": "2.5.3", "strip-comments": "0.3.2", - "yargs": "4.8.1" + "yargs": "5.0.0" }, "scripts": { "start": "node server.js",