// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Components/MeshComponent.h" #include "WaterQuadTree.h" #include "WaterQuadTreeBuilder.h" #include "WaterMeshComponent.generated.h" #define UE_API WATER_API struct FPSOPrecacheParams; /** * Water Mesh Component responsible for generating and rendering a continuous water mesh on top of all the existing water body actors in the world * The component contains a quadtree which defines where there are water tiles. A function for traversing the quadtree and outputing a list of instance data for each tile to be rendered from a point of view is included */ UCLASS(MinimalAPI, ClassGroup = (Rendering, Water), hidecategories = (Object, Activation, "Components|Activation", Collision, Lighting, HLOD, Navigation, Replication, Input, MaterialParameters, TextureStreaming), editinlinenew) class UWaterMeshComponent : public UMeshComponent { GENERATED_BODY() public: UE_API UWaterMeshComponent(); //~ Begin UObject Interface UE_API virtual void PostLoad() override; UE_API virtual void PostInitProperties() override; //~ End UObject Interface //~ Begin UMeshComponent Interface virtual int32 GetNumMaterials() const override { return 0; } //~ End UMeshComponent Interface //~ Begin UPrimitiveComponent Interface UE_API virtual FPrimitiveSceneProxy* CreateSceneProxy() override; UE_API virtual void GetUsedMaterials(TArray& OutMaterials, bool bGetDebugMaterials = false) const override; UE_API virtual void SetMaterial(int32 ElementIndex, UMaterialInterface* Material) override; #if WITH_EDITOR UE_API virtual bool ShouldRenderSelected() const override; #endif // WITH_EDITOR //~ End UPrimitiveComponent Interface //~ Begin INavRelevantInterface Interface virtual bool IsNavigationRelevant() const override { return false; } //~ End INavRelevantInterface Interface UE_API virtual void CollectPSOPrecacheData(const FPSOPrecacheParams& BasePrecachePSOParams, FMaterialInterfacePSOPrecacheParamsList& OutParams) override; UE_API void Update(); /** Use this instead of GetMaterialRelevance, since this one will go over all materials from all tiles */ UE_API FMaterialRelevance GetWaterMaterialRelevance(ERHIFeatureLevel::Type InFeatureLevel) const; const FWaterQuadTreeBuilder& GetWaterQuadTreeBuilder() const { return WaterQuadTreeBuilder; } const TSet>& GetUsedMaterialsSet() const { return UsedMaterials; } void MarkWaterMeshGridDirty() { bNeedsRebuild = true; } int32 GetTessellationFactor() const { return FMath::Clamp(TessellationFactor + TessFactorBiasScalability, 1, 12); } float GetLODScale() const { return LODScale + LODScaleBiasScalability; } UE_API FIntPoint GetExtentInTiles() const; UE_DEPRECATED(5.5, "It is no longer possible to manually set the dynamic mesh center. This is controlled per view by the water view extension.") void SetDynamicWaterMeshCenter(const FVector2D& NewCenter) { } UE_DEPRECATED(5.5, "Dynamic water mesh center is now per-view and must be retrieved through the water view extension (water zone actor provides utilities to do this as well)") FVector2D GetDynamicWaterMeshCenter() const { return FVector2D::ZeroVector; } UE_API FVector2D GetGlobalWaterMeshCenter() const; UE_API bool IsLocalOnlyTessellationEnabled() const; UE_API void SetTileSize(float NewTileSize); float GetTileSize() const { return TileSize; } /** At above what density level a tile is allowed to force collapse even if not all leaf nodes in the subtree are present. * Collapsing will not occus if any child node in the subtree has different materials. * Setting this to -1 means no collapsing is allowed and the water mesh will always keep it's silhouette at any distance. * Setting this to 0 will allow every level to collapse * Setting this to something higher than the LODCount will have no effect */ UPROPERTY(EditAnywhere, Category = Rendering, meta = (ClampMin = "-1")) int32 ForceCollapseDensityLevel = -1; UPROPERTY(EditAnywhere, Category = "Rendering|FarDistance") TObjectPtr FarDistanceMaterial = nullptr; UPROPERTY(EditAnywhere, Category = "Rendering|FarDistance", meta = (ClampMin = "0")) float FarDistanceMeshExtent = 0.0f; UFUNCTION(BlueprintPure, Category = Rendering) bool IsEnabled() const { return bIsEnabled; } private: //~ Begin USceneComponent Interface UE_API virtual FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const override; //~ Begin USceneComponent Interface /** Based on all water bodies in the scene, rebuild the water mesh */ UE_API void RebuildWaterMesh(float InTileSize, const FIntPoint& InExtentInTiles); /** World size of the water tiles at LOD0. Multiply this with the ExtentInTiles to get the world extents of the system */ UPROPERTY(EditAnywhere, Category = Rendering, meta = (ClampMin = "100", AllowPrivateAcces = "true")) float TileSize = 2400.0f; /** The current quad tree resolution derived from the extent of the water zone and the water mesh tile size (Extent / TileSize). */ UPROPERTY(Transient, VisibleAnywhere, Category = Rendering) mutable FIntPoint QuadTreeResolution = FIntPoint::ZeroValue; FWaterQuadTreeBuilder WaterQuadTreeBuilder; /** Tiles containing water, stored in a quad tree */ FWaterQuadTree WaterQuadTree; /** Unique list of materials used by this component */ UPROPERTY(Transient, NonPIEDuplicateTransient, TextExportTransient) TSet> UsedMaterials; /** Maps from materials assigned to each water body to actually used MIDs. Persists across rebuilds in order to cache MIDs */ UPROPERTY(Transient, NonPIEDuplicateTransient, TextExportTransient) TMap, TObjectPtr> MaterialToMID; /** Forces the water mesh to always render the far mesh, regardless if there is an ocean or not.*/ UPROPERTY(Category = "Rendering|FarDistance", EditAnywhere) bool bUseFarMeshWithoutOcean = false; /** Dirty flag which will make sure the water mesh is updated properly */ bool bNeedsRebuild = true; /** If the system is enabled */ bool bIsEnabled = false; /** Cached CVarWaterMeshLODCountBias to detect changes in scalability */ int32 LODCountBiasScalability = 0; /** Cached CVarWaterMeshTessFactorBias to detect changes in scalability */ int32 TessFactorBiasScalability = 0; /** Cached CVarWaterMeshLODScaleBias to detect changes in scalability */ float LODScaleBiasScalability = 0.0f; /** Highest tessellation factor of a water tile. Max number of verts on the side of a tile will be (2^TessellationFactor)+1) */ UPROPERTY(EditAnywhere, Category = Rendering, meta = (ClampMin = "1", ClampMax = "12")) int32 TessellationFactor = 6; /** World scale of the concentric LODs */ UPROPERTY(EditAnywhere, Category = Rendering, meta = (ClampMin = "0.5")) float LODScale = 1.0f; #if WITH_EDITOR //~ Begin USceneComponent Interface UE_API virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; //~ Begin USceneComponent Interface #endif #if WITH_EDITORONLY_DATA UPROPERTY() FIntPoint ExtentInTiles_DEPRECATED = FIntPoint(64, 64); #endif // WITH_EDITORONLY_DATA }; #undef UE_API