0
votes

enter image description here In the image above, I show the result of having the camera positioned in the same position as the vertex covered by the mouse. A similar result comes from using an orthographic matrix. My problem is that when rotating the camera, it rotates around the visible origin of the camera. What I want is for the view to rotate like normal FPS Cameras.

What I believe to be useful information:

  • I am doing the math manually and rendering to the screen using OpenGL.
  • The cube's vertices are from {0, 0, 0} to {1, 1, 1}
  • The camera is positioned at {0, 0, 0}
  • My (4x4) matrices are in column major and I get the same result from uploading the individual matrices to the shader via uniforms and multiplying them in the same order
  • The movement and rotation is otherwise sensible even when translating the camera, just that the origin of the camera is visible.

This last point makes sense to me mathematically with an orthographic projection, however, since the near clipping plane is supposed to be slightly in front of the camera, I'd expect the point near the mouse to be clipped. I know for a fact that it is not clipped, because if I rotate the camera to look down on the cube (without translating it), the clipping plane cuts off roughly halfway up that vertical edge of the cube.

I think my confusion may be due to a fundamental misunderstanding of how the mathematics works for the perspective projection matrix, but it may be due to my code as well, so let me include that:

static inline constexpr auto ortho(T l, T r, T b, T t, T n, T f) {
    return Matrix4x4{{(T)2 / (r - l), 0, 0, 0},
                     {0, (T)2 / (t - b), 0, 0},
                     {0, 0, (T)2 / (n - f), 0},
                     {(l + r) / (l - r), (b + t) / (b - t), (f + n) / (n - f), 1}};
}
static inline constexpr auto perspective(T fov, T aspect, T near, T far) {
    const T q = (T)1.0 / std::tan(0.5 * fov), 
            a = q * aspect, 
            b = (near + far) / (near - far), 
            c = near * far * 2 / (near - far);
    return Matrix4x4{
        {q, 0, 0, 0},
        {0, a, 0, 0},
        {0, 0, b, -1},
        {0, 0, c, 1},
    };
}

If anyone needs extra information on what is going on, let me know in the comments and will happily either answer or make an addendum to the question

1
You are using a quite unusual projection matrix where the projection center is not in the eye space origin. So this is either just a bug, or your math doesn't work out the way you intent it to.derhass
@derhass, how does one usually do perspective projection matrix math? I found resources that used matrices that are mathematically equivalent to this, which is why I used it, however, I don't understand entirely how it works. Do you have a link to a formula that you would use?Gabe Rundlett
The GL in this is quite outdated, but the math is solid and as relevant today as back then: songho.ca/opengl/gl_projectionmatrix.htmlderhass
Thanks so much @derhass, I made such a dumb mistake, and corrected it in my answer for anyone else who has this issue. I must have copied my code for creating an identity matrix and forgotten to change the 1!Gabe Rundlett

1 Answers

0
votes

After reading the link provided in the comments, and comparing my method with the code that I had written, I realized that I made a mistake in transcribing the mathematics into my code. I accidentally put a 1 in the last row of the last column of the perspective matrix, while it should have been a 0.

The corrected code is shown here:

static inline constexpr auto perspective(T fov, T aspect, T near, T far) {
    const T q = (T)1.0 / std::tan(0.5 * fov), 
            a = q * aspect, 
            b = (near + far) / (near - far), 
            c = near * far * 2 / (near - far);
    return Matrix4x4{
        {q, 0, 0, 0},
        {0, a, 0, 0},
        {0, 0, b, -1},
        {0, 0, c, 0},
    };
}