Hey there, I recently made a Vector4 module because I thought it would be nice to have a version that’s as similar to Vector3 in functionality as possible.
So here it is in all it’s glory, Vector4 module with support for all operations Vector3’s have, using meta-methods, all of the functions and constants, etc. There’s also a Vector4int16 version because why not!
Vector4
https://www.roblox.com/library/5906902916/Vector4
Vector4 Main Module Code
local meta = require(script:WaitForChild("Vec4MetaMethods"))
type Vector4 = {
X : number,
Y : number,
Z : number,
W : number
}
local Vector4 = {}
Vector4.__index = Vector4
Vector4 = meta.copy(Vector4)
function Vector4.new(x : number?, y : number?, z : number?, w : number?): Vector4
assert((type(x) == "number") or x == nil, "Vector4's xAxis must be a number")
assert((type(y) == "number") or y == nil, "Vector4's yAxis must be a number")
assert((type(z) == "number") or z == nil, "Vector4's zAxis must be a number")
assert((type(w) == "number") or w == nil, "Vector4's wAxis must be a number")
local newVector = {
["X"] = x or 0,
["Y"] = y or 0,
["Z"] = z or 0,
["W"] = w or 0
}
return setmetatable(newVector, Vector4)
end
function Vector4.FromNormalId(normal : EnumItem): Vector4
local directions = {
["Right"] = Vector4.new(1),
["Left"] = Vector4.new(-1),
["Top"] = Vector4.new(0, 1),
["Bottom"] = Vector4.new(0, -1),
["Back"] = Vector4.new(0, 0, 1),
["Front"] = Vector4.new(0, 0, -1)
}
return directions[normal.Name]
end
function Vector4.FromAxis(axis : EnumItem): Vector4
local axes = {
["X"] = Vector4.new(1),
["Y"] = Vector4.new(0, 1),
["Z"] = Vector4.new(0, 0, 1)
}
return axes[axis.Name]
end
function Vector4.FromString(str : string): Vector4
local x, y, z, w = string.match(str, "^"..string.rep("([%d%p]+)%s?,%s?", 3).."([%d%p]+)$")
assert((x and y and z and w), str.." is not compatible with FromString()")
return Vector4.new(
tonumber(x),
tonumber(y),
tonumber(z),
tonumber(w)
)
end
Vector4.zero = Vector4.new()
Vector4.one = Vector4.new(1, 1, 1, 1)
Vector4.xAxis = Vector4.new(1)
Vector4.yAxis = Vector4.new(0, 1)
Vector4.zAxis = Vector4.new(0, 0, 1)
Vector4.wAxis = Vector4.new(0, 0, 0, 1)
Vector4.min = Vector4.new(-math.huge, -math.huge, -math.huge, -math.huge)
Vector4.max = Vector4.new(math.huge, math.huge, math.huge, math.huge)
Vector4.pi = Vector4.new(math.pi, math.pi, math.pi, math.pi)
function Vector4:Magnitude(): number
return math.sqrt(self.X ^ 2 + self.Y ^ 2 + self.Z ^ 2 + self.W ^ 2)
end
function Vector4:Unit(): Vector4
local mag = math.sqrt(self.X ^ 2 + self.Y ^ 2 + self.Z ^ 2 + self.W ^ 2)
return Vector4.new(
(self.X / mag),
(self.Y / mag),
(self.Z / mag),
(self.W / mag)
)
end
function Vector4:Cross(other : Vector4): Vector4
return Vector4.new(
(self.Y * other.Z) - (self.Z * other.Y),
(self.Z * other.X) - (self.X * other.Z),
(self.X * other.Y) - (self.Y * other.X),
self.W -- Can't cross 4d vectors --
)
end
function Vector4:Dot(other : Vector4): number
return (self.X * other.X) + (self.Y * other.Y) + (self.Z * other.Z) + (self.W * other.W)
end
function Vector4:FuzzyEq(other : Vector4, epsilon : number?): boolean
epsilon = (epsilon or 1e-5)
local function fuzzyEq(a : number, b : number): boolean
return a == b or math.abs(a - b) <= (math.abs(a) + 1) * epsilon
end
for _, axis in ipairs({"X", "Y", "Z", "W"}) do
if not fuzzyEq(self[axis], other[axis]) then
return false
end
end
return true
end
function Vector4:Lerp(goal : Vector4, alpha : number): Vector4
return (self + (goal - self) * alpha)
end
function Vector4:Max(... : Vector4): Vector4
local x, y, z, w = {}, {}, {}, {}
local vectors = {self, ...}
for _, vec in ipairs(vectors) do
table.insert(x, vec.X)
table.insert(y, vec.Y)
table.insert(z, vec.Z)
table.insert(w, vec.W)
end
return Vector4.new(
math.max(table.unpack(x)),
math.max(table.unpack(y)),
math.max(table.unpack(z)),
math.max(table.unpack(w))
)
end
function Vector4:Min(... : Vector4): Vector4
local x, y, z, w = {}, {}, {}, {}
local vectors = {self, ...}
for _, vec in ipairs(vectors) do
table.insert(x, vec.X)
table.insert(y, vec.Y)
table.insert(z, vec.Z)
table.insert(w, vec.W)
end
return Vector4.new(
math.min(table.unpack(x)),
math.min(table.unpack(y)),
math.min(table.unpack(z)),
math.min(table.unpack(w))
)
end
function Vector4:ToString(condense : boolean?): string
if condense then
return (self.X .. "," .. self.Y .. "," .. self.Z .. "," .. self.W)
else
return tostring(self)
end
end
function Vector4:GetComponents()
return self.X, self.Y, self.Z, self.W
end
return Vector4
--[[
Made by M_dgettMann (shadowflame63)
Vector4 has all the functionality Vector3 has. (Excluding deprecated stuff)
There are also a few extras:
> Vector4.min -- All values are -inf
> Vector4.max -- All values are inf
> Vector4.pi -- All values are pi
> Vector4:ToString(condense) -- if condense is true, then returns tostring(Vector4) without the spaces, otherwise identical to tostring(Vector4)
> Vector4.FromString(str) -- Converts the product from tostring(Vector4) or ToString() back into a Vector4
> Vector4:GetComponents() -- Similar to CFrame:GetComponents(), returns all components of the Vector4
Note: > It's Vector4:Magnitude() and Vector4:Unit(), instead of Vector4.Magnitude and Vector4.Unit
> Vector4:Cross() is identical to Vector3:Cross(), so W is ignored
]]
Vector4 MetaMethods Module Code
local metaMethods = {
__unm = function(vec4)
for i, v in pairs(vec4) do
vec4[i] = -v
end
return vec4
end,
__add = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] += v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v + v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v + v1
end
end
return merge
end,
__sub = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] -= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v - v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v - v1
end
end
return merge
end,
__mul = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] *= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v * v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v * v1
end
end
return merge
end,
__div = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] /= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v / v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v / v1
end
end
return merge
end,
__mod = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] %= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v % v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v % v1
end
end
return merge
end,
__pow = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] ^= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v ^ v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v ^ v1
end
end
return merge
end,
__tostring = function(vec4)
local tbl = {}
for i, num in pairs(vec4) do
local str = string.split(tostring(num), ".")
if str[2] then tbl[i] = #str[2] else tbl[i] = 0 end
end
local format = ("%."..tbl.X.."f, %."..tbl.Y.."f, %."..tbl.Z.."f, %."..tbl.W.."f")
return string.format(format, vec4.X, vec4.Y, vec4.Z, vec4.W)
end,
__eq = function(vec4, value)
for i, v in pairs(vec4) do
if not rawequal(value[i], v) then return false end
end
return true
end,
__lt = function(vec4, value)
for i, v in pairs(vec4) do
if value[i] <= v then return false end
end
return true
end,
__le = function(vec4, value)
for i, v in pairs(vec4) do
if value[i] < v then return false end
end
return true
end,
__type = "Vector4"
}
return {
setup = function(vec4)
local metaCopy = {}
for i, v in pairs(metaMethods) do
metaCopy[i] = v
end
return setmetatable(vec4, metaCopy)
end,
copy = function(vec4)
if vec4 then
for i, v in pairs(metaMethods) do
vec4[i] = v
end
return vec4
else
return metaMethods
end
end,
remove = function(vec4)
return setmetatable(vec4, nil)
end
}
)
Vector4int16
https://www.roblox.com/library/5742651074/Vector4int16
Vector4int16 Main Module Code
local meta = require(script:WaitForChild("Vec4int16MetaMethods"))
local function int16(num : number): number
if num > (2 ^ 15) - 1 then num = (2 ^ 15) - 1 end
if num < (-2 ^ 15) then num = (-2 ^ 15) end
return math.round(num)
end
type Vector4int16 = {
X : number,
Y : number,
Z : number,
W : number
}
local Vector4int16 = {}
Vector4int16.__index = Vector4int16
Vector4int16 = meta.copy(Vector4int16)
function Vector4int16.new(x : number?, y : number?, z : number?, w : number?): Vector4int16
assert((type(x) == "number") or x == nil, "Vector4int16's xAxis must be a number")
assert((type(y) == "number") or y == nil, "Vector4int16's yAxis must be a number")
assert((type(z) == "number") or z == nil, "Vector4int16's zAxis must be a number")
assert((type(w) == "number") or w == nil, "Vector4int16's wAxis must be a number")
local newVector = {
["X"] = int16(x or 0),
["Y"] = int16(y or 0),
["Z"] = int16(z or 0),
["W"] = int16(w or 0)
}
return setmetatable(newVector, Vector4int16)
end
function Vector4int16.FromVector3int16(vec3 : Vector3int16, w : number?): Vector4int16
return Vector4int16.new(vec3.X, vec3.Y, vec3.Z, w or 0)
end
function Vector4int16.FromString(str : string): Vector4int16
local x, y, z, w = string.match(str, "^"..string.rep("([%d%p]+)%s?,%s?", 3).."([%d%p]+)$")
assert((x and y and z and w), str.." is not compatible with FromString()")
return Vector4int16.new(
tonumber(x),
tonumber(y),
tonumber(z),
tonumber(w)
)
end
function Vector4int16.UnpackVector(str : string): Vector4int16
local px = string.sub(str, 1, 2)
local py = string.sub(str, 3, 4)
local pz = string.sub(str, 5, 6)
local pw = string.sub(str, 7, 8)
return Vector4int16.new(
string.unpack("i2", px),
string.unpack("i2", py),
string.unpack("i2", pz),
string.unpack("i2", pw)
)
end
Vector4int16.zero = Vector4int16.new()
Vector4int16.one = Vector4int16.new(1, 1, 1, 1)
Vector4int16.xAxis = Vector4int16.new(1)
Vector4int16.yAxis = Vector4int16.new(0, 1)
Vector4int16.zAxis = Vector4int16.new(0, 0, 1)
Vector4int16.wAxis = Vector4int16.new(0, 0, 0, 1)
Vector4int16.min = Vector4int16.new((-2 ^ 15), (-2 ^ 15), (-2 ^ 15), (-2 ^ 15))
Vector4int16.max = Vector4int16.new((2 ^ 15) - 1, (2 ^ 15) - 1, (2 ^ 15) - 1, (2 ^ 15) - 1)
function Vector4int16:Max(... : Vector4int16): Vector4int16
local x, y, z, w = {}, {}, {}, {}
local vectors = {self, ...}
for _, vec in ipairs(vectors) do
table.insert(x, vec.X)
table.insert(y, vec.Y)
table.insert(z, vec.Z)
table.insert(w, vec.W)
end
return Vector4int16.new(
math.max(table.unpack(x)),
math.max(table.unpack(y)),
math.max(table.unpack(z)),
math.max(table.unpack(w))
)
end
function Vector4int16:Min(... : Vector4int16): Vector4int16
local x, y, z, w = {}, {}, {}, {}
local vectors = {self, ...}
for _, vec in ipairs(vectors) do
table.insert(x, vec.X)
table.insert(y, vec.Y)
table.insert(z, vec.Z)
table.insert(w, vec.W)
end
return Vector4int16.new(
math.min(table.unpack(x)),
math.min(table.unpack(y)),
math.min(table.unpack(z)),
math.min(table.unpack(w))
)
end
function Vector4int16:ToString(condense : boolean?): string
if condense then
return (self.X .. "," .. self.Y .. "," .. self.Z .. "," .. self.W)
else
return tostring(self)
end
end
function Vector4int16:PackVector(): string
local px = string.pack("i2", self.X)
local py = string.pack("i2", self.Y)
local pz = string.pack("i2", self.Z)
local pw = string.pack("i2", self.W)
return (px .. py .. pz .. pw)
end
function Vector4int16:GetComponents()
return self.X, self.Y, self.Z, self.W
end
return Vector4int16
--[[
Made by M_dgettMann (shadowflame63)
Vector4int16 has all the functionality Vector3int16 has. (Excluding deprecated stuff)
There are also a few extras:
> Vector4int16.min -- All values are -2 ^ 15
> Vector4int16.max -- All values are 2 ^ 15 - 1
> Vector4int16:ToString(condense) -- if condense is true, then returns tostring(Vector4int16) without the spaces, otherwise identical to tostring(Vector4int16)
> Vector4int16.FromString(str) -- Converts the product from tostring(Vector4int16) or ToString() back into a Vector4int16
> Vector4int16:PackVector() -- Uses string.pack to pack a Vector4int16 into a string with a length of 8
> Vector4int16.UnpackVector(str) -- Converts the product from PackVector() back into a Vector4int16
> Vector4int16:GetComponents() -- Similar to CFrame:GetComponents(), returns all components of the Vector4int16
What's the purpose of an int16 version? Well it's niche but can be used when tranferring data at lower costs (e.g. RemoteEvents to reduce bandwidth usage)
However, it's mostly a micro-optimisation that many won't use, but I made it because Vector3int16 exists, and string.pack is cool
Note: If you want to convert a Vector4 into a Vector4int16 and visa versa, you'll have to do it the same way as Vector3
]]
Vector4int16 MetaMethods Module Code
local metaMethods = {
__unm = function(vec4)
for i, v in pairs(vec4) do
vec4[i] = -v
end
return vec4
end,
__add = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] += v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v + v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v + v1
end
end
return merge
end,
__sub = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] -= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v - v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v - v1
end
end
return merge
end,
__mul = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] *= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v * v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v * v1
end
end
return merge
end,
__div = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] /= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v / v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v / v1
end
end
return merge
end,
__mod = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] %= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v % v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v % v1
end
end
return merge
end,
__pow = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] ^= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v ^ v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v ^ v1
end
end
return merge
end,
__tostring = function(vec4)
local tbl = {}
for i, num in pairs(vec4) do
local str = string.split(tostring(num), ".")
if str[2] then tbl[i] = #str[2] else tbl[i] = 0 end
end
local format = ("%."..tbl.X.."f, %."..tbl.Y.."f, %."..tbl.Z.."f, %."..tbl.W.."f")
return string.format(format, vec4.X, vec4.Y, vec4.Z, vec4.W)
end,
__eq = function(vec4, value)
for i, v in pairs(vec4) do
if not rawequal(value[i], v) then return false end
end
return true
end,
__lt = function(vec4, value)
for i, v in pairs(vec4) do
if value[i] <= v then return false end
end
return true
end,
__le = function(vec4, value)
for i, v in pairs(vec4) do
if value[i] < v then return false end
end
return true
end,
__type = "Vector4int16"
}
return {
setup = function(vec4)
local metaCopy = {}
for i, v in pairs(metaMethods) do
metaCopy[i] = v
end
return setmetatable(vec4, metaCopy)
end,
copy = function(vec4)
if vec4 then
for i, v in pairs(metaMethods) do
vec4[i] = v
end
return vec4
else
return metaMethods
end
end,
remove = function(vec4)
return setmetatable(vec4, nil)
end
}
However, I found I couldn’t implement Vector4:Cross() because according to this publication (near the end because the rest is gibberish to me) cross products are only possible with 3d and 7d vectors. There are alternatives like triple cross products, etc, but these aren’t the same as Vector3:Cross().
I made these grids in excel to help visualise cross products:
3-axis (x, y, z)
Here’s a grid that represents two 3d vectors. The 0’s are the dot product, aka Vector3:Dot(), and the rest is the cross product, aka Vector3:Cross().
4-axis (x, y, z, w)
As you can see, this 4d grid is just an extension of the 3d one. But hold on, where did v, u and t come from? That’s where 7d comes in.
7-axis (x, y, z, w, v, u, t)
Wow, that’s big. As you can see though, the top left corner is the same as the 3d grid, and there’s no extra axes! You can see the relationship when you compare a row and a column coming off the same 0, they’re all inversed.
Keep in mind though that there are 480 different combinations of this table, this version just matches Vector3.
Well, why does the cross product work with 3d and 7d, but not 4d? This is just a guess, but I’m assuming it’s because there’s no way to order all the axes in a way that fits into the pattern 3d and 7d do. You could use the same technique 2d uses, and fill the extra axes of 7d as 0’s to make a 4d cross product, but this will most likely give an incorrect result because higher dimensions are weird. It may also have something to do with quaternions and octonions.
I’m sure you see where this is going, I made a Vector7 module including :Cross(), and of course Vector7int16 to go along with it:
Vector7
https://www.roblox.com/library/5699748049/Vector7
Vector7 Main Module Code
local meta = require(script:WaitForChild("Vec7MetaMethods"))
type Vector7 = {
X : number,
Y : number,
Z : number,
W : number,
V : number,
U : number,
T : number
}
local Vector7 = {}
Vector7.__index = Vector7
Vector7 = meta.copy(Vector7)
function Vector7.new(x : number?, y : number?, z : number?, w : number?, v : number?, u : number?, t : number?): Vector7
assert((type(x) == "number") or x == nil, "Vector7's xAxis must be a number")
assert((type(y) == "number") or y == nil, "Vector7's yAxis must be a number")
assert((type(z) == "number") or z == nil, "Vector7's zAxis must be a number")
assert((type(w) == "number") or w == nil, "Vector7's wAxis must be a number")
assert((type(v) == "number") or v == nil, "Vector7's vAxis must be a number")
assert((type(u) == "number") or u == nil, "Vector7's uAxis must be a number")
assert((type(t) == "number") or t == nil, "Vector7's tAxis must be a number")
local newVector = {
["X"] = x or 0,
["Y"] = y or 0,
["Z"] = z or 0,
["W"] = w or 0,
["V"] = v or 0,
["U"] = u or 0,
["T"] = t or 0
}
return setmetatable(newVector, Vector7)
end
function Vector7.FromNormalId(normal : EnumItem): Vector7
local directions = {
["Right"] = Vector7.new(1),
["Left"] = Vector7.new(-1),
["Top"] = Vector7.new(0, 1),
["Bottom"] = Vector7.new(0, -1),
["Back"] = Vector7.new(0, 0, 1),
["Front"] = Vector7.new(0, 0, -1)
}
return directions[normal.Name]
end
function Vector7.FromAxis(axis : EnumItem): Vector7
local axes = {
["X"] = Vector7.new(1),
["Y"] = Vector7.new(0, 1),
["Z"] = Vector7.new(0, 0, 1)
}
return axes[axis.Name]
end
function Vector7.FromString(str : string): Vector7
local x, y, z, w, v, u, t = string.match(str, "^"..string.rep("([%d%p]+)%s?,%s?", 6).."([%d%p]+)$")
assert((x and y and z and w and v and u and t), str.." is not compatible with FromString()")
return Vector7.new(
tonumber(x),
tonumber(y),
tonumber(z),
tonumber(w),
tonumber(v),
tonumber(u),
tonumber(t)
)
end
Vector7.zero = Vector7.new()
Vector7.one = Vector7.new(1, 1, 1, 1, 1, 1, 1)
Vector7.xAxis = Vector7.new(1)
Vector7.yAxis = Vector7.new(0, 1)
Vector7.zAxis = Vector7.new(0, 0, 1)
Vector7.wAxis = Vector7.new(0, 0, 0, 1)
Vector7.vAxis = Vector7.new(0, 0, 0, 0, 1)
Vector7.uAxis = Vector7.new(0, 0, 0, 0, 0, 1)
Vector7.tAxis = Vector7.new(0, 0, 0, 0, 0, 0, 1)
Vector7.min = Vector7.new(-math.huge, -math.huge, -math.huge, -math.huge, -math.huge, -math.huge, -math.huge)
Vector7.max = Vector7.new(math.huge, math.huge, math.huge, math.huge, math.huge, math.huge, math.huge)
Vector7.pi = Vector7.new(math.pi, math.pi, math.pi, math.pi, math.pi, math.pi, math.pi)
function Vector7:Magnitude(): number
return math.sqrt(self.X ^ 2 + self.Y ^ 2 + self.Z ^ 2 + self.W ^ 2 + self.V ^ 2 + self.U ^ 2 + self.T ^ 2)
end
function Vector7:Unit(): Vector7
local mag = math.sqrt(self.X ^ 2 + self.Y ^ 2 + self.Z ^ 2 + self.W ^ 2 + self.V ^ 2 + self.U ^ 2 + self.T ^ 2)
return Vector7.new(
(self.X / mag),
(self.Y / mag),
(self.Z / mag),
(self.W / mag),
(self.V / mag),
(self.U / mag),
(self.T / mag)
)
end
function Vector7:Cross(other : Vector7): Vector7
return Vector7.new(
((self.Y * other.Z) - (self.Z * other.Y)) + ((self.W * other.V) - (self.V * other.W)) + ((self.T * other.U) - (self.U * other.T)),
((self.Z * other.X) - (self.X * other.Z)) + ((self.T * other.U) - (self.U * other.T)) + ((self.V * other.W) - (self.W * other.V)),
((self.X * other.Y) - (self.Y * other.X)) + ((self.U * other.T) - (self.T * other.U)) + ((self.W * other.V) - (self.V * other.W)),
((self.U * other.V) - (self.V * other.U)) + ((self.X * other.T) - (self.T * other.X)) + ((self.Z * other.Y) - (self.Y * other.Z)),
((self.T * other.W) - (self.W * other.T)) + ((self.X * other.U) - (self.U * other.X)) + ((self.Y * other.Z) - (self.Z * other.Y)),
((self.W * other.T) - (self.T * other.W)) + ((self.Y * other.V) - (self.V * other.Y)) + ((self.X * other.Z) - (self.Z * other.X)),
((self.V * other.U) - (self.U * other.V)) + ((self.Z * other.W) - (self.W * other.Z)) + ((self.X * other.Y) - (self.Y * other.X))
)
-- There's 480 total combinations for the cross product of 7d, this one matches the cross product of Vector3
-- ((self.Z * other.X) - (self.X * other.Z)) in the yAxis is flipped due to Roblox using the right-hand rule
end
function Vector7:Dot(other : Vector7): number
return (self.X * other.X) + (self.Y * other.Y) + (self.Z * other.Z) + (self.W * other.W) + (self.V * other.V) + (self.U * other.U) + (self.T * other.T)
end
function Vector7:FuzzyEq(other : Vector7, epsilon : number?): boolean
epsilon = (epsilon or 1e-5)
local function fuzzyEq(a : number, b : number): boolean
return a == b or math.abs(a - b) <= (math.abs(a) + 1) * epsilon
end
for _, axis in ipairs({"X", "Y", "Z", "W", "V", "U", "T"}) do
if not fuzzyEq(self[axis], other[axis]) then
return false
end
end
return true
end
function Vector7:Lerp(goal : Vector7, alpha : number): Vector7
return (self + (goal - self) * alpha)
end
function Vector7:Max(... : Vector7): Vector7
local x, y, z, w, v, u, t = {}, {}, {}, {}, {}, {}, {}
local vectors = {self, ...}
for _, vec in ipairs(vectors) do
table.insert(x, vec.X)
table.insert(y, vec.Y)
table.insert(z, vec.Z)
table.insert(w, vec.W)
table.insert(v, vec.V)
table.insert(u, vec.U)
table.insert(t, vec.T)
end
return Vector7.new(
math.max(table.unpack(x)),
math.max(table.unpack(y)),
math.max(table.unpack(z)),
math.max(table.unpack(w)),
math.max(table.unpack(v)),
math.max(table.unpack(u)),
math.max(table.unpack(t))
)
end
function Vector7:Min(... : Vector7): Vector7
local x, y, z, w, v, u, t = {}, {}, {}, {}, {}, {}, {}
local vectors = {self, ...}
for _, vec in ipairs(vectors) do
table.insert(x, vec.X)
table.insert(y, vec.Y)
table.insert(z, vec.Z)
table.insert(w, vec.W)
table.insert(v, vec.V)
table.insert(u, vec.U)
table.insert(t, vec.T)
end
return Vector7.new(
math.min(table.unpack(x)),
math.min(table.unpack(y)),
math.min(table.unpack(z)),
math.min(table.unpack(w)),
math.min(table.unpack(v)),
math.min(table.unpack(u)),
math.min(table.unpack(t))
)
end
function Vector7:ToString(condense : boolean?): string
if condense then
return (self.X .. "," .. self.Y .. "," .. self.Z .. "," .. self.W .. "," .. self.V .. "," .. self.U .. "," .. self.T)
else
return tostring(self)
end
end
function Vector7:GetComponents()
return self.X, self.Y, self.Z, self.W, self.V, self.U, self.T
end
return Vector7
--[[
Made by M_dgettMann (shadowflame63)
Vector7 has all the functionality Vector3 has. (Excluding deprecated stuff)
There's also a few extras:
> Vector7.min -- All values are -inf
> Vector7.max -- All values are inf
> Vector7.pi -- All values are pi
> Vector7:ToString(condense) -- if condense is true, then returns tostring(Vector7) without the spaces, otherwise identical to tostring(Vector7)
> Vector7.FromString(str) -- Converts the product from tostring(Vector7) or ToString() back into a Vector7
> Vector7:GetComponents() -- Similar to CFrame:GetComponents(), returns all components of the Vector7
Credit for 7d cross products: https://en.wikipedia.org/wiki/Seven-dimensional_cross_product#Multiplication_table
Note: It's Vector7:Magnitude() and Vector7:Unit(), instead of Vector7.Magnitude and Vector7.Unit
]]
Vector7 MetaMethods Module Code
local metaMethods = {
__unm = function(vec7)
for i, v in pairs(vec7) do
vec7[i] = -v
end
return vec7
end,
__add = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] += v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v + v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v + v1
end
end
return merge
end,
__sub = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] -= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v - v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v - v1
end
end
return merge
end,
__mul = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] *= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v * v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v * v1
end
end
return merge
end,
__div = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] /= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v / v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v / v1
end
end
return merge
end,
__mod = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] %= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v % v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v % v1
end
end
return merge
end,
__pow = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] ^= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v ^ v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v ^ v1
end
end
return merge
end,
__tostring = function(vec7)
local tbl = {}
for i, num in pairs(vec7) do
local str = string.split(tostring(num), ".")
if str[2] then tbl[i] = #str[2] else tbl[i] = 0 end
end
local format = ("%."..tbl.X.."f, %."..tbl.Y.."f, %."..tbl.Z.."f, %."..tbl.W.."f, %."..tbl.V.."f, %."..tbl.U.."f, %."..tbl.T.."f")
return string.format(format, vec7.X, vec7.Y, vec7.Z, vec7.W, vec7.V, vec7.U, vec7.T)
end,
__eq = function(vec7, value)
for i, v in pairs(vec7) do
if not rawequal(value[i], v) then return false end
end
return true
end,
__lt = function(vec7, value)
for i, v in pairs(vec7) do
if value[i] <= v then return false end
end
return true
end,
__le = function(vec7, value)
for i, v in pairs(vec7) do
if value[i] < v then return false end
end
return true
end,
__type = "Vector7"
}
return {
setup = function(vec7)
local metaCopy = {}
for i, v in pairs(metaMethods) do
metaCopy[i] = v
end
return setmetatable(vec7, metaCopy)
end,
copy = function(vec7)
if vec7 then
for i, v in pairs(metaMethods) do
vec7[i] = v
end
return vec7
else
return metaMethods
end
end,
remove = function(vec7)
return setmetatable(vec7, nil)
end
}
)
Vector7int16
https://www.roblox.com/library/5431302799/Vector7int16
Vector7int16 Main Module Code
local meta = require(script:WaitForChild("Vec7int16MetaMethods"))
local function int16(num : number): number
if num > (2 ^ 15) - 1 then num = (2 ^ 15) - 1 end
if num < (-2 ^ 15) then num = (-2 ^ 15) end
return math.round(num)
end
type Vector7int16 = {
X : number,
Y : number,
Z : number,
W : number,
V : number,
U : number,
T : number
}
local Vector7int16 = {}
Vector7int16.__index = Vector7int16
Vector7int16 = meta.copy(Vector7int16)
function Vector7int16.new(x : number?, y : number?, z : number?, w : number?, v : number?, u : number?, t : number?): Vector7int16
assert((type(x) == "number") or x == nil, "Vector7int16's xAxis must be a number")
assert((type(y) == "number") or y == nil, "Vector7int16's yAxis must be a number")
assert((type(z) == "number") or z == nil, "Vector7int16's zAxis must be a number")
assert((type(w) == "number") or w == nil, "Vector7int16's wAxis must be a number")
assert((type(v) == "number") or v == nil, "Vector7int16's vAxis must be a number")
assert((type(u) == "number") or u == nil, "Vector7int16's uAxis must be a number")
assert((type(t) == "number") or t == nil, "Vector7int16's tAxis must be a number")
local newVector = {
["X"] = int16(x or 0),
["Y"] = int16(y or 0),
["Z"] = int16(z or 0),
["W"] = int16(w or 0),
["V"] = int16(v or 0),
["U"] = int16(u or 0),
["T"] = int16(t or 0)
}
return setmetatable(newVector, Vector7int16)
end
function Vector7int16.FromString(str : string): Vector7int16
local x, y, z, w, v, u, t = string.match(str, "^"..string.rep("([%d%p]+)%s?,%s?", 6).."([%d%p]+)$")
assert((x and y and z and w and v and u and t), str.." is not compatible with FromString()")
return Vector7int16.new(
tonumber(x),
tonumber(y),
tonumber(z),
tonumber(w),
tonumber(v),
tonumber(u),
tonumber(t)
)
end
function Vector7int16.UnpackVector(str: string): Vector7int16
local px = string.sub(str, 1, 2)
local py = string.sub(str, 3, 4)
local pz = string.sub(str, 5, 6)
local pw = string.sub(str, 7, 8)
local pv = string.sub(str, 9, 10)
local pu = string.sub(str, 11, 12)
local pt = string.sub(str, 13, 14)
return Vector7int16.new(
string.unpack("i2", px),
string.unpack("i2", py),
string.unpack("i2", pz),
string.unpack("i2", pw),
string.unpack("i2", pv),
string.unpack("i2", pu),
string.unpack("i2", pt)
)
end
Vector7int16.zero = Vector7int16.new()
Vector7int16.one = Vector7int16.new(1, 1, 1, 1, 1, 1, 1)
Vector7int16.xAxis = Vector7int16.new(1)
Vector7int16.yAxis = Vector7int16.new(0, 1)
Vector7int16.zAxis = Vector7int16.new(0, 0, 1)
Vector7int16.wAxis = Vector7int16.new(0, 0, 0, 1)
Vector7int16.vAxis = Vector7int16.new(0, 0, 0, 0, 1)
Vector7int16.uAxis = Vector7int16.new(0, 0, 0, 0, 0, 1)
Vector7int16.tAxis = Vector7int16.new(0, 0, 0, 0, 0, 0, 1)
Vector7int16.min = Vector7int16.new((-2 ^ 15), (-2 ^ 15), (-2 ^ 15), (-2 ^ 15), (-2 ^ 15), (-2 ^ 15), (-2 ^ 15))
Vector7int16.max = Vector7int16.new((2 ^ 15) - 1, (2 ^ 15) - 1, (2 ^ 15) - 1, (2 ^ 15) - 1, (2 ^ 15) - 1, (2 ^ 15) - 1, (2 ^ 15) - 1)
function Vector7int16:Max(... : Vector7int16): Vector7int16
local x, y, z, w, v, u, t = {}, {}, {}, {}, {}, {}, {}
local vectors = {self, ...}
for _, vec in ipairs(vectors) do
table.insert(x, vec.X)
table.insert(y, vec.Y)
table.insert(z, vec.Z)
table.insert(w, vec.W)
table.insert(v, vec.V)
table.insert(u, vec.U)
table.insert(t, vec.T)
end
return Vector7int16.new(
math.max(table.unpack(x)),
math.max(table.unpack(y)),
math.max(table.unpack(z)),
math.max(table.unpack(w)),
math.max(table.unpack(v)),
math.max(table.unpack(u)),
math.max(table.unpack(t))
)
end
function Vector7int16:Min(... : Vector7int16): Vector7int16
local x, y, z, w, v, u, t = {}, {}, {}, {}, {}, {}, {}
local vectors = {self, ...}
for _, vec in ipairs(vectors) do
table.insert(x, vec.X)
table.insert(y, vec.Y)
table.insert(z, vec.Z)
table.insert(w, vec.W)
table.insert(v, vec.V)
table.insert(u, vec.U)
table.insert(t, vec.T)
end
return Vector7int16.new(
math.min(table.unpack(x)),
math.min(table.unpack(y)),
math.min(table.unpack(z)),
math.min(table.unpack(w)),
math.min(table.unpack(v)),
math.min(table.unpack(u)),
math.min(table.unpack(t))
)
end
function Vector7int16:ToString(condense : boolean?): string
if condense then
return (self.X .. "," .. self.Y .. "," .. self.Z .. "," .. self.W .. "," .. self.V .. "," .. self.U .. "," .. self.T)
else
return tostring(self)
end
end
function Vector7int16:PackVector(): string
local px = string.pack("i2", self.X)
local py = string.pack("i2", self.Y)
local pz = string.pack("i2", self.Z)
local pw = string.pack("i2", self.W)
local pv = string.pack("i2", self.V)
local pu = string.pack("i2", self.U)
local pt = string.pack("i2", self.T)
return (px .. py .. pz .. pw .. pv .. pu .. pt)
end
function Vector7int16:GetComponents()
return self.X, self.Y, self.Z, self.W, self.V, self.U, self.T
end
return Vector7int16
--[[
Made by M_dgettMann (shadowflame63)
Vector7int16 has all the functionality Vector3int16 has. (Excluding deprecated stuff)
There are also a few extras:
> Vector7int16.min -- All values are -2 ^ 15
> Vector7int16.max -- All values are 2 ^ 15 - 1
> Vector7int16:ToString(condense) -- if condense is true, then returns tostring(Vector7int16) without the spaces, otherwise identical to tostring(Vector7int16)
> Vector7int16.FromString(str) -- Converts the product from tostring(Vector7int16) or ToString() back into a Vector7int16
> Vector7int16:PackVector() -- Uses string.pack to pack a Vector7int16 into a string with a length of 14
> Vector7int16.UnpackVector(str) -- Converts the product from PackVector() back into a Vector7int16
> Vector7int16:GetComponents() -- Similar to CFrame:GetComponents(), returns all components of the Vector7int16
What's the purpose of an int16 version? Well it's niche but can be used when tranferring data at lower costs (e.g. RemoteEvents to reduce bandwidth usage)
However, it's mostly a micro-optimisation that many won't use, but I made it because Vector3int16 exists, and string.pack is cool
Note: If you want to convert a Vector7 into a Vector7int16 and visa versa, you'll have to do it the same way as Vector3
]]
Vector7int16 MetaMethods Module Code
local metaMethods = {
__unm = function(vec7)
for i, v in pairs(vec7) do
vec7[i] = -v
end
return vec7
end,
__add = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] += v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v + v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v + v1
end
end
return merge
end,
__sub = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] -= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v - v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v - v1
end
end
return merge
end,
__mul = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] *= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v * v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v * v1
end
end
return merge
end,
__div = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] /= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v / v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v / v1
end
end
return merge
end,
__mod = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] %= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v % v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v % v1
end
end
return merge
end,
__pow = function(v1, v2)
local merge = {}
local m1 = getmetatable(v1)
local m2 = getmetatable(v2)
if m1 and m2 then
assert(m1.__type == m1.__type, "Vectors must be the same type")
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v
end
for i, v in pairs(v2) do
if merge[i] then
merge[i] ^= v
else
merge[i] = v
end
end
elseif m1 and (type(v2) == "number") then
setmetatable(merge, m1)
for i, v in pairs(v1) do
merge[i] = v ^ v2
end
elseif m2 and (type(v1) == "number") then
setmetatable(merge, m2)
for i, v in pairs(v2) do
merge[i] = v ^ v1
end
end
return merge
end,
__tostring = function(vec7)
local tbl = {}
for i, num in pairs(vec7) do
local str = string.split(tostring(num), ".")
if str[2] then tbl[i] = #str[2] else tbl[i] = 0 end
end
local format = ("%."..tbl.X.."f, %."..tbl.Y.."f, %."..tbl.Z.."f, %."..tbl.W.."f, %."..tbl.V.."f, %."..tbl.U.."f, %."..tbl.T.."f")
return string.format(format, vec7.X, vec7.Y, vec7.Z, vec7.W, vec7.V, vec7.U, vec7.T)
end,
__eq = function(vec7, value)
for i, v in pairs(vec7) do
if not rawequal(value[i], v) then return false end
end
return true
end,
__lt = function(vec7, value)
for i, v in pairs(vec7) do
if value[i] <= v then return false end
end
return true
end,
__le = function(vec7, value)
for i, v in pairs(vec7) do
if value[i] < v then return false end
end
return true
end,
__type = "Vector7int16"
}
return {
setup = function(vec7)
local metaCopy = {}
for i, v in pairs(metaMethods) do
metaCopy[i] = v
end
return setmetatable(vec7, metaCopy)
end,
copy = function(vec7)
if vec7 then
for i, v in pairs(metaMethods) do
vec7[i] = v
end
return vec7
else
return metaMethods
end
end,
remove = function(vec7)
return setmetatable(vec7, nil)
end
}
Why did I decide to make such a creation? Well, the fact that cross products only work in 3d and 7d intrigued me so I did some research and wrote it up.
If you can find a use case for such a niche thing, then I applaud you. Thanks for checking out this weird and long post, and I hope you like what I’ve made, even if it’s a bit wild.