誰かが尋ねる前に、これは大学のプロジェクトであり、GLUT を使用する必要があります。これは要件ではないため、宿題としてタグ付けしていません。また、これに対する追加のポイントもありません。
気づいていない人のために、GLUTを使用すると、次のようになります。
glutIdleFunc(func)
: render 関数を登録します。これは、GLUT が他に何もしていないときに、この関数を呼び出すことを意味します。つまり、可能な限り高速にレンダリングし続けます。glutTimerFunc(msecs, func, val)
: で呼び出される関数を登録しますmsecs
。同じ関数を再帰的に登録すると、固定時間ベースの移動が可能になります。
今、私はこの目的のためにこれらの機能を避けようとしています.GLUTについて私が見つけたほとんどの議論/記事は、それらを時間ベースの動きに使用しています. ということでまた来ました…でも、これらの機能を使っていない場合、フレームはどのようにレンダリングされるのでしょうか? 呼び出すだけglutPostRedisplay
で、1 つのフレームがレンダリングされます。
GLUT で時間ベースの動きを簡単な方法で実装することができました。最適な実装ではないかもしれませんが、複雑すぎず機能します。ちょっとした問題があるだけで、それが私がここにいる理由です。
私のカメラの動きは、ニュートンの運動の第 2 法則に基づいており、変位の動きは次のように計算されます。
Vector3D displacement = (CurrentVelocity * elapsedTime) +
(Acceleration * 0.5f * elapsedTime * elapsedTime);
これelapsedTime
は私のタイマーの実装によるもので、そこに問題があると思います。問題はdisplacement
、移動方向に応じて正または負になる必要がありますCurrentVelocity
が、非常に低い値 (つまり、-0.1f) の場合、displacement
負であるべきときに正になることです。コードの残りの部分はカメラを加速または減速します。そのため、問題は加速時にのみ発生します。これは、加速時CurrentVelocity
に が小さくなり、カメラがわずかに右 (正) に移動し、次に左 (負) に移動するためです。負の値を与えるのに十分な勢いを得displacement
ます。
シーンに動きがない場合、何もレンダリングされません。移動キーを押すと、次のようになります。
CameraDirection.z = CAMERA_WALK_BACKWARD;
SceneTimer.PostRedisplayWindow();
それも私のタイマークラスから来ています。私は呼び出す代わりにそれを行います。そのglutPostRedisplay
理由は次のとおりです。
void Timer::PostRedisplayWindow(void) {
currentTime = glutGet(GLUT_ELAPSED_TIME);
glutPostRedisplay();
}
(経過時間を計算する必要がcurrentTime
ある場合は になります)を取得する必要があり、次に を呼び出します。単一のフレームがレンダリングされます。つまり、が呼び出されます。previousTime
glutPostRedisplay
renderScene
void renderScene(void) {
(...)
glLoadIdentity();
elapsedTime = SceneTimer.GetElapsedTimeInSeconds();
SceneCamera.Move(CameraDirection, elapsedTime);
SceneCamera.LookAt();
drawCompleteScene();
glutSwapBuffers();
checkAnimationRedisplay();
}
ご覧のとおり、経過時間が計算され、その上でカメラが移動されます。シーン内のすべてが描画され、バッファーがスワップされ、何かをアニメーション化する必要があるかどうかを確認するこの追加関数があります。この場合、カメラが必要です。
void checkAnimationRedisplay(void) {
if(SceneCamera.IsCameraMoving()) {
glutPostRedisplay();
return;
}
}
glutPostRedisplay
カメラの動きが止まるまで呼び出し続けます。つまり、renderScene
毎回呼び出され、経過時間が計算され、時間に基づいてカメラが移動され、すべてが機能しています。さらに、もちろん、すでに述べた小さな不具合ですが、この長い質問を私に作成させたものはほとんどありません (申し訳ありません)。
欠けているのは、この質問の最も重要な関数であり、経過時間を計算する関数です。これは次のように単純です。
float Timer::GetElapsedTimeInSeconds(void) { static int previousTime = 0; 静的 int 経過時間 = 0;
previousTime = currentTime;
currentTime = glutGet(GLUT_ELAPSED_TIME);
elapsedTime = currentTime - previousTime;
return elapsedTime / 1000.0f;
}
おそらく私のタイマーコードに問題がありますよね?つまり、前または右 (正の値) に移動しても、問題はありません。動きはスムーズで時間ベースです。たとえば、移動速度を 5m/s に設定すると、実際には 25 メートル移動するのに 5 秒かかります (1m = 1.0f と仮定しています)。
それで、タイマーで何が間違っているので、負の値が一瞬右に移動し始め、次に左に移動し始めますか?