25

this is related to The LookAt target location doesn't matter if it is z = 0 or z = 1000 or -1000?

I tried

    gluLookAt(512, 384, 2000,
              512, 384, 0,
              0.0f, 1.0f, 0.0f);

and things work fine, and now I change the 3rd row (the UP vector), last number to 0.8:

    gluLookAt(512, 384, 2000,
              512, 384, 0,
              0.0f, 1.0f, 0.8f);

and it is exactly the same... next I tried and modified the 3rd line, the first number to 0.8:

    gluLookAt(512, 384, 2000,
              512, 384, 0,
              0.8f, 1.0f, 0.8f);

Now the view is like it rotated 45 degree to the left. How does this UP vector work?

Community
  • 1
  • 1
Jeremy L
  • 3,770
  • 6
  • 41
  • 62

4 Answers4

35

The up vector is used to create a cross product between the eye and centre vector supplied to gluLookAt.

From the GLKit headers on iOS, you can see the implementation as:

static __inline__ GLKMatrix4 GLKMatrix4MakeLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)
{
    GLKVector3 ev = { eyeX, eyeY, eyeZ };
    GLKVector3 cv = { centerX, centerY, centerZ };
    GLKVector3 uv = { upX, upY, upZ };
    GLKVector3 n = GLKVector3Normalize(GLKVector3Add(ev, GLKVector3Negate(cv)));
    GLKVector3 u = GLKVector3Normalize(GLKVector3CrossProduct(uv, n));
    GLKVector3 v = GLKVector3CrossProduct(n, u);

    GLKMatrix4 m = { u.v[0], v.v[0], n.v[0], 0.0f,
        u.v[1], v.v[1], n.v[1], 0.0f,
        u.v[2], v.v[2], n.v[2], 0.0f,
        GLKVector3DotProduct(GLKVector3Negate(u), ev),
        GLKVector3DotProduct(GLKVector3Negate(v), ev),
        GLKVector3DotProduct(GLKVector3Negate(n), ev),
        1.0f };

    return m;
}

The accepted answer in this question How do I use gluLookAt properly? provides a good description of what the up vector actually impacts.

(The intuition behind the "up" vector in gluLookAt is simple: Look at anything. Now tilt your head 90 degrees. Where you are hasn't changed, the direction you're looking at hasn't changed, but the image in your retina clearly has. What's the difference? Where the top of your head is pointing to. That's the up vector.)
Community
  • 1
  • 1
Zack Brown
  • 5,990
  • 2
  • 41
  • 54
27

The up vector determines which direction is "up". Think of it like a video camera... if you hold the camera "properly", then an imaginary line going upward from the center of the camera to the top of the camera could be represented by a vector (0,1,0). If you tilt the camera 45 degrees to the right, the imaginary line going from the center of the camera to the "top" of the camera would now be represented by a new vector (1,1,0). If you then tilt the camera "back" just a bit, your "up" vector now becomes (1,1,1) [or (1,1,-1)... I always get the polarity of the z-axis reversed].

So, in short, the UP vector describes the roll of the camera by saying which point is "up" in the camera's orientation.

Hope that helps. :)

(edit to correct summary as per comment)

CodeHxr
  • 855
  • 8
  • 17
  • _"So, in short, the UP vector describes the pitch, yaw, and roll of the camera by saying which point is "up" in the camera's orientation."_ Wrong. Up is just the roll (yaw and pitch being constrained by the point the camera is looking at). – Stan Dec 04 '12 at 10:28
  • 4
    This might be Old, but thanks for that, this is so far the first explanation thats made sense to me! – Cail Demetri Oct 17 '13 at 11:01
5

The first two parameters of gluLookAt are the camera position and the camera target. With just those two the camera isn't fully constrained. Imagine standing somewhere holding a camera. You can hold the camera horizontally to take a landscape picture, or you could hold the camera vertically to take a portrait picture. In both cases, the position of the camera and the position of the subject of the picture are the same. You could rotate the camera to any angle and those two values don't change. The third parameter, the up vector, selects the orientation of the camera.

IronMensan
  • 6,761
  • 1
  • 26
  • 35
3

It works exactly the way it looks like it works.

Imagine you're at some point in space. And them imagine that you're looking at some point 2000 units directly in the -Z direction from you.

There are an infinite number of possible cameras with these characteristics, but they are different based solely on having a different "up" direction. So the different "up" directions correspond to having a different orientation around the direction of view.

The up vector is the vector direction that is aligned with the "up" direction you want the camera to have. That is, if you were to draw the up vector from your camera point, you would see a straight vertical line pointing up.

Now, look back at your imagined view, and look at that vertical line. Could you tell if that vertical line were moving towards or away from you? No; it's just a vertical line. So it doesn't matter if the up vector partially points in the direction of the view. What matters is that the up direction is not exactly pointing in the view direction.

When you give the up direction a non-zero Z coordinate, it now partially points in the view direction (ie: the Z axis). That part is ultimately irrelevant to the up direction you get, so it is ignored. When you give the up direction a non-zero X coordinate, that is not in the view direction, so it is significant.

The point of this is so that if you change the view look-at or camera origin point, you don't have to change the up direction too. As long as you're not looking directly along the up axis, you're fine.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • If I am sitting on a chair looking straight ahead, holding an iPad right in front of my eyes, then my top of my head is pointing up the sky, therefore the `(0, 1, 0)`... how about if I change it to `(0, 0.00001, 1)`, so that means I am almost lying down, with now my face and eyes facing the sky... so how come the result is exactly the same if I use `(0, 1, 0)`? – Jeremy L May 17 '12 at 13:23
  • 3
    @JeremyL: Because if you're lying down with your face and eyes facing the sky, you would not be looking at your iPad anymore. See the problem? The function has to figure out which are the most important constraints. Camera position and the look-at position trump the up direction in terms of deciding *where* you're looking. The up direction is used strictly for orientation *after* deciding where you're looking. Changing the up direction will never change where you're looking, only *how* you're looking in that direction. – Nicol Bolas May 17 '12 at 13:43
  • what I am saying is, if you are almost lying down, the result IS EXACTLY THE SAME as sitting on a chair facing straight ahead – Jeremy L May 17 '12 at 14:27
  • 3
    @JeremyL: Except that it's not. You cannot be lying down and looking at the same point you were when you were looking straight ahead. One must take precedence, and the look-at point is the one that does. You continue to not understand that the up-vector does not change the *direction that the camera is pointed*. If you want to show the camera "lying down", then you *must* change the lookat point. – Nicol Bolas May 17 '12 at 14:30