Understanding glm::lookAt()

116,168

Solution 1

The up vector is basically a vector defining your world's "upwards" direction. In almost all normal cases, this will be the vector (0, 1, 0) i.e. towards positive Y. eye is the position of the camera's viewpoint, and center is where you are looking at (a position). If you want to use a direction vector D instead of a center position, you can simply use eye + D as the center position, where D can be a unit vector for example.

As for the inner workings, or more details, this is a common basic function for building a view matrix. Try reading the docs for gluLookAt() which is functionally equivalent.

Solution 2

Here, the Up vector defines the "upwards" direction in your 3D world (for this camera). For example, the value of vec3(0, 0, 1) means the Z-axis points upwards.

Eye is the point where you virtual 3D camera is located.

And Center is the point which the camera looks at (center of the scene).

The best way to understand something is to make it yourself. Here is how a camera transformation can be constructed using 3 vectors: Eye, Center, and Up.

LMatrix4 LookAt( const LVector3& Eye, const LVector3& Center, const LVector3& Up )
{
    LMatrix4 Matrix;

    LVector3 X, Y, Z;

Create a new coordinate system:

    Z = Eye - Center;
    Z.Normalize();
    Y = Up;
    X = Y.Cross( Z );

Recompute Y = Z cross X:

    Y = Z.Cross( X );

The length of the cross product is equal to the area of the parallelogram, which is < 1.0 for non-perpendicular unit-length vectors; so normalize X, Y here:

    X.Normalize();
    Y.Normalize();

Put everything into the resulting 4x4 matrix:

    Matrix[0][0] = X.x;
    Matrix[1][0] = X.y;
    Matrix[2][0] = X.z;
    Matrix[3][0] = -X.Dot( Eye );
    Matrix[0][1] = Y.x;
    Matrix[1][1] = Y.y;
    Matrix[2][1] = Y.z;
    Matrix[3][1] = -Y.Dot( Eye );
    Matrix[0][2] = Z.x;
    Matrix[1][2] = Z.y;
    Matrix[2][2] = Z.z;
    Matrix[3][2] = -Z.Dot( Eye );
    Matrix[0][3] = 0;
    Matrix[1][3] = 0;
    Matrix[2][3] = 0;
    Matrix[3][3] = 1.0f;

    return Matrix;
}

Solution 3

After set the camera(or eye) and target(center), made camera face to target, we can still rotate the camera to get different pictures, so here comes the up vector which makes the camera fixed and cannot be rotate.

enter image description here

Share:
116,168
Cashif Ilyas
Author by

Cashif Ilyas

Updated on January 04, 2021

Comments

  • Cashif Ilyas
    Cashif Ilyas over 3 years

    I am following a tutorial to learn OpenGL in which they used glm::lookAt() function to build a view but I cannot understand the working of glm::lookAt() and apparently, there is no detailed documentation of GLM. Can anyone help me understand the parameters and working of glm::lookAt() please?

    GLM documentation says:

    detail::tmat4x4<T> glm::gtc::matrix_transform::lookAt   
    (   
        detail::tvec3< T > const &  eye,
        detail::tvec3< T > const &  center,
        detail::tvec3< T > const &  up 
    )
    

    My current understanding is that camera is located at eye and is faced towards center. (And I don't know what the up is)

  • Christian Rau
    Christian Rau over 10 years
    While the code is nice, if the OP doesn't know how lookAt works and what the parameters mean, this doesn't help him to understand anything at all. E.g. "Cross-product gives area of parallelogram, which is < 1.0 for non-perpendicular unit-length vectors" - utterly irrelevant, even more than that it gives a vector orthogonal to both operands (whose length is the area of the parallelogram) and this is the geometric property we're needing here. But ok, the last part salvages it from downvoting.
  • Sergey K.
    Sergey K. over 10 years
    @ChristianRau: I have updated my answer with a plain English explanation of the parameters' meaning. Putting unnormalized vectors into the resulting matrix will produce wrong results.
  • Christian Rau
    Christian Rau over 10 years
    "defines the "upwards" direction in your 3D world." - In your 3D world or just of your camera? But nevermind it's already upvotable now.
  • BitTickler
    BitTickler about 10 years
    One point missing might be the discussion about, why the return value of glm::lookAt() is not simply a glm::mat4 but instead a detail::tmat4x4<T, P>
  • Fox
    Fox over 7 years
    @SergeyK. Cross product yields a vector which is perpendicular to the two others. It yields a vector, not a scalar. The dot product yields a scalar. An area is not a vector. So, to be more correct, we should say that it's the magnitude of the cross product which is equal to the area of the parallelogram formed by the two operands: ||a x b|| = ||a|| ||b|| sin(theta)
  • Sergey K.
    Sergey K. over 7 years
    @Fox Thx. Updated.
  • Aadhish
    Aadhish over 3 years
    I'm following the LearnOpenGL tutorial, in this line he used Up which is acutally camera's Up direction shouldn't we use the world's upward direction?
  • Preet Kukreti
    Preet Kukreti over 3 years
    @Aadhish in that case the camera might be rolled (rotation on its view axis), and the author may want to support that possibility. In typical games and virtual scenarios camera roll is often restricted while pitch and yaw are allowed. One common exception is flight/space simulation where roll is an important aspect of the simulation and view.
  • blueether
    blueether over 2 years
    The docs seem to call the 2nd parameter the a center point, but it seems more like the 2nd parameter is supposed to be a vector originating at the eye and passing through the point you are looking at - meaning, it is not the actual point you are looking at, it is a vector looking in that direction. Am I understanding correctly?