| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135 | 
							- 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 Color from "../Core/Color.js";
 
- import defaultValue from "../Core/defaultValue.js";
 
- import defined from "../Core/defined.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 NearFarScalar from "../Core/NearFarScalar.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 AtmosphereCommon from "../Shaders/AtmosphereCommon.js";
 
- import GroundAtmosphere from "../Shaders/GroundAtmosphere.js";
 
- import GlobeSurfaceShaderSet from "./GlobeSurfaceShaderSet.js";
 
- import GlobeSurfaceTileProvider from "./GlobeSurfaceTileProvider.js";
 
- import GlobeTranslucency from "./GlobeTranslucency.js";
 
- import ImageryLayerCollection from "./ImageryLayerCollection.js";
 
- import QuadtreePrimitive from "./QuadtreePrimitive.js";
 
- import SceneMode from "./SceneMode.js";
 
- import ShadowMode from "./ShadowMode.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);
 
-   const terrainProvider = new EllipsoidTerrainProvider({
 
-     ellipsoid: ellipsoid,
 
-   });
 
-   const 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();
 
-   this._undergroundColor = Color.clone(Color.BLACK);
 
-   this._undergroundColorAlphaByDistance = new NearFarScalar(
 
-     ellipsoid.maximumRadius / 1000.0,
 
-     0.0,
 
-     ellipsoid.maximumRadius / 5.0,
 
-     1.0
 
-   );
 
-   this._translucency = new GlobeTranslucency();
 
-   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 scene's light source.
 
-    *
 
-    * @type {boolean}
 
-    * @default false
 
-    */
 
-   this.enableLighting = false;
 
-   /**
 
-    * A multiplier to adjust terrain lambert lighting.
 
-    * This number is multiplied by the result of <code>czm_getLambertDiffuse</code> in GlobeFS.glsl.
 
-    * This only takes effect when <code>enableLighting</code> is <code>true</code>.
 
-    *
 
-    * @type {number}
 
-    * @default 0.9
 
-    */
 
-   this.lambertDiffuseMultiplier = 0.9;
 
-   /**
 
-    * Enable dynamic lighting effects on atmosphere and fog. This only takes effect
 
-    * when <code>enableLighting</code> is <code>true</code>.
 
-    *
 
-    * @type {boolean}
 
-    * @default true
 
-    */
 
-   this.dynamicAtmosphereLighting = true;
 
-   /**
 
-    * Whether dynamic atmosphere lighting uses the sun direction instead of the scene's
 
-    * light direction. This only takes effect when <code>enableLighting</code> and
 
-    * <code>dynamicAtmosphereLighting</code> are <code>true</code>.
 
-    *
 
-    * @type {boolean}
 
-    * @default false
 
-    */
 
-   this.dynamicAtmosphereLightingFromSun = false;
 
-   /**
 
-    * Enable the ground atmosphere, which is drawn over the globe when viewed from a distance between <code>lightingFadeInDistance</code> and <code>lightingFadeOutDistance</code>.
 
-    *
 
-    * @type {boolean}
 
-    * @default true
 
-    */
 
-   this.showGroundAtmosphere = true;
 
-   /**
 
-    * The intensity of the light that is used for computing the ground atmosphere color.
 
-    *
 
-    * @type {number}
 
-    * @default 10.0
 
-    */
 
-   this.atmosphereLightIntensity = 10.0;
 
-   /**
 
-    * The Rayleigh scattering coefficient used in the atmospheric scattering equations for the ground atmosphere.
 
-    *
 
-    * @type {Cartesian3}
 
-    * @default Cartesian3(5.5e-6, 13.0e-6, 28.4e-6)
 
-    */
 
-   this.atmosphereRayleighCoefficient = new Cartesian3(5.5e-6, 13.0e-6, 28.4e-6);
 
-   /**
 
-    * The Mie scattering coefficient used in the atmospheric scattering equations for the ground atmosphere.
 
-    *
 
-    * @type {Cartesian3}
 
-    * @default Cartesian3(21e-6, 21e-6, 21e-6)
 
-    */
 
-   this.atmosphereMieCoefficient = new Cartesian3(21e-6, 21e-6, 21e-6);
 
