Difference between revisions of "Smooth Rotating Door"

From Second Life Wiki
Jump to navigation Jump to search
(Version 1.1)
Line 5: Line 5:
Most doors in SL use the same method for opening. They set the door's rotation in one or more steps, resulting in a somewhat choppy motion. This script uses a mixture of llTargetOmega() and llSetLocalRot() to achieve a very smooth, pleasant looking animation for the door. In laggy environments it might be that the script displays a somewhat flaky behavior, but for most cases it will work nicely.
Most doors in SL use the same method for opening. They set the door's rotation in one or more steps, resulting in a somewhat choppy motion. This script uses a mixture of llTargetOmega() and llSetLocalRot() to achieve a very smooth, pleasant looking animation for the door. In laggy environments it might be that the script displays a somewhat flaky behavior, but for most cases it will work nicely.


<lsl>// Smooth Door Script - Version 1.0
<lsl>// Smooth Door Script - Version 1.1
// by Toy Wylie
// by Toy Wylie
// Distributed under the following licence:
// Distributed under the following licence:
Line 17: Line 17:
float openingAngle=90.0;    // in degrees
float openingAngle=90.0;    // in degrees
float autocloseTime=5.0;    // in seconds
float autocloseTime=5.0;    // in seconds
integer steps=4;            // number of internal rotation steps


float omega=0.0;
float omega=0.0;
Line 35: Line 36:
         useAxis=-axis;
         useAxis=-axis;


     llSetTimerEvent(openingTime);
     llSetTimerEvent(openingTime/(float) steps);
     llTargetOmega(useAxis,omega,1.0);
     llTargetOmega(useAxis,omega,1.0);
}
go()
{
    if(swinging==0)
    {
        if(!open)
        {
            axis=llRot2Fwd(llGetLocalRot());
            closedRot=llGetLocalRot();
            openRot=llEuler2Rot(<openingAngle,0.0,0.0>*DEG_TO_RAD)*closedRot;
        }
        swinging=steps;
        openDoor(!open);
    }
}
rotation slerp(rotation source,rotation target,float amount)
{
  return llAxisAngle2Rot(llRot2Axis(target/=source),amount*llRot2Angle(target))*source;
}
}


Line 43: Line 64:
     state_entry()
     state_entry()
     {
     {
         swinging=FALSE;
         swinging=0;
         open=FALSE;
         open=FALSE;
         omega=TWO_PI/360*openingAngle/openingTime;
         omega=TWO_PI/360*openingAngle/openingTime;
Line 51: Line 72:
     touch_start(integer dummy)
     touch_start(integer dummy)
     {
     {
         if(!swinging)
         go();
        {
    }
            if(!open)
 
            {
    collision_start(integer dummy)
                axis=llRot2Fwd(llGetLocalRot());
    {
                closedRot=llGetLocalRot();
        go();
                openRot=llEuler2Rot(<openingAngle,0.0,0.0>*DEG_TO_RAD)*closedRot;
            }
            swinging=TRUE;
            openDoor(!open);
        }
     }
     }


     timer()
     timer()
     {
     {
         if(swinging)
         if(swinging>0)
         {
         {
             swinging=FALSE;
             swinging--;
            if(swinging!=0)
            {
                float amount=(float) swinging/(float) steps;
                if(open)
                    amount=1.0-amount;
                llSetLocalRot(slerp(closedRot,openRot,amount));
                return;
            }
 
             llTargetOmega(axis,0.0,0.0);
             llTargetOmega(axis,0.0,0.0);
             if(open)
             if(open)
Line 81: Line 106:
             }
             }
         }
         }
         else
         else // autoclose time reached
         {
         {
             llSetTimerEvent(0.0);
             llSetTimerEvent(0.0);
             openDoor(!open);
             openDoor(!open);
             swinging=TRUE;
             swinging=steps;
         }
         }
     }
     }
Line 94: Line 119:


To have the door swing on the Z axis use this version. For those unfamiliar with the typical swinging door, you do a path cut to remove one-half of the prim. This will make appear as if it is swinging on its edge and not around it's middle.
To have the door swing on the Z axis use this version. For those unfamiliar with the typical swinging door, you do a path cut to remove one-half of the prim. This will make appear as if it is swinging on its edge and not around it's middle.
<lsl>
<lsl>// Smooth Door Script - Version 1.1
// Smooth Door Script - Version 1.0
// by Toy Wylie
// by Toy Wylie
// swing on z axis changes by Clarke Kondor
// swing on z axis changes by Clarke Kondor
Line 104: Line 128:
// - This header notice must remain intact
// - This header notice must remain intact
// - You may modify this script as needed
// - You may modify this script as needed
 
