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

The problem with this was the wavelength was too short for my mesh
I Haven’t come back to this in a while but, if my theory is correct, make sure that the wavelength is half the distance between two bones.
because the wavelength was too short, there’d be waves that werent showing up, creating a fractal like effect. (You can see this in the gifs in my post you linked)
you could probably get this code working if you tuned the wavelength properly.
also the code has to be adjusted to be in a loop to go through all the bones, don’t put a script under each bone, but I think you know that.
(also make sure the bones are alligned within a grid)

Hey, thank you so much! Ill definitely give this try. However I might go with another method like @nicemike40 posted just because it might look and perform better. Quick question: In the method that you created is there away to easily add* some rotation? I mean like the boat/(floatingPart) going up and down the wave and rocking/tilting up/down.

I was trying to figure out floatation in my last post and found out the flaw with my setup (the one I mentioned above)
if you had, say a boat, and you wanted it to rotate, then you could sample four points around the boat, and generate the rotation with that. You’d have to come up with a way to determine the rotation of the boat from those points, which is what I haven’t figured out yet.

Ok i might mess around with it a little later. Thanks! :+1: (Probably wont be able to respond to any more reply’s until 3:00 CDT)

goodluck
I’ll be getting to water soon in my own project too, so if I get a working version I’ll condense it down into a module and post it publicly.

1 Like

How would i do this:

  1. Instead, we can calculate which grid position we’re at to figure out what box we’re in, and then we can figure out which of the two triangles in that box that we’re in.

Sorry for not being very responsive, it’s the weekend! :slight_smile:

I can go into more detail later but:

  • my first attempt at solving this was slightly wrong. We still need to figure out the grid (so that we can easily lookup which vertices are next to which others), but the part you quoted won’t work
  • this is because gerstner waves can move vertices side to side as well as up/down. So a simple “what grid square am I in” won’t really work
  • I’ll have to think about how to solve it. Maybe some octree based solution like @tyridge77 did
  • if you just want a quick and easy solution I would do what @TheCursedSpud suggested and make a few vertical raycasts to sample the slope easily. Raycasts aren’t too expensive

Sadly raycasts don’t work on deformable meshes in roblox at the moment.
You’d have to generate the info on whether or whether not your point is below the water, and how far below it is, etc.

1 Like

Good that means all this work is at least necessary :slight_smile:

What would be the best option then?

so I started work on the module, Wave(alphav1).rbxm (18.1 KB)
is my current version of it, you use it by adding a localscript somewhere, requiring it, then calling the ClientInit function. You also have to set the objectvalue “WaterFolder” to a folder in workspace. (the value is parented to the module)

Wave:ClientInit({RenderDistance = 1, WaterHeight = 0, Gravity = 0.5, Steepness = 0.3})

these are the settings I am using for it atm, they work just fine.
-note- don’t make RenderDistance higher than 1 unless you want to experience pain.
current problems with the module:
→ poorly optimized
→ seams appear between waterplanes
→ my loading system for the waterplanes (which is supposed to make a square of them around you) sometimes doesn’t put you at the middle of the square
→ currently don’t know how to make the wavedirection change dynamically with my current setup.
I’ll be pushing forward with this, but I have no idea why there are seams and the loading system messing up.

1 Like

ok, so I fixed the seams, and I found out that changing the wavedirection dyamically would be really hard with this algorithm I’m using, so I found a better setup with my values that just makes the waves look nicer.


here is a quick clip of me running through it.
I still have to optimize stuff and fix the loading system misplacing the middle.

1 Like

Wave(alphav2).rbxm (18.4 KB)
my final version before I go to sleep.
I still haven’t fixed the loading system yet but I know how, just too tired to do it right now.
you can just call the init function without giving it any parameters and it’ll use it’s own default parameters (would recommend to use those)
Still haven’t come up with a working way to optimize the positioning of bones, I tried to only move the bones that are: near camera, or within view of the camera with some slack. But I think the built in function for this was poorly optimized itself as this was laggier than it is without it. Either that or I screwed it up really badly somehow.

2 Likes

Again sorry for the lack of replies, it’s a busy week :slight_smile:

Don’t know if I have time to get super deep into it but @TheCursedSpud seems to be running with it!

As far as determining what triangle you’re in, I’ve thought about it a bit.

Regardless of how you do it, you’ll need data on which points make up polygons. We basically have this already with the Gridify function.

