OsSlerp

From OpenSimulator

(Difference between revisions)
Jump to: navigation, search
m (Fix typo on according)
m (Typo)
 
(7 intermediate revisions by 2 users not shown)
Line 4: Line 4:
 
|delay=0
 
|delay=0
 
|function_syntax=rotation osSlerp(rotation a, rotation b, float ratio);
 
|function_syntax=rotation osSlerp(rotation a, rotation b, float ratio);
|ossl_example=
+
|description=Slerp is shorthand for spherical linear interpolation, introduced by Ken Shoemake in the context of quaternion interpolation for the purpose of animating 3D rotation.
|description=Returns a rotation that is the spherical interpolation of a and b, according to ratio that can be from 0 (result is a) to 1 (result is b)
+
 
 +
It refers to constant-speed motion along a unit-radius great circle arc, given the ends and an interpolation parameter between 0 and 1.
 +
 
 +
osSlerp Returns a rotation that is the spherical interpolation of a and b, according to ratio that can be from 0.0 (result is a) to 1.0 (result is b)
 
|ossl_example=<source lang="lsl">
 
|ossl_example=<source lang="lsl">
    //Test osSlerp. Kayaker Mangic Sept 2019
+
//
  //This isn't the right way to wiggle a stick (llSetKeyframedMotion is better)
+
// osSlerp Script Example
  //but it does demostrate osSlerp working!
+
// Author: djphil
//Put this script in a prim that is long in the X direction,
+
//
//it will wave it's tip around in a figure 8 (infinity) pattern.
+
 
 +
rotation rot_a;
 +
rotation rot_b;
  
rotation lastrot=ZERO_ROTATION;    //slerp between these two rotations
 
rotation nextrot=ZERO_ROTATION;
 
float t=0.0;                //parameter for calculating angles to slerp between
 
float ratio=1.0;            //does 10 slerp steps of 0.1 between last and next
 
 
default
 
default
 
{
 
{
 
     state_entry()
 
     state_entry()
 
     {
 
     {
         llSetTimerEvent(0.1);
+
         llSay(PUBLIC_CHANNEL, "Touch to see osSlerp usage.");
 
     }
 
     }
   
+
 
     timer()
+
     touch_start(integer number)
 
     {
 
     {
         ratio += 0.1;       //step in 0.1 incriments
+
         float ratio;
         if (ratio>1.0)     //between 0 and 1
+
        rot_a = rot_b;
         {
+
         rot_b = llEuler2Rot(<llFrand(PI), llFrand(PI), llFrand(PI)>);
            ratio = 0.1;   //start over
+
         integer counter = 10;
            lastrot=nextrot;    //save the last rotation
+
 
             t += PI/10.0;      //bump t to generate points on a Lissajous curve
+
        do {
            float y=llSin(t);      //this will generate points around an
+
             ratio += 0.1;
            float z=llSin(2.0*t);   //infinity sympol
+
             llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROTATION, osSlerp(rot_a, rot_b, ratio)]);
             vector fwd=llVecNorm(<2.0,y,z>);    //tip of this vector carves out the shape
+
             llSleep(0.1);
            vector lft=llVecNorm(<0,0,1>%fwd); //convert that into a rotation
+
             nextrot = llAxes2Rot(fwd,lft,fwd%lft); //this will be the next rotation to slerp to
+
 
         }
 
         }
         rotation rot=osSlerp(lastrot,nextrot,ratio);   //slerp generates rotations between these
+
         while(--counter);
        llSetRot(rot);                      //rotate to that.
+
 
     }
 
     }
 
}
 
}
 
</source>
 
</source>
 +
'''With a couple of scripts:'''
 +
<source lang="lsl">
 +
//
 +
// osSlerp Script Example
 +
// Author: djphil
 +
//
  
|additional_info=Implemented Set, 2019 by Ubit Umarov
+
key target = "1209ffb3-3d27-4f77-bf09-d1da8bd36093";
 +
 
 +
