bruce-cesium 7.3.7 → 7.3.9
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/dist/bruce-cesium.es5.js +431 -53
- package/dist/bruce-cesium.es5.js.map +1 -1
- package/dist/bruce-cesium.umd.js +429 -51
- package/dist/bruce-cesium.umd.js.map +1 -1
- package/dist/lib/bruce-cesium.js +1 -1
- package/dist/lib/rendering/displaced-surface-primitive.js +63 -24
- package/dist/lib/rendering/displaced-surface-primitive.js.map +1 -1
- package/dist/lib/rendering/entity-gatherer.js +249 -16
- package/dist/lib/rendering/entity-gatherer.js.map +1 -1
- package/dist/lib/rendering/entity-render-engine.js +22 -0
- package/dist/lib/rendering/entity-render-engine.js.map +1 -1
- package/dist/lib/rendering/render-managers/common/historic-utils.js +64 -7
- package/dist/lib/rendering/render-managers/common/historic-utils.js.map +1 -1
- package/dist/lib/rendering/render-managers/entities/entities-datalab-render-manager.js +5 -0
- package/dist/lib/rendering/render-managers/entities/entities-datalab-render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/entities/entities-ids-render-manager.js +8 -3
- package/dist/lib/rendering/render-managers/entities/entities-ids-render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/entities/entities-loaded-render-manager.js +5 -0
- package/dist/lib/rendering/render-managers/entities/entities-loaded-render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/entities/entities-render-manager.js +5 -0
- package/dist/lib/rendering/render-managers/entities/entities-render-manager.js.map +1 -1
- package/dist/lib/rendering/visuals-register.js +8 -0
- package/dist/lib/rendering/visuals-register.js.map +1 -1
- package/dist/types/bruce-cesium.d.ts +1 -1
- package/dist/types/rendering/displaced-surface-primitive.d.ts +4 -0
- package/dist/types/rendering/entity-gatherer.d.ts +27 -4
- package/dist/types/rendering/entity-render-engine.d.ts +9 -0
- package/dist/types/rendering/render-managers/common/historic-utils.d.ts +12 -4
- package/dist/types/rendering/visuals-register.d.ts +5 -0
- package/package.json +1 -1
package/dist/bruce-cesium.es5.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as Cesium from 'cesium';
|
|
2
|
-
import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature,
|
|
3
|
-
import { Cartes, LRUCache, ProjectViewTile, ENVIRONMENT, Calculator, ClientFile, Entity as Entity$1, EntityLod, EntityTag, EntityType, ObjectUtils, Style, Carto, Geometry as Geometry$1,
|
|
2
|
+
import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, ShaderSource, Cartesian3, Math as Math$1, Ellipsoid, Transforms, Matrix4, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, Cartesian2, Cartesian4, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, JulianDate, Quaternion, HeadingPitchRoll, HeightReference, ColorBlendMode, ShadowMode, ClassificationType, Model, HorizontalOrigin, VerticalOrigin, ConstantPositionProperty, ArcType, CornerType, DistanceDisplayCondition, SceneTransforms, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Rectangle, NearFarScalar, Matrix3, KmlDataSource, GeoJsonDataSource, SceneMode, Cesium3DTileStyle, HeadingPitchRange, Ion, IonResource, Cesium3DTileColorBlendMode, Cesium3DTileset, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, OrthographicFrustum, EasingFunction, Intersect, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, PolygonPipeline, CustomDataSource, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, CesiumInspector, ClockRange, DynamicEnvironmentMapManager, ScreenSpaceEventHandler, ScreenSpaceEventType, GeometryInstance, Fullscreen, CzmlDataSource } from 'cesium';
|
|
3
|
+
import { Cartes, LRUCache, ProjectViewTile, ENVIRONMENT, Calculator, ClientFile, Entity as Entity$1, EntityLod, EntityTag, EntityType, ObjectUtils, Style, Api, Carto, Geometry as Geometry$1, Bounds, ClientFileValueMap, Color as Color$1, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, BruceEvent, EntityCoords, DataLab, DelayQueue, AccountConcept, EntityRelation, BruceApi, RecordChangeFeed, EntitySource, ProgramKey, ProjectViewLegacyTile, Camera, Account, AccountLimits, Session, UrlUtils, ProjectViewBookmarkGroup, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, EntityRelationType, EntityHistoricData } from 'bruce-models';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Ensures a number is returned from a given value.
|
|
@@ -9514,6 +9514,14 @@ var VisualsRegister;
|
|
|
9514
9514
|
}
|
|
9515
9515
|
};
|
|
9516
9516
|
}
|
|
9517
|
+
/**
|
|
9518
|
+
* Whether this register is holding a record of a visual.
|
|
9519
|
+
* @param visual
|
|
9520
|
+
*/
|
|
9521
|
+
HasRego(visual) {
|
|
9522
|
+
const vis = visual;
|
|
9523
|
+
return Boolean(vis && vis._register === this && vis._rego);
|
|
9524
|
+
}
|
|
9517
9525
|
/**
|
|
9518
9526
|
* Locates a visual corresponding to a given entity id.
|
|
9519
9527
|
* If no menu item id is provided, then it will pick the "best" one.
|
|
@@ -11040,10 +11048,6 @@ class PointClustering {
|
|
|
11040
11048
|
|
|
11041
11049
|
/**
|
|
11042
11050
|
* How often a historic refresh is worth running, and which Entities it should ask about first.
|
|
11043
|
-
*
|
|
11044
|
-
* A handful of tracked vehicles can afford to re-read on almost every clock tick. Thousands of
|
|
11045
|
-
* parcels cannot, and refreshing them that often was never buying anything since the answer barely
|
|
11046
|
-
* changes between ticks.
|
|
11047
11051
|
*/
|
|
11048
11052
|
var HistoricFetchOrder;
|
|
11049
11053
|
(function (HistoricFetchOrder) {
|
|
@@ -11088,6 +11092,13 @@ var HistoricFetchOrder;
|
|
|
11088
11092
|
HistoricFetchOrder.IntervalForClock = IntervalForClock;
|
|
11089
11093
|
// Upper bounds in metres for the distance bands, nearest first.
|
|
11090
11094
|
HistoricFetchOrder.DEFAULT_BANDS = [500, 2000, 10000, 50000];
|
|
11095
|
+
// How far outside the visible rectangle something still counts as worth re-reading, share of the view itself.
|
|
11096
|
+
HistoricFetchOrder.REFRESH_MARGIN_FRACTION = 0.5;
|
|
11097
|
+
// A close view still gets a usable buffer, and a distant one does not reach half the account.
|
|
11098
|
+
HistoricFetchOrder.MIN_REFRESH_MARGIN_METRES = 250;
|
|
11099
|
+
HistoricFetchOrder.MAX_REFRESH_MARGIN_METRES = 2000;
|
|
11100
|
+
const METRES_PER_DEGREE_LAT = 111320;
|
|
11101
|
+
const MIN_LAT_COSINE = 0.01;
|
|
11091
11102
|
/**
|
|
11092
11103
|
* Resolves what to order by from the view monitor, falling back to the camera itself.
|
|
11093
11104
|
*/
|
|
@@ -11168,6 +11179,55 @@ var HistoricFetchOrder;
|
|
|
11168
11179
|
return grouped.filter(group => group.length > 0);
|
|
11169
11180
|
}
|
|
11170
11181
|
HistoricFetchOrder.ByCameraDistanceOf = ByCameraDistanceOf;
|
|
11182
|
+
/**
|
|
11183
|
+
* Returns how far past a visible rectangle a refresh should still reach, in metres.
|
|
11184
|
+
*/
|
|
11185
|
+
function RefreshMarginFor(bounds) {
|
|
11186
|
+
if (!bounds) {
|
|
11187
|
+
return HistoricFetchOrder.MIN_REFRESH_MARGIN_METRES;
|
|
11188
|
+
}
|
|
11189
|
+
const latSpan = Math.abs(bounds.north - bounds.south) * METRES_PER_DEGREE_LAT;
|
|
11190
|
+
const cosine = Math.max(MIN_LAT_COSINE, Math.cos(Math$1.toRadians((bounds.north + bounds.south) / 2)));
|
|
11191
|
+
const lonDegrees = bounds.west > bounds.east
|
|
11192
|
+
? (bounds.east + 360) - bounds.west
|
|
11193
|
+
: bounds.east - bounds.west;
|
|
11194
|
+
const lonSpan = Math.abs(lonDegrees) * METRES_PER_DEGREE_LAT * cosine;
|
|
11195
|
+
const span = Math.min(latSpan, lonSpan);
|
|
11196
|
+
if (!(span > 0)) {
|
|
11197
|
+
return HistoricFetchOrder.MIN_REFRESH_MARGIN_METRES;
|
|
11198
|
+
}
|
|
11199
|
+
return Math.min(HistoricFetchOrder.MAX_REFRESH_MARGIN_METRES, Math.max(HistoricFetchOrder.MIN_REFRESH_MARGIN_METRES, span * HistoricFetchOrder.REFRESH_MARGIN_FRACTION));
|
|
11200
|
+
}
|
|
11201
|
+
HistoricFetchOrder.RefreshMarginFor = RefreshMarginFor;
|
|
11202
|
+
/**
|
|
11203
|
+
* Returns the rectangle grown outwards by a margin in metres.
|
|
11204
|
+
*/
|
|
11205
|
+
function GrowBounds(bounds, metres) {
|
|
11206
|
+
if (!bounds || !(metres > 0)) {
|
|
11207
|
+
return bounds;
|
|
11208
|
+
}
|
|
11209
|
+
const dLat = metres / METRES_PER_DEGREE_LAT;
|
|
11210
|
+
const north = Math.min(90, bounds.north + dLat);
|
|
11211
|
+
const south = Math.max(-90, bounds.south - dLat);
|
|
11212
|
+
const cosine = Math.cos(Math$1.toRadians((bounds.north + bounds.south) / 2));
|
|
11213
|
+
if (cosine < MIN_LAT_COSINE) {
|
|
11214
|
+
return { north, south, west: -180, east: 180 };
|
|
11215
|
+
}
|
|
11216
|
+
const dLon = metres / (METRES_PER_DEGREE_LAT * cosine);
|
|
11217
|
+
const straddles = bounds.west > bounds.east;
|
|
11218
|
+
const gap = straddles ? bounds.west - bounds.east : 360 - (bounds.east - bounds.west);
|
|
11219
|
+
if (gap <= dLon * 2) {
|
|
11220
|
+
return { north, south, west: -180, east: 180 };
|
|
11221
|
+
}
|
|
11222
|
+
return { north, south, west: wrapLongitude(bounds.west - dLon), east: wrapLongitude(bounds.east + dLon) };
|
|
11223
|
+
}
|
|
11224
|
+
HistoricFetchOrder.GrowBounds = GrowBounds;
|
|
11225
|
+
/*
|
|
11226
|
+
* Returns a longitude folded back into the range the bounds are expressed in.
|
|
11227
|
+
*/
|
|
11228
|
+
function wrapLongitude(lon) {
|
|
11229
|
+
return (((lon + 180) % 360) + 360) % 360 - 180;
|
|
11230
|
+
}
|
|
11171
11231
|
/*
|
|
11172
11232
|
* Returns whether a world position sits inside a ground rectangle given in degrees.
|
|
11173
11233
|
*/
|
|
@@ -11176,17 +11236,22 @@ var HistoricFetchOrder;
|
|
|
11176
11236
|
if (!degrees) {
|
|
11177
11237
|
return false;
|
|
11178
11238
|
}
|
|
11179
|
-
|
|
11239
|
+
return InDegreeBounds(degrees.lat, degrees.lon, bounds);
|
|
11240
|
+
}
|
|
11241
|
+
HistoricFetchOrder.InBounds = InBounds;
|
|
11242
|
+
/*
|
|
11243
|
+
* The same test for a caller that already holds the degrees and should not pay to resolve them from a world position again.
|
|
11244
|
+
*/
|
|
11245
|
+
function InDegreeBounds(lat, lon, bounds) {
|
|
11180
11246
|
if (lat < bounds.south || lat > bounds.north) {
|
|
11181
11247
|
return false;
|
|
11182
11248
|
}
|
|
11183
|
-
// A view straddling the antimeridian reports west east of east, so the span is the outside.
|
|
11184
11249
|
if (bounds.west > bounds.east) {
|
|
11185
11250
|
return lon >= bounds.west || lon <= bounds.east;
|
|
11186
11251
|
}
|
|
11187
11252
|
return lon >= bounds.west && lon <= bounds.east;
|
|
11188
11253
|
}
|
|
11189
|
-
HistoricFetchOrder.
|
|
11254
|
+
HistoricFetchOrder.InDegreeBounds = InDegreeBounds;
|
|
11190
11255
|
/*
|
|
11191
11256
|
* Returns an Entity's world position, or null when it has none to place it by.
|
|
11192
11257
|
*/
|
|
@@ -12685,6 +12750,11 @@ var EntitiesRenderManager;
|
|
|
12685
12750
|
optimizeTolerance: this.item.optimizeTolerance,
|
|
12686
12751
|
});
|
|
12687
12752
|
if (this.disposed) {
|
|
12753
|
+
EntityRenderEngine.RemoveAll({
|
|
12754
|
+
viewer: this.viewer,
|
|
12755
|
+
entities: cEntities,
|
|
12756
|
+
register: this.visualsManager
|
|
12757
|
+
});
|
|
12688
12758
|
this.doDispose();
|
|
12689
12759
|
return;
|
|
12690
12760
|
}
|
|
@@ -13692,6 +13762,11 @@ var EntitiesLoadedRenderManager;
|
|
|
13692
13762
|
force
|
|
13693
13763
|
});
|
|
13694
13764
|
if (this.disposed) {
|
|
13765
|
+
EntityRenderEngine.RemoveAll({
|
|
13766
|
+
viewer: this.viewer,
|
|
13767
|
+
entities: cEntities,
|
|
13768
|
+
register: this.visualsManager
|
|
13769
|
+
});
|
|
13695
13770
|
this.visualsManager.RemoveRegos({
|
|
13696
13771
|
menuItemId: this.item.id
|
|
13697
13772
|
});
|
|
@@ -14136,10 +14211,15 @@ var EntitiesIdsRenderManager;
|
|
|
14136
14211
|
zoomControl: this.item.CameraZoomSettings,
|
|
14137
14212
|
force: force || changed
|
|
14138
14213
|
});
|
|
14214
|
+
if (this.disposed) {
|
|
14215
|
+
EntityRenderEngine.RemoveAll({
|
|
14216
|
+
viewer: this.viewer,
|
|
14217
|
+
entities: cEntities,
|
|
14218
|
+
register: this.visualsManager
|
|
14219
|
+
});
|
|
14220
|
+
return;
|
|
14221
|
+
}
|
|
14139
14222
|
for (let i = 0; i < entities.length; i++) {
|
|
14140
|
-
if (this.disposed) {
|
|
14141
|
-
break;
|
|
14142
|
-
}
|
|
14143
14223
|
const entity = entities[i];
|
|
14144
14224
|
const id = entity.Bruce.ID;
|
|
14145
14225
|
const cEntity = cEntities.get(id);
|
|
@@ -14577,6 +14657,19 @@ class EntityGatherer {
|
|
|
14577
14657
|
// All IDs that have ever been queued.
|
|
14578
14658
|
// When nothing is in queue, we'll re-request the existing IDs based on timeline changes.
|
|
14579
14659
|
this.allEIds = new Set();
|
|
14660
|
+
// IDs a historic read has actually answered with a record, rather than falling back to a stub.
|
|
14661
|
+
// A refresh serves these before the ones that have never produced anything.
|
|
14662
|
+
this.everFound = new Set();
|
|
14663
|
+
// Every known Entity bucketed by the ground cell its position falls in, so a refresh can ask
|
|
14664
|
+
// what the view reaches instead of walking the whole set. Built as IDs arrive.
|
|
14665
|
+
this.cells = new Map();
|
|
14666
|
+
// IDs the position source could not place yet. They are always refreshed.
|
|
14667
|
+
this.unplaced = new Set();
|
|
14668
|
+
// The IDs the last decision found inside the view, so a camera move can queue the difference
|
|
14669
|
+
// rather than re-requesting everything it already asked about.
|
|
14670
|
+
this.lastInView = new Set();
|
|
14671
|
+
// Unsubscribes the view monitor listener that queues what the camera has moved onto.
|
|
14672
|
+
this.monitorRemoval = null;
|
|
14580
14673
|
// Indicates a tick is active.
|
|
14581
14674
|
// When true, we won't bother calling onTick again.
|
|
14582
14675
|
this.runningTick = false;
|
|
@@ -14627,6 +14720,16 @@ class EntityGatherer {
|
|
|
14627
14720
|
}
|
|
14628
14721
|
this.historic = historic;
|
|
14629
14722
|
this.expandSources = expandSources;
|
|
14723
|
+
if (this.historic) {
|
|
14724
|
+
// Anything already known was taken in before the index was being built, so it is filed
|
|
14725
|
+
// a bounded number at a time from here rather than in one pass now.
|
|
14726
|
+
for (const entityId of this.allEIds) {
|
|
14727
|
+
this.unplaced.add(entityId);
|
|
14728
|
+
}
|
|
14729
|
+
}
|
|
14730
|
+
else {
|
|
14731
|
+
this.clearIndex();
|
|
14732
|
+
}
|
|
14630
14733
|
if (this.historic) {
|
|
14631
14734
|
// 4 ticks per second.
|
|
14632
14735
|
// The fastest data we are working with is 5 times per second.
|
|
@@ -14678,6 +14781,8 @@ class EntityGatherer {
|
|
|
14678
14781
|
this.lastOrderFocus = null;
|
|
14679
14782
|
this.allEIds.clear();
|
|
14680
14783
|
this.lastFoundDateTimes.clear();
|
|
14784
|
+
this.everFound.clear();
|
|
14785
|
+
this.clearIndex();
|
|
14681
14786
|
this.lastDateTime = null;
|
|
14682
14787
|
}
|
|
14683
14788
|
ReQueueAll() {
|
|
@@ -14688,22 +14793,193 @@ class EntityGatherer {
|
|
|
14688
14793
|
this.eIdQueued = new Set(this.eIdQueue);
|
|
14689
14794
|
this.priorityCount = 0;
|
|
14690
14795
|
this.lastOrderFocus = null;
|
|
14796
|
+
this.clearIndex();
|
|
14691
14797
|
}
|
|
14692
14798
|
/**
|
|
14693
|
-
* Supplies a lookup from Entity ID to world position, letting the queue resolve what the camera
|
|
14694
|
-
*
|
|
14799
|
+
* Supplies a lookup from Entity ID to world position, letting the queue resolve what the camera is nearest first.
|
|
14800
|
+
* Sources that cannot answer should not call this, and are served in order.
|
|
14695
14801
|
*/
|
|
14696
14802
|
SetPositionSource(positionOf) {
|
|
14697
14803
|
this.positionOf = positionOf;
|
|
14698
14804
|
this.lastOrderFocus = null;
|
|
14805
|
+
this.cells.clear();
|
|
14806
|
+
this.lastInView.clear();
|
|
14807
|
+
for (const entityId of this.allEIds) {
|
|
14808
|
+
this.unplaced.add(entityId);
|
|
14809
|
+
}
|
|
14699
14810
|
}
|
|
14700
14811
|
/**
|
|
14701
|
-
* Supplies the view monitor, so the order follows the ground the camera is aimed at and prefers
|
|
14702
|
-
*
|
|
14812
|
+
* Supplies the view monitor, so the order follows the ground the camera is aimed at and prefers what is on screen.
|
|
14813
|
+
* Without one the ordering falls back to distance from the camera itself.
|
|
14703
14814
|
*/
|
|
14704
14815
|
SetViewMonitor(monitor) {
|
|
14816
|
+
var _a;
|
|
14817
|
+
(_a = this.monitorRemoval) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
14818
|
+
this.monitorRemoval = null;
|
|
14705
14819
|
this.monitor = monitor;
|
|
14706
14820
|
this.lastOrderFocus = null;
|
|
14821
|
+
if (!monitor) {
|
|
14822
|
+
return;
|
|
14823
|
+
}
|
|
14824
|
+
this.monitorRemoval = monitor.Updated().Subscribe(() => {
|
|
14825
|
+
this.admitNewlyInView();
|
|
14826
|
+
});
|
|
14827
|
+
}
|
|
14828
|
+
/*
|
|
14829
|
+
* Queues whatever the camera has moved onto since the last decision.
|
|
14830
|
+
*/
|
|
14831
|
+
admitNewlyInView() {
|
|
14832
|
+
if (this.disposed || !this.historic) {
|
|
14833
|
+
return;
|
|
14834
|
+
}
|
|
14835
|
+
const inView = this.decideInView();
|
|
14836
|
+
if (!inView) {
|
|
14837
|
+
return;
|
|
14838
|
+
}
|
|
14839
|
+
const admit = [];
|
|
14840
|
+
for (const entityId of inView) {
|
|
14841
|
+
if (!this.lastInView.has(entityId)) {
|
|
14842
|
+
admit.push(entityId);
|
|
14843
|
+
}
|
|
14844
|
+
}
|
|
14845
|
+
this.lastInView = new Set(inView);
|
|
14846
|
+
if (admit.length) {
|
|
14847
|
+
this.Queue(admit);
|
|
14848
|
+
}
|
|
14849
|
+
}
|
|
14850
|
+
/*
|
|
14851
|
+
* Returns the IDs a refresh should ask about, or null when the view cannot say and the answer has to be everything.
|
|
14852
|
+
*/
|
|
14853
|
+
decideInView() {
|
|
14854
|
+
if (!this.historic || !this.positionOf || !this.monitor) {
|
|
14855
|
+
return null;
|
|
14856
|
+
}
|
|
14857
|
+
const area = this.refreshArea();
|
|
14858
|
+
if (!area) {
|
|
14859
|
+
return null;
|
|
14860
|
+
}
|
|
14861
|
+
const inView = [];
|
|
14862
|
+
for (const key of this.candidateCellKeys(area)) {
|
|
14863
|
+
const cell = this.cells.get(key);
|
|
14864
|
+
if (!cell) {
|
|
14865
|
+
continue;
|
|
14866
|
+
}
|
|
14867
|
+
for (let i = 0; i < cell.ids.length; i++) {
|
|
14868
|
+
if (HistoricFetchOrder.InDegreeBounds(cell.lats[i], cell.lons[i], area)) {
|
|
14869
|
+
inView.push(cell.ids[i]);
|
|
14870
|
+
}
|
|
14871
|
+
}
|
|
14872
|
+
}
|
|
14873
|
+
// Anything the source cannot place yet is asked about rather than quietly dropped.
|
|
14874
|
+
for (const entityId of this.unplaced) {
|
|
14875
|
+
inView.push(entityId);
|
|
14876
|
+
}
|
|
14877
|
+
return inView;
|
|
14878
|
+
}
|
|
14879
|
+
/*
|
|
14880
|
+
* Returns the cell keys a rectangle can reach.
|
|
14881
|
+
*/
|
|
14882
|
+
candidateCellKeys(area) {
|
|
14883
|
+
const size = EntityGatherer.CELL_DEGREES;
|
|
14884
|
+
const southCell = Math.floor(area.south / size);
|
|
14885
|
+
const northCell = Math.floor(area.north / size);
|
|
14886
|
+
const spans = (area.west > area.east ? [
|
|
14887
|
+
{
|
|
14888
|
+
from: Math.floor(area.west / size),
|
|
14889
|
+
to: Math.floor(180 / size)
|
|
14890
|
+
},
|
|
14891
|
+
{
|
|
14892
|
+
from: Math.floor(-180 / size),
|
|
14893
|
+
to: Math.floor(area.east / size)
|
|
14894
|
+
}
|
|
14895
|
+
] :
|
|
14896
|
+
[{
|
|
14897
|
+
from: Math.floor(area.west / size),
|
|
14898
|
+
to: Math.floor(area.east / size)
|
|
14899
|
+
}]);
|
|
14900
|
+
let width = 0;
|
|
14901
|
+
for (const span of spans) {
|
|
14902
|
+
width += (span.to - span.from) + 1;
|
|
14903
|
+
}
|
|
14904
|
+
const wanted = ((northCell - southCell) + 1) * width;
|
|
14905
|
+
if (!(wanted > 0) || wanted > this.cells.size) {
|
|
14906
|
+
return Array.from(this.cells.keys());
|
|
14907
|
+
}
|
|
14908
|
+
const keys = [];
|
|
14909
|
+
for (let lat = southCell; lat <= northCell; lat++) {
|
|
14910
|
+
for (const span of spans) {
|
|
14911
|
+
for (let lon = span.from; lon <= span.to; lon++) {
|
|
14912
|
+
keys.push(lat + ":" + lon);
|
|
14913
|
+
}
|
|
14914
|
+
}
|
|
14915
|
+
}
|
|
14916
|
+
return keys;
|
|
14917
|
+
}
|
|
14918
|
+
/*
|
|
14919
|
+
* Files an Entity in the cell its position falls in.
|
|
14920
|
+
*/
|
|
14921
|
+
place(entityId) {
|
|
14922
|
+
const degrees = this.degreesOf(entityId);
|
|
14923
|
+
if (!degrees) {
|
|
14924
|
+
this.unplaced.add(entityId);
|
|
14925
|
+
return;
|
|
14926
|
+
}
|
|
14927
|
+
const size = EntityGatherer.CELL_DEGREES;
|
|
14928
|
+
const key = Math.floor(degrees.lat / size) + ":" + Math.floor(degrees.lon / size);
|
|
14929
|
+
let cell = this.cells.get(key);
|
|
14930
|
+
if (!cell) {
|
|
14931
|
+
cell = { ids: [], lats: [], lons: [] };
|
|
14932
|
+
this.cells.set(key, cell);
|
|
14933
|
+
}
|
|
14934
|
+
cell.ids.push(entityId);
|
|
14935
|
+
cell.lats.push(degrees.lat);
|
|
14936
|
+
cell.lons.push(degrees.lon);
|
|
14937
|
+
this.unplaced.delete(entityId);
|
|
14938
|
+
}
|
|
14939
|
+
/*
|
|
14940
|
+
* Retries a bounded number of the Entities the source could not place before, so a late baked
|
|
14941
|
+
* position joins the index without any one tick paying for all of them.
|
|
14942
|
+
*/
|
|
14943
|
+
placeStragglers() {
|
|
14944
|
+
if (!this.unplaced.size || !this.positionOf) {
|
|
14945
|
+
return;
|
|
14946
|
+
}
|
|
14947
|
+
let budget = EntityGatherer.PLACE_BATCH;
|
|
14948
|
+
for (const entityId of this.unplaced) {
|
|
14949
|
+
if (budget-- <= 0) {
|
|
14950
|
+
return;
|
|
14951
|
+
}
|
|
14952
|
+
this.place(entityId);
|
|
14953
|
+
}
|
|
14954
|
+
}
|
|
14955
|
+
clearIndex() {
|
|
14956
|
+
this.cells.clear();
|
|
14957
|
+
this.unplaced.clear();
|
|
14958
|
+
this.lastInView.clear();
|
|
14959
|
+
}
|
|
14960
|
+
/*
|
|
14961
|
+
* Returns where an Entity sits in degrees, or null when the source cannot place it.
|
|
14962
|
+
*/
|
|
14963
|
+
degreesOf(entityId) {
|
|
14964
|
+
let pos = null;
|
|
14965
|
+
try {
|
|
14966
|
+
pos = this.positionOf ? this.positionOf(entityId) : null;
|
|
14967
|
+
}
|
|
14968
|
+
catch {
|
|
14969
|
+
pos = null;
|
|
14970
|
+
}
|
|
14971
|
+
return pos ? CartesianToDegrees(pos) : null;
|
|
14972
|
+
}
|
|
14973
|
+
/*
|
|
14974
|
+
* Returns the visible rectangle plus the margin a refresh still reaches into,
|
|
14975
|
+
* or null when the view cannot say, which is what leaves every Entity in.
|
|
14976
|
+
*/
|
|
14977
|
+
refreshArea() {
|
|
14978
|
+
const focus = HistoricFetchOrder.FocusFrom({ viewer: this.viewer, monitor: this.monitor });
|
|
14979
|
+
if (!(focus === null || focus === void 0 ? void 0 : focus.bounds)) {
|
|
14980
|
+
return null;
|
|
14981
|
+
}
|
|
14982
|
+
return HistoricFetchOrder.GrowBounds(focus.bounds, HistoricFetchOrder.RefreshMarginFor(focus.bounds));
|
|
14707
14983
|
}
|
|
14708
14984
|
/**
|
|
14709
14985
|
* Re-bands the pending queue so the nearest Entities are requested first.
|
|
@@ -14716,8 +14992,6 @@ class EntityGatherer {
|
|
|
14716
14992
|
if (!focus) {
|
|
14717
14993
|
return;
|
|
14718
14994
|
}
|
|
14719
|
-
// Re-banding on every batch would cost a full pass per request for no change in the answer.
|
|
14720
|
-
// Measured on the focus, so panning across the ground counts even when the eye barely moves.
|
|
14721
14995
|
if (this.lastOrderFocus && !EntityGatherer.boundsChanged(this.lastOrderFocus, focus) &&
|
|
14722
14996
|
Cartesian3.distance(this.lastOrderFocus.origin, focus.origin) < EntityGatherer.REORDER_MOVE_METRES) {
|
|
14723
14997
|
return;
|
|
@@ -14764,26 +15038,47 @@ class EntityGatherer {
|
|
|
14764
15038
|
});
|
|
14765
15039
|
const ordered = [];
|
|
14766
15040
|
for (const band of banded) {
|
|
15041
|
+
// Within a band, the ones a read has answered for go first.
|
|
15042
|
+
// A building that has never produced a record is the one least likely to start now, so it waits.
|
|
15043
|
+
const withData = [];
|
|
15044
|
+
const withoutData = [];
|
|
14767
15045
|
for (const entityId of band) {
|
|
15046
|
+
(this.everFound.has(entityId) ? withData : withoutData).push(entityId);
|
|
15047
|
+
}
|
|
15048
|
+
for (const entityId of withData) {
|
|
15049
|
+
ordered.push(entityId);
|
|
15050
|
+
}
|
|
15051
|
+
for (const entityId of withoutData) {
|
|
14768
15052
|
ordered.push(entityId);
|
|
14769
15053
|
}
|
|
14770
15054
|
}
|
|
14771
15055
|
return ordered;
|
|
14772
15056
|
}
|
|
15057
|
+
/*
|
|
15058
|
+
* Takes an ID into the known set, filing it in the index the first time it is seen.
|
|
15059
|
+
*/
|
|
15060
|
+
remember(entityId) {
|
|
15061
|
+
if (this.allEIds.has(entityId)) {
|
|
15062
|
+
return;
|
|
15063
|
+
}
|
|
15064
|
+
this.allEIds.add(entityId);
|
|
15065
|
+
// Only a historic refresh reads the index, so nothing else pays to build it.
|
|
15066
|
+
if (this.historic) {
|
|
15067
|
+
this.place(entityId);
|
|
15068
|
+
}
|
|
15069
|
+
}
|
|
14773
15070
|
Queue(entityIds, topOfQueue = false) {
|
|
14774
15071
|
if (this.disposed || !(entityIds === null || entityIds === void 0 ? void 0 : entityIds.length)) {
|
|
14775
15072
|
return;
|
|
14776
15073
|
}
|
|
14777
15074
|
let changes = 0;
|
|
14778
15075
|
if (topOfQueue) {
|
|
14779
|
-
// Walked back to front so a repeated ID keeps the position of its last occurrence, then
|
|
14780
|
-
// laid down in that order, which is where inserting one at a time leaves them.
|
|
14781
15076
|
const toFront = [];
|
|
14782
15077
|
const promoting = new Set();
|
|
14783
15078
|
let anyAlreadyQueued = false;
|
|
14784
15079
|
for (let i = entityIds.length - 1; i >= 0; i--) {
|
|
14785
15080
|
const eId = entityIds[i];
|
|
14786
|
-
this.
|
|
15081
|
+
this.remember(eId);
|
|
14787
15082
|
if (promoting.has(eId)) {
|
|
14788
15083
|
continue;
|
|
14789
15084
|
}
|
|
@@ -14819,7 +15114,7 @@ class EntityGatherer {
|
|
|
14819
15114
|
else {
|
|
14820
15115
|
for (let i = 0; i < entityIds.length; i++) {
|
|
14821
15116
|
const eId = entityIds[i];
|
|
14822
|
-
this.
|
|
15117
|
+
this.remember(eId);
|
|
14823
15118
|
if (this.eIdQueued.has(eId)) {
|
|
14824
15119
|
continue;
|
|
14825
15120
|
}
|
|
@@ -14834,19 +15129,22 @@ class EntityGatherer {
|
|
|
14834
15129
|
this.onTick(false);
|
|
14835
15130
|
}
|
|
14836
15131
|
Dispose() {
|
|
15132
|
+
var _a;
|
|
14837
15133
|
if (this.disposed) {
|
|
14838
15134
|
return;
|
|
14839
15135
|
}
|
|
14840
15136
|
this.disposed = true;
|
|
15137
|
+
(_a = this.monitorRemoval) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
15138
|
+
this.monitorRemoval = null;
|
|
14841
15139
|
this.hDisposals.forEach((d) => d());
|
|
14842
15140
|
this.hDisposals = [];
|
|
14843
|
-
// A tick still awaiting a response resumes after this, and anything left here would have it
|
|
14844
|
-
// ask for the whole set again on the way out.
|
|
14845
15141
|
this.eIdQueue = [];
|
|
14846
15142
|
this.eIdQueued.clear();
|
|
14847
15143
|
this.priorityCount = 0;
|
|
14848
15144
|
this.allEIds.clear();
|
|
14849
15145
|
this.lastFoundDateTimes.clear();
|
|
15146
|
+
this.everFound.clear();
|
|
15147
|
+
this.clearIndex();
|
|
14850
15148
|
this.entityDataOverrides.clear();
|
|
14851
15149
|
}
|
|
14852
15150
|
checkRange(force) {
|
|
@@ -14870,6 +15168,7 @@ class EntityGatherer {
|
|
|
14870
15168
|
this.lastDateTime = rTime;
|
|
14871
15169
|
(async () => {
|
|
14872
15170
|
this.runningTick = true;
|
|
15171
|
+
this.placeStragglers();
|
|
14873
15172
|
let rerun = false;
|
|
14874
15173
|
try {
|
|
14875
15174
|
const handleResponse = async (requestedBatch, entities) => {
|
|
@@ -14882,6 +15181,13 @@ class EntityGatherer {
|
|
|
14882
15181
|
foundById.set(entityId, entity);
|
|
14883
15182
|
}
|
|
14884
15183
|
}
|
|
15184
|
+
if (this.historic) {
|
|
15185
|
+
for (const entityId of requestedBatch || []) {
|
|
15186
|
+
if (foundById.has(entityId)) {
|
|
15187
|
+
this.everFound.add(entityId);
|
|
15188
|
+
}
|
|
15189
|
+
}
|
|
15190
|
+
}
|
|
14885
15191
|
for (const entityId of requestedBatch || []) {
|
|
14886
15192
|
const override = this.entityDataOverrides.get(entityId);
|
|
14887
15193
|
if (override) {
|
|
@@ -15010,15 +15316,16 @@ class EntityGatherer {
|
|
|
15010
15316
|
this._onQueueProgress.Trigger(100);
|
|
15011
15317
|
}
|
|
15012
15318
|
}
|
|
15013
|
-
// Now run through
|
|
15319
|
+
// Now run through the IDs we've seen that the view still reaches, and request them.
|
|
15014
15320
|
// We'll skip those that we just requested.
|
|
15015
|
-
|
|
15321
|
+
const inView = this.decideInView();
|
|
15322
|
+
this.lastInView = inView ? new Set(inView) : new Set();
|
|
15323
|
+
let allEIds = inView || Array.from(this.allEIds);
|
|
15016
15324
|
if (requestedIds.size) {
|
|
15017
15325
|
allEIds = allEIds.filter((eId) => !requestedIds.has(eId));
|
|
15018
15326
|
}
|
|
15019
15327
|
if (allEIds.length) {
|
|
15020
|
-
//
|
|
15021
|
-
// first here even more than in the queue above.
|
|
15328
|
+
// The near ones are resolved first out of whatever the view still reaches.
|
|
15022
15329
|
allEIds = this.bandIds(allEIds);
|
|
15023
15330
|
while (allEIds.length && !this.disposed && !this.eIdQueue.length) {
|
|
15024
15331
|
if (this.historic && this.lastDateTime !== rTime) {
|
|
@@ -15057,6 +15364,11 @@ class EntityGatherer {
|
|
|
15057
15364
|
}
|
|
15058
15365
|
// Below this the whole queue clears in one or two requests, so ordering it buys nothing.
|
|
15059
15366
|
EntityGatherer.MIN_ORDER_QUEUE = 500;
|
|
15367
|
+
// Side of the ground cells Entities are bucketed into, in degrees.
|
|
15368
|
+
// About a kilometre, so a view covers a handful of them rather than hundreds.
|
|
15369
|
+
EntityGatherer.CELL_DEGREES = 0.01;
|
|
15370
|
+
// How many Entities one tick will try to place in the index.
|
|
15371
|
+
EntityGatherer.PLACE_BATCH = 20000;
|
|
15060
15372
|
// How far the point being looked at has to move before the queue is worth re-banding, in metres.
|
|
15061
15373
|
// Under the nearest band's width, so a move that could change what is nearest still triggers one.
|
|
15062
15374
|
EntityGatherer.REORDER_MOVE_METRES = 250;
|
|
@@ -19520,6 +19832,11 @@ var DataLabRenderManager;
|
|
|
19520
19832
|
force
|
|
19521
19833
|
});
|
|
19522
19834
|
if (this.disposed) {
|
|
19835
|
+
EntityRenderEngine.RemoveAll({
|
|
19836
|
+
viewer: this.viewer,
|
|
19837
|
+
entities: cEntities,
|
|
19838
|
+
register: this.visualsManager
|
|
19839
|
+
});
|
|
19523
19840
|
return;
|
|
19524
19841
|
}
|
|
19525
19842
|
for (let i = 0; i < entities.length; i++) {
|
|
@@ -43668,17 +43985,21 @@ uniform vec2 u_maskGroundSize;
|
|
|
43668
43985
|
uniform vec4 u_extentDegrees;
|
|
43669
43986
|
uniform vec4 u_maskGroundDegrees;
|
|
43670
43987
|
uniform float u_coverageCutoffVertex;
|
|
43988
|
+
//#water
|
|
43671
43989
|
uniform vec2 u_extentMetres;
|
|
43672
43990
|
uniform vec2 u_waveOrigin;
|
|
43991
|
+
//#endwater
|
|
43673
43992
|
|
|
43674
43993
|
out vec2 v_st;
|
|
43675
43994
|
out float v_value;
|
|
43676
43995
|
out float v_coverage;
|
|
43996
|
+
//#water
|
|
43677
43997
|
out vec3 v_positionEC;
|
|
43678
43998
|
out vec3 v_eastEC;
|
|
43679
43999
|
out vec3 v_northEC;
|
|
43680
44000
|
out vec3 v_upEC;
|
|
43681
44001
|
out vec2 v_waveMetres;
|
|
44002
|
+
//#endwater
|
|
43682
44003
|
|
|
43683
44004
|
float decodeGround(vec2 uv) {
|
|
43684
44005
|
// Channels arrive normalised to 0..1, so they go back to bytes before being reassembled.
|
|
@@ -43798,6 +44119,7 @@ void main() {
|
|
|
43798
44119
|
// would be lost to float32 rounding at an earth radius.
|
|
43799
44120
|
vec4 p = czm_translateRelativeToEye(position3DHigh, position3DLow + normal * displacement);
|
|
43800
44121
|
|
|
44122
|
+
//#water
|
|
43801
44123
|
// The local frame at this vertex so a shading normal built in east/north/up meters can be turned into something usable.
|
|
43802
44124
|
v_upEC = czm_normal * normal;
|
|
43803
44125
|
vec3 east = normalize(cross(vec3(0.0, 0.0, 1.0), normal));
|
|
@@ -43805,16 +44127,9 @@ void main() {
|
|
|
43805
44127
|
v_northEC = czm_normal * cross(normal, east);
|
|
43806
44128
|
v_positionEC = (czm_modelViewRelativeToEye * p).xyz;
|
|
43807
44129
|
|
|
43808
|
-
|
|
43809
|
-
* Where this vertex sits in the ripple field, in metres from an origin that follows the camera.
|
|
43810
|
-
*
|
|
43811
|
-
* Subtracted here rather than in the fragment shader because the position it is subtracted from
|
|
43812
|
-
* spans the whole archive, which over a sound is tens of kilometres. A wave number times that
|
|
43813
|
-
* is thousands of radians, and no fragment shader that may only have mediump can step through a
|
|
43814
|
-
* cosine at that magnitude: the ripples come out as a flat surface, which is what a first cut of
|
|
43815
|
-
* this did. What crosses into the fragment shader is a small number the camera is standing in.
|
|
43816
|
-
*/
|
|
44130
|
+
// Where this vertex sits in the ripple field, in metres from an origin that follows the camera.
|
|
43817
44131
|
v_waveMetres = st * u_extentMetres - u_waveOrigin;
|
|
44132
|
+
//#endwater
|
|
43818
44133
|
|
|
43819
44134
|
gl_Position = czm_modelViewProjectionRelativeToEye * p;
|
|
43820
44135
|
}
|
|
@@ -43828,7 +44143,7 @@ uniform float u_valuePacked;
|
|
|
43828
44143
|
uniform float u_valueRange;
|
|
43829
44144
|
uniform float u_exaggeration;
|
|
43830
44145
|
uniform float u_metresPerTexel;
|
|
43831
|
-
|
|
44146
|
+
//#water
|
|
43832
44147
|
uniform float u_waterWavelength;
|
|
43833
44148
|
uniform float u_waterAmplitude;
|
|
43834
44149
|
uniform float u_waterReflectivity;
|
|
@@ -43840,15 +44155,18 @@ uniform vec4 u_wavePhase;
|
|
|
43840
44155
|
uniform vec4 u_wavePhaseB;
|
|
43841
44156
|
// Metres the whole ripple field repeats over.
|
|
43842
44157
|
uniform float u_wavePeriod;
|
|
44158
|
+
//#endwater
|
|
43843
44159
|
|
|
43844
44160
|
in vec2 v_st;
|
|
43845
44161
|
in float v_value;
|
|
43846
44162
|
in float v_coverage;
|
|
44163
|
+
//#water
|
|
43847
44164
|
in vec3 v_positionEC;
|
|
43848
44165
|
in vec3 v_eastEC;
|
|
43849
44166
|
in vec3 v_northEC;
|
|
43850
44167
|
in vec3 v_upEC;
|
|
43851
44168
|
in vec2 v_waveMetres;
|
|
44169
|
+
//#endwater
|
|
43852
44170
|
|
|
43853
44171
|
/*
|
|
43854
44172
|
* Scaled per channel for the same reason the vertex shader's decode is: reassembling the pair reaches
|
|
@@ -43860,6 +44178,7 @@ float valueAt(vec2 uv) {
|
|
|
43860
44178
|
return mix(texel.r, packed16, u_valuePacked);
|
|
43861
44179
|
}
|
|
43862
44180
|
|
|
44181
|
+
//#water
|
|
43863
44182
|
/*
|
|
43864
44183
|
* Slope of the ripple field at a point, in metres of rise per metre travelled.
|
|
43865
44184
|
*/
|
|
@@ -43935,6 +44254,7 @@ vec4 water(vec3 relief, vec4 color) {
|
|
|
43935
44254
|
alpha = clamp(alpha + (1.0 - alpha) * (fresnel * 0.55 + glint), 0.0, 1.0);
|
|
43936
44255
|
return vec4(lit, alpha);
|
|
43937
44256
|
}
|
|
44257
|
+
//#endwater
|
|
43938
44258
|
|
|
43939
44259
|
void main() {
|
|
43940
44260
|
if (v_coverage < u_coverageCutoff) {
|
|
@@ -43957,10 +44277,10 @@ void main() {
|
|
|
43957
44277
|
float scale = u_valueRange * u_exaggeration;
|
|
43958
44278
|
vec3 n = normalize(vec3((left - right) * scale, (down - up) * scale, 2.0 * u_metresPerTexel));
|
|
43959
44279
|
|
|
43960
|
-
|
|
43961
|
-
|
|
43962
|
-
|
|
43963
|
-
|
|
44280
|
+
//#water
|
|
44281
|
+
out_FragColor = water(n, color);
|
|
44282
|
+
return;
|
|
44283
|
+
//#endwater
|
|
43964
44284
|
|
|
43965
44285
|
float lambert = clamp(dot(n, normalize(vec3(-0.5, -0.6, 0.62))), 0.0, 1.0);
|
|
43966
44286
|
color.rgb *= 0.45 + 0.9 * lambert;
|
|
@@ -43968,6 +44288,15 @@ void main() {
|
|
|
43968
44288
|
out_FragColor = vec4(color.rgb, color.a * v_coverage);
|
|
43969
44289
|
}
|
|
43970
44290
|
`;
|
|
44291
|
+
/*
|
|
44292
|
+
* Strips the water-only regions out of a shader source unless this surface is drawing water.
|
|
44293
|
+
*/
|
|
44294
|
+
function withWater(source, water) {
|
|
44295
|
+
if (water) {
|
|
44296
|
+
return source.replace(/^\/\/#(end)?water\n/gm, "");
|
|
44297
|
+
}
|
|
44298
|
+
return source.replace(/^\/\/#water\n[\s\S]*?^\/\/#endwater\n/gm, "");
|
|
44299
|
+
}
|
|
43971
44300
|
/*
|
|
43972
44301
|
* Rewrites a GLSL 300 es source into the GLSL 100 dialect older Cesium builds author in.
|
|
43973
44302
|
*/
|
|
@@ -44296,6 +44625,7 @@ void main() {
|
|
|
44296
44625
|
this.texture = null;
|
|
44297
44626
|
this.textureDirty = true;
|
|
44298
44627
|
this.shaderProgram = null;
|
|
44628
|
+
this.shaderProgramWater = false;
|
|
44299
44629
|
this.renderState = null;
|
|
44300
44630
|
this.destroyed = false;
|
|
44301
44631
|
this.lastEyePosition = null;
|
|
@@ -44315,6 +44645,10 @@ void main() {
|
|
|
44315
44645
|
this.water = null;
|
|
44316
44646
|
this.waterStartMs = now();
|
|
44317
44647
|
this.waveOrigin = new Cartesian2(0, 0);
|
|
44648
|
+
this.extentMetresCache = null;
|
|
44649
|
+
// Written in place each frame rather than reallocated, since they are read per tile.
|
|
44650
|
+
this.wavePhaseScratch = [new Cartesian4(), new Cartesian4()];
|
|
44651
|
+
this.waterSkyScratch = new Cartesian3();
|
|
44318
44652
|
this.followGround = Boolean(options.followGround);
|
|
44319
44653
|
this.terrainProvider = options.terrainProvider || null;
|
|
44320
44654
|
this.extent = options.extent;
|
|
@@ -44739,32 +45073,45 @@ void main() {
|
|
|
44739
45073
|
* 0..1 surface coordinate into the real distance the ripple wavelength is measured in.
|
|
44740
45074
|
*/
|
|
44741
45075
|
extentMetres() {
|
|
45076
|
+
// The extent never moves, and this is read once per tile per frame.
|
|
45077
|
+
if (this.extentMetresCache) {
|
|
45078
|
+
return this.extentMetresCache;
|
|
45079
|
+
}
|
|
44742
45080
|
const southWest = Cartesian3.fromDegrees(this.extent.West, this.extent.South, 0);
|
|
44743
45081
|
const southEast = Cartesian3.fromDegrees(this.extent.East, this.extent.South, 0);
|
|
44744
45082
|
const northWest = Cartesian3.fromDegrees(this.extent.West, this.extent.North, 0);
|
|
44745
|
-
|
|
45083
|
+
this.extentMetresCache = new Cartesian2(Math.max(1, Cartesian3.distance(southWest, southEast)), Math.max(1, Cartesian3.distance(southWest, northWest)));
|
|
45084
|
+
return this.extentMetresCache;
|
|
44746
45085
|
}
|
|
44747
45086
|
/*
|
|
44748
45087
|
* Where each ripple layer has scrolled to, wrapped into one turn.
|
|
44749
45088
|
*/
|
|
44750
45089
|
wavePhase(from) {
|
|
44751
45090
|
var _a;
|
|
45091
|
+
const into = this.wavePhaseScratch[from / 4];
|
|
44752
45092
|
const water = this.water;
|
|
44753
45093
|
if (!water) {
|
|
44754
|
-
return
|
|
45094
|
+
return Cartesian4.clone(Cartesian4.ZERO, into);
|
|
44755
45095
|
}
|
|
44756
45096
|
const speed = (_a = water.speed) !== null && _a !== void 0 ? _a : DEFAULT_WATER_SPEED_METRES_PER_SECOND;
|
|
44757
45097
|
const period = this.wavePeriod();
|
|
44758
45098
|
const seconds = (now() - this.waterStartMs) / 1000;
|
|
44759
45099
|
const base = waveCycles(WATER_WAVES[WATER_BASE_WAVE]);
|
|
44760
|
-
const
|
|
45100
|
+
const phaseAt = (index) => {
|
|
45101
|
+
const wave = WATER_WAVES[from + index];
|
|
45102
|
+
if (!wave) {
|
|
45103
|
+
return 0;
|
|
45104
|
+
}
|
|
44761
45105
|
const cycles = waveCycles(wave);
|
|
44762
45106
|
const waveNumber = 2 * Math.PI * cycles / period;
|
|
44763
45107
|
const travels = Math.sqrt(base / cycles);
|
|
44764
|
-
|
|
44765
|
-
|
|
44766
|
-
|
|
44767
|
-
|
|
45108
|
+
return (seconds * speed * travels * waveNumber) % (2 * Math.PI);
|
|
45109
|
+
};
|
|
45110
|
+
into.x = phaseAt(0);
|
|
45111
|
+
into.y = phaseAt(1);
|
|
45112
|
+
into.z = phaseAt(2);
|
|
45113
|
+
into.w = phaseAt(3);
|
|
45114
|
+
return into;
|
|
44768
45115
|
}
|
|
44769
45116
|
wavePeriod() {
|
|
44770
45117
|
const wavelength = (this.water && this.water.wavelength) || DEFAULT_WATER_WAVELENGTH_METRES;
|
|
@@ -44951,14 +45298,22 @@ void main() {
|
|
|
44951
45298
|
return isFinite(nearest) ? Math.max(1, nearest) : 1;
|
|
44952
45299
|
}
|
|
44953
45300
|
commandFor(context, tile, mesh) {
|
|
45301
|
+
// Rebuilt when the effect is switched, since which program is wanted is part of it.
|
|
45302
|
+
const wantsWater = Boolean(this.water);
|
|
45303
|
+
if (this.shaderProgram && this.shaderProgramWater !== wantsWater) {
|
|
45304
|
+
this.shaderProgram = null;
|
|
45305
|
+
}
|
|
44954
45306
|
if (!this.shaderProgram) {
|
|
44955
45307
|
const glsl300 = usesGlsl300(context);
|
|
45308
|
+
const vertex = withWater(VERTEX_SHADER_GLSL300, wantsWater);
|
|
45309
|
+
const fragment = withWater(FRAGMENT_SHADER_GLSL300, wantsWater);
|
|
44956
45310
|
this.shaderProgram = ShaderProgram.fromCache({
|
|
44957
45311
|
context,
|
|
44958
|
-
vertexShaderSource: glsl300 ?
|
|
44959
|
-
fragmentShaderSource: glsl300 ?
|
|
45312
|
+
vertexShaderSource: glsl300 ? vertex : toGlsl100(vertex, false),
|
|
45313
|
+
fragmentShaderSource: glsl300 ? fragment : toGlsl100(fragment, true),
|
|
44960
45314
|
attributeLocations: mesh.attributeLocations
|
|
44961
45315
|
});
|
|
45316
|
+
this.shaderProgramWater = wantsWater;
|
|
44962
45317
|
this.renderState = RenderState.fromCache({
|
|
44963
45318
|
depthTest: { enabled: true },
|
|
44964
45319
|
// Translucent ramp: blend, and leave the depth buffer to the opaque world.
|
|
@@ -45034,7 +45389,7 @@ void main() {
|
|
|
45034
45389
|
},
|
|
45035
45390
|
u_waterSky: () => {
|
|
45036
45391
|
const sky = (self.water && self.water.skyColor) || DEFAULT_WATER_SKY_COLOR;
|
|
45037
|
-
return
|
|
45392
|
+
return Cartesian3.fromElements(sky.red / 255, sky.green / 255, sky.blue / 255, self.waterSkyScratch);
|
|
45038
45393
|
},
|
|
45039
45394
|
u_wavePhase: () => self.wavePhase(0),
|
|
45040
45395
|
u_wavePhaseB: () => self.wavePhase(4),
|
|
@@ -45045,6 +45400,7 @@ void main() {
|
|
|
45045
45400
|
});
|
|
45046
45401
|
}
|
|
45047
45402
|
// Bounding volume belongs to the mesh, so it follows whichever tier is drawing.
|
|
45403
|
+
tile.command.shaderProgram = this.shaderProgram;
|
|
45048
45404
|
tile.command.vertexArray = mesh.vertexArray;
|
|
45049
45405
|
tile.command.boundingVolume = mesh.boundingSphere;
|
|
45050
45406
|
return tile.command;
|
|
@@ -47006,6 +47362,28 @@ var EntityRenderEngine;
|
|
|
47006
47362
|
};
|
|
47007
47363
|
}
|
|
47008
47364
|
EntityRenderEngine.Render = Render;
|
|
47365
|
+
/**
|
|
47366
|
+
* Removes what a render produced that nothing has a record of, for a render whose caller has gone away.
|
|
47367
|
+
* @param params
|
|
47368
|
+
*/
|
|
47369
|
+
function RemoveAll(params) {
|
|
47370
|
+
const { viewer, entities, register } = params;
|
|
47371
|
+
if (!entities || viewer.isDestroyed()) {
|
|
47372
|
+
return;
|
|
47373
|
+
}
|
|
47374
|
+
entities.forEach((entity) => {
|
|
47375
|
+
if (!entity || (register === null || register === void 0 ? void 0 : register.HasRego(entity))) {
|
|
47376
|
+
return;
|
|
47377
|
+
}
|
|
47378
|
+
try {
|
|
47379
|
+
Remove({ viewer, entity });
|
|
47380
|
+
}
|
|
47381
|
+
catch (e) {
|
|
47382
|
+
console.error("EntityRenderEngine.RemoveAll: failed to remove a visual:", e);
|
|
47383
|
+
}
|
|
47384
|
+
});
|
|
47385
|
+
}
|
|
47386
|
+
EntityRenderEngine.RemoveAll = RemoveAll;
|
|
47009
47387
|
function Remove(params) {
|
|
47010
47388
|
function doRemove(params) {
|
|
47011
47389
|
const { viewer, entity, ignoreParent } = params;
|
|
@@ -47834,7 +48212,7 @@ var StyleUtils;
|
|
|
47834
48212
|
StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
|
|
47835
48213
|
})(StyleUtils || (StyleUtils = {}));
|
|
47836
48214
|
|
|
47837
|
-
const VERSION = "7.3.
|
|
48215
|
+
const VERSION = "7.3.9";
|
|
47838
48216
|
/**
|
|
47839
48217
|
* Updates the environment instance used by bruce-cesium to one specified.
|
|
47840
48218
|
* This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
|