Пример #1
0
static void
graphene_matrix_transpose_transform_vec4 (const graphene_matrix_t *m,
                                          const graphene_vec4_t   *v,
                                          graphene_vec4_t         *res)
{
  float x, y, z, w;

  x = graphene_simd4f_get_x (graphene_simd4f_sum (graphene_simd4f_mul (m->value.x, v->value)));
  y = graphene_simd4f_get_x (graphene_simd4f_sum (graphene_simd4f_mul (m->value.y, v->value)));
  z = graphene_simd4f_get_x (graphene_simd4f_sum (graphene_simd4f_mul (m->value.z, v->value)));
  w = graphene_simd4f_get_x (graphene_simd4f_sum (graphene_simd4f_mul (m->value.w, v->value)));

  graphene_vec4_init (res, x, y, z, w);
}
Пример #2
0
float
graphene_matrix_get_x_scale (const graphene_matrix_t *m)
{
  g_return_val_if_fail (m != NULL, 0.f);

  return graphene_simd4f_get_x (m->value.x);
}
Пример #3
0
/**
 * graphene_quaternion_slerp:
 * @a: a #graphene_quaternion_t
 * @b: a #graphene_quaternion_t
 * @factor: the linear interpolation factor
 * @res: (out caller-allocates): return location for the interpolated
 *   quaternion
 *
 * Interpolates between the two given quaternions using a spherical
 * linear interpolation, or [SLERP](http://en.wikipedia.org/wiki/Slerp),
 * using the given interpolation @factor.
 *
 * Since: 1.0
 */
void
graphene_quaternion_slerp (const graphene_quaternion_t *a,
                           const graphene_quaternion_t *b,
                           float                        factor,
                           graphene_quaternion_t       *res)
{
  float theta, r_sin_theta, right_v, left_v, dot;
  graphene_simd4f_t v_a, v_b, left, right, sum;

  v_a = graphene_simd4f_init (a->x, a->y, a->z, a->w);
  v_b = graphene_simd4f_init (b->x, b->y, b->z, b->w);

  dot = CLAMP (graphene_simd4f_get_x (graphene_simd4f_dot4 (v_a, v_b)), -1.f, 1.f);
  if (dot == 1.f)
    {
      *res = *a;
      return;
    }

  theta = acos (dot);
  r_sin_theta = 1.f / sqrtf (1.f - dot * dot);
  right_v = sinf (factor * theta) * r_sin_theta;
  left_v = cosf (factor * theta) - dot * right_v;

  left = graphene_simd4f_init (a->x, a->y, a->z, a->w);
  right = graphene_simd4f_init (b->x, b->y, b->z, b->w);

  left = graphene_simd4f_mul (left, graphene_simd4f_splat (left_v));
  right = graphene_simd4f_mul (right, graphene_simd4f_splat (right_v));
  sum = graphene_simd4f_add (left, right);

  graphene_quaternion_init_from_simd4f (res, sum);
}
Пример #4
0
float
graphene_matrix_get_value (const graphene_matrix_t *m,
                           unsigned int             row,
                           unsigned int             col)
{
  graphene_simd4f_t r;
  float c = 0.f;

  g_return_val_if_fail (m != NULL, 0.f);
  g_return_val_if_fail (row >= 0 && row < 4, 0.f);
  g_return_val_if_fail (col >= 0 && row < 4, 0.f);

  switch (row)
    {
    case 0:
      r = m->value.x;
      break;

    case 1:
      r = m->value.y;
      break;

    case 2:
      r = m->value.z;
      break;

    case 3:
      r = m->value.w;
      break;

    default:
      g_assert_not_reached ();
    }

  switch (col)
    {
    case 0:
      c = graphene_simd4f_get_x (r);
      break;

    case 1:
      c = graphene_simd4f_get_y (r);
      break;

    case 2:
      c = graphene_simd4f_get_z (r);
      break;

    case 3:
      c = graphene_simd4f_get_w (r);
      break;

    default:
      g_assert_not_reached ();
    }

  return c;
}
Пример #5
0
/**
 * graphene_matrix_determinant:
 * @m: a #graphene_matrix_t
 *
 * Computes the determinant of the given matrix.
 *
 * Returns: the value of the determinant
 *
 * Since: 1.0
 */
