Как мне реализовать камеру от первого лица?


12

Я начинающий программист, и я создаю проект, который позволяет мне ходить по комнатам с помощью камеры от первого лица. До сих пор я рисовал здания и продолжал, но теперь я застрял и не знаю, как сделать камеру от первого лица, чтобы я мог ходить вокруг.

Кто-нибудь может указать мне на класс камеры, который я мог бы использовать, или какой-нибудь полезный код?


Ответы:


7

Вот несколько советов по повороту камеры (мышиный взгляд). После наивной реализации класса камеры с нуля, я обнаружил, что мне пришлось сделать несколько дополнительных настроек для хорошего поведения вращения:

  1. Сбрасывайте координаты мыши по центру экрана в каждом кадре, чтобы мышь не попадала на границы экрана

  2. Сохраните вектор «вверх» камеры (запретить поворот) и пересчитайте вектор «в сторону»

  3. Не разрешать смотреть вверх за вертикальную ось + ось или вниз за ось -у (слишком далеко вверх / вниз)

  4. Получите правильный порядок поворотов (сначала вверх / вниз, затем влево / вправо)

  5. Перенормируйте векторы «вверх», «цель» и «в сторону» в каждом кадре

Надеюсь, вы можете использовать часть этого кода в ваших интересах:

    const int mouseDeltaX = mouseAxisX * (input.GetMouseX() - int(app.GetWidth()/2));
    const int mouseDeltaY = -mouseAxisY * (input.GetMouseY() - int(app.GetHeight()/2));  // mouse y-offsets are upside-down!

    // HACK:  reset the cursor pos.:
    app.SetCursorPosition(app.GetWidth()/2, app.GetHeight()/2);

    float lookRightRads = mouseDeltaX * CAMERA_ANGULAR_SPEED_DEG * DEG_TO_RAD;
    float lookUpRads    = mouseDeltaY * CAMERA_ANGULAR_SPEED_DEG * DEG_TO_RAD;

    // Limit the aim vector in such a way that the 'up' vector never drops below the horizon:
    static const float zenithMinDeclination = DEG_TO_RAD * MIN_UPWARDS_TILT_DEG;
    static const float zenithMaxDeclination = DEG_TO_RAD * (180.0f - MIN_UPWARDS_TILT_DEG);

    const float currentDeclination = std::acosf(camera.aim_.y_);  ///< declination from vertical y-axis
    const float requestedDeclination = currentDeclination - lookUpRads;

    // Clamp the up/down rotation to at most the min/max zenith:
    if(requestedDeclination < zenithMinDeclination)
        lookUpRads = currentDeclination - zenithMinDeclination;
    else if(requestedDeclination > zenithMaxDeclination)
        lookUpRads = currentDeclination - zenithMaxDeclination;

    // Rotate both the "aim" vector and the "up" vector ccw by 
    // lookUpRads radians within their common plane -- which should 
    // also contain the y-axis:  (i.e. no diagonal tilt allowed!)
    camera.aim_.rotateAboutAxis(camera.right_, lookUpRads);
    camera.up_.rotateAboutAxis(camera.right_, lookUpRads);
    ASSERT_ORTHONORMAL(camera.aim_, camera.up_, camera.right_);

    // Rotate both the "aim" and the "up" vector ccw about the vertical y-axis:
    // (again, this keeps the y-axis in their common plane, and disallows diagonal tilt)
    camera.aim_.rotateAboutAxis(Y_AXIS, -lookRightRads);
    camera.up_.rotateAboutAxis(Y_AXIS, -lookRightRads);
    camera.updateRightAxis();

Обратите внимание, что:

mouseAxisX и mouseAxisY определены как +/- 1, в зависимости от того, хотите ли вы инвертировать вид мыши по оси x или y. Обычно игры предлагают эту опцию хотя бы для вертикальной оси.

MIN_UPWARDS_TILT_DEG определено равным 1,0 градусу (поэтому зрителю разрешено смотреть от -89 градуса вниз до +89 градуса вверх, что довольно убедительно выглядит как полный вертикальный диапазон 180 градусов - пропущенные 2 градуса в крайних значениях весьма незначительны) ,

camera.aim_, camera.right_ и camera.up_ - это, конечно, 3D-векторы, и метод rotateAboutAxis (), который вы можете объединять в википедии и любом количестве онлайн-источников. Y_AXIS - вектор с фиксированной константой (0,1,0).

ASSERT_ORTHONORMAL () - это проверка работоспособности только в режиме отладки, которая никогда не компилируется в режиме оптимизации / выпуска.

Заранее извиняюсь за код в стиле C ... опять же, вот вам совет от парня по имени Mediocritus! ; ^)


О чем ты говоришь? Код в стиле C является краеугольным камнем хакерского духа! 8-)
блаженство

5

Есть несколько способов сделать это (см. Учебники здесь , здесь и здесь, например, с большим количеством других доступных в Интернете через Google). Технология, используемая в ресурсах, которые вы можете найти в Интернете, может незначительно отличаться (с точки зрения D3D, XNA, OpenGL и так далее), но основные принципы будут такими же:

  • Ваш объект камеры сохраняет свое положение и направление, и, необязательно, другую пару векторов, которые наряду с направлением образуют ортогональную основу для системы координат камеры.
  • Публичный API вашей камеры предоставляет методы рыскания, качки и, при необходимости, прокручивания камеры вокруг ее базовых векторов - акт настройки ориентации камеры обновит базовые векторы для последующего использования.

Вы можете выбрать сохранение векторов напрямую или пересчитывать базовую матрицу представления каждый раз, когда вам нужно и что вы предпочитаете. Методика очень гибкая, поэтому, если вам нужна помощь, помимо этих общих шагов, вы можете опубликовать новый вопрос с более конкретным запросом.


2

Для конкретной ссылки на реализацию системы камер с использованием Direct3D я рекомендую эту статью: http://www.toymaker.info/Games/html/camera.html . Автор также описывает другие методы и функции, которые могут быть использованы для расширения реализации.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.