Finding Height of Gerstner Wave At Coordinates

Started by
6 comments, last by ShawnMGS 6 years, 10 months ago

Using the GPU Gems Article https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch01.html I have implemented Gerstner Waves into UE4, I have built the function both on GPU for the tessellated mesh displacement and in code for the purpose of sampling height of the waves, but the issue I have run into is that the points by nature of the formula move away from their original points, so when using the gerstner function to get the height of a point, it is not necessarily at the point you are sampling so provides an incorrect height for that coordinate.

So somehow I need to solve for the point in the gerstner function that is actually lines up with the world position.  Ive taught myself enough to implement the waves, but i'm stuck on this solution, though I suspect there is some sort of matrix or way to take the inputs, apply the cos values and use it as a lookup for the actual point to sample.  Any ideas and help is greatly appreciated.

For Reference the Gerstner Wave Formula

013equ01.jpg

Q = Slope  
L = WaveLength  
A = Amplitude  
D = Vector2 Direction  
x = x world coordinate  
y = y world coordinate  
t = time  
Where Qi = Q/wi * A * NumWaves  
Where wi = 2pi/L  
Where phase = Speed * 2/L  

Advertisement

I remember facing this problem.  If I recall correctly it boils down to finding the inverse of a function of the form f(x) = a*x + b*cos(c*x) for which I believe there is no analytic solution.  If you find one though let me know!  

Without an analytic solution you have a couple of options.  Probably the best option is to formulate some approximation.   A simple option though is to just displace a mesh on the CPU around where you need to sample heights and use that (e.g., if you need the heights for a boat, create a "collision mesh" around the boat extending beyond the boat boundary by the maximum horizontal wave displacement). 

4 hours ago, BFG said:

I remember facing this problem.  If I recall correctly it boils down to finding the inverse of a function of the form f(x) = a*x + b*cos(c*x) for which I believe there is no analytic solution.  If you find one though let me know!  

Without an analytic solution you have a couple of options.  Probably the best option is to formulate some approximation.   A simple option though is to just displace a mesh on the CPU around where you need to sample heights and use that (e.g., if you need the heights for a boat, create a "collision mesh" around the boat extending beyond the boat boundary by the maximum horizontal wave displacement). 

Just brainstorming as I work on this.  The last part of the function that determines the height of the point is still valid since its just a simple sin wave.  So it seems like you would be able to take that and modify it by the offset being applied from the rest of the function to essentially give it a curve that matches the slope of the wave so spikes to the top and then hangs at the bottom.  Trying brute force my way through that math but perhaps it will spark someone else's smarter brain to a simple solution.

This one sort of gives me a headache because im facing into it at the moment with my game, the exact same problem.

The issue is compounded when I feed the co-ordinate results back into the same function to generate additional wave data.

Im not sure there is even a non brute force method.  My thoughts, sample in 5 points, the central point, and 4 points (1 each side of the point in the XZ and YZ planes) equal to the max distance in the plane that it can travel (I assume you use Z as your height).  Then approximate.  This ends up being 5 times more costly than a single simulation point.  But you should at the least be able to solve on a curve for x and y because you have 3 points in each plane.  And that your required X and Y co-ordinate are within the sample space.  Horrible, but my first thought to solve for now, and its an approximation of epic proportions.

Indie game developer - Game WIP

Strafe (Working Title) - Currently in need of another developer and modeler/graphic artist (professional & amateur's artists welcome)

Insane Software Facebook

We have the ability to make the sine wave that produces a good Z height.  My instinct (which is probably totally wrong) is saying if you modify the time input with another sin/cos you could use the calculated offset from the cos to determine a way to multiply the time to slow it down a the bottom of the trough and speed it up for the crest.  How to do this is beyond me, but I really feel like all the info we need is already calculated within the Gerstner Wave Function. ive tried my hand guessing formulas and methods but high school algebra didn't prepare me for this lol.  

If you want a peak wave then constrain the sine wave value returned to height > 0. This will give you a repeating arcs.  Then just use z = 1 - height to flip this.  You will get a series of u shaped waves.  You need to play with the normal but should help get you the shape you want.   I will play around with my code tonight. 

Indie game developer - Game WIP

Strafe (Working Title) - Currently in need of another developer and modeler/graphic artist (professional & amateur's artists welcome)

Insane Software Facebook

4 hours ago, ErnieDingo said:

This one sort of gives me a headache because im facing into it at the moment with my game, the exact same problem.

The issue is compounded when I feed the co-ordinate results back into the same function to generate additional wave data.

Im not sure there is even a non brute force method.  My thoughts, sample in 5 points, the central point, and 4 points (1 each side of the point in the XZ and YZ planes) equal to the max distance in the plane that it can travel (I assume you use Z as your height).  Then approximate.  This ends up being 5 times more costly than a single simulation point.  But you should at the least be able to solve on a curve for x and y because you have 3 points in each plane.  And that your required X and Y co-ordinate are within the sample space.  Horrible, but my first thought to solve for now, and its an approximation of epic proportions.

Baring a proper formula for finding the height I did discover that if you calculate the xy offset then subtract that from your sample location and then calculate the height you get a very close approximation of the height. It's not perfect but it may be close enough especially after summing and averaging a lot of waves together. 

I need to do more testing with this method but I think it will be about as accurate but far less processor intensive that sampling upwards of 5 points per wave per check. 

I'll share what ever I come up with of course. 

This topic is closed to new replies.

Advertisement