forked from Bastion/Bastion
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
333 lines
7.4 KiB
333 lines
7.4 KiB
-- Create a Vector3 class
|
|
|
|
---@class Vector3
|
|
local Vector3 = { }
|
|
Vector3.__index = Vector3
|
|
|
|
---@return string
|
|
function Vector3:__tostring()
|
|
return "Vector3(" .. self.x .. ", " .. self.y .. ", " .. self.z .. ")"
|
|
end
|
|
|
|
---@param other Vector3
|
|
---@return Vector3
|
|
function Vector3:__add(other)
|
|
return Vector3:New(self.x + other.x, self.y + other.y, self.z + other.z)
|
|
end
|
|
|
|
---@param other Vector3
|
|
---@return Vector3
|
|
function Vector3:__sub(other)
|
|
if type(other) == "number" then
|
|
return Vector3:New(self.x - other, self.y - other, self.z - other)
|
|
end
|
|
return Vector3:New(self.x - other.x, self.y - other.y, self.z - other.z)
|
|
end
|
|
|
|
---@param other number
|
|
---@return Vector3
|
|
function Vector3:__mul(other)
|
|
return Vector3:New(self.x * other, self.y * other, self.z * other)
|
|
end
|
|
|
|
---@param other number
|
|
---@return Vector3
|
|
function Vector3:__div(other)
|
|
return Vector3:New(self.x / other, self.y / other, self.z / other)
|
|
end
|
|
|
|
---@param other Vector3
|
|
---@return boolean
|
|
function Vector3:__eq(other)
|
|
return self.x == other.x and self.y == other.y and self.z == other.z
|
|
end
|
|
|
|
---@param other Vector3
|
|
---@return boolean
|
|
function Vector3:__lt(other)
|
|
return self.x < other.x and self.y < other.y and self.z < other.z
|
|
end
|
|
|
|
---@param other Vector3
|
|
---@return boolean
|
|
function Vector3:__le(other)
|
|
return self.x <= other.x and self.y <= other.y and self.z <= other.z
|
|
end
|
|
|
|
---@return Vector3
|
|
function Vector3:__unm()
|
|
return Vector3:New(-self.x, -self.y, -self.z)
|
|
end
|
|
|
|
---@return number
|
|
function Vector3:__len()
|
|
return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
|
|
end
|
|
|
|
function Vector3:__index(k)
|
|
if Vector3[k] then
|
|
return Vector3[k]
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field length number
|
|
if k == "length" then
|
|
return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field normalized Vector3
|
|
if k == "normalized" then
|
|
local length = math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
|
|
return Vector3:New(self.x / length, self.y / length, self.z / length)
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field magnitude number
|
|
if k == "magnitude" then
|
|
return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field sqrMagnitude number
|
|
if k == "sqrMagnitude" then
|
|
return self.x * self.x + self.y * self.y + self.z * self.z
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field zero Vector3
|
|
if k == "zero" then
|
|
return Vector3:New(0, 0, 0)
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field one Vector3
|
|
if k == "one" then
|
|
return Vector3:New(1, 1, 1)
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field up Vector3
|
|
if k == "up" then
|
|
return Vector3:New(0, 1, 0)
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field down Vector3
|
|
if k == "down" then
|
|
return Vector3:New(0, -1, 0)
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field left Vector3
|
|
if k == "left" then
|
|
return Vector3:New(-1, 0, 0)
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field right Vector3
|
|
if k == "right" then
|
|
return Vector3:New(1, 0, 0)
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field forward Vector3
|
|
if k == "forward" then
|
|
return Vector3:New(0, 0, 1)
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field back Vector3
|
|
if k == "back" then
|
|
return Vector3:New(0, 0, -1)
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field positiveInfinity Vector3
|
|
if k == "positiveInfinity" then
|
|
return Vector3:New(math.huge, math.huge, math.huge)
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field negativeInfinity Vector3
|
|
if k == "negativeInfinity" then
|
|
return Vector3:New(-math.huge, -math.huge, -math.huge)
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field nan Vector3
|
|
if k == "nan" then
|
|
return Vector3:New(0 / 0, 0 / 0, 0 / 0)
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field epsilon number
|
|
if k == "epsilon" then
|
|
return 1.401298E-45
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field maxValue number
|
|
if k == "maxValue" then
|
|
return 3.402823E+38
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field minValue number
|
|
if k == "minValue" then
|
|
return -3.402823E+38
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field x number
|
|
if k == "x" then
|
|
return self[1]
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field y number
|
|
if k == "y" then
|
|
return self[2]
|
|
end
|
|
|
|
---@class Vector3
|
|
---@field z number
|
|
if k == "z" then
|
|
return self[3]
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
function Vector3:__newindex(k, v)
|
|
if k == "x" then
|
|
self[1] = v
|
|
elseif k == "y" then
|
|
self[2] = v
|
|
elseif k == "z" then
|
|
self[3] = v
|
|
else
|
|
rawset(self, k, v)
|
|
end
|
|
end
|
|
|
|
---@param x number
|
|
---@param y number
|
|
---@param z number
|
|
---@return Vector3
|
|
function Vector3:New(x, y, z)
|
|
if x == false then
|
|
return Vector3:New(0, 0, 0)
|
|
end
|
|
|
|
local self = setmetatable({ x, y, z }, Vector3)
|
|
return self
|
|
end
|
|
|
|
---@param rhs Vector3
|
|
---@return number
|
|
function Vector3:Dot(rhs)
|
|
return self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
|
|
end
|
|
|
|
---@param rhs Vector3
|
|
---@return Vector3
|
|
function Vector3:Cross(rhs)
|
|
return Vector3:New(self.y * rhs.z - self.z * rhs.y, self.z * rhs.x - self.x * rhs.z, self.x * rhs.y - self.y * rhs.x)
|
|
end
|
|
|
|
---@param b Vector3
|
|
---@return number
|
|
function Vector3:Distance(b)
|
|
return FastDistance(self.x, self.y, self.z, b.x, b.y, b.z)
|
|
end
|
|
|
|
---@param to Vector3
|
|
---@return number
|
|
function Vector3:Angle(to)
|
|
return math.acos(self:Dot(to) /
|
|
(
|
|
math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z) *
|
|
math.sqrt(to.x * to.x + to.y * to.y + to.z * to.z)))
|
|
end
|
|
|
|
---@param maxLength number
|
|
---@return Vector3
|
|
function Vector3:ClampMagnitude(maxLength)
|
|
if self:Dot(self) > maxLength * maxLength then
|
|
return self.normalized * maxLength
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
-- Implement a clamp function
|
|
---@param x number
|
|
---@param min number
|
|
---@param max number
|
|
---@return number
|
|
local function clamp(x, min, max)
|
|
return x < min and min or (x > max and max or x)
|
|
end
|
|
|
|
---@param b Vector3
|
|
---@param t number
|
|
---@return Vector3
|
|
function Vector3:Lerp(b, t)
|
|
t = clamp(t, 0, 1)
|
|
return Vector3:New(self.x + (b.x - self.x) * t, self.y + (b.y - self.y) * t, self.z + (b.z - self.z) * t)
|
|
end
|
|
|
|
---@param target Vector3
|
|
---@param maxDistanceDelta number
|
|
---@return Vector3
|
|
function Vector3:MoveTowards(target, maxDistanceDelta)
|
|
local toVector = target - self
|
|
local distance = toVector.magnitude
|
|
if distance <= maxDistanceDelta or distance == 0 then
|
|
return target
|
|
end
|
|
|
|
return self + toVector / distance * maxDistanceDelta
|
|
end
|
|
|
|
---@param b Vector3
|
|
---@return Vector3
|
|
function Vector3:Scale(b)
|
|
return Vector3:New(self.x * b.x, self.y * b.y, self.z * b.z)
|
|
end
|
|
|
|
---@param onNormal Vector3
|
|
---@return Vector3
|
|
function Vector3:Project(onNormal)
|
|
local num = onNormal:Dot(onNormal)
|
|
if num < 1.401298E-45 then
|
|
return Vector3:New(0, 0, 0)
|
|
end
|
|
|
|
return onNormal * self:Dot(onNormal) / num
|
|
end
|
|
|
|
---@param planeNormal Vector3
|
|
---@return Vector3
|
|
function Vector3:ProjectOnPlane(planeNormal)
|
|
return self - self:Project(planeNormal)
|
|
end
|
|
|
|
---@param inNormal Vector3
|
|
---@return Vector3
|
|
function Vector3:Reflect(inNormal)
|
|
return -2 * inNormal:Dot(self) * inNormal + self
|
|
end
|
|
|
|
---@return Vector3
|
|
function Vector3:Normalize()
|
|
local num = self:Dot(self)
|
|
if num > 1E-05 then
|
|
return self / math.sqrt(num)
|
|
end
|
|
|
|
return Vector3:New(0, 0, 0)
|
|
end
|
|
|
|
return Vector3
|
|
|