Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Rotation Datatype

Blobbus Beckett
Junior Member
Join date: 16 Jun 2004
Posts: 2
06-26-2004 16:54
I was wondering exactly how the fourth value of the Rotation datatype effected the rotation stuff. The "w" in <x,y,z,w>
Eggy Lippmann
Wiktator
Join date: 1 May 2003
Posts: 7,939
06-26-2004 17:31
A rotation is a quaternion. You need to look it up on google, cause Mr. Daniel Linden killed all the juicy posts about quaternions that were previously contained in the scripting forums. Make sure you let him know that you are displeased :)
Jake Cellardoor
CHM builder
Join date: 27 Mar 2003
Posts: 528
06-26-2004 17:32
Might as well repost this info, since the original forum posts haven't been restored yet.

Rotations

There 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:
CODE

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:
CODE

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 Rotations

You 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:
CODE

// 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:
CODE

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:
CODE

vector new_vec = old_vec * x_45; // compiles
vector new_v = x_45 * old_v; // doesn't compile


Details about Quaternions

If 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:
CODE

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>:
CODE

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:
CODE

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:
CODE

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


You can also find the inverse by negating the first three elements:
CODE

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.
Grim Lupis
Dark Wolf
Join date: 11 Jul 2003
Posts: 762
06-26-2004 19:21
<hijack>
Jake!! Hey, man. How's it going?

Where's the new help file? ;)
</hijack>
_____________________
Grim

"God only made a few perfect heads, the rest of them he put hair on." -- Unknown
Blobbus Beckett
Junior Member
Join date: 16 Jun 2004
Posts: 2
Thanks!
06-26-2004 20:12
Thanks for the explanation. n.n
Jake Cellardoor
CHM builder
Join date: 27 Mar 2003
Posts: 528
06-27-2004 00:56
From: someone
Originally posted by Grim Lupis
<hijack>
Jake!! Hey, man. How's it going?

Where's the new help file? ;)
</hijack>


Hey Grim! I'm glad you came back to SL.

As for the new help file, uh... I posted it just before the scripting forum was deleted. Yeah, that's it.

Actually, I had been thinking I could get the source files for the ever-updated wiki and convert them back into a help file, but that appears to be more difficult than I had hoped. In the meantime, I'll see what I can do about updating the previous help file.