# Need help with a 'Rocking' Pivot.

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

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

## Recommended Posts

Hey guys, I'm building a bell, and I'm no good with rotation atall. I'm looking for a pivot rotation script like this one:

This one id great, other then you have to click it in order for it to stop rocking. Does anybody know how to stop it rocking? Maybe put it on a timer or a certain amount of rotations?

Thanks, Gruff

##### Share on other sites

I'm going to regret this.... but here's a modification that should make it stop by itself after X number of swings...

`// Put this script in the pivot - the thing the swing swings around (it doesn't have to be a long rod). That needs to be the root of the prim set that actually swings - if you want/need a frame that needs to be a separate item. SL doesn't yet allow us hierarchical linking. // Play with these bits - the orange comments tell you what's going on with each line I hope.integer swing=FALSE; //So it starts out NOT swingingfloat time=0.1; //Decreasing this (on it's own) makes the swing move FASTER and vice versainteger steps=20; //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 = 30; //How far from the vertical the swing movesinteger gIntRepeat = 4; //-- number of times to swing, use -1 to swing until stopped by touch //If you play from here on down you might break the script. Do so at your own risk. There are no comments - just to encourage you NOT to play.integer gIntCnt;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("Swing");	}		touch_start(integer num)	{		if(swing)		{			swing=FALSE;			llSetTouchText("Swing");		}		else		{			swing=TRUE;			gIntCnt = gIntRepeat;			llSetTouchText("Stop swing");			llSetTimerEvent(time);		}	}		timer()	{		float stepOffset=(float)i/steps*TWO_PI;		if(i>steps)		{			i=1;			if (!--gIntCnt){			{				swing == FALSE;			}		}		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());	}}`

there are much simpler swing scripts out there.....

##### Share on other sites

Do you think you could refer any to me?

##### Share on other sites

I could probably write one faster than finding a link to one.... which I may do later if no one adds a link

##### Share on other sites

Here's one I used for a school bell I did for Rutgers University. No elegant loops, because it was timed to match a sound file for the bell. I modded this from a simple tail wag script...

As Void commented, this goes in the root prim, which acts as your pivot point. I used a cylinder prim since the bell needed an axle anyway.

`vector start;integer listener = -1;stoplisten(){    if (listener != -1)    {        llListenRemove(listener);        listener = -1;    }}startlisten(){    listener = llListen(1776, "", "", ""); // Listens on channel 1776}ringthebell(){        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));         llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));         llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, -40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*((RAD_TO_DEG*llRot2Euler(llGetLocalRot()))+ <0, 40, 0>)));        llSetRot(llEuler2Rot(DEG_TO_RAD*(start)));}default{    state_entry()    {        start = (RAD_TO_DEG*llRot2Euler(llGetLocalRot()));        // Start listening.        stoplisten();        startlisten();    }state_exit()    {        // Remove old listen.        stoplisten();    }        listen(integer channel, string name, key id, string message)    {        if(message == "ringbell")         {            ringthebell();        }    }    }`

It's set to listen on channel 1776 for the command "ringbell", which was sent via llRegionSay from the pull rope and its pose ball and animation.

To see and hear this bell in-world, go to the "RUCE 2" sim, and go into the school building that has a white bell tower on the roof. Go up the West stairwell, all the way to the attic, and in the center of the attic, under the bell tower, if you touch the rope leading to the bell, the bell will ring. On the ground floor there's a pull rope in a closet, with a pose ball. It's a little NW of the center of the building. If you sit on the pose ball there. you'll see yourself pulling the bell rope in time with the animation and sound file.

• 1
##### Share on other sites

Thank you, although it's the long process this is exactly what I was looking for!

I was able to easily adapt it into what I already had, play with variables and get it to work exactly how I wanted it!

Feel free to contact me in game to see the finished result!

##### Share on other sites

• 1 year later...

