cogl-clip-stack: Use orientation of the polygon to set clip planes

Previously the clip stack code was trying to detect when the
orientation of the on-screen rectangle had changed by checking if the
order of the y-coordinates on the left edge was different from the
order the x-coordinates on the top edge. This doesn't work for some
rotations which was causing the clip planes to clip the wrong side of
the line. This patch makes it detect the orientation by calculating
the signed area which is a standard computer graphics algorithm.

http://bugzilla.openedhand.com/show_bug.cgi?id=2079
This commit is contained in:
Neil Roberts 2010-04-20 14:58:57 +01:00
parent 7f2b2e1364
commit abc64a2c67

View File

@ -243,6 +243,7 @@ set_clip_planes (float x_1,
CoglMatrixStack *projection_stack = CoglMatrixStack *projection_stack =
_cogl_framebuffer_get_projection_stack (framebuffer); _cogl_framebuffer_get_projection_stack (framebuffer);
CoglMatrix projection_matrix; CoglMatrix projection_matrix;
float signed_area;
float vertex_tl[4] = { x_1, y_1, 0, 1.0 }; float vertex_tl[4] = { x_1, y_1, 0, 1.0 };
float vertex_tr[4] = { x_2, y_1, 0, 1.0 }; float vertex_tr[4] = { x_2, y_1, 0, 1.0 };
@ -257,27 +258,31 @@ set_clip_planes (float x_1,
project_vertex (&modelview_matrix, &projection_matrix, vertex_bl); project_vertex (&modelview_matrix, &projection_matrix, vertex_bl);
project_vertex (&modelview_matrix, &projection_matrix, vertex_br); project_vertex (&modelview_matrix, &projection_matrix, vertex_br);
/* If the order of the top and bottom lines is different from the /* Calculate the signed area of the polygon formed by the four
order of the left and right lines then the clip rect must have vertices so that we can know its orientation */
been transformed so that the back is visible. We therefore need signed_area = (vertex_tl[0] * (vertex_tr[1] - vertex_bl[1])
to swap one pair of vertices otherwise all of the planes will be + vertex_tr[0] * (vertex_br[1] - vertex_tl[1])
the wrong way around */ + vertex_br[0] * (vertex_bl[1] - vertex_tr[1])
if ((vertex_tl[0] < vertex_tr[0] ? 1 : 0) + vertex_bl[0] * (vertex_tl[1] - vertex_br[1]));
!= (vertex_bl[1] < vertex_tl[1] ? 1 : 0))
{
float temp[4];
memcpy (temp, vertex_tl, sizeof (temp));
memcpy (vertex_tl, vertex_tr, sizeof (temp));
memcpy (vertex_tr, temp, sizeof (temp));
memcpy (temp, vertex_bl, sizeof (temp));
memcpy (vertex_bl, vertex_br, sizeof (temp));
memcpy (vertex_br, temp, sizeof (temp));
}
set_clip_plane (GL_CLIP_PLANE0, vertex_tl, vertex_tr); /* Set the clip planes to form lines between all of the vertices
set_clip_plane (GL_CLIP_PLANE1, vertex_tr, vertex_br); using the same orientation as we calculated */
set_clip_plane (GL_CLIP_PLANE2, vertex_br, vertex_bl); if (signed_area > 0.0f)
set_clip_plane (GL_CLIP_PLANE3, vertex_bl, vertex_tl); {
/* counter-clockwise */
set_clip_plane (GL_CLIP_PLANE0, vertex_tl, vertex_bl);
set_clip_plane (GL_CLIP_PLANE1, vertex_bl, vertex_br);
set_clip_plane (GL_CLIP_PLANE2, vertex_br, vertex_tr);
set_clip_plane (GL_CLIP_PLANE3, vertex_tr, vertex_tl);
}
else
{
/* clockwise */
set_clip_plane (GL_CLIP_PLANE0, vertex_tl, vertex_tr);
set_clip_plane (GL_CLIP_PLANE1, vertex_tr, vertex_br);
set_clip_plane (GL_CLIP_PLANE2, vertex_br, vertex_bl);
set_clip_plane (GL_CLIP_PLANE3, vertex_bl, vertex_tl);
}
} }
void void