clutter/paint-volume: Use graphene for computing union of paint volumes

Apparently clutter_paint_volume_union() has problems building the union
of two paint volumes in eye coordinates, that's probably because of the
negative coordinates that come into play there.

Circumvent that by making even more use of Graphene and letting it take
care of computing the union. We do that by creating two graphene_box_t's
from the axis-aligned paint volumes and intersecting those boxes, then
setting our vertices to the new min and max points of the resulting box.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1507
This commit is contained in:
Jonas Dreßler 2020-10-16 22:58:22 +02:00
parent 7ab3eac0e2
commit d2f8a30625

View File

@ -533,6 +533,11 @@ clutter_paint_volume_union (ClutterPaintVolume *pv,
const ClutterPaintVolume *another_pv)
{
ClutterPaintVolume aligned_pv;
graphene_point3d_t min;
graphene_point3d_t max;
graphene_box_t another_box;
graphene_box_t union_box;
graphene_box_t box;
g_return_if_fail (pv != NULL);
g_return_if_fail (another_pv != NULL);
@ -540,9 +545,6 @@ clutter_paint_volume_union (ClutterPaintVolume *pv,
/* Both volumes have to belong to the same local coordinate space */
g_return_if_fail (pv->actor == another_pv->actor);
/* NB: we only have to update vertices 0, 1, 3 and 4
* (See the ClutterPaintVolume typedef for more details) */
/* We special case empty volumes because otherwise we'd end up
* calculating a bounding box that would enclose the origin of
* the empty volume which isn't desired.
@ -559,78 +561,34 @@ clutter_paint_volume_union (ClutterPaintVolume *pv,
if (!pv->is_axis_aligned)
_clutter_paint_volume_axis_align (pv);
if (!another_pv->is_axis_aligned)
_clutter_paint_volume_complete (pv);
if (!another_pv->is_axis_aligned || !another_pv->is_complete)
{
_clutter_paint_volume_copy_static (another_pv, &aligned_pv);
_clutter_paint_volume_axis_align (&aligned_pv);
_clutter_paint_volume_complete (&aligned_pv);
another_pv = &aligned_pv;
}
/* grow left*/
/* left vertices 0, 3, 4, 7 */
if (another_pv->vertices[0].x < pv->vertices[0].x)
{
int min_x = another_pv->vertices[0].x;
pv->vertices[0].x = min_x;
pv->vertices[3].x = min_x;
pv->vertices[4].x = min_x;
/* pv->vertices[7].x = min_x; */
}
if (G_LIKELY (pv->is_2d))
graphene_box_init_from_points (&box, 4, pv->vertices);
else
graphene_box_init_from_points (&box, 8, pv->vertices);
/* grow right */
/* right vertices 1, 2, 5, 6 */
if (another_pv->vertices[1].x > pv->vertices[1].x)
{
int max_x = another_pv->vertices[1].x;
pv->vertices[1].x = max_x;
/* pv->vertices[2].x = max_x; */
/* pv->vertices[5].x = max_x; */
/* pv->vertices[6].x = max_x; */
}
if (G_LIKELY (another_pv->is_2d))
graphene_box_init_from_points (&another_box, 4, another_pv->vertices);
else
graphene_box_init_from_points (&another_box, 8, another_pv->vertices);
/* grow up */
/* top vertices 0, 1, 4, 5 */
if (another_pv->vertices[0].y < pv->vertices[0].y)
{
int min_y = another_pv->vertices[0].y;
pv->vertices[0].y = min_y;
pv->vertices[1].y = min_y;
pv->vertices[4].y = min_y;
/* pv->vertices[5].y = min_y; */
}
graphene_box_union (&box, &another_box, &union_box);
/* grow down */
/* bottom vertices 2, 3, 6, 7 */
if (another_pv->vertices[3].y > pv->vertices[3].y)
{
int may_y = another_pv->vertices[3].y;
/* pv->vertices[2].y = may_y; */
pv->vertices[3].y = may_y;
/* pv->vertices[6].y = may_y; */
/* pv->vertices[7].y = may_y; */
}
/* grow forward */
/* front vertices 0, 1, 2, 3 */
if (another_pv->vertices[0].z < pv->vertices[0].z)
{
int min_z = another_pv->vertices[0].z;
pv->vertices[0].z = min_z;
pv->vertices[1].z = min_z;
/* pv->vertices[2].z = min_z; */
pv->vertices[3].z = min_z;
}
/* grow backward */
/* back vertices 4, 5, 6, 7 */
if (another_pv->vertices[4].z > pv->vertices[4].z)
{
int maz_z = another_pv->vertices[4].z;
pv->vertices[4].z = maz_z;
/* pv->vertices[5].z = maz_z; */
/* pv->vertices[6].z = maz_z; */
/* pv->vertices[7].z = maz_z; */
}
graphene_box_get_min (&union_box, &min);
graphene_box_get_max (&union_box, &max);
graphene_point3d_init (&pv->vertices[0], min.x, max.y, min.z);
graphene_point3d_init (&pv->vertices[1], max.x, max.y, min.z);
graphene_point3d_init (&pv->vertices[3], min.x, min.y, min.z);
graphene_point3d_init (&pv->vertices[4], min.x, max.y, max.z);
if (pv->vertices[4].z == pv->vertices[0].z)
pv->is_2d = TRUE;