コード例 #1
0
/**
 * clutter_paint_volume_get_depth:
 * @pv: a #ClutterPaintVolume
 *
 * Retrieves the depth of the volume's, axis aligned, bounding box.
 *
 * In other words; this takes into account what actor's coordinate
 * space @pv belongs too and conceptually fits an axis aligned box
 * around the volume. It returns the size of that bounding box as
 * measured along the z-axis.
 *
 * If, for example, clutter_actor_get_transformed_paint_volume()
 * is used to transform a 2D child actor that is 100px wide, 100px
 * high and 0px deep into container coordinates then the depth might
 * not simply be 0px if the child actor has a 3D rotation applied to
 * it.
 *
 * Remember: if clutter_actor_get_transformed_paint_volume() is
 * used then the transformed volume will be defined relative to the
 * container actor and in container coordinates a 2D child actor
 * can have a 3D bounding volume.
 *
 * There are no accuracy guarantees for the reported depth,
 * except that it must always be greater than, or equal to, the actor's
 * depth. This is because actors may report simple, loose fitting paint
 * volumes for efficiency.
 *
 * Return value: the depth, in units of @pv's local coordinate system.
 *
 * Since: 1.6
 */
gfloat
clutter_paint_volume_get_depth (const ClutterPaintVolume *pv)
{
  g_return_val_if_fail (pv != NULL, 0.0);

  if (pv->is_empty)
    return 0;
  else if (!pv->is_axis_aligned)
    {
      ClutterPaintVolume tmp;
      float depth;
      _clutter_paint_volume_copy_static (pv, &tmp);
      _clutter_paint_volume_axis_align (&tmp);
      depth = tmp.vertices[4].z - tmp.vertices[0].z;
      clutter_paint_volume_free (&tmp);
      return depth;
    }
  else
    return pv->vertices[4].z - pv->vertices[0].z;
}
コード例 #2
0
/**
 * clutter_paint_volume_get_height:
 * @pv: a #ClutterPaintVolume
 *
 * Retrieves the height of the volume's, axis aligned, bounding box.
 *
 * In other words; this takes into account what actor's coordinate
 * space @pv belongs too and conceptually fits an axis aligned box
 * around the volume. It returns the size of that bounding box as
 * measured along the y-axis.
 *
 * If, for example, clutter_actor_get_transformed_paint_volume()
 * is used to transform a 2D child actor that is 100px wide, 100px
 * high and 0px deep into container coordinates then the height might
 * not simply be 100px if the child actor has a 3D rotation applied to
 * it.
 *
 * Remember: if clutter_actor_get_transformed_paint_volume() is
 * used then a transformed child volume will be defined relative to the
 * ancestor container actor and so a 2D child actor
 * can have a 3D bounding volume.
 *
 * There are no accuracy guarantees for the reported height,
 * except that it must always be greater than, or equal to, the actor's
 * height. This is because actors may report simple, loose fitting paint
 * volumes for efficiency.
 *
 * Return value: the height, in units of @pv's local coordinate system.
 *
 * Since: 1.6
 */
gfloat
clutter_paint_volume_get_height (const ClutterPaintVolume *pv)
{
  g_return_val_if_fail (pv != NULL, 0.0);

  if (pv->is_empty)
    return 0;
  else if (!pv->is_axis_aligned)
    {
      ClutterPaintVolume tmp;
      float height;
      _clutter_paint_volume_copy_static (pv, &tmp);
      _clutter_paint_volume_axis_align (&tmp);
      height = tmp.vertices[3].y - tmp.vertices[0].y;
      clutter_paint_volume_free (&tmp);
      return height;
    }
  else
    return pv->vertices[3].y - pv->vertices[0].y;
}
コード例 #3
0
void
_clutter_paint_volume_get_stage_paint_box (ClutterPaintVolume *pv,
                                           ClutterStage *stage,
                                           ClutterActorBox *box)
{
  ClutterPaintVolume projected_pv;
  CoglMatrix modelview;
  CoglMatrix projection;
  float viewport[4];

  _clutter_paint_volume_copy_static (pv, &projected_pv);

  cogl_matrix_init_identity (&modelview);

  /* If the paint volume isn't already in eye coordinates... */
  if (pv->actor)
    _clutter_actor_apply_relative_transformation_matrix (pv->actor, NULL,
                                                         &modelview);

  _clutter_stage_get_projection_matrix (stage, &projection);
  _clutter_stage_get_viewport (stage,
                               &viewport[0],
                               &viewport[1],
                               &viewport[2],
                               &viewport[3]);

  _clutter_paint_volume_project (&projected_pv,
                                 &modelview,
                                 &projection,
                                 viewport);

  _clutter_paint_volume_get_bounding_box (&projected_pv, box);

  _clutter_actor_box_enlarge_for_effects (box);

  clutter_paint_volume_free (&projected_pv);
}
コード例 #4
0
/**
 * clutter_paint_volume_union:
 * @pv: The first #ClutterPaintVolume and destination for resulting
 *      union
 * @another_pv: A second #ClutterPaintVolume to union with @pv
 *
 * Updates the geometry of @pv to encompass @pv and @another_pv.
 *
 * There are no guarantees about how precisely the two volumes
 * will be unioned.
 *
 * Since: 1.6
 */
