Jump to content
You are about to reply to a thread that has been inactive for 1536 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Posted

I called llTargetOmega from within timer() and nothing happens. I moved llTargetOmega into a function *called* from the same line in timer() and it works as expected.

Is this really a thing?

If so, anyone have an explanation? The doc doesn't seem to say anything negative about calling llTargetOmega from within an event handler, or I missed it. Furthermore, how is a function call that executes llTargetOmega any different than calling it directly vis a vis the event queue model.

Severely puzzled,

G

Posted

Hmmm.. That shouldn't happen.  I would suspect that something else is messing it up.  A variable that should be global but isn't?  Or something that turns the timer off?  

You might take a look at the caveat in the wiki entry for llTargetOmega, but I doubt that it''s your problem.  After all, you said it does work sometimes. 

Posted

this is the code

the two params to llTO are on the stack of timer() for the calls that do not work but they are also on the stack of ChangeRotation...

 

integer spinON = FALSE;


ChangeRotation(float r, float dir)
{
    llTargetOmega(<0,0,1>,(dir*PI/r),1.0);
}


default
{
    state_entry()
    {
        //llOwnerSay("Hi");
    }

    touch_start(integer total_number)
    {
        if (spinON == FALSE)
        {
            
            spinON = TRUE;
            llSetTimerEvent(1.0);
        } else
        {
            spinON = FALSE;
            llSetTimerEvent(0.0);
            llTargetOmega(ZERO_VECTOR,0,0);
        }
    }
    timer()
    {
        float rateDenominator;
        float spinDirection;
        float secondsTillNextChange;


        // get a new rate between 10.0 and 50.0
        rateDenominator = llFrand(40.6) + 10.0;
        if (llFrand(1.1)< 0.5)
        {
            spinDirection = -1.0;
        } else
        {
            spinDirection = 1.0;
        }
        //llTargetOmega(<0,0,1>,(spinDirection*PI/rateDenominator),1.0); THIS DOES NOT WORK
        //llTargetOmega(<0,0,1>,-PI/48,1.0); THIS DOES NOT WORK
        ChangeRotation(rateDenominator, spinDirection); // This works
        // randomly set next change between 20.0 seconds and 60.0 seconds
        llSetTimerEvent(secondsTillNextChange);
    }
}

 

Posted (edited)

Likely unrelated to the primary issue: secondsTillNextChange is defined in the timer event, and that will set it to zero.   llSetTimerEvent(secondsTillNextChange) would shut off the timer.... doesn't explain the other behavior.

Edited by Phate Shepherd
Posted

Ah, well, one potential problem is that you are trying to make your object spin very slowly.  I have been unable to find documentation and don't see any JIRAs commenting on it, but I know from experience that if you set the spin rate too low, llTargetOmega can stall.  That doesn't explain why it would work in your function but not in the timer event, but it's something to think about.   For a spin that slow, you may do well to just use incremental rotations with llSetRot.

Posted
1 hour ago, GManB said:

I called llTargetOmega from within timer() and nothing happens. I moved llTargetOmega into a function *called* from the same line in timer() and it works as expected.

Is this really a thing?

If so, anyone have an explanation?

 

i have no explanation, but you have come up with a fix for the issues that I have been having with the omega wheels on my motobike

i have been trying to match the spinrate of the wheel based on the wheel size and the velocity of the bike. I have been trying to do all this in a timer event. And sometimes it goes as it should and sometimes it doesn't go at all

i changed to putting it into a function called from the timer event, as you have discovered. And my wheels work perfectly now. So thanks!

 

Posted

@Mollymews, you are welcome. Feels great to have helped!

 

@Phate, when llSetTimerEvent(secondsTillNextChange) is called secondsTillNextChange does have whatever value came back from llFRand() and it is on the stack of timer() but, I would assume, llSetTimerEvent has the value on it's stack and does what is necessary and should, very much, not depend on the value on the stack of the calling function (in our case timer()) being valid when llSetTimerEvent returns.

@Rolig, when it works, given the slow rotation value, it works fine and rotates fine. I have been using PI/48.0 in lots of objects and have not seen anomalous behavior you describe.

 

But, there is a fix, and I am moderately ok... I still do not like not understanding issues like this. Gives me a slightly creepy feeling about the underlying execution environment.

 

G

Posted (edited)

I just finished a project that successfully calls llTargetOmega() in a timer(), so I took your script to Morris for testing.  After 100 clicks, 50 first omega, and 50 second omega (with ChangeRotation() floated), it worked every time.  Since this is client-side, I'm on the standard SL Viewer 6.4.8.548890.

Edited by DoteDote Edison
Posted

