123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497 |
- /*
- * @Author: namidame
- * @Description: A Heatmap Generation plugin based on the old HeatMapActor, Supports Heightmap, Texture Coordinate Points And Geographic Location Data.
- * @Date: 2024/07/27
- */
- #pragma once
- #include "CoreMinimal.h"
- #include "ProceduralMeshComponent.h"
- #include "GameFramework/Actor.h"
- #include "DynamicHeatmapDefs.h"
- #include "JsonObjectWrapper.h"
- #include "Materials/MaterialInstanceDynamic.h"
- #include "Curves/CurveFloat.h"
- #include "Engine/Texture2D.h"
- #include "GeoReferencingSystem.h"
- #include "Layout/Margin.h"
- #include "DynamicHeatmap.generated.h"
- /**
- *
- */
- UCLASS()
- class HEATMAP_API ADynamicHeatmap : public AActor
- {
- GENERATED_BODY()
- public:
- // Sets default values for this actor's properties
- ADynamicHeatmap();
- protected:
- // Called when the game starts or when spawned
- virtual void BeginPlay() override;
- virtual void OnConstruction(const FTransform& Transform) override;
- public:
- // Called every frame
- virtual void Tick(float DeltaTime) override;
- #pragma region BaseSettigns
- /**
- * Whether refresh heatmap in construction method.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|BaseSettings")
- bool bRefreshOnConstruction;
-
- /*
- * Defines which method to create heatmap.
- * The UpdateHeatmap method use this value to choose a method to update heatmap.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|BaseSettings")
- EDynamicHeatmapType HeatmapType;
- /*
- * The base material of the heatmap.
- * A materialInstanceDynamic will be created base on this material and be applied to the heatmap mesh.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources")
- UMaterialInterface* HeatmapMaterial;
- /*
- * The gray scale texture to be set in this heatmap material.
- * Make sure to use a 8bit grayscale image texture. In texture details, set "Compress settings" to "VectorDisplacementmap(RGBA8)", set "sRGB" to false, set "Mip Gen Settings" to "NoMipMaps", and "Never Stream" set to true. Otherwise crash may happen in package build.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources", meta=(EditConditionHides, EditCondition = "HeatmapType==EDynamicHeatmapType::GrayScaleTexture"))
- UTexture2D* GrayScaleTexture;
- /*
- * Defines whether the .json or .hgt file path is relative to project root or a fullpath.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources", meta=(EditConditionHides, EditCondition = "HeatmapType==EDynamicHeatmapType::JsonFileData||HeatmapType==EDynamicHeatmapType::HgtFileData"), DisplayName="Is Path Relative to Project")
- bool bProjectRelativePath;
- /*
- * Path of the json file to load.
- * Must be relative path to project root if bProjectRelativePath is True,
- * or must be full path if bProjectRelativePath is False.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources", meta=(EditConditionHides, EditCondition = "HeatmapType==EDynamicHeatmapType::JsonFileData"))
- FString JsonFilePath;
- /*
- * Defines field names and types of the json file.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources", meta=(EditConditionHides, EditCondition = "HeatmapType==EDynamicHeatmapType::JsonFileData"))
- FJsonConfig JsonConfig;
- /*
- * Path of the hgt file to load.
- * Must be relative path to project root if bProjectRelativePath is True,
- * or must be full path if bProjectRelativePath is False.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources", meta=(EditConditionHides, EditCondition = "HeatmapType==EDynamicHeatmapType::HgtFileData"))
- FString HgtFilePath;
- /*
- * Geographic data table to create the heatmap.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources", meta=(EditConditionHides, EditCondition = "HeatmapType==EDynamicHeatmapType::GeographicData"))
- UDataTable* GeographicDataTable;
- /*
- * Texture coordinate point data table to create the heatmap.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources", meta=(EditConditionHides, EditCondition = "HeatmapType==EDynamicHeatmapType::TextureCoordPoint"))
- UDataTable* TextureCoordPointDataTable;
-
- /*
- * The size of the texture generated in TextureCoordPoint.
- * In GrayScaleTexture mode, this value will be set to the size of GrayScaleTexture automatically.
- * In TextureCoordPoint mode, this value should be set by user.
- * In GeographicData/JsonFileData mode, this value will be set automatically based on the DefaultTextureSizeBase value.
- * In HgtFileData mode, this value is fixed to 1201*1201.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters", meta=(EditConditionHides,EditCondition = "HeatmapType==EDynamicHeatmapType::TextureCoordPoint"))
- FVector2D TextureSize;
- /*
- * In GeographicData mode, this value controls the genrated texture size.
- * For example, if the longitude span is larger than latitude span, generated texture size equals to DefaultTextureSizeBase * (LongitudeSpan / LatitudeSpan).
- * If the longitude span is less than latitude span, generated texture size equals to DefaultTextureSizeBase * (LatitudeSpan / LongitudeSpan).
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters", meta=(EditConditionHides,EditCondition = "HeatmapType==EDynamicHeatmapType::GeographicData||HeatmapType==EDynamicHeatmapType::JsonFileData"))
- int32 DefaultTextureSizeBase;
- /*
- * The generated heatmap mesh size.
- * In GrayScaleTexture/TextureCoordPoint/HgtFileData mode, this value should be set by user.
- * In GeographicData/JsonFileData mode, this value will be calculated automatically.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters", meta=(EditConditionHides,EditCondition = "HeatmapType!=EDynamicHeatmapType::GeographicData&&HeatmapType!=EDynamicHeatmapType::JsonFileData"))
- FVector2D MeshSize;
-
- /*
- * The segmentation of the generated heatmap mesh.
- * Increse this value to smooth the bump up effect.
- * This value should not be too large because calculation time will increase rapidly.
- * If bump up effect is not needed, you can set this value to a (1,1) to improve performance.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters")
- FVector2D MeshSegment;
- /*
- * Control the margin of genrated heatmap mesh.
- * In case that heatmap effect on the edge be clipped.
- * Only affect TextureCoordPoint and GeographicData mode.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters", meta=(EditConditionHides,EditCondition="HeatmapType==EDynamicHeatmapType::GeographicData||HeatmapType==EDynamicHeatmapType::JsonFileData"))
- FMargin MeshMargin;
- /*
- * Generate heatmap mesh based on this altitude
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters", meta=(EditConditionHides,EditCondition = "(HeatmapType==EDynamicHeatmapType::GeographicData||HeatmapType==EDynamicHeatmapType::JsonFileData)"))
- double HeatmapAltitude;
- /**
- * Multiplier of origin texture pixel value.
- * Heat value gets to maximum value faster if this value set to a higher value.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters")
- float LerpScale;
- /*
- * Control the height offset scale in heatmap material.
- * Heatmap mesh will be higher at heat value points if this value is larger.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters")
- float HeightScale;
- /*
- * Control the total opacity of the heatmap material.
- * This value should be 0 to 1.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters")
- float Opacity;
- /*
- * Control the opacity of this heatmap material when heat value is zero .
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters")
- float ZeroValueOpacity;
- /*
- * Control the influence radius of single heat value point.
- * Area around heat value point gets higher if this value is larger.
- * This value should not be too large because calculation time will increase rapidly.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters")
- int32 InfluenceSize;
-
- /**
- * Control the emissive strength of the heatmap color.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters")
- float EmissiveStrength;
- /*
- * Control the influence rate change of area around heat value point.
- * Manipulate this curve to control the pattern of heatmap.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Curves")
- UCurveFloat* InfluenceCurve;
- /*
- * Control influence factor of heat value.
- * Influence area gets bigger when heat value increase.
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Curves")
- UCurveFloat* InfluenceFactorCurve;
-
- #pragma endregion
-
- #pragma region CreationMethods
- /**
- * Create heatmap with a gray scale texture.
- * Make sure to use a 8bit grayscale image texture. In texture details, set "Compress settings" to "VectorDisplacementmap(RGBA8)", set "sRGB" to false, set "Mip Gen Settings" to "NoMipMaps", and "Never Stream" set to true. Otherwise crash may happen in package build.
- * @param texture gray scale texture input
- * @param mesh_size generated heatmap size
- * @param bUpdateMesh whether to update generated mesh or only update other settings
- * @param bRecreateMesh whether to regenerate heatmap mesh
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
- void CreateWithGrayScaleTexture(UTexture2D* texture, FVector2D mesh_size, bool bUpdateMesh, bool bRecreateMesh);
- /**
- * Create with a map with texture coordinate point as keys and heat value as value.
- * For example, set texture_size to (1024,1024), keys of map should be in 0~1023, and values of map should be 0~1.
- * @param map texture coordinate point - heat value map to input
- * @param mesh_size generated heatmap size
- * @param texture_size generated texture size
- * @param bUpdateMesh whether to update generated mesh or only update other settings
- * @param bRecreateMesh whether to regenerate heatmap mesh
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
- void CreateWithTextureCoordPointMap(const TMap<FVector2D, float> &map, FVector2D texture_size, FVector2D mesh_size, bool bUpdateMesh, bool bRecreateMesh);
- /**
- * Create with a texture coordinate point map datatable.
- * @param DataTable texture coordinate point - heat value data table
- * @see CreateWithTextureCoordPointMap
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
- void CreateWithTextureCoordPointMapDataTable(UDataTable* DataTable, FVector2D texture_size, FVector2D mesh_size, bool bUpdateMesh, bool bRecreateMesh);
- /**
- * Use a map with geographic point (longitude, latitude) for keys and heat value(0 to 1) to create a heatmap.
- *
- * @param map geographic point - heat value map to input
- * @param bUpdateMesh whether to update generated mesh or only update other settings
- * @param bRecreateMesh whether to regenerate heatmap mesh
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
- void CreateWithGeographicData(const TMap<FVector, float> &map, bool bUpdateMesh, bool bRecreateMesh);
- /**
- *
- * @param DataTable geographic point - heat value data table to input
- * @see CreateWithGeographicData
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
- void CreateWithGeographicDataTable(UDataTable* DataTable, bool bUpdateMesh, bool bRecreateMesh);
- /**
- * Create heatmap with a json file. The json file stores longitude, latitude and heat value data.
- * Input different params according to the field name and field type of json file.
- * These params can be stored in a FJsonConfig object. @see CreateWithJsonFile_Config
- *
- * @param FilePath .json file path to load
- * @param bRelativePath is path relative to project root
- * @param bUpdateMesh whether to update generated mesh or only update other settings
- * @param bRecreateMesh whether to regenerate heatmap mesh
- * @param LngName longitude field name
- * @param LatName latitude field name
- * @param ValueName heat value field name
- * @param bStringCoord whether longitude and latitude string value or double value
- * @param bStringValue whether heat value string value or double value
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
- void CreateWithJsonFile(const FString& FilePath, bool bRelativePath, bool bUpdateMesh, bool bRecreateMesh, const FString& LngName, const FString& LatName, const FString& ValueName, bool bStringCoord, bool bStringValue);
- /**
- * Create heatmap with a json file and configuration.
- * @param Config controls how to load the json file
- * @see CreateWithJsonFile
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
- void CreateWithJsonFile_Config(const FString& FilePath, bool bRelativePath, bool bUpdateMesh, bool bRecreateMesh, FJsonConfig Config);
- /**
- * Create heatmap with a hgt file (a DEM data format file)
- * A .hgt file stores the height value of a specific area. One hgt file stores 1201x1201 pixel data. Each pixel stores in 2 bytes (16 bits), representing -32768 ~ +32767 meters away from sealevel (0 value).
- *
- * @param FilePath .hgt file path to load
- * @param bRelativePath is path relative to project root
- * @param mesh_size generated heatmap size
- * @param bUpdateMesh whether to update generated mesh or only update other settings
- * @param bRecreateMesh whether to regenerate heatmap mesh
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
- void CreateWithHgtFile(const FString& FilePath, bool bRelativePath, FVector2D mesh_size, bool bUpdateMesh = true, bool bRecreateMesh = true);
-
- #pragma endregion
- #pragma region UpdateMethods
- /**
- * Change the segmentation number of the gerenated mesh.
- *
- * @param segment how many segmentations does the mesh has, must be integer number
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
- void UpdateMapSegment(FVector2D segment);
-
- /**
- * Update the size of generated mesh.
- *
- * @param size size of generated mesh
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
- void UpdateMeshSize(FVector2D size);
-
- /**
- * Add point to existing TextureCoordPointMap without regenerating mesh.
- *
- * @param pos texture coordinate position
- * @param value heat value of the new point
- * @param bUpdate whether to update effect at once, set to false to improve performance during adding a lot of points at once
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
- void AddTextureCoordValue(const FVector2D &pos, float value, bool bUpdate);
-
- /**
- * Delete a point from existing TextureCoordPointMap without regenerating mesh.
- *
- * @param pos texture coordinate position
- * @param bUpdate whether to update effect at once, set to false to improve performance during adding a lot of points at once
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
- void DeleteTextureCoordValue(const FVector2D& pos, bool bUpdate);
- UFUNCTION(BlueprintPure, Category="DynamicHeatmap|Manipulate")
- const TMap<FVector2D, float> & GetTextureCoordPointMap() { return TextureCoordPointMap; };
-
- /**
- * Update influence size of single data point
- *
- * @param size radius of influence area
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
- void UpdatePointInfluenceSize(int32 size);
- /**
- * Update generated heatmap according to creation type and properties been set.
- *
- * @param bUpdateMesh whether to update generated mesh or only update other settings
- * @param bRecreateMesh whether to regenerate heatmap mesh
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
- void UpdateHeatmap(bool bUpdateMesh, bool bRecreateMesh);
- /**
- * Update origin heat value multiplier.
- *
- * @param scale origin heat value multiplier
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
- void UpdateLerpScale(float scale);
- /**
- * Update material height scale.
- *
- * @param scale material height scale
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
- void UpdateHeightScale(float scale);
- /**
- * Update total opacity of heatmap.
- *
- * @param value total opacity of heatmap
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
- void UpdateOpacity(float value);
- /**
- * Update the opacity where heat value is zero.
- *
- * @param value opacity where heat value is zero
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
- void UpdateZeroValueOpacity(float value);
- /**
- * Update the emissive strength of heatmap.
- *
- * @param value emissive strength
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
- void UpdateEmissive(float value);
-
- /**
- * Update all material parameters.
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
- void UpdateMaterialParameters();
- /**
- * Editor method to update heatmap effect.
- * @see UpdateHeatmap
- */
- UFUNCTION(BlueprintCallable, CallInEditor, Category="DynamicHeatmap")
- void RefreshHeatmap();
- /**
- * Editor method to update material parameters.
- * @see UpdateMaterialParameters
- */
- UFUNCTION(BlueprintCallable, CallInEditor, Category="DynamicHeatmap")
- void RefreshMaterial();
- protected:
- void UpdateGeneratedMesh(FVector2D mesh_Size, bool bRecreate);
- #pragma endregion
- #pragma region UtilMethods
- public:
-
- /**
- * Convert a geographic location to unreal position.
- * Override this method to adapt to cesium plugin.
- *
- * @param location FVector storing longitude, latitude and altitude
- * @return corresponding unreal position
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Calculation")
- virtual FVector ConvertGeoGraphicToEngine(FVector location);
- /**
- * Compute leftupcorner transform to calculate relative position to heatmap actor origin
- * Override this method to adapt to cesium plugin.
- *
- * @param MinLng minimum longitude of heatmap area span
- * @param MaxLat maximum latitude of heatmap area span
- */
- UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Calculation")
- virtual void ComputeLeftUpCornerESUTransform(float MinLng, float MaxLat);
- /**
- * Shift a heatmap actor local space position by (longitude, latitude).
- * Override this method to adapt to cesium plugin.
- *
- * @param LocalOriginPos a heatmap actor local space position
- * @param LngShift longitude value to shift
- * @param LatShift latitude value to shift
- * @return heatmap actor local space position after shifting
- */
- virtual FVector ComputeGeoShift(const FVector& LocalOriginPos, double LngShift, double LatShift);
- protected:
- TMap<FVector2D, float> ConvertGeoValueMapToUnrealValueMap(const TMap<FVector, float>& map);
- bool LoadJsonFileToGeographicData(const FString& Fullpath, TMap<FVector, float> &OutMap, const FString& LngName, const FString& LatName, const FString& ValueName, bool bStringCoord, bool bStringValue);
- TMap<FVector, float> LoadDataTableToGeographicData(UDataTable* DataTable);
-
- TMap<FVector2D, float> LoadDataTableToTextureCoordPointMap(UDataTable* DataTable);
-
- static bool CheckFileExists(const FString& FunctionName, const FString& Fullpath);
-
- static FString GetFullpath(const FString& RelativePath);
-
- TArray<FColor> LoadHgtFile(const FString & Fullpath);
-
- TArray<FColor> GetColorDataFromTextureCoordPointMap(const TMap<FVector2D, float> &map, FVector2D texture_size, int32 influenceSize);
- UTexture2D* CreateTexture(const FVector2D& texture_size, const TArray<FColor>& colorArr);
- #pragma endregion
- protected:
- UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Data")
- UMaterialInstanceDynamic* Material;
-
- UPROPERTY(BlueprintReadWrite, Category="DynamicHeatmap|Data")
- UProceduralMeshComponent* ProceduralMapMesh;
-
- TMap<FVector2D, float> TextureCoordPointMap;
- TMap<FVector, float> GeographicData;
- FVector2D GeographicSize;
- FTransform LeftUpCornerESUTransform;
- UPROPERTY()
- AGeoReferencingSystem* GeoReferencing;
- AGeoReferencingSystem* GetGeoReferencing();
- };
|