Mike
Mike

Reputation: 37

LookAt (glm) returns wrong translate z-value

Hello i have an issue with a returning value of the glm lookAt function. When i am executing in debug mode, i get at this point ... Result[3][2] = dot(f, eye); ... of the glm function a wrong value in the translate z-position of the matrix. The value is -2, that shows me that the forward and eye vector are in the opposite position. My eye, center and up vectors are eye(0,0,2), center(0,0,-1) and up(0,1,0). The cam coodinate vectors are: f(0,0,-1), s(1,0,0) and u(0,1,0). And the vantage point the user looks at is (0,0,0). So the right view matrix should be this one:

1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

but i get this one:

1  -0  0   -0
-0  1 -0   -0
0   0   1  -2
0   0   0   1

My code is:

struct camera {
vec3 position = vec3(0.0f);         // position of the camera
vec3 view_direction = vec3(0.0f);   // forward vector (orientation)
vec3 side = vec3(0.0f);             // right vector (side)
vec3 up = vec3(0.0f, 1.0f, 0.0f);   // up vector
float speed = 0.1;
float yaw = 0.0f;                   // y-rotation
float cam_yaw_speed = 10.0f;        // 10 degrees per second
float pitch = 0.0f;                 // x-rotation
float roll = 0.0f;      

...
// calculate the orientation vector (forward) 
vec3 getOrientation(vec3 vantage_point) {
    // calc the difference and normalize the resulting vector
    vec3 result = vantage_point - position;
    result = normalize(result);
    return result;
}

// calculate the right (side) vector of the camera, by given orientation(forward) and up vectors
mat4 look_at_point(vec3 vantage_point) {
    view_direction = getOrientation(vantage_point);

    // calculate the lookat matrix
    return lookAt(position, position + view_direction, up);
}
};

I have tryied to figure out how to manage this problem but i still have no idea. Can someone help me?

The main function where i am executing the main_cam.look_at_point(vantage_point) function is showed below:

...
GLfloat points[] = {
0.0f, 0.5f, 0.0f,
0.5f,  0.0f, 0.0f,
-0.5f, 0.0f, 0.0f };

float speed = 1.0f; // move at 1 unit per second

float last_position = 0.0f;

// init camera
main_cam.position = vec3(0.0f, 0.0f, 2.0f);         // don't start at zero, or will be too close
main_cam.speed = 1.0f;                              // 1 unit per second
main_cam.cam_yaw_speed = 10.0f;                     // 10 degrees per second
vec3 vantage_point = vec3(0.0f, 0.0f, 0.0f);

mat4 T = translate(mat4(1.0), main_cam.position);
//mat4 R = rotate(mat4(), -main_cam.yaw, vec3(0.0, 1.0, 0.0));
mat4 R = main_cam.look_at_point(vantage_point);
mat4 view_matrix = R * T;

// input variables
float near = 0.1f;      // clipping plane
float far = 100.0f;     // clipping plane
float fov = 67.0f * ONE_DEG_IN_RAD; // convert 67 degrees to radians
float aspect = (float)g_gl_width / (float)g_gl_height;  // aspect ratio

mat4 proj_matrix = perspective(fov, aspect, near, far);

use_shader_program(shader_program);
set_uniform_matrix4fv(shader_program, "view", 1, GL_FALSE, &view_matrix[0][0]);
set_uniform_matrix4fv(shader_program, "proj", 1, GL_FALSE, &proj_matrix[0][0]);
...

Testing with the rotate function of glm the triangle is shown right.

Triangle shown with the rotate function of glm

Upvotes: 1

Views: 1596

Answers (1)

Yakov Galka
Yakov Galka

Reputation: 72489

I suspect that the problem is here:

mat4 view_matrix = R * T; // <---

The matrix returned by lookAt already does the translation.

Try manually applying the transformation on the (0,0,0) point that is inside your triangle. T will translate it to (0,0,2), but now it coincides with the camera, so R will send it back into (0,0,0). Now you get a division by zero accident in the projective divide.

So remove the multiplication by T:

mat4 view_matrix = R;

Now (0,0,0) will be mapped to (0,0,-2), which is in the direction camera is looking. (In camera space the center-of-projection is at (0,0,0) and the camera is looking towards the negative Z direction).


EDIT: I want to point out that calculating the view_direction from vantage_point and then feeding position + view_direction back into lookAt is a rather contrived way of achieving your goals. What you do in getOrientation function is what lookAt already does inside. Instead you can get the view_direction from the result of lookAt:

mat4 look_at_point(vec3 vantage_point) {
    // calculate the lookat matrix
    mat4 M = lookAt(position, vantage_point, up);
    view_direction = -vec3(M[2][0], M[2][1], M[2][2]);
    return M;
}

However, considering that ultimately you're trying to implement yaw/pitch/roll camera controls, you are better off to not using lookAt at all.

Upvotes: 1

Related Questions