Box2D を使用して、ニュートンの万有引力の法則をシミュレートしたいと考えています。
マニュアルを調べましたが、これを行う方法が見つかりませんでした。
基本的に私がやりたいことは、いくつかのオブジェクトを空間 (無重力) に配置し、動きをシミュレートすることです。
任意のヒント?
Box2D を使用して、ニュートンの万有引力の法則をシミュレートしたいと考えています。
マニュアルを調べましたが、これを行う方法が見つかりませんでした。
基本的に私がやりたいことは、いくつかのオブジェクトを空間 (無重力) に配置し、動きをシミュレートすることです。
任意のヒント?
実装はとても簡単です:
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 );
}
}
残念ながら、Box2D はそれをネイティブでサポートしていませんが、自分で実装することができます: Box2D と放射重力コード
他の人が言ったように、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 つしかない場合、これは簡単な解決策です。遠くにいるほど力を弱めたい場合は、正規化する代わりに 1/gravityVector を使用できます。これにより、惑星の重力を合計することも可能になります。また、惑星リストを反復処理して、gravityVectors を合計することもできます。
さらに、b2World::CreatePlanet のような関数を実装すると便利な場合があります。
10.0f は、地球からの 9.81f の近似値にすぎません。調整が必要になる場合があります。惑星の質量が関連している場合は、定数を乗算してよりリアルに見せるか、オブジェクトの密度を上げて惑星の実際の重量と一致させる必要があります。
もちろん、重力を 0, 0 に設定してから、すべてのオブジェクトの各ステップの前に計算することもできますが、それほどパフォーマンスが高くない可能性があります。