1 --[[ builtin/vector.lua ]]--
3 local function wrap(op, body_wrapper, ...)
4 return loadstring("return function(a, b) " .. body_wrapper(op, ...) .. "end")()
7 local function arith_mt(...)
9 __add = wrap("+", ...),
10 __sub = wrap("-", ...),
11 __mul = wrap("*", ...),
12 __div = wrap("/", ...),
13 __mod = wrap("%", ...),
20 local mt_vec2 = arith_mt(function(op)
22 if type(b) == "number" then
23 return vec2(a.x ]] .. op.. [[ b, a.y ]] .. op .. [[ b)
25 return vec2(a.x ]] .. op.. [[ b.x, a.y ]] .. op.. [[ b.y)
30 function mt_vec2:__neg()
31 return vec2(-self.x, -self.y)
34 function mt_vec2:__len()
35 return math.sqrt(self:dot(self))
38 function mt_vec2:__eq(other)
39 return type(other) == "table" and self.x == other.x and self.y == other.y
42 function mt_vec2:__tostring()
43 return "(" .. self.x .. ", " .. self.y .. ")"
46 function mt_vec2.__index:validate()
47 assert(type(self.x) == "number")
48 assert(type(self.y) == "number")
52 function mt_vec2.__index:round()
53 return vec2(math.round(self.x), math.round(self.y))
56 function mt_vec2.__index:manhattan()
57 return math.abs(self.x) + math.abs(self.y)
60 function mt_vec2.__index:volume()
61 return self.x * self.y
64 function mt_vec2.__index:dot(other)
65 return self.x * other.x + self.y * other.y
68 function mt_vec2.__index:norm()
75 if type(a) == "number" then
83 setmetatable(o, mt_vec2)
89 local mt_vec3 = arith_mt(function(op)
91 if type(b) == "number" then
92 return vec3(a.x ]] .. op.. [[ b, a.y ]] .. op .. [[ b, a.z ]] .. op .. [[ b)
94 return vec3(a.x ]] .. op.. [[ b.x, a.y ]] .. op.. [[ b.y, a.z ]] .. op.. [[ b.z)
99 function mt_vec3:__neg()
100 return vec3(-self.x, -self.y, -self.z)
103 function mt_vec3:__len()
104 return math.sqrt(self:dot(self))
107 function mt_vec3:__eq(other)
108 return type(other) == "table" and self.x == other.x and self.y == other.y and self.z == other.z
111 function mt_vec3:__tostring()
112 return "(" .. self.x .. ", " .. self.y .. ", " .. self.z .. ")"
115 function mt_vec3.__index:validate()
116 assert(type(self.x) == "number")
117 assert(type(self.y) == "number")
118 assert(type(self.z) == "number")
122 function mt_vec3.__index:round()
123 return vec3(math.floor(self.x), math.floor(self.y), math.floor(self.z))
126 function mt_vec3.__index:manhattan()
127 return math.abs(self.x) + math.abs(self.y) + math.abs(self.z)
130 function mt_vec3.__index:volume()
131 return self.x * self.y * self.z
134 function mt_vec3.__index:dot(other)
135 return self.x * other.x + self.y * other.y + self.z * other.z
138 function mt_vec3.__index:cross(other)
140 self.y * other.z - self.z * other.y,
141 self.z * other.x - self.x * other.z,
142 self.x * other.y - self.y * other.x
146 function mt_vec3.__index:norm()
150 function vec3(a, b, c)
153 if type(a) == "number" then
163 setmetatable(o, mt_vec3)
169 local mt_box = arith_mt(function(op)
170 return "return box(a.min " .. op .. " b, a.max " .. op .. " b)"
173 function mt_box:__neg()
174 return box(-self.min, -self.max)
177 function mt_box:__eq(other)
178 return self.min == other.min and self.max == other.max
181 function mt_box:__tostring()
182 return "[" .. self.min .. "; " .. self.max .. "]"
185 function mt_box.__index:validate()
186 if type(self.min) == "number" then
187 assert(type(self.max) == "number")
189 assert(not self.min.z == not self.max.z)
195 function mt_box.__index:volume()
196 local diff = self.max - self.min
197 if type(diff) == "number" then
204 function mt_box.__index:contains(other)
205 if type(other) == "number" or other.x then
206 return self.min <= other and self.max >= other
208 return self.min <= other.min and self.max >= other.max
215 if type(a) == "number" or a.x then
223 setmetatable(o, mt_box)