User:Tyken Hightower/Slerping

From Second Life Wiki
Jump to navigation Jump to search

Spherical Linear Interpolation with Constant Angular Velocity and Upright Rotation

<lsl> // Spherical linear interpolation with constant angular 'velocity' - move the same number of degrees, or delta, per frame of motion. rotation slerp2(rotation current, rotation target, float delta) {

   rotation between = llRotBetween(llRot2Fwd(current), llRot2Fwd(target)); // Get the axis we want to rotate on.
   
   if (llRot2Angle(between) > delta) // This prevents wobbling. Also, llAngleBetween is dumb and doesn't work as expected when used on the two rotation arguments..
   {
       return current * llAxisAngle2Rot(llRot2Axis(between), delta);
   }
   else
   {
       return target;
   }

}

// Remove 'roll' from a rotation's x-axis and return the result (Originally posted on the forums by Seifert Surface, maybe).. rotation upright(rotation current) {

   vector fwd = llRot2Fwd(current);
   vector left = llVecNorm(<0.0, 0.0, 1.0> % fwd);
   return llAxes2Rot(fwd, left, fwd % left);

}

default {

   state_entry()
   {
       llSetTimerEvent(0.1);
   }
   
   timer()
   {
       vector target = llList2Vector(llGetObjectDetails(llGetOwner(), [OBJECT_POS]), 0); // Owner's location.
       rotation facing_forward = llGetRot(); // Rotation our object is currently looking in.
       rotation facing_target = llRotBetween(<1.0, 0.0, 0.0>, llVecNorm(target - llGetPos())); // Rotation representing our object's forward x-axis facing the target position.
       rotation slerped = slerp2(facing_forward, facing_target, PI / 55.0); // Our original rotation, turned a certain number of degrees toward the target rotation (PI / 55.0 is fairly smooth and slow).
       slerped = upright(slerped); // Make this new rotation have no 'roll' about its x-axis.
       
       llRotLookAt(slerped, 1.0, 0.1);
   }

} </lsl>