Камера - частина 1, Уроки та приклади програмування
У циклі уроків "Камера" ми навчимося рухатися в нашому світі, керуючи клавіатурою, а потім і мишею. Цей перший урок камери задасть базу для подальшого розвитку. Тут ми створимо клас камери і навчимося хоч якось рухаються.
Початковий код взято з попереднього уроку, "FPS".
Отже, перший файл main.h. У нього ми додамо оголошення класів CVector та CCamera. Можливо, ви звернете увагу, що цей хидер трохи безладний - пізніше ми створимо інший хидер і розділимо дані.
Також до хидера ми додамо глобальний екземпляр класу CCamera - gCamera. Таким чином будь-який файл зможе отримати доступ до позиції та напрямку камери.
// До решти інклудів додамо math.h - він нам знадобиться. #include
// *Vector Class* // Це початок нашого класу "Vector". На початку він буде дуже простий, але зі зростанням клас // підвищить функціональність, виникне більше типів даних. // Відтепер ми будемо використовувати його для класу камери. // Поки що нам потрібно просто запам'ятовування X, Y, Z. Поки що це буде більше схоже на структуру, а не на клас.
public // Ми не будемо використовувати контроль доступу і запхнемо все в public. float x, y, z; // Просто float для X, Y, Z & gt; ;
// *Camera Class* // Буде використовується для запам'ятовування позиції камери, нашого погляду та вертикального вектора. // Зараз у нас є 3 CVector'и, які запам'ятовуватимуть цю інформацію. // Крім того, пара допоміжних функцій. Ми зробимо всі дані // public, щоб у будь-який момент дізнатися про свою позицію. // Т.к. всі дані - public, можна було використовувати структуру. // Але я намагаюся все, що містить у собі методи, робити класом.
CVector3 m_vPosition; // Позиція камери. CVector3 m_vView; // Напрямок камери. CVector3 m_vUpVector; // Вертикальний вектор.
//На початку змінних підписуємо "m", т.к. це "member"-змінні. //"v" додаємо, т.к. це члени класу Vector (починається V).
// Конструктор класу Camera CCamera ();
// Тут змінюється становище, напрям і верт. вектор камери. // В основному використовується при ініціалізації. void PositionCamera (float positionX, float positionY, float positionZ, float viewX, float viewY, float viewZ, float upVectorX, float upVectorY, float upVectorZ);
// Ця ф-я пересуває камеру вперед / назад void MoveCamera (float speed); > ;
// Ну і нарешті додамо глобальну змінну даних камери. extern CCamera g_Camera; // Глобальні дані камери
// Все інше у файлі залишається без змін.
Файл Init.cpp залишився без змін.
Тепер переходимо до файлу camera.cpp, у якому буде описано реалізацію класу камери. Для початку реалізуємо просте переміщення вперед-назад, ускладнюватимемо у наступних уроках. Файл camera.cpp :
// Включаємо наш хидер #include "main.h"
CCamera :: CCamera ( ) < //Ініціалізуємо вектор нашої позиції в нульові координати CVector3 vZero = < 0.0, 0.0, 0.0 >; CVector3 vView = < 0.0, 1.0, 0.5 >; // Ініці. вектор погляду CVector3 vUp = < 0.0, 0.0, 1.0 >; // Вертикальний вектор
m_vPosition = vZero; m_vView = vView; m_vUpVector = vUp; >
GLvo >:: PositionCamera ( float positionX , float positionY , float positionZ , float viewX , float viewY , float viewZ , float upVectorX , float upVectorY , float upV> CVector3 vPosition = <positionX, positionY, positionZ >; CVector3 vView = < viewX, viewY, viewZ >; CVector3 vUpVector = < upVectorX, upVectorY, upVectorZ >;
//Обширний код легко легше призначення змінних. //Можна просто відразу присвоїти змінним класу передані функції значення.
m_vPosition = vPosition; m_vView = vView; m_vUpVector = vUpVector; >
void CCamera :: MoveCamera (float speed) < CVector3 vVector = < 0 >; //Ініц. вектор напряму погляду
// Отримуємо вектор напряму. Щоб отримати вектор із 2х // точок, ми віднімаємо першу точку з другої. // Це дає нам напрям, куди ми дивимося. // Пізніше ми напишемо ф-ю, що обчислює напрямок // по-іншому.
//Отримуємо напрям погляду (напр-е, куди ми повернуті "обличчям") vVector. x = m_vView. x - m_vPosition. x; //Напрямок X vVector. y = m_vView. y - m_vPosition. y; //Напрямок Y vVector. z = m_vView. z - m_vPosition. z; //Напрямок Z
// Наступний код рухає камеру вперед чи назад. // Ми додаємо до поточного положення напрям погляду, помножений на швидкість. // Можливо, ви думаєте, що простіше було б просто додати до позиції швидкість. Так, // зараз це спрацює - ви дивіться прямо по осі Х. Але як тільки почнеться обертання, код // перестане діяти. Повірте мені. // Отже, якщо ми дивимося в напрямку 45 градусів, ми й підемо в цьому напрямку. // Якщо рухаємося назад - просто передаємо у ф-ю негативну швидкість.
m_vPosition. x + = vVector. x * speed; m_vPosition. z + = vVector. z * speed; m_vView. x + = vVector. x * speed; m_vView. y + = vVector. z * speed;
// Це все. Зовсім не складний клас, що дозволяє нам хочякось рухатися у світі =)
Ну, а тепер використовуємо наш новий клас. Файл main.cpp :
// Десь угорі файлу додайте: #define kSpeed 0.03f //Як швидко рухається камера
// Оголосимо клас камери, визначений як extern в main.h: CCamera g_Camera;
// У функцію Init() додамо визначення камери. // Тепер функція виглядає так: void Init ( HWND hWnd ) < g_hWnd = hWnd; GetClientRect (g_hWnd, & g_rRect); InitializeOpenGL (g_rRect. right, g_rRect. bottom);
Font = new CFont ("arial.ttf", 16, 16); FPS = 0;
// Нижче ми ініціалізуємо камеру. Встановлюємо позицію, з якої дивитися на // кольоровий трикутник. // Пам'ятайте, ця ініціалізація необхідна тільки _одноразово_, // і більше ми її викликати не будемо.
// Позиція Напр-е верт. вектор g_Camera. PositionCamera (0, 0.5f, 6, 0, 0.5f, 0, 0, 1, 0); >
// Скормимо OpenGL дані камери gluLookAt ( g_Camera. m_vPosition . x , g_Camera. m_vPosition . y , g_Camera. , g_Camera.m_vUpVector.x, g_Camera.m_vUpVector.y, g_Camera.m_vUpVector.z);
// І малюємо трикутник =) glBegin (GL_TRIANGLES); glColor3ub (255, 0, 0); glVertex3f (0, 1, 0);
glColor3ub (0, 255, 0); glVertex3f (-1, 0, 0);
glColor3ub (0, 0, 255); glVertex3f (1, 0, 0); glEnd ();
// І, нарешті, внесемо зміни до функції WinProc, до секції обробки клавіш. // Тепер код case WM_KEYDOWN виглядає так: case WM_KEYDOWN : switch ( wParam ) < case VK_ESCAPE : PostQuitMessage (0); // Виходимо break;
caseVK_UP : // Якщо натиснули "вгору" // Рухаємося вперед - з позитивною швидкістю g_Camera. MoveCamera (kSpeed); RenderScene ( ); // Перемальовуємо сцену break;
case VK_DOWN : // Якщо "вниз" // Рухаємося назад - з негативною швидкістю g_Camera. MoveCamera (-kSpeed); RenderScene ( ); // Перемальовуємо сцену break; > break; //********************************************* ****************************
Це все. Якщо ви скомпілюєте програму, то зможете рухатися вперед назад біля невеликого трикутника, намальованого для орієнтування. У подальших уроках ми розширимо функціонал камери, додамо обертання, стрейф і багато іншого.