/**
 * graphene_quaternion_to_angle_vec3:
 * @q: a #graphene_quaternion_t
 * @angle: (out): return location for the angle, in degrees
 * @axis: (out caller-allocates): return location for the rotation axis
 *
 * Converts a quaternion into an @angle, @axis pair.
 *
 * Since: 1.0
 */
void
graphene_quaternion_to_angle_vec3 (const graphene_quaternion_t *q,
                                   float                       *angle,
                                   graphene_vec3_t             *axis)
{
  graphene_quaternion_t q_n;
  float cos_a;

  graphene_quaternion_normalize (q, &q_n);

  cos_a = q_n.w;

  if (angle != NULL)
    *angle = GRAPHENE_RAD_TO_DEG (acosf (cos_a) * 2.f);

  if (axis != NULL)
    {
      float sin_a = sqrtf (1.f - cos_a * cos_a);

      if (fabsf (sin_a) < 0.00005)
       sin_a = 1.f;

      graphene_vec3_init (axis, q_n.x / sin_a, q_n.y / sin_a, q_n.z / sin_a);
    }
}
/**
 * graphene_quaternion_to_angles:
 * @q: a #graphene_quaternion_t
 * @deg_x: (out) (optional): return location for the rotation angle on
 *   the X axis (yaw), in degress
 * @deg_y: (out) (optional): return location for the rotation angle on
 *   the Y axis (pitch), in degrees
 * @deg_z: (out) (optional): return location for the rotation angle on
 *   the Z axis (roll), in degrees
 *
 * Converts a #graphene_quaternion_t to its corresponding rotations
 * on the [Euler angles](http://en.wikipedia.org/wiki/Euler_angles)
 * on each axis.
 *
 * Since: 1.2
 */
void
graphene_quaternion_to_angles (const graphene_quaternion_t *q,
                               float                       *deg_x,
                               float                       *deg_y,
                               float                       *deg_z)
{
  graphene_vec4_t v;
  graphene_vec4_t sq;
  float qx, qy, qz, qw, sqx, sqy, sqz, sqw;

  graphene_quaternion_to_vec4 (q, &v);
  graphene_vec4_multiply (&v, &v, &sq);

  qx = graphene_vec4_get_x (&v);
  qy = graphene_vec4_get_y (&v);
  qz = graphene_vec4_get_z (&v);
  qw = graphene_vec4_get_w (&v);

  sqx = graphene_vec4_get_x (&sq);
  sqy = graphene_vec4_get_y (&sq);
  sqz = graphene_vec4_get_z (&sq);
  sqw = graphene_vec4_get_w (&sq);

  if (deg_x != NULL)
    {
      float res = atan2f (2 * (qx * qw - qy * qz), (sqw - sqx - sqy + sqz));

      *deg_x = GRAPHENE_RAD_TO_DEG (res);
    }

  if (deg_y != NULL)
    {
      float res = asinf (CLAMP (2 * ( qx * qz + qy * qw), -1, 1));

      *deg_y = GRAPHENE_RAD_TO_DEG (res);
    }

  if (deg_z != NULL)
    {
      float res = atan2f (2 * (qz * qw - qx * qy), (sqw + sqx - sqy - sqz));

      *deg_z = GRAPHENE_RAD_TO_DEG (res);
    }
}
Beispiel #3
0
/**
 * graphene_euler_get_z:
 * @e: a #graphene_euler_t
 *
 * Retrieves the rotation angle on the Z axis, in degrees.
 *
 * Returns: the rotation angle
 *
 * Since: 1.2
 */
float
graphene_euler_get_z (const graphene_euler_t *e)
{
  return GRAPHENE_RAD_TO_DEG (graphene_vec3_get_z (&e->angles));
}