DynamicHeatmap.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. /*
  2. * @Author: namidame
  3. * @Description: A Heatmap Generation plugin based on the old HeatMapActor, Supports Heightmap, Texture Coordinate Points And Geographic Location Data.
  4. * @Date: 2024/07/27
  5. */
  6. #pragma once
  7. #include "CoreMinimal.h"
  8. #include "ProceduralMeshComponent.h"
  9. #include "GameFramework/Actor.h"
  10. #include "DynamicHeatmapDefs.h"
  11. #include "JsonObjectWrapper.h"
  12. #include "Materials/MaterialInstanceDynamic.h"
  13. #include "Curves/CurveFloat.h"
  14. #include "Engine/Texture2D.h"
  15. #include "GeoReferencingSystem.h"
  16. #include "Layout/Margin.h"
  17. #include "DynamicHeatmap.generated.h"
  18. /**
  19. *
  20. */
  21. UCLASS()
  22. class HEATMAP_API ADynamicHeatmap : public AActor
  23. {
  24. GENERATED_BODY()
  25. public:
  26. // Sets default values for this actor's properties
  27. ADynamicHeatmap();
  28. protected:
  29. // Called when the game starts or when spawned
  30. virtual void BeginPlay() override;
  31. virtual void OnConstruction(const FTransform& Transform) override;
  32. public:
  33. // Called every frame
  34. virtual void Tick(float DeltaTime) override;
  35. #pragma region BaseSettigns
  36. /**
  37. * Whether refresh heatmap in construction method.
  38. */
  39. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|BaseSettings")
  40. bool bRefreshOnConstruction;
  41. /*
  42. * Defines which method to create heatmap.
  43. * The UpdateHeatmap method use this value to choose a method to update heatmap.
  44. */
  45. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|BaseSettings")
  46. EDynamicHeatmapType HeatmapType;
  47. /*
  48. * The base material of the heatmap.
  49. * A materialInstanceDynamic will be created base on this material and be applied to the heatmap mesh.
  50. */
  51. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources")
  52. UMaterialInterface* HeatmapMaterial;
  53. /*
  54. * The gray scale texture to be set in this heatmap material.
  55. * 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.
  56. */
  57. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources", meta=(EditConditionHides, EditCondition = "HeatmapType==EDynamicHeatmapType::GrayScaleTexture"))
  58. UTexture2D* GrayScaleTexture;
  59. /*
  60. * Defines whether the .json or .hgt file path is relative to project root or a fullpath.
  61. */
  62. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources", meta=(EditConditionHides, EditCondition = "HeatmapType==EDynamicHeatmapType::JsonFileData||HeatmapType==EDynamicHeatmapType::HgtFileData"), DisplayName="Is Path Relative to Project")
  63. bool bProjectRelativePath;
  64. /*
  65. * Path of the json file to load.
  66. * Must be relative path to project root if bProjectRelativePath is True,
  67. * or must be full path if bProjectRelativePath is False.
  68. */
  69. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources", meta=(EditConditionHides, EditCondition = "HeatmapType==EDynamicHeatmapType::JsonFileData"))
  70. FString JsonFilePath;
  71. /*
  72. * Defines field names and types of the json file.
  73. */
  74. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources", meta=(EditConditionHides, EditCondition = "HeatmapType==EDynamicHeatmapType::JsonFileData"))
  75. FJsonConfig JsonConfig;
  76. /*
  77. * Path of the hgt file to load.
  78. * Must be relative path to project root if bProjectRelativePath is True,
  79. * or must be full path if bProjectRelativePath is False.
  80. */
  81. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources", meta=(EditConditionHides, EditCondition = "HeatmapType==EDynamicHeatmapType::HgtFileData"))
  82. FString HgtFilePath;
  83. /*
  84. * Geographic data table to create the heatmap.
  85. */
  86. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources", meta=(EditConditionHides, EditCondition = "HeatmapType==EDynamicHeatmapType::GeographicData"))
  87. UDataTable* GeographicDataTable;
  88. /*
  89. * Texture coordinate point data table to create the heatmap.
  90. */
  91. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Resources", meta=(EditConditionHides, EditCondition = "HeatmapType==EDynamicHeatmapType::TextureCoordPoint"))
  92. UDataTable* TextureCoordPointDataTable;
  93. /*
  94. * The size of the texture generated in TextureCoordPoint.
  95. * In GrayScaleTexture mode, this value will be set to the size of GrayScaleTexture automatically.
  96. * In TextureCoordPoint mode, this value should be set by user.
  97. * In GeographicData/JsonFileData mode, this value will be set automatically based on the DefaultTextureSizeBase value.
  98. * In HgtFileData mode, this value is fixed to 1201*1201.
  99. */
  100. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters", meta=(EditConditionHides,EditCondition = "HeatmapType==EDynamicHeatmapType::TextureCoordPoint"))
  101. FVector2D TextureSize;
  102. /*
  103. * In GeographicData mode, this value controls the genrated texture size.
  104. * For example, if the longitude span is larger than latitude span, generated texture size equals to DefaultTextureSizeBase * (LongitudeSpan / LatitudeSpan).
  105. * If the longitude span is less than latitude span, generated texture size equals to DefaultTextureSizeBase * (LatitudeSpan / LongitudeSpan).
  106. */
  107. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters", meta=(EditConditionHides,EditCondition = "HeatmapType==EDynamicHeatmapType::GeographicData||HeatmapType==EDynamicHeatmapType::JsonFileData"))
  108. int32 DefaultTextureSizeBase;
  109. /*
  110. * The generated heatmap mesh size.
  111. * In GrayScaleTexture/TextureCoordPoint/HgtFileData mode, this value should be set by user.
  112. * In GeographicData/JsonFileData mode, this value will be calculated automatically.
  113. */
  114. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters", meta=(EditConditionHides,EditCondition = "HeatmapType!=EDynamicHeatmapType::GeographicData&&HeatmapType!=EDynamicHeatmapType::JsonFileData"))
  115. FVector2D MeshSize;
  116. /*
  117. * The segmentation of the generated heatmap mesh.
  118. * Increse this value to smooth the bump up effect.
  119. * This value should not be too large because calculation time will increase rapidly.
  120. * If bump up effect is not needed, you can set this value to a (1,1) to improve performance.
  121. */
  122. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters")
  123. FVector2D MeshSegment;
  124. /*
  125. * Control the margin of genrated heatmap mesh.
  126. * In case that heatmap effect on the edge be clipped.
  127. * Only affect TextureCoordPoint and GeographicData mode.
  128. */
  129. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters", meta=(EditConditionHides,EditCondition="HeatmapType==EDynamicHeatmapType::GeographicData||HeatmapType==EDynamicHeatmapType::JsonFileData"))
  130. FMargin MeshMargin;
  131. /*
  132. * Generate heatmap mesh based on this altitude
  133. */
  134. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters", meta=(EditConditionHides,EditCondition = "(HeatmapType==EDynamicHeatmapType::GeographicData||HeatmapType==EDynamicHeatmapType::JsonFileData)"))
  135. double HeatmapAltitude;
  136. /**
  137. * Multiplier of origin texture pixel value.
  138. * Heat value gets to maximum value faster if this value set to a higher value.
  139. */
  140. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters")
  141. float LerpScale;
  142. /*
  143. * Control the height offset scale in heatmap material.
  144. * Heatmap mesh will be higher at heat value points if this value is larger.
  145. */
  146. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters")
  147. float HeightScale;
  148. /*
  149. * Control the total opacity of the heatmap material.
  150. * This value should be 0 to 1.
  151. */
  152. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters")
  153. float Opacity;
  154. /*
  155. * Control the opacity of this heatmap material when heat value is zero .
  156. */
  157. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters")
  158. float ZeroValueOpacity;
  159. /*
  160. * Control the influence radius of single heat value point.
  161. * Area around heat value point gets higher if this value is larger.
  162. * This value should not be too large because calculation time will increase rapidly.
  163. */
  164. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters")
  165. int32 InfluenceSize;
  166. /**
  167. * Control the emissive strength of the heatmap color.
  168. */
  169. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Parameters")
  170. float EmissiveStrength;
  171. /*
  172. * Control the influence rate change of area around heat value point.
  173. * Manipulate this curve to control the pattern of heatmap.
  174. */
  175. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Curves")
  176. UCurveFloat* InfluenceCurve;
  177. /*
  178. * Control influence factor of heat value.
  179. * Influence area gets bigger when heat value increase.
  180. */
  181. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Curves")
  182. UCurveFloat* InfluenceFactorCurve;
  183. #pragma endregion
  184. #pragma region CreationMethods
  185. /**
  186. * Create heatmap with a gray scale texture.
  187. * 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.
  188. * @param texture gray scale texture input
  189. * @param mesh_size generated heatmap size
  190. * @param bUpdateMesh whether to update generated mesh or only update other settings
  191. * @param bRecreateMesh whether to regenerate heatmap mesh
  192. */
  193. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
  194. void CreateWithGrayScaleTexture(UTexture2D* texture, FVector2D mesh_size, bool bUpdateMesh, bool bRecreateMesh);
  195. /**
  196. * Create with a map with texture coordinate point as keys and heat value as value.
  197. * For example, set texture_size to (1024,1024), keys of map should be in 0~1023, and values of map should be 0~1.
  198. * @param map texture coordinate point - heat value map to input
  199. * @param mesh_size generated heatmap size
  200. * @param texture_size generated texture size
  201. * @param bUpdateMesh whether to update generated mesh or only update other settings
  202. * @param bRecreateMesh whether to regenerate heatmap mesh
  203. */
  204. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
  205. void CreateWithTextureCoordPointMap(const TMap<FVector2D, float> &map, FVector2D texture_size, FVector2D mesh_size, bool bUpdateMesh, bool bRecreateMesh);
  206. /**
  207. * Create with a texture coordinate point map datatable.
  208. * @param DataTable texture coordinate point - heat value data table
  209. * @see CreateWithTextureCoordPointMap
  210. */
  211. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
  212. void CreateWithTextureCoordPointMapDataTable(UDataTable* DataTable, FVector2D texture_size, FVector2D mesh_size, bool bUpdateMesh, bool bRecreateMesh);
  213. /**
  214. * Use a map with geographic point (longitude, latitude) for keys and heat value(0 to 1) to create a heatmap.
  215. *
  216. * @param map geographic point - heat value map to input
  217. * @param bUpdateMesh whether to update generated mesh or only update other settings
  218. * @param bRecreateMesh whether to regenerate heatmap mesh
  219. */
  220. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
  221. void CreateWithGeographicData(const TMap<FVector, float> &map, bool bUpdateMesh, bool bRecreateMesh);
  222. /**
  223. *
  224. * @param DataTable geographic point - heat value data table to input
  225. * @see CreateWithGeographicData
  226. */
  227. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
  228. void CreateWithGeographicDataTable(UDataTable* DataTable, bool bUpdateMesh, bool bRecreateMesh);
  229. /**
  230. * Create heatmap with a json file. The json file stores longitude, latitude and heat value data.
  231. * Input different params according to the field name and field type of json file.
  232. * These params can be stored in a FJsonConfig object. @see CreateWithJsonFile_Config
  233. *
  234. * @param FilePath .json file path to load
  235. * @param bRelativePath is path relative to project root
  236. * @param bUpdateMesh whether to update generated mesh or only update other settings
  237. * @param bRecreateMesh whether to regenerate heatmap mesh
  238. * @param LngName longitude field name
  239. * @param LatName latitude field name
  240. * @param ValueName heat value field name
  241. * @param bStringCoord whether longitude and latitude string value or double value
  242. * @param bStringValue whether heat value string value or double value
  243. */
  244. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
  245. void CreateWithJsonFile(const FString& FilePath, bool bRelativePath, bool bUpdateMesh, bool bRecreateMesh, const FString& LngName, const FString& LatName, const FString& ValueName, bool bStringCoord, bool bStringValue);
  246. /**
  247. * Create heatmap with a json file and configuration.
  248. * @param Config controls how to load the json file
  249. * @see CreateWithJsonFile
  250. */
  251. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
  252. void CreateWithJsonFile_Config(const FString& FilePath, bool bRelativePath, bool bUpdateMesh, bool bRecreateMesh, FJsonConfig Config);
  253. /**
  254. * Create heatmap with a hgt file (a DEM data format file)
  255. * 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).
  256. *
  257. * @param FilePath .hgt file path to load
  258. * @param bRelativePath is path relative to project root
  259. * @param mesh_size generated heatmap size
  260. * @param bUpdateMesh whether to update generated mesh or only update other settings
  261. * @param bRecreateMesh whether to regenerate heatmap mesh
  262. */
  263. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Creation")
  264. void CreateWithHgtFile(const FString& FilePath, bool bRelativePath, FVector2D mesh_size, bool bUpdateMesh = true, bool bRecreateMesh = true);
  265. #pragma endregion
  266. #pragma region UpdateMethods
  267. /**
  268. * Change the segmentation number of the gerenated mesh.
  269. *
  270. * @param segment how many segmentations does the mesh has, must be integer number
  271. */
  272. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
  273. void UpdateMapSegment(FVector2D segment);
  274. /**
  275. * Update the size of generated mesh.
  276. *
  277. * @param size size of generated mesh
  278. */
  279. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
  280. void UpdateMeshSize(FVector2D size);
  281. /**
  282. * Add point to existing TextureCoordPointMap without regenerating mesh.
  283. *
  284. * @param pos texture coordinate position
  285. * @param value heat value of the new point
  286. * @param bUpdate whether to update effect at once, set to false to improve performance during adding a lot of points at once
  287. */
  288. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
  289. void AddTextureCoordValue(const FVector2D &pos, float value, bool bUpdate);
  290. /**
  291. * Delete a point from existing TextureCoordPointMap without regenerating mesh.
  292. *
  293. * @param pos texture coordinate position
  294. * @param bUpdate whether to update effect at once, set to false to improve performance during adding a lot of points at once
  295. */
  296. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
  297. void DeleteTextureCoordValue(const FVector2D& pos, bool bUpdate);
  298. UFUNCTION(BlueprintPure, Category="DynamicHeatmap|Manipulate")
  299. const TMap<FVector2D, float> & GetTextureCoordPointMap() { return TextureCoordPointMap; };
  300. /**
  301. * Update influence size of single data point
  302. *
  303. * @param size radius of influence area
  304. */
  305. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
  306. void UpdatePointInfluenceSize(int32 size);
  307. /**
  308. * Update generated heatmap according to creation type and properties been set.
  309. *
  310. * @param bUpdateMesh whether to update generated mesh or only update other settings
  311. * @param bRecreateMesh whether to regenerate heatmap mesh
  312. */
  313. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
  314. void UpdateHeatmap(bool bUpdateMesh, bool bRecreateMesh);
  315. /**
  316. * Update origin heat value multiplier.
  317. *
  318. * @param scale origin heat value multiplier
  319. */
  320. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
  321. void UpdateLerpScale(float scale);
  322. /**
  323. * Update material height scale.
  324. *
  325. * @param scale material height scale
  326. */
  327. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
  328. void UpdateHeightScale(float scale);
  329. /**
  330. * Update total opacity of heatmap.
  331. *
  332. * @param value total opacity of heatmap
  333. */
  334. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
  335. void UpdateOpacity(float value);
  336. /**
  337. * Update the opacity where heat value is zero.
  338. *
  339. * @param value opacity where heat value is zero
  340. */
  341. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
  342. void UpdateZeroValueOpacity(float value);
  343. /**
  344. * Update the emissive strength of heatmap.
  345. *
  346. * @param value emissive strength
  347. */
  348. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
  349. void UpdateEmissive(float value);
  350. /**
  351. * Update all material parameters.
  352. */
  353. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Manipulate")
  354. void UpdateMaterialParameters();
  355. /**
  356. * Editor method to update heatmap effect.
  357. * @see UpdateHeatmap
  358. */
  359. UFUNCTION(BlueprintCallable, CallInEditor, Category="DynamicHeatmap")
  360. void RefreshHeatmap();
  361. /**
  362. * Editor method to update material parameters.
  363. * @see UpdateMaterialParameters
  364. */
  365. UFUNCTION(BlueprintCallable, CallInEditor, Category="DynamicHeatmap")
  366. void RefreshMaterial();
  367. protected:
  368. void UpdateGeneratedMesh(FVector2D mesh_Size, bool bRecreate);
  369. #pragma endregion
  370. #pragma region UtilMethods
  371. public:
  372. /**
  373. * Convert a geographic location to unreal position.
  374. * Override this method to adapt to cesium plugin.
  375. *
  376. * @param location FVector storing longitude, latitude and altitude
  377. * @return corresponding unreal position
  378. */
  379. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Calculation")
  380. virtual FVector ConvertGeoGraphicToEngine(FVector location);
  381. /**
  382. * Compute leftupcorner transform to calculate relative position to heatmap actor origin
  383. * Override this method to adapt to cesium plugin.
  384. *
  385. * @param MinLng minimum longitude of heatmap area span
  386. * @param MaxLat maximum latitude of heatmap area span
  387. */
  388. UFUNCTION(BlueprintCallable, Category="DynamicHeatmap|Calculation")
  389. virtual void ComputeLeftUpCornerESUTransform(float MinLng, float MaxLat);
  390. /**
  391. * Shift a heatmap actor local space position by (longitude, latitude).
  392. * Override this method to adapt to cesium plugin.
  393. *
  394. * @param LocalOriginPos a heatmap actor local space position
  395. * @param LngShift longitude value to shift
  396. * @param LatShift latitude value to shift
  397. * @return heatmap actor local space position after shifting
  398. */
  399. virtual FVector ComputeGeoShift(const FVector& LocalOriginPos, double LngShift, double LatShift);
  400. protected:
  401. TMap<FVector2D, float> ConvertGeoValueMapToUnrealValueMap(const TMap<FVector, float>& map);
  402. bool LoadJsonFileToGeographicData(const FString& Fullpath, TMap<FVector, float> &OutMap, const FString& LngName, const FString& LatName, const FString& ValueName, bool bStringCoord, bool bStringValue);
  403. TMap<FVector, float> LoadDataTableToGeographicData(UDataTable* DataTable);
  404. TMap<FVector2D, float> LoadDataTableToTextureCoordPointMap(UDataTable* DataTable);
  405. static bool CheckFileExists(const FString& FunctionName, const FString& Fullpath);
  406. static FString GetFullpath(const FString& RelativePath);
  407. TArray<FColor> LoadHgtFile(const FString & Fullpath);
  408. TArray<FColor> GetColorDataFromTextureCoordPointMap(const TMap<FVector2D, float> &map, FVector2D texture_size, int32 influenceSize);
  409. UTexture2D* CreateTexture(const FVector2D& texture_size, const TArray<FColor>& colorArr);
  410. #pragma endregion
  411. protected:
  412. UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="DynamicHeatmap|Data")
  413. UMaterialInstanceDynamic* Material;
  414. UPROPERTY(BlueprintReadWrite, Category="DynamicHeatmap|Data")
  415. UProceduralMeshComponent* ProceduralMapMesh;
  416. TMap<FVector2D, float> TextureCoordPointMap;
  417. TMap<FVector, float> GeographicData;
  418. FVector2D GeographicSize;
  419. FTransform LeftUpCornerESUTransform;
  420. UPROPERTY()
  421. AGeoReferencingSystem* GeoReferencing;
  422. AGeoReferencingSystem* GetGeoReferencing();
  423. };