bruce-cesium 7.3.6 → 7.3.8
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 +401 -10
- package/dist/bruce-cesium.es5.js.map +1 -1
- package/dist/bruce-cesium.umd.js +399 -8
- 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 +311 -3
- package/dist/lib/rendering/displaced-surface-primitive.js.map +1 -1
- package/dist/lib/rendering/entity-render-engine-polygon.js +27 -0
- package/dist/lib/rendering/entity-render-engine-polygon.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/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/lib/utils/cesium-entity-styler.js +6 -0
- package/dist/lib/utils/cesium-entity-styler.js.map +1 -1
- package/dist/lib/utils/drawing-utils.js +1 -1
- package/dist/lib/utils/drawing-utils.js.map +1 -1
- package/dist/types/bruce-cesium.d.ts +1 -1
- package/dist/types/rendering/displaced-surface-primitive.d.ts +33 -0
- package/dist/types/rendering/entity-render-engine-polygon.d.ts +6 -0
- package/dist/types/rendering/entity-render-engine.d.ts +9 -0
- package/dist/types/rendering/visuals-register.d.ts +5 -0
- package/dist/types/utils/cesium-entity-styler.d.ts +3 -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, HeightReference, DistanceDisplayCondition, Math as Math$1,
|
|
3
|
-
import { Cartes, LRUCache, ProjectViewTile, ENVIRONMENT, Calculator,
|
|
2
|
+
import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, HeightReference, DistanceDisplayCondition, 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, ClassificationType, ArcType, CornerType, ShadowMode, ConstantPositionProperty, HorizontalOrigin, VerticalOrigin, ColorBlendMode, Model, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Rectangle, SceneTransforms, 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, Intersect, OrthographicFrustum, EasingFunction, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, PolygonPipeline, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, CustomDataSource, CesiumInspector, ClockRange, DynamicEnvironmentMapManager, ScreenSpaceEventHandler, ScreenSpaceEventType, GeometryInstance, Fullscreen, CzmlDataSource } from 'cesium';
|
|
3
|
+
import { Cartes, LRUCache, ProjectViewTile, ENVIRONMENT, Calculator, Carto, Entity as Entity$1, EntityTag, EntityType, Geometry as Geometry$1, ObjectUtils, Style, Api, ClientFile, EntityLod, Bounds, ClientFileValueMap, Color as Color$1, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, BruceEvent, EntityCoords, DataLab, DelayQueue, AccountConcept, RecordChangeFeed, EntityRelation, BruceApi, EntitySource, ProgramKey, ProjectViewLegacyTile, Camera, Account, AccountLimits, Session, UrlUtils, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, ProjectViewBookmarkGroup, EntityRelationType, EntityHistoricData } from 'bruce-models';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Ensures a number is returned from a given value.
|
|
@@ -400,7 +400,7 @@ var DrawingUtils;
|
|
|
400
400
|
function EnsurePosHeight(params) {
|
|
401
401
|
let { pos3d, viewer, desiredHeightRef, heightRef } = params;
|
|
402
402
|
const carto = Cartes.ValidateCartes3(pos3d) ? Cartographic.fromCartesian(pos3d) : null;
|
|
403
|
-
if (!
|
|
403
|
+
if (!carto) {
|
|
404
404
|
return pos3d;
|
|
405
405
|
}
|
|
406
406
|
if (heightRef == null) {
|
|
@@ -3346,6 +3346,12 @@ var CesiumEntityStyler;
|
|
|
3346
3346
|
}
|
|
3347
3347
|
}
|
|
3348
3348
|
CesiumEntityStyler.Refresh = Refresh;
|
|
3349
|
+
// Read the unselected colour even while a selection animation is running.
|
|
3350
|
+
function GetDefaultColor(viewer, graphic) {
|
|
3351
|
+
var _a;
|
|
3352
|
+
return (_a = getColor$1(viewer, "default", graphic)) === null || _a === void 0 ? void 0 : _a.clone();
|
|
3353
|
+
}
|
|
3354
|
+
CesiumEntityStyler.GetDefaultColor = GetDefaultColor;
|
|
3349
3355
|
function BakeDefaultColor(params) {
|
|
3350
3356
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
3351
3357
|
let { viewer, entity, override, colors, refresh } = params;
|
|
@@ -9508,6 +9514,14 @@ var VisualsRegister;
|
|
|
9508
9514
|
}
|
|
9509
9515
|
};
|
|
9510
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
|
+
}
|
|
9511
9525
|
/**
|
|
9512
9526
|
* Locates a visual corresponding to a given entity id.
|
|
9513
9527
|
* If no menu item id is provided, then it will pick the "best" one.
|
|
@@ -12679,6 +12693,11 @@ var EntitiesRenderManager;
|
|
|
12679
12693
|
optimizeTolerance: this.item.optimizeTolerance,
|
|
12680
12694
|
});
|
|
12681
12695
|
if (this.disposed) {
|
|
12696
|
+
EntityRenderEngine.RemoveAll({
|
|
12697
|
+
viewer: this.viewer,
|
|
12698
|
+
entities: cEntities,
|
|
12699
|
+
register: this.visualsManager
|
|
12700
|
+
});
|
|
12682
12701
|
this.doDispose();
|
|
12683
12702
|
return;
|
|
12684
12703
|
}
|
|
@@ -13686,6 +13705,11 @@ var EntitiesLoadedRenderManager;
|
|
|
13686
13705
|
force
|
|
13687
13706
|
});
|
|
13688
13707
|
if (this.disposed) {
|
|
13708
|
+
EntityRenderEngine.RemoveAll({
|
|
13709
|
+
viewer: this.viewer,
|
|
13710
|
+
entities: cEntities,
|
|
13711
|
+
register: this.visualsManager
|
|
13712
|
+
});
|
|
13689
13713
|
this.visualsManager.RemoveRegos({
|
|
13690
13714
|
menuItemId: this.item.id
|
|
13691
13715
|
});
|
|
@@ -14130,10 +14154,15 @@ var EntitiesIdsRenderManager;
|
|
|
14130
14154
|
zoomControl: this.item.CameraZoomSettings,
|
|
14131
14155
|
force: force || changed
|
|
14132
14156
|
});
|
|
14157
|
+
if (this.disposed) {
|
|
14158
|
+
EntityRenderEngine.RemoveAll({
|
|
14159
|
+
viewer: this.viewer,
|
|
14160
|
+
entities: cEntities,
|
|
14161
|
+
register: this.visualsManager
|
|
14162
|
+
});
|
|
14163
|
+
return;
|
|
14164
|
+
}
|
|
14133
14165
|
for (let i = 0; i < entities.length; i++) {
|
|
14134
|
-
if (this.disposed) {
|
|
14135
|
-
break;
|
|
14136
|
-
}
|
|
14137
14166
|
const entity = entities[i];
|
|
14138
14167
|
const id = entity.Bruce.ID;
|
|
14139
14168
|
const cEntity = cEntities.get(id);
|
|
@@ -19514,6 +19543,11 @@ var DataLabRenderManager;
|
|
|
19514
19543
|
force
|
|
19515
19544
|
});
|
|
19516
19545
|
if (this.disposed) {
|
|
19546
|
+
EntityRenderEngine.RemoveAll({
|
|
19547
|
+
viewer: this.viewer,
|
|
19548
|
+
entities: cEntities,
|
|
19549
|
+
register: this.visualsManager
|
|
19550
|
+
});
|
|
19517
19551
|
return;
|
|
19518
19552
|
}
|
|
19519
19553
|
for (let i = 0; i < entities.length; i++) {
|
|
@@ -43589,6 +43623,44 @@ var DisplacedSurfacePrimitive;
|
|
|
43589
43623
|
const MASK_TEXTURE_MAX_SIDE = 1024;
|
|
43590
43624
|
// Stands in for "no floor" and "no clearance", far below anything the sheet can reach.
|
|
43591
43625
|
const NO_LIMIT_METRES = -1e6;
|
|
43626
|
+
// Ripple layers to cycle across the field's own repeat.
|
|
43627
|
+
const WATER_WAVES = [
|
|
43628
|
+
{ x: 2, y: 1, amplitude: 6.4 },
|
|
43629
|
+
{ x: 1, y: 4, amplitude: 3.9 },
|
|
43630
|
+
{ x: -6, y: 4, amplitude: 2.5 },
|
|
43631
|
+
{ x: 9, y: -9, amplitude: 1.6 },
|
|
43632
|
+
{ x: -14, y: 18, amplitude: 1.0 },
|
|
43633
|
+
{ x: 38, y: 15, amplitude: 0.63 },
|
|
43634
|
+
{ x: -30, y: 68, amplitude: 0.39 },
|
|
43635
|
+
{ x: 120, y: 57, amplitude: 0.245 }
|
|
43636
|
+
];
|
|
43637
|
+
const waveCycles = (wave) => Math.hypot(wave.x, wave.y);
|
|
43638
|
+
// Which layer the wavelength setting names. The ladder runs either side of it.
|
|
43639
|
+
const WATER_BASE_WAVE = 4;
|
|
43640
|
+
// How many metres the field repeats over, as a multiple of the settings' own wavelength.
|
|
43641
|
+
const WATER_PERIOD_IN_WAVELENGTHS = waveCycles(WATER_WAVES[WATER_BASE_WAVE]);
|
|
43642
|
+
/*
|
|
43643
|
+
* How much of the surface's total slope each layer carries, which is its amplitude against its
|
|
43644
|
+
* wave number rather than its amplitude alone.
|
|
43645
|
+
*/
|
|
43646
|
+
const WATER_WAVE_SLOPES = (() => {
|
|
43647
|
+
const raw = WATER_WAVES.map((wave) => wave.amplitude * waveCycles(wave));
|
|
43648
|
+
const total = raw.reduce((sum, value) => sum + value, 0);
|
|
43649
|
+
return raw.map((value) => value / total);
|
|
43650
|
+
})();
|
|
43651
|
+
// Screen pixels a ripple layer needs to span before it counts at all, and before it counts in
|
|
43652
|
+
// full. Below the first it is finer than the pixel grid and turns into moire that crawls as the
|
|
43653
|
+
// camera moves; the gap between the two is there so a layer leaves gradually rather than
|
|
43654
|
+
// stepping out and leaving a visible change in the surface.
|
|
43655
|
+
const WATER_MIN_PIXELS_PER_WAVE = 6;
|
|
43656
|
+
const WATER_FULL_PIXELS_PER_WAVE = 16;
|
|
43657
|
+
const DEFAULT_WATER_WAVELENGTH_METRES = 26;
|
|
43658
|
+
const DEFAULT_WATER_AMPLITUDE_METRES = 0.11;
|
|
43659
|
+
const DEFAULT_WATER_SPEED_METRES_PER_SECOND = 0.6;
|
|
43660
|
+
const DEFAULT_WATER_REFLECTIVITY = 0.72;
|
|
43661
|
+
const DEFAULT_WATER_GLOSSINESS = 140;
|
|
43662
|
+
const DEFAULT_WATER_SUN_INTENSITY = 1;
|
|
43663
|
+
const DEFAULT_WATER_SKY_COLOR = { red: 150, green: 186, blue: 214, alpha: 1 };
|
|
43592
43664
|
const GROUND_MIN_METRES = -1000;
|
|
43593
43665
|
const GROUND_MAX_METRES = 9000;
|
|
43594
43666
|
const DEFAULT_LOW_COLOR = { red: 255, green: 255, blue: 255, alpha: 0.12 };
|
|
@@ -43624,10 +43696,21 @@ uniform vec2 u_maskGroundSize;
|
|
|
43624
43696
|
uniform vec4 u_extentDegrees;
|
|
43625
43697
|
uniform vec4 u_maskGroundDegrees;
|
|
43626
43698
|
uniform float u_coverageCutoffVertex;
|
|
43699
|
+
//#water
|
|
43700
|
+
uniform vec2 u_extentMetres;
|
|
43701
|
+
uniform vec2 u_waveOrigin;
|
|
43702
|
+
//#endwater
|
|
43627
43703
|
|
|
43628
43704
|
out vec2 v_st;
|
|
43629
43705
|
out float v_value;
|
|
43630
43706
|
out float v_coverage;
|
|
43707
|
+
//#water
|
|
43708
|
+
out vec3 v_positionEC;
|
|
43709
|
+
out vec3 v_eastEC;
|
|
43710
|
+
out vec3 v_northEC;
|
|
43711
|
+
out vec3 v_upEC;
|
|
43712
|
+
out vec2 v_waveMetres;
|
|
43713
|
+
//#endwater
|
|
43631
43714
|
|
|
43632
43715
|
float decodeGround(vec2 uv) {
|
|
43633
43716
|
// Channels arrive normalised to 0..1, so they go back to bytes before being reassembled.
|
|
@@ -43746,6 +43829,19 @@ void main() {
|
|
|
43746
43829
|
// Added to the LOW half of the encoded position: a metre-scale offset added to the high half
|
|
43747
43830
|
// would be lost to float32 rounding at an earth radius.
|
|
43748
43831
|
vec4 p = czm_translateRelativeToEye(position3DHigh, position3DLow + normal * displacement);
|
|
43832
|
+
|
|
43833
|
+
//#water
|
|
43834
|
+
// The local frame at this vertex so a shading normal built in east/north/up meters can be turned into something usable.
|
|
43835
|
+
v_upEC = czm_normal * normal;
|
|
43836
|
+
vec3 east = normalize(cross(vec3(0.0, 0.0, 1.0), normal));
|
|
43837
|
+
v_eastEC = czm_normal * east;
|
|
43838
|
+
v_northEC = czm_normal * cross(normal, east);
|
|
43839
|
+
v_positionEC = (czm_modelViewRelativeToEye * p).xyz;
|
|
43840
|
+
|
|
43841
|
+
// Where this vertex sits in the ripple field, in metres from an origin that follows the camera.
|
|
43842
|
+
v_waveMetres = st * u_extentMetres - u_waveOrigin;
|
|
43843
|
+
//#endwater
|
|
43844
|
+
|
|
43749
43845
|
gl_Position = czm_modelViewProjectionRelativeToEye * p;
|
|
43750
43846
|
}
|
|
43751
43847
|
`;
|
|
@@ -43758,10 +43854,30 @@ uniform float u_valuePacked;
|
|
|
43758
43854
|
uniform float u_valueRange;
|
|
43759
43855
|
uniform float u_exaggeration;
|
|
43760
43856
|
uniform float u_metresPerTexel;
|
|
43857
|
+
//#water
|
|
43858
|
+
uniform float u_waterWavelength;
|
|
43859
|
+
uniform float u_waterAmplitude;
|
|
43860
|
+
uniform float u_waterReflectivity;
|
|
43861
|
+
uniform float u_waterGloss;
|
|
43862
|
+
uniform float u_waterSun;
|
|
43863
|
+
uniform vec3 u_waterSky;
|
|
43864
|
+
// One scrolled phase per ripple layer, wrapped into a turn on the CPU.
|
|
43865
|
+
uniform vec4 u_wavePhase;
|
|
43866
|
+
uniform vec4 u_wavePhaseB;
|
|
43867
|
+
// Metres the whole ripple field repeats over.
|
|
43868
|
+
uniform float u_wavePeriod;
|
|
43869
|
+
//#endwater
|
|
43761
43870
|
|
|
43762
43871
|
in vec2 v_st;
|
|
43763
43872
|
in float v_value;
|
|
43764
43873
|
in float v_coverage;
|
|
43874
|
+
//#water
|
|
43875
|
+
in vec3 v_positionEC;
|
|
43876
|
+
in vec3 v_eastEC;
|
|
43877
|
+
in vec3 v_northEC;
|
|
43878
|
+
in vec3 v_upEC;
|
|
43879
|
+
in vec2 v_waveMetres;
|
|
43880
|
+
//#endwater
|
|
43765
43881
|
|
|
43766
43882
|
/*
|
|
43767
43883
|
* Scaled per channel for the same reason the vertex shader's decode is: reassembling the pair reaches
|
|
@@ -43773,6 +43889,84 @@ float valueAt(vec2 uv) {
|
|
|
43773
43889
|
return mix(texel.r, packed16, u_valuePacked);
|
|
43774
43890
|
}
|
|
43775
43891
|
|
|
43892
|
+
//#water
|
|
43893
|
+
/*
|
|
43894
|
+
* Slope of the ripple field at a point, in metres of rise per metre travelled.
|
|
43895
|
+
*/
|
|
43896
|
+
vec2 rippleSlope(vec2 metres, float metresPerPixel, out float detail) {
|
|
43897
|
+
vec2 slope = vec2(0.0);
|
|
43898
|
+
detail = 0.0;
|
|
43899
|
+
float amplitude = u_waterAmplitude * 0.5;
|
|
43900
|
+
${WATER_WAVES.map((wave, index) => {
|
|
43901
|
+
const cycles = waveCycles(wave);
|
|
43902
|
+
return `
|
|
43903
|
+
{
|
|
43904
|
+
vec2 lattice = vec2(${wave.x.toFixed(1)}, ${wave.y.toFixed(1)});
|
|
43905
|
+
float k = 6.2831853 * ${cycles.toFixed(4)} / u_wavePeriod;
|
|
43906
|
+
float pixels = u_wavePeriod / ${cycles.toFixed(4)} / max(metresPerPixel, 1e-6);
|
|
43907
|
+
float weight = smoothstep(${WATER_MIN_PIXELS_PER_WAVE.toFixed(1)},
|
|
43908
|
+
${WATER_FULL_PIXELS_PER_WAVE.toFixed(1)}, pixels);
|
|
43909
|
+
vec2 direction = lattice / ${cycles.toFixed(4)};
|
|
43910
|
+
float phase = 6.2831853 * dot(lattice, metres) / u_wavePeriod
|
|
43911
|
+
+ ${index < 4 ? `u_wavePhase[${index}]` : `u_wavePhaseB[${index - 4}]`};
|
|
43912
|
+
slope += direction * (amplitude * ${wave.amplitude.toFixed(4)} * k * cos(phase) * weight);
|
|
43913
|
+
detail += ${WATER_WAVE_SLOPES[index].toFixed(5)} * weight;
|
|
43914
|
+
}`;
|
|
43915
|
+
}).join("")}
|
|
43916
|
+
return slope;
|
|
43917
|
+
}
|
|
43918
|
+
|
|
43919
|
+
/*
|
|
43920
|
+
* The sheet shaded as a water surface: a flat body colour seen through a sun glint and a grazing
|
|
43921
|
+
* sky reflection, with the ripple field standing in for a geometry it is far too fine to carry.
|
|
43922
|
+
*/
|
|
43923
|
+
vec4 water(vec3 relief, vec4 color) {
|
|
43924
|
+
float metresPerPixel = czm_metersPerPixel(vec4(v_positionEC, 1.0));
|
|
43925
|
+
float detail;
|
|
43926
|
+
vec2 slope = rippleSlope(v_waveMetres, metresPerPixel, detail);
|
|
43927
|
+
|
|
43928
|
+
// relief arrives normalised, so its horizontal part over its vertical part is the slope it means.
|
|
43929
|
+
vec2 reliefSlope = relief.xy / max(relief.z, 1e-3);
|
|
43930
|
+
vec3 local = normalize(vec3(-(slope + reliefSlope), 1.0));
|
|
43931
|
+
vec3 normalEC = normalize(local.x * v_eastEC + local.y * v_northEC + local.z * v_upEC);
|
|
43932
|
+
|
|
43933
|
+
vec3 view = normalize(-v_positionEC);
|
|
43934
|
+
// Drawn with culling off, so the underside of the sheet arrives with its normal pointing away.
|
|
43935
|
+
normalEC = dot(normalEC, view) < 0.0 ? -normalEC : normalEC;
|
|
43936
|
+
vec3 sun = normalize(czm_sunDirectionEC);
|
|
43937
|
+
|
|
43938
|
+
// Water at a grazing angle is almost a mirror and water looked straight down is almost clear.
|
|
43939
|
+
// That split is the single strongest cue that a blue surface is wet, more than any ripple is.
|
|
43940
|
+
float fresnel = u_waterReflectivity
|
|
43941
|
+
* (0.02 + 0.98 * pow(1.0 - clamp(dot(normalEC, view), 0.0, 1.0), 5.0));
|
|
43942
|
+
|
|
43943
|
+
// Softened by the roughness the shading has had to give up.
|
|
43944
|
+
fresnel *= mix(0.55, 1.0, detail);
|
|
43945
|
+
|
|
43946
|
+
// Where the ripples have faded out the surface is not smooth, it is rough below one pixel, so
|
|
43947
|
+
// the glint has to widen to cover what the normal no longer says.
|
|
43948
|
+
float gloss = mix(u_waterGloss * 0.12, u_waterGloss, detail);
|
|
43949
|
+
vec3 halfway = normalize(sun + view);
|
|
43950
|
+
// Weighted by the same reflectance as the sky, because a glint is a reflection too.
|
|
43951
|
+
float glint = pow(max(dot(normalEC, halfway), 0.0), gloss) * u_waterSun * fresnel;
|
|
43952
|
+
float lambert = clamp(dot(normalEC, sun), 0.0, 1.0);
|
|
43953
|
+
|
|
43954
|
+
vec3 body = color.rgb * (0.55 + 0.6 * lambert);
|
|
43955
|
+
vec3 lit = min(mix(body, u_waterSky, fresnel) + vec3(glint), vec3(1.0));
|
|
43956
|
+
|
|
43957
|
+
/*
|
|
43958
|
+
* The same fog the globe under it is already drawing with.
|
|
43959
|
+
*/
|
|
43960
|
+
lit = czm_fog(length(v_positionEC), lit, u_waterSky);
|
|
43961
|
+
|
|
43962
|
+
// A reflection seen through a half-transparent sheet is not a reflection, so the surface is
|
|
43963
|
+
// allowed to close up exactly where it is being reflective.
|
|
43964
|
+
float alpha = color.a * v_coverage;
|
|
43965
|
+
alpha = clamp(alpha + (1.0 - alpha) * (fresnel * 0.55 + glint), 0.0, 1.0);
|
|
43966
|
+
return vec4(lit, alpha);
|
|
43967
|
+
}
|
|
43968
|
+
//#endwater
|
|
43969
|
+
|
|
43776
43970
|
void main() {
|
|
43777
43971
|
if (v_coverage < u_coverageCutoff) {
|
|
43778
43972
|
discard;
|
|
@@ -43793,12 +43987,27 @@ void main() {
|
|
|
43793
43987
|
float up = valueAt(v_st + vec2(0.0, u_texelSize.y));
|
|
43794
43988
|
float scale = u_valueRange * u_exaggeration;
|
|
43795
43989
|
vec3 n = normalize(vec3((left - right) * scale, (down - up) * scale, 2.0 * u_metresPerTexel));
|
|
43990
|
+
|
|
43991
|
+
//#water
|
|
43992
|
+
out_FragColor = water(n, color);
|
|
43993
|
+
return;
|
|
43994
|
+
//#endwater
|
|
43995
|
+
|
|
43796
43996
|
float lambert = clamp(dot(n, normalize(vec3(-0.5, -0.6, 0.62))), 0.0, 1.0);
|
|
43797
43997
|
color.rgb *= 0.45 + 0.9 * lambert;
|
|
43798
43998
|
|
|
43799
43999
|
out_FragColor = vec4(color.rgb, color.a * v_coverage);
|
|
43800
44000
|
}
|
|
43801
44001
|
`;
|
|
44002
|
+
/*
|
|
44003
|
+
* Strips the water-only regions out of a shader source unless this surface is drawing water.
|
|
44004
|
+
*/
|
|
44005
|
+
function withWater(source, water) {
|
|
44006
|
+
if (water) {
|
|
44007
|
+
return source.replace(/^\/\/#(end)?water\n/gm, "");
|
|
44008
|
+
}
|
|
44009
|
+
return source.replace(/^\/\/#water\n[\s\S]*?^\/\/#endwater\n/gm, "");
|
|
44010
|
+
}
|
|
43802
44011
|
/*
|
|
43803
44012
|
* Rewrites a GLSL 300 es source into the GLSL 100 dialect older Cesium builds author in.
|
|
43804
44013
|
*/
|
|
@@ -44127,6 +44336,7 @@ void main() {
|
|
|
44127
44336
|
this.texture = null;
|
|
44128
44337
|
this.textureDirty = true;
|
|
44129
44338
|
this.shaderProgram = null;
|
|
44339
|
+
this.shaderProgramWater = false;
|
|
44130
44340
|
this.renderState = null;
|
|
44131
44341
|
this.destroyed = false;
|
|
44132
44342
|
this.lastEyePosition = null;
|
|
@@ -44143,6 +44353,13 @@ void main() {
|
|
|
44143
44353
|
this.maskGroundBox = null;
|
|
44144
44354
|
this.maskGroundRequested = false;
|
|
44145
44355
|
this.maskGroundLevel = 0;
|
|
44356
|
+
this.water = null;
|
|
44357
|
+
this.waterStartMs = now();
|
|
44358
|
+
this.waveOrigin = new Cartesian2(0, 0);
|
|
44359
|
+
this.extentMetresCache = null;
|
|
44360
|
+
// Written in place each frame rather than reallocated, since they are read per tile.
|
|
44361
|
+
this.wavePhaseScratch = [new Cartesian4(), new Cartesian4()];
|
|
44362
|
+
this.waterSkyScratch = new Cartesian3();
|
|
44146
44363
|
this.followGround = Boolean(options.followGround);
|
|
44147
44364
|
this.terrainProvider = options.terrainProvider || null;
|
|
44148
44365
|
this.extent = options.extent;
|
|
@@ -44158,6 +44375,23 @@ void main() {
|
|
|
44158
44375
|
this.maskFillValue = firstOpaqueStop(this.rampPixels);
|
|
44159
44376
|
this.tiles = buildTiles(hasCoverage);
|
|
44160
44377
|
this.SetGroundClearance(options.groundClearance || null);
|
|
44378
|
+
this.SetWater(options.water || null);
|
|
44379
|
+
}
|
|
44380
|
+
GetWater() {
|
|
44381
|
+
return this.water;
|
|
44382
|
+
}
|
|
44383
|
+
/**
|
|
44384
|
+
* Shades the sheet as water, or stops. Null goes back to the relief shading.
|
|
44385
|
+
*
|
|
44386
|
+
* Nothing is rebuilt: no mesh, no texture and no shader, since the water path is a branch in
|
|
44387
|
+
* the fragment shader the whole scene already carries. So this is cheap enough to drive from
|
|
44388
|
+
* a control the user is dragging.
|
|
44389
|
+
*/
|
|
44390
|
+
SetWater(water) {
|
|
44391
|
+
if (water && !this.water) {
|
|
44392
|
+
this.waterStartMs = now();
|
|
44393
|
+
}
|
|
44394
|
+
this.water = water;
|
|
44161
44395
|
}
|
|
44162
44396
|
GetFollowsGround() {
|
|
44163
44397
|
return this.followGround;
|
|
@@ -44328,6 +44562,12 @@ void main() {
|
|
|
44328
44562
|
const mesh = this.ensureMesh(context, tile, tile.tier);
|
|
44329
44563
|
frameState.commandList.push(this.commandFor(context, tile, mesh));
|
|
44330
44564
|
}
|
|
44565
|
+
if (this.water) {
|
|
44566
|
+
this.updateWaveOrigin(frameState);
|
|
44567
|
+
if (frameState.afterRender) {
|
|
44568
|
+
frameState.afterRender.push(() => true);
|
|
44569
|
+
}
|
|
44570
|
+
}
|
|
44331
44571
|
}
|
|
44332
44572
|
isDestroyed() {
|
|
44333
44573
|
return this.destroyed;
|
|
@@ -44539,6 +44779,73 @@ void main() {
|
|
|
44539
44779
|
})
|
|
44540
44780
|
});
|
|
44541
44781
|
}
|
|
44782
|
+
/*
|
|
44783
|
+
* Metres the extent spans west to east and north to south, which is what turns the shader's
|
|
44784
|
+
* 0..1 surface coordinate into the real distance the ripple wavelength is measured in.
|
|
44785
|
+
*/
|
|
44786
|
+
extentMetres() {
|
|
44787
|
+
// The extent never moves, and this is read once per tile per frame.
|
|
44788
|
+
if (this.extentMetresCache) {
|
|
44789
|
+
return this.extentMetresCache;
|
|
44790
|
+
}
|
|
44791
|
+
const southWest = Cartesian3.fromDegrees(this.extent.West, this.extent.South, 0);
|
|
44792
|
+
const southEast = Cartesian3.fromDegrees(this.extent.East, this.extent.South, 0);
|
|
44793
|
+
const northWest = Cartesian3.fromDegrees(this.extent.West, this.extent.North, 0);
|
|
44794
|
+
this.extentMetresCache = new Cartesian2(Math.max(1, Cartesian3.distance(southWest, southEast)), Math.max(1, Cartesian3.distance(southWest, northWest)));
|
|
44795
|
+
return this.extentMetresCache;
|
|
44796
|
+
}
|
|
44797
|
+
/*
|
|
44798
|
+
* Where each ripple layer has scrolled to, wrapped into one turn.
|
|
44799
|
+
*/
|
|
44800
|
+
wavePhase(from) {
|
|
44801
|
+
var _a;
|
|
44802
|
+
const into = this.wavePhaseScratch[from / 4];
|
|
44803
|
+
const water = this.water;
|
|
44804
|
+
if (!water) {
|
|
44805
|
+
return Cartesian4.clone(Cartesian4.ZERO, into);
|
|
44806
|
+
}
|
|
44807
|
+
const speed = (_a = water.speed) !== null && _a !== void 0 ? _a : DEFAULT_WATER_SPEED_METRES_PER_SECOND;
|
|
44808
|
+
const period = this.wavePeriod();
|
|
44809
|
+
const seconds = (now() - this.waterStartMs) / 1000;
|
|
44810
|
+
const base = waveCycles(WATER_WAVES[WATER_BASE_WAVE]);
|
|
44811
|
+
const phaseAt = (index) => {
|
|
44812
|
+
const wave = WATER_WAVES[from + index];
|
|
44813
|
+
if (!wave) {
|
|
44814
|
+
return 0;
|
|
44815
|
+
}
|
|
44816
|
+
const cycles = waveCycles(wave);
|
|
44817
|
+
const waveNumber = 2 * Math.PI * cycles / period;
|
|
44818
|
+
const travels = Math.sqrt(base / cycles);
|
|
44819
|
+
return (seconds * speed * travels * waveNumber) % (2 * Math.PI);
|
|
44820
|
+
};
|
|
44821
|
+
into.x = phaseAt(0);
|
|
44822
|
+
into.y = phaseAt(1);
|
|
44823
|
+
into.z = phaseAt(2);
|
|
44824
|
+
into.w = phaseAt(3);
|
|
44825
|
+
return into;
|
|
44826
|
+
}
|
|
44827
|
+
wavePeriod() {
|
|
44828
|
+
const wavelength = (this.water && this.water.wavelength) || DEFAULT_WATER_WAVELENGTH_METRES;
|
|
44829
|
+
return wavelength * WATER_PERIOD_IN_WAVELENGTHS;
|
|
44830
|
+
}
|
|
44831
|
+
/*
|
|
44832
|
+
* The point the ripple phase is measured from, kept near the camera and snapped to a whole
|
|
44833
|
+
* number of periods in each direction.
|
|
44834
|
+
*/
|
|
44835
|
+
updateWaveOrigin(frameState) {
|
|
44836
|
+
const period = this.wavePeriod();
|
|
44837
|
+
const carto = Cartographic.fromCartesian(frameState.camera.positionWC);
|
|
44838
|
+
if (!carto) {
|
|
44839
|
+
return;
|
|
44840
|
+
}
|
|
44841
|
+
const metres = this.extentMetres();
|
|
44842
|
+
const longitude = Math$1.toDegrees(carto.longitude);
|
|
44843
|
+
const latitude = Math$1.toDegrees(carto.latitude);
|
|
44844
|
+
const u = (longitude - this.extent.West) / (this.extent.East - this.extent.West);
|
|
44845
|
+
// North is v zero, the way the vertex shader places the surface.
|
|
44846
|
+
const v = (this.extent.North - latitude) / (this.extent.North - this.extent.South);
|
|
44847
|
+
this.waveOrigin = new Cartesian2(Math.floor(u * metres.x / period) * period, Math.floor(v * metres.y / period) * period);
|
|
44848
|
+
}
|
|
44542
44849
|
/*
|
|
44543
44850
|
* Ground distance between neighbouring texels, so the shading normal is built from a real
|
|
44544
44851
|
* slope rather than a made up one.
|
|
@@ -44702,14 +45009,22 @@ void main() {
|
|
|
44702
45009
|
return isFinite(nearest) ? Math.max(1, nearest) : 1;
|
|
44703
45010
|
}
|
|
44704
45011
|
commandFor(context, tile, mesh) {
|
|
45012
|
+
// Rebuilt when the effect is switched, since which program is wanted is part of it.
|
|
45013
|
+
const wantsWater = Boolean(this.water);
|
|
45014
|
+
if (this.shaderProgram && this.shaderProgramWater !== wantsWater) {
|
|
45015
|
+
this.shaderProgram = null;
|
|
45016
|
+
}
|
|
44705
45017
|
if (!this.shaderProgram) {
|
|
44706
45018
|
const glsl300 = usesGlsl300(context);
|
|
45019
|
+
const vertex = withWater(VERTEX_SHADER_GLSL300, wantsWater);
|
|
45020
|
+
const fragment = withWater(FRAGMENT_SHADER_GLSL300, wantsWater);
|
|
44707
45021
|
this.shaderProgram = ShaderProgram.fromCache({
|
|
44708
45022
|
context,
|
|
44709
|
-
vertexShaderSource: glsl300 ?
|
|
44710
|
-
fragmentShaderSource: glsl300 ?
|
|
45023
|
+
vertexShaderSource: glsl300 ? vertex : toGlsl100(vertex, false),
|
|
45024
|
+
fragmentShaderSource: glsl300 ? fragment : toGlsl100(fragment, true),
|
|
44711
45025
|
attributeLocations: mesh.attributeLocations
|
|
44712
45026
|
});
|
|
45027
|
+
this.shaderProgramWater = wantsWater;
|
|
44713
45028
|
this.renderState = RenderState.fromCache({
|
|
44714
45029
|
depthTest: { enabled: true },
|
|
44715
45030
|
// Translucent ramp: blend, and leave the depth buffer to the opaque world.
|
|
@@ -44765,11 +45080,38 @@ void main() {
|
|
|
44765
45080
|
: 0,
|
|
44766
45081
|
u_coverageCutoff: () => COVERAGE_CUTOFF,
|
|
44767
45082
|
u_rampTexture: () => self.rampTexture,
|
|
44768
|
-
u_texelSize: () => new Cartesian2(1 / self.source.width, 1 / self.source.height)
|
|
45083
|
+
u_texelSize: () => new Cartesian2(1 / self.source.width, 1 / self.source.height),
|
|
45084
|
+
u_waterOn: () => (self.water ? 1 : 0),
|
|
45085
|
+
u_waterWavelength: () => (self.water && self.water.wavelength)
|
|
45086
|
+
|| DEFAULT_WATER_WAVELENGTH_METRES,
|
|
45087
|
+
u_waterAmplitude: () => {
|
|
45088
|
+
var _a;
|
|
45089
|
+
return (_a = (self.water && self.water.amplitude)) !== null && _a !== void 0 ? _a : DEFAULT_WATER_AMPLITUDE_METRES;
|
|
45090
|
+
},
|
|
45091
|
+
u_waterReflectivity: () => {
|
|
45092
|
+
var _a;
|
|
45093
|
+
return (_a = (self.water && self.water.reflectivity)) !== null && _a !== void 0 ? _a : DEFAULT_WATER_REFLECTIVITY;
|
|
45094
|
+
},
|
|
45095
|
+
u_waterGloss: () => (self.water && self.water.glossiness)
|
|
45096
|
+
|| DEFAULT_WATER_GLOSSINESS,
|
|
45097
|
+
u_waterSun: () => {
|
|
45098
|
+
var _a;
|
|
45099
|
+
return (_a = (self.water && self.water.sunIntensity)) !== null && _a !== void 0 ? _a : DEFAULT_WATER_SUN_INTENSITY;
|
|
45100
|
+
},
|
|
45101
|
+
u_waterSky: () => {
|
|
45102
|
+
const sky = (self.water && self.water.skyColor) || DEFAULT_WATER_SKY_COLOR;
|
|
45103
|
+
return Cartesian3.fromElements(sky.red / 255, sky.green / 255, sky.blue / 255, self.waterSkyScratch);
|
|
45104
|
+
},
|
|
45105
|
+
u_wavePhase: () => self.wavePhase(0),
|
|
45106
|
+
u_wavePhaseB: () => self.wavePhase(4),
|
|
45107
|
+
u_wavePeriod: () => self.wavePeriod(),
|
|
45108
|
+
u_waveOrigin: () => self.waveOrigin,
|
|
45109
|
+
u_extentMetres: () => self.extentMetres()
|
|
44769
45110
|
}
|
|
44770
45111
|
});
|
|
44771
45112
|
}
|
|
44772
45113
|
// Bounding volume belongs to the mesh, so it follows whichever tier is drawing.
|
|
45114
|
+
tile.command.shaderProgram = this.shaderProgram;
|
|
44773
45115
|
tile.command.vertexArray = mesh.vertexArray;
|
|
44774
45116
|
tile.command.boundingVolume = mesh.boundingSphere;
|
|
44775
45117
|
return tile.command;
|
|
@@ -45419,6 +45761,23 @@ var EntityRenderEnginePolygon;
|
|
|
45419
45761
|
return touched;
|
|
45420
45762
|
}
|
|
45421
45763
|
EntityRenderEnginePolygon.SetGroundClearance = SetGroundClearance;
|
|
45764
|
+
/**
|
|
45765
|
+
* Shades every rendered polygon in a set as water rather than as a coloured surface.
|
|
45766
|
+
* @param cEntities
|
|
45767
|
+
* @param water Pass null to go back to the relief shading.
|
|
45768
|
+
*/
|
|
45769
|
+
function SetWater(cEntities, water) {
|
|
45770
|
+
let touched = 0;
|
|
45771
|
+
for (const cEntity of cEntities || []) {
|
|
45772
|
+
const surface = GetDisplacedSurface(cEntity);
|
|
45773
|
+
if (surface) {
|
|
45774
|
+
surface.SetWater(water);
|
|
45775
|
+
touched++;
|
|
45776
|
+
}
|
|
45777
|
+
}
|
|
45778
|
+
return touched;
|
|
45779
|
+
}
|
|
45780
|
+
EntityRenderEnginePolygon.SetWater = SetWater;
|
|
45422
45781
|
/**
|
|
45423
45782
|
* Disposes a cEntity's TextureFrameSeriesAnimator.Animator (if any).
|
|
45424
45783
|
*/
|
|
@@ -45576,6 +45935,7 @@ function syncDisplacedSurface(params) {
|
|
|
45576
45935
|
if (reusable && existingSurface.GetFollowsGround() === placement.followGround) {
|
|
45577
45936
|
existingSurface.SetBaseHeight(placement.baseHeight);
|
|
45578
45937
|
existingSurface.SetExaggeration(exaggerationFor(style));
|
|
45938
|
+
existingSurface.SetWater(waterFor(style));
|
|
45579
45939
|
return;
|
|
45580
45940
|
}
|
|
45581
45941
|
disposeDisplacedSurface(cEntity, viewer);
|
|
@@ -45615,6 +45975,7 @@ function syncDisplacedSurface(params) {
|
|
|
45615
45975
|
valueMax: extrusionArchive.metadata.ValueMax,
|
|
45616
45976
|
packedValue: TextureFrameSeriesAnimator.IsPackedValue(extrusionArchive.metadata),
|
|
45617
45977
|
exaggeration: exaggerationFor(style),
|
|
45978
|
+
water: waterFor(style),
|
|
45618
45979
|
lowColor: mask ? Color$1.ColorFromStr(mask.minColor) : null,
|
|
45619
45980
|
highColor: mask ? Color$1.ColorFromStr(mask.maxColor) : null,
|
|
45620
45981
|
// Normalised the same way the animator normalises them, so the surface and the flat drape
|
|
@@ -45660,6 +46021,14 @@ function exaggerationFor(style) {
|
|
|
45660
46021
|
}
|
|
45661
46022
|
return 1;
|
|
45662
46023
|
}
|
|
46024
|
+
const WATER_EFFECT = "WATER";
|
|
46025
|
+
/*
|
|
46026
|
+
* The water settings a style asks a displaced surface for, or null for the plain relief shading.
|
|
46027
|
+
*/
|
|
46028
|
+
function waterFor(style) {
|
|
46029
|
+
var _a;
|
|
46030
|
+
return ((_a = style.effect) === null || _a === void 0 ? void 0 : _a.type) === WATER_EFFECT ? {} : null;
|
|
46031
|
+
}
|
|
45663
46032
|
/*
|
|
45664
46033
|
* The lon/lat bounding rectangle of a ring, which is the frame Cesium drapes an image material in.
|
|
45665
46034
|
*/
|
|
@@ -46704,6 +47073,28 @@ var EntityRenderEngine;
|
|
|
46704
47073
|
};
|
|
46705
47074
|
}
|
|
46706
47075
|
EntityRenderEngine.Render = Render;
|
|
47076
|
+
/**
|
|
47077
|
+
* Removes what a render produced that nothing has a record of, for a render whose caller has gone away.
|
|
47078
|
+
* @param params
|
|
47079
|
+
*/
|
|
47080
|
+
function RemoveAll(params) {
|
|
47081
|
+
const { viewer, entities, register } = params;
|
|
47082
|
+
if (!entities || viewer.isDestroyed()) {
|
|
47083
|
+
return;
|
|
47084
|
+
}
|
|
47085
|
+
entities.forEach((entity) => {
|
|
47086
|
+
if (!entity || (register === null || register === void 0 ? void 0 : register.HasRego(entity))) {
|
|
47087
|
+
return;
|
|
47088
|
+
}
|
|
47089
|
+
try {
|
|
47090
|
+
Remove({ viewer, entity });
|
|
47091
|
+
}
|
|
47092
|
+
catch (e) {
|
|
47093
|
+
console.error("EntityRenderEngine.RemoveAll: failed to remove a visual:", e);
|
|
47094
|
+
}
|
|
47095
|
+
});
|
|
47096
|
+
}
|
|
47097
|
+
EntityRenderEngine.RemoveAll = RemoveAll;
|
|
46707
47098
|
function Remove(params) {
|
|
46708
47099
|
function doRemove(params) {
|
|
46709
47100
|
const { viewer, entity, ignoreParent } = params;
|
|
@@ -47532,7 +47923,7 @@ var StyleUtils;
|
|
|
47532
47923
|
StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
|
|
47533
47924
|
})(StyleUtils || (StyleUtils = {}));
|
|
47534
47925
|
|
|
47535
|
-
const VERSION = "7.3.
|
|
47926
|
+
const VERSION = "7.3.8";
|
|
47536
47927
|
/**
|
|
47537
47928
|
* Updates the environment instance used by bruce-cesium to one specified.
|
|
47538
47929
|
* This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
|