Возникла небольшая проблема с перемещением камеры в зависимости от времени, проведенного с использованием GLUT/OpenGL
Прежде чем кто-то спросит, это для университетского проекта, и я должен использовать 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).
Итак, что я делаю не так с таймером, так что отрицательные значения начинают двигаться вправо на доли секунды и только потом влево, как и должно быть?
1 ответ
Один ответ, который решает мою проблему, можно найти здесь: https://gamedev.stackexchange.com/questions/10902/having-a-slight-problem-moving-my-camera-based-on-time-passed-using-glut-opengl