diff --git a/Content/BP_BigIslandGenerator.uasset b/Content/BP_BigIslandGenerator.uasset index 3387c51f0e9ada6dd7bb99a4d723daee6f7e543a..d75036a1c569d62fbba15c804ffcc8d380f7a0c3 100644 GIT binary patch literal 24364 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 literal 30586 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 e&A!(Iq?!TG8ZBgB>OvJ`_!4wzIK^~<5 diff --git a/Source/PolygonalMapGenerator/Private/Elevation/IslandElevation.cpp b/Source/PolygonalMapGenerator/Private/Elevation/IslandElevation.cpp index 708925c..d19b532 100644 --- a/Source/PolygonalMapGenerator/Private/Elevation/IslandElevation.cpp +++ b/Source/PolygonalMapGenerator/Private/Elevation/IslandElevation.cpp @@ -73,12 +73,10 @@ void UIslandElevation::DistributeElevations(TArray &t_elevation, UTriangl if (IsTriangleOcean(t, Mesh, r_ocean)) { t_elevation[t] = -d / (float)MinDistance; - //UE_LOG(LogMapGen, Log, TEXT("Ocean triangle index %d's distance from coastline: %f; min distance: %d; elevation: %f"), t, d, MinDistance, t_elevation[t]); } else { t_elevation[t] = d / (float)MaxDistance; - //UE_LOG(LogMapGen, Log, TEXT("Land triangle index %d's distance from coastline: %f; max distance: %d; elevation: %f"), t, d, MaxDistance, t_elevation[t]); } } } diff --git a/Source/PolygonalMapGenerator/Private/IslandMap.cpp b/Source/PolygonalMapGenerator/Private/IslandMap.cpp index 22b76e4..5a3af78 100644 --- a/Source/PolygonalMapGenerator/Private/IslandMap.cpp +++ b/Source/PolygonalMapGenerator/Private/IslandMap.cpp @@ -19,7 +19,6 @@ #include "IslandMap.h" #include "DualMeshBuilder.h" #include "IslandMapUtils.h" -#include "DrawDebugHelpers.h" // Sets default values AIslandMap::AIslandMap() @@ -27,6 +26,8 @@ AIslandMap::AIslandMap() PrimaryActorTick.bCanEverTick = false; Seed = 0; NumRivers = 30; + + OnIslandGenerationComplete.AddDynamic(this, &AIslandMap::OnIslandGenComplete); } // Called when the game starts or when spawned @@ -45,6 +46,11 @@ void AIslandMap::GenerateIsland_Implementation() return; } +#if !UE_BUILD_SHIPPING + FDateTime startTime = FDateTime::UtcNow(); + FDateTime generationStartTime = startTime; +#endif + Rng = FRandomStream(); Rng.Initialize(Seed); RiverRng = FRandomStream(); @@ -59,8 +65,22 @@ void AIslandMap::GenerateIsland_Implementation() Shape.Amplitudes[i] = FMath::Pow(Persistence, i); } +#if !UE_BUILD_SHIPPING + FDateTime finishedTime = FDateTime::UtcNow(); + FTimespan difference = finishedTime - startTime; + startTime = finishedTime; + UE_LOG(LogMapGen, Log, TEXT("Initialization took %f seconds."), difference.GetTotalSeconds()); +#endif + // Generate map points - Mesh = PointGenerator->GenerateDualMesh(Rng); + Mesh = PointGenerator->GenerateDualMesh(Rng); + +#if !UE_BUILD_SHIPPING + finishedTime = FDateTime::UtcNow(); + difference = finishedTime - startTime; + startTime = finishedTime; + UE_LOG(LogMapGen, Log, TEXT("Generating points took %f seconds."), difference.GetTotalSeconds()); +#endif // Reset all arrays @@ -93,83 +113,106 @@ void AIslandMap::GenerateIsland_Implementation() r_biome.Empty(Mesh->NumRegions); r_biome.SetNumZeroed(Mesh->NumRegions); +#if !UE_BUILD_SHIPPING + finishedTime = FDateTime::UtcNow(); + difference = finishedTime - startTime; + startTime = finishedTime; + UE_LOG(LogMapGen, Log, TEXT("Resetting arrays took %f seconds."), difference.GetTotalSeconds()); +#endif + // Water Water->assign_r_water(r_water, Rng, Mesh, Shape); Water->assign_r_ocean(r_ocean, Mesh, r_water); - UE_LOG(LogMapGen, Log, TEXT("Generated map water.")); +#if !UE_BUILD_SHIPPING + finishedTime = FDateTime::UtcNow(); + difference = finishedTime - startTime; + startTime = finishedTime; + UE_LOG(LogMapGen, Log, TEXT("Generated map water in %f seconds."), difference.GetTotalSeconds()); +#endif // Elevation Elevation->assign_t_elevation(t_elevation, t_coastdistance, t_downslope_s, Mesh, r_ocean, r_water, DrainageRng); Elevation->redistribute_t_elevation(t_elevation, Mesh, r_ocean); Elevation->assign_r_elevation(r_elevation, Mesh, t_elevation, r_ocean); - UE_LOG(LogMapGen, Log, TEXT("Generated map elevation.")); +#if !UE_BUILD_SHIPPING + finishedTime = FDateTime::UtcNow(); + difference = finishedTime - startTime; + startTime = finishedTime; + UE_LOG(LogMapGen, Log, TEXT("Generated map elevation in %f seconds."), difference.GetTotalSeconds()); +#endif // Rivers spring_t = Rivers->find_spring_t(Mesh, r_water, t_elevation, t_downslope_s); - UE_LOG(LogMapGen, Log, TEXT("Created %d springs."), spring_t.Num()); UIslandMapUtils::RandomShuffle(spring_t, RiverRng); river_t.SetNum(NumRivers < spring_t.Num() ? NumRivers : spring_t.Num()); for (int i = 0; i < river_t.Num(); i++) { river_t[i] = spring_t[i]; } - UE_LOG(LogMapGen, Log, TEXT("Created %d rivers."), river_t.Num()); Rivers->assign_s_flow(s_flow, Mesh, t_downslope_s, river_t); - UE_LOG(LogMapGen, Log, TEXT("Generated map rivers.")); +#if !UE_BUILD_SHIPPING + finishedTime = FDateTime::UtcNow(); + difference = finishedTime - startTime; + startTime = finishedTime; + UE_LOG(LogMapGen, Log, TEXT("Generated %d map rivers in %f seconds."), river_t.Num(), difference.GetTotalSeconds()); +#endif // Moisture Moisture->assign_r_moisture(r_moisture, r_waterdistance, Mesh, r_water, Moisture->find_moisture_seeds_r(Mesh, s_flow, r_ocean, r_water)); Moisture->redistribute_r_moisture(r_moisture, Mesh, r_water, BiomeBias.Rainfall, 1.0f + BiomeBias.Rainfall); - UE_LOG(LogMapGen, Log, TEXT("Generated map moisture.")); +#if !UE_BUILD_SHIPPING + finishedTime = FDateTime::UtcNow(); + difference = finishedTime - startTime; + startTime = finishedTime; + UE_LOG(LogMapGen, Log, TEXT("Generated map moisture in %f seconds."), difference.GetTotalSeconds()); +#endif // Biomes Biomes->assign_r_coast(r_coast, Mesh, r_ocean); Biomes->assign_r_temperature(r_temperature, Mesh, r_ocean, r_water, r_elevation, r_moisture, BiomeBias.NorthernTemperature, BiomeBias.SouthernTemperature); Biomes->assign_r_biome(r_biome, Mesh, r_ocean, r_water, r_coast, r_temperature, r_moisture); - UE_LOG(LogMapGen, Log, TEXT("Generated map biomes.")); - - // Do whatever we need to do when the island generation is done - OnIslandGenComplete(); -} - -void AIslandMap::OnIslandGenComplete_Implementation() -{ - Draw(); -} +#if !UE_BUILD_SHIPPING + finishedTime = FDateTime::UtcNow(); + difference = finishedTime - startTime; + startTime = finishedTime; + UE_LOG(LogMapGen, Log, TEXT("Generated map biomes in %f seconds."), difference.GetTotalSeconds()); +#endif -void AIslandMap::Draw() const -{ - UWorld* world = GetWorld(); - const TArray& _halfedges = Mesh->GetHalfEdges(); - const FDualMesh& mesh = Mesh->GetRawMesh(); - const TArray& _r_vertex = Mesh->GetPoints(); - - for (FSideIndex e = 0; e < _halfedges.Num(); e++) + Polygons.Empty(Mesh->NumSolidRegions); + Polygons.SetNumZeroed(Mesh->NumSolidRegions); + for (FPointIndex r = 0; r < Mesh->NumSolidRegions; r++) { - if (e < _halfedges[e]) + Polygons[r].Biome = r_biome[r]; + Polygons[r].Vertices = Mesh->r_circulate_t(r); + for (FTriangleIndex t : Polygons[r].Vertices) { - FPointIndex first = UDelaunayHelper::GetPointIndexFromHalfEdge(mesh, e); - FPointIndex second = UDelaunayHelper::GetPointIndexFromHalfEdge(mesh, UDelaunayHelper::NextHalfEdge(e)); - - if (Mesh->r_ghost(first) || Mesh->r_ghost(second)) + if (!t.IsValid()) { continue; } - - const FVector2D p = _r_vertex[first]; - const FVector2D q = _r_vertex[second]; - float pZCoord = r_elevation.IsValidIndex(first) ? r_elevation[first] : -1000.0f; - float qZCoord = r_elevation.IsValidIndex(second) ? r_elevation[second] : -1000.0f; - FVector pVector = FVector(p.X, p.Y, pZCoord * 10000); - FVector qVector = FVector(q.X, q.Y, qZCoord * 10000); - - FLinearColor color = FMath::Lerp(r_biome[first].DebugColor.ReinterpretAsLinear(), r_biome[second].DebugColor.ReinterpretAsLinear(), 0.5f); - DrawDebugLine(world, pVector, qVector, color.ToFColor(false), false, 999.0f); + FVector2D point2D = Mesh->t_pos(t); + float z = t_elevation.IsValidIndex(t) ? t_elevation[t] : -1000.0f; + Polygons[r].VertexPoints.Add(FVector(point2D.X, point2D.Y, z * 10000)); } } + +#if !UE_BUILD_SHIPPING + finishedTime = FDateTime::UtcNow(); + difference = finishedTime - startTime; + FTimespan completedTime = finishedTime - generationStartTime; + UE_LOG(LogMapGen, Log, TEXT("Generated polygons in %f seconds. Total map generation time: %f seconds."), difference.GetTotalSeconds(), completedTime.GetTotalSeconds()); +#endif + + // Do whatever we need to do when the island generation is done + OnIslandGenerationComplete.Broadcast(); +} + +void AIslandMap::OnIslandGenComplete_Implementation() +{ + // Do nothing by default } \ No newline at end of file diff --git a/Source/PolygonalMapGenerator/Private/IslandMapUtils.cpp b/Source/PolygonalMapGenerator/Private/IslandMapUtils.cpp index 6fee837..047d7ae 100644 --- a/Source/PolygonalMapGenerator/Private/IslandMapUtils.cpp +++ b/Source/PolygonalMapGenerator/Private/IslandMapUtils.cpp @@ -17,6 +17,8 @@ */ #include "IslandMapUtils.h" #include "RandomSampling/SimplexNoise.h" +#include "DrawDebugHelpers.h" +#include "IslandMap.h" void UIslandMapUtils::RandomShuffle(TArray& OutShuffledArray, FRandomStream& Rng) { @@ -251,6 +253,97 @@ FBiomeData UIslandMapUtils::GetBiome(const UDataTable* BiomeData, bool bIsOcean, return possibleBiomes[0]; } +void UIslandMapUtils::DrawDelaunayFromMap(AIslandMap* Map) +{ + if (Map == NULL) + { + return; + } + DrawDelaunayMesh(Map, Map->Mesh, Map->r_elevation, Map->s_flow, Map->r_biome); +} + +void UIslandMapUtils::DrawVoronoiFromMap(class AIslandMap* Map) +{ + DrawVoronoiMesh(Map, Map->Polygons); +} + +void UIslandMapUtils::DrawDelaunayMesh(AActor* Context, UTriangleDualMesh* Mesh, const TArray& r_elevation, const TArray& s_flow, const TArray& r_biome) +{ + if (Context == NULL || Mesh == NULL) + { + return; + } + + UWorld* world = Context->GetWorld(); + const TArray& _halfedges = Mesh->GetHalfEdges(); + const FDualMesh& mesh = Mesh->GetRawMesh(); + const TArray& _r_vertex = Mesh->GetPoints(); + + for (FSideIndex e = 0; e < _halfedges.Num(); e++) + { + if (e < _halfedges[e]) + { + FPointIndex first = UDelaunayHelper::GetPointIndexFromHalfEdge(mesh, e); + FPointIndex second = UDelaunayHelper::GetPointIndexFromHalfEdge(mesh, UDelaunayHelper::NextHalfEdge(e)); + + if (Mesh->r_ghost(first) || Mesh->r_ghost(second)) + { + continue; + } + + const FVector2D p = _r_vertex[first]; + const FVector2D q = _r_vertex[second]; + float pZCoord = r_elevation.IsValidIndex(first) ? r_elevation[first] : -1000.0f; + float qZCoord = r_elevation.IsValidIndex(second) ? r_elevation[second] : -1000.0f; + FVector pVector = FVector(p.X, p.Y, pZCoord * 10000); + FVector qVector = FVector(q.X, q.Y, qZCoord * 10000); + + int flow = FMath::Max(s_flow[e], s_flow[UDelaunayHelper::NextHalfEdge(e)]); + if (flow == 0) + { + FLinearColor color = FMath::Lerp(r_biome[first].DebugColor.ReinterpretAsLinear(), r_biome[second].DebugColor.ReinterpretAsLinear(), 0.5f); + DrawDebugLine(world, pVector, qVector, color.ToFColor(false), false, 999.0f); + } + else + { + DrawDebugLine(world, pVector, qVector, FColor::Blue, false, 999.0f, (uint8)'\000', 100.0f * flow); + } + } + } +} + +void UIslandMapUtils::DrawVoronoiMesh(AActor* Context, const TArray& Polygons) +{ + if (Context == NULL) + { + return; + } + + UWorld* world = Context->GetWorld(); + for (int i = 0; i < Polygons.Num(); i++) + { + const FIslandPolygon& polygon = Polygons[i]; + for (int j = 0; j < polygon.VertexPoints.Num(); j++) + { + FVector point = polygon.VertexPoints[j]; + FTriangleIndex first = polygon.Vertices[j]; + FVector next; + FTriangleIndex second; + if (j == polygon.VertexPoints.Num() - 1) + { + next = polygon.VertexPoints[0]; + second = polygon.Vertices[0]; + } + else + { + next = polygon.VertexPoints[j + 1]; + second = polygon.Vertices[j + 1]; + } + DrawDebugLine(world, point, next, polygon.Biome.DebugColor, false, 999.0f); + } + } +} + void UIslandMapUtils::GenerateMapMesh(UTriangleDualMesh* Mesh, UProceduralMeshComponent* MapMesh, float ZScale, const TArray& RegionElevation) { const TArray& points = Mesh->GetPoints(); diff --git a/Source/PolygonalMapGenerator/Public/IslandMap.h b/Source/PolygonalMapGenerator/Public/IslandMap.h index 3964a65..8faf5ea 100644 --- a/Source/PolygonalMapGenerator/Public/IslandMap.h +++ b/Source/PolygonalMapGenerator/Public/IslandMap.h @@ -35,6 +35,8 @@ #include "IslandMap.generated.h" +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnIslandGenerationComplete); + UCLASS() class POLYGONALMAPGENERATOR_API AIslandMap : public AActor { @@ -87,6 +89,9 @@ public: UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Map") const UIslandWater* Water; + UPROPERTY(VisibleInstanceOnly, BlueprintReadWrite, Category = "RNG") + TArray Polygons; + UPROPERTY() TArray r_water; UPROPERTY() @@ -116,6 +121,9 @@ public: UPROPERTY() TArray river_t; + UPROPERTY(BlueprintAssignable) + FOnIslandGenerationComplete OnIslandGenerationComplete; + public: // Sets default values for this actor's properties AIslandMap(); diff --git a/Source/PolygonalMapGenerator/Public/IslandMapUtils.h b/Source/PolygonalMapGenerator/Public/IslandMapUtils.h index 33a7286..732104b 100644 --- a/Source/PolygonalMapGenerator/Public/IslandMapUtils.h +++ b/Source/PolygonalMapGenerator/Public/IslandMapUtils.h @@ -117,6 +117,19 @@ public: } }; +USTRUCT(BlueprintType) +struct POLYGONALMAPGENERATOR_API FIslandPolygon +{ + GENERATED_BODY() +public: + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + FBiomeData Biome; + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TArray VertexPoints; + UPROPERTY(VisibleAnywhere, BlueprintReadWrite) + TArray Vertices; +}; + /** * A collection of utilities used in island generation. */ @@ -137,6 +150,14 @@ public: // the FName into a GameplayTag. UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Biomes") static FBiomeData GetBiome(const UDataTable* BiomeData, bool bIsOcean, bool bIsWater, bool bIsCoast, float Temperature, float Moisture); - UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation") + UFUNCTION(BlueprintCallable, Category = "Procedural Generation|Island Generation|Debug") + static void DrawDelaunayFromMap(class AIslandMap* Map); + UFUNCTION(BlueprintCallable, Category = "Procedural Generation|Island Generation|Debug") + static void DrawVoronoiFromMap(class AIslandMap* Map); + UFUNCTION(BlueprintCallable, Category = "Procedural Generation|Island Generation|Debug") + static void DrawDelaunayMesh(AActor* Context, UTriangleDualMesh* Mesh, const TArray& RegionElevations, const TArray& SideFlow, const TArray& RegionBiomes); + UFUNCTION(BlueprintCallable, Category = "Procedural Generation|Island Generation|Debug") + static void DrawVoronoiMesh(AActor* Context, const TArray& Polygons); + UFUNCTION(BlueprintCallable, Category = "Procedural Generation|Island Generation") static void GenerateMapMesh(UTriangleDualMesh* Mesh, UProceduralMeshComponent* MapMesh, float ZScale, const TArray& RegionElevation); }; \ No newline at end of file -- 2.51.2 From bcade498bd70418721ae197db7ef100c99ad2393 Mon Sep 17 00:00:00 2001 From: Jay Stevens Date: Fri, 28 Dec 2018 17:35:48 -0800 Subject: [PATCH 2/3] Hotfix: Biome temperature/moisture not working. Also exposed the properties on IslandMap better. --- Content/BP_BigIslandGenerator.uasset | Bin 24364 -> 20615 bytes Content/BP_IslandGenerator.uasset | Bin 22878 -> 22840 bytes Content/BiomeTable.uasset | Bin 10862 -> 10862 bytes .../Private/Biomes/IslandBiome.cpp | 8 +- .../Private/IslandMap.cpp | 202 +++++++++++++++++- .../Private/IslandMapUtils.cpp | 17 +- .../Private/Moisture/IslandMoisture.cpp | 8 +- .../Public/Biomes/IslandBiome.h | 12 +- .../PolygonalMapGenerator/Public/IslandMap.h | 115 +++++++--- .../Public/IslandMapUtils.h | 3 + .../Public/Moisture/IslandMoisture.h | 12 +- 11 files changed, 324 insertions(+), 53 deletions(-) diff --git a/Content/BP_BigIslandGenerator.uasset b/Content/BP_BigIslandGenerator.uasset index d75036a1c569d62fbba15c804ffcc8d380f7a0c3..d380e2919cab7345c230a7f07e8bcbe8706f3f01 100644 GIT binary patch delta 6641 zcmZ3pkFk9r zfx$m1D>b=dDrEo9jW| z0J-$#|NsAGK@0{41|}#C5IoBmxUn*v7Z5CXby%XMBv%~|Nl84ObiP_a)Nl|V4;id zP>?=JkUo(8*d(n%lHk+@VZeM3(g;gh*z`3(lw);hGZwjAkQm6&4iE#2g-`$g|6hhf z?#ciE{~OWdU{M1~@RQKw3MMlK33I}nT`>8-h%{rtWNA_9`U0p*5CuxvAR4X?#DQW^ z9sn`1$$?TmNbcMJ|NlWW2s1MKDV}<93Y`J`9lE9WH)gUwNFS6 z-~%ax`V-`cTB!CAd$6f@#T2DLLF)_^1|{hhDEp%Q#7%Q}RQG+ObE2Ss}vH(<2fJ_3h z^FewT7#OsjLGGHICCvj?5&`ucNXZnCS_TG&S#BUDYCn*i4zi>OL_mu&Z;)RY7#Q?C zKuRaylH~zAKLn~olYxN&ghAX&U#Rm%Cr61xl$n9Vp-N!6a1o|5f2cA=1_uV1vJ((x zf8`({56UVaSA(3-16BUc7wjf22_7j>SpmwTFeT5RN`661Su3sxR{{zikSQ7Rvg&;#f zk|0GONe~UC8@fq_A2@f>rd`g5ug0Q++p)AoNJ0p3-DLJq1P?u;FC_nk5em0{5nE%eeWpbXO&1Mf1CPqeOu%;YSo5@#@_8%c z$zs-JyhaQb3`z_-3`z_}43?7%?ZhW9v*DW@XUoNCIGNwZdGZ=t0Zn753PT2S1|Wj1?CY@2-1x&8toZCy$_H{F#8sPLYsks0Tx_f`(TP- zg1Jyda-cA@nhMg-z`y{DdXS}HAy}n68O%eN2@5|^O(8M)yR(4gG&B{kR=f?!0!}xm zY$k}u2qL99J)mM;lj~e$IAIlh&*a4}cJ&odxrtC3?jTmMZx|SApb{7^hQ&CnmQsW& zgqh#~8{CV zTqWyaZnS`jLTOM!gfbB+5!T3rxewMdgxLjd5y4D!f@%k~13^r25W&E}5Co;cHca;M z;INB?iolHR1?2?fR0B#NFhww5M?e+XfqX4#4>bZNs|@9Lf@Hzf>327I$vUVgOcg95 zrcZt-s$d7sJ`4;D7`c~$p}`*JD|CxszCu{E(p?y@MG}+Wx^vVMWmzB8y|C;G4lG6Nrz^cYpu?{|{b78xk5K$s*!7jZG5I;qY}APYGNklCOV4l86} z;#Fv_x&cyzqr_5T0=|Jt}DLC%JCCSc~mYC}zs zx#9V^w1Vm>SceQ&RKT(x1FQoIYaYYQ2H6KP5E646d;}C>L7)o~M)ESOfEEV1A_CN? z1}VUd30PeXi%^)&FdIR-7+{J}1flJ630;^I&}ooXSTPLK**@98Ng+HIB!w*Q~}IP)Id@76R?B1Bps>}rE~>}onT;KNCPpDLJZZIZa)E0m@y!Qpz;Gm zb5Fh)BFqRTrCmV+Pz)J^aDnnb6{rNb8rA0d4^3wbJd+(mgeM34t2l$AHFSmbna2KE zUejOjGUwclxq?ls7it`c0$ad{#e&J_0~9BJ5arMWnQ&Ks$syi1u6~V2UD77#YnWgY zYnvPpV5F1{G8Cyn^%bp4%>eR)_T=*cs)Fc|=mv_!c$|?4GKpX$!on7REXahQ#sW%E zGJ*qCny5fR!~!Vl%#C2yg8~6mOo1@Sa1)RK17zU1q^L9%TzP{eBql3{iim+q1yHvW zqzcqm1}m|gd^${?F>&(iFipn($zP*xu!1xwO)d-*mIXDqK}p9Fq=SKh0hGg|6oQiz zb5a?=Dj1U|UkH_8l$d;hIO9dbk&OqLO4xW2Ny2I*7{Sf~7ZAkxlCf~|xoDmGa*!La z(i7IHAdx-VcWpqfAwBfL!y;t{6`VXi9!19?R^s7Qo0h71^J#fk#*k0!rc_C%|e_aODdc#R267kOV=6y5=Bd*wT~`Qh^0hbFf)!9srQ> Bfk*%V literal 24364 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 diff --git a/Content/BP_IslandGenerator.uasset b/Content/BP_IslandGenerator.uasset index e22db65626e71108f6680919116d09655e5e7286..cd7533639e9e1a4ced4ef75d20618d4d877ab304 100644 GIT binary patch literal 22840 zcmX@utTpfF|Ns9Jm>C#YnHa!;g@J+LZN`QtFP)}*;l5?K$Z@xuo)iNE!xN($8+iRY z<+sBGL6L!h!Og(j#LUgW*~HM&)y2fn(9GG{ z*woC?*}%ow!pYUh73?YyA;Q4Gz%0VRpu@nxV9d|Jpe)0{z{tSBz%R?dATGL74eX@UD*aVUX=>u8F!XV1P$gn8YjX{`!fk9h4)YU{gC^aWFu{c%N zM9;{O0i=L|q07e=mjaM0K==}qS1pJRk!4^oi3G6_`2YX^|3Ur*c}+hcKc_N1KQA%I zH?hDyH7~U&u_V7p-zhUcH`OJvB$2^2ZlaYI0|Nstg#q!N#W{(2DR8|E=aXMdApGV@B@ixLYm7+&74aRDU?eW6v+{3~dgro^nXSSR zH;m_#n3S5suw1+-UI-=>l9`v3rY28JY`)bzyUO25?9l#u*@(xUX#;Ox|#pwzTthW@oN)?hPWp~xU&Y0N7DG6N<8 zO`oYL&N+$2#SEIW3v@wFM1*^3W(vc3cBxQFWL=(lC8GcXc|oS;=jXsfLx5#N7brNB{L4~{ ziZWAD;lU~JZ9+6C`(w!!A3M@6iGobR$T0EF41Xq>Towa`Q*cRQQAv1aNd_pET=No> za#B+m_G+=Tfl^dbSY~l)VoqjNs&jsBL4ICpUJ1kMcC%Zc2y{*?Nlni$s$}?HH{~eE z#V`TC#N1SdKC=iO0R{#Jm|$>zQAuWAI)jLy+&NInfdp(xdBsFfEW=HQ2pj(U77Fq% zTsR~(w;(66B$eUHDy2gl3=9k|scDI&IVB8@|MTrY=@`n7kH-v$cxMLoGM$^CK!U4+ z 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 Zs09d8fK#CXNEX`+0mu~O00y0`3;>qxlcE3s diff --git a/Content/BiomeTable.uasset b/Content/BiomeTable.uasset index af841dbcf20958354e15d2a2c59995af958ea7ec..b0df242a7d143e818bdf33bce399d0b9d21a71e8 100644 GIT binary patch delta 66 zcmaDC@-Ae;DghtsDrfZzAN-eXtoitTZ}YT`yD}suTc}uVj*$#uoZKfOJNcQa?Bp29 Tpv^YY+KiLi)ghc~GBbDq57!(D delta 65 zcmaDC@-Ae;DuLA*Nm9oSTymPA9_Kgl>SouCyD}suY06I0WSM+XDtq%fNhU@Jck@N5 MX^b%8Ycex<0nWf1UjP6A diff --git a/Source/PolygonalMapGenerator/Private/Biomes/IslandBiome.cpp b/Source/PolygonalMapGenerator/Private/Biomes/IslandBiome.cpp index de2f6e1..5f6c538 100644 --- a/Source/PolygonalMapGenerator/Private/Biomes/IslandBiome.cpp +++ b/Source/PolygonalMapGenerator/Private/Biomes/IslandBiome.cpp @@ -39,7 +39,7 @@ void UIslandBiome::AssignCoast_Implementation(TArray& r_coast, UTriangleDu } } -void UIslandBiome::AssignTemperature_Implementation(TArray& r_temperature, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_elevation, const TArray& r_moisture, float NorthernTemperature, float SouthernTemperature) const +void UIslandBiome::AssignTemperature_Implementation(TArray& r_temperature, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_elevation, const TArray& r_moisture, float NorthernTemperature, float SouthernTemperature) const { r_temperature.Empty(Mesh->NumRegions); r_temperature.SetNumZeroed(Mesh->NumRegions); @@ -51,7 +51,7 @@ void UIslandBiome::AssignTemperature_Implementation(TArray& r_temperature } } -void UIslandBiome::AssignBiome_Implementation(TArray& r_biome, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_coast, const TArray& r_temperature, const TArray& r_moisture) const +void UIslandBiome::AssignBiome_Implementation(TArray& r_biome, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_coast, const TArray& r_temperature, const TArray& r_moisture) const { r_biome.Empty(Mesh->NumRegions); r_biome.SetNumZeroed(Mesh->NumRegions); @@ -66,12 +66,12 @@ void UIslandBiome::assign_r_coast(TArray& r_coast, UTriangleDualMesh* Mesh AssignCoast(r_coast, Mesh, r_ocean); } -void UIslandBiome::assign_r_temperature(TArray& r_temperature, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_elevation, const TArray& r_moisture, float NorthernTemperature, float SouthernTemperature) const +void UIslandBiome::assign_r_temperature(TArray& r_temperature, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_elevation, const TArray& r_moisture, float NorthernTemperature, float SouthernTemperature) const { AssignTemperature(r_temperature, Mesh, r_ocean, r_water, r_elevation, r_moisture, NorthernTemperature, SouthernTemperature); } -void UIslandBiome::assign_r_biome(TArray& r_biome, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_coast, const TArray& r_temperature, const TArray& r_moisture) const +void UIslandBiome::assign_r_biome(TArray& r_biome, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_coast, const TArray& r_temperature, const TArray& r_moisture) const { AssignBiome(r_biome, Mesh, r_ocean, r_water, r_coast, r_temperature, r_moisture); } diff --git a/Source/PolygonalMapGenerator/Private/IslandMap.cpp b/Source/PolygonalMapGenerator/Private/IslandMap.cpp index 5a3af78..48f1aee 100644 --- a/Source/PolygonalMapGenerator/Private/IslandMap.cpp +++ b/Source/PolygonalMapGenerator/Private/IslandMap.cpp @@ -215,4 +215,204 @@ void AIslandMap::GenerateIsland_Implementation() void AIslandMap::OnIslandGenComplete_Implementation() { // Do nothing by default -} \ No newline at end of file +} + +TArray& AIslandMap::GetWaterRegions() +{ + return r_water; +} + +bool AIslandMap::IsPointWater(FPointIndex Region) const +{ + if (r_water.IsValidIndex(Region)) + { + return r_water[Region]; + } + else + { + return false; + } +} + +TArray& AIslandMap::GetOceanRegions() +{ + return r_ocean; +} + +bool AIslandMap::IsPointOcean(FPointIndex Region) const +{ + if (r_ocean.IsValidIndex(Region)) + { + return r_ocean[Region]; + } + else + { + return false; + } +} + +TArray& AIslandMap::GetCoastalRegions() +{ + return r_coast; +} + +bool AIslandMap::IsPointCoast(FPointIndex Region) const +{ + if (r_coast.IsValidIndex(Region)) + { + return r_coast[Region]; + } + else + { + return false; + } +} + +TArray& AIslandMap::GetRegionElevations() +{ + return r_elevation; +} + +float AIslandMap::GetPointElevation(FPointIndex Region) const +{ + if (r_elevation.IsValidIndex(Region)) + { + return r_elevation[Region]; + } + else + { + return -1.0f; + } +} + +TArray& AIslandMap::GetRegionWaterDistance() +{ + return r_waterdistance; +} + +int32 AIslandMap::GetPointWaterDistance(FPointIndex Region) const +{ + if (r_waterdistance.IsValidIndex(Region)) + { + return r_waterdistance[Region]; + } + else + { + return -1; + } +} + +TArray& AIslandMap::GetRegionMoisture() +{ + return r_moisture; +} + +float AIslandMap::GetPointMoisture(FPointIndex Region) const +{ + if (r_moisture.IsValidIndex(Region)) + { + return r_moisture[Region]; + } + else + { + return -1.0f; + } +} + +TArray& AIslandMap::GetRegionTemperature() +{ + return r_temperature; +} + +float AIslandMap::GetPointTemperature(FPointIndex Region) const +{ + if (r_temperature.IsValidIndex(Region)) + { + return r_temperature[Region]; + } + else + { + return -1.0f; + } +} + +TArray& AIslandMap::GetRegionBiomes() +{ + return r_biome; +} + +FBiomeData AIslandMap::GetPointBiome(FPointIndex Region) const +{ + if (r_biome.IsValidIndex(Region)) + { + return r_biome[Region]; + } + else + { + return FBiomeData(); + } +} + +TArray& AIslandMap::GetTriangleCoastDistances() +{ + return t_coastdistance; +} + +int32 AIslandMap::GetTriangleCoastDistance(FTriangleIndex Triangle) const +{ + if (t_coastdistance.IsValidIndex(Triangle)) + { + return t_coastdistance[Triangle]; + } + else + { + return -1; + } +} + +TArray& AIslandMap::GetTriangleElevations() +{ + return t_elevation; +} + +float AIslandMap::GetTriangleElevation(FTriangleIndex Triangle) const +{ + if (t_elevation.IsValidIndex(Triangle)) + { + return t_elevation[Triangle]; + } + else + { + return -1.0f; + } +} + +TArray& AIslandMap::GetTriangleDownslopes() +{ + return t_downslope_s; +} + +TArray& AIslandMap::GetSideFlow() +{ + return s_flow; +} + +TArray& AIslandMap::GetSpringTriangles() +{ + return spring_t; +} + +bool AIslandMap::IsTriangleSpring(FTriangleIndex Triangle) const +{ + return spring_t.Contains(Triangle); +} + +TArray& AIslandMap::GetRiverTriangles() +{ + return river_t; +} + +bool AIslandMap::IsTriangleRiver(FTriangleIndex Triangle) const +{ + return river_t.Contains(Triangle); +} diff --git a/Source/PolygonalMapGenerator/Private/IslandMapUtils.cpp b/Source/PolygonalMapGenerator/Private/IslandMapUtils.cpp index 047d7ae..e717fa1 100644 --- a/Source/PolygonalMapGenerator/Private/IslandMapUtils.cpp +++ b/Source/PolygonalMapGenerator/Private/IslandMapUtils.cpp @@ -224,7 +224,7 @@ FBiomeData UIslandMapUtils::GetBiome(const UDataTable* BiomeData, bool bIsOcean, } else if (possibleBiomes.Num() == 0) { - UE_LOG(LogMapGen, Error, TEXT("Could not find any biomes with moisture %f!"), Moisture); + UE_LOG(LogMapGen, Error, TEXT("Could not find any biomes with moisture %f! Is ocean? %d Is coast? %d Is water? %d"), Moisture, (uint8)bIsOcean, (uint8)bIsCoast, (uint8)bIsWater); return FBiomeData(); } newPossibleBiomes.Empty(); @@ -244,7 +244,7 @@ FBiomeData UIslandMapUtils::GetBiome(const UDataTable* BiomeData, bool bIsOcean, } else if (possibleBiomes.Num() == 0) { - UE_LOG(LogMapGen, Error, TEXT("Could not find any biomes with moisture %f!"), Moisture); + UE_LOG(LogMapGen, Error, TEXT("Could not find any biomes with temperature %f! Is ocean? %d; Is coast? %d; Is water? %d; Moisture: %f"), Temperature, (uint8)bIsOcean, (uint8)bIsCoast, (uint8)bIsWater, Moisture); return FBiomeData(); } @@ -344,8 +344,21 @@ void UIslandMapUtils::DrawVoronoiMesh(AActor* Context, const TArrayMesh, MapMesh, ZScale, Map->r_elevation); +} + void UIslandMapUtils::GenerateMapMesh(UTriangleDualMesh* Mesh, UProceduralMeshComponent* MapMesh, float ZScale, const TArray& RegionElevation) { + if (Mesh == NULL || MapMesh == NULL) + { + return; + } const TArray& points = Mesh->GetPoints(); const FDualMesh& rawMesh = Mesh->GetRawMesh(); TArray vertices; diff --git a/Source/PolygonalMapGenerator/Private/Moisture/IslandMoisture.cpp b/Source/PolygonalMapGenerator/Private/Moisture/IslandMoisture.cpp index 015ccd4..19944f5 100644 --- a/Source/PolygonalMapGenerator/Private/Moisture/IslandMoisture.cpp +++ b/Source/PolygonalMapGenerator/Private/Moisture/IslandMoisture.cpp @@ -57,7 +57,7 @@ TSet UIslandMoisture::FindMoistureSeeds_Implementation(UTriangleDua return seeds; } -void UIslandMoisture::AssignRegionMoisture_Implementation(TArray& r_moisture, TArray& r_waterdistance, UTriangleDualMesh* Mesh, const TArray& r_water, const TSet& seed_r) const +void UIslandMoisture::AssignRegionMoisture_Implementation(TArray& r_moisture, TArray& r_waterdistance, UTriangleDualMesh* Mesh, const TArray& r_water, const TSet& seed_r) const { r_moisture.Empty(Mesh->NumRegions); r_moisture.SetNumZeroed(Mesh->NumRegions); @@ -102,7 +102,7 @@ void UIslandMoisture::AssignRegionMoisture_Implementation(TArray& r_moist } } -void UIslandMoisture::RedistributeRegionMoisture_Implementation(TArray& r_moisture, UTriangleDualMesh* Mesh, const TArray& r_water, float MinMoisture, float MaxMoisture) const +void UIslandMoisture::RedistributeRegionMoisture_Implementation(TArray& r_moisture, UTriangleDualMesh* Mesh, const TArray& r_water, float MinMoisture, float MaxMoisture) const { TArray land_r; for (FPointIndex r = 0; r < Mesh->NumSolidRegions; r++) @@ -129,12 +129,12 @@ void UIslandMoisture::RedistributeRegionMoisture_Implementation(TArray& r } } -void UIslandMoisture::assign_r_moisture(TArray& r_moisture, TArray& r_waterdistance, UTriangleDualMesh* Mesh, const TArray& r_water, const TSet& r_moisture_seeds) const +void UIslandMoisture::assign_r_moisture(TArray& r_moisture, TArray& r_waterdistance, UTriangleDualMesh* Mesh, const TArray& r_water, const TSet& r_moisture_seeds) const { AssignRegionMoisture(r_moisture, r_waterdistance, Mesh, r_water, r_moisture_seeds); } -void UIslandMoisture::redistribute_r_moisture(TArray& r_moisture, UTriangleDualMesh* Mesh, const TArray& r_water, float MinMoisture, float MaxMoisture) const +void UIslandMoisture::redistribute_r_moisture(TArray& r_moisture, UTriangleDualMesh* Mesh, const TArray& r_water, float MinMoisture, float MaxMoisture) const { RedistributeRegionMoisture(r_moisture, Mesh, r_water, MinMoisture, MaxMoisture); } diff --git a/Source/PolygonalMapGenerator/Public/Biomes/IslandBiome.h b/Source/PolygonalMapGenerator/Public/Biomes/IslandBiome.h index 61eadba..c7cea44 100644 --- a/Source/PolygonalMapGenerator/Public/Biomes/IslandBiome.h +++ b/Source/PolygonalMapGenerator/Public/Biomes/IslandBiome.h @@ -42,18 +42,18 @@ public: protected: virtual void AssignCoast_Implementation(TArray& r_coast, UTriangleDualMesh* Mesh, const TArray& r_ocean) const; - virtual void AssignTemperature_Implementation(TArray& r_temperature, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_elevation, const TArray& r_moisture, float NorthernTemperature, float SouthernTemperature) const; - virtual void AssignBiome_Implementation(TArray& r_biome, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_coast, const TArray& r_temperature, const TArray& r_moisture) const; + virtual void AssignTemperature_Implementation(TArray& r_temperature, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_elevation, const TArray& r_moisture, float NorthernTemperature, float SouthernTemperature) const; + virtual void AssignBiome_Implementation(TArray& r_biome, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_coast, const TArray& r_temperature, const TArray& r_moisture) const; public: UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Procedural Generation|Island Generation|Biome") void AssignCoast(UPARAM(ref) TArray& CoastalRegions, UTriangleDualMesh* Mesh, const TArray& OceanRegions) const; UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Procedural Generation|Island Generation|Biome") - void AssignTemperature(UPARAM(ref) TArray& RegionTemperatures, UTriangleDualMesh* Mesh, const TArray& OceanRegions, const TArray& WaterRegions, const TArray& RegionElevations, const TArray& RegionMoisture, float NorthernTemperature, float SouthernTemperature) const; + void AssignTemperature(UPARAM(ref) TArray& RegionTemperatures, UTriangleDualMesh* Mesh, const TArray& OceanRegions, const TArray& WaterRegions, const TArray& RegionElevations, const TArray& RegionMoisture, float NorthernTemperature, float SouthernTemperature) const; UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Procedural Generation|Island Generation|Biome") - void AssignBiome(UPARAM(ref) TArray& RegionBiomes, UTriangleDualMesh* Mesh, const TArray& OceanRegions, const TArray& WaterRegions, const TArray& CoastalRegions, const TArray& RegionTemperature, const TArray& RegionMoisture) const; + void AssignBiome(UPARAM(ref) TArray& RegionBiomes, UTriangleDualMesh* Mesh, const TArray& OceanRegions, const TArray& WaterRegions, const TArray& CoastalRegions, const TArray& RegionTemperature, const TArray& RegionMoisture) const; void assign_r_coast(TArray& r_coast, UTriangleDualMesh* Mesh, const TArray& r_ocean) const; - void assign_r_temperature(TArray& r_temperature, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_elevation, const TArray& r_moisture, float NorthernTemperature, float SouthernTemperature) const; - void assign_r_biome(TArray& r_biome, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_coast, const TArray& r_temperature, const TArray& r_moisture) const; + void assign_r_temperature(TArray& r_temperature, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_elevation, const TArray& r_moisture, float NorthernTemperature, float SouthernTemperature) const; + void assign_r_biome(TArray& r_biome, UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water, const TArray& r_coast, const TArray& r_temperature, const TArray& r_moisture) const; }; diff --git a/Source/PolygonalMapGenerator/Public/IslandMap.h b/Source/PolygonalMapGenerator/Public/IslandMap.h index 8faf5ea..662a4f6 100644 --- a/Source/PolygonalMapGenerator/Public/IslandMap.h +++ b/Source/PolygonalMapGenerator/Public/IslandMap.h @@ -41,6 +41,38 @@ UCLASS() class POLYGONALMAPGENERATOR_API AIslandMap : public AActor { GENERATED_BODY() + friend class UIslandMapUtils; + +protected: + UPROPERTY() + TArray r_water; + UPROPERTY() + TArray r_ocean; + UPROPERTY() + TArray r_coast; + UPROPERTY() + TArray r_elevation; + UPROPERTY() + TArray r_waterdistance; + UPROPERTY() + TArray r_moisture; + UPROPERTY() + TArray r_temperature; + UPROPERTY() + TArray r_biome; + + UPROPERTY() + TArray t_coastdistance; + UPROPERTY() + TArray t_elevation; + UPROPERTY() + TArray t_downslope_s; + UPROPERTY() + TArray s_flow; + UPROPERTY() + TArray spring_t; + UPROPERTY() + TArray river_t; public: // The random seed to use for the island. @@ -92,35 +124,6 @@ public: UPROPERTY(VisibleInstanceOnly, BlueprintReadWrite, Category = "RNG") TArray Polygons; - UPROPERTY() - TArray r_water; - UPROPERTY() - TArray r_ocean; - UPROPERTY() - TArray t_coastdistance; - UPROPERTY() - TArray t_elevation; - UPROPERTY() - TArray t_downslope_s; - UPROPERTY() - TArray r_elevation; - UPROPERTY() - TArray s_flow; - UPROPERTY() - TArray r_waterdistance; - UPROPERTY() - TArray r_moisture; - UPROPERTY() - TArray r_coast; - UPROPERTY() - TArray r_temperature; - UPROPERTY() - TArray r_biome; - UPROPERTY() - TArray spring_t; - UPROPERTY() - TArray river_t; - UPROPERTY(BlueprintAssignable) FOnIslandGenerationComplete OnIslandGenerationComplete; @@ -141,5 +144,57 @@ protected: virtual void OnIslandGenComplete_Implementation(); public: - void Draw() const; + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Water") + TArray& GetWaterRegions(); + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Water") + bool IsPointWater(FPointIndex Region) const; + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Ocean") + TArray& GetOceanRegions(); + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Ocean") + bool IsPointOcean(FPointIndex Region) const; + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Ocean") + TArray& GetCoastalRegions(); + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Ocean") + bool IsPointCoast(FPointIndex Region) const; + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Elevation") + TArray& GetRegionElevations(); + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Elevation") + float GetPointElevation(FPointIndex Region) const; + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Moisture") + TArray& GetRegionWaterDistance(); + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Moisture") + int32 GetPointWaterDistance(FPointIndex Region) const; + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Moisture") + TArray& GetRegionMoisture(); + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Moisture") + float GetPointMoisture(FPointIndex Region) const; + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Temperature") + TArray& GetRegionTemperature(); + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Temperature") + float GetPointTemperature(FPointIndex Region) const; + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Biomes") + TArray& GetRegionBiomes(); + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Moisture") + FBiomeData GetPointBiome(FPointIndex Region) const; + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Ocean") + TArray& GetTriangleCoastDistances(); + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Ocean") + int32 GetTriangleCoastDistance(FTriangleIndex Triangle) const; + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Elevation") + TArray& GetTriangleElevations(); + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Elevation") + float GetTriangleElevation(FTriangleIndex Triangle) const; + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Rivers") + TArray& GetTriangleDownslopes(); + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Rivers") + TArray& GetSideFlow(); + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Rivers") + TArray& GetSpringTriangles(); + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Rivers") + bool IsTriangleSpring(FTriangleIndex Triangle) const; + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Rivers") + TArray& GetRiverTriangles(); + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Rivers") + bool IsTriangleRiver(FTriangleIndex Triangle) const; }; diff --git a/Source/PolygonalMapGenerator/Public/IslandMapUtils.h b/Source/PolygonalMapGenerator/Public/IslandMapUtils.h index 732104b..8339f32 100644 --- a/Source/PolygonalMapGenerator/Public/IslandMapUtils.h +++ b/Source/PolygonalMapGenerator/Public/IslandMapUtils.h @@ -158,6 +158,9 @@ public: static void DrawDelaunayMesh(AActor* Context, UTriangleDualMesh* Mesh, const TArray& RegionElevations, const TArray& SideFlow, const TArray& RegionBiomes); UFUNCTION(BlueprintCallable, Category = "Procedural Generation|Island Generation|Debug") static void DrawVoronoiMesh(AActor* Context, const TArray& Polygons); + + UFUNCTION(BlueprintCallable, Category = "Procedural Generation|Island Generation") + static void GenerateMesh(class AIslandMap* Map, UProceduralMeshComponent* MapMesh, float ZScale); UFUNCTION(BlueprintCallable, Category = "Procedural Generation|Island Generation") static void GenerateMapMesh(UTriangleDualMesh* Mesh, UProceduralMeshComponent* MapMesh, float ZScale, const TArray& RegionElevation); }; \ No newline at end of file diff --git a/Source/PolygonalMapGenerator/Public/Moisture/IslandMoisture.h b/Source/PolygonalMapGenerator/Public/Moisture/IslandMoisture.h index dc4cb3a..c7b6847 100644 --- a/Source/PolygonalMapGenerator/Public/Moisture/IslandMoisture.h +++ b/Source/PolygonalMapGenerator/Public/Moisture/IslandMoisture.h @@ -38,18 +38,18 @@ protected: virtual TSet FindLakeshores(UTriangleDualMesh* Mesh, const TArray& r_ocean, const TArray& r_water) const; virtual TSet FindMoistureSeeds_Implementation(UTriangleDualMesh* Mesh, const TArray& s_flow, const TArray& r_ocean, const TArray& r_water) const; - virtual void AssignRegionMoisture_Implementation(TArray& r_moisture, TArray& r_waterdistance, UTriangleDualMesh* Mesh, const TArray& r_water, const TSet& r_moisture_seeds) const; - virtual void RedistributeRegionMoisture_Implementation(TArray& r_moisture, UTriangleDualMesh* Mesh, const TArray& r_water, float MinMoisture, float MaxMoisture) const; + virtual void AssignRegionMoisture_Implementation(TArray& r_moisture, TArray& r_waterdistance, UTriangleDualMesh* Mesh, const TArray& r_water, const TSet& r_moisture_seeds) const; + virtual void RedistributeRegionMoisture_Implementation(TArray& r_moisture, UTriangleDualMesh* Mesh, const TArray& r_water, float MinMoisture, float MaxMoisture) const; public: UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Procedural Generation|Island Generation|Moisture") TSet FindMoistureSeeds(UTriangleDualMesh* Mesh, const TArray& SideFlow, const TArray& OceanRegions, const TArray& WaterRegions) const; UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Procedural Generation|Island Generation|Moisture") - void AssignRegionMoisture(UPARAM(ref) TArray& RegionMoisture, UPARAM(ref) TArray& RegionWaterDistance, UTriangleDualMesh* Mesh, const TArray& WaterRegions, const TSet& MoistureSeedRegions) const; + void AssignRegionMoisture(UPARAM(ref) TArray& RegionMoisture, UPARAM(ref) TArray& RegionWaterDistance, UTriangleDualMesh* Mesh, const TArray& WaterRegions, const TSet& MoistureSeedRegions) const; UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Procedural Generation|Island Generation|Moisture") - void RedistributeRegionMoisture(UPARAM(ref) TArray& RegionMoisture, UTriangleDualMesh* Mesh, const TArray& WaterRegions, float MinMoisture, float MaxMoisture) const; + void RedistributeRegionMoisture(UPARAM(ref) TArray& RegionMoisture, UTriangleDualMesh* Mesh, const TArray& WaterRegions, float MinMoisture, float MaxMoisture) const; TSet find_moisture_seeds_r(UTriangleDualMesh* Mesh, const TArray& s_flow, const TArray& r_ocean, const TArray& r_water) const; - void assign_r_moisture(TArray& r_moisture, TArray& r_waterdistance, UTriangleDualMesh* Mesh, const TArray& r_water, const TSet& r_moisture_seeds) const; - void redistribute_r_moisture(TArray& r_moisture, UTriangleDualMesh* Mesh, const TArray& r_water, float MinMoisture, float MaxMoisture) const; + void assign_r_moisture(TArray& r_moisture, TArray& r_waterdistance, UTriangleDualMesh* Mesh, const TArray& r_water, const TSet& r_moisture_seeds) const; + void redistribute_r_moisture(TArray& r_moisture, UTriangleDualMesh* Mesh, const TArray& r_water, float MinMoisture, float MaxMoisture) const; }; -- 2.51.2 From c70db20a2a5ed407325ee5d779a97723c8701cae Mon Sep 17 00:00:00 2001 From: Jay Stevens Date: Fri, 28 Dec 2018 17:53:53 -0800 Subject: [PATCH 3/3] Separated river generation code into its own method. --- .../Private/Rivers/IslandRivers.cpp | 64 +++++++++++-------- .../Public/Rivers/IslandRivers.h | 2 + 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/Source/PolygonalMapGenerator/Private/Rivers/IslandRivers.cpp b/Source/PolygonalMapGenerator/Private/Rivers/IslandRivers.cpp index d7c33d8..d180479 100644 --- a/Source/PolygonalMapGenerator/Private/Rivers/IslandRivers.cpp +++ b/Source/PolygonalMapGenerator/Private/Rivers/IslandRivers.cpp @@ -60,6 +60,42 @@ TArray UIslandRivers::FindSpringTriangles_Implementation(UTriang return spring_t.Array(); } +TArray UIslandRivers::CreateRiver(FTriangleIndex RiverTriangle, TArray &s_flow, UTriangleDualMesh* Mesh, const TArray& t_downslope_s) const +{ + // We keep both a set and an array + // The set is for fast lookup when checking if we have already processed a point (we'll be doing this every iteration) + // The array is to keep track of the order in which we have navigated the river + TSet processedSlopes; + TArray river; + while(true) + { + FSideIndex s = t_downslope_s[RiverTriangle]; + + if (!s.IsValid()) + { + break; + } + + s_flow[s]++; + + FTriangleIndex next_t = Mesh->s_outer_t(s); + if (next_t == RiverTriangle) + { + break; + } + if (processedSlopes.Contains(RiverTriangle)) + { + UE_LOG(LogMapGen, Warning, TEXT("Tried to process a slope we've already processed once this loop! We have an infinite loop.")); + break; + } + processedSlopes.Add(RiverTriangle); + river.Add(RiverTriangle); + + RiverTriangle = next_t; + } + return river; +} + void UIslandRivers::AssignSideFlow_Implementation(TArray& s_flow, UTriangleDualMesh* Mesh, const TArray& t_downslope_s, const TArray& river_t) const { if (Mesh) @@ -69,33 +105,7 @@ void UIslandRivers::AssignSideFlow_Implementation(TArray& s_flow, UTriang s_flow.SetNumZeroed(Mesh->NumSides); for (int i = 0; i < river_t.Num(); i++) { - FTriangleIndex t = river_t[i]; - TSet processedSlopes; - for (;;) - { - FSideIndex s = t_downslope_s[t]; - - if (!s.IsValid()) - { - break; - } - - s_flow[s]++; - - FTriangleIndex next_t = Mesh->s_outer_t(s); - if (next_t == t) - { - break; - } - if (processedSlopes.Contains(t)) - { - UE_LOG(LogMapGen, Warning, TEXT("Tried to process a slope we've already processed once this loop! We have an infinite loop.")); - break; - } - processedSlopes.Add(t); - - t = next_t; - } + CreateRiver(river_t[i], s_flow, Mesh, t_downslope_s); } } else diff --git a/Source/PolygonalMapGenerator/Public/Rivers/IslandRivers.h b/Source/PolygonalMapGenerator/Public/Rivers/IslandRivers.h index da46aa8..10e6ffe 100644 --- a/Source/PolygonalMapGenerator/Public/Rivers/IslandRivers.h +++ b/Source/PolygonalMapGenerator/Public/Rivers/IslandRivers.h @@ -48,6 +48,8 @@ protected: */ UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Procedural Generation|Island Generation|Rivers") virtual bool IsTriangleWater(FTriangleIndex t, UTriangleDualMesh* Mesh, const TArray& WaterRegions) const; + UFUNCTION(BlueprintCallable, Category = "Procedural Generation|Island Generation|Rivers") + virtual TArray CreateRiver(FTriangleIndex RiverTriangle, TArray &s_flow, UTriangleDualMesh* Mesh, const TArray& t_downslope_s) const; virtual TArray FindSpringTriangles_Implementation(UTriangleDualMesh* Mesh, const TArray& r_water, const TArray& t_elevation, const TArray& t_downslope_s) const; virtual void AssignSideFlow_Implementation(TArray& s_flow, UTriangleDualMesh* Mesh, const TArray& t_downslope_s, const TArray& river_t) const;