default
 +
{
 +
    state_entry()
 +
    {
 +
        llSay(PUBLIC_CHANNEL, "Touch the blue primitive to see osSlerp usage.");
 +
        llSetColor(<0.0, 0.5, 1.0>, ALL_SIDES);
 +
    }
 +
 
 +
    touch_start(integer number)
 +
    {
 +
        rotation rot = llEuler2Rot(<llFrand(PI), llFrand(PI), llFrand(PI)>);
 +
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROTATION, rot]);
 +
        osMessageObject(target, (string)rot);
 +
    }
 +
}
 +
</source>
 +
<source lang="lsl">
 +
//
 +
// osSlerp Script Example
 +
// Author: djphil
 +
//
 +
 
 +
rotation rot_a;
 +
rotation rot_b;
 +
 
 +
default
 +
{
 +
    state_entry()
 +
    {
 +
        llSay(PUBLIC_CHANNEL, "Touch the blue primitive to see osSlerp usage.");
 +
        llSetColor(<1.0, 0.0, 1.0>, ALL_SIDES);
 +
    }
 +
 
 +
    dataserver(key uuid, string data)
 +
    {
 +
        float ratio;
 +
        rot_a = rot_b;
 +
        rot_b = (rotation)data;
 +
        integer counter = 10;
 +
 
 +
        do {
 +
            ratio += 0.1;
 +
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROTATION, osSlerp(rot_a, rot_b, ratio)]);
 +
            llSleep(0.1);
 +
        }
 +
        while(--counter);
 +
    }
 +
}
 +
</source>
 +
'''A more complex example:'''
 +
<source lang="lsl">
 +
//
 +
// osSlerp Script Example
 +
// Author: Kayaker Mangic Sept 2019
 +
//
 +
 
 +
// This isn't the right way to wiggle a stick (llSetKeyframedMotion is better) but it does demostrate osSlerp working!
 +
// Put this script in a prim that is long in the X direction, it will wave it's tip around in a figure 8 (infinity) pattern.
 +
 
 +
rotation lastrot;  // slerp between these two rotations
 +
rotation nextrot;  // slerp between these two rotations
 +
float t = 0.0;      // parameter for calculating angles to slerp between
 +
float ratio = 1.0;  // does 10 slerp steps of 0.1 between last and next
 +
integer switch;
 +
 
 +
default
 +
{
 +
    state_entry()
 +
    {
 +
        llSay(PUBLIC_CHANNEL, "Touch to see osSlerp usage.");
 +
    }
 +
 
 +
    touch_start(integer number)
 +
    {
 +
        if (switch = !switch)
 +
        {
 +
            llSetTimerEvent(1.0);
 +
        }
 +
 
 +
        else
 +
        {
 +
            llSetTimerEvent(0.0);
 +
        }
 +
    }
 +
 +
    timer()
 +
    {
 +
        integer counter = 10;
 +
   
 +
        while(--counter)
 +
        {
 +
            ratio += 0.1;
 +
 +
            if (ratio > 1.0)
 +
            {
 +
                ratio = 0.1;                                    // start over
 +
                lastrot = nextrot;                              // save the last rotation
 +
                t += PI / 10.0;                                // bump t to generate points on a Lissajous curve
 +
                float y = llSin(t);                            // this will generate points around an
 +
                float z = llSin(2.0 * t);                      // infinity sympol
 +
                vector fwd = llVecNorm(<2.0, y, z>);            // tip of this vector carves out the shape
 +
                vector lft = llVecNorm(<0.0, 0.0, 1.0> % fwd);  // convert that into a rotation
 +
                nextrot = llAxes2Rot(fwd, lft, fwd % lft);      // this will be the next rotation to slerp to
 +
            }
 +
 
 +
            rotation rot = osSlerp(lastrot, nextrot, ratio);
 +
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROTATION, rot]);
 +
            llSleep(0.09);
 +
        }
 +
    }
 +
}</source>
 +
|additional_info=Implemented Sept, 2019 by Ubit Umarov
 
}}
 
}}

Latest revision as of 14:21, 2 January 2021

rotation osSlerp(rotation a, rotation b, float ratio);
Slerp is shorthand for spherical linear interpolation, introduced by Ken Shoemake in the context of quaternion interpolation for the purpose of animating 3D rotation.

It refers to constant-speed motion along a unit-radius great circle arc, given the ends and an interpolation parameter between 0 and 1.

