# Simulating Water by changing Y values of Quad Vertices

hopefully this isn't too difficult to answer, but I'm stuck and could at least use some input. I'm working on simulating water for the first time with basic wave functionality. As in I click at a point on the quad, and it will generate a ripple throughout the quad.

I've been following two tutorials:

The mesh deformation tutorial is done and works just as expected, giving me the ability to deform a mesh with a mouse click. Unfortunately, the GDC presentation isn't as clear cut as I would have liked. Implementing the code on page 14 doesn't seem to do much, and messing around with the algorithm produces some results that make me think I'm in the right direction.

Here's what I have so far:

void UpdateVertex(int i)
{
// Handles deformation from mouse click
Vector3 velocity = vertexVelocities[i]; // Velocity for given vertex
displacedVertices[i] += velocity * Time.deltaTime; // Moves vertex based on velocity
Vector3 displacement = displacedVertices[i] - originalVertices[i]; // Gets how much the vertex was moved
displacement *= uniformScale; // Ensures forces act consistent across all scales
velocity -= displacement * springForce * Time.deltaTime; // Applies spring force so vertex will bounce back to its original position
velocity *= 1f - damping * Time.deltaTime; // Applies dampening value to vertex won't "explode"
vertexVelocities[i] = velocity; // Updates vertex velocity
displacedVertices[i] += velocity * (Time.deltaTime / uniformScale); // Applies velocity to vertex position based on scale

// Supposed to handle wave-ripple effect
nHeight = 0; // North Vertex Height
eHeight = 0; // East Vertex Height
sHeight = 0; // South Vertex Height
wHeight = 0; // West Vertex Height

// Simple boundary checks
if (i + 100 >= 0 && i + 100 < 10000)
nHeight = displacedVertices[i + 100].y;
if (i - 100 >= 0 && i - 100 < 10000)
sHeight = displacedVertices[i - 100].y;
if (i + 1 >= 0 && i + 1 < 10000)
eHeight = displacedVertices[i + 1].y;
if (i - 1 >= 0 && i - 1 < 10000)
wHeight = displacedVertices[i - 1].y;

// Struggle to understand how this is supposed to work; water ripple algorithm
float f = (waveSpeed * waveSpeed) * ((nHeight + sHeight + eHeight + wHeight) - 4f*displacedVertices[i].y) / 4f;
float fdt = f * Time.deltaTime;
velocity.y += fdt;
vertexVelocities[i] = velocity;
displacedVertices[i].y += vertexVelocities[i].y * Time.deltaTime * waveSpeed * 2;
}


Even with this current code I have to give the program specific variable parameters.

Mouse Click Force is set to 40, and Wave Speed is set to 5 in this picture. Not only are the ripples extending out in an oval pattern, but the rippling effect takes a while to start up, which is obviously not how water works.

If anyone can offer insight into these issues, that would be greatly appreciated. Please let me know if I should post further code or information.

I forgot to mention the quad I'm dealing with is 100x100 vertices

## UPDATE

I've made some good progress, however I'm now running into two issues:

1. the algorithm is computationally expensive (which is weird since it was given in a GDC presentation). Am I not implementing it right? Can optimizations be made
2. I've got some boundary issues I'm dealing with.

using UnityEngine;

