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.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;
|
|
@@ -9487,6 +9493,14 @@
|
|
|
9487
9493
|
}
|
|
9488
9494
|
};
|
|
9489
9495
|
}
|
|
9496
|
+
/**
|
|
9497
|
+
* Whether this register is holding a record of a visual.
|
|
9498
|
+
* @param visual
|
|
9499
|
+
*/
|
|
9500
|
+
HasRego(visual) {
|
|
9501
|
+
const vis = visual;
|
|
9502
|
+
return Boolean(vis && vis._register === this && vis._rego);
|
|
9503
|
+
}
|
|
9490
9504
|
/**
|
|
9491
9505
|
* Locates a visual corresponding to a given entity id.
|
|
9492
9506
|
* If no menu item id is provided, then it will pick the "best" one.
|
|
@@ -12653,6 +12667,11 @@
|
|
|
12653
12667
|
optimizeTolerance: this.item.optimizeTolerance,
|
|
12654
12668
|
});
|
|
12655
12669
|
if (this.disposed) {
|
|
12670
|
+
exports.EntityRenderEngine.RemoveAll({
|
|
12671
|
+
viewer: this.viewer,
|
|
12672
|
+
entities: cEntities,
|
|
12673
|
+
register: this.visualsManager
|
|
12674
|
+
});
|
|
12656
12675
|
this.doDispose();
|
|
12657
12676
|
return;
|
|
12658
12677
|
}
|
|
@@ -13654,6 +13673,11 @@
|
|
|
13654
13673
|
force
|
|
13655
13674
|
});
|
|
13656
13675
|
if (this.disposed) {
|
|
13676
|
+
exports.EntityRenderEngine.RemoveAll({
|
|
13677
|
+
viewer: this.viewer,
|
|
13678
|
+
entities: cEntities,
|
|
13679
|
+
register: this.visualsManager
|
|
13680
|
+
});
|
|
13657
13681
|
this.visualsManager.RemoveRegos({
|
|
13658
13682
|
menuItemId: this.item.id
|
|
13659
13683
|
});
|
|
@@ -14093,10 +14117,15 @@
|
|
|
14093
14117
|
zoomControl: this.item.CameraZoomSettings,
|
|
14094
14118
|
force: force || changed
|
|
14095
14119
|
});
|
|
14120
|
+
if (this.disposed) {
|
|
14121
|
+
exports.EntityRenderEngine.RemoveAll({
|
|
14122
|
+
viewer: this.viewer,
|
|
14123
|
+
entities: cEntities,
|
|
14124
|
+
register: this.visualsManager
|
|
14125
|
+
});
|
|
14126
|
+
return;
|
|
14127
|
+
}
|
|
14096
14128
|
for (let i = 0; i < entities.length; i++) {
|
|
14097
|
-
if (this.disposed) {
|
|
14098
|
-
break;
|
|
14099
|
-
}
|
|
14100
14129
|
const entity = entities[i];
|
|
14101
14130
|
const id = entity.Bruce.ID;
|
|
14102
14131
|
const cEntity = cEntities.get(id);
|
|
@@ -19465,6 +19494,11 @@
|
|
|
19465
19494
|
force
|
|
19466
19495
|
});
|
|
19467
19496
|
if (this.disposed) {
|
|
19497
|
+
exports.EntityRenderEngine.RemoveAll({
|
|
19498
|
+
viewer: this.viewer,
|
|
19499
|
+
entities: cEntities,
|
|
19500
|
+
register: this.visualsManager
|
|
19501
|
+
});
|
|
19468
19502
|
return;
|
|
19469
19503
|
}
|
|
19470
19504
|
for (let i = 0; i < entities.length; i++) {
|
|
@@ -43466,6 +43500,44 @@
|
|
|
43466
43500
|
const MASK_TEXTURE_MAX_SIDE = 1024;
|
|
43467
43501
|
// Stands in for "no floor" and "no clearance", far below anything the sheet can reach.
|
|
43468
43502
|
const NO_LIMIT_METRES = -1e6;
|
|
43503
|
+
// Ripple layers to cycle across the field's own repeat.
|
|
43504
|
+
const WATER_WAVES = [
|
|
43505
|
+
{ x: 2, y: 1, amplitude: 6.4 },
|
|
43506
|
+
{ x: 1, y: 4, amplitude: 3.9 },
|
|
43507
|
+
{ x: -6, y: 4, amplitude: 2.5 },
|
|
43508
|
+
{ x: 9, y: -9, amplitude: 1.6 },
|
|
43509
|
+
{ x: -14, y: 18, amplitude: 1.0 },
|
|
43510
|
+
{ x: 38, y: 15, amplitude: 0.63 },
|
|
43511
|
+
{ x: -30, y: 68, amplitude: 0.39 },
|
|
43512
|
+
{ x: 120, y: 57, amplitude: 0.245 }
|
|
43513
|
+
];
|
|
43514
|
+
const waveCycles = (wave) => Math.hypot(wave.x, wave.y);
|
|
43515
|
+
// Which layer the wavelength setting names. The ladder runs either side of it.
|
|
43516
|
+
const WATER_BASE_WAVE = 4;
|
|
43517
|
+
// How many metres the field repeats over, as a multiple of the settings' own wavelength.
|
|
43518
|
+
const WATER_PERIOD_IN_WAVELENGTHS = waveCycles(WATER_WAVES[WATER_BASE_WAVE]);
|
|
43519
|
+
/*
|
|
43520
|
+
* How much of the surface's total slope each layer carries, which is its amplitude against its
|
|
43521
|
+
* wave number rather than its amplitude alone.
|
|
43522
|
+
*/
|
|
43523
|
+
const WATER_WAVE_SLOPES = (() => {
|
|
43524
|
+
const raw = WATER_WAVES.map((wave) => wave.amplitude * waveCycles(wave));
|
|
43525
|
+
const total = raw.reduce((sum, value) => sum + value, 0);
|
|
43526
|
+
return raw.map((value) => value / total);
|
|
43527
|
+
})();
|
|
43528
|
+
// Screen pixels a ripple layer needs to span before it counts at all, and before it counts in
|
|
43529
|
+
// full. Below the first it is finer than the pixel grid and turns into moire that crawls as the
|
|
43530
|
+
// camera moves; the gap between the two is there so a layer leaves gradually rather than
|
|
43531
|
+
// stepping out and leaving a visible change in the surface.
|
|
43532
|
+
const WATER_MIN_PIXELS_PER_WAVE = 6;
|
|
43533
|
+
const WATER_FULL_PIXELS_PER_WAVE = 16;
|
|
43534
|
+
const DEFAULT_WATER_WAVELENGTH_METRES = 26;
|
|
43535
|
+
const DEFAULT_WATER_AMPLITUDE_METRES = 0.11;
|
|
43536
|
+
const DEFAULT_WATER_SPEED_METRES_PER_SECOND = 0.6;
|
|
43537
|
+
const DEFAULT_WATER_REFLECTIVITY = 0.72;
|
|
43538
|
+
const DEFAULT_WATER_GLOSSINESS = 140;
|
|
43539
|
+
const DEFAULT_WATER_SUN_INTENSITY = 1;
|
|
43540
|
+
const DEFAULT_WATER_SKY_COLOR = { red: 150, green: 186, blue: 214, alpha: 1 };
|
|
43469
43541
|
const GROUND_MIN_METRES = -1000;
|
|
43470
43542
|
const GROUND_MAX_METRES = 9000;
|
|
43471
43543
|
const DEFAULT_LOW_COLOR = { red: 255, green: 255, blue: 255, alpha: 0.12 };
|
|
@@ -43501,10 +43573,21 @@ uniform vec2 u_maskGroundSize;
|
|
|
43501
43573
|
uniform vec4 u_extentDegrees;
|
|
43502
43574
|
uniform vec4 u_maskGroundDegrees;
|
|
43503
43575
|
uniform float u_coverageCutoffVertex;
|
|
43576
|
+
//#water
|
|
43577
|
+
uniform vec2 u_extentMetres;
|
|
43578
|
+
uniform vec2 u_waveOrigin;
|
|
43579
|
+
//#endwater
|
|
43504
43580
|
|
|
43505
43581
|
out vec2 v_st;
|
|
43506
43582
|
out float v_value;
|
|
43507
43583
|
out float v_coverage;
|
|
43584
|
+
//#water
|
|
43585
|
+
out vec3 v_positionEC;
|
|
43586
|
+
out vec3 v_eastEC;
|
|
43587
|
+
out vec3 v_northEC;
|
|
43588
|
+
out vec3 v_upEC;
|
|
43589
|
+
out vec2 v_waveMetres;
|
|
43590
|
+
//#endwater
|
|
43508
43591
|
|
|
43509
43592
|
float decodeGround(vec2 uv) {
|
|
43510
43593
|
// Channels arrive normalised to 0..1, so they go back to bytes before being reassembled.
|
|
@@ -43623,6 +43706,19 @@ void main() {
|
|
|
43623
43706
|
// Added to the LOW half of the encoded position: a metre-scale offset added to the high half
|
|
43624
43707
|
// would be lost to float32 rounding at an earth radius.
|
|
43625
43708
|
vec4 p = czm_translateRelativeToEye(position3DHigh, position3DLow + normal * displacement);
|
|
43709
|
+
|
|
43710
|
+
//#water
|
|
43711
|
+
// The local frame at this vertex so a shading normal built in east/north/up meters can be turned into something usable.
|
|
43712
|
+
v_upEC = czm_normal * normal;
|
|
43713
|
+
vec3 east = normalize(cross(vec3(0.0, 0.0, 1.0), normal));
|
|
43714
|
+
v_eastEC = czm_normal * east;
|
|
43715
|
+
v_northEC = czm_normal * cross(normal, east);
|
|
43716
|
+
v_positionEC = (czm_modelViewRelativeToEye * p).xyz;
|
|
43717
|
+
|
|
43718
|
+
// Where this vertex sits in the ripple field, in metres from an origin that follows the camera.
|
|
43719
|
+
v_waveMetres = st * u_extentMetres - u_waveOrigin;
|
|
43720
|
+
//#endwater
|
|
43721
|
+
|
|
43626
43722
|
gl_Position = czm_modelViewProjectionRelativeToEye * p;
|
|
43627
43723
|
}
|
|
43628
43724
|
`;
|
|
@@ -43635,10 +43731,30 @@ uniform float u_valuePacked;
|
|
|
43635
43731
|
uniform float u_valueRange;
|
|
43636
43732
|
uniform float u_exaggeration;
|
|
43637
43733
|
uniform float u_metresPerTexel;
|
|
43734
|
+
//#water
|
|
43735
|
+
uniform float u_waterWavelength;
|
|
43736
|
+
uniform float u_waterAmplitude;
|
|
43737
|
+
uniform float u_waterReflectivity;
|
|
43738
|
+
uniform float u_waterGloss;
|
|
43739
|
+
uniform float u_waterSun;
|
|
43740
|
+
uniform vec3 u_waterSky;
|
|
43741
|
+
// One scrolled phase per ripple layer, wrapped into a turn on the CPU.
|
|
43742
|
+
uniform vec4 u_wavePhase;
|
|
43743
|
+
uniform vec4 u_wavePhaseB;
|
|
43744
|
+
// Metres the whole ripple field repeats over.
|
|
43745
|
+
uniform float u_wavePeriod;
|
|
43746
|
+
//#endwater
|
|
43638
43747
|
|
|
43639
43748
|
in vec2 v_st;
|
|
43640
43749
|
in float v_value;
|
|
43641
43750
|
in float v_coverage;
|
|
43751
|
+
//#water
|
|
43752
|
+
in vec3 v_positionEC;
|
|
43753
|
+
in vec3 v_eastEC;
|
|
43754
|
+
in vec3 v_northEC;
|
|
43755
|
+
in vec3 v_upEC;
|
|
43756
|
+
in vec2 v_waveMetres;
|
|
43757
|
+
//#endwater
|
|
43642
43758
|
|
|
43643
43759
|
/*
|
|
43644
43760
|
* Scaled per channel for the same reason the vertex shader's decode is: reassembling the pair reaches
|
|
@@ -43650,6 +43766,84 @@ float valueAt(vec2 uv) {
|
|
|
43650
43766
|
return mix(texel.r, packed16, u_valuePacked);
|
|
43651
43767
|
}
|
|
43652
43768
|
|
|
43769
|
+
//#water
|
|
43770
|
+
/*
|
|
43771
|
+
* Slope of the ripple field at a point, in metres of rise per metre travelled.
|
|
43772
|
+
*/
|
|
43773
|
+
vec2 rippleSlope(vec2 metres, float metresPerPixel, out float detail) {
|
|
43774
|
+
vec2 slope = vec2(0.0);
|
|
43775
|
+
detail = 0.0;
|
|
43776
|
+
float amplitude = u_waterAmplitude * 0.5;
|
|
43777
|
+
${WATER_WAVES.map((wave, index) => {
|
|
43778
|
+
const cycles = waveCycles(wave);
|
|
43779
|
+
return `
|
|
43780
|
+
{
|
|
43781
|
+
vec2 lattice = vec2(${wave.x.toFixed(1)}, ${wave.y.toFixed(1)});
|
|
43782
|
+
float k = 6.2831853 * ${cycles.toFixed(4)} / u_wavePeriod;
|
|
43783
|
+
float pixels = u_wavePeriod / ${cycles.toFixed(4)} / max(metresPerPixel, 1e-6);
|
|
43784
|
+
float weight = smoothstep(${WATER_MIN_PIXELS_PER_WAVE.toFixed(1)},
|
|
43785
|
+
${WATER_FULL_PIXELS_PER_WAVE.toFixed(1)}, pixels);
|
|
43786
|
+
vec2 direction = lattice / ${cycles.toFixed(4)};
|
|
43787
|
+
float phase = 6.2831853 * dot(lattice, metres) / u_wavePeriod
|
|
43788
|
+
+ ${index < 4 ? `u_wavePhase[${index}]` : `u_wavePhaseB[${index - 4}]`};
|
|
43789
|
+
slope += direction * (amplitude * ${wave.amplitude.toFixed(4)} * k * cos(phase) * weight);
|
|
43790
|
+
detail += ${WATER_WAVE_SLOPES[index].toFixed(5)} * weight;
|
|
43791
|
+
}`;
|
|
43792
|
+
}).join("")}
|
|
43793
|
+
return slope;
|
|
43794
|
+
}
|
|
43795
|
+
|
|
43796
|
+
/*
|
|
43797
|
+
* The sheet shaded as a water surface: a flat body colour seen through a sun glint and a grazing
|
|
43798
|
+
* sky reflection, with the ripple field standing in for a geometry it is far too fine to carry.
|
|
43799
|
+
*/
|
|
43800
|
+
vec4 water(vec3 relief, vec4 color) {
|
|
43801
|
+
float metresPerPixel = czm_metersPerPixel(vec4(v_positionEC, 1.0));
|
|
43802
|
+
float detail;
|
|
43803
|
+
vec2 slope = rippleSlope(v_waveMetres, metresPerPixel, detail);
|
|
43804
|
+
|
|
43805
|
+
// relief arrives normalised, so its horizontal part over its vertical part is the slope it means.
|
|
43806
|
+
vec2 reliefSlope = relief.xy / max(relief.z, 1e-3);
|
|
43807
|
+
vec3 local = normalize(vec3(-(slope + reliefSlope), 1.0));
|
|
43808
|
+
vec3 normalEC = normalize(local.x * v_eastEC + local.y * v_northEC + local.z * v_upEC);
|
|
43809
|
+
|
|
43810
|
+
vec3 view = normalize(-v_positionEC);
|
|
43811
|
+
// Drawn with culling off, so the underside of the sheet arrives with its normal pointing away.
|
|
43812
|
+
normalEC = dot(normalEC, view) < 0.0 ? -normalEC : normalEC;
|
|
43813
|
+
vec3 sun = normalize(czm_sunDirectionEC);
|
|
43814
|
+
|
|
43815
|
+
// Water at a grazing angle is almost a mirror and water looked straight down is almost clear.
|
|
43816
|
+
// That split is the single strongest cue that a blue surface is wet, more than any ripple is.
|
|
43817
|
+
float fresnel = u_waterReflectivity
|
|
43818
|
+
* (0.02 + 0.98 * pow(1.0 - clamp(dot(normalEC, view), 0.0, 1.0), 5.0));
|
|
43819
|
+
|
|
43820
|
+
// Softened by the roughness the shading has had to give up.
|
|
43821
|
+
fresnel *= mix(0.55, 1.0, detail);
|
|
43822
|
+
|
|
43823
|
+
// Where the ripples have faded out the surface is not smooth, it is rough below one pixel, so
|
|
43824
|
+
// the glint has to widen to cover what the normal no longer says.
|
|
43825
|
+
float gloss = mix(u_waterGloss * 0.12, u_waterGloss, detail);
|
|
43826
|
+
vec3 halfway = normalize(sun + view);
|
|
43827
|
+
// Weighted by the same reflectance as the sky, because a glint is a reflection too.
|
|
43828
|
+
float glint = pow(max(dot(normalEC, halfway), 0.0), gloss) * u_waterSun * fresnel;
|
|
43829
|
+
float lambert = clamp(dot(normalEC, sun), 0.0, 1.0);
|
|
43830
|
+
|
|
43831
|
+
vec3 body = color.rgb * (0.55 + 0.6 * lambert);
|
|
43832
|
+
vec3 lit = min(mix(body, u_waterSky, fresnel) + vec3(glint), vec3(1.0));
|
|
43833
|
+
|
|
43834
|
+
/*
|
|
43835
|
+
* The same fog the globe under it is already drawing with.
|
|
43836
|
+
*/
|
|
43837
|
+
lit = czm_fog(length(v_positionEC), lit, u_waterSky);
|
|
43838
|
+
|
|
43839
|
+
// A reflection seen through a half-transparent sheet is not a reflection, so the surface is
|
|
43840
|
+
// allowed to close up exactly where it is being reflective.
|
|
43841
|
+
float alpha = color.a * v_coverage;
|
|
43842
|
+
alpha = clamp(alpha + (1.0 - alpha) * (fresnel * 0.55 + glint), 0.0, 1.0);
|
|
43843
|
+
return vec4(lit, alpha);
|
|
43844
|
+
}
|
|
43845
|
+
//#endwater
|
|
43846
|
+
|
|
43653
43847
|
void main() {
|
|
43654
43848
|
if (v_coverage < u_coverageCutoff) {
|
|
43655
43849
|
discard;
|
|
@@ -43670,12 +43864,27 @@ void main() {
|
|
|
43670
43864
|
float up = valueAt(v_st + vec2(0.0, u_texelSize.y));
|
|
43671
43865
|
float scale = u_valueRange * u_exaggeration;
|
|
43672
43866
|
vec3 n = normalize(vec3((left - right) * scale, (down - up) * scale, 2.0 * u_metresPerTexel));
|
|
43867
|
+
|
|
43868
|
+
//#water
|
|
43869
|
+
out_FragColor = water(n, color);
|
|
43870
|
+
return;
|
|
43871
|
+
//#endwater
|
|
43872
|
+
|
|
43673
43873
|
float lambert = clamp(dot(n, normalize(vec3(-0.5, -0.6, 0.62))), 0.0, 1.0);
|
|
43674
43874
|
color.rgb *= 0.45 + 0.9 * lambert;
|
|
43675
43875
|
|
|
43676
43876
|
out_FragColor = vec4(color.rgb, color.a * v_coverage);
|
|
43677
43877
|
}
|
|
43678
43878
|
`;
|
|
43879
|
+
/*
|
|
43880
|
+
* Strips the water-only regions out of a shader source unless this surface is drawing water.
|
|
43881
|
+
*/
|
|
43882
|
+
function withWater(source, water) {
|
|
43883
|
+
if (water) {
|
|
43884
|
+
return source.replace(/^\/\/#(end)?water\n/gm, "");
|
|
43885
|
+
}
|
|
43886
|
+
return source.replace(/^\/\/#water\n[\s\S]*?^\/\/#endwater\n/gm, "");
|
|
43887
|
+
}
|
|
43679
43888
|
/*
|
|
43680
43889
|
* Rewrites a GLSL 300 es source into the GLSL 100 dialect older Cesium builds author in.
|
|
43681
43890
|
*/
|
|
@@ -44004,6 +44213,7 @@ void main() {
|
|
|
44004
44213
|
this.texture = null;
|
|
44005
44214
|
this.textureDirty = true;
|
|
44006
44215
|
this.shaderProgram = null;
|
|
44216
|
+
this.shaderProgramWater = false;
|
|
44007
44217
|
this.renderState = null;
|
|
44008
44218
|
this.destroyed = false;
|
|
44009
44219
|
this.lastEyePosition = null;
|
|
@@ -44020,6 +44230,13 @@ void main() {
|
|
|
44020
44230
|
this.maskGroundBox = null;
|
|
44021
44231
|
this.maskGroundRequested = false;
|
|
44022
44232
|
this.maskGroundLevel = 0;
|
|
44233
|
+
this.water = null;
|
|
44234
|
+
this.waterStartMs = now();
|
|
44235
|
+
this.waveOrigin = new Cesium.Cartesian2(0, 0);
|
|
44236
|
+
this.extentMetresCache = null;
|
|
44237
|
+
// Written in place each frame rather than reallocated, since they are read per tile.
|
|
44238
|
+
this.wavePhaseScratch = [new Cesium.Cartesian4(), new Cesium.Cartesian4()];
|
|
44239
|
+
this.waterSkyScratch = new Cesium.Cartesian3();
|
|
44023
44240
|
this.followGround = Boolean(options.followGround);
|
|
44024
44241
|
this.terrainProvider = options.terrainProvider || null;
|
|
44025
44242
|
this.extent = options.extent;
|
|
@@ -44035,6 +44252,23 @@ void main() {
|
|
|
44035
44252
|
this.maskFillValue = firstOpaqueStop(this.rampPixels);
|
|
44036
44253
|
this.tiles = buildTiles(hasCoverage);
|
|
44037
44254
|
this.SetGroundClearance(options.groundClearance || null);
|
|
44255
|
+
this.SetWater(options.water || null);
|
|
44256
|
+
}
|
|
44257
|
+
GetWater() {
|
|
44258
|
+
return this.water;
|
|
44259
|
+
}
|
|
44260
|
+
/**
|
|
44261
|
+
* Shades the sheet as water, or stops. Null goes back to the relief shading.
|
|
44262
|
+
*
|
|
44263
|
+
* Nothing is rebuilt: no mesh, no texture and no shader, since the water path is a branch in
|
|
44264
|
+
* the fragment shader the whole scene already carries. So this is cheap enough to drive from
|
|
44265
|
+
* a control the user is dragging.
|
|
44266
|
+
*/
|
|
44267
|
+
SetWater(water) {
|
|
44268
|
+
if (water && !this.water) {
|
|
44269
|
+
this.waterStartMs = now();
|
|
44270
|
+
}
|
|
44271
|
+
this.water = water;
|
|
44038
44272
|
}
|
|
44039
44273
|
GetFollowsGround() {
|
|
44040
44274
|
return this.followGround;
|
|
@@ -44205,6 +44439,12 @@ void main() {
|
|
|
44205
44439
|
const mesh = this.ensureMesh(context, tile, tile.tier);
|
|
44206
44440
|
frameState.commandList.push(this.commandFor(context, tile, mesh));
|
|
44207
44441
|
}
|
|
44442
|
+
if (this.water) {
|
|
44443
|
+
this.updateWaveOrigin(frameState);
|
|
44444
|
+
if (frameState.afterRender) {
|
|
44445
|
+
frameState.afterRender.push(() => true);
|
|
44446
|
+
}
|
|
44447
|
+
}
|
|
44208
44448
|
}
|
|
44209
44449
|
isDestroyed() {
|
|
44210
44450
|
return this.destroyed;
|
|
@@ -44416,6 +44656,73 @@ void main() {
|
|
|
44416
44656
|
})
|
|
44417
44657
|
});
|
|
44418
44658
|
}
|
|
44659
|
+
/*
|
|
44660
|
+
* Metres the extent spans west to east and north to south, which is what turns the shader's
|
|
44661
|
+
* 0..1 surface coordinate into the real distance the ripple wavelength is measured in.
|
|
44662
|
+
*/
|
|
44663
|
+
extentMetres() {
|
|
44664
|
+
// The extent never moves, and this is read once per tile per frame.
|
|
44665
|
+
if (this.extentMetresCache) {
|
|
44666
|
+
return this.extentMetresCache;
|
|
44667
|
+
}
|
|
44668
|
+
const southWest = Cesium.Cartesian3.fromDegrees(this.extent.West, this.extent.South, 0);
|
|
44669
|
+
const southEast = Cesium.Cartesian3.fromDegrees(this.extent.East, this.extent.South, 0);
|
|
44670
|
+
const northWest = Cesium.Cartesian3.fromDegrees(this.extent.West, this.extent.North, 0);
|
|
44671
|
+
this.extentMetresCache = new Cesium.Cartesian2(Math.max(1, Cesium.Cartesian3.distance(southWest, southEast)), Math.max(1, Cesium.Cartesian3.distance(southWest, northWest)));
|
|
44672
|
+
return this.extentMetresCache;
|
|
44673
|
+
}
|
|
44674
|
+
/*
|
|
44675
|
+
* Where each ripple layer has scrolled to, wrapped into one turn.
|
|
44676
|
+
*/
|
|
44677
|
+
wavePhase(from) {
|
|
44678
|
+
var _a;
|
|
44679
|
+
const into = this.wavePhaseScratch[from / 4];
|
|
44680
|
+
const water = this.water;
|
|
44681
|
+
if (!water) {
|
|
44682
|
+
return Cesium.Cartesian4.clone(Cesium.Cartesian4.ZERO, into);
|
|
44683
|
+
}
|
|
44684
|
+
const speed = (_a = water.speed) !== null && _a !== void 0 ? _a : DEFAULT_WATER_SPEED_METRES_PER_SECOND;
|
|
44685
|
+
const period = this.wavePeriod();
|
|
44686
|
+
const seconds = (now() - this.waterStartMs) / 1000;
|
|
44687
|
+
const base = waveCycles(WATER_WAVES[WATER_BASE_WAVE]);
|
|
44688
|
+
const phaseAt = (index) => {
|
|
44689
|
+
const wave = WATER_WAVES[from + index];
|
|
44690
|
+
if (!wave) {
|
|
44691
|
+
return 0;
|
|
44692
|
+
}
|
|
44693
|
+
const cycles = waveCycles(wave);
|
|
44694
|
+
const waveNumber = 2 * Math.PI * cycles / period;
|
|
44695
|
+
const travels = Math.sqrt(base / cycles);
|
|
44696
|
+
return (seconds * speed * travels * waveNumber) % (2 * Math.PI);
|
|
44697
|
+
};
|
|
44698
|
+
into.x = phaseAt(0);
|
|
44699
|
+
into.y = phaseAt(1);
|
|
44700
|
+
into.z = phaseAt(2);
|
|
44701
|
+
into.w = phaseAt(3);
|
|
44702
|
+
return into;
|
|
44703
|
+
}
|
|
44704
|
+
wavePeriod() {
|
|
44705
|
+
const wavelength = (this.water && this.water.wavelength) || DEFAULT_WATER_WAVELENGTH_METRES;
|
|
44706
|
+
return wavelength * WATER_PERIOD_IN_WAVELENGTHS;
|
|
44707
|
+
}
|
|
44708
|
+
/*
|
|
44709
|
+
* The point the ripple phase is measured from, kept near the camera and snapped to a whole
|
|
44710
|
+
* number of periods in each direction.
|
|
44711
|
+
*/
|
|
44712
|
+
updateWaveOrigin(frameState) {
|
|
44713
|
+
const period = this.wavePeriod();
|
|
44714
|
+
const carto = Cesium.Cartographic.fromCartesian(frameState.camera.positionWC);
|
|
44715
|
+
if (!carto) {
|
|
44716
|
+
return;
|
|
44717
|
+
}
|
|
44718
|
+
const metres = this.extentMetres();
|
|
44719
|
+
const longitude = Cesium.Math.toDegrees(carto.longitude);
|
|
44720
|
+
const latitude = Cesium.Math.toDegrees(carto.latitude);
|
|
44721
|
+
const u = (longitude - this.extent.West) / (this.extent.East - this.extent.West);
|
|
44722
|
+
// North is v zero, the way the vertex shader places the surface.
|
|
44723
|
+
const v = (this.extent.North - latitude) / (this.extent.North - this.extent.South);
|
|
44724
|
+
this.waveOrigin = new Cesium.Cartesian2(Math.floor(u * metres.x / period) * period, Math.floor(v * metres.y / period) * period);
|
|
44725
|
+
}
|
|
44419
44726
|
/*
|
|
44420
44727
|
* Ground distance between neighbouring texels, so the shading normal is built from a real
|
|
44421
44728
|
* slope rather than a made up one.
|
|
@@ -44579,14 +44886,22 @@ void main() {
|
|
|
44579
44886
|
return isFinite(nearest) ? Math.max(1, nearest) : 1;
|
|
44580
44887
|
}
|
|
44581
44888
|
commandFor(context, tile, mesh) {
|
|
44889
|
+
// Rebuilt when the effect is switched, since which program is wanted is part of it.
|
|
44890
|
+
const wantsWater = Boolean(this.water);
|
|
44891
|
+
if (this.shaderProgram && this.shaderProgramWater !== wantsWater) {
|
|
44892
|
+
this.shaderProgram = null;
|
|
44893
|
+
}
|
|
44582
44894
|
if (!this.shaderProgram) {
|
|
44583
44895
|
const glsl300 = usesGlsl300(context);
|
|
44896
|
+
const vertex = withWater(VERTEX_SHADER_GLSL300, wantsWater);
|
|
44897
|
+
const fragment = withWater(FRAGMENT_SHADER_GLSL300, wantsWater);
|
|
44584
44898
|
this.shaderProgram = Cesium.ShaderProgram.fromCache({
|
|
44585
44899
|
context,
|
|
44586
|
-
vertexShaderSource: glsl300 ?
|
|
44587
|
-
fragmentShaderSource: glsl300 ?
|
|
44900
|
+
vertexShaderSource: glsl300 ? vertex : toGlsl100(vertex, false),
|
|
44901
|
+
fragmentShaderSource: glsl300 ? fragment : toGlsl100(fragment, true),
|
|
44588
44902
|
attributeLocations: mesh.attributeLocations
|
|
44589
44903
|
});
|
|
44904
|
+
this.shaderProgramWater = wantsWater;
|
|
44590
44905
|
this.renderState = Cesium.RenderState.fromCache({
|
|
44591
44906
|
depthTest: { enabled: true },
|
|
44592
44907
|
// Translucent ramp: blend, and leave the depth buffer to the opaque world.
|
|
@@ -44642,11 +44957,38 @@ void main() {
|
|
|
44642
44957
|
: 0,
|
|
44643
44958
|
u_coverageCutoff: () => COVERAGE_CUTOFF,
|
|
44644
44959
|
u_rampTexture: () => self.rampTexture,
|
|
44645
|
-
u_texelSize: () => new Cesium.Cartesian2(1 / self.source.width, 1 / self.source.height)
|
|
44960
|
+
u_texelSize: () => new Cesium.Cartesian2(1 / self.source.width, 1 / self.source.height),
|
|
44961
|
+
u_waterOn: () => (self.water ? 1 : 0),
|
|
44962
|
+
u_waterWavelength: () => (self.water && self.water.wavelength)
|
|
44963
|
+
|| DEFAULT_WATER_WAVELENGTH_METRES,
|
|
44964
|
+
u_waterAmplitude: () => {
|
|
44965
|
+
var _a;
|
|
44966
|
+
return (_a = (self.water && self.water.amplitude)) !== null && _a !== void 0 ? _a : DEFAULT_WATER_AMPLITUDE_METRES;
|
|
44967
|
+
},
|
|
44968
|
+
u_waterReflectivity: () => {
|
|
44969
|
+
var _a;
|
|
44970
|
+
return (_a = (self.water && self.water.reflectivity)) !== null && _a !== void 0 ? _a : DEFAULT_WATER_REFLECTIVITY;
|
|
44971
|
+
},
|
|
44972
|
+
u_waterGloss: () => (self.water && self.water.glossiness)
|
|
44973
|
+
|| DEFAULT_WATER_GLOSSINESS,
|
|
44974
|
+
u_waterSun: () => {
|
|
44975
|
+
var _a;
|
|
44976
|
+
return (_a = (self.water && self.water.sunIntensity)) !== null && _a !== void 0 ? _a : DEFAULT_WATER_SUN_INTENSITY;
|
|
44977
|
+
},
|
|
44978
|
+
u_waterSky: () => {
|
|
44979
|
+
const sky = (self.water && self.water.skyColor) || DEFAULT_WATER_SKY_COLOR;
|
|
44980
|
+
return Cesium.Cartesian3.fromElements(sky.red / 255, sky.green / 255, sky.blue / 255, self.waterSkyScratch);
|
|
44981
|
+
},
|
|
44982
|
+
u_wavePhase: () => self.wavePhase(0),
|
|
44983
|
+
u_wavePhaseB: () => self.wavePhase(4),
|
|
44984
|
+
u_wavePeriod: () => self.wavePeriod(),
|
|
44985
|
+
u_waveOrigin: () => self.waveOrigin,
|
|
44986
|
+
u_extentMetres: () => self.extentMetres()
|
|
44646
44987
|
}
|
|
44647
44988
|
});
|
|
44648
44989
|
}
|
|
44649
44990
|
// Bounding volume belongs to the mesh, so it follows whichever tier is drawing.
|
|
44991
|
+
tile.command.shaderProgram = this.shaderProgram;
|
|
44650
44992
|
tile.command.vertexArray = mesh.vertexArray;
|
|
44651
44993
|
tile.command.boundingVolume = mesh.boundingSphere;
|
|
44652
44994
|
return tile.command;
|
|
@@ -45295,6 +45637,23 @@ void main() {
|
|
|
45295
45637
|
return touched;
|
|
45296
45638
|
}
|
|
45297
45639
|
EntityRenderEnginePolygon.SetGroundClearance = SetGroundClearance;
|
|
45640
|
+
/**
|
|
45641
|
+
* Shades every rendered polygon in a set as water rather than as a coloured surface.
|
|
45642
|
+
* @param cEntities
|
|
45643
|
+
* @param water Pass null to go back to the relief shading.
|
|
45644
|
+
*/
|
|
45645
|
+
function SetWater(cEntities, water) {
|
|
45646
|
+
let touched = 0;
|
|
45647
|
+
for (const cEntity of cEntities || []) {
|
|
45648
|
+
const surface = GetDisplacedSurface(cEntity);
|
|
45649
|
+
if (surface) {
|
|
45650
|
+
surface.SetWater(water);
|
|
45651
|
+
touched++;
|
|
45652
|
+
}
|
|
45653
|
+
}
|
|
45654
|
+
return touched;
|
|
45655
|
+
}
|
|
45656
|
+
EntityRenderEnginePolygon.SetWater = SetWater;
|
|
45298
45657
|
/**
|
|
45299
45658
|
* Disposes a cEntity's TextureFrameSeriesAnimator.Animator (if any).
|
|
45300
45659
|
*/
|
|
@@ -45452,6 +45811,7 @@ void main() {
|
|
|
45452
45811
|
if (reusable && existingSurface.GetFollowsGround() === placement.followGround) {
|
|
45453
45812
|
existingSurface.SetBaseHeight(placement.baseHeight);
|
|
45454
45813
|
existingSurface.SetExaggeration(exaggerationFor(style));
|
|
45814
|
+
existingSurface.SetWater(waterFor(style));
|
|
45455
45815
|
return;
|
|
45456
45816
|
}
|
|
45457
45817
|
disposeDisplacedSurface(cEntity, viewer);
|
|
@@ -45491,6 +45851,7 @@ void main() {
|
|
|
45491
45851
|
valueMax: extrusionArchive.metadata.ValueMax,
|
|
45492
45852
|
packedValue: exports.TextureFrameSeriesAnimator.IsPackedValue(extrusionArchive.metadata),
|
|
45493
45853
|
exaggeration: exaggerationFor(style),
|
|
45854
|
+
water: waterFor(style),
|
|
45494
45855
|
lowColor: mask ? BModels.Color.ColorFromStr(mask.minColor) : null,
|
|
45495
45856
|
highColor: mask ? BModels.Color.ColorFromStr(mask.maxColor) : null,
|
|
45496
45857
|
// Normalised the same way the animator normalises them, so the surface and the flat drape
|
|
@@ -45536,6 +45897,14 @@ void main() {
|
|
|
45536
45897
|
}
|
|
45537
45898
|
return 1;
|
|
45538
45899
|
}
|
|
45900
|
+
const WATER_EFFECT = "WATER";
|
|
45901
|
+
/*
|
|
45902
|
+
* The water settings a style asks a displaced surface for, or null for the plain relief shading.
|
|
45903
|
+
*/
|
|
45904
|
+
function waterFor(style) {
|
|
45905
|
+
var _a;
|
|
45906
|
+
return ((_a = style.effect) === null || _a === void 0 ? void 0 : _a.type) === WATER_EFFECT ? {} : null;
|
|
45907
|
+
}
|
|
45539
45908
|
/*
|
|
45540
45909
|
* The lon/lat bounding rectangle of a ring, which is the frame Cesium drapes an image material in.
|
|
45541
45910
|
*/
|
|
@@ -46568,6 +46937,28 @@ void main() {
|
|
|
46568
46937
|
};
|
|
46569
46938
|
}
|
|
46570
46939
|
EntityRenderEngine.Render = Render;
|
|
46940
|
+
/**
|
|
46941
|
+
* Removes what a render produced that nothing has a record of, for a render whose caller has gone away.
|
|
46942
|
+
* @param params
|
|
46943
|
+
*/
|
|
46944
|
+
function RemoveAll(params) {
|
|
46945
|
+
const { viewer, entities, register } = params;
|
|
46946
|
+
if (!entities || viewer.isDestroyed()) {
|
|
46947
|
+
return;
|
|
46948
|
+
}
|
|
46949
|
+
entities.forEach((entity) => {
|
|
46950
|
+
if (!entity || (register === null || register === void 0 ? void 0 : register.HasRego(entity))) {
|
|
46951
|
+
return;
|
|
46952
|
+
}
|
|
46953
|
+
try {
|
|
46954
|
+
Remove({ viewer, entity });
|
|
46955
|
+
}
|
|
46956
|
+
catch (e) {
|
|
46957
|
+
console.error("EntityRenderEngine.RemoveAll: failed to remove a visual:", e);
|
|
46958
|
+
}
|
|
46959
|
+
});
|
|
46960
|
+
}
|
|
46961
|
+
EntityRenderEngine.RemoveAll = RemoveAll;
|
|
46571
46962
|
function Remove(params) {
|
|
46572
46963
|
function doRemove(params) {
|
|
46573
46964
|
const { viewer, entity, ignoreParent } = params;
|
|
@@ -47393,7 +47784,7 @@ void main() {
|
|
|
47393
47784
|
StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
|
|
47394
47785
|
})(exports.StyleUtils || (exports.StyleUtils = {}));
|
|
47395
47786
|
|
|
47396
|
-
const VERSION = "7.3.
|
|
47787
|
+
const VERSION = "7.3.8";
|
|
47397
47788
|
/**
|
|
47398
47789
|
* Updates the environment instance used by bruce-cesium to one specified.
|
|
47399
47790
|
* This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
|