OpenGL камеры векторов - PullRequest
2 голосов
/ 04 апреля 2011

У меня очень элементарная камера, которая генерирует 3 вектора для использования с gluLookAt(...) проблема в том, что я не уверен, что это правильно, я адаптировал код из того, что показал мне мой лектор (я думаю, он откуда-то его получил).

Это на самом деле работает, пока вы не вращаете мышь по кругу, после чего камера начинает вращаться вокруг оси z.Этого не должно быть, поскольку координаты мыши привязаны только к полю и рысканию, а не крену.

Камера

// Camera.hpp

#ifndef MOOT_CAMERA_INCLUDE_HPP
#define MOOT_CAMERA_INCLUDE_HPP

#include <GL/gl.h>
#include <GL/glu.h>

#include <boost/utility.hpp>
#include <Moot/Platform.hpp>
#include <Moot/Vector3D.hpp>

namespace Moot
{
    class Camera : public boost::noncopyable
    {
    protected:

        Vec3f m_position, m_up, m_right, m_forward, m_viewPoint;
        uint16_t m_height, m_width;

    public:


        Camera()
        {
            m_forward = Vec3f(0.0f, 0.0f, -1.0f);
            m_right = Vec3f(1.0f, 0.0f, 0.0f);
            m_up = Vec3f(0.0f, 1.0f, 0.0f);
        }

        void setup(uint16_t setHeight, uint16_t setWidth)
        {
            m_height = setHeight;
            m_width = setWidth;
        }

        void move(float distance)
        {
            m_position += (m_forward * distance);
        }


        void addPitch(float setPitch)
        {
            m_forward = (m_forward * cos(setPitch) + (m_up * sin(setPitch)));
            m_forward.setNormal();

                    // Cross Product
            m_up = (m_forward / m_right) * -1;
        }


        void addYaw(float setYaw)
        {
            m_forward = ((m_forward * cos(setYaw)) - (m_right * sin(setYaw)));
            m_forward.setNormal();

                    // Cross Product
            m_right = m_forward / m_up;
        }


        void addRoll(float setRoll)
        {
            m_right = (m_right * cos(setRoll) + (m_up * sin(setRoll)));
            m_right.setNormal();

                    // Cross Product
            m_up = (m_forward / m_right) * -1;
        }

        virtual void apply() = 0;       

    }; // Camera
} // Moot

#endif

Фрагмент из цикла обновления

    // Mouse movement
    m_camera.addPitch((float)input().mouseDeltaY() * 0.001);
    m_camera.addYaw((float)input().mouseDeltaX() * 0.001);

apply () в классе камеры определено в унаследованном классе, который вызывается из функции draw игрового цикла.

void apply()
        {
            glMatrixMode(GL_PROJECTION);  
            glLoadIdentity();
            gluPerspective(40.0,(GLdouble)m_width/(GLdouble)m_height,0.5,20.0);

            m_viewPoint = m_position + m_forward;

            gluLookAt(  m_position.getX(),  m_position.getY(),  m_position.getZ(),
                        m_viewPoint.getX(), m_viewPoint.getY(), m_viewPoint.getZ(),
                        m_up.getX(),        m_up.getY(),        m_up.getZ());
        }

Ответы [ 3 ]

1 голос
/ 04 апреля 2011

Не накапливайте преобразования в ваших векторах, сохраняйте углы и генерируйте векторы на лету.

РЕДАКТИРОВАТЬ: стабильность с плавающей точкой.Сравните выходные данные a и b:

#include <iostream>

using namespace std;

int main()
{
    const float small = 0.00001;
    const unsigned int times = 100000;

    float a = 0.0f;
    for( unsigned int i = 0; i < times; ++i )
    {
        a += small;
    }
    cout << a << endl;

    float b = 0.0f;
    b = small * times;
    cout << b << endl;

    return 0;
}

Вывод:

1.00099
1
0 голосов
/ 04 апреля 2011

Возможно, вы захотите пересмотреть свой подход в пользу использования кватернионных вращений , как описано в этой статье .Преимуществом этого является представление всех ваших накопленных вращений в виде одного поворота вокруг одного вектора (необходимо отслеживать только один кватернион), который можно применять к векторам канонической ориентации (вверх, норма и право), описывающим ориентацию камеры,Кроме того, поскольку вы используете C ++, вы можете использовать класс Boost quaternion для управления математикой большинства из них.

0 голосов
/ 04 апреля 2011

Я не уверен, с чего начать, поскольку вы публикуете только небольшие фрагменты, которых недостаточно для полного воспроизведения проблемы.

В ваших методах вы обновляете все параметры, и ваши параметры зависят от предыдущих значений. Я не уверен, что именно вы звоните, потому что вы опубликовали, что вы называете только эти два:

m_camera.addPitch((float)input().mouseDeltaY() * 0.001);
m_camera.addYaw((float)input().mouseDeltaX() * 0.001);

Вы должны как-то разорвать этот круг, добавив новые параметры, и результат должен зависеть от ввода (например, m_position не должно зависеть от m_forward).

Вы также должны инициализировать все переменные в конструкторе, и я вижу, что вы инициализируете только m_forward, m_right и m_up (кстати, используйте список инициализации).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...