I have write a simple Matrix class that work for me.
Code: Select all
local class = require('middleclass')
local Matrix = class('Matrix')
--| 1 4 7 |
--| 2 5 8 |
--| 3 6 9 |
function Matrix:initialize(v1, v2, v3, v4, v5, v6, v7, v8, v9)
if not v1 then
self[1], self[4], self[7] = 1, 0, 0
self[2], self[5], self[8] = 0, 1, 0
self[3], self[6], self[9] = 0, 0, 1
elseif type(v1) == 'table' then
local m = v1
self[1], self[4], self[7] = m[1], m[4], m[7]
self[2], self[5], self[8] = m[2], m[5], m[8]
self[3], self[6], self[9] = m[3], m[6], m[9]
else
self[1], self[4], self[7] = v1, v4, v7
self[2], self[5], self[8] = v2, v5, v8
self[3], self[6], self[9] = v3, v6, v9
end
end
function Matrix:setIdentity()
self[1], self[4], self[7] = 1, 0, 0
self[2], self[5], self[8] = 0, 1, 0
self[3], self[6], self[9] = 0, 0, 1
end
-- | 1 4 7 |
-- | 2 5 8 |
-- | 3 6 9 |
--| 1 4 7 |
--| 2 5 8 |
--| 0 0 1 |
function Matrix:__mul(rhs)
local t = Matrix()
t[1] = self[1] * rhs[1] + self[4] * rhs[2] -- + self[7] * rhs[3]
t[4] = self[1] * rhs[4] + self[4] * rhs[5] -- + self[7] * rhs[6]
t[7] = self[1] * rhs[7] + self[4] * rhs[8] + self[7] -- * rhs[9]
t[2] = self[2] * rhs[1] + self[5] * rhs[2] -- + self[8] * rhs[3]
t[5] = self[2] * rhs[4] + self[5] * rhs[5] -- + self[8] * rhs[6]
t[8] = self[2] * rhs[7] + self[5] * rhs[8] + self[8] -- * rhs[9]
--t[3] = self[3] * rhs[1] + self[6] * rhs[2] + self[9] * rhs[3]
--t[6] = self[3] * rhs[4] + self[6] * rhs[5] + self[9] * rhs[6]
--t[9] = self[3] * rhs[7] + self[6] * rhs[8] + self[9] * rhs[9]
return t
end
function Matrix:build(x, y, angle, sx, sy, ox, oy, kx, ky)
-- matrix multiplication carried out on paper:
-- |1 x| |c -s | |sx | | 1 ky | |1 -ox|
-- | 1 y| |s c | | sy | |kx 1 | | 1 -oy|
-- | 1| | 1| | 1| | 1| | 1 |
-- move rotate scale skew origin
local cos, sin = math.cos(angle), math.sin(angle)
local a, c = cos*sx - ky*sin*sy, kx*cos*sx - sin*sy
local b, d = sin*sx + ky*cos*sy, kx*sin*sx + cos*sy
self[1],self[4],self[7]= a, c, x - ox*a - oy*c
self[2],self[5],self[8]= b, d, y - ox*b - oy*d
self[3],self[6],self[9]= 0, 0, 1
end
--| 1 4 7 |
--| 2 5 8 |
--| 3 6 9 |
function Matrix:invert() -- it is actually an affine invert
local det = self[1] * self[5] - self[4] * self[2]
if math.abs(det) < 0.00001 then
self:setIdentity()
return
end
local invDet = 1.0/det
local t = self[7];
self[7] = ( self[4] * self[8] - t * self[5]) * invDet;
self[8] = (t * self[2] - self[1] * self[8]) * invDet;
t = self[1];
self[1] = self[5] * invDet;
self[5] = t * invDet;
self[2] = - self[2] * invDet;
self[4] = - self[4] * invDet;
end
function Matrix:inverted()
local m = Matrix(self)
m:invert()
return m
end
-- | x |
-- | y |
-- | 0 |
--| 1 4 7 |
--| 2 5 8 |
--| 3 6 9 |
function Matrix:transform(x, y)
return self[1]*x + self[4]*y + self[7],
self[2]*x + self[5]*y + self[8]
end
return Matrix