aboutsummaryrefslogtreecommitdiff
path: root/builtin/vector.lua
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/vector.lua')
-rw-r--r--builtin/vector.lua126
1 files changed, 126 insertions, 0 deletions
diff --git a/builtin/vector.lua b/builtin/vector.lua
new file mode 100644
index 0000000..2fd926a
--- /dev/null
+++ b/builtin/vector.lua
@@ -0,0 +1,126 @@
+--[[ builtin/vector.lua ]]--
+
+local function wrap(op, body_wrapper, ...)
+ return load("return function(a, b) " .. body_wrapper(op, ...) .. "end")()
+end
+
+local function arith_mt(...)
+ return {
+ __add = wrap("+", ...),
+ __sub = wrap("-", ...),
+ __mul = wrap("*", ...),
+ __div = wrap("/", ...),
+ __mod = wrap("%", ...),
+ }
+end
+
+-- vec2
+
+local mt_vec2 = arith_mt(function(op)
+ return [[
+ if type(b) == "number" then
+ return vec2(a.x ]] .. op.. [[ b, a.y ]] .. op .. [[ b)
+ else
+ return vec2(a.x ]] .. op.. [[ b.x, a.y ]] .. op.. [[ b.y)
+ end
+ ]]
+end)
+
+function mt_vec2:__neg()
+ return vec2(-self.x, -self.y)
+end
+
+function mt_vec2:__tostring()
+ return "(" .. self.x .. ", " .. self.y .. ")"
+end
+
+function vec2(a, b)
+ local o = {}
+
+ if type(a) == "number" then
+ o.x = a
+ o.y = b or a
+ else
+ o.x = a.x
+ o.y = a.y
+ end
+
+ setmetatable(o, mt_vec2)
+ return o
+end
+
+-- vec3
+
+local mt_vec3 = arith_mt(function(op)
+ return [[
+ if type(b) == "number" then
+ return vec3(a.x ]] .. op.. [[ b, a.y ]] .. op .. [[ b, a.z ]] .. op .. [[ b)
+ else
+ return vec3(a.x ]] .. op.. [[ b.x, a.y ]] .. op.. [[ b.y, a.z ]] .. op.. [[ b.z)
+ end
+ ]]
+end)
+
+function mt_vec3:__neg()
+ return vec3(-self.x, -self.y, -self.z)
+end
+
+function mt_vec3:__tostring()
+ return "(" .. self.x .. ", " .. self.y .. ", " .. self.z .. ")"
+end
+
+function vec3(a, b, c)
+ local o = {}
+
+ if type(a) == "number" then
+ o.x = a
+ o.y = b or a
+ o.z = c or a
+ else
+ o.x = a.x
+ o.y = a.y
+ o.z = a.z
+ end
+
+ setmetatable(o, mt_vec3)
+ return o
+end
+
+-- box
+
+local mt_box = arith_mt(function(op)
+ return "return box(a.min " .. op .. " b, a.max " .. op .. " b)"
+end)
+
+function mt_box:__neg()
+ return box(-self.min, -self.max)
+end
+
+function mt_box:__tostring()
+ return "[" .. self.min .. "; " .. self.max .. "]"
+end
+
+mt_box.__index = {
+ contains = function(a, b)
+ if type(b) == "number" or b.x then
+ return a.min <= b and a.max >= b
+ else
+ return a.min <= b.min and a.max >= b.max
+ end
+ end,
+}
+
+function box(a, b)
+ local o = {}
+
+ if type(a) == "number" or a.x then
+ o.min = a
+ o.max = b
+ else
+ o.min = a.min
+ o.max = a.max
+ end
+
+ setmetatable(o, mt_box)
+ return o
+end