The three virtues of a programmer: Laziness, Impatience, and Hubris. – Larry Wall

Quaternion

From Unreal Wiki, The Unreal Engine Documentation Site
Revision as of 14:54, 14 May 2016 by SeriousBarbie (Talk | contribs) ("imarinary" -> "imaginary")

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Quaternions are a mathematical construct that could be seen as an extension of the complex numbers with three different imaginary units or as a combination of a scalar value and a three-dimensional vector. A special subset of the quaternions, the unit quaternions, can be used to represent rotations in 3D space.

Definition

Generally a quaternion is a four-dimensional value that is written as either x = x0+ x1i + x2j + x3k or as x = (x0, x1, x2, x3), where x0 is called the real or scalar part Re(x) and (x1, x2, x3) is the imaginary or vector part Im(x). If the vector part is zero, the quaternion is called real, while a quaternion with a zero scalar part is called a pure imaginary quaternion. Real quaternions (x0, 0, 0, 0) could also be written as x0+ 0i + 0j + 0k = x0.

Additive operations

Addition, subtraction and negation of quaternions is defined the same way as for vectors:

  • x + y = y + x = (x0+ y0, x1+ y1, x2+ y2, x3+ y3)
  • x - y = -y + x = (x0- y0, x1- y1, x2- y2, x3- y3)
  • -x = (-x0, -x1, -x2, -x3)

Scalar multiplication

The same goes for multiplication with and division by a scalar value a and "scalar multiplication" of two quaternions x and y:

  • a · x = x · a = (a · x0, a · x1, a · x2, a · x3)
  • x / a = x · 1/a = 1/a · x = x · a-1 = (x0 / a, x1 / a, x2 / a, x3 / a)
  • x · y = y · x = x0· y0 + x1· y1 + x2· y2 + x3· y3

Conjugate quaternion

Quaterions are "hypercomplex" numbers. Like "normal" complex numbers with one imaginary component, quaternions define the conjugate quaternion x or x*:

  • x = (x0, -x1, -x2, -x3)

Hamilton product

A quite unique operation of quaternions is the Hamilton product, i.e. the multiplication of two quaternions that yields a quaternion again. This one is special, because unlike addition or scalar product, it is not commutative.

  • x y = (x0· y0 - x1· y1 - x2· y2 - x3· y3, x0· y1 + x1· y0 + x2· y3 - x3· y2, x0· y2 - x1· y3 + x2· y0 + x3· y1, x0· y3 + x1· y2 - x2· y1 + x3· y0)

Now that looks vile. But if you express the quaternions as a combination of a scalar and a vector part, i.e. x = (x0, xV), you can express quaternion multiplication using the 3D vector scalar product "·", cross product "⨯" and vector multiplication by a scalar value:

  • x y = (x0, xV)(y0, yV) = (x0y0- xV· yV, x0yV + xVy0+ xV⨯ yV)

This representation also easily shows that x y ≠ y x, because xV⨯ yV = -(yV⨯ xV).

Now if you recall that a "real quaternion" (vector part zero) is essentially the same as a real number, you can easily see that the quaterion scalar product is basically a special, commutative case of the Hamilton product. In fact, even the multiplication of real numbers could be seen a special case of the Hamilton product, which both quaternions having zero vector parts.

Another important special case is the Hamilton product of two unit quaterions: The result of such a multiplication is a unit quaternion again.

Norm

A quaternion's norm ||x||2 (its "length") is defined similarly to a vector's length:

  • ||x||2 = x x = x x = x · x = x02+ x12+ x22+ x32

The value ||x|| is called the length or absolute value of the quaternion. Its square is equal to the scalar product of the quaternion with itself or the Hamilton product with its conjugate quaternion. A quaternion with the norm 1 is called a unit quaternion. Multiplying a quaternion by its conjugate results in the vector part becoming zero, which is why the resulting quaternion in the above equation can be considered a scalar number. (Remember that quaternions are hypercomplex numbers, not euclidean vectors. Real numbers are valid quaternion values with the vector part being zero.)

Inverse

A quaternion's multiplicative inverse, the reciprocal, x-1 is defined as the value that satisfies the equation x x-1 = 1:

  • x-1 = x / (x x) = x / ||x||2

