From cf0543651401b81a9fea5f143c96d71477160471 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Mon, 23 Feb 2026 02:11:02 +0000 Subject: [PATCH] _math: implement matrix multiplication --- _math.lua | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.lua | 43 ++++++++++++++++--------- 2 files changed, 122 insertions(+), 15 deletions(-) diff --git a/_math.lua b/_math.lua index 08b8d16..d0ebe52 100644 --- a/_math.lua +++ b/_math.lua @@ -31,6 +31,10 @@ mat4 = { return value end, + __mul = function(M1, M2) + return mat4.multiply(M1, M2) + end, + set = function(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, @@ -211,6 +215,45 @@ mat4 = { return MT end, + multiply = function(M1, M2) + local M = mat4() + + local x = M1.m[0 * 4 + 0] + local y = M1.m[0 * 4 + 1] + local z = M1.m[0 * 4 + 2] + local w = M1.m[0 * 4 + 3] + M.m[0 * 4 + 0] = (M2.m[0 * 4 + 0] * x) + (M2.m[1 * 4 + 0] * y) + (M2.m[2 * 4 + 0] * z) + (M2.m[3 * 4 + 0] * w) + M.m[0 * 4 + 1] = (M2.m[0 * 4 + 1] * x) + (M2.m[1 * 4 + 1] * y) + (M2.m[2 * 4 + 1] * z) + (M2.m[3 * 4 + 1] * w) + M.m[0 * 4 + 2] = (M2.m[0 * 4 + 2] * x) + (M2.m[1 * 4 + 2] * y) + (M2.m[2 * 4 + 2] * z) + (M2.m[3 * 4 + 2] * w) + M.m[0 * 4 + 3] = (M2.m[0 * 4 + 3] * x) + (M2.m[1 * 4 + 3] * y) + (M2.m[2 * 4 + 3] * z) + (M2.m[3 * 4 + 3] * w) + x = M1.m[1 * 4 + 0] + y = M1.m[1 * 4 + 1] + z = M1.m[1 * 4 + 2] + w = M1.m[1 * 4 + 3] + M.m[1 * 4 + 0] = (M2.m[0 * 4 + 0] * x) + (M2.m[1 * 4 + 0] * y) + (M2.m[2 * 4 + 0] * z) + (M2.m[3 * 4 + 0] * w) + M.m[1 * 4 + 1] = (M2.m[0 * 4 + 1] * x) + (M2.m[1 * 4 + 1] * y) + (M2.m[2 * 4 + 1] * z) + (M2.m[3 * 4 + 1] * w) + M.m[1 * 4 + 2] = (M2.m[0 * 4 + 2] * x) + (M2.m[1 * 4 + 2] * y) + (M2.m[2 * 4 + 2] * z) + (M2.m[3 * 4 + 2] * w) + M.m[1 * 4 + 3] = (M2.m[0 * 4 + 3] * x) + (M2.m[1 * 4 + 3] * y) + (M2.m[2 * 4 + 3] * z) + (M2.m[3 * 4 + 3] * w) + x = M1.m[2 * 4 + 0] + y = M1.m[2 * 4 + 1] + z = M1.m[2 * 4 + 2] + w = M1.m[2 * 4 + 3] + M.m[2 * 4 + 0] = (M2.m[0 * 4 + 0] * x) + (M2.m[1 * 4 + 0] * y) + (M2.m[2 * 4 + 0] * z) + (M2.m[3 * 4 + 0] * w) + M.m[2 * 4 + 1] = (M2.m[0 * 4 + 1] * x) + (M2.m[1 * 4 + 1] * y) + (M2.m[2 * 4 + 1] * z) + (M2.m[3 * 4 + 1] * w) + M.m[2 * 4 + 2] = (M2.m[0 * 4 + 2] * x) + (M2.m[1 * 4 + 2] * y) + (M2.m[2 * 4 + 2] * z) + (M2.m[3 * 4 + 2] * w) + M.m[2 * 4 + 3] = (M2.m[0 * 4 + 3] * x) + (M2.m[1 * 4 + 3] * y) + (M2.m[2 * 4 + 3] * z) + (M2.m[3 * 4 + 3] * w) + x = M1.m[3 * 4 + 0] + y = M1.m[3 * 4 + 1] + z = M1.m[3 * 4 + 2] + w = M1.m[3 * 4 + 3] + M.m[3 * 4 + 0] = (M2.m[0 * 4 + 0] * x) + (M2.m[1 * 4 + 0] * y) + (M2.m[2 * 4 + 0] * z) + (M2.m[3 * 4 + 0] * w) + M.m[3 * 4 + 1] = (M2.m[0 * 4 + 1] * x) + (M2.m[1 * 4 + 1] * y) + (M2.m[2 * 4 + 1] * z) + (M2.m[3 * 4 + 1] * w) + M.m[3 * 4 + 2] = (M2.m[0 * 4 + 2] * x) + (M2.m[1 * 4 + 2] * y) + (M2.m[2 * 4 + 2] * z) + (M2.m[3 * 4 + 2] * w) + M.m[3 * 4 + 3] = (M2.m[0 * 4 + 3] * x) + (M2.m[1 * 4 + 3] * y) + (M2.m[2 * 4 + 3] * z) + (M2.m[3 * 4 + 3] * w) + + return M + end, + look_to_lh = function(eye_position, eye_direction, up_direction) assert(not vec3.equal(eye_direction, vec3._zero)) assert(not vec3.isinfinite(eye_direction)) @@ -323,6 +366,30 @@ mat4 = { ) end, + equal = function(M1, M2) + return ( + M1.m[0 * 4 + 0] == M2.m[0 * 4 + 0] and + M1.m[0 * 4 + 1] == M2.m[0 * 4 + 1] and + M1.m[0 * 4 + 2] == M2.m[0 * 4 + 2] and + M1.m[0 * 4 + 3] == M2.m[0 * 4 + 3] and + + M1.m[1 * 4 + 0] == M2.m[1 * 4 + 0] and + M1.m[1 * 4 + 1] == M2.m[1 * 4 + 1] and + M1.m[1 * 4 + 2] == M2.m[1 * 4 + 2] and + M1.m[1 * 4 + 3] == M2.m[1 * 4 + 3] and + + M1.m[2 * 4 + 0] == M2.m[2 * 4 + 0] and + M1.m[2 * 4 + 1] == M2.m[2 * 4 + 1] and + M1.m[2 * 4 + 2] == M2.m[2 * 4 + 2] and + M1.m[2 * 4 + 3] == M2.m[2 * 4 + 3] and + + M1.m[3 * 4 + 0] == M2.m[3 * 4 + 0] and + M1.m[3 * 4 + 1] == M2.m[3 * 4 + 1] and + M1.m[3 * 4 + 2] == M2.m[3 * 4 + 2] and + M1.m[3 * 4 + 3] == M2.m[3 * 4 + 3] + ) + end, + print = function(M) for i = 0, 15 do io.write(tostring(M.m[i])) @@ -492,6 +559,33 @@ assert(mat4.near_equal(mat4.perspective_rh(2, 3, 4, 5), 0.000000, 0.000000, -20.000000, 0.000000), 0.00001)) +assert(mat4.equal(mat4.multiply(mat4.set(1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16), + mat4.set(17, 18, 19, 20, + 21, 22, 23, 24, + 25, 26, 27, 29, + 30, 31, 32, 33)), + mat4.set(254, 264, 274, 287, + 626, 652, 678, 711, + 998, 1040, 1082, 1135, + 1370, 1428, 1486, 1559))) + +assert(mat4.equal(mat4.set(1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16) + * + mat4.set(17, 18, 19, 20, + 21, 22, 23, 24, + 25, 26, 27, 29, + 30, 31, 32, 33), + mat4.set(254, 264, 274, 287, + 626, 652, 678, 711, + 998, 1040, 1082, 1135, + 1370, 1428, 1486, 1559))) + return { scalar = scalar, mat4 = mat4, diff --git a/main.lua b/main.lua index 265e3de..3ece31a 100644 --- a/main.lua +++ b/main.lua @@ -33,10 +33,7 @@ local vertexcode = [[ layout (location = 1) in vec4 VertexNormal; layout (location = 2) in vec4 VertexTexture; - uniform mat4 projection; - uniform mat4 view; - uniform mat4 model; - uniform mat4 model2; + uniform mat4 transform; varying vec4 PixelNormal; varying vec4 PixelTexture; @@ -45,8 +42,7 @@ local vertexcode = [[ { PixelNormal = VertexNormal * 0.5 + 0.5; PixelTexture = VertexTexture; - mat4 trans = projection * view * model * model2; - love_Position = trans * vec4(VertexPosition.xyz, 1); + love_Position = transform * vec4(VertexPosition.xyz, 1); } ]] @@ -109,16 +105,33 @@ function love.draw() local mx, my = love.mouse.getPosition() width, height = love.graphics.getDimensions() - shader:send("projection", "column", mat4.perspective_rh(width / width * 0.25, - height / width * 0.25, - 0.1, - 1000.0).data) - shader:send("view", "column", mat4.look_at_rh(vec3(0, -2, 0), - vec3(0, 0, 0), - vec3(0, 0, 1)).data) + -- shader:send("projection", "column", mat4.perspective_rh(width / width * 0.25, + -- height / width * 0.25, + -- 0.1, + -- 1000.0).data) + -- shader:send("view", "column", mat4.look_at_rh(vec3(0, -2, 0), + -- vec3(0, 0, 0), + -- vec3(0, 0, 1)).data) + + -- shader:send("model", "column", mat4.rotation_x(rotation).data) + -- shader:send("model2", "column", mat4.rotation_z(rotation * 0.5).data) + + local projection = mat4.perspective_rh(width / width * 0.25, + height / width * 0.25, + 0.1, + 1000.0) + local view = mat4.look_at_rh(vec3(0, -2, 0), + vec3(0, 0, 0), + vec3(0, 0, 1)) + + local world1 = mat4.rotation_x(rotation) + local world2 = mat4.rotation_z(rotation * 0.5) + local world3 = mat4.translation(0, 0, -0.5) + + local transform = world3 * world2 * world1 * view * projection + + shader:send("transform", "column", transform.data) - shader:send("model", "column", mat4.rotation_x(rotation).data) - shader:send("model2", "column", mat4.rotation_z(rotation * 0.5).data) shader:send("texture_sampler", texture) rotation = rotation + 0.01 love.graphics.setShader(shader)