Available on Simmer.io : https://simmer.io/@Yudhishtiran/cluster-2d
The most central formula in this project is:
... which states that the gravitational force between two objects depends on both the objects' masses and is inverse proportional to the distance between the mass centers (CM). According to Newton’s law of gravitation, the gravitational force between two objects will be the same. However, the direction of the forces will of course be the opposite. As a result, this algorithm would therefore do almost double the strictly necessary calculations.In C# with Unity:
for (int i = 0; i < particle_num; i++)
{
for (int j = 0; j < particle_num; j++)
{
if (i != j)
{
delta_force += GravitationalPull(particles[i], particles[j]);
}
}
particles[i].AddForce(delta_force, ForceMode2D.Force);
delta_force = new Vector2(0, 0);
}
Vector2 GravitationalPull(Rigidbody2D primary_object, Rigidbody2D secondary_object)
{
distance = Vector2.Distance(primary_object.transform.position, secondary_object.transform.position);
if (distance > 1)
{
Force = gravitational_constant / Mathf.Pow(distance, 3);
force_vector = Force * new Vector2(secondary_object.position.x - primary_object.position.x,
secondary_object.position.y - primary_object.position.y);
}
else
{
force_vector = new Vector2(0, 0);
}
return force_vector;
}
This algorithm takes into account that Newton’s formula for the gravitational force infers the force vector of both objects. This reduces the number of calculations that are performed. See the formula over or the code below for more information.
for (int i = 0; i < particle_num; i++)
{
for (int j = i+1; j < particle_num; j++)
{
forces[i] += GravitationalPull(particles[i], particles[j], j);
}
particles[i].AddForce(forces[i], ForceMode2D.Force);
forces[i] = new Vector2(0, 0);
}
Vector2 GravitationalPull(Rigidbody2D primary_object, Rigidbody2D secondary_object,int j)
{
distance = Vector2.Distance(primary_object.transform.position, secondary_object.transform.position);
if (distance > 1)
{
Force = (gravitational_constant*primary_object.mass*secondary_object.mass) / Mathf.Pow(distance, 3);
force_vector = Force * new Vector2(secondary_object.position.x - primary_object.position.x,
secondary_object.position.y - primary_object.position.y);
forces[j] += -1*force_vector;
}
else
{
force_vector = new Vector2(0, 0);
}
return force_vector;
}
Well, let be an estimate of calculation reduction.
That means that if we have 250 particles to simulate, we will save about 50% computation (31 375 iterations reduced).The image below illustrates the difference between these algorithms:
<iframe src="https://i.simmer.io/@Yudhishtiran/cluster" style="width:900px;height:600px"></iframe>