1
votes

I've been writing a program to display 3d models using OpenGL and until now I've used orthographic projection, but I want to switch to a perspective projection so that as the camera goes toward the model it appears to get larger. I understand that I have to multiply three matrices (model, view, and projection) together to correctly apply all of my transformations. As you can see in the following code, I have attempted to do that, and was able to correctly create the model and view matrices. I know these work properly because when I multiply the model and view projections together I can rotate and translate the object, as well as change the position and angle of the camera. My problem is that when I multiply that product by the projection matrix I can no longer see the object on the screen.

The default value for the camera struct here is {0,0,-.5} but I manipulate that value with the keyboard to move the camera around.

I am using GLFW+glad, and linmath.h for the matrix math.

    //The model matrix controls where the object is positioned. The
    //identity matrix means no transformations.
    mat4x4_identity(m);
    //Apply model transformations here.

    //The view matrix controls camera position and angle.
    vec3 eye={camera.x,camera.y,camera.z};
    vec3 center={camera.x,camera.y,camera.z+1};
    vec3 up={0,1,0};
    mat4x4_look_at(v,eye,center,up);

    //The projection matrix flattens the world to 2d to be rendered on a
    //screen.
    mat4x4_perspective(p, 1.57, width/(float)height, 1,10); //FOV of 90°
    //mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);

    //Apply the transformations. mvp=p*v*m.
    mat4x4_mul(mvp, p, v);
    mat4x4_mul(mvp, mvp, m);
1

1 Answers

4
votes

When the perspective projection matrix is set up, then the distance to the near plan and far plane are set. In your case this is 1 for the near plane and 10 for the far plane:

mat4x4_perspective(p, 1.57, width/(float)height, 1,10);

The model is clipped by the near plane. The model has to be in clip space.
The eye space coordinates in the camera frustum (a truncated pyramid) are mapped to a cube (the normalized device coordinates). All the geometry which is not in the volume of the frustum is clipped.

This means the distance of the model to the camera has to be greater than the distance to the near plane (1) and less than the distance to the far plane (10).

Since you can "see" the model when you don't use any projection matrix, the actual distance to the model is in range [-1, 1] (normalize device space). Note if you don't use a projection matrix, then the projection matrix is the identity matrix. This behaves like an orthographic projection, with a near plane distance of -1 and a far plane distance of 1.

Change the position of the camera to solve the issue:

e.g.

vec3 eye    = {camera.x, camera.y, camera.z - 5}; // <--- 5 is in range [1, 10] 
vec3 center = {camera.x, camera.y, camera.z};
vec3 up     = {0, 1, 0};
mat4x4_look_at(v, eye, center, up);