/// <summary> /// Creates a <see cref="Quaternion"/> that rotates one <see cref="Vector3D"/> onto another. A rotation axis must be supplied if <see cref="Vector3D"> Vector3Ds </see> are antiparallel. /// </summary> /// <param name="v1">The first <see cref="Vector3D"/>.</param> /// <param name="v2">The second <see cref="Vector3D"/>.</param> /// <param name="axis">Axis that will be rotated around if <see cref="Vector3D">Vector3Ds</see> are antiparallel.</param> /// <returns>A rotation <see cref="Quaternion"/>.</returns> public static Quaternion QuaternionRotateBetweenVectors(Vector3D v1, Vector3D v2, Vector3D?axis = null) { if (v1.ApproxEquals(v2, 1E-6f)) { return(Quaternion.Identity); } axis ??= Vector3D.UnitY; Vector3D rotationAxis = v1.ApproxEquals(-v2, 1E-6F) ? (Vector3D)axis : v1.CrossProduct(v2).Normalise(); float angle = v1.Angle(v2); return(QuaternionRotate(rotationAxis, angle)); }
private static void VectorCheck(Vector3D firstVector, Vector3D secondVector) { if (firstVector.ApproxEquals(Vector3D.Zero, 1E-6f) || secondVector.ApproxEquals(Vector3D.Zero, 1E-6f)) { throw new ArgumentException("New direction vector(s) cannot be set to zero vector."); } }