187 lines
4.6 KiB
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 |