123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032 |
- 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 GroundAtmosphere from "../Shaders/GroundAtmosphere.js";
- import when from "../ThirdParty/when.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";
- 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();
- 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);
-
- this.show = true;
- this._oceanNormalMapResourceDirty = true;
- this._oceanNormalMapResource = new Resource({
- url: buildModuleUrl("Assets/Textures/waterNormalsSmall.jpg"),
- });
-
- this.maximumScreenSpaceError = 2;
-
- this.tileCacheSize = 100;
-
- this.loadingDescendantLimit = 20;
-
- this.preloadAncestors = true;
-
- this.preloadSiblings = false;
-
- this.fillHighlightColor = undefined;
-
- this.enableLighting = false;
-
- this.dynamicAtmosphereLighting = true;
-
- this.dynamicAtmosphereLightingFromSun = false;
-
- this.showGroundAtmosphere = true;
-
- this.lightingFadeOutDistance = 1.0e7;
-
- this.lightingFadeInDistance = 2.0e7;
-
- this.nightFadeOutDistance = 1.0e7;
-
- this.nightFadeInDistance = 5.0e7;
-
- this.showWaterEffect = true;
-
- this.depthTestAgainstTerrain = false;
-
- this.shadows = ShadowMode.RECEIVE_ONLY;
-
- this.atmosphereHueShift = 0.0;
-
- this.atmosphereSaturationShift = 0.0;
-
- this.atmosphereBrightnessShift = 0.0;
-
- this.showSkirts = true;
-
- this.backFaceCulling = true;
- this._oceanNormalMap = undefined;
- this._zoomedOutOceanSpecularIntensity = undefined;
- }
- Object.defineProperties(Globe.prototype, {
-
- ellipsoid: {
- get: function () {
- return this._ellipsoid;
- },
- },
-
- imageryLayers: {
- get: function () {
- return this._imageryLayerCollection;
- },
- },
-
- imageryLayersUpdatedEvent: {
- get: function () {
- return this._surface.tileProvider.imageryLayersUpdatedEvent;
- },
- },
-
- 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
- );
- },
- },
-
- baseColor: {
- get: function () {
- return this._surface.tileProvider.baseColor;
- },
- set: function (value) {
- this._surface.tileProvider.baseColor = value;
- },
- },
-
- clippingPlanes: {
- get: function () {
- return this._surface.tileProvider.clippingPlanes;
- },
- set: function (value) {
- this._surface.tileProvider.clippingPlanes = 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;
- },
- },
-
- oceanNormalMapUrl: {
- get: function () {
- return this._oceanNormalMapResource.url;
- },
- set: function (value) {
- this._oceanNormalMapResource.url = value;
- this._oceanNormalMapResourceDirty = true;
- },
- },
-
- 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);
- }
- }
- },
- },
-
- terrainProviderChanged: {
- get: function () {
- return this._terrainProviderChanged;
- },
- },
-
- tileLoadProgressEvent: {
- get: function () {
- return this._surface.tileLoadProgressEvent;
- },
- },
-
- material: {
- get: function () {
- return this._material;
- },
- set: function (material) {
- if (this._material !== material) {
- this._material = material;
- makeShadersDirty(this);
- }
- },
- },
-
- undergroundColor: {
- get: function () {
- return this._undergroundColor;
- },
- set: function (value) {
- this._undergroundColor = Color.clone(value, this._undergroundColor);
- },
- },
-
- undergroundColorAlphaByDistance: {
- get: function () {
- return this._undergroundColorAlphaByDistance;
- },
- set: function (value) {
-
- if (defined(value) && value.far < value.near) {
- throw new DeveloperError(
- "far distance must be greater than near distance."
- );
- }
-
- this._undergroundColorAlphaByDistance = NearFarScalar.clone(
- value,
- this._undergroundColorAlphaByDistance
- );
- },
- },
-
- translucency: {
- get: function () {
- return this._translucency;
- },
- },
- });
- 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.materialUniformMap = globe._material._uniforms;
- } else {
- globe._surface._tileProvider.materialUniformMap = 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,
- };
- Globe.prototype.pickWorldCoordinates = function (
- ray,
- scene,
- cullBackFaces,
- result
- ) {
-
- if (!defined(ray)) {
- throw new DeveloperError("ray is required");
- }
- if (!defined(scene)) {
- throw new DeveloperError("scene is required");
- }
-
- cullBackFaces = defaultValue(cullBackFaces, true);
- 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 {
-
- 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,
- cullBackFaces,
- result
- );
- if (defined(intersection)) {
- break;
- }
- }
- return intersection;
- };
- var cartoScratch = new Cartographic();
- 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);
- 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 defined(tile) && Rectangle.contains(tile.rectangle, cartographic)
- ? tile
- : undefined;
- }
- Globe.prototype.getHeight = function (cartographic) {
-
- if (!defined(cartographic)) {
- throw new DeveloperError("cartographic is required");
- }
-
- 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;
- }
- var 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;
-
-
-
-
-
- if (
- !defined(tile) ||
- !defined(tile.data) ||
- !defined(tile.data.renderedMesh)
- ) {
-
- return undefined;
- }
- var ellipsoid = this._surface._tileProvider.tilingScheme.ellipsoid;
-
- var cartesian = Cartesian3.fromRadians(
- cartographic.longitude,
- cartographic.latitude,
- 0.0,
- ellipsoid,
- scratchGetHeightCartesian
- );
- var ray = scratchGetHeightRay;
- var surfaceNormal = ellipsoid.geodeticSurfaceNormal(cartesian, ray.direction);
-
-
- var rayOrigin = ellipsoid.getSurfaceNormalIntersectionWithZAxis(
- cartesian,
- 11500.0,
- ray.origin
- );
-
- if (!defined(rayOrigin)) {
-
-
- var minimumHeight;
- if (defined(tile.data.tileBoundingRegion)) {
- minimumHeight = tile.data.tileBoundingRegion.minimumHeight;
- }
- var magnitude = Math.min(defaultValue(minimumHeight, 0.0), -11500.0);
-
- 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;
- };
- Globe.prototype.update = function (frameState) {
- if (!this.show) {
- return;
- }
- if (frameState.passes.render) {
- this._surface.update(frameState);
- }
- };
- 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) {
-
- 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) {
-
- 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.dynamicAtmosphereLighting = this.dynamicAtmosphereLighting;
- tileProvider.dynamicAtmosphereLightingFromSun = this.dynamicAtmosphereLightingFromSun;
- tileProvider.showGroundAtmosphere = this.showGroundAtmosphere;
- 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.undergroundColor = this._undergroundColor;
- tileProvider.undergroundColorAlphaByDistance = this._undergroundColorAlphaByDistance;
- surface.beginFrame(frameState);
- }
- };
- Globe.prototype.render = function (frameState) {
- if (!this.show) {
- return;
- }
- if (defined(this._material)) {
- this._material.update(frameState.context);
- }
- this._surface.render(frameState);
- };
- Globe.prototype.endFrame = function (frameState) {
- if (!this.show) {
- return;
- }
- if (frameState.passes.render) {
- this._surface.endFrame(frameState);
- }
- };
- Globe.prototype.isDestroyed = function () {
- return false;
- };
- 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;
|