Difference between revisions of "User:Void Singer/Rotations"

From Second Life Wiki
Jump to navigation Jump to search
m (partial update)
Line 1: Line 1:
{{RightToc}}
{{RightToc}}
<div id="box">
{{void-box
== Common Rotation Tasks Simplified ==
|title=Common Rotation Tasks Simplified
<div style="padding: 0.5em">
|content=
These are a few simplifications of common rotation tasks for those (like me) who get a bit glassy eyed and overwhelmed reading the 'official' version...
This page is for people (like myself) who find the 'official' page on rotations to be either too complicated or have information that doesn't help you. This page walks you step by step through how to do the basic things to get the results you want, without looking under the hood too much. first a few definitions, then the basics, and then a few examples of common things you might want to do.
}}


{{void-box
|title=Rotation Frames Explained
|content=
A Rotation Frame is the coordinate axis around which a rotation operates, there are three possible frames to operate in
* Global Frame is the top level default axis. There are two equal but separate Global Frames
** Region Frame: Regions have a default frame that is East(+X or +Red), North(+Y or +Green), and Higher(+Z or +Blue). (negative values are the opposite direction)
** Attachment Frame: Attachment points have their own separate frame for each point. These frames do not change when the avatar is moving, but will appear to change in relation to the region frame as the avatar moves or is animated
* Reference Frame: this is the frame defined by the referenced prim itself. usually referred to as "it own axis".
** has default coordinates of Front(+X or +Red), Left(+Y or +Green), and Above(+Z or +Blue), that match the prim's axis (negative values are the opposite direction)
** A Region's or Attachment Point's  Reference Frame is the same as the Global Frame
* Local Frame: This is the same as the Reference Frame of the next highest connection.
** the Local Frame of a child prim is the root prim's Reference Frame
** the Local Frame of a root prim is the Region or Attachment Point (so, the same as the Global Frame)
}}


----
{{void-box
== Converting Degrees to Rotations (and back) ==
|title=Rotation Direction Clarified
* Convert Vector Degrees to a Rotation for ease of use
|content=
* Convert a Rotation to Vector Degrees for ease of reading
Rotation Direction can be either positive or negative around each axis, below are two ways to visualize them.
<lsl> //-- Degrees to Radians to a Rotation
* Point your arm straight out from with your thumb up. your hand is the positive end of the axis, and your shoulder the negative
vector vDeg90z = <0.0, 0.0, 90.0>;
** a positive value will turn your thumb clockwise(CW), just like the hands on a clock if you are reading the time
Rotation vRot90z = llEuler2Rot( vDeg90z * DEG_TO_RAD );
** a negative value will turn your thumb counter-clockwise(CCW), opposite of the way the hands on a clock move
* Imagine an arrow with your head (the positive end) at the top, and your feet (the negative end) at the bottom
** a positive value will turn you to your left(L)
** a negative value will turn you to your right(R)
}}


//-- to convert back
{{void-box
vector vDegReadable = llRot2Euler( vRot90z ) * RAD_TO_DEG;
|title=Preferred Functions
|content=
The following functions work in all scenarios. Other functions contain bugs in some situations, and not others. You can use them, but maximum compatibility will be obtained with these.
* To get the rotation of a prim
** [[llGetLocalRot]]
** [[llSetLocalRot]]
* If you also need to get or set additional parameters of the prim that the script is in, use the PRIM_ROT_LOCAL constant with
** [[llGetPrimitiveParams]]
** [[llSetPrimitiveParams]]
* If you need any of the above for multiple prims in a linked object, use the PRIM_ROT_LOCAL constant with
** [[llGetLinkPrimitiveParams]]
** [[llSetLinkPrimitiveParamsFast]]
*** You can use [[llSetLinkPrimitiveParams]], but it has a built in delay the the previous function does not.
}}


//-- note: some functions (like target omega) take or return Vectors in Radians
{{void-box
//-- to convert those to Vector Degrees  or a rotation, use the following
|title=Representing Rotations
vector   vDegReadable =  vRadReturn * RAD_TO_DEG;
|content=
rotation vRotUsable  = llEuler2Rot( vRadReturn );</lsl>
* There are three simple programmatically useful ways to represent rotations in a script
** as a [[vector]] of degrees (which you can easily read or write)
** as a [[vector]] of radians (which are understood by functions like [[llTargetOmega]])
** as a [[rotation]] quaternion (which are understood by functions that set rotations)
}}