osSlerp Returns a rotation that is the spherical interpolation of a and b, according to ratio that can be from 0.0 (result is a) to 1.0 (result is b)

Threat Level None
Permissions Use of this function is always allowed by default
Extra Delay 0 seconds
Example(s)
//
// osSlerp Script Example
// Author: djphil
//
 
rotation rot_a;
rotation rot_b;
 
default
{
    state_entry()
    {
        llSay(PUBLIC_CHANNEL, "Touch to see osSlerp usage.");
    }
 
    touch_start(integer number)
    {
        float ratio;
        rot_a = rot_b;
        rot_b = llEuler2Rot(<llFrand(PI), llFrand(PI), llFrand(PI)>);
        integer counter = 10;
 
        do {
            ratio += 0.1;
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROTATION, osSlerp(rot_a, rot_b, ratio)]);
            llSleep(0.1);
        }
        while(--counter);
    }
}

With a couple of scripts:

//
// osSlerp Script Example
// Author: djphil
//
 
key target = "1209ffb3-3d27-4f77-bf09-d1da8bd36093";
 
default
{
    state_entry()
    {
        llSay(PUBLIC_CHANNEL, "Touch the blue primitive to see osSlerp usage.");
        llSetColor(<0.0, 0.5, 1.0>, ALL_SIDES);
    }
 
    touch_start(integer number)
    {
        rotation rot = llEuler2Rot(<llFrand(PI), llFrand(PI), llFrand(PI)>);
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROTATION, rot]);
        osMessageObject(target, (string)rot);
    }
}
//
// osSlerp Script Example
// Author: djphil
//
 
rotation rot_a;
rotation rot_b;
 
default
{
    state_entry()
    {
        llSay(PUBLIC_CHANNEL, "Touch the blue primitive to see osSlerp usage.");
        llSetColor(<1.0, 0.0, 1.0>, ALL_SIDES);
    }
 
    dataserver(key uuid, string data)
    {
        float ratio;
        rot_a = rot_b;
        rot_b = (rotation)data;
        integer counter = 10;
 
        do {
            ratio += 0.1;
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROTATION, osSlerp(rot_a, rot_b, ratio)]);
            llSleep(0.1);
        }
        while(--counter);
    }
}

A more complex example:

//
// osSlerp Script Example
// Author: Kayaker Mangic Sept 2019
//
 
// This isn't the right way to wiggle a stick (llSetKeyframedMotion is better) but it does demostrate osSlerp working!
// Put this script in a prim that is long in the X direction, it will wave it's tip around in a figure 8 (infinity) pattern.
 
rotation lastrot;   // slerp between these two rotations
rotation nextrot;   // slerp between these two rotations
float t = 0.0;      // parameter for calculating angles to slerp between
float ratio = 1.0;  // does 10 slerp steps of 0.1 between last and next
integer switch;
 
default
{
    state_entry()
    {
        llSay(PUBLIC_CHANNEL, "Touch to see osSlerp usage.");
    }
 
    touch_start(integer number)
    {
        if (switch = !switch)
        {
            llSetTimerEvent(1.0);
        }
 
        else
        {
            llSetTimerEvent(0.0);
        }
    }
 
    timer()
    {
        integer counter = 10;
 
        while(--counter)
        {
            ratio += 0.1;
 
            if (ratio > 1.0)
            {
                ratio = 0.1;                                    // start over
                lastrot = nextrot;                              // save the last rotation
                t += PI / 10.0;                                 // bump t to generate points on a Lissajous curve
                float y = llSin(t);                             // this will generate points around an
                float z = llSin(2.0 * t);                       // infinity sympol
                vector fwd = llVecNorm(<2.0, y, z>);            // tip of this vector carves out the shape
                vector lft = llVecNorm(<0.0, 0.0, 1.0> % fwd);  // convert that into a rotation
                nextrot = llAxes2Rot(fwd, lft, fwd % lft);      // this will be the next rotation to slerp to
            }
 
            rotation rot = osSlerp(lastrot, nextrot, ratio);
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROTATION, rot]);
            llSleep(0.09);
        }
    }
}
Notes
Implemented Sept, 2019 by Ubit Umarov
Personal tools
General
About This Wiki