Difference between revisions of "Smooth Rotating Door"
(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. | <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= | 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) | ||
{ | { | ||
go(); | |||
} | |||
collision_start(integer dummy) | |||
{ | |||
go(); | |||
} | } | ||
timer() | timer() | ||
{ | { | ||
if(swinging) | if(swinging>0) | ||
{ | { | ||
swinging= | 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= | 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. | |||
// 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= | 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) | ||
{ | { | ||
go(); | |||
} | |||
collision_start(integer dummy) | |||
{ | |||
go(); | |||
} | } | ||
timer() | timer() | ||
{ | { | ||
if(swinging) | if(swinging>0) | ||
{ | { | ||
swinging= | 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= | 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
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