{{void-box
|title=Creating and Converting Rotations
|content=
<lsl> //-- To create a vector of 15 degrees clockwise around the Z axis
vector vDegLeft15z = <15.0, 0.0, 0.0>;
//-- always use a decimal point in rotation or vector elements,
//-- or the compiler will insert code to convert to floating point numbers


----
//-- To convert that to radians (needed for some functions, and to convert to rotation quaternion)
vector vRadLeft15z = vDegLeft15z * DEG_TO_RAD;
//-- or..
vector vRadLeft15z = <15.0, 0.0, 0.0> * DEG_TO_RAD;


== Reversing a Rotations Direction ==
//-- to convert the radians to a rotation quaternion
* same as counter-clockwise (CCW) vs clockwise (CW) as viewed from the positive end of the axis
rotation vRotLeft15z = llEuler2Rot( vRadLeft15z );
* same as left turn vs right turn as viewed as if standing in the axis w/ head at positive end
  //-- or directly from the degrees...
<lsl> //-- 3 ways to reverse rotation
rotation vRotLeft15z = llEuler2Rot( <15.0, 0.0, 0.0> * DEG_TO_RAD );
  //-- use negative numbers in original variable, good for rotations that won't change
vector vDegLeft90 = <.0, .0, 90.0>; //--  CCW 90 degrees around z-axis
vector vDegcRight90 = <.0, .0, -90.0>; //-- CW 90 degrees around z-axis
//-- or
vector vDegLeft90 = <.0, .0, 90.0> * -1; //--  CW 90 degrees around z-axis


  //-- use Zero rotation Flipping, good for inline statements [ALWAYS remember to use parentheses]
  //-- Say you have a rotation quaternion (vRot2Convert), and want to get radians or degrees notation for it...
vector   vDeg90 = <.0, .0, 90>; //-- left 90 degrees around the z-axis
vector vRadConverted = llRot2Euler( vRot2Convert );
rotation vRot90 = llEuler2Rot( vRot90 * DEG_TO_RAD ); //-- still left
vector vDegConverted = vRadConverted * RAD_TO_DEG;
vRot90 = (ZERO_ROTATION / vRot90); //-- reverses the rotation direction each time called
//-- or...
vector vDegConverted = llRot2Euler( vRot2Convert ) * RAD_TO_DEG;</lsl>
}}


//-- use quaternion inversion, good for rotations that will reverse dynamically
{{void-box
vector   vDeg90 = <.0, .0, 90>; //-- left 90 degrees around the z-axis
|title=Reversing a Rotations Direction
rotation vRot90 = llEuler2Rot( vRot90 * DEG_TO_RAD ); //-- still left
|content=
vRot90.s *= -1; //-- reverses the rotation direction each time called</lsl>
* sometimes you want to get the rotation to spin the opposite way here are three ways to do that
<lsl>vector vDegLeft15z = <0.0, 0.0, 15.0>; //-- this is the original value


//-- change the sign on all the non-zero x, y, z elements, good for rotations that won't change
vector vDegRight15z = <0.0, 0.0, -15.0>;


----
//-- Multiply the vector value by -1
== Rotating in Global or Local axis==
vector vDegRight15z = vDegLeft15z * -1; //-- also works for vector radians
* Global axis is the Region: East(+X), West(-X). North(+Y). South(-Y), Up(+Z), Down(-Z).
* Local axis is the Object, Front-Side(+X), Back-Side(-X), Left-Side(+Y), Right-Side(-Y), Top(+Z), Bottom(-Z) [imagine writing on a cardboard box]
**Note: in LSL functions, forward = +X, left = +Y. Hence the only semi-intuitive direction names based on axis.
<lsl> //-- to rotate around the global axis (think stationary carousel)
llSetRot( llGetLocalRot() * vRot90z );


  //-- to rotate around the local axis (think spinning tilted top) just reverse the order
  //-- Divide ZERO_ROTATION by the rotation quaternion
llSetRot( vRot90z  * llGetRot() );</lsl>
rotation vRotRight15z = (ZERO_ROTATION / vRotLeft15z); //-- always parenthesize your reversal</lsl>
}}


