2012-02-10 4 views
2

openglとCで小さなゲームをプログラミングしています 問題が発生しました:クリッピングのため ...私のアニメーション(実際にはglutTimerFuncに基づいています)は定数ではありませんfps。 可変fpsは問題ありませんが、アニメーションは影響を受けるため、タイミングに対応していません。fps1、pos1; fps2、pos2; fps3、pos3 ... しかし、fpsが正規でない場合、アニメーションはそうではありません。 私はそれを次のように実装します:fps1、pos1;(fps1が描画されない場合)fps2、pos1; (フレームをスキップしたので、fps1の描画が終了しました。)fps3、pos3。タイミング(OpenGL)で流れるアニメーション

どうすればいいですか?私はclock()関数を使用しますが、常に0を返します

ps:howtoは強制的にOpenGLでv-syncですか?

答えて

1

OpenGLアップデートが垂直リトレースに同期されるかどうかは、プラットフォームによってOpenGLが自動的に結びついているため、プラットフォーム固有の方法で通知されます。 Mac上のインターフェイスデザイナーのチェックボックスには、WGL_EXT_swap_controlという名前のWGL拡張機能と、X11のGLX拡張機能があります。

垂直リトレース時に(MacのCVDisplayLinkを介して、悲しいことに私はWindows/Linuxの同等物ではない)コールバックをインストールする手段があるとし、物理を実行したいとします秒ごとに一定のステップ数で次のように書くことができます。

void myRetraceFunction() 
{ 
    static unsigned int timeError = 0; 
    static unsigned int timeOfLastFrame = 0; 

    unsigned int timeNow = getTimeNow(); // assume this returns in ms 

    // Get time since last frame. 
    // Since we ignore overflow here, we don't care that the result of 
    // getTimeNow presumably overflows. 
    unsigned int timeSinceLastFrame = timeNow - timeOfLastFrame; 

    // Store this so that we get correct results next time around. 
    timeOfLastFrame = timeNow; 

    // Establish the number of times to update physics per second, as the 
    // name says. So supposing it has been 0.5 of a second since we last 
    // drew, we'd want to perform 0.5*200 physics updates 
    const unsigned int numberOfTimesToUpdatePhysicsPerSecond = 200; 

    // calculate updates as (updatesPerSecond * timeSinceLastFrame/1000), 
    // because we're assuming time is in milliseconds and there are 1000 
    // of them in a second. What we'll do though is preserve any amount we'd 
    // lose by dividing here, so that errors balance themselves. 
    // 
    // We assume that timeSinceLastFrame will be small enough that we won't 
    // overflow here. 
    unsigned int timeSinceLastFrameNumerator = 
      timeSinceLastFrame * numberOfTimesToUpdatePhysicsPerSecond 
      + timeError; 

    // calculate how much of the numerator we're going to lose to 
    // truncation, so that we add it next frame and don't lose time 
    timeError = timeSinceLastFrameNumerator % 1000; 

    // calculate how many physics updates to perform 
    unsigned int physicsUpdatesToPerform = timeSinceLastFrameNumerator/1000; 

    // do the physics work... 
    while(physicsUpdatesToPerform--) 
     updatePhysics(); 

    // ... and draw a frame 
    drawFrame(); 
} 

このtimeErrorは丸めの問題を規制することです。例えば。あなたが一定の70フレーム/秒で稼働していて、物理更新が1秒間に60回更新されたとします。実際に累積したエラーを無視した場合、最後のフレームを描画してからの時間が物理更新に必要な時間が十分ではないという結論に至ります必要でした。また、物理更新レートの整数除数ではないフレームレートを使って、別の方法で行った場合には、別名の問題が発生します。

明示的リトレース機能がなく、フレームをプッシュして垂直リトレースでブロックする永続ループの場合は、同じ種類のものを書きます。

垂直リトレースをブロックする方法がない場合は、目標のフレームレートでタイマーをインストールし、垂直リトレース同期のふりをすることがあります。できるだけ早くフレームを押し出すことができますが、ラップトップや他のマシンを持っている人と誰かが苦情を受け取り、ファンが来ているときはかなり分かります。

+0

答えをいただきありがとうございますが、私はクロスプラットフォームの方法を探しています。正確には、フレームレンダリングの前後の値を取得しています。 – user1191175

+0

基本的なアルゴリズムの実装以外には、クロスプラットフォームの方法はありません。 (i)関数を適切に呼び出すためのプラットフォーム固有のコードを書く。 (ii)現在の時刻をミリ秒単位で取得する。そのため、SDLのようなクロスプラットフォームのライブラリは、 SDL_GetTicks。 – Tommy

関連する問題