float openingTime=2.0;      // in seconds
float openingTime=2.0;      // in seconds
float openingAngle=90.0;    // in degrees
float openingAngle=90.0;    // in degrees
float autocloseTime=5.0;    // in seconds
float autocloseTime=5.0;    // in seconds
integer steps=4;            // number of internal rotation steps
 
float omega=0.0;
float omega=0.0;
 
vector axis;
vector axis;
rotation closedRot;
rotation closedRot;
rotation openRot;
rotation openRot;
 
integer swinging;
integer swinging;
integer open;
integer open;
 
openDoor(integer yes)
openDoor(integer yes)
{
{
     vector useAxis=axis;
     vector useAxis=axis;
     open=yes;
     open=yes;
 
     if(!yes)
     if(!yes)
         useAxis=-axis;
         useAxis=-axis;
 
     llSetTimerEvent(openingTime);
     llSetTimerEvent(openingTime/(float) steps);
     llTargetOmega(useAxis,omega,1.0);
     llTargetOmega(useAxis,omega,1.0);
}
}
 
go()
{
    if(swinging==0)
    {
        if(!open)
        {
            axis=llRot2Up(llGetLocalRot());
            closedRot=llGetLocalRot();
            openRot=llEuler2Rot(<0.0,0.0,openingAngle>*DEG_TO_RAD)*closedRot;
        }
        swinging=steps;
        openDoor(!open);
    }
}
 
rotation slerp(rotation source,rotation target,float amount)
{
  return llAxisAngle2Rot(llRot2Axis(target/=source),amount*llRot2Angle(target))*source;
}
 
default
default
{
{
     state_entry()
     state_entry()
     {
     {
         swinging=FALSE;
         swinging=0;
         open=FALSE;
         open=FALSE;
         omega=TWO_PI/360*openingAngle/openingTime;
         omega=TWO_PI/360*openingAngle/openingTime;
         llTargetOmega(ZERO_VECTOR,1.0,1.0);
         llTargetOmega(ZERO_VECTOR,1.0,1.0);
     }
     }
 
     touch_start(integer dummy)
     touch_start(integer dummy)
     {
     {
         if(!swinging)
         go();
        {
    }
            if(!open)
 
            {
    collision_start(integer dummy)
                axis=llRot2Up(llGetLocalRot());
    {
                closedRot=llGetLocalRot();
        go();
                openRot=llEuler2Rot(<0.0,0.0,openingAngle>*DEG_TO_RAD)*closedRot;
            }
            swinging=TRUE;
            openDoor(!open);
        }
     }
     }
 
     timer()
     timer()
     {
     {
         if(swinging)
         if(swinging>0)
         {
         {
             swinging=FALSE;
             swinging--;
            if(swinging!=0)
            {
                float amount=(float) swinging/(float) steps;
                if(open)
                    amount=1.0-amount;
                llSetLocalRot(slerp(closedRot,openRot,amount));
                return;
            }
 
             llTargetOmega(axis,0.0,0.0);
             llTargetOmega(axis,0.0,0.0);
             if(open)
             if(open)
Line 172: Line 221:
             }
             }
         }
         }
         else
         else // autoclose time reached
         {
         {
             llSetTimerEvent(0.0);
             llSetTimerEvent(0.0);
             openDoor(!open);
             openDoor(!open);
             swinging=TRUE;
             swinging=steps;
         }
         }
     }
     }
}
}</lsl>
</lsl>
 
==Changelog==
 
Version 1.1:
* Added rotation steps so people can start walking through the halfways-open door already
* Added opening on collision

Revision as of 07:20, 13 April 2010

Smooth Rotating Door Script

Introduction

Most doors in SL use the same method for opening. They set the door's rotation in one or more steps, resulting in a somewhat choppy motion. This script uses a mixture of llTargetOmega() and llSetLocalRot() to achieve a very smooth, pleasant looking animation for the door. In laggy environments it might be that the script displays a somewhat flaky behavior, but for most cases it will work nicely.

<lsl>// Smooth Door Script - Version 1.1 // by Toy Wylie // Distributed under the following licence: // - You can use it in your own works // - You can sell it with your work // - This script must remain full permissions // - This header notice must remain intact // - You may modify this script as needed

float openingTime=2.0; // in seconds float openingAngle=90.0; // in degrees float autocloseTime=5.0; // in seconds integer steps=4; // number of internal rotation steps

float omega=0.0;

vector axis; rotation closedRot; rotation openRot;

