- Joined
- Sep 20, 2018
- Messages
- 414
- Location
- Airport
- Joined SLU
- Yes
- SLU Posts
- -1000
I hear many people complain about rotations in LSL. This is an area that I think LL made some very good decisions, and they provide some very useful library routines to aid in using rotations in practice. One thing I do not hear is people asking very basic questions about what they are. For people who want to start using rotations I think the following ideas are extremely important.
This tutorial is my attempt at providing a very basic introduction into what rotations are and how to use them. It provides an overview of the basic concept and an overview of how to think about them both geometrically and algebraically.
Rotations in LSL are implemented using quaternions. Quaternions have an advantage in that they are computationally efficient. Most importantly there are no problems with gimbal lock which can occur with Euler rotations. Quaternions have another advantage in that they are simpler to think about geometrically.
There are two ways to think about rotations, geometrically and algebraically. When working with rotations it is important to use both approaches. The geometric viewpoint provides the intuition to help start the solution to a particular problem, and the algebraic viewpoint helps determine the specific formula to use in a script.
We first focus on the geometric viewpoint. One way to think about a rotation graphically is that a rotation has two parts, an axis of rotation and an angle to rotate around the axis. A visual depiction is shown in Figure 1.
Figure 1
The purple arrow in Figure 1 represents a direction and is a 3D vector. The direction is the "axis of rotation." The rotation is a "turn" or "twist" around the axis in the direction of the green arrow. The angle is how far to turn around the axis.
In this case the direction indicated by the green arrow is a positive angle. If you turn in the other direction it is a negative angle. The convention is based on the right hand rule. (More information can be found at Right-hand rule - Wikipedia, the free encyclopedia ) The basic idea is illustrated in Figure 2. The idea is that you lay your hand along the green arrow with your palm facing the purple vector. If your thumb is pointing in the same direction as the purple arrow then it is a positive angle by convention.
Figure 2
(image found at Right-hand rule - Wikipedia, the free encyclopedia )
Note: the angle is given in radians. There are 2*pi radians in a full circle (360 degrees).
Note: a list of LSL commands that relate to rotations can be found at Category:LSL Rotation - Second Life Wiki
To specify a rotation you can use the llAxisAngle2Rot command which takes an axis and an angle to define a rotation. For example to specify a rotation about the x-axis of 45 degrees you would use the following command:
rotation myRot = llAxisAngle2Rot(<1.0,0.0,0.0>,PI/4.0);
Rotations in LSL are manipulated by "multiplying" them. The "*" operation is overloaded so that when you multiply two rotations, A*B, you perform the first rotation (A) then perform the second rotation (B). The first problem that comes up is that the order matters. Rotating by A and then B is not necessarily the same as rotating by B and then A.
An example of this is given in Video 1. In the video, rotation A is defined to be a rotation of 90 degrees around the x-axis:
rotation A = llAxisAngle2Rot(<1.0,0.0,0.0>,PI/2.0);
Rotation B is defined to be a rotation of 90 degrees around the y-axis:
rotation B = llAxisAngle2Rot(<0.0,1.0,0.0>,PI/2.0);
In the video the object is originally in a "zero rotation." That is the object's x-axis is lined up with the world's x-axis as well as the y and z-axes. (In LSL the predefined constant "ZERO_ROTATION" is the zero rotation.) The object is then rotated according to A. (It is done slowly to demonstrate the action of the rotation.)
Next the object is put back into a zero rotation and then rotated according to B. (Again it is done slowly as a demonstration.) The object is then put into a zero rotation and rotated by A*B. In the demo it is done slowly so the A rotation is slowly applied and then the B rotation is slowly applied. Finally the object is put back into a zero rotation and the B*A rotation is demonstrated.
Video 1:
The order of operations is extremely important when trying to find the formula to implement in LSL. An equation that represents the rotations is generally constructed, and the rotation of interest is solved. Before an example is given it is important to note that the inverse of a rotation must be calculated.
The inverse can be thought of as rotating around the axis of rotation in the opposite direction or the negative of the angle. Another way to think about it is to flip the axis of rotation in the negative direction and then rotate around the given angle. Mathematically the two are equivalent, but the latter is more generally used to describe the inverse rotation.
In LSL there is not a library function to calculate the inverse. Rather you have to divide by the zero rotation. So if you want to calculate the inverse of a rotation A the inverse is given by (ZERO_ROTATION/A). The inverse has the special property that when you multiply by the inverse you get the zero rotation. Another way to say this is the following:
A*(ZERO_ROTATION/A) = ZERO_ROTATION,
or another way is the following:
(ZERO_ROTATION/A)*A = ZERO_ROTATION.
A common task is to to solve for a specific rotation. For example, if you have a formula A*B=C then if you want to solve for B you multiply on the left by (ZERO_ROTATION/A). The result is the following:
A*B = C,
(ZERO_ROTATION/A)*A*B = (ZERO_ROTATION/A)*C,
B = (ZERO_ROTATION/A)*C.
If you want to solve for A you multiple on the right by (ZERO_ROTATION/B) the result is the following:
A*B = C,
A*B*(ZERO_ROTATION/B) = C*(ZERO_ROTATION/B),
A = C*(ZERO_ROTATION/B),
A = C/B.
Again, the order that you do the multiplications matter so you have to be very careful about how you do the operations and how you type them into a script. Off hand this does not seem all that useful, but these ideas occur in a wide variety of situations when using rotations.
As an example, suppose that you have an object with rotation A, and you want to slowly rotate it to another rotation, C. The idea is that you want to find a rotation B so that
A*B = C.
Solving this equation for B you get
B = (ZERO_ROTATION/A)*C.
Now we will use linear interpolation ("lerping") to rotate change the angle of the rotation from zero to the final value. Before this can be done we need to find the axis of the rotation and the angle:
vector axis = llRot2Axis(B);
float angle = llRot2Angle(B);
If you want to take N steps the j'th angle is given by
((float)j)/((float)N)*angle
and the associated rotation is
A*llAxisAngle2Rot(axis,((float)j)/((float)N)*angle).
Putting it all together gives the following code snippet which defines a function to slowly rotate from a start rotation given by startRot to an end rotation given by endRot:
Rotations tutorial by Grandma Bates is licensed under a (http://creativecommons.org/licenses/by/3.0/) Creative Commons Attribution 3.0 Unported License.
Based on a work at Basic Introduction to Rotations - SLUniverse Forums
You are free to copy and share this. I would be grateful if you would include a link back to this page if you do.
This tutorial is my attempt at providing a very basic introduction into what rotations are and how to use them. It provides an overview of the basic concept and an overview of how to think about them both geometrically and algebraically.
Rotations in LSL are implemented using quaternions. Quaternions have an advantage in that they are computationally efficient. Most importantly there are no problems with gimbal lock which can occur with Euler rotations. Quaternions have another advantage in that they are simpler to think about geometrically.
There are two ways to think about rotations, geometrically and algebraically. When working with rotations it is important to use both approaches. The geometric viewpoint provides the intuition to help start the solution to a particular problem, and the algebraic viewpoint helps determine the specific formula to use in a script.
We first focus on the geometric viewpoint. One way to think about a rotation graphically is that a rotation has two parts, an axis of rotation and an angle to rotate around the axis. A visual depiction is shown in Figure 1.
Figure 1
The purple arrow in Figure 1 represents a direction and is a 3D vector. The direction is the "axis of rotation." The rotation is a "turn" or "twist" around the axis in the direction of the green arrow. The angle is how far to turn around the axis.
In this case the direction indicated by the green arrow is a positive angle. If you turn in the other direction it is a negative angle. The convention is based on the right hand rule. (More information can be found at Right-hand rule - Wikipedia, the free encyclopedia ) The basic idea is illustrated in Figure 2. The idea is that you lay your hand along the green arrow with your palm facing the purple vector. If your thumb is pointing in the same direction as the purple arrow then it is a positive angle by convention.
Figure 2
(image found at Right-hand rule - Wikipedia, the free encyclopedia )
Note: the angle is given in radians. There are 2*pi radians in a full circle (360 degrees).
Note: a list of LSL commands that relate to rotations can be found at Category:LSL Rotation - Second Life Wiki
To specify a rotation you can use the llAxisAngle2Rot command which takes an axis and an angle to define a rotation. For example to specify a rotation about the x-axis of 45 degrees you would use the following command:
rotation myRot = llAxisAngle2Rot(<1.0,0.0,0.0>,PI/4.0);
Rotations in LSL are manipulated by "multiplying" them. The "*" operation is overloaded so that when you multiply two rotations, A*B, you perform the first rotation (A) then perform the second rotation (B). The first problem that comes up is that the order matters. Rotating by A and then B is not necessarily the same as rotating by B and then A.
An example of this is given in Video 1. In the video, rotation A is defined to be a rotation of 90 degrees around the x-axis:
rotation A = llAxisAngle2Rot(<1.0,0.0,0.0>,PI/2.0);
Rotation B is defined to be a rotation of 90 degrees around the y-axis:
rotation B = llAxisAngle2Rot(<0.0,1.0,0.0>,PI/2.0);
In the video the object is originally in a "zero rotation." That is the object's x-axis is lined up with the world's x-axis as well as the y and z-axes. (In LSL the predefined constant "ZERO_ROTATION" is the zero rotation.) The object is then rotated according to A. (It is done slowly to demonstrate the action of the rotation.)
Next the object is put back into a zero rotation and then rotated according to B. (Again it is done slowly as a demonstration.) The object is then put into a zero rotation and rotated by A*B. In the demo it is done slowly so the A rotation is slowly applied and then the B rotation is slowly applied. Finally the object is put back into a zero rotation and the B*A rotation is demonstrated.
Video 1:
The order of operations is extremely important when trying to find the formula to implement in LSL. An equation that represents the rotations is generally constructed, and the rotation of interest is solved. Before an example is given it is important to note that the inverse of a rotation must be calculated.
The inverse can be thought of as rotating around the axis of rotation in the opposite direction or the negative of the angle. Another way to think about it is to flip the axis of rotation in the negative direction and then rotate around the given angle. Mathematically the two are equivalent, but the latter is more generally used to describe the inverse rotation.
In LSL there is not a library function to calculate the inverse. Rather you have to divide by the zero rotation. So if you want to calculate the inverse of a rotation A the inverse is given by (ZERO_ROTATION/A). The inverse has the special property that when you multiply by the inverse you get the zero rotation. Another way to say this is the following:
A*(ZERO_ROTATION/A) = ZERO_ROTATION,
or another way is the following:
(ZERO_ROTATION/A)*A = ZERO_ROTATION.
A common task is to to solve for a specific rotation. For example, if you have a formula A*B=C then if you want to solve for B you multiply on the left by (ZERO_ROTATION/A). The result is the following:
A*B = C,
(ZERO_ROTATION/A)*A*B = (ZERO_ROTATION/A)*C,
B = (ZERO_ROTATION/A)*C.
If you want to solve for A you multiple on the right by (ZERO_ROTATION/B) the result is the following:
A*B = C,
A*B*(ZERO_ROTATION/B) = C*(ZERO_ROTATION/B),
A = C*(ZERO_ROTATION/B),
A = C/B.
Again, the order that you do the multiplications matter so you have to be very careful about how you do the operations and how you type them into a script. Off hand this does not seem all that useful, but these ideas occur in a wide variety of situations when using rotations.
As an example, suppose that you have an object with rotation A, and you want to slowly rotate it to another rotation, C. The idea is that you want to find a rotation B so that
A*B = C.
Solving this equation for B you get
B = (ZERO_ROTATION/A)*C.
Now we will use linear interpolation ("lerping") to rotate change the angle of the rotation from zero to the final value. Before this can be done we need to find the axis of the rotation and the angle:
vector axis = llRot2Axis(B);
float angle = llRot2Angle(B);
If you want to take N steps the j'th angle is given by
((float)j)/((float)N)*angle
and the associated rotation is
A*llAxisAngle2Rot(axis,((float)j)/((float)N)*angle).
Putting it all together gives the following code snippet which defines a function to slowly rotate from a start rotation given by startRot to an end rotation given by endRot:
Code:
rotateFromStartToFinish(integer N,rotation startRot,rotation endRot)
{
rotation B = (ZERO_ROTATION/startRot)*endRot;
vector axis = llRot2Axis(B);
float angle = llRot2Angle(B);
integer j;
for(j=0;j<=N,++j)
{
llSetRot(startRot*llAxisAngle2Rot(axis,((float)j)/((float)N)*angle));
}
}
Based on a work at Basic Introduction to Rotations - SLUniverse Forums
You are free to copy and share this. I would be grateful if you would include a link back to this page if you do.