Rotations

rotation() or quaternion() create a rotation from its components:
myRot = rotation(1, 1, 1, 0) or myRot = quaternion(1, 1, 1, 0).

  • It’s not possible to assign a value to a component. We need to create a new rotation.
  • We can get a component from the return value of a function, not only from a variable.
  • Components are stored in 32 bits floats.
  • Vectors can use uppercase components (X, Y, Z) but rotations can’t. Let’s use always lowercase components.
-- rotations (SLua)

local myRot = rotation(1, 1, 1, 0)
local myRot2 = quaternion(2, 2, 2, 0)

myRot = rotation(myRot.x, myRot.y, myRot.z, -myRot.s)  -- we can't assign a value to a component

local rotS = ll.GetRot().s

torotation() or toquaternion() create a rotation from a string:
myRot = torotation("<1, 1, 1, 0>") or myRot = quaternion( torotation("<1, 1, 1, 0>")).

We have the datatypes rotation and quaternion, but internally only exists the type quaternion, rotation is just an alias:

if typeof(myVar) == "quaternion" then  -- NOT "rotation", it would never happen!
	-- do rotations stuff
end

typeof( ZERO_ROTATION ) -- > quaternion. There is no constant ZERO_QUATERNION.

The rotation (or quaternion) library

SLua has a library with functions for rotations. We can’t use the :method notation, we have to call them on rotation (or quaternion):

rotation.create( x, y, z, s ) : creates a new rotation.

  • same as rotation( x, y, z, s )

rotation.conjugate( rot ) : returns a rotation, the “inverse” or opposite of the rotation. If rot rotates 90° left, conjugate(rot) rotates 90° right.

-- rotation.conjugate() written in SLua

local function conjugate(rot)
    return rotation(-rot.x, -rot.y, -rot.z, rot.s)
end

rotation.dot( rot1, rot2 ) : returns a number, the dot product of the rotations. It measures how “similar” two rotations are.

  • If the result is 1 or -1, the rotations are identical.
  • If the result is 0, they are 180 degrees apart.
-- rotation.dot() written in SLua

local function dot(a, b)
    return a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s
end

rotation.magnitude( rot ) : returns a number, the magnitude of the rotation.

-- rotation.magnitude() written in SLua

local function magnitude(rot)
    return math.sqrt(rot.x * rot.x + rot.y * rot.y + rot.z * rot.z + rot.s * rot.s)
end

rotation.normalize( rot ) : returns a rotation, the normalized version (unit rotation) of the rotation.

-- rotation.normalize() written in SLua

local function normalize(rot)
    local mag = math.sqrt(rot.x * rot.x + rot.y * rot.y + rot.z * rot.z + rot.s * rot.s)  -- magnitude
    if mag > 0.0000001 then
        if math.abs(1 - mag) > 0.000001 then
            local oomag = 1 / mag
            return rotation(rot.x * oomag, rot.y * oomag, rot.z * oomag, rot.s * oomag)
        else
            return rot
        end
    end
    return rotation(0, 0, 0 ,1)
end

rotation.slerp( rot1, rot2, interpolation ) : returns a rotation, uses Spherical Linear Interpolation to calculate a smooth rotation between a start rotation and a target rotation based on a percent (interpolation between 0 and 1).

-- rotation.slerp() written in SLua

local function slerp(a, b, u)
    local cos_t = a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s  -- dot product

    local bflip = false
    if cos_t < 0.0 then
        cos_t = -cos_t
        bflip = true
    end

    local alpha, beta
    if (1 - cos_t) < 0.00001 then
        beta = 1 - u
        alpha = u
    else
        local theta = math.acos(cos_t)
        local sin_t = math.sin(theta)
        beta = math.sin(theta - u * theta) / sin_t
        alpha = math.sin(u * theta) / sin_t
    end

    if bflip then
        beta = -beta
    end

    return rotation(
        beta * a.x + alpha * b.x,
        beta * a.y + alpha * b.y,
        beta * a.z + alpha * b.z,
        beta * a.s + alpha * b.s
    )
end

rotation.tofwd( rot ) : returns a vector, the Forward vector (local X-axis) of the rotation.

  • same as ll.Rot2Fwd( rot )

rotation.toleft( rot ) : returns a vector, the Left vector (local Y-axis) of the rotation.

  • same as ll.Rot2Left( rot )

rotation.toup( rot ) : returns a vector, the Up vector (local Z-axis) of the rotation.

  • same as ll.Rot2Up( rot )

rotation.identity : returns the identity rotation.

  • same as ZERO_ROTATION