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

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!

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

Man thanks! Ill take a look at this and see how you did all this… Is this public? As in would you care if i maybe use some/all of it for just for the pre-alpha testing of my game?

ye idc if you use it or not
I’m planning on when I finish the module to post it publicly anyways
–side note, you can’t use surface appearances with the plane because of stoopid boblex no let me change the offset on a surface appearance, but you can change the texture to another texture or remove it entirely (if you remove the texture entirely you’d have to go into the module and delete all the references to the variable “Texture” aswell as the variable itself)

1 Like

Ok cool thanks! Ill probably just use/look at how you made the plane follow the character. Man that’s a bummer about the Surface appearance…

1 Like

Yeah, I have an idea or two for how I could do it still with a chunking system while still being as efficient as it is now, but I’ll only be trying that stuff when I come back around to working on water in my game.
When I do that, I’ll post my progress here again.

How exactly do you set this up in studio, it’s a cool addition to my Harbor game I just don’t know how exactly to make it work.

I’m actually working on a better version of the module at the moment,
It’s still a prototype but I can post it here if you want?
(It has a built in tutorial on how to setup)
It supports Surface Appearances too, and is even more optimized than that one.
It has an almost working floatation system, but you probably don’t need that yet.
Also you can setup that one by adding a folder under workspace, then going to the object value “WaterFolder” under the module, and setting it’s value to the folder.
Then you require the module and call the ClientInit() function from a local script, you only wanna call it once so put the local script in StarterPlayerScripts

Alright thank you, looking forward to your released version.

If you can post the better version that’d be much appreciated tho. Thank you!

1 Like

I posted the current prototype here along with the only problems it has rn
I’m currently trying to come up with solutions to the problems.

1 Like

Im still having a very hard time with this. Has anybody figured out the best way to do it?

If not what would be a good temporary solution?

1 Like