Прежде чем кто-либо спросит, это для университетского проекта, и Я должен использовать GLUT .Я не отмечаю это как домашнее задание, потому что это не является обязательным требованием, и при этом у меня не будет дополнительных очков за это.
С GLUT, для незнакомых людей, у вас есть:
glutIdleFunc(func)
: регистрирует функцию рендеринга, и это означает, что когда GLUT больше ничего не делает, она вызовет эту функцию.Другими словами, он будет продолжать рендеринг как можно быстрее. glutTimerFunc(msecs, func, val)
: регистрирует функцию, которая будет вызываться в msecs
, и рекурсивная регистрация той же самой функции обеспечит движение с фиксированным временем.
Теперь я стараюсь избегать этих функций для этой цели и в большинстве обсуждений / статей, которые я нашел о GLUT, использую их для движения по времени.Итак, я пришел сюда еще раз ... Но если я не использую какие-либо из этих функций, как отображаются кадры?Я просто называю glutPostRedisplay
, и будет отрисован один кадр.
Мне удалось реализовать перемещение по времени в GLUT простым способом.Может быть не самая лучшая реализация, но она не слишком сложна и работает.Ну, есть только небольшая проблема, поэтому я здесь.
Движение моей камеры основано на втором законе движения Ньютона, где я вычисляю движение смещения следующим образом:
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;static int elapsedTime = 0;
previousTime = currentTime;
currentTime = glutGet(GLUT_ELAPSED_TIME);
elapsedTime = currentTime - previousTime;
return elapsedTime / 1000.0f;
}
Возможно, что-то не так с моим кодом таймера, верно?Я имею в виду, двигаясь вперед или вправо (положительные значения), проблем нет.Движение плавное и основанное на времени.Например, если я установлю скорость движения 5 м / с, на самом деле потребуется 25 секунд для перемещения на 25 метров (я предполагаю, что 1 м = 1,0f).
Итак, что я делаю неправильно стаймер, чтобы отрицательные значения начали двигаться вправо на долю секунды и только затем влево, как и должно быть?