slerp method

Quaternion slerp(
  1. Quaternion qb,
  2. num t
)

Implementation

Quaternion slerp(Quaternion qb, num t) {
  if (t == 0) return this;
  if (t == 1) return copy(qb);

  var x = _x, y = _y, z = _z, w = _w;

  // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/

  var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;

  if (cosHalfTheta < 0) {
    _w = -qb._w;
    _x = -qb._x;
    _y = -qb._y;
    _z = -qb._z;

    cosHalfTheta = -cosHalfTheta;
  } else {
    copy(qb);
  }

  if (cosHalfTheta >= 1.0) {
    _w = w;
    _x = x;
    _y = y;
    _z = z;

    return this;
  }

  var sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;

  if (sqrSinHalfTheta <= Math.EPSILON) {
    var s = 1 - t;
    _w = s * w + t * _w;
    _x = s * x + t * _x;
    _y = s * y + t * _y;
    _z = s * z + t * _z;

    normalize();
    onChangeCallback();

    return this;
  }

  var sinHalfTheta = Math.sqrt(sqrSinHalfTheta);
  var halfTheta = Math.atan2(sinHalfTheta, cosHalfTheta);
  var ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta,
      ratioB = Math.sin(t * halfTheta) / sinHalfTheta;

  _w = (w * ratioA + _w * ratioB);
  _x = (x * ratioA + _x * ratioB);
  _y = (y * ratioA + _y * ratioB);
  _z = (z * ratioA + _z * ratioB);

  onChangeCallback();

  return this;
}