Note that the fractional notation is avoided if the denominator is not a real number because the notation itself is ambiguous since it does not specify if the denominator's reciprocal must be multiplied to the left or to the right of the numerator and quaternion multiplication is not commutative.

An important special case of the inverse are unit quaterions. Because their norm is already 1, the inverse of a unit quaterion is the same as the conjugate of that unit quaternion.

Quaternion rotation

The basis for expression rotations using quaternions are unit quaternions, i.e. quaternions with a length of 1, and pure imaginary quaternions, i.e. quaternions of the form (0, x1, x2, x3). Pure imaginary quaternions are used to represent vectors that will be rotated around the origin in some way, while unit quaternions define the rotation axis and angle. To apply a rotation defined by quaternion r to a vector defined by quaternion v, all you need to do is calculate the quaternion product r v r-1.

A property of quaternion multiplication is that the length of the resulting quaternion is the same as the product of the lengths of the two original quaternions. Consequently the product of two unit quaternions will be another unit quaternions. If those two unit quaternions represent 3D rotations, the resulting unit quaternion will represent the combination of these two rotations in the reverse order. The product r1 r2 represents a rotation achieved by first applying r2, then r1.

The vector to rotate can be converted to a quaternion simply by using the vector as the quaternion's vector part and zero as the scalar part. A rotation quaternion is calculated from a rotation axis and an angle. Given the rotation axis as unit vector u and the rotation angle α between 0 and 2π, the rotation quaternion r is calculated as r = (cos α/2, u sin α/2).

UnrealScript functions

The Object(U2, U2XMP, UE2Runtime, UT2003, UT2004, UDK, UT3) class provides several functions and (in UE3) operators for working with quaternions. It defines the struct Quat with the components W, X, Y and Z as data type for a quaternion value. Unreal Engine 3 also defines the binary operators + and -, and like with every struct you can compare Quat values for equality and inequality with the == and != operators.

The Quat struct type is subject to data reduction during replication. The engine assumes that you replicate only unit quaternions and only replicates the X, Y and Z components. The W component will be calculated on the remote side to get a unit quaternion again.

Quaternion rotation is used in rigid body physics calculations both in Unreal Engine 2 (PHYS_Karma) and Unreal Engine 3 (PHYS_RigidBody). The rigid body physics state of an actor is composed of a vector for the location, a quaternion for the rotation and two vectors for linear and angular velocity.

QuatProduct(Quat, Quat)

Calculates the Hamilton product of the two quaternions and returns the resulting quaternion value.

QuatDot(Quat, Quat)

Calculates the scalar product of the two quaternions and returns the resulting float value. This function is not available in Unreal Engine 2.

QuatInvert(Quat)

Returns the conjugate quaternion. Note that due to x-1 = x / ||x||2 the conjugate quaternion of a unit quaternion also is its reciprocal.

QuatRotateVector(Quat, Vector)

Rotates the specified vector by the given rotation quaternion and returns the resulting vector value. Note that the result will only be actually the rotated vector if the quaternion is a unit quaternion.

QuatFindBetween(Vector, Vector)

Calculates the quaternion that will rotate the first vector onto the second. It does so by calculating the rotation axis and angle between the vectors using the cross product and scalar product. Note that it short-circuits if the cross product is zero. In that case, whether the vectors point in the same or opposite directions, it always returns the identity quaternion (1,0,0,0), even though opposite direction vectors would require a rotation by 180° around an arbitrary rotation axis perpendicular to the vectors.

QuatFromAxisAndAngle(Vector, float)

Creates a rotation quaternion from the specifies axis vector and rotation angle in radians. The vector will be normalized for this calculation but must not be zero.

QuatFromRotator(Rotator)

Calculates a rotation quaternion that represents the same rotation as the specified Rotator value.

QuatToRotator(Quat)

Calculates a Rotator value that represents the same rotation as the specified rotation quaternion. This basically applies the quaternion rotation to the X, Y and Z axis vectors and uses the OrthoRotation function on the resulting vectors to calculate the Rotator value.

QuatSlerp(Quat, Quat, float)

Performs spherical linear interpolation on the two rotation quaternions, using the float value as blend alpha. A value of 0.0 maps to the first quaternion, a value of 1.0 to the second, while 0.5 is halfway between them.