bruce-cesium 7.1.2 → 7.1.4
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 +1000 -47
- package/dist/bruce-cesium.es5.js.map +1 -1
- package/dist/bruce-cesium.umd.js +970 -22
- package/dist/bruce-cesium.umd.js.map +1 -1
- package/dist/lib/bruce-cesium.js +2 -1
- package/dist/lib/bruce-cesium.js.map +1 -1
- package/dist/lib/rendering/displaced-surface-primitive.js +723 -0
- package/dist/lib/rendering/displaced-surface-primitive.js.map +1 -0
- package/dist/lib/rendering/entity-render-engine-polygon.js +193 -15
- package/dist/lib/rendering/entity-render-engine-polygon.js.map +1 -1
- package/dist/lib/rendering/entity-render-engine.js +1 -1
- package/dist/lib/rendering/entity-render-engine.js.map +1 -1
- package/dist/lib/rendering/texture-frame-series-animator.js +62 -5
- package/dist/lib/rendering/texture-frame-series-animator.js.map +1 -1
- package/dist/types/bruce-cesium.d.ts +2 -1
- package/dist/types/rendering/displaced-surface-primitive.d.ts +103 -0
- package/dist/types/rendering/entity-render-engine-polygon.d.ts +1 -1
- package/dist/types/rendering/texture-frame-series-animator.d.ts +25 -0
- package/package.json +2 -2
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, Entity as Entity$1, ENVIRONMENT, Calculator, ClientFile, EntityLod, EntityTag, EntityType, LRUCache, ObjectUtils, Style, Carto, Geometry
|
|
2
|
+
import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, ShaderSource, Ellipsoid, Cartesian3, Transforms, Matrix4, Math as Math$1, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, Cartesian2, DistanceDisplayCondition, HeightReference, ColorBlendMode, HeadingPitchRoll, ShadowMode, ClassificationType, Model, ArcType, CornerType, ConstantPositionProperty, JulianDate, Quaternion, HorizontalOrigin, VerticalOrigin, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Rectangle, SceneTransforms, NearFarScalar, Matrix3, KmlDataSource, GeoJsonDataSource, SceneMode, Cesium3DTileStyle, HeadingPitchRange, Ion, IonResource, Cesium3DTileset, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, Cesium3DTileColorBlendMode, Intersect, OrthographicFrustum, EasingFunction, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, PolygonPipeline, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, CesiumInspector, ClockRange, CustomDataSource, ScreenSpaceEventHandler, ScreenSpaceEventType, GeometryInstance, Fullscreen, CzmlDataSource } from 'cesium';
|
|
3
|
+
import { Cartes, Entity as Entity$1, ENVIRONMENT, Calculator, ClientFile, EntityLod, EntityTag, EntityType, LRUCache, ObjectUtils, Style, Carto, Geometry as Geometry$1, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, Api, Bounds, Color as Color$1, BruceEvent, EntityCoords, DataLab, DelayQueue, BruceApi, EntityHistoricData, EntityRelation, AccountConcept, RecordChangeFeed, ProgramKey, EntitySource, ProjectViewLegacyTile, ProjectViewTile, Camera, Account, AccountLimits, Session, UrlUtils, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, ProjectViewBookmarkGroup, EntityRelationType } from 'bruce-models';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Ensures a number is returned from a given value.
|
|
@@ -3563,11 +3563,11 @@ var SimplifyGeometry;
|
|
|
3563
3563
|
else if (geometry.Polygon) {
|
|
3564
3564
|
for (let i = 0; i < geometry.Polygon.length; i++) {
|
|
3565
3565
|
const polygon = geometry.Polygon[i];
|
|
3566
|
-
count += Geometry.ParsePoints(polygon.LinearRing).length;
|
|
3566
|
+
count += Geometry$1.ParsePoints(polygon.LinearRing).length;
|
|
3567
3567
|
}
|
|
3568
3568
|
}
|
|
3569
3569
|
else if (geometry.LineString) {
|
|
3570
|
-
count += Geometry.ParsePoints(geometry.LineString).length;
|
|
3570
|
+
count += Geometry$1.ParsePoints(geometry.LineString).length;
|
|
3571
3571
|
}
|
|
3572
3572
|
else if (geometry.Point) {
|
|
3573
3573
|
count += 1;
|
|
@@ -3588,7 +3588,7 @@ var SimplifyGeometry;
|
|
|
3588
3588
|
return geometry;
|
|
3589
3589
|
}
|
|
3590
3590
|
// Convert to geojson so that we can interact with turf.
|
|
3591
|
-
const gFeature = Geometry.ToGeoJsonFeature({
|
|
3591
|
+
const gFeature = Geometry$1.ToGeoJsonFeature({
|
|
3592
3592
|
geometry: geometry
|
|
3593
3593
|
});
|
|
3594
3594
|
// Unkink the geometry.
|
|
@@ -3607,7 +3607,7 @@ var SimplifyGeometry;
|
|
|
3607
3607
|
});
|
|
3608
3608
|
}
|
|
3609
3609
|
// Converting back to Bruce geometry.
|
|
3610
|
-
geometry = (_a = Geometry.FromGeoJson({
|
|
3610
|
+
geometry = (_a = Geometry$1.FromGeoJson({
|
|
3611
3611
|
geoJson: gFeature
|
|
3612
3612
|
})) === null || _a === void 0 ? void 0 : _a.geometry;
|
|
3613
3613
|
return geometry;
|
|
@@ -11288,7 +11288,7 @@ var EntitiesRenderManager;
|
|
|
11288
11288
|
};
|
|
11289
11289
|
for (let i = 0; i < entities.length; i++) {
|
|
11290
11290
|
const entity = entities[i];
|
|
11291
|
-
const feature = Geometry.ToGeoJsonFeature({
|
|
11291
|
+
const feature = Geometry$1.ToGeoJsonFeature({
|
|
11292
11292
|
geometry: entity.Bruce.VectorGeometry,
|
|
11293
11293
|
noAltitude: polygonsClamped && lineWidthPx <= 0,
|
|
11294
11294
|
altitude: lineWidthPx > 0 && polygonsClamped ? 1 : null,
|
|
@@ -12324,7 +12324,7 @@ var EntitiesLoadedRenderManager;
|
|
|
12324
12324
|
};
|
|
12325
12325
|
for (let i = 0; i < entities.length; i++) {
|
|
12326
12326
|
const entity = entities[i];
|
|
12327
|
-
const feature = Geometry.ToGeoJsonFeature({
|
|
12327
|
+
const feature = Geometry$1.ToGeoJsonFeature({
|
|
12328
12328
|
geometry: entity.Bruce.VectorGeometry,
|
|
12329
12329
|
noAltitude: polygonsClamped && lineWidthPx <= 0,
|
|
12330
12330
|
altitude: lineWidthPx > 0 && polygonsClamped ? 1 : null,
|
|
@@ -17048,7 +17048,7 @@ function createBoundsPolygonGeometry(bounds) {
|
|
|
17048
17048
|
return {
|
|
17049
17049
|
Polygon: [
|
|
17050
17050
|
{
|
|
17051
|
-
Facing: Geometry.EPolygonRingType.Boundaries,
|
|
17051
|
+
Facing: Geometry$1.EPolygonRingType.Boundaries,
|
|
17052
17052
|
LinearRing: ring
|
|
17053
17053
|
}
|
|
17054
17054
|
]
|
|
@@ -35816,7 +35816,7 @@ var EntityUtils;
|
|
|
35816
35816
|
// "0.0,0.0" seems to be generated on missing geometry in our re-index.
|
|
35817
35817
|
// No location -> turns into 0,0 -> turns into 0.0,0.0 point geometry.
|
|
35818
35818
|
if (pointStr && typeof pointStr == "string" && pointStr != "0.0,0.0") {
|
|
35819
|
-
const points = Geometry.ParsePoints(pointStr);
|
|
35819
|
+
const points = Geometry$1.ParsePoints(pointStr);
|
|
35820
35820
|
const point = points.length > 0 ? points[0] : null;
|
|
35821
35821
|
if (point && Carto.ValidateCarto(point)) {
|
|
35822
35822
|
const pos3d = Cartesian3.fromDegrees(EnsureNumber(point.longitude), EnsureNumber(point.latitude), EnsureNumber(point.altitude));
|
|
@@ -35825,7 +35825,7 @@ var EntityUtils;
|
|
|
35825
35825
|
}
|
|
35826
35826
|
const lineStr = geometry.LineString;
|
|
35827
35827
|
if (lineStr && typeof lineStr == "string") {
|
|
35828
|
-
const points = Geometry.ParsePoints(lineStr);
|
|
35828
|
+
const points = Geometry$1.ParsePoints(lineStr);
|
|
35829
35829
|
if (points.length > 0) {
|
|
35830
35830
|
const pPosses = points.map(x => Cartesian3.fromDegrees(EnsureNumber(x.longitude), EnsureNumber(x.latitude), EnsureNumber(x.altitude)));
|
|
35831
35831
|
await ensureHeightRefs(pPosses, sample);
|
|
@@ -35834,9 +35834,9 @@ var EntityUtils;
|
|
|
35834
35834
|
}
|
|
35835
35835
|
const pRings = geometry.Polygon;
|
|
35836
35836
|
if (pRings && typeof pRings == "object") {
|
|
35837
|
-
const boundary = pRings.find(x => x.Facing == Geometry.EPolygonRingType.Boundaries);
|
|
35837
|
+
const boundary = pRings.find(x => x.Facing == Geometry$1.EPolygonRingType.Boundaries);
|
|
35838
35838
|
if (boundary === null || boundary === void 0 ? void 0 : boundary.LinearRing) {
|
|
35839
|
-
const points = Geometry.ParsePoints(boundary.LinearRing);
|
|
35839
|
+
const points = Geometry$1.ParsePoints(boundary.LinearRing);
|
|
35840
35840
|
const pPosses = points.map(x => Cartesian3.fromDegrees(EnsureNumber(x.longitude), EnsureNumber(x.latitude), EnsureNumber(x.altitude)));
|
|
35841
35841
|
await ensureHeightRefs(pPosses, sample);
|
|
35842
35842
|
posses = posses.concat(pPosses);
|
|
@@ -36331,7 +36331,7 @@ var EntityUtils;
|
|
|
36331
36331
|
if (geometry && typeof geometry == "object") {
|
|
36332
36332
|
const pointStr = geometry.Point;
|
|
36333
36333
|
if (pointStr && typeof pointStr == "string") {
|
|
36334
|
-
const points = Geometry.ParsePoints(pointStr);
|
|
36334
|
+
const points = Geometry$1.ParsePoints(pointStr);
|
|
36335
36335
|
const point = points.length > 0 ? points[0] : null;
|
|
36336
36336
|
if (point && Carto.ValidateCarto(point)) {
|
|
36337
36337
|
return Cartesian3.fromDegrees(EnsureNumber(point.longitude), EnsureNumber(point.latitude), EnsureNumber(point.altitude));
|
|
@@ -36339,7 +36339,7 @@ var EntityUtils;
|
|
|
36339
36339
|
}
|
|
36340
36340
|
const lineStr = geometry.LineString;
|
|
36341
36341
|
if (lineStr && typeof lineStr == "string") {
|
|
36342
|
-
const points = Geometry.ParsePoints(lineStr);
|
|
36342
|
+
const points = Geometry$1.ParsePoints(lineStr);
|
|
36343
36343
|
if (points.length > 0) {
|
|
36344
36344
|
const posses = points.map(x => Cartesian3.fromDegrees(EnsureNumber(x.longitude), EnsureNumber(x.latitude), EnsureNumber(x.altitude)));
|
|
36345
36345
|
const { totalLength: length } = MeasureUtils.MeasurePolyline({
|
|
@@ -36362,9 +36362,9 @@ var EntityUtils;
|
|
|
36362
36362
|
}
|
|
36363
36363
|
const pRings = geometry.Polygon;
|
|
36364
36364
|
if (pRings && typeof pRings == "object") {
|
|
36365
|
-
const boundary = pRings.find(x => x.Facing == Geometry.EPolygonRingType.Boundaries);
|
|
36365
|
+
const boundary = pRings.find(x => x.Facing == Geometry$1.EPolygonRingType.Boundaries);
|
|
36366
36366
|
if (boundary === null || boundary === void 0 ? void 0 : boundary.LinearRing) {
|
|
36367
|
-
const points = Geometry.ParsePoints(boundary.LinearRing);
|
|
36367
|
+
const points = Geometry$1.ParsePoints(boundary.LinearRing);
|
|
36368
36368
|
const point = Carto.GetCenter(points);
|
|
36369
36369
|
if (point && Carto.ValidateCarto(point)) {
|
|
36370
36370
|
return Cartesian3.fromDegrees(EnsureNumber(point.longitude), EnsureNumber(point.latitude), EnsureNumber(point.altitude));
|
|
@@ -37098,7 +37098,7 @@ function calculateDistance(point, entity) {
|
|
|
37098
37098
|
if (geometry.Polygon) {
|
|
37099
37099
|
const polygonRings = geometry.Polygon;
|
|
37100
37100
|
const polygon = typeof polygonRings == "string" ? String(polygonRings) : polygonRings.length ? polygonRings[0].LinearRing : "";
|
|
37101
|
-
let points = polygon ? Geometry.ParsePoints(polygon) : [];
|
|
37101
|
+
let points = polygon ? Geometry$1.ParsePoints(polygon) : [];
|
|
37102
37102
|
if (points.length > 2) {
|
|
37103
37103
|
const distance = distanceToPolygon(point, points);
|
|
37104
37104
|
if (!isNaN(distance)) {
|
|
@@ -37108,7 +37108,7 @@ function calculateDistance(point, entity) {
|
|
|
37108
37108
|
}
|
|
37109
37109
|
}
|
|
37110
37110
|
if (!passedGeometry && geometry.LineString) {
|
|
37111
|
-
const points = Geometry.ParsePoints(geometry.LineString);
|
|
37111
|
+
const points = Geometry$1.ParsePoints(geometry.LineString);
|
|
37112
37112
|
if (points.length > 1) {
|
|
37113
37113
|
const pointsLen = points.length;
|
|
37114
37114
|
for (let i = 0; i < pointsLen; i++) {
|
|
@@ -39252,7 +39252,7 @@ var EntityRenderEnginePolyline;
|
|
|
39252
39252
|
entity: entity,
|
|
39253
39253
|
path: ["Bruce", "VectorGeometry", "LineString"]
|
|
39254
39254
|
});
|
|
39255
|
-
const points = lineString && typeof lineString == "string" ? Geometry.ParsePoints(lineString) : [];
|
|
39255
|
+
const points = lineString && typeof lineString == "string" ? Geometry$1.ParsePoints(lineString) : [];
|
|
39256
39256
|
if (!points || points.length < 2) {
|
|
39257
39257
|
return null;
|
|
39258
39258
|
}
|
|
@@ -39751,6 +39751,8 @@ var TextureFrameSeriesAnimator;
|
|
|
39751
39751
|
this.pendingIndex = -1;
|
|
39752
39752
|
this.displayedPixels = null;
|
|
39753
39753
|
this.fadeFromPixels = null;
|
|
39754
|
+
this.displayedValuePixels = null;
|
|
39755
|
+
this.fadeFromValuePixels = null;
|
|
39754
39756
|
this.fadeToIndex = -1;
|
|
39755
39757
|
this.fadeToDims = null;
|
|
39756
39758
|
this.fadeStartMs = null;
|
|
@@ -39759,6 +39761,8 @@ var TextureFrameSeriesAnimator;
|
|
|
39759
39761
|
// forcing Cesium to re-upload the texture only when something changed.
|
|
39760
39762
|
this.pool = [document.createElement("canvas"), document.createElement("canvas")];
|
|
39761
39763
|
this.poolIdx = 0;
|
|
39764
|
+
this.valueDims = null;
|
|
39765
|
+
this.presentVersion = 0;
|
|
39762
39766
|
if (!options.entity.polygon) {
|
|
39763
39767
|
throw new Error("TextureFrameSeriesAnimator requires an entity with polygon graphics.");
|
|
39764
39768
|
}
|
|
@@ -39776,9 +39780,15 @@ var TextureFrameSeriesAnimator;
|
|
|
39776
39780
|
this.frameDates = this.frames.map((f) => JulianDate.fromIso8601(f.Timestamp));
|
|
39777
39781
|
this.frameCache = new Array(this.frames.length).fill(null);
|
|
39778
39782
|
this.frameDims = new Array(this.frames.length).fill(null);
|
|
39783
|
+
this.valueCache = new Array(this.frames.length).fill(null);
|
|
39784
|
+
this.produceValueCanvas = Boolean(options.produceValueCanvas);
|
|
39785
|
+
this.valueCanvas = this.produceValueCanvas ? document.createElement("canvas") : null;
|
|
39786
|
+
this.driveMaterial = options.driveMaterial !== false;
|
|
39779
39787
|
this.originalMaterial = options.entity.polygon.material;
|
|
39780
39788
|
this.imageProperty = new CallbackProperty(() => this.pool[this.poolIdx], false);
|
|
39781
|
-
|
|
39789
|
+
if (this.driveMaterial) {
|
|
39790
|
+
options.entity.polygon.material = new ImageMaterialProperty({ image: this.imageProperty, transparent: true });
|
|
39791
|
+
}
|
|
39782
39792
|
this.removeCrossfadeTick = this.viewer.scene.postUpdate.addEventListener(() => this.tickCrossfade());
|
|
39783
39793
|
this.removeOnTick = this.viewer.clock.onTick.addEventListener((clock) => this.onClockTick(clock.currentTime));
|
|
39784
39794
|
this.onClockTick(this.viewer.clock.currentTime);
|
|
@@ -39800,7 +39810,7 @@ var TextureFrameSeriesAnimator;
|
|
|
39800
39810
|
this.removeCrossfadeTick();
|
|
39801
39811
|
this.removeCrossfadeTick = null;
|
|
39802
39812
|
}
|
|
39803
|
-
if (this.entity && this.entity.polygon) {
|
|
39813
|
+
if (this.driveMaterial && this.entity && this.entity.polygon) {
|
|
39804
39814
|
this.entity.polygon.material = this.originalMaterial;
|
|
39805
39815
|
}
|
|
39806
39816
|
}
|
|
@@ -39821,6 +39831,20 @@ var TextureFrameSeriesAnimator;
|
|
|
39821
39831
|
GetImageProperty() {
|
|
39822
39832
|
return this.imageProperty;
|
|
39823
39833
|
}
|
|
39834
|
+
/**
|
|
39835
|
+
* The untinted canvas carrying the presented frame's value in RGB and its coverage in alpha,
|
|
39836
|
+
* or null unless the instance was constructed with produceValueCanvas.
|
|
39837
|
+
*/
|
|
39838
|
+
GetValueCanvas() {
|
|
39839
|
+
return this.valueDims ? this.valueCanvas : null;
|
|
39840
|
+
}
|
|
39841
|
+
/**
|
|
39842
|
+
* Increments every time a frame is presented, so a consumer holding the value canvas can tell
|
|
39843
|
+
* whether it needs re-uploading without diffing pixels or subscribing to anything.
|
|
39844
|
+
*/
|
|
39845
|
+
GetPresentVersion() {
|
|
39846
|
+
return this.presentVersion;
|
|
39847
|
+
}
|
|
39824
39848
|
onClockTick(currentTime) {
|
|
39825
39849
|
if (this.disposed) {
|
|
39826
39850
|
return;
|
|
@@ -39933,6 +39957,7 @@ var TextureFrameSeriesAnimator;
|
|
|
39933
39957
|
}
|
|
39934
39958
|
this.frameCache[idx] = decoded.pixels;
|
|
39935
39959
|
this.frameDims[idx] = { width: decoded.width, height: decoded.height };
|
|
39960
|
+
this.valueCache[idx] = decoded.valuePixels || null;
|
|
39936
39961
|
if (idx === this.currentFrameIndex) {
|
|
39937
39962
|
this.beginCrossfadeTo(idx);
|
|
39938
39963
|
}
|
|
@@ -39956,11 +39981,17 @@ var TextureFrameSeriesAnimator;
|
|
|
39956
39981
|
const ctx = canvas.getContext("2d");
|
|
39957
39982
|
ctx.drawImage(image, 0, 0);
|
|
39958
39983
|
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
39984
|
+
// Copied before tinting: the ramp is a lerp between two colours, so the value cannot be
|
|
39985
|
+
// recovered from the tinted pixels afterwards.
|
|
39986
|
+
const valuePixels = this.produceValueCanvas ? new Uint8ClampedArray(imageData.data) : undefined;
|
|
39959
39987
|
ApplyGrayscaleColorMask(imageData, this.lowColor, this.highColor);
|
|
39960
|
-
return { pixels: imageData.data, width: canvas.width, height: canvas.height };
|
|
39988
|
+
return { pixels: imageData.data, width: canvas.width, height: canvas.height, valuePixels };
|
|
39961
39989
|
}
|
|
39962
39990
|
beginCrossfadeTo(idx) {
|
|
39963
39991
|
const to = this.frameCache[idx];
|
|
39992
|
+
this.fadeFromValuePixels = this.displayedValuePixels === null && this.valueCache[idx]
|
|
39993
|
+
? new Uint8ClampedArray(this.valueCache[idx].length)
|
|
39994
|
+
: this.displayedValuePixels;
|
|
39964
39995
|
this.fadeFromPixels = this.displayedPixels === null ? new Uint8ClampedArray(to.length) : this.displayedPixels;
|
|
39965
39996
|
this.fadeToIndex = idx;
|
|
39966
39997
|
this.fadeToDims = this.frameDims[idx];
|
|
@@ -39979,13 +40010,28 @@ var TextureFrameSeriesAnimator;
|
|
|
39979
40010
|
for (let i = 0; i < n; i++) {
|
|
39980
40011
|
blended[i] = from[i] + (to[i] - from[i]) * eased;
|
|
39981
40012
|
}
|
|
39982
|
-
|
|
40013
|
+
let blendedValue = null;
|
|
40014
|
+
const toValue = this.valueCache[this.fadeToIndex];
|
|
40015
|
+
if (toValue) {
|
|
40016
|
+
const fromValue = this.fadeFromValuePixels;
|
|
40017
|
+
blendedValue = new Uint8ClampedArray(toValue.length);
|
|
40018
|
+
if (fromValue && fromValue.length === toValue.length) {
|
|
40019
|
+
for (let i = 0; i < toValue.length; i++) {
|
|
40020
|
+
blendedValue[i] = fromValue[i] + (toValue[i] - fromValue[i]) * eased;
|
|
40021
|
+
}
|
|
40022
|
+
}
|
|
40023
|
+
else {
|
|
40024
|
+
blendedValue.set(toValue);
|
|
40025
|
+
}
|
|
40026
|
+
}
|
|
40027
|
+
this.presentPixels(blended, this.fadeToDims, blendedValue);
|
|
39983
40028
|
if (t >= 1) {
|
|
39984
40029
|
this.fadeStartMs = null;
|
|
39985
40030
|
this.fadeFromPixels = null;
|
|
40031
|
+
this.fadeFromValuePixels = null;
|
|
39986
40032
|
}
|
|
39987
40033
|
}
|
|
39988
|
-
presentPixels(pixels, dims) {
|
|
40034
|
+
presentPixels(pixels, dims, valuePixels) {
|
|
39989
40035
|
this.poolIdx = 1 - this.poolIdx;
|
|
39990
40036
|
const target = this.pool[this.poolIdx];
|
|
39991
40037
|
target.width = dims.width;
|
|
@@ -39995,6 +40041,17 @@ var TextureFrameSeriesAnimator;
|
|
|
39995
40041
|
imgData.data.set(pixels);
|
|
39996
40042
|
ctx.putImageData(imgData, 0, 0);
|
|
39997
40043
|
this.displayedPixels = pixels;
|
|
40044
|
+
if (this.valueCanvas && valuePixels) {
|
|
40045
|
+
this.valueCanvas.width = dims.width;
|
|
40046
|
+
this.valueCanvas.height = dims.height;
|
|
40047
|
+
const valueCtx = this.valueCanvas.getContext("2d");
|
|
40048
|
+
const valueImgData = valueCtx.createImageData(dims.width, dims.height);
|
|
40049
|
+
valueImgData.data.set(valuePixels);
|
|
40050
|
+
valueCtx.putImageData(valueImgData, 0, 0);
|
|
40051
|
+
this.displayedValuePixels = valuePixels;
|
|
40052
|
+
this.valueDims = dims;
|
|
40053
|
+
}
|
|
40054
|
+
this.presentVersion++;
|
|
39998
40055
|
}
|
|
39999
40056
|
}
|
|
40000
40057
|
TextureFrameSeriesAnimator.Animator = Animator;
|
|
@@ -40006,11 +40063,732 @@ var TextureFrameSeriesAnimator;
|
|
|
40006
40063
|
}
|
|
40007
40064
|
})(TextureFrameSeriesAnimator || (TextureFrameSeriesAnimator = {}));
|
|
40008
40065
|
|
|
40066
|
+
/**
|
|
40067
|
+
* Renders a value texture as a displaced, coloured surface.
|
|
40068
|
+
* The source canvas is expected as RGBA: value in R, coverage in A.
|
|
40069
|
+
*/
|
|
40070
|
+
var DisplacedSurfacePrimitive;
|
|
40071
|
+
(function (DisplacedSurfacePrimitive) {
|
|
40072
|
+
// Grid densities a tile can draw at, coarsest first.
|
|
40073
|
+
const TIERS = [32, 64, 128, 192];
|
|
40074
|
+
// Tiles per side the extent is cut into.
|
|
40075
|
+
const TILES_PER_SIDE = 6;
|
|
40076
|
+
// Screen pixels one grid cell should cover. Lower means finer meshes sooner.
|
|
40077
|
+
const TARGET_CELL_PIXELS = 12;
|
|
40078
|
+
// Fraction of its distance to the surface the camera must move before densities are reconsidered.
|
|
40079
|
+
const MOVEMENT_THRESHOLD = 0.12;
|
|
40080
|
+
const RESELECT_INTERVAL_MS = 400;
|
|
40081
|
+
// Skirt depth as a fraction of the displaced range. The sheet is translucent, so an oversized
|
|
40082
|
+
// skirt blends through it and paints a seam down every tile boundary.
|
|
40083
|
+
const SKIRT_FRACTION = 0.015;
|
|
40084
|
+
// Alpha below which a texel counts as no-data and is not drawn at all.
|
|
40085
|
+
const COVERAGE_CUTOFF = 0.35;
|
|
40086
|
+
// With no exaggeration stated, the full value range is drawn as this fraction of the extent's shorter side.
|
|
40087
|
+
const AUTO_RELIEF_FRACTION = 0.02;
|
|
40088
|
+
// Terrain is sampled on this grid and interpolated between samples.
|
|
40089
|
+
// Per-texel sampling would be hundreds of thousands of lookups for a surface whose own data is far coarser than that.
|
|
40090
|
+
const GROUND_SAMPLES_PER_SIDE = 64;
|
|
40091
|
+
// Terrain detail level the samples are taken at.
|
|
40092
|
+
// Most-detailed would fetch every tile under a parcel that can be a hundred kilometres across.
|
|
40093
|
+
const GROUND_SAMPLE_LEVEL = 11;
|
|
40094
|
+
// Height window the packed ground texture covers, wide enough for any terrain on Earth.
|
|
40095
|
+
const GROUND_MIN_METRES = -1000;
|
|
40096
|
+
const GROUND_MAX_METRES = 9000;
|
|
40097
|
+
const DEFAULT_LOW_COLOR = { red: 255, green: 255, blue: 255, alpha: 0.12 };
|
|
40098
|
+
const DEFAULT_HIGH_COLOR = { red: 21, green: 96, blue: 196, alpha: 0.92 };
|
|
40099
|
+
const VERTEX_SHADER_GLSL300 = `
|
|
40100
|
+
in vec3 position3DHigh;
|
|
40101
|
+
in vec3 position3DLow;
|
|
40102
|
+
in vec3 normal;
|
|
40103
|
+
in vec2 st;
|
|
40104
|
+
in float skirt;
|
|
40105
|
+
|
|
40106
|
+
uniform sampler2D u_valueTexture;
|
|
40107
|
+
uniform sampler2D u_groundTexture;
|
|
40108
|
+
uniform float u_valueMin;
|
|
40109
|
+
uniform float u_valueRange;
|
|
40110
|
+
uniform float u_exaggeration;
|
|
40111
|
+
uniform float u_baseHeight;
|
|
40112
|
+
uniform float u_skirtDepth;
|
|
40113
|
+
uniform float u_groundWeight;
|
|
40114
|
+
uniform vec2 u_groundRange;
|
|
40115
|
+
uniform vec2 u_groundSize;
|
|
40116
|
+
|
|
40117
|
+
out vec2 v_st;
|
|
40118
|
+
out float v_value;
|
|
40119
|
+
out float v_coverage;
|
|
40120
|
+
|
|
40121
|
+
float decodeGround(vec2 uv) {
|
|
40122
|
+
// Channels arrive normalised to 0..1, so they go back to bytes before being reassembled.
|
|
40123
|
+
vec3 packed = texture(u_groundTexture, uv).rgb * 255.0;
|
|
40124
|
+
float normalised = dot(packed, vec3(65536.0, 256.0, 1.0)) / 16777215.0;
|
|
40125
|
+
return u_groundRange.x + normalised * (u_groundRange.y - u_groundRange.x);
|
|
40126
|
+
}
|
|
40127
|
+
|
|
40128
|
+
/*
|
|
40129
|
+
* Bilinear by hand, because the height is packed across three channels and hardware filtering would
|
|
40130
|
+
* blend the packing rather than the heights, turning a smooth slope into noise at every texel edge.
|
|
40131
|
+
*/
|
|
40132
|
+
float sampleGround(vec2 uv) {
|
|
40133
|
+
vec2 texel = 1.0 / u_groundSize;
|
|
40134
|
+
vec2 coord = uv * u_groundSize - 0.5;
|
|
40135
|
+
vec2 base = floor(coord);
|
|
40136
|
+
vec2 f = coord - base;
|
|
40137
|
+
vec2 origin = (base + 0.5) * texel;
|
|
40138
|
+
float h00 = decodeGround(origin);
|
|
40139
|
+
float h10 = decodeGround(origin + vec2(texel.x, 0.0));
|
|
40140
|
+
float h01 = decodeGround(origin + vec2(0.0, texel.y));
|
|
40141
|
+
float h11 = decodeGround(origin + texel);
|
|
40142
|
+
return mix(mix(h00, h10, f.x), mix(h01, h11, f.x), f.y);
|
|
40143
|
+
}
|
|
40144
|
+
|
|
40145
|
+
void main() {
|
|
40146
|
+
vec4 texel = texture(u_valueTexture, st);
|
|
40147
|
+
v_st = st;
|
|
40148
|
+
v_value = texel.r;
|
|
40149
|
+
v_coverage = texel.a;
|
|
40150
|
+
|
|
40151
|
+
float metres = u_valueMin + texel.r * u_valueRange;
|
|
40152
|
+
|
|
40153
|
+
// Value zero sits at the polygon's own altitude, plus the terrain underneath when the polygon
|
|
40154
|
+
// is following the ground rather than absolutely positioned.
|
|
40155
|
+
float ground = sampleGround(st) * u_groundWeight;
|
|
40156
|
+
float displacement = u_baseHeight + ground + metres * u_exaggeration * texel.a - skirt * u_skirtDepth;
|
|
40157
|
+
|
|
40158
|
+
// Added to the LOW half of the encoded position: a metre-scale offset added to the high half
|
|
40159
|
+
// would be lost to float32 rounding at an earth radius.
|
|
40160
|
+
vec4 p = czm_translateRelativeToEye(position3DHigh, position3DLow + normal * displacement);
|
|
40161
|
+
gl_Position = czm_modelViewProjectionRelativeToEye * p;
|
|
40162
|
+
}
|
|
40163
|
+
`;
|
|
40164
|
+
const FRAGMENT_SHADER_GLSL300 = `
|
|
40165
|
+
uniform sampler2D u_valueTexture;
|
|
40166
|
+
uniform vec4 u_lowColor;
|
|
40167
|
+
uniform vec4 u_highColor;
|
|
40168
|
+
uniform float u_coverageCutoff;
|
|
40169
|
+
uniform vec2 u_texelSize;
|
|
40170
|
+
uniform float u_valueRange;
|
|
40171
|
+
uniform float u_exaggeration;
|
|
40172
|
+
uniform float u_metresPerTexel;
|
|
40173
|
+
|
|
40174
|
+
in vec2 v_st;
|
|
40175
|
+
in float v_value;
|
|
40176
|
+
in float v_coverage;
|
|
40177
|
+
|
|
40178
|
+
void main() {
|
|
40179
|
+
if (v_coverage < u_coverageCutoff) {
|
|
40180
|
+
discard;
|
|
40181
|
+
}
|
|
40182
|
+
vec4 color = mix(u_lowColor, u_highColor, v_value);
|
|
40183
|
+
|
|
40184
|
+
// Relief shading from the value gradient, so the displacement reads at a distance without
|
|
40185
|
+
// recomputing vertex normals every time the texture changes.
|
|
40186
|
+
float left = texture(u_valueTexture, v_st - vec2(u_texelSize.x, 0.0)).r;
|
|
40187
|
+
float right = texture(u_valueTexture, v_st + vec2(u_texelSize.x, 0.0)).r;
|
|
40188
|
+
float down = texture(u_valueTexture, v_st - vec2(0.0, u_texelSize.y)).r;
|
|
40189
|
+
float up = texture(u_valueTexture, v_st + vec2(0.0, u_texelSize.y)).r;
|
|
40190
|
+
float scale = u_valueRange * u_exaggeration;
|
|
40191
|
+
vec3 n = normalize(vec3((left - right) * scale, (down - up) * scale, 2.0 * u_metresPerTexel));
|
|
40192
|
+
float lambert = clamp(dot(n, normalize(vec3(-0.5, -0.6, 0.62))), 0.0, 1.0);
|
|
40193
|
+
color.rgb *= 0.45 + 0.9 * lambert;
|
|
40194
|
+
|
|
40195
|
+
out_FragColor = vec4(color.rgb, color.a * v_coverage);
|
|
40196
|
+
}
|
|
40197
|
+
`;
|
|
40198
|
+
/*
|
|
40199
|
+
* Rewrites a GLSL 300 es source into the GLSL 100 dialect older Cesium builds author in.
|
|
40200
|
+
*/
|
|
40201
|
+
function toGlsl100(source, isFragment) {
|
|
40202
|
+
let result = source
|
|
40203
|
+
.replace(/\btexture\s*\(/g, "texture2D(")
|
|
40204
|
+
.replace(/^in\s+/gm, isFragment ? "varying " : "attribute ")
|
|
40205
|
+
.replace(/^out\s+/gm, "varying ");
|
|
40206
|
+
if (isFragment) {
|
|
40207
|
+
result = result.replace(/\bout_FragColor\b/g, "gl_FragColor");
|
|
40208
|
+
}
|
|
40209
|
+
return result;
|
|
40210
|
+
}
|
|
40211
|
+
let _glsl300Support = null;
|
|
40212
|
+
/*
|
|
40213
|
+
* Works out which GLSL dialect this host's Cesium authors shaders in.
|
|
40214
|
+
*/
|
|
40215
|
+
function usesGlsl300(context) {
|
|
40216
|
+
if (_glsl300Support !== null) {
|
|
40217
|
+
return _glsl300Support;
|
|
40218
|
+
}
|
|
40219
|
+
let modernizes = false;
|
|
40220
|
+
try {
|
|
40221
|
+
const probe = new ShaderSource({
|
|
40222
|
+
sources: ["varying float v_probe;\nvoid main() { gl_Position = vec4(0.0); }"],
|
|
40223
|
+
includeBuiltIns: false
|
|
40224
|
+
});
|
|
40225
|
+
const combined = probe.createCombinedVertexShader(context);
|
|
40226
|
+
modernizes = combined.indexOf("varying") < 0;
|
|
40227
|
+
}
|
|
40228
|
+
catch (e) {
|
|
40229
|
+
// No probe means no evidence the host rewrites anything, so trust the context alone.
|
|
40230
|
+
modernizes = false;
|
|
40231
|
+
}
|
|
40232
|
+
_glsl300Support = Boolean(context.webgl2) && !modernizes;
|
|
40233
|
+
return _glsl300Support;
|
|
40234
|
+
}
|
|
40235
|
+
/*
|
|
40236
|
+
* Places grid node (fx, fy) on the ellipsoid, walking equal steps of east/north metres.
|
|
40237
|
+
* Cesium maps a polygon's material across a tangent-plane rectangle and the generated raster is
|
|
40238
|
+
* linear in a projected CRS, so stepping in degrees instead would skew the surface against the flat-textured polygon it replaces.
|
|
40239
|
+
*/
|
|
40240
|
+
function makePlacer(extent) {
|
|
40241
|
+
const ellipsoid = Ellipsoid.WGS84;
|
|
40242
|
+
const centre = Cartesian3.fromDegrees((extent.West + extent.East) / 2, (extent.South + extent.North) / 2, 0);
|
|
40243
|
+
const frame = Transforms.eastNorthUpToFixedFrame(centre);
|
|
40244
|
+
const toLocal = Matrix4.inverse(frame, new Matrix4());
|
|
40245
|
+
const southWest = Matrix4.multiplyByPoint(toLocal, Cartesian3.fromDegrees(extent.West, extent.South, 0), new Cartesian3());
|
|
40246
|
+
const northEast = Matrix4.multiplyByPoint(toLocal, Cartesian3.fromDegrees(extent.East, extent.North, 0), new Cartesian3());
|
|
40247
|
+
return (fx, fy) => {
|
|
40248
|
+
const local = new Cartesian3(Math$1.lerp(southWest.x, northEast.x, fx), Math$1.lerp(northEast.y, southWest.y, fy), 0);
|
|
40249
|
+
const world = Matrix4.multiplyByPoint(frame, local, new Cartesian3());
|
|
40250
|
+
return ellipsoid.scaleToGeodeticSurface(world, world);
|
|
40251
|
+
};
|
|
40252
|
+
}
|
|
40253
|
+
/*
|
|
40254
|
+
* Builds one tile's grid, plus a duplicated perimeter ring the shader pushes downwards to cover
|
|
40255
|
+
* the crack where a neighbouring tile at a different density interpolates the shared edge.
|
|
40256
|
+
*/
|
|
40257
|
+
function buildGeometry(extent, resolution, patch) {
|
|
40258
|
+
const cols = resolution;
|
|
40259
|
+
const rows = resolution;
|
|
40260
|
+
const gridCount = (cols + 1) * (rows + 1);
|
|
40261
|
+
const perimeterCount = 2 * (cols + 1) + 2 * (rows + 1) - 4;
|
|
40262
|
+
const count = gridCount + perimeterCount;
|
|
40263
|
+
const positions = new Float64Array(count * 3);
|
|
40264
|
+
const normals = new Float32Array(count * 3);
|
|
40265
|
+
const sts = new Float32Array(count * 2);
|
|
40266
|
+
const skirts = new Float32Array(count);
|
|
40267
|
+
const ellipsoid = Ellipsoid.WGS84;
|
|
40268
|
+
const place = makePlacer(extent);
|
|
40269
|
+
let v = 0;
|
|
40270
|
+
for (let row = 0; row <= rows; row++) {
|
|
40271
|
+
// Texture row 0 is the north edge, so t runs opposite to northing.
|
|
40272
|
+
const fy = Math$1.lerp(patch.v0, patch.v1, row / rows);
|
|
40273
|
+
for (let col = 0; col <= cols; col++) {
|
|
40274
|
+
const fx = Math$1.lerp(patch.u0, patch.u1, col / cols);
|
|
40275
|
+
const position = place(fx, fy);
|
|
40276
|
+
positions[v * 3] = position.x;
|
|
40277
|
+
positions[v * 3 + 1] = position.y;
|
|
40278
|
+
positions[v * 3 + 2] = position.z;
|
|
40279
|
+
const up = ellipsoid.geodeticSurfaceNormal(position, new Cartesian3());
|
|
40280
|
+
normals[v * 3] = up.x;
|
|
40281
|
+
normals[v * 3 + 1] = up.y;
|
|
40282
|
+
normals[v * 3 + 2] = up.z;
|
|
40283
|
+
sts[v * 2] = fx;
|
|
40284
|
+
sts[v * 2 + 1] = fy;
|
|
40285
|
+
v++;
|
|
40286
|
+
}
|
|
40287
|
+
}
|
|
40288
|
+
const indices = new Uint32Array(cols * rows * 6 + perimeterCount * 6);
|
|
40289
|
+
let i = 0;
|
|
40290
|
+
for (let row = 0; row < rows; row++) {
|
|
40291
|
+
for (let col = 0; col < cols; col++) {
|
|
40292
|
+
const topLeft = row * (cols + 1) + col;
|
|
40293
|
+
const topRight = topLeft + 1;
|
|
40294
|
+
const bottomLeft = topLeft + (cols + 1);
|
|
40295
|
+
const bottomRight = bottomLeft + 1;
|
|
40296
|
+
indices[i++] = topLeft;
|
|
40297
|
+
indices[i++] = bottomLeft;
|
|
40298
|
+
indices[i++] = topRight;
|
|
40299
|
+
indices[i++] = topRight;
|
|
40300
|
+
indices[i++] = bottomLeft;
|
|
40301
|
+
indices[i++] = bottomRight;
|
|
40302
|
+
}
|
|
40303
|
+
}
|
|
40304
|
+
// Perimeter walked as one closed loop, so consecutive entries are always neighbours.
|
|
40305
|
+
const loop = [];
|
|
40306
|
+
for (let col = 0; col <= cols; col++) {
|
|
40307
|
+
loop.push(col);
|
|
40308
|
+
}
|
|
40309
|
+
for (let row = 1; row <= rows; row++) {
|
|
40310
|
+
loop.push(row * (cols + 1) + cols);
|
|
40311
|
+
}
|
|
40312
|
+
for (let col = cols - 1; col >= 0; col--) {
|
|
40313
|
+
loop.push(rows * (cols + 1) + col);
|
|
40314
|
+
}
|
|
40315
|
+
for (let row = rows - 1; row >= 1; row--) {
|
|
40316
|
+
loop.push(row * (cols + 1));
|
|
40317
|
+
}
|
|
40318
|
+
const skirtStart = gridCount;
|
|
40319
|
+
loop.forEach((gridIndex, k) => {
|
|
40320
|
+
const target = skirtStart + k;
|
|
40321
|
+
positions[target * 3] = positions[gridIndex * 3];
|
|
40322
|
+
positions[target * 3 + 1] = positions[gridIndex * 3 + 1];
|
|
40323
|
+
positions[target * 3 + 2] = positions[gridIndex * 3 + 2];
|
|
40324
|
+
normals[target * 3] = normals[gridIndex * 3];
|
|
40325
|
+
normals[target * 3 + 1] = normals[gridIndex * 3 + 1];
|
|
40326
|
+
normals[target * 3 + 2] = normals[gridIndex * 3 + 2];
|
|
40327
|
+
sts[target * 2] = sts[gridIndex * 2];
|
|
40328
|
+
sts[target * 2 + 1] = sts[gridIndex * 2 + 1];
|
|
40329
|
+
skirts[target] = 1;
|
|
40330
|
+
});
|
|
40331
|
+
for (let k = 0; k < loop.length; k++) {
|
|
40332
|
+
const nextK = (k + 1) % loop.length;
|
|
40333
|
+
indices[i++] = loop[k];
|
|
40334
|
+
indices[i++] = skirtStart + k;
|
|
40335
|
+
indices[i++] = loop[nextK];
|
|
40336
|
+
indices[i++] = loop[nextK];
|
|
40337
|
+
indices[i++] = skirtStart + k;
|
|
40338
|
+
indices[i++] = skirtStart + nextK;
|
|
40339
|
+
}
|
|
40340
|
+
const geometry = new Geometry({
|
|
40341
|
+
attributes: {
|
|
40342
|
+
position: new GeometryAttribute({
|
|
40343
|
+
componentDatatype: ComponentDatatype.DOUBLE,
|
|
40344
|
+
componentsPerAttribute: 3,
|
|
40345
|
+
values: positions
|
|
40346
|
+
}),
|
|
40347
|
+
normal: new GeometryAttribute({
|
|
40348
|
+
componentDatatype: ComponentDatatype.FLOAT,
|
|
40349
|
+
componentsPerAttribute: 3,
|
|
40350
|
+
values: normals
|
|
40351
|
+
}),
|
|
40352
|
+
st: new GeometryAttribute({
|
|
40353
|
+
componentDatatype: ComponentDatatype.FLOAT,
|
|
40354
|
+
componentsPerAttribute: 2,
|
|
40355
|
+
values: sts
|
|
40356
|
+
}),
|
|
40357
|
+
skirt: new GeometryAttribute({
|
|
40358
|
+
componentDatatype: ComponentDatatype.FLOAT,
|
|
40359
|
+
componentsPerAttribute: 1,
|
|
40360
|
+
values: skirts
|
|
40361
|
+
})
|
|
40362
|
+
},
|
|
40363
|
+
indices: indices,
|
|
40364
|
+
primitiveType: PrimitiveType.TRIANGLES,
|
|
40365
|
+
boundingSphere: BoundingSphere.fromVertices(Array.prototype.slice.call(positions))
|
|
40366
|
+
});
|
|
40367
|
+
// Splits position into the high/low pair Cesium's relative-to-eye shaders expect.
|
|
40368
|
+
GeometryPipeline.encodeAttribute(geometry, "position", "position3DHigh", "position3DLow");
|
|
40369
|
+
return geometry;
|
|
40370
|
+
}
|
|
40371
|
+
class Surface {
|
|
40372
|
+
constructor(options, hasCoverage) {
|
|
40373
|
+
var _a, _b, _c, _d;
|
|
40374
|
+
this.show = true;
|
|
40375
|
+
this.valueSource = null;
|
|
40376
|
+
this.lastPresentVersion = -1;
|
|
40377
|
+
this.texture = null;
|
|
40378
|
+
this.textureDirty = true;
|
|
40379
|
+
this.shaderProgram = null;
|
|
40380
|
+
this.renderState = null;
|
|
40381
|
+
this.destroyed = false;
|
|
40382
|
+
this.lastEyePosition = null;
|
|
40383
|
+
this.lastSelectionMs = -Infinity;
|
|
40384
|
+
this.selectionDirty = true;
|
|
40385
|
+
this.groundTexture = null;
|
|
40386
|
+
this.groundPixels = null;
|
|
40387
|
+
this.groundRequested = false;
|
|
40388
|
+
this.followGround = Boolean(options.followGround);
|
|
40389
|
+
this.terrainProvider = options.terrainProvider || null;
|
|
40390
|
+
this.extent = options.extent;
|
|
40391
|
+
this.source = options.source || null;
|
|
40392
|
+
this.valueMin = (_a = options.valueMin) !== null && _a !== void 0 ? _a : 0;
|
|
40393
|
+
this.valueMax = (_b = options.valueMax) !== null && _b !== void 0 ? _b : 1;
|
|
40394
|
+
this.exaggeration = (_c = options.exaggeration) !== null && _c !== void 0 ? _c : autoExaggeration(this.extent, this.valueMin, this.valueMax);
|
|
40395
|
+
this.baseHeight = (_d = options.baseHeight) !== null && _d !== void 0 ? _d : 0;
|
|
40396
|
+
this.lowColor = toCesiumColor(options.lowColor || DEFAULT_LOW_COLOR);
|
|
40397
|
+
this.highColor = toCesiumColor(options.highColor || DEFAULT_HIGH_COLOR);
|
|
40398
|
+
this.tiles = buildTiles(hasCoverage);
|
|
40399
|
+
}
|
|
40400
|
+
GetFollowsGround() {
|
|
40401
|
+
return this.followGround;
|
|
40402
|
+
}
|
|
40403
|
+
GetBaseHeight() {
|
|
40404
|
+
return this.baseHeight;
|
|
40405
|
+
}
|
|
40406
|
+
GetExaggeration() {
|
|
40407
|
+
return this.exaggeration;
|
|
40408
|
+
}
|
|
40409
|
+
GetExtent() {
|
|
40410
|
+
return this.extent;
|
|
40411
|
+
}
|
|
40412
|
+
SetExaggeration(exaggeration) {
|
|
40413
|
+
this.exaggeration = exaggeration;
|
|
40414
|
+
}
|
|
40415
|
+
SetBaseHeight(baseHeight) {
|
|
40416
|
+
this.baseHeight = baseHeight;
|
|
40417
|
+
}
|
|
40418
|
+
/**
|
|
40419
|
+
* Feeds the surface from an animated frame series.
|
|
40420
|
+
* Height and colour advance with the clock without the caller having to push each frame in.
|
|
40421
|
+
*/
|
|
40422
|
+
BindAnimator(source) {
|
|
40423
|
+
this.valueSource = source;
|
|
40424
|
+
}
|
|
40425
|
+
/**
|
|
40426
|
+
* Tells the surface its source canvas has been redrawn and the texture needs re-uploading.
|
|
40427
|
+
*/
|
|
40428
|
+
MarkSourceDirty() {
|
|
40429
|
+
this.textureDirty = true;
|
|
40430
|
+
}
|
|
40431
|
+
update(frameState) {
|
|
40432
|
+
if (!this.show || this.destroyed || this.tiles.length === 0) {
|
|
40433
|
+
return;
|
|
40434
|
+
}
|
|
40435
|
+
const context = frameState.context;
|
|
40436
|
+
if (this.valueSource) {
|
|
40437
|
+
const canvas = this.valueSource.GetValueCanvas();
|
|
40438
|
+
if (!canvas) {
|
|
40439
|
+
// No frame decoded yet, so there is nothing to displace against.
|
|
40440
|
+
return;
|
|
40441
|
+
}
|
|
40442
|
+
const version = this.valueSource.GetPresentVersion();
|
|
40443
|
+
if (canvas !== this.source || version !== this.lastPresentVersion) {
|
|
40444
|
+
this.source = canvas;
|
|
40445
|
+
this.lastPresentVersion = version;
|
|
40446
|
+
this.textureDirty = true;
|
|
40447
|
+
}
|
|
40448
|
+
}
|
|
40449
|
+
if (!this.source || !this.source.width || !this.source.height) {
|
|
40450
|
+
return;
|
|
40451
|
+
}
|
|
40452
|
+
this.syncTexture(context);
|
|
40453
|
+
this.requestGround();
|
|
40454
|
+
this.syncGroundTexture(context);
|
|
40455
|
+
// A tile needs one mesh before it has a bounding sphere to measure against.
|
|
40456
|
+
for (const tile of this.tiles) {
|
|
40457
|
+
if (!tile.centre) {
|
|
40458
|
+
this.ensureMesh(context, tile, TIERS[0]);
|
|
40459
|
+
}
|
|
40460
|
+
}
|
|
40461
|
+
const nowMs = now();
|
|
40462
|
+
if (this.shouldReselect(frameState, nowMs)) {
|
|
40463
|
+
this.selectTiers(frameState);
|
|
40464
|
+
this.lastSelectionMs = nowMs;
|
|
40465
|
+
this.lastEyePosition = Cartesian3.clone(frameState.camera.positionWC, this.lastEyePosition);
|
|
40466
|
+
this.selectionDirty = false;
|
|
40467
|
+
}
|
|
40468
|
+
for (const tile of this.tiles) {
|
|
40469
|
+
const mesh = this.ensureMesh(context, tile, tile.tier);
|
|
40470
|
+
frameState.commandList.push(this.commandFor(context, tile, mesh));
|
|
40471
|
+
}
|
|
40472
|
+
}
|
|
40473
|
+
isDestroyed() {
|
|
40474
|
+
return this.destroyed;
|
|
40475
|
+
}
|
|
40476
|
+
destroy() {
|
|
40477
|
+
this.destroyed = true;
|
|
40478
|
+
for (const tile of this.tiles) {
|
|
40479
|
+
tile.meshes.forEach((mesh) => mesh.vertexArray.destroy());
|
|
40480
|
+
tile.meshes.clear();
|
|
40481
|
+
tile.command = null;
|
|
40482
|
+
}
|
|
40483
|
+
if (this.shaderProgram) {
|
|
40484
|
+
this.shaderProgram.destroy();
|
|
40485
|
+
this.shaderProgram = null;
|
|
40486
|
+
}
|
|
40487
|
+
if (this.texture) {
|
|
40488
|
+
this.texture.destroy();
|
|
40489
|
+
this.texture = null;
|
|
40490
|
+
}
|
|
40491
|
+
if (this.groundTexture) {
|
|
40492
|
+
this.groundTexture.destroy();
|
|
40493
|
+
this.groundTexture = null;
|
|
40494
|
+
}
|
|
40495
|
+
return undefined;
|
|
40496
|
+
}
|
|
40497
|
+
/*
|
|
40498
|
+
* Samples terrain across the extent once and packs it into a texture the vertex shader reads.
|
|
40499
|
+
*
|
|
40500
|
+
* A texture rather than heights baked into the meshes, because the samples arrive
|
|
40501
|
+
* asynchronously and every cached tile mesh would otherwise have to be rebuilt when they land.
|
|
40502
|
+
*/
|
|
40503
|
+
requestGround() {
|
|
40504
|
+
if (this.groundRequested || !this.followGround) {
|
|
40505
|
+
return;
|
|
40506
|
+
}
|
|
40507
|
+
this.groundRequested = true;
|
|
40508
|
+
const sampler = sampleTerrain;
|
|
40509
|
+
if (!this.terrainProvider || typeof sampler !== "function") {
|
|
40510
|
+
return;
|
|
40511
|
+
}
|
|
40512
|
+
const positions = [];
|
|
40513
|
+
for (let row = 0; row < GROUND_SAMPLES_PER_SIDE; row++) {
|
|
40514
|
+
const fy = row / (GROUND_SAMPLES_PER_SIDE - 1);
|
|
40515
|
+
const latitude = Math$1.lerp(this.extent.North, this.extent.South, fy);
|
|
40516
|
+
for (let col = 0; col < GROUND_SAMPLES_PER_SIDE; col++) {
|
|
40517
|
+
const fx = col / (GROUND_SAMPLES_PER_SIDE - 1);
|
|
40518
|
+
const longitude = Math$1.lerp(this.extent.West, this.extent.East, fx);
|
|
40519
|
+
positions.push(Cartographic.fromDegrees(longitude, latitude));
|
|
40520
|
+
}
|
|
40521
|
+
}
|
|
40522
|
+
Promise.resolve(sampler(this.terrainProvider, GROUND_SAMPLE_LEVEL, positions))
|
|
40523
|
+
.then((sampled) => {
|
|
40524
|
+
if (this.destroyed || !sampled) {
|
|
40525
|
+
return;
|
|
40526
|
+
}
|
|
40527
|
+
const pixels = new Uint8Array(GROUND_SAMPLES_PER_SIDE * GROUND_SAMPLES_PER_SIDE * 4);
|
|
40528
|
+
const span = GROUND_MAX_METRES - GROUND_MIN_METRES;
|
|
40529
|
+
for (let i = 0; i < sampled.length; i++) {
|
|
40530
|
+
const height = sampled[i] && isFinite(sampled[i].height) ? sampled[i].height : 0;
|
|
40531
|
+
const clamped = Math.min(GROUND_MAX_METRES, Math.max(GROUND_MIN_METRES, height));
|
|
40532
|
+
const packed = Math.round(((clamped - GROUND_MIN_METRES) / span) * 16777215);
|
|
40533
|
+
pixels[i * 4] = (packed >> 16) & 255;
|
|
40534
|
+
pixels[i * 4 + 1] = (packed >> 8) & 255;
|
|
40535
|
+
pixels[i * 4 + 2] = packed & 255;
|
|
40536
|
+
pixels[i * 4 + 3] = 255;
|
|
40537
|
+
}
|
|
40538
|
+
this.groundPixels = pixels;
|
|
40539
|
+
})
|
|
40540
|
+
.catch(() => {
|
|
40541
|
+
// Terrain that cannot be sampled leaves the surface on the ellipsoid, which is
|
|
40542
|
+
// where a clamped polygon sat before this existed.
|
|
40543
|
+
});
|
|
40544
|
+
}
|
|
40545
|
+
/*
|
|
40546
|
+
* Uploads whatever ground samples exist, and a flat stand-in until they arrive, so the
|
|
40547
|
+
* shader always has a texture bound whether or not this surface follows the ground.
|
|
40548
|
+
*/
|
|
40549
|
+
syncGroundTexture(context) {
|
|
40550
|
+
if (this.groundTexture && (!this.groundPixels || this.groundTexture.width === GROUND_SAMPLES_PER_SIDE)) {
|
|
40551
|
+
return;
|
|
40552
|
+
}
|
|
40553
|
+
if (this.groundTexture) {
|
|
40554
|
+
this.groundTexture.destroy();
|
|
40555
|
+
}
|
|
40556
|
+
const zero = Math.round(((0 - GROUND_MIN_METRES) / (GROUND_MAX_METRES - GROUND_MIN_METRES)) * 16777215);
|
|
40557
|
+
const size = this.groundPixels ? GROUND_SAMPLES_PER_SIDE : 1;
|
|
40558
|
+
const arrayBufferView = this.groundPixels
|
|
40559
|
+
|| new Uint8Array([(zero >> 16) & 255, (zero >> 8) & 255, zero & 255, 255]);
|
|
40560
|
+
this.groundTexture = new Texture({
|
|
40561
|
+
context,
|
|
40562
|
+
pixelFormat: PixelFormat.RGBA,
|
|
40563
|
+
source: { width: size, height: size, arrayBufferView },
|
|
40564
|
+
flipY: false,
|
|
40565
|
+
sampler: new Sampler({
|
|
40566
|
+
wrapS: TextureWrap.CLAMP_TO_EDGE,
|
|
40567
|
+
wrapT: TextureWrap.CLAMP_TO_EDGE,
|
|
40568
|
+
// Nearest, because the shader interpolates decoded heights itself.
|
|
40569
|
+
minificationFilter: TextureMinificationFilter.NEAREST,
|
|
40570
|
+
magnificationFilter: TextureMagnificationFilter.NEAREST
|
|
40571
|
+
})
|
|
40572
|
+
});
|
|
40573
|
+
}
|
|
40574
|
+
/*
|
|
40575
|
+
* Ground distance between neighbouring texels, so the shading normal is built from a real
|
|
40576
|
+
* slope rather than a made up one.
|
|
40577
|
+
*/
|
|
40578
|
+
metresPerTexel() {
|
|
40579
|
+
const southWest = Cartesian3.fromDegrees(this.extent.West, this.extent.South, 0);
|
|
40580
|
+
const southEast = Cartesian3.fromDegrees(this.extent.East, this.extent.South, 0);
|
|
40581
|
+
const width = Cartesian3.distance(southWest, southEast);
|
|
40582
|
+
return Math.max(1, width / Math.max(1, this.source ? this.source.width : 1));
|
|
40583
|
+
}
|
|
40584
|
+
syncTexture(context) {
|
|
40585
|
+
const sizeChanged = this.texture
|
|
40586
|
+
&& (this.texture.width !== this.source.width || this.texture.height !== this.source.height);
|
|
40587
|
+
if (!this.texture || sizeChanged) {
|
|
40588
|
+
if (this.texture) {
|
|
40589
|
+
this.texture.destroy();
|
|
40590
|
+
}
|
|
40591
|
+
this.texture = new Texture({
|
|
40592
|
+
context,
|
|
40593
|
+
source: this.source,
|
|
40594
|
+
// Cesium flips canvas rows on upload by default, which would put the archive's
|
|
40595
|
+
// row 0 (its north edge) at the south edge and mirror the whole surface.
|
|
40596
|
+
flipY: false,
|
|
40597
|
+
sampler: new Sampler({
|
|
40598
|
+
wrapS: TextureWrap.CLAMP_TO_EDGE,
|
|
40599
|
+
wrapT: TextureWrap.CLAMP_TO_EDGE,
|
|
40600
|
+
minificationFilter: TextureMinificationFilter.LINEAR,
|
|
40601
|
+
magnificationFilter: TextureMagnificationFilter.LINEAR
|
|
40602
|
+
})
|
|
40603
|
+
});
|
|
40604
|
+
this.textureDirty = false;
|
|
40605
|
+
return;
|
|
40606
|
+
}
|
|
40607
|
+
if (this.textureDirty) {
|
|
40608
|
+
this.texture.copyFrom({ source: this.source });
|
|
40609
|
+
this.textureDirty = false;
|
|
40610
|
+
}
|
|
40611
|
+
}
|
|
40612
|
+
ensureMesh(context, tile, tier) {
|
|
40613
|
+
const cached = tile.meshes.get(tier);
|
|
40614
|
+
if (cached) {
|
|
40615
|
+
return cached;
|
|
40616
|
+
}
|
|
40617
|
+
const geometry = buildGeometry(this.extent, tier, tile.patch);
|
|
40618
|
+
const attributeLocations = GeometryPipeline.createAttributeLocations(geometry);
|
|
40619
|
+
const mesh = {
|
|
40620
|
+
attributeLocations,
|
|
40621
|
+
vertexArray: VertexArray.fromGeometry({
|
|
40622
|
+
context,
|
|
40623
|
+
geometry,
|
|
40624
|
+
attributeLocations,
|
|
40625
|
+
bufferUsage: BufferUsage.STATIC_DRAW
|
|
40626
|
+
}),
|
|
40627
|
+
boundingSphere: geometry.boundingSphere
|
|
40628
|
+
};
|
|
40629
|
+
tile.meshes.set(tier, mesh);
|
|
40630
|
+
tile.centre = geometry.boundingSphere.center;
|
|
40631
|
+
tile.radius = geometry.boundingSphere.radius;
|
|
40632
|
+
return mesh;
|
|
40633
|
+
}
|
|
40634
|
+
/*
|
|
40635
|
+
* Picks each tile's density from how much screen it covers.
|
|
40636
|
+
*/
|
|
40637
|
+
selectTiers(frameState) {
|
|
40638
|
+
const camera = frameState.camera;
|
|
40639
|
+
const fovy = camera.frustum && camera.frustum.fovy ? camera.frustum.fovy : Math$1.PI_OVER_THREE;
|
|
40640
|
+
const pixelsPerRadian = frameState.context.drawingBufferHeight / fovy;
|
|
40641
|
+
for (const tile of this.tiles) {
|
|
40642
|
+
if (!tile.centre) {
|
|
40643
|
+
tile.tier = TIERS[0];
|
|
40644
|
+
continue;
|
|
40645
|
+
}
|
|
40646
|
+
const distance = Math.max(1, Cartesian3.distance(camera.positionWC, tile.centre) - tile.radius);
|
|
40647
|
+
const screenPixels = (2 * tile.radius / distance) * pixelsPerRadian;
|
|
40648
|
+
const wanted = screenPixels / TARGET_CELL_PIXELS;
|
|
40649
|
+
let tier = TIERS[0];
|
|
40650
|
+
for (const candidate of TIERS) {
|
|
40651
|
+
if (candidate <= wanted) {
|
|
40652
|
+
tier = candidate;
|
|
40653
|
+
}
|
|
40654
|
+
}
|
|
40655
|
+
tile.tier = tier;
|
|
40656
|
+
}
|
|
40657
|
+
}
|
|
40658
|
+
shouldReselect(frameState, nowMs) {
|
|
40659
|
+
if (this.selectionDirty) {
|
|
40660
|
+
return true;
|
|
40661
|
+
}
|
|
40662
|
+
if (nowMs - this.lastSelectionMs < RESELECT_INTERVAL_MS) {
|
|
40663
|
+
return false;
|
|
40664
|
+
}
|
|
40665
|
+
const eye = frameState.camera.positionWC;
|
|
40666
|
+
if (!this.lastEyePosition) {
|
|
40667
|
+
return true;
|
|
40668
|
+
}
|
|
40669
|
+
const moved = Cartesian3.distance(eye, this.lastEyePosition);
|
|
40670
|
+
const anchor = this.tiles[0].centre;
|
|
40671
|
+
const reference = anchor ? Math.max(1, Cartesian3.distance(eye, anchor)) : 1;
|
|
40672
|
+
return moved / reference > MOVEMENT_THRESHOLD;
|
|
40673
|
+
}
|
|
40674
|
+
commandFor(context, tile, mesh) {
|
|
40675
|
+
if (!this.shaderProgram) {
|
|
40676
|
+
const glsl300 = usesGlsl300(context);
|
|
40677
|
+
this.shaderProgram = ShaderProgram.fromCache({
|
|
40678
|
+
context,
|
|
40679
|
+
vertexShaderSource: glsl300 ? VERTEX_SHADER_GLSL300 : toGlsl100(VERTEX_SHADER_GLSL300, false),
|
|
40680
|
+
fragmentShaderSource: glsl300 ? FRAGMENT_SHADER_GLSL300 : toGlsl100(FRAGMENT_SHADER_GLSL300, true),
|
|
40681
|
+
attributeLocations: mesh.attributeLocations
|
|
40682
|
+
});
|
|
40683
|
+
this.renderState = RenderState.fromCache({
|
|
40684
|
+
depthTest: { enabled: true },
|
|
40685
|
+
// Translucent ramp: blend, and leave the depth buffer to the opaque world.
|
|
40686
|
+
depthMask: false,
|
|
40687
|
+
blending: BlendingState.ALPHA_BLEND,
|
|
40688
|
+
cull: { enabled: false }
|
|
40689
|
+
});
|
|
40690
|
+
}
|
|
40691
|
+
if (!tile.command) {
|
|
40692
|
+
const self = this;
|
|
40693
|
+
tile.command = new DrawCommand({
|
|
40694
|
+
shaderProgram: this.shaderProgram,
|
|
40695
|
+
renderState: this.renderState,
|
|
40696
|
+
pass: Pass.TRANSLUCENT,
|
|
40697
|
+
modelMatrix: Matrix4.IDENTITY,
|
|
40698
|
+
owner: this,
|
|
40699
|
+
uniformMap: {
|
|
40700
|
+
u_valueTexture: () => self.texture,
|
|
40701
|
+
u_groundTexture: () => self.groundTexture,
|
|
40702
|
+
u_groundWeight: () => (self.followGround && self.groundPixels ? 1 : 0),
|
|
40703
|
+
u_groundRange: () => new Cartesian2(GROUND_MIN_METRES, GROUND_MAX_METRES),
|
|
40704
|
+
u_groundSize: () => new Cartesian2(self.groundPixels ? GROUND_SAMPLES_PER_SIDE : 1, self.groundPixels ? GROUND_SAMPLES_PER_SIDE : 1),
|
|
40705
|
+
u_metresPerTexel: () => self.metresPerTexel(),
|
|
40706
|
+
u_valueMin: () => self.valueMin,
|
|
40707
|
+
u_valueRange: () => self.valueMax - self.valueMin,
|
|
40708
|
+
u_exaggeration: () => self.exaggeration,
|
|
40709
|
+
u_baseHeight: () => self.baseHeight,
|
|
40710
|
+
u_skirtDepth: () => Math.max(2, Math.abs(self.valueMax - self.valueMin) * self.exaggeration * SKIRT_FRACTION),
|
|
40711
|
+
u_coverageCutoff: () => COVERAGE_CUTOFF,
|
|
40712
|
+
u_lowColor: () => self.lowColor,
|
|
40713
|
+
u_highColor: () => self.highColor,
|
|
40714
|
+
u_texelSize: () => new Cartesian2(1 / self.source.width, 1 / self.source.height)
|
|
40715
|
+
}
|
|
40716
|
+
});
|
|
40717
|
+
}
|
|
40718
|
+
// Bounding volume belongs to the mesh, so it follows whichever tier is drawing.
|
|
40719
|
+
tile.command.vertexArray = mesh.vertexArray;
|
|
40720
|
+
tile.command.boundingVolume = mesh.boundingSphere;
|
|
40721
|
+
return tile.command;
|
|
40722
|
+
}
|
|
40723
|
+
}
|
|
40724
|
+
DisplacedSurfacePrimitive.Surface = Surface;
|
|
40725
|
+
/*
|
|
40726
|
+
* Cuts the extent into tiles, dropping any the caller says carry no data.
|
|
40727
|
+
*/
|
|
40728
|
+
function buildTiles(hasCoverage) {
|
|
40729
|
+
const tiles = [];
|
|
40730
|
+
for (let row = 0; row < TILES_PER_SIDE; row++) {
|
|
40731
|
+
for (let col = 0; col < TILES_PER_SIDE; col++) {
|
|
40732
|
+
const patch = {
|
|
40733
|
+
u0: col / TILES_PER_SIDE,
|
|
40734
|
+
u1: (col + 1) / TILES_PER_SIDE,
|
|
40735
|
+
v0: row / TILES_PER_SIDE,
|
|
40736
|
+
v1: (row + 1) / TILES_PER_SIDE
|
|
40737
|
+
};
|
|
40738
|
+
if (hasCoverage && !hasCoverage(patch)) {
|
|
40739
|
+
continue;
|
|
40740
|
+
}
|
|
40741
|
+
tiles.push({
|
|
40742
|
+
patch,
|
|
40743
|
+
meshes: new Map(),
|
|
40744
|
+
tier: TIERS[0],
|
|
40745
|
+
command: null,
|
|
40746
|
+
centre: null,
|
|
40747
|
+
radius: 0
|
|
40748
|
+
});
|
|
40749
|
+
}
|
|
40750
|
+
}
|
|
40751
|
+
return tiles;
|
|
40752
|
+
}
|
|
40753
|
+
/**
|
|
40754
|
+
* Exaggeration that makes the full value range stand AUTO_RELIEF_FRACTION of the extent tall.
|
|
40755
|
+
*
|
|
40756
|
+
* Derived from the whole extent rather than per tile: scaling each tile to its own size would
|
|
40757
|
+
* make neighbours disagree along their shared edge and tear the surface apart.
|
|
40758
|
+
* @param extent
|
|
40759
|
+
* @param valueMin
|
|
40760
|
+
* @param valueMax
|
|
40761
|
+
*/
|
|
40762
|
+
function autoExaggeration(extent, valueMin, valueMax) {
|
|
40763
|
+
const range = Math.abs(valueMax - valueMin);
|
|
40764
|
+
if (!(range > 0)) {
|
|
40765
|
+
return 1;
|
|
40766
|
+
}
|
|
40767
|
+
const southWest = Cartesian3.fromDegrees(extent.West, extent.South, 0);
|
|
40768
|
+
const southEast = Cartesian3.fromDegrees(extent.East, extent.South, 0);
|
|
40769
|
+
const northWest = Cartesian3.fromDegrees(extent.West, extent.North, 0);
|
|
40770
|
+
const shorterSide = Math.min(Cartesian3.distance(southWest, southEast), Cartesian3.distance(southWest, northWest));
|
|
40771
|
+
if (!(shorterSide > 0)) {
|
|
40772
|
+
return 1;
|
|
40773
|
+
}
|
|
40774
|
+
return (shorterSide * AUTO_RELIEF_FRACTION) / range;
|
|
40775
|
+
}
|
|
40776
|
+
DisplacedSurfacePrimitive.autoExaggeration = autoExaggeration;
|
|
40777
|
+
function toCesiumColor(color) {
|
|
40778
|
+
return new Color(color.red / 255, color.green / 255, color.blue / 255, color.alpha);
|
|
40779
|
+
}
|
|
40780
|
+
function now() {
|
|
40781
|
+
return typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
40782
|
+
}
|
|
40783
|
+
})(DisplacedSurfacePrimitive || (DisplacedSurfacePrimitive = {}));
|
|
40784
|
+
|
|
40009
40785
|
const TEXTURE_FRAME_SERIES_ANIMATOR_KEY = "TextureFrameSeriesAnimator.Animator";
|
|
40786
|
+
const EXTRUSION_ANIMATOR_KEY = "TextureFrameSeriesAnimator.ExtrusionAnimator";
|
|
40787
|
+
const DISPLACED_SURFACE_KEY = "DisplacedSurfacePrimitive.Surface";
|
|
40010
40788
|
var EntityRenderEnginePolygon;
|
|
40011
40789
|
(function (EntityRenderEnginePolygon) {
|
|
40012
40790
|
async function Render(params) {
|
|
40013
|
-
var _a, _b, _c;
|
|
40791
|
+
var _a, _b, _c, _d;
|
|
40014
40792
|
const entity = params.entity;
|
|
40015
40793
|
const style = params.style;
|
|
40016
40794
|
const pRings = Entity$1.GetValue({
|
|
@@ -40043,14 +40821,36 @@ var EntityRenderEnginePolygon;
|
|
|
40043
40821
|
console.error(`Polygon.Render: failed to resolve textured fill for entity ${((_a = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _a === void 0 ? void 0 : _a.ID) || "<NONE>"}:`, e);
|
|
40044
40822
|
}
|
|
40045
40823
|
}
|
|
40046
|
-
const
|
|
40047
|
-
|
|
40048
|
-
|
|
40049
|
-
|
|
40050
|
-
|
|
40051
|
-
|
|
40052
|
-
|
|
40053
|
-
|
|
40824
|
+
const usesTextureExtrusion = (Boolean(style.useExtrusion) &&
|
|
40825
|
+
style.extrusionType === Style.EPolygonExtrusionType.Texture);
|
|
40826
|
+
let extrusionArchive = null;
|
|
40827
|
+
if (usesTextureExtrusion && !params.offline) {
|
|
40828
|
+
try {
|
|
40829
|
+
const resolved = await resolveTextureValue({
|
|
40830
|
+
api: params.api,
|
|
40831
|
+
textureValue: style.extrusionTexture || style.texture,
|
|
40832
|
+
style,
|
|
40833
|
+
entity,
|
|
40834
|
+
tags: params.tags
|
|
40835
|
+
});
|
|
40836
|
+
extrusionArchive = resolved.frameArchive || null;
|
|
40837
|
+
}
|
|
40838
|
+
catch (e) {
|
|
40839
|
+
console.error(`Polygon.Render: failed to resolve extrusion texture for entity ${((_b = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _b === void 0 ? void 0 : _b.ID) || "<NONE>"}:`, e);
|
|
40840
|
+
}
|
|
40841
|
+
}
|
|
40842
|
+
const drawsDisplacedSurface = Boolean(extrusionArchive);
|
|
40843
|
+
const hasFill = (drawsDisplacedSurface ? true
|
|
40844
|
+
: fillType === Style.EPolygonFillType.Texture
|
|
40845
|
+
? Boolean(textureDataUri || frameArchive || cFillColor.alpha > 0)
|
|
40846
|
+
: cFillColor.alpha > 0);
|
|
40847
|
+
const fillMaterial = drawsDisplacedSurface
|
|
40848
|
+
? Color.WHITE.withAlpha(0)
|
|
40849
|
+
: textureDataUri
|
|
40850
|
+
? new ImageMaterialProperty({ image: textureDataUri, transparent: true })
|
|
40851
|
+
: frameArchive
|
|
40852
|
+
? Color.WHITE.withAlpha(0)
|
|
40853
|
+
: cFillColor;
|
|
40054
40854
|
const lineColorTrace = style.lineColor ? Calculator.TraceGetColor(style.lineColor, entity, params.tags) : { value: null, effective: null };
|
|
40055
40855
|
const bLineColor = lineColorTrace.value;
|
|
40056
40856
|
const cLineColor = bLineColor ? ColorToCColor(bLineColor) : Color.fromCssColorString("rgba(80, 80, 80, 0.8)");
|
|
@@ -40073,19 +40873,21 @@ var EntityRenderEnginePolygon;
|
|
|
40073
40873
|
return null;
|
|
40074
40874
|
}
|
|
40075
40875
|
let heightRef = getHeightRef$3(style);
|
|
40076
|
-
const outerRing = pRings.find(x => x.Facing == Geometry.EPolygonRingType.Boundaries);
|
|
40077
|
-
const points = Geometry.ParsePoints(outerRing === null || outerRing === void 0 ? void 0 : outerRing.LinearRing);
|
|
40876
|
+
const outerRing = pRings.find(x => x.Facing == Geometry$1.EPolygonRingType.Boundaries);
|
|
40877
|
+
const points = Geometry$1.ParsePoints(outerRing === null || outerRing === void 0 ? void 0 : outerRing.LinearRing);
|
|
40078
40878
|
let posses = points.map(x => Cartesian3.fromDegrees(EnsureNumber(x.longitude), EnsureNumber(x.latitude), EnsureNumber(x.altitude)));
|
|
40079
40879
|
Cartes.CloseRing3(posses);
|
|
40080
|
-
const extrusion =
|
|
40880
|
+
const extrusion = drawsDisplacedSurface
|
|
40881
|
+
? { posses, value: undefined, exHeightRef: HeightReference.NONE }
|
|
40882
|
+
: getPolygonExtrusion(entity, params.tags, outerRing, posses, heightRef, style);
|
|
40081
40883
|
posses = extrusion.posses;
|
|
40082
40884
|
posses = CullDuplicateCPosses(posses);
|
|
40083
40885
|
if (posses.length < 4) {
|
|
40084
40886
|
return null;
|
|
40085
40887
|
}
|
|
40086
|
-
const holeRings = pRings.filter(x => x.Facing == Geometry.EPolygonRingType.Hole);
|
|
40888
|
+
const holeRings = pRings.filter(x => x.Facing == Geometry$1.EPolygonRingType.Hole);
|
|
40087
40889
|
const holePosses = holeRings.map((x) => {
|
|
40088
|
-
const points = Geometry.ParsePoints(x.LinearRing);
|
|
40890
|
+
const points = Geometry$1.ParsePoints(x.LinearRing);
|
|
40089
40891
|
let holePosses = points.map(x => Cartesian3.fromDegrees(EnsureNumber(x.longitude), EnsureNumber(x.latitude), EnsureNumber(x.altitude)));
|
|
40090
40892
|
holePosses = CullDuplicateCPosses(holePosses);
|
|
40091
40893
|
Cartes.CloseRing3(holePosses);
|
|
@@ -40209,7 +41011,16 @@ var EntityRenderEnginePolygon;
|
|
|
40209
41011
|
}
|
|
40210
41012
|
// Must run before any material is baked below: the Animator takes over polygon.material, so a bake
|
|
40211
41013
|
// has to know whether it is baking over a live animation or over a disposed one's restored material.
|
|
40212
|
-
const animator = syncTextureFrameArchive(cEntity, frameArchive, params.viewer, style.textureColorMask);
|
|
41014
|
+
const animator = syncTextureFrameArchive(cEntity, drawsDisplacedSurface ? null : frameArchive, params.viewer, style.textureColorMask);
|
|
41015
|
+
syncDisplacedSurface({
|
|
41016
|
+
cEntity,
|
|
41017
|
+
extrusionArchive,
|
|
41018
|
+
viewer: params.viewer,
|
|
41019
|
+
style,
|
|
41020
|
+
entity,
|
|
41021
|
+
heightRef,
|
|
41022
|
+
outerRingPosses: posses
|
|
41023
|
+
});
|
|
40213
41024
|
if (animator) {
|
|
40214
41025
|
CesiumEntityStyler.SetDefaultTextureImage({
|
|
40215
41026
|
entity: cEntity,
|
|
@@ -40269,7 +41080,7 @@ var EntityRenderEnginePolygon;
|
|
|
40269
41080
|
}
|
|
40270
41081
|
}
|
|
40271
41082
|
let borderPosses = posses.map(x => x.clone ? x.clone() : { ...x });
|
|
40272
|
-
let cEntityBorder = (
|
|
41083
|
+
let cEntityBorder = (_d = (_c = params.rendered) === null || _c === void 0 ? void 0 : _c._siblingGraphics) === null || _d === void 0 ? void 0 : _d[0];
|
|
40273
41084
|
cEntity._siblingGraphics = [];
|
|
40274
41085
|
if (!cEntityBorder || ((!cEntityBorder.polyline && units == "px") ||
|
|
40275
41086
|
(!cEntityBorder.corridor && units == "m"))) {
|
|
@@ -40519,12 +41330,13 @@ var EntityRenderEnginePolygon;
|
|
|
40519
41330
|
/**
|
|
40520
41331
|
* Disposes a cEntity's TextureFrameSeriesAnimator.Animator (if any).
|
|
40521
41332
|
*/
|
|
40522
|
-
function DisposeTextureFrameSeriesAnimator(cEntity) {
|
|
41333
|
+
function DisposeTextureFrameSeriesAnimator(cEntity, viewer) {
|
|
40523
41334
|
const existing = cEntity === null || cEntity === void 0 ? void 0 : cEntity[TEXTURE_FRAME_SERIES_ANIMATOR_KEY];
|
|
40524
41335
|
if (existing && !existing.IsDisposed()) {
|
|
40525
41336
|
existing.Dispose();
|
|
40526
41337
|
cEntity[TEXTURE_FRAME_SERIES_ANIMATOR_KEY] = null;
|
|
40527
41338
|
}
|
|
41339
|
+
disposeDisplacedSurface(cEntity, viewer);
|
|
40528
41340
|
}
|
|
40529
41341
|
EntityRenderEnginePolygon.DisposeTextureFrameSeriesAnimator = DisposeTextureFrameSeriesAnimator;
|
|
40530
41342
|
})(EntityRenderEnginePolygon || (EntityRenderEnginePolygon = {}));
|
|
@@ -40638,6 +41450,140 @@ async function getStyle$4(api, entity, styleId) {
|
|
|
40638
41450
|
// Cache of tinted texture data URIs, keyed by resolved url + color mask, so repeated renders of the
|
|
40639
41451
|
// same polygon (or multiple polygons sharing a texture) don't refetch/reprocess the same image.
|
|
40640
41452
|
const _textureCache = new LRUCache(50);
|
|
41453
|
+
/**
|
|
41454
|
+
* Reconciles the displaced surface (and the animator feeding it) against this render's resolved
|
|
41455
|
+
* extrusion texture, creating, reusing or tearing down as the style demands.
|
|
41456
|
+
* @param params
|
|
41457
|
+
*/
|
|
41458
|
+
function syncDisplacedSurface(params) {
|
|
41459
|
+
var _a;
|
|
41460
|
+
const { cEntity, extrusionArchive, viewer, style, entity, heightRef, outerRingPosses } = params;
|
|
41461
|
+
const existingAnimator = cEntity[EXTRUSION_ANIMATOR_KEY];
|
|
41462
|
+
const existingSurface = cEntity[DISPLACED_SURFACE_KEY];
|
|
41463
|
+
// Nothing to draw and nothing left over, which is every polygon that does not use this feature.
|
|
41464
|
+
if (!extrusionArchive && !existingAnimator && !existingSurface) {
|
|
41465
|
+
return;
|
|
41466
|
+
}
|
|
41467
|
+
const reusable = extrusionArchive
|
|
41468
|
+
&& existingAnimator
|
|
41469
|
+
&& !existingAnimator.IsDisposed()
|
|
41470
|
+
&& existingAnimator.GetArchiveUrl() === extrusionArchive.url
|
|
41471
|
+
&& existingSurface
|
|
41472
|
+
&& !existingSurface.isDestroyed();
|
|
41473
|
+
const placement = surfacePlacement(entity, heightRef);
|
|
41474
|
+
// Whether the surface follows terrain is baked into its ground sampling, so a change there has
|
|
41475
|
+
// to rebuild rather than update in place.
|
|
41476
|
+
if (reusable && existingSurface.GetFollowsGround() === placement.followGround) {
|
|
41477
|
+
existingSurface.SetBaseHeight(placement.baseHeight);
|
|
41478
|
+
existingSurface.SetExaggeration((_a = style.extrusionExaggeration) !== null && _a !== void 0 ? _a : DisplacedSurfacePrimitive.autoExaggeration(existingSurface.GetExtent(), extrusionArchive.metadata.ValueMin, extrusionArchive.metadata.ValueMax));
|
|
41479
|
+
return;
|
|
41480
|
+
}
|
|
41481
|
+
disposeDisplacedSurface(cEntity, viewer);
|
|
41482
|
+
if (!extrusionArchive) {
|
|
41483
|
+
return;
|
|
41484
|
+
}
|
|
41485
|
+
const extent = archiveExtent(extrusionArchive.metadata, outerRingPosses);
|
|
41486
|
+
if (!extent) {
|
|
41487
|
+
console.warn("Polygon.Render: extrusion texture has no usable extent, skipping displaced surface.");
|
|
41488
|
+
return;
|
|
41489
|
+
}
|
|
41490
|
+
// Drives the value canvas only: the surface paints the colour, so the polygon's own material is
|
|
41491
|
+
// left transparent rather than animated underneath it.
|
|
41492
|
+
const animator = new TextureFrameSeriesAnimator.Animator({
|
|
41493
|
+
viewer,
|
|
41494
|
+
entity: cEntity,
|
|
41495
|
+
archiveUrl: extrusionArchive.url,
|
|
41496
|
+
frames: extrusionArchive.metadata.Frames,
|
|
41497
|
+
textureColorMask: style.textureColorMask,
|
|
41498
|
+
driveMaterial: false,
|
|
41499
|
+
produceValueCanvas: true
|
|
41500
|
+
});
|
|
41501
|
+
cEntity[EXTRUSION_ANIMATOR_KEY] = animator;
|
|
41502
|
+
const mask = style.textureColorMask;
|
|
41503
|
+
const surface = new DisplacedSurfacePrimitive.Surface({
|
|
41504
|
+
extent,
|
|
41505
|
+
source: null,
|
|
41506
|
+
baseHeight: placement.baseHeight,
|
|
41507
|
+
followGround: placement.followGround,
|
|
41508
|
+
terrainProvider: viewer && viewer.terrainProvider,
|
|
41509
|
+
valueMin: extrusionArchive.metadata.ValueMin,
|
|
41510
|
+
valueMax: extrusionArchive.metadata.ValueMax,
|
|
41511
|
+
exaggeration: style.extrusionExaggeration,
|
|
41512
|
+
lowColor: mask ? Color$1.ColorFromStr(mask.minColor) : null,
|
|
41513
|
+
highColor: mask ? Color$1.ColorFromStr(mask.maxColor) : null
|
|
41514
|
+
});
|
|
41515
|
+
surface.BindAnimator(animator);
|
|
41516
|
+
viewer.scene.primitives.add(surface);
|
|
41517
|
+
cEntity[DISPLACED_SURFACE_KEY] = surface;
|
|
41518
|
+
}
|
|
41519
|
+
/**
|
|
41520
|
+
* Turns the polygon's altitude option into the two things the displaced surface needs:
|
|
41521
|
+
* - how high value zero sits.
|
|
41522
|
+
* - whether that is measured from the terrain or from the ellipsoid.
|
|
41523
|
+
* @param entity
|
|
41524
|
+
* @param heightRef
|
|
41525
|
+
*/
|
|
41526
|
+
function surfacePlacement(entity, heightRef) {
|
|
41527
|
+
const rawAltitude = Entity$1.GetValue({
|
|
41528
|
+
entity,
|
|
41529
|
+
path: ["Bruce", "Location", "altitude"]
|
|
41530
|
+
});
|
|
41531
|
+
const altitude = rawAltitude ? EnsureNumber(rawAltitude) : 0;
|
|
41532
|
+
if (heightRef === HeightReference.CLAMP_TO_GROUND) {
|
|
41533
|
+
return { baseHeight: 0, followGround: true };
|
|
41534
|
+
}
|
|
41535
|
+
if (heightRef === HeightReference.RELATIVE_TO_GROUND) {
|
|
41536
|
+
return { baseHeight: altitude, followGround: true };
|
|
41537
|
+
}
|
|
41538
|
+
return { baseHeight: altitude, followGround: false };
|
|
41539
|
+
}
|
|
41540
|
+
/**
|
|
41541
|
+
* The archive's own extent when it recorded one, otherwise the polygon's own bounds so archives
|
|
41542
|
+
* generated before the extent was written still render somewhere sensible.
|
|
41543
|
+
* @param metadata
|
|
41544
|
+
* @param posses
|
|
41545
|
+
*/
|
|
41546
|
+
function archiveExtent(metadata, posses) {
|
|
41547
|
+
if (metadata.West != null && metadata.East != null && metadata.South != null && metadata.North != null) {
|
|
41548
|
+
return { West: metadata.West, East: metadata.East, South: metadata.South, North: metadata.North };
|
|
41549
|
+
}
|
|
41550
|
+
if (!posses || posses.length === 0) {
|
|
41551
|
+
return null;
|
|
41552
|
+
}
|
|
41553
|
+
const rectangle = Rectangle.fromCartesianArray(posses);
|
|
41554
|
+
return {
|
|
41555
|
+
West: Math$1.toDegrees(rectangle.west),
|
|
41556
|
+
East: Math$1.toDegrees(rectangle.east),
|
|
41557
|
+
South: Math$1.toDegrees(rectangle.south),
|
|
41558
|
+
North: Math$1.toDegrees(rectangle.north)
|
|
41559
|
+
};
|
|
41560
|
+
}
|
|
41561
|
+
/**
|
|
41562
|
+
* Tears down the displaced surface and its feeding animator, if this entity has them.
|
|
41563
|
+
* @param cEntity
|
|
41564
|
+
* @param viewer
|
|
41565
|
+
*/
|
|
41566
|
+
function disposeDisplacedSurface(cEntity, viewer) {
|
|
41567
|
+
const surface = cEntity === null || cEntity === void 0 ? void 0 : cEntity[DISPLACED_SURFACE_KEY];
|
|
41568
|
+
if (surface) {
|
|
41569
|
+
const viewerAlive = viewer && (typeof viewer.isDestroyed !== "function" || !viewer.isDestroyed());
|
|
41570
|
+
if (viewerAlive && viewer.scene && viewer.scene.primitives) {
|
|
41571
|
+
// Removing from the collection destroys the primitive, releasing its meshes and texture.
|
|
41572
|
+
viewer.scene.primitives.remove(surface);
|
|
41573
|
+
}
|
|
41574
|
+
else if (!surface.isDestroyed()) {
|
|
41575
|
+
surface.destroy();
|
|
41576
|
+
}
|
|
41577
|
+
cEntity[DISPLACED_SURFACE_KEY] = null;
|
|
41578
|
+
}
|
|
41579
|
+
const animator = cEntity === null || cEntity === void 0 ? void 0 : cEntity[EXTRUSION_ANIMATOR_KEY];
|
|
41580
|
+
if (animator && !animator.IsDisposed()) {
|
|
41581
|
+
animator.Dispose();
|
|
41582
|
+
}
|
|
41583
|
+
if (cEntity) {
|
|
41584
|
+
cEntity[EXTRUSION_ANIMATOR_KEY] = null;
|
|
41585
|
+
}
|
|
41586
|
+
}
|
|
40641
41587
|
/**
|
|
40642
41588
|
* Reconciles cEntity's TextureFrameSeriesAnimator.Animator (if any) against this render's resolved texture.
|
|
40643
41589
|
* Called once cEntity is fully created/updated and definitely has a `polygon` graphics.
|
|
@@ -40728,8 +41674,15 @@ function extractClientFileIdFromTextureValue(raw) {
|
|
|
40728
41674
|
* @param params
|
|
40729
41675
|
*/
|
|
40730
41676
|
async function resolveTexturedFill(params) {
|
|
40731
|
-
|
|
40732
|
-
|
|
41677
|
+
return resolveTextureValue({ ...params, textureValue: params.style.texture });
|
|
41678
|
+
}
|
|
41679
|
+
/**
|
|
41680
|
+
* Resolves either shape a texture setting can take (a calculated file id/URL, or a search condition)
|
|
41681
|
+
* into a tinted data URI or, when the resolved file is a frame archive, the archive itself.
|
|
41682
|
+
* @param params
|
|
41683
|
+
*/
|
|
41684
|
+
async function resolveTextureValue(params) {
|
|
41685
|
+
const { api, style, entity, tags, textureValue } = params;
|
|
40733
41686
|
if (textureValue && !Array.isArray(textureValue)) {
|
|
40734
41687
|
return resolveTextureCondition({ api, condition: textureValue });
|
|
40735
41688
|
}
|
|
@@ -41518,7 +42471,7 @@ var EntityRenderEngine;
|
|
|
41518
42471
|
entity._dispose();
|
|
41519
42472
|
entity._dispose = null;
|
|
41520
42473
|
}
|
|
41521
|
-
EntityRenderEnginePolygon.DisposeTextureFrameSeriesAnimator(entity);
|
|
42474
|
+
EntityRenderEnginePolygon.DisposeTextureFrameSeriesAnimator(entity, viewer);
|
|
41522
42475
|
if (entity._parentEntity && !ignoreParent) {
|
|
41523
42476
|
doRemove({
|
|
41524
42477
|
viewer,
|
|
@@ -42269,7 +43222,7 @@ var StyleUtils;
|
|
|
42269
43222
|
StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
|
|
42270
43223
|
})(StyleUtils || (StyleUtils = {}));
|
|
42271
43224
|
|
|
42272
|
-
const VERSION = "7.1.
|
|
43225
|
+
const VERSION = "7.1.4";
|
|
42273
43226
|
/**
|
|
42274
43227
|
* Updates the environment instance used by bruce-cesium to one specified.
|
|
42275
43228
|
* This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
|
|
@@ -42286,5 +43239,5 @@ const getENVIRONMENT = () => {
|
|
|
42286
43239
|
return ENVIRONMENT;
|
|
42287
43240
|
};
|
|
42288
43241
|
|
|
42289
|
-
export { VERSION, setENVIRONMENT, getENVIRONMENT, CesiumAnimatedInOut, CesiumAnimatedProperty, isStyleChanged, isOutlineChanged$1 as isOutlineChanged, StyleEffective, EntityRenderEngine, EntityRenderEngineModel3d, EntityRenderEnginePoint, EntityRenderEnginePolygon, EntityRenderEnginePolyline, MenuItemCreator, MenuItemManager, CesiumParabola, EntityLabel, LiveCursor, SharedGetters, DataSourceStaticKmlManager, DataLabRenderManager, EntitiesIdsRenderManager, EntitiesLoadedRenderManager, EntitiesRenderManager, EntityRenderManager, AssemblyRenderManager, GoogleSearchRenderManager, RelationsRenderManager, RenderManager, TilesetArbRenderManager, TilesetCadRenderManager, TilesetEntitiesRenderManager, TilesetGooglePhotosRenderManager, TilesetOsmRenderManager, TilesetPointcloudRenderManager, TileRenderEngine, createTileset, TilesetRenderEngine, ViewRenderEngine, VisualRegisterCuller, VisualsRegister, XGridsRenderEngine, CesiumEntityStyler, DrawingUtils, EntityUtils, MeasureUtils, StyleUtils, CESIUM_INSPECTOR_KEY, CESIUM_TIMELINE_KEY, CESIUM_TIMELINE_LIVE_KEY, CESIUM_TIMELINE_LIVE_PADDING_KEY, CESIUM_TIMELINE_INTERVAL_KEY, CESIUM_MODEL_SPACE_KEY, DEFAULT_LIVE_PADDING_SECONDS, ViewUtils, CesiumViewMonitor, ViewGroundArea, ViewerEventTracker, ViewerUtils, Draw3dPolygon, Draw3dPolyline, MeasureCreator, Walkthrough, WidgetControlViewBar, WidgetControlViewBarSearch, WidgetLeftPanelTab, WidgetLeftPanelTabBookmarks, WidgetLeftPanelTabDashboard, EMenuItemState, WidgetLeftPanelTabMenuItems, Widget, VIEWER_BOOKMARKS_WIDGET_KEY, WidgetBookmarks, WidgetBranding, WidgetCursorBar, WidgetEmbeddedInfoView, WidgetInfoView, VIEWER_LEFT_PANEL_WIDGET_KEY, VIEWER_LEFT_PANEL_CSS_VAR_LEFT, WidgetLeftPanel, WidgetNavCompass$$1 as WidgetNavCompass, VIEWER_VIEW_BAR_WIDGET_KEY, WidgetViewBar };
|
|
43242
|
+
export { VERSION, setENVIRONMENT, getENVIRONMENT, CesiumAnimatedInOut, DisplacedSurfacePrimitive, CesiumAnimatedProperty, isStyleChanged, isOutlineChanged$1 as isOutlineChanged, StyleEffective, EntityRenderEngine, EntityRenderEngineModel3d, EntityRenderEnginePoint, EntityRenderEnginePolygon, EntityRenderEnginePolyline, MenuItemCreator, MenuItemManager, CesiumParabola, EntityLabel, LiveCursor, SharedGetters, DataSourceStaticKmlManager, DataLabRenderManager, EntitiesIdsRenderManager, EntitiesLoadedRenderManager, EntitiesRenderManager, EntityRenderManager, AssemblyRenderManager, GoogleSearchRenderManager, RelationsRenderManager, RenderManager, TilesetArbRenderManager, TilesetCadRenderManager, TilesetEntitiesRenderManager, TilesetGooglePhotosRenderManager, TilesetOsmRenderManager, TilesetPointcloudRenderManager, TileRenderEngine, createTileset, TilesetRenderEngine, ViewRenderEngine, VisualRegisterCuller, VisualsRegister, XGridsRenderEngine, CesiumEntityStyler, DrawingUtils, EntityUtils, MeasureUtils, StyleUtils, CESIUM_INSPECTOR_KEY, CESIUM_TIMELINE_KEY, CESIUM_TIMELINE_LIVE_KEY, CESIUM_TIMELINE_LIVE_PADDING_KEY, CESIUM_TIMELINE_INTERVAL_KEY, CESIUM_MODEL_SPACE_KEY, DEFAULT_LIVE_PADDING_SECONDS, ViewUtils, CesiumViewMonitor, ViewGroundArea, ViewerEventTracker, ViewerUtils, Draw3dPolygon, Draw3dPolyline, MeasureCreator, Walkthrough, WidgetControlViewBar, WidgetControlViewBarSearch, WidgetLeftPanelTab, WidgetLeftPanelTabBookmarks, WidgetLeftPanelTabDashboard, EMenuItemState, WidgetLeftPanelTabMenuItems, Widget, VIEWER_BOOKMARKS_WIDGET_KEY, WidgetBookmarks, WidgetBranding, WidgetCursorBar, WidgetEmbeddedInfoView, WidgetInfoView, VIEWER_LEFT_PANEL_WIDGET_KEY, VIEWER_LEFT_PANEL_CSS_VAR_LEFT, WidgetLeftPanel, WidgetNavCompass$$1 as WidgetNavCompass, VIEWER_VIEW_BAR_WIDGET_KEY, WidgetViewBar };
|
|
42290
43243
|
//# sourceMappingURL=bruce-cesium.es5.js.map
|