Export Matrix class?

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
User avatar
xpol
Prole
Posts: 14
Joined: Tue May 13, 2014 2:00 am

Export Matrix class?

Post by xpol »

I'm trying to build a scene graph library for LOVE.
Every thing goes well except one:

It is hard to implement a hit check function for a rotated and scaled button.
(maybe rotated and scaled by parent nodes).

All I need is a matrix library and best integrated with LOVE graphics module.

Code: Select all

function love.load()
	node.mat = love.graphics.newMatrix()
	node.image = love.graphics.newImage('my/image.png')
	function node:draw()
		love.graphics.transform(self.mat)
		love.graphics.draw(self.image)
	end
end


function love.update(dt)
	node.mat.rotate(dt)
end


function love.draw()
	node:draw()
end
With this matrix library, I could translate screen coords to local

Code: Select all

function screenToLocal(x, y)
	local m = mat1*mat2*mat3
	return m:inverse():transform(x, y)
end

The problems are:

1. Where shall i put the Matrix object? love.math.Matrix?
2. The current Matrix class is not an Object, shall we convert it to Object or write a adaptor class?
User avatar
xpol
Prole
Posts: 14
Joined: Tue May 13, 2014 2:00 am

Re: Export Matrix class?

Post by xpol »

I have write a simple Matrix class that work for me.

Post it here hope that helps.

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
User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: Export Matrix class?

Post by Roland_Yonaba »

Hi,

I remember I once worked on a project (actually paused), where I needed a Matrix module. I was implementing an engine to simulate steering behaviors. I wouldn't advise using it (but it can serve for reference).

Also, there are tons of matrix classes written in plain Lua you can freely grab on Github. David Manura has a nice implementation, written in plain Lua 5.1 and adapted to be compatible with Lua 5.2 (I believe). I do hope it has all the operations you need. It seems to be widely used, anyway.

Hpe this helps.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Export Matrix class?

Post by kikito »

Even if it's my library and I like it very much, I would not use middleclass for creating a Matrix class.

Matrices are typically very short-lived objects that are created "as an entry point for something else", are almost pure data, and typically are involved in high performance operations. This makes them a not-so-good match for middleclass: it has some overhead. Not a lot - it is adequate for the majority of objects created by a game. But it is not adequate for all cases, and matrix manipulation, with its short life and performance constraints, is one of those cases IMHO.

I would look at Lua's native metatables for this - unless performance is absolutely critical, in which case I would stop using metatables and do plain functions instead (something similar to hump's vector-light)
When I write def I mean function.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot] and 3 guests