<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.secondlife.com/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Dora+Gustafson</id>
	<title>Second Life Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.secondlife.com/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Dora+Gustafson"/>
	<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/wiki/Special:Contributions/Dora_Gustafson"/>
	<updated>2026-07-26T14:54:30Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.1</generator>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/wind_motor_core&amp;diff=1205043</id>
		<title>User:Dora Gustafson/wind motor core</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/wind_motor_core&amp;diff=1205043"/>
		<updated>2016-12-10T18:56:14Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: /* A working LSL script based on this core */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Wind motor core ==&lt;br /&gt;
==== For use in virtual sailboats in SL ====&lt;br /&gt;
This wind motor uses four &#039;&#039;&#039;vectors&#039;&#039;&#039; to calculate boat velocity:&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;v&#039;&#039;&#039;&#039;&#039;: boat velocity&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;wind&#039;&#039;&#039;&#039;&#039;: wind velocity, direction at wind&#039;s eye&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;head&#039;&#039;&#039;&#039;&#039;: boat heading, normalized vector&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;n&#039;&#039;&#039;&#039;&#039;: sail normal, normalized vector. It doesn&#039;t matter which one of two normals is used&amp;lt;br&amp;gt;&lt;br /&gt;
; &#039;&#039;&#039;&#039;&#039;v = head∙(-n∙(v + wind)*n)*head&#039;&#039;&#039;&#039;&#039;&amp;lt;hr&amp;gt;&lt;br /&gt;
The tricky thing in a wind motor is that &#039;&#039;&#039;&#039;&#039;v&#039;&#039;&#039;&#039;&#039; is a function of &#039;&#039;&#039;&#039;&#039;v&#039;&#039;&#039;&#039;&#039; and it can not be isolated&amp;lt;br&amp;gt;&lt;br /&gt;
Therefor &#039;&#039;&#039;&#039;&#039;v&#039;&#039;&#039;&#039;&#039; is calculated by iteration, i.e. repeated calculations using the previous result&amp;lt;br&amp;gt;&lt;br /&gt;
Notes&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;head&#039;&#039;&#039;&#039;&#039; and &#039;&#039;&#039;&#039;&#039;n&#039;&#039;&#039;&#039;&#039; are normalized vectors&lt;br /&gt;
# It does not matter if the positive or negative sail normal &#039;&#039;&#039;&#039;&#039;n&#039;&#039;&#039;&#039;&#039; is used in the equation&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;wind&#039;&#039;&#039;&#039;&#039; is pointing the wind&#039;s eye so the wind blows opposite. Thus the minus sign in the equation&lt;br /&gt;
# The magnitude of &#039;&#039;&#039;&#039;&#039;wind&#039;&#039;&#039;&#039;&#039; is the wind speed&lt;br /&gt;
# The magnitude of &#039;&#039;&#039;&#039;&#039;v&#039;&#039;&#039;&#039;&#039; is the boat speed&lt;br /&gt;
==== A working LSL script based on this core ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
// wind motor core, minimal sailboat script by Dora Gustafson, Studio Dora 2016&lt;br /&gt;
// use a two prim object: root prim for hull and child prim for sail&lt;br /&gt;
// enter this script, rez on water, sit and sail&lt;br /&gt;
// up, down arrows for setting sail&lt;br /&gt;
// left, right arrows for steering&lt;br /&gt;
&lt;br /&gt;
vector windVector = &amp;lt;.0, 9.0, .0&amp;gt;; // wind from north, 9 m/S&lt;br /&gt;
float WindFactor = 12.0; // m/S&lt;br /&gt;
float heelFactor = .3;&lt;br /&gt;
float threeDEG = 0.052360; // 3°&lt;br /&gt;
float MAXSAIL = 1.48353; // 85°&lt;br /&gt;
float MINSAIL = 0.174533; // 10°&lt;br /&gt;
float sailAngle;&lt;br /&gt;
vector linear_motor;&lt;br /&gt;
vector angular_motor;&lt;br /&gt;
integer sailPrim = 2;&lt;br /&gt;
integer hullPrim = 1;&lt;br /&gt;
float time = 4.0;&lt;br /&gt;
vector blue = &amp;lt;0.0, 0.455, 0.851&amp;gt;;&lt;br /&gt;
vector green = &amp;lt;0.18, 0.8, 0.251&amp;gt;;&lt;br /&gt;
vector yellow = &amp;lt;1.0, 0.863, 0.0&amp;gt;;&lt;br /&gt;
vector red = &amp;lt;1.0, 0.255, 0.212&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetVehicleType(VEHICLE_TYPE_BOAT);&lt;br /&gt;
        llSetVehicleFloatParam( VEHICLE_HOVER_HEIGHT, 0.001 );&lt;br /&gt;
        llSetVehicleFloatParam( VEHICLE_BANKING_EFFICIENCY, 0.0 );&lt;br /&gt;
        llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_TIMESCALE, .75); // default 4&lt;br /&gt;
        llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 1); // default 0.5&lt;br /&gt;
        llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_TIMESCALE, .5); // default 3&lt;br /&gt;
        llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0); // default 0.5&lt;br /&gt;
        llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, .5); // default 5&lt;br /&gt;
        llSitTarget( &amp;lt;-1.5, .0, 1.25&amp;gt;, ZERO_ROTATION);&lt;br /&gt;
        sailAngle = MAXSAIL;&lt;br /&gt;
    }&lt;br /&gt;
    changed(integer change)&lt;br /&gt;
    {&lt;br /&gt;
        if (change &amp;amp; CHANGED_LINK)&lt;br /&gt;
        {&lt;br /&gt;
            key sitter = llAvatarOnSitTarget() ;&lt;br /&gt;
            if(sitter != NULL_KEY)&lt;br /&gt;
            {&lt;br /&gt;
                llSetStatus( STATUS_PHYSICS, TRUE);&lt;br /&gt;
                llRequestPermissions( sitter, PERMISSION_TAKE_CONTROLS);&lt;br /&gt;
                llSetTimerEvent( time);&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                llSetStatus( STATUS_PHYSICS, FALSE);&lt;br /&gt;
                llReleaseControls();&lt;br /&gt;
                llSetTimerEvent( .0);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    run_time_permissions(integer perm)&lt;br /&gt;
    {&lt;br /&gt;
        if ( perm &amp;amp; PERMISSION_TAKE_CONTROLS ) llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT, TRUE, FALSE);&lt;br /&gt;
    }&lt;br /&gt;
    control(key id, integer level, integer edge)&lt;br /&gt;
    {&lt;br /&gt;
        if ( edge &amp;amp; level &amp;amp; ( CONTROL_FWD | CONTROL_BACK) )&lt;br /&gt;
        {&lt;br /&gt;
            if ( edge &amp;amp; level &amp;amp; CONTROL_FWD )&lt;br /&gt;
            {&lt;br /&gt;
                if ( sailAngle + threeDEG &amp;lt; MAXSAIL ) sailAngle += threeDEG;&lt;br /&gt;
            }&lt;br /&gt;
            else if ( edge &amp;amp; level &amp;amp; CONTROL_BACK)&lt;br /&gt;
            {&lt;br /&gt;
                if ( sailAngle - threeDEG &amp;gt; MINSAIL ) sailAngle -= threeDEG;&lt;br /&gt;
            }&lt;br /&gt;
            llSetTimerEvent( 0.05);&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            if ( level &amp;amp; (CONTROL_ROT_RIGHT)) angular_motor.z = 0.8;&lt;br /&gt;
            else if ( level &amp;amp; (CONTROL_ROT_LEFT)) angular_motor.z = -0.8;&lt;br /&gt;
            else angular_motor.z = 0.0;&lt;br /&gt;
            llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, angular_motor);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    timer()&lt;br /&gt;
    {&lt;br /&gt;
        if ( llGetStatus( STATUS_PHYSICS) )&lt;br /&gt;
        {&lt;br /&gt;
        // vector capture&lt;br /&gt;
            rotation sailRot = llGetRot();&lt;br /&gt;
            vector heading = llRot2Fwd( sailRot);&lt;br /&gt;
            vector left = llRot2Left( sailRot);&lt;br /&gt;
            vector velocity = llGetVel();&lt;br /&gt;
            float speed = llVecMag( velocity);&lt;br /&gt;
            vector Aw = windVector + velocity;&lt;br /&gt;
            Aw.z = 0.0;&lt;br /&gt;
            vector nAw = llVecNorm( Aw);&lt;br /&gt;
            vector axs = heading%nAw; // up or down axis to turn sail around&lt;br /&gt;
            float AwAngle = llAcos( heading*nAw); // apparent wind, local angle [0;PI]&lt;br /&gt;
        // setting sail&lt;br /&gt;
            float setsail = AwAngle;&lt;br /&gt;
            if ( setsail &amp;gt; sailAngle ) setsail = sailAngle;&lt;br /&gt;
            sailRot = llAxisAngle2Rot( axs, setsail);&lt;br /&gt;
            vector sailnormal = llRot2Left( sailRot)*llGetRot(); // Global&lt;br /&gt;
            llSetLinkPrimitiveParamsFast( sailPrim, [PRIM_ROT_LOCAL, sailRot&#039;er]);&lt;br /&gt;
        // Linear and Angular Motors&lt;br /&gt;
            vector action = ZERO_VECTOR;&lt;br /&gt;
            if ( llFabs( sailnormal*nAw) &amp;gt; MINSAIL ) action = -(sailnormal*Aw)*sailnormal;&lt;br /&gt;
            linear_motor.x = WindFactor*action*heading;&lt;br /&gt;
            llSetVehicleVectorParam( VEHICLE_LINEAR_MOTOR_DIRECTION, linear_motor);&lt;br /&gt;
        // heel by wind&lt;br /&gt;
            angular_motor.x = -heelFactor*action*left;&lt;br /&gt;
            llSetVehicleVectorParam( VEHICLE_ANGULAR_MOTOR_DIRECTION, angular_motor);&lt;br /&gt;
            llSetTimerEvent( time);&lt;br /&gt;
        // optional signal color&lt;br /&gt;
            vector color = red;&lt;br /&gt;
            if ( sailAngle &amp;lt; 0.435*AwAngle ) color = blue;&lt;br /&gt;
            else if ( sailAngle &amp;lt; 0.565*AwAngle ) color = green;&lt;br /&gt;
            else if ( sailAngle &amp;lt; 0.825*AwAngle ) color = yellow;&lt;br /&gt;
            llSetLinkColor( sailPrim, color, ALL_SIDES);&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            llSetTimerEvent( 0.0);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    on_rez( integer p) { llResetScript(); }&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
A few boats in world use this core now. Two of mine are &amp;quot;Windy&amp;quot; and &amp;quot;Breezy 9&#039;er&amp;quot;&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson&amp;diff=1205042</id>
		<title>User:Dora Gustafson</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson&amp;diff=1205042"/>
		<updated>2016-12-10T18:46:38Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: /* Highlighted scripts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header}}&lt;br /&gt;
&amp;lt;div id=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
== About ==&lt;br /&gt;
I have been a premium since spring 2007.&amp;lt;br&amp;gt;&lt;br /&gt;
Over the time I made quite a few scripts.&amp;lt;br&amp;gt;&lt;br /&gt;
The scripts are the basis for my business.&amp;lt;br&amp;gt;&lt;br /&gt;
Many are published in the SL forums and some are given away.&amp;lt;br&amp;gt;&lt;br /&gt;
Here are some working scripts that highlights LSL functions and SL characteristics&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Highlighted scripts ==&lt;br /&gt;
#[[User:Dora_Gustafson/talking_die|Talking Die]]&lt;br /&gt;
#[[User:Dora_Gustafson/llAxes2Rot_right_and_wrong|llAxes2Rot]] Right and Wrong&lt;br /&gt;
#[[User:Dora_Gustafson/point_tracker|Key framed Motion forward on a closed track]]&lt;br /&gt;
#[[User:Dora_Gustafson/Basic_Resizer|Re-size or re-scale objects with a single small script]]&lt;br /&gt;
#[[User:Dora_Gustafson/sundirection_and_time_of_day|Show Sun Direction and compare to Time of Day]]&lt;br /&gt;
#[[User:Dora_Gustafson/universal_hinged_motion|Universal hinged motion]] in 8 Key Frames&lt;br /&gt;
#[[User:Dora_Gustafson/Pendulum_motion|Pendulum motion]] Simple Pendulum Motion in 24 Key Frames, a good swing motion&lt;br /&gt;
#[[User:Dora_Gustafson/Harmonic_Oscillator_motion|Harmonic Oscillator motion]] Motion in 12 Key Frames&lt;br /&gt;
#[[User:Dora_Gustafson/captureCameraView|Capture Camera View]] Using llSetLinkCamera()&lt;br /&gt;
#[[User:Dora_Gustafson/llRotBetween_alternatives#llRotBetween.2C_some_alternatives_and_considerations|llRotBetween]] alternatives and considerations&lt;br /&gt;
#[[User:Dora_Gustafson/fixed_3D_relation|Fixed 3D Relation]] Position and Rotation computations&lt;br /&gt;
#[[User:Dora_Gustafson/JSON_structure_facial_expression|JSON structured menu]] for all facial expressions&lt;br /&gt;
#[[User:Dora_Gustafson/insertion_sort|Straight insertion Sort script]]&lt;br /&gt;
#[[User:Dora_Gustafson/occurences|Count occurencces in a list]]&lt;br /&gt;
#[[User:Dora_Gustafson/bezier_toy|Bézier Toy]]&lt;br /&gt;
#[[LlTargetOmega_Replacement|Replacing llTargetOmega]] with a Key Framed Motion&lt;br /&gt;
#[[User:Dora_Gustafson/moderated_world_wind|Moderated in-world wind]]&lt;br /&gt;
#[[User:Dora_Gustafson/wind_motor_core|Wind motor Core]]&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/wind_motor_core&amp;diff=1205041</id>
		<title>User:Dora Gustafson/wind motor core</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/wind_motor_core&amp;diff=1205041"/>
		<updated>2016-12-10T18:41:19Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: /* Wind motor core */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Wind motor core ==&lt;br /&gt;
==== For use in virtual sailboats in SL ====&lt;br /&gt;
This wind motor uses four &#039;&#039;&#039;vectors&#039;&#039;&#039; to calculate boat velocity:&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;v&#039;&#039;&#039;&#039;&#039;: boat velocity&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;wind&#039;&#039;&#039;&#039;&#039;: wind velocity, direction at wind&#039;s eye&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;head&#039;&#039;&#039;&#039;&#039;: boat heading, normalized vector&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;n&#039;&#039;&#039;&#039;&#039;: sail normal, normalized vector. It doesn&#039;t matter which one of two normals is used&amp;lt;br&amp;gt;&lt;br /&gt;
; &#039;&#039;&#039;&#039;&#039;v = head∙(-n∙(v + wind)*n)*head&#039;&#039;&#039;&#039;&#039;&amp;lt;hr&amp;gt;&lt;br /&gt;
The tricky thing in a wind motor is that &#039;&#039;&#039;&#039;&#039;v&#039;&#039;&#039;&#039;&#039; is a function of &#039;&#039;&#039;&#039;&#039;v&#039;&#039;&#039;&#039;&#039; and it can not be isolated&amp;lt;br&amp;gt;&lt;br /&gt;
Therefor &#039;&#039;&#039;&#039;&#039;v&#039;&#039;&#039;&#039;&#039; is calculated by iteration, i.e. repeated calculations using the previous result&amp;lt;br&amp;gt;&lt;br /&gt;
Notes&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;head&#039;&#039;&#039;&#039;&#039; and &#039;&#039;&#039;&#039;&#039;n&#039;&#039;&#039;&#039;&#039; are normalized vectors&lt;br /&gt;
# It does not matter if the positive or negative sail normal &#039;&#039;&#039;&#039;&#039;n&#039;&#039;&#039;&#039;&#039; is used in the equation&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;wind&#039;&#039;&#039;&#039;&#039; is pointing the wind&#039;s eye so the wind blows opposite. Thus the minus sign in the equation&lt;br /&gt;
# The magnitude of &#039;&#039;&#039;&#039;&#039;wind&#039;&#039;&#039;&#039;&#039; is the wind speed&lt;br /&gt;
# The magnitude of &#039;&#039;&#039;&#039;&#039;v&#039;&#039;&#039;&#039;&#039; is the boat speed&lt;br /&gt;
==== A working LSL script based on this core ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
// wind motor core, minimal sailboat script by Dora Gustafson, Studio Dora 2016&lt;br /&gt;
// use a two prim object: root prim for hull and child prim for sail&lt;br /&gt;
// enter this script, rez on water, sit and sail&lt;br /&gt;
// up, down arrows for setting sail&lt;br /&gt;
// left, right arrows for steering&lt;br /&gt;
&lt;br /&gt;
vector windVector = &amp;lt;.0, 9.0, .0&amp;gt;; // wind from north, 9 m/S&lt;br /&gt;
float WindFactor = 12.0; // m/S&lt;br /&gt;
float heelFactor = .3;&lt;br /&gt;
float threeDEG = 0.052360; // 3°&lt;br /&gt;
float MAXSAIL = 1.48353; // 85°&lt;br /&gt;
float MINSAIL = 0.174533; // 10°&lt;br /&gt;
float sailAngle;&lt;br /&gt;
vector linear_motor;&lt;br /&gt;
vector angular_motor;&lt;br /&gt;
integer sailPrim = 2;&lt;br /&gt;
integer hullPrim = 1;&lt;br /&gt;
float time = 4.0;&lt;br /&gt;
vector blue = &amp;lt;0.0, 0.455, 0.851&amp;gt;;&lt;br /&gt;
vector green = &amp;lt;0.18, 0.8, 0.251&amp;gt;;&lt;br /&gt;
vector yellow = &amp;lt;1.0, 0.863, 0.0&amp;gt;;&lt;br /&gt;
vector red = &amp;lt;1.0, 0.255, 0.212&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetVehicleType(VEHICLE_TYPE_BOAT);&lt;br /&gt;
        llSetVehicleFloatParam( VEHICLE_HOVER_HEIGHT, 0.001 );&lt;br /&gt;
        llSetVehicleFloatParam( VEHICLE_BANKING_EFFICIENCY, 0.0 );&lt;br /&gt;
        llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_TIMESCALE, .75); // default 4&lt;br /&gt;
        llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 1); // default 0.5&lt;br /&gt;
        llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_TIMESCALE, .5); // default 3&lt;br /&gt;
        llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0); // default 0.5&lt;br /&gt;
        llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, .5); // default 5&lt;br /&gt;
        llSitTarget( &amp;lt;-1.5, .0, 1.25&amp;gt;, ZERO_ROTATION);&lt;br /&gt;
        sailAngle = MAXSAIL;&lt;br /&gt;
    }&lt;br /&gt;
    changed(integer change)&lt;br /&gt;
    {&lt;br /&gt;
        if (change &amp;amp; CHANGED_LINK)&lt;br /&gt;
        {&lt;br /&gt;
            key sitter = llAvatarOnSitTarget() ;&lt;br /&gt;
            if(sitter != NULL_KEY)&lt;br /&gt;
            {&lt;br /&gt;
                llSetStatus( STATUS_PHYSICS, TRUE);&lt;br /&gt;
                llRequestPermissions( sitter, PERMISSION_TAKE_CONTROLS);&lt;br /&gt;
                llSetTimerEvent( time);&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                llSetStatus( STATUS_PHYSICS, FALSE);&lt;br /&gt;
                llReleaseControls();&lt;br /&gt;
                llSetTimerEvent( .0);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    run_time_permissions(integer perm)&lt;br /&gt;
    {&lt;br /&gt;
        if ( perm &amp;amp; PERMISSION_TAKE_CONTROLS ) llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT, TRUE, FALSE);&lt;br /&gt;
    }&lt;br /&gt;
    control(key id, integer level, integer edge)&lt;br /&gt;
    {&lt;br /&gt;
        if ( edge &amp;amp; level &amp;amp; ( CONTROL_FWD | CONTROL_BACK) )&lt;br /&gt;
        {&lt;br /&gt;
            if ( edge &amp;amp; level &amp;amp; CONTROL_FWD )&lt;br /&gt;
            {&lt;br /&gt;
                if ( sailAngle + threeDEG &amp;lt; MAXSAIL ) sailAngle += threeDEG;&lt;br /&gt;
            }&lt;br /&gt;
            else if ( edge &amp;amp; level &amp;amp; CONTROL_BACK)&lt;br /&gt;
            {&lt;br /&gt;
                if ( sailAngle - threeDEG &amp;gt; MINSAIL ) sailAngle -= threeDEG;&lt;br /&gt;
            }&lt;br /&gt;
            llSetTimerEvent( 0.05);&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            if ( level &amp;amp; (CONTROL_ROT_RIGHT)) angular_motor.z = 0.8;&lt;br /&gt;
            else if ( level &amp;amp; (CONTROL_ROT_LEFT)) angular_motor.z = -0.8;&lt;br /&gt;
            else angular_motor.z = 0.0;&lt;br /&gt;
            llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, angular_motor);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    timer()&lt;br /&gt;
    {&lt;br /&gt;
        if ( llGetStatus( STATUS_PHYSICS) )&lt;br /&gt;
        {&lt;br /&gt;
        // vector capture&lt;br /&gt;
            rotation sailRot = llGetRot();&lt;br /&gt;
            vector heading = llRot2Fwd( sailRot);&lt;br /&gt;
            vector left = llRot2Left( sailRot);&lt;br /&gt;
            vector velocity = llGetVel();&lt;br /&gt;
            float speed = llVecMag( velocity);&lt;br /&gt;
            vector Aw = windVector + velocity;&lt;br /&gt;
            Aw.z = 0.0;&lt;br /&gt;
            vector nAw = llVecNorm( Aw);&lt;br /&gt;
            vector axs = heading%nAw; // up or down axis to turn sail around&lt;br /&gt;
            float AwAngle = llAcos( heading*nAw); // apparent wind, local angle [0;PI]&lt;br /&gt;
        // setting sail&lt;br /&gt;
            float setsail = AwAngle;&lt;br /&gt;
            if ( setsail &amp;gt; sailAngle ) setsail = sailAngle;&lt;br /&gt;
            sailRot = llAxisAngle2Rot( axs, setsail);&lt;br /&gt;
            vector sailnormal = llRot2Left( sailRot)*llGetRot(); // Global&lt;br /&gt;
            llSetLinkPrimitiveParamsFast( sailPrim, [PRIM_ROT_LOCAL, sailRot]);&lt;br /&gt;
        // Linear and Angular Motors&lt;br /&gt;
            vector action = ZERO_VECTOR;&lt;br /&gt;
            if ( llFabs( sailnormal*nAw) &amp;gt; MINSAIL ) action = -(sailnormal*Aw)*sailnormal;&lt;br /&gt;
            linear_motor.x = WindFactor*action*heading;&lt;br /&gt;
            llSetVehicleVectorParam( VEHICLE_LINEAR_MOTOR_DIRECTION, linear_motor);&lt;br /&gt;
        // heel by wind&lt;br /&gt;
            angular_motor.x = -heelFactor*action*left;&lt;br /&gt;
            llSetVehicleVectorParam( VEHICLE_ANGULAR_MOTOR_DIRECTION, angular_motor);&lt;br /&gt;
            llSetTimerEvent( time);&lt;br /&gt;
        // optional signal color&lt;br /&gt;
            vector color = red;&lt;br /&gt;
            if ( sailAngle &amp;lt; 0.435*AwAngle ) color = blue;&lt;br /&gt;
            else if ( sailAngle &amp;lt; 0.565*AwAngle ) color = green;&lt;br /&gt;
            else if ( sailAngle &amp;lt; 0.825*AwAngle ) color = yellow;&lt;br /&gt;
            llSetLinkColor( sailPrim, color, ALL_SIDES);&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            llSetTimerEvent( 0.0);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    on_rez( integer p) { llResetScript(); }&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/wind_motor_core&amp;diff=1205040</id>
		<title>User:Dora Gustafson/wind motor core</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/wind_motor_core&amp;diff=1205040"/>
		<updated>2016-12-10T18:20:09Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: Created page with &amp;quot; == Wind motor core == ==== For use in virtual sailboats in SL ==== This wind motor uses four &amp;#039;&amp;#039;&amp;#039;vectors&amp;#039;&amp;#039;&amp;#039; to calculate boat velocity: # &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;v&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;: boat velocity # &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;win...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Wind motor core ==&lt;br /&gt;
==== For use in virtual sailboats in SL ====&lt;br /&gt;
This wind motor uses four &#039;&#039;&#039;vectors&#039;&#039;&#039; to calculate boat velocity:&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;v&#039;&#039;&#039;&#039;&#039;: boat velocity&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;wind&#039;&#039;&#039;&#039;&#039;: wind velocity, direction at wind&#039;s eye&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;head&#039;&#039;&#039;&#039;&#039;: boat heading, normalized vector&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;n&#039;&#039;&#039;&#039;&#039;: sail normal, normalized vector. It doesn&#039;t matter which one of two normals is used&amp;lt;br&amp;gt;&lt;br /&gt;
; &#039;&#039;&#039;&#039;&#039;v = head∙(-n∙(v + wind)*n)*head&#039;&#039;&#039;&#039;&#039;&amp;lt;hr&amp;gt;&lt;br /&gt;
The tricky thing in a wind motor is that &#039;&#039;&#039;&#039;&#039;v&#039;&#039;&#039;&#039;&#039; is a function of &#039;&#039;&#039;&#039;&#039;v&#039;&#039;&#039;&#039;&#039; and it can not be isolated&amp;lt;br&amp;gt;&lt;br /&gt;
Therefor &#039;&#039;&#039;&#039;&#039;v&#039;&#039;&#039;&#039;&#039; is calculated by iteration, i.e. repeated calculations using the previous result&amp;lt;br&amp;gt;&lt;br /&gt;
Notes&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;head&#039;&#039;&#039;&#039;&#039; and &#039;&#039;&#039;&#039;&#039;n&#039;&#039;&#039;&#039;&#039; are normalized vectors&lt;br /&gt;
# It does not matter if the positive or negative sail normal &#039;&#039;&#039;&#039;&#039;n&#039;&#039;&#039;&#039;&#039; is used in the equation&lt;br /&gt;
# &#039;&#039;&#039;&#039;&#039;wind&#039;&#039;&#039;&#039;&#039; is pointing the wind&#039;s eye so the wind blows opposite. Thus the minus sign in the equation&lt;br /&gt;
# The magnitude of &#039;&#039;&#039;&#039;&#039;wind&#039;&#039;&#039;&#039;&#039; is the wind speed&lt;br /&gt;
# The magnitude of &#039;&#039;&#039;&#039;&#039;v&#039;&#039;&#039;&#039;&#039; is the boat speed&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LlWind&amp;diff=1204615</id>
		<title>LlWind</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LlWind&amp;diff=1204615"/>
		<updated>2016-09-19T19:26:04Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|inject-2={{LSL Function/offset|offset|noZ=*|sim=*}}&lt;br /&gt;
|func=llWind&lt;br /&gt;
|sort=Wind&lt;br /&gt;
|func_id=44&lt;br /&gt;
|func_sleep=0.0&lt;br /&gt;
|func_energy=10.0&lt;br /&gt;
|return_type=vector&lt;br /&gt;
|p1_type=vector&lt;br /&gt;
|p1_name=offset&lt;br /&gt;
|func_footnote&lt;br /&gt;
|return_text=that is the wind velocity at the prim&#039;s [[llGetPos|position]] + {{LSLPT|offset}}&lt;br /&gt;
|spec&lt;br /&gt;
|caveats&lt;br /&gt;
|examples=&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    touch_start(integer num)&lt;br /&gt;
    {&lt;br /&gt;
        llSay(0, &amp;quot;Wind velocity: &amp;quot; + (string)llWind(ZERO_VECTOR));&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
// wind interpretation as angle and speed&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        vector windVector = llWind( ZERO_VECTOR);&lt;br /&gt;
        float windSpeed = llVecMag( windVector);&lt;br /&gt;
        float windDirection = llAtan2( windVector.y, windVector.x);&lt;br /&gt;
        integer compassWind = ( 450 - (integer)( RAD_TO_DEG*windDirection))%360;&lt;br /&gt;
        llOwnerSay( &amp;quot;\nWind direction: &amp;quot;+(string)compassWind+&amp;quot;°\nWind speed: &amp;quot;+(string)windSpeed+&amp;quot; m/S&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_functions={{LSL DefineRow||[[llCloud]]}}&lt;br /&gt;
|also_articles={{LSL DefineRow||{{LSLGC|Weather}}|SL Weather information}}&lt;br /&gt;
{{LSL DefineRow||[[User:Dora_Gustafson/moderated_world_wind|Moderated in-world wind]]}}&lt;br /&gt;
|notes&lt;br /&gt;
|issues={{Issue/V1|SVC-3131|llWind() and viewer wind effects do not match}}&lt;br /&gt;
|cat1=Region&lt;br /&gt;
|cat2=Weather&lt;br /&gt;
|cat3&lt;br /&gt;
|cat4&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson&amp;diff=1204500</id>
		<title>User:Dora Gustafson</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson&amp;diff=1204500"/>
		<updated>2016-08-10T09:48:38Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: /* Highlighted scripts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header}}&lt;br /&gt;
&amp;lt;div id=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
== About ==&lt;br /&gt;
I have been a premium since spring 2007.&amp;lt;br&amp;gt;&lt;br /&gt;
Over the time I made quite a few scripts.&amp;lt;br&amp;gt;&lt;br /&gt;
The scripts are the basis for my business.&amp;lt;br&amp;gt;&lt;br /&gt;
Many are published in the SL forums and some are given away.&amp;lt;br&amp;gt;&lt;br /&gt;
Here are some working scripts that highlights LSL functions and SL characteristics&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Highlighted scripts ==&lt;br /&gt;
#[[User:Dora_Gustafson/talking_die|Talking Die]]&lt;br /&gt;
#[[User:Dora_Gustafson/llAxes2Rot_right_and_wrong|llAxes2Rot]] Right and Wrong&lt;br /&gt;
#[[User:Dora_Gustafson/point_tracker|Key framed Motion forward on a closed track]]&lt;br /&gt;
#[[User:Dora_Gustafson/Basic_Resizer|Re-size or re-scale objects with a single small script]]&lt;br /&gt;
#[[User:Dora_Gustafson/sundirection_and_time_of_day|Show Sun Direction and compare to Time of Day]]&lt;br /&gt;
#[[User:Dora_Gustafson/universal_hinged_motion|Universal hinged motion]] in 8 Key Frames&lt;br /&gt;
#[[User:Dora_Gustafson/Pendulum_motion|Pendulum motion]] Simple Pendulum Motion in 24 Key Frames, a good swing motion&lt;br /&gt;
#[[User:Dora_Gustafson/Harmonic_Oscillator_motion|Harmonic Oscillator motion]] Motion in 12 Key Frames&lt;br /&gt;
#[[User:Dora_Gustafson/captureCameraView|Capture Camera View]] Using llSetLinkCamera()&lt;br /&gt;
#[[User:Dora_Gustafson/llRotBetween_alternatives#llRotBetween.2C_some_alternatives_and_considerations|llRotBetween]] alternatives and considerations&lt;br /&gt;
#[[User:Dora_Gustafson/fixed_3D_relation|Fixed 3D Relation]] Position and Rotation computations&lt;br /&gt;
#[[User:Dora_Gustafson/JSON_structure_facial_expression|JSON structured menu]] for all facial expressions&lt;br /&gt;
#[[User:Dora_Gustafson/insertion_sort|Straight insertion Sort script]]&lt;br /&gt;
#[[User:Dora_Gustafson/occurences|Count occurencces in a list]]&lt;br /&gt;
#[[User:Dora_Gustafson/bezier_toy|Bézier Toy]]&lt;br /&gt;
#[[LlTargetOmega_Replacement|Replacing llTargetOmega]] with a Key Framed Motion&lt;br /&gt;
#[[User:Dora_Gustafson/moderated_world_wind|Moderated in-world wind]]&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/moderated_world_wind&amp;diff=1204499</id>
		<title>User:Dora Gustafson/moderated world wind</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/moderated_world_wind&amp;diff=1204499"/>
		<updated>2016-08-10T09:40:34Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: Moderated in world wind for sailing in general and racing particularely&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Moderated in World Wind ==&lt;br /&gt;
The sailing community in Second Life do not use the world wind for sailing. The reasons are&lt;br /&gt;
# The wind is different in each position so that two sailors are guarantied to have different wind at any time&lt;br /&gt;
# Most of the time the wind is too light or too heavy for sailing&lt;br /&gt;
This moderated wind overcomes these objections&amp;lt;br&amp;gt;&lt;br /&gt;
Firstly: Everybody read the wind in sim position &amp;lt;0,0,0&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Secondly: The wind speed is moderated to 5 times the cubic root of the obtained wind speed&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
vector windVector = llWind( -llGetPos()); // Wind velocity in region at &amp;lt;0,0,0&amp;gt;&lt;br /&gt;
float speed = 5.0*llPow( llVecMag( windVector), .333333); // moderated speed&lt;br /&gt;
windVector = speed*llVecNorm( windVector); // moderated wind velocity&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
With this moderated wind all sailors are guarantied the same unpredictable wind at any time&amp;lt;br&amp;gt;&lt;br /&gt;
Statistics for the moderated wind:&lt;br /&gt;
 measured: 33000 times (twelwe hours)&lt;br /&gt;
 Wind Mean: 15 kts&lt;br /&gt;
 Standard deviation: 3 kts&lt;br /&gt;
 Max: 24 kts&lt;br /&gt;
 Min: 3 kts&lt;br /&gt;
Observations:&amp;lt;br&amp;gt;&lt;br /&gt;
# very suitable for sailing&lt;br /&gt;
# may stay almost the same over one, two or more sims&lt;br /&gt;
# may change slowly over time or direction may jump&lt;br /&gt;
# wind direction may &#039;jump&#039; but only when the wind speed is low (very natural)&lt;br /&gt;
# all sailors have identical wind conditions and racing on equal terms is possible&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LSL_Operators&amp;diff=1197693</id>
		<title>LSL Operators</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LSL_Operators&amp;diff=1197693"/>
		<updated>2015-10-09T08:26:48Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: modulus runtime error&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header|ml=*}}{{LSLC|FixMe}}&amp;lt;!-- This article is woefully incomplete, it needs more Operator tables --&amp;gt;&lt;br /&gt;
Operators are used to cause an operation (or mathematical action) to be performed on one (such as !) or two operands. The easy and common example is 1 + 2 where 1 and 2 are operands, and the &#039;&#039;&#039;+&#039;&#039;&#039; is the operator.&lt;br /&gt;
&lt;br /&gt;
This concept can be extended much further with LSL since operands can be variables with the special case of the assignment operators requiring that the left hand side be a variable.&lt;br /&gt;
&lt;br /&gt;
{| bgcolor=&amp;quot;#FFFFFF&amp;quot; border=&amp;quot;1&amp;quot;  cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;6&amp;quot;&lt;br /&gt;
|- bgColor=&amp;quot;#A7C1F2&amp;quot;&lt;br /&gt;
! Operator&lt;br /&gt;
! Description&lt;br /&gt;
! Usage Example&lt;br /&gt;
|- &lt;br /&gt;
| () || Parentheses || a * (b + c)&lt;br /&gt;
|-&lt;br /&gt;
| [] || Brackets: list constructor || [a, 2, &amp;quot;this&amp;quot;, 0.01]&lt;br /&gt;
|-&lt;br /&gt;
| (&#039;&#039;type&#039;&#039;) || Typecasting || message = &amp;quot;The result is:&amp;quot; + (string) result;&lt;br /&gt;
|- &lt;br /&gt;
| ! ~ ++ --  || Logical-NOT, Bitwise-NOT, Increment, Decrement || counter++;  &lt;br /&gt;
|-&lt;br /&gt;
| * / %  || Multiply/Dot-Product, Divide, Modulus/Cross-Product  || rollover = (count + 1)%5;&lt;br /&gt;
|-&lt;br /&gt;
| -  ||   Subtraction  || one = 3 - 2;&lt;br /&gt;
|-&lt;br /&gt;
| + || Addition or joining Strings || two = 1+1;&lt;br /&gt;
text = &amp;quot;Hello&amp;quot; + &amp;quot;World&amp;quot;;&lt;br /&gt;
|-&lt;br /&gt;
| + || Concatenation or joining Lists || myList = [1, 2, 3] + [4, 5];&lt;br /&gt;
newList = oldList + addList;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;&amp;lt; &amp;gt;&amp;gt;  || Left Shift, Right Shift  || eight = 4 &amp;lt;&amp;lt; 1;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt; &amp;lt;= &amp;gt; &amp;gt;=  || Less Than, Less Than Or Equal To,&lt;br /&gt;
Greater Than, Greater Than or Equal To  &lt;br /&gt;
|| isFalse = (6 &amp;lt;= 4);&lt;br /&gt;
|-&lt;br /&gt;
| ==  !=  || Comparison Equal, Comparison Not Equal  || isFalse = (&amp;quot;this&amp;quot; == &amp;quot;that&amp;quot;);&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;  || Bitwise AND  || zero = 4 &amp;amp; 2;&lt;br /&gt;
four = 4 &amp;amp; 4;&lt;br /&gt;
|-&lt;br /&gt;
| ^  || Bitwise XOR  || zero = 4 ^ 4;&lt;br /&gt;
six = 4 ^ 2;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;  || Bitwise OR  || four = 4 &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; 4;&lt;br /&gt;
six = 4 &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; 2;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;||&amp;lt;/nowiki&amp;gt;  || Logical OR  || isTrue = (FALSE &amp;lt;nowiki&amp;gt;||&amp;lt;/nowiki&amp;gt; TRUE);&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;&amp;amp;  ||Logical AND  || isFalse = (FALSE &amp;amp;&amp;amp; TRUE);&lt;br /&gt;
|-&lt;br /&gt;
| = += -= *= /= %=  || Assignment  || four = 4;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; modulus, like integer division cause a &#039;&#039;Script run-time error. Math Error&#039;&#039; when second operand equals 0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Unlike all other binary operators, the % operator only allows integer or vector operands.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Unlike most, if not all, other languages that use the C style &#039;&#039;&#039;&amp;amp;&amp;amp;&#039;&#039;&#039; and &#039;&#039;&#039;||&#039;&#039;&#039; operators, &#039;&#039;&#039;both&#039;&#039;&#039; operands are &#039;&#039;&#039;always&#039;&#039;&#039; evaluated.  For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;if (TRUE || 1/0) llSay(PUBLIC_CHANNEL, &amp;quot;Aha!&amp;quot;);&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
will cause a Math Error rather than say &amp;quot;Aha&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The ++ (increment) and -- (decrement) have their effect on their number either before or after the number is evaluated when used in conditions dependent on whether they are before or after the number.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;integer count;&lt;br /&gt;
if(!(++count)) // Is incremented then evaluated.&lt;br /&gt;
llSay(PUBLIC_CHANNEL, &amp;quot;Aha&amp;quot;); // Will not be said.&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;integer count;&lt;br /&gt;
if(!(count++)) // Is evaluated then incremented.&lt;br /&gt;
llSay(PUBLIC_CHANNEL, &amp;quot;Aha&amp;quot;); // Will be said.&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The order of precedence of boolean operators is unclear. It is possible that there is a [http://jira.secondlife.com/browse/SVC-779 bug] in the expression parser, making precedence inconsistent, or it may simply be that &#039;&#039;&#039;||&#039;&#039;&#039; and &#039;&#039;&#039;&amp;amp;&amp;amp;&#039;&#039;&#039; have equal precedence; testing is inconclusive. Thus, when in doubt, parenthesize.&lt;br /&gt;
&#039;&#039;&#039;SubNote:&#039;&#039;&#039; As the above bug has been closed as expected behavior, one can only assume the boolean operators have equal precedence.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The order of evaluation appears to be backwards from most languages.  If the value of x starts as 1 then the first two conditions below evaluate false and the second two evaluate true:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;(x &amp;amp;&amp;amp; (x = 0) == 0 &amp;amp;&amp;amp; x)&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;(x &amp;amp;&amp;amp; (x = 0) == 0 &amp;amp;&amp;amp; x == 0)&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;(x == 0 &amp;amp;&amp;amp; (x = 0) == 0)&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;(x == 0 &amp;amp;&amp;amp; (x = 0) == 0 &amp;amp;&amp;amp; x)&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both sides are evaluated regardless of the the truth of either side.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Equality test on lists does not compare contents, only the length.&lt;br /&gt;
{| {{Prettytable}}&lt;br /&gt;
|+&lt;br /&gt;
==+ Operator==&lt;br /&gt;
&amp;lt;code&amp;gt;result = left + right&amp;lt;/code&amp;gt;&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Left Type&lt;br /&gt;
!Right Type&lt;br /&gt;
!Result Type&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|integer&lt;br /&gt;
|integer&lt;br /&gt;
|integer&lt;br /&gt;
|Adds &#039;&#039;&#039;left&#039;&#039;&#039; and &#039;&#039;&#039;right&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|integer&lt;br /&gt;
|float&lt;br /&gt;
|float&lt;br /&gt;
|Adds &#039;&#039;&#039;left&#039;&#039;&#039; and &#039;&#039;&#039;right&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|float&lt;br /&gt;
|integer&lt;br /&gt;
|float&lt;br /&gt;
|Adds &#039;&#039;&#039;left&#039;&#039;&#039; and &#039;&#039;&#039;right&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|string&lt;br /&gt;
|string&lt;br /&gt;
|string&lt;br /&gt;
|Concatenates &#039;&#039;&#039;right&#039;&#039;&#039; onto the end of &#039;&#039;&#039;left&#039;&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|*&lt;br /&gt;
|list&lt;br /&gt;
|Concatenates &#039;&#039;&#039;right&#039;&#039;&#039; onto the end of &#039;&#039;&#039;left&#039;&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|*&lt;br /&gt;
|list&lt;br /&gt;
|list&lt;br /&gt;
|Affixes &#039;&#039;&#039;left&#039;&#039;&#039; onto the start of &#039;&#039;&#039;right&#039;&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|vector&lt;br /&gt;
|vector&lt;br /&gt;
|vector&lt;br /&gt;
|Adds &#039;&#039;&#039;left&#039;&#039;&#039; and &#039;&#039;&#039;right&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rotation&lt;br /&gt;
|rotation&lt;br /&gt;
|rotation&lt;br /&gt;
|Adds &#039;&#039;&#039;left&#039;&#039;&#039; and &#039;&#039;&#039;right&#039;&#039;&#039;&amp;lt;br/&amp;gt;Not useful for combining rotations, use [[#* Operator|*]] or [[#/ Operator|/]] instead.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| {{Prettytable}}&lt;br /&gt;
|+&lt;br /&gt;
==Shorthand Operators==&lt;br /&gt;
Alternatives to the simple &#039;=&#039; operator...&lt;br /&gt;
|-{{Hl2}}&lt;br /&gt;
!Simple assignment operator&lt;br /&gt;
!Shorthand operator&lt;br /&gt;
|-&lt;br /&gt;
|a = a + 1&lt;br /&gt;
|a += 1&lt;br /&gt;
|-&lt;br /&gt;
|a = a – 1&lt;br /&gt;
|a -= 1&lt;br /&gt;
|-&lt;br /&gt;
|a = a * (n+1)&lt;br /&gt;
|a *= (n+1)&lt;br /&gt;
|-&lt;br /&gt;
|a = a / (n+1)&lt;br /&gt;
|a /= (n+1)&lt;br /&gt;
|-&lt;br /&gt;
|a = a % b&lt;br /&gt;
|a %= b&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=={{Wikipedia|De Morgan&#039;s laws|w=n}}==&lt;br /&gt;
{| {{Prettytable|style=margin-top:0; float:left;}}&lt;br /&gt;
|+ Bitwise Equivalencies&lt;br /&gt;
!AND&lt;br /&gt;
!OR&lt;br /&gt;
|-&lt;br /&gt;
|| &amp;lt;code&amp;gt;~(a &amp;amp; b)&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;~a &amp;amp;#124; ~b&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|| &amp;lt;code&amp;gt;~a &amp;amp; ~b&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;~(a &amp;amp;#124; b)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; |&lt;br /&gt;
|-&lt;br /&gt;
|| &amp;lt;code&amp;gt;a &amp;amp; ~b&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;~(~a &amp;amp;#124; b)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|| &amp;lt;code&amp;gt;~(a &amp;amp; ~b)&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;~a &amp;amp;#124; b&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
{| {{Prettytable|style=margin-top:0; float:left;}}&lt;br /&gt;
|+ Boolean Equivalencies&lt;br /&gt;
!AND&lt;br /&gt;
!OR&lt;br /&gt;
|-&lt;br /&gt;
|| &amp;lt;code&amp;gt;!(a &amp;amp;&amp;amp; b)&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;!a &amp;amp;#124;&amp;amp;#124; !b&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|| &amp;lt;code&amp;gt;!a &amp;amp;&amp;amp; !b&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;!(a &amp;amp;#124;&amp;amp;#124; b)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; |&lt;br /&gt;
|-&lt;br /&gt;
|| &amp;lt;code&amp;gt;a &amp;amp;&amp;amp; !b&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;!(!a &amp;amp;#124;&amp;amp;#124; b)&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|| &amp;lt;code&amp;gt;!(a &amp;amp;&amp;amp; !b)&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;!a &amp;amp;#124;&amp;amp;#124; b&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
Due to {{Wikipedia|De Morgan&#039;s laws|w=n}}, by row, code in the &#039;&#039;&#039;AND&#039;&#039;&#039; column is logically equivalent to code in the &#039;&#039;&#039;OR&#039;&#039;&#039;. &#039;&#039;&#039;a&#039;&#039;&#039; and &#039;&#039;&#039;b&#039;&#039;&#039; need not be variables, they can be expressions. In certain circumstances these equivalencies can be used to simplify complex code. It is important not to confuse the two sets when using them. The first two rows depict De Morgan&#039;s laws as it is formulated, the second two build upon it.&lt;br /&gt;
&lt;br /&gt;
{{LSLC|}}{{LSLC|Syntax}}{{LSLC|Keywords}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LlRequestSimulatorData&amp;diff=1197255</id>
		<title>LlRequestSimulatorData</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LlRequestSimulatorData&amp;diff=1197255"/>
		<updated>2015-08-22T15:27:37Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: Unit for length&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|inject-2={{Issues/SVC-2596}}{{Issues/SVC-4921}}{{Issues/BUG-5031}}&lt;br /&gt;
|func_id=293|func_sleep=1.0|func_energy=10.0&lt;br /&gt;
|func=llRequestSimulatorData&lt;br /&gt;
|return_type=key&lt;br /&gt;
|return_subtype=handle&lt;br /&gt;
|p1_type=string|p1_name=region|p1_desc=Case sensitive region name.&lt;br /&gt;
|p2_type=integer|p2_name=data|p2_desc=DATA_* flag&lt;br /&gt;
|func_footnote&lt;br /&gt;
|func_desc=Requests {{LSLP|data}} about {{LSLP|region}}. When {{LSLP|data}} is available the {{LSLG|dataserver}} event will be raised.&lt;br /&gt;
|return_text=for a {{LSLG|dataserver}} event response.&lt;br /&gt;
|spec&lt;br /&gt;
|caveats=&lt;br /&gt;
*There is no DATA_SIM_TYPE or DATA_SIM_MAXPRIMS flags. [[#SVC-4921|SVC-4921]]&lt;br /&gt;
|constants={{{!}} {{Prettytable|style=margin-top:0;}}&lt;br /&gt;
{{!}}- {{Hl2}}&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; {{!}} {{LSL Param|data}} Constant&lt;br /&gt;
! Type&lt;br /&gt;
! colspan=&amp;quot;4&amp;quot; {{!}} Description&lt;br /&gt;
{{!}}-&lt;br /&gt;
{{LSL_Constants/llRequestedSimulatorData}}&lt;br /&gt;
{{!}}}&lt;br /&gt;
|examples=Hide objects in PG or unknown regions&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
key         gRateingQuery       =   NULL_KEY        ;&lt;br /&gt;
&lt;br /&gt;
show()&lt;br /&gt;
{&lt;br /&gt;
    llSetLinkAlpha( LINK_SET, 1.0, ALL_SIDES );&lt;br /&gt;
}//show&lt;br /&gt;
&lt;br /&gt;
hide()&lt;br /&gt;
{&lt;br /&gt;
     llSetLinkAlpha( LINK_SET, 0.0, ALL_SIDES );&lt;br /&gt;
}//hide&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    on_rez(integer Setting)&lt;br /&gt;
    {&lt;br /&gt;
        llResetScript();&lt;br /&gt;
    }//on_rez&lt;br /&gt;
    &lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        gRateingQuery = llRequestSimulatorData( llGetRegionName(), DATA_SIM_RATING );&lt;br /&gt;
    }//state_entry&lt;br /&gt;
   &lt;br /&gt;
    changed(integer ItChanged)&lt;br /&gt;
    {&lt;br /&gt;
        if (ItChanged &amp;amp; CHANGED_OWNER)      llResetScript();&lt;br /&gt;
        if (ItChanged &amp;amp; CHANGED_REGION)     llResetScript();&lt;br /&gt;
    }//changed&lt;br /&gt;
    &lt;br /&gt;
    dataserver(key query_id, string data)&lt;br /&gt;
    {&lt;br /&gt;
        if (query_id == gRateingQuery)&lt;br /&gt;
        {&lt;br /&gt;
            if (data == &amp;quot;MATURE&amp;quot; || data == &amp;quot;ADULT&amp;quot;)        show();&lt;br /&gt;
            else if (data == &amp;quot;UNKNOWN&amp;quot; || data == &amp;quot;PG&amp;quot;)     hide();&lt;br /&gt;
        }//gRateingQuery&lt;br /&gt;
    }//dataserver&lt;br /&gt;
    &lt;br /&gt;
}//default&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_functions=&lt;br /&gt;
{{LSL DefineRow||[[llGetParcelDetails]]|}}&lt;br /&gt;
{{LSL DefineRow||[[llGetParcelFlags]]|}}&lt;br /&gt;
{{LSL DefineRow||[[llGetParcelMaxPrims]]|}}&lt;br /&gt;
{{LSL DefineRow||[[llGetParcelPrimCount]]|}}&lt;br /&gt;
|also_tests=&lt;br /&gt;
{{LSL DefineRow||[[llRequestSimulatorData Test]]}}&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles&lt;br /&gt;
|notes=Global Position in meters&lt;br /&gt;
|issues&lt;br /&gt;
|cat1=Dataserver&lt;br /&gt;
|cat2=Region&lt;br /&gt;
|cat3&lt;br /&gt;
|cat4&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LlInstantMessage&amp;diff=1195595</id>
		<title>LlInstantMessage</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LlInstantMessage&amp;diff=1195595"/>
		<updated>2015-02-18T18:07:52Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|inject-2={{Issues/SVC-92}}{{LSL_Function/avatar|user}}{{LSL_Function/chat||message}}&lt;br /&gt;
|func_id=118|func_sleep=2.0|func_energy=10.0&lt;br /&gt;
|func=llInstantMessage&lt;br /&gt;
|p1_type=key|p1_name=user|p1_desc&lt;br /&gt;
|p2_type=string|p2_name=message|p2_desc&lt;br /&gt;
|func_desc=Sends an Instant Message specified in the string {{LSLP|message}} to the user specified by {{LSLP|user}}.&lt;br /&gt;
|func_footer=To send a message directly to an object, use [[llRegionSayTo]].&lt;br /&gt;
|return_text&lt;br /&gt;
|spec&lt;br /&gt;
|caveats=&lt;br /&gt;
* All object IM&#039;s are throttled at a maximum of 2500 per 30mins, per owner, per region in a rolling window. this includes IM&#039;s sent after the throttle is in place&lt;br /&gt;
** Throttled IM&#039;s are dropped. for implementation see [[llInstantMessage#notes|notes]] below&lt;br /&gt;
* Messages longer than 1175 bytes will be truncated to 1175 bytes. This can convey 1175 ASCII characters, or fewer if non-ASCII characters are present.&lt;br /&gt;
{{KBcaution|width=100%|The 1175 byte limit is changing. As of Feb 26th, 2013 in all sims, Instant messages are now truncated to 1023 bytes to prevent certain types of delivery failure. (see https://wiki.secondlife.com/wiki/Release_Notes/Second_Life_Server/13#13.02.15.270481 ).}}&lt;br /&gt;
*{{LSLP|message}} will appear in the chat window and will not logged by the InstantMessage logging facility. (If a the specified user is not signed in, the messages will be delivered to their email just like a regular instant message, if the user has enabled email for their account.)&lt;br /&gt;
&lt;br /&gt;
|examples=Tell the owner somebody touched the object:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    touch_start( integer total_num )&lt;br /&gt;
    {        &lt;br /&gt;
        llInstantMessage( llGetOwner(), &amp;quot;Someone touched me&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
Send an IM to a detected avatar only&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    touch_start( integer total_num )&lt;br /&gt;
    {&lt;br /&gt;
        llInstantMessage( llDetectedKey(0), &amp;quot;Hands Off!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_functions=&lt;br /&gt;
{{LSL DefineRow||[[llOwnerSay]]|Sends chat region wide to owner}}&lt;br /&gt;
{{LSL DefineRow||[[llRegionSay]]|Sends chat region wide}}&lt;br /&gt;
{{LSL DefineRow||[[llRegionSayTo]]|Sends chat region wide to a specific prim/avatar}}&lt;br /&gt;
{{LSL DefineRow||[[llWhisper]]|Sends chat limited to 10 meters}}&lt;br /&gt;
{{LSL DefineRow||[[llSay]]|Sends chat limited to 20 meters}}&lt;br /&gt;
{{LSL DefineRow||[[llShout]]|Sends chat limited to 100 meters}}&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_articles&lt;br /&gt;
|also_events&lt;br /&gt;
|notes=&lt;br /&gt;
* [[llRegionSayTo]] may be a better choice if the target is in the same region as the object sending the message, as it has no built-in delay and can communicate directly with objects, as well as with avatars and their attachments.&lt;br /&gt;
* Instant Messaging allows communication from an object to an avatar anywhere on the Grid. However, an object cannot receive an Instant Message. &lt;br /&gt;
* Using [[llInstantMessage]] from one or more child scripts will avoid delays in the main script. Child scripts will still be subject to delays, [[LSL Event Queue|message queue]] limits, and region throttles.&lt;br /&gt;
* Throttling Implementation (Kelly Linden):&lt;br /&gt;
** The throttle is on all IMs from the object owner. It does not disable all IMs in the region, but does disable all IMs from the owner of the object.&lt;br /&gt;
** The throttle is not per object, but per owner. Splitting the spamming object into multiple objects will not help unless owned by different people. This also means that owning multiple almost too spammy objects will cause you to hit the limit.&lt;br /&gt;
** 2500 IMs in 30 minutes will trigger the block.&lt;br /&gt;
** IMs that are blocked continue to count against the throttle. The IM count must drop below 2500 before any IMs will be delivered.&lt;br /&gt;
** The IM count of the previous window is used to approximate the rolling window. If it is 20% into the current window the IM count will be the current count + 80% of the previous count. This allows us to approximate a rolling average, however it has the behavior that a flood of IMs can have an effect on the throttle for double the window length. This is why in practice the throttle behaves more like 5k in 1hr than 2.5k in 30min.&lt;br /&gt;
&lt;br /&gt;
|cat1=Communications&lt;br /&gt;
|cat2=Instant Message&lt;br /&gt;
|cat3&lt;br /&gt;
|cat4&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/talking_die&amp;diff=1194412</id>
		<title>User:Dora Gustafson/talking die</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/talking_die&amp;diff=1194412"/>
		<updated>2015-01-22T20:57:37Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: /* The Talking Die script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header}}&lt;br /&gt;
==The Talking Die script==&lt;br /&gt;
Place this script in a cube and you have a Die.&amp;lt;br&amp;gt;&lt;br /&gt;
The Die will say how many pips are on the upward face, after the Die is tossed.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
/////&lt;br /&gt;
//  The talking Die script, studio Dora, Dora Gustafson 2008&lt;br /&gt;
//  v1.20 Basics&lt;br /&gt;
/////&lt;br /&gt;
//  Place this script in a cube and you have a Die.&lt;br /&gt;
//  The Die will say how many pips are up after it is tossed.&lt;br /&gt;
//  Free ware! feel free to utilize this script&lt;br /&gt;
//    and texture, partially or as a whole&lt;br /&gt;
//  Please give credit to the creator: Dora Gustafson&lt;br /&gt;
//  You can do that by keeping this header unchanged&lt;br /&gt;
/////&lt;br /&gt;
&lt;br /&gt;
list pr;&lt;br /&gt;
string dieTexture = &amp;quot;b88d3ced-e298-83d7-7da6-e130a337b6ac&amp;quot;; // terning 2x6 SD.png&lt;br /&gt;
&lt;br /&gt;
string pips_up()&lt;br /&gt;
{&lt;br /&gt;
    vector u = llRot2Fwd( llGetRot() );&lt;br /&gt;
    vector v = llRot2Left( llGetRot() );&lt;br /&gt;
    vector w = llRot2Up( llGetRot() );&lt;br /&gt;
&lt;br /&gt;
    // Vectors associated with die pip numbers&lt;br /&gt;
    list pips_list = [ u.z, 1, -u.z, 6, v.z, 2, -v.z, 5, w.z, 3, -w.z, 4 ];&lt;br /&gt;
    // sort for the one with the biggest Z (vertical up) component,&lt;br /&gt;
    // the associated pip number is upward&lt;br /&gt;
    return llList2String( llListSort( pips_list, 2, FALSE ), 1 );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetPrimitiveParams([&lt;br /&gt;
        PRIM_TEXTURE, 0, dieTexture, &amp;lt; 0.5, 0.333, 0.0&amp;gt;, &amp;lt; 0.75, -0.333, 0.0&amp;gt;, 0.0,&lt;br /&gt;
        PRIM_TEXTURE, 1, dieTexture, &amp;lt; 0.5, 0.333, 0.0&amp;gt;, &amp;lt; -0.75, 0.0, 0.0&amp;gt;, 0.0,&lt;br /&gt;
        PRIM_TEXTURE, 2, dieTexture, &amp;lt; 0.5, 0.333, 0.0&amp;gt;, &amp;lt; 0.75, 0.333, 0.0&amp;gt;, 0.0,&lt;br /&gt;
        PRIM_TEXTURE, 3, dieTexture, &amp;lt; 0.5, 0.333, 0.0&amp;gt;, &amp;lt; 0.75, 0.0, 0.0&amp;gt;, 0.0,&lt;br /&gt;
        PRIM_TEXTURE, 4, dieTexture, &amp;lt; 0.5, 0.333, 0.0&amp;gt;, &amp;lt; -0.75, 0.333, 0.0&amp;gt;, 0.0,&lt;br /&gt;
        PRIM_TEXTURE, 5, dieTexture, &amp;lt; 0.5, 0.333, 0.0&amp;gt;, &amp;lt; -0.75, -0.333, 0.0&amp;gt;, 0.0 ]);&lt;br /&gt;
        llSetStatus( STATUS_PHYSICS, TRUE );&lt;br /&gt;
        llSetBuoyancy( 0.5 );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    collision_start(integer n)&lt;br /&gt;
    {&lt;br /&gt;
        llSetTimerEvent( 2.0 );&lt;br /&gt;
        pr = llGetPrimitiveParams([PRIM_POSITION, PRIM_ROTATION ]);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    land_collision_start(vector v) &lt;br /&gt;
    {&lt;br /&gt;
        llSetTimerEvent( 2.0 );&lt;br /&gt;
        pr = llGetPrimitiveParams([PRIM_POSITION, PRIM_ROTATION ]);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    timer()&lt;br /&gt;
    {&lt;br /&gt;
        list prnu = llGetPrimitiveParams([PRIM_POSITION, PRIM_ROTATION ]);&lt;br /&gt;
        if ( pr == prnu )&lt;br /&gt;
        {&lt;br /&gt;
            llSetTimerEvent( 0.0 );&lt;br /&gt;
            llWhisper( PUBLIC_CHANNEL, pips_up() + &amp;quot; pips&amp;quot; );&lt;br /&gt;
        }&lt;br /&gt;
        else pr = prnu;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/llAxes2Rot_right_and_wrong&amp;diff=1194410</id>
		<title>User:Dora Gustafson/llAxes2Rot right and wrong</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/llAxes2Rot_right_and_wrong&amp;diff=1194410"/>
		<updated>2015-01-22T20:56:34Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: /* llAxes2Rot right and wrong */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header}}&lt;br /&gt;
==llAxes2Rot right and wrong==&lt;br /&gt;
Does it matter if all three vectors are mutually orthogonal unit vectors?&amp;lt;br&amp;gt;&lt;br /&gt;
I made a test script to satisfy my own curiosity:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
key model;&lt;br /&gt;
integer tog=0;&lt;br /&gt;
vector lookat;&lt;br /&gt;
&lt;br /&gt;
rotation Vec2RotBastard( vector V )&lt;br /&gt;
{&lt;br /&gt;
    vector UP = &amp;lt; 0.0, 0.0, 1.0 &amp;gt;;&lt;br /&gt;
    vector LEFT = llVecNorm(UP%V);&lt;br /&gt;
    return llAxes2Rot(V, LEFT, UP);&lt;br /&gt;
    // demand for orthogonal, unit vectors is not fulfilled in general:&lt;br /&gt;
    // V is a unit vector in special cases only&lt;br /&gt;
    // UP and V are orthogonal in special cases only&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
rotation Vec2RotNorm( vector V )&lt;br /&gt;
{&lt;br /&gt;
    V = llVecNorm( V );&lt;br /&gt;
    vector UP = &amp;lt; 0.0, 0.0, 1.0 &amp;gt;;&lt;br /&gt;
    vector LEFT = llVecNorm(UP%V);&lt;br /&gt;
    return llAxes2Rot(V, LEFT, UP);&lt;br /&gt;
    // demand for orthogonal vectors is not fulfilled in general:&lt;br /&gt;
    // UP and V are orthogonal in special cases only&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
rotation Vec2RotTrue( vector V )&lt;br /&gt;
{&lt;br /&gt;
    V = llVecNorm( V );&lt;br /&gt;
    vector UP = &amp;lt; 0.0, 0.0, 1.0 &amp;gt;;&lt;br /&gt;
    vector LEFT = llVecNorm(UP%V);&lt;br /&gt;
    UP = llVecNorm(V%LEFT); // you want to keep the direction of V&lt;br /&gt;
    return llAxes2Rot(V, LEFT, UP);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
rotation Vec2RotHor( vector V )&lt;br /&gt;
{&lt;br /&gt;
    V = llVecNorm( V );&lt;br /&gt;
    vector UP = &amp;lt; 0.0, 0.0, 1.0 &amp;gt;;&lt;br /&gt;
    vector LEFT = llVecNorm(UP%V);&lt;br /&gt;
    V = llVecNorm(LEFT%UP); // you want V confined to the horizontal plane&lt;br /&gt;
    return llAxes2Rot(V, LEFT, UP);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    touch_end(integer n)&lt;br /&gt;
    {&lt;br /&gt;
        llSetTimerEvent( 4.0 );&lt;br /&gt;
        model = llDetectedKey(0);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    timer()&lt;br /&gt;
    {&lt;br /&gt;
        lookat = llList2Vector( llGetObjectDetails( model, [OBJECT_POS]), 0 );&lt;br /&gt;
        if ( lookat != ZERO_VECTOR )&lt;br /&gt;
        {&lt;br /&gt;
            if ( !tog )&lt;br /&gt;
            {&lt;br /&gt;
                llSetColor ( &amp;lt;1.0, 0.2, 0.0&amp;gt;, ALL_SIDES );&lt;br /&gt;
                llSetRot( Vec2RotBastard( lookat - llGetPos()));&lt;br /&gt;
            }&lt;br /&gt;
            else if ( tog == 1 )&lt;br /&gt;
            {&lt;br /&gt;
                llSetColor ( &amp;lt;1.0, 1.0, 0.0&amp;gt;, ALL_SIDES );&lt;br /&gt;
                llSetRot( Vec2RotNorm( lookat - llGetPos()));&lt;br /&gt;
            }&lt;br /&gt;
            else if ( tog == 2 )&lt;br /&gt;
            {&lt;br /&gt;
                llSetColor ( &amp;lt;0.4, 1.0, 0.0&amp;gt;, ALL_SIDES );&lt;br /&gt;
                llSetRot( Vec2RotTrue( lookat - llGetPos()));&lt;br /&gt;
            }&lt;br /&gt;
            else if ( tog == 3 )&lt;br /&gt;
            {&lt;br /&gt;
                llSetColor ( &amp;lt;0.0, 0.6, 1.0&amp;gt;, ALL_SIDES );&lt;br /&gt;
                llSetRot( Vec2RotHor( lookat - llGetPos()));&lt;br /&gt;
            }&lt;br /&gt;
            tog = ++tog % 4;&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            llSetColor ( &amp;lt;0.0, 0.0, 0.0&amp;gt;, ALL_SIDES );&lt;br /&gt;
            llSetTimerEvent( 0.0 );&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
How to use:&lt;br /&gt;
rezz a prim say x,y,z = 5.0, 0.2, 0.2 meters, put he script in and touch the prim.&lt;br /&gt;
It will point you for 4 sec with each routine in turn.&lt;br /&gt;
Move around and fly up to see where the prim will point.&amp;lt;br&amp;gt;&lt;br /&gt;
Each routine will color the prim its own color:&lt;br /&gt;
* Red: &amp;quot;Bastard&amp;quot; routine, Not unit and not orthogonal.&lt;br /&gt;
* Yellow: &amp;quot;Norm&amp;quot; routine, unit vectors but not orthogonal.&lt;br /&gt;
* Green: &amp;quot;True&amp;quot; routine, true direction, the demands are met.&lt;br /&gt;
* Blue: &amp;quot;Hor&amp;quot; routine, direction in the horizontal plane only, the demands are met.&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/point_tracker&amp;diff=1194409</id>
		<title>User:Dora Gustafson/point tracker</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/point_tracker&amp;diff=1194409"/>
		<updated>2015-01-22T20:55:10Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div id=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
== KFM Key framed Motion forward on a closed track ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
// point tracker script by Dora Gustafson, Studio Dora 2011&lt;br /&gt;
// The objct follows a path given by a number of points beginning with the object&#039;s position == &amp;lt;0,0,0&amp;gt;&lt;br /&gt;
// The path is closed so it ends where it begins&lt;br /&gt;
// Points prim&#039;s X-axis forward along the path and it&#039;s Y-axis is always horizontal&lt;br /&gt;
// v1.01 simplified for focus&lt;br /&gt;
// v1.02 with &#039;refFrame&#039; like in vehicles, to change what is forward&lt;br /&gt;
// Translation divided in a straight one and one including a rotation&lt;br /&gt;
// Object forward can either be horizontal or follow path forward up and down&lt;br /&gt;
// v1.02.1 For WIKI. RefFrame inverted. Track is relative to where script is reset&lt;br /&gt;
&lt;br /&gt;
float speed=2.0; // m/S&lt;br /&gt;
float straight=0.75; // part to travel without turning. 0.0 &amp;lt;= straight &amp;lt; 1.0&lt;br /&gt;
integer horz=FALSE; // TRUE object forward horizontal no matter if the track goes up or down&lt;br /&gt;
list track=[&amp;lt;0,0,0&amp;gt;,&amp;lt;4,0,0&amp;gt;,&amp;lt;4,5,2&amp;gt;,&amp;lt;0,5,2&amp;gt;]; // list of points to track; must have at least 2 elements&lt;br /&gt;
rotation refFrame=&amp;lt;0.0, 0.0, 0.0, 1.0&amp;gt;;&lt;br /&gt;
list KFMlist;&lt;br /&gt;
vector basePos;&lt;br /&gt;
integer i;&lt;br /&gt;
integer j;&lt;br /&gt;
integer k;&lt;br /&gt;
integer L;&lt;br /&gt;
vector U;&lt;br /&gt;
vector V;&lt;br /&gt;
vector W;&lt;br /&gt;
vector LEFT=&amp;lt; 0.0, 1.0, 0.0 &amp;gt;;&lt;br /&gt;
&lt;br /&gt;
rotation Vec2Rot( vector FWD )&lt;br /&gt;
{&lt;br /&gt;
    FWD = llVecNorm( FWD );&lt;br /&gt;
    vector UP = &amp;lt; 0.0, 0.0, 1.0 &amp;gt;;&lt;br /&gt;
    if ( llFabs(FWD.z) &amp;lt; 1.0 ) LEFT = llVecNorm(UP%FWD);&lt;br /&gt;
    if (horz) FWD = llVecNorm(LEFT%UP);&lt;br /&gt;
    else UP = llVecNorm(FWD%LEFT);&lt;br /&gt;
    return llAxes2Rot(FWD, LEFT, UP);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]); // make client mesh-aware&lt;br /&gt;
        refFrame.s = -refFrame.s;&lt;br /&gt;
        basePos = llGetPos();&lt;br /&gt;
        L = llGetListLength(track);&lt;br /&gt;
        KFMlist = [];&lt;br /&gt;
        for ( i=0; i&amp;lt;L; i++)&lt;br /&gt;
        {&lt;br /&gt;
            j = (i+1) % L;&lt;br /&gt;
            V = llList2Vector( track, j)-llList2Vector( track, i);&lt;br /&gt;
            U = straight*V;&lt;br /&gt;
            KFMlist += [U, ZERO_ROTATION, 0.1+llVecMag(U)/speed];&lt;br /&gt;
            k = (j+1) % L;&lt;br /&gt;
            W = llList2Vector( track, k)-llList2Vector( track, j);&lt;br /&gt;
            KFMlist += [V-U, refFrame*Vec2Rot(W)/(refFrame*Vec2Rot(V)), 0.1+llVecMag(V-U)/speed];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    touch_end(integer n)&lt;br /&gt;
    {&lt;br /&gt;
        llSetPrimitiveParams([PRIM_POSITION, basePos, PRIM_ROTATION, refFrame*Vec2Rot(llList2Vector( track, 1)-llList2Vector( track, 0))]);&lt;br /&gt;
        llSetKeyframedMotion( KFMlist, []);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Basic_Resizer&amp;diff=1194408</id>
		<title>User:Dora Gustafson/Basic Resizer</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Basic_Resizer&amp;diff=1194408"/>
		<updated>2015-01-22T20:54:01Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===The purpose is to resize a linkset/object using a single script===&lt;br /&gt;
The script is simple and does not meet special requests, but it can be used and it will work in big attached objects, like flexi skirts and prim hair as well as in non attached builds.&amp;lt;br&amp;gt;&lt;br /&gt;
The script can resize large link sets. It is small and doesn&#039;t keep long lists.&amp;lt;br&amp;gt;&lt;br /&gt;
It will take up 14000 bytes when compiled for MONO and 16 Kbytes when compiled for LSO&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;// resize script by Dora Gustafson, Studio Dora 2010&lt;br /&gt;
// Free for anybody to read, copy, modify, compile, use, rip apart, trample on and flush&lt;br /&gt;
// The script is open source and free. As so it is not supported in any way&lt;br /&gt;
// NOTE: only for SL server v1.38 and later&lt;br /&gt;
// Place in prim or linkset in order to resize&lt;br /&gt;
// Must run in root prim&lt;br /&gt;
// resizer v1.0 No check or precautions against dimensions out of limits&lt;br /&gt;
// resizer v1.1 Test if new dimensions are within limts [0.01;10.0]m If not, resize is cancelled&lt;br /&gt;
// resizer v1.2 Added kill script button&lt;br /&gt;
// resizer v1.3 Added llListenRemove() for low lag&lt;br /&gt;
// resizer v1.4 Added Current relative size display&lt;br /&gt;
// resizer v1.5 Added rounding for size display&lt;br /&gt;
// resizer v1.6 Reversible resize increments&lt;br /&gt;
// resizer v1.7 changed to accept 64m max prim size, limits [0.01;64.0]m&lt;br /&gt;
// resizer v1.8 minimized memory impact when compiled for mono&lt;br /&gt;
&lt;br /&gt;
integer dialogChanal;&lt;br /&gt;
list USER_MENU = [ &amp;quot;Size@Rez&amp;quot;, &amp;quot;Size@Buy&amp;quot;, &amp;quot;Kill Script&amp;quot;, &amp;quot;-1.96..%&amp;quot;, &amp;quot;-4.76..%&amp;quot;, &amp;quot;-9.09..%&amp;quot;, &amp;quot;+2%&amp;quot;, &amp;quot;+5%&amp;quot;, &amp;quot;+10%&amp;quot; ];&lt;br /&gt;
string uDialogP = &amp;quot;•Resize\n•Set to Size at Rez\n•Set to Size at Buy&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
float fabsizeX;&lt;br /&gt;
float rezsizeX;&lt;br /&gt;
vector rs;&lt;br /&gt;
float listenTimeout=1800.0; // seconds&lt;br /&gt;
integer listenHandle;&lt;br /&gt;
&lt;br /&gt;
open_dialog( vector vr )&lt;br /&gt;
{&lt;br /&gt;
    string s=&amp;quot;Size is &amp;quot;+(string)(llRound(100.0*vr.x/fabsizeX))+&amp;quot; %\n&amp;quot;;&lt;br /&gt;
    llDialog( llGetOwner(), s+uDialogP, USER_MENU, dialogChanal);&lt;br /&gt;
    llSetTimerEvent(listenTimeout);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
integer dimTest( vector vr )&lt;br /&gt;
{&lt;br /&gt;
    return !( vr.x&amp;lt;0.01 || vr.y&amp;lt;0.01 || vr.z&amp;lt;0.01 || vr.x&amp;gt;64.0 || vr.y&amp;gt;64.0 || vr.z&amp;gt;64.0 );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
primloop( float scal )&lt;br /&gt;
{&lt;br /&gt;
    integer primindx;&lt;br /&gt;
    integer validDim=TRUE;&lt;br /&gt;
    list primP;&lt;br /&gt;
&lt;br /&gt;
    if (llGetNumberOfPrims()&amp;lt;2) validDim = validDim &amp;amp;&amp;amp; dimTest( scal*llGetScale());&lt;br /&gt;
    else&lt;br /&gt;
    for ( primindx = 1; primindx &amp;lt;= llGetNumberOfPrims(); primindx++ )&lt;br /&gt;
    {&lt;br /&gt;
        primP = llGetLinkPrimitiveParams( primindx, [PRIM_SIZE]);&lt;br /&gt;
        validDim = validDim &amp;amp;&amp;amp; dimTest( scal*llList2Vector( primP, 0 ));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ( validDim )&lt;br /&gt;
    {&lt;br /&gt;
        if (llGetNumberOfPrims()&amp;lt;2) llSetScale( scal*llGetScale()); // not linked prim&lt;br /&gt;
        else&lt;br /&gt;
        for ( primindx = 1; primindx &amp;lt;= llGetNumberOfPrims(); primindx++ )&lt;br /&gt;
        {&lt;br /&gt;
            primP = llGetLinkPrimitiveParams( primindx, [PRIM_SIZE, PRIM_POSITION]);&lt;br /&gt;
            vector primScale = scal*llList2Vector( primP, 0 );&lt;br /&gt;
            vector primPos = scal*(llList2Vector( primP, 1 )-llGetPos());&lt;br /&gt;
            if ( primindx == 1 ) llSetLinkPrimitiveParamsFast( primindx, [PRIM_SIZE, primScale]);&lt;br /&gt;
            else llSetLinkPrimitiveParamsFast( primindx, [PRIM_SIZE, primScale, PRIM_POSITION, primPos/llGetRootRotation()]);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else llOwnerSay(&amp;quot;No resize! Out of limit sizes are not accepted&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetMemoryLimit(14000); // memory required&lt;br /&gt;
        rs = llGetScale();&lt;br /&gt;
        fabsizeX = rs.x;&lt;br /&gt;
        rezsizeX = fabsizeX;&lt;br /&gt;
        llOwnerSay(&amp;quot;Size at buy is set to Current size&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    on_rez( integer p)&lt;br /&gt;
    {&lt;br /&gt;
        rs = llGetScale();&lt;br /&gt;
        rezsizeX = rs.x;&lt;br /&gt;
    }&lt;br /&gt;
    touch_end(integer n)&lt;br /&gt;
    {&lt;br /&gt;
        if (llDetectedKey(0) == llGetOwner())&lt;br /&gt;
        {&lt;br /&gt;
            dialogChanal = (integer)llFrand( 8388608.0 ) + 0x80000000;&lt;br /&gt;
            llListenRemove(listenHandle);&lt;br /&gt;
            listenHandle = llListen( dialogChanal, &amp;quot;&amp;quot;, llGetOwner(), &amp;quot;&amp;quot;);&lt;br /&gt;
            open_dialog(llGetScale());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    listen(integer cannel, string name, key id, string message)&lt;br /&gt;
    {&lt;br /&gt;
        if ( message == &amp;quot;Kill Script&amp;quot; ) llRemoveInventory( llGetScriptName());&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            rs = llGetScale();&lt;br /&gt;
            if ( message == &amp;quot;+2%&amp;quot; ) primloop( 1.02);&lt;br /&gt;
            else if ( message == &amp;quot;+5%&amp;quot; ) primloop( 1.05);&lt;br /&gt;
            else if ( message == &amp;quot;+10%&amp;quot; ) primloop( 1.1);&lt;br /&gt;
            else if ( message == &amp;quot;-1.96..%&amp;quot; ) primloop( 1.0/1.02);&lt;br /&gt;
            else if ( message == &amp;quot;-4.76..%&amp;quot; ) primloop( 1.0/1.05);&lt;br /&gt;
            else if ( message == &amp;quot;-9.09..%&amp;quot; ) primloop( 1.0/1.1);&lt;br /&gt;
            else if ( message == &amp;quot;Size@Rez&amp;quot; ) primloop( rezsizeX/rs.x);&lt;br /&gt;
            else if ( message == &amp;quot;Size@Buy&amp;quot; ) primloop( fabsizeX/rs.x);&lt;br /&gt;
            open_dialog(llGetScale());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    timer()&lt;br /&gt;
    {&lt;br /&gt;
        llListenRemove(listenHandle);&lt;br /&gt;
        llSetTimerEvent(0.0);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/sundirection_and_time_of_day&amp;diff=1194406</id>
		<title>User:Dora Gustafson/sundirection and time of day</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/sundirection_and_time_of_day&amp;diff=1194406"/>
		<updated>2015-01-22T20:52:42Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header}}{{LSLC|Library}}&lt;br /&gt;
&amp;lt;div id=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
== Show Sun Direction and compare to Time of Day ==&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding: 0.5em;&amp;quot;&amp;gt;&lt;br /&gt;
Conclusion when compared to the &#039;&#039;Windlight default day cycle&#039;&#039;:&lt;br /&gt;
* When the SunDirection vector is confined to the X-Z plane(Ecliptic) the result matches fairly well what is seen.&lt;br /&gt;
* The moon direction is not always opposite the sun direction.&lt;br /&gt;
* When the east point in Windlight is moved the SunDirection vector doesn&#039;t move with it. &lt;br /&gt;
* The often used method of using the Z component to separate day from night is very rough. Sunset and sunrise are both (equivalent)hours from where the sign of Z changes.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
// sun pointer script by Dora Gustafson, Studio Dora 2012&lt;br /&gt;
// Will point the prim&#039;s FWD in the SunDirection&lt;br /&gt;
// Will show the SunDirection vector and the equivalent real day hour&lt;br /&gt;
// vertical ecliptic matches the default day cycle sun in windlight&lt;br /&gt;
&lt;br /&gt;
float sd_Rate=10.0;&lt;br /&gt;
integer vertical=TRUE; // vertical ecliptic&lt;br /&gt;
&lt;br /&gt;
rotation Vec2Rot( vector FWD )&lt;br /&gt;
{&lt;br /&gt;
    FWD = llVecNorm( FWD );&lt;br /&gt;
    vector UP = &amp;lt; 0.0, 1.0, 0.0 &amp;gt;;&lt;br /&gt;
    vector LEFT = llVecNorm(UP%FWD);&lt;br /&gt;
    if (vertical) FWD = llVecNorm(LEFT%UP);&lt;br /&gt;
    else UP = llVecNorm(FWD%LEFT);&lt;br /&gt;
    return llAxes2Rot(FWD, LEFT, UP);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetTimerEvent(sd_Rate);&lt;br /&gt;
    }&lt;br /&gt;
    timer()&lt;br /&gt;
    {&lt;br /&gt;
        llSetRot( Vec2Rot( llGetSunDirection()));&lt;br /&gt;
        float secs = 6.0*llGetTimeOfDay(); // multiply by 6 to show the equivalent real day hour&lt;br /&gt;
        integer minutes = ((integer)secs/60)%60;&lt;br /&gt;
        integer hours = (integer)secs/3600;&lt;br /&gt;
        llSetText(&amp;quot;Sundirection: &amp;quot;+(string)llGetSunDirection()+&amp;quot;\nSim Time: &amp;quot;+(string)hours+&amp;quot;H &amp;quot;+(string)minutes+&amp;quot;M&amp;quot;, &amp;lt;1.0,1.0,1.0&amp;gt;, 1.0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/universal_hinged_motion&amp;diff=1194404</id>
		<title>User:Dora Gustafson/universal hinged motion</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/universal_hinged_motion&amp;diff=1194404"/>
		<updated>2015-01-22T20:51:27Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Universal hinged motion in 8 key frames ==&lt;br /&gt;
Using [[LlSetKeyframedMotion|llSetKeyFramedMotion()]]&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
// Universal hinged motion by Dora Gustafson, Studio Dora 2012&lt;br /&gt;
// will turn a box prim around one edge parallel to the prim&#039;s Y-axis&lt;br /&gt;
// for any prim orientation&lt;br /&gt;
// note that the smallest accepted time per frame is 1/9=0.11111111 and NOT 0.1&lt;br /&gt;
// v1.03 tuned for wiki&lt;br /&gt;
// v1.04 time tuning&lt;br /&gt;
&lt;br /&gt;
float angleEnd=PI_BY_TWO;&lt;br /&gt;
float speed=0.2; // m/S&lt;br /&gt;
float steps=8.0; // number of Key Frames&lt;br /&gt;
float step=0.0;&lt;br /&gt;
list KFMlist=[];&lt;br /&gt;
vector V;&lt;br /&gt;
integer open=TRUE;&lt;br /&gt;
vector basePos;&lt;br /&gt;
rotation baseRot;&lt;br /&gt;
&lt;br /&gt;
float motion_time( float mt)&lt;br /&gt;
{&lt;br /&gt;
    mt = llRound(45.0*mt)/45.0;&lt;br /&gt;
    if ( mt &amp;gt; 0.11111111 ) return mt;&lt;br /&gt;
    else return 0.11111111;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetMemoryLimit(0x2000);&lt;br /&gt;
        llOwnerSay((string)llGetFreeMemory());&lt;br /&gt;
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);&lt;br /&gt;
        basePos = llGetPos();&lt;br /&gt;
        baseRot = llGetRot();&lt;br /&gt;
        vector v1 = 0.5*llGetScale()*llGetRot();&lt;br /&gt;
        rotation deltaRot = llEuler2Rot(&amp;lt; 0.0, angleEnd/steps, 0.0&amp;gt;);&lt;br /&gt;
        while ( step &amp;lt; steps )&lt;br /&gt;
        {&lt;br /&gt;
            V = v1*llAxisAngle2Rot(llRot2Left(llGetRot()), angleEnd*step/steps);&lt;br /&gt;
            V = v1*llAxisAngle2Rot(llRot2Left(llGetRot()), angleEnd*(step+1.0)/steps) - V;&lt;br /&gt;
            KFMlist += [V, deltaRot, motion_time(llVecMag(V)/speed)];&lt;br /&gt;
            step += 1.0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    touch_end( integer n)&lt;br /&gt;
    {&lt;br /&gt;
        llSetKeyframedMotion( [], []);&lt;br /&gt;
        if ( open )&lt;br /&gt;
        {&lt;br /&gt;
            llSetPrimitiveParams([PRIM_POSITION, basePos, PRIM_ROTATION, baseRot]);&lt;br /&gt;
            llSetKeyframedMotion( KFMlist, []);&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            llSetKeyframedMotion( KFMlist, [KFM_MODE, KFM_REVERSE]);&lt;br /&gt;
        }&lt;br /&gt;
        open = !open;&lt;br /&gt;
    }&lt;br /&gt;
    on_rez( integer n) { llResetScript(); }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
After editing prim position, rotation and/or size the script should be reset in order to update the motion&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Pendulum_motion&amp;diff=1194401</id>
		<title>User:Dora Gustafson/Pendulum motion</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Pendulum_motion&amp;diff=1194401"/>
		<updated>2015-01-22T20:50:23Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div id=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
==Simple Pendulum Motion in 24 Key Frames==&lt;br /&gt;
=====Swing script=====&lt;br /&gt;
Will swing a prim like a simple pendulum pivoting at an axis parallel to the prim&#039;s Y-axis&amp;lt;br&amp;gt;&lt;br /&gt;
The pivot axis will be at the top of a prim with the Z-axis pointing up&amp;lt;br&amp;gt;&lt;br /&gt;
 Quote from [http://en.wikipedia.org/wiki/Pendulum_(mathematics) Wikipedia]&lt;br /&gt;
 A simple pendulum is an idealization of a real pendulum using the following assumptions:&lt;br /&gt;
 The rod or cord on which the bob swings is massless, inextensible and always remains taut;&lt;br /&gt;
 Motion occurs only in two dimensions, i.e. the bob does not trace an ellipse but an arc.&lt;br /&gt;
 The motion does not lose energy to friction or air resistance.&lt;br /&gt;
The periode time increase with the Z dimension (the pendulum length)...&amp;lt;br&amp;gt;&lt;br /&gt;
If it is too small the motion will not be well because of the time limitation with Key Framed Motions&amp;lt;br&amp;gt;&lt;br /&gt;
The parameters set in the script works nice with a 3m long pendulum&amp;lt;br&amp;gt;&lt;br /&gt;
If the pendulum is moved, rotated or resized the script must be reset to update the motion&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
// Pendulum motion by Dora Gustafson, Studio Dora 2012&lt;br /&gt;
// Will swing a prim like a simple pendulum pivoting at an axis parallel to the prim&#039;s Y-axis&lt;br /&gt;
// The pivot axis will be at the top of a prim with the Z-axis pointing up&lt;br /&gt;
// Quote from http://en.wikipedia.org/wiki/Pendulum_(mathematics)&lt;br /&gt;
// • A simple pendulum is an idealization of a real pendulum using the following assumptions:&lt;br /&gt;
// • The rod or cord on which the bob swings is massless, inextensible and always remains taut;&lt;br /&gt;
// • Motion occurs only in two dimensions, i.e. the bob does not trace an ellipse but an arc.&lt;br /&gt;
// • The motion does not lose energy to friction or air resistance.&lt;br /&gt;
// The periode time increase with the Z dimension (the pendulum length)...&lt;br /&gt;
// If it is too small the motion will not be well because of the time limitation with Key Framed Motions&lt;br /&gt;
// The parameters set in the script works nice with a 3m long pendulum&lt;br /&gt;
// If the pendulum is moved, rotated or resized the script must be reset to update the motion&lt;br /&gt;
&lt;br /&gt;
float angle=0.2; // max swing from resting (radians)&lt;br /&gt;
float steps=24.0; // number of Key Frames&lt;br /&gt;
float step=0.0;&lt;br /&gt;
list KFMlist=[];&lt;br /&gt;
vector U;&lt;br /&gt;
vector V;&lt;br /&gt;
float angleU=0.0;&lt;br /&gt;
float angleV;&lt;br /&gt;
integer swing=TRUE;&lt;br /&gt;
vector basePos;&lt;br /&gt;
rotation baseRot;&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetMemoryLimit( llGetUsedMemory()+0x1000);&lt;br /&gt;
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);&lt;br /&gt;
        basePos = llGetPos();&lt;br /&gt;
        baseRot = llGetRot();&lt;br /&gt;
        vector v1 = llGetScale();&lt;br /&gt;
        float periode = TWO_PI*llSqrt( v1.z/9.81);&lt;br /&gt;
        float dT = periode/steps;&lt;br /&gt;
        dT = llRound(45.0*dT)/45.0;&lt;br /&gt;
        if ( dT &amp;lt; 0.11111111 ) dT = 0.11111111;&lt;br /&gt;
        v1.x = 0.0;&lt;br /&gt;
        v1.y = 0.0;&lt;br /&gt;
        v1 = -0.5*v1*llGetRot();&lt;br /&gt;
        U = v1;&lt;br /&gt;
        while ( step &amp;lt; steps )&lt;br /&gt;
        {&lt;br /&gt;
            step += 1.0;&lt;br /&gt;
            angleV = angle*llCos( TWO_PI*step/steps + PI_BY_TWO);&lt;br /&gt;
            V = v1*llAxisAngle2Rot(llRot2Left(llGetRot()), angleV);&lt;br /&gt;
            KFMlist += [V-U, llEuler2Rot(&amp;lt; 0.0, angleV-angleU, 0.0&amp;gt;), dT];&lt;br /&gt;
            angleU = angleV;&lt;br /&gt;
            U = V;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    touch_start( integer n)&lt;br /&gt;
    {&lt;br /&gt;
        llSetKeyframedMotion( [], []);&lt;br /&gt;
        llSleep(0.2);&lt;br /&gt;
        llSetPrimitiveParams([PRIM_POSITION, basePos, PRIM_ROTATION, baseRot]);&lt;br /&gt;
        if ( swing ) llSetKeyframedMotion( KFMlist, [ KFM_MODE, KFM_LOOP]);&lt;br /&gt;
        swing = !swing;&lt;br /&gt;
    }&lt;br /&gt;
    on_rez( integer n) { llResetScript(); }&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Harmonic_Oscillator_motion&amp;diff=1194399</id>
		<title>User:Dora Gustafson/Harmonic Oscillator motion</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Harmonic_Oscillator_motion&amp;diff=1194399"/>
		<updated>2015-01-22T20:49:13Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div id=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
==Harmonic oscillator motion in 12 Key Frames==&lt;br /&gt;
Will oscillate a prim along a straight line in space&amp;lt;br&amp;gt;&lt;br /&gt;
Only the first half period is computed, the second is the first in reverse&amp;lt;br&amp;gt;&lt;br /&gt;
If the prim is moved or scaled the script must be reset to update the motion&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
// Harmonic oscillator motion by Dora Gustafson, Studio Dora 2012&lt;br /&gt;
// will oscillate a prim along a straight line in space&lt;br /&gt;
// only the first half period is computed, the second is the first in reverse&lt;br /&gt;
&lt;br /&gt;
float phase=PI;&lt;br /&gt;
vector amplitude=&amp;lt; 0.0, 0.0, 2.0&amp;gt;; // amplitude and direction for oscillation&lt;br /&gt;
float Hperiode=2.0; // half periode time S&lt;br /&gt;
float steps=12; // number of Key Frames for a half periode&lt;br /&gt;
float step=0.0;&lt;br /&gt;
list KFMlist=[];&lt;br /&gt;
vector U;&lt;br /&gt;
vector V;&lt;br /&gt;
integer osc=TRUE;&lt;br /&gt;
vector basePos;&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetMemoryLimit( llGetUsedMemory()+0x1000);&lt;br /&gt;
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);&lt;br /&gt;
        basePos = llGetPos();&lt;br /&gt;
        float dT = Hperiode/steps;&lt;br /&gt;
        dT = llRound(45.0*dT)/45.0;&lt;br /&gt;
        if ( dT &amp;lt; 0.11111111 ) dT = 0.11111111;&lt;br /&gt;
        U = amplitude*llCos( phase);&lt;br /&gt;
        while ( step &amp;lt; steps )&lt;br /&gt;
        {&lt;br /&gt;
            step += 1.0;&lt;br /&gt;
            V = amplitude*llCos( PI*step/steps + phase);&lt;br /&gt;
            KFMlist += [V-U, dT];&lt;br /&gt;
            U = V;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    touch_start( integer n)&lt;br /&gt;
    {&lt;br /&gt;
        llSetKeyframedMotion( [], []);&lt;br /&gt;
        llSleep(0.2);&lt;br /&gt;
        llSetRegionPos( basePos);&lt;br /&gt;
        llSetPos( basePos);&lt;br /&gt;
        if ( osc ) llSetKeyframedMotion( KFMlist, [KFM_DATA, KFM_TRANSLATION, KFM_MODE, KFM_PING_PONG]);&lt;br /&gt;
        osc = !osc;&lt;br /&gt;
    }&lt;br /&gt;
    on_rez( integer n) { llResetScript(); }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/captureCameraView&amp;diff=1194398</id>
		<title>User:Dora Gustafson/captureCameraView</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/captureCameraView&amp;diff=1194398"/>
		<updated>2015-01-22T20:48:03Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: /* Capture Camera View */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div id=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
==llSetLinkCamera() Example==&lt;br /&gt;
=====Capture Camera View=====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
// camera capture/release test, script by Dora Gustafson, Studio Dora 2012&lt;br /&gt;
// v1.1&lt;br /&gt;
// save script in prim&lt;br /&gt;
// sit on the prim&lt;br /&gt;
// move camera&lt;br /&gt;
// touch the prim to capture camera view or release capture&lt;br /&gt;
&lt;br /&gt;
integer gag = FALSE;&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSitTarget( &amp;lt; 0.25, 0.0, 0.6 &amp;gt;, ZERO_ROTATION);&lt;br /&gt;
        llSetClickAction(CLICK_ACTION_SIT);&lt;br /&gt;
        llOwnerSay(&amp;quot;To verify: stand up, press Esc, sit down and try to move the camera by the arrow keys&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    touch_end(integer num)&lt;br /&gt;
    {&lt;br /&gt;
        gag = !gag;&lt;br /&gt;
        if (gag) llRequestPermissions( llGetOwner(), PERMISSION_TRACK_CAMERA);&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            llSetLinkCamera( LINK_THIS, ZERO_VECTOR, ZERO_VECTOR);&lt;br /&gt;
            llOwnerSay(&amp;quot;Capture released&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    run_time_permissions(integer perm)&lt;br /&gt;
    {&lt;br /&gt;
        if( perm &amp;amp; PERMISSION_TRACK_CAMERA)&lt;br /&gt;
        {&lt;br /&gt;
            rotation cam_rot=llGetCameraRot()/llGetRot(); // relative camera rotation&lt;br /&gt;
            vector cam_pos=(llGetCameraPos()-llGetPos())/llGetRot(); // relative camera position&lt;br /&gt;
            llSetLinkCamera( LINK_THIS, cam_pos, cam_pos + llRot2Fwd(cam_rot));&lt;br /&gt;
            llOwnerSay(&amp;quot;Camera view captured&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/llRotBetween_alternatives&amp;diff=1194397</id>
		<title>User:Dora Gustafson/llRotBetween alternatives</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/llRotBetween_alternatives&amp;diff=1194397"/>
		<updated>2015-01-22T20:46:07Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: /* Scripts and functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div id=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
==llRotBetween, some alternatives and considerations==&lt;br /&gt;
=====Scope=====&lt;br /&gt;
Four functions are covered, They are&lt;br /&gt;
# llRotBetween( vector a, vector b); // The built in function&lt;br /&gt;
# RotBetween( vector a, vector b); // The replacement outlined in the wiki&lt;br /&gt;
# rotV2V( vector a, vector b); // The shortest replacement&lt;br /&gt;
# rotbetween( vector a, vector b); // Using a &#039;&#039;Vector to rotation&#039;&#039; function&lt;br /&gt;
&lt;br /&gt;
=====Tests=====&lt;br /&gt;
First the rotations provided by functions were compared and they didn&#039;t compare at all.&lt;br /&gt;
: Testing rotations is a bad idea since there is no single solution to the question, but an infinite number of solutions.&lt;br /&gt;
: All 4 functions provide valid, but different rotations.&lt;br /&gt;
So the sensible thing to do is to test how the solution rotates a vector:&lt;br /&gt;
&lt;br /&gt;
== Test with random, normalized vectors ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
cycles = 0;&lt;br /&gt;
record = [];&lt;br /&gt;
while ( cycles++ &amp;lt; nLimit &amp;amp;&amp;amp; llGetListLength( record) &amp;lt; 30)&lt;br /&gt;
{&lt;br /&gt;
    u = llVecNorm(&amp;lt; llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 &amp;gt;);&lt;br /&gt;
    v = llVecNorm(&amp;lt; llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 &amp;gt;);&lt;br /&gt;
    solution = rotbetween( u, v);&lt;br /&gt;
    if ( llVecDist( u*solution, v) &amp;gt; epsilon ) record += [cycles, u, v];&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 800px;&amp;quot; border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
 cellspacing=&amp;quot;2&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;2&amp;quot;&amp;gt;Errors / test cycles&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 1&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 2&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 3&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 4&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;llRotBetween&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;RotBetween&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;rotV2V&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;rotbetween&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;3&amp;quot;&amp;gt;abs error &amp;amp;gt; 1e-7&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 13&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 18&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 15&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 16&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 14&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 21&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 22&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 23&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 27&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt;10 / 14&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 13&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;3&amp;quot;&amp;gt;abs error &amp;amp;gt; 1e-6&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 7 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 3 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 1 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 8 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test with close to parallel and anti parallel vectors ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
cycles = 0;&lt;br /&gt;
record = [];&lt;br /&gt;
while ( cycles++ &amp;lt; nLimit &amp;amp;&amp;amp; llGetListLength( record) &amp;lt; 30)&lt;br /&gt;
{&lt;br /&gt;
    u = llVecNorm(&amp;lt; llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 &amp;gt;);&lt;br /&gt;
    v = &amp;lt; llFrand( 2E-3)-1E-3, llFrand( 2E-3)-1E-3, llFrand( 2E-3)-1E-3 &amp;gt;;&lt;br /&gt;
    if ( llFrand(1.0) &amp;lt; 0.5 ) v -= u;&lt;br /&gt;
    else v += u;&lt;br /&gt;
    solution = rotbetween( u, v);&lt;br /&gt;
    if ( llVecDist( u*solution, v) &amp;gt; epsilon ) record += [cycles, u, v];&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 800px;&amp;quot; border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
 cellspacing=&amp;quot;2&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;2&amp;quot;&amp;gt;Errors / test cycles&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 1&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 2&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 3&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 4&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;llRotBetween&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;RotBetween&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;rotV2V&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;rotbetween&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;3&amp;quot;&amp;gt;abs error &amp;amp;gt; 1e-3&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 16&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 98&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 222&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 192&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 15&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 96&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 89&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 164&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 27&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 109&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt;10 / 99&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 75&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;2&amp;quot;&amp;gt;abs error &amp;amp;gt; 1e-2&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Functions 2, 3 and 4 have similar performances.&lt;br /&gt;
Function 1, the built-in, has a lower performance.&amp;lt;br&amp;gt;&lt;br /&gt;
All four functions are very good except with parallel and anti parallel vectors.&amp;lt;br&amp;gt;&lt;br /&gt;
The rotation found is not always what you expect.&amp;lt;br&amp;gt;&lt;br /&gt;
: The rotation will point a vector in the right direction, i.e. the rotation&#039;s &#039;&#039;forward&#039;&#039; is the vector direction.&lt;br /&gt;
: See [[User:Dora_Gustafson/llRotBetween_alternatives#About_the_function.27s_nature|note]] about the functions nature&lt;br /&gt;
: Function 4 is different, the solution will map a rotation with &#039;&#039;left&#039;&#039; in the horizontal plane&lt;br /&gt;
&lt;br /&gt;
== Scripts and functions ==&lt;br /&gt;
;Function 1, llRotBetween( vector a, vector b)&lt;br /&gt;
: This is the built in function, see [[LlRotBetween|llRotBetween]]&lt;br /&gt;
: See [[User:Dora_Gustafson/llRotBetween_alternatives#About_the_function.27s_nature|note]] about the functions nature&lt;br /&gt;
;Function 2, RotBetween( vector a, vector b)&lt;br /&gt;
: This is the suggested [[LlRotBetween#Replacement|Replacement]] for llRotBetween&lt;br /&gt;
: See [[User:Dora_Gustafson/llRotBetween_alternatives#About_the_function.27s_nature|note]] about the functions nature&lt;br /&gt;
;Function 3, rotV2V( vector a, vector b)&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;rotation rotV2V( vector a, vector b)&lt;br /&gt;
{&lt;br /&gt;
    a = llVecNorm(a);&lt;br /&gt;
    b = llVecNorm(b);&lt;br /&gt;
    vector c = b;&lt;br /&gt;
    while ( llFabs(a*c) &amp;gt; 0.999999 ) c = llVecNorm(&amp;lt; llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 &amp;gt;);&lt;br /&gt;
    c = llVecNorm(a%c);&lt;br /&gt;
    return ZERO_ROTATION/llAxes2Rot( a, c, a%c)*llAxes2Rot( b, c, b%c);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
: See [[User:Dora_Gustafson/llRotBetween_alternatives#About_the_function.27s_nature|note]] about the functions nature&lt;br /&gt;
&lt;br /&gt;
;Function 4, rotbetween( vector a, vector b)&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;rotation Vec2Rot( vector a)&lt;br /&gt;
{&lt;br /&gt;
    a = llVecNorm(a);&lt;br /&gt;
    vector  c = &amp;lt; 0.0, 0.0, 1.0 &amp;gt;;&lt;br /&gt;
    if ( llFabs(a*c) &amp;gt; 0.999999 ) c = llVecNorm(&amp;lt; llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, 0.0 &amp;gt;);&lt;br /&gt;
    vector b = llVecNorm(c%a);&lt;br /&gt;
    return llAxes2Rot( a, b, a%b);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
rotation rotbetween( vector a, vector b)&lt;br /&gt;
{&lt;br /&gt;
    return ZERO_ROTATION/Vec2Rot(a)*Vec2Rot(b);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
: Returns a solution that will map a rotation with &#039;&#039;left&#039;&#039; in the horizontal plane. This is convenient for cameras and prims you don&#039;t want tilted&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==About the function&#039;s nature==&lt;br /&gt;
The function determines a rotation (quaternion) which can map a vector onto another.&lt;br /&gt;
: It does nothing else, which means that there are no conditions on the other vectors associated with a rotation in space.&lt;br /&gt;
When the solution is used to rotate a body in space one should be aware of it’s nature.&lt;br /&gt;
: For a prim whose rotation is defined by three orthogonal vectors the forward vector mapping will be correct while the other vector mappings are unpredictable.&lt;br /&gt;
: A prim mapping will normally be rotated about the prim’s forward axis in an unpredictable way. &lt;br /&gt;
: The prim will be tilted to one side or the other side with respect to the vertical.&lt;br /&gt;
There are numerous solutions to the task of finding the rotation between two vectors and all are correct in the sense that they can correctly map one vector onto another.&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/llRotBetween_alternatives&amp;diff=1194396</id>
		<title>User:Dora Gustafson/llRotBetween alternatives</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/llRotBetween_alternatives&amp;diff=1194396"/>
		<updated>2015-01-22T20:44:09Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: /* Test with close to parallel and anti parallel vectors */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div id=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
==llRotBetween, some alternatives and considerations==&lt;br /&gt;
=====Scope=====&lt;br /&gt;
Four functions are covered, They are&lt;br /&gt;
# llRotBetween( vector a, vector b); // The built in function&lt;br /&gt;
# RotBetween( vector a, vector b); // The replacement outlined in the wiki&lt;br /&gt;
# rotV2V( vector a, vector b); // The shortest replacement&lt;br /&gt;
# rotbetween( vector a, vector b); // Using a &#039;&#039;Vector to rotation&#039;&#039; function&lt;br /&gt;
&lt;br /&gt;
=====Tests=====&lt;br /&gt;
First the rotations provided by functions were compared and they didn&#039;t compare at all.&lt;br /&gt;
: Testing rotations is a bad idea since there is no single solution to the question, but an infinite number of solutions.&lt;br /&gt;
: All 4 functions provide valid, but different rotations.&lt;br /&gt;
So the sensible thing to do is to test how the solution rotates a vector:&lt;br /&gt;
&lt;br /&gt;
== Test with random, normalized vectors ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
cycles = 0;&lt;br /&gt;
record = [];&lt;br /&gt;
while ( cycles++ &amp;lt; nLimit &amp;amp;&amp;amp; llGetListLength( record) &amp;lt; 30)&lt;br /&gt;
{&lt;br /&gt;
    u = llVecNorm(&amp;lt; llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 &amp;gt;);&lt;br /&gt;
    v = llVecNorm(&amp;lt; llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 &amp;gt;);&lt;br /&gt;
    solution = rotbetween( u, v);&lt;br /&gt;
    if ( llVecDist( u*solution, v) &amp;gt; epsilon ) record += [cycles, u, v];&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 800px;&amp;quot; border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
 cellspacing=&amp;quot;2&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;2&amp;quot;&amp;gt;Errors / test cycles&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 1&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 2&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 3&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 4&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;llRotBetween&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;RotBetween&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;rotV2V&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;rotbetween&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;3&amp;quot;&amp;gt;abs error &amp;amp;gt; 1e-7&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 13&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 18&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 15&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 16&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 14&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 21&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 22&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 23&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 27&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt;10 / 14&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 13&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;3&amp;quot;&amp;gt;abs error &amp;amp;gt; 1e-6&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 7 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 3 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 1 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 8 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test with close to parallel and anti parallel vectors ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
cycles = 0;&lt;br /&gt;
record = [];&lt;br /&gt;
while ( cycles++ &amp;lt; nLimit &amp;amp;&amp;amp; llGetListLength( record) &amp;lt; 30)&lt;br /&gt;
{&lt;br /&gt;
    u = llVecNorm(&amp;lt; llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 &amp;gt;);&lt;br /&gt;
    v = &amp;lt; llFrand( 2E-3)-1E-3, llFrand( 2E-3)-1E-3, llFrand( 2E-3)-1E-3 &amp;gt;;&lt;br /&gt;
    if ( llFrand(1.0) &amp;lt; 0.5 ) v -= u;&lt;br /&gt;
    else v += u;&lt;br /&gt;
    solution = rotbetween( u, v);&lt;br /&gt;
    if ( llVecDist( u*solution, v) &amp;gt; epsilon ) record += [cycles, u, v];&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 800px;&amp;quot; border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
 cellspacing=&amp;quot;2&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;2&amp;quot;&amp;gt;Errors / test cycles&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 1&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 2&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 3&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 4&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;llRotBetween&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;RotBetween&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;rotV2V&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;rotbetween&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;3&amp;quot;&amp;gt;abs error &amp;amp;gt; 1e-3&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 16&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 98&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 222&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 192&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 15&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 96&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 89&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 164&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 27&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 109&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt;10 / 99&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 75&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;2&amp;quot;&amp;gt;abs error &amp;amp;gt; 1e-2&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Functions 2, 3 and 4 have similar performances.&lt;br /&gt;
Function 1, the built-in, has a lower performance.&amp;lt;br&amp;gt;&lt;br /&gt;
All four functions are very good except with parallel and anti parallel vectors.&amp;lt;br&amp;gt;&lt;br /&gt;
The rotation found is not always what you expect.&amp;lt;br&amp;gt;&lt;br /&gt;
: The rotation will point a vector in the right direction, i.e. the rotation&#039;s &#039;&#039;forward&#039;&#039; is the vector direction.&lt;br /&gt;
: See [[User:Dora_Gustafson/llRotBetween_alternatives#About_the_function.27s_nature|note]] about the functions nature&lt;br /&gt;
: Function 4 is different, the solution will map a rotation with &#039;&#039;left&#039;&#039; in the horizontal plane&lt;br /&gt;
&lt;br /&gt;
== Scripts and functions ==&lt;br /&gt;
;Function 1, llRotBetween( vector a, vector b)&lt;br /&gt;
: This is the built in function, see [[LlRotBetween|llRotBetween]]&lt;br /&gt;
: See [[User:Dora_Gustafson/llRotBetween_alternatives#About_the_function.27s_nature|note]] about the functions nature&lt;br /&gt;
;Function 2, RotBetween( vector a, vector b)&lt;br /&gt;
: This is the suggested [[LlRotBetween#Replacement|Replacement]] for llRotBetween&lt;br /&gt;
: See [[User:Dora_Gustafson/llRotBetween_alternatives#About_the_function.27s_nature|note]] about the functions nature&lt;br /&gt;
;Function 3, rotV2V( vector a, vector b)&lt;br /&gt;
&amp;lt;lsl&amp;gt;rotation rotV2V( vector a, vector b)&lt;br /&gt;
{&lt;br /&gt;
    a = llVecNorm(a);&lt;br /&gt;
    b = llVecNorm(b);&lt;br /&gt;
    vector c = b;&lt;br /&gt;
    while ( llFabs(a*c) &amp;gt; 0.999999 ) c = llVecNorm(&amp;lt; llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 &amp;gt;);&lt;br /&gt;
    c = llVecNorm(a%c);&lt;br /&gt;
    return ZERO_ROTATION/llAxes2Rot( a, c, a%c)*llAxes2Rot( b, c, b%c);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
: See [[User:Dora_Gustafson/llRotBetween_alternatives#About_the_function.27s_nature|note]] about the functions nature&lt;br /&gt;
&lt;br /&gt;
;Function 4, rotbetween( vector a, vector b)&lt;br /&gt;
&amp;lt;lsl&amp;gt;rotation Vec2Rot( vector a)&lt;br /&gt;
{&lt;br /&gt;
    a = llVecNorm(a);&lt;br /&gt;
    vector  c = &amp;lt; 0.0, 0.0, 1.0 &amp;gt;;&lt;br /&gt;
    if ( llFabs(a*c) &amp;gt; 0.999999 ) c = llVecNorm(&amp;lt; llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, 0.0 &amp;gt;);&lt;br /&gt;
    vector b = llVecNorm(c%a);&lt;br /&gt;
    return llAxes2Rot( a, b, a%b);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
rotation rotbetween( vector a, vector b)&lt;br /&gt;
{&lt;br /&gt;
    return ZERO_ROTATION/Vec2Rot(a)*Vec2Rot(b);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
: Returns a solution that will map a rotation with &#039;&#039;left&#039;&#039; in the horizontal plane. This is convenient for cameras and prims you don&#039;t want tilted&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==About the function&#039;s nature==&lt;br /&gt;
The function determines a rotation (quaternion) which can map a vector onto another.&lt;br /&gt;
: It does nothing else, which means that there are no conditions on the other vectors associated with a rotation in space.&lt;br /&gt;
When the solution is used to rotate a body in space one should be aware of it’s nature.&lt;br /&gt;
: For a prim whose rotation is defined by three orthogonal vectors the forward vector mapping will be correct while the other vector mappings are unpredictable.&lt;br /&gt;
: A prim mapping will normally be rotated about the prim’s forward axis in an unpredictable way. &lt;br /&gt;
: The prim will be tilted to one side or the other side with respect to the vertical.&lt;br /&gt;
There are numerous solutions to the task of finding the rotation between two vectors and all are correct in the sense that they can correctly map one vector onto another.&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/llRotBetween_alternatives&amp;diff=1194395</id>
		<title>User:Dora Gustafson/llRotBetween alternatives</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/llRotBetween_alternatives&amp;diff=1194395"/>
		<updated>2015-01-22T20:43:30Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: /* Test with random, normalized vectors */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div id=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
==llRotBetween, some alternatives and considerations==&lt;br /&gt;
=====Scope=====&lt;br /&gt;
Four functions are covered, They are&lt;br /&gt;
# llRotBetween( vector a, vector b); // The built in function&lt;br /&gt;
# RotBetween( vector a, vector b); // The replacement outlined in the wiki&lt;br /&gt;
# rotV2V( vector a, vector b); // The shortest replacement&lt;br /&gt;
# rotbetween( vector a, vector b); // Using a &#039;&#039;Vector to rotation&#039;&#039; function&lt;br /&gt;
&lt;br /&gt;
=====Tests=====&lt;br /&gt;
First the rotations provided by functions were compared and they didn&#039;t compare at all.&lt;br /&gt;
: Testing rotations is a bad idea since there is no single solution to the question, but an infinite number of solutions.&lt;br /&gt;
: All 4 functions provide valid, but different rotations.&lt;br /&gt;
So the sensible thing to do is to test how the solution rotates a vector:&lt;br /&gt;
&lt;br /&gt;
== Test with random, normalized vectors ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
cycles = 0;&lt;br /&gt;
record = [];&lt;br /&gt;
while ( cycles++ &amp;lt; nLimit &amp;amp;&amp;amp; llGetListLength( record) &amp;lt; 30)&lt;br /&gt;
{&lt;br /&gt;
    u = llVecNorm(&amp;lt; llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 &amp;gt;);&lt;br /&gt;
    v = llVecNorm(&amp;lt; llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 &amp;gt;);&lt;br /&gt;
    solution = rotbetween( u, v);&lt;br /&gt;
    if ( llVecDist( u*solution, v) &amp;gt; epsilon ) record += [cycles, u, v];&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 800px;&amp;quot; border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
 cellspacing=&amp;quot;2&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;2&amp;quot;&amp;gt;Errors / test cycles&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 1&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 2&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 3&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 4&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;llRotBetween&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;RotBetween&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;rotV2V&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;rotbetween&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;3&amp;quot;&amp;gt;abs error &amp;amp;gt; 1e-7&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 13&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 18&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 15&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 16&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 14&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 21&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 22&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 23&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 27&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt;10 / 14&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 13&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;3&amp;quot;&amp;gt;abs error &amp;amp;gt; 1e-6&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 7 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 3 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 1 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 8 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Test with close to parallel and anti parallel vectors ==&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
cycles = 0;&lt;br /&gt;
record = [];&lt;br /&gt;
while ( cycles++ &amp;lt; nLimit &amp;amp;&amp;amp; llGetListLength( record) &amp;lt; 30)&lt;br /&gt;
{&lt;br /&gt;
    u = llVecNorm(&amp;lt; llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 &amp;gt;);&lt;br /&gt;
    v = &amp;lt; llFrand( 2E-3)-1E-3, llFrand( 2E-3)-1E-3, llFrand( 2E-3)-1E-3 &amp;gt;;&lt;br /&gt;
    if ( llFrand(1.0) &amp;lt; 0.5 ) v -= u;&lt;br /&gt;
    else v += u;&lt;br /&gt;
    solution = rotbetween( u, v);&lt;br /&gt;
    if ( llVecDist( u*solution, v) &amp;gt; epsilon ) record += [cycles, u, v];&lt;br /&gt;
}&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&amp;lt;table style=&amp;quot;width: 800px;&amp;quot; border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot;&lt;br /&gt;
 cellspacing=&amp;quot;2&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;2&amp;quot;&amp;gt;Errors / test cycles&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 1&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 2&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 3&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;Function 4&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;llRotBetween&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;RotBetween&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;rotV2V&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot;&amp;gt;rotbetween&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;3&amp;quot;&amp;gt;abs error &amp;amp;gt; 1e-3&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 16&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 98&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 222&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 192&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 15&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 96&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 89&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 164&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 27&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 109&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt;10 / 99&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 10 / 75&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th style=&amp;quot;text-align: center;&amp;quot; colspan=&amp;quot;1&amp;quot;&lt;br /&gt;
 rowspan=&amp;quot;2&amp;quot;&amp;gt;abs error &amp;amp;gt; 1e-2&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 1000&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td style=&amp;quot;text-align: right;&amp;quot;&amp;gt; 0 / 10000&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
Functions 2, 3 and 4 have similar performances.&lt;br /&gt;
Function 1, the built-in, has a lower performance.&amp;lt;br&amp;gt;&lt;br /&gt;
All four functions are very good except with parallel and anti parallel vectors.&amp;lt;br&amp;gt;&lt;br /&gt;
The rotation found is not always what you expect.&amp;lt;br&amp;gt;&lt;br /&gt;
: The rotation will point a vector in the right direction, i.e. the rotation&#039;s &#039;&#039;forward&#039;&#039; is the vector direction.&lt;br /&gt;
: See [[User:Dora_Gustafson/llRotBetween_alternatives#About_the_function.27s_nature|note]] about the functions nature&lt;br /&gt;
: Function 4 is different, the solution will map a rotation with &#039;&#039;left&#039;&#039; in the horizontal plane&lt;br /&gt;
&lt;br /&gt;
== Scripts and functions ==&lt;br /&gt;
;Function 1, llRotBetween( vector a, vector b)&lt;br /&gt;
: This is the built in function, see [[LlRotBetween|llRotBetween]]&lt;br /&gt;
: See [[User:Dora_Gustafson/llRotBetween_alternatives#About_the_function.27s_nature|note]] about the functions nature&lt;br /&gt;
;Function 2, RotBetween( vector a, vector b)&lt;br /&gt;
: This is the suggested [[LlRotBetween#Replacement|Replacement]] for llRotBetween&lt;br /&gt;
: See [[User:Dora_Gustafson/llRotBetween_alternatives#About_the_function.27s_nature|note]] about the functions nature&lt;br /&gt;
;Function 3, rotV2V( vector a, vector b)&lt;br /&gt;
&amp;lt;lsl&amp;gt;rotation rotV2V( vector a, vector b)&lt;br /&gt;
{&lt;br /&gt;
    a = llVecNorm(a);&lt;br /&gt;
    b = llVecNorm(b);&lt;br /&gt;
    vector c = b;&lt;br /&gt;
    while ( llFabs(a*c) &amp;gt; 0.999999 ) c = llVecNorm(&amp;lt; llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 &amp;gt;);&lt;br /&gt;
    c = llVecNorm(a%c);&lt;br /&gt;
    return ZERO_ROTATION/llAxes2Rot( a, c, a%c)*llAxes2Rot( b, c, b%c);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
: See [[User:Dora_Gustafson/llRotBetween_alternatives#About_the_function.27s_nature|note]] about the functions nature&lt;br /&gt;
&lt;br /&gt;
;Function 4, rotbetween( vector a, vector b)&lt;br /&gt;
&amp;lt;lsl&amp;gt;rotation Vec2Rot( vector a)&lt;br /&gt;
{&lt;br /&gt;
    a = llVecNorm(a);&lt;br /&gt;
    vector  c = &amp;lt; 0.0, 0.0, 1.0 &amp;gt;;&lt;br /&gt;
    if ( llFabs(a*c) &amp;gt; 0.999999 ) c = llVecNorm(&amp;lt; llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, 0.0 &amp;gt;);&lt;br /&gt;
    vector b = llVecNorm(c%a);&lt;br /&gt;
    return llAxes2Rot( a, b, a%b);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
rotation rotbetween( vector a, vector b)&lt;br /&gt;
{&lt;br /&gt;
    return ZERO_ROTATION/Vec2Rot(a)*Vec2Rot(b);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
: Returns a solution that will map a rotation with &#039;&#039;left&#039;&#039; in the horizontal plane. This is convenient for cameras and prims you don&#039;t want tilted&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==About the function&#039;s nature==&lt;br /&gt;
The function determines a rotation (quaternion) which can map a vector onto another.&lt;br /&gt;
: It does nothing else, which means that there are no conditions on the other vectors associated with a rotation in space.&lt;br /&gt;
When the solution is used to rotate a body in space one should be aware of it’s nature.&lt;br /&gt;
: For a prim whose rotation is defined by three orthogonal vectors the forward vector mapping will be correct while the other vector mappings are unpredictable.&lt;br /&gt;
: A prim mapping will normally be rotated about the prim’s forward axis in an unpredictable way. &lt;br /&gt;
: The prim will be tilted to one side or the other side with respect to the vertical.&lt;br /&gt;
There are numerous solutions to the task of finding the rotation between two vectors and all are correct in the sense that they can correctly map one vector onto another.&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/fixed_3D_relation&amp;diff=1194394</id>
		<title>User:Dora Gustafson/fixed 3D relation</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/fixed_3D_relation&amp;diff=1194394"/>
		<updated>2015-01-22T20:42:20Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Fixed 3D relation ==&lt;br /&gt;
Any prim in SL has a position and a rotation in space&amp;lt;br&amp;gt;&lt;br /&gt;
Two prims have a relative position and rotation between them&amp;lt;br&amp;gt;&lt;br /&gt;
The relative position and rotation is what I call the relation between the prims&amp;lt;br&amp;gt;&lt;br /&gt;
In scripting you often want to keep the relation after one or both prims have moved&amp;lt;br&amp;gt;&lt;br /&gt;
A typical example is to rez a prim with a fixed relation to the rezzing prim&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you know position and rotation for two prims the relation can be computed like this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
relativeRot = P2Rot / P1Rot;&lt;br /&gt;
relativePos = (P2Pos - P1Pos) / P1Rot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
When you know the relation and position and rotation for prim 1 you can compute position and rotation for prim 2 like this&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
P2Rot = relativeRot * P1Rot;&lt;br /&gt;
P2Pos = P1Pos + relativePos * P1Rot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Likewise you can compute position and rotation for prim 1 when they are known for prim 2&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
P1Rot = ZERO_ROTATION/relativeRot * P2Rot;&lt;br /&gt;
P1Pos = P2Pos - relativePos/relativeRot * P2Rot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/JSON_structure_facial_expression&amp;diff=1194393</id>
		<title>User:Dora Gustafson/JSON structure facial expression</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/JSON_structure_facial_expression&amp;diff=1194393"/>
		<updated>2015-01-22T20:39:24Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== JSON structured menu for all facial expressions ==&lt;br /&gt;
The script has 19 facial expressions that can be chosen from a menu&lt;br /&gt;
:The expressions can also be chosen by random and they can be played in a loop&lt;br /&gt;
:The script can be used in a pose ball or in an attached (HUD)prim&lt;br /&gt;
:When used for a pose ball the camera position is saved for next session&lt;br /&gt;
The script features a [[Json_usage_in_LSL|JSON structured]] dialog-menu&lt;br /&gt;
:In this case the menu has one main page and three child pages&lt;br /&gt;
:The power of JSON shows where the menu is decoded and in the navigation between menus. See the first lines in the listen event handler&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
// Pose ball and facial expressions, script by Dora Gustafson, Studio Dora 2012&lt;br /&gt;
// build on Basic pose ball script. by Dora Gustafson, Studio Dora 2010&lt;br /&gt;
// v1.00 Has 10 facial expressions that can be chosen from a menu, chosen by random,&lt;br /&gt;
// ... looped, has menu reopen and saves camera position&lt;br /&gt;
// v1.01 wearable. Sit on or attach&lt;br /&gt;
// v1.02 JSON structured dialog-menu with all 19 facial expressions&lt;br /&gt;
&lt;br /&gt;
// Define all menu names and menu button lay-outs&lt;br /&gt;
string mDisa = &amp;quot;Disapproval&amp;quot;;&lt;br /&gt;
list LDisa = [&amp;quot;Home&amp;quot;,&amp;quot;Open mouth&amp;quot;,&amp;quot;Disdain&amp;quot;,&amp;quot;Frown&amp;quot;,&amp;quot;Tongue out&amp;quot;,&amp;quot;Anger&amp;quot;,&amp;quot;Bored&amp;quot;];&lt;br /&gt;
string mChee = &amp;quot;Cheerful&amp;quot;;&lt;br /&gt;
list LChee = [&amp;quot;Home&amp;quot;,&amp;quot;Kiss&amp;quot;,&amp;quot;Smile&amp;quot;,&amp;quot;Toothsmile&amp;quot;,&amp;quot;Laugh&amp;quot;,&amp;quot;Surprise&amp;quot;,&amp;quot;Wink&amp;quot;];&lt;br /&gt;
string mMis = &amp;quot;Miserable&amp;quot;;&lt;br /&gt;
list LMis = [&amp;quot;Home&amp;quot;,&amp;quot;Worry&amp;quot;,&amp;quot;Afraid&amp;quot;,&amp;quot;Sad&amp;quot;,&amp;quot;Cry&amp;quot;,&amp;quot;Embarrassed&amp;quot;,&amp;quot;Repulsed&amp;quot;,&amp;quot;Shrug&amp;quot;];&lt;br /&gt;
string mHom = &amp;quot;Home&amp;quot;;&lt;br /&gt;
list LHom = [&amp;quot;Cheerful&amp;quot;,&amp;quot;Miserable&amp;quot;,&amp;quot;Disapproval&amp;quot;,&amp;quot;Loop&amp;quot;,&amp;quot;Random&amp;quot;];&lt;br /&gt;
&lt;br /&gt;
// strided list coupler button name and animation name. The order of strides doesn&#039;t matter&lt;br /&gt;
list coupling = [ &amp;quot;Afraid&amp;quot;, &amp;quot;express_afraid_emote&amp;quot;,&lt;br /&gt;
                 &amp;quot;Anger&amp;quot;, &amp;quot;express_anger_emote&amp;quot;,&lt;br /&gt;
                 &amp;quot;Bored&amp;quot;, &amp;quot;express_bored_emote&amp;quot;,&lt;br /&gt;
                 &amp;quot;Cry&amp;quot;, &amp;quot;express_cry_emote&amp;quot;,&lt;br /&gt;
                 &amp;quot;Disdain&amp;quot;, &amp;quot;express_disdain&amp;quot;,&lt;br /&gt;
                 &amp;quot;Embarrassed&amp;quot;, &amp;quot;express_embarrassed_emote&amp;quot;,&lt;br /&gt;
                 &amp;quot;Frown&amp;quot;, &amp;quot;express_frown&amp;quot;,&lt;br /&gt;
                 &amp;quot;Kiss&amp;quot;, &amp;quot;express_kiss&amp;quot;,&lt;br /&gt;
                 &amp;quot;Laugh&amp;quot;, &amp;quot;express_laugh_emote&amp;quot;,&lt;br /&gt;
                 &amp;quot;Open mouth&amp;quot;, &amp;quot;express_open_mouth&amp;quot;,&lt;br /&gt;
                 &amp;quot;Repulsed&amp;quot;, &amp;quot;express_repulsed_emote&amp;quot;,&lt;br /&gt;
                 &amp;quot;Sad&amp;quot;, &amp;quot;express_sad_emote&amp;quot;,&lt;br /&gt;
                 &amp;quot;Shrug&amp;quot;, &amp;quot;express_shrug_emote&amp;quot;,&lt;br /&gt;
                 &amp;quot;Smile&amp;quot;, &amp;quot;express_smile&amp;quot;,&lt;br /&gt;
                 &amp;quot;Surprise&amp;quot;, &amp;quot;express_surprise_emote&amp;quot;,&lt;br /&gt;
                 &amp;quot;Tongue out&amp;quot;, &amp;quot;express_tongue_out&amp;quot;,&lt;br /&gt;
                 &amp;quot;Toothsmile&amp;quot;, &amp;quot;express_toothsmile&amp;quot;,&lt;br /&gt;
                 &amp;quot;Wink&amp;quot;, &amp;quot;express_wink_emote&amp;quot;,&lt;br /&gt;
                 &amp;quot;Worry&amp;quot;, &amp;quot;express_worry_emote&amp;quot; ];&lt;br /&gt;
&lt;br /&gt;
string JSONMenu;&lt;br /&gt;
list BUTTONS;&lt;br /&gt;
key sitter;&lt;br /&gt;
integer dialogChanal=-532247677;&lt;br /&gt;
integer haandtag;&lt;br /&gt;
string menuHead;&lt;br /&gt;
integer act=0;&lt;br /&gt;
string Fanim = &amp;quot;stand&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        string s1 = llList2Json( JSON_ARRAY, LDisa);&lt;br /&gt;
        string s2 = llList2Json( JSON_ARRAY, LChee);&lt;br /&gt;
        string s3 = llList2Json( JSON_ARRAY, LMis);&lt;br /&gt;
        string s4 = llList2Json( JSON_ARRAY, LHom);&lt;br /&gt;
        JSONMenu = llList2Json( JSON_OBJECT, [mDisa, s1, mChee, s2, mMis, s3, mHom, s4]+coupling);&lt;br /&gt;
        BUTTONS = LHom ;&lt;br /&gt;
        llSitTarget( &amp;lt;0.0, 0.0, 1.0&amp;gt;, ZERO_ROTATION );&lt;br /&gt;
        llSetSitText(&amp;quot;Animate&amp;quot;);&lt;br /&gt;
        llSetClickAction(CLICK_ACTION_SIT);&lt;br /&gt;
    }&lt;br /&gt;
    attach(key id)&lt;br /&gt;
    {&lt;br /&gt;
        menuHead = llGetScriptName( )+&amp;quot;\nMemory in use: &amp;quot;+(string)llGetUsedMemory()+&amp;quot;\n\nChoose any of 19 facial expressions&amp;quot;;&lt;br /&gt;
        llSetClickAction(CLICK_ACTION_TOUCH);&lt;br /&gt;
        llSetTimerEvent( 0.0 );&lt;br /&gt;
        act = 0;&lt;br /&gt;
        if (id)&lt;br /&gt;
        {&lt;br /&gt;
            sitter = id;&lt;br /&gt;
            llRequestPermissions( sitter , PERMISSION_TRIGGER_ANIMATION);&lt;br /&gt;
        }&lt;br /&gt;
        else llListenRemove( haandtag);&lt;br /&gt;
    }&lt;br /&gt;
    changed(integer change)&lt;br /&gt;
    {&lt;br /&gt;
        menuHead = llGetScriptName( )+&amp;quot;\nMemory in use: &amp;quot;+(string)llGetUsedMemory()+&amp;quot;\n\n[Page Down] reopens this Dialog Menu\n\nChoose any of 19 facial expressions&amp;quot;;&lt;br /&gt;
        llSetTimerEvent( 0.0 );&lt;br /&gt;
        act = 0;&lt;br /&gt;
        if (change &amp;amp; CHANGED_LINK)&lt;br /&gt;
        {&lt;br /&gt;
            sitter = llAvatarOnSitTarget() ;&lt;br /&gt;
            if(sitter != NULL_KEY) llRequestPermissions( sitter , PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS | PERMISSION_TRACK_CAMERA);&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                if (llGetPermissions() &amp;amp; PERMISSION_TRIGGER_ANIMATION) llStopAnimation(Fanim);&lt;br /&gt;
                llSetAlpha(1.0, ALL_SIDES); // show prim&lt;br /&gt;
                llListenRemove( haandtag);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    run_time_permissions(integer perm)&lt;br /&gt;
    {&lt;br /&gt;
        if ( (perm &amp;amp; PERMISSION_TRIGGER_ANIMATION) &amp;amp;&amp;amp; (llAvatarOnSitTarget() != NULL_KEY) )&lt;br /&gt;
        {&lt;br /&gt;
            llSetAlpha(0.0, ALL_SIDES); // hide prim&lt;br /&gt;
            llStartAnimation(Fanim);&lt;br /&gt;
            llStopAnimation(&amp;quot;sit&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if ( perm &amp;amp; PERMISSION_TAKE_CONTROLS )&lt;br /&gt;
        {&lt;br /&gt;
            llTakeControls( CONTROL_DOWN , TRUE, TRUE);&lt;br /&gt;
            llListenRemove( haandtag);&lt;br /&gt;
            haandtag = llListen( dialogChanal, &amp;quot;&amp;quot;, sitter, &amp;quot;&amp;quot;);&lt;br /&gt;
            llDialog( sitter, menuHead, BUTTONS, dialogChanal);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    touch_end( integer num )&lt;br /&gt;
    {&lt;br /&gt;
        if ( llDetectedKey(0) == sitter )&lt;br /&gt;
        {&lt;br /&gt;
            llListenRemove( haandtag);&lt;br /&gt;
            haandtag = llListen( dialogChanal, &amp;quot;&amp;quot;, sitter, &amp;quot;&amp;quot;);&lt;br /&gt;
            llDialog( sitter, menuHead, BUTTONS, dialogChanal);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    control(key id, integer down, integer new)&lt;br /&gt;
    {&lt;br /&gt;
        if ( down &amp;amp; new &amp;amp; CONTROL_DOWN ) llDialog( sitter, menuHead, BUTTONS, dialogChanal);&lt;br /&gt;
    }&lt;br /&gt;
    listen( integer channel, string name, key id, string message)&lt;br /&gt;
    {&lt;br /&gt;
        if ( JSON_ARRAY == llJsonValueType( JSONMenu, [message])) BUTTONS = llParseString2List( llJsonGetValue( JSONMenu, [message]),[&amp;quot;,&amp;quot;,&amp;quot;[&amp;quot;,&amp;quot;]&amp;quot;,&amp;quot;\&amp;quot;&amp;quot;],[]);&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            if ( JSON_STRING == llJsonValueType( JSONMenu, [message])) Fanim = llJsonGetValue( JSONMenu, [message]);&lt;br /&gt;
            else if ( &amp;quot;Loop&amp;quot; == message )&lt;br /&gt;
            {&lt;br /&gt;
                act = act ^ 1;&lt;br /&gt;
                if ( act &amp;amp; 1 ) llSetTimerEvent( 3.0 );&lt;br /&gt;
                else llSetTimerEvent( 0.0 );&lt;br /&gt;
            }&lt;br /&gt;
            else if ( &amp;quot;Random&amp;quot; == message )&lt;br /&gt;
            {&lt;br /&gt;
                Fanim = llList2String( llListRandomize( coupling, 2), 1);&lt;br /&gt;
                act = act ^ 2;&lt;br /&gt;
            }&lt;br /&gt;
            if ( llGetPermissions() &amp;amp; PERMISSION_TRIGGER_ANIMATION) llStartAnimation( Fanim);&lt;br /&gt;
        }&lt;br /&gt;
        llDialog( sitter, menuHead, BUTTONS, dialogChanal);&lt;br /&gt;
        if( llGetPermissions() &amp;amp; PERMISSION_TRACK_CAMERA)&lt;br /&gt;
        {&lt;br /&gt;
            rotation cam_rot=llGetCameraRot()/llGetRot(); // relative camera rotation&lt;br /&gt;
            vector cam_pos=(llGetCameraPos()-llGetPos())/llGetRot(); // relative camera position&lt;br /&gt;
            llSetLinkCamera( LINK_THIS, cam_pos, cam_pos + llRot2Fwd(cam_rot));&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    timer()&lt;br /&gt;
    {&lt;br /&gt;
         if ( act &amp;amp; 2 ) Fanim = llList2String( llListRandomize( coupling, 2), 1);&lt;br /&gt;
         if ( llGetPermissions() &amp;amp; PERMISSION_TRIGGER_ANIMATION) llStartAnimation( Fanim);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/insertion_sort&amp;diff=1194392</id>
		<title>User:Dora Gustafson/insertion sort</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/insertion_sort&amp;diff=1194392"/>
		<updated>2015-01-22T20:37:04Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Straight insertion Sort ==&lt;br /&gt;
The effective straight insertion sort routine for LSL is included&lt;br /&gt;
: First is the most simplified edition&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
insertionSort()&lt;br /&gt;
{&lt;br /&gt;
    integer i;&lt;br /&gt;
    integer j;&lt;br /&gt;
    for ( i=1; i&amp;lt;llGetListLength(Lcrit); i++)&lt;br /&gt;
    {&lt;br /&gt;
        j=i;&lt;br /&gt;
        while ( llList2Integer( Lcrit, j-1)&amp;gt;llList2Integer( Lcrit, i) &amp;amp;&amp;amp; j&amp;gt;0) --j;&lt;br /&gt;
        if (j&amp;lt;i) Lcrit=llListReplaceList( Lcrit, llList2List( Lcrit, i, i)+llList2List( Lcrit, j, i-1), j, i);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
It will sort a list: Lcrit, of numbers in ascending order&amp;lt;br&amp;gt;&lt;br /&gt;
This simple edition can easily be expanded to sort parallel lists something that can&#039;t be done with the built in [[LlListSort|llListSort()]]&lt;br /&gt;
: Then a full version that can sort a strided list and take the same parameters as the built in [[LlListSort|llListSort()]] does&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
list insertionSort( list src, integer stride, integer ascending)&lt;br /&gt;
{&lt;br /&gt;
    integer i;&lt;br /&gt;
    integer j;&lt;br /&gt;
    integer k = llGetListLength(src);&lt;br /&gt;
    if (ascending) for ( i=stride; i&amp;lt;k; i+=stride)&lt;br /&gt;
    {&lt;br /&gt;
        j=i;&lt;br /&gt;
        while ( llList2Float( src, j-stride)&amp;gt;llList2Float( src, i) &amp;amp;&amp;amp; j&amp;gt;0) j -= stride;&lt;br /&gt;
        if (j&amp;lt;i) src=llListReplaceList( src, llList2List( src, i, i+stride-1)+llList2List( src, j, i-1), j, i+stride-1);&lt;br /&gt;
    }&lt;br /&gt;
    else for ( i=stride; i&amp;lt;k; i+=stride)&lt;br /&gt;
    {&lt;br /&gt;
        j=i;&lt;br /&gt;
        while ( llList2Float( src, j-stride)&amp;lt;llList2Float( src, i) &amp;amp;&amp;amp; j&amp;gt;0) j -= stride;&lt;br /&gt;
        if (j&amp;lt;i) src=llListReplaceList( src, llList2List( src, i, i+stride-1)+llList2List( src, j, i-1), j, i+stride-1);&lt;br /&gt;
    }&lt;br /&gt;
    return src;&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
The straight insertion sort method has great advantages over the bubble sort method, but in lsl the competition isn&#039;t even.&lt;br /&gt;
: The [[LlListSort|llListSort()]] is normally a factor 10 to 100 times faster.&lt;br /&gt;
: When sorting lists that are in order or almost in order, this sort and the built in are almost doing the job at the same speed.&lt;br /&gt;
: Lists used for testing had 100 strides with three elements in each&amp;lt;br&amp;gt;&lt;br /&gt;
This routine can sort on numbers only! A&amp;gt;B and A&amp;lt;B are only defined in LSL for numbers&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/occurences&amp;diff=1194391</id>
		<title>User:Dora Gustafson/occurences</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/occurences&amp;diff=1194391"/>
		<updated>2015-01-22T20:32:41Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Count Occurrences in a list ==&lt;br /&gt;
Look for and count anything, that can be an element, in a list&lt;br /&gt;
: This script is an example which include a list: &amp;quot;haystack&amp;quot; and an element: &amp;quot;needle&amp;quot;&lt;br /&gt;
: Here &amp;quot;haystack&amp;quot; and &amp;quot;needle&amp;quot; are constants and only meant to make up a working script &lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
// count occurrences in list; by Dora Gustafson, Studio Dora 2014&lt;br /&gt;
// v1.1 inline code&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        list haystack = [1,2,1,2,1,2,3,2,4,5,2,6,4,2,3,2,1,8];&lt;br /&gt;
        list needle = [2];&lt;br /&gt;
        integer i = 0;&lt;br /&gt;
        integer j = 0;&lt;br /&gt;
        integer k = llListFindList( haystack, needle);&lt;br /&gt;
        integer m = llGetListLength( haystack );&lt;br /&gt;
        while ( k &amp;gt;= 0 &amp;amp;&amp;amp; i &amp;lt; m )&lt;br /&gt;
        {&lt;br /&gt;
            i += k+1;&lt;br /&gt;
            k = llListFindList( llList2List( haystack, i, -1), needle);&lt;br /&gt;
            ++j;&lt;br /&gt;
        }&lt;br /&gt;
        llOwnerSay((string)needle+&amp;quot; occurs &amp;quot;+(string)j+&amp;quot; times in &amp;quot;+llDumpList2String( haystack, &amp;quot;, &amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
This program is straight, a recursive approach follows&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
// count occurrences in list; by Dora Gustafson, Studio Dora 2014&lt;br /&gt;
// v1.1 inline code&lt;br /&gt;
// v1.2 recursive approach&lt;br /&gt;
&lt;br /&gt;
list haystack = [1,2,1,2,1,2,3,2,4,5,2,6,4,2,3,2,1,8];&lt;br /&gt;
list needle = [2];&lt;br /&gt;
integer j = 0;&lt;br /&gt;
&lt;br /&gt;
tin( list L )&lt;br /&gt;
{&lt;br /&gt;
    integer k = llListFindList( L, needle);&lt;br /&gt;
    if ( k &amp;gt;= 0 )&lt;br /&gt;
    {&lt;br /&gt;
        ++j;&lt;br /&gt;
        if ( k+1 &amp;lt; llGetListLength(L) ) tin( llList2List( L, k+1, -1));&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        tin( haystack);&lt;br /&gt;
        llOwnerSay((string)needle+&amp;quot; occurs &amp;quot;+(string)j+&amp;quot; times in &amp;quot;+llDumpList2String( haystack, &amp;quot;, &amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
The advantage of recursion over straight code is a shorter code(the code is reused)&amp;lt;br&amp;gt;&lt;br /&gt;
The disadvantages are longer execution time and more overhead generated at runtime&lt;br /&gt;
: For these reasons the recursion approach is a bad choice to search a long list in LSL &lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega/function&amp;diff=1194390</id>
		<title>User:Dora Gustafson/Replacing llTargetOmega/function</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega/function&amp;diff=1194390"/>
		<updated>2015-01-22T20:29:28Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Replacing llTargetOmega, the function ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
KeyFramedOmega( vector axis, float spinrate)&lt;br /&gt;
{&lt;br /&gt;
    llSetKeyframedMotion( [], []);&lt;br /&gt;
    if ( spinrate )&lt;br /&gt;
    {&lt;br /&gt;
        float v = TWO_PI/3.0;&lt;br /&gt;
        if ( spinrate &amp;lt; 0 ) v = -v;&lt;br /&gt;
        list L = [llAxisAngle2Rot( axis/llGetRot(), v), v/spinrate];&lt;br /&gt;
        llSetKeyframedMotion( L+L+L, [KFM_DATA, KFM_ROTATION, KFM_MODE, KFM_LOOP]);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LlTargetOmega_Replacement&amp;diff=1194389</id>
		<title>LlTargetOmega Replacement</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LlTargetOmega_Replacement&amp;diff=1194389"/>
		<updated>2015-01-22T20:28:13Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|func=KeyFramedOmega&lt;br /&gt;
|func_id&lt;br /&gt;
|func_sleep&lt;br /&gt;
|func_energy&lt;br /&gt;
|func_desc=Rotates the object/prim around axis at a rate of spinrate in radians per second&lt;br /&gt;
|func_footnote&lt;br /&gt;
|return_type&lt;br /&gt;
|return_text&lt;br /&gt;
|p1_type=vector&lt;br /&gt;
|p1_name=axis&lt;br /&gt;
|p1_desc=arbitrary axis to rotate the object around&lt;br /&gt;
|p1_hover&lt;br /&gt;
|p2_type=float&lt;br /&gt;
|p2_name=spinrate&lt;br /&gt;
|p2_desc=rate of rotation in radians per second&lt;br /&gt;
|p2_hover&lt;br /&gt;
|constants&lt;br /&gt;
|spec=&lt;br /&gt;
* This doesn&#039;t make [[llTargetOmega]] redundant but in some cases a Key Framed motion may be preferred&lt;br /&gt;
* The routine: &amp;quot;KeyFramedOmega&amp;quot; is easy to use for [[llTargetOmega]]: It takes the first two parameters in [[llTargetOmega]]: axis and spinrate&lt;br /&gt;
* All viewers will see the same spin and rotation&lt;br /&gt;
* The object will keep the rotation it has when spin is stopped&lt;br /&gt;
* A spin will continue even when the script is deleted&lt;br /&gt;
|caveats=&lt;br /&gt;
* The script must be in the root prim&lt;br /&gt;
* It can not spin child prims&lt;br /&gt;
* The object must be convex hull physics type&lt;br /&gt;
* Can not spin physical objects&lt;br /&gt;
* If the center of mass is not at the center of the root, the object will shake and jerk and drift erratically ([https://jira.secondlife.com/browse/BUG-7266 BUG-7266])&lt;br /&gt;
|examples=&lt;br /&gt;
This script shows how to use the routine to start, stop and reverse a spin on repeated touches&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
// llTargetOmega substitution by Dora Gustafson, Studio Dora 2014&lt;br /&gt;
&lt;br /&gt;
integer P;&lt;br /&gt;
&lt;br /&gt;
KeyFramedOmega( vector axis, float spinrate)&lt;br /&gt;
{&lt;br /&gt;
    llSetKeyframedMotion( [], []);&lt;br /&gt;
    if ( spinrate )&lt;br /&gt;
    {&lt;br /&gt;
        float v = TWO_PI/3.0;&lt;br /&gt;
        if ( spinrate &amp;lt; 0 ) v = -v;&lt;br /&gt;
        list L = [llAxisAngle2Rot( axis/llGetRot(), v), v/spinrate];&lt;br /&gt;
        llSetKeyframedMotion( L+L+L, [KFM_DATA, KFM_ROTATION, KFM_MODE, KFM_LOOP]);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);&lt;br /&gt;
    }&lt;br /&gt;
    touch_end( integer n)&lt;br /&gt;
    {&lt;br /&gt;
        P = ++P%4;&lt;br /&gt;
        if ( P == 1 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 2.0);       // Positive spin&lt;br /&gt;
        else if ( P == 3 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, -2.0); // Negative spin&lt;br /&gt;
        else KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 0.0);                // Stop spin&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_header&lt;br /&gt;
|also_functions=: [[llTargetOmega]]&lt;br /&gt;
: [[llSetKeyframedMotion]]&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles&lt;br /&gt;
|also_footer&lt;br /&gt;
|notes=The magnitude of &#039;&#039;axis&#039;&#039; do &#039;&#039;&#039;not&#039;&#039;&#039; influence the &#039;&#039;spinrate&#039;&#039;&lt;br /&gt;
|mode=user&lt;br /&gt;
|deprecated&lt;br /&gt;
|location=[[User:Dora_Gustafson/Replacing_llTargetOmega/function|The Function]]&lt;br /&gt;
|cat1=Rotation&lt;br /&gt;
|cat2=Examples&lt;br /&gt;
|signature=[[User:Dora Gustafson|Dora Gustafson]] 04:36, 12 August 2014 (PDT)&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/bezier_toy&amp;diff=1194388</id>
		<title>User:Dora Gustafson/bezier toy</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/bezier_toy&amp;diff=1194388"/>
		<updated>2015-01-22T20:25:17Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header}}&lt;br /&gt;
== Bézier Toy ==&lt;br /&gt;
:Strictly for fun!&lt;br /&gt;
::The toy is made of one prim and a script.&lt;br /&gt;
::The prim will move along a smooth closed curve in space until it is stopped.&lt;br /&gt;
::The prim can be sat on and will then move you as a rollercoaster.&lt;br /&gt;
::Experimenting with the: camera distance, camera angle and camera in mouselook is great fun.&lt;br /&gt;
::Making a smoke tail is optional.&lt;br /&gt;
:The curve travelled&lt;br /&gt;
::The curve is made from a number of Bézier curves computed in the script.&lt;br /&gt;
::The curves are put together seamlessly.&lt;br /&gt;
::The points used for the curves are picked at random inside a box with editable size.&lt;br /&gt;
::New curves are computed each time The button New in the dialog menu is pressed.&lt;br /&gt;
:KeyFramed Motion&lt;br /&gt;
::The Second Life technique used is called: [[LlSetKeyframedMotion|KeyFramed Motion]]&lt;br /&gt;
::This makes it possible to let the toy run forever without a script.&lt;br /&gt;
::Just start the toy and remove the script with the Kill Script button in the dialog menu&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl2&amp;quot;&amp;gt;&lt;br /&gt;
// Bezier Key Framed Motion script by Dora Gustafson, Studio Dora 2012&lt;br /&gt;
// Build on Cubic(3.order) Bezier chain by Dora Gustafson, Studio Dora 2008&lt;br /&gt;
// v1.01 Key Framed Motion 2012&lt;br /&gt;
// v1.02 introducing KFM&lt;br /&gt;
// v1.03 KFM alone&lt;br /&gt;
// v1.04 Appending more seamless bezier curves&lt;br /&gt;
// v1.05 Box limited randomP&lt;br /&gt;
// v1.06 Smoke on/off and script erase&lt;br /&gt;
// v1.07 Parameter menu&lt;br /&gt;
// v1.08 Particle size = f(prim scale). Range separate for X, Y and Z&lt;br /&gt;
// v1.09 Same randomP as in: &amp;quot;Bezier Spot Light Key Framed Motion&amp;quot;. No more rangeOffset&lt;br /&gt;
// ... randomP box limits rotated as prim&lt;br /&gt;
&lt;br /&gt;
float Tmotion = 8.0; // seconds&lt;br /&gt;
vector range = &amp;lt; 5.0, 5.0, 5.0 &amp;gt;;  // ± half range for each coordinate in meters&lt;br /&gt;
rotation refFrame=&amp;lt;-0.5, -0.5, -0.5, 0.5&amp;gt;; // points Z forward&lt;br /&gt;
string toolDialog = &amp;quot;\nNew, Compute new points\nBegin Key Framed Motion\nEnd Key Framed Motion\nSmoke on or off\nKill Script to remove script from object\n...a Studio Dora product&amp;quot;;&lt;br /&gt;
list TOOL_MENU = [ &amp;quot;CurveNumb&amp;quot;, &amp;quot;Kill Script&amp;quot;, &amp;quot;Range&amp;quot;, &amp;quot;Cycle Time&amp;quot;, &amp;quot;Frames/Curve&amp;quot;, &amp;quot;New&amp;quot;, &amp;quot;Begin&amp;quot;, &amp;quot;End&amp;quot; ];&lt;br /&gt;
integer dialogChannel;&lt;br /&gt;
integer paramChannel;&lt;br /&gt;
integer paramHandl;&lt;br /&gt;
integer frames=16;&lt;br /&gt;
vector Po0;&lt;br /&gt;
vector Po1;&lt;br /&gt;
vector P0;&lt;br /&gt;
vector P1;&lt;br /&gt;
vector P2;&lt;br /&gt;
vector P3;&lt;br /&gt;
vector Q1;&lt;br /&gt;
vector Q2;&lt;br /&gt;
vector Q3;&lt;br /&gt;
vector LEFT=&amp;lt; 0.0, 1.0, 0.0 &amp;gt;;&lt;br /&gt;
list KFMlist=[];&lt;br /&gt;
vector b1;&lt;br /&gt;
vector b2;&lt;br /&gt;
rotation r1;&lt;br /&gt;
rotation r2;&lt;br /&gt;
integer curvNumb=3;&lt;br /&gt;
integer smoke=FALSE;&lt;br /&gt;
string partTextur;&lt;br /&gt;
rotation homeRot;&lt;br /&gt;
&lt;br /&gt;
MakeParticles()&lt;br /&gt;
{&lt;br /&gt;
    vector vsz = llGetScale();&lt;br /&gt;
    float sc = 0.5*(vsz.x+vsz.y);&lt;br /&gt;
    vsz = &amp;lt; sc, sc, 0.0 &amp;gt;;&lt;br /&gt;
    llParticleSystem([&lt;br /&gt;
    PSYS_PART_FLAGS,&lt;br /&gt;
    PSYS_PART_INTERP_COLOR_MASK       //Colors fade from start to end&lt;br /&gt;
    | PSYS_PART_INTERP_SCALE_MASK       //Scale fades from beginning to end&lt;br /&gt;
    ,PSYS_SRC_PATTERN,           PSYS_SRC_PATTERN_ANGLE_CONE&lt;br /&gt;
    ,PSYS_SRC_TEXTURE,           partTextur         //UUID of the desired particle texture, or inventory name&lt;br /&gt;
    ,PSYS_SRC_MAX_AGE,           0.0                //Time, in seconds, for particles to be emitted. 0 = forever&lt;br /&gt;
    ,PSYS_PART_MAX_AGE,          60.0               //Lifetime, in seconds, that a particle lasts&lt;br /&gt;
    ,PSYS_SRC_BURST_RATE,        0.02               //How long, in seconds, between each emission&lt;br /&gt;
    ,PSYS_SRC_BURST_PART_COUNT,  1                  //Number of particles per emission&lt;br /&gt;
    ,PSYS_SRC_BURST_RADIUS,      0.0                //Radius of emission&lt;br /&gt;
    ,PSYS_SRC_BURST_SPEED_MIN,   0.0                //Minimum speed of an emitted particle&lt;br /&gt;
    ,PSYS_SRC_BURST_SPEED_MAX,   0.0                //Maximum speed of an emitted particle&lt;br /&gt;
    ,PSYS_SRC_ACCEL,             &amp;lt;0.0,0.0,0.0&amp;gt;      //Acceleration of particles each second&lt;br /&gt;
    ,PSYS_PART_START_COLOR,      &amp;lt;1.0,1.0,1.0&amp;gt;      //Starting RGB color&lt;br /&gt;
    ,PSYS_PART_END_COLOR,        &amp;lt;1.0,1.0,1.0&amp;gt;      //Ending RGB color, if INTERP_COLOR_MASK is on&lt;br /&gt;
    ,PSYS_PART_START_ALPHA,      1.0                //Starting transparency, 1 is opaque, 0 is transparent.&lt;br /&gt;
    ,PSYS_PART_END_ALPHA,        0.0                //Ending transparency&lt;br /&gt;
    ,PSYS_PART_START_SCALE,      vsz                //Starting particle size&lt;br /&gt;
    ,PSYS_PART_END_SCALE,        1.5*vsz            //Ending particle size, if INTERP_SCALE_MASK is on&lt;br /&gt;
    ,PSYS_SRC_ANGLE_BEGIN,       3.1415             //Inner angle for ANGLE patterns&lt;br /&gt;
    ,PSYS_SRC_ANGLE_END,         3.1415             //Outer angle for ANGLE patterns&lt;br /&gt;
    ,PSYS_SRC_OMEGA,             &amp;lt;0.0,0.0,0.0&amp;gt;      //Rotation of ANGLE patterns, similar to llTargetOmega()&lt;br /&gt;
    ]);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
openBox( integer n, string menuText)&lt;br /&gt;
{&lt;br /&gt;
    paramChannel = dialogChannel + n;&lt;br /&gt;
    llListenRemove( paramHandl);&lt;br /&gt;
    paramHandl = llListen( paramChannel, &amp;quot;&amp;quot;, llGetOwner(), &amp;quot;&amp;quot;);&lt;br /&gt;
    llTextBox( llGetOwner(), menuText, paramChannel);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
vector randomP()&lt;br /&gt;
{&lt;br /&gt;
    return llGetPos() + &amp;lt; range.x*(llFrand( 2.0)-1.0), range.y*(llFrand( 2.0)-1.0), range.z*(llFrand( 2.0)-1.0) &amp;gt; * homeRot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
rotation Vec2Rot( vector FWD )&lt;br /&gt;
{&lt;br /&gt;
    FWD = llVecNorm( FWD );&lt;br /&gt;
    vector UP = &amp;lt; 0.0, 0.0, 1.0 &amp;gt;;&lt;br /&gt;
    if ( llFabs(FWD.z) &amp;lt; 1.0 ) LEFT = llVecNorm(UP%FWD);&lt;br /&gt;
    UP = llVecNorm(FWD%LEFT);&lt;br /&gt;
    return refFrame*llAxes2Rot(FWD, LEFT, UP);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
tDialog()&lt;br /&gt;
{&lt;br /&gt;
    string menuD = llGetScriptName( )+&amp;quot;\nMemory in use: &amp;quot;+(string)llGetUsedMemory();&lt;br /&gt;
    menuD += &amp;quot;\n\nRange = ±&amp;quot;+(string)range+&amp;quot; meters&amp;quot;;&lt;br /&gt;
    menuD += &amp;quot;\nCycle time = &amp;quot;+(string)Tmotion+&amp;quot; Seconds&amp;quot;;&lt;br /&gt;
    menuD += &amp;quot;\nFrames per curve = &amp;quot;+(string)frames;&lt;br /&gt;
    menuD += &amp;quot;\nNumber of curves = &amp;quot;+(string)curvNumb;&lt;br /&gt;
    list T_MENU = [&amp;quot;Smoke ON&amp;quot;];&lt;br /&gt;
    if (smoke) T_MENU = [&amp;quot;Smoke OFF&amp;quot;];&lt;br /&gt;
    llDialog( llGetOwner(), menuD + toolDialog, T_MENU + TOOL_MENU, dialogChannel);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
integer random_channel()&lt;br /&gt;
{// mask out 4 LSBits for other uses&lt;br /&gt;
    return ((128 * (integer)llFrand( 8388608.0 )) + (integer)llFrand( 8388608.0 ) + 0x80000000) &amp;amp; 0xFFFFFFF0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
coefisFirst()&lt;br /&gt;
{&lt;br /&gt;
    P0 = llGetPos();&lt;br /&gt;
    Po0 = P0;&lt;br /&gt;
    P3 = randomP();&lt;br /&gt;
    P2 = randomP();&lt;br /&gt;
    P1 = randomP();&lt;br /&gt;
    Po1 = P1;&lt;br /&gt;
    Q1 = 3.0*P1-3.0*P0;&lt;br /&gt;
    Q2 = 3.0*P0-6.0*P1+3.0*P2;&lt;br /&gt;
    Q3 = 3.0*P1-P0+P3-3.0*P2;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
coefisNext()&lt;br /&gt;
{&lt;br /&gt;
    P0 = P3;&lt;br /&gt;
    P1 = 2.0*P3-P2;&lt;br /&gt;
    P3 = randomP();&lt;br /&gt;
    P2 = randomP();&lt;br /&gt;
    Q1 = 3.0*P1-3.0*P0;&lt;br /&gt;
    Q2 = 3.0*P0-6.0*P1+3.0*P2;&lt;br /&gt;
    Q3 = 3.0*P1-P0+P3-3.0*P2;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
coefisLast()&lt;br /&gt;
{&lt;br /&gt;
    P0 = P3;&lt;br /&gt;
    P1 = 2.0*P3-P2;&lt;br /&gt;
    P2 = 2.0*Po0-Po1;&lt;br /&gt;
    P3 = Po0;&lt;br /&gt;
    Q1 = 3.0*P1-3.0*P0;&lt;br /&gt;
    Q2 = 3.0*P0-6.0*P1+3.0*P2;&lt;br /&gt;
    Q3 = 3.0*P1-P0+P3-3.0*P2;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
vector Bez( float x ) { return P0 + (Q1 + (Q2 + Q3*x)*x)*x; }&lt;br /&gt;
&lt;br /&gt;
vector dBez( float x ) { return Q1 + (2.0*Q2 + 3.0*Q3*x)*x; }&lt;br /&gt;
&lt;br /&gt;
vector sBez( float x ) { return 2.0*Q2 + 6.0*Q3*x; }&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);&lt;br /&gt;
        dialogChannel = random_channel();&lt;br /&gt;
        llListen( dialogChannel, &amp;quot;&amp;quot;, llGetOwner(), &amp;quot;&amp;quot;);&lt;br /&gt;
        refFrame.s = -refFrame.s;&lt;br /&gt;
        string textureName = llGetInventoryName(INVENTORY_TEXTURE, 0 );&lt;br /&gt;
        if ( llGetInventoryType( textureName ) == INVENTORY_TEXTURE ) partTextur = textureName;  // use extern, inventory texture&lt;br /&gt;
        else partTextur = &amp;quot;&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    touch_end(integer n)&lt;br /&gt;
    {&lt;br /&gt;
        if ( llDetectedKey(0) == llGetOwner() )&lt;br /&gt;
        {&lt;br /&gt;
            if ( llGetListLength( KFMlist) &amp;gt; 5 ) tDialog();&lt;br /&gt;
            else llDialog( llGetOwner(), llGetScriptName( )+&amp;quot;\n\nMust make a new&amp;quot;, [&amp;quot;New&amp;quot;], dialogChannel);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    listen(integer channel, string name, key id, string message)&lt;br /&gt;
    {&lt;br /&gt;
        if ( message == &amp;quot;CurveNumb&amp;quot; ) openBox( 1, &amp;quot;Enter number of appended Bezier curves= 2,3,4,...,18&amp;quot;);&lt;br /&gt;
        else if ( message == &amp;quot;Range&amp;quot; ) openBox( 2, &amp;quot;Specify ±range relative to curent position\nCube: [X range, Y range, Z range]&amp;quot;);&lt;br /&gt;
        else if ( message == &amp;quot;Cycle Time&amp;quot; ) openBox( 3, &amp;quot;Time in seconds for one cycle&amp;quot;);&lt;br /&gt;
        else if ( message == &amp;quot;Frames/Curve&amp;quot; ) openBox( 4, &amp;quot;Number of key frames per Bezier curve [2;100]&amp;quot;);&lt;br /&gt;
        else if ( message == &amp;quot;Kill Script&amp;quot; ) llRemoveInventory( llGetScriptName());&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            if ( message == &amp;quot;New&amp;quot; )&lt;br /&gt;
            {&lt;br /&gt;
                homeRot = llGetRot();&lt;br /&gt;
                float liN = (float)frames;&lt;br /&gt;
                float dT = Tmotion/liN/(float)curvNumb;&lt;br /&gt;
                dT = llRound(45.0*dT)/45.0;&lt;br /&gt;
                if ( dT &amp;lt; 0.11111111 ) dT = 0.11111111;&lt;br /&gt;
                KFMlist=[];&lt;br /&gt;
                coefisFirst();&lt;br /&gt;
                b1 = Bez(0);&lt;br /&gt;
                r1 = Vec2Rot( dBez(0));&lt;br /&gt;
                integer i;&lt;br /&gt;
                for ( i=1; i&amp;lt;=frames; i++ )&lt;br /&gt;
                {&lt;br /&gt;
                    b2 = Bez( i/liN); r2 = Vec2Rot(dBez( i/liN));&lt;br /&gt;
                    KFMlist += [ b2-b1, r2/r1, dT];&lt;br /&gt;
                    b1 = b2; r1 = r2;&lt;br /&gt;
                }&lt;br /&gt;
                integer j = curvNumb;&lt;br /&gt;
                while ( j-- &amp;gt; 2 )&lt;br /&gt;
                {&lt;br /&gt;
                    coefisNext();&lt;br /&gt;
                    for ( i=1; i&amp;lt;=frames; i++ )&lt;br /&gt;
                    {&lt;br /&gt;
                        b2 = Bez( i/liN); r2 = Vec2Rot(dBez( i/liN));&lt;br /&gt;
                        KFMlist += [ b2-b1, r2/r1, dT];&lt;br /&gt;
                        b1 = b2; r1 = r2;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
                coefisLast();&lt;br /&gt;
                for ( i=1; i&amp;lt;=frames; i++ )&lt;br /&gt;
                {&lt;br /&gt;
                    b2 = Bez( i/liN); r2 = Vec2Rot(dBez( i/liN));&lt;br /&gt;
                    KFMlist += [ b2-b1, r2/r1, dT];&lt;br /&gt;
                    b1 = b2; r1 = r2;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            else if ( message == &amp;quot;End&amp;quot; )&lt;br /&gt;
            {&lt;br /&gt;
                llSetKeyframedMotion( [], []);&lt;br /&gt;
                llSleep(0.2);&lt;br /&gt;
                llSetRegionPos( Po0);&lt;br /&gt;
                llSetPrimitiveParams([PRIM_POSITION, Po0, PRIM_ROTATION, homeRot]);&lt;br /&gt;
            }&lt;br /&gt;
            else if ( message == &amp;quot;Begin&amp;quot; &amp;amp;&amp;amp; llGetListLength( KFMlist))&lt;br /&gt;
            {&lt;br /&gt;
                llSetKeyframedMotion( [], []);&lt;br /&gt;
                llSleep(0.2);&lt;br /&gt;
                llSetRegionPos( Po0);&lt;br /&gt;
                llSetPrimitiveParams([PRIM_POSITION, Po0, PRIM_ROTATION, Vec2Rot( Po1-Po0)]);&lt;br /&gt;
                llSetKeyframedMotion( KFMlist, [KFM_MODE, KFM_LOOP]);&lt;br /&gt;
            }&lt;br /&gt;
            else if ( message == &amp;quot;Smoke ON&amp;quot; ) { MakeParticles(); smoke = TRUE; }&lt;br /&gt;
            else if ( message == &amp;quot;Smoke OFF&amp;quot; ) { llParticleSystem([]); smoke = FALSE; }&lt;br /&gt;
            else if ( channel == dialogChannel + 1 )&lt;br /&gt;
            {&lt;br /&gt;
                curvNumb = (integer)message;&lt;br /&gt;
                if ( curvNumb &amp;lt; 2 || curvNumb &amp;gt; 18 ) curvNumb = 2;&lt;br /&gt;
            }&lt;br /&gt;
            else if ( channel == dialogChannel + 2 )&lt;br /&gt;
            {&lt;br /&gt;
                list L = llCSV2List( message);&lt;br /&gt;
                if ( llGetListLength(L) == 3 )&lt;br /&gt;
                {&lt;br /&gt;
                    range.x = llList2Float( L, 0);&lt;br /&gt;
                    range.y = llList2Float( L, 1);&lt;br /&gt;
                    range.z = llList2Float( L, 2);&lt;br /&gt;
                }&lt;br /&gt;
                else if ( llGetListLength(L) == 1 ) range = (vector)llList2String( L, 0);&lt;br /&gt;
                else if ( range.x&amp;lt;=0.0 || range.y&amp;lt;=0.0 || range.z&amp;lt;=0.0 ) llOwnerSay(&amp;quot;Range must be entered as a vector with positive elements\nor as three comma separated positive numbers&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
            else if ( channel == dialogChannel + 3 )&lt;br /&gt;
            {&lt;br /&gt;
                Tmotion = (float)message;&lt;br /&gt;
                if ( Tmotion &amp;lt; 1.0 ) Tmotion = 1.0;&lt;br /&gt;
            }&lt;br /&gt;
            else if ( channel == dialogChannel + 4 )&lt;br /&gt;
            {&lt;br /&gt;
                frames = (integer)message;&lt;br /&gt;
                if ( frames &amp;lt; 2 || frames &amp;gt; 100 ) frames = 16;&lt;br /&gt;
            }&lt;br /&gt;
            llListenRemove( paramHandl );&lt;br /&gt;
            tDialog();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    on_rez(integer param) { llResetScript(); }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== The menu ===&lt;br /&gt;
:New&lt;br /&gt;
::Will compute new curves from new randomly picked points in space&lt;br /&gt;
::The points will be picked inside a box with the prim in the center and rotated just like the prim&lt;br /&gt;
::Do not press New when the prim is moving, if you want any control of the curve&lt;br /&gt;
:Begin&lt;br /&gt;
::Begin the prim travel&lt;br /&gt;
:End&lt;br /&gt;
::End the travel and reset prim to start position and start rotation&lt;br /&gt;
:Range&lt;br /&gt;
::The range in which random points will be picked for the Bézier curves&lt;br /&gt;
::It is given by 3 coordinates X, Y and Z&lt;br /&gt;
::The coordinates form a box with the prim in the middle: prim position ±X, ±Y and ±Z&lt;br /&gt;
::This imaginary box is rotated just like the prim!&lt;br /&gt;
::In edit mode you can see the prim’s axes when you choose local coordinates (as opposed to world coordinates)&lt;br /&gt;
::Note that the prim will not stay inside the box on its journey, only the points used to compute the journey are guarantied to be inside&lt;br /&gt;
:Cycle Time&lt;br /&gt;
::The time it takes to complete one cycle from start to start&lt;br /&gt;
:Frames/Curve&lt;br /&gt;
::The number of keyframes for each Bézier curve&lt;br /&gt;
:Smoke ON/OFF&lt;br /&gt;
::Toggles the particle emitter ON/OFF&lt;br /&gt;
:CurveNumb&lt;br /&gt;
::The number of Bézier curves from start to start&lt;br /&gt;
:Kill Script&lt;br /&gt;
::Will remove the script and the toy can’t be controlled anymore&lt;br /&gt;
::The toy will continue doing what it did when the script was removed&lt;br /&gt;
{{LSLC|Library}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LlRotBetween&amp;diff=1193714</id>
		<title>LlRotBetween</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LlRotBetween&amp;diff=1193714"/>
		<updated>2014-10-03T12:52:43Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|inject-2={{Issues/SVC-4415}}{{Issues/SCR-309}}&lt;br /&gt;
|func_id=21|func_sleep=0.0|func_energy=10.0&lt;br /&gt;
|func=llRotBetween&lt;br /&gt;
|return_type=rotation|p1_type=vector|p1_name=start|p2_type=vector|p2_name=end&lt;br /&gt;
|func_footnote&lt;br /&gt;
|func_desc&lt;br /&gt;
|return_text=that is the shortest rotation between the direction {{LSLP|start}} and the direction {{LSLP|end}} &lt;br /&gt;
|spec={{LSLP|start}} and {{LSLP|end}} are directions and are relative to the origin &amp;lt;0.0, 0.0, 0.0&amp;gt;. If you have coordinates relative to a different origin, subtract that origin from the input vectors.&lt;br /&gt;
|caveats=&lt;br /&gt;
*&amp;lt;code&amp;gt;start * llRotBetween(start, end) == end&amp;lt;/code&amp;gt; is only true if {{LSLP|start}} and {{LSLP|end}} have the same magnitude and neither have a magnitude of zero (see [[#Useful Snippets]] for a workaround).&lt;br /&gt;
**This of course is ignoring floating point precision errors.&lt;br /&gt;
* The above is true because of vector magnitudes and not a shortcoming of this function. The &#039;&#039;&#039;rotation&#039;&#039;&#039; returned is &#039;&#039;&#039;correct&#039;&#039;&#039; regardless of magnitudes&lt;br /&gt;
* Rotations are from -PI to +PI around each axis.&lt;br /&gt;
|constants&lt;br /&gt;
|examples=&lt;br /&gt;
&amp;lt;lsl&amp;gt;llRotBetween(&amp;lt;1.0, 0.0, 0.0&amp;gt;, &amp;lt;0.0, -1.0, 0.0&amp;gt;)&lt;br /&gt;
// will return &amp;lt;0.00000, 0.00000, -0.70711, 0.70711&amp;gt; (which represents -90 degrees on the z axis)&lt;br /&gt;
&lt;br /&gt;
llRotBetween(&amp;lt;0.0, 0.0, 0.0&amp;gt;, &amp;lt;0.0, -1.0, 0.0&amp;gt;)&lt;br /&gt;
// will return &amp;lt;0.00000, 0.00000, 0.00000, 1.00000&amp;gt; (which represents a zero angle on all axis)&lt;br /&gt;
// because &amp;lt;0.0, 0.0, 0.0&amp;gt; does not convey a direction.&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_functions={{LSL DefineRow||[[llAngleBetween]]}}&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles&lt;br /&gt;
|helpers=This function adjusts the magnitude of the quaternion so &amp;lt;code&amp;gt;start * llRotBetween(start, end) == end&amp;lt;/code&amp;gt; is true as long as neither have a magnitude really close to zero. They do not have to have the same magnitude. (If either is too close to zero than this will return an unadjusted quaternion). While this is mathematically correct, it won&#039;t help with floating point rounding errors, so it&#039;s more accurate to say &amp;lt;code&amp;gt;start * return ≈ end&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;lsl&amp;gt;rotation RotBetween(vector start, vector end) //adjusts quaternion magnitude so (start * return == end) &lt;br /&gt;
{//Authors note: I have never had a use for this but it&#039;s good to know how to do it if I did.&lt;br /&gt;
    rotation rot = llRotBetween(start, end);&lt;br /&gt;
    float d = start * start;&lt;br /&gt;
    if(d)//is &#039;start&#039; zero?&lt;br /&gt;
        if((d = llPow(end * end / d, 0.25)))//is &#039;end&#039; zero?&lt;br /&gt;
            return &amp;lt;rot.x * d, rot.y * d, rot.z * d, rot.s * d&amp;gt;;&lt;br /&gt;
    return rot;&lt;br /&gt;
}//Strife Onizuka&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|notes=&lt;br /&gt;
Vectors that are near opposite each other in direction may lead to erroneous results. &lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
// First Vector is due north second vector is ALMOST due south.&lt;br /&gt;
rotation lRotation = llRotBetween( &amp;lt;0., 1., 0.&amp;gt;, &amp;lt;-0.001, -.1, 0.&amp;gt; );&lt;br /&gt;
llSay(0, lRotation );&lt;br /&gt;
// Provides a result of &amp;lt;1.00000, 0.00000, 0.00000, 0.00000&amp;gt;.&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|location={{SourceLink/bitbucket|viewer-release|indra/llmath/llquaternion.cpp|line=425}}&lt;br /&gt;
|deepnotes= === Replacement ===&lt;br /&gt;
Due to the annoying quirks of this function {{User|Moon Metty}} wrote a drop in replacement. - {{Jira|SCR-309}}.&lt;br /&gt;
The maximum error is reported to be 2.7e-7 @ 2.2 radians.&lt;br /&gt;
&amp;lt;lsl&amp;gt;rotation RotBetween(vector a, vector b)&lt;br /&gt;
{&lt;br /&gt;
    float aabb = llSqrt((a * a) * (b * b)); // product of the lengths of the arguments&lt;br /&gt;
    if (aabb)&lt;br /&gt;
    {&lt;br /&gt;
        float ab = (a * b) / aabb; // normalized dotproduct of the arguments (cosine)&lt;br /&gt;
        vector c = &amp;lt;(a.y * b.z - a.z * b.y) / aabb,&lt;br /&gt;
                    (a.z * b.x - a.x * b.z) / aabb,&lt;br /&gt;
                    (a.x * b.y - a.y * b.x) / aabb &amp;gt;; // normalized crossproduct of the arguments&lt;br /&gt;
        float cc = c * c; // squared length of the normalized crossproduct (sine)&lt;br /&gt;
        if (cc) // test if the arguments are not (anti)parallel&lt;br /&gt;
        {&lt;br /&gt;
            float s;&lt;br /&gt;
            if (ab &amp;gt; -0.707107)&lt;br /&gt;
                s = 1 + ab; // use the cosine to adjust the s-element&lt;br /&gt;
            else &lt;br /&gt;
                s = cc / (1 + llSqrt(1 - cc)); // use the sine to adjust the s-element&lt;br /&gt;
            float m = llSqrt(cc + s * s); // the magnitude of the quaternion&lt;br /&gt;
            return &amp;lt;c.x / m, c.y / m, c.z / m, s / m&amp;gt;; // return the normalized quaternion&lt;br /&gt;
        }&lt;br /&gt;
        if (ab &amp;gt; 0) &lt;br /&gt;
            return ZERO_ROTATION; // the arguments are parallel, or anti-parallel if not true:&lt;br /&gt;
        float m = llSqrt(a.x * a.x + a.y * a.y); // the length of one argument projected on the XY-plane&lt;br /&gt;
        if (m) &lt;br /&gt;
            return &amp;lt;a.y / m, -a.x / m, 0, 0&amp;gt;; // return a rotation with the axis in the XY-plane&lt;br /&gt;
        return &amp;lt;1, 0, 0, 0&amp;gt;; // the arguments are parallel to the Z-axis, rotate around the X-axis&lt;br /&gt;
    }&lt;br /&gt;
    return ZERO_ROTATION; // the arguments are too small, return zero rotation&lt;br /&gt;
}//Written by Moon Metty, optimized by Strife Onizuka&lt;br /&gt;
 &lt;br /&gt;
// This version keeps the axis in the XY-plane, in case of anti-parallel vectors (unlike the current LL implementation). -- Moon Metty&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Bad Reference Implementation===&lt;br /&gt;
&amp;lt;lsl&amp;gt;//Loosely based on SL source code, like SL&#039;s version, it&#039;s not very accurate. You want to use the above version.&lt;br /&gt;
rotation llRotBetween(vector start, vector end) {&lt;br /&gt;
    vector v1 = llVecNorm(start);&lt;br /&gt;
    vector v2 = llVecNorm(end);&lt;br /&gt;
    float dot = v1 * v2;&lt;br /&gt;
    vector axis = v1 % v2;&lt;br /&gt;
    if (dot &amp;lt; -0.9999999) {&lt;br /&gt;
        // 180 degrees or there abouts&lt;br /&gt;
        vector ortho_axis = llVecNorm(&amp;lt;1.f, 0.f, 0.f&amp;gt; - (sn * (sn.x / (sn * sn))));&lt;br /&gt;
        if (ortho_axis)&lt;br /&gt;
            return &amp;lt; ortho_axis.x, ortho_axis.y, ortho_axis.z, 0.f&amp;gt;;&lt;br /&gt;
        return &amp;lt;0.0, 0.0, 1.0, 0.0&amp;gt;;&lt;br /&gt;
    }&lt;br /&gt;
    else if(dot &amp;gt; 0.9999999) {&lt;br /&gt;
        //parallel&lt;br /&gt;
        return ZERO_ROTATION;&lt;br /&gt;
    }&lt;br /&gt;
    dot = dot + 1.0;&lt;br /&gt;
    float m = llPow((axis * axis) + (dot * dot), -0.5);&lt;br /&gt;
    return &amp;lt;axis.x * m, axis.y * m, axis.z * m, dot * m&amp;gt;;&lt;br /&gt;
}&amp;lt;/lsl&amp;gt;&lt;br /&gt;
===llRotBetween alternatives===&lt;br /&gt;
[[User:Dora_Gustafson/llRotBetween_alternatives#llRotBetween.2C_some_alternatives_and_considerations|Alternatives and considerations]]&lt;br /&gt;
|cat1=Math/3D&lt;br /&gt;
|cat2=Rotation&lt;br /&gt;
|cat3&lt;br /&gt;
|cat4&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LlRotBetween&amp;diff=1193713</id>
		<title>LlRotBetween</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LlRotBetween&amp;diff=1193713"/>
		<updated>2014-10-03T12:45:45Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|inject-2={{Issues/SVC-4415}}{{Issues/SCR-309}}&lt;br /&gt;
|func_id=21|func_sleep=0.0|func_energy=10.0&lt;br /&gt;
|func=llRotBetween&lt;br /&gt;
|return_type=rotation|p1_type=vector|p1_name=start|p2_type=vector|p2_name=end&lt;br /&gt;
|func_footnote&lt;br /&gt;
|func_desc&lt;br /&gt;
|return_text=that is the shortest rotation between the direction {{LSLP|start}} and the direction {{LSLP|end}} &lt;br /&gt;
|spec={{LSLP|start}} and {{LSLP|end}} are directions and are relative to the origin &amp;lt;0.0, 0.0, 0.0&amp;gt;. If you have coordinates relative to a different origin, subtract that origin from the input vectors.&lt;br /&gt;
|caveats=&lt;br /&gt;
*&amp;lt;code&amp;gt;start * llRotBetween(start, end) == end&amp;lt;/code&amp;gt; is only true if {{LSLP|start}} and {{LSLP|end}} have the same magnitude and neither have a magnitude of zero (see [[#Useful Snippets]] for a workaround).&lt;br /&gt;
**This of course is ignoring floating point precision errors.&lt;br /&gt;
* The above is true because of vector magnitudes. The &#039;&#039;&#039;rotation&#039;&#039;&#039; returned is &#039;&#039;&#039;correct&#039;&#039;&#039; regardless of that (reserved rounding errors)&lt;br /&gt;
* Rotations are from -PI to +PI around each axis.&lt;br /&gt;
|constants&lt;br /&gt;
|examples=&lt;br /&gt;
&amp;lt;lsl&amp;gt;llRotBetween(&amp;lt;1.0, 0.0, 0.0&amp;gt;, &amp;lt;0.0, -1.0, 0.0&amp;gt;)&lt;br /&gt;
// will return &amp;lt;0.00000, 0.00000, -0.70711, 0.70711&amp;gt; (which represents -90 degrees on the z axis)&lt;br /&gt;
&lt;br /&gt;
llRotBetween(&amp;lt;0.0, 0.0, 0.0&amp;gt;, &amp;lt;0.0, -1.0, 0.0&amp;gt;)&lt;br /&gt;
// will return &amp;lt;0.00000, 0.00000, 0.00000, 1.00000&amp;gt; (which represents a zero angle on all axis)&lt;br /&gt;
// because &amp;lt;0.0, 0.0, 0.0&amp;gt; does not convey a direction.&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_functions={{LSL DefineRow||[[llAngleBetween]]}}&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles&lt;br /&gt;
|helpers=This function adjusts the magnitude of the quaternion so &amp;lt;code&amp;gt;start * llRotBetween(start, end) == end&amp;lt;/code&amp;gt; is true as long as neither have a magnitude really close to zero. They do not have to have the same magnitude. (If either is too close to zero than this will return an unadjusted quaternion). While this is mathematically correct, it won&#039;t help with floating point rounding errors, so it&#039;s more accurate to say &amp;lt;code&amp;gt;start * return ≈ end&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;lsl&amp;gt;rotation RotBetween(vector start, vector end) //adjusts quaternion magnitude so (start * return == end) &lt;br /&gt;
{//Authors note: I have never had a use for this but it&#039;s good to know how to do it if I did.&lt;br /&gt;
    rotation rot = llRotBetween(start, end);&lt;br /&gt;
    float d = start * start;&lt;br /&gt;
    if(d)//is &#039;start&#039; zero?&lt;br /&gt;
        if((d = llPow(end * end / d, 0.25)))//is &#039;end&#039; zero?&lt;br /&gt;
            return &amp;lt;rot.x * d, rot.y * d, rot.z * d, rot.s * d&amp;gt;;&lt;br /&gt;
    return rot;&lt;br /&gt;
}//Strife Onizuka&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|notes=&lt;br /&gt;
Vectors that are near opposite each other in direction may lead to erroneous results. &lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
// First Vector is due north second vector is ALMOST due south.&lt;br /&gt;
rotation lRotation = llRotBetween( &amp;lt;0., 1., 0.&amp;gt;, &amp;lt;-0.001, -.1, 0.&amp;gt; );&lt;br /&gt;
llSay(0, lRotation );&lt;br /&gt;
// Provides a result of &amp;lt;1.00000, 0.00000, 0.00000, 0.00000&amp;gt;.&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|location={{SourceLink/bitbucket|viewer-release|indra/llmath/llquaternion.cpp|line=425}}&lt;br /&gt;
|deepnotes= === Replacement ===&lt;br /&gt;
Due to the annoying quirks of this function {{User|Moon Metty}} wrote a drop in replacement. - {{Jira|SCR-309}}.&lt;br /&gt;
The maximum error is reported to be 2.7e-7 @ 2.2 radians.&lt;br /&gt;
&amp;lt;lsl&amp;gt;rotation RotBetween(vector a, vector b)&lt;br /&gt;
{&lt;br /&gt;
    float aabb = llSqrt((a * a) * (b * b)); // product of the lengths of the arguments&lt;br /&gt;
    if (aabb)&lt;br /&gt;
    {&lt;br /&gt;
        float ab = (a * b) / aabb; // normalized dotproduct of the arguments (cosine)&lt;br /&gt;
        vector c = &amp;lt;(a.y * b.z - a.z * b.y) / aabb,&lt;br /&gt;
                    (a.z * b.x - a.x * b.z) / aabb,&lt;br /&gt;
                    (a.x * b.y - a.y * b.x) / aabb &amp;gt;; // normalized crossproduct of the arguments&lt;br /&gt;
        float cc = c * c; // squared length of the normalized crossproduct (sine)&lt;br /&gt;
        if (cc) // test if the arguments are not (anti)parallel&lt;br /&gt;
        {&lt;br /&gt;
            float s;&lt;br /&gt;
            if (ab &amp;gt; -0.707107)&lt;br /&gt;
                s = 1 + ab; // use the cosine to adjust the s-element&lt;br /&gt;
            else &lt;br /&gt;
                s = cc / (1 + llSqrt(1 - cc)); // use the sine to adjust the s-element&lt;br /&gt;
            float m = llSqrt(cc + s * s); // the magnitude of the quaternion&lt;br /&gt;
            return &amp;lt;c.x / m, c.y / m, c.z / m, s / m&amp;gt;; // return the normalized quaternion&lt;br /&gt;
        }&lt;br /&gt;
        if (ab &amp;gt; 0) &lt;br /&gt;
            return ZERO_ROTATION; // the arguments are parallel, or anti-parallel if not true:&lt;br /&gt;
        float m = llSqrt(a.x * a.x + a.y * a.y); // the length of one argument projected on the XY-plane&lt;br /&gt;
        if (m) &lt;br /&gt;
            return &amp;lt;a.y / m, -a.x / m, 0, 0&amp;gt;; // return a rotation with the axis in the XY-plane&lt;br /&gt;
        return &amp;lt;1, 0, 0, 0&amp;gt;; // the arguments are parallel to the Z-axis, rotate around the X-axis&lt;br /&gt;
    }&lt;br /&gt;
    return ZERO_ROTATION; // the arguments are too small, return zero rotation&lt;br /&gt;
}//Written by Moon Metty, optimized by Strife Onizuka&lt;br /&gt;
 &lt;br /&gt;
// This version keeps the axis in the XY-plane, in case of anti-parallel vectors (unlike the current LL implementation). -- Moon Metty&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Bad Reference Implementation===&lt;br /&gt;
&amp;lt;lsl&amp;gt;//Loosely based on SL source code, like SL&#039;s version, it&#039;s not very accurate. You want to use the above version.&lt;br /&gt;
rotation llRotBetween(vector start, vector end) {&lt;br /&gt;
    vector v1 = llVecNorm(start);&lt;br /&gt;
    vector v2 = llVecNorm(end);&lt;br /&gt;
    float dot = v1 * v2;&lt;br /&gt;
    vector axis = v1 % v2;&lt;br /&gt;
    if (dot &amp;lt; -0.9999999) {&lt;br /&gt;
        // 180 degrees or there abouts&lt;br /&gt;
        vector ortho_axis = llVecNorm(&amp;lt;1.f, 0.f, 0.f&amp;gt; - (sn * (sn.x / (sn * sn))));&lt;br /&gt;
        if (ortho_axis)&lt;br /&gt;
            return &amp;lt; ortho_axis.x, ortho_axis.y, ortho_axis.z, 0.f&amp;gt;;&lt;br /&gt;
        return &amp;lt;0.0, 0.0, 1.0, 0.0&amp;gt;;&lt;br /&gt;
    }&lt;br /&gt;
    else if(dot &amp;gt; 0.9999999) {&lt;br /&gt;
        //parallel&lt;br /&gt;
        return ZERO_ROTATION;&lt;br /&gt;
    }&lt;br /&gt;
    dot = dot + 1.0;&lt;br /&gt;
    float m = llPow((axis * axis) + (dot * dot), -0.5);&lt;br /&gt;
    return &amp;lt;axis.x * m, axis.y * m, axis.z * m, dot * m&amp;gt;;&lt;br /&gt;
}&amp;lt;/lsl&amp;gt;&lt;br /&gt;
===llRotBetween alternatives===&lt;br /&gt;
[[User:Dora_Gustafson/llRotBetween_alternatives#llRotBetween.2C_some_alternatives_and_considerations|Alternatives and considerations]]&lt;br /&gt;
|cat1=Math/3D&lt;br /&gt;
|cat2=Rotation&lt;br /&gt;
|cat3&lt;br /&gt;
|cat4&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LlRotBetween&amp;diff=1193712</id>
		<title>LlRotBetween</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LlRotBetween&amp;diff=1193712"/>
		<updated>2014-10-03T12:41:32Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|inject-2={{Issues/SVC-4415}}{{Issues/SCR-309}}&lt;br /&gt;
|func_id=21|func_sleep=0.0|func_energy=10.0&lt;br /&gt;
|func=llRotBetween&lt;br /&gt;
|return_type=rotation|p1_type=vector|p1_name=start|p2_type=vector|p2_name=end&lt;br /&gt;
|func_footnote&lt;br /&gt;
|func_desc&lt;br /&gt;
|return_text=that is the shortest rotation between the direction {{LSLP|start}} and the direction {{LSLP|end}} &lt;br /&gt;
|spec={{LSLP|start}} and {{LSLP|end}} are directions and are relative to the origin &amp;lt;0.0, 0.0, 0.0&amp;gt;. If you have coordinates relative to a different origin, subtract that origin from the input vectors.&lt;br /&gt;
|caveats=&lt;br /&gt;
*&amp;lt;code&amp;gt;start * llRotBetween(start, end) == end&amp;lt;/code&amp;gt; is only true if {{LSLP|start}} and {{LSLP|end}} have the same magnitude and neither have a magnitude of zero (see [[#Useful Snippets]] for a workaround).&lt;br /&gt;
**This of course is ignoring floating point precision errors.&lt;br /&gt;
* The above is true because of vector magnitudes. The rotation returned is correct regardless of that (reserved rounding errors)&lt;br /&gt;
* Rotations are from -PI to +PI around each axis.&lt;br /&gt;
|constants&lt;br /&gt;
|examples=&lt;br /&gt;
&amp;lt;lsl&amp;gt;llRotBetween(&amp;lt;1.0, 0.0, 0.0&amp;gt;, &amp;lt;0.0, -1.0, 0.0&amp;gt;)&lt;br /&gt;
// will return &amp;lt;0.00000, 0.00000, -0.70711, 0.70711&amp;gt; (which represents -90 degrees on the z axis)&lt;br /&gt;
&lt;br /&gt;
llRotBetween(&amp;lt;0.0, 0.0, 0.0&amp;gt;, &amp;lt;0.0, -1.0, 0.0&amp;gt;)&lt;br /&gt;
// will return &amp;lt;0.00000, 0.00000, 0.00000, 1.00000&amp;gt; (which represents a zero angle on all axis)&lt;br /&gt;
// because &amp;lt;0.0, 0.0, 0.0&amp;gt; does not convey a direction.&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_functions={{LSL DefineRow||[[llAngleBetween]]}}&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles&lt;br /&gt;
|helpers=This function adjusts the magnitude of the quaternion so &amp;lt;code&amp;gt;start * llRotBetween(start, end) == end&amp;lt;/code&amp;gt; is true as long as neither have a magnitude really close to zero. They do not have to have the same magnitude. (If either is too close to zero than this will return an unadjusted quaternion). While this is mathematically correct, it won&#039;t help with floating point rounding errors, so it&#039;s more accurate to say &amp;lt;code&amp;gt;start * return ≈ end&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;lsl&amp;gt;rotation RotBetween(vector start, vector end) //adjusts quaternion magnitude so (start * return == end) &lt;br /&gt;
{//Authors note: I have never had a use for this but it&#039;s good to know how to do it if I did.&lt;br /&gt;
    rotation rot = llRotBetween(start, end);&lt;br /&gt;
    float d = start * start;&lt;br /&gt;
    if(d)//is &#039;start&#039; zero?&lt;br /&gt;
        if((d = llPow(end * end / d, 0.25)))//is &#039;end&#039; zero?&lt;br /&gt;
            return &amp;lt;rot.x * d, rot.y * d, rot.z * d, rot.s * d&amp;gt;;&lt;br /&gt;
    return rot;&lt;br /&gt;
}//Strife Onizuka&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|notes=&lt;br /&gt;
Vectors that are near opposite each other in direction may lead to erroneous results. &lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
// First Vector is due north second vector is ALMOST due south.&lt;br /&gt;
rotation lRotation = llRotBetween( &amp;lt;0., 1., 0.&amp;gt;, &amp;lt;-0.001, -.1, 0.&amp;gt; );&lt;br /&gt;
llSay(0, lRotation );&lt;br /&gt;
// Provides a result of &amp;lt;1.00000, 0.00000, 0.00000, 0.00000&amp;gt;.&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|location={{SourceLink/bitbucket|viewer-release|indra/llmath/llquaternion.cpp|line=425}}&lt;br /&gt;
|deepnotes= === Replacement ===&lt;br /&gt;
Due to the annoying quirks of this function {{User|Moon Metty}} wrote a drop in replacement. - {{Jira|SCR-309}}.&lt;br /&gt;
The maximum error is reported to be 2.7e-7 @ 2.2 radians.&lt;br /&gt;
&amp;lt;lsl&amp;gt;rotation RotBetween(vector a, vector b)&lt;br /&gt;
{&lt;br /&gt;
    float aabb = llSqrt((a * a) * (b * b)); // product of the lengths of the arguments&lt;br /&gt;
    if (aabb)&lt;br /&gt;
    {&lt;br /&gt;
        float ab = (a * b) / aabb; // normalized dotproduct of the arguments (cosine)&lt;br /&gt;
        vector c = &amp;lt;(a.y * b.z - a.z * b.y) / aabb,&lt;br /&gt;
                    (a.z * b.x - a.x * b.z) / aabb,&lt;br /&gt;
                    (a.x * b.y - a.y * b.x) / aabb &amp;gt;; // normalized crossproduct of the arguments&lt;br /&gt;
        float cc = c * c; // squared length of the normalized crossproduct (sine)&lt;br /&gt;
        if (cc) // test if the arguments are not (anti)parallel&lt;br /&gt;
        {&lt;br /&gt;
            float s;&lt;br /&gt;
            if (ab &amp;gt; -0.707107)&lt;br /&gt;
                s = 1 + ab; // use the cosine to adjust the s-element&lt;br /&gt;
            else &lt;br /&gt;
                s = cc / (1 + llSqrt(1 - cc)); // use the sine to adjust the s-element&lt;br /&gt;
            float m = llSqrt(cc + s * s); // the magnitude of the quaternion&lt;br /&gt;
            return &amp;lt;c.x / m, c.y / m, c.z / m, s / m&amp;gt;; // return the normalized quaternion&lt;br /&gt;
        }&lt;br /&gt;
        if (ab &amp;gt; 0) &lt;br /&gt;
            return ZERO_ROTATION; // the arguments are parallel, or anti-parallel if not true:&lt;br /&gt;
        float m = llSqrt(a.x * a.x + a.y * a.y); // the length of one argument projected on the XY-plane&lt;br /&gt;
        if (m) &lt;br /&gt;
            return &amp;lt;a.y / m, -a.x / m, 0, 0&amp;gt;; // return a rotation with the axis in the XY-plane&lt;br /&gt;
        return &amp;lt;1, 0, 0, 0&amp;gt;; // the arguments are parallel to the Z-axis, rotate around the X-axis&lt;br /&gt;
    }&lt;br /&gt;
    return ZERO_ROTATION; // the arguments are too small, return zero rotation&lt;br /&gt;
}//Written by Moon Metty, optimized by Strife Onizuka&lt;br /&gt;
 &lt;br /&gt;
// This version keeps the axis in the XY-plane, in case of anti-parallel vectors (unlike the current LL implementation). -- Moon Metty&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Bad Reference Implementation===&lt;br /&gt;
&amp;lt;lsl&amp;gt;//Loosely based on SL source code, like SL&#039;s version, it&#039;s not very accurate. You want to use the above version.&lt;br /&gt;
rotation llRotBetween(vector start, vector end) {&lt;br /&gt;
    vector v1 = llVecNorm(start);&lt;br /&gt;
    vector v2 = llVecNorm(end);&lt;br /&gt;
    float dot = v1 * v2;&lt;br /&gt;
    vector axis = v1 % v2;&lt;br /&gt;
    if (dot &amp;lt; -0.9999999) {&lt;br /&gt;
        // 180 degrees or there abouts&lt;br /&gt;
        vector ortho_axis = llVecNorm(&amp;lt;1.f, 0.f, 0.f&amp;gt; - (sn * (sn.x / (sn * sn))));&lt;br /&gt;
        if (ortho_axis)&lt;br /&gt;
            return &amp;lt; ortho_axis.x, ortho_axis.y, ortho_axis.z, 0.f&amp;gt;;&lt;br /&gt;
        return &amp;lt;0.0, 0.0, 1.0, 0.0&amp;gt;;&lt;br /&gt;
    }&lt;br /&gt;
    else if(dot &amp;gt; 0.9999999) {&lt;br /&gt;
        //parallel&lt;br /&gt;
        return ZERO_ROTATION;&lt;br /&gt;
    }&lt;br /&gt;
    dot = dot + 1.0;&lt;br /&gt;
    float m = llPow((axis * axis) + (dot * dot), -0.5);&lt;br /&gt;
    return &amp;lt;axis.x * m, axis.y * m, axis.z * m, dot * m&amp;gt;;&lt;br /&gt;
}&amp;lt;/lsl&amp;gt;&lt;br /&gt;
===llRotBetween alternatives===&lt;br /&gt;
[[User:Dora_Gustafson/llRotBetween_alternatives#llRotBetween.2C_some_alternatives_and_considerations|Alternatives and considerations]]&lt;br /&gt;
|cat1=Math/3D&lt;br /&gt;
|cat2=Rotation&lt;br /&gt;
|cat3&lt;br /&gt;
|cat4&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LlRotBetween&amp;diff=1193711</id>
		<title>LlRotBetween</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LlRotBetween&amp;diff=1193711"/>
		<updated>2014-10-03T12:39:32Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|inject-2={{Issues/SVC-4415}}{{Issues/SCR-309}}&lt;br /&gt;
|func_id=21|func_sleep=0.0|func_energy=10.0&lt;br /&gt;
|func=llRotBetween&lt;br /&gt;
|return_type=rotation|p1_type=vector|p1_name=start|p2_type=vector|p2_name=end&lt;br /&gt;
|func_footnote&lt;br /&gt;
|func_desc&lt;br /&gt;
|return_text=that is the shortest rotation between the direction {{LSLP|start}} and the direction {{LSLP|end}} &lt;br /&gt;
|spec={{LSLP|start}} and {{LSLP|end}} are directions and are relative to the origin &amp;lt;0.0, 0.0, 0.0&amp;gt;. If you have coordinates relative to a different origin, subtract that origin from the input vectors.&lt;br /&gt;
|caveats=&lt;br /&gt;
*&amp;lt;code&amp;gt;start * llRotBetween(start, end) == end&amp;lt;/code&amp;gt; is only true if {{LSLP|start}} and {{LSLP|end}} have the same magnitude and neither have a magnitude of zero (see [[#Useful Snippets]] for a workaround).&lt;br /&gt;
**This of course is ignoring floating point precision errors.&lt;br /&gt;
* The above is true because of different vector magnitudes. The rotation returned is correct regardless of vector sizes (reserved rounding errors)&lt;br /&gt;
* Rotations are from -PI to +PI around each axis.&lt;br /&gt;
|constants&lt;br /&gt;
|examples=&lt;br /&gt;
&amp;lt;lsl&amp;gt;llRotBetween(&amp;lt;1.0, 0.0, 0.0&amp;gt;, &amp;lt;0.0, -1.0, 0.0&amp;gt;)&lt;br /&gt;
// will return &amp;lt;0.00000, 0.00000, -0.70711, 0.70711&amp;gt; (which represents -90 degrees on the z axis)&lt;br /&gt;
&lt;br /&gt;
llRotBetween(&amp;lt;0.0, 0.0, 0.0&amp;gt;, &amp;lt;0.0, -1.0, 0.0&amp;gt;)&lt;br /&gt;
// will return &amp;lt;0.00000, 0.00000, 0.00000, 1.00000&amp;gt; (which represents a zero angle on all axis)&lt;br /&gt;
// because &amp;lt;0.0, 0.0, 0.0&amp;gt; does not convey a direction.&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_functions={{LSL DefineRow||[[llAngleBetween]]}}&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles&lt;br /&gt;
|helpers=This function adjusts the magnitude of the quaternion so &amp;lt;code&amp;gt;start * llRotBetween(start, end) == end&amp;lt;/code&amp;gt; is true as long as neither have a magnitude really close to zero. They do not have to have the same magnitude. (If either is too close to zero than this will return an unadjusted quaternion). While this is mathematically correct, it won&#039;t help with floating point rounding errors, so it&#039;s more accurate to say &amp;lt;code&amp;gt;start * return ≈ end&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;lsl&amp;gt;rotation RotBetween(vector start, vector end) //adjusts quaternion magnitude so (start * return == end) &lt;br /&gt;
{//Authors note: I have never had a use for this but it&#039;s good to know how to do it if I did.&lt;br /&gt;
    rotation rot = llRotBetween(start, end);&lt;br /&gt;
    float d = start * start;&lt;br /&gt;
    if(d)//is &#039;start&#039; zero?&lt;br /&gt;
        if((d = llPow(end * end / d, 0.25)))//is &#039;end&#039; zero?&lt;br /&gt;
            return &amp;lt;rot.x * d, rot.y * d, rot.z * d, rot.s * d&amp;gt;;&lt;br /&gt;
    return rot;&lt;br /&gt;
}//Strife Onizuka&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|notes=&lt;br /&gt;
Vectors that are near opposite each other in direction may lead to erroneous results. &lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
// First Vector is due north second vector is ALMOST due south.&lt;br /&gt;
rotation lRotation = llRotBetween( &amp;lt;0., 1., 0.&amp;gt;, &amp;lt;-0.001, -.1, 0.&amp;gt; );&lt;br /&gt;
llSay(0, lRotation );&lt;br /&gt;
// Provides a result of &amp;lt;1.00000, 0.00000, 0.00000, 0.00000&amp;gt;.&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|location={{SourceLink/bitbucket|viewer-release|indra/llmath/llquaternion.cpp|line=425}}&lt;br /&gt;
|deepnotes= === Replacement ===&lt;br /&gt;
Due to the annoying quirks of this function {{User|Moon Metty}} wrote a drop in replacement. - {{Jira|SCR-309}}.&lt;br /&gt;
The maximum error is reported to be 2.7e-7 @ 2.2 radians.&lt;br /&gt;
&amp;lt;lsl&amp;gt;rotation RotBetween(vector a, vector b)&lt;br /&gt;
{&lt;br /&gt;
    float aabb = llSqrt((a * a) * (b * b)); // product of the lengths of the arguments&lt;br /&gt;
    if (aabb)&lt;br /&gt;
    {&lt;br /&gt;
        float ab = (a * b) / aabb; // normalized dotproduct of the arguments (cosine)&lt;br /&gt;
        vector c = &amp;lt;(a.y * b.z - a.z * b.y) / aabb,&lt;br /&gt;
                    (a.z * b.x - a.x * b.z) / aabb,&lt;br /&gt;
                    (a.x * b.y - a.y * b.x) / aabb &amp;gt;; // normalized crossproduct of the arguments&lt;br /&gt;
        float cc = c * c; // squared length of the normalized crossproduct (sine)&lt;br /&gt;
        if (cc) // test if the arguments are not (anti)parallel&lt;br /&gt;
        {&lt;br /&gt;
            float s;&lt;br /&gt;
            if (ab &amp;gt; -0.707107)&lt;br /&gt;
                s = 1 + ab; // use the cosine to adjust the s-element&lt;br /&gt;
            else &lt;br /&gt;
                s = cc / (1 + llSqrt(1 - cc)); // use the sine to adjust the s-element&lt;br /&gt;
            float m = llSqrt(cc + s * s); // the magnitude of the quaternion&lt;br /&gt;
            return &amp;lt;c.x / m, c.y / m, c.z / m, s / m&amp;gt;; // return the normalized quaternion&lt;br /&gt;
        }&lt;br /&gt;
        if (ab &amp;gt; 0) &lt;br /&gt;
            return ZERO_ROTATION; // the arguments are parallel, or anti-parallel if not true:&lt;br /&gt;
        float m = llSqrt(a.x * a.x + a.y * a.y); // the length of one argument projected on the XY-plane&lt;br /&gt;
        if (m) &lt;br /&gt;
            return &amp;lt;a.y / m, -a.x / m, 0, 0&amp;gt;; // return a rotation with the axis in the XY-plane&lt;br /&gt;
        return &amp;lt;1, 0, 0, 0&amp;gt;; // the arguments are parallel to the Z-axis, rotate around the X-axis&lt;br /&gt;
    }&lt;br /&gt;
    return ZERO_ROTATION; // the arguments are too small, return zero rotation&lt;br /&gt;
}//Written by Moon Metty, optimized by Strife Onizuka&lt;br /&gt;
 &lt;br /&gt;
// This version keeps the axis in the XY-plane, in case of anti-parallel vectors (unlike the current LL implementation). -- Moon Metty&amp;lt;/lsl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Bad Reference Implementation===&lt;br /&gt;
&amp;lt;lsl&amp;gt;//Loosely based on SL source code, like SL&#039;s version, it&#039;s not very accurate. You want to use the above version.&lt;br /&gt;
rotation llRotBetween(vector start, vector end) {&lt;br /&gt;
    vector v1 = llVecNorm(start);&lt;br /&gt;
    vector v2 = llVecNorm(end);&lt;br /&gt;
    float dot = v1 * v2;&lt;br /&gt;
    vector axis = v1 % v2;&lt;br /&gt;
    if (dot &amp;lt; -0.9999999) {&lt;br /&gt;
        // 180 degrees or there abouts&lt;br /&gt;
        vector ortho_axis = llVecNorm(&amp;lt;1.f, 0.f, 0.f&amp;gt; - (sn * (sn.x / (sn * sn))));&lt;br /&gt;
        if (ortho_axis)&lt;br /&gt;
            return &amp;lt; ortho_axis.x, ortho_axis.y, ortho_axis.z, 0.f&amp;gt;;&lt;br /&gt;
        return &amp;lt;0.0, 0.0, 1.0, 0.0&amp;gt;;&lt;br /&gt;
    }&lt;br /&gt;
    else if(dot &amp;gt; 0.9999999) {&lt;br /&gt;
        //parallel&lt;br /&gt;
        return ZERO_ROTATION;&lt;br /&gt;
    }&lt;br /&gt;
    dot = dot + 1.0;&lt;br /&gt;
    float m = llPow((axis * axis) + (dot * dot), -0.5);&lt;br /&gt;
    return &amp;lt;axis.x * m, axis.y * m, axis.z * m, dot * m&amp;gt;;&lt;br /&gt;
}&amp;lt;/lsl&amp;gt;&lt;br /&gt;
===llRotBetween alternatives===&lt;br /&gt;
[[User:Dora_Gustafson/llRotBetween_alternatives#llRotBetween.2C_some_alternatives_and_considerations|Alternatives and considerations]]&lt;br /&gt;
|cat1=Math/3D&lt;br /&gt;
|cat2=Rotation&lt;br /&gt;
|cat3&lt;br /&gt;
|cat4&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LlTargetOmega_Replacement&amp;diff=1193686</id>
		<title>LlTargetOmega Replacement</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LlTargetOmega_Replacement&amp;diff=1193686"/>
		<updated>2014-10-01T12:35:09Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: Undo revision 1193685 by Dora Gustafson (Talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|func=KeyFramedOmega&lt;br /&gt;
|func_id&lt;br /&gt;
|func_sleep&lt;br /&gt;
|func_energy&lt;br /&gt;
|func_desc=Rotates the object/prim around axis at a rate of spinrate in radians per second&lt;br /&gt;
|func_footnote&lt;br /&gt;
|return_type&lt;br /&gt;
|return_text&lt;br /&gt;
|p1_type=vector&lt;br /&gt;
|p1_name=axis&lt;br /&gt;
|p1_desc=arbitrary axis to rotate the object around&lt;br /&gt;
|p1_hover&lt;br /&gt;
|p2_type=float&lt;br /&gt;
|p2_name=spinrate&lt;br /&gt;
|p2_desc=rate of rotation in radians per second&lt;br /&gt;
|p2_hover&lt;br /&gt;
|constants&lt;br /&gt;
|spec=&lt;br /&gt;
: This doesn&#039;t make [[llTargetOmega]] redundant but in some cases a Key Framed motion may be preferred&lt;br /&gt;
: The routine: &amp;quot;KeyFramedOmega&amp;quot; is easy to use for [[llTargetOmega]]: It takes the first two parameters in [[llTargetOmega]]: axis and spinrate&lt;br /&gt;
: All viewers will see the same spin and rotation&lt;br /&gt;
: The object will keep the rotation it has when spin is stopped&lt;br /&gt;
: A spin will continue even when the script is deleted&lt;br /&gt;
|caveats=&lt;br /&gt;
: The script must be in the root prim&lt;br /&gt;
: It can not spin child prims&lt;br /&gt;
: The object must be convex hull physics type&lt;br /&gt;
: Can not spin physical objects&lt;br /&gt;
|examples=&lt;br /&gt;
This script shows how to use the routine to start, stop and reverse a spin on repeated touches&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
// llTargetOmega substitution by Dora Gustafson, Studio Dora 2014&lt;br /&gt;
&lt;br /&gt;
integer P;&lt;br /&gt;
&lt;br /&gt;
KeyFramedOmega( vector axis, float spinrate)&lt;br /&gt;
{&lt;br /&gt;
    llSetKeyframedMotion( [], []);&lt;br /&gt;
    if ( spinrate )&lt;br /&gt;
    {&lt;br /&gt;
        float v = TWO_PI/3.0;&lt;br /&gt;
        if ( spinrate &amp;lt; 0 ) v = -v;&lt;br /&gt;
        list L = [llAxisAngle2Rot( axis/llGetRot(), v), v/spinrate];&lt;br /&gt;
        llSetKeyframedMotion( L+L+L, [KFM_DATA, KFM_ROTATION, KFM_MODE, KFM_LOOP]);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);&lt;br /&gt;
    }&lt;br /&gt;
    touch_end( integer n)&lt;br /&gt;
    {&lt;br /&gt;
        P = ++P%4;&lt;br /&gt;
        if ( P == 1 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 2.0);       // Positive spin&lt;br /&gt;
        else if ( P == 3 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, -2.0); // Negative spin&lt;br /&gt;
        else KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 0.0);                // Stop spin&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_header&lt;br /&gt;
|also_functions=: [[llTargetOmega]]&lt;br /&gt;
: [[llSetKeyframedMotion]]&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles&lt;br /&gt;
|also_footer&lt;br /&gt;
|notes=The magnitude of &#039;&#039;axis&#039;&#039; do &#039;&#039;&#039;not&#039;&#039;&#039; influence the &#039;&#039;spinrate&#039;&#039;&lt;br /&gt;
|mode=user&lt;br /&gt;
|deprecated&lt;br /&gt;
|location=[[User:Dora_Gustafson/Replacing_llTargetOmega/function|The Function]]&lt;br /&gt;
|cat1=Rotation&lt;br /&gt;
|cat2=Examples&lt;br /&gt;
|signature=[[User:Dora Gustafson|Dora Gustafson]] 04:36, 12 August 2014 (PDT)&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LlTargetOmega_Replacement&amp;diff=1193685</id>
		<title>LlTargetOmega Replacement</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LlTargetOmega_Replacement&amp;diff=1193685"/>
		<updated>2014-10-01T12:31:57Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|func=KeyFramedOmega&lt;br /&gt;
|func_id&lt;br /&gt;
|func_sleep&lt;br /&gt;
|func_energy&lt;br /&gt;
|func_desc=Rotates the object/prim around axis at a rate of spinrate in radians per second&lt;br /&gt;
|func_footnote&lt;br /&gt;
|return_type&lt;br /&gt;
|return_text&lt;br /&gt;
|p1_type=vector&lt;br /&gt;
|p1_name=axis&lt;br /&gt;
|p1_desc=arbitrary axis to rotate the object around&lt;br /&gt;
|p1_hover&lt;br /&gt;
|p2_type=float&lt;br /&gt;
|p2_name=spinrate&lt;br /&gt;
|p2_desc=rate of rotation in radians per second&lt;br /&gt;
|p2_hover&lt;br /&gt;
|constants&lt;br /&gt;
|spec=&lt;br /&gt;
: This doesn&#039;t make [[llTargetOmega]] redundant but in some cases a Key Framed motion may be preferred&lt;br /&gt;
: The routine: [[KeyFramedOmega]] is easy to use for [[llTargetOmega]]: It takes the first two parameters in [[llTargetOmega]]: axis and spinrate&lt;br /&gt;
: All viewers will see the same spin and rotation&lt;br /&gt;
: The object will keep the rotation it has when spin is stopped&lt;br /&gt;
: A spin will continue even when the script is deleted&lt;br /&gt;
|caveats=&lt;br /&gt;
: The script must be in the root prim&lt;br /&gt;
: It can not spin child prims&lt;br /&gt;
: The object must be convex hull physics type&lt;br /&gt;
: Can not spin physical objects&lt;br /&gt;
|examples=&lt;br /&gt;
This script shows how to use the routine to start, stop and reverse a spin on repeated touches&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
// llTargetOmega substitution by Dora Gustafson, Studio Dora 2014&lt;br /&gt;
&lt;br /&gt;
integer P;&lt;br /&gt;
&lt;br /&gt;
KeyFramedOmega( vector axis, float spinrate)&lt;br /&gt;
{&lt;br /&gt;
    llSetKeyframedMotion( [], []);&lt;br /&gt;
    if ( spinrate )&lt;br /&gt;
    {&lt;br /&gt;
        float v = TWO_PI/3.0;&lt;br /&gt;
        if ( spinrate &amp;lt; 0 ) v = -v;&lt;br /&gt;
        list L = [llAxisAngle2Rot( axis/llGetRot(), v), v/spinrate];&lt;br /&gt;
        llSetKeyframedMotion( L+L+L, [KFM_DATA, KFM_ROTATION, KFM_MODE, KFM_LOOP]);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);&lt;br /&gt;
    }&lt;br /&gt;
    touch_end( integer n)&lt;br /&gt;
    {&lt;br /&gt;
        P = ++P%4;&lt;br /&gt;
        if ( P == 1 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 2.0);       // Positive spin&lt;br /&gt;
        else if ( P == 3 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, -2.0); // Negative spin&lt;br /&gt;
        else KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 0.0);                // Stop spin&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_header&lt;br /&gt;
|also_functions=: [[llTargetOmega]]&lt;br /&gt;
: [[llSetKeyframedMotion]]&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles&lt;br /&gt;
|also_footer&lt;br /&gt;
|notes=The magnitude of &#039;&#039;axis&#039;&#039; do &#039;&#039;&#039;not&#039;&#039;&#039; influence the &#039;&#039;spinrate&#039;&#039;&lt;br /&gt;
|mode=user&lt;br /&gt;
|deprecated&lt;br /&gt;
|location=[[User:Dora_Gustafson/Replacing_llTargetOmega/function|The Function]]&lt;br /&gt;
|cat1=Rotation&lt;br /&gt;
|cat2=Examples&lt;br /&gt;
|signature=[[User:Dora Gustafson|Dora Gustafson]] 04:36, 12 August 2014 (PDT)&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson&amp;diff=1193684</id>
		<title>User:Dora Gustafson</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson&amp;diff=1193684"/>
		<updated>2014-10-01T12:17:35Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: /* Highlighted scripts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Header}}&lt;br /&gt;
&amp;lt;div id=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
== About ==&lt;br /&gt;
I have been a premium since spring 2007.&amp;lt;br&amp;gt;&lt;br /&gt;
Over the time I made quite a few scripts.&amp;lt;br&amp;gt;&lt;br /&gt;
The scripts are the basis for my business.&amp;lt;br&amp;gt;&lt;br /&gt;
Many are published in the SL forums and some are given away.&amp;lt;br&amp;gt;&lt;br /&gt;
Here are some working scripts that highlights LSL functions and SL characteristics&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;box&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Highlighted scripts ==&lt;br /&gt;
#[[User:Dora_Gustafson/talking_die|Talking Die]]&lt;br /&gt;
#[[User:Dora_Gustafson/llAxes2Rot_right_and_wrong|llAxes2Rot]] Right and Wrong&lt;br /&gt;
#[[User:Dora_Gustafson/point_tracker|Key framed Motion forward on a closed track]]&lt;br /&gt;
#[[User:Dora_Gustafson/Basic_Resizer|Re-size or re-scale objects with a single small script]]&lt;br /&gt;
#[[User:Dora_Gustafson/sundirection_and_time_of_day|Show Sun Direction and compare to Time of Day]]&lt;br /&gt;
#[[User:Dora_Gustafson/universal_hinged_motion|Universal hinged motion]] in 8 Key Frames&lt;br /&gt;
#[[User:Dora_Gustafson/Pendulum_motion|Pendulum motion]] Simple Pendulum Motion in 24 Key Frames, a good swing motion&lt;br /&gt;
#[[User:Dora_Gustafson/Harmonic_Oscillator_motion|Harmonic Oscillator motion]] Motion in 12 Key Frames&lt;br /&gt;
#[[User:Dora_Gustafson/captureCameraView|Capture Camera View]] Using llSetLinkCamera()&lt;br /&gt;
#[[User:Dora_Gustafson/llRotBetween_alternatives#llRotBetween.2C_some_alternatives_and_considerations|llRotBetween]] alternatives and considerations&lt;br /&gt;
#[[User:Dora_Gustafson/fixed_3D_relation|Fixed 3D Relation]] Position and Rotation computations&lt;br /&gt;
#[[User:Dora_Gustafson/JSON_structure_facial_expression|JSON structured menu]] for all facial expressions&lt;br /&gt;
#[[User:Dora_Gustafson/insertion_sort|Straight insertion Sort script]]&lt;br /&gt;
#[[User:Dora_Gustafson/occurences|Count occurencces in a list]]&lt;br /&gt;
#[[User:Dora_Gustafson/bezier_toy|Bézier Toy]]&lt;br /&gt;
#[[LlTargetOmega_Replacement|Replacing llTargetOmega]] with a Key Framed Motion&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega&amp;diff=1193683</id>
		<title>User:Dora Gustafson/Replacing llTargetOmega</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega&amp;diff=1193683"/>
		<updated>2014-10-01T12:15:56Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: Replaced content with &amp;quot;== Content moved ==
Moved to LlTargetOmega_Replacement
: ~~~~&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Content moved ==&lt;br /&gt;
Moved to [[LlTargetOmega_Replacement]]&lt;br /&gt;
: [[User:Dora Gustafson|Dora Gustafson]] 05:15, 1 October 2014 (PDT)&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LlTargetOmega_Replacement&amp;diff=1193682</id>
		<title>LlTargetOmega Replacement</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LlTargetOmega_Replacement&amp;diff=1193682"/>
		<updated>2014-10-01T11:59:09Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: Created page with &amp;quot;{{LSL_Function |func=KeyFramedOmega |func_id |func_sleep |func_energy |func_desc=Rotates the object/prim around axis at a rate of spinrate in radians per second |func_footnote |r…&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|func=KeyFramedOmega&lt;br /&gt;
|func_id&lt;br /&gt;
|func_sleep&lt;br /&gt;
|func_energy&lt;br /&gt;
|func_desc=Rotates the object/prim around axis at a rate of spinrate in radians per second&lt;br /&gt;
|func_footnote&lt;br /&gt;
|return_type&lt;br /&gt;
|return_text&lt;br /&gt;
|p1_type=vector&lt;br /&gt;
|p1_name=axis&lt;br /&gt;
|p1_desc=arbitrary axis to rotate the object around&lt;br /&gt;
|p1_hover&lt;br /&gt;
|p2_type=float&lt;br /&gt;
|p2_name=spinrate&lt;br /&gt;
|p2_desc=rate of rotation in radians per second&lt;br /&gt;
|p2_hover&lt;br /&gt;
|constants&lt;br /&gt;
|spec=&lt;br /&gt;
: This doesn&#039;t make [[llTargetOmega]] redundant but in some cases a Key Framed motion may be preferred&lt;br /&gt;
: The routine: &amp;quot;KeyFramedOmega&amp;quot; is easy to use for [[llTargetOmega]]: It takes the first two parameters in [[llTargetOmega]]: axis and spinrate&lt;br /&gt;
: All viewers will see the same spin and rotation&lt;br /&gt;
: The object will keep the rotation it has when spin is stopped&lt;br /&gt;
: A spin will continue even when the script is deleted&lt;br /&gt;
|caveats=&lt;br /&gt;
: The script must be in the root prim&lt;br /&gt;
: It can not spin child prims&lt;br /&gt;
: The object must be convex hull physics type&lt;br /&gt;
: Can not spin physical objects&lt;br /&gt;
|examples=&lt;br /&gt;
This script shows how to use the routine to start, stop and reverse a spin on repeated touches&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
// llTargetOmega substitution by Dora Gustafson, Studio Dora 2014&lt;br /&gt;
&lt;br /&gt;
integer P;&lt;br /&gt;
&lt;br /&gt;
KeyFramedOmega( vector axis, float spinrate)&lt;br /&gt;
{&lt;br /&gt;
    llSetKeyframedMotion( [], []);&lt;br /&gt;
    if ( spinrate )&lt;br /&gt;
    {&lt;br /&gt;
        float v = TWO_PI/3.0;&lt;br /&gt;
        if ( spinrate &amp;lt; 0 ) v = -v;&lt;br /&gt;
        list L = [llAxisAngle2Rot( axis/llGetRot(), v), v/spinrate];&lt;br /&gt;
        llSetKeyframedMotion( L+L+L, [KFM_DATA, KFM_ROTATION, KFM_MODE, KFM_LOOP]);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);&lt;br /&gt;
    }&lt;br /&gt;
    touch_end( integer n)&lt;br /&gt;
    {&lt;br /&gt;
        P = ++P%4;&lt;br /&gt;
        if ( P == 1 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 2.0);       // Positive spin&lt;br /&gt;
        else if ( P == 3 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, -2.0); // Negative spin&lt;br /&gt;
        else KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 0.0);                // Stop spin&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_header&lt;br /&gt;
|also_functions=: [[llTargetOmega]]&lt;br /&gt;
: [[llSetKeyframedMotion]]&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles&lt;br /&gt;
|also_footer&lt;br /&gt;
|notes=The magnitude of &#039;&#039;axis&#039;&#039; do &#039;&#039;&#039;not&#039;&#039;&#039; influence the &#039;&#039;spinrate&#039;&#039;&lt;br /&gt;
|mode=user&lt;br /&gt;
|deprecated&lt;br /&gt;
|location=[[User:Dora_Gustafson/Replacing_llTargetOmega/function|The Function]]&lt;br /&gt;
|cat1=Rotation&lt;br /&gt;
|cat2=Examples&lt;br /&gt;
|signature=[[User:Dora Gustafson|Dora Gustafson]] 04:36, 12 August 2014 (PDT)&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=VEHICLE_REFERENCE_FRAME&amp;diff=1193479</id>
		<title>VEHICLE REFERENCE FRAME</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=VEHICLE_REFERENCE_FRAME&amp;diff=1193479"/>
		<updated>2014-09-17T18:16:28Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: Undo revision 1193477 by Dora Gustafson (Talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Constant&lt;br /&gt;
|name=VEHICLE_REFERENCE_FRAME&lt;br /&gt;
|type=integer&lt;br /&gt;
|value=44&lt;br /&gt;
|desc=Used to set the rotation of vehicle axes relative to local frame.&lt;br /&gt;
|examples=The rotation for the reference frame can be found in two steps:&lt;br /&gt;
# Place the vehicle with front facing east(red arrow) and with left side facing north(green arrow)&lt;br /&gt;
# now: [[rotation]] refFrame = [[ZERO_ROTATION]] / [[llGetRootRotation]]();&lt;br /&gt;
|events&lt;br /&gt;
|functions={{LSL DefineRow||[[llSetVehicleRotationParam]]}}&lt;br /&gt;
|location&lt;br /&gt;
|history&lt;br /&gt;
|comment&lt;br /&gt;
|articles={{LSL DefineRow||[[Linden Vehicle Tutorial]]}}&lt;br /&gt;
|cat1=Vehicle/Parameters&lt;br /&gt;
|cat2&lt;br /&gt;
|cat3&lt;br /&gt;
|cat4&lt;br /&gt;
|cat5&lt;br /&gt;
|cat6&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=LlSetVehicleRotationParam&amp;diff=1193478</id>
		<title>LlSetVehicleRotationParam</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=LlSetVehicleRotationParam&amp;diff=1193478"/>
		<updated>2014-09-17T18:13:24Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|func_id=235|func_sleep=0.0|func_energy=10.0&lt;br /&gt;
|func=llSetVehicleRotationParam&lt;br /&gt;
|p1_type=integer|p1_name=param|p1_desc=VEHICLE_* flag&lt;br /&gt;
|p2_type=rotation|p2_name=rot&lt;br /&gt;
|func_footnote&lt;br /&gt;
|func_desc=Sets the vehicle rotation parameter {{LSLP|param}} to {{LSLP|rot}}.&lt;br /&gt;
|return_text&lt;br /&gt;
|spec&lt;br /&gt;
|caveats&lt;br /&gt;
|constants={{LSL Constants/Vehicle|type=rotation}}&lt;br /&gt;
|examples=The reference frame can be computed and set in two steps:&lt;br /&gt;
# Place the vehicle with front facing east(red arrow) and with left side facing north(green arrow)&lt;br /&gt;
# [[llSetVehicleRotationParam]]( [[VEHICLE_REFERENCE_FRAME]], [[ZERO_ROTATION]] / [[llGetRootRotation]]());&lt;br /&gt;
|helpers&lt;br /&gt;
|also_functions={{LSL DefineRow||{{LSLG|llSetVehicleFloatParam}}|Sets a vehicle float parameter}}&lt;br /&gt;
{{LSL DefineRow||{{LSLG|llSetVehicleVectorParam}}|Sets a vehicle vector parmeter}}&lt;br /&gt;
|also_events&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_articles={{LSL DefineRow||[[Linden Vehicle Tutorial]]}}&lt;br /&gt;
|notes&lt;br /&gt;
|permission&lt;br /&gt;
|cat1=Vehicle&lt;br /&gt;
|cat2&lt;br /&gt;
|cat3&lt;br /&gt;
|cat4&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=VEHICLE_REFERENCE_FRAME&amp;diff=1193477</id>
		<title>VEHICLE REFERENCE FRAME</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=VEHICLE_REFERENCE_FRAME&amp;diff=1193477"/>
		<updated>2014-09-17T18:04:34Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Constant&lt;br /&gt;
|name=VEHICLE_REFERENCE_FRAME&lt;br /&gt;
|type=integer&lt;br /&gt;
|value=44&lt;br /&gt;
|desc=Used to set the rotation of vehicle axes relative to local frame.&lt;br /&gt;
|examples&lt;br /&gt;
|events&lt;br /&gt;
|functions={{LSL DefineRow||[[llSetVehicleRotationParam]]}}&lt;br /&gt;
|location&lt;br /&gt;
|history&lt;br /&gt;
|comment&lt;br /&gt;
|articles={{LSL DefineRow||[[Linden Vehicle Tutorial]]}}&lt;br /&gt;
|cat1=Vehicle/Parameters&lt;br /&gt;
|cat2&lt;br /&gt;
|cat3&lt;br /&gt;
|cat4&lt;br /&gt;
|cat5&lt;br /&gt;
|cat6&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=VEHICLE_REFERENCE_FRAME&amp;diff=1193476</id>
		<title>VEHICLE REFERENCE FRAME</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=VEHICLE_REFERENCE_FRAME&amp;diff=1193476"/>
		<updated>2014-09-17T17:31:00Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Constant&lt;br /&gt;
|name=VEHICLE_REFERENCE_FRAME&lt;br /&gt;
|type=integer&lt;br /&gt;
|value=44&lt;br /&gt;
|desc=Used to set the rotation of vehicle axes relative to local frame.&lt;br /&gt;
|examples=The reference frame can be found in two steps:&lt;br /&gt;
# Place the vehicle with front facing east(red arrow) and with left side facing north(green arrow)&lt;br /&gt;
# now: [[rotation]] refFrame = [[ZERO_ROTATION]] / [[llGetRootRotation]]();&lt;br /&gt;
|events&lt;br /&gt;
|functions={{LSL DefineRow||[[llSetVehicleRotationParam]]}}&lt;br /&gt;
|location&lt;br /&gt;
|history&lt;br /&gt;
|comment&lt;br /&gt;
|articles={{LSL DefineRow||[[Linden Vehicle Tutorial]]}}&lt;br /&gt;
|cat1=Vehicle/Parameters&lt;br /&gt;
|cat2&lt;br /&gt;
|cat3&lt;br /&gt;
|cat4&lt;br /&gt;
|cat5&lt;br /&gt;
|cat6&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=VEHICLE_REFERENCE_FRAME&amp;diff=1193474</id>
		<title>VEHICLE REFERENCE FRAME</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=VEHICLE_REFERENCE_FRAME&amp;diff=1193474"/>
		<updated>2014-09-17T17:23:30Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: get reference frame&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL Constant&lt;br /&gt;
|name=VEHICLE_REFERENCE_FRAME&lt;br /&gt;
|type=integer&lt;br /&gt;
|value=44&lt;br /&gt;
|desc=Used to set the rotation of vehicle axes relative to local frame.&lt;br /&gt;
|examples=The reference frame can be found in two steps:&lt;br /&gt;
# Place the vehicle with front facing east(red arrow) and with left side facing north(green arrow)&lt;br /&gt;
# now: rotation refFrame = ZERO_ROTATION / llGetRootRotation();&lt;br /&gt;
|events&lt;br /&gt;
|functions={{LSL DefineRow||[[llSetVehicleRotationParam]]}}&lt;br /&gt;
|location&lt;br /&gt;
|history&lt;br /&gt;
|comment&lt;br /&gt;
|articles={{LSL DefineRow||[[Linden Vehicle Tutorial]]}}&lt;br /&gt;
|cat1=Vehicle/Parameters&lt;br /&gt;
|cat2&lt;br /&gt;
|cat3&lt;br /&gt;
|cat4&lt;br /&gt;
|cat5&lt;br /&gt;
|cat6&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega&amp;diff=1192698</id>
		<title>User:Dora Gustafson/Replacing llTargetOmega</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega&amp;diff=1192698"/>
		<updated>2014-08-12T14:38:06Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|func=KeyFramedOmega&lt;br /&gt;
|func_id&lt;br /&gt;
|func_sleep&lt;br /&gt;
|func_energy&lt;br /&gt;
|func_desc=Rotates the object/prim around axis at a rate of spinrate in radians per second&lt;br /&gt;
|func_footnote&lt;br /&gt;
|return_type&lt;br /&gt;
|return_text&lt;br /&gt;
|p1_type=vector&lt;br /&gt;
|p1_name=axis&lt;br /&gt;
|p1_desc=arbitrary axis to rotate the object around&lt;br /&gt;
|p1_hover&lt;br /&gt;
|p2_type=float&lt;br /&gt;
|p2_name=spinrate&lt;br /&gt;
|p2_desc=rate of rotation in radians per second&lt;br /&gt;
|p2_hover&lt;br /&gt;
|constants&lt;br /&gt;
|spec=&lt;br /&gt;
: This doesn&#039;t make [[llTargetOmega]] redundant but in some cases a Key Framed motion may be preferred&lt;br /&gt;
: The routine: &amp;quot;KeyFramedOmega&amp;quot; is easy to use for [[llTargetOmega]]: It takes the first two parameters in [[llTargetOmega]]: axis and spinrate&lt;br /&gt;
: All viewers will see the same spin and rotation&lt;br /&gt;
: The object will keep the rotation it has when spin is stopped&lt;br /&gt;
: A spin will continue even when the script is deleted&lt;br /&gt;
|caveats=&lt;br /&gt;
: The script must be in the root prim&lt;br /&gt;
: It can not spin child prims&lt;br /&gt;
: The object must be convex hull physics type&lt;br /&gt;
: Can not spin physical objects&lt;br /&gt;
|examples=&lt;br /&gt;
This script shows how to use the routine to start, stop and reverse a spin on repeated touches&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
// llTargetOmega substitution by Dora Gustafson, Studio Dora 2014&lt;br /&gt;
&lt;br /&gt;
integer P;&lt;br /&gt;
&lt;br /&gt;
KeyFramedOmega( vector axis, float spinrate)&lt;br /&gt;
{&lt;br /&gt;
    llSetKeyframedMotion( [], []);&lt;br /&gt;
    if ( spinrate )&lt;br /&gt;
    {&lt;br /&gt;
        float v = TWO_PI/3.0;&lt;br /&gt;
        if ( spinrate &amp;lt; 0 ) v = -v;&lt;br /&gt;
        list L = [llAxisAngle2Rot( axis/llGetRot(), v), v/spinrate];&lt;br /&gt;
        llSetKeyframedMotion( L+L+L, [KFM_DATA, KFM_ROTATION, KFM_MODE, KFM_LOOP]);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);&lt;br /&gt;
    }&lt;br /&gt;
    touch_end( integer n)&lt;br /&gt;
    {&lt;br /&gt;
        P = ++P%4;&lt;br /&gt;
        if ( P == 1 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 2.0);       // Positive spin&lt;br /&gt;
        else if ( P == 3 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, -2.0); // Negative spin&lt;br /&gt;
        else KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 0.0);                // Stop spin&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_header&lt;br /&gt;
|also_functions=: [[llTargetOmega]]&lt;br /&gt;
: [[llSetKeyframedMotion]]&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles&lt;br /&gt;
|also_footer&lt;br /&gt;
|notes=The magnitude of &#039;&#039;axis&#039;&#039; do &#039;&#039;&#039;not&#039;&#039;&#039; influence the &#039;&#039;spinrate&#039;&#039;&lt;br /&gt;
|mode=user&lt;br /&gt;
|deprecated&lt;br /&gt;
|location=[[User:Dora_Gustafson/Replacing_llTargetOmega/function|The Function]]&lt;br /&gt;
|cat1=Rotation&lt;br /&gt;
|cat2=Examples&lt;br /&gt;
|signature=[[User:Dora Gustafson|Dora Gustafson]] 04:36, 12 August 2014 (PDT)&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega&amp;diff=1192684</id>
		<title>User:Dora Gustafson/Replacing llTargetOmega</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega&amp;diff=1192684"/>
		<updated>2014-08-12T11:52:28Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|func=KeyFramedOmega&lt;br /&gt;
|func_id&lt;br /&gt;
|func_sleep&lt;br /&gt;
|func_energy&lt;br /&gt;
|func_desc=Rotates the object/prim around axis at a rate of spinrate in radians per second&lt;br /&gt;
|func_footnote&lt;br /&gt;
|return_type&lt;br /&gt;
|return_text&lt;br /&gt;
|p1_type=vector&lt;br /&gt;
|p1_name=axis&lt;br /&gt;
|p1_desc=arbitrary axis to rotate the object around&lt;br /&gt;
|p1_hover&lt;br /&gt;
|p2_type=float&lt;br /&gt;
|p2_name=spinrate&lt;br /&gt;
|p2_desc=rate of rotation in radians per second&lt;br /&gt;
|p2_hover&lt;br /&gt;
|constants&lt;br /&gt;
|spec=&lt;br /&gt;
: This doesn&#039;t make [[llTargetOmega]] redundant but in some cases a Key Framed motion may be preferred&lt;br /&gt;
: The routine: &amp;quot;KeyFramedOmega&amp;quot; is easy to use for [[llTargetOmega]]: It takes the first two parameters in [[llTargetOmega]]: axis and spinrate&lt;br /&gt;
: All viewers will see the same spin and rotation&lt;br /&gt;
: The object will keep the rotation it has when spin is stopped&lt;br /&gt;
: A spin will continue even when the script is deleted&lt;br /&gt;
|caveats=&lt;br /&gt;
: The script must be in the root prim&lt;br /&gt;
: It can not spin child prims&lt;br /&gt;
: The object must be convex hull physics type&lt;br /&gt;
: Can not spin physical objects&lt;br /&gt;
|examples=&lt;br /&gt;
This script shows how to use the routine to start, stop and reverse a spin on repeated touches&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
// llTargetOmega substitution by Dora Gustafson, Studio Dora 2014&lt;br /&gt;
&lt;br /&gt;
integer P;&lt;br /&gt;
&lt;br /&gt;
KeyFramedOmega( vector axis, float spinrate)&lt;br /&gt;
{&lt;br /&gt;
    llSetKeyframedMotion( [], []);&lt;br /&gt;
    if ( spinrate )&lt;br /&gt;
    {&lt;br /&gt;
        float v = TWO_PI/3.0;&lt;br /&gt;
        if ( spinrate &amp;lt; 0 ) v = -v;&lt;br /&gt;
        list L = [llAxisAngle2Rot( axis/llGetRot(), v), v/spinrate];&lt;br /&gt;
        llSetKeyframedMotion( L+L+L, [KFM_DATA, KFM_ROTATION, KFM_MODE, KFM_LOOP]);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);&lt;br /&gt;
    }&lt;br /&gt;
    touch_end( integer n)&lt;br /&gt;
    {&lt;br /&gt;
        P = ++P%4;&lt;br /&gt;
        if ( P == 1 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 2.0);       // Positive spin&lt;br /&gt;
        else if ( P == 3 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, -2.0); // Negative spin&lt;br /&gt;
        else KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 0.0);                // Stop spin&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_header&lt;br /&gt;
|also_functions=: [[llTargetOmega]]&lt;br /&gt;
: [[llSetKeyframedMotion]]&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles&lt;br /&gt;
|also_footer&lt;br /&gt;
|notes&lt;br /&gt;
|mode=user&lt;br /&gt;
|deprecated&lt;br /&gt;
|location=[[User:Dora_Gustafson/Replacing_llTargetOmega/function|The Function]]&lt;br /&gt;
|cat1=Rotation&lt;br /&gt;
|cat2=Examples&lt;br /&gt;
|signature=[[User:Dora Gustafson|Dora Gustafson]] 04:36, 12 August 2014 (PDT)&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega&amp;diff=1192683</id>
		<title>User:Dora Gustafson/Replacing llTargetOmega</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega&amp;diff=1192683"/>
		<updated>2014-08-12T11:45:22Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|func=KeyFramedOmega&lt;br /&gt;
|func_id&lt;br /&gt;
|func_sleep&lt;br /&gt;
|func_energy&lt;br /&gt;
|func_desc=Rotates the object/prim around axis at a rate of spinrate in radians per second&lt;br /&gt;
|func_footnote&lt;br /&gt;
|return_type&lt;br /&gt;
|return_text&lt;br /&gt;
|p1_type=vector&lt;br /&gt;
|p1_name=axis&lt;br /&gt;
|p1_desc=arbitrary axis to rotate the object around&lt;br /&gt;
|p1_hover&lt;br /&gt;
|p2_type=float&lt;br /&gt;
|p2_name=spinrate&lt;br /&gt;
|p2_desc=rate of rotation in radians per second&lt;br /&gt;
|p2_hover&lt;br /&gt;
|constants&lt;br /&gt;
|spec=&lt;br /&gt;
: This doesn&#039;t make [[llTargetOmega]] redundant but in some cases a Key Framed motion may be preferred&lt;br /&gt;
: The routine: &amp;quot;KeyFramedOmega&amp;quot; is easy to use for [[llTargetOmega]]: It takes the first two parameters in [[llTargetOmega]]: axis and spinrate&lt;br /&gt;
: All viewers will see the same spin and rotation&lt;br /&gt;
: The object will keep the rotation it has when spin is stopped&lt;br /&gt;
: A spin will continue even when the script is deleted&lt;br /&gt;
|caveats=&lt;br /&gt;
: The script must be in the root prim&lt;br /&gt;
: It can not spin child prims&lt;br /&gt;
: The object must be convex hull physics type&lt;br /&gt;
: Can not spin physical objects&lt;br /&gt;
|examples=&lt;br /&gt;
This script shows how to use the routine to start, stop and reverse a spin on repeated touches&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
// llTargetOmega substitution by Dora Gustafson, Studio Dora 2014&lt;br /&gt;
&lt;br /&gt;
integer P;&lt;br /&gt;
&lt;br /&gt;
KeyFramedOmega( vector axis, float spinrate)&lt;br /&gt;
{&lt;br /&gt;
    llSetKeyframedMotion( [], []);&lt;br /&gt;
    if ( spinrate )&lt;br /&gt;
    {&lt;br /&gt;
        float v = TWO_PI/3.0;&lt;br /&gt;
        if ( spinrate &amp;lt; 0 ) v = -v;&lt;br /&gt;
        list L = [llAxisAngle2Rot( axis/llGetRot(), v), v/spinrate];&lt;br /&gt;
        llSetKeyframedMotion( L+L+L, [KFM_DATA, KFM_ROTATION, KFM_MODE, KFM_LOOP]);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);&lt;br /&gt;
    }&lt;br /&gt;
    touch_end( integer n)&lt;br /&gt;
    {&lt;br /&gt;
        P = ++P%4;&lt;br /&gt;
        if ( P == 1 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 2.0);       // Positive spin&lt;br /&gt;
        else if ( P == 3 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, -2.0); // Negative spin&lt;br /&gt;
        else KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 0.0);                // Stop spin&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_header&lt;br /&gt;
|also_functions=: [[llTargetOmega]]&lt;br /&gt;
: [[llSetKeyframedMotion]]&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles&lt;br /&gt;
|also_footer&lt;br /&gt;
|notes&lt;br /&gt;
|mode=user&lt;br /&gt;
|deprecated&lt;br /&gt;
|location=[[User:Dora_Gustafson/Replacing_llTargetOmega/function|The Function]]&lt;br /&gt;
|cat1=Rotation&lt;br /&gt;
|cat2=LSL Examples&lt;br /&gt;
|signature=[[User:Dora Gustafson|Dora Gustafson]] 04:36, 12 August 2014 (PDT)&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega&amp;diff=1192675</id>
		<title>User:Dora Gustafson/Replacing llTargetOmega</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega&amp;diff=1192675"/>
		<updated>2014-08-12T11:36:38Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|func=KeyFramedOmega&lt;br /&gt;
|func_id&lt;br /&gt;
|func_sleep&lt;br /&gt;
|func_energy&lt;br /&gt;
|func_desc=Rotates the object/prim around axis at a rate of spinrate in radians per second&lt;br /&gt;
|func_footnote&lt;br /&gt;
|return_type&lt;br /&gt;
|return_text&lt;br /&gt;
|p1_type=vector&lt;br /&gt;
|p1_name=axis&lt;br /&gt;
|p1_desc=arbitrary axis to rotate the object around&lt;br /&gt;
|p1_hover&lt;br /&gt;
|p2_type=float&lt;br /&gt;
|p2_name=spinrate&lt;br /&gt;
|p2_desc=rate of rotation in radians per second&lt;br /&gt;
|p2_hover&lt;br /&gt;
|constants&lt;br /&gt;
|spec=&lt;br /&gt;
: This doesn&#039;t make [[llTargetOmega]] redundant but in some cases a Key Framed motion may be preferred&lt;br /&gt;
: The routine: &amp;quot;KeyFramedOmega&amp;quot; is easy to use for [[llTargetOmega]]: It takes the first two parameters in [[llTargetOmega]]: axis and spinrate&lt;br /&gt;
: All viewers will see the same spin and rotation&lt;br /&gt;
: The object will keep the rotation it has when spin is stopped&lt;br /&gt;
: A spin will continue even when the script is deleted&lt;br /&gt;
|caveats=&lt;br /&gt;
: The script must be in the root prim&lt;br /&gt;
: It can not spin child prims&lt;br /&gt;
: The object must be convex hull physics type&lt;br /&gt;
: Can not spin physical objects&lt;br /&gt;
|examples=&lt;br /&gt;
This script shows how to use the routine to start, stop and reverse a spin on repeated touches&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
// llTargetOmega substitution by Dora Gustafson, Studio Dora 2014&lt;br /&gt;
&lt;br /&gt;
integer P;&lt;br /&gt;
&lt;br /&gt;
KeyFramedOmega( vector axis, float spinrate)&lt;br /&gt;
{&lt;br /&gt;
    llSetKeyframedMotion( [], []);&lt;br /&gt;
    if ( spinrate )&lt;br /&gt;
    {&lt;br /&gt;
        float v = TWO_PI/3.0;&lt;br /&gt;
        if ( spinrate &amp;lt; 0 ) v = -v;&lt;br /&gt;
        list L = [llAxisAngle2Rot( axis/llGetRot(), v), v/spinrate];&lt;br /&gt;
        llSetKeyframedMotion( L+L+L, [KFM_DATA, KFM_ROTATION, KFM_MODE, KFM_LOOP]);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);&lt;br /&gt;
    }&lt;br /&gt;
    touch_end( integer n)&lt;br /&gt;
    {&lt;br /&gt;
        P = ++P%4;&lt;br /&gt;
        if ( P == 1 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 2.0);       // Positive spin&lt;br /&gt;
        else if ( P == 3 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, -2.0); // Negative spin&lt;br /&gt;
        else KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 0.0);                // Stop spin&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_header&lt;br /&gt;
|also_functions=[[llTargetOmega]]&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles=[[llSetKeyframedMotion]]&lt;br /&gt;
|also_footer&lt;br /&gt;
|notes&lt;br /&gt;
|mode=user&lt;br /&gt;
|deprecated&lt;br /&gt;
|location=[[User:Dora_Gustafson/Replacing_llTargetOmega/function|The Function]]&lt;br /&gt;
|cat1=Rotation&lt;br /&gt;
|cat2&lt;br /&gt;
|signature=[[User:Dora Gustafson|Dora Gustafson]] 04:36, 12 August 2014 (PDT)&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega&amp;diff=1192674</id>
		<title>User:Dora Gustafson/Replacing llTargetOmega</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega&amp;diff=1192674"/>
		<updated>2014-08-12T11:32:10Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LSL_Function&lt;br /&gt;
|func=KeyFramedOmega&lt;br /&gt;
|func_id&lt;br /&gt;
|func_sleep&lt;br /&gt;
|func_energy&lt;br /&gt;
|func_desc=Rotates the object/prim around axis at a rate of spinrate in radians per second&lt;br /&gt;
|func_footnote&lt;br /&gt;
|return_type&lt;br /&gt;
|return_text&lt;br /&gt;
|p1_type=vector&lt;br /&gt;
|p1_name=axis&lt;br /&gt;
|p1_desc=arbitrary axis to rotate the object around&lt;br /&gt;
|p1_hover&lt;br /&gt;
|p2_type=float&lt;br /&gt;
|p2_name=spinrate&lt;br /&gt;
|p2_desc=rate of rotation in radians per second&lt;br /&gt;
|p2_hover&lt;br /&gt;
|constants&lt;br /&gt;
|spec=&lt;br /&gt;
: This doesn&#039;t make [[llTargetOmega]] redundant but in some cases a Key Framed motion may be preferred&lt;br /&gt;
: The routine: &amp;quot;KeyFramedOmega&amp;quot; is easy to use for [[llTargetOmega]]: It takes the first two parameters in [[llTargetOmega]]: axis and spinrate&lt;br /&gt;
: All viewers will see the same spin and rotation&lt;br /&gt;
: The object will keep the rotation it has when spin is stopped&lt;br /&gt;
: A spin will continue even when the script is deleted&lt;br /&gt;
|caveats=&lt;br /&gt;
: The script must be in the root prim&lt;br /&gt;
: It can not spin child prims&lt;br /&gt;
: The object must be convex hull physics type&lt;br /&gt;
: Can not spin physical objects&lt;br /&gt;
|examples=&lt;br /&gt;
This script shows how to use the routine to start, stop and reverse a spin on repeated touches&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
// llTargetOmega substitution by Dora Gustafson, Studio Dora 2014&lt;br /&gt;
&lt;br /&gt;
integer P;&lt;br /&gt;
&lt;br /&gt;
KeyFramedOmega( vector axis, float spinrate)&lt;br /&gt;
{&lt;br /&gt;
    llSetKeyframedMotion( [], []);&lt;br /&gt;
    if ( spinrate )&lt;br /&gt;
    {&lt;br /&gt;
        float v = TWO_PI/3.0;&lt;br /&gt;
        if ( spinrate &amp;lt; 0 ) v = -v;&lt;br /&gt;
        list L = [llAxisAngle2Rot( axis/llGetRot(), v), v/spinrate];&lt;br /&gt;
        llSetKeyframedMotion( L+L+L, [KFM_DATA, KFM_ROTATION, KFM_MODE, KFM_LOOP]);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);&lt;br /&gt;
    }&lt;br /&gt;
    touch_end( integer n)&lt;br /&gt;
    {&lt;br /&gt;
        P = ++P%4;&lt;br /&gt;
        if ( P == 1 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 2.0);       // Positive spin&lt;br /&gt;
        else if ( P == 3 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, -2.0); // Negative spin&lt;br /&gt;
        else KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 0.0);                // Stop spin&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_header&lt;br /&gt;
|also_functions=[[llTargetOmega]]&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles=[[llSetKeyframedMotion]]&lt;br /&gt;
|also_footer&lt;br /&gt;
|notes&lt;br /&gt;
|mode=user&lt;br /&gt;
|deprecated&lt;br /&gt;
|location=[[User:Dora_Gustafson/Replacing_llTargetOmega/function|The Function]]&lt;br /&gt;
|cat1=Rotation&lt;br /&gt;
|cat2&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega/function&amp;diff=1192670</id>
		<title>User:Dora Gustafson/Replacing llTargetOmega/function</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega/function&amp;diff=1192670"/>
		<updated>2014-08-12T11:05:50Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: KeyFramedOmega function&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Replacing llTargetOmega, the function ==&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
KeyFramedOmega( vector axis, float spinrate)&lt;br /&gt;
{&lt;br /&gt;
    llSetKeyframedMotion( [], []);&lt;br /&gt;
    if ( spinrate )&lt;br /&gt;
    {&lt;br /&gt;
        float v = TWO_PI/3.0;&lt;br /&gt;
        if ( spinrate &amp;lt; 0 ) v = -v;&lt;br /&gt;
        list L = [llAxisAngle2Rot( axis/llGetRot(), v), v/spinrate];&lt;br /&gt;
        llSetKeyframedMotion( L+L+L, [KFM_DATA, KFM_ROTATION, KFM_MODE, KFM_LOOP]);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega&amp;diff=1192668</id>
		<title>User:Dora Gustafson/Replacing llTargetOmega</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=User:Dora_Gustafson/Replacing_llTargetOmega&amp;diff=1192668"/>
		<updated>2014-08-12T10:47:27Z</updated>

		<summary type="html">&lt;p&gt;Dora Gustafson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Replacing llTargetOmega with a Key Framed Motion ==&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
KeyFramedOmega( vector axis, float spinrate)&lt;br /&gt;
{&lt;br /&gt;
    llSetKeyframedMotion( [], []);&lt;br /&gt;
    if ( spinrate )&lt;br /&gt;
    {&lt;br /&gt;
        float v = TWO_PI/3.0;&lt;br /&gt;
        if ( spinrate &amp;lt; 0 ) v = -v;&lt;br /&gt;
        list L = [llAxisAngle2Rot( axis/llGetRot(), v), v/spinrate];&lt;br /&gt;
        llSetKeyframedMotion( L+L+L, [KFM_DATA, KFM_ROTATION, KFM_MODE, KFM_LOOP]);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
{{LSL_Function&lt;br /&gt;
|func=KeyFramedOmega&lt;br /&gt;
|func_id&lt;br /&gt;
|func_sleep&lt;br /&gt;
|func_energy&lt;br /&gt;
|func_desc=Rotates the object/prim around axis at a rate of spinrate in radians per second&lt;br /&gt;
|func_footnote&lt;br /&gt;
|return_type&lt;br /&gt;
|return_text&lt;br /&gt;
|p1_type=vector&lt;br /&gt;
|p1_name=axis&lt;br /&gt;
|p1_desc=arbitrary axis to rotate the object around&lt;br /&gt;
|p1_hover&lt;br /&gt;
|p2_type=float&lt;br /&gt;
|p2_name=spinrate&lt;br /&gt;
|p2_desc=rate of rotation in radians per second&lt;br /&gt;
|p2_hover&lt;br /&gt;
|constants&lt;br /&gt;
|spec=&lt;br /&gt;
: This doesn&#039;t make [[llTargetOmega]] redundant but in some cases a Key Framed motion may be preferred&lt;br /&gt;
: The routine: &amp;quot;KeyFramedOmega&amp;quot; is easy to use for [[llTargetOmega]]: It takes the first two parameters in [[llTargetOmega]]: axis and spinrate&lt;br /&gt;
: All viewers will see the same spin and rotation&lt;br /&gt;
: The object will keep the rotation it has when spin is stopped&lt;br /&gt;
: A spin will continue even when the script is deleted&lt;br /&gt;
|caveats=&lt;br /&gt;
: The script must be in the root prim&lt;br /&gt;
: It can not spin child prims&lt;br /&gt;
: The object must be convex hull physics type&lt;br /&gt;
: Can not spin physical objects&lt;br /&gt;
|examples=&lt;br /&gt;
This script shows how to use the routine to start, stop and reverse a spin on repeated touches&lt;br /&gt;
&amp;lt;lsl&amp;gt;&lt;br /&gt;
// llTargetOmega substitution by Dora Gustafson, Studio Dora 2014&lt;br /&gt;
&lt;br /&gt;
integer P;&lt;br /&gt;
&lt;br /&gt;
KeyFramedOmega( vector axis, float spinrate)&lt;br /&gt;
{&lt;br /&gt;
    llSetKeyframedMotion( [], []);&lt;br /&gt;
    if ( spinrate )&lt;br /&gt;
    {&lt;br /&gt;
        float v = TWO_PI/3.0;&lt;br /&gt;
        if ( spinrate &amp;lt; 0 ) v = -v;&lt;br /&gt;
        list L = [llAxisAngle2Rot( axis/llGetRot(), v), v/spinrate];&lt;br /&gt;
        llSetKeyframedMotion( L+L+L, [KFM_DATA, KFM_ROTATION, KFM_MODE, KFM_LOOP]);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);&lt;br /&gt;
    }&lt;br /&gt;
    touch_end( integer n)&lt;br /&gt;
    {&lt;br /&gt;
        P = ++P%4;&lt;br /&gt;
        if ( P == 1 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 2.0);       // Positive spin&lt;br /&gt;
        else if ( P == 3 ) KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, -2.0); // Negative spin&lt;br /&gt;
        else KeyFramedOmega( &amp;lt;0,0,1&amp;gt;, 0.0);                // Stop spin&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lsl&amp;gt;&lt;br /&gt;
|helpers&lt;br /&gt;
|also_header&lt;br /&gt;
|also_functions=[[llTargetOmega]]&lt;br /&gt;
|also_tests&lt;br /&gt;
|also_events&lt;br /&gt;
|also_articles=[[llSetKeyframedMotion]]&lt;br /&gt;
|also_footer&lt;br /&gt;
|notes&lt;br /&gt;
|mode=user&lt;br /&gt;
|deprecated&lt;br /&gt;
|location&lt;br /&gt;
|cat1=LSL Rotation&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dora Gustafson</name></author>
	</entry>
</feed>