Where do I even start with a Gerstner wave floating system?

The Title says it all!

How would I go about getting an object to float on Gerstner Waves.
I have made my gerstner waves by following this tutorial here

What I have tried
I have tried the code here and got a very weird glitchy result. Even when I got the code running semi-correctly I could tell that was not really what I wanted.

What I want
I’m looking for mainly the basics of how to do this and not really looking for full pieces of code. If full code is provided it will (obviously) make my task much easier. And of course I would love for my end result to be like @tyridge77’s System , @RawEggTheGreatIX 's System or this System (I forgot who made it)

Thanks in advance! :smiley:

(This is my first post don’t be to hard on me lol)

3 Likes

I think the main issue with your old code is that the gernster wave formula doesn’t just return a new Y value. It also returns new X and Z values. When you ignore the X and Z values, it will appear out of sync.

dump your existing code here, I’ll try to see what the issue might be

Thank you so much for the reply! The issue is that I never really made any code… because I have no knowledge to go about doing it.
However I did find some code from @TheCursedSpud here that kind of worked here it is:

function GerstnerWave(SamplePosition,Wavelength,Direction,Steepness,Gravity,SampleTick)
	local k = (2 * math.pi) / Wavelength
	local a = Steepness/k
	local d = Direction.Unit
	local c = math.sqrt(Gravity / k)
	local f = k * d:Dot(Vector2.new(SamplePosition.X,SamplePosition.Z)) - c * SampleTick
	local cosF = math.cos(f)

	--Displacement Vectors
	local dX = (d.X * (a * cosF))
	local dY = a * math.sin(f)
	local dZ = ( d.Y * (a * cosF))
	return Vector3.new(dX,dY,dZ)
end

local RunService = game:GetService("RunService")
RunService.Heartbeat:Connect(function()
	local Height1 = GerstnerWave(script.Parent.Position,10.0,Vector2.new(0,1),5.0,2.0,tick()).Y
	local Height2 = GerstnerWave(script.Parent.Position,10.0,Vector2.new(1,0),5.0,2.0,tick()+1).Y
	local NewHeight = (Height1/2)+(Height2/2)
	script.Parent.Position = Vector3.new(script.Parent.Position.X,NewHeight,script.Parent.Position.Z)
end)

Thank you for the reply! Yes I believe you are right. And again I do not want to take credit for work that is not mine all credit for the old code goes to @TheCursedSpud .

can you post video/gif of the waves?

Thank you for the reply! Yes here is a video:

How would I go about including said values?

sorry but Im having a hard time understanding the problem. The waves seem to deform properly. Is there a specific behavior you had in mind? If so what is it.

Ok so the problem is: I cant figure out how to script a buoyancy or floating system (Idk if this helps but it is for boats). I have found a method (the code above) And it did not work super great… Im looking for some help for just the basics on how to do this if and if im still stuck I might need some more help later.

1 Like

For each part that you want to float, calculate the wave height at the position of that part. This would be the same thing that you have in your Heartbeat handler.

Then, if your part is above that point, don’t do anything. If it’s below that point, add a BodyForce or something.

Thank you so much! Thats a really good idea but I have a question… So if im being honest i dont really understand why that heartbeat handler even works… If possible could you show me some example code? (excluding variables and the body force idea you had(i could add that later)

So the GerstnerWave function takes in a position (+some wave control variables), and returns the height at that position.

Sort of like if you put in a latitude and longitude into your GPS and it told you the elevation.

You didn’t say, but I’m assuming you have a grid of Bone objects inside your mesh object that defines the ocean surface. If you move those bones around, the surface of the ocean would follow.

Heartbeat runs every frame. So every frame, for every bone, it:

  1. Calls the GerstnerWave function to ask “what height should the ocean be at this position?”
  2. Moves the bone vertically to match that height.

Thank you so much! Thats probably the best explanation i have heard! And yes i should have mentioned earlier i am using bones…

So in a sense how would i “grab” the nearest bones position in a floating/bouncy script?
Next would i take that position and find the average of where the floating part should be?

Sorry for asking so many questions lol.

You have two options here.

I’m assuming you have a mesh plane made of triangles, and a bone at each vertex.

Option 1. Interpolate positions from neighboring bones.

First, figure out which triangle (mesh face) you’re on or above. Get the positions for the three vertices of that triangle, either by finding the bones associated with the vertices, or by recomputing their heights. The exact details depend on your exact setup, and whether or not you have an easy way to associate bones with grid positions.

Second, once you have the three bones closest to you (or at least their heights), you can interpolate between their heights based on your exact position within their triangle. This is just a little math. It’s a weighted average of the three points.

Option 2 is easier but may give imperfect results if your bones are spaced out really far.

Just call your wave function, but pass it your (the buoyant part’s) position instead of a bone’s. It gives you the height of the water at that point.

I say it might give you imperfect results, because the bones are connected with straight triangles rather than the smooth underlying curves.

1 Like

Hey thank you! Option 2 works but… Its kind of out of sync and stuff. So if I’m going to do this I should probably take the time to just try Option 1. One question: how would I find what Bones the Floating part is above in the first place? Again sorry for so many questions mesh deformation and working with bones is all new to me.

Well, that depends.

Are your bones organized in any way? I mean, if I asked you to give me the bone in row 7, column 12, could you tell me easily?

Or are they all just named “Bone” and tossed into the same parent?

If the latter—are they at least evenly spaced in a grid?

They are all evenly spaced and numbered.

How are they numbered? Are they named with their row and column? Are they at least named in spatial order (e.g. left to right, top to bottom)?

So… No they are not ordered under columns but just numbered under the Plane itself.
I just realized they are kinda random???
Although they are numbered as far as Can tell they are random… You would think bone 1 would be closest to 0 right? well not in my case. The nearest bone to 0 is 35. The bones appear to start on the x axis from right to left.