[mutter/gbsneto/untransformed-graphene-box-picking: 3/4] clutter/pick-stack: Use graphene_box_t for axis-aligned rectangles




commit a92def79e46d32548fd5e8575514069d29d7fca9
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Mon Nov 23 11:52:34 2020 -0300

    clutter/pick-stack: Use graphene_box_t for axis-aligned rectangles
    
    The most common case for Clutter is 2D axis-aligned actors, which
    maintain these properties even after projecting to eye coordinates.
    In those cases, we can use a simpler hit test by checking against
    boxes.
    
    Not only this is simpler, but this maintains an important aspect
    of picking that is a requirement for Clutter: watertightness. Even
    though the triangles checks do work on x86_64, they do not guarantee
    watertightness. This breaks tests on ARM.
    
    Use graphene_box_t to hit-test axis-aligned 2D actors.

 clutter/clutter/clutter-pick-stack.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
---
diff --git a/clutter/clutter/clutter-pick-stack.c b/clutter/clutter/clutter-pick-stack.c
index 6a0b13e58b..3c5ae786e2 100644
--- a/clutter/clutter/clutter-pick-stack.c
+++ b/clutter/clutter/clutter-pick-stack.c
@@ -91,6 +91,30 @@ maybe_project_record (Record *rec)
     }
 }
 
+static inline gboolean
+is_2d_rectangle (const graphene_point3d_t vertices[4])
+{
+  int i;
+
+  for (i = 0; i < 4; i++)
+    {
+      if (!G_APPROX_VALUE (vertices[i].z,
+                           vertices[(i + 1) % 4].z,
+                           FLT_EPSILON))
+        return FALSE;
+
+      if (!G_APPROX_VALUE (vertices[i].x,
+                           vertices[(i + 1) % 4].x,
+                           FLT_EPSILON) &&
+          !G_APPROX_VALUE (vertices[i].y,
+                           vertices[(i + 1) % 4].y,
+                           FLT_EPSILON))
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
 static gboolean
 ray_intersects_input_region (Record                   *rec,
                              const graphene_ray_t     *ray,
@@ -100,6 +124,15 @@ ray_intersects_input_region (Record                   *rec,
 
   maybe_project_record (rec);
 
+  if (G_LIKELY (is_2d_rectangle (rec->vertices)))
+    {
+      graphene_box_t box;
+
+      graphene_box_init_from_points (&box, 4, rec->vertices);
+      return graphene_box_contains_point (&box, point) ||
+             graphene_ray_intersects_box (ray, &box);
+    }
+
   /*
    * Degrade the projected quad into the following triangles:
    *


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]