local Vector3 = { x = 0, y = 0, z = 0, _CLASS_ = "Vector3" } setmetatable(Vector3, Vector3) local function is_weak_vector3(t) if type(t) ~= "table" then return false end local haskeys = t.x ~= nil and t.y ~= nil and t.z ~= nil if not haskeys then return type(t[1]) == "number" and type(t[2]) == "number" and type(t[3]) == "number" else return type(t.x) == "number" and type(t.y) == "number" and type(t.z) == "number" end end function Vector3:__mul(b) if type(b) == "number" then return Vector3{ x = self.x * b, y = self.y * b, z = self.z * b, } elseif type(b) == "table" and is_weak_vector3(b) then local other = Vector3(b) return Vector3{ self.x * other.x, self.y * other.y, self.z * other.z, } end error("Vector3: other must be either a number or a Vector3-like table.") return Vector3() end function Vector3:__div(b) if type(b) == "number" then return Vector3{ x = self.x / b, y = self.y / b, z = self.z / b, } elseif type(b) == "table" and is_weak_vector3(b) then local other = Vector3(b) return Vector3{ self.x / other.x, self.y / other.y, self.z / other.z, } end error("Vector3: other must be either a number or a Vector3-like table.") return Vector3() end function Vector3:__add(b) if not is_weak_vector3(b) then error("Vector3: other must be a Vector3-like table.") return self end local other = Vector3(b) return Vector3{ self.x + other.x, self.y + other.y, self.z + other.z, } end function Vector3:__sub(b) if not is_weak_vector3(b) then error("Vector3: other must be a Vector3-like table.") return self end local other = Vector3(b) return Vector3{ self.x - other.x, self.y - other.y, self.z - other.z, } end function Vector3:__unm() return Vector3{ -self.x, -self.y, -self.z, } end function Vector3:__call(...) local args = {...} local nv = {x = 0, y = 0, z = 0} setmetatable(nv, Vector3) if type(args[1]) == "number" then if #args == 1 then nv.x, nv.y, nv.z = args[1], args[1], args[1] else nv.x, nv.y, nv.z = args[1], args[2], args[3] end elseif type(args[1]) == "table" then if args[1].x ~= nil then nv.x, nv.y, nv.z = args[1].x, args[1].y, args[1].z else nv.x, nv.y, nv.z = args[1][1], args[1][2], args[1][3] end end return nv end function Vector3:__tostring() return "Vector3(" .. tostring(self.x) .. ", " .. tostring(self.y) .. ", " .. tostring(self.z) .. ")" end Vector3.__index = Vector3 --------API-------- function Vector3:length_squared() local x2 = self.x * self.x local y2 = self.y * self.y local z2 = self.z * self.z return x2 + y2 + z2 end function Vector3:length() return math.sqrt(self:length_squared()) end function Vector3:normalized() local length = math.sqrt(self:length_squared()) return Vector3(self.x / length, self.y / length, self.z / length) end ------------------- return Vector3