/// <summary> /// Sphere / Sphere Collision /// </summary> /// <param name="first"></param> /// <param name="second"></param> public void TestCollision(RigidObject first, RigidObject second) { // Simple sphere / sphere collision Vector3 direction = first.Position - second.Position; if (direction.LengthSquared() < Math.Pow(first.Scale.X + second.Scale.X, 2)) { float diff = direction.Length() - first.Scale.X - second.Scale.X; // First, normalize the direction vector direction.Normalize(); // If the spheres are overlapping, push them out a little so they just touch first.Position -= diff / 2 * direction; second.Position += diff / 2 * direction; // Next, find the relative velocity between the two bodies Vector3 relativeVelocity = first.Velocity - second.Velocity; // Find the velocity in the direction of contact - use dot product float relativeVelocityPerp = -Vector3.Dot(relativeVelocity, direction); // Esoteric: Finally, the impulse is determined using this relationship float impulse = relativeVelocityPerp / (1 / first.Mass + 1 / second.Mass); // Add the impulses in the correct direction to both bodies first.AddForce = 2 * impulse * direction; second.AddForce = -2 * impulse * direction; collisions[secondIndex]++; } }
private void AddSphere() { RigidObject sphere = new RigidObject(); sphere.Model = sphereModel; sphere.Texture = sphereTexture; sphere.Position = new Vector3( (float)(random.NextDouble()*20 - 10), (float)(random.NextDouble()*20 - 10), (float)(random.NextDouble()*20 - 10)); sphere.Velocity = new Vector3( (float)(random.NextDouble()*4 - 2), (float)(random.NextDouble()*4 - 2), (float)(random.NextDouble()*4 - 2)); sphere.Mass = (float)(1 + random.NextDouble() * 4); sphere.Scale *= (float)(0.5 + random.NextDouble()); sphere.BallColor = RigidObject.ColorBank[random.Next(0, 6)]; spheres.Add(sphere); }
/// <summary> /// Sphere / Triangle Collision /// </summary> /// <param name="first"></param> /// <param name="A"></param> /// <param name="B"></param> /// <param name="C"></param> public void TestCollision(RigidObject first, Vector3 A, Vector3 B, Vector3 C) { // First, make the sphere center our origin A = A - first.Position; B = B - first.Position; C = C - first.Position; // Find the surface normal for the triangle (using a cross product) Vector3 normal = Vector3.Cross(C - A, B - A); normal.Normalize(); // Find how far away the sphere is from the triangle // We use a dot prouct to "project" Vector A on the normal float separation = (float)Math.Abs(Vector3.Dot(A, normal)); // If the sphere is too far away, then quit if (separation > first.Scale.X) return; // Good, so now it is in range! Find the contact point on the plane of the triangle Vector3 P = separation * normal; // Esoteric: Determine if the point is actually in the triangle if (Vector3.Dot(Vector3.Cross(B - A, P - A), Vector3.Cross(C - A, P - A)) > 0 || Vector3.Dot(Vector3.Cross(B - C, P - C), Vector3.Cross(A - C, P - C)) > 0) return; // If the sphere is actually moving away, then don't bother (dot product here if (Vector3.Dot(first.Velocity, normal) > 0) return; // Finally, add the impulse force to the sphere first.AddForce = -2 * Vector3.Dot(first.Velocity, normal) * normal * first.Mass; }