void Shallow_Wave(float[,] old_h, float[,] h, float [,] new_h)
{
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
{
new_h[i, j] = h[i, j] + (h[i, j] - old_h[i, j]) * damping;
if (i != 0) new_h[i, j] += (h[i - 1, j] - h[i, j]) * rate;
if (i != size - 1) new_h[i, j] += (h[i + 1, j] - h[i, j]) * rate;
if (j != 0) new_h[i, j] += (h[i, j - 1] - h[i, j]) * rate;
if (j != size - 1) new_h[i, j] += (h[i, j + 1] - h[i, j]) * rate;
old_h[i, j] = h[i, j];
}
{
GameObject Cube = GameObject.Find("Cube");
Vector3 cube_p = Cube.transform.position;
Mesh cube_mesh = Cube.GetComponent<MeshFilter>().mesh;
int li = (int)((cube_p.x + 5.0f) * 10) - 3;
int ui = (int)((cube_p.x + 5.0f) * 10) + 3;
int lj = (int)((cube_p.z + 5.0f) * 10) - 3;
int uj = (int)((cube_p.z + 5.0f) * 10) + 3;
Bounds bounds = cube_mesh.bounds;
for (int i = li - 3; i <= ui + 3; i++)
for (int j = lj - 3; j <= uj + 3; j++)
if (i >= 0 && j >= 0 && i < size && j < size)
{
Vector3 p = new Vector3(i * 0.1f - size * 0.05f, -11, j * 0.1f - size * 0.05f);
Vector3 q = new Vector3(i * 0.1f - size * 0.05f, -10, j * 0.1f - size * 0.05f);
p = Cube.transform.InverseTransformPoint(p);
q = Cube.transform.InverseTransformPoint(q);
Ray ray = new Ray(p, q - p);
float dist = 99999;
bounds.IntersectRay(ray, out dist);
low_h[i, j] = -11 + dist;//cube_p.y-0.5f;
}
//Initialize Pressure
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
{
if (low_h[i, j] > h[i, j])
{
b[i, j] = 0;
vh[i, j] = 0;
cg_mask[i, j] = false;
}
else
{
cg_mask[i, j] = true;
b[i, j] = (new_h[i, j] - low_h[i, j]) / rate;
}
}
Conjugate_Gradient(cg_mask, b, vh, li - 1, ui + 1, lj - 1, uj + 1);
}
{
GameObject Cube = GameObject.Find("Block");
Vector3 cube_p = Cube.transform.position;
Mesh cube_mesh = Cube.GetComponent<MeshFilter>().mesh;
int li = (int)((cube_p.x + 5.0f) * 10) - 3;
int ui = (int)((cube_p.x + 5.0f) * 10) + 3;
int lj = (int)((cube_p.z + 5.0f) * 10) - 3;
int uj = (int)((cube_p.z + 5.0f) * 10) + 3;
Bounds bounds = cube_mesh.bounds;
for (int i = li - 3; i <= ui + 3; i++)
for (int j = lj - 3; j <= uj + 3; j++)
if (i >= 0 && j >= 0 && i < size && j < size)
{
Vector3 p = new Vector3(i * 0.1f - size * 0.05f, -11, j * 0.1f - size * 0.05f);
Vector3 q = new Vector3(i * 0.1f - size * 0.05f, -10, j * 0.1f - size * 0.05f);
p = Cube.transform.InverseTransformPoint(p);
q = Cube.transform.InverseTransformPoint(q);
Ray ray = new Ray(p, q - p);
float dist = 99999;
bounds.IntersectRay(ray, out dist);
low_h[i, j] = -11 + dist;//cube_p.y-0.5f;
}
//Initialize Pressure
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
{
if (low_h[i, j] > h[i, j])
{
b[i, j] = 0;
vh[i, j] = 0;
cg_mask[i, j] = false;
}
else
{
cg_mask[i, j] = true;
b[i, j] = (new_h[i, j] - low_h[i, j]) / rate;
}
}
Conjugate_Gradient(cg_mask, b, vh, li - 1, ui + 1, lj - 1, uj + 1);
}
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
{
if (cg_mask[i, j])
vh[i, j] *= gamma;
}
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
{
if (i != 0) new_h[i, j] += (vh[i - 1, j] - vh[i, j]) * rate;
if (i != size - 1) new_h[i, j] += (vh[i + 1, j] - vh[i, j]) * rate;
if (j != 0) new_h[i, j] += (vh[i, j - 1] - vh[i, j]) * rate;
if (j != size - 1) new_h[i, j] += (vh[i, j + 1] - vh[i, j]) * rate;
}
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
h[i, j] = new_h[i, j];
//Update cube
{
GameObject Cube = GameObject.Find("Cube");
Vector3 cube_p = Cube.transform.position;
Mesh cube_mesh = Cube.GetComponent<MeshFilter>().mesh;
int li = (int)((cube_p.x + 5.0f) * 10) - 3;
int ui = (int)((cube_p.x + 5.0f) * 10) + 3;
int lj = (int)((cube_p.z + 5.0f) * 10) - 3;
int uj = (int)((cube_p.z + 5.0f) * 10) + 3;
Bounds bounds = cube_mesh.bounds;
float t = 0.004f;
float mass = 10.0f;
Vector3 force = new Vector3(0, -mass * 9.8f, 0);
Vector3 torque = new Vector3(0, 0, 0);
for (int i = li - 3; i <= ui + 3; i++)
for (int j = lj - 3; j <= uj + 3; j++)
if (i >= 0 && j >= 0 && i < size && j < size)
{
Vector3 p = new Vector3(i * 0.1f - size * 0.05f, -11, j * 0.1f - size * 0.05f);
Vector3 q = new Vector3(i * 0.1f - size * 0.05f, -10, j * 0.1f - size * 0.05f);
//Debug.Log("ok");
//Debug.Log(p);
p = Cube.transform.InverseTransformPoint(p);
q = Cube.transform.InverseTransformPoint(q);
//Debug.Log(p);
Ray ray = new Ray(p, q - p);
float dist = 99999;
bounds.IntersectRay(ray, out dist);
/*if(i==50 && j==50)
{
Debug.Log(p);
Debug.Log(q);
Debug.Log(-11+dist);
}*/
//Debug.Log(cube_p.y-0.5f);
if (vh[i, j] != 0)
{
Vector3 r = p + dist * (q - p) - cube_p;
Vector3 f = new Vector3(0, vh[i, j], 0) * 4.0f;
force += f;
torque += Vector3.Cross(r, f);
}
}
cube_v *= 0.99f;
cube_w *= 0.99f;
cube_v += force * t / mass;
cube_p += cube_v * t;
Cube.transform.position = cube_p;
cube_w += torque * t / (100.0f * mass);
Quaternion cube_q = Cube.transform.rotation;
Quaternion wq = new Quaternion(cube_w.x, cube_w.y, cube_w.z, 0);
Quaternion temp_q = wq * cube_q;
cube_q.x += 0.5f * t * temp_q.x;
cube_q.y += 0.5f * t * temp_q.y;
cube_q.z += 0.5f * t * temp_q.z;
cube_q.w += 0.5f * t * temp_q.w;
Cube.transform.rotation = cube_q;
}
}
void Update ()
{
Mesh mesh = GetComponent<MeshFilter> ().mesh;
Vector3[] X = mesh.vertices;
float[,] new_h = new float[size, size];
float[,] h = new float[size, size];
//TODO: Load X.y into h.
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
h[i, j] = X[i * size + j].y;
}
}
if (Input.GetKeyDown ("r"))
{
//TODO: Add random water.
int i = Random.Range(0, size);
int j = Random.Range(0, size);
float val = Random.value;
if (i < 1) i = 1;
if (j < 1) j = 1;
if (i >= size - 1) i = size - 2;
if (j >= size - 1) j = size - 2;
h[i, j] += val;
h[i - 1, j] -= val / 4.0f;
h[i + 1, j] -= val / 4.0f;
h[i, j - 1] -= val / 4.0f;
h[i, j + 1] -= val / 4.0f;
}
for(int l=0; l<8; l++)
{
Shallow_Wave(old_h, h, new_h);
}
//TODO: Store h back into X.y and recalculate normal.
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
X[i * size + j].y = h[i, j];
}
}
mesh.vertices = X;
mesh.RecalculateNormals();
}