Esempio n. 1
0
void
rut_camera_unproject_coord (RutCamera *camera,
                            const CoglMatrix *modelview,
                            const CoglMatrix *inverse_modelview,
                            float object_coord_z,
                            float *x,
                            float *y)
{
  const CoglMatrix *projection = rut_camera_get_projection (camera);
  const CoglMatrix *inverse_projection =
    rut_camera_get_inverse_projection (camera);
  //float z;
  float ndc_x, ndc_y, ndc_z, ndc_w;
  float eye_x, eye_y, eye_z, eye_w;
  const float *viewport = rut_camera_get_viewport (camera);

  /* Convert item z into NDC z */
  {
    //float x = 0, y = 0, z = 0, w = 1;
    float z = 0, w = 1;
    float tmp_x, tmp_y, tmp_z;
    const CoglMatrix *m = modelview;

    tmp_x = m->xw;
    tmp_y = m->yw;
    tmp_z = m->zw;

    m = projection;
    z = m->zx * tmp_x + m->zy * tmp_y + m->zz * tmp_z + m->zw;
    w = m->wx * tmp_x + m->wy * tmp_y + m->wz * tmp_z + m->ww;

    ndc_z = z / w;
  }

  /* Undo the Viewport transform, putting us in Normalized Device Coords */
  ndc_x = (*x - viewport[0]) * 2.0f / viewport[2] - 1.0f;
  ndc_y = ((viewport[3] - 1 + viewport[1] - *y) * 2.0f / viewport[3] - 1.0f);

  /* Undo the Projection, putting us in Eye Coords. */
  ndc_w = 1;
  cogl_matrix_transform_point (inverse_projection,
                               &ndc_x, &ndc_y, &ndc_z, &ndc_w);
  eye_x = ndc_x / ndc_w;
  eye_y = ndc_y / ndc_w;
  eye_z = ndc_z / ndc_w;
  eye_w = 1;

  /* Undo the Modelview transform, putting us in Object Coords */
  cogl_matrix_transform_point (inverse_modelview,
                               &eye_x,
                               &eye_y,
                               &eye_z,
                               &eye_w);

  *x = eye_x;
  *y = eye_y;
  //*z = eye_z;
}
Esempio n. 2
0
static void
project_vertex (const CoglMatrix *modelview_matrix,
		const CoglMatrix *projection_matrix,
		float *vertex)
{
  int i;

  /* Apply the modelview matrix */
  cogl_matrix_transform_point (modelview_matrix,
                               &vertex[0], &vertex[1],
                               &vertex[2], &vertex[3]);
  /* Apply the projection matrix */
  cogl_matrix_transform_point (projection_matrix,
                               &vertex[0], &vertex[1],
                               &vertex[2], &vertex[3]);
  /* Convert from homogenized coordinates */
  for (i = 0; i < 4; i++)
    vertex[i] /= vertex[3];
}
Esempio n. 3
0
/* Transform a homogeneous vertex position from model space to Cogl
 * window coordinates (with 0,0 being top left) */
static void
transform_point (CoglMatrix *matrix_mv,
                 CoglMatrix *matrix_p,
                 float *viewport,
                 float *x,
                 float *y)
{
  float z = 0;
  float w = 1;

  /* Apply the modelview matrix transform */
  cogl_matrix_transform_point (matrix_mv, x, y, &z, &w);

  /* Apply the projection matrix transform */
  cogl_matrix_transform_point (matrix_p, x, y, &z, &w);

  /* Perform perspective division */
  *x /= w;
  *y /= w;

  /* Apply viewport transform */
  *x = VIEWPORT_TRANSFORM_X (*x, viewport[0], viewport[2]);
  *y = VIEWPORT_TRANSFORM_Y (*y, viewport[1], viewport[3]);
}
Esempio n. 4
0
/* Check if we're painting the MetaWindowGroup "untransformed". This can
 * differ from the result of actor_is_untransformed(window_group) if we're
 * inside a clone paint. The integer translation, if any, is returned.
 */
