0

I'm trying to draw a cylinder in a specific direction with gluCylinder. To specify the direction I use gluLookAt, however, as so many before me, I am not sure about the "up" vector and thus can't get the cylinder to point to the correct direction.

I've read from another SO answer that

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.

It is a simple explanation but in the case of my cylinder I feel like the up vector is totally unimportant. Since a cylinder can be rotated around its axis and still look the same, a different up vector wouldn't change anything. So there should be infinitely many valid up vectors for my problem: all orthogonals to the vector from start point to end point.

So this is what I do:

  1. I have the world coordinates of where the start-point and end-point of the cylinder should be, A_world and B_world.

  2. I project them to viewport coordinates A_vp and B_vp with gluProject:

    GLdouble A_vp[3], B_vp[3], up[3], model[16], projection[16];
    GLint gl_viewport[4];
    glGetDoublev(GL_MODELVIEW_MATRIX, &model[0]);
    glGetDoublev(GL_PROJECTION_MATRIX, &projection[0]);
    glGetIntegerv(GL_VIEWPORT, gl_viewport);
    
    gluProject(A_world[0], A_world[1], A_world[2], &model[0], &projection[0], &gl_viewport[0], &A_vp[0], &A_vp[1], &A_vp[2]);
    
    gluProject(B_world[0], B_world[1], B_world[2], &model[0], &projection[0], &gl_viewport[0], &B_vp[0], &B_vp[1], &B_vp[2]);
    
  3. I call glOrtho to reset the camera to its default position: Negative z into picture, x to the right, y up:

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, vp_edgelen, vp_edgelen, 0, 25, -25);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    
  4. I translate to coordinate A_vp, calculate the up vector as the normal to the vector A_vp — B_vp and specify the view with gluLookAt:

    glTranslatef(A_vp[0], gl_viewport[2] - A_vp[1], A_vp[2]);
    glMatrixMode(GL_MODELVIEW);
    
    GLdouble[] up = {A_vp[1] * B_vp[2] - A_vp[2] * B_vp[1], 
                     A_vp[2] * B_vp[0] - A_vp[0] * B_vp[2],
                     A_vp[0] * B_vp[1] - A_vp[1] * B_vp[0]};
    
    gluLookAt(0, 0, 0,
              B_vp[0], gl_viewport[2] - B_vp[1], B_vp[2],
              up[0], up[1], up[2]);
    
  5. I draw the cylinder with gluCylinder:

    GLUquadricObj *gluCylObj = gluNewQuadric();
    gluQuadricNormals(gluCylObj, GLU_SMOOTH);
    gluQuadricOrientation(gluCylObj, GLU_OUTSIDE);
    gluCylinder(gluCylObj, 10, 10, 50, 10, 10);
    

Here is the unexpected result:

enter image description here

Since the cylinder starts at the correct position and since I was able to draw a circle at position B_vp, the only thing that must be wrong is the "up" vector in gluLookAt, right?

x squared
  • 3,173
  • 1
  • 26
  • 41
  • What is your system? Is there a really good reason to use the old OpenGL? Have a look at the new one, e.g. in [this](http://open.gl) tutorial. – DanceIgel Aug 13 '15 at 14:29
  • Can you post more information about the rendering context? E.g. how are you rendering the other stuff? Posting it in pseudocode will be enough. – DanceIgel Aug 13 '15 at 14:39
  • Ok, I guess I got your error. Currently, you are creating an up vector which points out of the screen, but what you want is an up vector from `A_vp` to `B_vp`. So you just have to change the cross product with the difference `B_vp - A_vp` – DanceIgel Aug 13 '15 at 14:44
  • You mean, instead of using the cross product as up vector using the `B_vp - A_vp` vector as up vector? But that is not correct, since this is the vector wher my cylinder is supposed to lie on. And in the `gluCylinder` documentation it says that the cylinder will point in the z direction. – x squared Aug 13 '15 at 15:00
  • Oh and about modern OpenGL, thank you for the link. Unfortunately this is not my private project, so I am restricted in this regard :( – x squared Aug 13 '15 at 15:00
  • Okay, I did not know that it will point in the z direction. But instead of using an up vector, you should be able to perform a simple rotation with a matrix. (Usually no one renders stuff with changing the up vector.) So try using `glRotate()` before rendering the Cylinder to get the correct result. Remember that you have to calculate the anlge before and that you have to push and pop the transformation matrix before and after calling `glRotate`.Btw: in my opinion you should remove everything you transformed by `gluLookAt` and its upvector and implement it new with `glTranslate` and `glRotate` – DanceIgel Aug 14 '15 at 08:08

1 Answers1

0

gluLookAt() is not necessary to achieve the proper perspective. It is enough to rotate the current z-vector to point to the direction the cylinder should point.

x squared
  • 3,173
  • 1
  • 26
  • 41