DoteDote,

What's 'Morris'?

And the script I posted does work for me too. But, if I make the call to llTargetOmega() in the timer it does not. So, exactly what did you test?

 

I am on Firestorm version 6.3.9.58205 (6.3.9.58205)

 

G

Posted
13 minutes ago, GManB said:

But, there is a fix, and I am moderately ok... I still do not like not understanding issues like this. Gives me a slightly creepy feeling about the underlying execution environment.

I don't blame you.  llTargetOmega is an odd duck. It works best if your object is physical, because then the servers handle the motion. When you use it on non-physical objects, they spin client-side. That means they have the same vulnerability that animations and keyframed motion do.  They depend on each viewer and each person's graphics card to do the spinning -- a potentially chancy operation on some older or underpowered machines.  I have suspected that's where the function gets into trouble at slow spin rates.

Years ago now, I was asked to script a large rotating platform for a club.  There was a good-sized non-rotating dance floor in the middle, and the ring around the outside was supposed to be for seated avatars to watch, eat, and be sociable.  The ring was supposed to spin at a very low speed.  I tried llTargetOmega valiantly, but couldn't get the thing to spin reliably.  It would seem to move fine, but then if you looked away for a bit, it would stall.  I ended up giving up and using small rotational increments instead, as I suggested to you earlier.  It worked quite well.

Posted

Must be the different viewers then.

When you said Morris I thought maybe it was some sort of test harness :)

I'll come by and we can look at the object with the different viewers and determine if we see different things..

 

G

Posted
9 minutes ago, Rolig Loon said:

I don't blame you.  llTargetOmega is an odd duck. It works best if your object is physical, because then the servers handle the motion. When you use it on non-physical objects, they spin client-side. That means they have the same vulnerability that animations and keyframed motion do.  They depend on each viewer and each person's graphics card to do the spinning -- a potentially chancy operation on some older or underpowered machines.  I have suspected that's where the function gets into trouble at slow spin rates.

Years ago now, I was asked to script a large rotating platform for a club.  There was a good-sized non-rotating dance floor in the middle, and the ring around the outside was supposed to be for seated avatars to watch, eat, and be sociable.  The ring was supposed to spin at a very low speed.  I tried llTargetOmega valiantly, but couldn't get the thing to spin reliably.  It would seem to move fine, but then if you looked away for a bit, it would stall.  I ended up giving up and using small rotational increments instead, as I suggested to you earlier.  It worked quite well.

Ultimately, that's that I had to do with the teak bench swing I built. llTargetOmega and keyframed motion just were not doing well.

Posted

Just to close this, DoteDote and I did some experiments and could not re-create what I (thought) I initially saw. I know I did see what I reported initially. And, I have subsequently seen one of my rotating objects stop for a while... not just super slow, stopped. Then, after less than a minute, it starts again. So, as Rolig says, llTargetOmega() s an odd duck.

 

G

Posted
On 9/25/2020 at 12:43 PM, GManB said:

Just to close this, DoteDote and I did some experiments and could not re-create what I (thought) I initially saw. I know I did see what I reported initially. And, I have subsequently seen one of my rotating objects stop for a while... not just super slow, stopped. Then, after less than a minute, it starts again

what I found was that the back wheel of my motobike (which is always in the view of the follow camera on my screen) doesn't always begin turning in the first timer event when the bike first begins to move.  Wrapping it in a function corrects this. Why I dunno

my back wheel is a torus prim, not sure if this has anything to do with it tho

Posted
5 hours ago, Mollymews said:

what I found was that the back wheel of my motobike (which is always in the view of the follow camera on my screen) doesn't always begin turning in the first timer event when the bike first begins to move.  Wrapping it in a function corrects this. Why I dunno

my back wheel is a torus prim, not sure if this has anything to do with it tho

A good little trick - force an update of the part in question, for example simple forced texture update.

  • Like 1
Posted

I have a little script I put in wheels. It calls llTargetOmega(axis, rate, 1.0); directly from the timer event, which fires every 0.300 second. Rate is calculated from the vehicle velocity in the forward direction.

There are some protections. If rate is < 0.01 rad/sec, it's set to zero, because very low rotation rates don't work with llTargetOmega. If it's above 10 rad/sec, it's clamped, because rotating too fast for the frame rate is useless; it won't look right. The call to llTargetOmega is skipped if there's been less than a 20% change in rate since last time, to hold down the number of updates. And when the vehicle is turned off, the script gets a message to go to an off state, stopping the timer.

Works fine. Inch the bike forward and the wheel rolls slowly, synchronized against the ground. Zoom around fast and it continues to look right.

  • Thanks 1
