Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simulate "Newton's law of universal gravitation" using Box2D

I want to simulate Newton's law of universal gravitation using Box2D.

I went through the manual but couldn't find a way to do this.

Basically what I want to do is place several objects in space (zero gravity) and simulate the movement.

Any tips?

like image 805
Ashika Umanga Umagiliya Avatar asked Jul 20 '11 06:07

Ashika Umanga Umagiliya


People also ask

How do you calculate Newton's law of universal gravitation?

In symbols, the magnitude of the attractive force F is equal to G (the gravitational constant, a number the size of which depends on the system of units used and which is a universal constant) multiplied by the product of the masses (m1 and m2) and divided by the square of the distance R: F = G(m1m2)/R2.

Does gravity work in 2d?

The usual definition of gravity in different dimension makes it so that if space is 2d, then Newtonian gravity goes as 1/r not 1/r^2 (as David Zaslavsky points out, GR in 2+1 dimensions is even weirder--- gravity doesn't exert long range forces in 2d, but it creates point conical deficits.

What are the 3 law of universal gravitation?

If the mass of one of the objects is doubled, then the force of gravity between them is doubled. If the mass of one of the objects is tripled, then the force of gravity between them is tripled. If the mass of both of the objects is doubled, then the force of gravity between them is quadrupled; and so on.

What is an example of Newton's law of gravitation?

The gravitational force exerted by the celestial bodies at the center increases as their mass increases and decreases as their distance to the revolving body increases. For example, the force of gravity of the Sun on the Earth is much larger than that of the Earth on the moon.


2 Answers

As said by others, Box2D has no buildin support for it. But you can add support for it to the library in b2_islands.cpp. Just replace

v += h * b->m_invMass * (b->m_gravityScale * b->m_mass * gravity + b->m_force);  

with

int planet_x = 0;
int planet_y = 0;
b2Vec2 gravityVector = (b2Vec2(planet_x, planet_y) - b->GetPosition());    
gravityVector.Normalize();    
gravityVector.x = gravityVector.x * 10.0f;    
gravityVector.y = gravityVector.y * 10.0f;    
v += h * b->m_invMass * (b->m_gravityScale * b->m_mass * gravityVector + b->m_force);    

Thats a simple solution if you have only one planet. If you want less force the further away you are, you could use 1/gravityVector instead of normalizing it. That would also make it possible to add up the gravity of to planets. The you could also iterate over a planet list and sum the gravityVectors up.

Additionally implementing a function like b2World::CreatePlanet might be usefull then.

The 10.0f are just an approximation of the 9.81f from earth, you might need to adjust it. If the mass of the planet is relevant you might need a constant to be multiplied with it, to make it look more realistic, or just increase the density of the object to make it match the real weight of a planet.

Sure you can also set the gravity to 0, 0 and then calculate it before each step for every object, but that might not have so much performance.

like image 135
cpdef Avatar answered Sep 25 '22 04:09

cpdef


It's pretty easy to implement:

for ( int i = 0; i < numBodies; i++ ) {

    b2Body* bi = bodies[i];
    b2Vec2 pi = bi->GetWorldCenter();
    float mi = bi->GetMass();

    for ( int k = i; k < numBodies; k++ ) {

        b2Body* bk = bodies[k];
        b2Vec2 pk = bk->GetWorldCenter();
        float mk = bk->GetMass();

        b2Vec2 delta = pk - pi;
        float r = delta.Length();
        float force = G * mi * mk / (r*r);

        delta.Normalize();
        bi->ApplyForce(  force * delta, pi );
        bk->ApplyForce( -force * delta, pk );
    }
}
like image 22
iforce2d Avatar answered Sep 22 '22 04:09

iforce2d