From c6790ae7b77e32af33ab290ff6b645536b69210e Mon Sep 17 00:00:00 2001 From: sanine-a Date: Wed, 28 Oct 2020 21:40:28 -0500 Subject: refactor Matrix.lua --- demo/FPSCamera.lua | 112 +++++--------- demo/Matrix.lua | 443 +++++++++++++++++++++++++++++++++++++++++++---------- demo/main.lua | 15 +- 3 files changed, 410 insertions(+), 160 deletions(-) (limited to 'demo') diff --git a/demo/FPSCamera.lua b/demo/FPSCamera.lua index 5e21117..1ec5097 100644 --- a/demo/FPSCamera.lua +++ b/demo/FPSCamera.lua @@ -1,29 +1,5 @@ local Vector = require('Vector') -local Mat3, Mat4 = require('Matrix')() - -local Basis = function(M) - local m = Mat3.new() - honey.cglm.mat4.pick3(M, m) - - local x0 = honey.cglm.get_value(m, Mat3.index(1,1)) - local x1 = honey.cglm.get_value(m, Mat3.index(2,1)) - local x2 = honey.cglm.get_value(m, Mat3.index(3,1)) - - local y0 = honey.cglm.get_value(m, Mat3.index(1,2)) - local y1 = honey.cglm.get_value(m, Mat3.index(2,2)) - local y2 = honey.cglm.get_value(m, Mat3.index(3,2)) - - local z0 = honey.cglm.get_value(m, Mat3.index(1,3)) - local z1 = honey.cglm.get_value(m, Mat3.index(2,3)) - local z2 = honey.cglm.get_value(m, Mat3.index(3,3)) - - local b = {} - b.x = Vector.Vec3.new{x0, x1, x2} - b.y = Vector.Vec3.new{y0, y1, y2} - b.z = Vector.Vec3.new{z0, z1, z2} - - return b -end +local Matrix = require('Matrix') local camera = {} @@ -36,46 +12,40 @@ camera.movement_speed = 1 camera.position = Vector.Vec3.new{0,0,-1} -camera.view = Mat4.new() -honey.cglm.mat4.identity(camera.view) - -camera.basis = Basis(camera.view) +camera.view = Matrix.Mat4.eye() +camera.basis = camera.view:basis() -camera.projection = Mat4.new() -honey.cglm.camera.perspective( - camera.projection, - math.rad(90), - 640/480, - 0.1, - 8192) +camera.projection = Matrix.Mat4.perspective(math.rad(90), + 640/480, + 0.1, + 8192) function camera:update() - local M = Mat4.new() - honey.cglm.mat4.identity(M) - honey.cglm.affine.rotate(M, Vector.Vec3.ZERO.array, self.basis.x.array, math.rad(self.pitch)) - honey.cglm.affine.rotate(M, Vector.Vec3.ZERO.array, Vector.Vec3.Y_UNIT.array, math.rad(self.yaw)) - self.basis = Basis(M) - - movement = Vector.Vec3.new() - if honey.input.key.is_down(honey.input.key.w) then - movement:add(self.basis.z, movement) - end - if honey.input.key.is_down(honey.input.key.a) then - movement:add(self.basis.x, movement) - end - if honey.input.key.is_down(honey.input.key.s) then - movement:sub(self.basis.z, movement) - end - if honey.input.key.is_down(honey.input.key.d) then - movement:sub(self.basis.x, movement) - end - - movement:setAt(1, 0) - movement:normalize() - movement:muls(self.movement_speed, movement) - self.position:add(movement, self.position) - - honey.cglm.camera.look(self.position.array, self.basis.z.array, Vector.Vec3.Y_UNIT.array, self.view) + local M = Matrix.Mat4.eye() + M:rotate(Vector.Vec3.ZERO, self.basis.x, math.rad(self.pitch)) + M:rotate(Vector.Vec3.ZERO, Vector.Vec3.Y_UNIT, math.rad(self.yaw)) + self.basis = M:basis() + + movement = Vector.Vec3.new() + if honey.input.key.is_down(honey.input.key.w) then + movement:add(self.basis.z, movement) + end + if honey.input.key.is_down(honey.input.key.a) then + movement:add(self.basis.x, movement) + end + if honey.input.key.is_down(honey.input.key.s) then + movement:sub(self.basis.z, movement) + end + if honey.input.key.is_down(honey.input.key.d) then + movement:sub(self.basis.x, movement) + end + + movement:setAt(1, 0) + movement:normalize() + movement:muls(self.movement_speed, movement) + self.position:add(movement, self.position) + + Matrix.Mat4.look(self.position, self.basis.z, Vector.Vec3.Y_UNIT, self.view) end camera.mouse_pos = {} @@ -83,18 +53,18 @@ camera.mouse_pos.x = 0 camera.mouse_pos.y = 0 honey.input.mouse.bind_movement( - function(xpos, ypos) - local dx = xpos - camera.mouse_pos.x - local dy = ypos - camera.mouse_pos.y + function(xpos, ypos) + local dx = xpos - camera.mouse_pos.x + local dy = ypos - camera.mouse_pos.y - camera.mouse_pos = { x=xpos, y=ypos } + camera.mouse_pos = { x=xpos, y=ypos } - camera.pitch = camera.pitch + camera.sensitivity * dy - camera.yaw = camera.yaw - camera.sensitivity * dx + camera.pitch = camera.pitch + camera.sensitivity * dy + camera.yaw = camera.yaw - camera.sensitivity * dx - if camera.pitch > 89 then camera.pitch = 89 end - if camera.pitch < -89 then camera.pitch = -89 end - end + if camera.pitch > 89 then camera.pitch = 89 end + if camera.pitch < -89 then camera.pitch = -89 end + end ) honey.input.mouse.set_mode(honey.input.mouse.mode.disabled) diff --git a/demo/Matrix.lua b/demo/Matrix.lua index 11b704c..eae210f 100644 --- a/demo/Matrix.lua +++ b/demo/Matrix.lua @@ -1,90 +1,375 @@ -local Mat3 = {} - -Mat3.index = function(i, j) - return (i-1) + 3*(j-1) -end - -Mat3.tostring = function(mat) - local str = '[ ['.. - tostring(honey.cglm.get_value(mat, 0))..', '.. - tostring(honey.cglm.get_value(mat, 3))..', '.. - tostring(honey.cglm.get_value(mat, 6))..']\n ['.. - tostring(honey.cglm.get_value(mat, 1))..', '.. - tostring(honey.cglm.get_value(mat, 4))..', '.. - tostring(honey.cglm.get_value(mat, 7))..']\n ['.. - tostring(honey.cglm.get_value(mat, 2))..', '.. - tostring(honey.cglm.get_value(mat, 5))..', '.. - tostring(honey.cglm.get_value(mat, 8))..'] ]' - return str -end - -Mat3.new = function(tbl) - if tbl == nil then - return honey.cglm.new_array_zero(9) - end - - if #tbl ~= 9 then - error('3x3 matrices require exactly nine elements!') - end - - local mat3 = honey.cglm.new_array_zero(9) - for i = 0,8 do - honey.cglm.set_value(mat3, i, tbl[i+1]) - end +local Vector = require('Vector') + +local Matrix = {} + +Matrix.Mat3 = {} + +Matrix.Mat3.prototype = {} + +Matrix.Mat3.prototype.at = function(self, i, j) + return honey.cglm.get_value(self.array, (i-1) + 3*(j-1)) +end + +Matrix.Mat3.prototype.setAt = function(self, i, j, value) + honey.cglm.set_value(self.array, (i-1) + 3*(j-1), value) +end + +Matrix.Mat3.prototype.clone = function(self) + local clone = honey.cglm.new_array_zero(9) + clone.array = honey.cglm.copy_array(self.array, 9) + return clone +end + +Matrix.Mat3.prototype.mul = function(self, M, dest) + local result + if dest == nil then + result = Matrix.Mat3.new() + else + result = dest + end + + honey.cglm.mat3.mul(self.array, M.array, result) + return result +end + +Matrix.Mat3.prototype.muls = function(self, s, dest) + local result + if dest == nil then + result = Matrix.Mat3.new() + else + result = dest + end + + honey.cglm.mat3.muls(s, self.array, result) + return result +end + +Matrix.Mat3.prototype.mulv = function(self, v, dest) + local result + if dest == nil then + result = Matrix.Mat3.new() + else + result = dest + end + + honey.cglm.mat3.mulv(self.array, v.array, result) + return result +end + +Matrix.Mat3.prototype.T = function(self, auto) + auto = auto or false + if auto then + honey.cglm.mat3.trans(self.array) + return + end + + local M = self.clone() + + honey.cglm.mat3.trans(M.array) + return M +end + +Matrix.Mat3.prototype.det = function(self) + return honey.cglm.mat3.det(self.array) +end + +Matrix.Mat3.prototype.trace = function(self) + return honey.cglm.mat3.trace(self.array) +end + +Matrix.Mat3.prototype.inv = function(self, dest) + local result + if dest == nil then + result = Matrix.Mat3.new() + else + result = dest + end + + honey.cglm.mat3.inv(self.array, result.array) + return result +end + +Matrix.Mat3.prototype.basis = function(self) + local x0 = self:at(1,1) + local x1 = self:at(2,1) + local x2 = self:at(3,1) + + local y0 = self:at(1,2) + local y1 = self:at(2,2) + local y2 = self:at(3,2) + + local z0 = self:at(1,3) + local z1 = self:at(2,3) + local z2 = self:at(3,3) + + local b = {} + b.x = Vector.Vec3.new{x0, x1, x2} + b.y = Vector.Vec3.new{y0, y1, y2} + b.z = Vector.Vec3.new{z0, z1, z2} + + return b +end + +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Matrix.Mat3.mt = {} + +Matrix.Mat3.mt.__index = Matrix.Mat3.prototype +Matrix.Mat3.mt.__tostring = function(mat3) + local line1 = 'mat3('.. + tostring(mat3:at(1,1))..', '.. + tostring(mat3:at(1,2))..', '.. + tostring(mat3:at(1,3))..', \n' + local line2 = ' '.. + tostring(mat3:at(2,1))..', '.. + tostring(mat3:at(2,2))..', '.. + tostring(mat3:at(2,3))..', \n' + local line3 = ' '.. + tostring(mat3:at(3,1))..', '.. + tostring(mat3:at(3,2))..', '.. + tostring(mat3:at(3,3))..')' + return line1..line2..line3 +end + +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Matrix.Mat3.new = function(tbl) + local mat3 = {} + mat3.array = honey.cglm.new_array_zero(9) + setmetatable(mat3, Matrix.Mat3.mt) + + if tbl == nil then return mat3 end + + for i = 1,3 do + for j = 1,3 do + mat3:setAt(i,j, tbl[3*(i-1) + j]) + end + end return mat3 end +Matrix.Mat3.eye = function() + local eye3 = Matrix.Mat3.new() + honey.cglm.mat3.identity(eye3.array) + return eye3 +end + +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-- +-- Mat4 +-- +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Matrix.Mat4 = {} + +Matrix.Mat4.prototype = {} + +Matrix.Mat4.prototype.at = function(self, i, j) + return honey.cglm.get_value(self.array, (i-1) + 4*(j-1)) +end + +Matrix.Mat4.prototype.setAt = function(self, i, j, value) + honey.cglm.set_value(self.array, (i-1) + 4*(j-1), value) +end + +Matrix.Mat4.prototype.clone = function(self) + local clone = honey.cglm.new_array_zero(16) + clone.array = honey.cglm.copy_array(self.array, 16) + return clone +end + +Matrix.Mat4.prototype.pick3 = function(self, dest) + local result + if dest == nil then + result = Matrix.Mat3.new() + else + result = dest + end + + honey.cglm.mat4.pick3(self.array, result.array) + return result +end + +Matrix.Mat4.prototype.mul = function(self, M, dest) + local result + if dest == nil then + result = Matrix.Mat4.new() + else + result = dest + end + + honey.cglm.mat4.mul(self.array, M.array, result) + return result +end + +Matrix.Mat4.prototype.muls = function(self, s, dest) + local result + if dest == nil then + result = Matrix.Mat4.new() + else + result = dest + end + + honey.cglm.mat4.muls(s, self.array, result) + return result +end + +Matrix.Mat4.prototype.mulv = function(self, v, dest) + local result + if dest == nil then + result = Matrix.Mat4.new() + else + result = dest + end + + honey.cglm.mat4.mulv(self.array, v.array, result) + return result +end + +Matrix.Mat4.prototype.T = function(self, auto) + auto = auto or false + if auto then + honey.cglm.mat4.trans(self.array) + return + end + + local M = self.clone() + + honey.cglm.mat4.trans(M.array) + return M +end + +Matrix.Mat4.prototype.det = function(self) + return honey.cglm.mat4.det(self.array) +end + +Matrix.Mat4.prototype.trace = function(self) + return honey.cglm.mat4.trace(self.array) +end + +Matrix.Mat4.prototype.inv = function(self, dest) + local result + if dest == nil then + result = Matrix.Mat4.new() + else + result = dest + end + + honey.cglm.mat4.inv(self.array, result.array) + return result +end + +Matrix.Mat4.prototype.fastInv = function(self, dest) + local result + if dest == nil then + result = Matrix.Mat4.new() + else + result = dest + end + + honey.cglm.mat4.inv_fast(self.array, result.array) + return result +end + +Matrix.Mat4.prototype.basis = function(self) + local M = self:pick3() + + return M:basis() +end + +Matrix.Mat4.prototype.rotate = function(self, center, axis, angle) + honey.cglm.affine.rotate(self.array, center.array, axis.array, angle) +end + +Matrix.Mat4.prototype.translate = function(self, v) + honey.cglm.affine.translate(self.array, v.array) +end + +Matrix.Mat4.prototype.scale = function(self, v) + honey.cglm.affine.scale(self.array, v.array) +end + -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -local Mat4 = {} - -Mat4.index = function(i, j) - return (i-1) + 4*(j-1) -end - -Mat4.tostring = function(matrix) - str = '' - for i = 1,4 do - for j = 1,4 do - str = str..tostring(honey.cglm.get_value(matrix, Mat4.index(i,j)))..', ' - end - str = str..'\n' - end - return str -end - -Mat4.new = function(tbl) - if tbl == nil then - return honey.cglm.new_array_zero(16) - end - - if #tbl ~= 16 then - error('4x4 matrices require exactly 16 elements!') - end - - local mat4 = honey.cglm.new_array_zero(16) - honey.cglm.set_value(mat4, 0, tbl[1]) - honey.cglm.set_value(mat4, 1, tbl[5]) - honey.cglm.set_value(mat4, 2, tbl[9]) - honey.cglm.set_value(mat4, 3, tbl[13]) - honey.cglm.set_value(mat4, 4, tbl[2]) - honey.cglm.set_value(mat4, 5, tbl[6]) - honey.cglm.set_value(mat4, 6, tbl[10]) - honey.cglm.set_value(mat4, 7, tbl[14]) - honey.cglm.set_value(mat4, 8, tbl[3]) - honey.cglm.set_value(mat4, 9, tbl[7]) - honey.cglm.set_value(mat4, 10, tbl[11]) - honey.cglm.set_value(mat4, 11, tbl[15]) - honey.cglm.set_value(mat4, 12, tbl[4]) - honey.cglm.set_value(mat4, 13, tbl[8]) - honey.cglm.set_value(mat4, 14, tbl[12]) - honey.cglm.set_value(mat4, 15, tbl[16]) - - setmetatable(mat4, Mat4.mt) +Matrix.Mat4.mt = {} + +Matrix.Mat4.mt.__index = Matrix.Mat4.prototype +Matrix.Mat4.mt.__tostring = function(mat4) + local line1 = 'mat4('.. + tostring(mat4:at(1,1))..', '.. + tostring(mat4:at(1,2))..', '.. + tostring(mat4:at(1,3))..', '.. + tostring(mat4:at(1,4))..', \n' + local line2 = ' '.. + tostring(mat4:at(2,1))..', '.. + tostring(mat4:at(2,2))..', '.. + tostring(mat4:at(2,3))..', '.. + tostring(mat4:at(2,4))..', \n' + local line3 = ' '.. + tostring(mat4:at(3,1))..', '.. + tostring(mat4:at(3,2))..', '.. + tostring(mat4:at(3,3))..', '.. + tostring(mat4:at(3,4))..')' + local line4 = ' '.. + tostring(mat4:at(4,1))..', '.. + tostring(mat4:at(4,2))..', '.. + tostring(mat4:at(4,3))..', '.. + tostring(mat4:at(4,4))..')' + return line1..line2..line4 +end + +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Matrix.Mat4.new = function(tbl) + local mat4 = {} + mat4.array = honey.cglm.new_array_zero(16) + setmetatable(mat4, Matrix.Mat4.mt) + + if tbl == nil then return mat4 end + + for i = 1,4 do + for j = 1,4 do + mat4:setAt(i,j, tbl[4*(i-1) + j]) + end + end return mat4 end +Matrix.Mat4.eye = function() + local eye4 = Matrix.Mat4.new() + honey.cglm.mat4.identity(eye4.array) + return eye4 +end + +Matrix.Mat4.perspective = function(fov, aspectRatio, near, far) + local M = Matrix.Mat4.new() + honey.cglm.camera.perspective(M.array, fov, aspectRatio, near, far) + return M +end + +Matrix.Mat4.orthographic = function(a, b) + local M = Matrix.Mat4.new() + honey.cglm.camera.orthographic(M.array, a.array, b.array) + return M +end + +Matrix.Mat4.look = function(position, direction, up, dest) + local result + if dest == nil then + result = Matrix.Mat4.new() + else + result = dest + end + + honey.cglm.camera.look(position.array, + direction.array, + up.array, + dest.array) + return dest +end + +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -return function() return Mat3, Mat4 end +return Matrix diff --git a/demo/main.lua b/demo/main.lua index 62ffcd2..f534952 100644 --- a/demo/main.lua +++ b/demo/main.lua @@ -1,13 +1,8 @@ local Vector = require('Vector') -local Mat3, Mat4 = require('Matrix')() +local Matrix = require('Matrix') local FPSCamera = require('FPSCamera') -local model = Mat4.new() -honey.cglm.mat4.identity(model) -honey.cglm.affine.rotate(model, - Vector.Vec3.ZERO.array, - Vector.Vec3.X_UNIT.array, - math.pi/4) +local model = Matrix.Mat4.eye() honey.input.key.bind(honey.input.key.escape, honey.exit) @@ -47,9 +42,9 @@ end function honey.draw() FPSCamera:update() - honey.shader.set_mat4(shader, 'model', model) - honey.shader.set_mat4(shader, 'view', FPSCamera.view) - honey.shader.set_mat4(shader, 'projection', FPSCamera.projection) + honey.shader.set_mat4(shader, 'model', model.array) + honey.shader.set_mat4(shader, 'view', FPSCamera.view.array) + honey.shader.set_mat4(shader, 'projection', FPSCamera.projection.array) honey.shader.set_vec4(shader, "base_color", color.array) honey.mesh.draw(plane, shader) end -- cgit v1.2.1