void Get_Gradient(Vector3[] X, Vector3[] X_hat, float t, Vector3[] G)
{
for (int i = 0; i < G.Length; i++)
{
G[i] = (mass / (t * t)) * (X[i] - X_hat[i]) - mass * new Vector3(0, -9.8f, 0);
}
for (int e = 0; e < E.Length / 2; e++)
{
int i = E[e * 2 + 0];
int j = E[e * 2 + 1];
Vector3 f = spring_k * (1-L[e] / (X[i] - X[j]).magnitude) *(X[i] - X[j]);
G[i] += f;
G[j] -= f;
}
}
void Update ()
{
Mesh mesh = GetComponent<MeshFilter> ().mesh;
Vector3[] X = mesh.vertices;
Vector3[] last_X = new Vector3[X.Length];
Vector3[] X_hat = new Vector3[X.Length];
Vector3[] G = new Vector3[X.Length];
//Initial Setup.
for (int i = 0; i < X.Length; i++)
{
V[i] *= damping;
X[i] = X_hat[i]= X[i] + t * V[i];
}
float omega = 1.0f;
for(int k=0; k<32; k++)
{
if (k == 0) omega = 1.0f;
else if (k == 1) omega = 2.0f / (2.0f - rho * rho);
else omega = 4.0f / (4.0f - rho * rho * omega);
Get_Gradient(X, X_hat, t, G);
//Update X by gradient.
for (int i = 0; i < X.Length; i++)
{
if(i == 0 || i == 20) continue;
Vector3 new_x = omega * (X[i] - 1/ (mass / (t * t) + spring_k*4)*G[i])
+ (1-omega)*last_X[i];
last_X[i] = X[i];
X[i] = new_x;
}
}
for (int i = 0; i < X.Length; i++)
{
V[i] += (X[i] - X_hat[i]) / t;
}
mesh.vertices = X;
Collision_Handling ();
mesh.RecalculateNormals ();
}