float
graphene_matrix_determinant (const graphene_matrix_t *m)
{
  graphene_simd4f_t det;

  graphene_simd4x4f_determinant (&m->value, &det, NULL);

  return graphene_simd4f_get_x (det);
}
Пример #6
0
static graphene_quaternion_t *
graphene_quaternion_init_from_simd4f (graphene_quaternion_t *q,
                                      graphene_simd4f_t      v)
{
  q->x = graphene_simd4f_get_x (v);
  q->y = graphene_simd4f_get_y (v);
  q->z = graphene_simd4f_get_z (v);
  q->w = graphene_simd4f_get_w (v);

  return q;
}
Пример #7
0
/**
 * graphene_matrix_get_value:
 * @m: a #grapheme_matrix_t
 * @row: the row index
 * @col: the column index
 *
 * Retrieves the value at the given @row and @col index.
 *
 * Returns: the value at the given indices
 *
 * Since: 1.0
 */
float
graphene_matrix_get_value (const graphene_matrix_t *m,
                           unsigned int             row,
                           unsigned int             col)
{
  graphene_simd4f_t r;
  float c = 0.f;

  switch (row)
    {
    case 0:
      r = m->value.x;
      break;

    case 1:
      r = m->value.y;
      break;

    case 2:
      r = m->value.z;
      break;

    case 3:
      r = m->value.w;
      break;

    default:
      return 0.f;
    }

  switch (col)
    {
    case 0:
      c = graphene_simd4f_get_x (r);
      break;

    case 1:
      c = graphene_simd4f_get_y (r);
      break;

    case 2:
      c = graphene_simd4f_get_z (r);
      break;

    case 3:
      c = graphene_simd4f_get_w (r);
      break;

    default:
      return 0;
    }

  return c;
}
Пример #8
0
float
graphene_matrix_determinant (const graphene_matrix_t *m)
{
  graphene_simd4f_t det;

  g_return_val_if_fail (m != NULL, 0.f);

  graphene_simd4x4f_determinant (&m->value, &det, NULL);

  return graphene_simd4f_get_x (det);
}
Пример #9
0
/**
 * graphene_quaternion_dot:
 * @a: a #graphene_quaternion_t
 * @b: a #graphene_quaternion_t
 *
 * Computes the dot product of two #graphene_quaternion_t.
 *
 * Returns: the value of the dot products
 *
 * Since: 1.0
 */
float
graphene_quaternion_dot (const graphene_quaternion_t *a,
                         const graphene_quaternion_t *b)
{
  graphene_simd4f_t v_a, v_b;

  v_a = graphene_simd4f_init (a->x, a->y, a->z, a->w);
  v_b = graphene_simd4f_init (b->x, b->y, b->z, b->w);

  return graphene_simd4f_get_x (graphene_simd4f_dot4 (v_a, v_b));
}
Пример #10
0
/**
 * graphene_matrix_transform_point:
 * @m: a #graphene_matrix_t
 * @p: a #graphene_point_t
 * @res: (out caller-allocates): return location for the
 *   transformed #graphene_point_t
 *
 * Transforms the given #graphene_point_t using the matrix @m.
 *
 * Since: 1.0
 */
