33#include " RMC_Examples.h"
44#include " AnimatedTerrain.h"
55#include " RuntimeMeshLibrary.h"
6+ #include " ParallelFor.h"
67
78// Sets default values
8- AAnimatedTerrain::AAnimatedTerrain ()
9+ AAnimatedTerrain::AAnimatedTerrain () : bGenerated( false )
910{
1011 // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
1112 PrimaryActorTick.bCanEverTick = true ;
@@ -21,21 +22,22 @@ void AAnimatedTerrain::BeginPlay()
2122
2223void AAnimatedTerrain::Generate ()
2324{
24- Positions. Empty () ;
25- VertexData. Empty () ;
26- Triangles. Empty () ;
25+ TArray<FVector> Positions;
26+ TArray<FRuntimeMeshVertexNoPosition> VertexData;
27+ TArray<int32> Triangles;
2728
2829
2930 // Oversized bounding box so we don't have to update it
3031 BoundingBox = FBox (FVector (-HalfWidth * CellSize, -HalfWidth * CellSize, -100 ), FVector (HalfWidth * CellSize, HalfWidth * CellSize, 100 ));
3132
33+ float Scale = CellSize / 50 .0f ;
3234 // Create the vertex array
3335 for (int32 YIndex = -HalfWidth; YIndex < HalfWidth; YIndex++)
3436 {
3537 for (int32 XIndex = -HalfWidth; XIndex < HalfWidth; XIndex++)
3638 {
3739 Positions.Add (FVector (XIndex * CellSize, YIndex * CellSize, 0 ));
38- VertexData.Add (FRuntimeMeshVertexNoPosition (FVector (0 , 0 , 1 ), FRuntimeMeshTangent (-1 , 0 , 0 ), FVector2D (XIndex, YIndex)));
40+ VertexData.Add (FRuntimeMeshVertexNoPosition (FVector (0 , 0 , 1 ), FRuntimeMeshTangent (-1 , 0 , 0 ), FVector2D (XIndex * Scale , YIndex * Scale )));
3941 }
4042 }
4143
@@ -45,14 +47,17 @@ void AAnimatedTerrain::Generate()
4547
4648 // Here we're going to use a dual buffer section for performance since we'll be updating positions only each frame
4749 RuntimeMesh->CreateMeshSectionDualBuffer (0 , Positions, VertexData, Triangles, BoundingBox, false , EUpdateFrequency::Frequent);
50+
51+ bGenerated = true ;
4852}
4953
54+
5055// Called every frame
5156void AAnimatedTerrain::Tick ( float DeltaTime )
5257{
5358 Super::Tick ( DeltaTime );
5459
55- if (Positions. Num () <= 0 )
60+ if (!bGenerated )
5661 {
5762 Generate ();
5863 }
@@ -63,25 +68,31 @@ void AAnimatedTerrain::Tick( float DeltaTime )
6368 AnimationOffsetX += DeltaTime * AnimationStepX;
6469 AnimationOffsetY += DeltaTime * AnimationStepY;
6570
71+ // Start position only update
72+ TArray<FVector>& Positions = *RuntimeMesh->BeginMeshSectionPositionUpdate (0 );
6673
67- int32 Index = 0 ;
68- for (int32 YIndex = - HalfWidth; YIndex < HalfWidth; YIndex++ )
74+
75+ ParallelFor ((HalfWidth * 2 )*( HalfWidth* 2 ), [ this , &Positions](int32 Index )
6976 {
70- for ( int32 XIndex = - HalfWidth; XIndex < HalfWidth; XIndex++)
71- {
72- float Scale = FMath::Cos (XIndex + AnimationOffsetX) + FMath::Sin (YIndex + AnimationOffsetY) ;
77+ int32 PlaneWidth = HalfWidth * 2 ;
78+ int32 XIndex = Index % PlaneWidth;
79+ int32 YIndex = Index / PlaneWidth ;
7380
74- Positions[Index++]. Z = Scale * Height ;
75- }
76- }
81+ float Scale = CellSize / 50 . 0f ;
82+
83+ float HeightScale = FMath::Cos ((XIndex * Scale) + AnimationOffsetX) + FMath::Sin ((YIndex * Scale) + AnimationOffsetY);
7784
85+ Positions[Index].Z = HeightScale * Height;
7886
79- // Update positions
80- RuntimeMesh->UpdateMeshSectionPositionsImmediate (0 , Positions, BoundingBox);
87+ });
88+
89+ // Commit position only update (sends updates to GPU)
90+ RuntimeMesh->EndMeshSectionPositionUpdate (0 , BoundingBox);
8191}
8292
8393
8494
95+
8596void AAnimatedTerrain::OnConstruction (const FTransform& Transform)
8697{
8798 Generate ();
0 commit comments