简体   繁体   中英

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?

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 );
    }
}

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.

Unfortunately, Box2D doesn't have native support for it, but you can implement it yourself: Box2D and radial gravity code

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM