diff --git a/Content/BP_BigIslandGenerator.uasset b/Content/BP_BigIslandGenerator.uasset index d380e2919cab7345c230a7f07e8bcbe8706f3f01..4657c0d6b0b7d647d6876ea12fb891b9b03d61f5 100644 GIT binary patch literal 34051 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 qKrse#AuM@n0;p60X#{t^kgWzCK?neD?%AmT diff --git a/Content/BP_IslandGenerator.uasset b/Content/BP_IslandGenerator.uasset index cd7533639e9e1a4ced4ef75d20618d4d877ab304..16bd38d11da9acb4af08b00e82b4b61279bb8842 100644 GIT binary patch delta 3984 zcmdn7iShnU#t9ihDRvADtPBhce))N+3=9k`4AUo8Sy(!XFfiyaFfbJIGcY8|FfcGO zFfjPaGBAY7GBBjdGB6m=zg*RsTs4n$Swm?=UJSSn3v*Kl$f5Inpcuol9`{!z;qv#N6QZQc&X$+P)QSa1IS|37?k1HUw5#N-eB(vvUq zTQJ6fSd7_VG6zg{Pfif%W~`r_ARx`y3?|zrI|v%HUi<(5zyIV0esR{T|NsAQn7lzy zob}89|Nke0S#SUU|DQW~gJAMxeIXt}EvT=!p|t;G10iY604VS7|Ns9Jp=_9nKq&vt z|Ns9pCQlF&H@yA-|Nkt<7e+iWR_5c6>P$mNt0|UbZC#5esF2WEhZT8PKS3cAso0<}|rlLO?VOoXsF^sfIdz_2dN-!D8V^8f!r2GcYiy z`GGZhOA3faAV~*9r58;ukPH?pg1Q4_nm!kV^ECjhQCdocNhNx+qf{D`M>IHmUP}px zH6R%Ui=@2h$%4{BV$DcW&mcxIR6%s^mKG3eN0P3FN+-ljeki?;m5+gefqU{4nLUh= zn*(LD_$MDXC}LEY+@Pa4IoeQxQ4!3l*X5YJ)X<4h3C!a(vY2eBr!-mKm}7Fb5f`Hh zSoE>J7^CXs4;t>1?R7XNA2qUIRGZwOqsd;vkj9Y9kUn{zzUt(wI%bR-VAb*Z9Ft9T zH6}M2C{3={<#2XouwZayFlBIOaAj~|umZE37+e@k8B7`6z|fGvoxzI1lEIL{iNT4% zoxz2{iNTV=nE@nj%D~8=1vdA!t{bB^nANSpH#t!+j8O;drvG|&jJja)czuJ(jz&s? ztPG4`=*N)6P{_c@pbu6Da=WL21)~92?P3F&&4$KmY?Ggwn=l(Qm`tv-P!%_3FlA6; z&|y$wFlI1gP-3tGv&<*&v(=q^-ilAtn85-n527KmmQWEx1_P)L69$9HT$ZZLCJcs? z514~!qsdX0(!3@N#&8uTlkeCRPR_MRnw)FFH@V$fi_vuQChOOe^({3fAGLYH4RePH zgW2RQwnbi<(5MAb;H0LY0Ae!0#IOAS{~weTK!Q0S0-C77Oi&3w5zJy>$eCPVC&HLH zxz)~|7nZX?#lhss7wyzFVa9d22Pe2UK-m%`(KVUHQ4=m&3=(1h#ZREOh#cOi zoHW_dRh%(ra)+Y^W6tD_jv8XgP|XY=+clt^%*pQ^b@U>kJV7Yk3r;-B?@sUA7WaF zvp8PUBqq;s=75-}2aEqcs0kR6BE-PJ;0lwR{NCA&v3qi$zs6)g7lC+~W~eknBb0$* z2&hGr4wZxj7A$6AioxLvDxX1d2&!m>Cii=bb2BiwK{Z0`Wp@?OLbeybozU2fbTxuH zdyA_8FS7Q`$roM4IbkB1lRvtKGiFZqbhBj4oZReY0*^14BVs}E;whX?V}eCP5XD=zn@2WNm$SO2iU|W-*s1D%mg`~F>~@n5$(xN9Wwb5ha|F2P=0nC%1bmGJ+#)vb{SG zG+BM~7GTVr%{uE$}Q&x>pdh(h8iOEYtMeyjrX9BwUS6D#_pm1_v zxDI3H~mn!d2l_0w|1NF$7|(fe3J&cPCtiF=z76a2dv)$zlmwUj11(E0MQGT;$~|zcEX=^bpbs?@CIL@bAW39X4mNAe0|4+u3IqTE delta 3804 zcmcb=lX1r;#t9ihYIY0^tPBhce))N+3=9k`3{xgnSy(cQFfiyaFfbVNGcYL2FfcGO zFfj1TGBAkCGBBviGB7;h*!||er<3PYLqVVHUl%rk z|NsAAZF3~!L-xsGoc)`Batg6*mgMVTWDK6Xk6)TG1Vm0=$Zs;4SHOlbX0o1uG-D>1 z%mR}gljjL^GuBR?Cm_w(2qs%5*9l59`hv*GwSp3?SO5S2UpM)kpg8N7|Ns9_0JGly z|NlRG@;kv~SzoAQuKoZ2Ukl3ShSGkM^Ms@)=L&IT-u?goe>_waCK~|d-}(Rle;Skx zlM96MZ~y=QzXZyL$pu0AxBmbCUk+t+Lg~E87e$08^9plV=0Qb36f=lmU|@i&g7QHW z3y46Lo9rhn&6qbiOIRAk40d#NP(Fy_01+r=>;s!|OIW%d*&Q$+U~>l#ni&mH{`LR= z{}(~oU;qFA4`nhiF)%RnLOGx`q5@@uQXP~Dq9)%Hk)QlqL~Qa(5fvscyU71SYI;IM}ZiA}B)Rbe!pJWn*8DbHnczL?WwPcZ?}2_Qp2>KGUp)#V znJ&13b!Ll8O_mi`VEO>#s)=Po)q$L41!a4JjnD_auVFLXkAqfDC6~V3_0!*4Qa2AR2}w z9SoJ`o4igkSgZi*2#{$q(6~+v0BektQemnM2RnbYloiuL2on^hn$iMdbx20S;_!I* zWPj-(u|_1RXHfGmBXs|i77%MeQc?|7vNHl~m$yt4D=5M6O}-?vhf#WSzibx& zllSVIF)B=+prSZg)WCpIadLpFrn3=)6N52>1%n}j34Yl^_b7%oG$rOa_?v zmH+?$gQ6ZJm^FE#orqi?h{?dfkOifoi5`;1(cz9=HW2~*uVd856AECWNs{z{M}0|Nt0y%UsQ22wv+*+G`EX|kh( zj37*BF;qTla-M?>W7gzu2bp>d2S5A&|9>1zA(V#u=JEgk|0|$^7&;&P|Nnn7F3Cs# z|NqZ{N+v*Q0S1Q2YL0w@u#hQ*ig!$Qb##Kenhz@4K6!?trXI{Mg-}rpSAeQEl(=E+ zpPU#Y&X_e>#z})QYqG18hFBt0GXp5pHK3gI$<0nWjNy|vIEjnFLKIv~heH)~Oup-6 zAPAFEhKja<1KZ45SrS$Nz*K;WH;|%9lP`)WFxG&gO_hP6!5-!XGms=w^oc|H5EEZG zi{mv>VzPk?2gFn(WK+ALreFk&5Ca2)D@<~7vx^yH$7BUJ4NYM?`4ug9q`Vh!_ZJ;A z%a{Ul9#knqJ(Q6(`GBhkW9noDS8*|z;otxS6`PQf&ev5HV(8@At^%US2B8}QiIKOi zMqu?8C^-&UA1L=tfjR&to<6zNEu1lZ@?AGe#`MYJ?k4a!af7Oi2E~bc6qE;ZEIbvz z`TzevtQ7`J3b4pxFoNoW*_J%n(LsV0)Xqx*v3La-85okFYQO>L^PE{-%G>_6$M#D< z%-fddEP?3+DT3Jv3ZL8k!q2lq&p3B~k!?`lX5WuZY;vK80%JPJ`Cw9ea-KKm1NzMrgzw*=hg|CUE8g% zf(%6$im;g8b@=Ju2;SMkUB3oKXoYSJEd-`zSI(q7M|2DA6~$ z%SV7Qee!G{Yw295Yd{pZp~h$cVuC_r@<$&D#_Y)#MZjS?InGyuv1_ulza%)EVWFMp z%_#y31oViWT<5PM=>jzhRyv@hRZh4ECnxxc7~%90tlb4mVyHej=Lho1eLrg~Zmaay zWP~JTP*VvK76IrhH;?Ka)FYQc_J(sV<#5|YBKgrE{M1zAPv&S0O^926qTk|X26I4|NpDQBquM3mSOCi zyf@mEb0Sm>T#`&yj*(zYoNN;#!HaBY6}0}UjM1=zm1Ur0%plCbz@QH`044!)BUlI| LiEPTjX03SuM$P9H diff --git a/Source/PolygonalMapGenerator/Private/IslandMap.cpp b/Source/PolygonalMapGenerator/Private/IslandMap.cpp index 48f1aee..83a26b7 100644 --- a/Source/PolygonalMapGenerator/Private/IslandMap.cpp +++ b/Source/PolygonalMapGenerator/Private/IslandMap.cpp @@ -151,7 +151,7 @@ void AIslandMap::GenerateIsland_Implementation() { river_t[i] = spring_t[i]; } - Rivers->assign_s_flow(s_flow, Mesh, t_downslope_s, river_t); + Rivers->assign_s_flow(s_flow, CreatedRivers, Mesh, t_downslope_s, river_t); #if !UE_BUILD_SHIPPING finishedTime = FDateTime::UtcNow(); @@ -181,31 +181,8 @@ void AIslandMap::GenerateIsland_Implementation() difference = finishedTime - startTime; startTime = finishedTime; UE_LOG(LogMapGen, Log, TEXT("Generated map biomes in %f seconds."), difference.GetTotalSeconds()); -#endif - - Polygons.Empty(Mesh->NumSolidRegions); - Polygons.SetNumZeroed(Mesh->NumSolidRegions); - for (FPointIndex r = 0; r < Mesh->NumSolidRegions; r++) - { - Polygons[r].Biome = r_biome[r]; - Polygons[r].Vertices = Mesh->r_circulate_t(r); - for (FTriangleIndex t : Polygons[r].Vertices) - { - if (!t.IsValid()) - { - continue; - } - 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()); + UE_LOG(LogMapGen, Log, TEXT("Total map generation time: %f seconds."), completedTime.GetTotalSeconds()); #endif // Do whatever we need to do when the island generation is done @@ -217,6 +194,30 @@ void AIslandMap::OnIslandGenComplete_Implementation() // Do nothing by default } +TArray& AIslandMap::GetVoronoiPolygons() +{ + if (VoronoiPolygons.Num() == 0) + { + VoronoiPolygons.SetNumZeroed(Mesh->NumSolidRegions); + for (FPointIndex r = 0; r < Mesh->NumSolidRegions; r++) + { + VoronoiPolygons[r].Biome = r_biome[r]; + VoronoiPolygons[r].Vertices = Mesh->r_circulate_t(r); + for (FTriangleIndex t : VoronoiPolygons[r].Vertices) + { + if (!t.IsValid()) + { + continue; + } + FVector2D point2D = Mesh->t_pos(t); + float z = t_elevation.IsValidIndex(t) ? t_elevation[t] : -1000.0f; + VoronoiPolygons[r].VertexPoints.Add(FVector(point2D.X, point2D.Y, z * 10000)); + } + } + } + return VoronoiPolygons; +} + TArray& AIslandMap::GetWaterRegions() { return r_water; diff --git a/Source/PolygonalMapGenerator/Private/IslandMapUtils.cpp b/Source/PolygonalMapGenerator/Private/IslandMapUtils.cpp index e717fa1..9d3e3b1 100644 --- a/Source/PolygonalMapGenerator/Private/IslandMapUtils.cpp +++ b/Source/PolygonalMapGenerator/Private/IslandMapUtils.cpp @@ -259,20 +259,27 @@ void UIslandMapUtils::DrawDelaunayFromMap(AIslandMap* Map) { return; } - DrawDelaunayMesh(Map, Map->Mesh, Map->r_elevation, Map->s_flow, Map->r_biome); + DrawDelaunayMesh(Map, Map->Mesh, Map->r_elevation, Map->s_flow, Map->CreatedRivers, Map->t_elevation, Map->r_biome); } void UIslandMapUtils::DrawVoronoiFromMap(class AIslandMap* Map) { - DrawVoronoiMesh(Map, Map->Polygons); + if (Map == NULL) + { + return; + } + DrawVoronoiMesh(Map, Map->Mesh, Map->GetVoronoiPolygons(), Map->s_flow, Map->CreatedRivers, Map->t_elevation); } -void UIslandMapUtils::DrawDelaunayMesh(AActor* Context, UTriangleDualMesh* Mesh, const TArray& r_elevation, const TArray& s_flow, const TArray& r_biome) +void UIslandMapUtils::DrawDelaunayMesh(AActor* Context, UTriangleDualMesh* Mesh, const TArray& RegionElevations, const TArray& SideFlow, const TArray& Rivers, const TArray &TriangleElevations, const TArray& RegionBiomes) { if (Context == NULL || Mesh == NULL) { return; } +#if !UE_BUILD_SHIPPING + FDateTime startTime = FDateTime::UtcNow(); +#endif UWorld* world = Context->GetWorld(); const TArray& _halfedges = Mesh->GetHalfEdges(); @@ -293,31 +300,33 @@ void UIslandMapUtils::DrawDelaunayMesh(AActor* Context, UTriangleDualMesh* Mesh, 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; + float pZCoord = RegionElevations.IsValidIndex(first) ? RegionElevations[first] : -1000.0f; + float qZCoord = RegionElevations.IsValidIndex(second) ? RegionElevations[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); - } + FLinearColor color = FMath::Lerp(RegionBiomes[first].DebugColor.ReinterpretAsLinear(), RegionBiomes[second].DebugColor.ReinterpretAsLinear(), 0.5f); + DrawDebugLine(world, pVector, qVector, color.ToFColor(false), false, 999.0f); } } + +#if !UE_BUILD_SHIPPING + FDateTime finishedTime = FDateTime::UtcNow(); + FTimespan difference = finishedTime - startTime; + UE_LOG(LogMapGen, Log, TEXT("Drawing delaunay map took %f seconds."), difference.GetTotalSeconds()); +#endif + + DrawRivers(Context, Mesh, Rivers, SideFlow, TriangleElevations); } -void UIslandMapUtils::DrawVoronoiMesh(AActor* Context, const TArray& Polygons) +void UIslandMapUtils::DrawVoronoiMesh(AActor* Context, UTriangleDualMesh* Mesh, const TArray& Polygons, const TArray& SideFlow, const TArray& Rivers, const TArray& TriangleElevations) { if (Context == NULL) { return; } +#if !UE_BUILD_SHIPPING + FDateTime startTime = FDateTime::UtcNow(); +#endif UWorld* world = Context->GetWorld(); for (int i = 0; i < Polygons.Num(); i++) @@ -342,6 +351,54 @@ void UIslandMapUtils::DrawVoronoiMesh(AActor* Context, const TArray& Rivers, const TArray& SideFlow, const TArray &TriangleElevations) +{ + if (Context == NULL || Mesh == NULL) + { + return; + } + +#if !UE_BUILD_SHIPPING + FDateTime startTime = FDateTime::UtcNow(); +#endif + + UWorld* world = Context->GetWorld(); + for (FRiver river : Rivers) + { + for (int i = 0; i < river.RiverTriangles.Num() - 1; i++) + { + FTriangleIndex t1 = river.RiverTriangles[i]; + int32 flow = SideFlow[river.Downslopes[i]]; + + FVector2D first2D = Mesh->t_pos(t1); + float z1 = TriangleElevations.IsValidIndex(t1) ? TriangleElevations[t1] : -1000.0f; + FVector first3D = FVector(first2D.X, first2D.Y, z1 * 10000); + + FTriangleIndex t2 = river.RiverTriangles[i + 1]; + FVector2D second2D = Mesh->t_pos(t2); + float z2 = TriangleElevations.IsValidIndex(t2) ? TriangleElevations[t2] : -1000.0f; + FVector second3D = FVector(second2D.X, second2D.Y, z2 * 10000); + + DrawDebugLine(world, first3D, second3D, FColor::Blue, false, 999.0f, (uint8)'\000', 100.0f * flow); + } + } + +#if !UE_BUILD_SHIPPING + FDateTime finishedTime = FDateTime::UtcNow(); + FTimespan difference = finishedTime - startTime; + UE_LOG(LogMapGen, Log, TEXT("Drawing rivers took %f seconds."), difference.GetTotalSeconds()); +#endif + } void UIslandMapUtils::GenerateMesh(class AIslandMap* Map, UProceduralMeshComponent* MapMesh, float ZScale) diff --git a/Source/PolygonalMapGenerator/Private/Rivers/IslandRivers.cpp b/Source/PolygonalMapGenerator/Private/Rivers/IslandRivers.cpp index d180479..381216f 100644 --- a/Source/PolygonalMapGenerator/Private/Rivers/IslandRivers.cpp +++ b/Source/PolygonalMapGenerator/Private/Rivers/IslandRivers.cpp @@ -60,43 +60,50 @@ 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 +FRiver 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; + FRiver river; + FSideIndex lastS = FSideIndex(); while(true) { - FSideIndex s = t_downslope_s[RiverTriangle]; + 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; + } + FSideIndex s = t_downslope_s[RiverTriangle]; if (!s.IsValid()) { + // Hit the coastline; add the last triangles + s = Mesh->s_opposite_s(lastS); + if (s.IsValid()) + { + s_flow[s]++; + river.Add(RiverTriangle, s); + } break; } s_flow[s]++; + river.Add(RiverTriangle, s); + processedSlopes.Add(RiverTriangle); + 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; + lastS = s; } return river; } -void UIslandRivers::AssignSideFlow_Implementation(TArray& s_flow, UTriangleDualMesh* Mesh, const TArray& t_downslope_s, const TArray& river_t) const +void UIslandRivers::AssignSideFlow_Implementation(TArray& s_flow, TArray& Rivers, UTriangleDualMesh* Mesh, const TArray& t_downslope_s, const TArray& river_t) const { if (Mesh) { @@ -105,7 +112,7 @@ void UIslandRivers::AssignSideFlow_Implementation(TArray& s_flow, UTriang s_flow.SetNumZeroed(Mesh->NumSides); for (int i = 0; i < river_t.Num(); i++) { - CreateRiver(river_t[i], s_flow, Mesh, t_downslope_s); + Rivers.Add(CreateRiver(river_t[i], s_flow, Mesh, t_downslope_s)); } } else @@ -119,7 +126,7 @@ TArray UIslandRivers::find_spring_t(UTriangleDualMesh* Mesh, con return FindSpringTriangles(Mesh, r_water, t_elevation, t_downslope_s); } -void UIslandRivers::assign_s_flow(TArray& s_flow, UTriangleDualMesh* Mesh, const TArray& t_downslope_s, const TArray& river_t) const +void UIslandRivers::assign_s_flow(TArray& s_flow, TArray& Rivers, UTriangleDualMesh* Mesh, const TArray& t_downslope_s, const TArray& river_t) const { - AssignSideFlow(s_flow, Mesh, t_downslope_s, river_t); + AssignSideFlow(s_flow, Rivers, Mesh, t_downslope_s, river_t); } \ No newline at end of file diff --git a/Source/PolygonalMapGenerator/Public/IslandMap.h b/Source/PolygonalMapGenerator/Public/IslandMap.h index 662a4f6..90ad6b1 100644 --- a/Source/PolygonalMapGenerator/Public/IslandMap.h +++ b/Source/PolygonalMapGenerator/Public/IslandMap.h @@ -74,6 +74,11 @@ protected: UPROPERTY() TArray river_t; + // Note -- will be compiled when GetVoronoiPolygons is first called. + // This will take a long time to compile and use a lot of memory. Use with caution! + UPROPERTY() + TArray VoronoiPolygons; + public: // The random seed to use for the island. UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "RNG") @@ -121,8 +126,8 @@ public: UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Map") const UIslandWater* Water; - UPROPERTY(VisibleInstanceOnly, BlueprintReadWrite, Category = "RNG") - TArray Polygons; + UPROPERTY(VisibleInstanceOnly, BlueprintReadWrite, Category = "Map") + TArray CreatedRivers; UPROPERTY(BlueprintAssignable) FOnIslandGenerationComplete OnIslandGenerationComplete; @@ -144,6 +149,11 @@ protected: virtual void OnIslandGenComplete_Implementation(); public: + // WARNING: This will take a long time to compile and will use a lot of memory. + // Use with caution! + UFUNCTION() + TArray& GetVoronoiPolygons(); + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Water") TArray& GetWaterRegions(); UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Procedural Generation|Island Generation|Water") diff --git a/Source/PolygonalMapGenerator/Public/IslandMapUtils.h b/Source/PolygonalMapGenerator/Public/IslandMapUtils.h index 8339f32..2da2f2a 100644 --- a/Source/PolygonalMapGenerator/Public/IslandMapUtils.h +++ b/Source/PolygonalMapGenerator/Public/IslandMapUtils.h @@ -52,6 +52,27 @@ struct POLYGONALMAPGENERATOR_API FIslandShape } }; +USTRUCT(BlueprintType) +struct POLYGONALMAPGENERATOR_API FRiver +{ + GENERATED_BODY() +public: + TArray RiverTriangles; + TArray Downslopes; + +public: + void Add(FTriangleIndex Triangle, FSideIndex Downslope) + { + RiverTriangles.Add(Triangle); + Downslopes.Add(Downslope); + } + + int32 Length() const + { + return RiverTriangles.Num(); + } +}; + USTRUCT(BlueprintType) struct POLYGONALMAPGENERATOR_API FBiomeBias { @@ -152,12 +173,16 @@ public: static FBiomeData GetBiome(const UDataTable* BiomeData, bool bIsOcean, bool bIsWater, bool bIsCoast, float Temperature, float Moisture); UFUNCTION(BlueprintCallable, Category = "Procedural Generation|Island Generation|Debug") static void DrawDelaunayFromMap(class AIslandMap* Map); - UFUNCTION(BlueprintCallable, Category = "Procedural Generation|Island Generation|Debug") + //UFUNCTION(BlueprintCallable, Category = "Procedural Generation|Island Generation|Debug") + UFUNCTION() 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); + static void DrawDelaunayMesh(AActor* Context, UTriangleDualMesh* Mesh, const TArray& RegionElevations, const TArray& SideFlow, const TArray& Rivers, const TArray &TriangleElevations, const TArray& RegionBiomes); + //UFUNCTION(BlueprintCallable, Category = "Procedural Generation|Island Generation|Debug") + UFUNCTION() + static void DrawVoronoiMesh(AActor* Context, UTriangleDualMesh* Mesh, const TArray& Polygons, const TArray& SideFlow, const TArray& Rivers, const TArray& TriangleElevations); UFUNCTION(BlueprintCallable, Category = "Procedural Generation|Island Generation|Debug") - static void DrawVoronoiMesh(AActor* Context, const TArray& Polygons); + static void DrawRivers(AActor* Context, UTriangleDualMesh* Mesh, const TArray& Rivers, const TArray& SideFlow, const TArray &TriangleElevations); UFUNCTION(BlueprintCallable, Category = "Procedural Generation|Island Generation") static void GenerateMesh(class AIslandMap* Map, UProceduralMeshComponent* MapMesh, float ZScale); diff --git a/Source/PolygonalMapGenerator/Public/Rivers/IslandRivers.h b/Source/PolygonalMapGenerator/Public/Rivers/IslandRivers.h index 10e6ffe..9665245 100644 --- a/Source/PolygonalMapGenerator/Public/Rivers/IslandRivers.h +++ b/Source/PolygonalMapGenerator/Public/Rivers/IslandRivers.h @@ -20,8 +20,12 @@ #include "CoreMinimal.h" #include "Engine/DataAsset.h" + #include "PolygonalMapGenerator.h" #include "TriangleDualMesh.h" + +#include "IslandMapUtils.h" + #include "IslandRivers.generated.h" /** @@ -49,10 +53,10 @@ 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 FRiver 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; + virtual void AssignSideFlow_Implementation(TArray& s_flow, TArray& Rivers, UTriangleDualMesh* Mesh, const TArray& t_downslope_s, const TArray& river_t) const; public: /** @@ -63,8 +67,8 @@ public: UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Procedural Generation|Island Generation|Rivers") TArray FindSpringTriangles(UTriangleDualMesh* Mesh, const TArray& WaterRegions, const TArray& TriangleElevations, const TArray& TriangleSideDownslopes) const; UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Procedural Generation|Island Generation|Rivers") - void AssignSideFlow(UPARAM(ref) TArray& SideFlow, UTriangleDualMesh* Mesh, const TArray& TriangleSideDownslopes, const TArray& RiverTriangles) const; + void AssignSideFlow(UPARAM(ref) TArray& SideFlow, UPARAM(ref) TArray& Rivers, UTriangleDualMesh* Mesh, const TArray& TriangleSideDownslopes, const TArray& RiverTriangles) const; TArray find_spring_t(UTriangleDualMesh* Mesh, const TArray& r_water, const TArray& t_elevation, const TArray& t_downslope_s) const; - void assign_s_flow(TArray& s_flow, UTriangleDualMesh* Mesh, const TArray& t_downslope_s, const TArray& river_t) const; + void assign_s_flow(TArray& s_flow, TArray& Rivers, UTriangleDualMesh* Mesh, const TArray& t_downslope_s, const TArray& river_t) const; };