Procedural Mesh C++, Perlin Noise, Infinite Terrain Math Question

Hello!

I have been attempting to design a function to create an infinite terrain.

I created a Procedural Mesh that loads a grid of verticeses around the player’s location and am trying to iterate through it with PerlinNoise3D but I can’t seem to line up the mathematics to keep the environment static (I must have the player location offset disproportionate to the vertices index.

My function to determine the z float for each vertice I thought would be something like:

float PerlinFloat = FMath::PerlinNoise3D(FVector(PlayerLoc.X + x * spacing - ((width * spacing) / 2), PlayerLoc.Y + y * spacing - ((width * spacing) / 2), 0));

I’ve also tried several other functions proportioning the vertice index, player position and grid spacing.

Anyone know what I’m missing? I’m almost thinking to write my own form of sudo perlin noise.

Thank you in advance.

You are using 3D noise for grid line ? Maybe 2D noise, The third cord is the noise it’s self in 2D, so you plan X,Y outside the perlin noise factor to draw a grid line first then you fill it with noise, since the grid line is defined first maybe this way you can pull off what you want. You plot X,Y then draw Z there (noise).
On a grid line you plot X-Y, (where to plot), then Z to draw the noise at the X-Y you chose, so Z is the noise Variable and X,Y is perhaps your looping system. In this case the Z has all the noise (x,y) in it from perlin noise lib.

So think of it this way, you have an x and a y on the grid system where you create the grid line, then you got the Z where you plot noise on the X-y you build, but this Z (the noise) contains it’s own x,Y to draw noise at the other x-y you created (the grid line) So you have an X-Y and then this determins where you are going to plot your X,Y from the noise. So it’s an X-Y (your noise) representing Z inside the X-Y(your grid line). An X,Y inside an X-Y how about that.

You would have to figure out how to extend it infinite I guess, so it draws a radius then stops then you move it draws more and so on.

Also your noise function is a bit funny, it’s missing the Z cord, it’s " FMath::PerlinNoise3D" but you only have X,Y there for data variable, I take it zero is the Z but it has undefined value.

You only use 3d noise when you are building 3d objects, like cubes, shapes that are objects.

2 Likes

Even with PerlinNoise2D I get the same outcome of the noise shifting when the player moves causing the terrain to change shape.

I’m fairly certain it has to do with not adjusting the PlayerLocation vector to be proportionate to the grid’s spacing but I haven’t been able to solve for the proper function.

So when you move terrains distorts around the player ? So you want the terrain to change only at start time around the player and then as he moves out of that area change no more, and remain static ? You can use the loop system if you know where it is spawned and specify a section of the mesh where it distorts.

I don’t really understand what you are trying to do. You say load a grid of vertices around the player location, meaning it’s a distortion of terrain where he is, but then you say you don’t want to change and you want everyting to be static.

float PerlinFloat = FMath::PerlinNoise3D(FVector(PlayerLoc.X + x * spacing - ((width * spacing) / 2), PlayerLoc.Y + y * spacing - ((width * spacing) / 2), 0));

“PlayerLoc”, is this from a library or is it a variable made by you, it represents the player location on the X axis I take it * spacing, spacing towards what, spacing between parcels, quads on the grid or between the distortion and player. I don’t think anyone can help you if you don’t explain your variables inside your code, where you made them, and the code view is very little.

2 Likes

Thank you for helping with this.

To clarify here is all the relevant code:

`

FVector PlayLoc = GetWorld()->GetFirstPlayerController()->GetPawn()->GetActorLocation();


for (int32 y = 0; y < height; y++)
{
	for (int32 x = 0; x < width; x++)
	{ 

		float PerlinFloat = FMath::PerlinNoise2D(FVector2D(PlayLoc.X / spacing  + x * spacing - (width * spacing) / 2,  PlayLoc.Y / spacing + y * spacing - (width * spacing) / 2));

		Vertices.Add(FVector(PlayLoc.X + x * spacing - ((width * spacing) / 2), PlayLoc.Y + y * spacing - ((width * spacing) / 2), PerlinFloat * 350));

	}
}

`

This creates a grid of vertices surrounding the player. Height width and spacing of the grid are set in editor.

What I meant by static and terrain changes is that the terrain loads with noise but when the player moves the entire terrain starts changing shape. So I’m thinking it’s caused by the theta in PlayerLocation being improportionate to my grid vertices.

Well yea, you have a nested loop, one loop inside the other for creating a grid line.
You got your Vertice array that you add inside PlayerLoc.X PlayerLocY, and at the end on the Z you add your perlin noise * 350 ? why *350 this can have a huge magnitude.

So PlayerLocX + x so it’s your player location + counting x on the grid, that is not good. So what you are going to get inside your Vertex Possition Array is your player location all over the grid line, each vertex point you add in floats will contain your x grid line that you are using to build the grid + that(playerLoc.x and y) . So it is what I was saying, build an independent grid line first, you are building your grid line with player location embeded in it, each possition of vertexes will contain + player location offseting it while you roam around.

There for why it constantly get’s distorted because it constantly adds the player position distorting it. So you have to rethink maybe and build the grid line first, and then make another section you know but with the same lod number, same section number and modify it then with player location.

1 Like

Oh that souds like a great approach, I’ll give it a shot! Thank you!

The 350 would be z range since the Perlin function outputs -1 - 1

Thanks again!

You could try to tweak your player var based on some condition too if you must have it embeded with the construction of the grid.

Use a bool maybe to turn player location on and off and it is only on when it’s in a spot, then if it’s not there it’s off and player location value is +0 and nothing is added.

Or a condition based on a negative operator.
If player location not there condition (excetera)
{ player location = 0; }
and var is changed to 0.

The smart way to do this is to make a copy of player location variable that does not affect player actual location and use that in your loop sintax. So the copy is for when you set it to zero not to affect the actual location of the player and this new variable handles adding or not adding to your grid line offset.

Now in your loop CopyVariablePlayerlocation.x will equal to zero, then nothing additional will be added.

If the condition is broken and player is at that spot then the value will add in the array, if not it will add +0 to array meaning nothing in addition.