Array ( )
Вход:




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

OpenGL: Камера - часть 2 - Вращение






Начальный код взят из прошлого урока - "Камера - часть 1". В этом уроке мы научимся
вращать камеру.
Итак, приступим.

файл init.cpp остается без изменений.

В файл main.h мы добавим только прототип функции вращения в класс камеры:

class CCamera:
public:
.......
.......
.......
    // Эта ф-я вращает камеру вокруг позиции в зависимости от переданных параметров.
    // Ротация сделана как осево-угловое вращение. Это значит, что вы передаете
    // ф-ии угол вращения и ось, вокруг которой нужно вращатся.
    void RotateView(float angle, float x, float y, float z);
};
 


Далее мы напишем реализацию вращения камеры.
Добавим новую функцию в файл camera.cpp:
///////////////////////////////// ROTATE VIEW \\\\*
/////
/////                     Вращение камеры вокруг оси
/////
///////////////////////////////// ROTATE VIEW \\\\*

void CCamera::RotateView(float angle, float x, float y, float z)
{
    CVector3 vNewView;
    CVector3 vView;

    // Получим наш вектор взгляда (направление, куда мы смотрим)
    vView.x = m_vView.x - m_vPosition.x;    //направление по X
    vView.y = m_vView.y - m_vPosition.y;    //направление по Y
    vView.z = m_vView.z - m_vPosition.z;    //направление по Z

    // Теперь, имея вектор взгляда, хранящийся в CVector3 "vView", мы можем вращать его.
    // Эта ф-я будет вызыватся, когда нужно повернутся налево-направо.
    // Итак, нам нужно вращаться вокруг нашей позиции. Представьте это примерно так:
    // скажем, мы стоим на месте, смотря вперед. Мы смотрим в какую-то точку, верно?
    // Теперь, если мы повернем голову налево или направо, направление взгляда изменится.
    // Соответственно переместится точка, на которую мы смотрим (вектор взгляда).
    // Вот почему мы изменяем m_vView - потому что это и есть вектор
    // взгляда. Мы будем вращать m_vView вокруг m_vPosition
    // по кругу, чтобы реализовать всё это.
    // Чтобы вращать что-то, используем синус и косинус. Для использования sin() & cos() мы
    // ранее подключили math.h.
    //
    // Чтобы реализовать вращение камеры, мы будем использовать axis-angle вращение.
    // Я должен предупредить, что формулы для рассчета вращения не очень просты, но
    // занимают не много кода. Axis-angle вращение позволяет нам вращать точку в пространстве
    // вокруг нужной оси. Это значит, что мы можем взять нашу точку взгляда (m_vView) и
    // вращать вокруг нашей позиции.
    // Чтобы лучше понять следующие рассчеты, советую вам посмотреть детальное
    // описание: http://astronomy.swin.edu.au/~pbourke/geometry/rotate/

    // Рассчитаем 1 раз синус и косинус переданного угла
    float cosTheta = (float)cos(angle);
    float sinTheta = (float)sin(angle);

    // Найдем новую позицию X для вращаемой точки
    vNewView.x  = (cosTheta + (1 - cosTheta) * x * x)   * vView.x;
    vNewView.x += ((1 - cosTheta) * x * y - z * sinTheta)   * vView.y;
    vNewView.x += ((1 - cosTheta) * x * z + y * sinTheta)   * vView.z;

    // Найдем позицию Y
    vNewView.y  = ((1 - cosTheta) * x * y + z * sinTheta)   * vView.x;
    vNewView.y += (cosTheta + (1 - cosTheta) * y * y)   * vView.y;
    vNewView.y += ((1 - cosTheta) * y * z - x * sinTheta)   * vView.z;

    // И позицию Z
    vNewView.z  = ((1 - cosTheta) * x * z - y * sinTheta)   * vView.x;
    vNewView.z += ((1 - cosTheta) * y * z + x * sinTheta)   * vView.y;
    vNewView.z += (cosTheta + (1 - cosTheta) * z * z)   * vView.z;

    // Теперь просто добавим новый вектор вращения к нашей позиции, чтобы
    // установить новый взгляд камеры.
    m_vView.x = m_vPosition.x + vNewView.x;
    m_vView.y = m_vPosition.y + vNewView.y;
    m_vView.z = m_vPosition.z + vNewView.z;
}


Теперь включим вращение в нашем главном файле, main.cpp.
Кроме того, мы уберём обработку клавиш из WinProc(), так как это не самый
быстрый способ.

Файл main.cpp

// Добавим в файл функцию обработки ввода:
//////////////////////////// CHECK FOR MOVEMENT \\\*
/////
/////   Эта функция обрабатывает нажатия клавиатуры быстрее WinProc()
/////
//////////////////////////// CHECK FOR MOVEMENT \\\*

void CheckForMovement()
{
    // Функция GetKeyState() возвращает true или false
    // в зависимости от того, нажата ли переданная ей клавиша.
    if(GetKeyState(VK_UP) & 0x80)
        g_Camera.MoveCamera(kSpeed);

    if(GetKeyState(VK_DOWN) & 0x80)
        g_Camera.MoveCamera(-kSpeed);

    //Вращаем вокруг оси Y
    if(GetKeyState(VK_LEFT) & 0x80)         // Если нажали "влево"
        g_Camera.RotateView(kSpeed*2,0,1,0);    // Вращаем с положит. скоростью

    if(GetKeyState(VK_RIGHT) & 0x80)        // Если "вправо"
        g_Camera.RotateView(-kSpeed*2,0,1,0);   // С отрицательной
}

// Далее, немного изменим функцию MainLoop(). Перед вызовом функции
// RenderScene() вызовем только что написанную CheckForMovement():
///////////////////////////////// MAIN GAME LOOP \\\\*
/////
/////               Основной игровой цикл
/////
///////////////////////////////// MAIN GAME LOOP \\\\*

WPARAM MainLoop()
{
.............................................
.............................................
.............................................
            CheckForMovement();
            RenderScene();
.............................................
.............................................
}

// Немного изменим функцию RenderScene(). Вместо одного треугольника
// нарисуем 10, расположенных вертикально:

void RenderScene()
{
.............................................
    //Рисуем треугольнег =)
    glBegin (GL_TRIANGLES);

    //Нарисуем 10 3угольников в ряд
    for(float i = -10; i < 0; i++){
        glColor3ub(255, 0, 0);
        glVertex3f(0, 1, i);

        glColor3ub(0, 255, 0);
        glVertex3f(-1, 0, i);

        glColor3ub(0, 0, 255);
        glVertex3f(1, 0, i);
    }

    glEnd();
    SwapBuffers(g_hDC);
}


// Ну и наконец WinProc(). Уберём из него обработку всех клавиш кроме VK_ESCAPE:
    case WM_KEYDOWN:
        switch(wParam) {
            case VK_ESCAPE:
                PostQuitMessage(0);
                break;
        }
        break;
 



В этом уроке мы научили камеру вращатся. Также мы поправили ввод с клавиатуры,
убрав его из WinProc().
Позже мы сделаем управление мышью, как в большинстве шутеров.
Также можно сделать какие-нибуть стены и уровни, чтобы можно было даже
пройтись по нашему миру =)







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




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

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












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