I've been working on this hobby game engine in cC and sokolSokol with cglmCGLM for a short while now, and I've ran into a bit of a snag regarding portal rendering. It works as it should when the player camera's yaw is below 90 degrees, but it breaks down at all angles beyond it. thisThis video should give you a better understanding of my issue. The portals are rendered as off-screen render targets with quads being used as cutouts with each portal having it's own framebuffer and camera to draw to. The code regarding portal camera transformation has been posted below. Thanks in advance!
static inline void model_matrix_to_euler_angles(mat4 model_matrix, vec3 out_euler_angles) { mat3 rotation_matrix = { {model_matrix[0][0], model_matrix[0][1], model_matrix[0][2]}, {model_matrix[1][0], model_matrix[1][1], model_matrix[1][2]}, {model_matrix[2][0], model_matrix[2][1], model_matrix[2][2]} }; f32 pitch, yaw, roll; yaw = -asinf(-rotation_matrix[2][0]); pitch = -atan2f(rotation_matrix[2][1], rotation_matrix[2][2]); roll = -atan2f(rotation_matrix[1][0], rotation_matrix[0][0]); out_euler_angles[0] = glm_deg(pitch); out_euler_angles[1] = glm_deg(yaw); out_euler_angles[2] = glm_deg(roll); } static void updatePortalCamera( gfx__portal_t* src_portal, gfx__portal_t* dest_portal ) { mat4 player_model = GLM_MAT4_IDENTITY_INIT, proj_model = GLM_MAT4_IDENTITY_INIT, src_inv; glm_translate(player_model, state.cam3D.pos); glm_mat4_inv(src_portal->model, src_inv); glm_mul(src_inv, player_model, proj_model); glm_mul(dest_portal->model, proj_model, proj_model); glm_rotate_x(proj_model, glm_rad(state.cam3D.pitch), proj_model); glm_rotate_y(proj_model, glm_rad(state.cam3D.yaw), proj_model); v3 proj_angles; model_matrix_to_euler_angles(proj_model, proj_angles); dest_portal->cam.pos[0] = proj_model[3][0]; dest_portal->cam.pos[1] = proj_model[3][1]; dest_portal->cam.pos[2] = proj_model[3][2]; dest_portal->cam.pitch = proj_angles[0]; dest_portal->cam.yaw = -proj_angles[1]; gfx__cam3D_updateFront(&dest_portal->cam); gfx__cam3D_updateVP(&dest_portal->cam); } static inline void model_matrix_to_euler_angles(mat4 model_matrix, vec3 out_euler_angles) { mat3 rotation_matrix = { {model_matrix[0][0], model_matrix[0][1], model_matrix[0][2]}, {model_matrix[1][0], model_matrix[1][1], model_matrix[1][2]}, {model_matrix[2][0], model_matrix[2][1], model_matrix[2][2]} }; f32 pitch, yaw, roll; yaw = -asinf(-rotation_matrix[2][0]); pitch = -atan2f(rotation_matrix[2][1], rotation_matrix[2][2]); roll = -atan2f(rotation_matrix[1][0], rotation_matrix[0][0]); out_euler_angles[0] = glm_deg(pitch); out_euler_angles[1] = glm_deg(yaw); out_euler_angles[2] = glm_deg(roll); } static void updatePortalCamera( gfx__portal_t* src_portal, gfx__portal_t* dest_portal ) { mat4 player_model = GLM_MAT4_IDENTITY_INIT, proj_model = GLM_MAT4_IDENTITY_INIT, src_inv; glm_translate(player_model, state.cam3D.pos); glm_mat4_inv(src_portal->model, src_inv); glm_mul(src_inv, player_model, proj_model); glm_mul(dest_portal->model, proj_model, proj_model); glm_rotate_x(proj_model, glm_rad(state.cam3D.pitch), proj_model); glm_rotate_y(proj_model, glm_rad(state.cam3D.yaw), proj_model); v3 proj_angles; model_matrix_to_euler_angles(proj_model, proj_angles); dest_portal->cam.pos[0] = proj_model[3][0]; dest_portal->cam.pos[1] = proj_model[3][1]; dest_portal->cam.pos[2] = proj_model[3][2]; dest_portal->cam.pitch = proj_angles[0]; dest_portal->cam.yaw = -proj_angles[1]; gfx__cam3D_updateFront(&dest_portal->cam); gfx__cam3D_updateVP(&dest_portal->cam); }