7

私は自分の基本的な物理エンジンを書いていますが、今は解決できない問題に直面しています。おそらく私はこの問題をグーグルで検索する方法がないからです。

これが私の問題です。この画像がそれを説明できることを願っています:

衝突応答

2つのオブジェクトがあります。灰色のものは固定されて動かず、緑色のものは上から落ちます。緑のオブジェクトには、力、加速度、速度の3つのベクトルがあります。固定された灰色のオブジェクトと衝突します。

本当の問題は、緑色のオブジェクトが落下したときに、どうすれば回転を取得できるかということです。

4

2 に答える 2

12

剛体の力学の根底にある基本的な物理学を理解していないようです。この種の問題について話すときに一般的に使用される用語のいずれにも言及していないという理由だけで、私は言います。システム内の各動的ボディに方向と角速度(位置と線速度の回転アナログ)の概念を導入し、慣性モーメント、角加速度、トルクなどのあらゆる種類の中間量を計算する必要があります。

おそらく、これに関する最も優れた入門書は、GameDeveloperMagazineのChrisHeckerの一連の記事です。非回転ダイナミクス(パート1でカバー)と衝突検出(このシリーズではカバーされていない)がすでに解決されていると仮定すると、パート2から始めて、パート3に進む必要があります。回転衝突応答を実装するために必要な数学。

于 2012-07-25T17:32:04.800 に答える
10

オブジェクトが衝突したときに、以下で説明するように1回実行します。

緑の長方形を「a」、もう一方を「b」と呼びましょう。

1.1。

まず、長方形の「回転質量」、慣性質量が必要です。

ai = 4/3 *幅*高さ*(幅^ 2+高さ^2)*a。密度

2.2。

次に、長方形の重心(すべての角の平均位置)から接触位置(長方形が衝突する場所)を指すベクトルが必要です。これを「r」と呼びます。

3.3。

次に、衝突法線を見つける必要があります。この法線は、bからaに適用されるインパルスの方向です。法線は、長さが1単位のベクトルです。あなたの例では、法線はおそらく上向きになります。法線ベクトルを「n」と呼びましょう。

4.4。

ここで、上の接触点の速度が必要になります。aが回転していない場合、式は次のようになります。

vp = a.vel

aが回転している場合、式は次のようになります。

vp = a.vel + cross(a.r_vel、r)

a.r_velはラジアンで与えられるaの回転速度であり、正の方向は反時計回りです。

cross()は外積を意味し、関数は次のとおりです。

cross(v、i)= [-i * vy、i * vx]

展開された式は次のようになります。

vp = av + [-r * a.r_vel.y、r * a.r_vel.x]

5.5。

次に、オブジェクトが互いに向かって移動しているかどうかを計算する必要があります。vpをnに投影します。

vp_p = dot(vp、n)

ドット(v1、v2)= v1.x * v2.x + v1.y * v2.y

vp_pはスカラー(ベクトルではなく値)です。

vp_pが負の場合、オブジェクトは互いに向かって移動し、0より大きい場合、オブジェクトは離れて移動します。

6.6。

ここで、aがbに移動するのを防ぐために、インパルスを計算する必要があります。インパルスは次のとおりです。

j = -vp_p /(1 / a.mass + cross(r、n)^ 2 / ai)

2つのベクトル間の外積は次のとおりです。

cross(v1、v2)= v1.x * v2.y-v1.y * v2.x

スカラーを返します。

インパルスに法線を掛けて、インパルスベクトルを取得します。

jn = j * n

7。

次に、インパルスを以下に適用する必要があります。

a.new_vel = a.old_vel + jn / a.mass;

a.new_r_vel = a.old_r_vel + cross(r、jn)/ ai;

衝突を完全に弾力性のあるものにしたい場合は、力積に2を掛ける必要があります。この乗数を「e」と呼びます。eは1から2の間である必要があります。1はエネルギーが節約されないことを意味し、2はすべてのエネルギーが節約されることを意味します。

コード例:

var vp = a.vel + cross(a.r_vel, r);
var vp_p = dot(vp,n); // negative val = moving towards each other
if (vp_p >= 0) { // do they move apart?
    return false;
}

// normal impulse
var j = - e * vp_p / (
            1/a.mass + cross(r,n)^2 / a.i
        );
var jn = j * n;
//
a.vel = a.vel + jn / a.mass;
a.r_vel = a.r_vel + cross(r,jn) / a.i;

bが静的でない場合、アルゴリズムはわずかに異なります。

ar=aの重心から接触位置を指すベクトル

var vp = a.vel + cross(a.r_vel, a.r) - b.vel - cross(b.r_vel, b.r);
var vp_p = dot(vp,n); // negative val = moving towards each other
if (vp_p >= 0) { // do they move apart?
    return false;
}

// normal impulse
var j = - e * vp_p / (
            1/a.mass + cross(a.r,n)^2 / a.i +
            1/b.mass + cross(b.r,n)^2 / b.i
        );
var jn = j * n;
//
a.vel = a.vel + jp / a.mass;
a.r_vel = a.r_vel + cross(a.r,jn) / a.i;
b.vel = b.vel - jp / b.mass;
b.r_vel = b.r_vel - cross(b.r,jn) / b.i;

数式のしくみ/出典:

http://www.myphysicslab.com/collision.html#resting_contact

于 2015-06-25T13:58:31.203 に答える