## Is there a way to get current transformation?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
AnRu
Citizen
Posts: 69
Joined: Sun Oct 27, 2013 1:33 pm
Contact:

### Is there a way to get current transformation?

I would like to get current position, rotation and scaling values of graphics transform, caused by nested transformations

Code: Select all

function drawObject(object)
love.graphics.push()
love.graphics.translate(...)
love.graphics.rotate(...)
love.graphics.scale(...)

-- I want to do something like this:
globalPos, globalRot, globalScale = love.graphics.currentTransformation()

for k, v in pairs(object.children) do
drawObject(v)
end
love.graphics.pop()
end
Is there a way to achieve this?

Plu
Inner party member
Posts: 722
Joined: Fri Mar 15, 2013 9:36 pm

### Re: Is there a way to get current transformation?

I asked the same question recently (viewtopic.php?f=4&t=82545&hilit=translation) and the answer seems to be "no".

4aiman
Party member
Posts: 248
Joined: Sat Jan 16, 2016 10:30 am

### Re: Is there a way to get current transformation?

Uhmm...
When you call translate with some args you should know what args you're using, right?
So use those args and get what you want.
The same goes for "scale" and "rotate".

Or maybe...
You haven't hardcoded the arguments, have you?

zorg
Party member
Posts: 2527
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

### Re: Is there a way to get current transformation?

4aiman wrote:Uhmm...
When you call translate with some args you should know what args you're using, right?
So use those args and get what you want.
The same goes for "scale" and "rotate".

Or maybe...
You haven't hardcoded the arguments, have you?
Doesn't matter whether the args are hardcoded or not, what matters is that, as you said, if he wants to use them later, he needs to store them somewhere.

You could monkeypatch the love.graphics coordsys manipulating functions to update a matrix you handle on the lua side, and have a neat function as you wrote, to get back those values, but i don't know why you would want to know this. (Or, i don't know the reason why, but i do believe löve uses such a matrix internally anyway, one could "beg" for a function to return those values... you'll need to work out the separate translation, rotation, scale, skew values yourself... if you need those, i mean.)

Two major paths when drawing stuff:

- You have the unmodified transform state (gettable by l.g.origin), because you want to draw "absolutely", or relative to the window itself.
- You have the modified transform state, because you want to draw "relatively" to that modified system.

Neither need you to get the current transformation, and although there may be other uses, i can't think of one myself.
...Also, only i replied to the other thread as well? I'm sad since graphics isn't exactly my forté either
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.

pgimeno
Party member
Posts: 1530
Joined: Sun Oct 18, 2015 2:58 pm

### Re: Is there a way to get current transformation?

zorg wrote:one could "beg" for a function to return those values...
And set them, please, to not have to deal with dirty tricks such as SVD which very few people even know about.
Thrust II Reloaded - GifLoad for Löve - GSpöt GUI - My NotABug.org repositories - portland (mobile orientation)
The MS-Github repositories I had have been closed after the acquisition announcement and will be removed in the near future.

AnRu
Citizen
Posts: 69
Joined: Sun Oct 27, 2013 1:33 pm
Contact:

### Re: Is there a way to get current transformation?

The reason i ask that is that i need to get global position of an child object in the tree
I have no problems with storing positions, but what about rotation? If i rotate parent, childs will rotate with it and a have rotated coordinates. How get this changed coords?

4aiman
Party member
Posts: 248
Joined: Sat Jan 16, 2016 10:30 am

### Re: Is there a way to get current transformation?

AnRu wrote:The reason i ask that is that i need to get global position of an child object in the tree
I bet the real question should be not "How to get X" but "Why do I need X?"
Chances are you're doing something counter-productive or over-engineering things.
AnRu wrote:but what about rotation? If i rotate parent, childs will rotate with it and a have rotated coordinates.
In the case you're dealing with something most of people haven't heard of, see Wikipedia: https://en.wikipedia.org/wiki/Rotation_(mathematics)

airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

### Re: Is there a way to get current transformation?

If you don't have control over all transformations that may be happening, the monkeypatching thing zorg mentioned will work. There's an example of that in box2dhelper (I don't remember where exactly, but I'm sure I saw it there).

If you do have control over the transformations (at least the ones you care about), it should be pretty easy to reverse them to convert between world and screen coordinates. There's an example of that here.

AnRu
Citizen
Posts: 69
Joined: Sun Oct 27, 2013 1:33 pm
Contact:

### Re: Is there a way to get current transformation?

Thank you all for replies
I\ll try to write own transform system

pgimeno
Party member
Posts: 1530
Joined: Sun Oct 18, 2015 2:58 pm

### Re: Is there a way to get current transformation?

You can always use a wrapper that keeps track of the matrix.

Code: Select all

local lgorigin = love.graphics.origin
local lgscale = love.graphics.scale
local lgrotate = love.graphics.rotate
local lgshear = love.graphics.shear
local lgtranslate = love.graphics.translate

