Rotation
A rotation is a variable
type comprising 4
floats used together as a single item. This data is interpreted as a
quaternion. As with vectors, each component can be accessed via '.x', '.y', '.z', and '.s' (
not '.w').
Syntax:
float x = 0.0;
float y = 0.0;
float z = 0.0;
float s = 1.0;
rotation rot_a = <0.0, 0.0, 0.0, 1.0>;//copies these values into the respecive values of the rotation.
rotation rot_b = <x,y,z,s>;//copies the values of the variable into the rot.
rotation rot_c = rot_b;//copies the value of rot_b into rot_c
LSL does do some implicit typecasting but the LSL compiler does not actualy convert types or simplify code; it just makes implicit typecasts explicit. So while
<0, 0, 0, 1> is valid, it will use more bytecode and be slower than
<0.0, 0.0, 0.0, 1.0>. For this reason please be sure to use a decimal point.
"0." is enough, you don't need an extra zero. However, this does lack clarity.
There are a number of ways to visualize an arbitrary rotation in three dimensions. The simplest is to think of a rotation as being equivalent to a set of 3 rotations around the x, y, and z
axes (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). Also see
Banking.
Unfortunately, the Euler representation has drawbacks when it comes to combining rotations (see below). To avoid these problems, LSL represents rotations using
mathematical entities known as
quaternions, which consists of 4 elements: 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 page on
quaternions.
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: 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 2*
PI 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.
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 Rotations
An object is rotated by multiplying its current orientation with the desired rotation. The order in which the
operands are specified depends if a rotation is performed around the global axes or the local axes.
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 * llGetLocalRot(); // compute local rotation
llSetLocalRot(new_rot); // orient the object accordingly
This rotates the object around its local x-axis, which depends on its current orientation. Think of this as specifying the rotation from the object's point of view, that is, relative to the direction it is currently facing.
This also works Inversely by Dividing two rotations:
rotation new_rot = x_45 / llGetRot(); // compute local rotation
llSetRot(new_rot); // orient the object accordingly
Like previously, this would rotate your object along the x-axis based on its current orientation, but in the opposite direction.
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
Note: An object can be rotated around an arbitrary point by multiplying a vector by a rotation in the manner described above. The vector should be the difference between the object's current position and the desired "center-point" of rotation. Take the result of the multiplication and add it to the point of rotation. This vector will be the "new location" the object should be moved to.
vector currentPos = llGetPos();
vector rotPoint = llGetPos() + <1, 1, 1>; // in global coordinates
vector newPos = rotPoint + ((currentPos - rotPoint) * x_45);
llSetPos(newPos);
Bear in mind that any translation (position) operation can result in a vector that would put the object outside of the world, or require a move further than 10
meters--so plan for these possibilities.
Math Functions
World Functions
Events
Event Name | Purpose |
at_rot_target | when object comes within target angle |
not_at_rot_target | when rotation target is set but object is not there |
changed | when texture is changed, but not when object rotates |
control | when avatar rotates left or right |
Q: Is there a non lossy way to convert a rotation to a string and then back to a rotation again so that the resulting rotation has the same value as the original rotation?
A: See: Serialization
Q: I see 1/rot sometimes. What does that mean, exactly?
A: Do you mean <0,0,0,1>/rot ? That inverts the quaternion. Or do you mean <0,0,1>/rot ? Which multiples the vector by the inverse quaternion.
Q: How do I use llTargetOmega to rotate an object about it's local Z-axis?
A: Use llRot2Up(llGetRot()) as the axis. It's automatically normalized to 1.
It seems that, for some strange reason, things that rotate don't necessarily update their rotation immediately. You have to grab them in edit mode to actually see the new rotation occur if the new rotation is under a certain threshhold. Physically, the object is still rotated, it just doesn't update on the screen. Is there any way to force the new rotation to update and be visible? -- Myra Loveless
There's similar behaviour with position changes; below a certain treshhold, no changes are shown. The way to fix that one is to first move the object some distance in the opposite direction by atleast the treshhold distance, then to it's intended direction. This trick probably works for rotation too. It's not pretty, but it works if you're just using it to set things up.
This has been reported as a viewer bug, SVC-220 I believe. The script needs to force a viewer update. The best workaround I've found is to set the text, but the update is only forced if the text changes. I use llSetText("x", <1,1,1>, 1.0); immediately followed by llSetText("", <1,1,1>, 1.0); I've seen documentation that suggests llSetColor() will force one as well. -- RJ Thibaud
Functions |
Types |
Constants |
Transform |
Child Rotation |
Quaternion |
Vector |
Euler |
LibraryRotationFunctions |
Dynamics |
Interpolate |
Joint |
Memory Usages