void
clutter_paint_volume_union (ClutterPaintVolume *pv,
                            const ClutterPaintVolume *another_pv)
{
  ClutterPaintVolume aligned_pv;

  g_return_if_fail (pv != NULL);
  g_return_if_fail (another_pv != NULL);

  /* 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.
   */
  if (another_pv->is_empty)
    return;

  if (pv->is_empty)
    {
      _clutter_paint_volume_set_from_volume (pv, another_pv);
      goto done;
    }

  if (!pv->is_axis_aligned)
    _clutter_paint_volume_axis_align (pv);

  if (!another_pv->is_axis_aligned)
    {
      _clutter_paint_volume_copy_static (another_pv, &aligned_pv);
      _clutter_paint_volume_axis_align (&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; */
    }

  /* 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; */
    }

  /* 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; */
    }

  /* 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; */
    }

  if (pv->vertices[4].z == pv->vertices[0].z)
    pv->is_2d = TRUE;
  else
    pv->is_2d = FALSE;

done:
  pv->is_empty = FALSE;
  pv->is_complete = FALSE;
}
コード例 #5
0
void
_clutter_paint_volume_get_stage_paint_box (ClutterPaintVolume *pv,
                                           ClutterStage *stage,
                                           ClutterActorBox *box)
{
  ClutterPaintVolume projected_pv;
  CoglMatrix modelview;
  CoglMatrix projection;
  float viewport[4];
  float width;
  float height;

  _clutter_paint_volume_copy_static (pv, &projected_pv);

  cogl_matrix_init_identity (&modelview);

  /* If the paint volume isn't already in eye coordinates... */
  if (pv->actor)
    _clutter_actor_apply_relative_transformation_matrix (pv->actor, NULL,
                                                         &modelview);

  _clutter_stage_get_projection_matrix (stage, &projection);
  _clutter_stage_get_viewport (stage,
                               &viewport[0],
                               &viewport[1],
                               &viewport[2],
                               &viewport[3]);

  _clutter_paint_volume_project (&projected_pv,
                                 &modelview,
                                 &projection,
                                 viewport);

  _clutter_paint_volume_get_bounding_box (&projected_pv, box);

  /* The aim here is that for a given rectangle defined with floating point
   * coordinates we want to determine a stable quantized size in pixels
   * that doesn't vary due to the original box's sub-pixel position.
   *
   * The reason this is important is because effects will use this
   * API to determine the size of offscreen framebuffers and so for
   * a fixed-size object that may be animated accross the screen we
   * want to make sure that the stage paint-box has an equally stable
   * size so that effects aren't made to continuously re-allocate
   * a corresponding fbo.
   *
   * The other thing we consider is that the calculation of this box is
   * subject to floating point precision issues that might be slightly
   * different to the precision issues involved with actually painting the
   * actor, which might result in painting slightly leaking outside the
   * user's calculated paint-volume. For this we simply aim to pad out the
   * paint-volume by at least half a pixel all the way around.
   */
  width = box->x2 - box->x1;
  height = box->y2 - box->y1;
  width = CLUTTER_NEARBYINT (width);
  height = CLUTTER_NEARBYINT (height);
  /* XXX: NB the width/height may now be up to 0.5px too small so we
   * must also pad by 0.25px all around to account for this. In total we
   * must padd by at least 0.75px around all sides. */

  /* XXX: The furthest that we can overshoot the bottom right corner by
   * here is 1.75px in total if you consider that the 0.75 padding could
   * just cross an integer boundary and so ceil will effectively add 1.
   */
  box->x2 = ceilf (box->x2 + 0.75);
  box->y2 = ceilf (box->y2 + 0.75);

  /* Now we redefine the top-left relative to the bottom right based on the
   * rounded width/height determined above + a constant so that the overall
   * size of the box will be stable and not dependant on the box's
   * position.
   *
   * Adding 3px to the width/height will ensure we cover the maximum of
   * 1.75px padding on the bottom/right and still ensure we have > 0.75px
   * padding on the top/left.
   */
  box->x1 = box->x2 - width - 3;
  box->y1 = box->y2 - height - 3;

  clutter_paint_volume_free (&projected_pv);
}