-   /**
 
-    * The Rayleigh scale height used in the atmospheric scattering equations for the ground atmosphere, in meters.
 
-    *
 
-    * @type {number}
 
-    * @default 10000.0
 
-    */
 
-   this.atmosphereRayleighScaleHeight = 10000.0;
 
-   /**
 
-    * The Mie scale height used in the atmospheric scattering equations for the ground atmosphere, in meters.
 
-    *
 
-    * @type {number}
 
-    * @default 3200.0
 
-    */
 
-   this.atmosphereMieScaleHeight = 3200.0;
 
-   /**
 
-    * The anisotropy of the medium to consider for Mie scattering.
 
-    * <p>
 
-    * Valid values are between -1.0 and 1.0.
 
-    * </p>
 
-    * @type {number}
 
-    * @default 0.9
 
-    */
 
-   this.atmosphereMieAnisotropy = 0.9;
 
-   /**
 
-    * 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>, <code>enableLighting</code>, and
 
-    * <code>dynamicAtmosphereLighting</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>, <code>enableLighting</code>, and
 
-    * <code>dynamicAtmosphereLighting</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 light sources. 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;
 
-   /**
 
-    * A scalar used to exaggerate the terrain. Defaults to <code>1.0</code> (no exaggeration).
 
-    * A value of <code>2.0</code> scales the terrain by 2x.
 
-    * A value of <code>0.0</code> makes the terrain completely flat.
 
-    * Note that terrain exaggeration will not modify any other primitive as they are positioned relative to the ellipsoid.
 
-    * @type {number}
 
-    * @default 1.0
 
-    */
 
-   this.terrainExaggeration = 1.0;
 
-   /**
 
-    * The height from which terrain is exaggerated. Defaults to <code>0.0</code> (scaled relative to ellipsoid surface).
 
-    * Terrain that is above this height will scale upwards and terrain that is below this height will scale downwards.
 
-    * Note that terrain exaggeration will not modify any other primitive as they are positioned relative to the ellipsoid.
 
-    * If {@link Globe#terrainExaggeration} is <code>1.0</code> this value will have no effect.
 
-    * @type {number}
 
-    * @default 0.0
 
-    */
 
-   this.terrainExaggerationRelativeHeight = 0.0;
 
-   /**
 
-    * Whether to show terrain skirts. Terrain skirts are geometry extending downwards from a tile's edges used to hide seams between neighboring tiles.
 
-    * Skirts are always hidden when the camera is underground or translucency is enabled.
 
-    *
 
-    * @type {boolean}
 
-    * @default true
 
-    */
 
-   this.showSkirts = true;
 
-   /**
 
-    * Whether to cull back-facing terrain. Back faces are not culled when the camera is underground or translucency is enabled.
 
-    *
 
-    * @type {boolean}
 
-    * @default true
 
-    */
 
-   this.backFaceCulling = true;
 
-   this._oceanNormalMap = undefined;
 
-   this._zoomedOutOceanSpecularIntensity = undefined;
 
-   /**
 
-    * Determines the darkness of the vertex shadow.
 
-    * This only takes effect when <code>enableLighting</code> is <code>true</code>.
 
-    *
 
-    * @type {number}
 
-    * @default 0.3
 
-    */
 
-   this.vertexShadowDarkness = 0.3;
 
- }
 
