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