Sitting, poses and poseballs
Sit targets
1. The basics of llSitTarget(offset, rot)
The sitter faces the target rotation's +X. A changed sit target applies only after the sitter stands and sits
again. WorldBridge set_sit_target (uuid, x,y,z in the root prim's frame, rx,ry,rz in degrees) sets one
without a script.
2. Start from OpenSim's arithmetic, then bracket with a real sitter
From OpenSim's ScenePresence: a sit with no target puts the avatar root about 0.65 m over the surface; a sit
target puts it at target + 0.40 + about 0.05. The traditional correction is about -0.4 m in z from where you first
think the seat is, plus a nudge forward. Then find the height by BRACKETING with someone actually sitting, not by
formula.
- Learned: for one chair the plain sit landed at (0.18 forward, 0.20 up) after (0.12, 0.15) was too low and too far back and (0.25, 0.25) too far and too high. A bench ended at 0.12 forward, 0.30 above the seat top; the first guess of 0.20 sank into the wall behind it.
- Judge from the SITTER'S camera angle. A top-down screenshot hid a 0.1 m gap that the sitter's side view showed at once; the final fireside values took four rounds of "too high / too far" in local chat.
- Carry a tuned height to another seat by the difference in half-thickness (a stone seat: +0.115).
3. Every clickable part of a multi-prim seat needs the sit target
A bed is several prims (frame, quilt, pillow, fold). Each needs the sit target, expressed in its own rotated frame, or the sitter lands anywhere.
- See:
tools/bed_sit.py.
4. The built-in 'sleep' pose lies down from standing height
Aim about 0.75 m above the mattress, and turn the target by PI: it lies with the head where the sitter's back was.
5. A bench on a slope
Legs down to the ground under each foot, a level seat, clear of any plinth, and one sit target per board so two
people can sit. See tools/build_bench.py.
Poseballs
6. What a poseball is
A small, hideable prim with a sit target and a script. On sit: llRequestPermissions(av, PERMISSION_TRIGGER_ANIMATION) (granted automatically to a sitter), llStopAnimation("sit"),
llStartAnimation(pose), hide the ball. On stand: stop the pose and show the ball.
7. OpenSim plays an animation only by the prim's inventory NAME
llStartAnimation and osAvatarPlayAnimation never accept an asset id (read in LSL_Api.cs / OSSL_Api.cs). The
pose must be INSIDE the ball: WorldBridge put_inventory puts a stored animation asset into the prim's contents.
If the pose is missing, fall back to the plain sit rather than stopping sit and leaving the sitter in no pose.
8. Do not copy the classic touch-to-hide toggle
A visitor who left-clicks the ball makes it vanish and then "loses" it. Make touch SHOW the ball and whisper how to sit.
9. Watching for a sit
The ball hiding is not proof by itself (a touch could hide it); also require the avatar to be within reach of the ball.
10. Tune a poseball with set_sit_target, not by rebuilding it
A rebuild despawns the ball and stands the sitter up; a direct sit-target change applies at their next sit. A custom pose with level thighs sits HIGHER than the default sit, so the poseball needed its own, lower offset (the final fireside values: poseball 0.5 above the seat, offset z -0.575).
Writing avatar poses as .anim
11. The avatar skeleton has no rest rotations
avatar_skeleton.xml gives positions only, so an .anim joint rotation is a parent-relative rotation in one body
frame: X forward, Y left, Z up. Proven in the real viewer with someone sitting:
- The sign is as derived: hip = -90 degrees about Y swings the thigh FORWARD; knee = +82 about Y hangs the shin down.
- The bind pose is a T-POSE: the arms lie along +Y (left) and -Y (right). A pitch about Y only spins an arm about
its own length (the first try left the arms sticking straight out). Roll it DOWN first (about X: -84 left, +84
right), THEN pitch forward (about Y, -36);
qmul(a, b)applies b first. Elbows bend about Z with opposite signs per side (-50 left, +50 right). That set reads as someone warming their hands at a fire. - A static pose is two identical keys, looped, at priority 4 so it overrides the default sit on the joints it names.
- See:
tools/make_sit_pose.py(its binary layout matchestools/build_walk_anim.py).
12. Make the first pose diagnostic
One unmistakable joint (thighs forward 90 degrees) settles the sign convention before a library of poses is built
on it. make_sit_pose.py has a SIGN constant for exactly this reason.
13. A moving pose is a keyed loop, and one screenshot cannot show it
The warming pose keeps the legs still and moves the arms on a 3.2 s cycle built from whole-cycle terms, so the loop seam is about 3e-5. To check motion in the viewer, take two screenshots about half a cycle apart and compare.
Sit cameras
14. A sitter grants camera control without being asked
PERMISSION_CONTROL_CAMERA is granted to a sitter automatically. llSetCameraParams with a locked
CAMERA_POSITION far out along a telescope's axis and the focus beyond it gives "the sea comes near". Stop sit
and start stand so the sitter stands at the eyepiece; llClearCameraParams on unsit. Seen working in Firestorm.
- A glass needs something out there to find: the open sea alone reads empty.
- See:
tools/grow_lookout.py,tools/grow_skerry.py.