- Object.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 (
 
-         // ready is deprecated. This is here for backwards compatibility
 
-         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.
 
-    *
 
-    * @memberof Globe.prototype
 
-    * @type {Rectangle}
 
-    * @default {@link 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/CesiumGS/cesium/wiki/Fabric|Fabric}.
 
-    * @memberof Globe.prototype
 
-    * @type {Material | undefined}
 
-    */
 
-   material: {
 
-     get: function () {
 
-       return this._material;
 
-     },
 
-     set: function (material) {
 
-       if (this._material !== material) {
 
-         this._material = material;
 
-         makeShadersDirty(this);
 
-       }
 
-     },
 
-   },
 
-   /**
 
-    * The color to render the back side of the globe when the camera is underground or the globe is translucent,
 
-    * blended with the globe color based on the camera's distance.
 
-    * <br /><br />
 
-    * To disable underground coloring, set <code>undergroundColor</code> to <code>undefined</code>.
 
-    *
 
-    * @memberof Globe.prototype
 
-    * @type {Color}
 
-    * @default {@link Color.BLACK}
 
-    *
 
-    * @see Globe#undergroundColorAlphaByDistance
 
-    */
 
-   undergroundColor: {
 
-     get: function () {
 
-       return this._undergroundColor;
 
-     },
 
-     set: function (value) {
 
-       this._undergroundColor = Color.clone(value, this._undergroundColor);
 
-     },
 
-   },
 
-   /**
 
-    * Gets or sets the near and far distance for blending {@link Globe#undergroundColor} with the globe color.
 
-    * The alpha will interpolate between the {@link NearFarScalar#nearValue} and
 
-    * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds
 
-    * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
 
-    * Outside of these ranges the alpha remains clamped to the nearest bound. If undefined,
 
-    * the underground color will not be blended with the globe color.
 
-    * <br /> <br />
 
-    * When the camera is above the ellipsoid the distance is computed from the nearest
 
-    * point on the ellipsoid instead of the camera's position.
 
-    *
 
-    * @memberof Globe.prototype
 
-    * @type {NearFarScalar}
 
-    *
 
-    * @see Globe#undergroundColor
 
-    *
 
-    */
 
-   undergroundColorAlphaByDistance: {
 
-     get: function () {
 
-       return this._undergroundColorAlphaByDistance;
 
-     },
 
-     set: function (value) {
 
-       //>>includeStart('debug', pragmas.debug);
 
-       if (defined(value) && value.far < value.near) {
 
-         throw new DeveloperError(
 
-           "far distance must be greater than near distance."
 
-         );
 
-       }
 
-       //>>includeEnd('debug');
 
-       this._undergroundColorAlphaByDistance = NearFarScalar.clone(
 
-         value,
 
-         this._undergroundColorAlphaByDistance
 
-       );
 
-     },
 
-   },
 
-   /**
 
-    * Properties for controlling globe translucency.
 
-    *
 
-    * @memberof Globe.prototype
 
-    * @type {GlobeTranslucency}
 
-    */
 
-   translucency: {
 
-     get: function () {
 
-       return this._translucency;
 
-     },
 
-   },
 
- });
 
- function makeShadersDirty(globe) {
 
-   const defines = [];
 
-   const requireNormals =
 
-     defined(globe._material) &&
 
-     (globe._material.shaderSource.match(/slope/) ||
 
-       globe._material.shaderSource.match("normalEC"));
 
-   const fragmentSources = [AtmosphereCommon, GroundAtmosphere];
 
-   if (
 
-     defined(globe._material) &&
 
-     (!requireNormals || globe._terrainProvider.requestVertexNormals)
 
-   ) {
 
-     fragmentSources.push(globe._material.shaderSource);
 
-     defines.push("APPLY_MATERIAL");
 
-     globe._surface._tileProvider.materialUniformMap = globe._material._uniforms;
 
-   } else {
 
-     globe._surface._tileProvider.materialUniformMap = undefined;
 
-   }
 
-   fragmentSources.push(GlobeFS);
 
-   globe._surfaceShaderSet.baseVertexShaderSource = new ShaderSource({
 
-     sources: [AtmosphereCommon, 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) {
 
-     const aDist = BoundingSphere.distanceSquaredTo(
 
-       a.pickBoundingSphere,
 
-       rayOrigin
 
-     );
 
-     const bDist = BoundingSphere.distanceSquaredTo(
 
-       b.pickBoundingSphere,
 
-       rayOrigin
 
-     );
 
-     return aDist - bDist;
 
-   };
 
- }
 
- const scratchArray = [];
 
- const 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 {boolean} [cullBackFaces=true] Set to true to not pick back faces.
 
-  * @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,
 
-   cullBackFaces,
 
-   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');
 
-   cullBackFaces = defaultValue(cullBackFaces, true);
 
-   const mode = scene.mode;
 
-   const projection = scene.mapProjection;
 
-   const sphereIntersections = scratchArray;
 
-   sphereIntersections.length = 0;
 
-   const tilesToRender = this._surface._tilesToRender;
 
-   let length = tilesToRender.length;
 
-   let tile;
 
-   let i;
 
-   for (i = 0; i < length; ++i) {
 
-     tile = tilesToRender[i];
 
-     const surfaceTile = tile.data;
 
-     if (!defined(surfaceTile)) {
 
-       continue;
 
-     }
 
-     let 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.tileBoundingRegion.boundingSphere,
 
-         boundingVolume
 
-       );
 
-     } else {
 
-       // So wait how did we render this thing then? It shouldn't be possible to get here.
 
-       continue;
 
-     }
 
-     const boundingSphereIntersection = IntersectionTests.raySphere(
 
-       ray,
 
-       boundingVolume,
 
-       scratchSphereIntersectionResult
 
-     );
 
-     if (defined(boundingSphereIntersection)) {
 
-       sphereIntersections.push(surfaceTile);
 
-     }
 
-   }
 
