It has been some time since I last made a post. I have been a bit busy with college and some personal projects, but I have some time now to talk about the last subject of what I wanted to share about physics: Elastic collision.

Just like previously, let’s take a look at what Wikipedia has to say about Elastic Collision:

An elastic collision is an encounter between two bodies in which the total kinetic energy of the two bodies after the encounter is equal to their total kinetic energy before the encounter. Elastic collisions occur only if there is no net conversion of kinetic energy into other forms.

During the collision of small objects, kinetic energy is first converted to potential energy associated with a repulsive force between the particles (when the particles move against this force, i.e. the angle between the force and the relative velocity is obtuse), then this potential energy is converted back to kinetic energy (when the particles move with this force, i.e. the angle between the force and the relative velocity is acute).

To fully understand this, you must understand what kinetic energy is. I’ll let you follow the link in the Wikipedia quote if you want a broad explanation on the matter, but for the most basic explanation, you can think of it that every moving object has energy due to its motion. This energy can be transferred to another object on impact and that is exactly what we are going to do here.

To calculate the new motion of an object after collision, we will need to know at least the mass and the current velocity. Let’s initialize some spheres for our simulation:

for(int i = 0; i < COLLISIONAMOUNT; ++i)
[i] = new Rld::Sphere(a_SceneManager, "CollisionSphere" + StringConverter::toString(i), 4, ColourValue(1, 1, 0), Vector3((rand() % 120 + 1), (1 + rand() % 120 + 1), (rand() % 120 + 1))); m_CollisionSphere[i]->SetMass((rand() % 10 + 1)); m_CollisionSphere[i]->SetRadius(m_CollisionSphere[i]->GetMass()); m_CollisionSphere[i]->SetCoefficientOfRestitution(0.9f); m_CollisionSphere[i]->SetVelocity(Vector3((rand() % 4 + 1), 0, (rand() % 4 + 1))); }

In here I simply put some random position values to the sphere, a random mass, set the radius according to the mass so we can easily see which sphere has the bigger mass. Set a coefficient of Restitution of 0.9 so the simulation eventually stops due to bouncing on the walls. The collision amount is what you want to make it for yourself. I did 24 so the scene wouldn’t be that crowded and objects would surely hit each other.

At the very first step of the simulation, I am simply integrating the velocity and position over time to create the motion, if you are not sure on how to do this, check back on this post.

The next step we want to take is to check every sphere against each other to see if they collide. As collision checking was not the initial thought behind this post, I took the most simplest way of doing this:

for(int i = 0; i < COLLISIONAMOUNT; ++i)
	for(int j = i + 1; j < COLLISIONAMOUNT; ++j)
		Ogre::Vector3 dist = m_CollisionSphere[i]->GetPosition() - m_CollisionSphere[j]->GetPosition();
		float length = dist.length();

		float sumradius = m_CollisionSphere[i]->GetRadius() + m_CollisionSphere[j]->GetRadius();

		if(length <= (sumradius + 0.01))

we simply check the distance between the 2 spheres, take the sum of the radius and see of the length is smaller or equal to the radius + a small offset, if this is true, we have a collision and we can calculate the new velocity.

Now that we know that the spheres collided with each other, we need to figure out which way they will bounce off each other, and what the velocity will be. As momentum (look it up!) is conserved on each axis independently we can work this out on the axis of collision, which is the position between the 2 sphere. We now want to project the velocity on this axis and we can do that by normalizing the the position between these 2 sphere and use the cross product with the velocity and we can use this to calculate the proper velocity on each of the balls’ axis. Here is how you do that in code:

Vector3 pos = m_CollisionSphere[i]->GetPosition() - m_CollisionSphere[j]->GetPosition();

Vector3 v1 = m_CollisionSphere[i]->GetVelocity();
float x1 = pos.dotProduct(v1);
Vector3 v1x = pos * x1;
Vector3 v1y = v1 - v1x;
float m1 = m_CollisionSphere[i]->GetMass();

pos = pos * -1;
Vector3 v2 = m_CollisionSphere[j]->GetVelocity();
float x2 = pos.dotProduct(v2);
Vector3 v2x = pos * x2;
Vector3 v2y = v2 - v2x;
float m2 = m_CollisionSphere[j]->GetMass();

With this given, we have enough information to use the following formula to calculate the final velocity:

Solving this, we will get the following for the final velocity:

m_CollisionSphere[i]->SetVelocity(v1x * (m1 - m2) / (m1 + m2) + v2x * (2 * m2) / (m1 + m2) + v1y);
m_CollisionSphere[j]->SetVelocity(v1x * (2 * m1) / (m1 + m2) + v2x * (m2 - m1) / (m1 + m2) + v2y);

If everything is done right, you should end up with something like this:

Note that there is some penetration in there due to the simple collision checking. I hope you enjoyed these 4 short posts, hopefully they are a bit helpful and will get you on your way with something you want to do with physics. The explanations are mostly rather bruteforce and simple, but it was only meant to show you how it can be done, these are not always the best ways to do it. Nevertheless, I hope you enjoyed them and until next time with a different topic!