Warning: Creating default object from empty value in /home/davancamus/public_html/blog/wp-includes/functions.php on line 292
Royal Cavorite Society » Blog Archive » Rotating A Wheel

Rotating A Wheel

December 29th, 2006 by Davan Camus

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/davancamus/public_html/blog/wp-includes/functions-formatting.php on line 76

…or a reel.

From time to time I have come across a device whose wheels are rotating all akimbo. This is due to incorrect usage of llTargetOmega(). The behavior of llTargetOmega() is a little bit odd, and we shall here demonstrate a small script which tames it.

llTargetOmega(vector axis, float spinrate, float gain);

For a nonphysical object (the only kind we shall here discuss) this creates a client-side rotation*. The “axis” is in world coordinates. the spin-rate is in radians-per-second (there are 6.28 radians in a circle). and the gain is ignored. I always set the gain to “1″.

To rotate an object around a vertical axis at one-tenth revolution per second, you would say:

default
{
    state_entry()
    {
        llTargetOmega(<0,0,1>,0.628,1);
    }
}

This rotates the object around the vertical axis regardless of how the object itself is oriented.

For a wheel, this is almost certainly not what you want! You want the wheel to rotate around its center no matter which way it is turned. Furthermore, if the wheel is linked to something, you still want the wheel to rotate around its own center. So, without further ado, here is a simple script which turns a wheel around its correct center, even if it’s attached to something. The script is set to start and stop the wheel by touch.

	
integer running = 0; // if zero, stopped. if one, we are presently turning.
	
default
{
    touch_start(integer k)
    {
        integer isRoot = llGetLinkNumber() < = 1;
        running = !running;
        if(running)
        {
            vector axis = <0,0,1>;
            axis *= llGetRot();
            if(!isRoot)
                axis /= llGetRootRotation();
            llTargetOmega(axis,1,1);
        }
        else
        {
            llTargetOmega(<0,0,0>,0,0);
        }
        // one last trick: sometimes the client doesn’t update
        // after a change to client target omega. setting the
        // text to a new thing — but with alpha zero, so it
        // doesn’t actually display anything — works around that.
        llSetText((string)llFrand(1.0),<0,0,0>,0);
    }
}

(Edit: Thanks Ordinal Malaprop for the more correct way to ascertain root-ness.)

(One last hack: there is a bug in Second Life where sometimes a change to llTargetOmega() doesn’t get sent to the client. The llSetText() sets a random number as the text with alpha 0.0, so it is invisible. This is enough to “nudge” the client into respecting the llTargetOmega().)

And then you can link complex items whose wheels, and reels, behave.

An Open Question

What is the best way to determine if the prim running the script is the root prim? The script above attempts to discern it programmatically, and will behave correctly, but a more explicity query would be nice.

*Note: It appears to me that in recent revisions of the client that this may be more than client side, now; when the object is stopped, the edit tab shows a new and different rotation.

2 Responses to “Rotating A Wheel”

  1. Ordinal Malaprop Says:

    Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/davancamus/public_html/blog/wp-includes/functions-formatting.php on line 76

    llGetLinkNumber() should return 1 if the script is running in the root, or 0 if it is not linked at all I believe.

  2. Davan Camus Says:

    Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/davancamus/public_html/blog/wp-includes/functions-formatting.php on line 76

    D’oh! Thanks! …will update the example when the world reopens and we can test this.

Leave a Reply