/// Copy-construct from another quaternion. public Quaternion(Quaternion quat) { w_ = quat.w_; x_ = quat.x_; y_ = quat.y_; z_ = quat.z_; }
/// Spherical interpolation with another quaternion. public Quaternion Slerp(Quaternion rhs, float t) { float cosAngle = DotProduct(rhs); // Enable shortest path rotation if (cosAngle < 0.0f) { cosAngle = -cosAngle; rhs = -rhs; } float angle = (float)Math.Acos(cosAngle); float sinAngle = (float)Math.Sin(angle); float t1, t2; if (sinAngle > 0.001f) { float invSinAngle = 1.0f / sinAngle; t1 = (float)Math.Sin((1.0f - t) * angle) * invSinAngle; t2 = (float)Math.Sin(t * angle) * invSinAngle; } else { t1 = 1.0f - t; t2 = t; } return this * t1 + rhs * t2; }
/// Assign from another quaternion. public Quaternion Set(Quaternion rhs) { w_ = rhs.w_; x_ = rhs.x_; y_ = rhs.y_; z_ = rhs.z_; return this; }
/// Normalized linear interpolation with another quaternion. public Quaternion Nlerp(Quaternion rhs, float t, bool shortestPath = false) { Quaternion result; float fCos = DotProduct(rhs); if (fCos < 0.0f && shortestPath) result = (this) + (((-rhs) - (this)) * t); else result = (this) + ((rhs - (this)) * t); result.Normalize(); return result; }
/// Test for equality with another quaternion with epsilon. public bool Equals(Quaternion rhs) { return MathUtils.FloatEquals(w_, rhs.w_) && MathUtils.FloatEquals(x_, rhs.x_) && MathUtils.FloatEquals(y_, rhs.y_) && MathUtils.FloatEquals(z_, rhs.z_); }
/// Define from a direction to look in and an up direction. Return true if successful, or false if would result in a NaN, in which case the current value remains. public bool FromLookRotation(Vector3 direction, Vector3 upDirection) { Vector3 forward = direction.Normalized(); Vector3 v = forward.Cross(upDirection).Normalized(); Vector3 up = v.Cross(forward); Vector3 right = up.Cross(forward); Quaternion ret = new Quaternion(); ret.FromAxes(right, up, forward); if (!ret.IsNaN()) { this.Set(ret); return true; } else return false; }
/// Calculate dot product. public float DotProduct(Quaternion rhs) { return w_ * rhs.w_ + x_ * rhs.x_ + y_ * rhs.y_ + z_ * rhs.z_; }
/// Add-assign a quaternion. public static Quaternion operator +(Quaternion lhs, Quaternion rhs) { Quaternion ret = new Quaternion(lhs); ret.w_ += rhs.w_; ret.x_ += rhs.x_; ret.y_ += rhs.y_; ret.z_ += rhs.z_; return ret; }
/// Multiply-assign a scalar. public static Quaternion operator *(Quaternion lhs, float rhs) { Quaternion ret = new Quaternion(lhs); ret.w_ *= rhs; ret.x_ *= rhs; ret.y_ *= rhs; ret.z_ *= rhs; return lhs; }
/// Return decomposition to translation, rotation and scale. public void Decompose(out Vector3 translation, out Quaternion rotation, out Vector3 scale) { translation = new Vector3(); translation.x = m03_; translation.y = m13_; translation.z = m23_; scale = new Vector3(); scale.x = (float)Math.Sqrt(m00_ * m00_ + m10_ * m10_ + m20_ * m20_); scale.y = (float)Math.Sqrt(m01_ * m01_ + m11_ * m11_ + m21_ * m21_); scale.z = (float)Math.Sqrt(m02_ * m02_ + m12_ * m12_ + m22_ * m22_); Vector3 invScale = new Vector3(1.0f / scale.x, 1.0f / scale.y, 1.0f / scale.z); rotation = new Quaternion(ToMatrix3().Scaled(invScale)); }
/// Construct from translation, rotation and nonuniform scale. public Matrix3x4(Vector3 translation, Quaternion rotation, Vector3 scale) { }