void
graphene_matrix_transform_point (const graphene_matrix_t *m,
                                 const graphene_point_t  *p,
                                 graphene_point_t        *res)
{
  graphene_simd4f_t vec3;

  vec3 = graphene_simd4f_init (p->x, p->y, 0.0f, 0.0f);
  graphene_simd4x4f_vec3_mul (&m->value, &vec3, &vec3);

  res->x = graphene_simd4f_get_x (vec3);
  res->y = graphene_simd4f_get_y (vec3);
}
Пример #11
0
static void
matrix_project (gpointer data_)
{
  MatrixBench *data = data_;
  int i;

  for (i = 0; i < N_ROUNDS; i++)
    {
      graphene_simd4f_t pback, qback, uback;
      float t, x, y;

      graphene_simd4x4f_vec3_mul (&(data->a[i]), &(data->pa[i]), &pback);
      graphene_simd4x4f_vec3_mul (&(data->a[i]), &(data->qa[i]), &qback);

      uback = graphene_simd4f_sub (data->pa[i], pback);
      t = -1.0f * graphene_simd4f_get_z (pback) / graphene_simd4f_get_z (uback);
      x = graphene_simd4f_get_x (pback) + t * graphene_simd4f_get_x (uback);
      y = graphene_simd4f_get_y (pback) + t * graphene_simd4f_get_y (uback);

      data->ra[i] = graphene_simd4f_init (x, y, 0.f, 0.f);
    }
}
Пример #12
0
/**
 * graphene_point_distance:
 * @a: a #graphene_point_t
 * @b: a #graphene_point_t
 * @d_x: (out) (optional): distance component on the X axis
 * @d_y: (out) (optional): distance component on the Y axis
 *
 * Computes the distance between @a and @b.
 *
 * Returns: the distance between the two points
 *
 * Since: 1.0
 */
float
graphene_point_distance (const graphene_point_t *a,
                         const graphene_point_t *b,
                         float                  *d_x,
                         float                  *d_y)
{
  graphene_simd4f_t s_a, s_b, res;

  if (a == b)
    return 0.f;

  s_a = graphene_simd4f_init (a->x, a->y, 0.f, 0.f);
  s_b = graphene_simd4f_init (b->x, b->y, 0.f, 0.f);
  res = graphene_simd4f_sub (s_a, s_b);

  if (d_x != NULL)
    *d_x = fabsf (graphene_simd4f_get_x (res));

  if (d_y != NULL)
    *d_y = fabsf (graphene_simd4f_get_y (res));

  return graphene_simd4f_get_x (graphene_simd4f_length2 (res));
}
Пример #13
0
/**
 * graphene_point_near:
 * @a: a #graphene_point_t
 * @b: a #graphene_point_t
 * @epsilon: threshold between the two points
 *
 * Checks whether the two points @a and @b are within
 * the threshold of @epsilon.
 *
 * Returns: `true` if the distance is within @epsilon
 *
 * Since: 1.0
 */
bool
graphene_point_near (const graphene_point_t *a,
                     const graphene_point_t *b,
                     float                   epsilon)
{
  graphene_simd4f_t s_a, s_b, res;

  if (a == b)
    return true;

  s_a = graphene_simd4f_init (a->x, a->y, 0.f, 0.f);
  s_b = graphene_simd4f_init (b->x, b->y, 0.f, 0.f);
  res = graphene_simd4f_sub (s_a, s_b);

  return fabsf (graphene_simd4f_get_x (res)) < epsilon &&
         fabsf (graphene_simd4f_get_y (res)) < epsilon;
}
Пример #14
0
/**
 * graphene_vec2_near:
 * @v1: a #graphene_vec2_t
 * @v2: a #graphene_vec2_t
 * @epsilon: the threshold between the two vectors
 *
 * Compares the two given #graphene_vec2_t vectors and checks
 * whether their values are within the given @epsilon.
 *
 * Returns: `true` if the two vectors are near each other
 *
 * Since: 1.2
 */
bool
graphene_vec2_near (const graphene_vec2_t *v1,
                    const graphene_vec2_t *v2,
                    float                  epsilon)
{
  float epsilon_sq = epsilon * epsilon;
  graphene_simd4f_t d;

  if (v1 == v2)
    return true;

  if (v1 == NULL || v2 == NULL)
    return false;

  d = graphene_simd4f_sub (v1->value, v2->value);

  return graphene_simd4f_get_x (graphene_simd4f_dot2 (d, d)) < epsilon_sq;
}
Пример #15
0
/**
 * graphene_quaternion_init_from_angle_vec3:
 * @q: a #graphene_quaternion_t
 * @angle: the rotation on a given axis, in degrees
 * @axis: the axis of rotation, expressed as a vector
 *
 * Initializes a #graphene_quaternion_t using an @angle on a
 * specific @axis.
 *
 * Returns: (transfer none): the initialized quaternion
 *
 * Since: 1.0
 */