[RequireComponent(typeof(MeshFilter))] public class WaterWaves : MonoBehaviour {

public float c = 10f;
public float h = 4f;
public int height, width;

Mesh mesh;
int n, s, e, w = 0;
float[] originalVerts;
float[] u, v;
float[] newVerts;
Vector3[] vertices;

float dt;

void Start()
{
mesh = GetComponent<MeshFilter>().mesh;
originalVerts = new float[mesh.vertices.Length];
u = new float[mesh.vertices.Length];
v = new float[mesh.vertices.Length];
newVerts = new float[mesh.vertices.Length];
vertices = new Vector3[mesh.vertices.Length];

for (int i = 0; i < mesh.vertices.Length; i++)
{
originalVerts[i] = mesh.vertices[i].y;
newVerts[i] = originalVerts[i];
u[i] = newVerts[i];
v[i] = 0;
}

v = -5;
Debug.Log("v: " + v);
}

void Update()
{
Debug.Log("u: "+u);
dt = Time.deltaTime;
for(int i = 0; i < originalVerts.Length; i++)
{
BoundaryCheck(i);
float f = (c * c) * (u[n] + u[s] + u[e] + u[w] - 4*u[i]) / (h * h);
v[i] += f * dt;
v[i] -= 0.05f * (newVerts[i] - originalVerts[i]);
newVerts[i] = u[i] + v[i] * dt;
newVerts[i] *= 0.99f;
}
for(int i = 0; i < originalVerts.Length; i++)
{
vertices[i] = new Vector3(mesh.vertices[i].x, newVerts[i]+mesh.vertices[i].y, mesh.vertices[i].z);
u[i] = newVerts[i];
}
mesh.vertices = vertices;
mesh.RecalculateNormals();
}

void BoundaryCheck(int i)
{
n = i - height;
s = i + height;
e = i + 1;
w = i - 1;

if (n < 0 || n >= originalVerts.Length)
{
n = i;
}
if (s < 0 || s >= originalVerts.Length)
{
s = i;
}
if (e < 0 || e >= originalVerts.Length)
{
e = i;
}
if (w < 0 || w >= originalVerts.Length)
{
w = i;
}
}


}

Here's the full file I'm working with. I'm dealing with a 1D array, and that makes testing the boundary issues, kind of difficult. I'm arbitrarily choosing a point and applying velocity to get the algorithm going (at this point I just want to get it to work; interactivity comes later). Lastly, for anyone looking to help, but unsure of where to start, my brother made the astute point that what I'm trying to do is essentially a JavaScript program by Mr. Doob.

His code is a bit more abstract than I'd like, so I have trouble understanding how it works.

Mr. Doob Liquid Voxels

## UPDATE 2

Super close to figuring it out I think. Here's the good news: Thanks to Stephen's insight, I realized that I was handling the vertices incorrectly which was making some weird patterns and waves. Fixing that actually makes it work SO CLOSELY. Next up, I redid the boundary constraints based on Mr. Doob's code, and it appears to be working well!

Now the newest and hopefully last issue, is that my spring doesn't seem to be working properly. I'm using Hooke's Law F = -kX, but when the spring comes to a rest, the restored mesh is not a flat quad.

Here's the relevant code:

BoundaryCheck(i);
newVerts[i] += v[i] * dt;
float f = (c * c) * (n + s + e + w - 4*u[i]) / (h * h);
v[i] += f * dt;
v[i] -= springConstant * (newVerts[i] - originalVerts[i]); // SPRING
v[i] *= 1f - damping * dt;
newVerts[i] = u[i] + v[i] * dt;

• How are you applying the force? If you aren't making sure it's straight down, you can get oval propagation. What boundary issues are you getting? Specific questions get specific answers. – Stephan Jan 2 '18 at 18:28
• Thank you for the response. I guess part of my issue is that I don't exactly know what might be causing the problem which I know isn't helpful for anyone looking to answer. For example, to help understand how the algorithm works, I did a 1D implementation of it in a 2D space and I after tweaking it for quite a while, I found out I didn't have my spring equation implemented properly For the boundary issues, as you can see in my newest photo, you get those double dips on the border. Based on my BoundaryCheck() code, that shouldn't be happening. – David King Jan 2 '18 at 22:33
• After doing some basic testing, I think I might know what's causing one of the issues. I set up a 3x3 quad and extract the vertices from the mesh. Now, naturally I'd expect to get an array of size 9, but instead I get one of 16. Which is strange because this is not how many vertices were used to create the mesh. Meaning that I think Unity recreates the vertex array to in relation to the triangle array. So the vertex array unity spits out is how many vertices are being used, rather than the true number of vertices. This means I'll likely need to rebuild the mesh every frame. – David King Jan 2 '18 at 23:08
• 3x3 quads will have 16 verts. We're you thinking you were creating 3x3 verts? That'd be 2x2 quads. – Stephan Jan 3 '18 at 1:16
• Oh jeeze. How embarrassing. – David King Jan 3 '18 at 2:01