-- The implicit third row is always 0, 0, 1
local matrix = {1,0,0,
0,1,0}

local function getMatrix(t)
if t == nil then
-- Return a copy
return {matrix[ 1], matrix[ 2], matrix[ 3],
matrix[ 4], matrix[ 5], matrix[ 6]}
end
-- Assign the elements (enables reusing tables)
-- (unrolled loop)
t[1] = matrix[1]; t[2] = matrix[2]; t[3] = matrix[3]
t[4] = matrix[4]; t[5] = matrix[5]; t[6] = matrix[6]
return t
end

local function origin()
matrix[1] = 1  matrix[2] = 0  matrix[3] = 0
matrix[4] = 0  matrix[5] = 1  matrix[6] = 0
lgorigin()
end

local function scale(x, y)
matrix[1] = matrix[1] * x; matrix[2] = matrix[2] * y
matrix[4] = matrix[4] * x; matrix[5] = matrix[5] * y
lgscale(x, y)
end

local function rotate(a)
local c, s = math.cos(a), math.sin(a)
matrix[1], matrix[2] = matrix[1]*c + matrix[2]*s, matrix[1]*-s + matrix[2]*c
matrix[4], matrix[5] = matrix[4]*c + matrix[5]*s, matrix[4]*-s + matrix[5]*c
lgrotate(a)
end

local function shear(x, y)
matrix[1], matrix[2] = matrix[1] + matrix[2]*y, matrix[1]*x + matrix[2]
matrix[4], matrix[5] = matrix[4] + matrix[5]*y, matrix[4]*x + matrix[5]
lgshear(x, y)
end

local function translate(x, y)
matrix[3] = matrix[3] + matrix[1]*x + matrix[2]*y
matrix[6] = matrix[6] + matrix[4]*x + matrix[5]*y
lgtranslate(x, y)
end

local function xform(matrix, x, y)
return matrix[1]*x + matrix[2]*y + matrix[3], matrix[4]*x + matrix[5]*y + matrix[6]
end

local function xformBack(matrix, x, y)
x, y = x - matrix[3], y - matrix[6]
local det = matrix[1] * matrix[5] - matrix[2] * matrix[4]
if det ~= 0 then
return (matrix[5] * x - matrix[2] * y) / det,
(matrix[1] * y - matrix[4] * x) / det
end
-- The transform is 1D or 0D
return x, y
end

return {getMatrix=getMatrix, xform = xform, xformBack = xformBack, origin=origin,
scale=scale, rotate=rotate, shear=shear, translate=translate}

Inverting the matrix is left as an exercise to the reader

Removed the unnecessary generic matrix calculations from the above, leaving only the strictly necessary part, and used a 2D matrix to add the backward transform, now called xformBack.

Example:

Code: Select all

local xform = require('xform')
local matrix

function love.draw()
xform.origin()
love.graphics.setColor(255,255,255)
xform.translate(400,300)
xform.rotate(0.3)
xform.scale(0.7, 1.1)
xform.translate(42, 86)
xform.rotate(0.5)
xform.shear(1.7, 1.3)
matrix = xform.getMatrix()
love.graphics.rectangle("fill", 5, 9, 53, 31)

xform.origin()
love.graphics.setColor(255,0,0)
local x, y = xform.xform(matrix, 5, 9)
love.graphics.rectangle("fill", x-1, y-1, 3, 3)
x, y = xform.xform(matrix, 5+52, 9)
love.graphics.rectangle("fill", x-1, y-1, 3, 3)
x, y = xform.xform(matrix, 5, 9+30)
love.graphics.rectangle("fill", x-1, y-1, 3, 3)
x, y = xform.xform(matrix, 5+52, 9+30)
love.graphics.rectangle("fill", x-1, y-1, 3, 3)

x, y = xform.xformBack(matrix, xform.xform(matrix, 5, 3))
love.graphics.print(string.format("%.17g\t%.17g\t%s", x, y, "<- should be 5, 3"))
end

Remember to always call xform.origin() at the beginning of love.draw() to reset the matrix, because the default love.run calls love.graphics.origin() internally right before calling love.draw().

Edit: Modified so you can also do this hack if you want:

Code: Select all

local xform = require 'xform'

do
local lg = love.graphics
lg.translate = xform.translate
lg.rotate = xform.rotate
lg.scale = xform.scale
lg.shear = xform.shear
lg.origin = xform.origin
end

so that your program can access any transformation function transparently, and you don't need to call xform.origin() manually at the start.

Edit2: Simplified and added backwards transform.
Last edited by pgimeno on Mon Oct 17, 2016 11:41 pm, edited 1 time in total.
Thrust II Reloaded - GifLoad for Löve - GSpöt GUI - My NotABug.org repositories - portland (mobile orientation)
The MS-Github repositories I had have been closed after the acquisition announcement and will be removed in the near future.

### Who is online

Users browsing this forum: No registered users and 8 guests