-- Geometry module for Lunatic. local ffi = require("ffi") local math = require("math") local type = type local error = error module(...) -- This has no metamethods, but can be useful for calculations expecting -- integer values, e.g. geom.ivec3(x, y, z) is a reasonable way to round -- a vec3. It can be also used as the RHS to the vec2/vec3 arithmetic -- methods. -- NOTE: We must have a typedef with that exact name, because for -- Lunatic (i.e. not stand-alone), it is a duplicate (and ignored) -- declaration for an already metatype'd type. ffi.cdef "typedef struct { int32_t x, y, z; } vec3_t;" ivec3 = ffi.typeof("vec3_t") local dvec2_t = ffi.typeof("struct { double x, y; }") local dvec3_t = ffi.typeof("struct { double x, y, z; }") local vec2_mt = { __add = function(a, b) return dvec2_t(a.x+b.x, a.y+b.y) end, __sub = function(a, b) return dvec2_t(a.x-b.x, a.y-b.y) end, __unm = function(a) return dvec2_t(-a.x, -a.y) end, __mul = function(a,b) if (type(a)=="number") then return dvec2_t(a*b.x, a*b.y) end if (type(b)~="number") then error("number expected in vec2 multiplication", 2) end return dvec2_t(a.x*b, a.y*b) end, __div = function(a,b) if (type(b)~="number") then error("number expected in vec2 division", 2) end return dvec2_t(a.x/b, a.y/b) end, __len = function(a) return math.sqrt(a.x*a.x + a.y*a.y) end, __tostring = function(a) return "vec2("..a.x..", "..a.y..")" end, __index = { lensq = function(a) return a.x*a.x + a.y*a.y end, -- Manhattan distance: len1 = function(a) return math.abs(a.x)+math.abs(a.y) end, }, } local vec3_mt = { __add = function(a, b) return dvec3_t(a.x+b.x, a.y+b.y, a.z+b.z) end, __sub = function(a, b) return dvec3_t(a.x-b.x, a.y-b.y, a.z-b.z) end, __unm = function(a) return dvec3_t(-a.x, -a.y, -a.z) end, __mul = function(a,b) if (type(a)=="number") then return dvec3_t(a*b.x, a*b.y, a*b.z) end if (type(b)~="number") then error("number expected in vec3 multiplication", 2) end return dvec3_t(a.x*b, a.y*b, a.z*b) end, __div = function(a,b) if (type(b)~="number") then error("number expected in vec3 division", 2) end return dvec3_t(a.x/b, a.y/b, a.z/b) end, __len = function(a) return math.sqrt(a.x*a.x + a.y*a.y + a.z*a.z) end, __tostring = function(a) return "vec3("..a.x..", "..a.y..", "..a.z..")" end, __index = { lensq = function(a) return a.x*a.x + a.y*a.y + a.z*a.z end, -- Manhattan distance: len1 = function(a) return math.abs(a.x)+math.abs(a.y)+math.abs(a.z) end, toivec3 = function(v) return ivec3(v.x, v.y, v.z) end, }, } -- VEC2 user data constructor. -- * vec2(