bruce-cesium 7.3.5 → 7.3.7

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.
@@ -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, Cartesian3, JulianDate, Quaternion, Transforms, HeadingPitchRoll, Matrix4, ShaderSource, Ellipsoid, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, Cartesian2, Cartesian4, ClassificationType, ArcType, CornerType, ShadowMode, ConstantPositionProperty, ColorBlendMode, Model, HorizontalOrigin, VerticalOrigin, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Rectangle, SceneTransforms, NearFarScalar, Matrix3, KmlDataSource, GeoJsonDataSource, SceneMode, Ion, IonResource, Cesium3DTileStyle, HeadingPitchRange, Cesium3DTileset, Intersect, Cesium3DTileColorBlendMode, OrthographicFrustum, EasingFunction, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, PolygonPipeline, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, CustomDataSource, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, 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, ClientFile, EntityLod, Api, Bounds, ClientFileValueMap, Color as Color$1, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, BruceEvent, EntityCoords, DataLab, DelayQueue, AccountConcept, BruceApi, RecordChangeFeed, EntityRelation, EntitySource, Camera, ProgramKey, ProjectViewLegacyTile, Account, AccountLimits, Session, UrlUtils, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, ProjectViewBookmarkGroup, EntityRelationType, EntityHistoricData } from 'bruce-models';
2
+ import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, HeightReference, ColorBlendMode, HeadingPitchRoll, Math as Math$1, Transforms, ShadowMode, Cartesian3, ClassificationType, Model, JulianDate, Quaternion, Matrix4, ArcType, CornerType, ConstantPositionProperty, HorizontalOrigin, VerticalOrigin, ShaderSource, Ellipsoid, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, Cartesian2, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, Cartesian4, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, DistanceDisplayCondition, ImageMaterialProperty, SceneTransforms, PolygonHierarchy, PolylineGraphics, Rectangle, NearFarScalar, Matrix3, KmlDataSource, GeoJsonDataSource, SceneMode, Cesium3DTileStyle, Cesium3DTileColorBlendMode, HeadingPitchRange, Ion, IonResource, OrthographicFrustum, EasingFunction, Cesium3DTileset, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, Intersect, PolygonPipeline, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, CesiumInspector, ClockRange, DynamicEnvironmentMapManager, GeometryInstance, CustomDataSource, ScreenSpaceEventHandler, ScreenSpaceEventType, Fullscreen, CzmlDataSource } from 'cesium';
3
+ import { Cartes, LRUCache, ProjectViewTile, ENVIRONMENT, Calculator, ClientFile, Entity as Entity$1, EntityLod, EntityTag, EntityType, ObjectUtils, Style, Carto, Geometry as Geometry$1, Api, ClientFileValueMap, Color as Color$1, Bounds, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, BruceEvent, EntityCoords, DataLab, DelayQueue, AccountConcept, BruceApi, EntityRelation, EntitySource, RecordChangeFeed, Camera, ProgramKey, ProjectViewLegacyTile, Account, AccountLimits, Session, UrlUtils, ProjectViewBookmarkGroup, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, EntityRelationType, EntityHistoricData } from 'bruce-models';
4
4
 
