5

WebGLでBox2Dを使用しています。Box2D は、一定のフレーム レート (「ワールド」更新のタイム ステップ) を要求します。

function update(time) {//update of box2d world
     world.Step(
           1/60   // 1 / frame-rate
        ,  3      //velocity iterations
        ,  8       //position iterations
     );

しかし、以下のように定義された requestAnimFrame が正しい方法であることを読みました。

     requestAnimFrame = (function() {
     return window.requestAnimationFrame ||
     window.webkitRequestAnimationFrame ||
     window.mozRequestAnimationFrame ||
     window.oRequestAnimationFrame ||
     window.msRequestAnimationFrame ||
     function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
       window.setTimeout(callback, 1000/60);
     };
})();

requestAnimFrame では一定のフレーム レートが得られないため、Box2D の変数が非同期になります。

これに対する修正はありますか?

[編集]

John (Cutch) のソリューションを実装すると、次のようになります。

function interpolate(dt) {
    var t = dt/time_step;
    body_coordinates = (1-t) * body_coordinates + t * next_body_coordinates;
}

var physicsDt = 0;
function tick() {
    var time_now = new Date().getTime();
    var dt = time_now - last_time; //Note that last_time is initialized priorly
    last_time = time_now;
    physicsDt += dt;
    clear_the_screen();
    requestAnimFrame(tick);
    drawEverything();
    if(physicsDt >= time_step) {
        update();
        physicsDt -= time_step;
    }
    interpolate(dt);
}

next_attribue私の物理更新関数はs が設定されていることに注意してください。また、updateこの前に物理演算が呼び出され、物理演算の世界を 1 フレーム先に進めます。

結果

アニメーションは非常にスムーズですが、非常に悪いジャンプとランダムに現れる微動が見られる場合を除きます。

このソリューションでは、次の問題が解決されていないと思いました。

----> 1) dtより大きくなる可能性がありtime_stepます : これによりdt/time_step1 より大きくなり、補間式が台無しになります。

一貫しdtてより大きいままである場合、問題が増加します。time_stepタイムギャップが よりも大きくなるという問題を克服することは可能time_stepですか?

つまり、世界をレンダリングの 1 フレーム先に維持したとしても、時間のギャップが一貫して より大きいままであれば、time_stepその「先の」フレームを通過するのに長い時間はかからないでしょう。

----> 2) 1 ミリ秒dt未満であると 想像してください。time_stepすると、世界は一度も更新されません。これで補間が行われ、おおよその位置が見つかりました (あるべき場所から 1 ミリ秒遅れています)。

次回は と の間dtに違いが見られないとしましょうtime_step

dt現在、とtime_stepが等しいことを考慮して、補間は行われません。では、次に描画されるのは、世界の「前方」フレームですよね?(これらの方程式を使用して、 でt = 1)

しかし、正確には、レンダリングされた世界は、以前よりも 1 ミリ秒遅れているはずです。つまり、ワールド フレームから 1ms 遅れていたということは、消えてはならないということです。しかし、t = 1では、物理ワールド フレームを描画し、その 1ms を忘れます。

私はコードまたは上記の2点について間違っていますか?

これらの問題を明確にしていただきたい。

[編集]

このWeb ページの作成者に、多くの図形を効率的に描画する方法をコメントで尋ねました。

私はこの方法でそれを行うことを学びました: 私は bufferData呼び出しをcreateBuffer節約bindBufferしていbufferDataます。

画面を更新するたびに、すべての形状を反復処理する必要があり、必要な形状のバッファーをバインドした後に呼び出す必要があります (を使用enableVertexAttribArray) 。vertexAttribPointerbindBuffer

私の形は時間とともに変化しません。最初から最後までさまざまな形 (多角形、円、三角形など) があります。

4

2 に答える 2

6

物理シミュレーションのステッピングタイミングをレンダリングvsyncタイミングから切り離す必要があります。最も簡単な解決策はこれを行うことです:

frameCallback(dt) {
  physicsDt += dt;
  if (physicsDt > 16) {
    stepPhysics();
    physicsDt -= 16;
  }
  renderWorld();
  requestAnimFrame(frameCallback);
}

ここでの最大の問題は、古い物理ワールドでレンダリングする場合があることです。たとえば、physicsDtが15の場合、シミュレーションの更新は行われませんが、オブジェクトはその時点までにほぼフレーム全体を移動します。これを回避するには、物理​​学をレンダリングの1フレーム前に保ち、レンダラーでオブジェクトの位置を線形補間します。何かのようなもの:

var t = dt/16.0;
framePosition = (1-t) * previousFramePositions + (t) * nextFramePositions;

これにより、レンダリングが物理シミュレーションと同期していない場合でも、オブジェクトがスムーズに移動します。ご不明な点がございましたら、お気軽にお問い合わせください。

ジョン

于 2012-10-23T19:07:28.793 に答える
1

requestAnimFrame一定のフレーム レートを保証することを意図したものではありません。ブラウザが実際に描画するフレームの計算のみを行うように設計されています。

描画されていないフレームを計算したい/計算しなければならない場合、それは道ではありません。

于 2012-10-23T18:48:12.087 に答える