@cesium/engine 17.0.0 → 18.0.1-splats.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/ThirdParty/Workers/z-worker-pako.js +1 -1
- package/Build/Workers/{chunk-UC7KH56Y.js → chunk-2AXKROJA.js} +5 -5
- package/Build/Workers/{chunk-IKDQX7DY.js → chunk-2J5ZZ7CY.js} +4 -4
- package/Build/Workers/{chunk-4TIR5UPL.js → chunk-2SYY3UBI.js} +1 -1
- package/Build/Workers/{chunk-CC2WKHIW.js → chunk-2WKW3BEB.js} +6 -6
- package/Build/Workers/{chunk-CBFJVM6I.js → chunk-2ZO6BCHN.js} +11 -11
- package/Build/Workers/{chunk-7PHT4JHA.js → chunk-3UKG5X7F.js} +12 -12
- package/Build/Workers/{chunk-PM4Q36WX.js → chunk-4GYIDPXP.js} +9 -9
- package/Build/Workers/{chunk-QUFN3GEO.js → chunk-6EP7ED36.js} +3 -3
- package/Build/Workers/{chunk-QJTIOB2Z.js → chunk-6QOBORNG.js} +6 -6
- package/Build/Workers/{chunk-YE6MDFDA.js → chunk-6WWHK2ER.js} +14 -14
- package/Build/Workers/{chunk-RX65FA7X.js → chunk-6Y6TVYHS.js} +7 -7
- package/Build/Workers/{chunk-P2N5IDWU.js → chunk-744VWE2U.js} +13 -13
- package/Build/Workers/{chunk-LVGYWPEX.js → chunk-7PQ52XCW.js} +4 -4
- package/Build/Workers/{chunk-PS3OKVOQ.js → chunk-A5UFJW2M.js} +12 -12
- package/Build/Workers/{chunk-CAKU6ZPR.js → chunk-AQKVFTWV.js} +8 -8
- package/Build/Workers/{chunk-236N6BJN.js → chunk-BKTEHJFD.js} +2 -2
- package/Build/Workers/{chunk-5PC577K7.js → chunk-CQXYKPAW.js} +16 -16
- package/Build/Workers/{chunk-DRMXU674.js → chunk-DI7PHKC6.js} +5 -5
- package/Build/Workers/{chunk-CQMXZF4A.js → chunk-DKKIQS6F.js} +6 -6
- package/Build/Workers/{chunk-J2HTPGC7.js → chunk-DTVWE5YL.js} +2 -2
- package/Build/Workers/{chunk-SSLK4U3V.js → chunk-ERPS2WZC.js} +4 -4
- package/Build/Workers/chunk-EYMZ5FSQ.js +280 -0
- package/Build/Workers/{chunk-LPGOAMYH.js → chunk-F43TQW5B.js} +2 -2
- package/Build/Workers/{chunk-5RPUEFSA.js → chunk-FOMRN6II.js} +6 -6
- package/Build/Workers/{chunk-2BJXFXD7.js → chunk-FOTXJYKS.js} +4 -4
- package/Build/Workers/{chunk-VXAKU6EV.js → chunk-G2Y7EA4W.js} +5 -5
- package/Build/Workers/{chunk-KE45DUDH.js → chunk-GY4E4ZP6.js} +10 -10
- package/Build/Workers/{chunk-NZSBSY5K.js → chunk-HDG3VHYL.js} +2 -2
- package/Build/Workers/{chunk-WP3IJYLC.js → chunk-HOEUXPBL.js} +9 -9
- package/Build/Workers/{chunk-5YEFZMMM.js → chunk-IWDYVJ56.js} +12 -12
- package/Build/Workers/{chunk-SQKTLDSD.js → chunk-JA4KPQJL.js} +12 -12
- package/Build/Workers/{chunk-MAIKDIBS.js → chunk-JZZQEZMA.js} +6 -6
- package/Build/Workers/{chunk-77MDEA47.js → chunk-KPLU3WDY.js} +5 -5
- package/Build/Workers/{chunk-E7SMO47Q.js → chunk-LHM6V4D6.js} +5 -5
- package/Build/Workers/{chunk-HBNWBMAM.js → chunk-LMTGCD6P.js} +1 -1
- package/Build/Workers/{chunk-XYGBWBD5.js → chunk-LWZOYSSF.js} +1 -1
- package/Build/Workers/{chunk-OBHLT34A.js → chunk-M6U7SV4T.js} +7 -7
- package/Build/Workers/{chunk-MS5NWDHH.js → chunk-O25M56DO.js} +2 -2
- package/Build/Workers/{chunk-UX5JWAC7.js → chunk-OE2WXO2Z.js} +10 -10
- package/Build/Workers/{chunk-C5DCX2YQ.js → chunk-PFD462OE.js} +6 -6
- package/Build/Workers/{chunk-37PA7GZW.js → chunk-PPI33PXH.js} +7 -7
- package/Build/Workers/{chunk-4BGKMM7J.js → chunk-PRQQHLUB.js} +1 -1
- package/Build/Workers/{chunk-IFIS4CVK.js → chunk-RTUZ7MJB.js} +2 -2
- package/Build/Workers/{chunk-G6JUXZUO.js → chunk-S6QBTP5U.js} +4 -4
- package/Build/Workers/{chunk-UFV3YUIN.js → chunk-SMFCIGM3.js} +5 -5
- package/Build/Workers/{chunk-P57PR3WM.js → chunk-TC3LEKFJ.js} +5 -5
- package/Build/Workers/{chunk-7IIMO7ZZ.js → chunk-UTLYCPFY.js} +16 -16
- package/Build/Workers/{chunk-HGEGZ67N.js → chunk-V7LEBY53.js} +6 -6
- package/Build/Workers/{chunk-GO3RZX2R.js → chunk-VE3UKRDB.js} +9 -9
- package/Build/Workers/{chunk-ZTBZMRQT.js → chunk-W3FBD4FE.js} +8 -8
- package/Build/Workers/{chunk-K5JTWJPE.js → chunk-YRR6CJGG.js} +4 -4
- package/Build/Workers/{chunk-UZ6KXWCA.js → chunk-ZVTKMLU6.js} +4 -4
- package/Build/Workers/combineGeometry.js +21 -21
- package/Build/Workers/createBoxGeometry.js +15 -15
- package/Build/Workers/createBoxOutlineGeometry.js +13 -13
- package/Build/Workers/createCircleGeometry.js +23 -23
- package/Build/Workers/createCircleOutlineGeometry.js +16 -16
- package/Build/Workers/createCoplanarPolygonGeometry.js +30 -30
- package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +28 -28
- package/Build/Workers/createCorridorGeometry.js +26 -26
- package/Build/Workers/createCorridorOutlineGeometry.js +25 -25
- package/Build/Workers/createCylinderGeometry.js +17 -17
- package/Build/Workers/createCylinderOutlineGeometry.js +15 -15
- package/Build/Workers/createEllipseGeometry.js +23 -23
- package/Build/Workers/createEllipseOutlineGeometry.js +16 -16
- package/Build/Workers/createEllipsoidGeometry.js +16 -16
- package/Build/Workers/createEllipsoidOutlineGeometry.js +15 -15
- package/Build/Workers/createFrustumGeometry.js +15 -15
- package/Build/Workers/createFrustumOutlineGeometry.js +15 -15
- package/Build/Workers/createGeometry.js +23 -21
- package/Build/Workers/createGroundPolylineGeometry.js +19 -19
- package/Build/Workers/createPlaneGeometry.js +13 -13
- package/Build/Workers/createPlaneOutlineGeometry.js +12 -12
- package/Build/Workers/createPolygonGeometry.js +29 -29
- package/Build/Workers/createPolygonOutlineGeometry.js +27 -27
- package/Build/Workers/createPolylineGeometry.js +22 -22
- package/Build/Workers/createPolylineVolumeGeometry.js +28 -28
- package/Build/Workers/createPolylineVolumeOutlineGeometry.js +24 -24
- package/Build/Workers/createRectangleGeometry.js +24 -24
- package/Build/Workers/createRectangleOutlineGeometry.js +17 -17
- package/Build/Workers/createSimplePolylineGeometry.js +20 -20
- package/Build/Workers/createSphereGeometry.js +16 -16
- package/Build/Workers/createSphereOutlineGeometry.js +15 -15
- package/Build/Workers/createTaskProcessorWorker.js +3 -3
- package/Build/Workers/createVectorTileClampedPolylines.js +12 -12
- package/Build/Workers/createVectorTileGeometries.js +21 -21
- package/Build/Workers/createVectorTilePoints.js +11 -11
- package/Build/Workers/createVectorTilePolygons.js +19 -19
- package/Build/Workers/createVectorTilePolylines.js +12 -12
- package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +19 -19
- package/Build/Workers/createVerticesFromHeightmap.js +19 -19
- package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +16 -16
- package/Build/Workers/createWallGeometry.js +21 -21
- package/Build/Workers/createWallOutlineGeometry.js +20 -20
- package/Build/Workers/decodeDraco.js +10 -10
- package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
- package/Build/Workers/decodeI3S.js +9 -9
- package/Build/Workers/gaussianSplatSorter.js +62 -0
- package/Build/Workers/gaussianSplatTextureGenerator.js +68 -0
- package/Build/Workers/transcodeKTX2.js +78 -7
- package/Build/Workers/transferTypedArrayTest.js +1 -1
- package/Build/Workers/upsampleQuantizedTerrainMesh.js +19 -19
- package/Source/Core/Ion.js +1 -1
- package/Source/Core/PixelFormat.js +98 -0
- package/Source/Renderer/Context.js +2 -0
- package/Source/Renderer/Pass.js +3 -2
- package/Source/Renderer/Texture.js +1 -0
- package/Source/Renderer/Texture3D.js +568 -0
- package/Source/Renderer/VertexArray.js +33 -8
- package/Source/Renderer/createUniform.js +3 -0
- package/Source/Renderer/createUniformArray.js +1 -0
- package/Source/Scene/ArcGisMapService.js +1 -1
- package/Source/Scene/Cesium3DTileContentFactory.js +23 -0
- package/Source/Scene/Cesium3DTileset.js +197 -2
- package/Source/Scene/GaussianSplat3DTileContent.js +504 -0
- package/Source/Scene/GaussianSplatPrimitive.js +932 -0
- package/Source/Scene/GaussianSplatRenderResources.js +81 -0
- package/Source/Scene/GaussianSplatSorter.js +73 -0
- package/Source/Scene/GaussianSplatTextureGenerator.js +64 -0
- package/Source/Scene/GlobeSurfaceShaderSet.js +4 -5
- package/Source/Scene/GltfLoader.js +82 -4
- package/Source/Scene/GltfSpzLoader.js +222 -0
- package/Source/Scene/GltfVertexBufferLoader.js +98 -3
- package/Source/Scene/ImageryLayer.js +19 -4
- package/Source/Scene/ImageryLayerCollection.js +3 -2
- package/Source/Scene/Model/CartesianRectangle.js +108 -0
- package/Source/Scene/Model/ImageryConfiguration.js +25 -0
- package/Source/Scene/Model/ImageryCoverage.js +488 -0
- package/Source/Scene/Model/ImageryFlags.js +31 -0
- package/Source/Scene/Model/ImageryInput.js +60 -0
- package/Source/Scene/Model/ImageryPipelineStage.js +1040 -0
- package/Source/Scene/Model/MappedPositions.js +84 -0
- package/Source/Scene/Model/Model.js +38 -0
- package/Source/Scene/Model/ModelImagery.js +403 -0
- package/Source/Scene/Model/ModelImageryMapping.js +489 -0
- package/Source/Scene/Model/ModelPrimitiveImagery.js +972 -0
- package/Source/Scene/Model/ModelReader.js +810 -0
- package/Source/Scene/Model/ModelRenderResources.js +13 -0
- package/Source/Scene/Model/ModelRuntimePrimitive.js +20 -0
- package/Source/Scene/Model/ModelSceneGraph.js +133 -27
- package/Source/Scene/Model/ModelUtility.js +2 -0
- package/Source/Scene/Model/NodeRenderResources.js +10 -0
- package/Source/Scene/ModelComponents.js +10 -0
- package/Source/Scene/PrimitiveLoadPlan.js +59 -0
- package/Source/Scene/ResourceCache.js +60 -3
- package/Source/Scene/ResourceCacheKey.js +39 -1
- package/Source/Scene/Scene.js +32 -1
- package/Source/Scene/VertexAttributeSemantic.js +30 -0
- package/Source/Scene/VoxelPrimitive.js +22 -37
- package/Source/Scene/VoxelRenderResources.js +1 -1
- package/Source/Scene/processVoxelProperties.js +41 -100
- package/Source/Shaders/Builtin/Constants/passGaussianSplats.glsl +9 -0
- package/Source/Shaders/Builtin/Constants/passGaussianSplats.js +11 -0
- package/Source/Shaders/Builtin/Constants/passOverlay.glsl +1 -1
- package/Source/Shaders/Builtin/Constants/passOverlay.js +1 -1
- package/Source/Shaders/Builtin/CzmBuiltins.js +2 -0
- package/Source/Shaders/Builtin/Functions/windowToEyeCoordinates.glsl +0 -1
- package/Source/Shaders/Builtin/Functions/windowToEyeCoordinates.js +0 -1
- package/Source/Shaders/GlobeFS.glsl +22 -0
- package/Source/Shaders/GlobeFS.js +22 -0
- package/Source/Shaders/Model/MaterialStageFS.glsl +4 -0
- package/Source/Shaders/Model/MaterialStageFS.js +4 -0
- package/Source/Shaders/Model/ModelFS.glsl +3 -1
- package/Source/Shaders/Model/ModelFS.js +3 -1
- package/Source/Shaders/Model/ModelVS.glsl +5 -1
- package/Source/Shaders/Model/ModelVS.js +5 -1
- package/Source/Shaders/Model/PointCloudStylingStageVS.glsl +1 -1
- package/Source/Shaders/Model/PointCloudStylingStageVS.js +2 -1
- package/Source/Shaders/PrimitiveGaussianSplatFS.glsl +18 -0
- package/Source/Shaders/PrimitiveGaussianSplatFS.js +20 -0
- package/Source/Shaders/PrimitiveGaussianSplatVS.glsl +108 -0
- package/Source/Shaders/PrimitiveGaussianSplatVS.js +109 -0
- package/Source/Shaders/Voxels/IntersectDepth.glsl +10 -3
- package/Source/Shaders/Voxels/IntersectDepth.js +10 -3
- package/Source/Shaders/Voxels/Intersection.glsl +1 -3
- package/Source/Shaders/Voxels/Intersection.js +1 -3
- package/Source/Shaders/Voxels/IntersectionUtils.glsl +1 -0
- package/Source/Shaders/Voxels/IntersectionUtils.js +1 -0
- package/Source/Shaders/Voxels/VoxelFS.glsl +37 -24
- package/Source/Shaders/Voxels/VoxelFS.js +37 -24
- package/Source/ThirdParty/Workers/z-worker-pako.js +1 -1
- package/Source/ThirdParty/wasm_splats_bg.wasm +0 -0
- package/Source/Workers/gaussianSplatSorter.js +34 -0
- package/Source/Workers/gaussianSplatTextureGenerator.js +39 -0
- package/index.d.ts +66 -2
- package/index.js +101 -80
- package/package.json +6 -4
|
@@ -0,0 +1,972 @@
|
|
|
1
|
+
import defined from "../../Core/defined.js";
|
|
2
|
+
import DeveloperError from "../../Core/DeveloperError.js";
|
|
3
|
+
import Matrix4 from "../../Core/Matrix4.js";
|
|
4
|
+
import Check from "../../Core/Check.js";
|
|
5
|
+
import destroyObject from "../../Core/destroyObject.js";
|
|
6
|
+
|
|
7
|
+
import ImageryState from "../ImageryState.js";
|
|
8
|
+
import ImageryCoverage from "./ImageryCoverage.js";
|
|
9
|
+
import ModelImageryMapping from "./ModelImageryMapping.js";
|
|
10
|
+
import ModelUtility from "./ModelUtility.js";
|
|
11
|
+
import MappedPositions from "./MappedPositions.js";
|
|
12
|
+
|
|
13
|
+
import Buffer from "../../Renderer/Buffer.js";
|
|
14
|
+
import BufferUsage from "../../Renderer/BufferUsage.js";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A class managing the draping of imagery on a single model primitive.
|
|
18
|
+
*
|
|
19
|
+
* The <code>ModelImagery</code> class creates one instance of this
|
|
20
|
+
* class for each primitive that appears in the model.
|
|
21
|
+
*
|
|
22
|
+
* It is responsible for computing
|
|
23
|
+
* - the mapped (cartographic) positions of the primitive
|
|
24
|
+
* - the imagery tiles that are covered by these mapped positions
|
|
25
|
+
* - the texture coordinates (attributes) that correspond to these mapped positions
|
|
26
|
+
*
|
|
27
|
+
* @private
|
|
28
|
+
*/
|
|
29
|
+
class ModelPrimitiveImagery {
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new instance
|
|
32
|
+
*
|
|
33
|
+
* @param {Model} model The model
|
|
34
|
+
* @param {ModelRuntimeNode} runtimeNode The node that the primitive is attached to
|
|
35
|
+
* @param {ModelRuntimePrimitive} runtimePrimitive The primitive
|
|
36
|
+
* @throws {DeveloperError} If any argument is not defined
|
|
37
|
+
*/
|
|
38
|
+
constructor(model, runtimeNode, runtimePrimitive) {
|
|
39
|
+
//>>includeStart('debug', pragmas.debug);
|
|
40
|
+
Check.defined("model", model);
|
|
41
|
+
Check.defined("runtimeNode", runtimeNode);
|
|
42
|
+
Check.defined("runtimePrimitive", runtimePrimitive);
|
|
43
|
+
//>>includeEnd('debug');
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The model that this instance was created for.
|
|
47
|
+
*
|
|
48
|
+
* @type {Model}
|
|
49
|
+
* @readonly
|
|
50
|
+
* @private
|
|
51
|
+
*/
|
|
52
|
+
this._model = model;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The node that the primitive is attached to
|
|
56
|
+
*
|
|
57
|
+
* @type {ModelRuntimeNode}
|
|
58
|
+
* @readonly
|
|
59
|
+
* @private
|
|
60
|
+
*/
|
|
61
|
+
this._runtimeNode = runtimeNode;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The primitive that this instance was created for.
|
|
65
|
+
*
|
|
66
|
+
* @type {ModelRuntimePrimitive}
|
|
67
|
+
* @readonly
|
|
68
|
+
* @private
|
|
69
|
+
*/
|
|
70
|
+
this._runtimePrimitive = runtimePrimitive;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* The <code>MappedPositions</code> objects, one for each ellipsoid
|
|
74
|
+
* of one of the imagery layers
|
|
75
|
+
*
|
|
76
|
+
* These objects are just plain structures that summarize the
|
|
77
|
+
* cartographic positions of the primitive for one specific
|
|
78
|
+
* ellipsoid
|
|
79
|
+
*
|
|
80
|
+
* @type {MappedPositions[]|undefined}
|
|
81
|
+
* @private
|
|
82
|
+
*/
|
|
83
|
+
this._mappedPositionsPerEllipsoid = undefined;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The last <code>model.modelMatrix</code> for which the mapped
|
|
87
|
+
* positions have been computed.
|
|
88
|
+
*
|
|
89
|
+
* This is used for detecting changes in the model matrix that
|
|
90
|
+
* make it necessary to re-compute the mapped positions.
|
|
91
|
+
*
|
|
92
|
+
* @type {Matrix4}
|
|
93
|
+
* @readonly
|
|
94
|
+
* @private
|
|
95
|
+
*/
|
|
96
|
+
this._mappedPositionsModelMatrix = new Matrix4();
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The value that the <code>Cesium3DTileset.imageryLayersModificationCounter</code>
|
|
100
|
+
* had during the last update call. This is used for triggering updates when the
|
|
101
|
+
* imagery layer collection in the tileset changes.
|
|
102
|
+
*/
|
|
103
|
+
this._lastImageryLayersModificationCounter = 0;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The texture coordinate attributes, one for each projection.
|
|
107
|
+
*
|
|
108
|
+
* This contains one <code>ModelComponents.Attribute</code> for each
|
|
109
|
+
* unique projection that is used in the imagery layers. These
|
|
110
|
+
* texture coordinate attributes are computed based on the mapped
|
|
111
|
+
* positions for the respective ellipsoid of that projection.
|
|
112
|
+
*/
|
|
113
|
+
this._imageryTexCoordAttributesPerProjection = undefined;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The current imagery layers.
|
|
117
|
+
*
|
|
118
|
+
* This is initialized when the _coveragesPerLayer are computed,
|
|
119
|
+
* and tracked to that the reference counters of the imageries
|
|
120
|
+
* can be decreased when the coverages per layer are deleted.
|
|
121
|
+
*
|
|
122
|
+
* @type {ImageryLayer[]|undefined}
|
|
123
|
+
* @private
|
|
124
|
+
*/
|
|
125
|
+
this._currentImageryLayers = undefined;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Information about the imagery tiles that are covered by the positions
|
|
129
|
+
* of the primitive.
|
|
130
|
+
*
|
|
131
|
+
* This is computed in the <code>update</code> function, based on the
|
|
132
|
+
* mapped positions of the primitive. After this computation,
|
|
133
|
+
* <code>_coveragesPerLayer[layerIndex]</code> is an array that contains
|
|
134
|
+
* the <code>ImageryCoverage</code> objects that describe the imagery
|
|
135
|
+
* tiles that are covered, including their texture coordinate rectangle.
|
|
136
|
+
*
|
|
137
|
+
* @type {ImageryCoverage[][]|undefined}
|
|
138
|
+
* @private
|
|
139
|
+
*/
|
|
140
|
+
this._coveragesPerLayer = undefined;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* A flag indicating whether all imagery objects that are covered
|
|
144
|
+
* are "ready".
|
|
145
|
+
*
|
|
146
|
+
* This is initially <code>false</code>. During the calls to the
|
|
147
|
+
* <code>update</code> function (which are triggered from the
|
|
148
|
+
* <code>Model.update</code> function, each frame), the
|
|
149
|
+
* <code>_updateImageries</code> function will be called, and
|
|
150
|
+
* process the imagery tiles, until all them them are in a
|
|
151
|
+
* state like <code>ImageryState.READY</code>, at which point
|
|
152
|
+
* this flag is set to <code>true</code>.
|
|
153
|
+
*
|
|
154
|
+
* @type {boolean}
|
|
155
|
+
* @private
|
|
156
|
+
*/
|
|
157
|
+
this._allImageriesReady = false;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Returns the <code>ImageryCoverage</code> array that has been
|
|
162
|
+
* computed for the given imagery layer.
|
|
163
|
+
*
|
|
164
|
+
* This assumes that the given imagery layer is part of the
|
|
165
|
+
* imagery layer collection of the model, and that this
|
|
166
|
+
* model primitive imagery is "ready", meaning that the
|
|
167
|
+
* coverages have already been computed.
|
|
168
|
+
*
|
|
169
|
+
* Clients may <b>not</b> modify the returned array or any
|
|
170
|
+
* of its objects!
|
|
171
|
+
*
|
|
172
|
+
* @param {ImageryLayer} imageryLayer The imagery layer
|
|
173
|
+
* @returns {ImageryCoverage[]} The coverage information
|
|
174
|
+
*/
|
|
175
|
+
coveragesForImageryLayer(imageryLayer) {
|
|
176
|
+
const model = this._model;
|
|
177
|
+
const imageryLayers = model.imageryLayers;
|
|
178
|
+
const index = imageryLayers.indexOf(imageryLayer);
|
|
179
|
+
if (index === -1) {
|
|
180
|
+
throw new DeveloperError("Imagery layer is not part of the model");
|
|
181
|
+
}
|
|
182
|
+
const coveragesPerLayer = this._coveragesPerLayer;
|
|
183
|
+
if (!defined(coveragesPerLayer)) {
|
|
184
|
+
throw new DeveloperError(
|
|
185
|
+
`The coveragesPerLayer have not been computed yet`,
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
return coveragesPerLayer[index];
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Update the state of this instance.
|
|
193
|
+
*
|
|
194
|
+
* This is called as part of <code>ModelImagery.update</code>, which in
|
|
195
|
+
* turn is part of the <code>Model.update</code> that is called in each
|
|
196
|
+
* frame.
|
|
197
|
+
*
|
|
198
|
+
* This will perform the computations that are required to establish
|
|
199
|
+
* the mapping between the imagery and the primitive. It will...
|
|
200
|
+
* <ul>
|
|
201
|
+
* <li>
|
|
202
|
+
* Compute the <code>MappedPositions</code> of the primitive,
|
|
203
|
+
* one instance for each ellipsoid
|
|
204
|
+
* </li>
|
|
205
|
+
* <li>
|
|
206
|
+
* Compute the "coverages per layer", containing the information
|
|
207
|
+
* about which parts of the respective imagery layer are covered
|
|
208
|
+
* by the mapped positions
|
|
209
|
+
* </li>
|
|
210
|
+
* <li>
|
|
211
|
+
* Compute the texture coordinate attributes for the imagery, one
|
|
212
|
+
* for each projection, and store them as the
|
|
213
|
+
* <code>_imageryTexCoordAttributesPerProjection</code>
|
|
214
|
+
* </li>
|
|
215
|
+
* <li>
|
|
216
|
+
* Update the imageries (i.e. processing their state machine by
|
|
217
|
+
* calling <code>Imagery.processStateMachine</code>) until they
|
|
218
|
+
* are in the <code>ImageryState.READY</code> state
|
|
219
|
+
* </li>
|
|
220
|
+
* </ul>
|
|
221
|
+
*
|
|
222
|
+
* @param {FrameState} frameState The frame state
|
|
223
|
+
*/
|
|
224
|
+
update(frameState) {
|
|
225
|
+
//>>includeStart('debug', pragmas.debug);
|
|
226
|
+
Check.defined("frameState", frameState);
|
|
227
|
+
//>>includeEnd('debug');
|
|
228
|
+
|
|
229
|
+
// If the imagery layers have been modified since the last call
|
|
230
|
+
// to this function, then re-build everything
|
|
231
|
+
const model = this._model;
|
|
232
|
+
const content = model.content;
|
|
233
|
+
const tileset = content.tileset;
|
|
234
|
+
const modificationCounter = tileset.imageryLayersModificationCounter;
|
|
235
|
+
if (this._lastImageryLayersModificationCounter !== modificationCounter) {
|
|
236
|
+
delete this._mappedPositionsPerEllipsoid;
|
|
237
|
+
this._lastImageryLayersModificationCounter = modificationCounter;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (this._mappedPositionsNeedUpdate) {
|
|
241
|
+
model.resetDrawCommands();
|
|
242
|
+
this._mappedPositionsPerEllipsoid =
|
|
243
|
+
this._computeMappedPositionsPerEllipsoid();
|
|
244
|
+
this._deleteCoveragesPerLayer();
|
|
245
|
+
this._destroyImageryTexCoordAttributes();
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (!defined(this._imageryTexCoordAttributesPerProjection)) {
|
|
249
|
+
this._imageryTexCoordAttributesPerProjection =
|
|
250
|
+
this._computeImageryTexCoordsAttributesPerProjection();
|
|
251
|
+
this._uploadImageryTexCoordAttributes(frameState.context);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (!defined(this._coveragesPerLayer)) {
|
|
255
|
+
this._computeCoveragesPerLayer();
|
|
256
|
+
this._allImageriesReady = false;
|
|
257
|
+
}
|
|
258
|
+
if (!this._allImageriesReady) {
|
|
259
|
+
this._updateImageries(frameState);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Delete the <code>_coveragesPerLayer</code> if they are defined.
|
|
265
|
+
*
|
|
266
|
+
* This will call <code>deleteCoverages</code> for each set of coverages,
|
|
267
|
+
* and eventually delete the <code>_coveragesPerLayer</code>.
|
|
268
|
+
*
|
|
269
|
+
* This will cause the reference counters of the imageries to be
|
|
270
|
+
* decreased.
|
|
271
|
+
*/
|
|
272
|
+
_deleteCoveragesPerLayer() {
|
|
273
|
+
const coveragesPerLayer = this._coveragesPerLayer;
|
|
274
|
+
if (!defined(coveragesPerLayer)) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
const imageryLayers = this._currentImageryLayers;
|
|
278
|
+
const length = coveragesPerLayer.length;
|
|
279
|
+
for (let i = 0; i < length; i++) {
|
|
280
|
+
const imageryLayer = imageryLayers[i];
|
|
281
|
+
const coverages = coveragesPerLayer[i];
|
|
282
|
+
this._deleteCoverages(imageryLayer, coverages);
|
|
283
|
+
}
|
|
284
|
+
delete this._currentImageryLayers;
|
|
285
|
+
delete this._coveragesPerLayer;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Delete the given imagery coverage objects for the given imagery
|
|
290
|
+
* layer, meaning that it will cause the reference counters of the
|
|
291
|
+
* imageries to be decreased.
|
|
292
|
+
*
|
|
293
|
+
* If the imagery layer already has been destroyed, then nothing
|
|
294
|
+
* will be done.
|
|
295
|
+
*
|
|
296
|
+
* @param {ImageryLayer} imageryLayer The imagery layer
|
|
297
|
+
* @param {ImageryCoverage[]} coverages The coverages
|
|
298
|
+
*/
|
|
299
|
+
_deleteCoverages(imageryLayer, coverages) {
|
|
300
|
+
if (imageryLayer.isDestroyed()) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const length = coverages.length;
|
|
304
|
+
for (let i = 0; i < length; i++) {
|
|
305
|
+
const coverage = coverages[i];
|
|
306
|
+
const imagery = coverage.imagery;
|
|
307
|
+
imagery.releaseReference();
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Create the GPU buffers for the typed arrays that are contained
|
|
313
|
+
* in the <code>_imageryTexCoordAttributesPerProjection</code>
|
|
314
|
+
*
|
|
315
|
+
* @param {Context} context The GL context
|
|
316
|
+
*/
|
|
317
|
+
_uploadImageryTexCoordAttributes(context) {
|
|
318
|
+
//>>includeStart('debug', pragmas.debug);
|
|
319
|
+
Check.defined("context", context);
|
|
320
|
+
//>>includeEnd('debug');
|
|
321
|
+
|
|
322
|
+
const attributes = this._imageryTexCoordAttributesPerProjection;
|
|
323
|
+
if (!defined(attributes)) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
const n = attributes.length;
|
|
327
|
+
for (let i = 0; i < n; i++) {
|
|
328
|
+
const attribute = attributes[i];
|
|
329
|
+
|
|
330
|
+
// Allocate the GL resources for the new attribute
|
|
331
|
+
const imageryTexCoordBuffer = Buffer.createVertexBuffer({
|
|
332
|
+
context: context,
|
|
333
|
+
typedArray: attribute.typedArray,
|
|
334
|
+
usage: BufferUsage.STATIC_DRAW,
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
// TODO_DRAPING Review this. Probably, some cleanup
|
|
338
|
+
// has to happen somewhere else after setting this.
|
|
339
|
+
// Check that the call to "destroy" in
|
|
340
|
+
// _destroyImageryTexCoordAttributes is the right
|
|
341
|
+
// thing to do here.
|
|
342
|
+
imageryTexCoordBuffer.vertexArrayDestroyable = false;
|
|
343
|
+
|
|
344
|
+
attribute.buffer = imageryTexCoordBuffer;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Destroy the <code>_imageryTexCoordAttributesPerProjection</code>
|
|
350
|
+
* array.
|
|
351
|
+
*
|
|
352
|
+
* This is called for cleaning up the allocated GPU resources, before
|
|
353
|
+
* they are supposed to be re-computed with
|
|
354
|
+
* <code>_computeImageryTexCoordsAttributesPerProjection</code>
|
|
355
|
+
*/
|
|
356
|
+
_destroyImageryTexCoordAttributes() {
|
|
357
|
+
const attributes = this._imageryTexCoordAttributesPerProjection;
|
|
358
|
+
if (!defined(attributes)) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
const n = attributes.length;
|
|
362
|
+
for (let i = 0; i < n; i++) {
|
|
363
|
+
const attribute = attributes[i];
|
|
364
|
+
if (defined(attribute)) {
|
|
365
|
+
if (defined(attribute.buffer)) {
|
|
366
|
+
if (!attribute.buffer.isDestroyed()) {
|
|
367
|
+
attribute.buffer.destroy();
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
attributes[i] = undefined;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
delete this._imageryTexCoordAttributesPerProjection;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Returns whether the <code>MappedPositions</code> have to be
|
|
378
|
+
* re-computed with <code>_computeMappedPositionsPerEllipsoid</code>.
|
|
379
|
+
*
|
|
380
|
+
* This is <code>true</code> when the positions have not yet been
|
|
381
|
+
* computed, or when the <code>modelMatrix</code> of the model
|
|
382
|
+
* changed since the previous call.
|
|
383
|
+
*
|
|
384
|
+
* @returns {boolean} Whether the mapped positions need an update
|
|
385
|
+
* @private
|
|
386
|
+
*/
|
|
387
|
+
get _mappedPositionsNeedUpdate() {
|
|
388
|
+
if (!defined(this._mappedPositionsPerEllipsoid)) {
|
|
389
|
+
return true;
|
|
390
|
+
}
|
|
391
|
+
const model = this._model;
|
|
392
|
+
const lastModelMatrix = this._mappedPositionsModelMatrix;
|
|
393
|
+
if (!Matrix4.equals(model.modelMatrix, lastModelMatrix)) {
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
return false;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Computes the mapped positions of the primitive, one for each ellipsoid.
|
|
401
|
+
*
|
|
402
|
+
* This computes the <i>unique</i> ellipsoids that appear in the imagery
|
|
403
|
+
* layers of the model, and creates one <code>MappedPositions</code>
|
|
404
|
+
* object for each of them.
|
|
405
|
+
*
|
|
406
|
+
* The respective <code>MappedPositions</code> objects will contain
|
|
407
|
+
* the cartographic positions that are computed from the positions
|
|
408
|
+
* of the primitive. These will serve as the basis for computing the
|
|
409
|
+
* part of the imagery that is covered by the primitive.
|
|
410
|
+
*
|
|
411
|
+
* These mapped positions depend on the current <code>modelMatrix</code>
|
|
412
|
+
* of the model. So they have to be re-computed when the model matrix
|
|
413
|
+
* changes.
|
|
414
|
+
*
|
|
415
|
+
* @returns {MappedPositions[]} The mapped positions
|
|
416
|
+
* @private
|
|
417
|
+
*/
|
|
418
|
+
_computeMappedPositionsPerEllipsoid() {
|
|
419
|
+
const model = this._model;
|
|
420
|
+
const runtimeNode = this._runtimeNode;
|
|
421
|
+
const runtimePrimitive = this._runtimePrimitive;
|
|
422
|
+
|
|
423
|
+
const primitivePositionAttribute =
|
|
424
|
+
ModelPrimitiveImagery._obtainPrimitivePositionAttribute(
|
|
425
|
+
runtimePrimitive.primitive,
|
|
426
|
+
);
|
|
427
|
+
const numPositions = primitivePositionAttribute.count;
|
|
428
|
+
|
|
429
|
+
const primitivePositionTransform =
|
|
430
|
+
ModelPrimitiveImagery._computePrimitivePositionTransform(
|
|
431
|
+
model,
|
|
432
|
+
runtimeNode,
|
|
433
|
+
undefined,
|
|
434
|
+
);
|
|
435
|
+
|
|
436
|
+
const mappedPositionsPerEllipsoid = [];
|
|
437
|
+
const ellipsoids = ModelPrimitiveImagery._computeUniqueEllipsoids(
|
|
438
|
+
model.imageryLayers,
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
const length = ellipsoids.length;
|
|
442
|
+
for (let i = 0; i < length; i++) {
|
|
443
|
+
const ellipsoid = ellipsoids[i];
|
|
444
|
+
const cartographicPositions =
|
|
445
|
+
ModelImageryMapping.createCartographicPositions(
|
|
446
|
+
primitivePositionAttribute,
|
|
447
|
+
primitivePositionTransform,
|
|
448
|
+
ellipsoid,
|
|
449
|
+
);
|
|
450
|
+
const cartographicBoundingRectangle =
|
|
451
|
+
ModelImageryMapping.computeCartographicBoundingRectangle(
|
|
452
|
+
cartographicPositions,
|
|
453
|
+
);
|
|
454
|
+
|
|
455
|
+
const mappedPositions = new MappedPositions(
|
|
456
|
+
cartographicPositions,
|
|
457
|
+
numPositions,
|
|
458
|
+
cartographicBoundingRectangle,
|
|
459
|
+
ellipsoid,
|
|
460
|
+
);
|
|
461
|
+
mappedPositionsPerEllipsoid.push(mappedPositions);
|
|
462
|
+
}
|
|
463
|
+
Matrix4.clone(model.modelMatrix, this._mappedPositionsModelMatrix);
|
|
464
|
+
return mappedPositionsPerEllipsoid;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Computes an array containing the <i>unique</i> ellipsoids that
|
|
469
|
+
* appear in the imagery layers of the given collection.
|
|
470
|
+
*
|
|
471
|
+
* @param {ImageryLayerCollection} imageryLayers
|
|
472
|
+
* @returns {Ellipsoid[]} The ellipsoids
|
|
473
|
+
* @private
|
|
474
|
+
*/
|
|
475
|
+
static _computeUniqueEllipsoids(imageryLayers) {
|
|
476
|
+
//>>includeStart('debug', pragmas.debug);
|
|
477
|
+
Check.defined("imageryLayers", imageryLayers);
|
|
478
|
+
//>>includeEnd('debug');
|
|
479
|
+
|
|
480
|
+
const ellipsoidsSet = new Set();
|
|
481
|
+
const length = imageryLayers.length;
|
|
482
|
+
for (let i = 0; i < length; i++) {
|
|
483
|
+
const imageryLayer = imageryLayers.get(i);
|
|
484
|
+
const ellipsoid = ModelPrimitiveImagery._getEllipsoid(imageryLayer);
|
|
485
|
+
ellipsoidsSet.add(ellipsoid);
|
|
486
|
+
}
|
|
487
|
+
return [...ellipsoidsSet];
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Computes one coordinate attribute for each unique projection
|
|
492
|
+
* that is used in the imagery layers.
|
|
493
|
+
*
|
|
494
|
+
* This is taking the mapped positions, projecting them with
|
|
495
|
+
* the respective projection, and creating a texture coordinate
|
|
496
|
+
* attribute that describes the texture coordinates of these
|
|
497
|
+
* positions, relative to the cartographic bounding rectangle
|
|
498
|
+
* of the mapped positions.
|
|
499
|
+
*
|
|
500
|
+
* @returns {ModelComponents.Attribute[]} The attributes
|
|
501
|
+
*/
|
|
502
|
+
_computeImageryTexCoordsAttributesPerProjection() {
|
|
503
|
+
const model = this._model;
|
|
504
|
+
const imageryLayers = model.imageryLayers;
|
|
505
|
+
|
|
506
|
+
// Compute the arrays containing ALL projections and the array
|
|
507
|
+
// containing the UNIQUE projections from the imagery layers.
|
|
508
|
+
// Texture coordinate attributes only have to be created once
|
|
509
|
+
// for each projection.
|
|
510
|
+
const allProjections =
|
|
511
|
+
ModelPrimitiveImagery._extractProjections(imageryLayers);
|
|
512
|
+
const uniqueProjections = [...new Set(allProjections)];
|
|
513
|
+
|
|
514
|
+
// Create one texture coordinate attribute for each distinct
|
|
515
|
+
// projection that is used in the imagery layers
|
|
516
|
+
const attributes = this._createImageryTexCoordAttributes(uniqueProjections);
|
|
517
|
+
return attributes;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Computes an array containing the projections that are used in
|
|
522
|
+
* the given imagery layers.
|
|
523
|
+
*
|
|
524
|
+
* (Note that this array may contain duplicates)
|
|
525
|
+
*
|
|
526
|
+
* @param {ImageryLayerCollection} imageryLayers The imagery layers
|
|
527
|
+
* @returns {MapProjection[]} The projections
|
|
528
|
+
* @private
|
|
529
|
+
*/
|
|
530
|
+
static _extractProjections(imageryLayers) {
|
|
531
|
+
//>>includeStart('debug', pragmas.debug);
|
|
532
|
+
Check.defined("imageryLayers", imageryLayers);
|
|
533
|
+
//>>includeEnd('debug');
|
|
534
|
+
|
|
535
|
+
const projections = [];
|
|
536
|
+
const length = imageryLayers.length;
|
|
537
|
+
for (let i = 0; i < length; i++) {
|
|
538
|
+
const imageryLayer = imageryLayers.get(i);
|
|
539
|
+
const projection = ModelPrimitiveImagery._getProjection(imageryLayer);
|
|
540
|
+
projections.push(projection);
|
|
541
|
+
}
|
|
542
|
+
return projections;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Returns the projection of the given imagery layer.
|
|
547
|
+
*
|
|
548
|
+
* This only exists to hide a train wreck
|
|
549
|
+
*
|
|
550
|
+
* @param {ImageryLayer} imageryLayer The imagery layer
|
|
551
|
+
* @returns {MapProjection} The projection
|
|
552
|
+
* @private
|
|
553
|
+
*/
|
|
554
|
+
static _getProjection(imageryLayer) {
|
|
555
|
+
//>>includeStart('debug', pragmas.debug);
|
|
556
|
+
Check.defined("imageryLayer", imageryLayer);
|
|
557
|
+
//>>includeEnd('debug');
|
|
558
|
+
const projection = imageryLayer.imageryProvider.tilingScheme.projection;
|
|
559
|
+
return projection;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Create texture coordinates, one for each projection.
|
|
564
|
+
*
|
|
565
|
+
* This will create a texture coordinate attribute for each of the given projections,
|
|
566
|
+
* using <code>ModelImageryMapping.createTextureCoordinatesAttributeForMappedPositions</code>,
|
|
567
|
+
*
|
|
568
|
+
* (This means that the given projections should indeed be unique,
|
|
569
|
+
* i.e. contain no duplicates)
|
|
570
|
+
*
|
|
571
|
+
* @param {MapProjection[]} uniqueProjections The projections
|
|
572
|
+
* @returns {ModelComponents.Attribute[]} The attributes
|
|
573
|
+
*/
|
|
574
|
+
_createImageryTexCoordAttributes(uniqueProjections) {
|
|
575
|
+
//>>includeStart('debug', pragmas.debug);
|
|
576
|
+
Check.defined("uniqueProjections", uniqueProjections);
|
|
577
|
+
//>>includeEnd('debug');
|
|
578
|
+
|
|
579
|
+
const imageryTexCoordAttributePerUniqueProjection = [];
|
|
580
|
+
const length = uniqueProjections.length;
|
|
581
|
+
for (let i = 0; i < length; i++) {
|
|
582
|
+
// Obtain the mapped positions for the ellipsoid that is used
|
|
583
|
+
// in the projection (i.e. the cartographic positions of the
|
|
584
|
+
// primitive, for the respective ellipsoid)
|
|
585
|
+
const projection = uniqueProjections[i];
|
|
586
|
+
const ellipsoid = projection.ellipsoid;
|
|
587
|
+
const mappedPositions = this.mappedPositionsForEllipsoid(ellipsoid);
|
|
588
|
+
|
|
589
|
+
// Create the actual attribute
|
|
590
|
+
const imageryTexCoordAttribute =
|
|
591
|
+
ModelImageryMapping.createTextureCoordinatesAttributeForMappedPositions(
|
|
592
|
+
mappedPositions,
|
|
593
|
+
projection,
|
|
594
|
+
);
|
|
595
|
+
imageryTexCoordAttributePerUniqueProjection.push(
|
|
596
|
+
imageryTexCoordAttribute,
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
return imageryTexCoordAttributePerUniqueProjection;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Compute the coverage information for the primitive, based on the
|
|
604
|
+
* imagery layers that are associated with the model.
|
|
605
|
+
*
|
|
606
|
+
* This updates the <code>_coveragesPerLayer[layerIndex]</code>, which
|
|
607
|
+
* is an array that contains the <code>ImageryCoverage</code> objects that
|
|
608
|
+
* describe the imagery tiles that are covered by the primitive, including
|
|
609
|
+
* their texture coordinate rectangle.
|
|
610
|
+
*
|
|
611
|
+
* This has to be called after the mapped positions for the primitive
|
|
612
|
+
* have been computed with <code>_computeMappedPositionsPerEllipsoid</code>.
|
|
613
|
+
*
|
|
614
|
+
* @private
|
|
615
|
+
*/
|
|
616
|
+
_computeCoveragesPerLayer() {
|
|
617
|
+
const coveragesPerLayer = [];
|
|
618
|
+
const currentImageryLayers = [];
|
|
619
|
+
|
|
620
|
+
const model = this._model;
|
|
621
|
+
const imageryLayers = model.imageryLayers;
|
|
622
|
+
const length = imageryLayers.length;
|
|
623
|
+
for (let i = 0; i < length; i++) {
|
|
624
|
+
const imageryLayer = imageryLayers.get(i);
|
|
625
|
+
const coverages = this._computeCoverage(imageryLayer);
|
|
626
|
+
coveragesPerLayer.push(coverages);
|
|
627
|
+
currentImageryLayers.push(imageryLayer);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
this._coveragesPerLayer = coveragesPerLayer;
|
|
631
|
+
this._currentImageryLayers = currentImageryLayers;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Compute the coverage information for the primitive, based on the
|
|
636
|
+
* given imagery layer.
|
|
637
|
+
*
|
|
638
|
+
* This returns an array that contains the <code>ImageryCoverage</code>
|
|
639
|
+
* objects that describe the imagery tiles that are covered by the
|
|
640
|
+
* primitive, including their texture coordinate rectangle.
|
|
641
|
+
*
|
|
642
|
+
* This has to be called after the mapped positions for the primitive
|
|
643
|
+
* have been computed with <code>_computeMappedPositionsPerEllipsoid</code>.
|
|
644
|
+
*
|
|
645
|
+
* @param {ImageryLayer} imageryLayer The imagery layer
|
|
646
|
+
* @returns {ImageryCoverage[]} The coverage information
|
|
647
|
+
* @private
|
|
648
|
+
*/
|
|
649
|
+
_computeCoverage(imageryLayer) {
|
|
650
|
+
const mappedPositions = this.mappedPositionsForImageryLayer(imageryLayer);
|
|
651
|
+
const cartographicBoundingRectangle =
|
|
652
|
+
mappedPositions.cartographicBoundingRectangle;
|
|
653
|
+
|
|
654
|
+
const imageryLevel = this._computeImageryLevel(
|
|
655
|
+
imageryLayer,
|
|
656
|
+
cartographicBoundingRectangle,
|
|
657
|
+
);
|
|
658
|
+
|
|
659
|
+
const coverages = ImageryCoverage.createImageryCoverages(
|
|
660
|
+
cartographicBoundingRectangle,
|
|
661
|
+
imageryLayer,
|
|
662
|
+
imageryLevel,
|
|
663
|
+
);
|
|
664
|
+
return coverages;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Compute a <code>level</code> for accessing the imagery from the given
|
|
669
|
+
* imagery layer that is suitable for a primitive with the given bounding
|
|
670
|
+
* rectangle.
|
|
671
|
+
*
|
|
672
|
+
* @param {ImageryLayer} imageryLayer The imagery layer
|
|
673
|
+
* @param {Rectangle} cartographicBoundingRectangle The cartographic
|
|
674
|
+
* bounding rectangle, as obtained from the MappedPositions for
|
|
675
|
+
* the given imagery layer
|
|
676
|
+
* @returns {number} The imagery level
|
|
677
|
+
*/
|
|
678
|
+
_computeImageryLevel(imageryLayer, cartographicBoundingRectangle) {
|
|
679
|
+
const imageryProvider = imageryLayer.imageryProvider;
|
|
680
|
+
const tilingScheme = imageryProvider.tilingScheme;
|
|
681
|
+
const rectangle = tilingScheme.rectangle;
|
|
682
|
+
|
|
683
|
+
// The number of tiles covered by the boundingRectangle (b)
|
|
684
|
+
// for a certain level, based on the tiling scheme rectangle (r) is
|
|
685
|
+
// numberOfTilesCovered = b / (r / 2^level)
|
|
686
|
+
// Solving for "level" yields
|
|
687
|
+
// level = log2( numberOfTilesCovered * r / b)
|
|
688
|
+
|
|
689
|
+
// The goal here is to drape approximately (!) one imagery
|
|
690
|
+
// tile on each primitive. In practice, it may be more
|
|
691
|
+
// (up to 9 in theory)
|
|
692
|
+
const desiredNumberOfTilesCovered = 1;
|
|
693
|
+
|
|
694
|
+
// Perform the computation of the desired level, based on the
|
|
695
|
+
// number of tiles that should be covered (by whatever is
|
|
696
|
+
// larger, the width or the height)
|
|
697
|
+
let boundingRectangleSize = cartographicBoundingRectangle.width;
|
|
698
|
+
let rectangleSize = rectangle.width;
|
|
699
|
+
if (
|
|
700
|
+
cartographicBoundingRectangle.height > cartographicBoundingRectangle.width
|
|
701
|
+
) {
|
|
702
|
+
boundingRectangleSize = cartographicBoundingRectangle.height;
|
|
703
|
+
rectangleSize = rectangle.height;
|
|
704
|
+
}
|
|
705
|
+
const desiredLevel = Math.log2(
|
|
706
|
+
(desiredNumberOfTilesCovered * rectangleSize) / boundingRectangleSize,
|
|
707
|
+
);
|
|
708
|
+
|
|
709
|
+
// Clamp the level to a valid range, and an integer value
|
|
710
|
+
const imageryLevel = ImageryCoverage._clampImageryLevel(
|
|
711
|
+
imageryProvider,
|
|
712
|
+
desiredLevel,
|
|
713
|
+
);
|
|
714
|
+
return imageryLevel;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* Update all <code>Imagery</code> objects.
|
|
719
|
+
*
|
|
720
|
+
* This is called as part of <code>update</code>, until all required
|
|
721
|
+
* imagery tiles are "ready", as indicated by their <code>state</code>
|
|
722
|
+
* being <code>ImageryState.READY</code>.
|
|
723
|
+
*
|
|
724
|
+
* This is called after it has been determined which imagery tiles are
|
|
725
|
+
* covered by the primitive (i.e. after the <code>_coveragesPerLayer</code>
|
|
726
|
+
* have been computed by calling <code>_computeCoverages</code>).
|
|
727
|
+
*
|
|
728
|
+
* For each covered imagery tile, this will call
|
|
729
|
+
* <code>Imagery.processStateMachine</code> until they are either
|
|
730
|
+
* READY, FAILED, or INVALID.
|
|
731
|
+
*
|
|
732
|
+
* Once they all are in one of these final states, it will set the
|
|
733
|
+
* <code>_allImageriesReady</code> flag to <code>true</code>.
|
|
734
|
+
*
|
|
735
|
+
* @param {FrameState} frameState The frame state, to be passed to
|
|
736
|
+
* <code>imagery.processStateMachine</code>
|
|
737
|
+
* @private
|
|
738
|
+
*/
|
|
739
|
+
_updateImageries(frameState) {
|
|
740
|
+
const model = this._model;
|
|
741
|
+
const coveragesPerLayer = this._coveragesPerLayer;
|
|
742
|
+
const length = coveragesPerLayer.length;
|
|
743
|
+
let allImageriesReady = true;
|
|
744
|
+
for (let i = 0; i < length; i++) {
|
|
745
|
+
const coverages = coveragesPerLayer[i];
|
|
746
|
+
const n = coverages.length;
|
|
747
|
+
for (let j = 0; j < n; j++) {
|
|
748
|
+
const coverage = coverages[j];
|
|
749
|
+
const imagery = coverage.imagery;
|
|
750
|
+
|
|
751
|
+
// In the context of loading the imagery for draping
|
|
752
|
+
// it over the primitive, the imagery counts as "ready"
|
|
753
|
+
// when it is really ready, but also when it failed
|
|
754
|
+
// or was invalid (otherwise, the primitive would
|
|
755
|
+
// never turn "ready"
|
|
756
|
+
const countsAsReady =
|
|
757
|
+
imagery.state === ImageryState.READY ||
|
|
758
|
+
imagery.state === ImageryState.FAILED ||
|
|
759
|
+
imagery.state === ImageryState.INVALID;
|
|
760
|
+
if (!countsAsReady) {
|
|
761
|
+
allImageriesReady = false;
|
|
762
|
+
imagery.processStateMachine(frameState, false, false);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// When the imageries turned ready, reset the draw commands
|
|
768
|
+
// to trigger a rendering with the updated draw commands
|
|
769
|
+
// that include the imagery now.
|
|
770
|
+
if (allImageriesReady) {
|
|
771
|
+
model.resetDrawCommands();
|
|
772
|
+
}
|
|
773
|
+
this._allImageriesReady = allImageriesReady;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* Returns the <code>MappedPositions</code> object that contains
|
|
778
|
+
* information about the primitive positions that have been computed
|
|
779
|
+
* for the given imagery layer.
|
|
780
|
+
*
|
|
781
|
+
* This assumes that <code>_computeMappedPositionsPerEllipsoid</code> has
|
|
782
|
+
* already been called.
|
|
783
|
+
*
|
|
784
|
+
* @param {ImageryLayer} imageryLayer The imageryLayer
|
|
785
|
+
* @returns {MappedPositions} The mapped positions
|
|
786
|
+
* @throws {DeveloperError} If the mapped positions for the
|
|
787
|
+
* ellipsoid could not be found.
|
|
788
|
+
*/
|
|
789
|
+
mappedPositionsForImageryLayer(imageryLayer) {
|
|
790
|
+
const ellipsoid = ModelPrimitiveImagery._getEllipsoid(imageryLayer);
|
|
791
|
+
return this.mappedPositionsForEllipsoid(ellipsoid);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Returns the <code>MappedPositions</code> object that contains
|
|
796
|
+
* information about the primitive positions that have been computed
|
|
797
|
+
* from the given ellipsoid.
|
|
798
|
+
*
|
|
799
|
+
* This assumes that <code>_computeMappedPositions</code> has
|
|
800
|
+
* already been called.
|
|
801
|
+
*
|
|
802
|
+
* @param {Ellipsoid} ellipsoid The ellipsoid
|
|
803
|
+
* @returns {MappedPositions} The mapped positions
|
|
804
|
+
* @throws {DeveloperError} If the mapped positions for the
|
|
805
|
+
* given ellipsoid could not be found.
|
|
806
|
+
*/
|
|
807
|
+
mappedPositionsForEllipsoid(ellipsoid) {
|
|
808
|
+
const mappedPositionsPerEllipsoid = this._mappedPositionsPerEllipsoid;
|
|
809
|
+
if (!defined(mappedPositionsPerEllipsoid)) {
|
|
810
|
+
throw new DeveloperError(
|
|
811
|
+
`The mappedPositions have not been computed yet`,
|
|
812
|
+
);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
const length = mappedPositionsPerEllipsoid.length;
|
|
816
|
+
for (let i = 0; i < length; i++) {
|
|
817
|
+
const mappedPositions = mappedPositionsPerEllipsoid[i];
|
|
818
|
+
if (mappedPositions.ellipsoid === ellipsoid) {
|
|
819
|
+
return mappedPositions;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
throw new DeveloperError(
|
|
823
|
+
`Could not find mapped positions for ellipsoid ${ellipsoid}`,
|
|
824
|
+
);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
/**
|
|
828
|
+
* Returns the texture coordinate attributes for the primitive that
|
|
829
|
+
* are used for draping the imagery.
|
|
830
|
+
*
|
|
831
|
+
* This will be available when this object is <code>ready</code>, and
|
|
832
|
+
* will contain one attribute for each unique projection that appears
|
|
833
|
+
* in the imagery layers.
|
|
834
|
+
*
|
|
835
|
+
* @returns {ModelComponents.Attribute[]} The attributes
|
|
836
|
+
*/
|
|
837
|
+
imageryTexCoordAttributesPerProjection() {
|
|
838
|
+
const imageryTexCoordAttributesPerProjection =
|
|
839
|
+
this._imageryTexCoordAttributesPerProjection;
|
|
840
|
+
if (!defined(imageryTexCoordAttributesPerProjection)) {
|
|
841
|
+
throw new DeveloperError(
|
|
842
|
+
`The imagery texture coordinate attributes have not been computed yet`,
|
|
843
|
+
);
|
|
844
|
+
}
|
|
845
|
+
return this._imageryTexCoordAttributesPerProjection;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* Returns whether the draping computations are "ready".
|
|
850
|
+
*
|
|
851
|
+
* This means that the <code>coveragesPerLayer</code> information
|
|
852
|
+
* has been computed, which describes the set of imagery tiles
|
|
853
|
+
* that are covered by the primitive, <b>and</b> that all the
|
|
854
|
+
* covered imagery tiles are in a state that counts as "ready"
|
|
855
|
+
* (i.e. <code>ImageryState.READY</code>, <code>FAILED</code>,
|
|
856
|
+
* or <code>INVALID</code>).
|
|
857
|
+
*
|
|
858
|
+
* @returns {boolean} Whether the draping computations are ready
|
|
859
|
+
*/
|
|
860
|
+
get ready() {
|
|
861
|
+
const coveragesPerLayer = this._coveragesPerLayer;
|
|
862
|
+
if (!defined(coveragesPerLayer)) {
|
|
863
|
+
return false;
|
|
864
|
+
}
|
|
865
|
+
return this._allImageriesReady;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
/**
|
|
869
|
+
* Returns whether this object was destroyed.
|
|
870
|
+
*
|
|
871
|
+
* If this object was destroyed, calling any function other than
|
|
872
|
+
* <code>isDestroyed</code> will result in a {@link DeveloperError}.
|
|
873
|
+
*
|
|
874
|
+
* @returns {boolean} Whether this object was destroyed
|
|
875
|
+
*/
|
|
876
|
+
isDestroyed() {
|
|
877
|
+
return false;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
/**
|
|
881
|
+
* Destroys this object and all its resources.
|
|
882
|
+
*/
|
|
883
|
+
destroy() {
|
|
884
|
+
if (this.isDestroyed()) {
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
this._deleteCoveragesPerLayer();
|
|
888
|
+
this._destroyImageryTexCoordAttributes();
|
|
889
|
+
return destroyObject(this);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
/**
|
|
893
|
+
* Compute the transform that apparently has to be applied to
|
|
894
|
+
* the positions attribute of a primitive, to compute the
|
|
895
|
+
* actual, final positions in ECEF coordinates.
|
|
896
|
+
*
|
|
897
|
+
* This is based on the computation of the bounding
|
|
898
|
+
* sphere that is done at the end of buildDrawCommands
|
|
899
|
+
*
|
|
900
|
+
* @param {Model} model The model
|
|
901
|
+
* @param {ModelComponents.Node} runtimeNode The runtime node
|
|
902
|
+
* that the primitive is attached to
|
|
903
|
+
* @param {Matrix4} [result] The result
|
|
904
|
+
* @returns {Matrix4} The result
|
|
905
|
+
* @private
|
|
906
|
+
*/
|
|
907
|
+
static _computePrimitivePositionTransform(model, runtimeNode, result) {
|
|
908
|
+
//>>includeStart('debug', pragmas.debug);
|
|
909
|
+
Check.defined("model", model);
|
|
910
|
+
Check.defined("runtimeNode", runtimeNode);
|
|
911
|
+
//>>includeEnd('debug');
|
|
912
|
+
|
|
913
|
+
if (!defined(result)) {
|
|
914
|
+
result = new Matrix4();
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
const modelSceneGraph = model.sceneGraph;
|
|
918
|
+
|
|
919
|
+
Matrix4.clone(Matrix4.IDENTITY, result);
|
|
920
|
+
Matrix4.multiply(result, model.modelMatrix, result);
|
|
921
|
+
Matrix4.multiply(result, modelSceneGraph.components.transform, result);
|
|
922
|
+
Matrix4.multiply(result, modelSceneGraph.axisCorrectionMatrix, result);
|
|
923
|
+
Matrix4.multiply(result, runtimeNode.computedTransform, result);
|
|
924
|
+
return result;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
/**
|
|
928
|
+
* Returns the <code>"POSITION"</code> attribute from the given primitive.
|
|
929
|
+
*
|
|
930
|
+
* The <code>"POSITION"</code> attribute is required. If it is not
|
|
931
|
+
* defined for the given primitive, then a <code>DeveloperError</code>
|
|
932
|
+
* is thrown.
|
|
933
|
+
*
|
|
934
|
+
* @param {ModelComponents.Primitive} primitive The primitive
|
|
935
|
+
* @returns {ModelComponents.Attribute} The position attribute
|
|
936
|
+
* @throws {DeveloperError} If there is no position attribute
|
|
937
|
+
* @private
|
|
938
|
+
*/
|
|
939
|
+
static _obtainPrimitivePositionAttribute(primitive) {
|
|
940
|
+
//>>includeStart('debug', pragmas.debug);
|
|
941
|
+
Check.defined("primitive", primitive);
|
|
942
|
+
//>>includeEnd('debug');
|
|
943
|
+
|
|
944
|
+
const primitivePositionAttribute = ModelUtility.getAttributeBySemantic(
|
|
945
|
+
primitive,
|
|
946
|
+
"POSITION",
|
|
947
|
+
);
|
|
948
|
+
if (!defined(primitivePositionAttribute)) {
|
|
949
|
+
throw new DeveloperError(
|
|
950
|
+
"The primitive does not have a POSITION attribute",
|
|
951
|
+
);
|
|
952
|
+
}
|
|
953
|
+
return primitivePositionAttribute;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
/**
|
|
957
|
+
* Returns the ellipsoid of the given imagery layer.
|
|
958
|
+
*
|
|
959
|
+
* This only exists to hide a train wreck
|
|
960
|
+
*
|
|
961
|
+
* @param {ImageryLayer} imageryLayer The imagery layer
|
|
962
|
+
* @returns {Ellipsoid} The ellipsoid
|
|
963
|
+
* @private
|
|
964
|
+
*/
|
|
965
|
+
static _getEllipsoid(imageryLayer) {
|
|
966
|
+
const ellipsoid =
|
|
967
|
+
imageryLayer.imageryProvider.tilingScheme.projection.ellipsoid;
|
|
968
|
+
return ellipsoid;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
export default ModelPrimitiveImagery;
|