5
5
  /**
6
6
  * Ensures a number is returned from a given value.
@@ -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 (!(carto === null || carto === void 0 ? void 0 : carto.latitude)) {
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;
@@ -33591,6 +33597,24 @@ class WidgetCursorBar extends Widget.AWidget {
33591
33597
  this._listenSelection();
33592
33598
  }
33593
33599
  }
33600
+ /**
33601
+ * @param cursor
33602
+ */
33603
+ SetCursor(cursor) {
33604
+ if (cursor == this._selectedCursor) {
33605
+ return;
33606
+ }
33607
+ this._disposeMeasureTool();
33608
+ this._disposeCesiumEvent();
33609
+ this._selectedCursor = cursor;
33610
+ this._selectedSecondaryCursor = ESecondaryCursor.None;
33611
+ this._secondary.style.display = "none";
33612
+ if (cursor == ECursor.Select) {
33613
+ this._listenSelection();
33614
+ }
33615
+ this._updateControls();
33616
+ this.OnCursorChange.Trigger(cursor);
33617
+ }
33594
33618
  Dispose() {
33595
33619
  var _a, _b;
33596
33620
  super.Dispose();
@@ -43571,6 +43595,44 @@ var DisplacedSurfacePrimitive;
43571
43595
  const MASK_TEXTURE_MAX_SIDE = 1024;
43572
43596
  // Stands in for "no floor" and "no clearance", far below anything the sheet can reach.
43573
43597
  const NO_LIMIT_METRES = -1e6;
43598
+ // Ripple layers to cycle across the field's own repeat.
43599
+ const WATER_WAVES = [
43600
+ { x: 2, y: 1, amplitude: 6.4 },
43601
+ { x: 1, y: 4, amplitude: 3.9 },
43602
+ { x: -6, y: 4, amplitude: 2.5 },
43603
+ { x: 9, y: -9, amplitude: 1.6 },
43604
+ { x: -14, y: 18, amplitude: 1.0 },
43605
+ { x: 38, y: 15, amplitude: 0.63 },
43606
+ { x: -30, y: 68, amplitude: 0.39 },
43607
+ { x: 120, y: 57, amplitude: 0.245 }
43608
+ ];
43609
+ const waveCycles = (wave) => Math.hypot(wave.x, wave.y);
43610
+ // Which layer the wavelength setting names. The ladder runs either side of it.
43611
+ const WATER_BASE_WAVE = 4;
43612
+ // How many metres the field repeats over, as a multiple of the settings' own wavelength.
43613
+ const WATER_PERIOD_IN_WAVELENGTHS = waveCycles(WATER_WAVES[WATER_BASE_WAVE]);
43614
+ /*
43615
+ * How much of the surface's total slope each layer carries, which is its amplitude against its
43616
+ * wave number rather than its amplitude alone.
43617
+ */
43618
+ const WATER_WAVE_SLOPES = (() => {
43619
+ const raw = WATER_WAVES.map((wave) => wave.amplitude * waveCycles(wave));
43620
+ const total = raw.reduce((sum, value) => sum + value, 0);
43621
+ return raw.map((value) => value / total);
43622
+ })();
43623
+ // Screen pixels a ripple layer needs to span before it counts at all, and before it counts in
43624
+ // full. Below the first it is finer than the pixel grid and turns into moire that crawls as the
43625
+ // camera moves; the gap between the two is there so a layer leaves gradually rather than
43626
+ // stepping out and leaving a visible change in the surface.
43627
+ const WATER_MIN_PIXELS_PER_WAVE = 6;
43628
+ const WATER_FULL_PIXELS_PER_WAVE = 16;
43629
+ const DEFAULT_WATER_WAVELENGTH_METRES = 26;
43630
+ const DEFAULT_WATER_AMPLITUDE_METRES = 0.11;
43631
+ const DEFAULT_WATER_SPEED_METRES_PER_SECOND = 0.6;
43632
+ const DEFAULT_WATER_REFLECTIVITY = 0.72;
43633
+ const DEFAULT_WATER_GLOSSINESS = 140;
43634
+ const DEFAULT_WATER_SUN_INTENSITY = 1;
43635
+ const DEFAULT_WATER_SKY_COLOR = { red: 150, green: 186, blue: 214, alpha: 1 };
43574
43636
  const GROUND_MIN_METRES = -1000;
43575
43637
  const GROUND_MAX_METRES = 9000;
43576
43638
  const DEFAULT_LOW_COLOR = { red: 255, green: 255, blue: 255, alpha: 0.12 };
@@ -43606,10 +43668,17 @@ uniform vec2 u_maskGroundSize;
43606
43668
  uniform vec4 u_extentDegrees;
43607
43669
  uniform vec4 u_maskGroundDegrees;
43608
43670
  uniform float u_coverageCutoffVertex;
43671
+ uniform vec2 u_extentMetres;
43672
+ uniform vec2 u_waveOrigin;
43609
43673
 
43610
43674
  out vec2 v_st;
43611
43675
  out float v_value;
43612
43676
  out float v_coverage;
43677
+ out vec3 v_positionEC;
43678
+ out vec3 v_eastEC;
43679
+ out vec3 v_northEC;
43680
+ out vec3 v_upEC;
43681
+ out vec2 v_waveMetres;
43613
43682
 
43614
43683
  float decodeGround(vec2 uv) {
43615
43684
  // Channels arrive normalised to 0..1, so they go back to bytes before being reassembled.
@@ -43728,6 +43797,25 @@ void main() {
43728
43797
  // Added to the LOW half of the encoded position: a metre-scale offset added to the high half
43729
43798
  // would be lost to float32 rounding at an earth radius.
43730
43799
  vec4 p = czm_translateRelativeToEye(position3DHigh, position3DLow + normal * displacement);
43800
+
43801
+ // The local frame at this vertex so a shading normal built in east/north/up meters can be turned into something usable.
43802
+ v_upEC = czm_normal * normal;
43803
+ vec3 east = normalize(cross(vec3(0.0, 0.0, 1.0), normal));
43804
+ v_eastEC = czm_normal * east;
43805
+ v_northEC = czm_normal * cross(normal, east);
43806
+ v_positionEC = (czm_modelViewRelativeToEye * p).xyz;
43807
+
43808
+ /*
43809
+ * Where this vertex sits in the ripple field, in metres from an origin that follows the camera.
43810
+ *
43811
+ * Subtracted here rather than in the fragment shader because the position it is subtracted from
43812
+ * spans the whole archive, which over a sound is tens of kilometres. A wave number times that
43813
+ * is thousands of radians, and no fragment shader that may only have mediump can step through a
43814
+ * cosine at that magnitude: the ripples come out as a flat surface, which is what a first cut of
43815
+ * this did. What crosses into the fragment shader is a small number the camera is standing in.
43816
+ */
43817
+ v_waveMetres = st * u_extentMetres - u_waveOrigin;
43818
+
43731
43819
  gl_Position = czm_modelViewProjectionRelativeToEye * p;
43732
43820
  }
43733
43821
  `;
@@ -43740,10 +43828,27 @@ uniform float u_valuePacked;
43740
43828
  uniform float u_valueRange;
43741
43829
  uniform float u_exaggeration;
43742
43830
  uniform float u_metresPerTexel;
43831
+ uniform float u_waterOn;
43832
+ uniform float u_waterWavelength;
43833
+ uniform float u_waterAmplitude;
43834
+ uniform float u_waterReflectivity;
43835
+ uniform float u_waterGloss;
43836
+ uniform float u_waterSun;
43837
+ uniform vec3 u_waterSky;
43838
+ // One scrolled phase per ripple layer, wrapped into a turn on the CPU.
43839
+ uniform vec4 u_wavePhase;
43840
+ uniform vec4 u_wavePhaseB;
43841
+ // Metres the whole ripple field repeats over.
43842
+ uniform float u_wavePeriod;
43743
43843
 
43744
43844
  in vec2 v_st;
43745
43845
  in float v_value;
43746
43846
  in float v_coverage;
43847
+ in vec3 v_positionEC;
43848
+ in vec3 v_eastEC;
43849
+ in vec3 v_northEC;
43850
+ in vec3 v_upEC;
43851
+ in vec2 v_waveMetres;
43747
43852
 
43748
43853
  /*
43749
43854
  * Scaled per channel for the same reason the vertex shader's decode is: reassembling the pair reaches
@@ -43755,6 +43860,82 @@ float valueAt(vec2 uv) {
43755
43860
  return mix(texel.r, packed16, u_valuePacked);
43756
43861
  }
43757
43862
 
43863
+ /*
43864
+ * Slope of the ripple field at a point, in metres of rise per metre travelled.
43865
+ */
43866
+ vec2 rippleSlope(vec2 metres, float metresPerPixel, out float detail) {
43867
+ vec2 slope = vec2(0.0);
43868
+ detail = 0.0;
43869
+ float amplitude = u_waterAmplitude * 0.5;
43870
+ ${WATER_WAVES.map((wave, index) => {
43871
+ const cycles = waveCycles(wave);
43872
+ return `
43873
+ {
43874
+ vec2 lattice = vec2(${wave.x.toFixed(1)}, ${wave.y.toFixed(1)});
43875
+ float k = 6.2831853 * ${cycles.toFixed(4)} / u_wavePeriod;
43876
+ float pixels = u_wavePeriod / ${cycles.toFixed(4)} / max(metresPerPixel, 1e-6);
43877
+ float weight = smoothstep(${WATER_MIN_PIXELS_PER_WAVE.toFixed(1)},
43878
+ ${WATER_FULL_PIXELS_PER_WAVE.toFixed(1)}, pixels);
43879
+ vec2 direction = lattice / ${cycles.toFixed(4)};
43880
+ float phase = 6.2831853 * dot(lattice, metres) / u_wavePeriod
43881
+ + ${index < 4 ? `u_wavePhase[${index}]` : `u_wavePhaseB[${index - 4}]`};
43882
+ slope += direction * (amplitude * ${wave.amplitude.toFixed(4)} * k * cos(phase) * weight);
43883
+ detail += ${WATER_WAVE_SLOPES[index].toFixed(5)} * weight;
43884
+ }`;
43885
+ }).join("")}
43886
+ return slope;
43887
+ }
43888
+
43889
+ /*
43890
+ * The sheet shaded as a water surface: a flat body colour seen through a sun glint and a grazing
43891
+ * sky reflection, with the ripple field standing in for a geometry it is far too fine to carry.
43892
+ */
43893
+ vec4 water(vec3 relief, vec4 color) {
43894
+ float metresPerPixel = czm_metersPerPixel(vec4(v_positionEC, 1.0));
43895
+ float detail;
43896
+ vec2 slope = rippleSlope(v_waveMetres, metresPerPixel, detail);
43897
+
43898
+ // relief arrives normalised, so its horizontal part over its vertical part is the slope it means.
43899
+ vec2 reliefSlope = relief.xy / max(relief.z, 1e-3);
43900
+ vec3 local = normalize(vec3(-(slope + reliefSlope), 1.0));
43901
+ vec3 normalEC = normalize(local.x * v_eastEC + local.y * v_northEC + local.z * v_upEC);
43902
+
43903
+ vec3 view = normalize(-v_positionEC);
43904
+ // Drawn with culling off, so the underside of the sheet arrives with its normal pointing away.
43905
+ normalEC = dot(normalEC, view) < 0.0 ? -normalEC : normalEC;
43906
+ vec3 sun = normalize(czm_sunDirectionEC);
43907
+
43908
+ // Water at a grazing angle is almost a mirror and water looked straight down is almost clear.
43909
+ // That split is the single strongest cue that a blue surface is wet, more than any ripple is.
43910
+ float fresnel = u_waterReflectivity
43911
+ * (0.02 + 0.98 * pow(1.0 - clamp(dot(normalEC, view), 0.0, 1.0), 5.0));
43912
+
43913
+ // Softened by the roughness the shading has had to give up.
43914
+ fresnel *= mix(0.55, 1.0, detail);
43915
+
43916
+ // Where the ripples have faded out the surface is not smooth, it is rough below one pixel, so
43917
+ // the glint has to widen to cover what the normal no longer says.
43918
+ float gloss = mix(u_waterGloss * 0.12, u_waterGloss, detail);
43919
+ vec3 halfway = normalize(sun + view);
43920
+ // Weighted by the same reflectance as the sky, because a glint is a reflection too.
43921
+ float glint = pow(max(dot(normalEC, halfway), 0.0), gloss) * u_waterSun * fresnel;
43922
+ float lambert = clamp(dot(normalEC, sun), 0.0, 1.0);
43923
+
43924
+ vec3 body = color.rgb * (0.55 + 0.6 * lambert);
43925
+ vec3 lit = min(mix(body, u_waterSky, fresnel) + vec3(glint), vec3(1.0));
43926
+
43927
+ /*
43928
+ * The same fog the globe under it is already drawing with.
43929
+ */
43930
+ lit = czm_fog(length(v_positionEC), lit, u_waterSky);
43931
+
43932
+ // A reflection seen through a half-transparent sheet is not a reflection, so the surface is
43933
+ // allowed to close up exactly where it is being reflective.
43934
+ float alpha = color.a * v_coverage;
43935
+ alpha = clamp(alpha + (1.0 - alpha) * (fresnel * 0.55 + glint), 0.0, 1.0);
43936
+ return vec4(lit, alpha);
43937
+ }
43938
+
43758
43939
  void main() {
43759
43940
  if (v_coverage < u_coverageCutoff) {
43760
43941
  discard;
@@ -43775,6 +43956,12 @@ void main() {
43775
43956
  float up = valueAt(v_st + vec2(0.0, u_texelSize.y));
43776
43957
  float scale = u_valueRange * u_exaggeration;
43777
43958
  vec3 n = normalize(vec3((left - right) * scale, (down - up) * scale, 2.0 * u_metresPerTexel));
43959
+
43960
+ if (u_waterOn > 0.5) {
43961
+ out_FragColor = water(n, color);
43962
+ return;
43963
+ }
43964
+
43778
43965
  float lambert = clamp(dot(n, normalize(vec3(-0.5, -0.6, 0.62))), 0.0, 1.0);
43779
43966
  color.rgb *= 0.45 + 0.9 * lambert;
43780
43967
 
@@ -44125,6 +44312,9 @@ void main() {
44125
44312
  this.maskGroundBox = null;
44126
44313
  this.maskGroundRequested = false;
44127
44314
  this.maskGroundLevel = 0;
44315
+ this.water = null;
44316
+ this.waterStartMs = now();
44317
+ this.waveOrigin = new Cartesian2(0, 0);
44128
44318
  this.followGround = Boolean(options.followGround);
44129
44319
  this.terrainProvider = options.terrainProvider || null;
44130
44320
  this.extent = options.extent;
@@ -44140,6 +44330,23 @@ void main() {
44140
44330
  this.maskFillValue = firstOpaqueStop(this.rampPixels);
44141
44331
  this.tiles = buildTiles(hasCoverage);
44142
44332
  this.SetGroundClearance(options.groundClearance || null);
44333
+ this.SetWater(options.water || null);
44334
+ }
44335
+ GetWater() {
44336
+ return this.water;
44337
+ }
44338
+ /**
44339
+ * Shades the sheet as water, or stops. Null goes back to the relief shading.
44340
+ *
44341
+ * Nothing is rebuilt: no mesh, no texture and no shader, since the water path is a branch in
44342
+ * the fragment shader the whole scene already carries. So this is cheap enough to drive from
44343
+ * a control the user is dragging.
44344
+ */
44345
+ SetWater(water) {
44346
+ if (water && !this.water) {
44347
+ this.waterStartMs = now();
44348
+ }
44349
+ this.water = water;
44143
44350
  }
44144
44351
  GetFollowsGround() {
44145
44352
  return this.followGround;
@@ -44310,6 +44517,12 @@ void main() {
44310
44517
  const mesh = this.ensureMesh(context, tile, tile.tier);
44311
44518
  frameState.commandList.push(this.commandFor(context, tile, mesh));
44312
44519
  }
44520
+ if (this.water) {
44521
+ this.updateWaveOrigin(frameState);
44522
+ if (frameState.afterRender) {
44523
+ frameState.afterRender.push(() => true);
44524
+ }
44525
+ }
44313
44526
  }
44314
44527
  isDestroyed() {
44315
44528
  return this.destroyed;
@@ -44521,6 +44734,60 @@ void main() {
44521
44734
  })
44522
44735
  });
44523
44736
  }
44737
+ /*
44738
+ * Metres the extent spans west to east and north to south, which is what turns the shader's
44739
+ * 0..1 surface coordinate into the real distance the ripple wavelength is measured in.
44740
+ */
44741
+ extentMetres() {
44742
+ const southWest = Cartesian3.fromDegrees(this.extent.West, this.extent.South, 0);
44743
+ const southEast = Cartesian3.fromDegrees(this.extent.East, this.extent.South, 0);
44744
+ const northWest = Cartesian3.fromDegrees(this.extent.West, this.extent.North, 0);
44745
+ return new Cartesian2(Math.max(1, Cartesian3.distance(southWest, southEast)), Math.max(1, Cartesian3.distance(southWest, northWest)));
44746
+ }
44747
+ /*
44748
+ * Where each ripple layer has scrolled to, wrapped into one turn.
44749
+ */
44750
+ wavePhase(from) {
44751
+ var _a;
44752
+ const water = this.water;
44753
+ if (!water) {
44754
+ return new Cartesian4(0, 0, 0, 0);
44755
+ }
44756
+ const speed = (_a = water.speed) !== null && _a !== void 0 ? _a : DEFAULT_WATER_SPEED_METRES_PER_SECOND;
44757
+ const period = this.wavePeriod();
44758
+ const seconds = (now() - this.waterStartMs) / 1000;
44759
+ const base = waveCycles(WATER_WAVES[WATER_BASE_WAVE]);
44760
+ const phases = WATER_WAVES.slice(from, from + 4).map((wave) => {
44761
+ const cycles = waveCycles(wave);
44762
+ const waveNumber = 2 * Math.PI * cycles / period;
44763
+ const travels = Math.sqrt(base / cycles);
44764
+ const travelled = seconds * speed * travels * waveNumber;
44765
+ return travelled % (2 * Math.PI);
44766
+ });
44767
+ return new Cartesian4(phases[0] || 0, phases[1] || 0, phases[2] || 0, phases[3] || 0);
44768
+ }
44769
+ wavePeriod() {
44770
+ const wavelength = (this.water && this.water.wavelength) || DEFAULT_WATER_WAVELENGTH_METRES;
44771
+ return wavelength * WATER_PERIOD_IN_WAVELENGTHS;
44772
+ }
44773
+ /*
44774
+ * The point the ripple phase is measured from, kept near the camera and snapped to a whole
44775
+ * number of periods in each direction.
44776
+ */
44777
+ updateWaveOrigin(frameState) {
44778
+ const period = this.wavePeriod();
44779
+ const carto = Cartographic.fromCartesian(frameState.camera.positionWC);
44780
+ if (!carto) {
44781
+ return;
44782
+ }
44783
+ const metres = this.extentMetres();
44784
+ const longitude = Math$1.toDegrees(carto.longitude);
44785
+ const latitude = Math$1.toDegrees(carto.latitude);
44786
+ const u = (longitude - this.extent.West) / (this.extent.East - this.extent.West);
44787
+ // North is v zero, the way the vertex shader places the surface.
44788
+ const v = (this.extent.North - latitude) / (this.extent.North - this.extent.South);
44789
+ this.waveOrigin = new Cartesian2(Math.floor(u * metres.x / period) * period, Math.floor(v * metres.y / period) * period);
44790
+ }
44524
44791
  /*
44525
44792
  * Ground distance between neighbouring texels, so the shading normal is built from a real
44526
44793
  * slope rather than a made up one.
@@ -44747,7 +45014,33 @@ void main() {
44747
45014
  : 0,
44748
45015
  u_coverageCutoff: () => COVERAGE_CUTOFF,
44749
45016
  u_rampTexture: () => self.rampTexture,
44750
- u_texelSize: () => new Cartesian2(1 / self.source.width, 1 / self.source.height)
45017
+ u_texelSize: () => new Cartesian2(1 / self.source.width, 1 / self.source.height),
45018
+ u_waterOn: () => (self.water ? 1 : 0),
45019
+ u_waterWavelength: () => (self.water && self.water.wavelength)
45020
+ || DEFAULT_WATER_WAVELENGTH_METRES,
45021
+ u_waterAmplitude: () => {
45022
+ var _a;
45023
+ return (_a = (self.water && self.water.amplitude)) !== null && _a !== void 0 ? _a : DEFAULT_WATER_AMPLITUDE_METRES;
45024
+ },
45025
+ u_waterReflectivity: () => {
45026
+ var _a;
45027
+ return (_a = (self.water && self.water.reflectivity)) !== null && _a !== void 0 ? _a : DEFAULT_WATER_REFLECTIVITY;
45028
+ },
45029
+ u_waterGloss: () => (self.water && self.water.glossiness)
45030
+ || DEFAULT_WATER_GLOSSINESS,
45031
+ u_waterSun: () => {
45032
+ var _a;
45033
+ return (_a = (self.water && self.water.sunIntensity)) !== null && _a !== void 0 ? _a : DEFAULT_WATER_SUN_INTENSITY;
45034
+ },
45035
+ u_waterSky: () => {
45036
+ const sky = (self.water && self.water.skyColor) || DEFAULT_WATER_SKY_COLOR;
45037
+ return new Cartesian3(sky.red / 255, sky.green / 255, sky.blue / 255);
45038
+ },
45039
+ u_wavePhase: () => self.wavePhase(0),
45040
+ u_wavePhaseB: () => self.wavePhase(4),
45041
+ u_wavePeriod: () => self.wavePeriod(),
45042
+ u_waveOrigin: () => self.waveOrigin,
45043
+ u_extentMetres: () => self.extentMetres()
44751
45044
  }
44752
45045
  });
44753
45046
  }
@@ -45401,6 +45694,23 @@ var EntityRenderEnginePolygon;
45401
45694
  return touched;
45402
45695
  }
45403
45696
  EntityRenderEnginePolygon.SetGroundClearance = SetGroundClearance;
45697
+ /**
45698
+ * Shades every rendered polygon in a set as water rather than as a coloured surface.
45699
+ * @param cEntities
45700
+ * @param water Pass null to go back to the relief shading.
45701
+ */
45702
+ function SetWater(cEntities, water) {
45703
+ let touched = 0;
45704
+ for (const cEntity of cEntities || []) {
45705
+ const surface = GetDisplacedSurface(cEntity);
45706
+ if (surface) {
45707
+ surface.SetWater(water);
45708
+ touched++;
45709
+ }
45710
+ }
45711
+ return touched;
45712
+ }
45713
+ EntityRenderEnginePolygon.SetWater = SetWater;
45404
45714
  /**
45405
45715
  * Disposes a cEntity's TextureFrameSeriesAnimator.Animator (if any).
45406
45716
  */
@@ -45558,6 +45868,7 @@ function syncDisplacedSurface(params) {
45558
45868
  if (reusable && existingSurface.GetFollowsGround() === placement.followGround) {
45559
45869
  existingSurface.SetBaseHeight(placement.baseHeight);
45560
45870
  existingSurface.SetExaggeration(exaggerationFor(style));
45871
+ existingSurface.SetWater(waterFor(style));
45561
45872
  return;
45562
45873
  }
45563
45874
  disposeDisplacedSurface(cEntity, viewer);
@@ -45597,6 +45908,7 @@ function syncDisplacedSurface(params) {
45597
45908
  valueMax: extrusionArchive.metadata.ValueMax,
45598
45909
  packedValue: TextureFrameSeriesAnimator.IsPackedValue(extrusionArchive.metadata),
45599
45910
  exaggeration: exaggerationFor(style),
45911
+ water: waterFor(style),
45600
45912
  lowColor: mask ? Color$1.ColorFromStr(mask.minColor) : null,
45601
45913
  highColor: mask ? Color$1.ColorFromStr(mask.maxColor) : null,
45602
45914
  // Normalised the same way the animator normalises them, so the surface and the flat drape
@@ -45642,6 +45954,14 @@ function exaggerationFor(style) {
45642
45954
  }
45643
45955
  return 1;
45644
45956
  }
45957
+ const WATER_EFFECT = "WATER";
45958
+ /*
45959
+ * The water settings a style asks a displaced surface for, or null for the plain relief shading.
45960
+ */
45961
+ function waterFor(style) {
45962
+ var _a;
45963
+ return ((_a = style.effect) === null || _a === void 0 ? void 0 : _a.type) === WATER_EFFECT ? {} : null;
45964
+ }
45645
45965
  /*
45646
45966
  * The lon/lat bounding rectangle of a ring, which is the frame Cesium drapes an image material in.
45647
45967
  */
@@ -47514,7 +47834,7 @@ var StyleUtils;
47514
47834
  StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
47515
47835
  })(StyleUtils || (StyleUtils = {}));
47516
47836
 
47517
- const VERSION = "7.3.5";
47837
+ const VERSION = "7.3.7";
47518
47838
  /**
47519
47839
  * Updates the environment instance used by bruce-cesium to one specified.
47520
47840
  * This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
@@ -47531,5 +47851,5 @@ const getENVIRONMENT = () => {
47531
47851
  return ENVIRONMENT;
47532
47852
  };
47533
47853
 
47534
- export { VERSION, setENVIRONMENT, getENVIRONMENT, CesiumAnimatedInOut, DisplacedSurfacePrimitive, CesiumAnimatedProperty, isStyleChanged, isOutlineChanged$1 as isOutlineChanged, StyleEffective, EntityRenderEngine, EntityRenderEngineModel3d, EntityRenderEnginePoint, EntityRenderEnginePolygon, EntityRenderEnginePolyline, TextureFrameSeriesAnimator, TextureValueLabels, 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, DEFAULT_BRIGHTNESS_SHIFT, DEFAULT_LIGHT_INTENSITY, LIGHTING_SETTINGS_VERSION, LIGHT_INTENSITY_COMPENSATION, MAX_COMPENSATED_LIGHT_INTENSITY, 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 };
47854
+ export { VERSION, setENVIRONMENT, getENVIRONMENT, CesiumAnimatedInOut, DisplacedSurfacePrimitive, CesiumAnimatedProperty, isStyleChanged, isOutlineChanged$1 as isOutlineChanged, StyleEffective, EntityRenderEngine, EntityRenderEngineModel3d, EntityRenderEnginePoint, EntityRenderEnginePolygon, EntityRenderEnginePolyline, TextureFrameSeriesAnimator, TextureValueLabels, 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, DEFAULT_BRIGHTNESS_SHIFT, DEFAULT_LIGHT_INTENSITY, LIGHTING_SETTINGS_VERSION, LIGHT_INTENSITY_COMPENSATION, MAX_COMPENSATED_LIGHT_INTENSITY, ViewUtils, CesiumViewMonitor, ViewGroundArea, ViewerEventTracker, ViewerUtils, Draw3dPolygon, Draw3dPolyline, MeasureCreator, Walkthrough, WidgetControlViewBar, WidgetControlViewBarSearch, WidgetLeftPanelTab, WidgetLeftPanelTabBookmarks, WidgetLeftPanelTabDashboard, EMenuItemState, WidgetLeftPanelTabMenuItems, Widget, VIEWER_BOOKMARKS_WIDGET_KEY, WidgetBookmarks, WidgetBranding, ECursor, 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 };
47535
47855
  //# sourceMappingURL=bruce-cesium.es5.js.map