I'm calling a function:
// Get pixel coordinates
vertex_3 p = get_screen_coords_from_world_coords(transformed_vertex, camera_pos, projection_modelview_mat, win_x, win_y);
// Detect region
GLint y_viewport_pos = -1;
if (p.y < 0)
y_viewport_pos = ABOVE_VIEWPORT;
else if (p.y < win_y)
y_viewport_pos = IN_VIEWPORT;
else
y_viewport_pos = BELOW_VIEWPORT;
GLint x_viewport_pos = -1;
if (p.x < 0)
x_viewport_pos = LEFT_OF_VIEWPORT;
else if (p.x < win_x)
x_viewport_pos = IN_VIEWPORT;
else
x_viewport_pos = RIGHT_OF_VIEWPORT;
where
vertex_3 get_screen_coords_from_world_coords(const vertex_3 p, const vertex_3 c, const float(&mat)[16], const int width, const int height)
{
vertex_3 v = p - c;
v.x /= v.z;
v.y /= v.z;
v.z /= v.z;
float point[4];
point[0] = c.x + v.x;
point[1] = c.y + v.y;
point[2] = c.z + v.z;
point[3] = 0;
float out[4];
multiply_4x4_matrix_by_4_vector(mat, point, out);
return vertex_3(
round(((1.0f + out[0]) * 0.5f) * (float)width),
round(((1.0f - out[1]) * 0.5f) * (float)height),
0.0f);
}
This function tells the 2D pixel coordinate of a 3D vertex. It works great for 8 of 9 cases, except for the last case, This last case is where the x location lies on screen and the y location lies below the screen. Instead of detecting these last case locations, it detects that the location is actually above the screen – that is, the value of p.y < 0, where it should be p.y > win_y. Any idea why? Thanks for your time.
P.S.
void init_perspective_camera(float fovy, float aspect, float znear, float zfar,
float eyex, float eyey, float eyez, float centrex, float centrey,
float centrez, float upx, float upy, float upz,
float (&projection_modelview_mat)[16])
{
float projection_mat[16];
get_perspective_matrix(fovy, aspect, znear, zfar, projection_mat);
float modelview_mat[16];
get_look_at_matrix(eyex, eyey, eyez, // Eye position.
centrex, centrey, centrez, // Look at position (not direction).
upx, upy, upz, // Up direction vector.
modelview_mat);
multiply_4x4_matrices(projection_mat, modelview_mat, projection_modelview_mat);
}
and
void multiply_4x4_matrix_by_4_vector(const float(&in_a)[16], const float(&in_b)[4], float(&out)[4])
{
float temp[4];
for (int i = 0; i < 4; i++)
{
temp[i] = 0.0;
for (int j = 0; j < 4; j++)
{
temp[i] += in_a[i*4 + j] * in_b[j];
}
}
for (size_t i = 0; i < 4; i++)
out[i] = temp[i];
}
void multiply_4x4_matrices(float (&in_a)[16], float (&in_b)[16], float (&out)[16])
{
/*
matrix layout:
[0 4 8 12]
[1 5 9 13]
[2 6 10 14]
[3 7 11 15]
*/
out[0] = in_a[0] * in_b[0] + in_a[4] * in_b[1] + in_a[8] * in_b[2] + in_a[12] * in_b[3];
out[1] = in_a[1] * in_b[0] + in_a[5] * in_b[1] + in_a[9] * in_b[2] + in_a[13] * in_b[3];
out[2] = in_a[2] * in_b[0] + in_a[6] * in_b[1] + in_a[10] * in_b[2] + in_a[14] * in_b[3];
out[3] = in_a[3] * in_b[0] + in_a[7] * in_b[1] + in_a[11] * in_b[2] + in_a[15] * in_b[3];
out[4] = in_a[0] * in_b[4] + in_a[4] * in_b[5] + in_a[8] * in_b[6] + in_a[12] * in_b[7];
out[5] = in_a[1] * in_b[4] + in_a[5] * in_b[5] + in_a[9] * in_b[6] + in_a[13] * in_b[7];
out[6] = in_a[2] * in_b[4] + in_a[6] * in_b[5] + in_a[10] * in_b[6] + in_a[14] * in_b[7];
out[7] = in_a[3] * in_b[4] + in_a[7] * in_b[5] + in_a[11] * in_b[6] + in_a[15] * in_b[7];
out[8] = in_a[0] * in_b[8] + in_a[4] * in_b[9] + in_a[8] * in_b[10] + in_a[12] * in_b[11];
out[9] = in_a[1] * in_b[8] + in_a[5] * in_b[9] + in_a[9] * in_b[10] + in_a[13] * in_b[11];
out[10] = in_a[2] * in_b[8] + in_a[6] * in_b[9] + in_a[10] * in_b[10] + in_a[14] * in_b[11];
out[11] = in_a[3] * in_b[8] + in_a[7] * in_b[9] + in_a[11] * in_b[10] + in_a[15] * in_b[11];
out[12] = in_a[0] * in_b[12] + in_a[4] * in_b[13] + in_a[8] * in_b[14] + in_a[12] * in_b[15];
out[13] = in_a[1] * in_b[12] + in_a[5] * in_b[13] + in_a[9] * in_b[14] + in_a[13] * in_b[15];
out[14] = in_a[2] * in_b[12] + in_a[6] * in_b[13] + in_a[10] * in_b[14] + in_a[14] * in_b[15];
out[15] = in_a[3] * in_b[12] + in_a[7] * in_b[13] + in_a[11] * in_b[14] + in_a[15] * in_b[15];
}