使用Box2D模拟“牛顿万有引力定律”。

9
我希望使用Box2D模拟牛顿万有引力定律,属于编程相关内容。我已经查阅了手册,但没有找到具体方法。我的目标是在空间中(零重力)放置多个物体并模拟运动。请问是否有什么建议?
3个回答

18

实现起来相当简单:

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

1
对于那些不知道的人,G = 万有引力常数 = 6.67×10 ^−11 N·(m/kg)^2。它是一个普遍常数(而非地球的g=9.8 m^2/s^2)。 - GKFX
嘿,仅供参考,维基百科关于轨道的页面有一些有价值的信息。例如,您可以找到遵循普遍引力定律的两个物体的轨道中心:它们的质心。此外,对公式进行小检查可以帮助您决定两个物体的初始速度,使它们彼此环绕而不发生碰撞。 - Gustavo Maciel

1

1
正如其他人所说,Box2D没有内置支持。但是你可以在b2_islands.cpp库中添加对其的支持。只需替换即可。
v += h * b->m_invMass * (b->m_gravityScale * b->m_mass * gravity + b->m_force);  

使用

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

如果你只有一个星球,那么这是一个简单的解决方案。 如果你希望距离越远受到的力越小,可以使用1/gravityVector代替归一化。这样也可以将两个星球的引力相加。然后你还可以遍历星球列表并将引力向量相加。

此外,实现像b2World::CreatePlanet这样的函数可能会很有用。

10.0f只是对地球上的9.81f的近似值,你可能需要进行调整。如果行星的质量很重要,你可能需要乘以一个常数来使其更加逼真,或者只需增加物体的密度以使其与行星的实际重量相匹配。

当然,你也可以将重力设置为0,0,然后在每个对象的每个步骤之前计算它,但这可能会影响性能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接