I'm late to the party but after having spent considerable time looking around for a way to do a smooth pivot, I finally just modified the old "Smooth Door Script" by Toy Wylie. It uses targetomega for the animation, rather than dozens or more individual rotation changes pushed through the server. The result is an almost perfectly smooth rock/pivot with much lower cost to region resources. At the end of each swing there is just a single llSetLocalRot() to snap it in place. It's a door script so this would be needed, but it also seems to correct for accumulating rotation oddities I noticed when I commented those functions. I didn't do much to the original script, just added some code to do start/stop on touch, and to put it in a continuous back and forth loop. My application was a simple rocking chair, and it works perfectly. You'll likely need to use an extra prim as the pivot point, depending on your requirements and build.

`// Smooth Door Script - Version 1.1// by Toy Wylie// Distributed under the following licence:// - You can use it in your own works// - You can sell it with your work// - This script must remain full permissions// - This header notice must remain intact// - You may modify this script as needed// -------------// - Modified into basic rocker/pivot with// - touch start/stop. Zaphod Kotobide float openingTime=2.0;      // in secondsfloat openingAngle=15.0;    // in degreesfloat autocloseTime=1.0;    // in secondsinteger steps=4;            // number of internal rotation steps float omega=0.0; vector axis;rotation closedRot;rotation openRot; integer swinging;integer open;integer rocking; openDoor(integer yes){    vector useAxis=axis;    open=yes;     if(!yes)    {        useAxis=-axis;    }        llSetTimerEvent(openingTime/(float) steps);    llTargetOmega(useAxis,omega,1.0);} go(){    if(swinging==0)    {        if(!open)        {            axis=llRot2Fwd(llGetLocalRot());            closedRot=llGetLocalRot();            openRot=llEuler2Rot(<openingAngle,0.0,0.0>*DEG_TO_RAD)*closedRot;        }                swinging=steps;        openDoor(!open);    }} rotation slerp(rotation source,rotation target,float amount){   return llAxisAngle2Rot(llRot2Axis(target/=source),amount*llRot2Angle(target))*source;} default{    state_entry()    {        rocking=FALSE;        swinging=0;        open=FALSE;        omega=TWO_PI/360*openingAngle/openingTime;        llTargetOmega(ZERO_VECTOR,1.0,1.0);    }     touch_start(integer dummy)    {        if (llDetectedKey(0) == llGetOwner())        {            if (rocking == FALSE)            {                llLoopSound("rocking-chair",0.8);                rocking=TRUE;                go();            }            else            {                llStopSound();                rocking=FALSE;            }        }    }     timer()    {        if(swinging>0)        {            swinging--;            if(swinging!=0)            {                float amount=(float) swinging/(float) steps;                if(open)                {                    amount=1.0-amount;                }                                llSetLocalRot(slerp(closedRot,openRot,amount));               return;            }             llTargetOmega(axis,0.0,0.0);            if(open)            {                llSetLocalRot(openRot);                llSetTimerEvent(autocloseTime);            }            else            {                llSetLocalRot(closedRot);                llSetTimerEvent(0.0);                if (rocking == TRUE)                {                    go();                }            }        }        else // autoclose time reached        {            llSetTimerEvent(0.0);            openDoor(!open);            swinging=steps;        }    }}`

##### Share on other sites

One of the challenges of adding to a thread that's a year and a half old is that  lot of things change in SL during that length of time.  When the OP posted the question at the top of his thread, llSetKeyframedMotion was not yet available.  If I were answering today, that's what I would recommend.  It's smoth, easy to script, and much more compact than something like the Smooth Door script.  In fact, Dora Gustafson has an example of a pendulum script at http://wiki.secondlife.com/wiki/User:Dora_Gustafson/Pendulum_motion that is very close to what the OP wanted.

##### Share on other sites

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

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

## Create an account or sign in to comment

You need to be a member in order to leave a comment

## Create an account

Sign up for a new account in our community. It's easy!

Register a new account