{{void-box
|title=Rotation Math
|content=
* Adding or Subtracting rotations are achieved with the "*" and "/" operators respectively.
** The order that you add rotation in changes the rotation frame that the operation works on (detailed below)
** Do not use the "/" operator for anything but rotation reversal, as it's rules are slightly in the behavior frame and can give unexpected results
* To rotate in the Reference Frame:
** (vRotAmount2ChangeBy * vRotCurrentLocal)
* To rotate in the Local Frame:
** (vRotCurrentLocal * vRotAmount2ChangeBy)
* To rotate a child prim in the Global Frame
** (vRotCurrentLocal * vRotAmount2ChangeBy * vRotRootLocal)
}}


----
{{void-box
== Rotating an offset point to match objects position/rotation ==
|title=Rotating a Point Relative to the Prim
* Do this to find where a point is in relation to an object (good for rezzors)
|content=
* Imagine a ball at the end of an invisible stick attached to a box
* Being rewritten
<lsl>vector vPosOffset = <2.0, .0, .0>; //-- two meters from object "top"
}}
//-- even after rotating your object this will give the point in relation to the object's new rotation
vector vPosCurrentOffset = llGetPos() + vPosOffset * llGetLocalRot();</lsl>


{{void-box
|title=Rotating a Prim Around a Point
|content=
* Being rewritten
}}


