impulse方法
void Collision_Impulse(Vector3 P, Vector3 N)
{
Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] vertices = mesh.vertices;
Matrix4x4 R = Matrix4x4.Rotate(this.transform.rotation);
Vector3 T = transform.position;
Vector3 sum = Vector3.zero;
int collisionNum = 0;
for (int i = 0; i < vertices.Length; i++)
{
Vector3 r_i = vertices[i];
Vector3 Rri = R.MultiplyVector(r_i);
Vector3 x_i = T + Rri;
float d = Vector3.Dot(x_i - P, N);
if (d < 0.0f) // collision occur
{
Vector3 v_i = v + Vector3.Cross(w, Rri);
float v_N_size = Vector3.Dot(v_i, N);
// check velocity
if (v_N_size < 0.0f)
{
sum += r_i;
collisionNum++;
}
}
}
if (collisionNum == 0) return;
Matrix4x4 I_rot = R * I_ref * R.transpose;
Matrix4x4 I_inverse = I_rot.inverse;
Vector3 r_collision = sum / (float)collisionNum; // virtual collision point(local coordination)
Vector3 Rr_collision = R.MultiplyVector(r_collision);
//Vector3 x_collision = T + Rr_collision; // virtual collision point(global coordination)
Vector3 v_collision = v + Vector3.Cross(w, Rr_collision);
// Compute the wanted v_N
Vector3 v_N = Vector3.Dot(v_collision, N) * N;
Vector3 v_T = v_collision - v_N;
Vector3 v_N_new = -1.0f * restitution * v_N;
float a = Math.Max(1.0f - friction * (1.0f + restitution) * v_N.magnitude / v_T.magnitude, 0.0f);
Vector3 v_T_new = a * v_T;
Vector3 v_new = v_N_new + v_T_new;
// Compute the impulse J
Matrix4x4 Rri_star = Get_Cross_Matrix(Rr_collision);
Matrix4x4 K = Matrix_subtraction(Matrix_miltiply_float(Matrix4x4.identity, 1.0f / mass),
Rri_star * I_inverse * Rri_star);
Vector3 J = K.inverse.MultiplyVector(v_new - v_collision);
// Update v and w with impulse J
v = v + 1.0f / mass * J;
w = w + I_inverse.MultiplyVector(Vector3.Cross(Rr_collision, J));
}