Jump to content

Linked pendulum (perhaps SLPPF?) :)


Tattooshop
 Share

You are about to reply to a thread that has been inactive for 1062 days.

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

Recommended Posts

9 minutes ago, Rolig Loon said:

Pick your favorite script for a linked door and tinker with it to make the "door" swing back and forth in a timer event.

Thanks!

Based on the Void Singer script, I made such a two-position pendulum, but can you clarify a bit where in this post the use of SLPPF is indicated? ;)

 /*//-- USERS MODIFY HERE v --//*/
integer gIntSwing = 30;
/*//-- use -# to reverse the direction of swing, eg. -90; --//*/
rotation gRotSwing;
 
default
{
    state_entry()
    {
        // Activate the timer listener every 3 seconds
        llSetTimerEvent(3);
        gRotSwing = llEuler2Rot( <0.0, 0.0, (float)gIntSwing * DEG_TO_RAD> );
    }
 
    timer()
    {
        llSetLocalRot( (gRotSwing = (ZERO_ROTATION / gRotSwing)) * llGetLocalRot() );
    }
}

 

Link to comment
Share on other sites

17 minutes ago, Rolig Loon said:

Well, you can always use llSetLinkPrimitiveParamsFast( iPendulumLink, [PRIM_ROT_LOCAL, (gRotSwing = (ZERO_ROTATION / gRotSwing)) * llGetLocalRot()]) instead of using the llSetLocalRot version if you wish....

Thank you!

And here's another question. I would like to add the ability to turn the pendulum on and off by touch. When off, it should point down. When on - the movement left/right must be performed. How can this be done better?

Link to comment
Share on other sites

33 minutes ago, Rolig Loon said:

Just use your touch_start event to stop the timer and make the final SLPPF local rotation that sets the pendulum's Z axis vertical.

Thank you!

Is it possible to somehow move the pendulum position in the ON state by half the "opening" angle (so that the OFF state position is equal to zero)? *

* Automatically

** To divide the angle by two and automatically shift the swing of the pendulum to the side. I hope this makes sense. :D

Edited by Tattooshop
Link to comment
Share on other sites

1 hour ago, Rolig Loon said:

Of course. That's how you turn on the timed pendulum swing.  Trigger the start in the touch_start event with a half swing and start the timer.

Almost succeeded, thanks! :)
But how to set half the angle?

 

Edited by Tattooshop
Link to comment
Share on other sites

* A bug has been detected! Please use the updated version!

That's what I did. May come in handy to someone...

I would be grateful if anyone can find a way to simplify the script or improve it.

It would also be cool to make the movements smoother, for example in a few steps. ;)👍

integer gIntSwing = 30;
rotation gRotSwing;
rotation hRotSwing;
float hIntSwing;

integer run;
default
{
    state_entry()
    {
        hIntSwing = gIntSwing*-0.5;
        gRotSwing = llEuler2Rot( < 0.0, 0.0, (float) gIntSwing * DEG_TO_RAD > );
        hRotSwing = llEuler2Rot( < 0.0, 0.0, (float) hIntSwing * DEG_TO_RAD > );
    }

    touch_start(integer total_number)
    {
        if (llDetectedKey(0) == llGetOwner())
        {
            if (run)
            {
                run = FALSE;
                llSetTimerEvent(0);
                llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, ZERO_ROTATION]);
            }
            else
            {
                run = TRUE;
                llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, (hRotSwing = (ZERO_ROTATION / hRotSwing)) * llGetLocalRot()]) ;
                llSetTimerEvent(3);
            }
        }
    }

    timer()
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, (gRotSwing = (ZERO_ROTATION / gRotSwing)) * llGetLocalRot()]);
    }
}

 

Edited by Tattooshop
Link to comment
Share on other sites

Off the top of my head ...

vector vAxis = llRot2Axis(gRotSwing);

float fHalfAngle = llRot2Angle(gRotSwing) * 0.5;

llSetLinkPrimitiveParamsFast( iPendulumLink,[PRIM_ROT_LOCAL, llAxisAngle2Rot( vAxis, fHalfAngle) * llGetLocalRot()]);

Not tested, but I think that should work.

 

EDIT:  Or, actually, your way is easier.  ;) Nice job.

Edited by Rolig Loon
  • Like 2
Link to comment
Share on other sites

7 minutes ago, Rolig Loon said:

Not tested, but I think that should work.

So much better!

* I would not recommend first version of the script, there is some incomprehensible bug. Please use the version below. :D

integer gIntSwing = 30;
rotation gRotSwing;

integer run;
default
{
    state_entry()
    {
        gRotSwing = llEuler2Rot( < 0.0, 0.0, (float) gIntSwing * DEG_TO_RAD > );
    }

    touch_start(integer total_number)
    {
        if (llDetectedKey(0) == llGetOwner())
        {
            if (run)
            {
                run = FALSE;
                llSetTimerEvent(0);
                llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, ZERO_ROTATION]);
            }
            else
            {
                run = TRUE;
                vector vAxis = llRot2Axis(gRotSwing);
                float fHalfAngle = llRot2Angle(gRotSwing) * 0.5;
                llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL, llAxisAngle2Rot( vAxis, fHalfAngle) * llGetLocalRot()]); 
                llSetTimerEvent(3);
            }
        }
    }

    timer()
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, (gRotSwing = (ZERO_ROTATION / gRotSwing)) * llGetLocalRot()]);
    }
}

 

