## LSL Wiki : Quaternions

HomePage :: PageIndex :: RecentChanges :: RecentlyCommented :: UserSettings :: You are crawling22.us.archive.org

## Quaternions

(continued from rotation)

To set the elements of the rotation type directly, compute the quaternion as follows. To represent a rotation of a given angle around a given axis, first, convert the axis to a unit vector (a vector of magnitude 1). 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 function llAxisAngle2Rot. 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 0 around any axis is represented the same way. Consider that the sine of 0 is 0, while the cosine of 0 is 1. As a result, no matter what axis is chosen, the null rotation is equal to <0,0,0,1>.

To find the inverse of a rotation, negate the last element of the quaternion:

inverse_quat = quat;
inverse_quat.s = -quat.s;

To find the inverse, negate the first 3 elements:

inverse_quat = < -quat.x, -quat.y, -quat.z, quat.s >;

If you negate all 4 elements of a quaternion, you end up with the same effective rotation.

"Quaternions are the things that scare all manner of mice and men. They are the things that go bump in the night. They are the reason your math teacher gave you an F. They are all that you have come to fear, and more. Quaternions are your worst nightmare." -- Confuted

This is so inappropriate. I understand why folks think this is funny, but come on. Why scare foks off? Quanternions aren't out of reach for most of us. Just takes a little patience. Note "Confuted" goes on to say "Okay, not really. They aren't actually that hard. I just wanted to scare you. "

Mathworld
Delphi3D
GameDev.net
Programming Rotations with Quaternions
Michel Isner's guide to Quaternions - arguably the best and clearest tutorial on rotation representations.

Rotation | Types
For those of us who are too lazy ATM to think about quaternions for real, can we get some shortcuts verified?

How to express the net result of two quat rotations combined? Is it addition, multiplication, or what? With normal rotations, I can sum the triples. For instance, <PI, 0, 0> + <0, PI, 0> = <PI, PI, 0>

How can I "combine" quaternions?
-- GenePoole (2005-03-16 13:05:08)
```rotation myRot = llGetRot();
vector degRot = <180, 0 ,0>; // Rotate 180 degrees on x-axis.
rotation targQuat = llEuler2Rot(degRot);
llSetRot(myRot * targQuat); // Rotate 180 degrees on global x-axis
llSetRot(targQuat * myRot); // Rotate 180 degrees on local x-axis.
llSetRot(targQuat); // Set the rotation to 180 degrees on the global x-axis.```

You multiply them together.
For example, if you wanted to rotate 180 degrees on the global x axis, then 180 degrees on the global z-axis, you'd say:
rotation xRoted = llGetRot() * llEuler2Rot(<180, 0, 0> * DEG_TO_RAD);
rotation zRoted = xRoted * llEuler2Rot(<0, 0, 180> * DEG_TO_RAD);
llSetRot(zRoted);

Im not exactly sure how several multiplications in series work on rotations...
-- ChristopherOmega (2005-03-16 14:17:51)
I recall that
a * (b * c) == (a * b) * c
a * b != b * a
but only when
(a.x * a.x + a.y * a.y + a.z * a.z + a.s * a.s) == (b.x * b.x + b.y * b.y + b.z * b.z + b.s * b.s) == (c.x * c.x + c.y * c.y + c.z * c.z + c.s * c.s)

remember that SL is using 32-bit floats, each operation will result in inacuraccies being introduced.
see LibraryRotationFunctions
-- BlindWanderer (2005-04-02 00:52:01)