Урок 6 Клавіатура та миша

Ласкаво просимо до нашого шостого уроку!

Настав час дізнатися, як використовувати клавіатуру та мишу, щоб переміщати камеру так само, як і в іграх жанру FPS.

Так як код цього уроку буде використовуватися надалі, ми помістимо його в окремий файл common/controls.cpp і оголосимо необхідні функції common/controls.hpp, таким чином tutorial06.cpp буде їх бачити.

Код цього уроку мало відрізнятиметься від попередніх. Головна відмінність полягає в тому, що тепер ми обчислюватимемо MVP матрицю не один раз, а в кожному кадрі, тому давайте перейдемо до коду головного циклу:

Цей уривок коду має 3 нові функції:

  • computeMatricesFromInputs() обчислює Проекційну та Видову матриці залежно від поточного введення. Це функція, де відбувається основна робота.
  • getProjectionMatrix() просто повертає обчислену проекційну матрицю.
  • getViewMatrix() просто повертає обчислену видову матрицю.

Звичайно ж, зазначений спосіб - один з небагатьох, яким ви можете слідувати.

Тепер перейдемо безпосередньо до controls.cpp

Основний код

Отже, нам знадобиться кілька змінних:

FoV - це "рівень зуму". 80 = дуже широкий кут огляду, сильні деформації. Значення від 60 до 45 є стандартним. 20 – це сильний зум.

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

Читання позиції миші – це просто:

однак, нам важливо не забути про переміщення курсору назад до центру екрана, щоб він не виходив за межі вікна:

Зверніть увагу, що цей код передбачає, що розмір вікна - 1024*768, що не завждибуде істиною, тому найкращим рішенням буде використовувати glfwGetWindowSize().

Тепер ми можемо обчислити наші кути:

Давайте розберемо цей код праворуч наліво:

  • 1024/2 – xpos означає, як миша знаходиться від центру вікна. Що далі, то більше буде поворот.
  • float(…) наводить значення у дужках до речового типу.
  • mouseSpeed ​​- це швидкість, з якою відбуватиметься поворот (чутливість миші).
  • += : Якщо ви не перемістили мишу, то 1024/2 - xpos дорівнюватиме 0, значить horizontalAngle+=0 не змінить кут.

We can now compute a vector that represents, in World Space, the direction in which we’re looking

Зараз нам необхідно обчислити вектор у Світовому просторі, який вказуватиме напрям погляду:

Це стандартне обчислення, але якщо ви не знаєте про синус і косинус, то ось невелика ілюстрація:

урок

Тепер нам необхідно визначити вектор “up”. Тобто вектор вказує напрямок вгору для камери. Зверніть увагу, що він не завжди дорівнює +Y. Наприклад, якщо ви дивитеся вниз, то вектор up буде горизонтальним.

вектор

У нашому випадку, єдине, що залишається незмінним – це вектор, який спрямований праворуч від камери.

Отже, у нас є вектор Вправо і є напрямок (вектор Вперед), тоді вектор "вгору" - це вектор, який їм перпендикулярний, а щоб його отримати - потрібно скористатися векторним твором:

Щоб запам'ятати що робить векторний твір, спробуйте згадати Правило правої руки з Уроку 3. Перший вектор - це великий палець; Другий вектор – це вказівний палець; Результатом буде ваш середній палець.

Єдина незрозуміла річ у цьому коді – це deltaTime. Якщо мипросто помножимо вектор на швидкість, то отримаємо неприємні ефекти:

  • Якщо у вас швидкий комп'ютер і програма працює з частотою кадрів 60, то ви пересуватиметеся зі швидкістю 60 юнітів в секунду.
  • Якщо ж у вас повільний комп'ютер і частота кадрів = 20, то ви пересуватиметеся зі швидкістю 20 юнітів в секунду.

Таким чином той, хто має швидкий комп'ютер, буде рухатися швидше, тому ми вводимо змінну, в яку заносимо час, що минув з останнього кадру. За допомогою GLFW воно обчислюється так:

Для розваги ми можемо також прив'язати колесо мишки до змінної FoV і змінювати таким чином Поле огляду, що в результаті дасть нам такий собі зум:

Ми вже використовували всі функції, наведені нижче у попередніх уроках, тільки тепер ми використовуємо інші параметри:

##Відсікання задніх граней

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

Щоб не виводити невидимі грані, а відповідно підвищити швидкодію, нам необхідно перевіряти де знаходиться камера щодо полігону (спереду або ззаду). Хороша новина у тому, що цю перевірку дуже просто реалізувати. GPU повинен обчислити нормаль полігону (використовуючи векторний твір, пам'ятаєте?) та перевіряє, як орієнтована нормаль по відношенню до камери.

Проте, є один нюанс. Векторний твір не є комутативним. Це означає, що порядок, в якому ви множите вектори є важливим фактором в результаті. Тобто, якщо ви переплутаєте порядок, то отримаєте неправильну нормаль, а отжезможете розраховувати освітлення (надалі) і відсікання невидимих ​​граней працюватиме неправильно.

Увімкнення режиму відсікання полігонів виконується лише однією командою:

Вправи

    Зробіть так, щоб ви не могли пересуватися вниз або вгору

Створіть камеру, яка обертатиметься навколо заданого об'єкта. Підказка:

прив'яжіть radius, height, time до клавіатури