Table of Contents

Shortnote

This script was tested and works on OpenSim version 0.7.4!

This is an opensim-compatible sit script. When an avatar sits on the target, permissions are requested and then the Sit Relaxed animation is triggered.

Setup

  1. Create a primitive and drop and animation named Sit Relaxed inside.
  2. Create a new script inside the same primitive and copy the contents of the script below.

Calibration

Chairs and other furniture pieces in OpenSim are usually made of sculptures that have the same geometry as their bounding boxes. In other words, although you may see a chair being curved and elegant, in OpenSim terms the chair is in fact a big box bounded by the dimensions of the sculpture. Because of that, you will have to change the following line in the script:

llSitTarget(<-.8,.0,-1>, llEuler2Rot(<0,275,180> * DEG_TO_RAD));

Where the vector -.8,.0,-1 represents the position of the avatar relative to the gravity center of the sculpture and the rotation llEuler2Rot(<0,275,180> * DEG_TO_RAD) represents the avatar's relative rotation to the sculpture.

These modifications have to be made for every sculpted furniture piece since the sculptures have different geometries.

Translations and Rotations Avatar Positon
''llSitTarget'' takes a translation as the first function parameter and a rotation as a second function parameter.  The avatar will be seated and rotated like the lower left box. In this case, upside down.

The llSitTarget takes a translation (in meters) and a rotation (in quarterions) that specifies where the avatar will appear sitting (Avatar Position figure on the right-hand side). We use llEuler2Rot since it is easier to work in degrees rather than radians and quarterions.

Optimization Note

Although we use:

llEuler2Rot(<0,275,180> * DEG_TO_RAD)

in the script to convert the degrees to radians and then to quarterions, it may be a good idea if the object is final to find out the quarterion vector:

llOwnerSay((string)llEuler2Rot(<0,275,180> * DEG_TO_RAD));

and place the result in the script so that the llSitTarget line reads:

llSitTarget(<-.8,.0,-1>, <-.67559, .00000, .73728, .00000>);

where $<-.67559, .00000, .73728, .00000>\text{quarterions}\equiv<0,275,180>\text{degrees}$.

The benefit of doing that is that the script containing the original line:

llSitTarget(<-.8,.0,-1>, llEuler2Rot(<0,275,180> * DEG_TO_RAD));

has to perform the following operations:

  1. multiply the vector <0,275,180> to obtain radians.
  2. convert the Euler rotation to quarterions via llEuler2Rot.
  3. finally, use that value with llSitTarget.

When, a call such as:

llSitTarget(<-.8,.0,-1>, <-.67559, .00000, .73728, .00000>);

just calls llSitTarget with the given values.

Depending on the compiler optimizations, the advantage may be minimal if the llSitTaget line does not get re-evaluated at runtime. The downside is that you will have magic numbers in the code which decreases readability and may not work in particular cases.

Code

sit.lsl
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2011 - License: GNU GPLv3      //
//  Please see: http://www.gnu.org/licenses/gpl.html for legal details,  //
//  rights of fair usage, the disclaimer and warranty conditions.        //
///////////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////////////
//                              INTERNALS                                //
///////////////////////////////////////////////////////////////////////////
 
default
{
    state_entry() {
        // set sit target, otherwise sitting will not work 
        llSitTarget(<-.8,.0,-1>, llEuler2Rot(<0,275,180> * DEG_TO_RAD));
        // set the mouse click action to sit
        llSetClickAction(CLICK_ACTION_SIT);
    }
    changed(integer change) {
        if(change & CHANGED_LINK) {
            if(llAvatarOnSitTarget()) {
                llRequestPermissions(llAvatarOnSitTarget(), PERMISSION_TRIGGER_ANIMATION);
            }
        }
    }
 
    run_time_permissions(integer perm) {
        if(perm & PERMISSION_TRIGGER_ANIMATION) {
            if(llGetInventoryType("Sit Relaxed") == INVENTORY_ANIMATION)
                llStartAnimation("Sit Relaxed");
        }
    }
}

Notes

OpenSim (and Second Life) call the rotations around the $x,y,z$-axes "Euler" degrees, after the mathematician that was first to develop polar coordinates (after Alexis Clairaut first introduced them). Each vector component $x,y,z$ represents a rotation around the local axes of the object. For example, in this particular case, the rotation is a $275$ degree rotation around the local $y$ axis of the object, composed with a $180$ degree rotation around the $z$ axes. The API function llEuler2Rot takes radians instead of degrees so that DEG_TO_RAD constant is a crude constant that when multiplied with the rotational angular vector <0,275,180> results in radians which llEuler2Rot then converts to quaternion notation and fed to the llSitTarget function.

Poseballs

Contrary to sculptures, poseballs rarely need code-level adjustments. A poseball is a sphere and given uniform coloring of that sphere it is impossible to tell by observation what rotation it has. Thus, for a poseball, the code could read a default of:

llSitTarget(<0,0,.1>, ZERO_ROTATION);

and then be adjusted in-world by using the translate and rotate features of the Edit interface pane in order to make an avatar look properly while sitting.

Note however, that a non-zero vector is needed for the translate component of the llSitTarget call. Any zero-vector such as:

llSitTarget(<0,0,0>, ZERO_ROTATION);

or literally,

llSitTarget(ZERO_VECTOR, ZERO_ROTATION);

will cancel out any sit target set by the script.