Реализация strafe — Opengl — камеры

#opengl #camera

#opengl #камера

Вопрос:

Я создал класс camera. С помощью моей мыши можно поворачивать на 360 градусов и перемещаться вверх и вниз. Как я и предполагал, как и во всех играх. Также возможно перемещаться вперед и назад, как и во всех играх. Но я не знаю, как реализовать перемещение влево и вправо.

Я делаю следующее:

Это вызывается в каждом кадре:

 gluLookAt(_posX , _posY , _posZ,
          _viewX, _viewY, _viewZ,
          _upX,   _upY,   _upZ );
  

Моя функция перемещения
Не работает:

 void Camera::moveLeft() 
{

    float rot= (_viewY / 180 * PI);
    _moveX -= float(cos(rot)) * 0.5;
    _moveZ -= float(sin(rot)) * 0.5;
}
  

Работает

перемещение вперед в сцене:

 void Camera::moveForward() 
{

    float viewX = _viewX - _posX;
    float viewY = _viewY - _posY;
    float viewZ = _viewZ - _posZ;

    _posX  = viewX * speed
    _posY  = viewY * speed;
    _posZ  = viewZ * speed;

    _viewX  = viewX * speed;
    _viewY  = viewY * speed;
    _viewZ  = viewZ * speed;

}
  

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

Есть идеи, как это решить?

Спасибо

@редактировать

Итак, я удалил инструкцию glTranslated и изменил свою функцию moveLeft на следующую:


void Camera::moveLeft(){

 float x = ((_viewY * _upZ) - (_viewZ * _upY));
float y = ((_viewZ * _upX) - (_viewX * _upZ));
float z = ((_viewX * _upY) - (_viewY * _upX));

float magnitude = sqrt( (x * x)   (y * y)   (z * z) );

x /= magnitude;
y /= magnitude;
z /= magnitude;

_posX -= x;
_posY -= y;
_posZ -= z;
  

}

Я явно делаю что-то не так, потому что движения влево и вправо «лучше», но все равно не то, что вы ожидаете.

Ответ №1:

Чтобы получить вектор, который указывает под углом 90 градусов к плоскости, содержащей ваши векторы up и view, вам нужно выполнить перекрестное произведение: http://en.wikipedia.org/wiki/Cross_product. Любая приличная библиотека векторной математики будет иметь функцию для этого.

Результирующий вектор будет либо левым вектором, либо правым вектором (попробуйте и выясните, какой именно), а затем добавьте его в свою позицию соответствующим образом.

Обратите внимание, что это не сработает, если ваш вектор обзора находится точно в том же направлении, что и ваш вектор вверх.

Редактировать: Основываясь на вашем отредактированном вопросе, я думаю, вам нужно сделать это:

Вам нужно получить вектор направления обзора и использовать его вместо вашего вектора вида в перекрестном произведении, а затем добавить как к позиции, так и к вектору вида:

 void Camera::moveLeft() 
{

    float viewX = _viewX - _posX;
    float viewY = _viewY - _posY;
    float viewZ = _viewZ - _posZ;

    float x = ((viewY * _upZ) - (viewZ * _upY));
    float y = ((viewZ * _upX) - (viewX * _upZ));
    float z = ((viewX * _upY) - (viewY * _upX));

    float magnitude = sqrt( (x * x)   (y * y)   (z * z) );

    x /= magnitude;
    y /= magnitude;
    z /= magnitude;

    _posX -= x;
    _posY -= y;
    _posZ -= z;

    _viewX -= x;
    _viewY -= y;
    _viewZ -= z;
}
  

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

1. Не могли бы вы еще раз прочитать мой вопрос, если у вас есть время, я его отредактировал. Спасибо

2. Это должно быть _viewX -= x, …-= y, …-= z . Вероятно, это была опечатка. Но это работает, большое вам спасибо за вашу помощь.