@cesium/engine 26.0.0 → 26.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Build/Workers/{chunk-EF2QYXGA.js → chunk-2EFYUSUY.js} +14 -14
- package/Build/Workers/{chunk-KFSTQKNM.js → chunk-5LSOO2KD.js} +7 -7
- package/Build/Workers/{chunk-VQYETPWC.js → chunk-6HK6IXK2.js} +4 -4
- package/Build/Workers/{chunk-AYKR4VBR.js → chunk-6YR6JBMY.js} +2 -2
- package/Build/Workers/{chunk-DOBXCNC3.js → chunk-76FDC45O.js} +13 -13
- package/Build/Workers/{chunk-54I6Y66F.js → chunk-7D2HZKH7.js} +6 -6
- package/Build/Workers/{chunk-4MGMYHOO.js → chunk-7KVKHY7O.js} +6 -6
- package/Build/Workers/{chunk-IRBKFCEJ.js → chunk-A3O6EDBK.js} +2 -2
- package/Build/Workers/{chunk-V7VQKN6N.js → chunk-A6X24AZI.js} +5 -5
- package/Build/Workers/{chunk-ZP7JMQV4.js → chunk-AHWAZRBV.js} +6 -2
- package/Build/Workers/{chunk-YLY7NKAB.js → chunk-B4CQSLZJ.js} +4 -4
- package/Build/Workers/{chunk-J6BWOHUF.js → chunk-C7JQVRLM.js} +3 -3
- package/Build/Workers/{chunk-KSSWJIZW.js → chunk-CDJDJ5LK.js} +2 -2
- package/Build/Workers/{chunk-G7PXZRVF.js → chunk-CEEZE3YZ.js} +7 -7
- package/Build/Workers/{chunk-INUEEEQA.js → chunk-CLCTQVVL.js} +8 -8
- package/Build/Workers/{chunk-O3EA5HS7.js → chunk-DBD5WWG2.js} +10 -10
- package/Build/Workers/{chunk-E7VQ76KE.js → chunk-DIGUUD6G.js} +6 -6
- package/Build/Workers/{chunk-424RNO3D.js → chunk-E7NZJOK7.js} +196 -22
- package/Build/Workers/{chunk-ACXQXN46.js → chunk-EHTS2YPT.js} +16 -16
- package/Build/Workers/{chunk-VWV2IJRB.js → chunk-ENNFMWDW.js} +11 -11
- package/Build/Workers/{chunk-FRQZECAO.js → chunk-FCP2QY4G.js} +5 -5
- package/Build/Workers/{chunk-ZZ46LWL6.js → chunk-FDK4K5IA.js} +1 -1
- package/Build/Workers/{chunk-C6KNZ7T4.js → chunk-FGQFQHN5.js} +17 -17
- package/Build/Workers/{chunk-MYP774IS.js → chunk-GSWMAFTE.js} +8 -8
- package/Build/Workers/{chunk-Y5BF6AFU.js → chunk-GXWQZBAI.js} +2 -2
- package/Build/Workers/{chunk-DDWSZVMY.js → chunk-HHV3MCGV.js} +5 -5
- package/Build/Workers/{chunk-52JDLOEM.js → chunk-HS6AD4P2.js} +14 -14
- package/Build/Workers/{chunk-Q3PY526V.js → chunk-IGAZBTFZ.js} +6 -6
- package/Build/Workers/{chunk-EBSIOBXY.js → chunk-ILME5BXA.js} +8 -8
- package/Build/Workers/{chunk-C6J67V5A.js → chunk-JKXV6PG5.js} +1 -1
- package/Build/Workers/{chunk-SMQZZOW6.js → chunk-JW6OZT4R.js} +10 -10
- package/Build/Workers/{chunk-F6QDY6HU.js → chunk-KGXSYGBG.js} +13 -13
- package/Build/Workers/{chunk-UOOIQ3KX.js → chunk-LD64RPYV.js} +12 -12
- package/Build/Workers/{chunk-CFQP6LYM.js → chunk-LGNDTZVX.js} +4 -4
- package/Build/Workers/{chunk-U3ZA64U7.js → chunk-LNSQVXFH.js} +2 -2
- package/Build/Workers/{chunk-TKKIREQ6.js → chunk-N7CCOFLX.js} +1 -1
- package/Build/Workers/{chunk-UA25D5MX.js → chunk-NIWITKQK.js} +10 -10
- package/Build/Workers/{chunk-KKOSKAZB.js → chunk-OBEU25PI.js} +17 -17
- package/Build/Workers/{chunk-M3B5JKSM.js → chunk-QVLAFFJY.js} +1 -1
- package/Build/Workers/{chunk-6YEE6JDR.js → chunk-R4FPNAZ2.js} +6 -6
- package/Build/Workers/{chunk-7J2HKPRH.js → chunk-RG4F5R57.js} +9 -9
- package/Build/Workers/{chunk-CXOYE2WM.js → chunk-SF6K72D7.js} +5 -5
- package/Build/Workers/{chunk-CZEYZU4N.js → chunk-SGRGNDOD.js} +10 -10
- package/Build/Workers/{chunk-DBOEKL43.js → chunk-SM2CDCYF.js} +7 -7
- package/Build/Workers/{chunk-Y57HREW5.js → chunk-SS5ABQGY.js} +4 -4
- package/Build/Workers/{chunk-QRWGUWI6.js → chunk-T5QBPLE3.js} +11 -11
- package/Build/Workers/{chunk-ZK3CF7ZD.js → chunk-TVZD72WJ.js} +12 -12
- package/Build/Workers/{chunk-IYOUHCZB.js → chunk-UEY73NRN.js} +1 -1
- package/Build/Workers/{chunk-7WM2PX4V.js → chunk-UVO6COT2.js} +5 -5
- package/Build/Workers/{chunk-P3CK7MCY.js → chunk-VAL7DYNR.js} +4 -4
- package/Build/Workers/{chunk-EPYXRCDB.js → chunk-WBSY7HDY.js} +12 -12
- package/Build/Workers/{chunk-4S7IE3LB.js → chunk-XDWCTQCZ.js} +2 -2
- package/Build/Workers/{chunk-QN67VG36.js → chunk-XLXSDIP5.js} +6 -6
- package/Build/Workers/{chunk-S4MCOY6I.js → chunk-XQ3SKCMM.js} +5 -5
- package/Build/Workers/{chunk-XZMBNNDX.js → chunk-YKU2Q3A2.js} +9 -9
- package/Build/Workers/{chunk-3VFEWOBI.js → chunk-ZMBHFYOX.js} +7 -7
- package/Build/Workers/{chunk-MPZHGZU6.js → chunk-ZSGUV73H.js} +4 -4
- package/Build/Workers/combineGeometry.js +24 -24
- package/Build/Workers/createBoxGeometry.js +18 -18
- package/Build/Workers/createBoxOutlineGeometry.js +16 -16
- package/Build/Workers/createCircleGeometry.js +26 -26
- package/Build/Workers/createCircleOutlineGeometry.js +19 -19
- package/Build/Workers/createCoplanarPolygonGeometry.js +33 -33
- package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +31 -31
- package/Build/Workers/createCorridorGeometry.js +29 -29
- package/Build/Workers/createCorridorOutlineGeometry.js +28 -28
- package/Build/Workers/createCylinderGeometry.js +20 -20
- package/Build/Workers/createCylinderOutlineGeometry.js +18 -18
- package/Build/Workers/createEllipseGeometry.js +26 -26
- package/Build/Workers/createEllipseOutlineGeometry.js +19 -19
- package/Build/Workers/createEllipsoidGeometry.js +19 -19
- package/Build/Workers/createEllipsoidOutlineGeometry.js +18 -18
- package/Build/Workers/createFrustumGeometry.js +18 -18
- package/Build/Workers/createFrustumOutlineGeometry.js +18 -18
- package/Build/Workers/createGeometry.js +24 -24
- package/Build/Workers/createGroundPolylineGeometry.js +22 -22
- package/Build/Workers/createPlaneGeometry.js +16 -16
- package/Build/Workers/createPlaneOutlineGeometry.js +15 -15
- package/Build/Workers/createPolygonGeometry.js +32 -32
- package/Build/Workers/createPolygonOutlineGeometry.js +30 -30
- package/Build/Workers/createPolylineGeometry.js +25 -25
- package/Build/Workers/createPolylineVolumeGeometry.js +31 -31
- package/Build/Workers/createPolylineVolumeOutlineGeometry.js +27 -27
- package/Build/Workers/createRectangleGeometry.js +27 -27
- package/Build/Workers/createRectangleOutlineGeometry.js +20 -20
- package/Build/Workers/createSimplePolylineGeometry.js +23 -23
- package/Build/Workers/createSphereGeometry.js +19 -19
- package/Build/Workers/createSphereOutlineGeometry.js +18 -18
- package/Build/Workers/createTaskProcessorWorker.js +3 -3
- package/Build/Workers/createVectorTileClampedPolylines.js +14 -14
- package/Build/Workers/createVectorTileGeometries.js +24 -24
- package/Build/Workers/createVectorTilePoints.js +13 -13
- package/Build/Workers/createVectorTilePolygons.js +22 -22
- package/Build/Workers/createVectorTilePolylines.js +14 -14
- package/Build/Workers/createVerticesFromCesium3DTilesTerrain.js +25 -25
- package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +22 -22
- package/Build/Workers/createVerticesFromHeightmap.js +22 -22
- package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +20 -20
- package/Build/Workers/createWallGeometry.js +24 -24
- package/Build/Workers/createWallOutlineGeometry.js +23 -23
- package/Build/Workers/decodeDraco.js +10 -10
- package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +987 -2320
- package/Build/Workers/decodeI3S.js +10 -10
- package/Build/Workers/gaussianSplatSorter.js +4 -4
- package/Build/Workers/gaussianSplatTextureGenerator.js +4 -4
- package/Build/Workers/incrementallyBuildTerrainPicker.js +10 -10
- package/Build/Workers/transcodeKTX2.js +6 -6
- package/Build/Workers/transferTypedArrayTest.js +1 -1
- package/Build/Workers/upsampleQuantizedTerrainMesh.js +22 -22
- package/Build/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +25 -25
- package/Source/Core/BoundingRectangle.js +6 -8
- package/Source/Core/Color.js +1 -0
- package/Source/Core/InterpolationAlgorithm.js +57 -50
- package/Source/Core/Ion.js +1 -1
- package/Source/Core/TerrainMesh.js +3 -3
- package/Source/Core/TerrainPicker.js +1 -0
- package/Source/Core/writeTextToCanvas.js +1 -0
- package/Source/DataSources/CzmlDataSource.js +12 -0
- package/Source/DataSources/KmlDataSource.js +528 -555
- package/Source/DataSources/PathGraphics.js +8 -1
- package/Source/DataSources/PathMode.js +27 -0
- package/Source/DataSources/PathVisualizer.js +298 -1
- package/Source/Renderer/Texture.js +1 -1
- package/Source/Renderer/VertexArray.js +1 -0
- package/Source/Scene/ArcGisMapService.js +1 -1
- package/Source/Scene/BillboardTexture.js +5 -3
- package/Source/Scene/Cesium3DTileOptimizations.js +4 -6
- package/Source/Scene/ClippingPlaneCollection.js +2 -2
- package/Source/Scene/ClippingPolygon.js +2 -0
- package/Source/Scene/ClippingPolygonCollection.js +2 -2
- package/Source/Scene/DerivedCommand.js +4 -0
- package/Source/Scene/Expression.js +6 -8
- package/Source/Scene/GlobeSurfaceShaderSet.js +501 -409
- package/Source/Scene/GlobeSurfaceTile.js +540 -401
- package/Source/Scene/GlobeSurfaceTileProvider.js +1259 -1146
- package/Source/Scene/GltfBufferViewLoader.js +3 -3
- package/Source/Scene/GltfLoader.js +1 -0
- package/Source/Scene/GltfLoaderUtil.js +20 -4
- package/Source/Scene/GltfPipeline/forEachTextureInMaterial.js +10 -0
- package/Source/Scene/GltfPipeline/removeUnusedElements.js +21 -11
- package/Source/Scene/ImageryLayer.js +2 -2
- package/Source/Scene/ImageryLayerCollection.js +2 -2
- package/Source/Scene/Material.js +1 -0
- package/Source/Scene/Model/Extensions/Gpm/GltfGpmLoader.js +4 -0
- package/Source/Scene/Model/Model.js +3 -0
- package/Source/Scene/Model/ModelUtility.js +1 -0
- package/Source/Scene/Picking.js +5 -0
- package/Source/Scene/PntsParser.js +1 -0
- package/Source/Scene/QuadtreePrimitive.js +3 -2
- package/Source/Scene/ResourceCacheKey.js +5 -5
- package/Source/Scene/Scene.js +1 -0
- package/Source/Scene/findMeshoptExtension.js +23 -0
- package/Source/Scene/renderBufferPointCollection.js +13 -8
- package/Source/Scene/renderBufferPolygonCollection.js +9 -13
- package/Source/Scene/renderBufferPolylineCollection.js +120 -192
- package/Source/Workers/decodeGoogleEarthEnterprisePacket.js +2 -2
- package/Source/Workers/incrementallyBuildTerrainPicker.js +2 -0
- package/index.d.ts +59 -254
- package/index.js +155 -153
- package/package.json +4 -4
|
@@ -52,1021 +52,1370 @@ import TerrainState from "./TerrainState.js";
|
|
|
52
52
|
import TileBoundingRegion from "./TileBoundingRegion.js";
|
|
53
53
|
import TileSelectionResult from "./TileSelectionResult.js";
|
|
54
54
|
|
|
55
|
+
/** @import Context from "../Renderer/Context.js"; */
|
|
56
|
+
/** @import EllipsoidalOccluder from "../Core/EllipsoidalOccluder.js"; */
|
|
57
|
+
/** @import FrameState from "./FrameState.js"; */
|
|
58
|
+
/** @import GlobeSurfaceShaderSet from "./GlobeSurfaceShaderSet.js"; */
|
|
59
|
+
/** @import ImageryLayerCollection from "./ImageryLayerCollection.js"; */
|
|
60
|
+
/** @import QuadtreeOccluders from "./QuadtreeOccluders.js"; */
|
|
61
|
+
/** @import QuadtreePrimitive from "./QuadtreePrimitive.js"; */
|
|
62
|
+
/** @import QuadtreeTile from "./QuadtreeTile.js"; */
|
|
63
|
+
/** @import TerrainMesh from "../Core/TerrainMesh.js"; */
|
|
64
|
+
/** @import TerrainProvider from "../Core/TerrainProvider.js"; */
|
|
65
|
+
/** @import TilingScheme from "../Core/TilingScheme.js"; */
|
|
66
|
+
/** @import { GlobeSurfaceShaderSetOptions } from "./GlobeSurfaceShaderSet.js"; */
|
|
67
|
+
|
|
55
68
|
/**
|
|
56
69
|
* Provides quadtree tiles representing the surface of the globe. This type is intended to be used
|
|
57
70
|
* with {@link QuadtreePrimitive}.
|
|
58
71
|
*
|
|
59
|
-
* @alias GlobeSurfaceTileProvider
|
|
60
|
-
* @constructor
|
|
61
|
-
*
|
|
62
|
-
* @param {TerrainProvider} options.terrainProvider The terrain provider that describes the surface geometry.
|
|
63
|
-
* @param {ImageryLayerCollection} option.imageryLayers The collection of imagery layers describing the shading of the surface.
|
|
64
|
-
* @param {GlobeSurfaceShaderSet} options.surfaceShaderSet The set of shaders used to render the surface.
|
|
65
|
-
*
|
|
66
72
|
* @private
|
|
67
73
|
*/
|
|
68
|
-
|
|
69
|
-
//>>includeStart('debug', pragmas.debug);
|
|
70
|
-
if (!defined(options)) {
|
|
71
|
-
throw new DeveloperError("options is required.");
|
|
72
|
-
}
|
|
73
|
-
if (!defined(options.terrainProvider)) {
|
|
74
|
-
throw new DeveloperError("options.terrainProvider is required.");
|
|
75
|
-
} else if (!defined(options.imageryLayers)) {
|
|
76
|
-
throw new DeveloperError("options.imageryLayers is required.");
|
|
77
|
-
} else if (!defined(options.surfaceShaderSet)) {
|
|
78
|
-
throw new DeveloperError("options.surfaceShaderSet is required.");
|
|
79
|
-
}
|
|
80
|
-
//>>includeEnd('debug');
|
|
81
|
-
|
|
82
|
-
this.lightingFadeOutDistance = 6500000.0;
|
|
83
|
-
this.lightingFadeInDistance = 9000000.0;
|
|
84
|
-
this.hasWaterMask = false;
|
|
85
|
-
this.showWaterEffect = false;
|
|
86
|
-
this.oceanNormalMap = undefined;
|
|
87
|
-
this.zoomedOutOceanSpecularIntensity = 0.5;
|
|
88
|
-
this.enableLighting = false;
|
|
89
|
-
this.dynamicAtmosphereLighting = false;
|
|
90
|
-
this.dynamicAtmosphereLightingFromSun = false;
|
|
91
|
-
this.showGroundAtmosphere = false;
|
|
92
|
-
this.shadows = ShadowMode.RECEIVE_ONLY;
|
|
93
|
-
this.vertexShadowDarkness = 0.3;
|
|
94
|
-
|
|
74
|
+
class GlobeSurfaceTileProvider {
|
|
95
75
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* @type {Color}
|
|
101
|
-
* @default undefined
|
|
76
|
+
* @param {object} options
|
|
77
|
+
* @param {TerrainProvider} options.terrainProvider The terrain provider that describes the surface geometry.
|
|
78
|
+
* @param {ImageryLayerCollection} options.imageryLayers The collection of imagery layers describing the shading of the surface.
|
|
79
|
+
* @param {GlobeSurfaceShaderSet} options.surfaceShaderSet The set of shaders used to render the surface.
|
|
102
80
|
*/
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
81
|
+
constructor(options) {
|
|
82
|
+
//>>includeStart('debug', pragmas.debug);
|
|
83
|
+
if (!defined(options)) {
|
|
84
|
+
throw new DeveloperError("options is required.");
|
|
85
|
+
}
|
|
86
|
+
if (!defined(options.terrainProvider)) {
|
|
87
|
+
throw new DeveloperError("options.terrainProvider is required.");
|
|
88
|
+
} else if (!defined(options.imageryLayers)) {
|
|
89
|
+
throw new DeveloperError("options.imageryLayers is required.");
|
|
90
|
+
} else if (!defined(options.surfaceShaderSet)) {
|
|
91
|
+
throw new DeveloperError("options.surfaceShaderSet is required.");
|
|
92
|
+
}
|
|
93
|
+
//>>includeEnd('debug');
|
|
94
|
+
|
|
95
|
+
this.lightingFadeOutDistance = 6500000.0;
|
|
96
|
+
this.lightingFadeInDistance = 9000000.0;
|
|
97
|
+
this.hasWaterMask = false;
|
|
98
|
+
this.showWaterEffect = false;
|
|
99
|
+
this.oceanNormalMap = undefined;
|
|
100
|
+
this.zoomedOutOceanSpecularIntensity = 0.5;
|
|
101
|
+
this.enableLighting = false;
|
|
102
|
+
this.dynamicAtmosphereLighting = false;
|
|
103
|
+
this.dynamicAtmosphereLightingFromSun = false;
|
|
104
|
+
this.showGroundAtmosphere = false;
|
|
105
|
+
this.shadows = ShadowMode.RECEIVE_ONLY;
|
|
106
|
+
this.vertexShadowDarkness = 0.3;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The color to use to highlight terrain fill tiles. If undefined, fill tiles are not
|
|
110
|
+
* highlighted at all. The alpha value is used to alpha blend with the tile's
|
|
111
|
+
* actual color. Because terrain fill tiles do not represent the actual terrain surface,
|
|
112
|
+
* it may be useful in some applications to indicate visually that they are not to be trusted.
|
|
113
|
+
* @type {Color}
|
|
114
|
+
* @default undefined
|
|
115
|
+
*/
|
|
116
|
+
this.fillHighlightColor = undefined;
|
|
117
|
+
|
|
118
|
+
this.hueShift = 0.0;
|
|
119
|
+
this.saturationShift = 0.0;
|
|
120
|
+
this.brightnessShift = 0.0;
|
|
121
|
+
|
|
122
|
+
this.showSkirts = true;
|
|
123
|
+
this.backFaceCulling = true;
|
|
124
|
+
this.undergroundColor = undefined;
|
|
125
|
+
this.undergroundColorAlphaByDistance = undefined;
|
|
126
|
+
|
|
127
|
+
this.lambertDiffuseMultiplier = 0.0;
|
|
128
|
+
|
|
129
|
+
this.materialUniformMap = undefined;
|
|
130
|
+
this._materialUniformMap = undefined;
|
|
131
|
+
|
|
132
|
+
this._quadtree = undefined;
|
|
133
|
+
this._terrainProvider = options.terrainProvider;
|
|
134
|
+
this._imageryLayers = options.imageryLayers;
|
|
135
|
+
this._surfaceShaderSet = options.surfaceShaderSet;
|
|
136
|
+
|
|
137
|
+
this._renderState = undefined;
|
|
138
|
+
this._blendRenderState = undefined;
|
|
139
|
+
this._disableCullingRenderState = undefined;
|
|
140
|
+
this._disableCullingBlendRenderState = undefined;
|
|
141
|
+
|
|
142
|
+
this._errorEvent = new Event();
|
|
143
|
+
|
|
144
|
+
this._removeLayerAddedListener =
|
|
145
|
+
this._imageryLayers.layerAdded.addEventListener(
|
|
146
|
+
GlobeSurfaceTileProvider.prototype._onLayerAdded,
|
|
147
|
+
this,
|
|
148
|
+
);
|
|
149
|
+
this._removeLayerRemovedListener =
|
|
150
|
+
this._imageryLayers.layerRemoved.addEventListener(
|
|
151
|
+
GlobeSurfaceTileProvider.prototype._onLayerRemoved,
|
|
152
|
+
this,
|
|
153
|
+
);
|
|
154
|
+
this._removeLayerMovedListener =
|
|
155
|
+
this._imageryLayers.layerMoved.addEventListener(
|
|
156
|
+
GlobeSurfaceTileProvider.prototype._onLayerMoved,
|
|
157
|
+
this,
|
|
158
|
+
);
|
|
159
|
+
this._removeLayerShownListener =
|
|
160
|
+
this._imageryLayers.layerShownOrHidden.addEventListener(
|
|
161
|
+
GlobeSurfaceTileProvider.prototype._onLayerShownOrHidden,
|
|
162
|
+
this,
|
|
163
|
+
);
|
|
164
|
+
this._imageryLayersUpdatedEvent = new Event();
|
|
123
165
|
|
|
124
|
-
|
|
125
|
-
this._blendRenderState = undefined;
|
|
126
|
-
this._disableCullingRenderState = undefined;
|
|
127
|
-
this._disableCullingBlendRenderState = undefined;
|
|
166
|
+
this._layerOrderChanged = false;
|
|
128
167
|
|
|
129
|
-
|
|
168
|
+
/** @type {QuadtreeTile[][]} */
|
|
169
|
+
this._tilesToRenderByTextureCount = [];
|
|
130
170
|
|
|
131
|
-
|
|
132
|
-
this.
|
|
133
|
-
GlobeSurfaceTileProvider.prototype._onLayerAdded,
|
|
134
|
-
this,
|
|
135
|
-
);
|
|
136
|
-
this._removeLayerRemovedListener =
|
|
137
|
-
this._imageryLayers.layerRemoved.addEventListener(
|
|
138
|
-
GlobeSurfaceTileProvider.prototype._onLayerRemoved,
|
|
139
|
-
this,
|
|
140
|
-
);
|
|
141
|
-
this._removeLayerMovedListener =
|
|
142
|
-
this._imageryLayers.layerMoved.addEventListener(
|
|
143
|
-
GlobeSurfaceTileProvider.prototype._onLayerMoved,
|
|
144
|
-
this,
|
|
145
|
-
);
|
|
146
|
-
this._removeLayerShownListener =
|
|
147
|
-
this._imageryLayers.layerShownOrHidden.addEventListener(
|
|
148
|
-
GlobeSurfaceTileProvider.prototype._onLayerShownOrHidden,
|
|
149
|
-
this,
|
|
150
|
-
);
|
|
151
|
-
this._imageryLayersUpdatedEvent = new Event();
|
|
171
|
+
/** @type {DrawCommand[]} */
|
|
172
|
+
this._drawCommands = [];
|
|
152
173
|
|
|
153
|
-
|
|
174
|
+
/** @type {object[]} */
|
|
175
|
+
this._uniformMaps = [];
|
|
154
176
|
|
|
155
|
-
|
|
156
|
-
this._drawCommands = [];
|
|
157
|
-
this._uniformMaps = [];
|
|
158
|
-
this._usedDrawCommands = 0;
|
|
177
|
+
this._usedDrawCommands = 0;
|
|
159
178
|
|
|
160
|
-
|
|
179
|
+
/** @type {VertexArray[]} */
|
|
180
|
+
this._vertexArraysToDestroy = [];
|
|
161
181
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
182
|
+
this._debug = {
|
|
183
|
+
wireframe: false,
|
|
184
|
+
boundingSphereTile: undefined,
|
|
185
|
+
tilesRendered: 0,
|
|
186
|
+
texturesRendered: 0,
|
|
187
|
+
};
|
|
166
188
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
189
|
+
this._baseColor = undefined;
|
|
190
|
+
this._firstPassInitialColor = undefined;
|
|
191
|
+
this.baseColor = new Color(0.0, 0.0, 0.5, 1.0);
|
|
170
192
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
193
|
+
/**
|
|
194
|
+
* A property specifying a {@link ClippingPlaneCollection} used to selectively disable rendering on the outside of each plane.
|
|
195
|
+
* @type {ClippingPlaneCollection}
|
|
196
|
+
* @ignore
|
|
197
|
+
*/
|
|
198
|
+
this._clippingPlanes = undefined;
|
|
177
199
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
200
|
+
/**
|
|
201
|
+
* A property specifying a {@link ClippingPolygonCollection} used to selectively disable rendering inside or outside a list of polygons.
|
|
202
|
+
* @type {ClippingPolygonCollection}
|
|
203
|
+
* @ignore
|
|
204
|
+
*/
|
|
205
|
+
this._clippingPolygons = undefined;
|
|
184
206
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
207
|
+
/**
|
|
208
|
+
* A property specifying a {@link Rectangle} used to selectively limit terrain and imagery rendering.
|
|
209
|
+
* @type {Rectangle}
|
|
210
|
+
*/
|
|
211
|
+
this.cartographicLimitRectangle = Rectangle.clone(Rectangle.MAX_VALUE);
|
|
190
212
|
|
|
191
|
-
|
|
192
|
-
|
|
213
|
+
this._hasLoadedTilesThisFrame = false;
|
|
214
|
+
this._hasFillTilesThisFrame = false;
|
|
193
215
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
216
|
+
this._oldVerticalExaggeration = undefined;
|
|
217
|
+
this._oldVerticalExaggerationRelativeHeight = undefined;
|
|
218
|
+
this._oldSceneMode = SceneMode.SCENE3D;
|
|
219
|
+
}
|
|
198
220
|
|
|
199
|
-
Object.defineProperties(GlobeSurfaceTileProvider.prototype, {
|
|
200
221
|
/**
|
|
201
222
|
* Gets or sets the color of the globe when no imagery is available.
|
|
202
|
-
* @memberof GlobeSurfaceTileProvider.prototype
|
|
203
223
|
* @type {Color}
|
|
204
224
|
*/
|
|
205
|
-
baseColor
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
225
|
+
get baseColor() {
|
|
226
|
+
return this._baseColor;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
set baseColor(value) {
|
|
230
|
+
//>>includeStart('debug', pragmas.debug);
|
|
231
|
+
if (!defined(value)) {
|
|
232
|
+
throw new DeveloperError("value is required.");
|
|
233
|
+
}
|
|
234
|
+
//>>includeEnd('debug');
|
|
235
|
+
|
|
236
|
+
this._baseColor = value;
|
|
237
|
+
this._firstPassInitialColor = Cartesian4.fromColor(
|
|
238
|
+
value,
|
|
239
|
+
this._firstPassInitialColor,
|
|
240
|
+
);
|
|
241
|
+
}
|
|
215
242
|
|
|
216
|
-
this._baseColor = value;
|
|
217
|
-
this._firstPassInitialColor = Cartesian4.fromColor(
|
|
218
|
-
value,
|
|
219
|
-
this._firstPassInitialColor,
|
|
220
|
-
);
|
|
221
|
-
},
|
|
222
|
-
},
|
|
223
243
|
/**
|
|
224
244
|
* Gets or sets the {@link QuadtreePrimitive} for which this provider is
|
|
225
245
|
* providing tiles. This property may be undefined if the provider is not yet associated
|
|
226
246
|
* with a {@link QuadtreePrimitive}.
|
|
227
|
-
* @memberof GlobeSurfaceTileProvider.prototype
|
|
228
247
|
* @type {QuadtreePrimitive}
|
|
229
248
|
*/
|
|
230
|
-
quadtree
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
},
|
|
234
|
-
set: function (value) {
|
|
235
|
-
//>>includeStart('debug', pragmas.debug);
|
|
236
|
-
if (!defined(value)) {
|
|
237
|
-
throw new DeveloperError("value is required.");
|
|
238
|
-
}
|
|
239
|
-
//>>includeEnd('debug');
|
|
249
|
+
get quadtree() {
|
|
250
|
+
return this._quadtree;
|
|
251
|
+
}
|
|
240
252
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
253
|
+
set quadtree(value) {
|
|
254
|
+
//>>includeStart('debug', pragmas.debug);
|
|
255
|
+
if (!defined(value)) {
|
|
256
|
+
throw new DeveloperError("value is required.");
|
|
257
|
+
}
|
|
258
|
+
//>>includeEnd('debug');
|
|
259
|
+
|
|
260
|
+
this._quadtree = value;
|
|
261
|
+
}
|
|
244
262
|
|
|
245
263
|
/**
|
|
246
264
|
* Gets the tiling scheme used by the provider.
|
|
247
|
-
* @memberof GlobeSurfaceTileProvider.prototype
|
|
248
265
|
* @type {TilingScheme}
|
|
249
266
|
*/
|
|
250
|
-
tilingScheme
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
}
|
|
267
|
+
get tilingScheme() {
|
|
268
|
+
if (!defined(this._terrainProvider)) {
|
|
269
|
+
return undefined;
|
|
270
|
+
}
|
|
255
271
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
272
|
+
// @ts-expect-error Missing types.
|
|
273
|
+
return this._terrainProvider.tilingScheme;
|
|
274
|
+
}
|
|
259
275
|
|
|
260
276
|
/**
|
|
261
277
|
* Gets an event that is raised when the geometry provider encounters an asynchronous error. By subscribing
|
|
262
278
|
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
|
|
263
279
|
* are passed an instance of {@link TileProviderError}.
|
|
264
|
-
* @
|
|
265
|
-
* @type {Event}
|
|
280
|
+
* @type {Event<*>}
|
|
266
281
|
*/
|
|
267
|
-
errorEvent
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
},
|
|
271
|
-
},
|
|
282
|
+
get errorEvent() {
|
|
283
|
+
return this._errorEvent;
|
|
284
|
+
}
|
|
272
285
|
|
|
273
286
|
/**
|
|
274
287
|
* Gets an event that is raised when an imagery layer is added, shown, hidden, moved, or removed.
|
|
275
|
-
* @
|
|
276
|
-
* @type {Event}
|
|
288
|
+
* @type {Event<*>}
|
|
277
289
|
*/
|
|
278
|
-
imageryLayersUpdatedEvent
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
},
|
|
282
|
-
},
|
|
290
|
+
get imageryLayersUpdatedEvent() {
|
|
291
|
+
return this._imageryLayersUpdatedEvent;
|
|
292
|
+
}
|
|
283
293
|
|
|
284
294
|
/**
|
|
285
295
|
* Gets or sets the terrain provider that describes the surface geometry.
|
|
286
|
-
* @memberof GlobeSurfaceTileProvider.prototype
|
|
287
296
|
* @type {TerrainProvider}
|
|
288
297
|
*/
|
|
289
|
-
terrainProvider
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
},
|
|
293
|
-
set: function (terrainProvider) {
|
|
294
|
-
if (this._terrainProvider === terrainProvider) {
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
298
|
+
get terrainProvider() {
|
|
299
|
+
return this._terrainProvider;
|
|
300
|
+
}
|
|
297
301
|
|
|
298
|
-
|
|
302
|
+
set terrainProvider(terrainProvider) {
|
|
303
|
+
if (this._terrainProvider === terrainProvider) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
this._terrainProvider = terrainProvider;
|
|
308
|
+
|
|
309
|
+
if (defined(this._quadtree)) {
|
|
310
|
+
this._quadtree.invalidateAllTiles();
|
|
311
|
+
}
|
|
312
|
+
}
|
|
299
313
|
|
|
300
|
-
if (defined(this._quadtree)) {
|
|
301
|
-
this._quadtree.invalidateAllTiles();
|
|
302
|
-
}
|
|
303
|
-
},
|
|
304
|
-
},
|
|
305
314
|
/**
|
|
306
315
|
* The {@link ClippingPlaneCollection} used to selectively disable rendering.
|
|
307
316
|
*
|
|
308
317
|
* @type {ClippingPlaneCollection}
|
|
309
318
|
*
|
|
310
|
-
* @
|
|
319
|
+
* @ignore
|
|
311
320
|
*/
|
|
312
|
-
clippingPlanes
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
},
|
|
321
|
+
get clippingPlanes() {
|
|
322
|
+
return this._clippingPlanes;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
set clippingPlanes(value) {
|
|
326
|
+
ClippingPlaneCollection.setOwner(value, this, "_clippingPlanes");
|
|
327
|
+
}
|
|
320
328
|
|
|
321
329
|
/**
|
|
322
330
|
* The {@link ClippingPolygonCollection} used to selectively disable rendering inside or outside a list of polygons.
|
|
323
331
|
*
|
|
324
332
|
* @type {ClippingPolygonCollection}
|
|
325
333
|
*
|
|
326
|
-
* @
|
|
334
|
+
* @ignore
|
|
327
335
|
*/
|
|
328
|
-
clippingPolygons
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
},
|
|
332
|
-
set: function (value) {
|
|
333
|
-
ClippingPolygonCollection.setOwner(value, this, "_clippingPolygons");
|
|
334
|
-
},
|
|
335
|
-
},
|
|
336
|
-
});
|
|
336
|
+
get clippingPolygons() {
|
|
337
|
+
return this._clippingPolygons;
|
|
338
|
+
}
|
|
337
339
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
if (!defined(aImagery)) {
|
|
341
|
-
aImagery = a.readyImagery;
|
|
340
|
+
set clippingPolygons(value) {
|
|
341
|
+
ClippingPolygonCollection.setOwner(value, this, "_clippingPolygons");
|
|
342
342
|
}
|
|
343
343
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
344
|
+
/**
|
|
345
|
+
* Make updates to the tile provider that are not involved in rendering. Called before the render update cycle.
|
|
346
|
+
* @param {FrameState} frameState
|
|
347
|
+
*/
|
|
348
|
+
update(frameState) {
|
|
349
|
+
// update collection: imagery indices, base layers, raise layer show/hide event
|
|
350
|
+
this._imageryLayers._update();
|
|
347
351
|
}
|
|
348
352
|
|
|
349
|
-
|
|
350
|
-
}
|
|
353
|
+
/**
|
|
354
|
+
* Called at the beginning of each render frame, before {@link QuadtreeTileProvider#showTileThisFrame}
|
|
355
|
+
* @param {FrameState} frameState The frame state.
|
|
356
|
+
*/
|
|
357
|
+
initialize(frameState) {
|
|
358
|
+
// update each layer for texture reprojection.
|
|
359
|
+
this._imageryLayers.queueReprojectionCommands(frameState);
|
|
360
|
+
|
|
361
|
+
if (this._layerOrderChanged) {
|
|
362
|
+
this._layerOrderChanged = false;
|
|
363
|
+
|
|
364
|
+
// Sort the TileImagery instances in each tile by the layer index.
|
|
365
|
+
this._quadtree.forEachLoadedTile(
|
|
366
|
+
/** @param {QuadtreeTile} tile */
|
|
367
|
+
function (tile) {
|
|
368
|
+
const surfaceTile = /** @type {GlobeSurfaceTile} */ (tile.data);
|
|
369
|
+
surfaceTile.imagery.sort(sortTileImageryByLayerIndex);
|
|
370
|
+
},
|
|
371
|
+
);
|
|
372
|
+
}
|
|
351
373
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
*/
|
|
355
|
-
GlobeSurfaceTileProvider.prototype.update = function (frameState) {
|
|
356
|
-
// update collection: imagery indices, base layers, raise layer show/hide event
|
|
357
|
-
this._imageryLayers._update();
|
|
358
|
-
};
|
|
374
|
+
// Add credits for terrain and imagery providers.
|
|
375
|
+
updateCredits(this, frameState);
|
|
359
376
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
377
|
+
const vertexArraysToDestroy = this._vertexArraysToDestroy;
|
|
378
|
+
const length = vertexArraysToDestroy.length;
|
|
379
|
+
for (let j = 0; j < length; ++j) {
|
|
380
|
+
GlobeSurfaceTile._freeVertexArray(vertexArraysToDestroy[j]);
|
|
381
|
+
}
|
|
382
|
+
vertexArraysToDestroy.length = 0;
|
|
365
383
|
}
|
|
366
384
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
385
|
+
/**
|
|
386
|
+
* Called at the beginning of the update cycle for each render frame, before {@link QuadtreeTileProvider#showTileThisFrame}
|
|
387
|
+
* or any other functions.
|
|
388
|
+
*
|
|
389
|
+
* @param {FrameState} frameState The frame state.
|
|
390
|
+
*/
|
|
391
|
+
beginUpdate(frameState) {
|
|
392
|
+
const tilesToRenderByTextureCount = this._tilesToRenderByTextureCount;
|
|
393
|
+
for (let i = 0, len = tilesToRenderByTextureCount.length; i < len; ++i) {
|
|
394
|
+
const tiles = tilesToRenderByTextureCount[i];
|
|
395
|
+
if (defined(tiles)) {
|
|
396
|
+
tiles.length = 0;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
// update clipping planes
|
|
400
|
+
const clippingPlanes = this._clippingPlanes;
|
|
401
|
+
// @ts-expect-error Missing types.
|
|
402
|
+
if (defined(clippingPlanes) && clippingPlanes.enabled) {
|
|
403
|
+
clippingPlanes.update(frameState);
|
|
372
404
|
}
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
405
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
406
|
+
// update clipping polygons
|
|
407
|
+
const clippingPolygons = this._clippingPolygons;
|
|
408
|
+
if (defined(clippingPolygons) && clippingPolygons.enabled) {
|
|
409
|
+
// @ts-expect-error Missing types.
|
|
410
|
+
clippingPolygons.update(frameState);
|
|
411
|
+
// @ts-expect-error Missing types.
|
|
412
|
+
clippingPolygons.queueCommands(frameState);
|
|
413
|
+
}
|
|
383
414
|
|
|
384
|
-
|
|
385
|
-
this._layerOrderChanged = false;
|
|
415
|
+
this._usedDrawCommands = 0;
|
|
386
416
|
|
|
387
|
-
|
|
388
|
-
this.
|
|
389
|
-
tile.data.imagery.sort(sortTileImageryByLayerIndex);
|
|
390
|
-
});
|
|
417
|
+
this._hasLoadedTilesThisFrame = false;
|
|
418
|
+
this._hasFillTilesThisFrame = false;
|
|
391
419
|
}
|
|
392
420
|
|
|
393
|
-
|
|
394
|
-
|
|
421
|
+
/**
|
|
422
|
+
* Called at the end of the update cycle for each render frame, after {@link QuadtreeTileProvider#showTileThisFrame}
|
|
423
|
+
* and any other functions.
|
|
424
|
+
*
|
|
425
|
+
* @param {FrameState} frameState The frame state.
|
|
426
|
+
*/
|
|
427
|
+
endUpdate(frameState) {
|
|
428
|
+
if (!defined(this._renderState)) {
|
|
429
|
+
this._renderState = RenderState.fromCache({
|
|
430
|
+
// Write color and depth
|
|
431
|
+
cull: {
|
|
432
|
+
enabled: true,
|
|
433
|
+
},
|
|
434
|
+
depthTest: {
|
|
435
|
+
enabled: true,
|
|
436
|
+
func: DepthFunction.LESS,
|
|
437
|
+
},
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
this._blendRenderState = RenderState.fromCache({
|
|
441
|
+
// Write color and depth
|
|
442
|
+
cull: {
|
|
443
|
+
enabled: true,
|
|
444
|
+
},
|
|
445
|
+
depthTest: {
|
|
446
|
+
enabled: true,
|
|
447
|
+
func: DepthFunction.LESS_OR_EQUAL,
|
|
448
|
+
},
|
|
449
|
+
blending: BlendingState.ALPHA_BLEND,
|
|
450
|
+
});
|
|
395
451
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
GlobeSurfaceTile._freeVertexArray(vertexArraysToDestroy[j]);
|
|
400
|
-
}
|
|
401
|
-
vertexArraysToDestroy.length = 0;
|
|
402
|
-
};
|
|
452
|
+
let rs = /** @type {RenderState} */ (clone(this._renderState, true));
|
|
453
|
+
rs.cull.enabled = false;
|
|
454
|
+
this._disableCullingRenderState = RenderState.fromCache(rs);
|
|
403
455
|
|
|
404
|
-
/**
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
*
|
|
408
|
-
* @param {FrameState} frameState The frame state.
|
|
409
|
-
*/
|
|
410
|
-
GlobeSurfaceTileProvider.prototype.beginUpdate = function (frameState) {
|
|
411
|
-
const tilesToRenderByTextureCount = this._tilesToRenderByTextureCount;
|
|
412
|
-
for (let i = 0, len = tilesToRenderByTextureCount.length; i < len; ++i) {
|
|
413
|
-
const tiles = tilesToRenderByTextureCount[i];
|
|
414
|
-
if (defined(tiles)) {
|
|
415
|
-
tiles.length = 0;
|
|
456
|
+
rs = /** @type {RenderState} */ (clone(this._blendRenderState, true));
|
|
457
|
+
rs.cull.enabled = false;
|
|
458
|
+
this._disableCullingBlendRenderState = RenderState.fromCache(rs);
|
|
416
459
|
}
|
|
417
|
-
}
|
|
418
|
-
// update clipping planes
|
|
419
|
-
const clippingPlanes = this._clippingPlanes;
|
|
420
|
-
if (defined(clippingPlanes) && clippingPlanes.enabled) {
|
|
421
|
-
clippingPlanes.update(frameState);
|
|
422
|
-
}
|
|
423
460
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
461
|
+
// If this frame has a mix of loaded and fill tiles, we need to propagate
|
|
462
|
+
// loaded heights to the fill tiles.
|
|
463
|
+
if (this._hasFillTilesThisFrame && this._hasLoadedTilesThisFrame) {
|
|
464
|
+
TerrainFillMesh.updateFillTiles(
|
|
465
|
+
this,
|
|
466
|
+
this._quadtree._tilesToRender,
|
|
467
|
+
frameState,
|
|
468
|
+
this._vertexArraysToDestroy,
|
|
469
|
+
);
|
|
470
|
+
}
|
|
430
471
|
|
|
431
|
-
|
|
472
|
+
// When vertical exaggeration changes, all of the loaded tiles need to generate
|
|
473
|
+
// geodetic surface normals so they can scale properly when rendered.
|
|
474
|
+
// When exaggeration is reset, geodetic surface normals are removed to decrease
|
|
475
|
+
// memory usage. Some tiles might have been constructed with the correct
|
|
476
|
+
// exaggeration already, so skip over them.
|
|
432
477
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
478
|
+
// If the geodetic surface normals can't be created because the tile doesn't
|
|
479
|
+
// have a mesh, keep checking until the tile does have a mesh. This can happen
|
|
480
|
+
// if the tile's mesh starts construction in a worker thread right before the
|
|
481
|
+
// exaggeration changes.
|
|
436
482
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
483
|
+
const quadtree = this.quadtree;
|
|
484
|
+
const exaggeration = frameState.verticalExaggeration;
|
|
485
|
+
const exaggerationRelativeHeight =
|
|
486
|
+
frameState.verticalExaggerationRelativeHeight;
|
|
487
|
+
const exaggerationChanged =
|
|
488
|
+
this._oldVerticalExaggeration !== exaggeration ||
|
|
489
|
+
this._oldVerticalExaggerationRelativeHeight !==
|
|
490
|
+
exaggerationRelativeHeight;
|
|
491
|
+
|
|
492
|
+
// Keep track of the next time there is a change in exaggeration
|
|
493
|
+
this._oldVerticalExaggeration = exaggeration;
|
|
494
|
+
this._oldVerticalExaggerationRelativeHeight = exaggerationRelativeHeight;
|
|
495
|
+
|
|
496
|
+
if (exaggerationChanged) {
|
|
497
|
+
quadtree.forEachLoadedTile(
|
|
498
|
+
/** @param {QuadtreeTile} tile */
|
|
499
|
+
function (tile) {
|
|
500
|
+
const surfaceTile = /** @type {GlobeSurfaceTile} */ (tile.data);
|
|
501
|
+
surfaceTile.updateExaggeration(tile, frameState, quadtree);
|
|
502
|
+
},
|
|
503
|
+
);
|
|
504
|
+
}
|
|
455
505
|
|
|
456
|
-
this.
|
|
457
|
-
|
|
458
|
-
cull: {
|
|
459
|
-
enabled: true,
|
|
460
|
-
},
|
|
461
|
-
depthTest: {
|
|
462
|
-
enabled: true,
|
|
463
|
-
func: DepthFunction.LESS_OR_EQUAL,
|
|
464
|
-
},
|
|
465
|
-
blending: BlendingState.ALPHA_BLEND,
|
|
466
|
-
});
|
|
506
|
+
const sceneModeChanged = this._oldSceneMode !== frameState.mode;
|
|
507
|
+
this._oldSceneMode = frameState.mode;
|
|
467
508
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
509
|
+
if (sceneModeChanged) {
|
|
510
|
+
quadtree.forEachLoadedTile(
|
|
511
|
+
/** @param {QuadtreeTile} tile */
|
|
512
|
+
function (tile) {
|
|
513
|
+
const surfaceTile = /** @type {GlobeSurfaceTile} */ (tile.data);
|
|
514
|
+
surfaceTile.updateSceneMode(frameState.mode);
|
|
515
|
+
},
|
|
516
|
+
);
|
|
517
|
+
}
|
|
471
518
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
519
|
+
// Add the tile render commands to the command list, sorted by texture count.
|
|
520
|
+
const tilesToRenderByTextureCount = this._tilesToRenderByTextureCount;
|
|
521
|
+
for (
|
|
522
|
+
let textureCountIndex = 0,
|
|
523
|
+
textureCountLength = tilesToRenderByTextureCount.length;
|
|
524
|
+
textureCountIndex < textureCountLength;
|
|
525
|
+
++textureCountIndex
|
|
526
|
+
) {
|
|
527
|
+
const tilesToRender = tilesToRenderByTextureCount[textureCountIndex];
|
|
528
|
+
if (!defined(tilesToRender)) {
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
476
531
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
532
|
+
for (
|
|
533
|
+
let tileIndex = 0, tileLength = tilesToRender.length;
|
|
534
|
+
tileIndex < tileLength;
|
|
535
|
+
++tileIndex
|
|
536
|
+
) {
|
|
537
|
+
const tile = tilesToRender[tileIndex];
|
|
538
|
+
const surfaceTile = /** @type {GlobeSurfaceTile} */ (tile.data);
|
|
539
|
+
const tileBoundingRegion = surfaceTile.tileBoundingRegion;
|
|
540
|
+
addDrawCommandsForTile(this, tile, frameState);
|
|
541
|
+
frameState.minimumTerrainHeight = Math.min(
|
|
542
|
+
frameState.minimumTerrainHeight,
|
|
543
|
+
tileBoundingRegion.minimumHeight,
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
486
547
|
}
|
|
487
548
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
const quadtree = this.quadtree;
|
|
500
|
-
const exaggeration = frameState.verticalExaggeration;
|
|
501
|
-
const exaggerationRelativeHeight =
|
|
502
|
-
frameState.verticalExaggerationRelativeHeight;
|
|
503
|
-
const exaggerationChanged =
|
|
504
|
-
this._oldVerticalExaggeration !== exaggeration ||
|
|
505
|
-
this._oldVerticalExaggerationRelativeHeight !== exaggerationRelativeHeight;
|
|
506
|
-
|
|
507
|
-
// Keep track of the next time there is a change in exaggeration
|
|
508
|
-
this._oldVerticalExaggeration = exaggeration;
|
|
509
|
-
this._oldVerticalExaggerationRelativeHeight = exaggerationRelativeHeight;
|
|
510
|
-
|
|
511
|
-
if (exaggerationChanged) {
|
|
512
|
-
quadtree.forEachLoadedTile(function (tile) {
|
|
513
|
-
const surfaceTile = tile.data;
|
|
514
|
-
surfaceTile.updateExaggeration(tile, frameState, quadtree);
|
|
515
|
-
});
|
|
549
|
+
/**
|
|
550
|
+
* Adds draw commands for tiles rendered in the previous frame for a pick pass.
|
|
551
|
+
*
|
|
552
|
+
* @param {FrameState} frameState The frame state.
|
|
553
|
+
*/
|
|
554
|
+
updateForPick(frameState) {
|
|
555
|
+
// Add the tile pick commands from the tiles drawn last frame.
|
|
556
|
+
const drawCommands = this._drawCommands;
|
|
557
|
+
for (let i = 0, length = this._usedDrawCommands; i < length; ++i) {
|
|
558
|
+
pushCommand(drawCommands[i], frameState);
|
|
559
|
+
}
|
|
516
560
|
}
|
|
517
561
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
const surfaceTile = tile.data;
|
|
524
|
-
surfaceTile.updateSceneMode(frameState.mode);
|
|
525
|
-
});
|
|
562
|
+
/**
|
|
563
|
+
* Cancels any imagery re-projections in the queue.
|
|
564
|
+
*/
|
|
565
|
+
cancelReprojections() {
|
|
566
|
+
this._imageryLayers.cancelReprojections();
|
|
526
567
|
}
|
|
527
568
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
if (!defined(tilesToRender)) {
|
|
538
|
-
continue;
|
|
569
|
+
/**
|
|
570
|
+
* Gets the maximum geometric error allowed in a tile at a given level, in meters.
|
|
571
|
+
*
|
|
572
|
+
* @param {number} level The tile level for which to get the maximum geometric error.
|
|
573
|
+
* @returns {number} The maximum geometric error in meters.
|
|
574
|
+
*/
|
|
575
|
+
getLevelMaximumGeometricError(level) {
|
|
576
|
+
if (!defined(this._terrainProvider)) {
|
|
577
|
+
return 0;
|
|
539
578
|
}
|
|
540
579
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
tileIndex < tileLength;
|
|
544
|
-
++tileIndex
|
|
545
|
-
) {
|
|
546
|
-
const tile = tilesToRender[tileIndex];
|
|
547
|
-
const tileBoundingRegion = tile.data.tileBoundingRegion;
|
|
548
|
-
addDrawCommandsForTile(this, tile, frameState);
|
|
549
|
-
frameState.minimumTerrainHeight = Math.min(
|
|
550
|
-
frameState.minimumTerrainHeight,
|
|
551
|
-
tileBoundingRegion.minimumHeight,
|
|
552
|
-
);
|
|
553
|
-
}
|
|
580
|
+
// @ts-expect-error Missing types.
|
|
581
|
+
return this._terrainProvider.getLevelMaximumGeometricError(level);
|
|
554
582
|
}
|
|
555
|
-
};
|
|
556
583
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
584
|
+
/**
|
|
585
|
+
* Loads, or continues loading, a given tile. This function will continue to be called
|
|
586
|
+
* until {@link QuadtreeTile#state} is no longer {@link QuadtreeTileLoadState#LOADING}.
|
|
587
|
+
*
|
|
588
|
+
* @param {FrameState} frameState The frame state.
|
|
589
|
+
* @param {QuadtreeTile} tile The tile to load.
|
|
590
|
+
*/
|
|
591
|
+
loadTile(frameState, tile) {
|
|
592
|
+
// We don't want to load imagery until we're certain that the terrain tiles are actually visible.
|
|
593
|
+
// So if our bounding volume isn't accurate because it came from another tile, load terrain only
|
|
594
|
+
// initially. If we load some terrain and suddenly have a more accurate bounding volume and the
|
|
595
|
+
// tile is _still_ visible, give the tile a chance to load imagery immediately rather than
|
|
596
|
+
// waiting for next frame.
|
|
597
|
+
|
|
598
|
+
let surfaceTile = /** @type {GlobeSurfaceTile} */ (tile.data);
|
|
599
|
+
let terrainOnly = true;
|
|
600
|
+
let terrainStateBefore;
|
|
601
|
+
if (defined(surfaceTile)) {
|
|
602
|
+
terrainOnly =
|
|
603
|
+
surfaceTile.boundingVolumeSourceTile !== tile ||
|
|
604
|
+
tile._lastSelectionResult === TileSelectionResult.CULLED_BUT_NEEDED;
|
|
605
|
+
terrainStateBefore = surfaceTile.terrainState;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
GlobeSurfaceTile.processStateMachine(
|
|
609
|
+
tile,
|
|
564
610
|
frameState,
|
|
611
|
+
this.terrainProvider,
|
|
612
|
+
this._imageryLayers,
|
|
613
|
+
this.quadtree,
|
|
614
|
+
this._vertexArraysToDestroy,
|
|
615
|
+
terrainOnly,
|
|
565
616
|
);
|
|
566
|
-
} else {
|
|
567
|
-
frameState.commandList.push(command);
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
617
|
|
|
571
|
-
/**
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
618
|
+
surfaceTile = /** @type {GlobeSurfaceTile} */ (tile.data);
|
|
619
|
+
if (terrainOnly && terrainStateBefore !== surfaceTile.terrainState) {
|
|
620
|
+
// Terrain state changed. If:
|
|
621
|
+
// a) The tile is visible, and
|
|
622
|
+
// b) The bounding volume is accurate (updated as a side effect of computing visibility)
|
|
623
|
+
// Then we'll load imagery, too.
|
|
624
|
+
if (
|
|
625
|
+
this.computeTileVisibility(
|
|
626
|
+
tile,
|
|
627
|
+
frameState,
|
|
628
|
+
// @ts-expect-error Missing types.
|
|
629
|
+
this.quadtree.occluders,
|
|
630
|
+
) !== Visibility.NONE &&
|
|
631
|
+
surfaceTile.boundingVolumeSourceTile === tile
|
|
632
|
+
) {
|
|
633
|
+
terrainOnly = false;
|
|
634
|
+
GlobeSurfaceTile.processStateMachine(
|
|
635
|
+
tile,
|
|
636
|
+
frameState,
|
|
637
|
+
this.terrainProvider,
|
|
638
|
+
this._imageryLayers,
|
|
639
|
+
this.quadtree,
|
|
640
|
+
this._vertexArraysToDestroy,
|
|
641
|
+
terrainOnly,
|
|
642
|
+
);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
581
645
|
}
|
|
582
|
-
};
|
|
583
646
|
|
|
584
|
-
/**
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
}
|
|
647
|
+
/**
|
|
648
|
+
* Determines the visibility of a given tile. The tile may be fully visible, partially visible, or not
|
|
649
|
+
* visible at all. Tiles that are renderable and are at least partially visible will be shown by a call
|
|
650
|
+
* to {@link GlobeSurfaceTileProvider#showTileThisFrame}.
|
|
651
|
+
*
|
|
652
|
+
* @param {QuadtreeTile} tile The tile instance.
|
|
653
|
+
* @param {FrameState} frameState The state information about the current frame.
|
|
654
|
+
* @param {QuadtreeOccluders} occluders The objects that may occlude this tile.
|
|
655
|
+
*
|
|
656
|
+
* @returns {Visibility} Visibility.NONE if the tile is not visible,
|
|
657
|
+
* Visibility.PARTIAL if the tile is partially visible, or
|
|
658
|
+
* Visibility.FULL if the tile is fully visible.
|
|
659
|
+
*/
|
|
660
|
+
computeTileVisibility(tile, frameState, occluders) {
|
|
661
|
+
const distance = this.computeDistanceToTile(tile, frameState);
|
|
662
|
+
tile._distance = distance;
|
|
590
663
|
|
|
591
|
-
|
|
592
|
-
* Gets the maximum geometric error allowed in a tile at a given level, in meters.
|
|
593
|
-
*
|
|
594
|
-
* @param {number} level The tile level for which to get the maximum geometric error.
|
|
595
|
-
* @returns {number} The maximum geometric error in meters.
|
|
596
|
-
*/
|
|
597
|
-
GlobeSurfaceTileProvider.prototype.getLevelMaximumGeometricError = function (
|
|
598
|
-
level,
|
|
599
|
-
) {
|
|
600
|
-
if (!defined(this._terrainProvider)) {
|
|
601
|
-
return 0;
|
|
602
|
-
}
|
|
664
|
+
const undergroundVisible = isUndergroundVisible(this, frameState);
|
|
603
665
|
|
|
604
|
-
|
|
605
|
-
|
|
666
|
+
if (frameState.fog.enabled && !undergroundVisible) {
|
|
667
|
+
if (CesiumMath.fog(distance, frameState.fog.density) >= 1.0) {
|
|
668
|
+
// Tile is completely in fog so return that it is not visible.
|
|
669
|
+
return Visibility.NONE;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
606
672
|
|
|
607
|
-
/**
|
|
608
|
-
|
|
609
|
-
* until {@link QuadtreeTile#state} is no longer {@link QuadtreeTileLoadState#LOADING}.
|
|
610
|
-
*
|
|
611
|
-
* @param {FrameState} frameState The frame state.
|
|
612
|
-
* @param {QuadtreeTile} tile The tile to load.
|
|
613
|
-
*/
|
|
614
|
-
GlobeSurfaceTileProvider.prototype.loadTile = function (frameState, tile) {
|
|
615
|
-
// We don't want to load imagery until we're certain that the terrain tiles are actually visible.
|
|
616
|
-
// So if our bounding volume isn't accurate because it came from another tile, load terrain only
|
|
617
|
-
// initially. If we load some terrain and suddenly have a more accurate bounding volume and the
|
|
618
|
-
// tile is _still_ visible, give the tile a chance to load imagery immediately rather than
|
|
619
|
-
// waiting for next frame.
|
|
620
|
-
|
|
621
|
-
let surfaceTile = tile.data;
|
|
622
|
-
let terrainOnly = true;
|
|
623
|
-
let terrainStateBefore;
|
|
624
|
-
if (defined(surfaceTile)) {
|
|
625
|
-
terrainOnly =
|
|
626
|
-
surfaceTile.boundingVolumeSourceTile !== tile ||
|
|
627
|
-
tile._lastSelectionResult === TileSelectionResult.CULLED_BUT_NEEDED;
|
|
628
|
-
terrainStateBefore = surfaceTile.terrainState;
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
GlobeSurfaceTile.processStateMachine(
|
|
632
|
-
tile,
|
|
633
|
-
frameState,
|
|
634
|
-
this.terrainProvider,
|
|
635
|
-
this._imageryLayers,
|
|
636
|
-
this.quadtree,
|
|
637
|
-
this._vertexArraysToDestroy,
|
|
638
|
-
terrainOnly,
|
|
639
|
-
);
|
|
673
|
+
const surfaceTile = /** @type {GlobeSurfaceTile} */ (tile.data);
|
|
674
|
+
const tileBoundingRegion = surfaceTile.tileBoundingRegion;
|
|
640
675
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
// a) The tile is visible, and
|
|
645
|
-
// b) The bounding volume is accurate (updated as a side effect of computing visibility)
|
|
646
|
-
// Then we'll load imagery, too.
|
|
647
|
-
if (
|
|
648
|
-
this.computeTileVisibility(tile, frameState, this.quadtree.occluders) !==
|
|
649
|
-
Visibility.NONE &&
|
|
650
|
-
surfaceTile.boundingVolumeSourceTile === tile
|
|
651
|
-
) {
|
|
652
|
-
terrainOnly = false;
|
|
653
|
-
GlobeSurfaceTile.processStateMachine(
|
|
654
|
-
tile,
|
|
655
|
-
frameState,
|
|
656
|
-
this.terrainProvider,
|
|
657
|
-
this._imageryLayers,
|
|
658
|
-
this.quadtree,
|
|
659
|
-
this._vertexArraysToDestroy,
|
|
660
|
-
terrainOnly,
|
|
661
|
-
);
|
|
676
|
+
if (surfaceTile.boundingVolumeSourceTile === undefined) {
|
|
677
|
+
// We have no idea where this tile is, so let's just call it partially visible.
|
|
678
|
+
return Visibility.PARTIAL;
|
|
662
679
|
}
|
|
663
|
-
}
|
|
664
|
-
};
|
|
665
680
|
|
|
666
|
-
const
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
const rectangleCenterScratch = new Cartographic();
|
|
681
|
+
const cullingVolume = frameState.cullingVolume;
|
|
682
|
+
// @ts-expect-error Missing types.
|
|
683
|
+
let boundingVolume = tileBoundingRegion.boundingVolume;
|
|
670
684
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
}
|
|
676
|
-
const splitRectangle = Rectangle.clone(
|
|
677
|
-
cartographicLimitRectangle,
|
|
678
|
-
splitCartographicLimitRectangleScratch,
|
|
679
|
-
);
|
|
680
|
-
const tileCenter = Rectangle.center(tileRectangle, rectangleCenterScratch);
|
|
681
|
-
if (tileCenter.longitude > 0.0) {
|
|
682
|
-
splitRectangle.east = CesiumMath.PI;
|
|
683
|
-
} else {
|
|
684
|
-
splitRectangle.west = -CesiumMath.PI;
|
|
685
|
-
}
|
|
686
|
-
return splitRectangle;
|
|
687
|
-
}
|
|
685
|
+
if (!defined(boundingVolume)) {
|
|
686
|
+
// @ts-expect-error Missing types.
|
|
687
|
+
boundingVolume = tileBoundingRegion.boundingSphere;
|
|
688
|
+
}
|
|
688
689
|
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
690
|
+
// Check if the tile is outside the limit area in cartographic space
|
|
691
|
+
surfaceTile.clippedByBoundaries = false;
|
|
692
|
+
const clippedCartographicLimitRectangle = clipRectangleAntimeridian(
|
|
693
|
+
tile.rectangle,
|
|
694
|
+
this.cartographicLimitRectangle,
|
|
695
|
+
);
|
|
696
|
+
const areaLimitIntersection = Rectangle.simpleIntersection(
|
|
697
|
+
clippedCartographicLimitRectangle,
|
|
698
|
+
tile.rectangle,
|
|
699
|
+
rectangleIntersectionScratch,
|
|
700
|
+
);
|
|
701
|
+
if (!defined(areaLimitIntersection)) {
|
|
702
|
+
return Visibility.NONE;
|
|
703
|
+
}
|
|
704
|
+
if (!Rectangle.equals(areaLimitIntersection, tile.rectangle)) {
|
|
705
|
+
surfaceTile.clippedByBoundaries = true;
|
|
706
|
+
}
|
|
693
707
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
708
|
+
if (frameState.mode !== SceneMode.SCENE3D) {
|
|
709
|
+
boundingVolume = boundingSphereScratch;
|
|
710
|
+
BoundingSphere.fromRectangleWithHeights2D(
|
|
711
|
+
tile.rectangle,
|
|
712
|
+
frameState.mapProjection,
|
|
713
|
+
tileBoundingRegion.minimumHeight,
|
|
714
|
+
tileBoundingRegion.maximumHeight,
|
|
715
|
+
boundingVolume,
|
|
716
|
+
);
|
|
717
|
+
Cartesian3.fromElements(
|
|
718
|
+
boundingVolume.center.z,
|
|
719
|
+
boundingVolume.center.x,
|
|
720
|
+
boundingVolume.center.y,
|
|
721
|
+
boundingVolume.center,
|
|
722
|
+
);
|
|
697
723
|
|
|
698
|
-
|
|
699
|
-
|
|
724
|
+
if (
|
|
725
|
+
frameState.mode === SceneMode.MORPHING &&
|
|
726
|
+
defined(surfaceTile.renderedMesh)
|
|
727
|
+
) {
|
|
728
|
+
boundingVolume = BoundingSphere.union(
|
|
729
|
+
// @ts-expect-error Missing types.
|
|
730
|
+
tileBoundingRegion.boundingSphere,
|
|
731
|
+
boundingVolume,
|
|
732
|
+
boundingVolume,
|
|
733
|
+
);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
if (!defined(boundingVolume)) {
|
|
738
|
+
return Visibility.PARTIAL;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
const clippingPlanes = this._clippingPlanes;
|
|
742
|
+
// @ts-expect-error Missing types.
|
|
743
|
+
if (defined(clippingPlanes) && clippingPlanes.enabled) {
|
|
744
|
+
const planeIntersection =
|
|
745
|
+
clippingPlanes.computeIntersectionWithBoundingVolume(boundingVolume);
|
|
746
|
+
// @ts-expect-error Possibly an error? isClipped is defined on surfaceTile, not tile.
|
|
747
|
+
tile.isClipped = planeIntersection !== Intersect.INSIDE;
|
|
748
|
+
if (planeIntersection === Intersect.OUTSIDE) {
|
|
749
|
+
return Visibility.NONE;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
const clippingPolygons = this._clippingPolygons;
|
|
754
|
+
if (defined(clippingPolygons) && clippingPolygons.enabled) {
|
|
755
|
+
const polygonIntersection =
|
|
756
|
+
clippingPolygons.computeIntersectionWithBoundingVolume(
|
|
757
|
+
tileBoundingRegion,
|
|
758
|
+
);
|
|
759
|
+
// @ts-expect-error Possibly an error? isClipped is defined on surfaceTile, not tile.
|
|
760
|
+
tile.isClipped = polygonIntersection !== Intersect.OUTSIDE;
|
|
761
|
+
// Polygon clipping intersections are determined by outer rectangles, therefore we cannot
|
|
762
|
+
// preemptively determine if a tile is completely clipped or not here.
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
let visibility;
|
|
766
|
+
const intersection = cullingVolume.computeVisibility(boundingVolume);
|
|
767
|
+
|
|
768
|
+
if (intersection === Intersect.OUTSIDE) {
|
|
769
|
+
visibility = Visibility.NONE;
|
|
770
|
+
} else if (intersection === Intersect.INTERSECTING) {
|
|
771
|
+
visibility = Visibility.PARTIAL;
|
|
772
|
+
} else if (intersection === Intersect.INSIDE) {
|
|
773
|
+
visibility = Visibility.FULL;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
if (visibility === Visibility.NONE) {
|
|
777
|
+
return visibility;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
const ortho3D =
|
|
781
|
+
frameState.mode === SceneMode.SCENE3D &&
|
|
782
|
+
frameState.camera.frustum instanceof OrthographicFrustum;
|
|
783
|
+
if (
|
|
784
|
+
frameState.mode === SceneMode.SCENE3D &&
|
|
785
|
+
!ortho3D &&
|
|
786
|
+
defined(occluders) &&
|
|
787
|
+
!undergroundVisible
|
|
788
|
+
) {
|
|
789
|
+
const occludeePointInScaledSpace = surfaceTile.occludeePointInScaledSpace;
|
|
790
|
+
if (!defined(occludeePointInScaledSpace)) {
|
|
791
|
+
return visibility;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
if (
|
|
795
|
+
occluders.ellipsoid.isScaledSpacePointVisiblePossiblyUnderEllipsoid(
|
|
796
|
+
occludeePointInScaledSpace,
|
|
797
|
+
tileBoundingRegion.minimumHeight,
|
|
798
|
+
)
|
|
799
|
+
) {
|
|
800
|
+
return visibility;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
return Visibility.NONE;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
return visibility;
|
|
700
807
|
}
|
|
701
808
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
809
|
+
/**
|
|
810
|
+
* Determines if the given tile can be refined
|
|
811
|
+
* @param {QuadtreeTile} tile The tile to check.
|
|
812
|
+
* @returns {boolean} True if the tile can be refined, false if it cannot.
|
|
813
|
+
*/
|
|
814
|
+
canRefine(tile) {
|
|
815
|
+
const surfaceTile = /** @type {GlobeSurfaceTile} */ (tile.data);
|
|
816
|
+
|
|
817
|
+
// Only allow refinement it we know whether or not the children of this tile exist.
|
|
818
|
+
// For a tileset with `availability`, we'll always be able to refine.
|
|
819
|
+
// We can ask for availability of _any_ child tile because we only need to confirm
|
|
820
|
+
// that we get a yes or no answer, it doesn't matter what the answer is.
|
|
821
|
+
if (defined(surfaceTile.terrainData)) {
|
|
822
|
+
return true;
|
|
823
|
+
}
|
|
824
|
+
const childAvailable = this.terrainProvider.getTileDataAvailable(
|
|
825
|
+
// @ts-expect-error Missing types.
|
|
826
|
+
tile.x * 2,
|
|
827
|
+
tile.y * 2,
|
|
828
|
+
tile.level + 1,
|
|
829
|
+
);
|
|
830
|
+
return childAvailable !== undefined;
|
|
705
831
|
}
|
|
706
832
|
|
|
707
|
-
|
|
708
|
-
|
|
833
|
+
/**
|
|
834
|
+
* Determines if the given not-fully-loaded tile can be rendered without losing detail that
|
|
835
|
+
* was present last frame as a result of rendering descendant tiles. This method will only be
|
|
836
|
+
* called if this tile's descendants were rendered last frame. If the tile is fully loaded,
|
|
837
|
+
* it is assumed that this method will return true and it will not be called.
|
|
838
|
+
* @param {QuadtreeTile} tile The tile to check.
|
|
839
|
+
* @returns {boolean} True if the tile can be rendered without losing detail.
|
|
840
|
+
*/
|
|
841
|
+
canRenderWithoutLosingDetail(tile) {
|
|
842
|
+
const surfaceTile = /** @type {GlobeSurfaceTile} */ (tile.data);
|
|
843
|
+
|
|
844
|
+
const readyImagery = readyImageryScratch;
|
|
845
|
+
// @ts-expect-error Missing types.
|
|
846
|
+
readyImagery.length = this._imageryLayers.length;
|
|
847
|
+
|
|
848
|
+
let terrainReady = false;
|
|
849
|
+
let initialImageryState = false;
|
|
850
|
+
let imagery;
|
|
851
|
+
|
|
852
|
+
if (defined(surfaceTile)) {
|
|
853
|
+
// We can render even with non-ready terrain as long as all our rendered descendants
|
|
854
|
+
// are missing terrain geometry too. i.e. if we rendered fills for more detailed tiles
|
|
855
|
+
// last frame, it's ok to render a fill for this tile this frame.
|
|
856
|
+
terrainReady = surfaceTile.terrainState === TerrainState.READY;
|
|
857
|
+
|
|
858
|
+
// Initially assume all imagery layers are ready, unless imagery hasn't been initialized at all.
|
|
859
|
+
initialImageryState = true;
|
|
860
|
+
|
|
861
|
+
imagery = surfaceTile.imagery;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
let i;
|
|
865
|
+
let len;
|
|
866
|
+
|
|
867
|
+
for (i = 0, len = readyImagery.length; i < len; ++i) {
|
|
868
|
+
readyImagery[i] = initialImageryState;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
if (defined(imagery)) {
|
|
872
|
+
for (i = 0, len = imagery.length; i < len; ++i) {
|
|
873
|
+
const tileImagery = imagery[i];
|
|
874
|
+
const loadingImagery = tileImagery.loadingImagery;
|
|
875
|
+
const isReady =
|
|
876
|
+
!defined(loadingImagery) ||
|
|
877
|
+
loadingImagery.state === ImageryState.FAILED ||
|
|
878
|
+
loadingImagery.state === ImageryState.INVALID;
|
|
879
|
+
const layerIndex = (
|
|
880
|
+
tileImagery.loadingImagery || tileImagery.readyImagery
|
|
881
|
+
).imageryLayer._layerIndex;
|
|
882
|
+
|
|
883
|
+
// For a layer to be ready, all tiles belonging to that layer must be ready.
|
|
884
|
+
readyImagery[layerIndex] = isReady && readyImagery[layerIndex];
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
const lastFrame = this.quadtree._lastSelectionFrameNumber;
|
|
889
|
+
|
|
890
|
+
// Traverse the descendants looking for one with terrain or imagery that is not loaded on this tile.
|
|
891
|
+
const stack = canRenderTraversalStack;
|
|
892
|
+
stack.length = 0;
|
|
893
|
+
stack.push(
|
|
894
|
+
tile.southwestChild,
|
|
895
|
+
tile.southeastChild,
|
|
896
|
+
tile.northwestChild,
|
|
897
|
+
tile.northeastChild,
|
|
898
|
+
);
|
|
899
|
+
|
|
900
|
+
while (stack.length > 0) {
|
|
901
|
+
const descendant = stack.pop();
|
|
902
|
+
const lastFrameSelectionResult =
|
|
903
|
+
descendant._lastSelectionResultFrame === lastFrame
|
|
904
|
+
? descendant._lastSelectionResult
|
|
905
|
+
: TileSelectionResult.NONE;
|
|
906
|
+
|
|
907
|
+
if (lastFrameSelectionResult === TileSelectionResult.RENDERED) {
|
|
908
|
+
const descendantSurface = descendant.data;
|
|
909
|
+
|
|
910
|
+
if (!defined(descendantSurface)) {
|
|
911
|
+
// Descendant has no data, so it can't block rendering.
|
|
912
|
+
continue;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
if (
|
|
916
|
+
!terrainReady &&
|
|
917
|
+
descendant.data.terrainState === TerrainState.READY
|
|
918
|
+
) {
|
|
919
|
+
// Rendered descendant has real terrain, but we don't. Rendering is blocked.
|
|
920
|
+
return false;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
const descendantImagery = descendant.data.imagery;
|
|
924
|
+
for (i = 0, len = descendantImagery.length; i < len; ++i) {
|
|
925
|
+
const descendantTileImagery = descendantImagery[i];
|
|
926
|
+
const descendantLoadingImagery = descendantTileImagery.loadingImagery;
|
|
927
|
+
const descendantIsReady =
|
|
928
|
+
!defined(descendantLoadingImagery) ||
|
|
929
|
+
descendantLoadingImagery.state === ImageryState.FAILED ||
|
|
930
|
+
descendantLoadingImagery.state === ImageryState.INVALID;
|
|
931
|
+
const descendantLayerIndex = (
|
|
932
|
+
descendantTileImagery.loadingImagery ||
|
|
933
|
+
descendantTileImagery.readyImagery
|
|
934
|
+
).imageryLayer._layerIndex;
|
|
935
|
+
|
|
936
|
+
// If this imagery tile of a descendant is ready but the layer isn't ready in this tile,
|
|
937
|
+
// then rendering is blocked.
|
|
938
|
+
if (descendantIsReady && !readyImagery[descendantLayerIndex]) {
|
|
939
|
+
return false;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
} else if (lastFrameSelectionResult === TileSelectionResult.REFINED) {
|
|
943
|
+
stack.push(
|
|
944
|
+
descendant.southwestChild,
|
|
945
|
+
descendant.southeastChild,
|
|
946
|
+
descendant.northwestChild,
|
|
947
|
+
descendant.northeastChild,
|
|
948
|
+
);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
|
|
709
952
|
return true;
|
|
710
953
|
}
|
|
711
954
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
955
|
+
/**
|
|
956
|
+
* Determines the priority for loading this tile. Lower priority values load sooner.
|
|
957
|
+
* @param {QuadtreeTile} tile The tile.
|
|
958
|
+
* @param {FrameState} frameState The frame state.
|
|
959
|
+
* @returns {number} The load priority value.
|
|
960
|
+
*/
|
|
961
|
+
computeTileLoadPriority(tile, frameState) {
|
|
962
|
+
const surfaceTile = /** @type {GlobeSurfaceTile} */ (tile.data);
|
|
963
|
+
if (surfaceTile === undefined) {
|
|
964
|
+
return 0.0;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
const obb = surfaceTile.tileBoundingRegion.boundingVolume;
|
|
968
|
+
if (obb === undefined) {
|
|
969
|
+
return 0.0;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
const cameraPosition = frameState.camera.positionWC;
|
|
973
|
+
const cameraDirection = frameState.camera.directionWC;
|
|
974
|
+
const tileDirection = Cartesian3.subtract(
|
|
975
|
+
obb.center,
|
|
976
|
+
cameraPosition,
|
|
977
|
+
tileDirectionScratch,
|
|
978
|
+
);
|
|
979
|
+
const magnitude = Cartesian3.magnitude(tileDirection);
|
|
980
|
+
if (magnitude < CesiumMath.EPSILON5) {
|
|
981
|
+
return 0.0;
|
|
982
|
+
}
|
|
983
|
+
Cartesian3.divideByScalar(tileDirection, magnitude, tileDirection);
|
|
984
|
+
return (
|
|
985
|
+
(1.0 - Cartesian3.dot(tileDirection, cameraDirection)) * tile._distance
|
|
986
|
+
);
|
|
719
987
|
}
|
|
720
988
|
|
|
721
|
-
|
|
722
|
-
|
|
989
|
+
/**
|
|
990
|
+
* Shows a specified tile in this frame. The provider can cause the tile to be shown by adding
|
|
991
|
+
* render commands to the commandList, or use any other method as appropriate. The tile is not
|
|
992
|
+
* expected to be visible next frame as well, unless this method is called next frame, too.
|
|
993
|
+
*
|
|
994
|
+
* @param {QuadtreeTile} tile The tile instance.
|
|
995
|
+
* @param {FrameState} frameState The state information of the current rendering frame.
|
|
996
|
+
*/
|
|
997
|
+
showTileThisFrame(tile, frameState) {
|
|
998
|
+
let readyTextureCount = 0;
|
|
999
|
+
const surfaceTile = /** @type {GlobeSurfaceTile} */ (tile.data);
|
|
1000
|
+
const tileImageryCollection = surfaceTile.imagery;
|
|
1001
|
+
for (let i = 0, len = tileImageryCollection.length; i < len; ++i) {
|
|
1002
|
+
const tileImagery = tileImageryCollection[i];
|
|
1003
|
+
if (
|
|
1004
|
+
defined(tileImagery.readyImagery) &&
|
|
1005
|
+
tileImagery.readyImagery.imageryLayer.alpha !== 0.0
|
|
1006
|
+
) {
|
|
1007
|
+
++readyTextureCount;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
723
1010
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
* @param {QuadtreeTile} tile The tile instance.
|
|
730
|
-
* @param {FrameState} frameState The state information about the current frame.
|
|
731
|
-
* @param {QuadtreeOccluders} occluders The objects that may occlude this tile.
|
|
732
|
-
*
|
|
733
|
-
* @returns {Visibility} Visibility.NONE if the tile is not visible,
|
|
734
|
-
* Visibility.PARTIAL if the tile is partially visible, or
|
|
735
|
-
* Visibility.FULL if the tile is fully visible.
|
|
736
|
-
*/
|
|
737
|
-
GlobeSurfaceTileProvider.prototype.computeTileVisibility = function (
|
|
738
|
-
tile,
|
|
739
|
-
frameState,
|
|
740
|
-
occluders,
|
|
741
|
-
) {
|
|
742
|
-
const distance = this.computeDistanceToTile(tile, frameState);
|
|
743
|
-
tile._distance = distance;
|
|
1011
|
+
let tileSet = this._tilesToRenderByTextureCount[readyTextureCount];
|
|
1012
|
+
if (!defined(tileSet)) {
|
|
1013
|
+
tileSet = [];
|
|
1014
|
+
this._tilesToRenderByTextureCount[readyTextureCount] = tileSet;
|
|
1015
|
+
}
|
|
744
1016
|
|
|
745
|
-
|
|
1017
|
+
tileSet.push(tile);
|
|
746
1018
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
1019
|
+
if (!defined(surfaceTile.vertexArray)) {
|
|
1020
|
+
this._hasFillTilesThisFrame = true;
|
|
1021
|
+
} else {
|
|
1022
|
+
this._hasLoadedTilesThisFrame = true;
|
|
751
1023
|
}
|
|
1024
|
+
|
|
1025
|
+
const debug = this._debug;
|
|
1026
|
+
++debug.tilesRendered;
|
|
1027
|
+
debug.texturesRendered += readyTextureCount;
|
|
752
1028
|
}
|
|
753
1029
|
|
|
754
|
-
|
|
755
|
-
|
|
1030
|
+
/**
|
|
1031
|
+
* Gets the distance from the camera to the closest point on the tile. This is used for level-of-detail selection.
|
|
1032
|
+
*
|
|
1033
|
+
* @param {QuadtreeTile} tile The tile instance.
|
|
1034
|
+
* @param {FrameState} frameState The state information of the current rendering frame.
|
|
1035
|
+
*
|
|
1036
|
+
* @returns {number} The distance from the camera to the closest point on the tile, in meters.
|
|
1037
|
+
*/
|
|
1038
|
+
computeDistanceToTile(tile, frameState) {
|
|
1039
|
+
// The distance should be:
|
|
1040
|
+
// 1. the actual distance to the tight-fitting bounding volume, or
|
|
1041
|
+
// 2. a distance that is equal to or greater than the actual distance to the tight-fitting bounding volume.
|
|
1042
|
+
//
|
|
1043
|
+
// When we don't know the min/max heights for a tile, but we do know the min/max of an ancestor tile, we can
|
|
1044
|
+
// build a tight-fitting bounding volume horizontally, but not vertically. The min/max heights from the
|
|
1045
|
+
// ancestor will likely form a volume that is much bigger than it needs to be. This means that the volume may
|
|
1046
|
+
// be deemed to be much closer to the camera than it really is, causing us to select tiles that are too detailed.
|
|
1047
|
+
// Loading too-detailed tiles is super expensive, so we don't want to do that. We don't know where the child
|
|
1048
|
+
// tile really lies within the parent range of heights, but we _do_ know the child tile can't be any closer than
|
|
1049
|
+
// the ancestor height surface (min or max) that is _farthest away_ from the camera. So if we compute distance
|
|
1050
|
+
// based on that conservative metric, we may end up loading tiles that are not detailed enough, but that's much
|
|
1051
|
+
// better (faster) than loading tiles that are too detailed.
|
|
1052
|
+
|
|
1053
|
+
updateTileBoundingRegion(tile, this, frameState);
|
|
1054
|
+
|
|
1055
|
+
const surfaceTile = /** @type {GlobeSurfaceTile} */ (tile.data);
|
|
1056
|
+
const boundingVolumeSourceTile = surfaceTile.boundingVolumeSourceTile;
|
|
1057
|
+
if (boundingVolumeSourceTile === undefined) {
|
|
1058
|
+
// Can't find any min/max heights anywhere? Ok, let's just say the
|
|
1059
|
+
// tile is really far away so we'll load and render it rather than
|
|
1060
|
+
// refining.
|
|
1061
|
+
return 9999999999.0;
|
|
1062
|
+
}
|
|
756
1063
|
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
1064
|
+
const tileBoundingRegion = surfaceTile.tileBoundingRegion;
|
|
1065
|
+
const min = tileBoundingRegion.minimumHeight;
|
|
1066
|
+
const max = tileBoundingRegion.maximumHeight;
|
|
1067
|
+
|
|
1068
|
+
if (surfaceTile.boundingVolumeSourceTile !== tile) {
|
|
1069
|
+
const cameraHeight = frameState.camera.positionCartographic.height;
|
|
1070
|
+
const distanceToMin = Math.abs(cameraHeight - min);
|
|
1071
|
+
const distanceToMax = Math.abs(cameraHeight - max);
|
|
1072
|
+
if (distanceToMin > distanceToMax) {
|
|
1073
|
+
tileBoundingRegion.minimumHeight = min;
|
|
1074
|
+
tileBoundingRegion.maximumHeight = min;
|
|
1075
|
+
} else {
|
|
1076
|
+
tileBoundingRegion.minimumHeight = max;
|
|
1077
|
+
tileBoundingRegion.maximumHeight = max;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
761
1080
|
|
|
762
|
-
|
|
763
|
-
let boundingVolume = tileBoundingRegion.boundingVolume;
|
|
1081
|
+
const result = tileBoundingRegion.distanceToCamera(frameState);
|
|
764
1082
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
}
|
|
1083
|
+
tileBoundingRegion.minimumHeight = min;
|
|
1084
|
+
tileBoundingRegion.maximumHeight = max;
|
|
768
1085
|
|
|
769
|
-
|
|
770
|
-
surfaceTile.clippedByBoundaries = false;
|
|
771
|
-
const clippedCartographicLimitRectangle = clipRectangleAntimeridian(
|
|
772
|
-
tile.rectangle,
|
|
773
|
-
this.cartographicLimitRectangle,
|
|
774
|
-
);
|
|
775
|
-
const areaLimitIntersection = Rectangle.simpleIntersection(
|
|
776
|
-
clippedCartographicLimitRectangle,
|
|
777
|
-
tile.rectangle,
|
|
778
|
-
rectangleIntersectionScratch,
|
|
779
|
-
);
|
|
780
|
-
if (!defined(areaLimitIntersection)) {
|
|
781
|
-
return Visibility.NONE;
|
|
1086
|
+
return result;
|
|
782
1087
|
}
|
|
783
|
-
|
|
784
|
-
|
|
1088
|
+
|
|
1089
|
+
/**
|
|
1090
|
+
* Returns true if this object was destroyed; otherwise, false.
|
|
1091
|
+
* <br /><br />
|
|
1092
|
+
* If this object was destroyed, it should not be used; calling any function other than
|
|
1093
|
+
* <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
|
|
1094
|
+
*
|
|
1095
|
+
* @returns {boolean} True if this object was destroyed; otherwise, false.
|
|
1096
|
+
*
|
|
1097
|
+
* @see GlobeSurfaceTileProvider#destroy
|
|
1098
|
+
*/
|
|
1099
|
+
isDestroyed() {
|
|
1100
|
+
return false;
|
|
785
1101
|
}
|
|
786
1102
|
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
1103
|
+
/**
|
|
1104
|
+
* Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
|
|
1105
|
+
* release of WebGL resources, instead of relying on the garbage collector to destroy this object.
|
|
1106
|
+
* <br /><br />
|
|
1107
|
+
* Once an object is destroyed, it should not be used; calling any function other than
|
|
1108
|
+
* <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
|
|
1109
|
+
* assign the return value (<code>undefined</code>) to the object as done in the example.
|
|
1110
|
+
*
|
|
1111
|
+
* @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
|
|
1112
|
+
*
|
|
1113
|
+
*
|
|
1114
|
+
* @example
|
|
1115
|
+
* provider = provider && provider.destroy();
|
|
1116
|
+
*
|
|
1117
|
+
* @see GlobeSurfaceTileProvider#isDestroyed
|
|
1118
|
+
*/
|
|
1119
|
+
destroy() {
|
|
1120
|
+
this._tileProvider = this._tileProvider && this._tileProvider.destroy();
|
|
1121
|
+
this._clippingPlanes =
|
|
1122
|
+
this._clippingPlanes && this._clippingPlanes.destroy();
|
|
1123
|
+
this._clippingPolygons =
|
|
1124
|
+
this._clippingPolygons && this._clippingPolygons.destroy();
|
|
1125
|
+
this._removeLayerAddedListener =
|
|
1126
|
+
this._removeLayerAddedListener && this._removeLayerAddedListener();
|
|
1127
|
+
this._removeLayerRemovedListener =
|
|
1128
|
+
this._removeLayerRemovedListener && this._removeLayerRemovedListener();
|
|
1129
|
+
this._removeLayerMovedListener =
|
|
1130
|
+
this._removeLayerMovedListener && this._removeLayerMovedListener();
|
|
1131
|
+
this._removeLayerShownListener =
|
|
1132
|
+
this._removeLayerShownListener && this._removeLayerShownListener();
|
|
1133
|
+
|
|
1134
|
+
return destroyObject(this);
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
_onLayerAdded(layer, index) {
|
|
1138
|
+
if (this.isDestroyed()) {
|
|
1139
|
+
return;
|
|
1140
|
+
}
|
|
802
1141
|
|
|
803
|
-
if (
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
1142
|
+
if (layer.show) {
|
|
1143
|
+
const terrainProvider = this._terrainProvider;
|
|
1144
|
+
|
|
1145
|
+
const that = this;
|
|
1146
|
+
const tileImageryUpdatedEvent = this._imageryLayersUpdatedEvent;
|
|
1147
|
+
const reloadFunction = function () {
|
|
1148
|
+
// Clear the layer's cache
|
|
1149
|
+
layer._imageryCache = {};
|
|
1150
|
+
|
|
1151
|
+
that._quadtree.forEachLoadedTile(function (tile) {
|
|
1152
|
+
// If this layer is still waiting to for the loaded callback, just return
|
|
1153
|
+
if (defined(tile._loadedCallbacks[layer._layerIndex])) {
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
let i;
|
|
1158
|
+
|
|
1159
|
+
// Figure out how many TileImageries we will need to remove and where to insert new ones
|
|
1160
|
+
const tileImageryCollection = tile.data.imagery;
|
|
1161
|
+
const length = tileImageryCollection.length;
|
|
1162
|
+
let startIndex = -1;
|
|
1163
|
+
let tileImageriesToFree = 0;
|
|
1164
|
+
for (i = 0; i < length; ++i) {
|
|
1165
|
+
const tileImagery = tileImageryCollection[i];
|
|
1166
|
+
const imagery =
|
|
1167
|
+
tileImagery.readyImagery ?? tileImagery.loadingImagery;
|
|
1168
|
+
if (imagery.imageryLayer === layer) {
|
|
1169
|
+
if (startIndex === -1) {
|
|
1170
|
+
startIndex = i;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
++tileImageriesToFree;
|
|
1174
|
+
} else if (startIndex !== -1) {
|
|
1175
|
+
// iterated past the section of TileImageries belonging to this layer, no need to continue.
|
|
1176
|
+
break;
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
if (startIndex === -1) {
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
// Insert immediately after existing TileImageries
|
|
1185
|
+
const insertionPoint = startIndex + tileImageriesToFree;
|
|
1186
|
+
|
|
1187
|
+
// Create new TileImageries for all loaded tiles
|
|
1188
|
+
if (
|
|
1189
|
+
layer._createTileImagerySkeletons(
|
|
1190
|
+
tile,
|
|
1191
|
+
terrainProvider,
|
|
1192
|
+
insertionPoint,
|
|
1193
|
+
)
|
|
1194
|
+
) {
|
|
1195
|
+
// Add callback to remove old TileImageries when the new TileImageries are ready
|
|
1196
|
+
tile._loadedCallbacks[layer._layerIndex] = getTileReadyCallback(
|
|
1197
|
+
tileImageriesToFree,
|
|
1198
|
+
layer,
|
|
1199
|
+
terrainProvider,
|
|
1200
|
+
);
|
|
1201
|
+
|
|
1202
|
+
tile.state = QuadtreeTileLoadState.LOADING;
|
|
1203
|
+
}
|
|
1204
|
+
});
|
|
1205
|
+
};
|
|
1206
|
+
|
|
1207
|
+
if (layer.ready) {
|
|
1208
|
+
const imageryProvider = layer.imageryProvider;
|
|
1209
|
+
imageryProvider._reload = reloadFunction;
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
// create TileImageries for this layer for all previously loaded tiles
|
|
1213
|
+
this._quadtree.forEachLoadedTile(function (tile) {
|
|
1214
|
+
if (layer._createTileImagerySkeletons(tile, terrainProvider)) {
|
|
1215
|
+
tile.state = QuadtreeTileLoadState.LOADING;
|
|
1216
|
+
|
|
1217
|
+
// Tiles that are not currently being rendered need to load the new layer before they're renderable.
|
|
1218
|
+
// We don't mark the rendered tiles non-renderable, though, because that would make the globe disappear.
|
|
1219
|
+
if (
|
|
1220
|
+
tile.level !== 0 &&
|
|
1221
|
+
(tile._lastSelectionResultFrame !==
|
|
1222
|
+
that.quadtree._lastSelectionFrameNumber ||
|
|
1223
|
+
tile._lastSelectionResult !== TileSelectionResult.RENDERED)
|
|
1224
|
+
) {
|
|
1225
|
+
tile.renderable = false;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
});
|
|
1229
|
+
|
|
1230
|
+
this._layerOrderChanged = true;
|
|
1231
|
+
tileImageryUpdatedEvent.raiseEvent();
|
|
812
1232
|
}
|
|
813
1233
|
}
|
|
814
1234
|
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
1235
|
+
_onLayerRemoved(layer, index) {
|
|
1236
|
+
// destroy TileImagerys for this layer for all previously loaded tiles
|
|
1237
|
+
this._quadtree.forEachLoadedTile(function (tile) {
|
|
1238
|
+
const tileImageryCollection = tile.data.imagery;
|
|
1239
|
+
|
|
1240
|
+
let startIndex = -1;
|
|
1241
|
+
let numDestroyed = 0;
|
|
1242
|
+
for (let i = 0, len = tileImageryCollection.length; i < len; ++i) {
|
|
1243
|
+
const tileImagery = tileImageryCollection[i];
|
|
1244
|
+
let imagery = tileImagery.loadingImagery;
|
|
1245
|
+
if (!defined(imagery)) {
|
|
1246
|
+
imagery = tileImagery.readyImagery;
|
|
1247
|
+
}
|
|
1248
|
+
if (imagery.imageryLayer === layer) {
|
|
1249
|
+
if (startIndex === -1) {
|
|
1250
|
+
startIndex = i;
|
|
1251
|
+
}
|
|
818
1252
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
1253
|
+
tileImagery.freeResources();
|
|
1254
|
+
++numDestroyed;
|
|
1255
|
+
} else if (startIndex !== -1) {
|
|
1256
|
+
// iterated past the section of TileImagerys belonging to this layer, no need to continue.
|
|
1257
|
+
break;
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
if (startIndex !== -1) {
|
|
1262
|
+
tileImageryCollection.splice(startIndex, numDestroyed);
|
|
1263
|
+
}
|
|
1264
|
+
});
|
|
1265
|
+
|
|
1266
|
+
if (defined(layer.imageryProvider)) {
|
|
1267
|
+
layer.imageryProvider._reload = undefined;
|
|
826
1268
|
}
|
|
1269
|
+
|
|
1270
|
+
this._imageryLayersUpdatedEvent.raiseEvent();
|
|
827
1271
|
}
|
|
828
1272
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
clippingPolygons.computeIntersectionWithBoundingVolume(
|
|
833
|
-
tileBoundingRegion,
|
|
834
|
-
);
|
|
835
|
-
tile.isClipped = polygonIntersection !== Intersect.OUTSIDE;
|
|
836
|
-
// Polygon clipping intersections are determined by outer rectangles, therefore we cannot
|
|
837
|
-
// preemptively determine if a tile is completely clipped or not here.
|
|
1273
|
+
_onLayerMoved(layer, newIndex, oldIndex) {
|
|
1274
|
+
this._layerOrderChanged = true;
|
|
1275
|
+
this._imageryLayersUpdatedEvent.raiseEvent();
|
|
838
1276
|
}
|
|
839
1277
|
|
|
840
|
-
|
|
841
|
-
|
|
1278
|
+
_onLayerShownOrHidden(layer, index, show) {
|
|
1279
|
+
if (show) {
|
|
1280
|
+
this._onLayerAdded(layer, index);
|
|
1281
|
+
} else {
|
|
1282
|
+
this._onLayerRemoved(layer, index);
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
842
1286
|
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
} else if (intersection === Intersect.INSIDE) {
|
|
848
|
-
visibility = Visibility.FULL;
|
|
1287
|
+
function sortTileImageryByLayerIndex(a, b) {
|
|
1288
|
+
let aImagery = a.loadingImagery;
|
|
1289
|
+
if (!defined(aImagery)) {
|
|
1290
|
+
aImagery = a.readyImagery;
|
|
849
1291
|
}
|
|
850
1292
|
|
|
851
|
-
|
|
852
|
-
|
|
1293
|
+
let bImagery = b.loadingImagery;
|
|
1294
|
+
if (!defined(bImagery)) {
|
|
1295
|
+
bImagery = b.readyImagery;
|
|
853
1296
|
}
|
|
854
1297
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
1298
|
+
return aImagery.imageryLayer._layerIndex - bImagery.imageryLayer._layerIndex;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
/**
|
|
1302
|
+
* @param {GlobeSurfaceTileProvider} surface
|
|
1303
|
+
* @param {FrameState} frameState
|
|
1304
|
+
* @ignore
|
|
1305
|
+
*/
|
|
1306
|
+
function updateCredits(surface, frameState) {
|
|
1307
|
+
const creditDisplay = frameState.creditDisplay;
|
|
1308
|
+
const terrainProvider = surface._terrainProvider;
|
|
1309
|
+
// @ts-expect-error Missing types.
|
|
1310
|
+
if (defined(terrainProvider) && defined(terrainProvider.credit)) {
|
|
1311
|
+
// @ts-expect-error Missing types.
|
|
1312
|
+
creditDisplay.addCreditToNextFrame(terrainProvider.credit);
|
|
1313
|
+
}
|
|
868
1314
|
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
) {
|
|
875
|
-
|
|
1315
|
+
const imageryLayers = surface._imageryLayers;
|
|
1316
|
+
// @ts-expect-error Missing types.
|
|
1317
|
+
for (let i = 0, len = imageryLayers.length; i < len; ++i) {
|
|
1318
|
+
const layer = imageryLayers.get(i);
|
|
1319
|
+
// @ts-expect-error Missing types.
|
|
1320
|
+
if (layer.ready && layer.show && defined(layer.imageryProvider.credit)) {
|
|
1321
|
+
// @ts-expect-error Missing types.
|
|
1322
|
+
creditDisplay.addCreditToNextFrame(layer.imageryProvider.credit);
|
|
876
1323
|
}
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
877
1326
|
|
|
878
|
-
|
|
1327
|
+
/**
|
|
1328
|
+
* @param {DrawCommand} command
|
|
1329
|
+
* @param {FrameState} frameState
|
|
1330
|
+
* @ignore
|
|
1331
|
+
*/
|
|
1332
|
+
function pushCommand(command, frameState) {
|
|
1333
|
+
const globeTranslucencyState = frameState.globeTranslucencyState;
|
|
1334
|
+
if (globeTranslucencyState.translucent) {
|
|
1335
|
+
// @ts-expect-error Missing types.
|
|
1336
|
+
const isBlendCommand = command.renderState.blending.enabled;
|
|
1337
|
+
globeTranslucencyState.pushDerivedCommands(
|
|
1338
|
+
command,
|
|
1339
|
+
isBlendCommand,
|
|
1340
|
+
frameState,
|
|
1341
|
+
);
|
|
1342
|
+
} else {
|
|
1343
|
+
frameState.commandList.push(command);
|
|
879
1344
|
}
|
|
1345
|
+
}
|
|
880
1346
|
|
|
881
|
-
|
|
882
|
-
|
|
1347
|
+
const boundingSphereScratch = new BoundingSphere();
|
|
1348
|
+
const rectangleIntersectionScratch = new Rectangle();
|
|
1349
|
+
const splitCartographicLimitRectangleScratch = new Rectangle();
|
|
1350
|
+
const rectangleCenterScratch = new Cartographic();
|
|
883
1351
|
|
|
884
1352
|
/**
|
|
885
|
-
*
|
|
886
|
-
* @param {
|
|
887
|
-
* @
|
|
1353
|
+
* @param {Rectangle} tileRectangle
|
|
1354
|
+
* @param {Rectangle} cartographicLimitRectangle
|
|
1355
|
+
* @ignore
|
|
888
1356
|
*/
|
|
889
|
-
|
|
890
|
-
//
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
// that we get a yes or no answer, it doesn't matter what the answer is.
|
|
894
|
-
if (defined(tile.data.terrainData)) {
|
|
895
|
-
return true;
|
|
1357
|
+
function clipRectangleAntimeridian(tileRectangle, cartographicLimitRectangle) {
|
|
1358
|
+
// cartographicLimitRectangle may span the IDL, but tiles never will.
|
|
1359
|
+
if (cartographicLimitRectangle.west < cartographicLimitRectangle.east) {
|
|
1360
|
+
return cartographicLimitRectangle;
|
|
896
1361
|
}
|
|
897
|
-
const
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
tile.level + 1,
|
|
1362
|
+
const splitRectangle = Rectangle.clone(
|
|
1363
|
+
cartographicLimitRectangle,
|
|
1364
|
+
splitCartographicLimitRectangleScratch,
|
|
901
1365
|
);
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
1366
|
+
const tileCenter = Rectangle.center(tileRectangle, rectangleCenterScratch);
|
|
1367
|
+
if (tileCenter.longitude > 0.0) {
|
|
1368
|
+
splitRectangle.east = CesiumMath.PI;
|
|
1369
|
+
} else {
|
|
1370
|
+
splitRectangle.west = -CesiumMath.PI;
|
|
1371
|
+
}
|
|
1372
|
+
return splitRectangle;
|
|
1373
|
+
}
|
|
907
1374
|
|
|
908
1375
|
/**
|
|
909
|
-
*
|
|
910
|
-
*
|
|
911
|
-
*
|
|
912
|
-
* it is assumed that this method will return true and it will not be called.
|
|
913
|
-
* @param {QuadtreeTile} tile The tile to check.
|
|
914
|
-
* @returns {boolean} True if the tile can be rendered without losing detail.
|
|
1376
|
+
* @param {GlobeSurfaceTileProvider} tileProvider
|
|
1377
|
+
* @param {FrameState} frameState
|
|
1378
|
+
* @ignore
|
|
915
1379
|
*/
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
) {
|
|
920
|
-
const surfaceTile = tile.data;
|
|
921
|
-
|
|
922
|
-
const readyImagery = readyImageryScratch;
|
|
923
|
-
readyImagery.length = this._imageryLayers.length;
|
|
924
|
-
|
|
925
|
-
let terrainReady = false;
|
|
926
|
-
let initialImageryState = false;
|
|
927
|
-
let imagery;
|
|
928
|
-
|
|
929
|
-
if (defined(surfaceTile)) {
|
|
930
|
-
// We can render even with non-ready terrain as long as all our rendered descendants
|
|
931
|
-
// are missing terrain geometry too. i.e. if we rendered fills for more detailed tiles
|
|
932
|
-
// last frame, it's ok to render a fill for this tile this frame.
|
|
933
|
-
terrainReady = surfaceTile.terrainState === TerrainState.READY;
|
|
934
|
-
|
|
935
|
-
// Initially assume all imagery layers are ready, unless imagery hasn't been initialized at all.
|
|
936
|
-
initialImageryState = true;
|
|
937
|
-
|
|
938
|
-
imagery = surfaceTile.imagery;
|
|
1380
|
+
function isUndergroundVisible(tileProvider, frameState) {
|
|
1381
|
+
if (frameState.cameraUnderground) {
|
|
1382
|
+
return true;
|
|
939
1383
|
}
|
|
940
1384
|
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
for (i = 0, len = readyImagery.length; i < len; ++i) {
|
|
945
|
-
readyImagery[i] = initialImageryState;
|
|
1385
|
+
if (frameState.globeTranslucencyState.translucent) {
|
|
1386
|
+
return true;
|
|
946
1387
|
}
|
|
947
1388
|
|
|
948
|
-
if (
|
|
949
|
-
|
|
950
|
-
const tileImagery = imagery[i];
|
|
951
|
-
const loadingImagery = tileImagery.loadingImagery;
|
|
952
|
-
const isReady =
|
|
953
|
-
!defined(loadingImagery) ||
|
|
954
|
-
loadingImagery.state === ImageryState.FAILED ||
|
|
955
|
-
loadingImagery.state === ImageryState.INVALID;
|
|
956
|
-
const layerIndex = (
|
|
957
|
-
tileImagery.loadingImagery || tileImagery.readyImagery
|
|
958
|
-
).imageryLayer._layerIndex;
|
|
959
|
-
|
|
960
|
-
// For a layer to be ready, all tiles belonging to that layer must be ready.
|
|
961
|
-
readyImagery[layerIndex] = isReady && readyImagery[layerIndex];
|
|
962
|
-
}
|
|
1389
|
+
if (tileProvider.backFaceCulling) {
|
|
1390
|
+
return false;
|
|
963
1391
|
}
|
|
964
1392
|
|
|
965
|
-
const
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
const stack = canRenderTraversalStack;
|
|
969
|
-
stack.length = 0;
|
|
970
|
-
stack.push(
|
|
971
|
-
tile.southwestChild,
|
|
972
|
-
tile.southeastChild,
|
|
973
|
-
tile.northwestChild,
|
|
974
|
-
tile.northeastChild,
|
|
975
|
-
);
|
|
976
|
-
|
|
977
|
-
while (stack.length > 0) {
|
|
978
|
-
const descendant = stack.pop();
|
|
979
|
-
const lastFrameSelectionResult =
|
|
980
|
-
descendant._lastSelectionResultFrame === lastFrame
|
|
981
|
-
? descendant._lastSelectionResult
|
|
982
|
-
: TileSelectionResult.NONE;
|
|
983
|
-
|
|
984
|
-
if (lastFrameSelectionResult === TileSelectionResult.RENDERED) {
|
|
985
|
-
const descendantSurface = descendant.data;
|
|
986
|
-
|
|
987
|
-
if (!defined(descendantSurface)) {
|
|
988
|
-
// Descendant has no data, so it can't block rendering.
|
|
989
|
-
continue;
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
if (
|
|
993
|
-
!terrainReady &&
|
|
994
|
-
descendant.data.terrainState === TerrainState.READY
|
|
995
|
-
) {
|
|
996
|
-
// Rendered descendant has real terrain, but we don't. Rendering is blocked.
|
|
997
|
-
return false;
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
const descendantImagery = descendant.data.imagery;
|
|
1001
|
-
for (i = 0, len = descendantImagery.length; i < len; ++i) {
|
|
1002
|
-
const descendantTileImagery = descendantImagery[i];
|
|
1003
|
-
const descendantLoadingImagery = descendantTileImagery.loadingImagery;
|
|
1004
|
-
const descendantIsReady =
|
|
1005
|
-
!defined(descendantLoadingImagery) ||
|
|
1006
|
-
descendantLoadingImagery.state === ImageryState.FAILED ||
|
|
1007
|
-
descendantLoadingImagery.state === ImageryState.INVALID;
|
|
1008
|
-
const descendantLayerIndex = (
|
|
1009
|
-
descendantTileImagery.loadingImagery ||
|
|
1010
|
-
descendantTileImagery.readyImagery
|
|
1011
|
-
).imageryLayer._layerIndex;
|
|
1012
|
-
|
|
1013
|
-
// If this imagery tile of a descendant is ready but the layer isn't ready in this tile,
|
|
1014
|
-
// then rendering is blocked.
|
|
1015
|
-
if (descendantIsReady && !readyImagery[descendantLayerIndex]) {
|
|
1016
|
-
return false;
|
|
1017
|
-
}
|
|
1018
|
-
}
|
|
1019
|
-
} else if (lastFrameSelectionResult === TileSelectionResult.REFINED) {
|
|
1020
|
-
stack.push(
|
|
1021
|
-
descendant.southwestChild,
|
|
1022
|
-
descendant.southeastChild,
|
|
1023
|
-
descendant.northwestChild,
|
|
1024
|
-
descendant.northeastChild,
|
|
1025
|
-
);
|
|
1026
|
-
}
|
|
1393
|
+
const clippingPlanes = tileProvider._clippingPlanes;
|
|
1394
|
+
if (defined(clippingPlanes) && clippingPlanes.enabled) {
|
|
1395
|
+
return true;
|
|
1027
1396
|
}
|
|
1028
1397
|
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
const tileDirectionScratch = new Cartesian3();
|
|
1033
|
-
|
|
1034
|
-
/**
|
|
1035
|
-
* Determines the priority for loading this tile. Lower priority values load sooner.
|
|
1036
|
-
* @param {QuadtreeTile} tile The tile.
|
|
1037
|
-
* @param {FrameState} frameState The frame state.
|
|
1038
|
-
* @returns {number} The load priority value.
|
|
1039
|
-
*/
|
|
1040
|
-
GlobeSurfaceTileProvider.prototype.computeTileLoadPriority = function (
|
|
1041
|
-
tile,
|
|
1042
|
-
frameState,
|
|
1043
|
-
) {
|
|
1044
|
-
const surfaceTile = tile.data;
|
|
1045
|
-
if (surfaceTile === undefined) {
|
|
1046
|
-
return 0.0;
|
|
1398
|
+
const clippingPolygons = tileProvider._clippingPolygons;
|
|
1399
|
+
if (defined(clippingPolygons) && clippingPolygons.enabled) {
|
|
1400
|
+
return true;
|
|
1047
1401
|
}
|
|
1048
1402
|
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1403
|
+
if (
|
|
1404
|
+
!Rectangle.equals(
|
|
1405
|
+
tileProvider.cartographicLimitRectangle,
|
|
1406
|
+
Rectangle.MAX_VALUE,
|
|
1407
|
+
)
|
|
1408
|
+
) {
|
|
1409
|
+
return true;
|
|
1052
1410
|
}
|
|
1053
1411
|
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
const magnitude = Cartesian3.magnitude(tileDirection);
|
|
1062
|
-
if (magnitude < CesiumMath.EPSILON5) {
|
|
1063
|
-
return 0.0;
|
|
1064
|
-
}
|
|
1065
|
-
Cartesian3.divideByScalar(tileDirection, magnitude, tileDirection);
|
|
1066
|
-
return (
|
|
1067
|
-
(1.0 - Cartesian3.dot(tileDirection, cameraDirection)) * tile._distance
|
|
1068
|
-
);
|
|
1069
|
-
};
|
|
1412
|
+
return false;
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
const readyImageryScratch = [];
|
|
1416
|
+
const canRenderTraversalStack = [];
|
|
1417
|
+
|
|
1418
|
+
const tileDirectionScratch = new Cartesian3();
|
|
1070
1419
|
|
|
1071
1420
|
const modifiedModelViewScratch = new Matrix4();
|
|
1072
1421
|
const modifiedModelViewProjectionScratch = new Matrix4();
|
|
@@ -1078,50 +1427,6 @@ const centerEyeScratch = new Cartesian3();
|
|
|
1078
1427
|
const southwestScratch = new Cartesian3();
|
|
1079
1428
|
const northeastScratch = new Cartesian3();
|
|
1080
1429
|
|
|
1081
|
-
/**
|
|
1082
|
-
* Shows a specified tile in this frame. The provider can cause the tile to be shown by adding
|
|
1083
|
-
* render commands to the commandList, or use any other method as appropriate. The tile is not
|
|
1084
|
-
* expected to be visible next frame as well, unless this method is called next frame, too.
|
|
1085
|
-
*
|
|
1086
|
-
* @param {QuadtreeTile} tile The tile instance.
|
|
1087
|
-
* @param {FrameState} frameState The state information of the current rendering frame.
|
|
1088
|
-
*/
|
|
1089
|
-
GlobeSurfaceTileProvider.prototype.showTileThisFrame = function (
|
|
1090
|
-
tile,
|
|
1091
|
-
frameState,
|
|
1092
|
-
) {
|
|
1093
|
-
let readyTextureCount = 0;
|
|
1094
|
-
const tileImageryCollection = tile.data.imagery;
|
|
1095
|
-
for (let i = 0, len = tileImageryCollection.length; i < len; ++i) {
|
|
1096
|
-
const tileImagery = tileImageryCollection[i];
|
|
1097
|
-
if (
|
|
1098
|
-
defined(tileImagery.readyImagery) &&
|
|
1099
|
-
tileImagery.readyImagery.imageryLayer.alpha !== 0.0
|
|
1100
|
-
) {
|
|
1101
|
-
++readyTextureCount;
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
|
|
1105
|
-
let tileSet = this._tilesToRenderByTextureCount[readyTextureCount];
|
|
1106
|
-
if (!defined(tileSet)) {
|
|
1107
|
-
tileSet = [];
|
|
1108
|
-
this._tilesToRenderByTextureCount[readyTextureCount] = tileSet;
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
tileSet.push(tile);
|
|
1112
|
-
|
|
1113
|
-
const surfaceTile = tile.data;
|
|
1114
|
-
if (!defined(surfaceTile.vertexArray)) {
|
|
1115
|
-
this._hasFillTilesThisFrame = true;
|
|
1116
|
-
} else {
|
|
1117
|
-
this._hasLoadedTilesThisFrame = true;
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
const debug = this._debug;
|
|
1121
|
-
++debug.tilesRendered;
|
|
1122
|
-
debug.texturesRendered += readyTextureCount;
|
|
1123
|
-
};
|
|
1124
|
-
|
|
1125
1430
|
const cornerPositionsScratch = [
|
|
1126
1431
|
new Cartesian3(),
|
|
1127
1432
|
new Cartesian3(),
|
|
@@ -1137,7 +1442,9 @@ function computeOccludeePoint(
|
|
|
1137
1442
|
maximumHeight,
|
|
1138
1443
|
result,
|
|
1139
1444
|
) {
|
|
1445
|
+
/** @type {EllipsoidalOccluder} */
|
|
1140
1446
|
const ellipsoidalOccluder = tileProvider.quadtree._occluders.ellipsoid;
|
|
1447
|
+
// @ts-expect-error Missing types.
|
|
1141
1448
|
const ellipsoid = ellipsoidalOccluder.ellipsoid;
|
|
1142
1449
|
|
|
1143
1450
|
const cornerPositions = cornerPositionsScratch;
|
|
@@ -1179,69 +1486,13 @@ function computeOccludeePoint(
|
|
|
1179
1486
|
}
|
|
1180
1487
|
|
|
1181
1488
|
/**
|
|
1182
|
-
*
|
|
1183
|
-
*
|
|
1184
|
-
* @param {
|
|
1185
|
-
* @
|
|
1186
|
-
*
|
|
1187
|
-
* @returns {number} The distance from the camera to the closest point on the tile, in meters.
|
|
1489
|
+
* @param {QuadtreeTile} tile
|
|
1490
|
+
* @param {GlobeSurfaceTileProvider} tileProvider
|
|
1491
|
+
* @param {FrameState} frameState
|
|
1492
|
+
* @ignore
|
|
1188
1493
|
*/
|
|
1189
|
-
GlobeSurfaceTileProvider.prototype.computeDistanceToTile = function (
|
|
1190
|
-
tile,
|
|
1191
|
-
frameState,
|
|
1192
|
-
) {
|
|
1193
|
-
// The distance should be:
|
|
1194
|
-
// 1. the actual distance to the tight-fitting bounding volume, or
|
|
1195
|
-
// 2. a distance that is equal to or greater than the actual distance to the tight-fitting bounding volume.
|
|
1196
|
-
//
|
|
1197
|
-
// When we don't know the min/max heights for a tile, but we do know the min/max of an ancestor tile, we can
|
|
1198
|
-
// build a tight-fitting bounding volume horizontally, but not vertically. The min/max heights from the
|
|
1199
|
-
// ancestor will likely form a volume that is much bigger than it needs to be. This means that the volume may
|
|
1200
|
-
// be deemed to be much closer to the camera than it really is, causing us to select tiles that are too detailed.
|
|
1201
|
-
// Loading too-detailed tiles is super expensive, so we don't want to do that. We don't know where the child
|
|
1202
|
-
// tile really lies within the parent range of heights, but we _do_ know the child tile can't be any closer than
|
|
1203
|
-
// the ancestor height surface (min or max) that is _farthest away_ from the camera. So if we compute distance
|
|
1204
|
-
// based on that conservative metric, we may end up loading tiles that are not detailed enough, but that's much
|
|
1205
|
-
// better (faster) than loading tiles that are too detailed.
|
|
1206
|
-
|
|
1207
|
-
updateTileBoundingRegion(tile, this, frameState);
|
|
1208
|
-
|
|
1209
|
-
const surfaceTile = tile.data;
|
|
1210
|
-
const boundingVolumeSourceTile = surfaceTile.boundingVolumeSourceTile;
|
|
1211
|
-
if (boundingVolumeSourceTile === undefined) {
|
|
1212
|
-
// Can't find any min/max heights anywhere? Ok, let's just say the
|
|
1213
|
-
// tile is really far away so we'll load and render it rather than
|
|
1214
|
-
// refining.
|
|
1215
|
-
return 9999999999.0;
|
|
1216
|
-
}
|
|
1217
|
-
|
|
1218
|
-
const tileBoundingRegion = surfaceTile.tileBoundingRegion;
|
|
1219
|
-
const min = tileBoundingRegion.minimumHeight;
|
|
1220
|
-
const max = tileBoundingRegion.maximumHeight;
|
|
1221
|
-
|
|
1222
|
-
if (surfaceTile.boundingVolumeSourceTile !== tile) {
|
|
1223
|
-
const cameraHeight = frameState.camera.positionCartographic.height;
|
|
1224
|
-
const distanceToMin = Math.abs(cameraHeight - min);
|
|
1225
|
-
const distanceToMax = Math.abs(cameraHeight - max);
|
|
1226
|
-
if (distanceToMin > distanceToMax) {
|
|
1227
|
-
tileBoundingRegion.minimumHeight = min;
|
|
1228
|
-
tileBoundingRegion.maximumHeight = min;
|
|
1229
|
-
} else {
|
|
1230
|
-
tileBoundingRegion.minimumHeight = max;
|
|
1231
|
-
tileBoundingRegion.maximumHeight = max;
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
const result = tileBoundingRegion.distanceToCamera(frameState);
|
|
1236
|
-
|
|
1237
|
-
tileBoundingRegion.minimumHeight = min;
|
|
1238
|
-
tileBoundingRegion.maximumHeight = max;
|
|
1239
|
-
|
|
1240
|
-
return result;
|
|
1241
|
-
};
|
|
1242
|
-
|
|
1243
1494
|
function updateTileBoundingRegion(tile, tileProvider, frameState) {
|
|
1244
|
-
let surfaceTile = tile.data;
|
|
1495
|
+
let surfaceTile = /** @type {GlobeSurfaceTile} */ (tile.data);
|
|
1245
1496
|
if (surfaceTile === undefined) {
|
|
1246
1497
|
surfaceTile = tile.data = new GlobeSurfaceTile();
|
|
1247
1498
|
}
|
|
@@ -1291,7 +1542,9 @@ function updateTileBoundingRegion(tile, tileProvider, frameState) {
|
|
|
1291
1542
|
|
|
1292
1543
|
let ancestorTile = tile.parent;
|
|
1293
1544
|
while (ancestorTile !== undefined) {
|
|
1294
|
-
const ancestorSurfaceTile =
|
|
1545
|
+
const ancestorSurfaceTile = /** @type {GlobeSurfaceTile} */ (
|
|
1546
|
+
ancestorTile.data
|
|
1547
|
+
);
|
|
1295
1548
|
if (ancestorSurfaceTile !== undefined) {
|
|
1296
1549
|
const ancestorMesh = ancestorSurfaceTile.mesh;
|
|
1297
1550
|
const ancestorTerrainData = ancestorSurfaceTile.terrainData;
|
|
@@ -1393,53 +1646,6 @@ function updateTileBoundingRegion(tile, tileProvider, frameState) {
|
|
|
1393
1646
|
}
|
|
1394
1647
|
}
|
|
1395
1648
|
|
|
1396
|
-
/**
|
|
1397
|
-
* Returns true if this object was destroyed; otherwise, false.
|
|
1398
|
-
* <br /><br />
|
|
1399
|
-
* If this object was destroyed, it should not be used; calling any function other than
|
|
1400
|
-
* <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
|
|
1401
|
-
*
|
|
1402
|
-
* @returns {boolean} True if this object was destroyed; otherwise, false.
|
|
1403
|
-
*
|
|
1404
|
-
* @see GlobeSurfaceTileProvider#destroy
|
|
1405
|
-
*/
|
|
1406
|
-
GlobeSurfaceTileProvider.prototype.isDestroyed = function () {
|
|
1407
|
-
return false;
|
|
1408
|
-
};
|
|
1409
|
-
|
|
1410
|
-
/**
|
|
1411
|
-
* Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
|
|
1412
|
-
* release of WebGL resources, instead of relying on the garbage collector to destroy this object.
|
|
1413
|
-
* <br /><br />
|
|
1414
|
-
* Once an object is destroyed, it should not be used; calling any function other than
|
|
1415
|
-
* <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
|
|
1416
|
-
* assign the return value (<code>undefined</code>) to the object as done in the example.
|
|
1417
|
-
*
|
|
1418
|
-
* @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
|
|
1419
|
-
*
|
|
1420
|
-
*
|
|
1421
|
-
* @example
|
|
1422
|
-
* provider = provider && provider();
|
|
1423
|
-
*
|
|
1424
|
-
* @see GlobeSurfaceTileProvider#isDestroyed
|
|
1425
|
-
*/
|
|
1426
|
-
GlobeSurfaceTileProvider.prototype.destroy = function () {
|
|
1427
|
-
this._tileProvider = this._tileProvider && this._tileProvider.destroy();
|
|
1428
|
-
this._clippingPlanes = this._clippingPlanes && this._clippingPlanes.destroy();
|
|
1429
|
-
this._clippingPolygons =
|
|
1430
|
-
this._clippingPolygons && this._clippingPolygons.destroy();
|
|
1431
|
-
this._removeLayerAddedListener =
|
|
1432
|
-
this._removeLayerAddedListener && this._removeLayerAddedListener();
|
|
1433
|
-
this._removeLayerRemovedListener =
|
|
1434
|
-
this._removeLayerRemovedListener && this._removeLayerRemovedListener();
|
|
1435
|
-
this._removeLayerMovedListener =
|
|
1436
|
-
this._removeLayerMovedListener && this._removeLayerMovedListener();
|
|
1437
|
-
this._removeLayerShownListener =
|
|
1438
|
-
this._removeLayerShownListener && this._removeLayerShownListener();
|
|
1439
|
-
|
|
1440
|
-
return destroyObject(this);
|
|
1441
|
-
};
|
|
1442
|
-
|
|
1443
1649
|
function getTileReadyCallback(tileImageriesToFree, layer, terrainProvider) {
|
|
1444
1650
|
return function (tile) {
|
|
1445
1651
|
let tileImagery;
|
|
@@ -1484,165 +1690,14 @@ function getTileReadyCallback(tileImageriesToFree, layer, terrainProvider) {
|
|
|
1484
1690
|
};
|
|
1485
1691
|
}
|
|
1486
1692
|
|
|
1487
|
-
GlobeSurfaceTileProvider.prototype._onLayerAdded = function (layer, index) {
|
|
1488
|
-
if (this.isDestroyed()) {
|
|
1489
|
-
return;
|
|
1490
|
-
}
|
|
1491
|
-
|
|
1492
|
-
if (layer.show) {
|
|
1493
|
-
const terrainProvider = this._terrainProvider;
|
|
1494
|
-
|
|
1495
|
-
const that = this;
|
|
1496
|
-
const tileImageryUpdatedEvent = this._imageryLayersUpdatedEvent;
|
|
1497
|
-
const reloadFunction = function () {
|
|
1498
|
-
// Clear the layer's cache
|
|
1499
|
-
layer._imageryCache = {};
|
|
1500
|
-
|
|
1501
|
-
that._quadtree.forEachLoadedTile(function (tile) {
|
|
1502
|
-
// If this layer is still waiting to for the loaded callback, just return
|
|
1503
|
-
if (defined(tile._loadedCallbacks[layer._layerIndex])) {
|
|
1504
|
-
return;
|
|
1505
|
-
}
|
|
1506
|
-
|
|
1507
|
-
let i;
|
|
1508
|
-
|
|
1509
|
-
// Figure out how many TileImageries we will need to remove and where to insert new ones
|
|
1510
|
-
const tileImageryCollection = tile.data.imagery;
|
|
1511
|
-
const length = tileImageryCollection.length;
|
|
1512
|
-
let startIndex = -1;
|
|
1513
|
-
let tileImageriesToFree = 0;
|
|
1514
|
-
for (i = 0; i < length; ++i) {
|
|
1515
|
-
const tileImagery = tileImageryCollection[i];
|
|
1516
|
-
const imagery =
|
|
1517
|
-
tileImagery.readyImagery ?? tileImagery.loadingImagery;
|
|
1518
|
-
if (imagery.imageryLayer === layer) {
|
|
1519
|
-
if (startIndex === -1) {
|
|
1520
|
-
startIndex = i;
|
|
1521
|
-
}
|
|
1522
|
-
|
|
1523
|
-
++tileImageriesToFree;
|
|
1524
|
-
} else if (startIndex !== -1) {
|
|
1525
|
-
// iterated past the section of TileImageries belonging to this layer, no need to continue.
|
|
1526
|
-
break;
|
|
1527
|
-
}
|
|
1528
|
-
}
|
|
1529
|
-
|
|
1530
|
-
if (startIndex === -1) {
|
|
1531
|
-
return;
|
|
1532
|
-
}
|
|
1533
|
-
|
|
1534
|
-
// Insert immediately after existing TileImageries
|
|
1535
|
-
const insertionPoint = startIndex + tileImageriesToFree;
|
|
1536
|
-
|
|
1537
|
-
// Create new TileImageries for all loaded tiles
|
|
1538
|
-
if (
|
|
1539
|
-
layer._createTileImagerySkeletons(
|
|
1540
|
-
tile,
|
|
1541
|
-
terrainProvider,
|
|
1542
|
-
insertionPoint,
|
|
1543
|
-
)
|
|
1544
|
-
) {
|
|
1545
|
-
// Add callback to remove old TileImageries when the new TileImageries are ready
|
|
1546
|
-
tile._loadedCallbacks[layer._layerIndex] = getTileReadyCallback(
|
|
1547
|
-
tileImageriesToFree,
|
|
1548
|
-
layer,
|
|
1549
|
-
terrainProvider,
|
|
1550
|
-
);
|
|
1551
|
-
|
|
1552
|
-
tile.state = QuadtreeTileLoadState.LOADING;
|
|
1553
|
-
}
|
|
1554
|
-
});
|
|
1555
|
-
};
|
|
1556
|
-
|
|
1557
|
-
if (layer.ready) {
|
|
1558
|
-
const imageryProvider = layer.imageryProvider;
|
|
1559
|
-
imageryProvider._reload = reloadFunction;
|
|
1560
|
-
}
|
|
1561
|
-
|
|
1562
|
-
// create TileImageries for this layer for all previously loaded tiles
|
|
1563
|
-
this._quadtree.forEachLoadedTile(function (tile) {
|
|
1564
|
-
if (layer._createTileImagerySkeletons(tile, terrainProvider)) {
|
|
1565
|
-
tile.state = QuadtreeTileLoadState.LOADING;
|
|
1566
|
-
|
|
1567
|
-
// Tiles that are not currently being rendered need to load the new layer before they're renderable.
|
|
1568
|
-
// We don't mark the rendered tiles non-renderable, though, because that would make the globe disappear.
|
|
1569
|
-
if (
|
|
1570
|
-
tile.level !== 0 &&
|
|
1571
|
-
(tile._lastSelectionResultFrame !==
|
|
1572
|
-
that.quadtree._lastSelectionFrameNumber ||
|
|
1573
|
-
tile._lastSelectionResult !== TileSelectionResult.RENDERED)
|
|
1574
|
-
) {
|
|
1575
|
-
tile.renderable = false;
|
|
1576
|
-
}
|
|
1577
|
-
}
|
|
1578
|
-
});
|
|
1579
|
-
|
|
1580
|
-
this._layerOrderChanged = true;
|
|
1581
|
-
tileImageryUpdatedEvent.raiseEvent();
|
|
1582
|
-
}
|
|
1583
|
-
};
|
|
1584
|
-
|
|
1585
|
-
GlobeSurfaceTileProvider.prototype._onLayerRemoved = function (layer, index) {
|
|
1586
|
-
// destroy TileImagerys for this layer for all previously loaded tiles
|
|
1587
|
-
this._quadtree.forEachLoadedTile(function (tile) {
|
|
1588
|
-
const tileImageryCollection = tile.data.imagery;
|
|
1589
|
-
|
|
1590
|
-
let startIndex = -1;
|
|
1591
|
-
let numDestroyed = 0;
|
|
1592
|
-
for (let i = 0, len = tileImageryCollection.length; i < len; ++i) {
|
|
1593
|
-
const tileImagery = tileImageryCollection[i];
|
|
1594
|
-
let imagery = tileImagery.loadingImagery;
|
|
1595
|
-
if (!defined(imagery)) {
|
|
1596
|
-
imagery = tileImagery.readyImagery;
|
|
1597
|
-
}
|
|
1598
|
-
if (imagery.imageryLayer === layer) {
|
|
1599
|
-
if (startIndex === -1) {
|
|
1600
|
-
startIndex = i;
|
|
1601
|
-
}
|
|
1602
|
-
|
|
1603
|
-
tileImagery.freeResources();
|
|
1604
|
-
++numDestroyed;
|
|
1605
|
-
} else if (startIndex !== -1) {
|
|
1606
|
-
// iterated past the section of TileImagerys belonging to this layer, no need to continue.
|
|
1607
|
-
break;
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
|
|
1611
|
-
if (startIndex !== -1) {
|
|
1612
|
-
tileImageryCollection.splice(startIndex, numDestroyed);
|
|
1613
|
-
}
|
|
1614
|
-
});
|
|
1615
|
-
|
|
1616
|
-
if (defined(layer.imageryProvider)) {
|
|
1617
|
-
layer.imageryProvider._reload = undefined;
|
|
1618
|
-
}
|
|
1619
|
-
|
|
1620
|
-
this._imageryLayersUpdatedEvent.raiseEvent();
|
|
1621
|
-
};
|
|
1622
|
-
|
|
1623
|
-
GlobeSurfaceTileProvider.prototype._onLayerMoved = function (
|
|
1624
|
-
layer,
|
|
1625
|
-
newIndex,
|
|
1626
|
-
oldIndex,
|
|
1627
|
-
) {
|
|
1628
|
-
this._layerOrderChanged = true;
|
|
1629
|
-
this._imageryLayersUpdatedEvent.raiseEvent();
|
|
1630
|
-
};
|
|
1631
|
-
|
|
1632
|
-
GlobeSurfaceTileProvider.prototype._onLayerShownOrHidden = function (
|
|
1633
|
-
layer,
|
|
1634
|
-
index,
|
|
1635
|
-
show,
|
|
1636
|
-
) {
|
|
1637
|
-
if (show) {
|
|
1638
|
-
this._onLayerAdded(layer, index);
|
|
1639
|
-
} else {
|
|
1640
|
-
this._onLayerRemoved(layer, index);
|
|
1641
|
-
}
|
|
1642
|
-
};
|
|
1643
|
-
|
|
1644
1693
|
const scratchClippingPlanesMatrix = new Matrix4();
|
|
1645
1694
|
const scratchInverseTransposeClippingPlanesMatrix = new Matrix4();
|
|
1695
|
+
|
|
1696
|
+
/**
|
|
1697
|
+
* @param {FrameState} frameState
|
|
1698
|
+
* @param {GlobeSurfaceTileProvider} globeSurfaceTileProvider
|
|
1699
|
+
* @ignore
|
|
1700
|
+
*/
|
|
1646
1701
|
function createTileUniformMap(frameState, globeSurfaceTileProvider) {
|
|
1647
1702
|
const uniformMap = {
|
|
1648
1703
|
u_initialColor: function () {
|
|
@@ -1823,6 +1878,7 @@ function createTileUniformMap(frameState, globeSurfaceTileProvider) {
|
|
|
1823
1878
|
return frameState.context.defaultTexture;
|
|
1824
1879
|
},
|
|
1825
1880
|
u_clippingExtents: function () {
|
|
1881
|
+
// @ts-expect-error Missing types.
|
|
1826
1882
|
const texture = globeSurfaceTileProvider._clippingPolygons.extentsTexture;
|
|
1827
1883
|
if (defined(texture)) {
|
|
1828
1884
|
return texture;
|
|
@@ -1931,8 +1987,13 @@ function createTileUniformMap(frameState, globeSurfaceTileProvider) {
|
|
|
1931
1987
|
return uniformMap;
|
|
1932
1988
|
}
|
|
1933
1989
|
|
|
1934
|
-
|
|
1935
|
-
|
|
1990
|
+
/**
|
|
1991
|
+
* @param {Context} context
|
|
1992
|
+
* @param {QuadtreeTile} tile
|
|
1993
|
+
* @ignore
|
|
1994
|
+
*/
|
|
1995
|
+
function createWireframeVertexArrayIfNecessary(context, tile) {
|
|
1996
|
+
const surfaceTile = /** @type {GlobeSurfaceTile} */ (tile.data);
|
|
1936
1997
|
|
|
1937
1998
|
let mesh;
|
|
1938
1999
|
let vertexArray;
|
|
@@ -2006,8 +2067,22 @@ function createWireframeVertexArray(context, vertexArray, terrainMesh) {
|
|
|
2006
2067
|
});
|
|
2007
2068
|
}
|
|
2008
2069
|
|
|
2070
|
+
/**
|
|
2071
|
+
* @type {Function}
|
|
2072
|
+
* @ignore
|
|
2073
|
+
*/
|
|
2009
2074
|
let getDebugOrientedBoundingBox;
|
|
2075
|
+
|
|
2076
|
+
/**
|
|
2077
|
+
* @type {Function}
|
|
2078
|
+
* @ignore
|
|
2079
|
+
*/
|
|
2010
2080
|
let getDebugBoundingSphere;
|
|
2081
|
+
|
|
2082
|
+
/**
|
|
2083
|
+
* @type {VoidFunction}
|
|
2084
|
+
* @ignore
|
|
2085
|
+
*/
|
|
2011
2086
|
let debugDestroyPrimitive;
|
|
2012
2087
|
|
|
2013
2088
|
(function () {
|
|
@@ -2020,9 +2095,15 @@ let debugDestroyPrimitive;
|
|
|
2020
2095
|
geometry: new SphereOutlineGeometry({ radius: 1.0 }),
|
|
2021
2096
|
});
|
|
2022
2097
|
let modelMatrix = new Matrix4();
|
|
2098
|
+
/** @type {OrientedBoundingBox|BoundingSphere} */
|
|
2023
2099
|
let previousVolume;
|
|
2100
|
+
/** @type {Primitive} */
|
|
2024
2101
|
let primitive;
|
|
2025
2102
|
|
|
2103
|
+
/**
|
|
2104
|
+
* @param {unknown} instance
|
|
2105
|
+
* @returns {Primitive}
|
|
2106
|
+
*/
|
|
2026
2107
|
function createDebugPrimitive(instance) {
|
|
2027
2108
|
return new Primitive({
|
|
2028
2109
|
geometryInstances: instance,
|
|
@@ -2034,6 +2115,10 @@ let debugDestroyPrimitive;
|
|
|
2034
2115
|
});
|
|
2035
2116
|
}
|
|
2036
2117
|
|
|
2118
|
+
/**
|
|
2119
|
+
* @param {OrientedBoundingBox} obb
|
|
2120
|
+
* @param {Color} color
|
|
2121
|
+
*/
|
|
2037
2122
|
getDebugOrientedBoundingBox = function (obb, color) {
|
|
2038
2123
|
if (obb === previousVolume) {
|
|
2039
2124
|
return primitive;
|
|
@@ -2048,6 +2133,7 @@ let debugDestroyPrimitive;
|
|
|
2048
2133
|
);
|
|
2049
2134
|
|
|
2050
2135
|
instanceOBB.modelMatrix = modelMatrix;
|
|
2136
|
+
// @ts-expect-error Missing types.
|
|
2051
2137
|
instanceOBB.attributes.color =
|
|
2052
2138
|
ColorGeometryInstanceAttribute.fromColor(color);
|
|
2053
2139
|
|
|
@@ -2055,6 +2141,11 @@ let debugDestroyPrimitive;
|
|
|
2055
2141
|
return primitive;
|
|
2056
2142
|
};
|
|
2057
2143
|
|
|
2144
|
+
/**
|
|
2145
|
+
* @param {BoundingSphere} sphere
|
|
2146
|
+
* @param {Color} color
|
|
2147
|
+
* @returns {Primitive}
|
|
2148
|
+
*/
|
|
2058
2149
|
getDebugBoundingSphere = function (sphere, color) {
|
|
2059
2150
|
if (sphere === previousVolume) {
|
|
2060
2151
|
return primitive;
|
|
@@ -2070,6 +2161,7 @@ let debugDestroyPrimitive;
|
|
|
2070
2161
|
);
|
|
2071
2162
|
|
|
2072
2163
|
instanceSphere.modelMatrix = modelMatrix;
|
|
2164
|
+
// @ts-expect-error Missing types.
|
|
2073
2165
|
instanceSphere.attributes.color =
|
|
2074
2166
|
ColorGeometryInstanceAttribute.fromColor(color);
|
|
2075
2167
|
|
|
@@ -2087,6 +2179,11 @@ let debugDestroyPrimitive;
|
|
|
2087
2179
|
})();
|
|
2088
2180
|
|
|
2089
2181
|
const otherPassesInitialColor = new Cartesian4(0.0, 0.0, 0.0, 0.0);
|
|
2182
|
+
|
|
2183
|
+
/**
|
|
2184
|
+
* @type {GlobeSurfaceShaderSetOptions}
|
|
2185
|
+
* @ignore
|
|
2186
|
+
*/
|
|
2090
2187
|
const surfaceShaderSetOptionsScratch = {
|
|
2091
2188
|
frameState: undefined,
|
|
2092
2189
|
surfaceTile: undefined,
|
|
@@ -2124,8 +2221,14 @@ const surfaceShaderSetOptionsScratch = {
|
|
|
2124
2221
|
const defaultUndergroundColor = Color.TRANSPARENT;
|
|
2125
2222
|
const defaultUndergroundColorAlphaByDistance = new NearFarScalar();
|
|
2126
2223
|
|
|
2224
|
+
/**
|
|
2225
|
+
* @param {GlobeSurfaceTileProvider} tileProvider
|
|
2226
|
+
* @param {QuadtreeTile} tile
|
|
2227
|
+
* @param {FrameState} frameState
|
|
2228
|
+
* @ignore
|
|
2229
|
+
*/
|
|
2127
2230
|
function addDrawCommandsForTile(tileProvider, tile, frameState) {
|
|
2128
|
-
const surfaceTile = tile.data;
|
|
2231
|
+
const surfaceTile = /** @type {GlobeSurfaceTile} */ (tile.data);
|
|
2129
2232
|
|
|
2130
2233
|
if (!defined(surfaceTile.vertexArray)) {
|
|
2131
2234
|
if (surfaceTile.fill === undefined) {
|
|
@@ -2151,6 +2254,7 @@ function addDrawCommandsForTile(tileProvider, tile, frameState) {
|
|
|
2151
2254
|
}
|
|
2152
2255
|
}
|
|
2153
2256
|
|
|
2257
|
+
// @ts-expect-error Missing types.
|
|
2154
2258
|
let maxTextures = ContextLimits.maximumTextureImageUnits;
|
|
2155
2259
|
|
|
2156
2260
|
let waterMaskTexture = surfaceTile.waterMaskTexture;
|
|
@@ -2192,14 +2296,17 @@ function addDrawCommandsForTile(tileProvider, tile, frameState) {
|
|
|
2192
2296
|
const showOceanWaves = showReflectiveOcean && defined(oceanNormalMap);
|
|
2193
2297
|
const terrainProvider = tileProvider.terrainProvider;
|
|
2194
2298
|
const hasVertexNormals =
|
|
2299
|
+
// @ts-expect-error Missing types.
|
|
2195
2300
|
defined(terrainProvider) && tileProvider.terrainProvider.hasVertexNormals;
|
|
2196
2301
|
const enableFog =
|
|
2197
2302
|
frameState.fog.enabled && frameState.fog.renderable && !cameraUnderground;
|
|
2198
2303
|
const showGroundAtmosphere =
|
|
2199
2304
|
tileProvider.showGroundAtmosphere && frameState.mode === SceneMode.SCENE3D;
|
|
2200
2305
|
const castShadows =
|
|
2306
|
+
// @ts-expect-error https://github.com/CesiumGS/cesium/issues/13420
|
|
2201
2307
|
ShadowMode.castShadows(tileProvider.shadows) && !translucent;
|
|
2202
2308
|
const receiveShadows =
|
|
2309
|
+
// @ts-expect-error https://github.com/CesiumGS/cesium/issues/13420
|
|
2203
2310
|
ShadowMode.receiveShadows(tileProvider.shadows) && !translucent;
|
|
2204
2311
|
|
|
2205
2312
|
const hueShift = tileProvider.hueShift;
|
|
@@ -2233,6 +2340,7 @@ function addDrawCommandsForTile(tileProvider, tile, frameState) {
|
|
|
2233
2340
|
}
|
|
2234
2341
|
if (
|
|
2235
2342
|
defined(tileProvider.clippingPlanes) &&
|
|
2343
|
+
// @ts-expect-error Missing types.
|
|
2236
2344
|
tileProvider.clippingPlanes.enabled
|
|
2237
2345
|
) {
|
|
2238
2346
|
--maxTextures;
|
|
@@ -2426,7 +2534,9 @@ function addDrawCommandsForTile(tileProvider, tile, frameState) {
|
|
|
2426
2534
|
++tileProvider._usedDrawCommands;
|
|
2427
2535
|
|
|
2428
2536
|
if (tile === tileProvider._debug.boundingSphereTile) {
|
|
2537
|
+
// @ts-expect-error Missing types.
|
|
2429
2538
|
const obb = tileBoundingRegion.boundingVolume;
|
|
2539
|
+
// @ts-expect-error Missing types.
|
|
2430
2540
|
const boundingSphere = tileBoundingRegion.boundingSphere;
|
|
2431
2541
|
// If a debug primitive already exists for this tile, it will not be
|
|
2432
2542
|
// re-created, to avoid allocation every frame. If it were possible
|
|
@@ -2851,7 +2961,7 @@ function addDrawCommandsForTile(tileProvider, tile, frameState) {
|
|
|
2851
2961
|
command.pass = Pass.GLOBE;
|
|
2852
2962
|
|
|
2853
2963
|
if (tileProvider._debug.wireframe) {
|
|
2854
|
-
createWireframeVertexArrayIfNecessary(context,
|
|
2964
|
+
createWireframeVertexArrayIfNecessary(context, tile);
|
|
2855
2965
|
if (defined(surfaceTile.wireframeVertexArray)) {
|
|
2856
2966
|
command.vertexArray = surfaceTile.wireframeVertexArray;
|
|
2857
2967
|
command.primitiveType = PrimitiveType.LINES;
|
|
@@ -2879,6 +2989,7 @@ function addDrawCommandsForTile(tileProvider, tile, frameState) {
|
|
|
2879
2989
|
|
|
2880
2990
|
if (frameState.mode === SceneMode.MORPHING) {
|
|
2881
2991
|
boundingVolume = BoundingSphere.union(
|
|
2992
|
+
// @ts-expect-error Missing types.
|
|
2882
2993
|
tileBoundingRegion.boundingSphere,
|
|
2883
2994
|
boundingVolume,
|
|
2884
2995
|
boundingVolume,
|
|
@@ -2886,10 +2997,12 @@ function addDrawCommandsForTile(tileProvider, tile, frameState) {
|
|
|
2886
2997
|
}
|
|
2887
2998
|
} else {
|
|
2888
2999
|
command.boundingVolume = BoundingSphere.clone(
|
|
3000
|
+
// @ts-expect-error Missing types.
|
|
2889
3001
|
tileBoundingRegion.boundingSphere,
|
|
2890
3002
|
boundingVolume,
|
|
2891
3003
|
);
|
|
2892
3004
|
command.orientedBoundingBox = OrientedBoundingBox.clone(
|
|
3005
|
+
// @ts-expect-error Missing types.
|
|
2893
3006
|
tileBoundingRegion.boundingVolume,
|
|
2894
3007
|
orientedBoundingBox,
|
|
2895
3008
|
);
|