Search code examples
c++openglglutglm-math

Camera Rotation using lookAt


Hey guys I am trying to do a Camera class that uses lookAt from glm library. I have 4 points, the first one is eye, that is the camera position in space, the second one is the look, that is the point where the camera is looking at, the third one is the upp, that set the orientation of camera, and the forth is side, that is a cross product of look - eye and upp -eye.

So in the end I got a base of 3 vectors all of them with origin in the eye point. I got a coordinate system of the camera.

In my camera class, I want to be able to rotate about the coordinate system of the camera, not the coordinate system of the world. So what I am doing is rotate about one of the axis of the coordinate system of the camera.

I construct the class with initial values like this:

void Observer::initialize(glm::vec3 eye, glm::vec3 look, glm::vec3 upp, glm::vec3 side) 
{
    this->eye = eye;        // (0.0, 0.0,  0.0)
    this->look = look;      // (0.0, 0.0, -1.0)
    this->upp = upp;        // (0.0, 1.0,  0.0)
    this->side = side;      // (1.0, 0.0,  0.0)
}

When I want to rotate the coordinate system about the x axis for example I call the function from glm like this:

void Observer::pitch(GLfloat pitch) 
{
    glm::mat4 rotate(1.0f);

    rotate = glm::rotate(rotate, pitch, side - eye);

    look = glm::vec3(rotate * glm::vec4(look, 1.0f));
    upp = glm::vec3(rotate * glm::vec4(upp, 1.0f));
}

So far, I am understanding that all my points still form a coordinate system for the camera and all vector are perpendicular between each other.

But then I use these points I got with the lookAt function, to position the camera in the world.

 glm::mat4 view = glm::lookAt(eye, look, upp);

And multiply this matrix with the modelview matrix from OpenGL

If I start to rotate a lot, the camera after a few rotations "reflect" the rotation, like I was rotating in the other way (I don't know how to describe what is really happening in a better way =s).

I really don't understand what is happening. I should normalize the vectors after I apply the rotation? Am I having a problem with gimbal lock (I don't know a lot about gimbal lock)?


Solution

  • When you do incremental rotations on vectors as you have done, numerical errors mount. When error causes the up and look-at vectors to point nearly in the same direction or opposite each other, the camera transformation calculation is unstable and whacky things can happen. Gimbal lock. Length changes cause different problems.

    A solution that has worked for me is to re-orthogonalize the up and look-at vectors after each rotation. To do this, compute their cross-product L, then adjust (really replace) the up vector by crossing L with the lookAt. After all this re-normalize both up and look-at to unit length.

    Though the orthogonalization-normalization is a fast operation, you don't really have to do it with every camera motion.

    Note that when you correct the vectors like this you are actually doing part of the lookAt matrix calculation, so consider implementing your own to avoid an unnecessary cross product. See e.g. this prior SO article on this topic.