-
Notifications
You must be signed in to change notification settings - Fork 3.5k
/
Cesium3DTileset.js
3762 lines (3411 loc) · 129 KB
/
Cesium3DTileset.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import ApproximateTerrainHeights from "../Core/ApproximateTerrainHeights.js";
import BoundingSphere from "../Core/BoundingSphere.js";
import Cartesian2 from "../Core/Cartesian2.js";
import Cartesian3 from "../Core/Cartesian3.js";
import Cartographic from "../Core/Cartographic.js";
import Check from "../Core/Check.js";
import clone from "../Core/clone.js";
import Color from "../Core/Color.js";
import Credit from "../Core/Credit.js";
import defaultValue from "../Core/defaultValue.js";
import defined from "../Core/defined.js";
import deprecationWarning from "../Core/deprecationWarning.js";
import destroyObject from "../Core/destroyObject.js";
import Ellipsoid from "../Core/Ellipsoid.js";
import Event from "../Core/Event.js";
import ImageBasedLighting from "./ImageBasedLighting.js";
import Interval from "../Core/Interval.js";
import IntersectionTests from "../Core/IntersectionTests.js";
import IonResource from "../Core/IonResource.js";
import JulianDate from "../Core/JulianDate.js";
import ManagedArray from "../Core/ManagedArray.js";
import CesiumMath from "../Core/Math.js";
import Matrix3 from "../Core/Matrix3.js";
import Matrix4 from "../Core/Matrix4.js";
import Resource from "../Core/Resource.js";
import RuntimeError from "../Core/RuntimeError.js";
import Transforms from "../Core/Transforms.js";
import ClearCommand from "../Renderer/ClearCommand.js";
import Pass from "../Renderer/Pass.js";
import RenderState from "../Renderer/RenderState.js";
import Axis from "./Axis.js";
import Cesium3DTile from "./Cesium3DTile.js";
import Cesium3DTileColorBlendMode from "./Cesium3DTileColorBlendMode.js";
import Cesium3DTileContentState from "./Cesium3DTileContentState.js";
import Cesium3DTilesetMetadata from "./Cesium3DTilesetMetadata.js";
import Cesium3DTileOptimizations from "./Cesium3DTileOptimizations.js";
import Cesium3DTilePass from "./Cesium3DTilePass.js";
import Cesium3DTileRefine from "./Cesium3DTileRefine.js";
import Cesium3DTilesetCache from "./Cesium3DTilesetCache.js";
import Cesium3DTilesetHeatmap from "./Cesium3DTilesetHeatmap.js";
import Cesium3DTilesetStatistics from "./Cesium3DTilesetStatistics.js";
import Cesium3DTileStyleEngine from "./Cesium3DTileStyleEngine.js";
import ClippingPlaneCollection from "./ClippingPlaneCollection.js";
import ClippingPolygonCollection from "./ClippingPolygonCollection.js";
import hasExtension from "./hasExtension.js";
import ImplicitTileset from "./ImplicitTileset.js";
import ImplicitTileCoordinates from "./ImplicitTileCoordinates.js";
import LabelCollection from "./LabelCollection.js";
import oneTimeWarning from "../Core/oneTimeWarning.js";
import PointCloudEyeDomeLighting from "./PointCloudEyeDomeLighting.js";
import PointCloudShading from "./PointCloudShading.js";
import ResourceCache from "./ResourceCache.js";
import SceneMode from "./SceneMode.js";
import ShadowMode from "./ShadowMode.js";
import SplitDirection from "./SplitDirection.js";
import StencilConstants from "./StencilConstants.js";
import TileBoundingRegion from "./TileBoundingRegion.js";
import TileBoundingSphere from "./TileBoundingSphere.js";
import TileOrientedBoundingBox from "./TileOrientedBoundingBox.js";
import Cesium3DTilesetMostDetailedTraversal from "./Cesium3DTilesetMostDetailedTraversal.js";
import Cesium3DTilesetBaseTraversal from "./Cesium3DTilesetBaseTraversal.js";
import Cesium3DTilesetSkipTraversal from "./Cesium3DTilesetSkipTraversal.js";
import Ray from "../Core/Ray.js";
import DynamicEnvironmentMapManager from "./DynamicEnvironmentMapManager.js";
/**
* @typedef {Object} Cesium3DTileset.ConstructorOptions
*
* Initialization options for the Cesium3DTileset constructor
*
* @property {boolean} [show=true] Determines if the tileset will be shown.
* @property {Matrix4} [modelMatrix=Matrix4.IDENTITY] A 4x4 transformation matrix that transforms the tileset's root tile.
* @property {Axis} [modelUpAxis=Axis.Y] Which axis is considered up when loading models for tile contents.
* @property {Axis} [modelForwardAxis=Axis.X] Which axis is considered forward when loading models for tile contents.
* @property {ShadowMode} [shadows=ShadowMode.ENABLED] Determines whether the tileset casts or receives shadows from light sources.
* @property {number} [maximumScreenSpaceError=16] The maximum screen space error used to drive level of detail refinement.
* @property {number} [cacheBytes=536870912] The size (in bytes) to which the tile cache will be trimmed, if the cache contains tiles not needed for the current view.
* @property {number} [maximumCacheOverflowBytes=536870912] The maximum additional memory (in bytes) to allow for cache headroom, if more than {@link Cesium3DTileset#cacheBytes} are needed for the current view.
* @property {boolean} [cullWithChildrenBounds=true] Optimization option. Whether to cull tiles using the union of their children bounding volumes.
* @property {boolean} [cullRequestsWhileMoving=true] Optimization option. Don't request tiles that will likely be unused when they come back because of the camera's movement. This optimization only applies to stationary tilesets.
* @property {number} [cullRequestsWhileMovingMultiplier=60.0] Optimization option. Multiplier used in culling requests while moving. Larger is more aggressive culling, smaller less aggressive culling.
* @property {boolean} [preloadWhenHidden=false] Preload tiles when <code>tileset.show</code> is <code>false</code>. Loads tiles as if the tileset is visible but does not render them.
* @property {boolean} [preloadFlightDestinations=true] Optimization option. Preload tiles at the camera's flight destination while the camera is in flight.
* @property {boolean} [preferLeaves=false] Optimization option. Prefer loading of leaves first.
* @property {boolean} [dynamicScreenSpaceError=true] Optimization option. For street-level horizon views, use lower resolution tiles far from the camera. This reduces the amount of data loaded and improves tileset loading time with a slight drop in visual quality in the distance.
* @property {number} [dynamicScreenSpaceErrorDensity=2.0e-4] Similar to {@link Fog#density}, this option controls the camera distance at which the {@link Cesium3DTileset#dynamicScreenSpaceError} optimization applies. Larger values will cause tiles closer to the camera to be affected.
* @property {number} [dynamicScreenSpaceErrorFactor=24.0] A parameter that controls the intensity of the {@link Cesium3DTileset#dynamicScreenSpaceError} optimization for tiles on the horizon. Larger values cause lower resolution tiles to load, improving runtime performance at a slight reduction of visual quality.
* @property {number} [dynamicScreenSpaceErrorHeightFalloff=0.25] A ratio of the tileset's height that determines where "street level" camera views occur. When the camera is below this height, the {@link Cesium3DTileset#dynamicScreenSpaceError} optimization will have the maximum effect, and it will roll off above this value.
* @property {number} [progressiveResolutionHeightFraction=0.3] Optimization option. If between (0.0, 0.5], tiles at or above the screen space error for the reduced screen resolution of <code>progressiveResolutionHeightFraction*screenHeight</code> will be prioritized first. This can help get a quick layer of tiles down while full resolution tiles continue to load.
* @property {boolean} [foveatedScreenSpaceError=true] Optimization option. Prioritize loading tiles in the center of the screen by temporarily raising the screen space error for tiles around the edge of the screen. Screen space error returns to normal once all the tiles in the center of the screen as determined by the {@link Cesium3DTileset#foveatedConeSize} are loaded.
* @property {number} [foveatedConeSize=0.1] Optimization option. Used when {@link Cesium3DTileset#foveatedScreenSpaceError} is true to control the cone size that determines which tiles are deferred. Tiles that are inside this cone are loaded immediately. Tiles outside the cone are potentially deferred based on how far outside the cone they are and their screen space error. This is controlled by {@link Cesium3DTileset#foveatedInterpolationCallback} and {@link Cesium3DTileset#foveatedMinimumScreenSpaceErrorRelaxation}. Setting this to 0.0 means the cone will be the line formed by the camera position and its view direction. Setting this to 1.0 means the cone encompasses the entire field of view of the camera, disabling the effect.
* @property {number} [foveatedMinimumScreenSpaceErrorRelaxation=0.0] Optimization option. Used when {@link Cesium3DTileset#foveatedScreenSpaceError} is true to control the starting screen space error relaxation for tiles outside the foveated cone. The screen space error will be raised starting with tileset value up to {@link Cesium3DTileset#maximumScreenSpaceError} based on the provided {@link Cesium3DTileset#foveatedInterpolationCallback}.
* @property {Cesium3DTileset.foveatedInterpolationCallback} [foveatedInterpolationCallback=Math.lerp] Optimization option. Used when {@link Cesium3DTileset#foveatedScreenSpaceError} is true to control how much to raise the screen space error for tiles outside the foveated cone, interpolating between {@link Cesium3DTileset#foveatedMinimumScreenSpaceErrorRelaxation} and {@link Cesium3DTileset#maximumScreenSpaceError}
* @property {number} [foveatedTimeDelay=0.2] Optimization option. Used when {@link Cesium3DTileset#foveatedScreenSpaceError} is true to control how long in seconds to wait after the camera stops moving before deferred tiles start loading in. This time delay prevents requesting tiles around the edges of the screen when the camera is moving. Setting this to 0.0 will immediately request all tiles in any given view.
* @property {boolean} [skipLevelOfDetail=false] Optimization option. Determines if level of detail skipping should be applied during the traversal.
* @property {number} [baseScreenSpaceError=1024] When <code>skipLevelOfDetail</code> is <code>true</code>, the screen space error that must be reached before skipping levels of detail.
* @property {number} [skipScreenSpaceErrorFactor=16] When <code>skipLevelOfDetail</code> is <code>true</code>, a multiplier defining the minimum screen space error to skip. Used in conjunction with <code>skipLevels</code> to determine which tiles to load.
* @property {number} [skipLevels=1] When <code>skipLevelOfDetail</code> is <code>true</code>, a constant defining the minimum number of levels to skip when loading tiles. When it is 0, no levels are skipped. Used in conjunction with <code>skipScreenSpaceErrorFactor</code> to determine which tiles to load.
* @property {boolean} [immediatelyLoadDesiredLevelOfDetail=false] When <code>skipLevelOfDetail</code> is <code>true</code>, only tiles that meet the maximum screen space error will ever be downloaded. Skipping factors are ignored and just the desired tiles are loaded.
* @property {boolean} [loadSiblings=false] When <code>skipLevelOfDetail</code> is <code>true</code>, determines whether siblings of visible tiles are always downloaded during traversal.
* @property {ClippingPlaneCollection} [clippingPlanes] The {@link ClippingPlaneCollection} used to selectively disable rendering the tileset.
* @property {ClippingPolygonCollection} [clippingPolygons] The {@link ClippingPolygonCollection} used to selectively disable rendering the tileset.
* @property {ClassificationType} [classificationType] Determines whether terrain, 3D Tiles or both will be classified by this tileset. See {@link Cesium3DTileset#classificationType} for details about restrictions and limitations.
* @property {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid determining the size and shape of the globe.
* @property {object} [pointCloudShading] Options for constructing a {@link PointCloudShading} object to control point attenuation based on geometric error and lighting.
* @property {Cartesian3} [lightColor] The light color when shading models. When <code>undefined</code> the scene's light color is used instead.
* @property {ImageBasedLighting} [imageBasedLighting] The properties for managing image-based lighting for this tileset.
* @param {DynamicEnvironmentMapManager.ConstructorOptions} [options.environmentMapOptions] The properties for managing dynamic environment maps on this model.
* @property {boolean} [backFaceCulling=true] Whether to cull back-facing geometry. When true, back face culling is determined by the glTF material's doubleSided property; when false, back face culling is disabled.
* @property {boolean} [enableShowOutline=true] Whether to enable outlines for models using the {@link https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/CESIUM_primitive_outline|CESIUM_primitive_outline} extension. This can be set to false to avoid the additional processing of geometry at load time. When false, the showOutlines and outlineColor options are ignored.
* @property {boolean} [showOutline=true] Whether to display the outline for models using the {@link https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/CESIUM_primitive_outline|CESIUM_primitive_outline} extension. When true, outlines are displayed. When false, outlines are not displayed.
* @property {Color} [outlineColor=Color.BLACK] The color to use when rendering outlines.
* @property {boolean} [vectorClassificationOnly=false] Indicates that only the tileset's vector tiles should be used for classification.
* @property {boolean} [vectorKeepDecodedPositions=false] Whether vector tiles should keep decoded positions in memory. This is used with {@link Cesium3DTileFeature.getPolylinePositions}.
* @property {string|number} [featureIdLabel="featureId_0"] Label of the feature ID set to use for picking and styling. For EXT_mesh_features, this is the feature ID's label property, or "featureId_N" (where N is the index in the featureIds array) when not specified. EXT_feature_metadata did not have a label field, so such feature ID sets are always labeled "featureId_N" where N is the index in the list of all feature Ids, where feature ID attributes are listed before feature ID textures. If featureIdLabel is an integer N, it is converted to the string "featureId_N" automatically. If both per-primitive and per-instance feature IDs are present, the instance feature IDs take priority.
* @property {string|number} [instanceFeatureIdLabel="instanceFeatureId_0"] Label of the instance feature ID set used for picking and styling. If instanceFeatureIdLabel is set to an integer N, it is converted to the string "instanceFeatureId_N" automatically. If both per-primitive and per-instance feature IDs are present, the instance feature IDs take priority.
* @property {boolean} [showCreditsOnScreen=false] Whether to display the credits of this tileset on screen.
* @property {SplitDirection} [splitDirection=SplitDirection.NONE] The {@link SplitDirection} split to apply to this tileset.
* @property {boolean} [enableCollision=false] When <code>true</code>, enables collisions for camera or CPU picking. While this is <code>true</code> the camera will be prevented from going below the tileset surface if {@link ScreenSpaceCameraController#enableCollisionDetection} is true.
* @property {boolean} [projectTo2D=false] Whether to accurately project the tileset to 2D. If this is true, the tileset will be projected accurately to 2D, but it will use more memory to do so. If this is false, the tileset will use less memory and will still render in 2D / CV mode, but its projected positions may be inaccurate. This cannot be set after the tileset has been created.
* @property {boolean} [enablePick=false] Whether to allow collision and CPU picking with <code>pick</code> when using WebGL 1. If using WebGL 2 or above, this option will be ignored. If using WebGL 1 and this is true, the <code>pick</code> operation will work correctly, but it will use more memory to do so. If running with WebGL 1 and this is false, the model will use less memory, but <code>pick</code> will always return <code>undefined</code>. This cannot be set after the tileset has loaded.
* @property {string} [debugHeatmapTilePropertyName] The tile variable to colorize as a heatmap. All rendered tiles will be colorized relative to each other's specified variable value.
* @property {boolean} [debugFreezeFrame=false] For debugging only. Determines if only the tiles from last frame should be used for rendering.
* @property {boolean} [debugColorizeTiles=false] For debugging only. When true, assigns a random color to each tile.
* @property {boolean} [enableDebugWireframe=false] For debugging only. This must be true for debugWireframe to work in WebGL1. This cannot be set after the tileset has been created.
* @property {boolean} [debugWireframe=false] For debugging only. When true, render's each tile's content as a wireframe.
* @property {boolean} [debugShowBoundingVolume=false] For debugging only. When true, renders the bounding volume for each tile.
* @property {boolean} [debugShowContentBoundingVolume=false] For debugging only. When true, renders the bounding volume for each tile's content.
* @property {boolean} [debugShowViewerRequestVolume=false] For debugging only. When true, renders the viewer request volume for each tile.
* @property {boolean} [debugShowGeometricError=false] For debugging only. When true, draws labels to indicate the geometric error of each tile.
* @property {boolean} [debugShowRenderingStatistics=false] For debugging only. When true, draws labels to indicate the number of commands, points, triangles and features for each tile.
* @property {boolean} [debugShowMemoryUsage=false] For debugging only. When true, draws labels to indicate the texture and geometry memory in megabytes used by each tile.
* @property {boolean} [debugShowUrl=false] For debugging only. When true, draws labels to indicate the url of each tile.
*/
/**
* A {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification|3D Tiles tileset},
* used for streaming massive heterogeneous 3D geospatial datasets.
*
* <div class="notice">
* This object is normally not instantiated directly, use {@link Cesium3DTileset.fromUrl}.
* </div>
*
* @alias Cesium3DTileset
* @constructor
*
* @param {Cesium3DTileset.ConstructorOptions} options An object describing initialization options
*
* @exception {DeveloperError} The tileset must be 3D Tiles version 0.0 or 1.0.
*
* @example
* try {
* const tileset = await Cesium.Cesium3DTileset.fromUrl(
* "http://localhost:8002/tilesets/Seattle/tileset.json"
* );
* scene.primitives.add(tileset);
* } catch (error) {
* console.error(`Error creating tileset: ${error}`);
* }
*
* @example
* // Turn on camera collisions with the tileset.
* try {
* const tileset = await Cesium.Cesium3DTileset.fromUrl(
* "http://localhost:8002/tilesets/Seattle/tileset.json",
* { enableCollision: true }
* );
* scene.primitives.add(tileset);
* } catch (error) {
* console.error(`Error creating tileset: ${error}`);
* }
*
* @example
* // Common setting for the skipLevelOfDetail optimization
* const tileset = await Cesium.Cesium3DTileset.fromUrl(
* "http://localhost:8002/tilesets/Seattle/tileset.json", {
* skipLevelOfDetail: true,
* baseScreenSpaceError: 1024,
* skipScreenSpaceErrorFactor: 16,
* skipLevels: 1,
* immediatelyLoadDesiredLevelOfDetail: false,
* loadSiblings: false,
* cullWithChildrenBounds: true
* });
* scene.primitives.add(tileset);
*
* @example
* // Common settings for the dynamicScreenSpaceError optimization
* const tileset = await Cesium.Cesium3DTileset.fromUrl(
* "http://localhost:8002/tilesets/Seattle/tileset.json", {
* dynamicScreenSpaceError: true,
* dynamicScreenSpaceErrorDensity: 2.0e-4,
* dynamicScreenSpaceErrorFactor: 24.0,
* dynamicScreenSpaceErrorHeightFalloff: 0.25
* });
* scene.primitives.add(tileset);
*
* @see {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification|3D Tiles specification}
*/
function Cesium3DTileset(options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
this._url = undefined;
this._basePath = undefined;
this._root = undefined;
this._resource = undefined;
this._asset = undefined; // Metadata for the entire tileset
this._properties = undefined; // Metadata for per-model/point/etc properties
this._geometricError = undefined; // Geometric error when the tree is not rendered at all
this._scaledGeometricError = undefined; // Geometric error scaled by root tile scale
this._extensionsUsed = undefined;
this._extensions = undefined;
this._modelUpAxis = undefined;
this._modelForwardAxis = undefined;
this._cache = new Cesium3DTilesetCache();
this._processingQueue = [];
this._selectedTiles = [];
this._emptyTiles = [];
this._requestedTiles = [];
this._selectedTilesToStyle = [];
this._loadTimestamp = undefined;
this._timeSinceLoad = 0.0;
this._updatedVisibilityFrame = 0;
this._updatedModelMatrixFrame = 0;
this._modelMatrixChanged = false;
this._previousModelMatrix = undefined;
this._extras = undefined;
this._credits = undefined;
this._showCreditsOnScreen = defaultValue(options.showCreditsOnScreen, false);
this._cullWithChildrenBounds = defaultValue(
options.cullWithChildrenBounds,
true,
);
this._allTilesAdditive = true;
this._hasMixedContent = false;
this._stencilClearCommand = undefined;
this._backfaceCommands = new ManagedArray();
this._maximumScreenSpaceError = defaultValue(
options.maximumScreenSpaceError,
16,
);
this._memoryAdjustedScreenSpaceError = this._maximumScreenSpaceError;
this._cacheBytes = defaultValue(options.cacheBytes, 512 * 1024 * 1024);
//>>includeStart('debug', pragmas.debug);
Check.typeOf.number.greaterThanOrEquals("cacheBytes", this._cacheBytes, 0);
//>>includeEnd('debug');
const maximumCacheOverflowBytes = defaultValue(
options.maximumCacheOverflowBytes,
512 * 1024 * 1024,
);
//>>includeStart('debug', pragmas.debug);
Check.typeOf.number.greaterThanOrEquals(
"maximumCacheOverflowBytes",
maximumCacheOverflowBytes,
0,
);
//>>includeEnd('debug');
this._maximumCacheOverflowBytes = maximumCacheOverflowBytes;
this._styleEngine = new Cesium3DTileStyleEngine();
this._styleApplied = false;
this._modelMatrix = defined(options.modelMatrix)
? Matrix4.clone(options.modelMatrix)
: Matrix4.clone(Matrix4.IDENTITY);
this._addHeightCallbacks = [];
this._statistics = new Cesium3DTilesetStatistics();
this._statisticsLast = new Cesium3DTilesetStatistics();
this._statisticsPerPass = new Array(Cesium3DTilePass.NUMBER_OF_PASSES);
for (let i = 0; i < Cesium3DTilePass.NUMBER_OF_PASSES; ++i) {
this._statisticsPerPass[i] = new Cesium3DTilesetStatistics();
}
this._requestedTilesInFlight = [];
this._maximumPriority = {
foveatedFactor: -Number.MAX_VALUE,
depth: -Number.MAX_VALUE,
distance: -Number.MAX_VALUE,
reverseScreenSpaceError: -Number.MAX_VALUE,
};
this._minimumPriority = {
foveatedFactor: Number.MAX_VALUE,
depth: Number.MAX_VALUE,
distance: Number.MAX_VALUE,
reverseScreenSpaceError: Number.MAX_VALUE,
};
this._heatmap = new Cesium3DTilesetHeatmap(
options.debugHeatmapTilePropertyName,
);
/**
* Optimization option. Don't request tiles that will likely be unused when they come back because of the camera's movement. This optimization only applies to stationary tilesets.
*
* @type {boolean}
* @default true
*/
this.cullRequestsWhileMoving = defaultValue(
options.cullRequestsWhileMoving,
true,
);
this._cullRequestsWhileMoving = false;
/**
* Optimization option. Multiplier used in culling requests while moving. Larger is more aggressive culling, smaller less aggressive culling.
*
* @type {number}
* @default 60.0
*/
this.cullRequestsWhileMovingMultiplier = defaultValue(
options.cullRequestsWhileMovingMultiplier,
60.0,
);
/**
* Optimization option. If between (0.0, 0.5], tiles at or above the screen space error for the reduced screen resolution of <code>progressiveResolutionHeightFraction*screenHeight</code> will be prioritized first. This can help get a quick layer of tiles down while full resolution tiles continue to load.
*
* @type {number}
* @default 0.3
*/
this.progressiveResolutionHeightFraction = CesiumMath.clamp(
defaultValue(options.progressiveResolutionHeightFraction, 0.3),
0.0,
0.5,
);
/**
* Optimization option. Prefer loading of leaves first.
*
* @type {boolean}
* @default false
*/
this.preferLeaves = defaultValue(options.preferLeaves, false);
this._tilesLoaded = false;
this._initialTilesLoaded = false;
this._tileDebugLabels = undefined;
this._classificationType = options.classificationType;
this._ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);
this._initialClippingPlanesOriginMatrix = Matrix4.IDENTITY; // Computed from the tileset JSON.
this._clippingPlanesOriginMatrix = undefined; // Combines the above with any run-time transforms.
this._clippingPlanesOriginMatrixDirty = true;
this._vectorClassificationOnly = defaultValue(
options.vectorClassificationOnly,
false,
);
this._vectorKeepDecodedPositions = defaultValue(
options.vectorKeepDecodedPositions,
false,
);
/**
* Preload tiles when <code>tileset.show</code> is <code>false</code>. Loads tiles as if the tileset is visible but does not render them.
*
* @type {boolean}
* @default false
*/
this.preloadWhenHidden = defaultValue(options.preloadWhenHidden, false);
/**
* Optimization option. Fetch tiles at the camera's flight destination while the camera is in flight.
*
* @type {boolean}
* @default true
*/
this.preloadFlightDestinations = defaultValue(
options.preloadFlightDestinations,
true,
);
this._pass = undefined; // Cesium3DTilePass
/**
* Optimization option. For street-level horizon views, use lower resolution tiles far from the camera. This reduces
* the amount of data loaded and improves tileset loading time with a slight drop in visual quality in the distance.
* <p>
* This optimization is strongest when the camera is close to the ground plane of the tileset and looking at the
* horizon. Furthermore, the results are more accurate for tightly fitting bounding volumes like box and region.
*
* @type {boolean}
* @default true
*/
this.dynamicScreenSpaceError = defaultValue(
options.dynamicScreenSpaceError,
true,
);
/**
* Optimization option. Prioritize loading tiles in the center of the screen by temporarily raising the
* screen space error for tiles around the edge of the screen. Screen space error returns to normal once all
* the tiles in the center of the screen as determined by the {@link Cesium3DTileset#foveatedConeSize} are loaded.
*
* @type {boolean}
* @default true
*/
this.foveatedScreenSpaceError = defaultValue(
options.foveatedScreenSpaceError,
true,
);
this._foveatedConeSize = defaultValue(options.foveatedConeSize, 0.1);
this._foveatedMinimumScreenSpaceErrorRelaxation = defaultValue(
options.foveatedMinimumScreenSpaceErrorRelaxation,
0.0,
);
/**
* Gets or sets a callback to control how much to raise the screen space error for tiles outside the foveated cone,
* interpolating between {@link Cesium3DTileset#foveatedMinimumScreenSpaceErrorRelaxation} and {@link Cesium3DTileset#maximumScreenSpaceError}.
*
* @type {Cesium3DTileset.foveatedInterpolationCallback}
*/
this.foveatedInterpolationCallback = defaultValue(
options.foveatedInterpolationCallback,
CesiumMath.lerp,
);
/**
* Optimization option. Used when {@link Cesium3DTileset#foveatedScreenSpaceError} is true to control
* how long in seconds to wait after the camera stops moving before deferred tiles start loading in.
* This time delay prevents requesting tiles around the edges of the screen when the camera is moving.
* Setting this to 0.0 will immediately request all tiles in any given view.
*
* @type {number}
* @default 0.2
*/
this.foveatedTimeDelay = defaultValue(options.foveatedTimeDelay, 0.2);
/**
* Similar to {@link Fog#density}, this option controls the camera distance at which the {@link Cesium3DTileset#dynamicScreenSpaceError}
* optimization applies. Larger values will cause tiles closer to the camera to be affected. This value must be
* non-negative.
* <p>
* This optimization works by rolling off the tile screen space error (SSE) with camera distance like a bell curve.
* This has the effect of selecting lower resolution tiles far from the camera. Near the camera, no adjustment is
* made. For tiles further away, the SSE is reduced by up to {@link Cesium3DTileset#dynamicScreenSpaceErrorFactor}
* (measured in pixels of error).
* </p>
* <p>
* Increasing the density makes the bell curve narrower so tiles closer to the camera are affected. This is analagous
* to moving fog closer to the camera.
* </p>
* <p>
* When the density is 0, the optimization will have no effect on the tileset.
* </p>
*
* @type {number}
* @default 2.0e-4
*/
this.dynamicScreenSpaceErrorDensity = defaultValue(
options.dynamicScreenSpaceErrorDensity,
2.0e-4,
);
/**
* A parameter that controls the intensity of the {@link Cesium3DTileset#dynamicScreenSpaceError} optimization for
* tiles on the horizon. Larger values cause lower resolution tiles to load, improving runtime performance at a slight
* reduction of visual quality. The value must be non-negative.
* <p>
* More specifically, this parameter represents the maximum adjustment to screen space error (SSE) in pixels for tiles
* far away from the camera. See {@link Cesium3DTileset#dynamicScreenSpaceErrorDensity} for more details about how
* this optimization works.
* </p>
* <p>
* When the SSE factor is set to 0, the optimization will have no effect on the tileset.
* </p>
*
* @type {number}
* @default 24.0
*/
this.dynamicScreenSpaceErrorFactor = defaultValue(
options.dynamicScreenSpaceErrorFactor,
24.0,
);
/**
* A ratio of the tileset's height that determines "street level" for the {@link Cesium3DTileset#dynamicScreenSpaceError}
* optimization. When the camera is below this height, the dynamic screen space error optimization will have the maximum
* effect, and it will roll off above this value. Valid values are between 0.0 and 1.0.
* <p>
*
* @type {number}
* @default 0.25
*/
this.dynamicScreenSpaceErrorHeightFalloff = defaultValue(
options.dynamicScreenSpaceErrorHeightFalloff,
0.25,
);
// Updated based on the camera position and direction
this._dynamicScreenSpaceErrorComputedDensity = 0.0;
/**
* Determines whether the tileset casts or receives shadows from light sources.
* <p>
* Enabling shadows has a performance impact. A tileset that casts shadows must be rendered twice, once from the camera and again from the light's point of view.
* </p>
* <p>
* Shadows are rendered only when {@link Viewer#shadows} is <code>true</code>.
* </p>
*
* @type {ShadowMode}
* @default ShadowMode.ENABLED
*/
this.shadows = defaultValue(options.shadows, ShadowMode.ENABLED);
/**
* Determines if the tileset will be shown.
*
* @type {boolean}
* @default true
*/
this.show = defaultValue(options.show, true);
/**
* Defines how per-feature colors set from the Cesium API or declarative styling blend with the source colors from
* the original feature, e.g. glTF material or per-point color in the tile.
*
* @type {Cesium3DTileColorBlendMode}
* @default Cesium3DTileColorBlendMode.HIGHLIGHT
*/
this.colorBlendMode = Cesium3DTileColorBlendMode.HIGHLIGHT;
/**
* Defines the value used to linearly interpolate between the source color and feature color when the {@link Cesium3DTileset#colorBlendMode} is <code>MIX</code>.
* A value of 0.0 results in the source color while a value of 1.0 results in the feature color, with any value in-between
* resulting in a mix of the source color and feature color.
*
* @type {number}
* @default 0.5
*/
this.colorBlendAmount = 0.5;
this._pointCloudShading = new PointCloudShading(options.pointCloudShading);
this._pointCloudEyeDomeLighting = new PointCloudEyeDomeLighting();
/**
* The event fired to indicate progress of loading new tiles. This event is fired when a new tile
* is requested, when a requested tile is finished downloading, and when a downloaded tile has been
* processed and is ready to render.
* <p>
* The number of pending tile requests, <code>numberOfPendingRequests</code>, and number of tiles
* processing, <code>numberOfTilesProcessing</code> are passed to the event listener.
* </p>
* <p>
* This event is fired at the end of the frame after the scene is rendered.
* </p>
*
* @type {Event}
* @default new Event()
*
* @example
* tileset.loadProgress.addEventListener(function(numberOfPendingRequests, numberOfTilesProcessing) {
* if ((numberOfPendingRequests === 0) && (numberOfTilesProcessing === 0)) {
* console.log('Stopped loading');
* return;
* }
*
* console.log(`Loading: requests: ${numberOfPendingRequests}, processing: ${numberOfTilesProcessing}`);
* });
*/
this.loadProgress = new Event();
/**
* The event fired to indicate that all tiles that meet the screen space error this frame are loaded. The tileset
* is completely loaded for this view.
* <p>
* This event is fired at the end of the frame after the scene is rendered.
* </p>
*
* @type {Event}
* @default new Event()
*
* @example
* tileset.allTilesLoaded.addEventListener(function() {
* console.log('All tiles are loaded');
* });
*
* @see Cesium3DTileset#tilesLoaded
*/
this.allTilesLoaded = new Event();
/**
* The event fired to indicate that all tiles that meet the screen space error this frame are loaded. This event
* is fired once when all tiles in the initial view are loaded.
* <p>
* This event is fired at the end of the frame after the scene is rendered.
* </p>
*
* @type {Event}
* @default new Event()
*
* @example
* tileset.initialTilesLoaded.addEventListener(function() {
* console.log('Initial tiles are loaded');
* });
*
* @see Cesium3DTileset#allTilesLoaded
*/
this.initialTilesLoaded = new Event();
/**
* The event fired to indicate that a tile's content was loaded.
* <p>
* The loaded {@link Cesium3DTile} is passed to the event listener.
* </p>
* <p>
* This event is fired during the tileset traversal while the frame is being rendered
* so that updates to the tile take effect in the same frame. Do not create or modify
* Cesium entities or primitives during the event listener.
* </p>
*
* @type {Event}
* @default new Event()
*
* @example
* tileset.tileLoad.addEventListener(function(tile) {
* console.log('A tile was loaded.');
* });
*/
this.tileLoad = new Event();
/**
* The event fired to indicate that a tile's content was unloaded.
* <p>
* The unloaded {@link Cesium3DTile} is passed to the event listener.
* </p>
* <p>
* This event is fired immediately before the tile's content is unloaded while the frame is being
* rendered so that the event listener has access to the tile's content. Do not create
* or modify Cesium entities or primitives during the event listener.
* </p>
*
* @type {Event}
* @default new Event()
*
* @example
* tileset.tileUnload.addEventListener(function(tile) {
* console.log('A tile was unloaded from the cache.');
* });
*
* @see Cesium3DTileset#cacheBytes
* @see Cesium3DTileset#trimLoadedTiles
*/
this.tileUnload = new Event();
/**
* The event fired to indicate that a tile's content failed to load.
* <p>
* If there are no event listeners, error messages will be logged to the console.
* </p>
* <p>
* The error object passed to the listener contains two properties:
* <ul>
* <li><code>url</code>: the url of the failed tile.</li>
* <li><code>message</code>: the error message.</li>
* </ul>
* <p>
* If multiple contents are present, this event is raised once per inner content with errors.
* </p>
*
* @type {Event}
* @default new Event()
*
* @example
* tileset.tileFailed.addEventListener(function(error) {
* console.log(`An error occurred loading tile: ${error.url}`);
* console.log(`Error: ${error.message}`);
* });
*/
this.tileFailed = new Event();
/**
* This event fires once for each visible tile in a frame. This can be used to manually
* style a tileset.
* <p>
* The visible {@link Cesium3DTile} is passed to the event listener.
* </p>
* <p>
* This event is fired during the tileset traversal while the frame is being rendered
* so that updates to the tile take effect in the same frame. Do not create or modify
* Cesium entities or primitives during the event listener.
* </p>
*
* @type {Event}
* @default new Event()
*
* @example
* tileset.tileVisible.addEventListener(function(tile) {
* if (tile.content instanceof Cesium.Model3DTileContent) {
* console.log('A 3D model tile is visible.');
* }
* });
*
* @example
* // Apply a red style and then manually set random colors for every other feature when the tile becomes visible.
* tileset.style = new Cesium.Cesium3DTileStyle({
* color : 'color("red")'
* });
* tileset.tileVisible.addEventListener(function(tile) {
* const content = tile.content;
* const featuresLength = content.featuresLength;
* for (let i = 0; i < featuresLength; i+=2) {
* content.getFeature(i).color = Cesium.Color.fromRandom();
* }
* });
*/
this.tileVisible = new Event();
/**
* Optimization option. Determines if level of detail skipping should be applied during the traversal.
* <p>
* The common strategy for replacement-refinement traversal is to store all levels of the tree in memory and require
* all children to be loaded before the parent can refine. With this optimization levels of the tree can be skipped
* entirely and children can be rendered alongside their parents. The tileset requires significantly less memory when
* using this optimization.
* </p>
*
* @type {boolean}
* @default false
*/
this.skipLevelOfDetail = defaultValue(options.skipLevelOfDetail, false);
this._disableSkipLevelOfDetail = false;
/**
* The screen space error that must be reached before skipping levels of detail.
* <p>
* Only used when {@link Cesium3DTileset#skipLevelOfDetail} is <code>true</code>.
* </p>
*
* @type {number}
* @default 1024
*/
this.baseScreenSpaceError = defaultValue(options.baseScreenSpaceError, 1024);
/**
* Multiplier defining the minimum screen space error to skip.
* For example, if a tile has screen space error of 100, no tiles will be loaded unless they
* are leaves or have a screen space error <code><= 100 / skipScreenSpaceErrorFactor</code>.
* <p>
* Only used when {@link Cesium3DTileset#skipLevelOfDetail} is <code>true</code>.
* </p>
*
* @type {number}
* @default 16
*/
this.skipScreenSpaceErrorFactor = defaultValue(
options.skipScreenSpaceErrorFactor,
16,
);
/**
* Constant defining the minimum number of levels to skip when loading tiles. When it is 0, no levels are skipped.
* For example, if a tile is level 1, no tiles will be loaded unless they are at level greater than 2.
* <p>
* Only used when {@link Cesium3DTileset#skipLevelOfDetail} is <code>true</code>.
* </p>
*
* @type {number}
* @default 1
*/
this.skipLevels = defaultValue(options.skipLevels, 1);
/**
* When true, only tiles that meet the maximum screen space error will ever be downloaded.
* Skipping factors are ignored and just the desired tiles are loaded.
* <p>
* Only used when {@link Cesium3DTileset#skipLevelOfDetail} is <code>true</code>.
* </p>
*
* @type {boolean}
* @default false
*/
this.immediatelyLoadDesiredLevelOfDetail = defaultValue(
options.immediatelyLoadDesiredLevelOfDetail,
false,
);
/**
* Determines whether siblings of visible tiles are always downloaded during traversal.
* This may be useful for ensuring that tiles are already available when the viewer turns left/right.
* <p>
* Only used when {@link Cesium3DTileset#skipLevelOfDetail} is <code>true</code>.
* </p>
*
* @type {boolean}
* @default false
*/
this.loadSiblings = defaultValue(options.loadSiblings, false);
this._clippingPlanes = undefined;
if (defined(options.clippingPlanes)) {
ClippingPlaneCollection.setOwner(
options.clippingPlanes,
this,
"_clippingPlanes",
);
}
this._clippingPolygons = undefined;
if (defined(options.clippingPolygons)) {
ClippingPolygonCollection.setOwner(
options.clippingPolygons,
this,
"_clippingPolygons",
);
}
if (defined(options.imageBasedLighting)) {
this._imageBasedLighting = options.imageBasedLighting;
this._shouldDestroyImageBasedLighting = false;
} else {
this._imageBasedLighting = new ImageBasedLighting();
this._shouldDestroyImageBasedLighting = true;
}
this._environmentMapManager = new DynamicEnvironmentMapManager(
options.environmentMapOptions,
);
/**
* The light color when shading models. When <code>undefined</code> the scene's light color is used instead.
* <p>
* For example, disabling additional light sources by setting
* <code>tileset.imageBasedLighting.imageBasedLightingFactor = new Cartesian2(0.0, 0.0)</code>
* will make the tileset much darker. Here, increasing the intensity of the light source will make the tileset brighter.
* </p>
*
* @type {Cartesian3}
* @default undefined
*/
this.lightColor = options.lightColor;
/**
* Whether to cull back-facing geometry. When true, back face culling is determined
* by the glTF material's doubleSided property; when false, back face culling is disabled.
*
* @type {boolean}
* @default true
*/
this.backFaceCulling = defaultValue(options.backFaceCulling, true);
this._enableShowOutline = defaultValue(options.enableShowOutline, true);
/**
* Whether to display the outline for models using the
* {@link https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/CESIUM_primitive_outline|CESIUM_primitive_outline} extension.
* When true, outlines are displayed. When false, outlines are not displayed.
*
* @type {boolean}
* @default true
*/
this.showOutline = defaultValue(options.showOutline, true);
/**
* The color to use when rendering outlines.
*
* @type {Color}
* @default Color.BLACK
*/
this.outlineColor = defaultValue(options.outlineColor, Color.BLACK);
/**
* The {@link SplitDirection} to apply to this tileset.
*
* @type {SplitDirection}
* @default {@link SplitDirection.NONE}
*/
this.splitDirection = defaultValue(
options.splitDirection,
SplitDirection.NONE,
);
/**
* If <code>true</code>, allows collisions for camera collisions or picking. While this is <code>true</code> the camera will be prevented from going in or below the tileset surface if {@link ScreenSpaceCameraController#enableCollisionDetection} is true. This can have performance implecations if the tileset contains tile with a larger number of vertices.
*
* @type {boolean}
* @default false
*/
this.enableCollision = defaultValue(options.enableCollision, false);
this._projectTo2D = defaultValue(options.projectTo2D, false);
this._enablePick = defaultValue(options.enablePick, false);
/**
* This property is for debugging only; it is not optimized for production use.
* <p>
* Determines if only the tiles from last frame should be used for rendering. This
* effectively "freezes" the tileset to the previous frame so it is possible to zoom
* out and see what was rendered.
* </p>
*
* @type {boolean}
* @default false
*/
this.debugFreezeFrame = defaultValue(options.debugFreezeFrame, false);
/**
* This property is for debugging only; it is not optimized for production use.
* <p>
* When true, assigns a random color to each tile. This is useful for visualizing
* what features belong to what tiles, especially with additive refinement where features
* from parent tiles may be interleaved with features from child tiles.
* </p>
*
* @type {boolean}
* @default false
*/
this.debugColorizeTiles = defaultValue(options.debugColorizeTiles, false);
this._enableDebugWireframe = defaultValue(
options.enableDebugWireframe,
false,
);
/**
* This property is for debugging only; it is not optimized for production use.
* <p>
* When true, renders each tile's content as a wireframe.
* </p>
*
* @type {boolean}
* @default false
*/
this.debugWireframe = defaultValue(options.debugWireframe, false);
// Warning for improper setup of debug wireframe
if (this.debugWireframe === true && this._enableDebugWireframe === false) {
oneTimeWarning(
"tileset-debug-wireframe-ignored",
"enableDebugWireframe must be set to true in the Cesium3DTileset constructor, otherwise debugWireframe will be ignored.",
);
}
/**
* This property is for debugging only; it is not optimized for production use.
* <p>
* When true, renders the bounding volume for each visible tile. The bounding volume is
* white if the tile has a content bounding volume or is empty; otherwise, it is red. Tiles that don't meet the
* screen space error and are still refining to their descendants are yellow.
* </p>
*
* @type {boolean}
* @default false
*/
this.debugShowBoundingVolume = defaultValue(
options.debugShowBoundingVolume,
false,
);
/**
* This property is for debugging only; it is not optimized for production use.
* <p>
* When true, renders the bounding volume for each visible tile's content. The bounding volume is
* blue if the tile has a content bounding volume; otherwise it is red.
* </p>
*
* @type {boolean}
* @default false
*/
this.debugShowContentBoundingVolume = defaultValue(
options.debugShowContentBoundingVolume,
false,
);
/**
* This property is for debugging only; it is not optimized for production use.
* <p>
* When true, renders the viewer request volume for each tile.
* </p>
*
* @type {boolean}
* @default false
*/
this.debugShowViewerRequestVolume = defaultValue(
options.debugShowViewerRequestVolume,
false,
);
/**
* @private
* @type {LabelCollection|undefined}
*/
this._tileDebugLabels = undefined;
this.debugPickedTileLabelOnly = false;
this.debugPickedTile = undefined;