When working with 3D graphics, projecting a world position to screen space can sometimes lead to unexpected results, like the mirrored effect you're observing. This issue often arises from the way matrices—specifically the view-projection matrix—are combined when rendering a scene. In your code, you mention that the screen position moves in the opposite direction when you rotate the camera. Let's delve deeper into why this might be happening and how we can fix it effectively.
Understanding the Problem
In your code, you set up the view and projection matrices and then combine them to create a view-projection matrix. However, if the view matrix isn't correctly set up to reflect the camera's orientation, the resulting transformations can appear inverted or mirrored. To ensure proper functionality, it’s crucial to validate how the matrices are combined and whether any extra transformations are required.
Building the View Matrix
Here’s your current setup:
vec3 world_pos = { x, y, z };
mat4 proj;
glm_perspective(fov, viewport_w / viewport_h, clip_near, clip_far, proj);
mat4 view;
glm_quat_look((vec3){ cam.x, cam.y, cam.z }, cam.rotation_quat, view);
mat4 vp;
glm_mat4_mul(proj, view, vp);
vec4 viewport = { 0, 0, (f32)cam->cam.viewport_w, (f32)cam->cam.viewport_h };
vec3 screen;
glm_project(world_pos, vp, viewport, screen);
Here, you correctly create the perspective projection matrix with glm_perspective
, but let's focus on how glm_quat_look
behaves with respect to your camera setup. The glm_quat_look
function generates a view matrix from a position and a rotation quaternion. Ensure that the quaternion correctly represents the camera's orientation. If the camera is upside down or rotated incorrectly, it will lead to unexpected projections like mirroring.
Ensuring Proper Quaternion Setup
Make sure your quaternion represents the camera from which you're looking at the scene. If you accidentally input an incorrect up vector or misconfigured quaternion, the view matrix will be wrong. Typically, the up vector should be oriented correctly, like (vec3){0.0f, 1.0f, 0.0f}
for a Y-up coordinate system.
Including the Model Matrix
For your current setup, where you project the world position directly without scoping transformations, you technically don't need to include a model matrix (even as an identity matrix). However, if your world space doesn’t align well with your camera, be mindful of how the world position transforms around the camera's orientation. Here’s what you can do:
Check World Position Transformation
To ensure that the world position is aligned with how your camera is looking at the scene, wrap the world position application in a model matrix if necessary. For instance:
mat4 model;
glm_mat4_identity(model);
// If there's a model transformation, apply it here
mat4 mvp;
glm_mat4_mul(vp, model, mvp);
vec3 screen;
glm_project(world_pos, mvp, viewport, screen);
Re-evaluate Quaternion Input
Ensure your quaternion is correctly computed before projection. A mirrored projection may result from providing a quaternion that represents a backward rotation to the camera. You might want to glm_quat_invert()
your quaternion if you notice any discrepancies in rotation.
Debugging Steps
- Log Quaternion Values: Output the quaternion values right before creating the view matrix to see if it looks appropriate.
- Change Camera Orientation: Temporarily swap the camera's rotation to see if it has the intended behavior when rendered.
- Test with Identity Model Matrix: If you’re not using any transformations, using an identity matrix for the model can prove that your view matrix works before scaling it with more transformations.
Frequently Asked Questions
What is the difference between projection and view matrices?
The view matrix transforms world coordinates to view coordinates, simulating the camera’s position and orientation. The projection matrix then maps those view coordinates onto normalized device coordinates, making them displayable on your screen.
Do I need to always use a model matrix?
If your objects have transformations (scale, rotation, translation) in a 3D scene, you will need a model matrix to combine these transformations effectively with the view and projection matrices. If objects are not transformed, the identity matrix suffices.
How do I check if my matrices are correct?
Printing values of your matrices and comparing the expected results can help. Additionally, visualizing how these matrices align with your 3D model space can be beneficial.
Conclusion
Understanding the nuances of matrix manipulation in 3D graphics is crucial for achieving seamless projections from world space to screen space. In your case, ensuring the camera's quaternion is applied correctly and potentially integrating a model matrix can address the inversion problem. With proper adjustments, you should see your projected screen position behave as expected when rotating the camera.