-   sphereIntersections.sort(createComparePickTileFunction(ray.origin));
 
-   let intersection;
 
-   length = sphereIntersections.length;
 
-   for (i = 0; i < length; ++i) {
 
-     intersection = sphereIntersections[i].pick(
 
-       ray,
 
-       scene.mode,
 
-       scene.mapProjection,
 
-       cullBackFaces,
 
-       result
 
-     );
 
-     if (defined(intersection)) {
 
-       break;
 
-     }
 
-   }
 
-   return intersection;
 
- };
 
- const 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
 
-  * const ray = viewer.camera.getPickRay(windowCoordinates);
 
-  * const intersection = globe.pick(ray, scene);
 
-  */
 
- Globe.prototype.pick = function (ray, scene, result) {
 
-   result = this.pickWorldCoordinates(ray, scene, true, result);
 
-   if (defined(result) && scene.mode !== SceneMode.SCENE3D) {
 
-     result = Cartesian3.fromElements(result.y, result.z, result.x, result);
 
-     const carto = scene.mapProjection.unproject(result, cartoScratch);
 
-     result = scene.globe.ellipsoid.cartographicToCartesian(carto, result);
 
-   }
 
-   return result;
 
- };
 
- const scratchGetHeightCartesian = new Cartesian3();
 
- const scratchGetHeightIntersection = new Cartesian3();
 
- const scratchGetHeightCartographic = new Cartographic();
 
- const scratchGetHeightRay = new Ray();
 
- function tileIfContainsCartographic(tile, cartographic) {
 
-   return defined(tile) && 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');
 
-   const levelZeroTiles = this._surface._levelZeroTiles;
 
-   if (!defined(levelZeroTiles)) {
 
-     return;
 
-   }
 
-   let tile;
 
-   let i;
 
-   const length = levelZeroTiles.length;
 
-   for (i = 0; i < length; ++i) {
 
-     tile = levelZeroTiles[i];
 
-     if (Rectangle.contains(tile.rectangle, cartographic)) {
 
-       break;
 
-     }
 
-   }
 
-   if (i >= length) {
 
-     return undefined;
 
-   }
 
-   let tileWithMesh = tile;
 
-   while (defined(tile)) {
 
-     tile =
 
-       tileIfContainsCartographic(tile._southwestChild, cartographic) ||
 
-       tileIfContainsCartographic(tile._southeastChild, cartographic) ||
 
-       tileIfContainsCartographic(tile._northwestChild, cartographic) ||
 
-       tile._northeastChild;
 
-     if (
 
-       defined(tile) &&
 
-       defined(tile.data) &&
 
-       defined(tile.data.renderedMesh)
 
-     ) {
 
-       tileWithMesh = tile;
 
-     }
 
-   }
 
-   tile = tileWithMesh;
 
-   // 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) ||
 
-     !defined(tile.data) ||
 
-     !defined(tile.data.renderedMesh)
 
-   ) {
 
-     // Tile was not rendered (culled).
 
-     return undefined;
 
-   }
 
-   const projection = this._surface._tileProvider.tilingScheme.projection;
 
-   const ellipsoid = this._surface._tileProvider.tilingScheme.ellipsoid;
 