I think I would do this:

  1. Get a set of a bunch of triangles close to your position. Your first implementation can just be looping through all the points and finding the ones closest. Other faster options for the future are:

    • If your points are always in a regular grid, you can just do some simple division to get the current row/column (approximately, because the points will have moved slightly).
    • If your points are not in a grid—for instance they might be more dense closest to the camera—you’ll need to put their initial positions in an octree or kd tree or something so you can lookup approximately which points are near you.
  2. Once you have a set of triangles that you might be over, you can do fine-grained tests to see which one you’re actually on top of

  3. Once you have the triangle you’re on top of, it’s pretty easy to check if you’re above or below it, and to project your position downwards or upwards onto the triangle surface to get the “where to float” position

It also wouldn’t be a bad idea to crack open some of those links you first posted of other’s implementations to see how they did it! I would, I just don’t have a whole lot of time free to do it sadly!

1 Like

Maybe a hint at how to optimize the bones?

1 Like

So I’ve fixed the issues with the plane loader placing the middle incorrectly (turns out I had actually fixed it in a test at first, but forgot to add that to the main command before deleting the test) And now I’m trying the approach SelDraken linked to with only rendering squares of bones within view of camera, kind of like a chunking system.
Using nikemike40’s Gridify function to generate a base grid that can be used on all planes (as they are the same) I then cut these up into nine squares and I check each of these, if any of their middle positions is within view of the camera I then add all the bones within that square to a table of bones.
problems: it doens’t work at all, it only works on the first square in each plane, and it’s lagging even worse now.
code:

local ValidBones = {}
		
		for i, Plane in ipairs(WaterFolder:GetChildren()) do
			for Top = 0, 2 do
				for Side = 0, 2 do
					--//Calculate middle of square
					local Corner1 = {Column = (11*Side)+1, Row = (11*Top)+1}
					local Corner2 = {Column = 11*(Side+1), Row = 11*(Top+1)}
					local Corner1Pos = BasePositions[PlaneGrid[Corner1.Column][Corner1.Row].Name]+Plane.Position
					local Corner2Pos = BasePositions[PlaneGrid[Corner2.Column][Corner2.Row].Name]+Plane.Position
					local MiddlePos = (Corner1Pos/2)+(Corner2Pos/2)
					
					--//Getting the required info for next part
					local ScreenSize = Camera.ViewportSize
					local MinBounds = -(ScreenSize/4)
					local MaxBounds = ScreenSize+(ScreenSize/4)
					local ViewPoint = Camera:WorldToScreenPoint(MiddlePos)
					
					--//If the point is within bounds of the screen, or near the camera, then we will add all of the squares bones to ValidBones.
					if ViewPoint.X > MinBounds.X and ViewPoint.X < MaxBounds.X and ViewPoint.Y > MinBounds.Y and ViewPoint.Y < MaxBounds.Y or (MiddlePos-Camera.CFrame.Position).Magnitude <= 400 then
						for Column = 1, 11 do
							for Row = 1, 11 do
								table.insert(ValidBones, Plane[PlaneGrid[Column][Row].Name])
							end
						end
					end
				end
			end
		end

I have no idea why this is breaking.
here is a clip of what it looks like:

@nicemike40 @TheCursedSpud and everybody else responding to this topic: Thank you guys so much! I will be experimenting over the next few days and see what i can do based on the code, ideas, and the methods you guys came up with! Thank you! I will most likely be back for more help lol.

Here, these are the final optimizations I could come up with that (mostly) worked without causing any visual glitches.
Wave(alphav3).rbxm (18.9 KB)
I’m gonna take a break from this and go back to working on my game. Good luck to you and your watery journey.

1 Like

hey question, is there any way to make a texture world aligned instead of it being aligned to the instance it’s on?
I know I can do math with the uv offsets but I’ve found doing that every frame lags like hell

1 Like

alrighty, so basically, I moved away from a chunking system, and did a bunch of dark magic to make a single plane that follows the character. You call the function the same way as you did before Wave2(beta-v1).rbxm (20.3 KB)
(upload://9QyCz0DGOzLr803AnxFBGPcsyc3.rbxm) (20.3 KB)
I also giga optimized it, a l o t, you’ll probably get little lagspikes every once in a while but that should be it.


(from my pov) I had a friend here running the game on their 6 gb old phone, and they weren’t crashing somehow.

1 Like