----
{{void-box
== Rotate an objects POSITION around a given offset point ==
|title=Comments
* same idea as the Moon orbiting the Earth
|content=
<lsl>vector vPosOffset = <.0, .0, 1.0>; //-- the point we are rotating around in relation to our object
vector  vDegArc = <.0, .0, 60.0>; //-- how far around the circle to travel each move
rotation vRotArc = llEuler2Rot( vDegArc * DEG_TO_RAD );
rotation vRotTrack; //-- optional, only used in method 2
//-- Method 1: Always keep same face toward the point
//-- notice you have to move AND rotate, or else the new
//-- position becomes a diagonal line instead of a circle
llSetPrimitiveParams( [PRIM_POSITION, llGetPos() + (vPosOffset - vPosOffset * vRotArc) * llGetLocalRot(),
                      PRIM_ROTATION, vRotArc * llGetLocalRot()] );
 
//-- Method 2: Track Rotation around the point
//-- object itself does not rotate, only it's position around the point
llSetPrimitiveParams( [PRIM_POSITION, llGetPos() + (vPosOffset - vPosOffset * vRotArc) * vRotTrack );
vRotTrack = vRotArc * vRotTrack;</lsl>
 
 
----
== Warnings: ==
* Do NOT use division to reverse rotation direction
* llSetPrimitiveParams & llSetRot do not work correctly for rotations in child prims.
** see jira article [http://jira.secondlife.com/browse/SVC-93 SVC-93] for details & a workaround if you need to use them in a child prim.
<lsl> //-- This only has the desired effect in global rotations,
//--  I STRONGLY suggest using one of the other methods regardless, to avoid confusion
llSetRot( llGetRot() / vgRotConvertedDegrees  );
//-- this presumably works too, but again, I STRONGLY urge the alternative methods.
vector vPosReverseRotatedPoint = vPosOffsetPoint / vRot90z;
 
//-- this function works correctly in a child prims
llSetLocalRot( vgRotConvertedDegrees  * llGetLocalRot() );
 
//-- these work incorrectly in child prims
llSetRot( vRot90z  * llGetLocalRot() );
llSetPrimitiveParams( [PRIM_ROTATION, vRot90z  * llGetLocalRot()] );
 
//-- presumably this works incorrectly as well
llSetLinkPrimitiveParams( 2, [PRIM_ROTATION, vRot90z  * llGetLocalRot()] );</lsl>
</div></div>
 
 
<div id="box">
== Comments ==
<div style="padding: 0.5em">
Feel free to leave me a note on my [[User_talk:Void_Singer|User Talk]] page.
Feel free to leave me a note on my [[User_talk:Void_Singer|User Talk]] page.
</div></div>
}}

Revision as of 23:00, 25 October 2010

Common Rotation Tasks Simplified

This page is for people (like myself) who find the 'official' page on rotations to be either too complicated or have information that doesn't help you. This page walks you step by step through how to do the basic things to get the results you want, without looking under the hood too much. first a few definitions, then the basics, and then a few examples of common things you might want to do.

Rotation Frames Explained

A Rotation Frame is the coordinate axis around which a rotation operates, there are three possible frames to operate in

  • Global Frame is the top level default axis. There are two equal but separate Global Frames
    • Region Frame: Regions have a default frame that is East(+X or +Red), North(+Y or +Green), and Higher(+Z or +Blue). (negative values are the opposite direction)
    • Attachment Frame: Attachment points have their own separate frame for each point. These frames do not change when the avatar is moving, but will appear to change in relation to the region frame as the avatar moves or is animated
  • Reference Frame: this is the frame defined by the referenced prim itself. usually referred to as "it own axis".
    • has default coordinates of Front(+X or +Red), Left(+Y or +Green), and Above(+Z or +Blue), that match the prim's axis (negative values are the opposite direction)
    • A Region's or Attachment Point's Reference Frame is the same as the Global Frame
  • Local Frame: This is the same as the Reference Frame of the next highest connection.
    • the Local Frame of a child prim is the root prim's Reference Frame
    • the Local Frame of a root prim is the Region or Attachment Point (so, the same as the Global Frame)

Rotation Direction Clarified

Rotation Direction can be either positive or negative around each axis, below are two ways to visualize them.

  • Point your arm straight out from with your thumb up. your hand is the positive end of the axis, and your shoulder the negative
    • a positive value will turn your thumb clockwise(CW), just like the hands on a clock if you are reading the time
    • a negative value will turn your thumb counter-clockwise(CCW), opposite of the way the hands on a clock move
  • Imagine an arrow with your head (the positive end) at the top, and your feet (the negative end) at the bottom
    • a positive value will turn you to your left(L)
    • a negative value will turn you to your right(R)

Preferred Functions

The following functions work in all scenarios. Other functions contain bugs in some situations, and not others. You can use them, but maximum compatibility will be obtained with these.

Representing Rotations

  • There are three simple programmatically useful ways to represent rotations in a script
    • as a vector of degrees (which you can easily read or write)
    • as a vector of radians (which are understood by functions like llTargetOmega)
    • as a rotation quaternion (which are understood by functions that set rotations)

Creating and Converting Rotations

<lsl> //-- To create a vector of 15 degrees clockwise around the Z axis vector vDegLeft15z = <15.0, 0.0, 0.0>;

//-- always use a decimal point in rotation or vector elements,
//-- or the compiler will insert code to convert to floating point numbers
//-- To convert that to radians (needed for some functions, and to convert to rotation quaternion)

vector vRadLeft15z = vDegLeft15z * DEG_TO_RAD;

//-- or..

vector vRadLeft15z = <15.0, 0.0, 0.0> * DEG_TO_RAD;

//-- to convert the radians to a rotation quaternion

rotation vRotLeft15z = llEuler2Rot( vRadLeft15z );

//-- or directly from the degrees...

rotation vRotLeft15z = llEuler2Rot( <15.0, 0.0, 0.0> * DEG_TO_RAD );

//-- Say you have a rotation quaternion (vRot2Convert), and want to get radians or degrees notation for it...

vector vRadConverted = llRot2Euler( vRot2Convert ); vector vDegConverted = vRadConverted * RAD_TO_DEG;

//-- or...
vector vDegConverted = llRot2Euler( vRot2Convert ) * RAD_TO_DEG;</lsl>

Reversing a Rotations Direction

  • sometimes you want to get the rotation to spin the opposite way here are three ways to do that

<lsl>vector vDegLeft15z = <0.0, 0.0, 15.0>; //-- this is the original value

//-- change the sign on all the non-zero x, y, z elements, good for rotations that won't change

vector vDegRight15z = <0.0, 0.0, -15.0>;

//-- Multiply the vector value by -1

vector vDegRight15z = vDegLeft15z * -1; //-- also works for vector radians

//-- Divide ZERO_ROTATION by the rotation quaternion
rotation vRotRight15z = (ZERO_ROTATION / vRotLeft15z); //-- always parenthesize your reversal</lsl>

Rotation Math

  • Adding or Subtracting rotations are achieved with the "*" and "/" operators respectively.
    • The order that you add rotation in changes the rotation frame that the operation works on (detailed below)
    • Do not use the "/" operator for anything but rotation reversal, as it's rules are slightly in the behavior frame and can give unexpected results
  • To rotate in the Reference Frame:
    • (vRotAmount2ChangeBy * vRotCurrentLocal)
  • To rotate in the Local Frame:
    • (vRotCurrentLocal * vRotAmount2ChangeBy)
  • To rotate a child prim in the Global Frame
    • (vRotCurrentLocal * vRotAmount2ChangeBy * vRotRootLocal)

Rotating a Point Relative to the Prim

  • Being rewritten

Rotating a Prim Around a Point

  • Being rewritten

Comments

Feel free to leave me a note on my User Talk page.