Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Discussion: Smooth rotation transition using llTargetOmega()

Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
10-30-2005 11:09
I was thinking about how to reduce the impact on screen real estate that a HUD attachment would have when I'm not using it. I thought of the possibility of having it rotate out of view when inactive, and started exploring the use of llSetRot() in steps to make the transition seem smoother. Then I realized that llTargetOmega() could be used to smoothly transition between two rotations, and if you quickly stop the llTargetOmega() and call llSetRot() at just the right moment, the transition could be seamless.

Here's a script I came up with that does this (apologies if this has already been done). Given an axis, an angle, a duration, and an initial rotation, this script will smoothly transition back and forth between two rotations each time the object is touched. To see a demo, just put this script in a prim and poke at it a few times :) Works on attachments and in-world objects.

CODE

// Lex Neva
//
// Smooth Rotation

// This script demonstrates how to use llTargetOmega() to smoothly transition between two
// rotations. Occasionally the object will under- or over-rotate, but generally, the effect
// is to rotate smoothly between a starting and ending rotation.


// how long to take to rotate
float ROT_TIME=1.0;

// axis to rotate around
vector ROT_AXIS=<0.0,0,1>;

// angle in radians to rotate
float ROT_ANGLE=PI_BY_TWO;

// initial rotation
rotation ROT_START=ZERO_ROTATION;

default
{
state_entry() {
// this needs to be a unit vector
ROT_AXIS = llVecNorm(ROT_AXIS);

// get the process started
llSetRot(ROT_START * llAxisAngle2Rot(ROT_AXIS, ROT_ANGLE));
state unflipped;
}
}

state unflipped {
state_entry()
{
llTargetOmega(ROT_AXIS,-ROT_ANGLE/ROT_TIME,1);
llSleep(ROT_TIME);
llTargetOmega(ROT_AXIS,0,1);
llSetRot(ROT_START);
}

touch_start(integer total_number)
{
state flipped;
}
}

state flipped {
state_entry()
{
llTargetOmega(ROT_AXIS,ROT_ANGLE/ROT_TIME,1);
llSleep(ROT_TIME);
llTargetOmega(ROT_AXIS,0,1);
llSetRot(ROT_START * llAxisAngle2Rot(ROT_AXIS, ROT_ANGLE));
}

touch_start(integer total_number)
{
state unflipped;
}
}
Nada Epoch
The Librarian
Join date: 4 Nov 2002
Posts: 1,423
Original Thread
11-01-2005 06:06
/15/17/68933/1.html
_____________________
i've got nothing. ;)
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
11-02-2005 09:32
One good use for this script is a door. If you take a cube and cut it to 0.375,0.875 (I think), it should make it so that it rotates around one side rather than the center. Pop this script in unmodified, and you'll have a door that smoothly opens and closes when touched. No more jerky doors!
Helen Quatro
Cephalopod Overlord
Join date: 6 Sep 2005
Posts: 24
11-04-2005 10:27
What would I do to make this not set the object to a zero rotation?

Great script by the way, the movement is excellent.
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
11-05-2005 09:15
The line you want to change is this:

CODE

// initial rotation
rotation ROT_START=ZERO_ROTATION;


You'll have to set a rotation directly if you do it there. If you want to set a rotation that you get from the edit box, put a line like this in state_entry() of the default state:

CODE

ROT_START = llEuler2Rot(DEG_TO_RAD * <90,0,180>);


Fill in whatever rotation you want where I've written <90,0,180>.
Beatfox Xevious
is THOUSANDS OF PEOPLE
Join date: 1 Jun 2004
Posts: 879
11-05-2005 11:17
Good idea! I've sometimes wondered how well a method like this would work (esp. WRT moving attachments, such as tails), but never bothered to give it a try myself. Guess I'll have to check it out next time I'm inworld.

From: Lex Neva
One good use for this script is a door. If you take a cube and cut it to 0.375,0.875 (I think), it should make it so that it rotates around one side rather than the center. Pop this script in unmodified, and you'll have a door that smoothly opens and closes when touched. No more jerky doors!

Another more versatile solution is to use a transparent root prim as the "hinge". Put the script in the root prim, and the whole object will pivot around the root's center.
_____________________
My Beatworks: Zephyr Chimes wind chimes, the KanaMaster Japanese kana tutor, and the FREE Invisibility Prim Public. Look for them at the Luskwood General Store in Lusk (144, 165).

"You have been frozen. You cannot move or chat. A pony will contact you via instant message (IM)."
- mysterious system message I received after making off with Pony Linden
Helen Quatro
Cephalopod Overlord
Join date: 6 Sep 2005
Posts: 24
11-05-2005 12:41
From: Lex Neva
The line you want to change is this:

CODE

// initial rotation
rotation ROT_START=ZERO_ROTATION;


You'll have to set a rotation directly if you do it there. If you want to set a rotation that you get from the edit box, put a line like this in state_entry() of the default state:

CODE

ROT_START = llEuler2Rot(DEG_TO_RAD * <90,0,180>);


Fill in whatever rotation you want where I've written <90,0,180>.


Ahh oke, thank you! I'll have smooth rotating doors in no time now! (and hopefully wings and tails as well ;) )
Helen Quatro
Cephalopod Overlord
Join date: 6 Sep 2005
Posts: 24
11-05-2005 22:10
Hmm I get a syntax error changing the rotation ROT_START to that. I get it inbetween the llEuler2Rot and the ";(". Adding a space gives me the same error.
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
11-06-2005 09:35
I think I know what happened. If you're using the second method, you're actually going to have to leave the first ROT_START line alone and add a new one at the start of state_entry() to set it, because of the way global variables work. Hopefully this makes it more clear:

