Bastion aims to serve as a highly performant, simplisitic, and expandable World of Warcraft data visualization framework.
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.
Bastion/src/Vector3/Vector3.lua

241 lines
5.3 KiB

2 years ago
-- Create a Vector3 class
local Vector3 = {}
Vector3.__index = Vector3
function Vector3:__tostring()
return "Vector3(" .. self.x .. ", " .. self.y .. ", " .. self.z .. ")"
end
function Vector3:__add(other)
return Vector3:New(self.x + other.x, self.y + other.y, self.z + other.z)
end
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
function Vector3:__mul(other)
return Vector3:New(self.x * other, self.y * other, self.z * other)
end
function Vector3:__div(other)
return Vector3:New(self.x / other, self.y / other, self.z / other)
end
function Vector3:__eq(other)
return self.x == other.x and self.y == other.y and self.z == other.z
end
function Vector3:__lt(other)
return self.x < other.x and self.y < other.y and self.z < other.z
end
function Vector3:__le(other)
return self.x <= other.x and self.y <= other.y and self.z <= other.z
end
function Vector3:__unm()
return Vector3:New(-self.x, -self.y, -self.z)
end
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
if k == "length" then
return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
end
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
if k == "magnitude" then
return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
end
if k == "sqrMagnitude" then
return self.x * self.x + self.y * self.y + self.z * self.z
end
if k == "zero" then
return Vector3:New(0, 0, 0)
end
if k == "one" then
return Vector3:New(1, 1, 1)
end
if k == "up" then
return Vector3:New(0, 1, 0)
end
if k == "down" then
return Vector3:New(0, -1, 0)
end
if k == "left" then
return Vector3:New(-1, 0, 0)
end
if k == "right" then
return Vector3:New(1, 0, 0)
end
if k == "forward" then
return Vector3:New(0, 0, 1)
end
if k == "back" then
return Vector3:New(0, 0, -1)
end
if k == "positiveInfinity" then
return Vector3:New(math.huge, math.huge, math.huge)
end
if k == "negativeInfinity" then
return Vector3:New(-math.huge, -math.huge, -math.huge)
end
if k == "nan" then
return Vector3:New(0 / 0, 0 / 0, 0 / 0)
end
if k == "epsilon" then
return 1.401298E-45
end
if k == "maxValue" then
return 3.402823E+38
end
if k == "minValue" then
return -3.402823E+38
end
if k == "x" then
return self[1]
end
if k == "y" then
return self[2]
end
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
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
function Vector3:Dot(rhs)
return self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
end
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
function Vector3:Distance(b)
return FastDistance(self.x, self.y, self.z, b.x, b.y, b.z)
end
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
function Vector3:ClampMagnitude(maxLength)
if self:Dot(self) > maxLength * maxLength then
return self.normalized * maxLength
end
return self
end
-- Implement a clamp function
local function clamp(x, min, max)
return x < min and min or (x > max and max or x)
end
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
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
function Vector3:Scale(b)
return Vector3:New(self.x * b.x, self.y * b.y, self.z * b.z)
end
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
function Vector3:ProjectOnPlane(planeNormal)
return self - self:Project(planeNormal)
end
function Vector3:Reflect(inNormal)
return -2 * inNormal:Dot(self) * inNormal + self
end
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