0
votes

I have a camera in OpenGL.I had no problem with it until adding FPS controller.The problem is that the basic FPS behavior is ok. The camera moves forward,backward,left and right+ rotates towards the direction supplied by mouse input.The problems begin when the camera moves to the sides or the back of the target position.In such a case camera local forward,backward,left,right directions aren't updated based on its current forward look but remain the same as if it was right in front of the target.Example: If the target object position is at (0,0,0) and camera position is at (-50,0,0) (to the left of the target) and camera is looking at the target,then to move it back and forth I have to use the keys for left and right movement while backward/forward keys move the camera sideways. Here is the code I use to calculate camera position, rotation and LookAt matrix:

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


}

Then in the render loop I set camera's transformations:

 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() method comes from GLM math lib. I am pretty sure I have to multiply some of the vectors (eye ,center etc) with rotation matrix but I am not sure which ones.I tried to multiply _viewMatrix by the _rotationMatrix but it creates a mess.The code for FPS camera position and rotation calculation is taken from here.But for the actual rendering I use programmable pipeline.

Update: I solved the issue by adding a separate method which doesn't calculate camera matrix using lookAt but rather using the usual and basic approach:

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

It solved the problem but I still want to know how to make it work with lookAt() methods I presented here.

1

1 Answers

0
votes

You need to change the forward direction of the camera, which is presumably fixed to (0,0,-1). You can do this by rotating the directions about the y axis by camYRot (as computed in the lookat function) so that forwards is in the same direction that the camera is pointing (in the plane made by the z and x axes).