$nav **IMPORTANT:**\\ Please note that this is **NOT** an introductory text on rotations, but a reference on the usage of the rotation type in LSL. If you want to learn on rotations, you may want to check the $lart[Rotations] tutorial. ===== Rotation type ===== Unlike many other languages, LSL has native support for several operations that are common in 3D geometry. The $ty[rotation] or $ty[quaternion] type is fundamental to that support. At the lowest level, a rotation can be defined as a type that is able to hold four floats, but LSL supports many operations that are designed for geometry handling. $ty[quaternion] is an alias for $ty[rotation]; they can be used indistinctly. A $ty[rotation] literal is written as four comma-separated float expressions enclosed in angle brackets. As usual, integer expressions are automatically cast to float. Note, however, that it's unusual to write a rotation literal yourself; more commonly, rotation values come from the result of functions such as $lfn[llGetRot], $lfn[llEuler2Rot], $lfn[llList2Rot], etc. While functions that accept rotation values are somewhat permissive, writing a //valid// rotation (one which when applied to a vector, returns a vector of the same length) is not a trivial task and you're not recommended to do it unless you have a good understanding of the underlying rules. In particular, ''<0, 0, 0, 0>'' is **not** a valid rotation. It can work in some situations but will utterly fail in others. The null rotation (a rotation that doesn't alter the original object's orientation) is written as ''<0, 0, 0, 1>'' and has the associated constant $lct[ZERO_ROTATION]. As with vectors, the components of a quaternion can only be accessed individually when they are in a variable, and in that case, the syntax is the name of the variable followed by a dot and then the letter **x**, **y**, **z** or **s** (the components of a literal appear in that order). For example, ''rotation_var.s'' is the fourth (**s**) component of a quaternion. === Addition, subtraction, and negation of rotations === These are operations that are //very rarely// used, and only in cases where the maths require it, which in LSL is pretty close to never. However, they are implemented, so here's a description: * Negating a rotation is done by placing a minus sign in front of it, and has the effect of negating every component. For example, if **r** is a rotation, then the result of ''-r'' is the same as ''<-r.x, -r.y, -r.z, -r.s>''. It turns out that for quaternions (in the mathematical sense) that represent rotations (in the sense of an orientation in space), **r** and **-r** represent the //same rotation,// therefore this operation is of little use besides some hard maths. * Adding and subtracting two rotations, as with vectors, is done component by component: if **q** and **r** are rotations, then ''q+r'' gives the same result as '''', and similarly for subtraction. Note, however, that this is **not** how you accumulate rotations: you do that by multiplying them (see below). In most cases, the addition of rotations gives something that is not a valid rotation, so better don't use it unless you know the underlying maths. === Multiplication of rotations === There are two operations with rotations that use the $op[*] multiplication operator: $lty[vector]$op[*]$ty[rotation] and $ty[rotation]$op[*]$ty[rotation]. No other combination of rotation with any other type or in any other order is supported. In particular, the following are NOT supported: $ty[rotation]$op[*]$ty[vector], $ty[float]$op[*]$ty[rotation] and $ty[rotation]$op[*]$ty[float]. $ty[vector]$op[*]$ty[rotation] returns a //vector//, and is the result of applying the rotation to the vector. The rotation needs to be valid (in mathematical terms, //normalized//), otherwise the vector's length will also be altered. All LSL functions except $lfn[llAxes2Rot] and $lfn[llList2Rot] always return normalized rotations, ($fn[llAxes2Rot] does too if it receives proper arguments). $ty[rotation]$op[*]$ty[rotation] has the effect of accumulating the rotations. Say you have an object and rotate it by **q** and then by **r**; the final orientation will be the same as if you rotated it by the single rotation given by ''q*r''. For example, if **q** is a rotation that turns 40° counter-clockwise over the positive Z axis, and **r** is a rotation that turns 30° clockwise over the positive Z axis, then ''q*r'' will represent a rotation that turns 10° counter-clockwise over the positive Z axis. Note that due to how the concept of rotating an object works, ''q*r'' is not always the same as ''r*q''. This may seem unintuitive, but rotations work like that in the real world too. In the example given above it would be the same, as the rotations turn over the same axis, but in general it's not the case. === Division of rotations === Rotations can be divided by another rotation, and vectors can be divided by a rotation. In both cases, the effect is the same as multiplying by the rotation that would cancel the one in the denominator. For example, if **q** is a rotation that turns 40° counter-clockwise over the positive Z axis, and **r** is a rotation that turns 30° clockwise over the positive Z axis, then ''q/r'' is a rotation that turns 70° over the positive Z axis (because the rotation that cancels **r** is one that turns 30° counter-clockwise, and multiplying **q** by that one gives a total rotation angle of 70°). === Inverse of a rotation === The rotation that cancels a given rotation can be obtained by negating the **s** component. Unfortunately, LSL does not support an operator that does this, so it has to be done by hand. For example: '''' is the inverse rotation of **q**, or if you want to invert the variable you can do: ''q.s = -q.s;'' === Type casting a quaternion === As with vectors, type cast of a rotation is very limited: * ''(rotation)rotation_value'' does nothing special to the value, as expected. * ''(rotation)string_value'' is supported; see $lty[string#Type casting of strings] for details. * ''(string)rotation_value'' is supported too; see $lty[float#Type casting a float to string] for details. * ''(list)rotation_value'' results in a list with one single element of type $ty[rotation]. === For people with a maths background === If //v = vx//**i**//+vy//**j**//+vz//**k** is a vector and //r = rw+rx//**i**//+ry//**j**//+rz//**k** is a quaternion, then ''v*r'' does the operation //r·v·r*// (where //r*// is the conjugate of //r//), so if the quaternion is normalized, it performs a conjugation of //v// by //r,// which has the effect of rotating the vector (see [[http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation]]). As expected, if the quaternion isn't normalized, it will scale the vector as well. ''q*r'' (for two quaternions //q// and //r//) performs the multiplication in inverse order with respect to the maths convention, i.e. it performs //r·q//.