- Home /
(C#) Issues implementing Gerstner waves
I'm having a few issues implementing Gerstner waves based on this GPU Gems article. I've successfully implemented a 2d version of the algorithm, and I'm now trying to create a 3d version in Unity using C#. So far the code I have is:
void Update () {
Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] vertices = mesh.vertices;
int i = 0;
while(i < vertices.Length)
{
Vector3 newPos = new Vector3(vertices[i].x, 0, vertices[i].z);
foreach (Wave wave in allWaves)
{
float inner = Vector2.Dot(wave.wavelength * wave.direction, new Vector2(vertices[i].x, vertices[i].z)) + wave.phase * Time.time;
//Qi = Q/(wi * Ai * numWaves)
float Qi = steepness / (wave.wavelength * wave.amplitude * waves.Length);
float cosFunction = Mathf.Cos(inner);
newPos.x += Qi * wave.amplitude * wave.direction.x * cosFunction;
newPos.y += wave.amplitude * Mathf.Sin(inner);
newPos.z += Qi * wave.amplitude * wave.direction.y * cosFunction;
}
vertices[i] = newPos;
i++;
}
mesh.vertices = vertices;
mesh.RecalculateBounds();
}
This is based on this equation in the article: Waves is a class containing parameters of each of the waves, eg amplitude, wavelength, and there are currently 4 waves with the same parameters.
Been trying to get this to work all day - any pointers as to where I'm going wrong would be really appreciated.
Answer by Bunny83 · Mar 23, 2018 at 07:16 PM
Well, the problem is that you modify the vertices and feed them back in the algorithm the next frame. This results in a gradual alignment of the vertices over the first few frames. You want to run the algorithm on the non modified original vertices.
In general you want to avoid reallocating the vertex array each frame. I suggest you create two vertices arrays in start. Use one as the source array and the other as the destination array.
Basically this:
Mesh mesh;
Vector3[] source;
Vector3[] dest;
void Start()
{
mesh = GetComponent<MeshFilter>().mesh;
source = mesh.vertices;
dest = new Vector3[source.Length];
}
void Update ()
{
for(int i = 0; i < vertices.Length; i++)
{
Vector3 newPos = new Vector3(source[i].x, 0, source[i].z);
Vector2 dir = new Vector2(source[i].x, source[i].z);
foreach (Wave wave in allWaves)
{
float inner = Vector2.Dot(wave.wavelength * wave.direction, dir) + wave.phase * Time.time;
float Qi = steepness / (wave.wavelength * wave.amplitude * waves.Length);
float cosFunction = Mathf.Cos(inner);
newPos.x += Qi * wave.amplitude * wave.direction.x * cosFunction;
newPos.y += wave.amplitude * Mathf.Sin(inner);
newPos.z += Qi * wave.amplitude * wave.direction.y * cosFunction;
}
dest[i] = newPos;
}
mesh.vertices = dest;
mesh.RecalculateBounds();
mesh.RecalculateNormals();
}
Works just fine for me.
Note that you use an array / list called allWaves
in your foreach loop but you also seem to have an array named waves
which you use when you calculate Qi. I guess that should be the same array?
Yeah thats a typo, working pretty nicely now. thanks for the help
Your answer
