OpenGL FPS Движение камеры относительно цели

У меня есть камера в OpenGL, у меня не было проблем с ней до добавления контроллера FPS. Проблема в том, что с основным поведением FPS все в порядке. Камера движется вперед, назад, влево и вправо + вращается в направлении, определяемом вводом мыши. Проблемы начинаются, когда камера перемещается в стороны или назад от целевой позиции. В таком случае камера локально вперед, назад, влево, вправо направления не обновляются на основе текущего прямого взгляда, но остаются такими же, как если бы он находился прямо перед целью. Пример: если положение целевого объекта находится в (0,0,0), а положение камеры - в (-50 , 0,0) (слева от цели) и камера смотрит на цель, затем, чтобы перемещать ее вперед и назад, я должен использовать клавиши для перемещения влево и вправо, в то время как клавиши назад / вперед перемещают камеру в сторону. Вот код, который я использую для расчета положения камеры, поворота и матрицы LookAt:

void LookAtTarget(const vec3 &eye,const  vec3 &center,const  vec3 &up)
{


    this->_eye = eye;
    this->_center = center;
    this->_up = up;
    this->_direction =normalize((center - eye)); 

    _viewMatrix=lookAt( eye,  center , up);
    _transform.SetModel(_viewMatrix );
    UpdateViewFrustum();
}

void SetPosition(const vec3 &position){
    this->_eye=position;
    this->_center=position + _direction;
    LookAtTarget(_eye,_center,_up);
}
void SetRotation(float rz , float ry ,float rx){
    _rotationMatrix=mat4(1);
    vec3 direction(0.0f, 0.0f, -1.0f);
    vec3 up(0.0f, 1.0f, 0.0f);

    _rotationMatrix=eulerAngleYXZ(ry,rx,rz);
    vec4 rotatedDir= _rotationMatrix * vec4(direction,1) ;
    this->_center = this->_eye + vec3(rotatedDir);

    this->_up =vec3( _rotationMatrix * vec4(up,1));

    LookAtTarget(_eye, _center, up);


}

Затем в цикле рендеринга я установил трансформации камеры:

 while(true)
{
    display();
    fps->print(GetElapsedTime());
    if(glfwGetKey(GLFW_KEY_ESC) || !glfwGetWindowParam(GLFW_OPENED)){
        break;
    }

    calculateCameraMovement();

    moveCamera();

    view->GetScene()->GetCurrentCam()->SetRotation(0,-camYRot,-camXRot);

    view->GetScene()->GetCurrentCam()->SetPosition(camXPos,camYPos,camZPos);

}

LookAt () происходит из математической библиотеки GLM. Я почти уверен, что мне нужно умножить некоторые векторы (глаз, центр и т. Д.) На матрицу вращения, но я не уверен, какие именно. Я пытался умножить _viewMatrix на _rotationMatrix, но это создает беспорядок. Код для положения камеры FPS и расчет вращения взят из здесь. для собственно рендеринга я использую программируемый конвейер.

Обновление: я решил проблему, добавив отдельный метод, который не рассчитывает матрицу камеры с помощью lookAt, а использует обычный базовый подход:

void FpsMove(GLfloat x, GLfloat y , GLfloat z,float pitch,float yaw){
    _viewMatrix =rotate(mat4(1.0f), pitch, vec3(1, 0, 0));
    _viewMatrix=rotate(_viewMatrix, yaw, vec3(0, 1, 0));
    _viewMatrix= translate(_viewMatrix, vec3(-x, -y, -z));
    _transform.SetModel( _viewMatrix );
}

Это решило проблему, но я все еще хочу знать, как заставить его работать с методами lookAt (), которые я представил здесь.


person Michael IV    schedule 12.12.2012    source источник


Ответы (1)


Вам нужно изменить прямое направление камеры, которое предположительно зафиксировано на (0,0,-1). Вы можете сделать это, поворачивая направления вокруг оси y с помощью camYRot (как вычислено в функции lookat) так, чтобы вперед было в том же направлении, что и камера (в плоскости, образованной осями z и x).

person Matt Esch    schedule 12.12.2012
comment
Направление представлено вектором _center. Он обновляется, и камера вращается в соответствии с направлением ввода мыши, поэтому я не уверен, что это проблема. - person Michael IV; 12.12.2012