Smooth Rotating Door
| LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
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