Cesium for Unreal 2.15.0
Loading...
Searching...
No Matches
CesiumSunSky.h
Go to the documentation of this file.
1// Copyright 2020-2024 CesiumGS, Inc. and Contributors
2
3#pragma once
4
5#include "CoreMinimal.h"
6
8#include "Components/DirectionalLightComponent.h"
9#include "Components/SkyAtmosphereComponent.h"
10#include "Components/SkyLightComponent.h"
11#include "Components/StaticMeshComponent.h"
12#include "Engine/DirectionalLight.h"
13#include "GameFramework/Actor.h"
14#include "CesiumSunSky.generated.h"
15
17
18/**
19 * A globe-aware sun sky actor. If the georeference is set to CartographicOrigin
20 * (aka Longitude/Latitude/Height) mode, then this actor will automatically
21 * sync its longitude and latitude properties with the georeference's, and
22 * recalculate the sun position whenever those properties change.
23 *
24 * Note: because we use `Planet Center at Component Transform`
25 * for the SkyAtmosphere transform mode, this actor's location will be forced
26 * to the Earth's center if the georeference is set to CartographicOrigin.
27 */
28UCLASS()
29class CESIUMRUNTIME_API ACesiumSunSky : public AActor {
30 GENERATED_BODY()
31
32public:
33 // Sets default values for this actor's properties
35
36 UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Components)
37 USceneComponent* Scene;
38
39 UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Components)
40 USkyLightComponent* SkyLight;
41
42 UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Components)
43 UDirectionalLightComponent* DirectionalLight;
44
45 UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Components)
46 USkyAtmosphereComponent* SkyAtmosphere;
47
48 /**
49 * The Globe Anchor Component that precisely ties this Actor to the Globe.
50 */
51 UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Components)
53
54 /**
55 * Gets the time zone, represented as hours offset from GMT.
56 *
57 * After changing this value from Blueprints or C++, you must call UpdateSun
58 * for it to take effect.
59 */
60 UPROPERTY(
61 EditAnywhere,
62 BlueprintReadWrite,
63 Category = "Cesium|Date and Time",
64 meta = (ClampMin = -12, ClampMax = 14))
65 double TimeZone = -5.0;
66
67 /**
68 * The current solar time represented as hours from midnight.
69 *
70 * After changing this value from Blueprints or C++, you must call UpdateSun
71 * for it to take effect.
72 */
73 UPROPERTY(
74 EditAnywhere,
75 BlueprintReadWrite,
76 Category = "Cesium|Date and Time",
77 meta = (UIMin = 4, UIMax = 22, ClampMin = 0, ClampMax = 23.9999))
78 double SolarTime = 13.0;
79
80 /**
81 * The day of the month.
82 *
83 * After changing this value from Blueprints or C++, you must call UpdateSun
84 * for it to take effect.
85 */
86 UPROPERTY(
87 EditAnywhere,
88 BlueprintReadWrite,
89 Category = "Cesium|Date and Time",
90 meta = (ClampMin = 1, ClampMax = 31))
91 int32 Day = 21;
92
93 /**
94 * The month of the year, where 1 is January and 12 is December.
95 *
96 * After changing this value from Blueprints or C++, you must call UpdateSun
97 * for it to take effect.
98 */
99 UPROPERTY(
100 EditAnywhere,
101 BlueprintReadWrite,
102 Category = "Cesium|Date and Time",
103 meta = (ClampMin = 1, ClampMax = 12))
104 int32 Month = 9;
105
106 /**
107 * The year.
108 *
109 * After changing this value from Blueprints or C++, you must call UpdateSun
110 * for it to take effect.
111 */
112 UPROPERTY(
113 EditAnywhere,
114 BlueprintReadWrite,
115 Category = "Cesium|Date and Time",
116 meta = (UIMin = 1800, UIMax = 2200, ClampMin = 0, ClampMax = 4000))
117 int32 Year = 2019;
118
119 /**
120 * Offset in the sun's position. Should be set to -90 for the sun's position
121 * to be accurate in the Unreal reference frame.
122 *
123 * After changing this value from Blueprints or C++, you must call UpdateSun
124 * for it to take effect.
125 */
126 UPROPERTY(
127 BlueprintReadWrite,
128 Category = "Cesium|Date and Time",
129 meta = (ClampMin = -360, ClampMax = 360))
130 double NorthOffset = -90.0;
131
132 /**
133 * Enables adjustment of the Solar Time for Daylight Saving Time (DST).
134 *
135 * After changing this value from Blueprints or C++, you must call UpdateSun
136 * for it to take effect.
137 */
138 UPROPERTY(
139 EditAnywhere,
140 BlueprintReadWrite,
141 Category = "Cesium|Date and Time|Daylight Savings")
143
144protected:
145 /**
146 * THIS PROPERTY IS DEPRECATED.
147 *
148 * Get the Georeference instance from the Globe Anchor Component instead.
149 */
150 UPROPERTY(
151 BlueprintReadOnly,
152 Category = "Cesium",
153 BlueprintGetter = GetGeoreference,
154 Meta =
155 (DeprecatedProperty,
156 DeprecationMessage =
157 "Get the Georeference instance from the Globe Anchor Component instead."))
159
160 /**
161 * Gets the Georeference Actor associated with this instance. It is obtained
162 * from the Globe Anchor Component.
163 */
164 UFUNCTION(BlueprintGetter, Category = "Cesium")
166
167 /**
168 * Set the Date at which DST starts in the current year.
169 *
170 * After changing this value from Blueprints or C++, you must call UpdateSun
171 * for it to take effect.
172 */
173 UPROPERTY(
174 EditAnywhere,
175 BlueprintReadWrite,
176 Category = "Cesium|Date and Time|Daylight Savings",
177 meta = (ClampMin = 1, ClampMax = 12),
178 meta = (EditCondition = "UseDaylightSavingTime"))
179 int32 DSTStartMonth = 3;
180
181 /**
182 * Set the Date at which DST starts in the current year.
183 *
184 * After changing this value from Blueprints or C++, you must call UpdateSun
185 * for it to take effect.
186 */
187 UPROPERTY(
188 EditAnywhere,
189 BlueprintReadWrite,
190 Category = "Cesium|Date and Time|Daylight Savings",
191 meta = (ClampMin = 1, ClampMax = 31),
192 meta = (EditCondition = "UseDaylightSavingTime"))
193 int32 DSTStartDay = 10;
194
195 /**
196 * Set the Date at which DST ends in the current year.
197 *
198 * After changing this value from Blueprints or C++, you must call UpdateSun
199 * for it to take effect.
200 */
201 UPROPERTY(
202 EditAnywhere,
203 BlueprintReadWrite,
204 Category = "Cesium|Date and Time|Daylight Savings",
205 meta = (ClampMin = 1, ClampMax = 12),
206 meta = (EditCondition = "UseDaylightSavingTime"))
207 int32 DSTEndMonth = 11;
208
209 /**
210 * Set the Date at which DST ends in the current year.
211 *
212 * After changing this value from Blueprints or C++, you must call UpdateSun
213 * for it to take effect.
214 */
215 UPROPERTY(
216 EditAnywhere,
217 BlueprintReadWrite,
218 Category = "Cesium|Date and Time|Daylight Savings",
219 meta = (ClampMin = 1, ClampMax = 31),
220 meta = (EditCondition = "UseDaylightSavingTime"))
221 int32 DSTEndDay = 3;
222
223 /**
224 * Hour of the DST Switch for both beginning and end.
225 *
226 * After changing this value from Blueprints or C++, you must call UpdateSun
227 * for it to take effect.
228 */
229 UPROPERTY(
230 EditAnywhere,
231 BlueprintReadWrite,
232 Category = "Cesium|Date and Time|Daylight Savings",
233 meta = (ClampMin = 0, ClampMax = 23),
234 meta = (EditCondition = "UseDaylightSavingTime"))
235 int32 DSTSwitchHour = 2;
236
237 /**
238 * Updates the atmosphere automatically given current player pawn's longitude,
239 * latitude, and height. Fixes artifacts seen with the atmosphere rendering
240 * when flying high above the surface, or low to the ground in high latitudes.
241 */
242 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Atmosphere")
244
245 /**
246 * When the player pawn is below this height, which is expressed in kilometers
247 * above the ellipsoid, this Actor will use an atmosphere ground radius that
248 * is calculated to be at or below the terrain surface at the player pawn's
249 * current location. This avoids a gap between the bottom of the atmosphere
250 * and the top of the terrain when zoomed in close to the terrain surface.
251 *
252 * Above CircumscribedGroundThreshold, this Actor will use an atmosphere
253 * ground radius that is guaranteed to be above the terrain surface anywhere
254 * on Earth. This avoids artifacts caused by terrain poking through the
255 * atmosphere when viewing the Earth from far away.
256 *
257 * At player pawn heights in between InscribedGroundThreshold and
258 * CircumscribedGroundThreshold, this Actor uses a linear interpolation
259 * between the two ground radii.
260 *
261 * This value is automatically scaled according to the CesiumGeoreference
262 * Scale and the Actor scale.
263 */
264 UPROPERTY(
265 EditAnywhere,
266 BlueprintReadWrite,
267 meta = (EditCondition = "UpdateAtmosphereAtRuntime"),
268 Category = "Cesium|Atmosphere")
269 double InscribedGroundThreshold = 30.0;
270
271 /**
272 * When the player pawn is above this height, which is expressed in kilometers
273 * above the ellipsoid, this Actor will use an atmosphere ground radius that
274 * is guaranteed to be above the terrain surface anywhere on Earth. This
275 * avoids artifacts caused by terrain poking through the atmosphere when
276 * viewing the Earth from far away.
277 *
278 * Below InscribedGroundThreshold, this Actor will use an atmosphere
279 * ground radius that is calculated to be at or below the terrain surface at
280 * the player pawn's current location. This avoids a gap between the bottom of
281 * the atmosphere and the top of the terrain when zoomed in close to the
282 * terrain surface.
283 *
284 * At heights in between InscribedGroundThreshold and
285 * CircumscribedGroundThreshold, this Actor uses a linear interpolation
286 * between the two ground radii.
287 *
288 * This value is automatically scaled according to the CesiumGeoreference
289 * Scale and the Actor scale.
290 */
291 UPROPERTY(
292 EditAnywhere,
293 BlueprintReadWrite,
294 meta = (EditCondition = "UpdateAtmosphereAtRuntime"),
295 Category = "Cesium|Atmosphere")
296 double CircumscribedGroundThreshold = 100.0;
297
298 /**
299 * The height at which to place the bottom of the atmosphere when the player
300 * pawn is above the CircumscribedGroundThreshold. This is expressed as a
301 * height in kilometers above the maximum radius of the ellipsoid (usually
302 * WGS84). To avoid dark splotchy artifacts in the atmosphere when zoomed out
303 * far from the globe, this value must be above the greatest height achieved
304 * by any part of the tileset.
305 */
306 UPROPERTY(
307 EditAnywhere,
308 BlueprintReadWrite,
309 meta = (EditCondition = "UpdateAtmosphereAtRuntime"),
310 Category = "Cesium|Atmosphere")
311 double CircumscribedGroundHeight = 0.0;
312
313 /**
314 * The height of the atmosphere layer above the ground, in kilometers. This
315 * value is automatically scaled according to the CesiumGeoreference Scale and
316 * the Actor scale. However, Unreal Engine's SkyAtmosphere has a hard-coded
317 * minimum effective value of 0.1, so the atmosphere will look too thick when
318 * the globe is scaled down drastically.
319 */
320 UPROPERTY(
321 EditAnywhere,
322 BlueprintReadOnly,
323 interp,
324 Category = "Cesium|Atmosphere",
325 meta = (UIMin = 1.0, UIMax = 200.0, ClampMin = 0.1, SliderExponent = 2.0))
326 float AtmosphereHeight = 60.0f;
327
328 /**
329 * Makes the aerial perspective look thicker by scaling distances from view
330 * to surfaces (opaque and translucent). This value is automatically scaled
331 * according to the CesiumGeoreference Scale and the Actor scale.
332 */
333 UPROPERTY(
334 EditAnywhere,
335 BlueprintReadOnly,
336 interp,
337 Category = "Cesium|Atmosphere",
338 meta =
339 (DisplayName = "Aerial Perspective View Distance Scale",
340 UIMin = 0.0,
341 UIMax = 3.0,
342 ClampMin = 0.0,
343 SliderExponent = 2.0))
345
346 /**
347 * The altitude in kilometers at which Rayleigh scattering effect is reduced
348 * to 40%. This value is automatically scaled according to the
349 * CesiumGeoreference Scale and the Actor scale.
350 */
351 UPROPERTY(
352 EditAnywhere,
353 BlueprintReadOnly,
354 interp,
355 Category = "Cesium|Atmosphere",
356 meta =
357 (UIMin = 0.01, UIMax = 20.0, ClampMin = 0.001, SliderExponent = 5.0))
359
360 /**
361 * The altitude in kilometers at which Mie effects are reduced to 40%. This
362 * value is automatically scaled according to the CesiumGeoreference Scale and
363 * the Actor scale.
364 */
365 UPROPERTY(
366 EditAnywhere,
367 BlueprintReadOnly,
368 interp,
369 Category = "Cesium|Atmosphere",
370 meta =
371 (UIMin = 0.01, UIMax = 10.0, ClampMin = 0.001, SliderExponent = 5.0))
373
374 /**
375 * False: Use Directional Light component inside CesiumSunSky.
376 * True: Use the assigned Directional Light in the level.
377 */
378 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Sun")
380
381 /**
382 * Reference to a manually assigned Directional Light in the level.
383 */
384 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Sun")
385 ADirectionalLight* LevelDirectionalLight;
386
387 /**
388 * The current sun elevation in degrees above the horizontal, as viewed from
389 * the Georeference origin.
390 */
391 UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Sun")
392 double Elevation = 0.f;
393
394 /**
395 * The current sun elevation, corrected for atmospheric diffraction, in
396 * degrees above the horizontal, as viewed from the Georeference origin.
397 */
398 UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Sun")
399 double CorrectedElevation = 0.f;
400
401 /**
402 * The current sun azimuth in degrees clockwise from North toward East, as
403 * viewed from the Georeference origin.
404 */
405 UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Sun")
406 double Azimuth = 0.f;
407
408 /**
409 * A switch to toggle between desktop and mobile rendering code paths.
410 * This will NOT be automatically set when running on mobile, so make sure
411 * to check this setting before building on mobile platforms.
412 */
413 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cesium|Mobile")
415
416 /**
417 * Mobile platforms currently do not support the SkyAtmosphereComponent.
418 * In lieu of that, use the engine BP_Sky_Sphere class, or a derived class.
419 */
420 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Mobile")
421 TSubclassOf<AActor> SkySphereClass;
422
423 /**
424 * Reference to BP_Sky_Sphere or similar actor (mobile only)
425 */
426 UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Cesium|Mobile")
428
429 /**
430 * Default intensity of directional light that's spawned for mobile rendering.
431 */
432 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cesium|Mobile")
434
435public:
436 UFUNCTION(
437 CallInEditor,
438 BlueprintCallable,
439 BlueprintNativeEvent,
440 Category = "Cesium")
441 void UpdateSun();
443
444 UFUNCTION(CallInEditor, BlueprintCallable, Category = "Cesium")
446
447 /**
448 * Adjusts the time zone of this CesiumSunSky to an estimate based on the
449 * given longitude.
450 *
451 * The time zone is naively calculated from the longitude, where every
452 * 15 degrees equals 1 hour. This may not necessarily match the official
453 * time zone at a given location within that longitude.
454 *
455 * This method will call @ref UpdateSun automatically.
456 *
457 * @param InLongitude The longitude that the calculated time zone will be
458 * based on in degrees in the range [-180, 180].
459 */
460 UFUNCTION(CallInEditor, BlueprintCallable, Category = "Cesium")
461 void EstimateTimeZoneForLongitude(double InLongitude);
462
463 /**
464 * Convert solar time to Hours:Minutes:Seconds. Copied the implementation
465 * from the engine SunSkyBP class.
466 */
467 UFUNCTION(BlueprintCallable, BlueprintPure, Category = Sun)
469 double InSolarTime,
470 int32& Hour,
471 int32& Minute,
472 int32& Second);
473
474 /**
475 * Check whether the current time and date (based on this class instance's
476 * properties) falls within Daylight Savings Time. Copied the implementation
477 * from the engine SunSkyBP class.
478 */
479 UFUNCTION(BlueprintCallable, BlueprintPure, Category = Sun)
480 bool IsDST(
481 bool DSTEnable,
482 int32 InDSTStartMonth,
483 int32 InDSTStartDay,
484 int32 InDSTEndMonth,
485 int32 InDSTEndDay,
486 int32 InDSTSwitchHour) const;
487
488 // Begin AActor Interface
489 /**
490 * Gets called when the actor is first created, and when properties are
491 * changed at edit-time. Refreshes the actor's position w/r/t the georeference
492 * and handles mobile-specific setup if needed.
493 */
494 virtual void OnConstruction(const FTransform& Transform) override;
495 // End AActor Interface
496
497protected:
498 /**
499 * Modifies the sky atmosphere's ground radius, which represents the Earth's
500 * radius in the SkyAtmosphere rendering model. Only changes if there's a >0.1
501 * difference, to reduce redraws.
502 *
503 * @param Sky A pointer to the SkyAtmosphereComponent
504 * @param Radius The radius in kilometers.
505 */
506 UFUNCTION(BlueprintCallable, Category = "Cesium")
507 void
508 SetSkyAtmosphereGroundRadius(USkyAtmosphereComponent* Sky, double Radius);
509
510 /**
511 * Update MobileSkySphere by calling its RefreshMaterial function
512 */
513 UFUNCTION(BlueprintCallable, Category = "Mobile")
515
516 virtual void BeginPlay() override;
517 virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
518 virtual void Serialize(FArchive& Ar) override;
519 virtual void Tick(float DeltaSeconds) override;
520 virtual void PostLoad() override;
521 virtual bool ShouldTickIfViewportsOnly() const override;
522
523#if WITH_EDITOR
524 virtual void
525 PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
526#endif
527
528private:
529 void _spawnSkySphere();
530 double _computeScale() const;
531
532 // Sets Directional Light Component in Sky Sphere actor
533 void _setSkySphereDirectionalLight();
534
535 void _setSkyAtmosphereVisibility(bool bVisible);
536
537 // Determines whether mobile sky sphere will be spawned during OnConstruction.
538 bool _wantsSpawnMobileSkySphere;
539
540 void _handleTransformUpdated(
541 USceneComponent* InRootComponent,
542 EUpdateTransformFlags UpdateTransformFlags,
543 ETeleportType Teleport);
544
545 FDelegateHandle _transformUpdatedSubscription;
546};
Controls how global geospatial coordinates are mapped to coordinates in the Unreal Engine level.
double Elevation
The current sun elevation in degrees above the horizontal, as viewed from the Georeference origin.
USkyAtmosphereComponent * SkyAtmosphere
virtual void OnConstruction(const FTransform &Transform) override
Gets called when the actor is first created, and when properties are changed at edit-time.
USceneComponent * Scene
bool IsDST(bool DSTEnable, int32 InDSTStartMonth, int32 InDSTStartDay, int32 InDSTEndMonth, int32 InDSTEndDay, int32 InDSTSwitchHour) const
Check whether the current time and date (based on this class instance's properties) falls within Dayl...
double NorthOffset
Offset in the sun's position.
int32 Year
The year.
double TimeZone
Gets the time zone, represented as hours offset from GMT.
int32 Month
The month of the year, where 1 is January and 12 is December.
AActor * SkySphereActor
Reference to BP_Sky_Sphere or similar actor (mobile only)
void UpdateSun_Implementation()
virtual void Tick(float DeltaSeconds) override
ACesiumGeoreference * GetGeoreference() const
Gets the Georeference Actor associated with this instance.
static void GetHMSFromSolarTime(double InSolarTime, int32 &Hour, int32 &Minute, int32 &Second)
Convert solar time to Hours:Minutes:Seconds.
bool UpdateAtmosphereAtRuntime
Updates the atmosphere automatically given current player pawn's longitude, latitude,...
void UpdateSun()
double MobileDirectionalLightIntensity
Default intensity of directional light that's spawned for mobile rendering.
bool UseMobileRendering
A switch to toggle between desktop and mobile rendering code paths.
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
TSubclassOf< AActor > SkySphereClass
Mobile platforms currently do not support the SkyAtmosphereComponent.
USkyLightComponent * SkyLight
double CorrectedElevation
The current sun elevation, corrected for atmospheric diffraction, in degrees above the horizontal,...
bool UseDaylightSavingTime
Enables adjustment of the Solar Time for Daylight Saving Time (DST).
void UpdateAtmosphereRadius()
virtual void Serialize(FArchive &Ar) override
bool UseLevelDirectionalLight
False: Use Directional Light component inside CesiumSunSky.
virtual bool ShouldTickIfViewportsOnly() const override
ADirectionalLight * LevelDirectionalLight
Reference to a manually assigned Directional Light in the level.
virtual void PostLoad() override
ACesiumGeoreference * Georeference_DEPRECATED
THIS PROPERTY IS DEPRECATED.
float MieExponentialDistribution
The altitude in kilometers at which Mie effects are reduced to 40%.
float AerialPerspectiveViewDistanceScale
Makes the aerial perspective look thicker by scaling distances from view to surfaces (opaque and tran...
float AtmosphereHeight
The height of the atmosphere layer above the ground, in kilometers.
float RayleighExponentialDistribution
The altitude in kilometers at which Rayleigh scattering effect is reduced to 40%.
void EstimateTimeZoneForLongitude(double InLongitude)
Adjusts the time zone of this CesiumSunSky to an estimate based on the given longitude.
UDirectionalLightComponent * DirectionalLight
double SolarTime
The current solar time represented as hours from midnight.
int32 Day
The day of the month.
double Azimuth
The current sun azimuth in degrees clockwise from North toward East, as viewed from the Georeference ...
UCesiumGlobeAnchorComponent * GlobeAnchor
The Globe Anchor Component that precisely ties this Actor to the Globe.
virtual void BeginPlay() override
void SetSkyAtmosphereGroundRadius(USkyAtmosphereComponent *Sky, double Radius)
Modifies the sky atmosphere's ground radius, which represents the Earth's radius in the SkyAtmosphere...
void UpdateSkySphere()
Update MobileSkySphere by calling its RefreshMaterial function.
This component can be added to a movable actor to anchor it to the globe and maintain precise placeme...