Як я повинен реалізувати камеру від першої особи?


12

Я початківець програміст і створюю проект, який дозволяє мені ходити по кімнатах через камеру від першої особи. Поки що у мене будівлі намальовані і ввімкнуті, але зараз я застряг і не знаю, як зробити камеру від першої особи, яка дозволить мені ходити.

Чи міг би хтось вказати мені на клас камери, який я міг би використовувати, чи якийсь корисний код?


Відповіді:


7

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

  1. Скиньте координати миші на центр екрану на кожному кадрі, щоб миша ніколи не потрапляла на межі екрана

  2. Підтримуйте вектор "камери" вгору (забороняйте перекидання) та перераховуйте вектор "набік"

  3. Заборонити дивитися вгору по вертикалі + осі y або вниз по осі -y (занадто далеко вгору / вниз)

  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 градусів - відсутні два градуси в крайніх межах досить незначні) .

camera.aim_, camera.right_ і camera.up_ - це звичайно тривимірні вектори, і метод rotateAboutAxis (), який ви можете спільно використовувати з wikipedia та будь-якої кількості Інтернет-джерел. Y_AXIS - фіксований постійний (0,1,0) вектор.

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

Заздалегідь вибачте за код у стилі С ... потім знову, ви отримуєте поради від хлопця на ім'я Медіокрит! ; ^)


Про що ти говориш? Код у стилі 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.