1
0
Fork 0
mirror of https://github.com/Reuh/wirefame.git synced 2025-10-27 09:39:30 +00:00
wirefame/math/v3.lua
2021-02-18 17:22:21 +01:00

114 lines
No EOL
2.9 KiB
Lua

--- 3D vector
local v3
local sqrt = math.sqrt
-- v3 methods
-- Unless specified otherwise, all operations are done in place and do not create a new vector.
local v3_mt = {
-- Clone the vector. Returns a new vector.
clone = function(self)
return v3(self[1], self[2], self[3])
end,
-- Set vector
set = function(self, other)
self[1], self[2], self[3] = other[1], other[2], other[3]
return self
end,
-- Retrieve coordinates
unpack = function(self)
return self[1], self[2], self[3]
end,
-- Normalize
normalize = function(self)
local x, y, z = self[1], self[2], self[3]
local l = sqrt(x*x + y*y + z*z)
self[1], self[2], self[3] = x/l, y/l, z/l
return self
end,
-- Vector product. Returns a new vector.
cross = function(self, other)
local x1, y1, z1 = self[1], self[2], self[3]
local x2, y2, z2 = other[1], other[2], other[3]
return v3(
y1*z2 - z1*y2,
z1*x2 - x1*z2,
x1*y2 - y1*x2
)
end,
dot = function(self, other)
return self[1] * other[1] + self[2] * other[2] + self[3] * other[3]
end,
-- Transform by a mat4
transform = function(self, matrix)
local x, y, z = self[1], self[2], self[3]
-- Transform matrix * Homogeneous coordinates
local mx = matrix[1] * x + matrix[2] * y + matrix[3] * z + matrix[4]
local my = matrix[5] * x + matrix[6] * y + matrix[7] * z + matrix[8]
local mz = matrix[9] * x + matrix[10] * y + matrix[11] * z + matrix[12]
local mw = matrix[13] * x + matrix[14] * y + matrix[15] * z + matrix[16]
-- Go back to euclidian coordinates
self[1], self[2], self[3] = mx/mw, my/mw, mz/mw
return self
end,
-- Length
len2 = function(self)
local x, y, z = self[1], self[2], self[3]
return x*x + y*y + z*z
end,
len = function(self)
local x, y, z = self[1], self[2], self[3]
return sqrt(x*x + y*y + z*z)
end,
-- Distance
distance = function(self, other)
return (self - other):len()
end,
distance2 = function(self, other)
return (self - other):len2()
end,
-- Common operations. Returns a new vector.
__sub = function(self, other)
return v3(self[1] - other[1], self[2] - other[2], self[3] - other[3])
end,
__add = function(self, other)
return v3(self[1] + other[1], self[2] + other[2], self[3] + other[3])
end,
__unm = function(self)
return v3(-self[1], -self[2], -self[3])
end,
__div = function(self, other)
return v3(self[1] / other, self[2] / other, self[3] / other)
end,
__mul = function(self, other)
return v3(self[1] * other, self[2] * other, self[3] * other)
end,
__eq = function(self, other)
return self[1] == other[1] and self[2] == other[2] and self[3] == other[3]
end,
__tostring = function(self)
return ("v3(%s,%s,%s)"):format(self[1], self[2], self[3])
end
}
v3_mt.__index = v3_mt
-- If x is a table, will reuse it without copying.
v3 = function(x, y, z)
if type(x) == "number" then
return setmetatable({ x, y, z }, v3_mt)
else
return setmetatable(x, v3_mt)
end
end
return v3