Example #1
0
  /**
   * Simply returns {@code log(a. inverse() * b)}.
   *
   * <p>Useful for {@link #squadTangent(Quaternion, Quaternion, Quaternion)}.
   *
   * @param a the first Quaternion
   * @param b the second Quaternion
   */
  public static final Quaternion lnDif(Quaternion a, Quaternion b) {
    Quaternion dif = a.inverse();
    dif.multiply(b);

    dif.normalize();
    return dif.log();
  }
Example #2
0
  /**
   * Returns a tangent Quaternion for {@code center}, defined by {@code before} and {@code after}
   * quaternions.
   *
   * @param before the first Quaternion
   * @param center the second Quaternion
   * @param after the third Quaternion
   */
  public static final Quaternion squadTangent(
      Quaternion before, Quaternion center, Quaternion after) {
    Quaternion l1 = Quaternion.lnDif(center, before);
    Quaternion l2 = Quaternion.lnDif(center, after);
    Quaternion e = new Quaternion();

    e.x = -0.25f * (l1.x + l2.x);
    e.y = -0.25f * (l1.y + l2.y);
    e.z = -0.25f * (l1.z + l2.z);
    e.w = -0.25f * (l1.w + l2.w);

    return Quaternion.multiply(center, e.exp());
  }
Example #3
0
  /**
   * Returns the slerp interpolation of quaternions {@code a} and {@code b}, at time {@code t}.
   *
   * <p>{@code t} should range in {@code [0,1]}. Result is a when {@code t=0 } and {@code b} when
   * {@code t=1}.
   *
   * <p>When {@code allowFlip} is true (default) the slerp interpolation will always use the
   * "shortest path" between the quaternions' orientations, by "flipping" the source Quaternion if
   * needed (see {@link #negate()}).
   *
   * @param a the first Quaternion
   * @param b the second Quaternion
   * @param t the t interpolation parameter
   * @param allowFlip tells whether or not the interpolation allows axis flip
   */
  public static final Quaternion slerp(Quaternion a, Quaternion b, float t, boolean allowFlip) {
    // Warning: this method should not normalize the Quaternion
    float cosAngle = Quaternion.dotProduct(a, b);

    float c1, c2;
    // Linear interpolation for close orientations
    if ((1.0 - PApplet.abs(cosAngle)) < 0.01) {
      c1 = 1.0f - t;
      c2 = t;
    } else {
      // Spherical interpolation
      float angle = PApplet.acos(PApplet.abs(cosAngle));
      float sinAngle = PApplet.sin(angle);
      c1 = PApplet.sin(angle * (1.0f - t)) / sinAngle;
      c2 = PApplet.sin(angle * t) / sinAngle;
    }

    // Use the shortest path
    if (allowFlip && (cosAngle < 0.0)) c1 = -c1;

    return new Quaternion(
        c1 * a.x + c2 * b.x, c1 * a.y + c2 * b.y, c1 * a.z + c2 * b.z, c1 * a.w + c2 * b.w, false);
  }
Example #4
0
 /**
  * Returns the slerp interpolation of the two quaternions {@code a} and {@code b}, at time {@code
  * t}, using tangents {@code tgA} and {@code tgB}.
  *
  * <p>The resulting Quaternion is "between" {@code a} and {@code b} (result is {@code a} when
  * {@code t=0} and {@code b} for {@code t=1}).
  *
  * <p>Use {@link #squadTangent(Quaternion, Quaternion, Quaternion)} to define the Quaternion
  * tangents {@code tgA} and {@code tgB}.
  *
  * @param a the first Quaternion
  * @param tgA the first tangent Quaternion
  * @param tgB the second tangent Quaternion
  * @param b the second Quaternion
  * @param t the t interpolation parameter
  */
 public static final Quaternion squad(
     Quaternion a, Quaternion tgA, Quaternion tgB, Quaternion b, float t) {
   Quaternion ab = Quaternion.slerp(a, b, t);
   Quaternion tg = Quaternion.slerp(tgA, tgB, t, false);
   return Quaternion.slerp(ab, tg, 2.0f * t * (1.0f - t), false);
 }
Example #5
0
 /**
  * Returns the associated inverse rotation processing PMatrix3D. This is simply {@link #matrix()}
  * of the {@link #inverse()}.
  *
  * <p><b>Attention:</b> The result is only valid until the next call to {@link #inverseMatrix()}.
  * Use it immediately (as in {@code applyMatrix(q.inverseMatrix())}).
  */
 public final PMatrix3D inverseMatrix() {
   Quaternion tempQuat = new Quaternion(x, y, z, w);
   tempQuat.invert();
   return tempQuat.matrix();
 }
Example #6
0
 /**
  * Wrapper function that simply calls {@code slerp(a, b, t, true)}.
  *
  * <p>See {@link #slerp(Quaternion, Quaternion, float, boolean)} for details.
  */
 public static final Quaternion slerp(Quaternion a, Quaternion b, float t) {
   return Quaternion.slerp(a, b, t, true);
 }
Example #7
0
 /**
  * Returns the image of {@code v} by the Quaternion {@link #inverse()} rotation.
  *
  * <p>{@link #rotate(PVector)} performs an inverse transformation.
  *
  * @param v the PVector
  */
 public final PVector inverseRotate(PVector v) {
   Quaternion tempQuat = new Quaternion(x, y, z, w);
   tempQuat.invert();
   return tempQuat.rotate(v);
 }
Example #8
0
 /**
  * Returns the inverse Quaternion (inverse rotation).
  *
  * <p>The result has a negated {@link #axis()} direction and the same {@link #angle()}.
  *
  * <p>A composition of a Quaternion and its {@link #inverse()} results in an identity function.
  * Use {@link #invert()} to actually modify the Quaternion.
  *
  * @see #invert()
  */
 public final Quaternion inverse() {
   Quaternion tempQuat = new Quaternion(this);
   tempQuat.invert();
   return tempQuat;
 }
Example #9
0
 /**
  * Returns the product of Quaternion {@code q1} by the inverse of Quaternion {@code q2} (i.e.,
  * {@code q1 * q2^-1}). The value of both argument quaternions is preserved.
  *
  * @param q1 the first Quaternion
  * @param q2 the second Quaternion
  */
 public static final Quaternion multiplyInverse(Quaternion q1, Quaternion q2) {
   Quaternion tempQuat = new Quaternion(q2);
   tempQuat.invert();
   return Quaternion.multiply(q1, tempQuat);
 }
Example #10
0
 /**
  * Multiplies this Quaternion by the inverse of Quaternion {@code q1} and places the value into
  * this Quaternion (i.e., {@code this = this * q^-1}). The value of the argument Quaternion is
  * preserved.
  *
  * @param q1 the other Quaternion
  */
 public final void multiplyInverse(Quaternion q1) {
   Quaternion tempQuat = new Quaternion(q1);
   tempQuat.invert();
   this.multiply(tempQuat);
 }
Example #11
0
 /**
  * Returns the image of {@code v} by the rotation {@code q1}. Same as {@code q1.rotate(v).}
  *
  * @param q1 the Quaternion
  * @param v the PVector
  * @see #rotate(PVector)
  * @see #inverseRotate(PVector)
  */
 public static final PVector multiply(Quaternion q1, PVector v) {
   return q1.rotate(v);
 }