integer swinging; integer open;

openDoor(integer yes) {

   vector useAxis=axis;
   open=yes;
   if(!yes)
       useAxis=-axis;
   llSetTimerEvent(openingTime/(float) steps);
   llTargetOmega(useAxis,omega,1.0);

}

go() {

   if(swinging==0)
   {
       if(!open)
       {
           axis=llRot2Fwd(llGetLocalRot());
           closedRot=llGetLocalRot();
           openRot=llEuler2Rot(<openingAngle,0.0,0.0>*DEG_TO_RAD)*closedRot;
       }
       swinging=steps;
       openDoor(!open);
   }

}

rotation slerp(rotation source,rotation target,float amount) {

  return llAxisAngle2Rot(llRot2Axis(target/=source),amount*llRot2Angle(target))*source;

}

default {

   state_entry()
   {
       swinging=0;
       open=FALSE;
       omega=TWO_PI/360*openingAngle/openingTime;
       llTargetOmega(ZERO_VECTOR,1.0,1.0);
   }
   touch_start(integer dummy)
   {
       go();
   }
   collision_start(integer dummy)
   {
       go();
   }
   timer()
   {
       if(swinging>0)
       {
           swinging--;
           if(swinging!=0)
           {
               float amount=(float) swinging/(float) steps;
               if(open)
                   amount=1.0-amount;
               llSetLocalRot(slerp(closedRot,openRot,amount));
               return;
           }
           llTargetOmega(axis,0.0,0.0);
           if(open)
           {
               llSetLocalRot(openRot);
               llSetTimerEvent(autocloseTime);
           }
           else
           {
               llSetLocalRot(closedRot);
               llSetTimerEvent(0.0);
           }
       }
       else // autoclose time reached
       {
           llSetTimerEvent(0.0);
           openDoor(!open);
           swinging=steps;
       }
   }

}</lsl>

See also

To have the door swing on the Z axis use this version. For those unfamiliar with the typical swinging door, you do a path cut to remove one-half of the prim. This will make appear as if it is swinging on its edge and not around it's middle. <lsl>// Smooth Door Script - Version 1.1 // by Toy Wylie // swing on z axis changes by Clarke Kondor // Distributed under the following licence: // - You can use it in your own works // - You can sell it with your work // - This script must remain full permissions // - This header notice must remain intact // - You may modify this script as needed

float openingTime=2.0; // in seconds float openingAngle=90.0; // in degrees float autocloseTime=5.0; // in seconds integer steps=4; // number of internal rotation steps

float omega=0.0;

vector axis; rotation closedRot; rotation openRot;

integer swinging; integer open;

openDoor(integer yes) {

   vector useAxis=axis;
   open=yes;
   if(!yes)
       useAxis=-axis;
   llSetTimerEvent(openingTime/(float) steps);
   llTargetOmega(useAxis,omega,1.0);

}

go() {

   if(swinging==0)
   {
       if(!open)
       {
           axis=llRot2Up(llGetLocalRot());
           closedRot=llGetLocalRot();
           openRot=llEuler2Rot(<0.0,0.0,openingAngle>*DEG_TO_RAD)*closedRot;
       }
       swinging=steps;
       openDoor(!open);
   }

}

rotation slerp(rotation source,rotation target,float amount) {

  return llAxisAngle2Rot(llRot2Axis(target/=source),amount*llRot2Angle(target))*source;

}

default {

   state_entry()
   {
       swinging=0;
       open=FALSE;
       omega=TWO_PI/360*openingAngle/openingTime;
       llTargetOmega(ZERO_VECTOR,1.0,1.0);
   }
   touch_start(integer dummy)
   {
       go();
   }
   collision_start(integer dummy)
   {
       go();
   }
   timer()
   {
       if(swinging>0)
       {
           swinging--;
           if(swinging!=0)
           {
               float amount=(float) swinging/(float) steps;
               if(open)
                   amount=1.0-amount;
               llSetLocalRot(slerp(closedRot,openRot,amount));
               return;
           }
           llTargetOmega(axis,0.0,0.0);
           if(open)
           {
               llSetLocalRot(openRot);
               llSetTimerEvent(autocloseTime);
           }
           else
           {
               llSetLocalRot(closedRot);
               llSetTimerEvent(0.0);
           }
       }
       else // autoclose time reached
       {
           llSetTimerEvent(0.0);
           openDoor(!open);
           swinging=steps;
       }
   }

}</lsl>

Changelog

Version 1.1:

  • Added rotation steps so people can start walking through the halfways-open door already
  • Added opening on collision