static gboolean
painting_untransformed (MetaWindowGroup *window_group,
                        int             *x_origin,
                        int             *y_origin)
{
  CoglMatrix modelview, projection, modelview_projection;
  ClutterVertex vertices[4];
  int width, height;
  float viewport[4];
  int i;

  cogl_get_modelview_matrix (&modelview);
  cogl_get_projection_matrix (&projection);

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

  meta_screen_get_size (window_group->screen, &width, &height);

  vertices[0].x = 0;
  vertices[0].y = 0;
  vertices[0].z = 0;
  vertices[1].x = width;
  vertices[1].y = 0;
  vertices[1].z = 0;
  vertices[2].x = 0;
  vertices[2].y = height;
  vertices[2].z = 0;
  vertices[3].x = width;
  vertices[3].y = height;
  vertices[3].z = 0;

  cogl_get_viewport (viewport);

  for (i = 0; i < 4; i++)
    {
      float w = 1;
      cogl_matrix_transform_point (&modelview_projection, &vertices[i].x, &vertices[i].y, &vertices[i].z, &w);
      vertices[i].x = MTX_GL_SCALE_X (vertices[i].x, w,
                                      viewport[2], viewport[0]);
      vertices[i].y = MTX_GL_SCALE_Y (vertices[i].y, w,
                                      viewport[3], viewport[1]);
    }

  return meta_actor_vertices_are_untransformed (vertices, width, height, x_origin, y_origin);
}
Esempio n. 5
0
void
_clutter_paint_volume_transform (ClutterPaintVolume *pv,
                                 const CoglMatrix *matrix)
{
  int transform_count;

  if (pv->is_empty)
    {
      gfloat w = 1;
      /* Just transform the origin */
      cogl_matrix_transform_point (matrix,
                                   &pv->vertices[0].x,
                                   &pv->vertices[0].y,
                                   &pv->vertices[0].z,
                                   &w);
      return;
    }

  /* All the vertices must be up to date, since after the transform
   * it wont be trivial to derive the other vertices. */
  _clutter_paint_volume_complete (pv);

  /* Most actors are 2D so we only have to transform the front 4
   * vertices of the paint volume... */
  if (G_LIKELY (pv->is_2d))
    transform_count = 4;
  else
    transform_count = 8;

  cogl_matrix_transform_points (matrix,
                                3,
                                sizeof (ClutterVertex),
                                pv->vertices,
                                sizeof (ClutterVertex),
                                pv->vertices,
                                transform_count);

  pv->is_axis_aligned = FALSE;
}
Esempio n. 6
0
void
_rut_volume_transform (RutVolume *volume,
                       const CoglMatrix *matrix)
{
  int transform_count;

  if (volume->is_empty)
    {
      float w = 1;
      /* Just transform the origin */
      cogl_matrix_transform_point (matrix,
                                   &volume->vertices[0].x,
                                   &volume->vertices[0].y,
                                   &volume->vertices[0].z,
                                   &w);
      return;
    }

  /* All the vertices must be up to date, since after the transform
   * it wont be trivial to derive the other vertices. */
  _rut_volume_complete (volume);

  /* Most actors are 2D so we only have to transform the front 4
   * vertices of the volume... */
  if (G_LIKELY (volume->is_2d))
    transform_count = 4;
  else
    transform_count = 8;

  cogl_matrix_transform_points (matrix,
                                3,
                                sizeof (RutVector3),
                                volume->vertices,
                                sizeof (RutVector3),
                                volume->vertices,
                                transform_count);

  volume->is_axis_aligned = FALSE;
}
Esempio n. 7
0
/**
 * mash_light_set_direction_uniform:
 * @light: The #MashLight which is generating the shader
 * @uniform_location: The location of the uniform
 * @direction_in: The untransformed direction uniform
 *
 * This is a convenience intended to be used within
 * mash_light_update_uniforms() to help set uniforms. It
 * should not generally need to be called by an application unless it
 * is implementing its own lighting algorithms.
 *
 * This is intended to help when setting a direction
 * uniform. @direction_in should be an untransformed array of 3 floats
 * representing a vector. The vector will be transformed into eye
 * space according to the inverse transposed matrix of @light so that
 * it won't change direction for non-uniform scaling transformations.
 */
