0

私は非常に単純な 2D 物理関数を作成して、球粒子をコライダーとして使用して RigidBody を解決しようとしています。

私はそうリジッドボディとパーティクルクラスを持っています:

    function _rigidBody () {
        this._position = cc.p(0.0, 0.0);
    this._angle = 0;
    this._linearVelocity = cc.p(0.0, 0.0);
    this._angularVelocity = 0.0;
    this._force = cc.p(0.0, 0.0);
    this._angularMoment = 0;
    this._mass = 1.0;

    this._particles = [];
    }
    function _particle () {
    this._initialPosition = cc.p(0.0, 0.0);
    this._relativePosition = cc.p(0.0, 0.0);
    this._worldPosition = cc.p(0.0, 0.0);
    this._linearVelocity = cc.p(0.0, 0.0);
    this._force = cc.p(0.0, 0.0);
    this._radius = 10.0;
    }

基本的に、各フレームで各リジッドボディに保存されている各パーティクルの新しい位置を計算し、次にパーティクル間の衝突をチェックし、衝突の場合は、それらを反発させる力を計算します (半径と内部の量に基づいて)それら)、次にこの力を粒子に保存します。

そして、rigidBody に含まれるすべてのパーティクルのすべての力ストアに対して、rigidBody にインパルスを追加することにより、LinearVelocity と AngularVelocity を計算します。

my function addImpulse (インパルスを使用して力を粒子に保存し、粒子のワールド pos を配置します):

    this.AddImpulse = function(bodyIdx,impulse,position){
    var b = g_Bodies[ bodyIdx ];
    if(position == null){position = b._position;}

    b._linearVelocity.x += (impulse.x/ b._mass);
        b._linearVelocity.y += (impulse.y/ b._mass);
        b._angularVelocity +=  ((position.x - b._position.x) * impulse.y -                
                                (position.y - b._position.y) * impulse.x);
};

私の問題は、この関数が linearVelocity に対して非常にうまく機能することです。これは、角速度が最も小さな衝突で非常に大きくなるように調整されているためです。今のところ、ダンピング (線形または角度) を使用していません。 angularVelocity の慣性、

慣性のミスが私の問題だと思いますが、インターネットでそれを計算する方法を見ると少し混乱します。

box2d を調べて、慣性が格納されていて、rigidBody の変数 (質量として) であることを確認します。インターネットで、慣性 = 質量 * (r*r)
問題 => r とは...

-if は重心の距離 (つまり、rigidBody の位置) であり、明らかに常に 0 に等しい (body.position - body.position == 0 )

  • box2d で見つけた: this.m_I = massData.I - this.m_mass * (massData.center.x * massData.center.x + massData.center.y * massData.center.y); そして、massData.center seam は、rigidBody からの形状の中心になります。私の場合の問題は、私の形状が (0,10) と (0,-10) の 2 つの球体であるため、その中心は (0 ,0) ....

  • 別のウェブサイトで次のことがわかりました: for(i < numberOfParticle) I += ( massOfParticle(i) * ( RelativePosOfParticle(i)*RelativePosOfParticle(i) )最初に中心を検索する代わりに)、私の I は 0 よりも大きくなります。しかし、使用する正しい式はわかりません...

誰かが簡単な方法で私を説明できる場合、慣性を計算する方法は? RigidBody の慣性を直接 (粒子ではなく) 計算できる場合は? 慣性を保存できる場合、またはインパルスをどこに適用するかが深まる場合(他のウェブサイトでも読みました...)?および/または、なぜこのような大きな角速度を得るために衝動の関数で間違ったことをすることができるのですか (おそらく正常であり、この問題を解決するダンピングは他の物理エンジンです)。

また、誰かが(好奇心だけで)答えることができれば、計算が速く、結果が十分に良いため、box2dは慣性の単純なバージョンを使用しますか?それとも、Box2d の計算は正しく、コードを読むと何かが抜けているのでしょうか?

どうもありがとう^^,

マリウス。

4

1 に答える 1

1

最初:あなたは正しいです。問題は、慣性モーメント(質量の回転アナログ)を考慮していないことです。コードを見てください:

b._linearVelocity.x += (impulse.x/ b._mass);
b._linearVelocity.y += (impulse.y/ b._mass);
b._angularVelocity +=  ((position.x - b._position.x) * impulse.y -
                            (position.y - b._position.y) * impulse.x);

線速度を計算するときは、質量で割ります。角運動についても同様のことを行う必要があります。

の位置がrigidBody重心であれば、作業は簡単です。

慣性モーメントは mr 2で、粒子全体で合計されます。つまり、各粒子は に寄与しますm*r*r。ここmで、 は粒子の質量、 はr粒子から重心までの距離です。

たとえば、形状が (0,10) と (0,-10) にある 2 つの球で、どちらも質量が 5の場合、重心は

C = (5*(0,10)+5*(0,-10))/(5+5) = (0,0)

慣性モーメントは

I = 5*10*10 + 5*(-10)*(-10) = 1000

角速度の変化は

b._angularVelocity += (((position.x - b._position.x) * impulse.y -
                        (position.y - b._position.y) * impulse.x))/I;

形状が 2 つの球で、1 つは質量 5 の (0,10) にあり、もう 1 つは質量 10 の (0,-10) にある場合、重心は

C = (5*(0,10)+10*(0,-10))/(5+10) = (0,-10/3)

慣性モーメントは

I = 5*(40/3)*(40/3) + 5*(-20/3)*(-20/3) = 10000/9

編集:

問題は、単一の球体 (または複数の球体) の特殊なケースで発生します。これらの球は質量点として扱われるため、慣性モーメント ( I) はゼロになります。また、すべての衝撃は球の中心を通るため、トルク (角度の「力」) はゼロになります。したがって、角速度は存在しないはずですが、上記の方法では になります0/01 つの解決策:各球体は、慣性モーメントに対して小さな一定の寄与をします (これは、球体が質量点ではないことを意味します。わずかな範囲があるため、回転することができます)。ここで、各球の寄与は です。m*r*r + dここdで、たとえば0.0001です。したがって、唯一の球体には正の慣性モーメントがあり (そして回転しません)、他のすべてのオブジェクトはまだ現実的な物理特性を持っています。

于 2013-01-21T23:51:53.197 に答える