Ejemplo n.º 1
0
/* Try to push a rectangle given in object coordinates as a rectangle in window
 * coordinates instead of object coordinates */
gboolean
try_pushing_rect_as_window_rect (float x_1,
	                         float y_1,
                                 float x_2,
                                 float y_2)
{
  CoglMatrix matrix;
  CoglMatrix matrix_p;
  float v[4];

  cogl_get_modelview_matrix (&matrix);

  /* If the modelview meets these constraints then a transformed rectangle
   * should still be a rectangle when it reaches screen coordinates.
   *
   * FIXME: we are are making certain assumptions about the projection
   * matrix a.t.m and should really be looking at the combined modelview
   * and projection matrix.
   * FIXME: we don't consider rotations that are a multiple of 90 degrees
   * which could be quite common.
   */
  if (matrix.xy != 0 || matrix.xz != 0 ||
      matrix.yx != 0 || matrix.yz != 0 ||
      matrix.zx != 0 || matrix.zy != 0)
    return FALSE;

  cogl_get_projection_matrix (&matrix_p);
  cogl_get_viewport (v);

  transform_point (&matrix, &matrix_p, v, &x_1, &y_1);
  transform_point (&matrix, &matrix_p, v, &x_2, &y_2);

  /* Consider that the modelview matrix may flip the rectangle
   * along the x or y axis... */
#define SWAP(A,B) do { float tmp = B; B = A; A = tmp; } while (0)
  if (x_1 > x_2)
    SWAP (x_1, x_2);
  if (y_1 > y_2)
    SWAP (y_1, y_2);
#undef SWAP

  cogl_clip_push_window_rectangle (COGL_UTIL_NEARBYINT (x_1),
                                   COGL_UTIL_NEARBYINT (y_1),
                                   COGL_UTIL_NEARBYINT (x_2 - x_1),
                                   COGL_UTIL_NEARBYINT (y_2 - y_1));
  return TRUE;
}
Ejemplo n.º 2
0
CoglClipStack *
_cogl_clip_stack_push_rectangle (CoglClipStack *stack,
                                 float x_1,
                                 float y_1,
                                 float x_2,
                                 float y_2,
                                 CoglMatrixEntry *modelview_entry,
                                 CoglMatrixEntry *projection_entry,
                                 const float *viewport)
{
  CoglClipStackRect *entry;
  CoglMatrix modelview;
  CoglMatrix projection;
  CoglMatrix modelview_projection;

  /* Corners of the given rectangle in an clockwise order:
   *  (0, 1)     (2, 3)
   *
   *
   *
   *  (6, 7)     (4, 5)
   */
  float rect[] = {
    x_1, y_1,
    x_2, y_1,
    x_2, y_2,
    x_1, y_2
  };

  /* Make a new entry */
  entry = _cogl_clip_stack_push_entry (stack,
                                       sizeof (CoglClipStackRect),
                                       COGL_CLIP_STACK_RECT);

  entry->x0 = x_1;
  entry->y0 = y_1;
  entry->x1 = x_2;
  entry->y1 = y_2;

  entry->matrix_entry = cogl_matrix_entry_ref (modelview_entry);

  cogl_matrix_entry_get (modelview_entry, &modelview);
  cogl_matrix_entry_get (projection_entry, &projection);

  cogl_matrix_multiply (&modelview_projection,
                        &projection,
                        &modelview);

  /* Technically we could avoid the viewport transform at this point
   * if we want to make this a bit faster. */
  _cogl_transform_point (&modelview, &projection, viewport, &rect[0], &rect[1]);
  _cogl_transform_point (&modelview, &projection, viewport, &rect[2], &rect[3]);
  _cogl_transform_point (&modelview, &projection, viewport, &rect[4], &rect[5]);
  _cogl_transform_point (&modelview, &projection, viewport, &rect[6], &rect[7]);

  /* If the fully transformed rectangle isn't still axis aligned we
   * can't handle it using a scissor.
   *
   * We don't use an epsilon here since we only really aim to catch
   * simple cases where the transform doesn't leave the rectangle screen
   * aligned and don't mind some false positives.
   */
  if (rect[0] != rect[6] ||
      rect[1] != rect[3] ||
      rect[2] != rect[4] ||
      rect[7] != rect[5])
    {
      entry->can_be_scissor = FALSE;

      _cogl_clip_stack_entry_set_bounds ((CoglClipStack *) entry,
                                         rect);
    }
  else
    {
      CoglClipStack *base_entry = (CoglClipStack *) entry;
      x_1 = rect[0];
      y_1 = rect[1];
      x_2 = rect[4];
      y_2 = rect[5];

      /* Consider that the modelview matrix may flip the rectangle
       * along the x or y axis... */
#define SWAP(A,B) do { float tmp = B; B = A; A = tmp; } while (0)
      if (x_1 > x_2)
        SWAP (x_1, x_2);
      if (y_1 > y_2)
        SWAP (y_1, y_2);
#undef SWAP

      base_entry->bounds_x0 = COGL_UTIL_NEARBYINT (x_1);
      base_entry->bounds_y0 = COGL_UTIL_NEARBYINT (y_1);
      base_entry->bounds_x1 = COGL_UTIL_NEARBYINT (x_2);
      base_entry->bounds_y1 = COGL_UTIL_NEARBYINT (y_2);
      entry->can_be_scissor = TRUE;
    }

  return (CoglClipStack *) entry;
}