-   //cartesian has to be on the ellipsoid surface for `ellipsoid.geodeticSurfaceNormal`
 
-   const cartesian = Cartesian3.fromRadians(
 
-     cartographic.longitude,
 
-     cartographic.latitude,
 
-     0.0,
 
-     ellipsoid,
 
-     scratchGetHeightCartesian
 
-   );
 
-   const ray = scratchGetHeightRay;
 
-   const 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
 
-   const 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
 
-     let minimumHeight;
 
-     if (defined(tile.data.tileBoundingRegion)) {
 
-       minimumHeight = tile.data.tileBoundingRegion.minimumHeight;
 
-     }
 
-     const magnitude = Math.min(defaultValue(minimumHeight, 0.0), -11500.0);
 
-     // multiply by the *positive* value of the magnitude
 
-     const vectorToMinimumPoint = Cartesian3.multiplyByScalar(
 
-       surfaceNormal,
 
-       Math.abs(magnitude) + 1,
 
-       scratchGetHeightIntersection
 
-     );
 
-     Cartesian3.subtract(cartesian, vectorToMinimumPoint, ray.origin);
 
-   }
 
-   const intersection = tile.data.pick(
 
-     ray,
 
-     undefined,
 
-     projection,
 
-     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) {
 
-   const surface = this._surface;
 
-   const tileProvider = surface.tileProvider;
 
-   const terrainProvider = this.terrainProvider;
 
-   const hasWaterMask =
 
-     this.showWaterEffect &&
 
-     defined(terrainProvider) &&
 
-     terrainProvider.hasWaterMask &&
 
-     // ready is deprecated; This is here for backwards compatibility
 
-     terrainProvider._ready &&
 
-     terrainProvider.hasWaterMask;
 
-   if (hasWaterMask && this._oceanNormalMapResourceDirty) {
 
-     // url changed, load new normal map asynchronously
 
-     this._oceanNormalMapResourceDirty = false;
 
-     const oceanNormalMapResource = this._oceanNormalMapResource;
 
-     const oceanNormalMapUrl = oceanNormalMapResource.url;
 
-     if (defined(oceanNormalMapUrl)) {
 
-       const that = this;
 
-       oceanNormalMapResource.fetchImage().then(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();
 
-     }
 
-   }
 
-   const pass = frameState.passes;
 
-   const 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.dynamicAtmosphereLighting = this.dynamicAtmosphereLighting;
 
-     tileProvider.dynamicAtmosphereLightingFromSun = this.dynamicAtmosphereLightingFromSun;
 
-     tileProvider.showGroundAtmosphere = this.showGroundAtmosphere;
 
-     tileProvider.atmosphereLightIntensity = this.atmosphereLightIntensity;
 
-     tileProvider.atmosphereRayleighCoefficient = this.atmosphereRayleighCoefficient;
 
-     tileProvider.atmosphereMieCoefficient = this.atmosphereMieCoefficient;
 
-     tileProvider.atmosphereRayleighScaleHeight = this.atmosphereRayleighScaleHeight;
 
-     tileProvider.atmosphereMieScaleHeight = this.atmosphereMieScaleHeight;
 
-     tileProvider.atmosphereMieAnisotropy = this.atmosphereMieAnisotropy;
 
-     tileProvider.shadows = this.shadows;
 
-     tileProvider.hueShift = this.atmosphereHueShift;
 
-     tileProvider.saturationShift = this.atmosphereSaturationShift;
 
-     tileProvider.brightnessShift = this.atmosphereBrightnessShift;
 
-     tileProvider.fillHighlightColor = this.fillHighlightColor;
 
-     tileProvider.showSkirts = this.showSkirts;
 
-     tileProvider.backFaceCulling = this.backFaceCulling;
 
-     tileProvider.vertexShadowDarkness = this.vertexShadowDarkness;
 
-     tileProvider.undergroundColor = this._undergroundColor;
 
-     tileProvider.undergroundColorAlphaByDistance = this._undergroundColorAlphaByDistance;
 
-     tileProvider.lambertDiffuseMultiplier = this.lambertDiffuseMultiplier;
 
-     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;
 
 
  |