Might as well repost this info, since the original forum posts haven't been restored yet.
RotationsThere are a number of ways to visualize an arbitrary rotation in three dimensions. The simplest to think of a rotation as being equivalent to a set of three rotations around the x, y, and z axes. This is known as the Euler representation. In LSL, this can be represented using the vector type, where the x element specifies the roll (angle of rotation around the x-axis), the y element specifies the pitch (angle of rotation around the y-axis), and the z element specifies the yaw (angle of rotation around the z-axis).
Unfortunately, the Euler representation has drawbacks when it comes to combining rotations. To avoid these problems, LSL represents rotations using mathematical entities known as quaternions. A quaternion consists of four elements, labeled x, y, z, and s. Note that the x, y, and z elements DO NOT correspond to roll, pitch, and yaw. For more information on what they represent, see the section "Details about Quaternions" below.
However, you can use rotations without dealing with the individual elements of quaternions. LSL offers library calls that convert between a quaternion and a vector containing the equivalent Euler representation: llEuler2Rot and llRot2Euler.
Note that LSL expects angles to be specified in terms of radians rather than degrees. A radian is the angle reached if you were to take a string the length of a circle’s radius and lay it along the circumference, approximately equal to 57.296 degrees. This ratio means that a full circle, which contains 360 degrees, is equal to 2pi radians. Similarly, a semicircle of 180 degrees equals pi radians. LSL defines the constants DEG_TO_RAD and RAD_TO_DEG to facilitate conversion to and from degrees. For example:
vector eul = <0, 0, 45>; // 45 degrees around the z-axis, in Euler form
eul *= DEG_TO_RAD; //convert to radians
rotation quat = llEuler2Rot( eul ); // convert to quaternion
llSetRot( quat ); // rotate the object
LSL also defines the constants PI_BY_TWO, PI, and TWO_PI to let you specify common rotations in radians directly:
vector x_ninety = <PI_BY_TWO, 0, 0>; // 90 degrees around the x-axis
vector y_one_eighty = <0, PI, 0>; // 180 degrees around the y-axis
LSL defines the constant ZERO_ROTATION to represent a rotation of angle zero. Calling llSetRot( ZERO_ROTATION ) orients the object so that its local axes are aligned with the global axes. The value returned by llGetRot is the object's current orientation relative to this null rotation.
Combining RotationsYou rotate an object by multiplying its current orientation with the desired rotation. The order in which you specify the operands depends on whether you want to perform a rotation around the global axes or a rotation around the local axes. For example:
// a rotation of 45 degrees around the x-axis
rotation x_45 = llEuler2Rot( <45 * DEG_TO_RAD, 0, 0> );
rotation new_rot = llGetRot() * x_45; // compute global rotation
llSetRot( new_rot ); // orient the object accordingly
This rotates the object around the global x-axis (the axis which runs from west to east).
Now consider the following:
rotation new_rot = x_45 * llGetRot(); // compute local rotation
llSetRot( new_rot ); // orient the object accordingly
This rotates the object around its local x-axis, which depends on its current orientation. You can think of this as specifying the rotation from the object's point of view, that is, relative to the direction it is currently facing.
When rotating a vector, the rotation must appear to the right of the vector:
vector new_vec = old_vec * x_45; // compiles
vector new_v = x_45 * old_v; // doesn't compile
Details about QuaternionsIf you wish to set the elements of the rotation type directly, you can compute the quaternion as follows. Suppose you want to represent a rotation of a given angle around a given axis. First convert the axis to a unit vector, that is, a vector of magnitude one. Take the x, y, and z components of the unit vector and multiply them by the sine of half the angle; these are the x, y, and z elements of the quaternion. The s element of the quaternion is equal to the cosine of half the angle.
The following function performs this in LSL:
rotation make_quaternion( vector axis, float angle )
{
vector unit_axis = llVecNorm( axis );
float sine_half_angle = llSin( angle/2 );
float cosine_half_angle = llCos( angle/2 );
rotation quat;
quat.x = sine_half_angle * unit_axis.x;
quat.y = sine_half_angle * unit_axis.y;
quat.z = sine_half_angle * unit_axis.z;
quat.s = cosine_half_angle;
return quat;
}
This example duplicates the llAxisAngle2Rot library call. Note that the angle must be specified in radians rather than degrees.
For a rotation around just the x-axis, the quaternion becomes simpler to compute, because in this case the unit axis is <1,0,0>:
rotation x_rot = <llSin( angle/2 ), 0, 0, llCos( angle/2 )>; // rotate around x-axis
Similarly, a rotation around just the y-axis or just the z-axis is also simpler to compute:
rotation y_rot = <0, llSin( angle/2 ), 0, llCos( angle/2 )>; // rotate around y-axis
rotation z_rot = <0, 0, llSin( angle/2 ), llCos( angle/2 )>; // rotate around z-axis
A rotation of angle zero around any axis is represented the same way. Consider that the sine of zero is zero, while the cosine of zero is one. As a result, no matter what axis you choose, the null rotation is equal to <0, 0, 0, 1>.
You can find the inverse of a rotation by negating the last element of the quaternion:
inverse_quat = quat;
inverse_quat.s = -quat.s;
You can also find the inverse by negating the first three elements:
inverse_quat = < -quat.x, -quat.y, -quat.z, quat.s >;
If you negate all four elements of a quaternion, you end up with the same effective rotation.