Урок 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 до клавіатури