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.
- package/dist/bruce-cesium.es5.js +326 -6
- package/dist/bruce-cesium.es5.js.map +1 -1
- package/dist/bruce-cesium.umd.js +335 -16
- 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 +270 -1
- 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/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/lib/widgets/widget-cursorbar.js +20 -2
- package/dist/lib/widgets/widget-cursorbar.js.map +1 -1
- package/dist/types/bruce-cesium.d.ts +1 -1
- package/dist/types/rendering/displaced-surface-primitive.d.ts +29 -0
- package/dist/types/rendering/entity-render-engine-polygon.d.ts +6 -0
- package/dist/types/utils/cesium-entity-styler.d.ts +3 -0
- package/dist/types/widgets/widget-cursorbar.d.ts +5 -2
- package/package.json +2 -2
package/dist/bruce-cesium.umd.js
CHANGED
|
@@ -400,7 +400,7 @@
|
|
|
400
400
|
function EnsurePosHeight(params) {
|
|
401
401
|
let { pos3d, viewer, desiredHeightRef, heightRef } = params;
|
|
402
402
|
const carto = BModels.Cartes.ValidateCartes3(pos3d) ? Cesium.Cartographic.fromCartesian(pos3d) : null;
|
|
403
|
-
if (!
|
|
403
|
+
if (!carto) {
|
|
404
404
|
return pos3d;
|
|
405
405
|
}
|
|
406
406
|
if (heightRef == null) {
|
|
@@ -3339,6 +3339,12 @@
|
|
|
3339
3339
|
}
|
|
3340
3340
|
}
|
|
3341
3341
|
CesiumEntityStyler.Refresh = Refresh;
|
|
3342
|
+
// Read the unselected colour even while a selection animation is running.
|
|
3343
|
+
function GetDefaultColor(viewer, graphic) {
|
|
3344
|
+
var _a;
|
|
3345
|
+
return (_a = getColor$1(viewer, "default", graphic)) === null || _a === void 0 ? void 0 : _a.clone();
|
|
3346
|
+
}
|
|
3347
|
+
CesiumEntityStyler.GetDefaultColor = GetDefaultColor;
|
|
3342
3348
|
function BakeDefaultColor(params) {
|
|
3343
3349
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
3344
3350
|
let { viewer, entity, override, colors, refresh } = params;
|
|
@@ -33467,12 +33473,11 @@
|
|
|
33467
33473
|
}
|
|
33468
33474
|
}
|
|
33469
33475
|
|
|
33470
|
-
var ECursor;
|
|
33471
33476
|
(function (ECursor) {
|
|
33472
33477
|
ECursor["Select"] = "select";
|
|
33473
33478
|
ECursor["Pan"] = "pan";
|
|
33474
33479
|
ECursor["Measure"] = "measure";
|
|
33475
|
-
})(ECursor || (ECursor = {}));
|
|
33480
|
+
})(exports.ECursor || (exports.ECursor = {}));
|
|
33476
33481
|
var ESecondaryCursor;
|
|
33477
33482
|
(function (ESecondaryCursor) {
|
|
33478
33483
|
ESecondaryCursor["None"] = "none";
|
|
@@ -33486,14 +33491,32 @@
|
|
|
33486
33491
|
constructor(params) {
|
|
33487
33492
|
super(params);
|
|
33488
33493
|
this.STYLESHEET_ID = "nextspace-cursorbar-stylesheet";
|
|
33489
|
-
this._selectedCursor = ECursor.Select;
|
|
33494
|
+
this._selectedCursor = exports.ECursor.Select;
|
|
33490
33495
|
this._selectedSecondaryCursor = ESecondaryCursor.None;
|
|
33491
33496
|
this.OnCursorChange = new BModels.BruceEvent();
|
|
33492
33497
|
this._generateStyles();
|
|
33493
33498
|
this._generateElement();
|
|
33494
|
-
if (this._selectedCursor == ECursor.Select || this._selectedSecondaryCursor == ESecondaryCursor.Select) {
|
|
33499
|
+
if (this._selectedCursor == exports.ECursor.Select || this._selectedSecondaryCursor == ESecondaryCursor.Select) {
|
|
33500
|
+
this._listenSelection();
|
|
33501
|
+
}
|
|
33502
|
+
}
|
|
33503
|
+
/**
|
|
33504
|
+
* @param cursor
|
|
33505
|
+
*/
|
|
33506
|
+
SetCursor(cursor) {
|
|
33507
|
+
if (cursor == this._selectedCursor) {
|
|
33508
|
+
return;
|
|
33509
|
+
}
|
|
33510
|
+
this._disposeMeasureTool();
|
|
33511
|
+
this._disposeCesiumEvent();
|
|
33512
|
+
this._selectedCursor = cursor;
|
|
33513
|
+
this._selectedSecondaryCursor = ESecondaryCursor.None;
|
|
33514
|
+
this._secondary.style.display = "none";
|
|
33515
|
+
if (cursor == exports.ECursor.Select) {
|
|
33495
33516
|
this._listenSelection();
|
|
33496
33517
|
}
|
|
33518
|
+
this._updateControls();
|
|
33519
|
+
this.OnCursorChange.Trigger(cursor);
|
|
33497
33520
|
}
|
|
33498
33521
|
Dispose() {
|
|
33499
33522
|
var _a, _b;
|
|
@@ -33745,8 +33768,8 @@
|
|
|
33745
33768
|
<path d="M11.0706 25L9 7L23 17.8592L15.3135 18.3375L11.0706 25Z" fill="white" stroke="white" strokeLinejoin="round"/>
|
|
33746
33769
|
</svg>
|
|
33747
33770
|
`;
|
|
33748
|
-
this._generateControl("Select", ECursor.Select, () => {
|
|
33749
|
-
this._selectedCursor = ECursor.Select;
|
|
33771
|
+
this._generateControl("Select", exports.ECursor.Select, () => {
|
|
33772
|
+
this._selectedCursor = exports.ECursor.Select;
|
|
33750
33773
|
this._secondary.style.display = "none";
|
|
33751
33774
|
this._listenSelection();
|
|
33752
33775
|
this.OnCursorChange.Trigger(this._selectedCursor);
|
|
@@ -33758,10 +33781,10 @@
|
|
|
33758
33781
|
<path d="M15.5652 6C14.9172 6 14.3913 6.51692 14.3913 7.15385V14.4615H13.6087V8.69231C13.6087 8.05538 13.0828 7.53846 12.4348 7.53846C11.7868 7.53846 11.2609 8.05538 11.2609 8.69231V14.4615V16.7692V19.6734C11.2609 19.6734 9.0069 18.2402 7.87211 17.7548C7.55594 17.6194 7.22575 17.5385 6.89079 17.5385C5.1401 17.5385 5 19.0769 5 19.0769L8.13043 21.3846L10.6357 24.3398C11.5279 25.3922 12.85 26 14.243 26H19.8696C21.5983 26 23 24.6223 23 22.9231V14.4615V11C23 10.3631 22.4741 9.84615 21.8261 9.84615C21.1781 9.84615 20.6522 10.3631 20.6522 11V14.4615H19.8696V8.69231C19.8696 8.05538 19.3437 7.53846 18.6957 7.53846C18.0477 7.53846 17.5217 8.05538 17.5217 8.69231V14.4615H16.7391V7.15385C16.7391 6.51692 16.2132 6 15.5652 6Z" fill="white"/>
|
|
33759
33782
|
</svg>
|
|
33760
33783
|
`;
|
|
33761
|
-
this._generateControl("Pan", ECursor.Pan, () => {
|
|
33762
|
-
this._selectedCursor = this._selectedCursor == ECursor.Pan ? ECursor.Select : ECursor.Pan;
|
|
33784
|
+
this._generateControl("Pan", exports.ECursor.Pan, () => {
|
|
33785
|
+
this._selectedCursor = this._selectedCursor == exports.ECursor.Pan ? exports.ECursor.Select : exports.ECursor.Pan;
|
|
33763
33786
|
this._secondary.style.display = "none";
|
|
33764
|
-
if (this._selectedCursor == ECursor.Select) {
|
|
33787
|
+
if (this._selectedCursor == exports.ECursor.Select) {
|
|
33765
33788
|
this._listenSelection();
|
|
33766
33789
|
}
|
|
33767
33790
|
this.OnCursorChange.Trigger(this._selectedCursor);
|
|
@@ -33773,17 +33796,17 @@
|
|
|
33773
33796
|
<path d="M26.5044 8.88032C26.1735 8.54947 23.4505 5.8265 23.1197 5.49564C22.4588 4.83479 21.3876 4.83479 20.7267 5.49564C20.6878 5.53457 20.4449 5.77742 20.0557 6.16666L21.6753 7.78623C22.0061 8.11708 22.0061 8.65186 21.6753 8.98271C21.5103 9.14771 21.2936 9.23064 21.077 9.23064C20.8604 9.23064 20.6438 9.14771 20.4788 8.98271L18.8592 7.36314C18.4581 7.76423 18.0063 8.21608 17.5172 8.70517L18.2906 9.47857C18.6214 9.80942 18.6214 10.3442 18.2906 10.6751C18.1256 10.8401 17.909 10.923 17.6923 10.923C17.4757 10.923 17.2591 10.8401 17.0941 10.6751L16.3207 9.90165C15.8875 10.3349 15.4381 10.7842 14.9787 11.2437L16.5982 12.8632C16.9291 13.1941 16.9291 13.7289 16.5982 14.0597C16.4332 14.2247 16.2166 14.3077 16 14.3077C15.7834 14.3077 15.5668 14.2247 15.4018 14.0597L13.7822 12.4402C13.3363 12.8861 12.8869 13.3354 12.4402 13.7822L13.2136 14.5556C13.5444 14.8864 13.5444 15.4212 13.2136 15.7521C13.0486 15.9171 12.8319 16 12.6153 16C12.3987 16 12.1821 15.9171 12.0171 15.7521L11.2437 14.9787C10.7842 15.4381 10.3349 15.8875 9.90165 16.3207L11.5212 17.9403C11.8521 18.2711 11.8521 18.8059 11.5212 19.1368C11.3562 19.3018 11.1396 19.3847 10.923 19.3847C10.7064 19.3847 10.4897 19.3018 10.3247 19.1368L8.70517 17.5172C8.21608 18.0063 7.76423 18.4581 7.36314 18.8592L8.13654 19.6326C8.46739 19.9635 8.46739 20.4982 8.13654 20.8291C7.97154 20.9941 7.75492 21.077 7.5383 21.077C7.32168 21.077 7.10506 20.9941 6.94006 20.8291L6.16666 20.0557C5.77742 20.4449 5.53457 20.6878 5.49564 20.7267C4.83479 21.3876 4.83479 22.4588 5.49564 23.1197C5.8265 23.4505 8.54947 26.1735 8.88032 26.5044C9.54118 27.1652 10.6124 27.1652 11.2733 26.5044C11.6041 26.1735 26.1735 11.6041 26.5044 11.2733C27.1652 10.6124 27.1652 9.54118 26.5044 8.88032Z" fill="white"/>
|
|
33774
33797
|
</svg>
|
|
33775
33798
|
`;
|
|
33776
|
-
this._generateControl("Measure", ECursor.Measure, () => {
|
|
33799
|
+
this._generateControl("Measure", exports.ECursor.Measure, () => {
|
|
33777
33800
|
this._selectedSecondaryCursor = ESecondaryCursor.Pan;
|
|
33778
|
-
this._selectedCursor = this._selectedCursor == ECursor.Measure ? ECursor.Select : ECursor.Measure;
|
|
33779
|
-
if (this._selectedCursor == ECursor.Measure) {
|
|
33801
|
+
this._selectedCursor = this._selectedCursor == exports.ECursor.Measure ? exports.ECursor.Select : exports.ECursor.Measure;
|
|
33802
|
+
if (this._selectedCursor == exports.ECursor.Measure) {
|
|
33780
33803
|
this._generateMeasureSecondary();
|
|
33781
33804
|
this._updateSecondary();
|
|
33782
33805
|
}
|
|
33783
33806
|
else {
|
|
33784
33807
|
this._secondary.style.display = "none";
|
|
33785
33808
|
}
|
|
33786
|
-
if (this._selectedCursor == ECursor.Select) {
|
|
33809
|
+
if (this._selectedCursor == exports.ECursor.Select) {
|
|
33787
33810
|
this._listenSelection();
|
|
33788
33811
|
}
|
|
33789
33812
|
this.OnCursorChange.Trigger(this._selectedCursor);
|
|
@@ -43449,6 +43472,44 @@
|
|
|
43449
43472
|
const MASK_TEXTURE_MAX_SIDE = 1024;
|
|
43450
43473
|
// Stands in for "no floor" and "no clearance", far below anything the sheet can reach.
|
|
43451
43474
|
const NO_LIMIT_METRES = -1e6;
|
|
43475
|
+
// Ripple layers to cycle across the field's own repeat.
|
|
43476
|
+
const WATER_WAVES = [
|
|
43477
|
+
{ x: 2, y: 1, amplitude: 6.4 },
|
|
43478
|
+
{ x: 1, y: 4, amplitude: 3.9 },
|
|
43479
|
+
{ x: -6, y: 4, amplitude: 2.5 },
|
|
43480
|
+
{ x: 9, y: -9, amplitude: 1.6 },
|
|
43481
|
+
{ x: -14, y: 18, amplitude: 1.0 },
|
|
43482
|
+
{ x: 38, y: 15, amplitude: 0.63 },
|
|
43483
|
+
{ x: -30, y: 68, amplitude: 0.39 },
|
|
43484
|
+
{ x: 120, y: 57, amplitude: 0.245 }
|
|
43485
|
+
];
|
|
43486
|
+
const waveCycles = (wave) => Math.hypot(wave.x, wave.y);
|
|
43487
|
+
// Which layer the wavelength setting names. The ladder runs either side of it.
|
|
43488
|
+
const WATER_BASE_WAVE = 4;
|
|
43489
|
+
// How many metres the field repeats over, as a multiple of the settings' own wavelength.
|
|
43490
|
+
const WATER_PERIOD_IN_WAVELENGTHS = waveCycles(WATER_WAVES[WATER_BASE_WAVE]);
|
|
43491
|
+
/*
|
|
43492
|
+
* How much of the surface's total slope each layer carries, which is its amplitude against its
|
|
43493
|
+
* wave number rather than its amplitude alone.
|
|
43494
|
+
*/
|
|
43495
|
+
const WATER_WAVE_SLOPES = (() => {
|
|
43496
|
+
const raw = WATER_WAVES.map((wave) => wave.amplitude * waveCycles(wave));
|
|
43497
|
+
const total = raw.reduce((sum, value) => sum + value, 0);
|
|
43498
|
+
return raw.map((value) => value / total);
|
|
43499
|
+
})();
|
|
43500
|
+
// Screen pixels a ripple layer needs to span before it counts at all, and before it counts in
|
|
43501
|
+
// full. Below the first it is finer than the pixel grid and turns into moire that crawls as the
|
|
43502
|
+
// camera moves; the gap between the two is there so a layer leaves gradually rather than
|
|
43503
|
+
// stepping out and leaving a visible change in the surface.
|
|
43504
|
+
const WATER_MIN_PIXELS_PER_WAVE = 6;
|
|
43505
|
+
const WATER_FULL_PIXELS_PER_WAVE = 16;
|
|
43506
|
+
const DEFAULT_WATER_WAVELENGTH_METRES = 26;
|
|
43507
|
+
const DEFAULT_WATER_AMPLITUDE_METRES = 0.11;
|
|
43508
|
+
const DEFAULT_WATER_SPEED_METRES_PER_SECOND = 0.6;
|
|
43509
|
+
const DEFAULT_WATER_REFLECTIVITY = 0.72;
|
|
43510
|
+
const DEFAULT_WATER_GLOSSINESS = 140;
|
|
43511
|
+
const DEFAULT_WATER_SUN_INTENSITY = 1;
|
|
43512
|
+
const DEFAULT_WATER_SKY_COLOR = { red: 150, green: 186, blue: 214, alpha: 1 };
|
|
43452
43513
|
const GROUND_MIN_METRES = -1000;
|
|
43453
43514
|
const GROUND_MAX_METRES = 9000;
|
|
43454
43515
|
const DEFAULT_LOW_COLOR = { red: 255, green: 255, blue: 255, alpha: 0.12 };
|
|
@@ -43484,10 +43545,17 @@ uniform vec2 u_maskGroundSize;
|
|
|
43484
43545
|
uniform vec4 u_extentDegrees;
|
|
43485
43546
|
uniform vec4 u_maskGroundDegrees;
|
|
43486
43547
|
uniform float u_coverageCutoffVertex;
|
|
43548
|
+
uniform vec2 u_extentMetres;
|
|
43549
|
+
uniform vec2 u_waveOrigin;
|
|
43487
43550
|
|
|
43488
43551
|
out vec2 v_st;
|
|
43489
43552
|
out float v_value;
|
|
43490
43553
|
out float v_coverage;
|
|
43554
|
+
out vec3 v_positionEC;
|
|
43555
|
+
out vec3 v_eastEC;
|
|
43556
|
+
out vec3 v_northEC;
|
|
43557
|
+
out vec3 v_upEC;
|
|
43558
|
+
out vec2 v_waveMetres;
|
|
43491
43559
|
|
|
43492
43560
|
float decodeGround(vec2 uv) {
|
|
43493
43561
|
// Channels arrive normalised to 0..1, so they go back to bytes before being reassembled.
|
|
@@ -43606,6 +43674,25 @@ void main() {
|
|
|
43606
43674
|
// Added to the LOW half of the encoded position: a metre-scale offset added to the high half
|
|
43607
43675
|
// would be lost to float32 rounding at an earth radius.
|
|
43608
43676
|
vec4 p = czm_translateRelativeToEye(position3DHigh, position3DLow + normal * displacement);
|
|
43677
|
+
|
|
43678
|
+
// The local frame at this vertex so a shading normal built in east/north/up meters can be turned into something usable.
|
|
43679
|
+
v_upEC = czm_normal * normal;
|
|
43680
|
+
vec3 east = normalize(cross(vec3(0.0, 0.0, 1.0), normal));
|
|
43681
|
+
v_eastEC = czm_normal * east;
|
|
43682
|
+
v_northEC = czm_normal * cross(normal, east);
|
|
43683
|
+
v_positionEC = (czm_modelViewRelativeToEye * p).xyz;
|
|
43684
|
+
|
|
43685
|
+
/*
|
|
43686
|
+
* Where this vertex sits in the ripple field, in metres from an origin that follows the camera.
|
|
43687
|
+
*
|
|
43688
|
+
* Subtracted here rather than in the fragment shader because the position it is subtracted from
|
|
43689
|
+
* spans the whole archive, which over a sound is tens of kilometres. A wave number times that
|
|
43690
|
+
* is thousands of radians, and no fragment shader that may only have mediump can step through a
|
|
43691
|
+
* cosine at that magnitude: the ripples come out as a flat surface, which is what a first cut of
|
|
43692
|
+
* this did. What crosses into the fragment shader is a small number the camera is standing in.
|
|
43693
|
+
*/
|
|
43694
|
+
v_waveMetres = st * u_extentMetres - u_waveOrigin;
|
|
43695
|
+
|
|
43609
43696
|
gl_Position = czm_modelViewProjectionRelativeToEye * p;
|
|
43610
43697
|
}
|
|
43611
43698
|
`;
|
|
@@ -43618,10 +43705,27 @@ uniform float u_valuePacked;
|
|
|
43618
43705
|
uniform float u_valueRange;
|
|
43619
43706
|
uniform float u_exaggeration;
|
|
43620
43707
|
uniform float u_metresPerTexel;
|
|
43708
|
+
uniform float u_waterOn;
|
|
43709
|
+
uniform float u_waterWavelength;
|
|
43710
|
+
uniform float u_waterAmplitude;
|
|
43711
|
+
uniform float u_waterReflectivity;
|
|
43712
|
+
uniform float u_waterGloss;
|
|
43713
|
+
uniform float u_waterSun;
|
|
43714
|
+
uniform vec3 u_waterSky;
|
|
43715
|
+
// One scrolled phase per ripple layer, wrapped into a turn on the CPU.
|
|
43716
|
+
uniform vec4 u_wavePhase;
|
|
43717
|
+
uniform vec4 u_wavePhaseB;
|
|
43718
|
+
// Metres the whole ripple field repeats over.
|
|
43719
|
+
uniform float u_wavePeriod;
|
|
43621
43720
|
|
|
43622
43721
|
in vec2 v_st;
|
|
43623
43722
|
in float v_value;
|
|
43624
43723
|
in float v_coverage;
|
|
43724
|
+
in vec3 v_positionEC;
|
|
43725
|
+
in vec3 v_eastEC;
|
|
43726
|
+
in vec3 v_northEC;
|
|
43727
|
+
in vec3 v_upEC;
|
|
43728
|
+
in vec2 v_waveMetres;
|
|
43625
43729
|
|
|
43626
43730
|
/*
|
|
43627
43731
|
* Scaled per channel for the same reason the vertex shader's decode is: reassembling the pair reaches
|
|
@@ -43633,6 +43737,82 @@ float valueAt(vec2 uv) {
|
|
|
43633
43737
|
return mix(texel.r, packed16, u_valuePacked);
|
|
43634
43738
|
}
|
|
43635
43739
|
|
|
43740
|
+
/*
|
|
43741
|
+
* Slope of the ripple field at a point, in metres of rise per metre travelled.
|
|
43742
|
+
*/
|
|
43743
|
+
vec2 rippleSlope(vec2 metres, float metresPerPixel, out float detail) {
|
|
43744
|
+
vec2 slope = vec2(0.0);
|
|
43745
|
+
detail = 0.0;
|
|
43746
|
+
float amplitude = u_waterAmplitude * 0.5;
|
|
43747
|
+
${WATER_WAVES.map((wave, index) => {
|
|
43748
|
+
const cycles = waveCycles(wave);
|
|
43749
|
+
return `
|
|
43750
|
+
{
|
|
43751
|
+
vec2 lattice = vec2(${wave.x.toFixed(1)}, ${wave.y.toFixed(1)});
|
|
43752
|
+
float k = 6.2831853 * ${cycles.toFixed(4)} / u_wavePeriod;
|
|
43753
|
+
float pixels = u_wavePeriod / ${cycles.toFixed(4)} / max(metresPerPixel, 1e-6);
|
|
43754
|
+
float weight = smoothstep(${WATER_MIN_PIXELS_PER_WAVE.toFixed(1)},
|
|
43755
|
+
${WATER_FULL_PIXELS_PER_WAVE.toFixed(1)}, pixels);
|
|
43756
|
+
vec2 direction = lattice / ${cycles.toFixed(4)};
|
|
43757
|
+
float phase = 6.2831853 * dot(lattice, metres) / u_wavePeriod
|
|
43758
|
+
+ ${index < 4 ? `u_wavePhase[${index}]` : `u_wavePhaseB[${index - 4}]`};
|
|
43759
|
+
slope += direction * (amplitude * ${wave.amplitude.toFixed(4)} * k * cos(phase) * weight);
|
|
43760
|
+
detail += ${WATER_WAVE_SLOPES[index].toFixed(5)} * weight;
|
|
43761
|
+
}`;
|
|
43762
|
+
}).join("")}
|
|
43763
|
+
return slope;
|
|
43764
|
+
}
|
|
43765
|
+
|
|
43766
|
+
/*
|
|
43767
|
+
* The sheet shaded as a water surface: a flat body colour seen through a sun glint and a grazing
|
|
43768
|
+
* sky reflection, with the ripple field standing in for a geometry it is far too fine to carry.
|
|
43769
|
+
*/
|
|
43770
|
+
vec4 water(vec3 relief, vec4 color) {
|
|
43771
|
+
float metresPerPixel = czm_metersPerPixel(vec4(v_positionEC, 1.0));
|
|
43772
|
+
float detail;
|
|
43773
|
+
vec2 slope = rippleSlope(v_waveMetres, metresPerPixel, detail);
|
|
43774
|
+
|
|
43775
|
+
// relief arrives normalised, so its horizontal part over its vertical part is the slope it means.
|
|
43776
|
+
vec2 reliefSlope = relief.xy / max(relief.z, 1e-3);
|
|
43777
|
+
vec3 local = normalize(vec3(-(slope + reliefSlope), 1.0));
|
|
43778
|
+
vec3 normalEC = normalize(local.x * v_eastEC + local.y * v_northEC + local.z * v_upEC);
|
|
43779
|
+
|
|
43780
|
+
vec3 view = normalize(-v_positionEC);
|
|
43781
|
+
// Drawn with culling off, so the underside of the sheet arrives with its normal pointing away.
|
|
43782
|
+
normalEC = dot(normalEC, view) < 0.0 ? -normalEC : normalEC;
|
|
43783
|
+
vec3 sun = normalize(czm_sunDirectionEC);
|
|
43784
|
+
|
|
43785
|
+
// Water at a grazing angle is almost a mirror and water looked straight down is almost clear.
|
|
43786
|
+
// That split is the single strongest cue that a blue surface is wet, more than any ripple is.
|
|
43787
|
+
float fresnel = u_waterReflectivity
|
|
43788
|
+
* (0.02 + 0.98 * pow(1.0 - clamp(dot(normalEC, view), 0.0, 1.0), 5.0));
|
|
43789
|
+
|
|
43790
|
+
// Softened by the roughness the shading has had to give up.
|
|
43791
|
+
fresnel *= mix(0.55, 1.0, detail);
|
|
43792
|
+
|
|
43793
|
+
// Where the ripples have faded out the surface is not smooth, it is rough below one pixel, so
|
|
43794
|
+
// the glint has to widen to cover what the normal no longer says.
|
|
43795
|
+
float gloss = mix(u_waterGloss * 0.12, u_waterGloss, detail);
|
|
43796
|
+
vec3 halfway = normalize(sun + view);
|
|
43797
|
+
// Weighted by the same reflectance as the sky, because a glint is a reflection too.
|
|
43798
|
+
float glint = pow(max(dot(normalEC, halfway), 0.0), gloss) * u_waterSun * fresnel;
|
|
43799
|
+
float lambert = clamp(dot(normalEC, sun), 0.0, 1.0);
|
|
43800
|
+
|
|
43801
|
+
vec3 body = color.rgb * (0.55 + 0.6 * lambert);
|
|
43802
|
+
vec3 lit = min(mix(body, u_waterSky, fresnel) + vec3(glint), vec3(1.0));
|
|
43803
|
+
|
|
43804
|
+
/*
|
|
43805
|
+
* The same fog the globe under it is already drawing with.
|
|
43806
|
+
*/
|
|
43807
|
+
lit = czm_fog(length(v_positionEC), lit, u_waterSky);
|
|
43808
|
+
|
|
43809
|
+
// A reflection seen through a half-transparent sheet is not a reflection, so the surface is
|
|
43810
|
+
// allowed to close up exactly where it is being reflective.
|
|
43811
|
+
float alpha = color.a * v_coverage;
|
|
43812
|
+
alpha = clamp(alpha + (1.0 - alpha) * (fresnel * 0.55 + glint), 0.0, 1.0);
|
|
43813
|
+
return vec4(lit, alpha);
|
|
43814
|
+
}
|
|
43815
|
+
|
|
43636
43816
|
void main() {
|
|
43637
43817
|
if (v_coverage < u_coverageCutoff) {
|
|
43638
43818
|
discard;
|
|
@@ -43653,6 +43833,12 @@ void main() {
|
|
|
43653
43833
|
float up = valueAt(v_st + vec2(0.0, u_texelSize.y));
|
|
43654
43834
|
float scale = u_valueRange * u_exaggeration;
|
|
43655
43835
|
vec3 n = normalize(vec3((left - right) * scale, (down - up) * scale, 2.0 * u_metresPerTexel));
|
|
43836
|
+
|
|
43837
|
+
if (u_waterOn > 0.5) {
|
|
43838
|
+
out_FragColor = water(n, color);
|
|
43839
|
+
return;
|
|
43840
|
+
}
|
|
43841
|
+
|
|
43656
43842
|
float lambert = clamp(dot(n, normalize(vec3(-0.5, -0.6, 0.62))), 0.0, 1.0);
|
|
43657
43843
|
color.rgb *= 0.45 + 0.9 * lambert;
|
|
43658
43844
|
|
|
@@ -44003,6 +44189,9 @@ void main() {
|
|
|
44003
44189
|
this.maskGroundBox = null;
|
|
44004
44190
|
this.maskGroundRequested = false;
|
|
44005
44191
|
this.maskGroundLevel = 0;
|
|
44192
|
+
this.water = null;
|
|
44193
|
+
this.waterStartMs = now();
|
|
44194
|
+
this.waveOrigin = new Cesium.Cartesian2(0, 0);
|
|
44006
44195
|
this.followGround = Boolean(options.followGround);
|
|
44007
44196
|
this.terrainProvider = options.terrainProvider || null;
|
|
44008
44197
|
this.extent = options.extent;
|
|
@@ -44018,6 +44207,23 @@ void main() {
|
|
|
44018
44207
|
this.maskFillValue = firstOpaqueStop(this.rampPixels);
|
|
44019
44208
|
this.tiles = buildTiles(hasCoverage);
|
|
44020
44209
|
this.SetGroundClearance(options.groundClearance || null);
|
|
44210
|
+
this.SetWater(options.water || null);
|
|
44211
|
+
}
|
|
44212
|
+
GetWater() {
|
|
44213
|
+
return this.water;
|
|
44214
|
+
}
|
|
44215
|
+
/**
|
|
44216
|
+
* Shades the sheet as water, or stops. Null goes back to the relief shading.
|
|
44217
|
+
*
|
|
44218
|
+
* Nothing is rebuilt: no mesh, no texture and no shader, since the water path is a branch in
|
|
44219
|
+
* the fragment shader the whole scene already carries. So this is cheap enough to drive from
|
|
44220
|
+
* a control the user is dragging.
|
|
44221
|
+
*/
|
|
44222
|
+
SetWater(water) {
|
|
44223
|
+
if (water && !this.water) {
|
|
44224
|
+
this.waterStartMs = now();
|
|
44225
|
+
}
|
|
44226
|
+
this.water = water;
|
|
44021
44227
|
}
|
|
44022
44228
|
GetFollowsGround() {
|
|
44023
44229
|
return this.followGround;
|
|
@@ -44188,6 +44394,12 @@ void main() {
|
|
|
44188
44394
|
const mesh = this.ensureMesh(context, tile, tile.tier);
|
|
44189
44395
|
frameState.commandList.push(this.commandFor(context, tile, mesh));
|
|
44190
44396
|
}
|
|
44397
|
+
if (this.water) {
|
|
44398
|
+
this.updateWaveOrigin(frameState);
|
|
44399
|
+
if (frameState.afterRender) {
|
|
44400
|
+
frameState.afterRender.push(() => true);
|
|
44401
|
+
}
|
|
44402
|
+
}
|
|
44191
44403
|
}
|
|
44192
44404
|
isDestroyed() {
|
|
44193
44405
|
return this.destroyed;
|
|
@@ -44399,6 +44611,60 @@ void main() {
|
|
|
44399
44611
|
})
|
|
44400
44612
|
});
|
|
44401
44613
|
}
|
|
44614
|
+
/*
|
|
44615
|
+
* Metres the extent spans west to east and north to south, which is what turns the shader's
|
|
44616
|
+
* 0..1 surface coordinate into the real distance the ripple wavelength is measured in.
|
|
44617
|
+
*/
|
|
44618
|
+
extentMetres() {
|
|
44619
|
+
const southWest = Cesium.Cartesian3.fromDegrees(this.extent.West, this.extent.South, 0);
|
|
44620
|
+
const southEast = Cesium.Cartesian3.fromDegrees(this.extent.East, this.extent.South, 0);
|
|
44621
|
+
const northWest = Cesium.Cartesian3.fromDegrees(this.extent.West, this.extent.North, 0);
|
|
44622
|
+
return new Cesium.Cartesian2(Math.max(1, Cesium.Cartesian3.distance(southWest, southEast)), Math.max(1, Cesium.Cartesian3.distance(southWest, northWest)));
|
|
44623
|
+
}
|
|
44624
|
+
/*
|
|
44625
|
+
* Where each ripple layer has scrolled to, wrapped into one turn.
|
|
44626
|
+
*/
|
|
44627
|
+
wavePhase(from) {
|
|
44628
|
+
var _a;
|
|
44629
|
+
const water = this.water;
|
|
44630
|
+
if (!water) {
|
|
44631
|
+
return new Cesium.Cartesian4(0, 0, 0, 0);
|
|
44632
|
+
}
|
|
44633
|
+
const speed = (_a = water.speed) !== null && _a !== void 0 ? _a : DEFAULT_WATER_SPEED_METRES_PER_SECOND;
|
|
44634
|
+
const period = this.wavePeriod();
|
|
44635
|
+
const seconds = (now() - this.waterStartMs) / 1000;
|
|
44636
|
+
const base = waveCycles(WATER_WAVES[WATER_BASE_WAVE]);
|
|
44637
|
+
const phases = WATER_WAVES.slice(from, from + 4).map((wave) => {
|
|
44638
|
+
const cycles = waveCycles(wave);
|
|
44639
|
+
const waveNumber = 2 * Math.PI * cycles / period;
|
|
44640
|
+
const travels = Math.sqrt(base / cycles);
|
|
44641
|
+
const travelled = seconds * speed * travels * waveNumber;
|
|
44642
|
+
return travelled % (2 * Math.PI);
|
|
44643
|
+
});
|
|
44644
|
+
return new Cesium.Cartesian4(phases[0] || 0, phases[1] || 0, phases[2] || 0, phases[3] || 0);
|
|
44645
|
+
}
|
|
44646
|
+
wavePeriod() {
|
|
44647
|
+
const wavelength = (this.water && this.water.wavelength) || DEFAULT_WATER_WAVELENGTH_METRES;
|
|
44648
|
+
return wavelength * WATER_PERIOD_IN_WAVELENGTHS;
|
|
44649
|
+
}
|
|
44650
|
+
/*
|
|
44651
|
+
* The point the ripple phase is measured from, kept near the camera and snapped to a whole
|
|
44652
|
+
* number of periods in each direction.
|
|
44653
|
+
*/
|
|
44654
|
+
updateWaveOrigin(frameState) {
|
|
44655
|
+
const period = this.wavePeriod();
|
|
44656
|
+
const carto = Cesium.Cartographic.fromCartesian(frameState.camera.positionWC);
|
|
44657
|
+
if (!carto) {
|
|
44658
|
+
return;
|
|
44659
|
+
}
|
|
44660
|
+
const metres = this.extentMetres();
|
|
44661
|
+
const longitude = Cesium.Math.toDegrees(carto.longitude);
|
|
44662
|
+
const latitude = Cesium.Math.toDegrees(carto.latitude);
|
|
44663
|
+
const u = (longitude - this.extent.West) / (this.extent.East - this.extent.West);
|
|
44664
|
+
// North is v zero, the way the vertex shader places the surface.
|
|
44665
|
+
const v = (this.extent.North - latitude) / (this.extent.North - this.extent.South);
|
|
44666
|
+
this.waveOrigin = new Cesium.Cartesian2(Math.floor(u * metres.x / period) * period, Math.floor(v * metres.y / period) * period);
|
|
44667
|
+
}
|
|
44402
44668
|
/*
|
|
44403
44669
|
* Ground distance between neighbouring texels, so the shading normal is built from a real
|
|
44404
44670
|
* slope rather than a made up one.
|
|
@@ -44625,7 +44891,33 @@ void main() {
|
|
|
44625
44891
|
: 0,
|
|
44626
44892
|
u_coverageCutoff: () => COVERAGE_CUTOFF,
|
|
44627
44893
|
u_rampTexture: () => self.rampTexture,
|
|
44628
|
-
u_texelSize: () => new Cesium.Cartesian2(1 / self.source.width, 1 / self.source.height)
|
|
44894
|
+
u_texelSize: () => new Cesium.Cartesian2(1 / self.source.width, 1 / self.source.height),
|
|
44895
|
+
u_waterOn: () => (self.water ? 1 : 0),
|
|
44896
|
+
u_waterWavelength: () => (self.water && self.water.wavelength)
|
|
44897
|
+
|| DEFAULT_WATER_WAVELENGTH_METRES,
|
|
44898
|
+
u_waterAmplitude: () => {
|
|
44899
|
+
var _a;
|
|
44900
|
+
return (_a = (self.water && self.water.amplitude)) !== null && _a !== void 0 ? _a : DEFAULT_WATER_AMPLITUDE_METRES;
|
|
44901
|
+
},
|
|
44902
|
+
u_waterReflectivity: () => {
|
|
44903
|
+
var _a;
|
|
44904
|
+
return (_a = (self.water && self.water.reflectivity)) !== null && _a !== void 0 ? _a : DEFAULT_WATER_REFLECTIVITY;
|
|
44905
|
+
},
|
|
44906
|
+
u_waterGloss: () => (self.water && self.water.glossiness)
|
|
44907
|
+
|| DEFAULT_WATER_GLOSSINESS,
|
|
44908
|
+
u_waterSun: () => {
|
|
44909
|
+
var _a;
|
|
44910
|
+
return (_a = (self.water && self.water.sunIntensity)) !== null && _a !== void 0 ? _a : DEFAULT_WATER_SUN_INTENSITY;
|
|
44911
|
+
},
|
|
44912
|
+
u_waterSky: () => {
|
|
44913
|
+
const sky = (self.water && self.water.skyColor) || DEFAULT_WATER_SKY_COLOR;
|
|
44914
|
+
return new Cesium.Cartesian3(sky.red / 255, sky.green / 255, sky.blue / 255);
|
|
44915
|
+
},
|
|
44916
|
+
u_wavePhase: () => self.wavePhase(0),
|
|
44917
|
+
u_wavePhaseB: () => self.wavePhase(4),
|
|
44918
|
+
u_wavePeriod: () => self.wavePeriod(),
|
|
44919
|
+
u_waveOrigin: () => self.waveOrigin,
|
|
44920
|
+
u_extentMetres: () => self.extentMetres()
|
|
44629
44921
|
}
|
|
44630
44922
|
});
|
|
44631
44923
|
}
|
|
@@ -45278,6 +45570,23 @@ void main() {
|
|
|
45278
45570
|
return touched;
|
|
45279
45571
|
}
|
|
45280
45572
|
EntityRenderEnginePolygon.SetGroundClearance = SetGroundClearance;
|
|
45573
|
+
/**
|
|
45574
|
+
* Shades every rendered polygon in a set as water rather than as a coloured surface.
|
|
45575
|
+
* @param cEntities
|
|
45576
|
+
* @param water Pass null to go back to the relief shading.
|
|
45577
|
+
*/
|
|
45578
|
+
function SetWater(cEntities, water) {
|
|
45579
|
+
let touched = 0;
|
|
45580
|
+
for (const cEntity of cEntities || []) {
|
|
45581
|
+
const surface = GetDisplacedSurface(cEntity);
|
|
45582
|
+
if (surface) {
|
|
45583
|
+
surface.SetWater(water);
|
|
45584
|
+
touched++;
|
|
45585
|
+
}
|
|
45586
|
+
}
|
|
45587
|
+
return touched;
|
|
45588
|
+
}
|
|
45589
|
+
EntityRenderEnginePolygon.SetWater = SetWater;
|
|
45281
45590
|
/**
|
|
45282
45591
|
* Disposes a cEntity's TextureFrameSeriesAnimator.Animator (if any).
|
|
45283
45592
|
*/
|
|
@@ -45435,6 +45744,7 @@ void main() {
|
|
|
45435
45744
|
if (reusable && existingSurface.GetFollowsGround() === placement.followGround) {
|
|
45436
45745
|
existingSurface.SetBaseHeight(placement.baseHeight);
|
|
45437
45746
|
existingSurface.SetExaggeration(exaggerationFor(style));
|
|
45747
|
+
existingSurface.SetWater(waterFor(style));
|
|
45438
45748
|
return;
|
|
45439
45749
|
}
|
|
45440
45750
|
disposeDisplacedSurface(cEntity, viewer);
|
|
@@ -45474,6 +45784,7 @@ void main() {
|
|
|
45474
45784
|
valueMax: extrusionArchive.metadata.ValueMax,
|
|
45475
45785
|
packedValue: exports.TextureFrameSeriesAnimator.IsPackedValue(extrusionArchive.metadata),
|
|
45476
45786
|
exaggeration: exaggerationFor(style),
|
|
45787
|
+
water: waterFor(style),
|
|
45477
45788
|
lowColor: mask ? BModels.Color.ColorFromStr(mask.minColor) : null,
|
|
45478
45789
|
highColor: mask ? BModels.Color.ColorFromStr(mask.maxColor) : null,
|
|
45479
45790
|
// Normalised the same way the animator normalises them, so the surface and the flat drape
|
|
@@ -45519,6 +45830,14 @@ void main() {
|
|
|
45519
45830
|
}
|
|
45520
45831
|
return 1;
|
|
45521
45832
|
}
|
|
45833
|
+
const WATER_EFFECT = "WATER";
|
|
45834
|
+
/*
|
|
45835
|
+
* The water settings a style asks a displaced surface for, or null for the plain relief shading.
|
|
45836
|
+
*/
|
|
45837
|
+
function waterFor(style) {
|
|
45838
|
+
var _a;
|
|
45839
|
+
return ((_a = style.effect) === null || _a === void 0 ? void 0 : _a.type) === WATER_EFFECT ? {} : null;
|
|
45840
|
+
}
|
|
45522
45841
|
/*
|
|
45523
45842
|
* The lon/lat bounding rectangle of a ring, which is the frame Cesium drapes an image material in.
|
|
45524
45843
|
*/
|
|
@@ -47376,7 +47695,7 @@ void main() {
|
|
|
47376
47695
|
StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
|
|
47377
47696
|
})(exports.StyleUtils || (exports.StyleUtils = {}));
|
|
47378
47697
|
|
|
47379
|
-
const VERSION = "7.3.
|
|
47698
|
+
const VERSION = "7.3.7";
|
|
47380
47699
|
/**
|
|
47381
47700
|
* Updates the environment instance used by bruce-cesium to one specified.
|
|
47382
47701
|
* This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
|