From 46f8261ea04cf73923a9683e7bc76e5a41041cf9 Mon Sep 17 00:00:00 2001 From: karai17 Date: Mon, 18 Jul 2016 06:17:42 -0300 Subject: [PATCH] Refactored mat4 (in progress) Cleaned up vec2, vec3, quat --- modules/mat4.lua | 641 ++++++++++++++++++++++++++--------------------- modules/quat.lua | 5 +- modules/vec2.lua | 34 +-- modules/vec3.lua | 28 +-- 4 files changed, 388 insertions(+), 320 deletions(-) diff --git a/modules/mat4.lua b/modules/mat4.lua index eaee714..4b51ea6 100644 --- a/modules/mat4.lua +++ b/modules/mat4.lua @@ -1,12 +1,16 @@ --- double 4x4, 1-based, column major matrices -- @module mat4 -local current_folder = (...):gsub('%.[^%.]+$', '') .. "." -local constants = require(current_folder .. "constants") -local vec2 = require(current_folder .. "vec2") -local vec3 = require(current_folder .. "vec3") -local quat = require(current_folder .. "quat") - -local mat4 = {} +local modules = (...):gsub('%.[^%.]+$', '') .. "." +local constants = require(modules .. "constants") +local vec2 = require(modules .. "vec2") +local vec3 = require(modules .. "vec3") +local quat = require(modules .. "quat") +local sqrt = math.sqrt +local cos = math.cos +local sin = math.sin +local tan = math.tan +local rad = math.rad +local mat4 = {} -- Private constructor. local function new(m) @@ -17,7 +21,7 @@ local function new(m) 0, 0, 0, 0 } m._m = m - return setmetatable(m, vec3_mt) + return setmetatable(m, mat4_mt) end -- Do the check to see if JIT is enabled. If so use the optimized FFI structs. @@ -30,30 +34,33 @@ if type(jit) == "table" and jit.status() then end end -function mat4.new(v) +-- Statically allocate a temporary variable used in some of our functions. +local tmp = new() + +function mat4.new(a) local o = new() local m = o._m - if type(v) == "table" and #v == 16 then + if type(a) == "table" and #a == 16 then for i=1,16 do - m[i] = tonumber(v[i]) + m[i] = tonumber(a[i]) end - elseif type(v) == "table" and #v == 9 then - m[1], m[2], m[3] = v[1], v[2], v[3] - m[5], m[6], m[7] = v[4], v[5], v[6] - m[9], m[10], m[11] = v[7], v[8], v[9] + elseif type(a) == "table" and #a == 9 then + m[1], m[2], m[3] = a[1], a[2], a[3] + m[5], m[6], m[7] = a[4], a[5], a[6] + m[9], m[10], m[11] = a[7], a[8], a[9] m[16] = 1 - elseif type(v) == "table" and type(v[1]) == "table" then + elseif type(a) == "table" and type(a[1]) == "table" then local idx = 1 - for i=1, 4 do - for j=1, 4 do - m[idx] = v[i][j] + for i = 1, 4 do + for j = 1, 4 do + m[idx] = a[i][j] idx = idx + 1 end end else - m[1] = 1 - m[6] = 1 + m[1] = 1 + m[6] = 1 m[11] = 1 m[16] = 1 end @@ -61,87 +68,83 @@ function mat4.new(v) return o end -local temp = mat4.new() - -function mat4:clone() - return new(self._m) +function mat4.identity() + return new { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + } end function mat4.from_axis_angle(angle, axis) if type(angle) == "table" then - angle, axis = angle:to_axis_angle() + angle, axis = vec3.to_angle_axis(angle) end - local l = axis:len() + + local l = vec3.len(axis) if l == 0 then - return self + return new() end + local x, y, z = axis.x / l, axis.y / l, axis.z / l - local c = math.cos(angle) - local s = math.sin(angle) - local m = { - x*x*(1-c)+c, y*x*(1-c)+z*s, x*z*(1-c)-y*s, 0, - x*y*(1-c)-z*s, y*y*(1-c)+c, y*z*(1-c)+x*s, 0, - x*z*(1-c)+y*s, y*z*(1-c)-x*s, z*z*(1-c)+c, 0, - 0, 0, 0, 1, + local c = cos(angle) + local s = sin(angle) + + return new { + x*x*(1-c)+c, y*x*(1-c)+z*s, x*z*(1-c)-y*s, 0, + x*y*(1-c)-z*s, y*y*(1-c)+c, y*z*(1-c)+x*s, 0, + x*z*(1-c)+y*s, y*z*(1-c)-x*s, z*z*(1-c)+c, 0, + 0, 0, 0, 1 } - return new(m) end function mat4.from_direction(direction, up) - local forward = direction:normalize() - local side = forward:cross(up):normalize() - local new_up = side:cross(forward):normalize() + local forward = vec3.normalize(vec3(), direction) + local side = vec3.normalize(vec3(), vec3.cross(vec3(), forward, up) + local new_up = vec3.normalize(vec3(), vec3.cross(vec3(), side, forward)) - local view = mat4.new() - local m = view._m - m[1] = side.x - m[5] = side.y - m[9] = side.z + local out = new() + out[1] = side.x + out[5] = side.y + out[9] = side.z + out[2] = new_up.x + out[6] = new_up.y + out[10] = new_up.z + out[3] = forward.x + out[7] = forward.y + out[11] = forward.z + out[16] = 1 - m[2] = new_up.x - m[6] = new_up.y - m[10] = new_up.z - - m[3] = forward.x - m[7] = forward.y - m[11] = forward.z - - m[16] = 1 - - return view + return out end function mat4.from_perspective(fovy, aspect, near, far) assert(aspect ~= 0) - assert(near ~= far) + assert(near ~= far) - local t = math.tan(math.rad(fovy) / 2) - local result = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 - } + local t = tan(rad(fovy) / 2) + local out = new() + out[1] = 1 / (t * aspect) + out[6] = 1 / t + out[11] = -(far + near) / (far - near) + out[12] = -1 + out[15] = -(2 * far * near) / (far - near) + out[16] = 1 - result[1] = 1 / (t * aspect) - result[6] = 1 / t - result[11] = -(far + near) / (far - near) - result[12] = -1 - result[15] = -(2 * far * near) / (far - near) - result[16] = 1 - - return mat4.new(result) + return out end function mat4.from_ortho(left, right, top, bottom, near, far) - local out = mat4.new() - out[1] = 2 / (right - left) - out[6] = 2 / (top - bottom) - out[11] = -2 / (far - near) - out[13] = -((right + left) / (right - left)) - out[14] = -((top + bottom) / (top - bottom)) - out[15] = -((far + near) / (far - near)) - out[16] = 1 + local out = new() + out[1] = 2 / (right - left) + out[6] = 2 / (top - bottom) + out[11] = -2 / (far - near) + out[13] = -((right + left) / (right - left)) + out[14] = -((top + bottom) / (top - bottom)) + out[15] = -((far + near) / (far - near)) + out[16] = 1 + return out end @@ -150,6 +153,7 @@ function mat4.from_hmd_perspective(tanHalfFov, zNear, zFar, flipZ, farAtInfinity -- CPML is right-handed and intended for GL, so these don't need to be arguments. local rightHanded = true local isOpenGL = true + local function CreateNDCScaleAndOffsetFromFov(tanHalfFov) x_scale = 2 / (tanHalfFov.LeftTan + tanHalfFov.RightTan) x_offset = (tanHalfFov.LeftTan - tanHalfFov.RightTan) * x_scale * 0.5 @@ -173,9 +177,9 @@ function mat4.from_hmd_perspective(tanHalfFov, zNear, zFar, flipZ, farAtInfinity end -- A projection matrix is very like a scaling from NDC, so we can start with that. - local scaleAndOffset = CreateNDCScaleAndOffsetFromFov(tanHalfFov) + local scaleAndOffset = CreateNDCScaleAndOffsetFromFov(tanHalfFov) local handednessScale = rightHanded and -1.0 or 1.0 - local projection = mat4.new() + local projection = new() -- Produces X result, mapping clip edges to [-w,+w] projection[1] = scaleAndOffset.Scale.x @@ -224,78 +228,146 @@ function mat4.from_hmd_perspective(tanHalfFov, zNear, zFar, flipZ, farAtInfinity projection[15] = handednessScale projection[16] = 0 - return projection:transpose() + return mat4.transpose(projection) end - -function mat4.compose_world_matrix(t, rot, scale) - local angle, axis = rot:to_axis_angle() - local l = axis:len() - - if l == 0 then - return self - end - - local x, y, z = axis.x / l, axis.y / l, axis.z / l - local c = math.cos(angle) - local s = math.sin(angle) - local m = { - x*x*(1-c)+c, y*x*(1-c)+z*s, x*z*(1-c)-y*s, 0, - x*y*(1-c)-z*s, y*y*(1-c)+c, y*z*(1-c)+x*s, 0, - x*z*(1-c)+y*s, y*z*(1-c)-x*s, z*z*(1-c)+c, 0, - t.x, t.y, t.z, 1, - } - - return new(m) -end - -function mat4:to_quat() - local m = self:transpose():to_vec4s() - - print(m[1][1], m[2][2], m[3][3]) - local w = math.sqrt(1 + m[1][1] + m[2][2] + m[3][3]) / 2 - local scale = w * 4 - - return quat.new( - m[3][2] - m[2][3] / scale, - m[1][3] - m[3][1] / scale, - m[2][1] - m[1][2] / scale, - w - ):normalize() +function mat4.clone(a) + return new(a) end function mat4.mul(out, a, b) - out[1] = a[1]*b[1]+a[2]*b[5]+a[3]*b[9]+a[4]*b[13] - out[2] = a[1]*b[2]+a[2]*b[6]+a[3]*b[10]+a[4]*b[14] - out[3] = a[1]*b[3]+a[2]*b[7]+a[3]*b[11]+a[4]*b[15] - out[4] = a[1]*b[4]+a[2]*b[8]+a[3]*b[12]+a[4]*b[16] + out[1] = a[1] * b[1] + a[2] * b[5] + a [3] * b[9] + a[4] * b[13] + out[2] = a[1] * b[2] + a[2] * b[6] + a [3] * b[10] + a[4] * b[14] + out[3] = a[1] * b[3] + a[2] * b[7] + a [3] * b[11] + a[4] * b[15] + out[4] = a[1] * b[4] + a[2] * b[8] + a [3] * b[12] + a[4] * b[16] + out[5] = a[5] * b[1] + a[6] * b[5] + a [7] * b[9] + a[8] * b[13] + out[6] = a[5] * b[2] + a[6] * b[6] + a [7] * b[10] + a[8] * b[14] + out[7] = a[5] * b[3] + a[6] * b[7] + a [7] * b[11] + a[8] * b[15] + out[8] = a[5] * b[4] + a[6] * b[8] + a [7] * b[12] + a[8] * b[16] + out[9] = a[9] * b[1] + a[10] * b[5] + a[11] * b[9] + a[12] * b[13] + out[10] = a[9] * b[2] + a[10] * b[6] + a[11] * b[10] + a[12] * b[14] + out[11] = a[9] * b[3] + a[10] * b[7] + a[11] * b[11] + a[12] * b[15] + out[12] = a[9] * b[4] + a[10] * b[8] + a[11] * b[12] + a[12] * b[16] + out[13] = a[13] * b[1] + a[14] * b[5] + a[15] * b[9] + a[16] * b[13] + out[14] = a[13] * b[2] + a[14] * b[6] + a[15] * b[10] + a[16] * b[14] + out[15] = a[13] * b[3] + a[14] * b[7] + a[15] * b[11] + a[16] * b[15] + out[16] = a[13] * b[4] + a[14] * b[8] + a[15] * b[12] + a[16] * b[16] - out[5] = a[5]*b[1]+a[6]*b[5]+a[7]*b[9]+a[8]*b[13] - out[6] = a[5]*b[2]+a[6]*b[6]+a[7]*b[10]+a[8]*b[14] - out[7] = a[5]*b[3]+a[6]*b[7]+a[7]*b[11]+a[8]*b[15] - out[8] = a[5]*b[4]+a[6]*b[8]+a[7]*b[12]+a[8]*b[16] - - out[9] = a[9]*b[1]+a[10]*b[5]+a[11]*b[9]+a[12]*b[13] - out[10] = a[9]*b[2]+a[10]*b[6]+a[11]*b[10]+a[12]*b[14] - out[11] = a[9]*b[3]+a[10]*b[7]+a[11]*b[11]+a[12]*b[15] - out[12] = a[9]*b[4]+a[10]*b[8]+a[11]*b[12]+a[12]*b[16] - - out[13] = a[13]*b[1]+a[14]*b[5]+a[15]*b[9]+a[16]*b[13] - out[14] = a[13]*b[2]+a[14]*b[6]+a[15]*b[10]+a[16]*b[14] - out[15] = a[13]*b[3]+a[14]*b[7]+a[15]*b[11]+a[16]*b[15] - out[16] = a[13]*b[4]+a[14]*b[8]+a[15]*b[12]+a[16]*b[16] return out end -function mat4.translate(out, a, t) - local m = new { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, +function mat4.invert(out, a) + out[1] = a[6] * a[11] * a[16] - a[6] * + a[12] * a[15] - a[10] * a[7] * a[16] + + a[10] * a[8] * a[15] + a[14] * a[7] * + a[12] - a[14] * a[8] * a[11] + + out[5] = -a[5] * a[11] * a[16] + a[5] * + a[12] * a[15] + a[9] * a[7] * a[16] - + a[9] * a[8] * a[15] - a[13] * a[7] * + a[12] + a[13] * a[8] * a[11] + + out[9] = a[5] * a[10] * a[16] - a[5] * + a[12] * a[14] - a[9] * a[6] * a[16] + + a[9] * a[8] * a[14] + a[13] * a[6] * + a[12] - a[13] * a[8] * a[10] + + out[13] = -a[5] * a[10] * a[15] + a[5] * + a[11] * a[14] + a[9] * a[6] * a[15] - + a[9] * a[7] * a[14] - a[13] * a[6] * + a[11] + a[13] * a[7] * a[10] + + out[2] = -a[2] * a[11] * a[16] + a[2] * + a[12] * a[15] + a[10] * a[3] * a[16] - + a[10] * a[4] * a[15] - a[14] * a[3] * + a[12] + a[14] * a[4] * a[11] + + out[6] = a[1] * a[11] * a[16] - a[1] * + a[12] * a[15] - a[9] * a[3] * a[16] + + a[9] * a[4] * a[15] + a[13] * a[3] * + a[12] - a[13] * a[4] * a[11] + + out[10] = -a[1] * a[10] * a[16] + a[1] * + a[12] * a[14] + a[9] * a[2] * a[16] - + a[9] * a[4] * a[14] - a[13] * a[2] * + a[12] + a[13] * a[4] * a[10] + + out[14] = a[1] * a[10] * a[15] - a[1] * + a[11] * a[14] - a[9] * a[2] * a[15] + + a[9] * a[3] * a[14] + a[13] * a[2] * + a[11] - a[13] * a[3] * a[10] + + out[3] = a[2] * a[7] * a[16] - a[2] * + a[8] * a[15] - a[6] * a[3] * a[16] + + a[6] * a[4] * a[15] + a[14] * a[3] * + a[8] - a[14] * a[4] * a[7] + + out[7] = -a[1] * a[7] * a[16] + a[1] * + a[8] * a[15] + a[5] * a[3] * a[16] - + a[5] * a[4] * a[15] - a[13] * a[3] * + a[8] + a[13] * a[4] * a[7] + + out[11] = a[1] * a[6] * a[16] - a[1] * + a[8] * a[14] - a[5] * a[2] * a[16] + + a[5] * a[4] * a[14] + a[13] * a[2] * + a[8] - a[13] * a[4] * a[6] + + out[15] = -a[1] * a[6] * a[15] + a[1] * + a[7] * a[14] + a[5] * a[2] * a[15] - + a[5] * a[3] * a[14] - a[13] * a[2] * + a[7] + a[13] * a[3] * a[6] + + out[4] = -a[2] * a[7] * a[12] + a[2] * + a[8] * a[11] + a[6] * a[3] * a[12] - + a[6] * a[4] * a[11] - a[10] * a[3] * + a[8] + a[10] * a[4] * a[7] + + out[8] = a[1] * a[7] * a[12] - a[1] * + a[8] * a[11] - a[5] * a[3] * a[12] + + a[5] * a[4] * a[11] + a[9] * a[3] * + a[8] - a[9] * a[4] * a[7] + + out[12] = -a[1] * a[6] * a[12] + a[1] * + a[8] * a[10] + a[5] * a[2] * a[12] - + a[5] * a[4] * a[10] - a[9] * a[2] * + a[8] + a[9] * a[4] * a[6] + + out[16] = a[1] * a[6] * a[11] - a[1] * + a[7] * a[10] - a[5] * a[2] * a[11] + + a[5] * a[3] * a[10] + a[9] * a[2] * + a[7] - a[9] * a[3] * a[6] + + local det = a[1] * out[1] + a[2] * out[5] + a[3] * out[9] + a[4] * out[13] + + if det == 0 then return a end + + det = 1 / det + + for i = 1, 16 do + out[i] = out[i] * det + end + + return out +end + +function mat4.compose_world_matrix(t, rot, scale) + local angle, axis = vec3.to_angle_axis(rot) + local l = vec3.len(axis) + + if l == 0 then + return new() + end + + local x, y, z = axis.x / l, axis.y / l, axis.z / l + local c = cos(angle) + local s = sin(angle) + + return new { + x*x*(1-c)+c, y*x*(1-c)+z*s, x*z*(1-c)-y*s, 0, + x*y*(1-c)-z*s, y*y*(1-c)+c, y*z*(1-c)+x*s, 0, + x*z*(1-c)+y*s, y*z*(1-c)-x*s, z*z*(1-c)+c, 0, t.x, t.y, t.z, 1 } - - return mat4.mul(out, a, m) end function mat4.scale(out, a, s) @@ -309,145 +381,106 @@ function mat4.scale(out, a, s) return mat4.mul(out, a, m) end --- Inverse of matrix. Tested OK -function mat4:invert() - local out = mat4() - - out[1] = self[6] * self[11] * self[16] - self[6] * self[12] * self[15] - - self[10] * self[7] * self[16] + self[10] * self[8] * self[15] + self[14] - * self[7] * self[12] - self[14] * self[8] * self[11] - - out[5] = -self[5] * self[11] * self[16] + self[5] * self[12] * self[15] + - self[9] * self[7] * self[16] - self[9] * self[8] * self[15] - self[13] * - self[7] * self[12] + self[13] * self[8] * self[11] - - out[9] = self[5] * self[10] * self[16] - self[5] * self[12] * self[14] - - self[9] * self[6] * self[16] + self[9] * self[8] * self[14] + self[13] * - self[6] * self[12] - self[13] * self[8] * self[10] - - out[13] = -self[5] * self[10] * self[15] + self[5] * self[11] * self[14] + - self[9] * self[6] * self[15] - self[9] * self[7] * self[14] - self[13] * - self[6] * self[11] + self[13] * self[7] * self[10] - - out[2] = -self[2] * self[11] * self[16] + self[2] * self[12] * self[15] + - self[10] * self[3] * self[16] - self[10] * self[4] * self[15] - self[14] * - self[3] * self[12] +self[14] * self[4] * self[11] - - out[6] = self[1] * self[11] * self[16] - self[1] * self[12] * self[15] - - self[9] * self[3] * self[16] + self[9] * self[4] * self[15] + self[13] * - self[3] * self[12] - self[13] * self[4] * self[11] - - out[10] = -self[1] * self[10] * self[16] + self[1] * self[12] * self[14] + - self[9] * self[2] * self[16] - self[9] * self[4] * self[14] - self[13] * - self[2] * self[12] + self[13] * self[4] * self[10] - - out[14] = self[1] * self[10] * self[15] - self[1] * self[11] * self[14] - - self[9] * self[2] * self[15] + self[9] * self[3] * self[14] + self[13] * - self[2] * self[11] - self[13] * self[3] * self[10] - - out[3] = self[2] * self[7] * self[16] - self[2] * self[8] * self[15] - - self[6] * self[3] * self[16] + self[6] * self[4] * self[15] + self[14] * - self[3] * self[8] - self[14] * self[4] * self[7] - - out[7] = -self[1] * self[7] * self[16] + self[1] * self[8] * self[15] + - self[5] * self[3] * self[16] - self[5] * self[4] * self[15] - self[13] * - self[3] * self[8] + self[13] * self[4] * self[7] - - out[11] = self[1] * self[6] * self[16] - self[1] * self[8] * self[14] - - self[5] * self[2] * self[16] + self[5] * self[4] * self[14] + self[13] * - self[2] * self[8] - self[13] * self[4] * self[6] - - out[15] = -self[1] * self[6] * self[15] + self[1] * self[7] * self[14] + - self[5] * self[2] * self[15] - self[5] * self[3] * self[14] - self[13] * - self[2] * self[7] + self[13] * self[3] * self[6] - - out[4] = -self[2] * self[7] * self[12] + self[2] * self[8] * self[11] + - self[6] * self[3] * self[12] - self[6] * self[4] * self[11] - self[10] * - self[3] * self[8] + self[10] * self[4] * self[7] - - out[8] = self[1] * self[7] * self[12] - self[1] * self[8] * self[11] - - self[5] * self[3] * self[12] + self[5] * self[4] * self[11] +self[9] * - self[3] * self[8] - self[9] * self[4] * self[7] - - out[12] = -self[1] * self[6] * self[12] + self[1] * self[8] * self[10] + - self[5] * self[2] * self[12] - self[5] * self[4] * self[10] - self[9] * - self[2] * self[8] + self[9] * self[4] * self[6] - - out[16] = self[1] * self[6] * self[11] - self[1] * self[7] * self[10] - - self[5] * self[2] * self[11] + self[5] * self[3] * self[10] + self[9] * - self[2] * self[7] - self[9] * self[3] * self[6] - - local det = self[1] * out[1] + self[2] * out[5] + self[3] * out[9] + self[4] * out[13] - - if det == 0 then return self end - - det = 1.0 / det - - for i = 1, 16 do - out[i] = out[i] * det +function mat4.rotate(out, a, angle, axis) + if type(angle) == "table" then + angle, axis = vec3.to_angle_axis(angle) end + local l = vec3.len(axis) + + if l == 0 then + return a + end + + local x, y, z = axis.x / l, axis.y / l, axis.z / l + local c = cos(angle) + local s = sin(angle) + local m = { + x*x*(1-c)+c, y*x*(1-c)+z*s, x*z*(1-c)-y*s, 0, + x*y*(1-c)-z*s, y*y*(1-c)+c, y*z*(1-c)+x*s, 0, + x*z*(1-c)+y*s, y*z*(1-c)-x*s, z*z*(1-c)+c, 0, + 0, 0, 0, 1, + } + + return mat4.mul(out, a, m) +end + +function mat4.translate(out, a, t) + local m = new { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + t.x, t.y, t.z, 1 + } + + return mat4.mul(out, a, m) +end + +function mat4.shear(out, a, yx, zx, xy, zy, xz, yz) + local yx = yx or 0 + local zx = zx or 0 + local xy = xy or 0 + local zy = zy or 0 + local xz = xz or 0 + local yz = yz or 0 + local m = { + 1, yx, zx, 0, + xy, 1, zy, 0, + xz, yz, 1, 0, + 0, 0, 0, 1 + } + + return mat4.mul(out, a, m) +end + +function mat4.look_at(a, eye, center, up) + local forward = vec3.normalize(vec3(), center - eye) + local side = vec3.normalize(vec3(), vec3.cross(vec3(), forward, up) + local new_up = vec3.normalize(vec3(), vec3.cross(vec3(), side, forward)) + + local view = new() + view[1] = side.x + view[5] = side.y + view[9] = side.z + view[2] = new_up.x + view[6] = new_up.y + view[10] = new_up.z + view[3] = -forward.x + view[7] = -forward.y + view[11] = -forward.z + view[16] = 1 + + local out = mat4.mul(new(), mat4.translate(new(), -eye - forward), view) + + return mat4.mul(out, out, a) +end + +function mat4.transpose(out, a) + out[1] = a[1] + out[2] = a[5] + out[3] = a[9] + out[4] = a[13] + out[5] = a[2] + out[6] = a[6] + out[7] = a[10] + out[8] = a[14] + out[9] = a[3] + out[10] = a[7] + out[11] = a[11] + out[12] = a[15] + out[13] = a[4] + out[14] = a[8] + out[15] = a[12] + out[16] = a[16] + return out end -function mat4:look_at(eye, center, up) - local forward = (center - eye):normalize() - local side = forward:cross(up):normalize() - local new_up = side:cross(forward):normalize() - - local view = mat4() - view[1] = side.x - view[5] = side.y - view[9] = side.z - - view[2] = new_up.x - view[6] = new_up.y - view[10] = new_up.z - - view[3] = -forward.x - view[7] = -forward.y - view[11] = -forward.z - - view[16] = 1 - - local out = mat4():translate(-eye - forward) * view - return out * self -end - - -function mat4.transpose(out, a) - do - return new { - self[1], self[5], self[9], self[13], - self[2], self[6], self[10], self[14], - self[3], self[7], self[11], self[15], - self[4], self[8], self[12], self[16] - } - end - out[1] = a[1] - out[2] = a[5] - out[3] = a[9] - return mat4(m) -end - - -function mat4:__eq(b) - do return false end - - local abs = math.abs - for i=1, 16 do - if true then - return false - end - end - return true -end - -function mat4:__tostring() +function mat4.tostring() local str = "[ " - for i, v in ipairs(self) do + for i, v in ipairs(a) do str = str .. string.format("%2.5f", v) - if i < #self then + if i < #a then str = str .. ", " end end @@ -455,22 +488,58 @@ function mat4:__tostring() return str end -function mat4:__unm() - return self:invert() +function mat4.to_quat(a) + local m = mat4.to_vec4s(mat4.transpose(out, a)) + + local w = sqrt(1 + m[1][1] + m[2][2] + m[3][3]) / 2 + local scale = w * 4 + + return quat.normalize(quat(), quat.new( + m[3][2] - m[2][3] / scale, + m[1][3] - m[3][1] / scale, + m[2][1] - m[1][2] / scale, + w + )) end --- Multiply mat4 by a mat4. Tested OK -function mat4:__mul(m) - if #m == 4 then - local tmp = matrix_mult_nxn(self:transpose():to_vec4s(), { {m[1]}, {m[2]}, {m[3]}, {m[4]} }) - local v = {} - for i=1, 4 do - v[i] = tmp[i][1] +local mat4_mt = {} +mat4_mt.__index = mat4 +mat4_mt.__tostring = mat4.tostring + +function mat4_mt.__call(a) + return mat4.new(a) +end + +function mat4_mt.__tostring(a) + return mat4.tostring(a) +end + +function mat4_mt.__unm(a) + return mat4.invert(new(), a) +end + +function mat4_mt.__eq(a, b) + assert(mat4.ismat4(a), "__eq: Wrong argument type for left hand operant. ( expected)") + assert(mat4.ismat4(b), "__eq: Wrong argument type for right hand operant. ( expected)") + + for i = 1, 16 do + if a[i] ~= b[i] then + return false end - return v end - + return true end -return mat4 +function mat4_mt.__mul(a, b) + assert(mat4.ismat4(a), "__mul: Wrong argument type for left hand operant. ( expected)") + assert(mat4.ismat4(b), "__mul: Wrong argument type for right hand operant. ( expected)") + + return mat4.mul(new(), a, b) +end + +if status then + ffi.metatype(new, mat4_mt) +end + +return setmetatable({}, mat4_mt) diff --git a/modules/quat.lua b/modules/quat.lua index e96dbc4..13605a4 100644 --- a/modules/quat.lua +++ b/modules/quat.lua @@ -342,7 +342,10 @@ end -- @treturn boolean function quat.isquat(q) return - type(v) == "table" and + ( + type(v) == "table" or + type(v) == "cdata" + ) and type(v.x) == "number" and type(v.y) == "number" and type(v.z) == "number" and diff --git a/modules/vec2.lua b/modules/vec2.lua index ebaa16b..da91584 100644 --- a/modules/vec2.lua +++ b/modules/vec2.lua @@ -1,12 +1,16 @@ --- A 2 component vector. -- @module vec2 -local atan2, sqrt,cos, sin, pi = math.atan2, math.sqrt, math.cos, math,sin, math.pi -local vec2 = {} +local atan2 = math.atan2 +local sqrt = math.sqrt +local cos = math.cos +local sin = math.sin +local pi = math.pi +local vec2 = {} -- Private constructor. local function new(x, y) - local v = {} + local v = {} v.x, v.y = x, y return setmetatable(v, vec2_mt) end @@ -241,6 +245,10 @@ function vec2_mt.__call(self, x, y) return vec2.new(x, y) end +function vec2_mt.__tostring(a) + return vec2.tostring(a) +end + function vec2_mt.__unm(a) return vec2.new(-a.x, -a.y) end @@ -256,18 +264,14 @@ function vec2_mt.__add(a, b) assert(vec2.isvec2(a), "__add: Wrong argument type for left hand operant. ( expected)") assert(vec2.isvec2(b), "__add: Wrong argument type for right hand operant. ( expected)") - local temp = vec2.new() - vec2.add(temp, a, b) - return temp + return vec2.add(new(), a, b) end function vec2_mt.__sub(a, b) assert(vec2.isvec2(a), "__add: Wrong argument type for left hand operant. ( expected)") assert(vec2.isvec2(b), "__add: Wrong argument type for right hand operant. ( expected)") - local temp = vec2.new() - vec2.sub(temp, a, b) - return temp + return vec2.sub(new(), a, b) end function vec2_mt.__mul(a, b) @@ -277,9 +281,7 @@ function vec2_mt.__mul(a, b) assert(vec2.isvec2(a), "__mul: Wrong argument type for left hand operant. ( expected)") assert(type(b) == "number", "__mul: Wrong argument type for right hand operant. ( expected)") - local temp = vec2.new() - vec2.mul(temp, a, b) - return temp + return vec2.mul(new(), a, b) end function vec2_mt.__div(a, b) @@ -289,13 +291,11 @@ function vec2_mt.__div(a, b) assert(vec2.isvec2(a), "__div: Wrong argument type for left hand operant. ( expected)") assert(type(b) == "number", "__div: Wrong argument type for right hand operant. ( expected)") - local temp = vec2.new() - vec2.div(temp, a, b) - return temp + return vec2.div(new(), a, b) end -vec2.unit_x = vec2.new(1, 0) -vec2.unit_y = vec2.new(0, 1) +vec2.unit_x = new(1, 0) +vec2.unit_y = new(0, 1) if status then ffi.metatype(new, vec2_mt) diff --git a/modules/vec3.lua b/modules/vec3.lua index ab337a5..5bcac65 100644 --- a/modules/vec3.lua +++ b/modules/vec3.lua @@ -6,7 +6,7 @@ local vec3 = {} -- Private constructor. local function new(x, y, z) - local v = {} + local v = {} v.x, v.y, v.z = x, y, z return setmetatable(v, vec3_mt) end @@ -256,6 +256,10 @@ function vec3_mt.__call(self, x, y, z) return vec3.new(x, y, z) end +function vec3_mt.__tostring(a) + return vec3.tostring(a) +end + function vec3_mt.__unm(a) return vec3.new(-a.x, -a.y, -a.z) end @@ -271,18 +275,14 @@ function vec3_mt.__add(a, b) assert(vec3.isvec3(a), "__add: Wrong argument type for left hand operant. ( expected)") assert(vec3.isvec3(b), "__add: Wrong argument type for right hand operant. ( expected)") - local temp = vec3.new() - vec3.add(temp, a, b) - return temp + return vec3.add(new(), a, b) end function vec3_mt.__sub(a, b) assert(vec3.isvec3(a), "__sub: Wrong argument type for left hand operant. ( expected)") assert(vec3.isvec3(b), "__sub: Wrong argument type for right hand operant. ( expected)") - local temp = vec3.new() - vec3.sub(temp, a, b) - return temp + return vec3.sub(new(), a, b) end function vec3_mt.__mul(a, b) @@ -292,9 +292,7 @@ function vec3_mt.__mul(a, b) assert(vec3.isvec3(a), "__mul: Wrong argument type for left hand operant. ( expected)") assert(type(b) == "number", "__mul: Wrong argument type for right hand operant. ( expected)") - local temp = vec3.new() - vec3.mul(temp, a, b) - return temp + return vec3.mul(new(), a, b) end function vec3_mt.__div(a, b) @@ -304,14 +302,12 @@ function vec3_mt.__div(a, b) assert(vec3.isvec3(a), "__div: Wrong argument type for left hand operant. ( expected)") assert(type(b) == "number", "__div: Wrong argument type for right hand operant. ( expected)") - local temp = vec3.new() - vec3.div(temp, a, b) - return temp + return vec3.div(new(), a, b) end -vec3.unit_x = vec3.new(1, 0, 0) -vec3.unit_y = vec3.new(0, 1, 0) -vec3.unit_z = vec3.new(0, 0, 1) +vec3.unit_x = new(1, 0, 0) +vec3.unit_y = new(0, 1, 0) +vec3.unit_z = new(0, 0, 1) if status then ffi.metatype(new, vec3_mt)