graphene_quaternion_t *
graphene_quaternion_init_from_angle_vec3 (graphene_quaternion_t *q,
                                          float                  angle,
                                          const graphene_vec3_t *axis)
{
  float rad, sin_a, cos_a;
  graphene_simd4f_t axis_n;

  rad = GRAPHENE_DEG_TO_RAD (angle);

  sin_a = sinf (rad / 2.f);
  cos_a = cosf (rad / 2.f);
  axis_n = graphene_simd4f_mul (graphene_simd4f_normalize3 (axis->value),
                                graphene_simd4f_splat (sin_a));

  q->x = graphene_simd4f_get_x (axis_n);
  q->y = graphene_simd4f_get_y (axis_n);
  q->z = graphene_simd4f_get_z (axis_n);
  q->w = cos_a;

  return q;
}
Пример #16
0
static gboolean
matrix_decompose_3d (const graphene_matrix_t *m,
                     graphene_point3d_t      *scale_r,
                     float                    shear_r[3],
                     graphene_quaternion_t   *rotate_r,
                     graphene_point3d_t      *translate_r,
                     graphene_vec4_t         *perspective_r)
{
  graphene_matrix_t local, perspective;
  float shear_xy, shear_xz, shear_yz;
  float scale_x, scale_y, scale_z;
  graphene_simd4f_t dot, cross;

  if (graphene_matrix_get_value (m, 3, 3) == 0.f)
    return FALSE;

  local = *m;

  /* normalize the matrix */
  graphene_matrix_normalize (&local, &local);

  /* perspective is used to solve for the perspective component,
   * but it also provides an easy way to test for singularity of
   * the upper 3x3 component
   */
  perspective = local;
  perspective.value.w = graphene_simd4f_init (0.f, 0.f, 0.f, 1.f);

  if (graphene_matrix_determinant (&perspective) == 0.f)
    return FALSE;

  /* isolate the perspective */
  if (graphene_simd4f_is_zero3 (local.value.w))
    {
      graphene_matrix_t tmp;

      /* perspective_r is the right hand side of the equation */
      perspective_r->value = local.value.w;

      /* solve the equation by inverting perspective and multiplying
       * the inverse with the perspective vector
       */
      graphene_matrix_inverse (&perspective, &tmp);
      graphene_matrix_transpose_transform_vec4 (&tmp, perspective_r, perspective_r);

      /* clear the perspective partition */
      local.value.w = graphene_simd4f_init (0.f, 0.f, 0.f, 1.f);
    }
  else
    graphene_vec4_init (perspective_r, 0.f, 0.f, 0.f, 1.f);

  /* next, take care of the translation partition */
  translate_r->x = graphene_simd4f_get_x (local.value.w);
  translate_r->y = graphene_simd4f_get_y (local.value.w);
  translate_r->z = graphene_simd4f_get_z (local.value.w);
  local.value.w = graphene_simd4f_init (0.f, 0.f, 0.f, graphene_simd4f_get_w (local.value.w));

  /* now get scale and shear */

  /* compute the X scale factor and normalize the first row */
  scale_x = graphene_simd4f_get_x (graphene_simd4f_length4 (local.value.x));
  local.value.x = graphene_simd4f_div (local.value.x, graphene_simd4f_splat (scale_x));

  /* compute XY shear factor and the second row orthogonal to the first */
  shear_xy = graphene_simd4f_get_x (graphene_simd4f_dot4 (local.value.x, local.value.y));
  local.value.y = graphene_simd4f_sub (local.value.y, graphene_simd4f_mul (local.value.x, graphene_simd4f_splat (shear_xy)));

  /* now, compute the Y scale factor and normalize the second row */
  scale_y = graphene_simd4f_get_x (graphene_simd4f_length4 (local.value.y));
  local.value.y = graphene_simd4f_div (local.value.y, graphene_simd4f_splat (scale_y));
  shear_xy /= scale_y;

  /* compute XZ and YZ shears, make the third row orthogonal */
  shear_xz = graphene_simd4f_get_x (graphene_simd4f_dot4 (local.value.x, local.value.z));
  local.value.z = graphene_simd4f_sub (local.value.z, graphene_simd4f_mul (local.value.x, graphene_simd4f_splat (shear_xz)));
  shear_yz = graphene_simd4f_get_x (graphene_simd4f_dot4 (local.value.y, local.value.z));
  local.value.z = graphene_simd4f_sub (local.value.z, graphene_simd4f_mul (local.value.y, graphene_simd4f_splat (shear_yz)));

  /* next, get the Z scale and normalize the third row */
  scale_z = graphene_simd4f_get_x (graphene_simd4f_length4 (local.value.z));
  local.value.z = graphene_simd4f_div (local.value.z, graphene_simd4f_splat (scale_z));

  shear_xz /= scale_z;
  shear_yz /= scale_z;

  shear_r[XY_SHEAR] = shear_xy;
  shear_r[XZ_SHEAR] = shear_xz;
  shear_r[YZ_SHEAR] = shear_yz;

  /* at this point, the matrix is orthonormal. we check for a
   * coordinate system flip. if the determinant is -1, then
   * negate the matrix and the scaling factors
   */
  dot = graphene_simd4f_cross3 (local.value.y, local.value.z);
  cross = graphene_simd4f_dot4 (local.value.x, dot);
  if (graphene_simd4f_get_x (cross) < 0.f)
    {
      scale_x *= -1.f;
      scale_y *= -1.f;
      scale_z *= -1.f;

      graphene_simd4f_mul (local.value.x, graphene_simd4f_splat (-1.f));
      graphene_simd4f_mul (local.value.y, graphene_simd4f_splat (-1.f));
      graphene_simd4f_mul (local.value.z, graphene_simd4f_splat (-1.f));
    }

  graphene_point3d_init (scale_r, scale_x, scale_y, scale_z);

  /* get the rotations out */
  graphene_quaternion_init_from_matrix (rotate_r, &local);

  return TRUE;
}
Пример #17
0
/**
 * graphene_vec3_get_x:
 * @v: a #graphene_vec3_t
 *
 * Retrieves the first component of the given vector @v.
 *
 * Returns: the value of the first component of the vector
 *
 * Since: 1.0
 */
