-- Small package of 3D vector functions local mt = {} local function new(v) local vec = {v[1], v[2], v[3]} setmetatable(vec, mt) return vec end local function addvec(v, w) return new{v[1]+w[1], v[2]+w[2], v[3]+w[3]} end local function subvec(v, w) return new{v[1]-w[1], v[2]-w[2], v[3]-w[3]} end local function addnum(v, n) return new{v[1] + n, v[2] + n, v[3] + n} end local function subnum(v, n) return new{v[1] - n, v[2] - n, v[3] - n} end local function addany(v, x) if type(x) == "table" then return addvec(v, x) else return addnum(v, x) end end local function subany(v, x) if type(x) == "table" then return subvec(v, x) else return subnum(v, x) end end local function scale(v, n) return new{v[1]*n, v[2]*n, v[3]*n} end local function dot(v, w) return v[1]*w[1] +v[2]*w[2] + v[3]*w[3] end local function mulany(v, x) if type(x) == "table" then return dot(v, x) else return scale(v, x) end end local function cross(v, w) return new {v[2]*w[3] - w[2]*v[3], w[1]*v[3] - v[1]*w[3], v[1]*w[2] - w[1]*v[2]} end local function scaleinv(v,n) return new{v[1]/n, v[2]/n, v[3]/n} end local function neg(v) return v*(-1) end local function norm2(v) return dot(v,v) end local function norm(v) return math.sqrt(norm2(v)) end local function normalize(v) return v/norm(v) end local function vectostring(v) return "{" .. v[1] .. ", " .. v[2] .. ", " .. v[3] .. "}" end mt.__add = addany mt.__sub = subany mt.__mul = mulany mt.__div = scaleinv mt.__unm = neg mt.__tostring = vectostring Vector = { new = new, norm = norm, norm2 = norm2, cross = cross, normalize = normalize, x = new{1,0,0}, y = new{0,1,0}, z = new{0,0,1}, origin = new{0,0,0} } return Vector