# accumulative rotations in llSetKeyframedMotion()

## Recommended Posts

I understand that the rotations in llSetKeyframedMotion() are accumulative.  These rotations are added on to previous rotations, rather than setting orientations directly.

I would like to implement world-Z-axis rotations on an object undergoing motion in llSetKeyframedMotion().

Consider the following code:

```vector   kspan = <5,0,0>;
float     ktime  = 5.0;
vector   krotE   = <0,0,31>
rotation krot    = llEuler2Rot( krotE );//llSetKeyframedMotion( [],[] );llSetKeyframedMotion( [kspan,krot,ktime],                                  [KFM_MODE, KFM_FORWARD] );```

The above code will cause most "fresh" prims to rotate smoothly and end up at the end with an accumulated world-Z-axis rotation of 31 degrees. However, if the object is an "unfresh" cone that has been previously tilted to the side, the Z-rotation is performed so that the cone is spun about its tip. (This looks like a local rotation rather than a revolving around the world-Z-axis).  To get a world-Z rotation on a previously-tipped object, something unusual must be performed on the 'krotE', the 'krot', or both.

##### Share on other sites

Try specifying, at runtime, krot = llGetRot()*krot.   I'm not that familiar with KeyFramed Motion, but that makes it a sim-relative  rotation.

##### Share on other sites

Without first trying it I will say that you must eliminate the prim's initial rotation:

`llSetKeyframedMotion( [kspan, krot / llGetRot(), ktime], [KFM_MODE, KFM_FORWARD]);`

##### Share on other sites

There may be a more concise way to torture the quarternions, but what I think you're after is illustrated:

`vector   kspan = <0,0,0>;float     ktime  = 1.0;vector   krotE   = <0,0,31> ;rotation normRot(rotation Q){    float MagQ = llSqrt(Q.x*Q.x + Q.y*Q.y +Q.z*Q.z + Q.s*Q.s);    return <Q.x/MagQ, Q.y/MagQ, Q.z/MagQ, Q.s/MagQ>;}//default{    state_entry()    {        rotation grot =             (llGetRot() * (llEuler2Rot( krotE ))            / llGetRot());        llSetKeyframedMotion( [],[] );        llSetKeyframedMotion( [kspan, normRot(grot), ktime], [KFM_MODE, KFM_LOOP] );    }}`

I threw in the normRot cliche, just to prevent a possible runtime error (which may not even apply here; not sure).

[EDIT: Eww. Maybe not.  I just tried it, and it seems to be drifting off the spin axis I was trying to set. Hmm.]

[EDIT 2: I guess, with KFM_LOOP, any slight error in the incremental rotation would compound over time, but I'm not sure that accounts for the drift.]

##### Share on other sites

I'm still not quite sure what rotation the OP is looking for, but this works and gives a nice smooth rotation....

`float     ktime  = 1.0;vector   krotE   = <0,0,31> ;list KFMlist;default{    state_entry()    {        llSetLinkPrimitiveParamsFast(LINK_SET, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);   //Set door in Prim Equivalence system        integer i;        for (i=0;i<10;++i)        {            rotation grot = (llGetRot() * (llEuler2Rot( krotE ))/ llGetRot());            KFMlist += [grot,ktime];        }        llSetTimerEvent(10.1);    }        timer()    {        llSetKeyframedMotion( [],[] );        llSetKeyframedMotion( KFMlist, [KFM_DATA,KFM_ROTATION] );    }}`

##### Share on other sites
`default{    state_entry()    {         llSetLinkPrimitiveParamsFast(            LINK_THIS,             [ PRIM_PHYSICS_SHAPE_TYPE,               PRIM_PHYSICS_SHAPE_CONVEX ] );     }    touch_start(integer total_number)    {        vector  kspan   = <2,0,0>;        float   ktime   = 5.0;        vector  krotE   = <0,0,(140*DEG_TO_RAD)>;        rotation krot   = llEuler2Rot( krotE );        //        llSetKeyframedMotion( [], [] );        llSetKeyframedMotion( [kspan, krot, ktime],                               [KFM_MODE, KFM_FORWARD] );    }}`

OP here.  I'm going to use a neologism in this post - "fresh prim".  A fresh prim is a prim that you just created with the creation wand in world.. You have neither scaled nor rotated it, or done any other tomfoolery with its parameters.

-

-

After several days of contemplation, I have decided this is not possible. llSetKeyframedMotion() takes accumulated rotations as arguments. It has no power to set rotations.

Fortunately, there is a work-around. Your build has been rotated to strange places out in left field. You can take this wacker-jawed build and link it to a FRESH PRIM box, such that the fresh-prim-box is root.  You can set the box fully transparent and then perform your keyframe script from inside it.  Voila.

##### Share on other sites

No, it's absolutely possible, just try either Rolig's script or mine. It will do what you describe. It's only a question of precision, and I suspect Rolig's omission of normRot() will reduce floating-point error.

I admit that I introduced some unnecessary parentheses into the formula, intending to make it more obvious what was going on--but I only managed to make it more obscure by putting the parens in the wrong places.

Anyway, here's how it works: You want to apply an incremental rotation--as you say, "accumulative"--so the formula for the desired incremental rotation must calculate the difference (quaternion division) between the desired rotation (llGetRot() * rotationRelativeToWorldAxes) and the current rotation (llGetRot()).

[EDIT: I renamed to "rotationRelativeToWorldAxes" in hopes it's clearer than what I used before. Anyway, in this case, it's just the z-axis-only spin.]

##### Share on other sites

What is the problem? It works for me.
I modified your script a bit and used Rolig's calculation:

`vector   kspan = <0.05,0,0>;float    ktime  = 5.0;vector   krotE   = <0,0,90> ;rotation krot;default{    state_entry()    {        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);        krot = llEuler2Rot( krotE * DEG_TO_RAD );    }    touch_start( integer n)    {        llSetKeyframedMotion( [],[] );        llSetKeyframedMotion( [kspan, llGetRot()*krot/llGetRot(), ktime], []);    }}`

##### Share on other sites

Exactly. There no reason to link your structure to a "fresh prim". Dora's got it right, and it works like a dream.

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.