1
0
Fork 0
mirror of https://github.com/Reuh/wirefame.git synced 2025-10-27 17:49:31 +00:00
This commit is contained in:
Étienne Fildadut 2021-02-18 17:22:21 +01:00
parent b4798c8c16
commit 77cfbaad52
24 changed files with 3033 additions and 1545 deletions

246
math/m4.lua Normal file
View file

@ -0,0 +1,246 @@
--- 4x4 matrix.
-- Reminder: they are represented in row-major order, **unlike** GLM which is column-major.
local m4
local cos, sin, tan = math.cos, math.sin, math.tan
local v3 = require((...):match("^(.*)m4$").."v3")
local tmpv3 = v3(0,0,0) -- temporary vector used in our computations
-- m4 methods
-- Unless specified otherwise, all operations are done in place and do not create a new matrix.
local m4_mt = {
-- Clone the matrix. Returns a new matrix.
clone = function(self)
return m4{
self[1], self[2], self[3], self[4],
self[5], self[6], self[7], self[8],
self[9], self[10], self[11], self[12],
self[13], self[14], self[15], self[16]
}
end,
-- Set matrix
set = function(self, other)
self[1], self[2], self[3], self[4] = other[1], other[2], other[3], other[4]
self[5], self[6], self[7], self[8] = other[5], other[6], other[7], other[8]
self[9], self[10], self[11], self[12] = other[9], other[10], other[11], other[12]
self[13], self[14], self[15], self[16] = other[13], other[14], other[15], other[16]
return self
end,
-- Retrieve values
unpack = function(self)
return self[1], self[2], self[3], self[4],
self[5], self[6], self[7], self[8],
self[9], self[10], self[11], self[12],
self[13], self[14], self[15], self[16]
end,
-- Apply a transformation matrix to our matrix
transform = function(self, tr)
local s1, s2, s3, s4 = self[1], self[2], self[3], self[4]
local s5, s6, s7, s8 = self[5], self[6], self[7], self[8]
local s9, s10, s11, s12 = self[9], self[10], self[11], self[12]
local s13, s14, s15, s16 = self[13], self[14], self[15], self[16]
self[1] = tr[1] * s1 + tr[2] * s5 + tr[3] * s9 + tr[4] * s13
self[2] = tr[1] * s2 + tr[2] * s6 + tr[3] * s10 + tr[4] * s14
self[3] = tr[1] * s3 + tr[2] * s7 + tr[3] * s11 + tr[4] * s15
self[4] = tr[1] * s4 + tr[2] * s8 + tr[3] * s12 + tr[4] * s16
self[5] = tr[5] * s1 + tr[6] * s5 + tr[7] * s9 + tr[8] * s13
self[6] = tr[5] * s2 + tr[6] * s6 + tr[7] * s10 + tr[8] * s14
self[7] = tr[5] * s3 + tr[6] * s7 + tr[7] * s11 + tr[8] * s15
self[8] = tr[5] * s4 + tr[6] * s8 + tr[7] * s12 + tr[8] * s16
self[9] = tr[9] * s1 + tr[10] * s5 + tr[11] * s9 + tr[12] * s13
self[10] = tr[9] * s2 + tr[10] * s6 + tr[11] * s10 + tr[12] * s14
self[11] = tr[9] * s3 + tr[10] * s7 + tr[11] * s11 + tr[12] * s15
self[12] = tr[9] * s4 + tr[10] * s8 + tr[11] * s12 + tr[12] * s16
self[13] = tr[13] * s1 + tr[14] * s5 + tr[15] * s9 + tr[16] * s13
self[14] = tr[13] * s2 + tr[14] * s6 + tr[15] * s10 + tr[16] * s14
self[15] = tr[13] * s3 + tr[14] * s7 + tr[15] * s11 + tr[16] * s15
self[16] = tr[13] * s4 + tr[14] * s8 + tr[15] * s12 + tr[16] * s16
return self
end,
translate = function(self, v)
return self:transform(m4.translate(v))
end,
scale = function(self, v)
return self:transform(m4.scale(v))
end,
rotate = function(self, angle, v)
return self:transform(m4.rotate(angle, v))
end,
shear = function(self, vxy, vyz)
return self:transform(m4.shear(vxy, vyz))
end,
-- Common operations. Returns a new matrix.
__mul = function(self, other)
return m4{
self[1] * other[1] + self[2] * other[5] + self[3] * other[9] + self[4] * other[13],
self[1] * other[2] + self[2] * other[6] + self[3] * other[10] + self[4] * other[14],
self[1] * other[3] + self[2] * other[7] + self[3] * other[11] + self[4] * other[15],
self[1] * other[4] + self[2] * other[8] + self[3] * other[12] + self[4] * other[16],
self[5] * other[1] + self[6] * other[5] + self[7] * other[9] + self[8] * other[13],
self[5] * other[2] + self[6] * other[6] + self[7] * other[10] + self[8] * other[14],
self[5] * other[3] + self[6] * other[7] + self[7] * other[11] + self[8] * other[15],
self[5] * other[4] + self[6] * other[8] + self[7] * other[12] + self[8] * other[16],
self[9] * other[1] + self[10] * other[5] + self[11] * other[9] + self[12] * other[13],
self[9] * other[2] + self[10] * other[6] + self[11] * other[10] + self[12] * other[14],
self[9] * other[3] + self[10] * other[7] + self[11] * other[11] + self[12] * other[15],
self[9] * other[4] + self[10] * other[8] + self[11] * other[12] + self[12] * other[16],
self[13] * other[1] + self[14] * other[5] + self[15] * other[9] + self[16] * other[13],
self[13] * other[2] + self[14] * other[6] + self[15] * other[10] + self[16] * other[14],
self[13] * other[3] + self[14] * other[7] + self[15] * other[11] + self[16] * other[15],
self[13] * other[4] + self[14] * other[8] + self[15] * other[12] + self[16] * other[16]
}
end,
__add = function(self, other)
return m4{
self[1] + other[1], self[2] + other[2], self[3] + other[3], self[4] + other[4],
self[5] + other[5], self[6] + other[6], self[7] + other[7], self[8] + other[8],
self[9] + other[9], self[10] + other[10], self[11] + other[11], self[12] + other[12],
self[13] + other[13], self[14] + other[14], self[15] + other[15], self[16] + other[16],
}
end,
__sub = function(self, other)
return m4{
self[1] - other[1], self[2] - other[2], self[3] - other[3], self[4] - other[4],
self[5] - other[5], self[6] - other[6], self[7] - other[7], self[8] - other[8],
self[9] - other[9], self[10] - other[10], self[11] - other[11], self[12] - other[12],
self[13] - other[13], self[14] - other[14], self[15] - other[15], self[16] - other[16],
}
end,
__unm = function(self)
return m4{
-self[1], -self[2], -self[3], -self[4],
-self[5], -self[6], -self[7], -self[8],
-self[9], -self[10], -self[11], -self[12],
-self[13], -self[14], -self[15], -self[16]
}
end,
__tostring = function(self)
local mt = getmetatable(self)
setmetatable(self, nil)
local str = "m4: "..(tostring(self):gsub("^table: ", ""))
setmetatable(self, mt)
return str
end
}
m4_mt.__index = m4_mt
m4 = setmetatable({
-- Common transformation to create new matrices from
identity = function()
return m4{
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
}
end,
translate = function(v)
return m4{
1, 0, 0, v[1],
0, 1, 0, v[2],
0, 0, 1, v[3],
0, 0, 0, 1
}
end,
scale = function(v)
return m4{
v[1], 0, 0, 0,
0, v[2], 0, 0,
0, 0, v[3], 0,
0, 0, 0, 1
}
end,
rotate = function(angle, v)
local c = cos(angle)
local s = sin(angle)
local x, y, z = tmpv3:set(v):normalize():unpack()
local tx, ty, tz = (1 - c) * x, (1 - c) * y, (1 - c) * z
return m4{
c + tx * x, ty * x - s * z, tz * x + s * y, 0,
tx * y + s * z, c + ty * y, tz * y - s * x, 0,
tx * z - s * y, ty * z + s * x, c + tz * z, 0,
0, 0, 0, 1
}
end,
-- vxy: shearing vector in the (xy) plane
-- vyz: shearing vector in the (yz) plane
shear = function(vxy, vyz)
return m4{
1, vxy[1], vyz[1], 0,
vxy[2], 1, vyz[2], 0,
vxy[3], vyz[3], 1, 0,
0, 0, 0, 1
}
end,
-- Projection matrix constructor (right-handed).
perspective = function(fovy, aspect, zNear, zFar) -- If zFar is not specified, will return an infinite perspective matrix.
local f = 1 / tan(fovy / 2)
if zFar then
return m4{
f / aspect, 0, 0, 0,
0, f, 0, 0,
0, 0, (zFar + zNear) / (zNear - zFar), (2 * zFar * zNear) / (zNear - zFar),
0, 0, -1, 0
}
else
return m4{
f / aspect, 0, 0, 0,
0, f, 0, 0,
0, 0, -1, -2 * zNear,
0, 0, -1, 0
}
end
end,
orthographic = function(xmag, ymag, znear, zfar)
return m4{
1 / xmag, 0, 0, 0,
0, 1 / ymag, 0, 0,
0, 0, 2 / (znear - zfar), (zfar + znear) / (znear - zfar),
0, 0, 0, 1
}
end,
lookAt = function(eye, center, up)
center, up = v3(center), v3(up)
local f = (center - eye):normalize()
local s = f:cross(up):normalize()
local u = s:cross(f)
return m4{
s[1], s[2], s[3], -s:dot(eye),
u[1], u[2], u[3], -u:dot(eye),
-f[1], -f[2], -f[3], f:dot(eye),
0, 0, 0, 1
}
end,
-- Create a new matrix from column major list
fromColumnMajor = function(m)
return m4{
m[1], m[5], m[9], m[13],
m[2], m[6], m[10], m[14],
m[3], m[7], m[11], m[15],
m[4], m[8], m[12], m[16]
}
end
}, {
-- Will not copy the table.
__call = function(self, t)
return setmetatable(t, m4_mt)
end
})
return m4