Array ( )
Вход:




Главная | OpenGL | GLSL | AI | Сеть | Примеры | Библиотека

OpenGL: Камера - часть 1






В цикле уроков "Камера" мы научимся двигатся в нашем мире, управляя клавиатурой,
а впоследствии и мышью. Этот, первый урок камеры, задаст базу для дальнейшего развития.
Здесь мы создадим класс камеры и научимся хоть как-то двигатся.

Первоначальный код взят из предидущего урока, "FPS".

Итак, первый файл, main.h.
В него мы добавим обьявления классов CVector и CCamera.
Возможно, вы обратите внимание, что этот хидер немного беспорядочный -
позже мы создадим другой хидер и разделим данные.

Также в хидер мы добавим глобальный экземпляр класса CCamera - gCamera.
Таким образом любой файл сможет получить доступ к позиции и направлению камеры.

Файл main.h:
// К остальным инклудам добавим math.h - он нам пригодится.
#include <math.h>


// *Vector Class*
// Это начало нашего класса "Vector". В начале он будет совсем простой, но по мере роста класс
// повысит функциональность, возникнет больше типов данных.
// Отныне мы будем использовать его для класса камеры.
// Пока что нам нужно просто запоминание X,Y,Z. Пока это будет больше похоже на
// структуру, а не на класс.

class CVector3 {    // Буква "C" перед именем означает, что перед нами класс.

public:     // Мы не будем использовать контроль доступа и запихнем всё в public.
    float x, y, z;  // Просто float для X,Y,Z
};


// *Camera Class*
// Будет использоватся для запоминания позиции камеры, нашего взгляда и вертикального вектора.
// Сейчас у нас есть 3 CVector'а, которые будут запоминать эту информацию.
// Кроме того, пара вспомогательных функций. Мы сделаем все данные
// public, чтобы в любой момент узнать свою позицию.
// Т.к. все данные - public, можно было использовать структуру.
// Но я стараюсь все, что содержит в себе методы, делать классом.

class CCamera {

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
/////
///////////////////////////////// CCAMERA \\\\\\\\\\\\\\\\*

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;
}

///////////////////////////////// POSITION CAMERA \\\\\\\\\\\\\\\\*
/////
/////   Устанавливает позицию, взгляд, верт. вектор камеры
/////
///////////////////////////////// POSITION CAMERA \\\\\\\\\\\\\\\\*

GLvoid CCamera::PositionCamera(float positionX, float positionY, float positionZ,
        float viewX, float viewY, float viewZ,
        float upVectorX, float upVectorY, float upVectorZ)
{
    CVector3 vPosition  = {positionX, positionY, positionZ};
    CVector3 vView      = {viewX, viewY, viewZ};
    CVector3 vUpVector  = {upVectorX, upVectorY, upVectorZ};

    //Обширный код просто делает легче назначение переменных.
    //Можно просто сразу присвоить переменным класса переданные функции значения.

    m_vPosition = vPosition;
    m_vView = vView;
    m_vUpVector = vUpVector;
}


///////////////////////////////// MOVE CAMERA \\\\\\\\\\\\\\\\*
/////
/////   Движение камеры вперед-назад с заданной скоростью
/////
///////////////////////////////// MOVE CAMERA \\\\\\\\\\\\\\\\*

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);
}


//*************************************************************************
// В функции RenderScene(), после вызова CalculateFrameRate(), добавьте:

    // Скормим OpenGL данные камеры
    gluLookAt(g_Camera.m_vPosition.x, g_Camera.m_vPosition.y, g_Camera.m_vPosition.z,
          g_Camera.m_vView.x,     g_Camera.m_vView.y,     g_Camera.m_vView.z,
          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;

            case VK_UP:         // Если нажали "вверх"
                // Движемся вперед - с положительной скоростью
                g_Camera.MoveCamera(kSpeed);
                RenderScene();      // Перерисовываем сцену
                break;

            case VK_DOWN:           // Если "вниз"
                // Движемся назад - с отрицательной скоростью
                g_Camera.MoveCamera(-kSpeed);
                RenderScene();          // Перерисовываем сцену
                break;
        }
        break;
//*************************************************************************


Это всё. Если вы скомпилируете программу, то сможете двигатся вперед назад
около небольшого треугольника, нарисованного для ориентировки.
В дальнейших уроках мы расширим функционал камеры, добавим вращение, стрейф
и многое другое.







Исходные коды к уроку




Комментарии:

Войдите, чтобы оставить комментарий:












Яндекс.Метрика
 Яндекс цитирования.