lyra-engine/lyra-scripting/scripts/lua/math/vec3.lua

187 lines
4.6 KiB
Lua

---@class Vec3
---@field x number
---@field y number
---@field z number
Vec3 = { x = 0.0, y = 0.0, z = 0.0 }
Vec3.__index = Vec3
Vec3.__name = "Vec3"
--- Constructs a new vector
---@param x number
---@param y number
---@param z number
---@return Vec3
function Vec3:new(x, y, z)
local v = {}
setmetatable(v, Vec3)
v.x = x
v.y = y
v.z = z
return v
end
---Creates a copy of self
---@return Vec3
function Vec3:clone()
return Vec3:new(self.x, self.y, self.z)
end
--- Constructs a vector with all elements as parameter `x`.
---@param x number
---@return Vec3
function Vec3:all(x)
return Vec3:new(x, x, x)
end
--- A unit-length vector pointing alongside the positive X axis.
Vec3.X = Vec3:new(1, 0, 0)
--- A unit-length vector pointing alongside the positive Y axis.
Vec3.Y = Vec3:new(0, 1, 0)
--- A unit-length vector pointing alongside the positive Z axis.
Vec3.Z = Vec3:new(0, 0, 1)
--- A unit-length vector pointing alongside the negative X axis.
Vec3.NEG_X = Vec3:new(-1, 0, 0)
--- A unit-length vector pointing alongside the negative Y axis.
Vec3.NEG_Y = Vec3:new(0, -1, 0)
--- A unit-length vector pointing alongside the negative Z axis.
Vec3.NEG_Z = Vec3:new(0, 0, -1)
--- A vector of all zeros
Vec3.ZERO = Vec3:new(0, 0, 0)
--- A vector of all ones
Vec3.ONE = Vec3:new(1, 1, 1)
--- Computes the absolute value of `self`.
function Vec3:abs()
self.x = math.abs(self.x)
self.y = math.abs(self.y)
self.z = math.abs(self.z)
end
--- Computes the length of `self`.
---@return number
function Vec3:length()
return math.sqrt(self:dot(self))
end
---Moves `self` by the provided coordinates
---@param x number
---@param y number
---@param z number
function Vec3:move_by(x, y, z)
self.x = self.x + x
self.y = self.y + y
self.z = self.z + z
end
--- Computes the dot product of `self` and `rhs`.
---@param rhs Vec3
---@return number
function Vec3:dot(rhs)
assert(rhs.__name == "Vec3")
return (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
end
--- Returns a vector that has the minimum value of each element of `self` and `rhs`
---@param rhs Vec3
---@return Vec3
function Vec3:min(rhs)
local x = math.min(self.x, rhs.x)
local y = math.min(self.y, rhs.y)
local z = math.min(self.z, rhs.z)
return Vec3:new(x, y, z)
end
--- Modifies `self` to be normalized to a length 1.
function Vec3:normalize()
local len_recip = 1.0 / self:length()
self.x = self.x * len_recip
self.y = self.y * len_recip
self.z = self.z * len_recip
end
--- Calculates the linear iterpolation between `self` and `rhs` based on the `alpha`.
--- When `alpha` is `0`, the result will be equal to `self`. When `s` is `1`, the result
--- will be equal to `rhs`
--- @param rhs Vec3
--- @param alpha number
--- @return Vec3
function Vec3:lerp(rhs, alpha)
-- ensure alpha is [0, 1]
local alpha = math.max(0, math.min(1, alpha))
local res = self:clone()
res = res + ((rhs - res) * alpha)
return res
end
function Vec3:__add(rhs)
if type(rhs) == "Vec3" then
return Vec3:new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
else
return Vec3:new(self.x + rhs, self.y + rhs, self.z + rhs)
end
end
function Vec3:__sub(rhs)
if type(rhs) == "Vec3" then
return Vec3:new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
else
return Vec3:new(self.x - rhs, self.y - rhs, self.z - rhs)
end
end
function Vec3:__mul(rhs)
if type(rhs) == "Vec3" then
return Vec3:new(self.x * rhs.x, self.y * rhs.y, self.z * rhs.z)
else
return Vec3:new(self.x * rhs, self.y * rhs, self.z * rhs)
end
end
function Vec3:__div(rhs)
if type(rhs) == "Vec3" then
return Vec3:new(self.x / rhs.x, self.y / rhs.y, self.z / rhs.z)
else
return Vec3:new(self.x / rhs, self.y / rhs, self.z / rhs)
end
end
function Vec3:__idiv(rhs)
if type(rhs) == "Vec3" then
return Vec3:new(self.x // rhs.x, self.y // rhs.y, self.z // rhs.z)
else
return Vec3:new(self.x // rhs, self.y // rhs, self.z // rhs)
end
end
function Vec3:__unm()
return Vec3:new(-self.x, -self.y, -self.z)
end
function Vec3:__pow(rhs)
if type(rhs) == "number" then
return Vec3:new(self.x ^ rhs, self.y ^ rhs, self.z ^ rhs)
end
end
function Vec3:__eq(rhs)
return self.x == rhs.x and self.y == rhs.y and self.z == rhs.z
end
function Vec3:__lt(rhs)
return self.x < rhs.x and self.y < rhs.y and self.z < rhs.z
end
function Vec3:__le(rhs)
return self.x <= rhs.x and self.y <= rhs.y and self.z <= rhs.z
end
function Vec3:__tostring()
return "Vec3(" .. self.x .. ", " .. self.y .. ", " .. self.z .. ")"
end