123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811 |
- import BoundingSphere from '../Core/BoundingSphere.js';
- import buildModuleUrl from '../Core/buildModuleUrl.js';
- import Cartesian3 from '../Core/Cartesian3.js';
- import Cartographic from '../Core/Cartographic.js';
- import defaultValue from '../Core/defaultValue.js';
- import defined from '../Core/defined.js';
- import defineProperties from '../Core/defineProperties.js';
- import destroyObject from '../Core/destroyObject.js';
- import DeveloperError from '../Core/DeveloperError.js';
- import Ellipsoid from '../Core/Ellipsoid.js';
- import EllipsoidTerrainProvider from '../Core/EllipsoidTerrainProvider.js';
- import Event from '../Core/Event.js';
- import IntersectionTests from '../Core/IntersectionTests.js';
- import Ray from '../Core/Ray.js';
- import Rectangle from '../Core/Rectangle.js';
- import Resource from '../Core/Resource.js';
- import ShaderSource from '../Renderer/ShaderSource.js';
- import Texture from '../Renderer/Texture.js';
- import GlobeFS from '../Shaders/GlobeFS.js';
- import GlobeVS from '../Shaders/GlobeVS.js';
- import GroundAtmosphere from '../Shaders/GroundAtmosphere.js';
- import when from '../ThirdParty/when.js';
- import GlobeSurfaceShaderSet from './GlobeSurfaceShaderSet.js';
- import GlobeSurfaceTileProvider from './GlobeSurfaceTileProvider.js';
- import ImageryLayerCollection from './ImageryLayerCollection.js';
- import QuadtreePrimitive from './QuadtreePrimitive.js';
- import SceneMode from './SceneMode.js';
- import ShadowMode from './ShadowMode.js';
- import TileSelectionResult from './TileSelectionResult.js';
- /**
- * The globe rendered in the scene, including its terrain ({@link Globe#terrainProvider})
- * and imagery layers ({@link Globe#imageryLayers}). Access the globe using {@link Scene#globe}.
- *
- * @alias Globe
- * @constructor
- *
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] Determines the size and shape of the
- * globe.
- */
- function Globe(ellipsoid) {
- ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);
- var terrainProvider = new EllipsoidTerrainProvider({
- ellipsoid : ellipsoid
- });
- var imageryLayerCollection = new ImageryLayerCollection();
- this._ellipsoid = ellipsoid;
- this._imageryLayerCollection = imageryLayerCollection;
- this._surfaceShaderSet = new GlobeSurfaceShaderSet();
- this._material = undefined;
- this._surface = new QuadtreePrimitive({
- tileProvider : new GlobeSurfaceTileProvider({
- terrainProvider : terrainProvider,
- imageryLayers : imageryLayerCollection,
- surfaceShaderSet : this._surfaceShaderSet
- })
- });
- this._terrainProvider = terrainProvider;
- this._terrainProviderChanged = new Event();
- makeShadersDirty(this);
- /**
- * Determines if the globe will be shown.
- *
- * @type {Boolean}
- * @default true
- */
- this.show = true;
- this._oceanNormalMapResourceDirty = true;
- this._oceanNormalMapResource = new Resource({
- url: buildModuleUrl('Assets/Textures/waterNormalsSmall.jpg')
- });
- /**
- * The maximum screen-space error used to drive level-of-detail refinement. Higher
- * values will provide better performance but lower visual quality.
- *
- * @type {Number}
- * @default 2
- */
- this.maximumScreenSpaceError = 2;
- /**
- * The size of the terrain tile cache, expressed as a number of tiles. Any additional
- * tiles beyond this number will be freed, as long as they aren't needed for rendering
- * this frame. A larger number will consume more memory but will show detail faster
- * when, for example, zooming out and then back in.
- *
- * @type {Number}
- * @default 100
- */
- this.tileCacheSize = 100;
- /**
- * Gets or sets the number of loading descendant tiles that is considered "too many".
- * If a tile has too many loading descendants, that tile will be loaded and rendered before any of
- * its descendants are loaded and rendered. This means more feedback for the user that something
- * is happening at the cost of a longer overall load time. Setting this to 0 will cause each
- * tile level to be loaded successively, significantly increasing load time. Setting it to a large
- * number (e.g. 1000) will minimize the number of tiles that are loaded but tend to make
- * detail appear all at once after a long wait.
- * @type {Number}
- * @default 20
- */
- this.loadingDescendantLimit = 20;
- /**
- * Gets or sets a value indicating whether the ancestors of rendered tiles should be preloaded.
- * Setting this to true optimizes the zoom-out experience and provides more detail in
- * newly-exposed areas when panning. The down side is that it requires loading more tiles.
- * @type {Boolean}
- * @default true
- */
- this.preloadAncestors = true;
- /**
- * Gets or sets a value indicating whether the siblings of rendered tiles should be preloaded.
- * Setting this to true causes tiles with the same parent as a rendered tile to be loaded, even
- * if they are culled. Setting this to true may provide a better panning experience at the
- * cost of loading more tiles.
- * @type {Boolean}
- * @default false
- */
- this.preloadSiblings = false;
- /**
- * The color to use to highlight terrain fill tiles. If undefined, fill tiles are not
- * highlighted at all. The alpha value is used to alpha blend with the tile's
- * actual color. Because terrain fill tiles do not represent the actual terrain surface,
- * it may be useful in some applications to indicate visually that they are not to be trusted.
- * @type {Color}
- * @default undefined
- */
- this.fillHighlightColor = undefined;
- /**
- * Enable lighting the globe with the sun as a light source.
- *
- * @type {Boolean}
- * @default false
- */
- this.enableLighting = false;
- /**
- * Enable the ground atmosphere, which is drawn over the globe when viewed from a distance between <code>lightingFadeInDistance</code> and <code>lightingFadeOutDistance</code>.
- *
- * @demo {@link https://sandcastle.cesium.com/index.html?src=Ground%20Atmosphere.html|Ground atmosphere demo in Sandcastle}
- *
- * @type {Boolean}
- * @default true
- */
- this.showGroundAtmosphere = true;
- /**
- * The distance where everything becomes lit. This only takes effect
- * when <code>enableLighting</code> or <code>showGroundAtmosphere</code> is <code>true</code>.
- *
- * @type {Number}
- * @default 10000000.0
- */
- this.lightingFadeOutDistance = 1.0e7;
- /**
- * The distance where lighting resumes. This only takes effect
- * when <code>enableLighting</code> or <code>showGroundAtmosphere</code> is <code>true</code>.
- *
- * @type {Number}
- * @default 20000000.0
- */
- this.lightingFadeInDistance = 2.0e7;
- /**
- * The distance where the darkness of night from the ground atmosphere fades out to a lit ground atmosphere.
- * This only takes effect when <code>showGroundAtmosphere</code> and <code>enableLighting</code> are <code>true</code>.
- *
- * @type {Number}
- * @default 10000000.0
- */
- this.nightFadeOutDistance = 1.0e7;
- /**
- * The distance where the darkness of night from the ground atmosphere fades in to an unlit ground atmosphere.
- * This only takes effect when <code>showGroundAtmosphere</code> and <code>enableLighting</code> are <code>true</code>.
- *
- * @type {Number}
- * @default 50000000.0
- */
- this.nightFadeInDistance = 5.0e7;
- /**
- * True if an animated wave effect should be shown in areas of the globe
- * covered by water; otherwise, false. This property is ignored if the
- * <code>terrainProvider</code> does not provide a water mask.
- *
- * @type {Boolean}
- * @default true
- */
- this.showWaterEffect = true;
- /**
- * True if primitives such as billboards, polylines, labels, etc. should be depth-tested
- * against the terrain surface, or false if such primitives should always be drawn on top
- * of terrain unless they're on the opposite side of the globe. The disadvantage of depth
- * testing primitives against terrain is that slight numerical noise or terrain level-of-detail
- * switched can sometimes make a primitive that should be on the surface disappear underneath it.
- *
- * @type {Boolean}
- * @default false
- *
- */
- this.depthTestAgainstTerrain = false;
- /**
- * 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 {ShadowMode}
- * @default ShadowMode.RECEIVE_ONLY
- */
- this.shadows = ShadowMode.RECEIVE_ONLY;
- /**
- * The hue shift to apply to the atmosphere. Defaults to 0.0 (no shift).
- * A hue shift of 1.0 indicates a complete rotation of the hues available.
- * @type {Number}
- * @default 0.0
- */
- this.atmosphereHueShift = 0.0;
- /**
- * The saturation shift to apply to the atmosphere. Defaults to 0.0 (no shift).
- * A saturation shift of -1.0 is monochrome.
- * @type {Number}
- * @default 0.0
- */
- this.atmosphereSaturationShift = 0.0;
- /**
- * The brightness shift to apply to the atmosphere. Defaults to 0.0 (no shift).
- * A brightness shift of -1.0 is complete darkness, which will let space show through.
- * @type {Number}
- * @default 0.0
- */
- this.atmosphereBrightnessShift = 0.0;
- this._oceanNormalMap = undefined;
- this._zoomedOutOceanSpecularIntensity = undefined;
- }
- defineProperties(Globe.prototype, {
- /**
- * Gets an ellipsoid describing the shape of this globe.
- * @memberof Globe.prototype
- * @type {Ellipsoid}
- */
- ellipsoid : {
- get : function() {
- return this._ellipsoid;
- }
- },
- /**
- * Gets the collection of image layers that will be rendered on this globe.
- * @memberof Globe.prototype
- * @type {ImageryLayerCollection}
- */
- imageryLayers : {
- get : function() {
- return this._imageryLayerCollection;
- }
- },
- /**
- * Gets an event that's raised when an imagery layer is added, shown, hidden, moved, or removed.
- *
- * @memberof Globe.prototype
- * @type {Event}
- * @readonly
- */
- imageryLayersUpdatedEvent : {
- get : function() {
- return this._surface.tileProvider.imageryLayersUpdatedEvent;
- }
- },
- /**
- * Returns <code>true</code> when the tile load queue is empty, <code>false</code> otherwise. When the load queue is empty,
- * all terrain and imagery for the current view have been loaded.
- * @memberof Globe.prototype
- * @type {Boolean}
- * @readonly
- */
- tilesLoaded: {
- get: function() {
- if (!defined(this._surface)) {
- return true;
- }
- return (this._surface.tileProvider.ready && this._surface._tileLoadQueueHigh.length === 0 && this._surface._tileLoadQueueMedium.length === 0 && this._surface._tileLoadQueueLow.length === 0);
- }
- },
- /**
- * Gets or sets the color of the globe when no imagery is available.
- * @memberof Globe.prototype
- * @type {Color}
- */
- baseColor : {
- get : function() {
- return this._surface.tileProvider.baseColor;
- },
- set : function(value) {
- this._surface.tileProvider.baseColor = value;
- }
- },
- /**
- * A property specifying a {@link ClippingPlaneCollection} used to selectively disable rendering on the outside of each plane.
- *
- * @memberof Globe.prototype
- * @type {ClippingPlaneCollection}
- */
- clippingPlanes : {
- get : function() {
- return this._surface.tileProvider.clippingPlanes;
- },
- set : function(value) {
- this._surface.tileProvider.clippingPlanes = value;
- }
- },
- /**
- * A property specifying a {@link Rectangle} used to limit globe rendering to a cartographic area.
- * Defaults to the maximum extent of cartographic coordinates.
- *
- * @member Globe.prototype
- * @type {Rectangle}
- * @default Rectangle.MAX_VALUE
- */
- cartographicLimitRectangle : {
- get : function() {
- return this._surface.tileProvider.cartographicLimitRectangle;
- },
- set : function(value) {
- if (!defined(value)) {
- value = Rectangle.clone(Rectangle.MAX_VALUE);
- }
- this._surface.tileProvider.cartographicLimitRectangle = value;
- }
- },
- /**
- * The normal map to use for rendering waves in the ocean. Setting this property will
- * only have an effect if the configured terrain provider includes a water mask.
- * @memberof Globe.prototype
- * @type {String}
- * @default buildModuleUrl('Assets/Textures/waterNormalsSmall.jpg')
- */
- oceanNormalMapUrl: {
- get: function() {
- return this._oceanNormalMapResource.url;
- },
- set: function(value) {
- this._oceanNormalMapResource.url = value;
- this._oceanNormalMapResourceDirty = true;
- }
- },
- /**
- * The terrain provider providing surface geometry for this globe.
- * @type {TerrainProvider}
- *
- * @memberof Globe.prototype
- * @type {TerrainProvider}
- *
- */
- terrainProvider : {
- get : function() {
- return this._terrainProvider;
- },
- set : function(value) {
- if (value !== this._terrainProvider) {
- this._terrainProvider = value;
- this._terrainProviderChanged.raiseEvent(value);
- if (defined(this._material)) {
- makeShadersDirty(this);
- }
- }
- }
- },
- /**
- * Gets an event that's raised when the terrain provider is changed
- *
- * @memberof Globe.prototype
- * @type {Event}
- * @readonly
- */
- terrainProviderChanged : {
- get: function() {
- return this._terrainProviderChanged;
- }
- },
- /**
- * Gets an event that's raised when the length of the tile load queue has changed since the last render frame. When the load queue is empty,
- * all terrain and imagery for the current view have been loaded. The event passes the new length of the tile load queue.
- *
- * @memberof Globe.prototype
- * @type {Event}
- */
- tileLoadProgressEvent : {
- get: function() {
- return this._surface.tileLoadProgressEvent;
- }
- },
- /**
- * Gets or sets the material appearance of the Globe. This can be one of several built-in {@link Material} objects or a custom material, scripted with
- * {@link https://github.com/AnalyticalGraphicsInc/cesium/wiki/Fabric|Fabric}.
- * @memberof Globe.prototype
- * @type {Material}
- */
- material: {
- get: function() {
- return this._material;
- },
- set: function(material) {
- if (this._material !== material) {
- this._material = material;
- makeShadersDirty(this);
- }
- }
- }
- });
- function makeShadersDirty(globe) {
- var defines = [];
- var requireNormals = defined(globe._material) && (globe._material.shaderSource.match(/slope/) || globe._material.shaderSource.match('normalEC'));
- var fragmentSources = [GroundAtmosphere];
- if (defined(globe._material) && (!requireNormals || globe._terrainProvider.requestVertexNormals)) {
- fragmentSources.push(globe._material.shaderSource);
- defines.push('APPLY_MATERIAL');
- globe._surface._tileProvider.uniformMap = globe._material._uniforms;
- } else {
- globe._surface._tileProvider.uniformMap = undefined;
- }
- fragmentSources.push(GlobeFS);
- globe._surfaceShaderSet.baseVertexShaderSource = new ShaderSource({
- sources : [GroundAtmosphere, GlobeVS],
- defines : defines
- });
- globe._surfaceShaderSet.baseFragmentShaderSource = new ShaderSource({
- sources : fragmentSources,
- defines : defines
- });
- globe._surfaceShaderSet.material = globe._material;
- }
- function createComparePickTileFunction(rayOrigin) {
- return function(a, b) {
- var aDist = BoundingSphere.distanceSquaredTo(a.pickBoundingSphere, rayOrigin);
- var bDist = BoundingSphere.distanceSquaredTo(b.pickBoundingSphere, rayOrigin);
- return aDist - bDist;
- };
- }
- var scratchArray = [];
- var scratchSphereIntersectionResult = {
- start : 0.0,
- stop : 0.0
- };
- /**
- * Find an intersection between a ray and the globe surface that was rendered. The ray must be given in world coordinates.
- *
- * @param {Ray} ray The ray to test for intersection.
- * @param {Scene} scene The scene.
- * @param {Cartesian3} [result] The object onto which to store the result.
- * @returns {Cartesian3|undefined} The intersection or <code>undefined</code> if none was found. The returned position is in projected coordinates for 2D and Columbus View.
- *
- * @private
- */
- Globe.prototype.pickWorldCoordinates = function(ray, scene, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!defined(ray)) {
- throw new DeveloperError('ray is required');
- }
- if (!defined(scene)) {
- throw new DeveloperError('scene is required');
- }
- //>>includeEnd('debug');
- var mode = scene.mode;
- var projection = scene.mapProjection;
- var sphereIntersections = scratchArray;
- sphereIntersections.length = 0;
- var tilesToRender = this._surface._tilesToRender;
- var length = tilesToRender.length;
- var tile;
- var i;
- for (i = 0; i < length; ++i) {
- tile = tilesToRender[i];
- var surfaceTile = tile.data;
- if (!defined(surfaceTile)) {
- continue;
- }
- var boundingVolume = surfaceTile.pickBoundingSphere;
- if (mode !== SceneMode.SCENE3D) {
- surfaceTile.pickBoundingSphere = boundingVolume = BoundingSphere.fromRectangleWithHeights2D(tile.rectangle, projection, surfaceTile.tileBoundingRegion.minimumHeight, surfaceTile.tileBoundingRegion.maximumHeight, boundingVolume);
- Cartesian3.fromElements(boundingVolume.center.z, boundingVolume.center.x, boundingVolume.center.y, boundingVolume.center);
- } else if (defined(surfaceTile.renderedMesh)) {
- BoundingSphere.clone(surfaceTile.renderedMesh.boundingSphere3D, boundingVolume);
- } else {
- // So wait how did we render this thing then? It shouldn't be possible to get here.
- continue;
- }
- var boundingSphereIntersection = IntersectionTests.raySphere(ray, boundingVolume, scratchSphereIntersectionResult);
- if (defined(boundingSphereIntersection)) {
- sphereIntersections.push(surfaceTile);
- }
- }
- sphereIntersections.sort(createComparePickTileFunction(ray.origin));
- var intersection;
- length = sphereIntersections.length;
- for (i = 0; i < length; ++i) {
- intersection = sphereIntersections[i].pick(ray, scene.mode, scene.mapProjection, true, result);
- if (defined(intersection)) {
- break;
- }
- }
- return intersection;
- };
- var cartoScratch = new Cartographic();
- /**
- * Find an intersection between a ray and the globe surface that was rendered. The ray must be given in world coordinates.
- *
- * @param {Ray} ray The ray to test for intersection.
- * @param {Scene} scene The scene.
- * @param {Cartesian3} [result] The object onto which to store the result.
- * @returns {Cartesian3|undefined} The intersection or <code>undefined</code> if none was found.
- *
- * @example
- * // find intersection of ray through a pixel and the globe
- * var ray = viewer.camera.getPickRay(windowCoordinates);
- * var intersection = globe.pick(ray, scene);
- */
- Globe.prototype.pick = function(ray, scene, result) {
- result = this.pickWorldCoordinates(ray, scene, result);
- if (defined(result) && scene.mode !== SceneMode.SCENE3D) {
- result = Cartesian3.fromElements(result.y, result.z, result.x, result);
- var carto = scene.mapProjection.unproject(result, cartoScratch);
- result = scene.globe.ellipsoid.cartographicToCartesian(carto, result);
- }
- return result;
- };
- var scratchGetHeightCartesian = new Cartesian3();
- var scratchGetHeightIntersection = new Cartesian3();
- var scratchGetHeightCartographic = new Cartographic();
- var scratchGetHeightRay = new Ray();
- function tileIfContainsCartographic(tile, cartographic) {
- return Rectangle.contains(tile.rectangle, cartographic) ? tile : undefined;
- }
- /**
- * Get the height of the surface at a given cartographic.
- *
- * @param {Cartographic} cartographic The cartographic for which to find the height.
- * @returns {Number|undefined} The height of the cartographic or undefined if it could not be found.
- */
- Globe.prototype.getHeight = function(cartographic) {
- //>>includeStart('debug', pragmas.debug);
- if (!defined(cartographic)) {
- throw new DeveloperError('cartographic is required');
- }
- //>>includeEnd('debug');
- var levelZeroTiles = this._surface._levelZeroTiles;
- if (!defined(levelZeroTiles)) {
- return;
- }
- var tile;
- var i;
- var length = levelZeroTiles.length;
- for (i = 0; i < length; ++i) {
- tile = levelZeroTiles[i];
- if (Rectangle.contains(tile.rectangle, cartographic)) {
- break;
- }
- }
- if (i >= length) {
- return undefined;
- }
- while (tile._lastSelectionResult === TileSelectionResult.REFINED) {
- tile = tileIfContainsCartographic(tile.southwestChild, cartographic) ||
- tileIfContainsCartographic(tile.southeastChild, cartographic) ||
- tileIfContainsCartographic(tile.northwestChild, cartographic) ||
- tile.northeastChild;
- }
- // This tile was either rendered or culled.
- // It is sometimes useful to get a height from a culled tile,
- // e.g. when we're getting a height in order to place a billboard
- // on terrain, and the camera is looking at that same billboard.
- // The culled tile must have a valid mesh, though.
- if (!defined(tile.data) || !defined(tile.data.renderedMesh)) {
- // Tile was not rendered (culled).
- return undefined;
- }
- var ellipsoid = this._surface._tileProvider.tilingScheme.ellipsoid;
- //cartesian has to be on the ellipsoid surface for `ellipsoid.geodeticSurfaceNormal`
- var cartesian = Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0, ellipsoid, scratchGetHeightCartesian);
- var ray = scratchGetHeightRay;
- var surfaceNormal = ellipsoid.geodeticSurfaceNormal(cartesian, ray.direction);
- // Try to find the intersection point between the surface normal and z-axis.
- // minimum height (-11500.0) for the terrain set, need to get this information from the terrain provider
- var rayOrigin = ellipsoid.getSurfaceNormalIntersectionWithZAxis(cartesian, 11500.0, ray.origin);
- // Theoretically, not with Earth datums, the intersection point can be outside the ellipsoid
- if (!defined(rayOrigin)) {
- // intersection point is outside the ellipsoid, try other value
- // minimum height (-11500.0) for the terrain set, need to get this information from the terrain provider
- var minimumHeight;
- if (defined(tile.data.tileBoundingRegion)) {
- minimumHeight = tile.data.tileBoundingRegion.minimumHeight;
- }
- var magnitude = Math.min(defaultValue(minimumHeight, 0.0), -11500.0);
- // multiply by the *positive* value of the magnitude
- var vectorToMinimumPoint = Cartesian3.multiplyByScalar(surfaceNormal, Math.abs(magnitude) + 1, scratchGetHeightIntersection);
- Cartesian3.subtract(cartesian, vectorToMinimumPoint, ray.origin);
- }
- var intersection = tile.data.pick(ray, undefined, undefined, false, scratchGetHeightIntersection);
- if (!defined(intersection)) {
- return undefined;
- }
- return ellipsoid.cartesianToCartographic(intersection, scratchGetHeightCartographic).height;
- };
- /**
- * @private
- */
- Globe.prototype.update = function(frameState) {
- if (!this.show) {
- return;
- }
- if (frameState.passes.render) {
- this._surface.update(frameState);
- }
- };
- /**
- * @private
- */
- Globe.prototype.beginFrame = function(frameState) {
- var surface = this._surface;
- var tileProvider = surface.tileProvider;
- var terrainProvider = this.terrainProvider;
- var hasWaterMask = this.showWaterEffect && terrainProvider.ready && terrainProvider.hasWaterMask;
- if (hasWaterMask && this._oceanNormalMapResourceDirty) {
- // url changed, load new normal map asynchronously
- this._oceanNormalMapResourceDirty = false;
- var oceanNormalMapResource = this._oceanNormalMapResource;
- var oceanNormalMapUrl = oceanNormalMapResource.url;
- if (defined(oceanNormalMapUrl)) {
- var that = this;
- when(oceanNormalMapResource.fetchImage(), function(image) {
- if (oceanNormalMapUrl !== that._oceanNormalMapResource.url) {
- // url changed while we were loading
- return;
- }
- that._oceanNormalMap = that._oceanNormalMap && that._oceanNormalMap.destroy();
- that._oceanNormalMap = new Texture({
- context : frameState.context,
- source : image
- });
- });
- } else {
- this._oceanNormalMap = this._oceanNormalMap && this._oceanNormalMap.destroy();
- }
- }
- var pass = frameState.passes;
- var mode = frameState.mode;
- if (pass.render) {
- if (this.showGroundAtmosphere) {
- this._zoomedOutOceanSpecularIntensity = 0.4;
- } else {
- this._zoomedOutOceanSpecularIntensity = 0.5;
- }
- surface.maximumScreenSpaceError = this.maximumScreenSpaceError;
- surface.tileCacheSize = this.tileCacheSize;
- surface.loadingDescendantLimit = this.loadingDescendantLimit;
- surface.preloadAncestors = this.preloadAncestors;
- surface.preloadSiblings = this.preloadSiblings;
- tileProvider.terrainProvider = this.terrainProvider;
- tileProvider.lightingFadeOutDistance = this.lightingFadeOutDistance;
- tileProvider.lightingFadeInDistance = this.lightingFadeInDistance;
- tileProvider.nightFadeOutDistance = this.nightFadeOutDistance;
- tileProvider.nightFadeInDistance = this.nightFadeInDistance;
- tileProvider.zoomedOutOceanSpecularIntensity = mode === SceneMode.SCENE3D ? this._zoomedOutOceanSpecularIntensity : 0.0;
- tileProvider.hasWaterMask = hasWaterMask;
- tileProvider.oceanNormalMap = this._oceanNormalMap;
- tileProvider.enableLighting = this.enableLighting;
- tileProvider.showGroundAtmosphere = this.showGroundAtmosphere;
- tileProvider.shadows = this.shadows;
- tileProvider.hueShift = this.atmosphereHueShift;
- tileProvider.saturationShift = this.atmosphereSaturationShift;
- tileProvider.brightnessShift = this.atmosphereBrightnessShift;
- tileProvider.fillHighlightColor = this.fillHighlightColor;
- surface.beginFrame(frameState);
- }
- };
- /**
- * @private
- */
- Globe.prototype.render = function(frameState) {
- if (!this.show) {
- return;
- }
- if (defined(this._material)) {
- this._material.update(frameState.context);
- }
- this._surface.render(frameState);
- };
- /**
- * @private
- */
- Globe.prototype.endFrame = function(frameState) {
- if (!this.show) {
- return;
- }
- if (frameState.passes.render) {
- this._surface.endFrame(frameState);
- }
- };
- /**
- * Returns true if this object was destroyed; otherwise, false.
- * <br /><br />
- * If this object was destroyed, it should not be used; calling any function other than
- * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
- *
- * @returns {Boolean} True if this object was destroyed; otherwise, false.
- *
- * @see Globe#destroy
- */
- Globe.prototype.isDestroyed = function() {
- return false;
- };
- /**
- * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
- * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
- * <br /><br />
- * Once an object is destroyed, it should not be used; calling any function other than
- * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
- * assign the return value (<code>undefined</code>) to the object as done in the example.
- *
- * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
- *
- *
- * @example
- * globe = globe && globe.destroy();
- *
- * @see Globe#isDestroyed
- */
- Globe.prototype.destroy = function() {
- this._surfaceShaderSet = this._surfaceShaderSet && this._surfaceShaderSet.destroy();
- this._surface = this._surface && this._surface.destroy();
- this._oceanNormalMap = this._oceanNormalMap && this._oceanNormalMap.destroy();
- return destroyObject(this);
- };
- export default Globe;
|