// Copyright 2020-2024 CesiumGS, Inc. and Contributors #pragma once #include "Cesium3DTilesSelection/Tileset.h" #include "Cesium3DTilesSelection/ViewState.h" #include "Cesium3DTilesSelection/ViewUpdateResult.h" #include "Cesium3DTilesetLoadFailureDetails.h" #include "CesiumCreditSystem.h" #include "CesiumEncodedMetadataComponent.h" #include "CesiumFeaturesMetadataComponent.h" #include "CesiumGeoreference.h" #include "CesiumIonServer.h" #include "CesiumPointCloudShading.h" #include "CesiumSampleHeightResult.h" #include "CoreMinimal.h" #include "CustomDepthParameters.h" #include "Engine/EngineTypes.h" #include "GameFramework/Actor.h" #include "Interfaces/IHttpRequest.h" #include "PrimitiveSceneProxy.h" #include #include #include #include #include #include #include "Cesium3DTileset.generated.h" #ifdef CESIUM_DEBUG_TILE_STATES #include #endif class UMaterialInterface; class ACesiumCartographicSelection; class ACesiumCameraManager; class UCesiumBoundingVolumePoolComponent; class CesiumViewExtension; struct FCesiumCamera; namespace Cesium3DTilesSelection { class Tileset; class TilesetView; class TileOcclusionRendererProxyPool; } // namespace Cesium3DTilesSelection /** * The delegate for OnCesium3DTilesetLoadFailure, which is triggered when * the tileset encounters a load error. */ DECLARE_MULTICAST_DELEGATE_OneParam( FCesium3DTilesetLoadFailure, const FCesium3DTilesetLoadFailureDetails&); DECLARE_DELEGATE_ThreeParams( FCesiumSampleHeightMostDetailedCallback, ACesium3DTileset*, const TArray&, const TArray&); /** * The delegate for the Acesium3DTileset::OnTilesetLoaded, * which is triggered from UpdateLoadStatus */ DECLARE_DYNAMIC_MULTICAST_DELEGATE(FCompletedLoadTrigger); CESIUMRUNTIME_API extern FCesium3DTilesetLoadFailure OnCesium3DTilesetLoadFailure; UENUM(BlueprintType) enum class ETilesetSource : uint8 { /** * The tileset will be loaded from Cesium Ion using the provided IonAssetID * and IonAccessToken. */ FromCesiumIon UMETA(DisplayName = "From Cesium Ion"), /** * The tileset will be loaded from the specified Url. */ FromUrl UMETA(DisplayName = "From Url"), /** * The tileset will be loaded from the georeference ellipsoid. */ FromEllipsoid UMETA(DisplayName = "From Ellipsoid") }; UENUM(BlueprintType) enum class EApplyDpiScaling : uint8 { Yes, No, UseProjectDefault }; UCLASS() class CESIUMRUNTIME_API ACesium3DTileset : public AActor { GENERATED_BODY() public: ACesium3DTileset(); virtual ~ACesium3DTileset(); private: UPROPERTY(VisibleAnywhere, Category = "Cesium") USceneComponent* Root; UPROPERTY( Meta = (AllowPrivateAccess, DeprecatedProperty, DeprecationMessage = "Use the Mobility property on the RootComponent instead.")) TEnumAsByte Mobility_DEPRECATED = EComponentMobility::Static; public: UFUNCTION(BlueprintCallable, meta = (DeprecatedFunction)) EComponentMobility::Type GetMobility() const { return this->RootComponent->Mobility; } UFUNCTION(BlueprintCallable, meta = (DeprecatedFunction)) void SetMobility(EComponentMobility::Type NewMobility); /** * @brief Initiates an asynchronous query for the height of this tileset at a * list of cartographic positions, where the Longitude (X) and Latitude (Y) * are given in degrees. The most detailed available tiles are used to * determine each height. * * The height of the input positions is ignored, unless height sampling fails * at that location. The output height is expressed in meters above the * ellipsoid (usually WGS84), which should not be confused with a height above * mean sea level. * * @param LongitudeLatitudeHeightArray The cartographic positions for which to * sample heights. The Longitude (X) and Latitude (Y) are expressed in * degrees, while Height (Z) is given in meters. * @param OnHeightsSampled A callback that is invoked in the game thread when * heights have been sampled for all positions. */ void SampleHeightMostDetailed( const TArray& LongitudeLatitudeHeightArray, FCesiumSampleHeightMostDetailedCallback OnHeightsSampled); private: /** * The designated georeference actor controlling how the actor's * coordinate system relates to the coordinate system in this Unreal Engine * level. * * If this is null, the Tileset will find and use the first Georeference * Actor in the level, or create one if necessary. To get the active/effective * Georeference from Blueprints or C++, use ResolvedGeoreference instead. */ UPROPERTY( EditAnywhere, BlueprintReadWrite, BlueprintGetter = GetGeoreference, BlueprintSetter = SetGeoreference, Category = "Cesium", Meta = (AllowPrivateAccess)) TSoftObjectPtr Georeference; /** * The resolved georeference used by this Tileset. This is not serialized * because it may point to a Georeference in the PersistentLevel while this * tileset is in a sublevel. If the Georeference property is specified, * however then this property will have the same value. * * This property will be null before ResolveGeoreference is called. */ UPROPERTY( Transient, VisibleAnywhere, BlueprintReadOnly, Category = "Cesium", Meta = (AllowPrivateAccess)) ACesiumGeoreference* ResolvedGeoreference = nullptr; public: /** @copydoc ACesium3DTileset::Georeference */ UFUNCTION(BlueprintCallable, Category = "Cesium") TSoftObjectPtr GetGeoreference() const; /** @copydoc ACesium3DTileset::Georeference */ UFUNCTION(BlueprintCallable, Category = "Cesium") void SetGeoreference(TSoftObjectPtr NewGeoreference); /** * Resolves the Cesium Georeference to use with this Actor. Returns * the value of the Georeference property if it is set. Otherwise, finds a * Georeference in the World and returns it, creating it if necessary. The * resolved Georeference is cached so subsequent calls to this function will * return the same instance. */ UFUNCTION(BlueprintCallable, Category = "Cesium") ACesiumGeoreference* ResolveGeoreference(); /** * Invalidates the cached resolved georeference, unsubscribing from it and * setting it to null. The next time ResolveGeoreference is called, the * Georeference will be re-resolved and re-subscribed. */ UFUNCTION(BlueprintCallable, Category = "Cesium") void InvalidateResolvedGeoreference(); private: /** * The actor managing this tileset's content attributions. * * If this is null, the Tileset will find and use the first Credit System * Actor in the level, or create one if necessary. To get the active/effective * Credit System from Blueprints or C++, use ResolvedCreditSystem instead. */ UPROPERTY( EditAnywhere, BlueprintReadWrite, BlueprintGetter = GetCreditSystem, BlueprintSetter = SetCreditSystem, Category = "Cesium", Meta = (AllowPrivateAccess)) TSoftObjectPtr CreditSystem; /** * The resolved Credit System used by this Tileset. This is not serialized * because it may point to a Credit System in the PersistentLevel while this * tileset is in a sublevel. If the CreditSystem property is specified, * however then this property will have the same value. * * This property will be null before ResolveCreditSystem is called. */ UPROPERTY( Transient, BlueprintReadOnly, Category = "Cesium", Meta = (AllowPrivateAccess)) ACesiumCreditSystem* ResolvedCreditSystem = nullptr; /** * The actor providing custom cameras for use with this Tileset. * * If this is null, the Tileset will find and use the first * CesiumCameraManager Actor in the level, or create one if necessary. To get * the active/effective Camera Manager from Blueprints or C++, use * ResolvedCameraManager instead. */ UPROPERTY( EditAnywhere, BlueprintReadWrite, BlueprintGetter = GetCameraManager, BlueprintSetter = SetCameraManager, Category = "Cesium", Meta = (AllowPrivateAccess)) TSoftObjectPtr CameraManager; /** * The resolved Camera Manager used by this Tileset. This is not serialized * because it may point to a Camera Manager in the PersistentLevel while this * tileset is in a sublevel. If the CameraManager property is specified, * however then this property will have the same value. * * This property will be null before ResolveCameraManager is called. */ UPROPERTY( Transient, BlueprintReadOnly, Category = "Cesium", Meta = (AllowPrivateAccess)) ACesiumCameraManager* ResolvedCameraManager = nullptr; /** * The bounding volume pool component that manages occlusion bounding volume * proxies. */ UPROPERTY( Transient, BlueprintReadOnly, Category = "Cesium", Meta = (AllowPrivateAccess)) UCesiumBoundingVolumePoolComponent* BoundingVolumePoolComponent = nullptr; /** * The custom view extension this tileset uses to pull renderer view * information. */ TSharedPtr _cesiumViewExtension = nullptr; public: /** @copydoc ACesium3DTileset::CreditSystem */ UFUNCTION(BlueprintCallable, Category = "Cesium") TSoftObjectPtr GetCreditSystem() const; /** @copydoc ACesium3DTileset::CreditSystem */ UFUNCTION(BlueprintCallable, Category = "Cesium") void SetCreditSystem(TSoftObjectPtr NewCreditSystem); /** * Resolves the Cesium Credit System to use with this Actor. Returns * the value of the CreditSystem property if it is set. Otherwise, finds a * Credit System in the World and returns it, creating it if necessary. The * resolved Credit System is cached so subsequent calls to this function will * return the same instance. */ UFUNCTION(BlueprintCallable, Category = "Cesium") ACesiumCreditSystem* ResolveCreditSystem(); /** * Invalidates the cached resolved Credit System, setting it to null. The next * time ResolveCreditSystem is called, the Credit System will be re-resolved. */ UFUNCTION(BlueprintCallable, Category = "Cesium") void InvalidateResolvedCreditSystem(); /** * Whether or not to show this tileset's credits on screen. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") bool ShowCreditsOnScreen = false; /** @copydoc ACesium3DTileset::CameraManager */ UFUNCTION(BlueprintGetter, Category = "Cesium") TSoftObjectPtr GetCameraManager() const; /** @copydoc ACesium3DTileset::CameraManager */ UFUNCTION(BlueprintSetter, Category = "Cesium") void SetCameraManager(TSoftObjectPtr NewCameraManager); /** * Resolves the Cesium Camera Manager to use with this Actor. Returns * the value of the CameraManager property if it is set. Otherwise, finds a * Camera Manager in the World and returns it, creating it if necessary. The * resolved Camera Manager is cached so subsequent calls to this function will * return the same instance. */ UFUNCTION(BlueprintCallable, Category = "Cesium") ACesiumCameraManager* ResolveCameraManager(); /** * Invalidates the cached resolved Camera Manager, setting it to null. The * next time ResolveCameraManager is called, the Camera Manager will be * re-resolved. */ UFUNCTION(BlueprintCallable, Category = "Cesium") void InvalidateResolvedCameraManager(); /** * The maximum number of pixels of error when rendering this tileset. * * This is used to select an appropriate level-of-detail: A low value * will cause many tiles with a high level of detail to be loaded, * causing a finer visual representation of the tiles, but with a * higher performance cost for loading and rendering. A higher value will * cause a coarser visual representation, with lower performance * requirements. * * When a tileset uses the older layer.json / quantized-mesh format rather * than 3D Tiles, this value is effectively divided by 8.0. So the default * value of 16.0 corresponds to the standard value for quantized-mesh terrain * of 2.0. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetMaximumScreenSpaceError, BlueprintSetter = SetMaximumScreenSpaceError, Category = "Cesium|Level of Detail", meta = (ClampMin = 0.0)) double MaximumScreenSpaceError = 16.0; /** * Scale Level-of-Detail by Display DPI. This increases the performance for * mobile devices and high DPI screens. */ UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "Cesium|Level of Detail") EApplyDpiScaling ApplyDpiScaling = EApplyDpiScaling::UseProjectDefault; /** * Whether to preload ancestor tiles. * * Setting this to true optimizes the zoom-out experience and provides more * detail in newly-exposed areas when panning. The down side is that it * requires loading more tiles. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Tile Loading") bool PreloadAncestors = true; /** * Whether to preload sibling tiles. * * Setting this to true causes tiles with the same parent as a rendered tile * to be loaded, even if they are culled. Setting this to true may provide a * better panning experience at the cost of loading more tiles. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Tile Loading") bool PreloadSiblings = true; /** * Whether to unrefine back to a parent tile when a child isn't done loading. * * When this is set to true, the tileset will guarantee that the tileset will * never be rendered with holes in place of tiles that are not yet loaded, * even though the tile that is rendered instead may have low resolution. When * false, overall loading will be faster, but newly-visible parts of the * tileset may initially be blank. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Tile Loading") bool ForbidHoles = false; /** * The maximum number of tiles that may be loaded at once. * * When new parts of the tileset become visible, the tasks to load the * corresponding tiles are put into a queue. This value determines how * many of these tasks are processed at the same time. A higher value * may cause the tiles to be loaded and rendered more quickly, at the * cost of a higher network- and processing load. */ UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "Cesium|Tile Loading", meta = (ClampMin = 0)) int32 MaximumSimultaneousTileLoads = 20; /** * @brief The maximum number of bytes that may be cached. * * Note that this value, even if 0, will never * cause tiles that are needed for rendering to be unloaded. However, if the * total number of loaded bytes is greater than this value, tiles will be * unloaded until the total is under this number or until only required tiles * remain, whichever comes first. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Tile Loading") int64 MaximumCachedBytes = 256 * 1024 * 1024; /** * The number of loading descendents a tile should allow before deciding to * render itself instead of waiting. * * Setting this to 0 will cause each level of detail to be loaded * successively. This will increase the overall loading time, but cause * additional detail to appear more gradually. Setting this to a high value * like 1000 will decrease the overall time until the desired level of detail * is achieved, but this high-detail representation will appear at once, as * soon as it is loaded completely. */ UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "Cesium|Tile Loading", meta = (ClampMin = 0)) int32 LoadingDescendantLimit = 20; /** * Whether to cull tiles that are outside the frustum. * * By default this is true, meaning that tiles that are not visible with the * current camera configuration will be ignored. It can be set to false, so * that these tiles are still considered for loading, refinement and * rendering. * * This will cause more tiles to be loaded, but helps to avoid holes and * provides a more consistent mesh, which may be helpful for physics. * * Note that this will always be disabled if UseLodTransitions is set to true. */ UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "Cesium|Tile Culling", Meta = (EditCondition = "!UseLodTransitions", EditConditionHides)) bool EnableFrustumCulling = true; /** * Whether to cull tiles that are occluded by fog. * * This does not refer to the atmospheric fog of the Unreal Engine, * but to an internal representation of fog: Depending on the height * of the camera above the ground, tiles that are far away (close to * the horizon) will be culled when this flag is enabled. * * Note that this will always be disabled if UseLodTransitions is set to true. */ UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "Cesium|Tile Culling", Meta = (EditCondition = "!UseLodTransitions", EditConditionHides)) bool EnableFogCulling = true; /** * Whether a specified screen-space error should be enforced for tiles that * are outside the frustum or hidden in fog. * * When "Enable Frustum Culling" and "Enable Fog Culling" are both true, tiles * outside the view frustum or hidden in fog are effectively ignored, and so * their level-of-detail doesn't matter. And in this scenario, this property * is ignored. * * However, when either of those flags are false, these "would-be-culled" * tiles continue to be processed, and the question arises of how to handle * their level-of-detail. When this property is false, refinement terminates * at these tiles, no matter what their current screen-space error. The tiles * are available for physics, shadows, etc., but their level-of-detail may * be very low. * * When set to true, these tiles are refined until they achieve the specified * "Culled Screen Space Error". This allows control over the minimum quality * of these would-be-culled tiles. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Tile Culling") bool EnforceCulledScreenSpaceError = false; /** * The screen-space error to be enforced for tiles that are outside the view * frustum or hidden in fog. * * When "Enable Frustum Culling" and "Enable Fog Culling" are both true, tiles * outside the view frustum or hidden in fog are effectively ignored, and so * their level-of-detail doesn't matter. And in this scenario, this property * is ignored. * * However, when either of those flags are false, these "would-be-culled" * tiles continue to be processed, and the question arises of how to handle * their level-of-detail. When "Enforce Culled Screen Space Error" is false, * this property is ignored and refinement terminates at these tiles, no * matter what their current screen-space error. The tiles are available for * physics, shadows, etc., but their level-of-detail may be very low. * * When set to true, these tiles are refined until they achieve the * screen-space error specified by this property. */ UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "Cesium|Tile Culling", meta = (EditCondition = "EnforceCulledScreenSpaceError", ClampMin = 0.0)) double CulledScreenSpaceError = 64.0; // This mirrors // UCesiumRuntimeSettings::EnableExperimentalOcclusionCullingFeature so that // it can be used as an EditCondition. UPROPERTY(Transient, VisibleDefaultsOnly, Category = "Cesium|Tile Occlusion") bool CanEnableOcclusionCulling = false; /** * Whether to cull tiles that are occluded. * * If this option is disabled, check that "Enable Experimental Occlusion * Culling Feature" is enabled in the Plugins -> Cesium section of the Project * Settings. * * When enabled, this feature will use Unreal's occlusion system to determine * if tiles are actually visible on the screen. For tiles found to be * occluded, the tile will not refine to show descendants, but it will still * be rendered to avoid holes. This results in less tile loads and less GPU * resource usage for dense, high-occlusion scenes like ground-level views in * cities. * * This will not work for tilesets with poorly fit bounding volumes and cause * more draw calls with very few extra culled tiles. When there is minimal * occlusion in a scene, such as with terrain tilesets and applications * focused on top-down views, this feature will yield minimal benefit and * potentially cause needless overhead. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetEnableOcclusionCulling, BlueprintSetter = SetEnableOcclusionCulling, Category = "Cesium|Tile Occlusion", meta = (EditCondition = "CanEnableOcclusionCulling")) bool EnableOcclusionCulling = true; /** * The number of CesiumBoundingVolumeComponents to use for querying the * occlusion state of traversed tiles. * * Only applicable when EnableOcclusionCulling is enabled. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetOcclusionPoolSize, BlueprintSetter = SetOcclusionPoolSize, Category = "Cesium|Tile Occlusion", meta = (EditCondition = "EnableOcclusionCulling && CanEnableOcclusionCulling", ClampMin = "0", ClampMax = "1000")) int32 OcclusionPoolSize = 500; /** * Whether to wait for valid occlusion results before refining tiles. * * Only applicable when EnableOcclusionCulling is enabled. When this option * is enabled, there may be small delays before tiles are refined, but there * may be an overall performance advantage by avoiding loads of descendants * that will be found to be occluded. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetDelayRefinementForOcclusion, BlueprintSetter = SetDelayRefinementForOcclusion, Category = "Cesium|Tile Occlusion", meta = (EditCondition = "EnableOcclusionCulling && CanEnableOcclusionCulling")) bool DelayRefinementForOcclusion = true; /** * Refreshes this tileset, ensuring that all materials and other settings are * applied. It is not usually necessary to invoke this, but when * behind-the-scenes changes are made and not reflected in the tileset, this * function can help. */ UFUNCTION(CallInEditor, BlueprintCallable, Category = "Cesium") void RefreshTileset(); /** * Pauses level-of-detail and culling updates of this tileset. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium|Debug") bool SuspendUpdate; /** * If true, this tileset is ticked/updated in the editor. If false, is only * ticked while playing (including Play-in-Editor). */ UPROPERTY(EditAnywhere, Category = "Cesium|Debug") bool UpdateInEditor = true; /** * If true, stats about tile selection are printed to the Output Log. */ UPROPERTY(EditAnywhere, Category = "Cesium|Debug") bool LogSelectionStats = false; /** * If true, logs stats on the assets in this tileset's shared asset system to * the Output Log. */ UPROPERTY(EditAnywhere, Category = "Cesium|Debug") bool LogSharedAssetStats = false; /** * If true, draws debug text above each tile being rendered with information * about that tile. */ UPROPERTY(EditAnywhere, Category = "Cesium|Debug") bool DrawTileInfo = false; /** * Define the collision profile for all the 3D tiles created inside this * actor. */ UPROPERTY( EditAnywhere, BlueprintReadOnly, Category = "Collision", meta = (ShowOnlyInnerProperties, SkipUCSModifiedProperties)) FBodyInstance BodyInstance; /** * A delegate that will be called whenever the tileset is fully loaded. */ UPROPERTY(BlueprintAssignable, Category = "Cesium"); FCompletedLoadTrigger OnTilesetLoaded; /** * Use a dithering effect when transitioning between tiles of different LODs. * * When this is set to true, Frustrum Culling and Fog Culling are always * disabled. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetUseLodTransitions, BlueprintSetter = SetUseLodTransitions, Category = "Cesium|Rendering") bool UseLodTransitions = false; /** * How long dithered LOD transitions between different tiles should take, in * seconds. * * Only relevant if UseLodTransitions is true. */ UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "Cesium|Rendering", meta = (EditCondition = "UseLodTransitions", EditConditionHides)) float LodTransitionLength = 0.5f; private: UPROPERTY(BlueprintGetter = GetLoadProgress, Category = "Cesium") float LoadProgress = 0.0f; /** * The type of source from which to load this tileset. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetTilesetSource, BlueprintSetter = SetTilesetSource, Category = "Cesium", meta = (DisplayName = "Source")) ETilesetSource TilesetSource = ETilesetSource::FromCesiumIon; /** * The URL of this tileset's "tileset.json" file. * * If this property is specified, the ion asset ID and token are ignored. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetUrl, BlueprintSetter = SetUrl, Category = "Cesium", meta = (EditCondition = "TilesetSource==ETilesetSource::FromUrl")) FString Url = ""; /** * The ID of the Cesium ion asset to use. * * This property is ignored if the Url is specified. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetIonAssetID, BlueprintSetter = SetIonAssetID, Category = "Cesium", meta = (EditCondition = "TilesetSource==ETilesetSource::FromCesiumIon", ClampMin = 0)) int64 IonAssetID; /** * The access token to use to access the Cesium ion resource. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetIonAccessToken, BlueprintSetter = SetIonAccessToken, Category = "Cesium", meta = (EditCondition = "TilesetSource==ETilesetSource::FromCesiumIon")) FString IonAccessToken; UPROPERTY( meta = (DeprecatedProperty, DeprecationMessage = "Use CesiumIonServer instead.")) FString IonAssetEndpointUrl_DEPRECATED; /** * The Cesium ion Server from which this tileset is loaded. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetCesiumIonServer, BlueprintSetter = SetCesiumIonServer, Category = "Cesium", AdvancedDisplay, meta = (EditCondition = "TilesetSource==ETilesetSource::FromCesiumIon")) UCesiumIonServer* CesiumIonServer; /** * Headers to be attached to each request made for this tileset. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetRequestHeaders, BlueprintSetter = SetRequestHeaders, Category = "Cesium") TMap RequestHeaders; /** * Check if the Cesium ion token used to access this tileset is working * correctly, and fix it if necessary. */ UFUNCTION(CallInEditor, Category = "Cesium") void TroubleshootToken(); /** * Whether to generate physics meshes for this tileset. * * Disabling this option will improve the performance of tile loading, but it * will no longer be possible to collide with the tileset since the physics * meshes will not be created. * * Physics meshes cannot be generated for primitives containing points. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetCreatePhysicsMeshes, BlueprintSetter = SetCreatePhysicsMeshes, Category = "Cesium|Physics") bool CreatePhysicsMeshes = true; /** * Whether to generate navigation collisions for this tileset. * * Enabling this option creates collisions for navigation when a 3D Tiles * tileset is loaded. It is recommended to set "Runtime Generation" to * "Static" in the navigation mesh settings in the project settings, as * collision calculations become very slow. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetCreateNavCollision, BlueprintSetter = SetCreateNavCollision, Category = "Cesium|Navigation") bool CreateNavCollision = false; /** * Whether to always generate a correct tangent space basis for tiles that * don't have them. * * Normally, a per-vertex tangent space basis is only required for glTF models * with a normal map. However, a custom, user-supplied material may need a * tangent space basis for other purposes. When this property is set to true, * tiles lacking an explicit tangent vector will have one computed * automatically using the MikkTSpace algorithm. When this property is false, * load time will be improved by skipping the generation of the tangent * vector, but the tangent space basis will be unreliable. * * Note that a tileset with "Enable Water Mask" set will include tangents * for tiles containing water, regardless of the value of this property. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetAlwaysIncludeTangents, BlueprintSetter = SetAlwaysIncludeTangents, Category = "Cesium|Rendering") bool AlwaysIncludeTangents = false; /** * Whether to generate smooth normals when normals are missing in the glTF. * * According to the Gltf spec: "When normals are not specified, client * implementations should calculate flat normals." However, calculating flat * normals requires duplicating vertices. This option allows the gltfs to be * sent with explicit smooth normals when the original gltf was missing * normals. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetGenerateSmoothNormals, BlueprintSetter = SetGenerateSmoothNormals, Category = "Cesium|Rendering") bool GenerateSmoothNormals = false; /** * Whether to request and render the water mask. * * Currently only applicable for quantized-mesh tilesets that support the * water mask extension. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetEnableWaterMask, BlueprintSetter = SetEnableWaterMask, Category = "Cesium|Rendering") bool EnableWaterMask = false; /** * Whether to ignore the KHR_materials_unlit extension on the glTF tiles in * this tileset, if it exists, and instead render with standard lighting and * shadows. This property will have no effect if the tileset does not have any * tiles that use this extension. * * The KHR_materials_unlit extension is often applied to photogrammetry * tilesets because lighting and shadows are already baked into their * textures. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetIgnoreKhrMaterialsUnlit, BlueprintSetter = SetIgnoreKhrMaterialsUnlit, Category = "Cesium|Rendering", meta = (DisplayName = "Ignore KHR_materials_unlit")) bool IgnoreKhrMaterialsUnlit = false; /** * A custom Material to use to render opaque elements in this tileset, in * order to implement custom visual effects. * * The custom material should generally be created by copying the Material * Instance "MI_CesiumThreeOverlaysAndClipping" and customizing the copy as * desired. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetMaterial, BlueprintSetter = SetMaterial, Category = "Cesium|Rendering") UMaterialInterface* Material = nullptr; /** * A custom Material to use to render translucent elements of the tileset, in * order to implement custom visual effects. * * The custom material should generally be created by copying the Material * Instance "MI_CesiumThreeOverlaysAndClippingTranslucent" and customizing the * copy as desired. Make sure that its Material Property Overrides -> Blend * Mode is set to "Translucent". */ UPROPERTY( EditAnywhere, BlueprintGetter = GetTranslucentMaterial, BlueprintSetter = SetTranslucentMaterial, Category = "Cesium|Rendering") UMaterialInterface* TranslucentMaterial = nullptr; /** * A custom Material to use to render this tileset in areas where the * watermask is, in order to implement custom visual effects. * Currently only applicable for quantized-mesh tilesets that support the * water mask extension. * * The custom material should generally be created by copying the Material * Instance "MI_CesiumThreeOverlaysAndClippingAndWater" and customizing the * copy as desired. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetWaterMaterial, BlueprintSetter = SetWaterMaterial, Category = "Cesium|Rendering") UMaterialInterface* WaterMaterial = nullptr; UPROPERTY( EditAnywhere, BlueprintGetter = GetCustomDepthParameters, BlueprintSetter = SetCustomDepthParameters, Category = "Rendering", meta = (ShowOnlyInnerProperties)) FCustomDepthParameters CustomDepthParameters; /** * If this tileset contains points, their appearance can be configured with * these point cloud shading parameters. * * These settings are not supported on mobile platforms. */ UPROPERTY( EditAnywhere, BlueprintGetter = GetPointCloudShading, BlueprintSetter = SetPointCloudShading, Category = "Cesium|Rendering") FCesiumPointCloudShading PointCloudShading; protected: UPROPERTY() FString PlatformName; public: UFUNCTION(BlueprintGetter, Category = "Cesium") float GetLoadProgress() const { return LoadProgress; } UFUNCTION(BlueprintGetter, Category = "Cesium") bool GetUseLodTransitions() const { return UseLodTransitions; } UFUNCTION(BlueprintSetter, Category = "Cesium") void SetUseLodTransitions(bool InUseLodTransitions); UFUNCTION(BlueprintGetter, Category = "Cesium") ETilesetSource GetTilesetSource() const { return TilesetSource; } UFUNCTION(BlueprintSetter, Category = "Cesium") void SetTilesetSource(ETilesetSource InSource); UFUNCTION(BlueprintGetter, Category = "Cesium") FString GetUrl() const { return Url; } UFUNCTION(BlueprintSetter, Category = "Cesium") void SetUrl(const FString& InUrl); UFUNCTION(BlueprintGetter, Category = "Cesium") TMap GetRequestHeaders() const { return RequestHeaders; } UFUNCTION(BlueprintSetter, Category = "Cesium") void SetRequestHeaders(const TMap& InRequestHeaders); UFUNCTION(BlueprintGetter, Category = "Cesium") int64 GetIonAssetID() const { return IonAssetID; } UFUNCTION(BlueprintSetter, Category = "Cesium") void SetIonAssetID(int64 InAssetID); UFUNCTION(BlueprintGetter, Category = "Cesium") FString GetIonAccessToken() const { return IonAccessToken; } UFUNCTION(BlueprintSetter, Category = "Cesium") void SetIonAccessToken(const FString& InAccessToken); UFUNCTION(BlueprintGetter, Category = "Cesium") UCesiumIonServer* GetCesiumIonServer() const { return CesiumIonServer; } UFUNCTION(BlueprintSetter, Category = "Cesium") void SetCesiumIonServer(UCesiumIonServer* Server); UFUNCTION(BlueprintGetter, Category = "Cesium") double GetMaximumScreenSpaceError() { return MaximumScreenSpaceError; } UFUNCTION(BlueprintSetter, Category = "Cesium") void SetMaximumScreenSpaceError(double InMaximumScreenSpaceError); UFUNCTION(BlueprintGetter, Category = "Cesium|Tile Culling|Experimental") bool GetEnableOcclusionCulling() const; UFUNCTION(BlueprintSetter, Category = "Cesium|Tile Culling|Experimental") void SetEnableOcclusionCulling(bool bEnableOcclusionCulling); UFUNCTION(BlueprintGetter, Category = "Cesium|Tile Culling|Experimental") int32 GetOcclusionPoolSize() const { return OcclusionPoolSize; } UFUNCTION(BlueprintSetter, Category = "Cesium|Tile Culling|Experimental") void SetOcclusionPoolSize(int32 newOcclusionPoolSize); UFUNCTION(BlueprintGetter, Category = "Cesium|Tile Culling|Experimental") bool GetDelayRefinementForOcclusion() const { return DelayRefinementForOcclusion; } UFUNCTION(BlueprintSetter, Category = "Cesium|Tile Culling|Experimental") void SetDelayRefinementForOcclusion(bool bDelayRefinementForOcclusion); UFUNCTION(BlueprintGetter, Category = "Cesium|Physics") bool GetCreatePhysicsMeshes() const { return CreatePhysicsMeshes; } UFUNCTION(BlueprintSetter, Category = "Cesium|Physics") void SetCreatePhysicsMeshes(bool bCreatePhysicsMeshes); UFUNCTION(BlueprintGetter, Category = "Cesium|Navigation") bool GetCreateNavCollision() const { return CreateNavCollision; } UFUNCTION(BlueprintSetter, Category = "Cesium|Navigation") void SetCreateNavCollision(bool bCreateNavCollision); UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") bool GetAlwaysIncludeTangents() const { return AlwaysIncludeTangents; } UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") void SetAlwaysIncludeTangents(bool bAlwaysIncludeTangents); UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") bool GetGenerateSmoothNormals() const { return GenerateSmoothNormals; } UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") void SetGenerateSmoothNormals(bool bGenerateSmoothNormals); UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") bool GetEnableWaterMask() const { return EnableWaterMask; } UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") void SetEnableWaterMask(bool bEnableMask); UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") bool GetIgnoreKhrMaterialsUnlit() const { return IgnoreKhrMaterialsUnlit; } UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") void SetIgnoreKhrMaterialsUnlit(bool bIgnoreKhrMaterialsUnlit); UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") UMaterialInterface* GetMaterial() const { return Material; } UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") void SetMaterial(UMaterialInterface* InMaterial); UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") UMaterialInterface* GetTranslucentMaterial() const { return TranslucentMaterial; } UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") void SetTranslucentMaterial(UMaterialInterface* InMaterial); UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") UMaterialInterface* GetWaterMaterial() const { return WaterMaterial; } UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") void SetWaterMaterial(UMaterialInterface* InMaterial); UFUNCTION(BlueprintGetter, Category = "Rendering") FCustomDepthParameters GetCustomDepthParameters() const { return CustomDepthParameters; } UFUNCTION(BlueprintSetter, Category = "Rendering") void SetCustomDepthParameters(FCustomDepthParameters InCustomDepthParameters); UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering") FCesiumPointCloudShading GetPointCloudShading() const { return PointCloudShading; } UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering") void SetPointCloudShading(FCesiumPointCloudShading InPointCloudShading); UFUNCTION(BlueprintCallable, Category = "Cesium|Rendering") void PlayMovieSequencer(); UFUNCTION(BlueprintCallable, Category = "Cesium|Rendering") void StopMovieSequencer(); UFUNCTION(BlueprintCallable, Category = "Cesium|Rendering") void PauseMovieSequencer(); /** * This method is not supposed to be called by clients. It is currently * only required by the UnrealPrepareRendererResources. * * @internal * See {@link * UCesium3DTilesetRoot::GetCesiumTilesetToUnrealRelativeWorldTransform}. * @endinternal */ const glm::dmat4& GetCesiumTilesetToUnrealRelativeWorldTransform() const; Cesium3DTilesSelection::Tileset* GetTileset() { return this->_pTileset.Get(); } const Cesium3DTilesSelection::Tileset* GetTileset() const { return this->_pTileset.Get(); } const std::optional& getFeaturesMetadataDescription() const { return this->_featuresMetadataDescription; } // AActor overrides (some or most of them should be protected) virtual bool ShouldTickIfViewportsOnly() const override; virtual void Tick(float DeltaTime) override; virtual void BeginDestroy() override; virtual bool IsReadyForFinishDestroy() override; virtual void Destroyed() override; virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; virtual void PostLoad() override; virtual void Serialize(FArchive& Ar) override; void UpdateLoadStatus(); // UObject overrides #if WITH_EDITOR virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; virtual void PostEditChangeChainProperty( FPropertyChangedChainEvent& PropertyChangedChainEvent) override; virtual void PostEditUndo() override; virtual void PostEditImport() override; virtual bool CanEditChange(const FProperty* InProperty) const override; #endif protected: // Called when the game starts or when spawned virtual void BeginPlay() override; virtual void OnConstruction(const FTransform& Transform) override; /** * Called after the C++ constructor and after the properties have * been initialized, including those loaded from config. */ void PostInitProperties() override; virtual void NotifyHit( class UPrimitiveComponent* MyComp, AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit) override; private: void LoadTileset(); void DestroyTileset(); static Cesium3DTilesSelection::ViewState CreateViewStateFromViewParameters( const FCesiumCamera& camera, const glm::dmat4& unrealWorldToTileset, UCesiumEllipsoid* ellipsoid); std::vector GetCameras() const; std::vector GetPlayerCameras() const; std::vector GetSceneCaptures() const; public: /** * Update the transforms of the glTF components based on the * the transform of the root component. * * This is supposed to be called during Tick, if the transform of * the root component has changed since the previous Tick. */ void UpdateTransformFromCesium(); private: /** * The event handler for ACesiumGeoreference::OnEllipsoidChanged. */ UFUNCTION(CallInEditor) void HandleOnGeoreferenceEllipsoidChanged( UCesiumEllipsoid* OldEllipsoid, UCesiumEllipsoid* NewEllpisoid); /** * Writes the values of all properties of this actor into the * TilesetOptions, to take them into account during the next * traversal. */ void updateTilesetOptionsFromProperties(); /** * Update all the "_last..." fields of this instance based * on the given ViewUpdateResult, printing a log message * if any value changed. * * @param result The ViewUpdateREsult */ void updateLastViewUpdateResultState( const Cesium3DTilesSelection::ViewUpdateResult& result); /** * Creates the visual representations of the given tiles to * be rendered in the current frame. * * @param tiles The tiles */ void showTilesToRender(const std::vector& tiles); /** * Will be called after the tileset is loaded or spawned, to register * a delegate that calls OnFocusEditorViewportOnThis when this * tileset is double-clicked */ void AddFocusViewportDelegate(); #if WITH_EDITOR std::vector GetEditorCameras() const; /** * Will focus all viewports on this tileset. * * This is called when double-clicking the tileset in the World Outliner. * It will move the tileset into the center of the view, *even if* the * tileset was not visible before, and no geometry has been created yet * for the tileset: It solely operates on the tile bounding volume that * was given in the root tile. */ void OnFocusEditorViewportOnThis(); void RuntimeSettingsChanged( UObject* pObject, struct FPropertyChangedEvent& changed); #endif private: TUniquePtr _pTileset; #ifdef CESIUM_DEBUG_TILE_STATES TUniquePtr _pStateDebug; #endif std::optional _featuresMetadataDescription; PRAGMA_DISABLE_DEPRECATION_WARNINGS std::optional _metadataDescription_DEPRECATED; PRAGMA_ENABLE_DEPRECATION_WARNINGS // For debug output uint32_t _lastTilesRendered; uint32_t _lastWorkerThreadTileLoadQueueLength; uint32_t _lastMainThreadTileLoadQueueLength; uint32_t _lastTilesVisited; uint32_t _lastCulledTilesVisited; uint32_t _lastTilesCulled; uint32_t _lastTilesOccluded; uint32_t _lastTilesWaitingForOcclusionResults; uint32_t _lastMaxDepthVisited; std::chrono::high_resolution_clock::time_point _startTime; bool _captureMovieMode; bool _beforeMoviePreloadAncestors; bool _beforeMoviePreloadSiblings; int32_t _beforeMovieLoadingDescendantLimit; bool _beforeMovieUseLodTransitions; bool _scaleUsingDPI; // This is used as a workaround for cesium-native#186 // // The tiles that are no longer supposed to be rendered in the current // frame, according to ViewUpdateResult::tilesToHideThisFrame, // are kept in this list, and hidden in the NEXT frame, because some // internal occlusion culling information from Unreal might prevent // the tiles that are supposed to be rendered instead from appearing // immediately. // // If we find a way to clear the wrong occlusion information in the // Unreal Engine, then this field may be removed, and the // tilesToHideThisFrame may be hidden immediately. std::vector _tilesToHideNextFrame; int32 _tilesetsBeingDestroyed; friend class UnrealPrepareRendererResources; friend class UCesiumGltfPointsComponent; };