Posted
12 hours ago, Rachel1206 said:

A good little trick - force an update of the part in question, for example simple forced texture update.

my bike is all prims.  The wheel is 2 parts. Cylinder for the wheel and torus for the tyre. I used a torus for the tyre because in my eyes it has a better shape than a cylinder or a sphere

i did want to use a animated texture on the torus because as you mention is a whole lot simpler, but unless there is something I am missing, we can't animate a texture on any axis other than the X. So ended up with having to turn the torus with omega 

  • Like 1
Posted
11 hours ago, animats said:

If rate is < 0.01 rad/sec, it's set to zero, because very low rotation rates don't work with llTargetOmega. If it's above 10 rad/sec, it's clamped, because rotating too fast for the frame rate is useless; it won't look right. The call to llTargetOmega is skipped if there's been less than a 20% change in rate since last time, to hold down the number of updates.

this is most likely my problem. When my bike first moves then rate maybe less < 0.01

what I am doing is adjusting the omega spinrate to the size of the wheel. On the basis that a little wheel performs more revolutions than a bigger wheel over the same distance. My calculation of this might be all wrong
 

// approximate circumference (rim) of wheel in metres
// idea is that a smaller wheel will perform more revolutions
// than a larger wheel over the same distance

   vector s = llGetScale();
   s.y /= 2.0;      
   float rim = llSqrt(s.y * s.y);  

// spinrate is calibrated to size of wheel
// dir is either 1 or -1. FWD or BACK
// AXLE is <0.0, 1.0, 0.0>  Y-axis

   float mag = dir * (llVecMag(llGetVel()) / rim * TWO_PI);

   llTargetOmega(AXLE, mag, 1.0);

 

Posted (edited)
5 hours ago, Mollymews said:

this is most likely my problem. When my bike first moves then rate maybe less < 0.01

what I am doing is adjusting the omega spinrate to the size of the wheel. On the basis that a little wheel performs more revolutions than a bigger wheel over the same distance. My calculation of this might be all wrong
 


// approximate circumference (rim) of wheel in metres
// idea is that a smaller wheel will perform more revolutions
// than a larger wheel over the same distance

   vector s = llGetScale();
   s.y /= 2.0;      
   float rim = llSqrt(s.y * s.y);  

// spinrate is calibrated to size of wheel
// dir is either 1 or -1. FWD or BACK
// AXLE is <0.0, 1.0, 0.0>  Y-axis

   float mag = dir * (llVecMag(llGetVel()) / rim * TWO_PI);

   llTargetOmega(AXLE, mag, 1.0);

 

Mm, I'm sorry... I can't resist 😉

float rim = llSqrt(s.y * s.y);

(Note: I would have to play endlessly with the formula until I got it right, so, I don't claim any mathematical high ground!)

Edited by Phate Shepherd
  • Like 1
Posted
5 hours ago, Mollymews said:

float rim = llSqrt(s.y * s.y);

You squared the number, then took its square root? But what you have in "rim" is the radius of the wheel, anyway. Not the circumference.

5 hours ago, Mollymews said:

float mag = dir * (llVecMag(llGetVel()) / rim * TWO_PI);

Parentheses. I think you wanted

float mag = dir * (llVecMag(llGetVel()) / (rim * TWO_PI));

rim*TWO_PI is the wheel circumference, which is what you need to divide the velocity by.

 

  • Thanks 1
Posted
56 minutes ago, animats said:

You squared the number, then took its square root? But what you have in "rim" is the radius of the wheel, anyway. Not the circumference.

Parentheses. I think you wanted


float mag = dir * (llVecMag(llGetVel()) / (rim * TWO_PI));

rim*TWO_PI is the wheel circumference, which is what you need to divide the velocity by.

 

oops. gah!

google and animats is my friend. Not my brains!

no wonder it wasn't working as I thought it should

float rim = s.y * PI;

so when our big wheel is 1 metre in diameter then its rim is 3.14 metres. When our little wheel is 0.5 metres in diameter then its rim is 1.57 metres. So over the distance of 3.14 metres our big wheel will turn 1 revolution and our little wheel will turn 2 revolutions

therefore ( I hope)

float mag = dir  * (llVecMag(llGetVel(() / rim);

 

  • Like 1
Posted (edited)
22 hours ago, Mollymews said:

 


float rim = s.y * PI;

 


float mag = dir  * (llVecMag(llGetVel(() / rim);

 

I'm going to have to remember this... I never considered actually making wheels turn at a truly accurate speed.

Edited by Phate Shepherd
  • Like 1
You are about to reply to a thread that has been inactive for 1536 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...