Edited by Tattooshop
  • Like 1
Link to comment
Share on other sites

To make a smooth version, you should probably start with a different door script. Void's simple hinge is a lovely script, very straightforward.  It is designed to open a door in one move, though. As you have figured out, making the swing smooth means taking multiple small steps.  That will be more of a challenge for you, but I'm confident that you can do it.

The best way to make a smooth pendulum, of course, is to use Keyframed Motion.  Take a look at Dora Gustafson's classic pendulum script, for example.  Sadly, if you use KFM, your script has to be in the root prim.  You can't swing a child prim with it, so you'd be back to making your clock with an unlinked pendulum.  There are clever ways to do that -- several of us have made two-piece garden swings that self-align on rez so that the swinging part fits properly in the frame -- but it's more awkward than having a linked pendulum.  This is one of the basic scripting projects that I think most LSL scripters try to solve for themselves at some point, so you'll find many clever approaches if you start digging around for them. It's more fun to work out your own, though.  ;) 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Lessons learned the hard way with a swinging pub sign using KFM:

Rotation is less accurate than position, left to itself a swinging pub sign slowly works around until it is well to one side of where the centre is.

moving_end does not always trigger precisely enough to be certain the swinging object has actually stopped swinging

ping-pong mode exacerbates rotational problems in regions with idling happening.

Oddly, the errors seem to preponderate in one direction, leading to the ratcheting round effect.  (Still not investigated is if the direction of the error is connected to the initial swing direction).

Use @Animat 's defensive programming techniques and constantly check where the rotation is and make a second KFM call if it's lagging behind where it should be.

However, doing an llSetRot() at the end of each KFM rotation can break the smoothness of the required swing due to the inherent 10mSec function call delay. The best way to get around this is to either check the discrepancy and only do a setRot when it exceeds a certain value, or only do the correction every few cycles.

 

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

@Rolig Loon @Profaitchikenz Haiku :)🤚

So managed to add 10 steps option, but the root prim is rotated 90 degrees and there is no way to change it because of the clock script. As a result, when the movement begins, the pendulum rotates 90 degrees with the root. I changed the rotation of the pendulum mesh, but now it is swinging upside down. Help please, how to avoid it? My function now looks like this:

* It is clear that all this can be achieved by applying the correct rotation of the mesh, but this is not very convenient. :D

integer run;
integer intSwing = 10; // 10 degrees

myFunction()
{
    integer x = 0;
    for (x = 0; x <= 10; x++)
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, llEuler2Rot( < (float)intSwing, 0.0, 0.0 >*DEG_TO_RAD ) + llGetLocalRot()]);
        llSleep(0.1);
    }
    for (x = 0; x <= 10; x++)
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, llEuler2Rot( < -(float)intSwing, 0.0, 0.0 >*DEG_TO_RAD ) + llGetLocalRot()]);
        llSleep(0.1);
    }
}

 

Edited by Tattooshop
Link to comment
Share on other sites

I don't have the advantage that you do of being able to tinker with the model on the ground, so all I can do is guess. As a suggestion, though, first fix the typo in

llEuler2Rot( < (float)intSwing, 0.0, 0.0 >*DEG_TO_RAD ) * llGetLocalRot()   // That's supposed to be multiplication, not addition  ;) 

and then be sure that you really intend to apply your rotation around the X axis of the pendulum (which is what you wrote).

 

  • Thanks 1
Link to comment
Share on other sites

1 hour ago, Rolig Loon said:

I don't have the advantage that you do of being able to tinker with the model on the ground, so all I can do is guess. As a suggestion, though, first fix the typo in

llEuler2Rot( < (float)intSwing, 0.0, 0.0 >*DEG_TO_RAD ) * llGetLocalRot()   // That's supposed to be multiplication, not addition  ;) 

and then be sure that you really intend to apply your rotation around the X axis of the pendulum (which is what you wrote).

 

Thanks a lot!
But now it seems broken :D (of course not lol)

The object has changed its behavior...

Before it the pendulum swung evenly left and right (I dunno why):

ezgif-5-e5539a011b71.gif.981e3e37a894f236115aca59005a2c66.gif

and now in one direction.

ezgif-5-f9c9aac62ddd.gif.1dc2c7805020d1ae6046873ca4fa8b31.gif

that is, I understand that I made a mistake, but why did it happen and what should I do? 🤔

Link to comment
Share on other sites

That's the whole code, if anyone needs it:

integer run;
integer intSwing = 10; // 1 degrees

