Constraining rotations
A turret follows a rotation such as the camera’s, but its ring only turns around its mount (yaw)
and its barrel only tilts (pitch), often each at its own speed. These functions take any rotation
and keep only the part you want, relative to a normal N (the “up” direction of the mount). They build new axes with cross products and turn them back into a rotation
with llAxes2Rot.
The functions
Section titled “The functions”// Yaw only: turns around N to face where R faces, with N as up.rotation ConstrainYaw(rotation R, vector N){ vector U = N; vector L = llRot2Fwd(R) % U; vector F = llVecNorm(U % L); L = llVecNorm(U % F); return llAxes2Rot(F, L, U);}
// No roll: faces exactly where R faces, with its left axis kept level with N.rotation ConstrainPitch(rotation R, vector N){ vector F = llRot2Fwd(R); vector L = llVecNorm(F % N); vector U = -llVecNorm(F % L); L = U % F; return llAxes2Rot(F, L, U);}
// Yaw only, taken from R's left axis instead of its forward axis.// Unlike ConstrainYaw, this still works when R looks straight along N (e.g. a camera looking down).rotation ConstrainTopDown(rotation R, vector N){ vector L = llVecNorm((N % llRot2Left(R)) % N); return llAxes2Rot(L % N, L, N);}
// Scales a quaternion to unit length. Zero-length input is returned unchanged.rotation NormalizeRot(rotation Q){ float magnitude = llSqrt((Q.x * Q.x) + (Q.y * Q.y) + (Q.z * Q.z) + (Q.s * Q.s)); if (magnitude == 0.0) return Q; return <Q.x / magnitude, Q.y / magnitude, Q.z / magnitude, Q.s / magnitude>;}
// Turns from towards to by at most maxAngle radians, taking the shorter way round.rotation StepRotation(rotation from, rotation to, float maxAngle){ rotation delta = (ZERO_ROTATION / from) * to; // q and -q are the same rotation; pick the one with the smaller angle. if (delta.s < 0.0) delta = <-delta.x, -delta.y, -delta.z, -delta.s>; if (llRot2Angle(delta) <= maxAngle) return to; return from * llAxisAngle2Rot(llRot2Axis(delta), maxAngle);}StepRotation turns one rotation towards another by at most a given angle per step, so each part
can move at its own top speed; see Interpolation and easing for more ways
to blend rotations.
Turret rotation puts these functions to work in a
complete script: a turret ring (Turret) that turns only around the vehicle’s up axis and a barrel
(Barrel) that only tilts, each at its own top speed, following the camera of whoever sits on the
root prim.
Notes and limits
Section titled “Notes and limits”- N must be a unit vector for
ConstrainYawandConstrainTopDown; pass it throughllVecNormif it comes from a calculation. ConstrainYawhas no answer when R looks exactly along N (straight up or down): the cross product is zero,llVecNormreturnsZERO_VECTOR, and the axes passed tollAxes2Rotare not valid. UseConstrainTopDownfor cameras that can look straight down, or keep the previous result in that case.ConstrainPitchhas the same problem, since it also crosses R’s forward axis with N.ConstrainPitchkeeps R’s forward direction, including any yaw. To get the tilt alone, remove the yaw first withR / ConstrainYaw(R, N), as the turret does withlocalRot / targetYaw.StepRotationmoves at a fixed angular speed: at most maxAngle per call, measured withllRot2Angle.llGetCameraRotneedsPERMISSION_TRACK_CAMERAand returns the camera of the avatar that granted it.
Source and licence
Section titled “Source and licence”From rotations.lsl in
NexiiLSL by Martin Pitt, © 2026, under the
MIT licence, at commit 996fbd7.
Changes from the original:
ConstrainTopDownpassed axes that were not unit length tollAxes2Rot, which needs mutually orthogonal unit vectors. The left axis is now normalised, and the unused intermediate forward vector is folded into it.NormalizeRot’sval >= 0.0check was always true, because a sum of squares cannot be negative. It is removed; only the zero-length check remains, and the function now returns a new rotation instead of assigning to the components of Q.StepRotationis added, written for this page: the original turret example calledstepRotation, which was not defined.- The turret example is on its own page, Turret rotation, with its changes listed there.