Vectors

vector() creates a vector from its components: myVec = vector(50, 50, 20).

  • It’s not possible to assign a value to a component. We need to create a new vector.
  • 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.
-- vectors

local myVec = vector(50, 50, 0)

myVec = vector(myVec.x, myVec.y, 20)  -- we can't assign a value to a component

local posZ = ll.GetPos().z

tovector() creates a vector from a string: myVec = tovector("<50, 50, 20>")

  • it returns nil when is passed an invalid vector.

The vector library

The SLua vector internally uses a Luau vector and its library. We can’t use the :method notation, we have to call them on vector:

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

  • same as vector( x, y, z )

vector.magnitude( vec ) : returns a number, the magnitude of the vector.

  • same as ll.VecMag( vec ).
    • vector.magnitude( vec1 - vec2 ) : returns a number, the distance between the vectors.
      • same as ll.VecDist( vec1, vec2 )

vector.normalize( vec ) : returns a vector, the normalized version (unit vector) of the vector.

  • same as ll.VecNorm( vec ).

vector.dot( vec1, vec2 ) : returns a number, the dot product of the vectors.

  • same as vec1 * vec2 in LSL (but not in SLua).

vector.cross( vec1, vec2 ) : returns a vector, the cross product of the vectors.

  • same as vec1 % vec2 in LSL and SLua.

vector.angle( vec1, vec2, axis ) : returns a number, the angle between the vectors in radians. The axis, if specified, is used to determine the sign of the angle.

-- vector.angle() written in SLua
local function angle(a, b, axis)
    local cross = vector.cross(a, b)
    local sinA = vector.magnitude(cross)
    local cosA = vector.dot(a, b)
    local angle = math.atan2(sinA, cosA)
    if axis then
        if vector.dot(cross, axis) < 0 then
            angle = -angle
        end
    end
    return angle
end

vector.lerp(vec1, vec2, t): Performs linear interpolation between two vectors. It calculates a specific point along the straight, shortest line between vector vec1 and vector vec2, based on a fractional value t. Parameters:

  • vec1 (vector): The starting vector.
  • vec2 (vector): The target/ending vector.
  • t (number): The interpolation fraction (alpha). Returns a new vector representing the interpolated position.

Behaviors:

  • Fractional Movement (t):
    • If t == 0, it returns the position of vector vec1.
    • If t == 1, it returns the position of vector vec2.
    • If t == 0.5, it returns a vector exactly halfway between vec1 and vec2.
  • Extrapolation: The function does not clamp t between 0 and 1. If we pass a t value less than 0 or greater than 1, it will “extrapolate,” meaning the point will continue past the start or end vectors along the same line.
  • Component-wise operation: The operation evaluates the X, Y, and Z axes independently. It does not curve or track rotation; it simply draws a straight line between the two points.
-- vector.lerp()
print(vector.lerp(vector(10, 50, 20),vector(60, 60, 20), 0.5))
-- > <35, 55, 20>

It’s equivalent to:

-- vector.lerp() in SLua
local function vectorLerp(vec1: vector, vec2: vector, t: number): vector
    -- (vec2 - vec1) gets the directional distance between the two vectors
    -- * t scales that distance
    -- vec1 + adds that scaled distance to the starting point
    return vec1 + (vec2 - vec1) * t
end

Vector operators

vec1 * vec2

In LSL is the dot product, in SLua multiplies the components:

  • print( vector(3, 4, 5) * vector(10, 10, 10) ) -- > <30, 40, 50>

In LSL this:

  • float dotProduct = myVec1 * myVec2; // LSL
    is this in SLua:
  • local dotProduct = vector.dot(myVec1, myVec2) -- SLua

SLua has added the division, that divides the components, and doesn’t exist in LSL:

  • print( vector(12, 6, 3) / vector(3, 2, 1) ) -- > <4, 3, 3>