myFunction()
{
    integer x = 0;
    for (x = 0; x <= 10; x++)
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, llEuler2Rot( < (float)intSwing, 0.0, 0.0 > * DEG_TO_RAD ) + llGetLocalRot()]);
        llSleep(0.1);
    }
    for (x = 0; x <= 10; x++)
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, llEuler2Rot( < -(float)intSwing, 0.0, 0.0 > * DEG_TO_RAD ) + llGetLocalRot()]);
        llSleep(0.1);
    }
}

default
{
    
    touch_start(integer total_number)
    {
        if (llDetectedKey(0) == llGetOwner())
        {
            if (run)
            {
                run = FALSE;
                llSetTimerEvent(0);
                llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, ZERO_ROTATION]);
            }
            else
            {
                run = TRUE;
                llSetTimerEvent(1);
            }
        }
    }

    timer()
    {
        myFunction();
    }
}

 

Link to comment
Share on other sites

Never give up! You're doing fine with it and rotations are notoriously nightmarish.

 

I've rezzed your script and its swinging to both sides as expected. At this stage, it helps to rez a fresh prim and test its behavior with the bare minimum script.

 

 

+ llSetLocalRot has a 0.2 delay, I use it sometimes where it can replace llSleep. I've left in the code for llSetLocalRot, just halve the number of iterations (x) if using it.

Using llSetLinkPrimitiveParamsFast is a little more intensive but gives a smoother result.

integer run;
vector intSwing = <2.0, 0.0, 0.0>; // 2 degrees


myFunction()
{
    integer x;

    for (x = 0; x < 10; x++)
    {
//      llSetLocalRot(llGetLocalRot() * llEuler2Rot( intSwing * DEG_TO_RAD ));
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, llEuler2Rot( intSwing * DEG_TO_RAD ) * llGetLocalRot()]);
        llSleep(0.1);
    }

    for (x = 0; x < 20; x++)
    {
//      llSetLocalRot(llGetLocalRot() * llEuler2Rot( -intSwing * DEG_TO_RAD ));
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, llEuler2Rot( -intSwing * DEG_TO_RAD ) * llGetLocalRot()]);
        llSleep(0.1);
    }

    for (x = 0; x < 10; x++)
    {
//      llSetLocalRot(llGetLocalRot() * llEuler2Rot( intSwing * DEG_TO_RAD ));
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, llEuler2Rot( intSwing * DEG_TO_RAD ) * llGetLocalRot()]);
        llSleep(0.1);
    }
}

default
{
    
    touch_start(integer total_number)
    {
        if (llDetectedKey(0) == llGetOwner())
        {
            if (run)
            {
                run = FALSE;
                llSetTimerEvent(0);
                llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, ZERO_ROTATION]);
            }
            else
            {
                run = TRUE;
                llSetTimerEvent(4);
            }
        }
    }

    timer()
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, ZERO_ROTATION]);
        myFunction();
    }
}

 

 

 

 

 

Edited by Mr Amore
  • Thanks 1
Link to comment
Share on other sites

22 hours ago, Mr Amore said:

Never give up! You're doing fine with it and rotations are notoriously nightmarish.

 

I've rezzed your script and its swinging to both sides as expected. At this stage, it helps to rez a fresh prim and test its behavior with the bare minimum script.

 

 

+ llSetLocalRot has a 0.2 delay, I use it sometimes where it can replace llSleep. I've left in the code for llSetLocalRot, just halve the number of iterations (x) if using it.

Using llSetLinkPrimitiveParamsFast is a little more intensive but gives a smoother result.

integer run;
vector intSwing = <2.0, 0.0, 0.0>; // 2 degrees


myFunction()
{
    integer x;

    for (x = 0; x < 10; x++)
    {
//      llSetLocalRot(llGetLocalRot() * llEuler2Rot( intSwing * DEG_TO_RAD ));
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, llEuler2Rot( intSwing * DEG_TO_RAD ) * llGetLocalRot()]);
        llSleep(0.1);
    }

    for (x = 0; x < 20; x++)
    {
//      llSetLocalRot(llGetLocalRot() * llEuler2Rot( -intSwing * DEG_TO_RAD ));
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, llEuler2Rot( -intSwing * DEG_TO_RAD ) * llGetLocalRot()]);
        llSleep(0.1);
    }

    for (x = 0; x < 10; x++)
    {
//      llSetLocalRot(llGetLocalRot() * llEuler2Rot( intSwing * DEG_TO_RAD ));
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, llEuler2Rot( intSwing * DEG_TO_RAD ) * llGetLocalRot()]);
        llSleep(0.1);
    }
}

default
{
    
    touch_start(integer total_number)
    {
        if (llDetectedKey(0) == llGetOwner())
        {
            if (run)
            {
                run = FALSE;
                llSetTimerEvent(0);
                llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, ZERO_ROTATION]);
            }
            else
            {
                run = TRUE;
                llSetTimerEvent(4);
            }
        }
    }

    timer()
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, ZERO_ROTATION]);
        myFunction();
    }
}

 

 

 

 

 

Thank you very much for your support and for sharing your script, now everything works as it should! :)👍

  • Like 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 1062 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
 Share

×
×
  • Create New...