Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Rotation coming out slightly skewed.. can't understand why

Innula Zenovka
Registered User
Join date: 20 Jun 2007
Posts: 1,825
05-31-2009 18:58
When I get things wrong with rotations, it's normally obvious where I've gone wrong because stuff is upside down or back to front, but I am getting much smaller errors here and it's driving me nuts.

I am rezzing a drawbridge when I have positioned my castle, and I want it to raise and lower slowly and creakily. I'm trying to do it thus:
CODE
integer maxcount=6; 
rotation rot;
integer counter=0;
integer on_int=0;
integer timcnt=0;
string sound = "05eb9e74-9d89-28ce-55c2-f92f5eded2e4";
init(){


if(llGetInventoryType(llGetInventoryName(INVENTORY_SOUND,0))==INVENTORY_SOUND){
sound = llGetInventoryName(INVENTORY_SOUND,0);
}
llPreloadSound(sound);
timcnt=0;

rot= llEuler2Rot(15*llRot2Fwd(llGetRot()) * DEG_TO_RAD);
rot.s*=-1;
}
default
{
state_entry()
{
init();

}
on_rez(integer p)
{
init();

llListen(p,"",NULL_KEY,"");

}
touch_start(integer total_number)
{
llSetTimerEvent(1.0); // generate a timer event every second
rot.s*=-1;
llPlaySound(sound,1.0);
if (on_int==0) on_int++;
}

listen(integer channel, string name, key id, string message){
if(message== "boo"){
llDie();
}

if (message == "open"||message=="close"){
llSetTimerEvent(1.0);
rot.s*=-1;
llPlaySound(sound,1.0);
if (on_int==0) on_int++;

}
}

timer()
{
if (on_int>0)
{

llSetRot( llGetRot() * rot);

counter++;
if (counter > maxcount-1)
{
counter=0;
on_int=0;
}
else if (counter < 0 )
{
counter=0;
}
}

}
}
Everything's lined up properly when I start, with the drawbridge raised, but when I lower it, it ends up slightly skewed if the castle is at certain angles. At other angles, though, it is as straight as a die.

For example, when the castle is angled at <0.0, 0.0, 290.0> in the edit window, so's my raised drawbridge. However, when I lower it, it ends up at <89.55, 287.50, 357.25> instead of <90, 290, 0>. When I raise the drawbridge, though, it's back to <0.0, 0.0, 290.0>.

But when I turn the castle round a bit further, so both the castle and the drawbridge are at <0.0, 0.0, 270.0>, the drawbridge starts and finishes where I want it to.

I am ever so confused.. what am I doing wrong, please?
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
05-31-2009 20:02
it's somewhere in your calculation of "rot" I think, (or it could be the fact that you're trying to calculate/apply a local rotation in the global frame)

you're obviously rotating a half or even quarter cut prim, so the following rot calculation should serve you better (change it to suit your builds local axis of rotation, negate PI to reverse direction)
//-- 1/12pi == 15Deg * DEG_TO_RAD--//
rot = llEuler2Rot( <0.0, 0.0, (1.0 /12.0) * PI> );


and then apply it as
llSetRot( rot * llGetRot() );
_____________________
|
| . "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...
| -
Innula Zenovka
Registered User
Join date: 20 Jun 2007
Posts: 1,825
05-31-2009 20:18
Thank you so much, Void.. that works a treat. If I ask why one works and the other one doesn't, am I likely to understand the answer?
Anti Antonelli
Deranged Toymaker
Join date: 25 Apr 2006
Posts: 1,091
05-31-2009 20:18
You might also run into rounding errors that accumulate inconveniently at times, depending on the angles in question. Happens to doors a lot. What you might do is, before starting the movement, first save the original position and rotation as variables with llGetRot and llGetPos. Then do your counter/timer stuff, but at the very end apply llSetRot and llSetPos with the values of those variables so it ends up precisely in the right place instead of counting 100% on the math. Especially if you have more than a couple prims linked together.

Something else random that might turn out to be helpful: see what happens if you click the bridge again while it's moving, and it if does bad things think about putting all the motion stuff in another state without a touch_start handler. :)
_____________________
Designer of sensual, tasteful couple's animations - for residents who take their leisure time seriously. ;)

http://slurl.com/secondlife/Brownlee/203/110/109/

Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
05-31-2009 20:39
@Anti:
ouch, good catch... those touch and listen events need to be moderated while the timer is running on the scripted movement... either a variable check, or a state change would work for both (I also note the time is never stopped, only the code ignored because the counters are zeroed.)

From: Innula Zenovka
Thank you so much, Void.. that works a treat. If I ask why one works and the other one doesn't, am I likely to understand the answer?

well TBH, I understand what your trying to do in the original, but I can't wrap my brain around what it's actually doing or if you can even do it that way.

I CAN explain why my version does give the desired result. by use a local rotation (local amount first) you simplify your actions... you build regardless of orientation never changes it's local axis, so when we work from the local, we can hard code the amount, and apply it to the global which is only known at run time (but accessible from the get rot call)

order of operations in rotations is important, unlike in basic multiplication.

for SL you can think of it as starting with the last rotation (the global in this case) and adding the rotation(s) before it on top of it... or just remember that that get rot is global and if you apply it first you're working on the (sim) rotation, otherwise you're in the local (object) rotation.

(and if you want to SEE those frames of reference, change the ruler mode in edit, from global to local and back on a rotated object... and imagine applying a rotation around the axis as you see them.)
_____________________
|
| . "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...
| -
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
05-31-2009 21:01
ok, short rewrite, skipping the sounds. I'm not going the state change route so that your listen doesn't have to be re started each time, or the channel stored.

CODE

integer gIntCounter;
rotation gRot15Dz;

uTryMove(){
if (!gIntCounter){
llSetTimerEvent( 1.0 );
gRot15Dz.s *= -1;
gIntCounter = 7;
}
}

default{
on_rez( integer p ){
gRot15Dz = llEuler2Rot( <0.0, 0.0, (1.0 /12.0) * PI> );
llListen( p, "", "", "" );
}

touch_start( integer vIntTotal ){
uTryMove();
}

listen( integer vInt, string vStr, key vKey, string vStrMsg ){
if ("open" == vStrMsg | "close" = vStrMsg){
uTryMove();
}
else if ("boo" == vStrMsg){
llDie();
}
}

timer(){
if (--gIntCounter){
llSetRot( gRot15Dz * llGetRot() );
}
else{
llSetTimerEvent( 0.0 );
}
}
}
_____________________
|
| . "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...
| -
Anti Antonelli
Deranged Toymaker
Join date: 25 Apr 2006
Posts: 1,091
05-31-2009 22:08
And this is why I don't post code snippets any more, instead making little English language observations that I hope will occasionally be helpful. Your examples are always as concise and clear and correct as could be hoped for, Void. :)
_____________________
Designer of sensual, tasteful couple's animations - for residents who take their leisure time seriously. ;)

http://slurl.com/secondlife/Brownlee/203/110/109/

Innula Zenovka
Registered User
Join date: 20 Jun 2007
Posts: 1,825
06-01-2009 17:03
Thank you so much, both Anti and Void. I do understand rather more clearly now, I think.

My original was, in fact, based on one someone had helped me to write about a year ago, when I understood even less about rotations than now I do. I knew it gave the effect I wanted on my original build, so I made the mistake, as I now realise, of tinkering with it to try to get it to work out the rezzer rather than starting from scratch. Thank you for showing me how to do it.