void
mash_light_set_direction_uniform (MashLight *light,
                                  CoglHandle program,
                                  int uniform_location,
                                  const float *direction_in)
{
  float light_direction[4];
  CoglMatrix matrix, inverse_matrix;
  float magnitude;

  memcpy (light_direction, direction_in, sizeof (light_direction));

  mash_light_get_modelview_matrix (light, &matrix);

  /* To safely transform the direction when the matrix might not be
     orthogonal we need the transposed inverse matrix */

  cogl_matrix_get_inverse (&matrix, &inverse_matrix);
  transpose_matrix (&inverse_matrix, &matrix);

  cogl_matrix_transform_point (&matrix,
                               light_direction + 0,
                               light_direction + 1,
                               light_direction + 2,
                               light_direction + 3);

  /* Normalize the light direction */
  magnitude = sqrtf ((light_direction[0] * light_direction[0])
                     + (light_direction[1] * light_direction[1])
                     + (light_direction[2] * light_direction[2]));
  light_direction[0] /= magnitude;
  light_direction[1] /= magnitude;
  light_direction[2] /= magnitude;

  cogl_program_set_uniform_float (program,
                                  uniform_location,
                                  3, 1,
                                  light_direction);
}
Esempio n. 8
0
void
_clutter_util_fully_transform_vertices (const CoglMatrix *modelview,
                                        const CoglMatrix *projection,
                                        const int *viewport,
                                        const ClutterVertex *vertices_in,
                                        ClutterVertex *vertices_out,
                                        int n_vertices)
{
  CoglMatrix modelview_projection;
  int i;

  /* XXX: we should find a way to cache this per actor */
  cogl_matrix_multiply (&modelview_projection,
                        projection,
                        modelview);

  for (i = 0; i < n_vertices; i++)
    {
      const ClutterVertex *vertex_in = &vertices_in[i];
      ClutterVertex *vertex_out = &vertices_out[i];
      gfloat x, y, z, w;

      x = vertex_in->x;
      y = vertex_in->y;
      z = vertex_in->z;
      w = 1.0;

      /* Transform the point using the modelview matrix */
      cogl_matrix_transform_point (&modelview_projection, &x, &y, &z, &w);

      /* Finally translate from OpenGL coords to window coords */
      vertex_out->x = MTX_GL_SCALE_X (x, w, viewport[2], viewport[0]);
      vertex_out->y = MTX_GL_SCALE_Y (y, w, viewport[3], viewport[1]);
      vertex_out->z = MTX_GL_SCALE_Z (z, w, viewport[2], viewport[0]);
    }
}
Esempio n. 9
0
static RutShapeModel *
shape_model_new (RutContext *ctx,
                 CoglBool shaped,
                 float tex_width,
                 float tex_height)
{
  RutShapeModel *shape_model = g_slice_new (RutShapeModel);
  RutBuffer *buffer = rut_buffer_new (sizeof (CoglVertexP3) * 6);
  RutMesh *pick_mesh = rut_mesh_new_from_buffer_p3 (COGL_VERTICES_MODE_TRIANGLES,
                                                    6,
                                                    buffer);
  CoglVertexP3 *pick_vertices = (CoglVertexP3 *)buffer->data;
  CoglMatrix matrix;
  float tex_aspect;
  float size_x;
  float size_y;
  float half_size_x;
  float half_size_y;
  float geom_size_x;
  float geom_size_y;
  float half_geom_size_x;
  float half_geom_size_y;

  rut_object_init (&shape_model->_parent, &rut_shape_model_type);

  shape_model->ref_count = 1;

  if (shaped)
    {
      /* In this case we are using a shape mask texture which is has a
       * square size and is padded with transparent pixels to provide
       * antialiasing. The shape mask is half the size of the texture
       * itself so we make the geometry twice as large to compensate.
       */
      size_x = MIN (tex_width, tex_height);
      size_y = size_x;
      geom_size_x = size_x * 2.0;
      geom_size_y = geom_size_x;
    }
  else
    {
      size_x = tex_width;
      size_y = tex_height;
      geom_size_x = tex_width;
      geom_size_y = tex_height;
    }

  half_size_x = size_x / 2.0;
  half_size_y = size_y / 2.0;
  half_geom_size_x = geom_size_x / 2.0;
  half_geom_size_y = geom_size_y / 2.0;

    {
      int n_vertices;
      int i;

      VertexP2T2T2 vertices[] =
        {
          { -half_geom_size_x, -half_geom_size_y, 0, 0, 0, 0 },
          { -half_geom_size_x,  half_geom_size_y, 0, 1, 0, 1 },
          {  half_geom_size_x,  half_geom_size_y, 1, 1, 1, 1 },

          { -half_geom_size_x, -half_geom_size_y, 0, 0, 0, 0 },
          {  half_geom_size_x,  half_geom_size_y, 1, 1, 1, 1 },
          {  half_geom_size_x, -half_geom_size_y, 1, 0, 1, 0 },
        };

      cogl_matrix_init_identity (&matrix);
      tex_aspect = (float)tex_width / (float)tex_height;

      if (shaped)
        {
          float s_scale, t_scale;
          float s0, t0;

          /* NB: The circle mask texture has a centered circle that is
           * half the width of the texture itself. We want the primary
           * texture to be mapped to this center circle. */

          s_scale = 2;
          t_scale = 2;

          if (tex_aspect < 1) /* taller than it is wide */
            t_scale *= tex_aspect;
          else /* wider than it is tall */
            {
              float inverse_aspect = 1.0f / tex_aspect;
              s_scale *= inverse_aspect;
            }

          s0 = 0.5 - (s_scale / 2.0);
          t0 = 0.5 - (t_scale / 2.0);

          cogl_matrix_translate (&matrix, s0, t0, 0);
          cogl_matrix_scale (&matrix, s_scale, t_scale, 1);
        }

      n_vertices = sizeof (vertices) / sizeof (VertexP2T2T2);
      for (i = 0; i < n_vertices; i++)
        {
          float z = 0, w = 1;

          cogl_matrix_transform_point (&matrix,
                                       &vertices[i].s1,
                                       &vertices[i].t1,
                                       &z,
                                       &w);
#ifdef MESA_CONST_ATTRIB_BUG_WORKAROUND
          vertices[i].Nx = 0;
          vertices[i].Ny = 0;
          vertices[i].Nz = 1;

          vertices[i].Tx = 1;
          vertices[i].Ty = 0;
          vertices[i].Tz = 0;
#endif
        }

      shape_model->primitive =
        primitive_new_p2t2t2 (ctx->cogl_context,
                              COGL_VERTICES_MODE_TRIANGLES,
                              n_vertices,
                              vertices);
    }

  shape_model->shape_texture = cogl_object_ref (ctx->circle_texture);

  pick_vertices[0].x = -half_size_x;
  pick_vertices[0].y = -half_size_y;
  pick_vertices[1].x = -half_size_x;
  pick_vertices[1].y = half_size_y;
  pick_vertices[2].x = half_size_x;
  pick_vertices[2].y = half_size_y;
  pick_vertices[3] = pick_vertices[0];
  pick_vertices[4] = pick_vertices[2];
  pick_vertices[5].x = half_size_x;
  pick_vertices[5].y = -half_size_y;

  shape_model->pick_mesh = pick_mesh;


  return shape_model;
}
Esempio n. 10
0
static RutDiamondSlice *
diamond_slice_new (RutContext *ctx,
                   float size,
                   int tex_width,
                   int tex_height)
{
  RutDiamondSlice *diamond_slice = g_slice_new (RutDiamondSlice);
  float width = size;
  float height = size;
#define DIAMOND_SLICE_CORNER_RADIUS 20
  CoglMatrix matrix;
  float tex_aspect;

  rut_object_init (&diamond_slice->_parent, &rut_diamond_slice_type);

  diamond_slice->ref_count = 1;

  diamond_slice->size = size;

    {
      /* x0,y0,x1,y1 and s0,t0,s1,t1 define the postion and texture
       * coordinates for the center rectangle... */
      float x0 = DIAMOND_SLICE_CORNER_RADIUS;
      float y0 = DIAMOND_SLICE_CORNER_RADIUS;
      float x1 = width - DIAMOND_SLICE_CORNER_RADIUS;
      float y1 = height - DIAMOND_SLICE_CORNER_RADIUS;

      /* The center region of the nine-slice can simply map to the
       * degenerate center of the circle */
      float s0 = 0.5;
      float t0 = 0.5;
      float s1 = 0.5;
      float t1 = 0.5;

      int n_vertices;
      int i;

      /*
       * 0,0      x0,0      x1,0      width,0
       * 0,0      s0,0      s1,0      1,0
       * 0        1         2         3
       *
       * 0,y0     x0,y0     x1,y0     width,y0
       * 0,t0     s0,t0     s1,t0     1,t0
       * 4        5         6         7
       *
       * 0,y1     x0,y1     x1,y1     width,y1
       * 0,t1     s0,t1     s1,t1     1,t1
       * 8        9         10        11
       *
       * 0,height x0,height x1,height width,height
       * 0,1      s0,1      s1,1      1,1
       * 12       13        14        15
       */

      VertexP2T2T2 vertices[] =
        {
          { 0,  0, 0, 0, 0, 0 },
          { x0, 0, s0, 0, x0, 0},
          { x1, 0, s1, 0, x1, 0},
          { width, 0, 1, 0, width, 0},

          { 0, y0, 0, t0, 0, y0},
          { x0, y0, s0, t0, x0, y0},
          { x1, y0, s1, t0, x1, y0},
          { width, y0, 1, t0, width, y0},

          { 0, y1, 0, t1, 0, y1},
          { x0, y1, s0, t1, x0, y1},
          { x1, y1, s1, t1, x1, y1},
          { width, y1, 1, t1, width, y1},

          { 0, height, 0, 1, 0, height},
          { x0, height, s0, 1, x0, height},
          { x1, height, s1, 1, x1, height},
          { width, height, 1, 1, width, height},
        };

      cogl_matrix_init_identity (&diamond_slice->rotate_matrix);
      cogl_matrix_rotate (&diamond_slice->rotate_matrix, 45, 0, 0, 1);
      cogl_matrix_translate (&diamond_slice->rotate_matrix, - width / 2.0, - height / 2.0, 0);

      n_vertices = sizeof (vertices) / sizeof (VertexP2T2T2);
      for (i = 0; i < n_vertices; i++)
        {
          float z = 0, w = 1;

          cogl_matrix_transform_point (&diamond_slice->rotate_matrix,
                                       &vertices[i].x,
                                       &vertices[i].y,
                                       &z,
                                       &w);

#ifdef MESA_CONST_ATTRIB_BUG_WORKAROUND
          vertices[i].Nx = 0;
          vertices[i].Ny = 0;
          vertices[i].Nz = 1;

          vertices[i].Tx = 1;
          vertices[i].Ty = 0;
          vertices[i].Tz = 0;
#endif
        }

      cogl_matrix_init_identity (&matrix);

      {
        float s_scale = 1.0, t_scale = 1.0;
        float s0, t0;
        float diagonal_size_scale = 1.0 / (sinf (G_PI_4) * 2.0);

        tex_aspect = (float)tex_width / (float)tex_height;

        if (tex_aspect < 1) /* taller than it is wide */
          t_scale *= tex_aspect;
        else /* wider than it is tall */
          {
            float inverse_aspect = 1.0f / tex_aspect;
            s_scale *= inverse_aspect;
          }

        s_scale *= diagonal_size_scale;
        t_scale *= diagonal_size_scale;

        s0 = 0.5 - (s_scale / 2.0);
        t0 = 0.5 - (t_scale / 2.0);

        cogl_matrix_translate (&matrix, s0, t0, 0);
        cogl_matrix_scale (&matrix, s_scale / width, t_scale / height, 1);

        cogl_matrix_translate (&matrix, width / 2.0, height / 2.0, 1);
        cogl_matrix_rotate (&matrix, 45, 0, 0, 1);
        cogl_matrix_translate (&matrix, -width / 2.0, -height / 2.0, 1);
      }

      n_vertices = sizeof (vertices) / sizeof (VertexP2T2T2);
      for (i = 0; i < n_vertices; i++)
        {
          float z = 0, w = 1;

          cogl_matrix_transform_point (&matrix,
                                       &vertices[i].s1,
                                       &vertices[i].t1,
                                       &z,
                                       &w);
        }


      diamond_slice->primitive =
        primitive_new_p2t2t2 (ctx->cogl_context,
                              COGL_VERTICES_MODE_TRIANGLES,
                              n_vertices,
                              vertices);

      /* The vertices uploaded only map to the key intersection points of the
       * 9-slice grid which isn't a topology that GPUs can handle directly so
       * this specifies an array of indices that allow the GPU to interpret the
       * vertices as a list of triangles... */
      cogl_primitive_set_indices (diamond_slice->primitive,
                                  ctx->nine_slice_indices,
                                  sizeof (_rut_nine_slice_indices_data) /
                                  sizeof (_rut_nine_slice_indices_data[0]));
    }

  return diamond_slice;
}
Esempio n. 11
0
CoglPrimitive *
rut_camera_create_frustum_primitive (RutCamera *camera)
{
  RutVertex4 vertices[8] = {
    /* near plane in projection space */
    {-1, -1, -1, 1, },
    { 1, -1, -1, 1, },
    { 1,  1, -1, 1, },
    {-1,  1, -1, 1, },
    /* far plane in projection space */
    {-1, -1, 1, 1, },
    { 1, -1, 1, 1, },
    { 1,  1, 1, 1, },
    {-1,  1, 1, 1, }
  };
  const CoglMatrix *projection_inv;
  CoglAttributeBuffer *attribute_buffer;
  CoglAttribute *attributes[1];
  CoglPrimitive *primitive;
  CoglIndices *indices;
  unsigned char indices_data[24] = {
      0,1, 1,2, 2,3, 3,0,
      4,5, 5,6, 6,7, 7,4,
      0,4, 1,5, 2,6, 3,7
  };
  int i;

  projection_inv = rut_camera_get_inverse_projection (camera);

  for (i = 0; i < 8; i++)
    {
      cogl_matrix_transform_point (projection_inv,
                                   &vertices[i].x,
                                   &vertices[i].y,
                                   &vertices[i].z,
                                   &vertices[i].w);
      vertices[i].x /= vertices[i].w;
      vertices[i].y /= vertices[i].w;
      vertices[i].z /= vertices[i].w;
      vertices[i].w /= 1.0f;
    }

  attribute_buffer = cogl_attribute_buffer_new (rut_cogl_context,
                                                8 * sizeof (RutVertex4),
                                                vertices);

  attributes[0] = cogl_attribute_new (attribute_buffer,
                                      "cogl_position_in",
                                      sizeof (RutVertex4),
                                      offsetof (RutVertex4, x),
                                      3,
                                      COGL_ATTRIBUTE_TYPE_FLOAT);

  indices = cogl_indices_new (rut_cogl_context,
                              COGL_INDICES_TYPE_UNSIGNED_BYTE,
                              indices_data,
                              G_N_ELEMENTS (indices_data));

  primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_LINES,
                                                  8, attributes, 1);

  cogl_primitive_set_indices (primitive, indices, G_N_ELEMENTS(indices_data));

  cogl_object_unref (attribute_buffer);
  cogl_object_unref (attributes[0]);
  cogl_object_unref (indices);

  return primitive;
}