CODE


...

default
{
state_entry() {
// set a different start rotation
ROT_START = llEuler2Rot(DEG_TO_RAD * <90,0,180>);

// this needs to be a unit vector
ROT_AXIS = llVecNorm(ROT_AXIS);

// get the process started
llSetRot(ROT_START * llAxisAngle2Rot(ROT_AXIS, ROT_ANGLE));
state unflipped;
}
}

...

Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
11-06-2005 09:39
From: Beatfox Xevious
Good idea! I've sometimes wondered how well a method like this would work (esp. WRT moving attachments, such as tails), but never bothered to give it a try myself. Guess I'll have to check it out next time I'm inworld.


I'm not even sure whether this worked smoothly enough before 1.7 came out... I imagine someone would have thought of it before. One annoying problem is that sometimes, attachments simply fail to respond to llTargetOmega() calls until you poke at them, leave the sim, relog, etc. Argh. Anyway, I'd love to see if you get this working on a realistic-looking attachment!

From: Beatfox Xevious
Another more versatile solution is to use a transparent root prim as the "hinge". Put the script in the root prim, and the whole object will pivot around the root's center.


Well, sure. I was just sort of going for the simplest possible method, there. Box prims are special cases because you can move the rotation axis an "edge" by cutting it in half.
Helen Quatro
Cephalopod Overlord
Join date: 6 Sep 2005
Posts: 24
11-06-2005 09:56
Oke, I will try that in a bit here. Hopefully it works! :)

I've heard about attachments not continuosly responding to llTargetOmega. I am hoping I can find some way around it when I try this script out in a series of wings I have made. (Scripting (clearly) is not my strong point as I am fairly unpracticed in it.)

Thanks for the further help!
Helen Quatro
Cephalopod Overlord
Join date: 6 Sep 2005
Posts: 24
11-06-2005 13:02
Yes! My doors work exactly how I want them to now. I commented out the initial ROT_START and put in "rotation ROT_START . . ." right above each of the actual rotation codes as so:
CODE

integer open() // Opens the door.
{
rotation ROT_START = llEuler2Rot ( DEG_TO_RAD * <0,0,270>);
// vv Replace this snippet with custom code to close the door vv
llTargetOmega(-ROT_AXIS,ROT_ANGLE/ROT_TIME,1); //Negatives added to ROT_AXIS for right-side door -HQ
llSleep(ROT_TIME);
llTargetOmega(-ROT_AXIS,0,1);
llSetRot(ROT_START * llAxisAngle2Rot(-ROT_AXIS, ROT_ANGLE));
// ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
return TRUE;
}
//- - - - - - - - - - - - - - - -
integer close() // Closes the door.
{
rotation ROT_START = llEuler2Rot ( DEG_TO_RAD * <0,0,270>);
// vv Replace this snippet with custom code to close the door vv
llTargetOmega(-ROT_AXIS,-ROT_ANGLE/ROT_TIME,1);
llSleep(ROT_TIME);
llTargetOmega(-ROT_AXIS,0,1);
llSetRot(ROT_START);
// ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
return FALSE;
}


Now to start in on my bird wings.
_____________________
Eristic Strangelove
Registered User
Join date: 16 Nov 2005
Posts: 39
02-29-2008 13:55
This slow rotation is exactly what i need for a rotating door fixed to an object, but i need the door to be a linked child prim. Is it possible to adapt this script to allow that? Is it also possible to explain how to do it without using the terms 'euler vector' or 'quaternion' which mean NOTHING to me! :D

Actually i can almost get the rotation to work but the ROT_START thing confuses me, it resets the prim to zero rotation as it's supposed to, but i need it to assume a start position relative to the root prim.

Is that possible?

EDIT: It appears that it IS possible cos i seem to have done it...basically just changed all the llSetRot to llSetLocalRot and played around with the settings. Seems to work fine, haven't managed to get it to mess-up yet and it looks amazing compared to the previous 'snap' rotation the door had.
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
03-01-2008 08:48
Yup, you got it :) I have a version that does root-relative rotation, but all I did was to change llSetRot() to llSetLocalRot().
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
03-01-2008 09:28
just be careful because target omega can appear under/over rotate depending on server or viewer lag, and then snap to it's new physical destination. not so bad with a single small time frame like this, messy for bigger or more continuous calls (or changed directions called without setting a position). also the door looks to be staying solid so it's not actualy open till it's finished with the set * rot. (could make it phantom inbetween if it's unlinked)

PS I like it though =)
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Eristic Strangelove
Registered User
Join date: 16 Nov 2005
Posts: 39
03-01-2008 10:11
I just tried it out on a Mono sim and it doesn't like Mono, or vice versa. A bit ironic that i should find Lex's excellent script just before mono breaks it! ;)

Under mono it gives me the over-rotate problem Void describes and then it snaps back to its correct position. Presumably something to do with the (previously seamless) shift between llTargetOmega() and call llSetRot()?

Hopefully that can be fixed in the script or in Mono, I'd hate to lose this now...
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
03-02-2008 09:29
I'll take a look at it when I have a chance and file a bug report.
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
03-02-2008 11:46
it's kinda weird, since overrotating is usually caused by sim lag, and under rotating by viewer lag... could be how mono treats some of the commands (sleep would be my guess).
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Eristic Strangelove
Registered User
Join date: 16 Nov 2005
Posts: 39
03-22-2008 06:13
Had a spare moment, so i tried this script again in the latest beta of Mono - and it works! Whatever was causing it to over-rotate before seems to have been fixed with the latest mono build and we're good to go...smooth as silk actually, let's hope that lasts too.
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
03-22-2008 09:36
That matches what I saw when I tested this in mono last week. Yay!