Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Script won't work at 45 deg. angles

Cunundrum Alcott
A Sardonic Pessimist
Join date: 15 Jan 2007
Posts: 773
02-23-2008 08:43
If I turn the prim at a 45 degree angle it will move to the nearest 90 deg. angle;

integer swing=FALSE; //So it starts out NOT swinging
float time=0.4; //Decreasing this (on it's own) makes the swing move FASTER and vice versa
integer steps=12; //The total number of steps in the swing's path. More steps=smoother swing. More steps (alone) means slower swing too - time for a complete swing cycle is steps * time (so 4.8 s with the default settings).
integer swingDegrees = 10; //How far from the vertical the swing moves

integer i=1;
float swingRad;
vector normal;

rotation Inverse(rotation r)
{
r.x = -r.x;
r.y = -r.y;
r.z = -r.z;
return r;
}
rotation GetParentRot()
{
return Inverse(llGetLocalRot())*llGetRot();
}
SetLocalRot(rotation x)
{
llSetRot(x*Inverse(GetParentRot()));
}

default
{
state_entry()
{
normal = llRot2Euler(llGetRot());
swingRad=DEG_TO_RAD*swingDegrees;
llSetTouchText("Rock";);
}
touch_start(integer num)
{
if(swing)
{
swing=FALSE;
llSetTouchText("Rock";);
}
else
{
swing=TRUE;
llSetTouchText("Stop Rocking";);
llSetTimerEvent(time);
}
}
timer()
{
float stepOffset=(float)i/steps*TWO_PI;
if(i>steps) i=1;
if(swing==FALSE && (i==steps || i==steps/2))
{
llSetTimerEvent(0.0);
SetLocalRot(llEuler2Rot(<normal.x, normal.y, normal.z + swingRad*llSin(stepOffset)>;));
} else
{
SetLocalRot(llEuler2Rot(<normal.x, normal.y, normal.z + swingRad*llSin(stepOffset)>;));
i++;
}
}
moving_end()
{
normal=llRot2Euler(llGetRot());
}
}
_____________________
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
02-23-2008 18:48
first, please, I'm begging, use php tags... quoting to get code is annoying and if it's a bad day I'll just skip it. (i'm probably not the only one).

ok a few things to simplify. your inverse rotation function can be acheived in one operation, allowing you to dump the function. to invert a rotation use
rotation.s *= -1; //-- equavalent to rot.s = rot.s * -1 or rot.s = -rot.s

next simplification, is your fractional change in magnitude of your rotation...
rot.s *= 2;
will halve the rotation degrees, and basicly acts as a denominator to your degrees movement. so the get 1/12 you'd multiply the s component by 12. to increase degree you'd multiply by a fraction, such as .5 to double.

I'm not even going to dive into the logic of your SetLocal/getParent rot functions, in fact I'm having trouble wrapping my head around what you were trying to do, but what I'm guessing is that you are swinging the object around it's axis based on it's starting global axis, rather than a local one, which is where the problem is cropping up.

assuming that I've got that right, and you're just trying to swing in a particular local direction, what you'd want is to add the incremental rotation to the current rotation, like this:
llSetLocalRot( rot2move * llGetRot() ); //-- amount to move goes first

now if I've got the intention of this all wrong, please ignore the next part, it's basically a tire swing I made that swings based on it's local facing, around it's root (or the center of a cut root prim rope in this case) very similarly to a door script

CODE

float gFltDegSwing = 10; //-- from 'center' position
integer gIntSteps = 12; //--should at least be 1

rotation gRotSwing;
rotation gRotSwingStep;
rotation gRotCurrent;
integer gIntCounter;

default{
state_entry(){
gRotSwing = llEuler2Rot( <gFltDegSwing, 0.0, 0.0> * DEG_TO_RAD );
gRotSwingStep = llEuler2Rot( <gFltSwing * 2.0 / (float)gIntSteps, 0.0, 0.0> * DEG_TO_RAD );
//-- times 2 because gRotSwing is .5 of total swing
}

touch_start( integer vIntTouched ){
state sMoving;
}
}

state sMoving{
state_entry(){
gRotCurrent = llGetRot();
//-- start the timer early to chain the calls together tighter
llSetTimerEvent( .2 );
//-- pre swing covers half the distance
llSetRot( gRotSwing * gRotCurrent );
}

timer(){
//-- kill the timer while we're looping to avoid extra queues/processing
llSetTimerEvent( 0.0 );
gIntCounter = 1;
//-- our loop will take use from gFltdegrees back, to gFltDegrees front,
//-- for a total of vFltDegrees * 2
do{
llSetRot( gRotCurrent = gRotSwingStep * gRotCurrent );
//-- should be faster than llSetRot( gRotSwingStep * llGetRot() ); but I haven't tested
}while (gIntSteps < ++gIntCounter){
//-- restart the timer a lil early
llSetTimerEvent( .2 );
//-- reverse or rotations
gRotSwingStep.s *= -1;
gRotSwing.s *= -1;
}

touch_start( integer vIntTouched ){
state default;
}

state_exit(){
//-- kill the timer so it doesn't run uselessly
llSetTimerEvent( 0.0 );
//-- apply half the swing to recenter
llSetRot( gRotSwing * gRotCurrent );
}
}
_____________________
|
| . "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...
| -