float
graphene_vec3_get_x (const graphene_vec3_t *v)
{
  return graphene_simd4f_get_x (v->value);
}
Пример #18
0
/**
 * graphene_vec3_length:
 * @v: a #graphene_vec3_t
 *
 * Retrieves the length of the given vector @v.
 *
 * Returns: the value of the length of the vector
 *
 * Since: 1.0
 */
float
graphene_vec3_length (const graphene_vec3_t *v)
{
  return graphene_simd4f_get_x (graphene_simd4f_length3 (v->value));
}
Пример #19
0
/**
 * graphene_vec3_dot:
 * @a: a #graphene_vec3_t
 * @b: a #graphene_vec3_t
 *
 * Computes the dot product of the two given vectors.
 *
 * Returns: the value of the dot product
 *
 * Since: 1.0
 */
float
graphene_vec3_dot (const graphene_vec3_t *a,
                   const graphene_vec3_t *b)
{
  return graphene_simd4f_get_x (graphene_simd4f_dot3 (a->value, b->value));
}
Пример #20
0
/**
 * graphene_simd4f_get_x:
 * @s: a #graphene_simd4f_t
 *
 * Retrieves the first component of @s.
 *
 * Returns: the first component of a #graphene_simd4f_t
 *
 * Since: 1.0
 */
float
(graphene_simd4f_get_x) (const graphene_simd4f_t s)
{
  return graphene_simd4f_get_x (s);
}
Пример #21
0
/**
 * graphene_matrix_get_x_scale:
 * @m: a #graphene_matrix_t
 *
 * Retrieves the scaling factor on the X axis in @m.
 *
 * Returns: the value of the scaling factor
 *
 * Since: 1.0
 */
float
graphene_matrix_get_x_scale (const graphene_matrix_t *m)
{
  return graphene_simd4f_get_x (m->value.x);
}