Using .Noise to generate 'Hill'?

I’m trying to use .Noise to generate a Hill using the below code:

if Selection ~= nil then
	for __,i in (self.Terrain:GetChildren(...)) do
		local Distance = (Selection.Position - i.Position).Magnitude
		if Distance < 20 then
			local Noise = math.noise(i.Position.X/NOISE_SPACE, i.Position.Y, i.Position.Z/NOISE_SPACE)
			i.Position = Vector3.new(i.Position.X, i.Position.Y + Noise * NOISE_SIZE, i.Position.Z)
		end
	end
end

However I get some undesired results:

The code itself works for generating the terrain shown however for some reason it won’t create the ‘bump’?
Does anyone have any suggestions.

This is an example of what I wish to achieve:

1 Like

Definitely shouldn’t be using math.noise for this, after this seems to be more like Blender’s proportional editing, where parts closer to the part being raised get raised more than parts further away from it. The code would look more like:

if Selection ~= nil then
	for __, i in (self.Terrain:GetChildren(...)) do
		local Distance = (Selection.Position - i.Position).Magnitude
		if Distance < 20 then
            -- Raise height is just how far the center part moves
			local falloff = RaiseHeight / Distance -- You can change the falloff to be whatever you want
			i.Position = Vector3.new(i.Position.X, i.Position.Y + falloff, i.Position.Z)
		end
	end
end
2 Likes

Thanks for the reply!
I still seem to be having issues such as the initial Part disappearing:

1 Like

Ahh, division by zero error. Oops.

if Selection ~= nil then
	for __, i in (self.Terrain:GetChildren(...)) do
		local Distance = (Selection.Position - i.Position).Magnitude
		if Distance < 20 then
            -- Raise height is just how far the center part moves
			local falloff = if distance ~= 0 then RaiseHeight / Distance else RaiseHeight -- You can change the falloff to be whatever you want
            --Assumes distance > 1, use a bump function if not
			i.Position = Vector3.new(i.Position.X, i.Position.Y + falloff, i.Position.Z)
		end
	end
end

Bump function

2 Likes

Brilliant so far! Thank you!
Final issue I run into is the speed difference - I assume this is because it’s going beyond the magnitude so certain parts start moving. Is there any way of clamping it so the Parts move regardless / at a similar rate?

1 Like

It wouldn’t really make sense for them to go at the same speed, as they’re travelling different distances in the same time. If you want the other parts to be closer to the center part, just tack on a scalar at the front.

if Selection ~= nil then
	for __, i in (self.Terrain:GetChildren(...)) do
		local Distance = (Selection.Position - i.Position).Magnitude
		if Distance < 20 then
            -- Raise height is just how far the center part moves
			local falloff = if distance ~= 0 then k * RaiseHeight / Distance else RaiseHeight -- You can change the falloff to be whatever you want
            --Assumes distance > 1, use a bump function if not
            --k can be whatever
			i.Position = Vector3.new(i.Position.X, i.Position.Y + falloff, i.Position.Z)
		end
	end
end
2 Likes

I’ve tried various different methods and still not quite at a decent place.
Does anyone have any suggestions on how I can best replicate the 2nd video?

Thank you

I think you want both a more gradual falloff with distance, but also probably you only want to consider distance in the horizontal direction, not Y axis, otherwise the number of nearby tiles being affected will drop as the center block gets farther away from the rest.

The distance you want is probably:

local Distance = ((Selection.Position - i.Position) * Vector3.new(1,0,1)).Magnitude

In other words, just the XZ-plane distance, excluding Y.

1 Like

Brilliant! - Big fan of your work btw.
I’ve got it working utilising that line:

for Part, Size in (self.Size) do
			local Magnitude = ((Part.Position - self.Handles.Adornee.Position) * Vector3.new(1,0,1)).Magnitude
			if Magnitude < 50 then
				local goalSize = nil
				if Part == self.Handles.Adornee then
					goalSize = minimumVector(Size + toPositive(Vector3.fromNormalId(Face)) * Distance / 5)
				else
					goalSize = minimumVector(Size + toPositive(Vector3.fromNormalId(Face)) * (Distance / Magnitude))
				end
				Part.Size = goalSize
			end
		end

Only issue is the speed of which the centre one moves with the cursor.
I’ve had to dampen it using Distance / 5 otherwise the initial Part will become much larger / distanced from the other parts.

This is because constant / distance isn’t a convex bump, it’s a spike. Mathematically, it’s a surface of revolution of a hyperbola., so the slope is like 1/x:


You want more of a bump. The example you show is probably more like a Gaussian shape:

But there are lots of different “bump” functions. For things like hills, you don’t necessarily want the gradual falloff of the gaussian, you might use something like a parabola and just clamp negative values to zero, to make a hill like so:

Math gives you infinitely many interesting options that are all pretty simple functions.
You can multiply bump functions together too, like here is that parabola multipled by the square of the gaussian:

3 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.