Возникла небольшая проблема с перемещением камеры в зависимости от времени, проведенного с использованием 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

Другие вопросы по тегам