Page 2 of 2

Re: Is there a way to get current transformation?

Posted: Wed Aug 10, 2016 3:06 pm
by AnRu
pgimeno wrote: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

local matrix = {1,0,0,0,
                0,1,0,0,
                0,0,1,0,
                0,0,0,1}

local function getMatrix(t)
  if t == nil then
    -- Return a copy
    return {matrix[ 1], matrix[ 2], matrix[ 3], matrix[ 4],
            matrix[ 5], matrix[ 6], matrix[ 7], matrix[ 8],
            matrix[ 9], matrix[10], matrix[11], matrix[12],
            matrix[13], matrix[14], matrix[15], matrix[16]}
  end
  -- Assign the elements (enables reusing tables)
  for i = 1, 16 do t[i] = matrix[i] end
  return t
end

local function origin()
  matrix[1] = 1  matrix[2] = 0  matrix[3] = 0  matrix[4] = 0
  matrix[5] = 0  matrix[6] = 1  matrix[7] = 0  matrix[8] = 0
  matrix[9] = 0  matrix[10]= 0  matrix[11]= 1  matrix[12]= 0
  matrix[13]= 0  matrix[14]= 0  matrix[15]= 0  matrix[16]= 1
  lgorigin()
end

local function scale(x, y)
  matrix[ 1] = matrix[ 1] * x  matrix[ 2] = matrix[ 2] * y
  matrix[ 5] = matrix[ 5] * x  matrix[ 6] = matrix[ 6] * y
  matrix[ 9] = matrix[ 9] * x  matrix[10] = matrix[10] * y
  matrix[13] = matrix[13] * x  matrix[14] = matrix[14] * 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[ 5], matrix[ 6] = matrix[ 5]*c + matrix[ 6]*s, matrix[ 5]*-s + matrix[ 6]*c
  matrix[ 9], matrix[10] = matrix[ 9]*c + matrix[10]*s, matrix[ 9]*-s + matrix[10]*c
  matrix[13], matrix[14] = matrix[13]*c + matrix[14]*s, matrix[13]*-s + matrix[14]*c
  lgrotate(a)
end

local function shear(x, y)
  matrix[ 1], matrix[ 2] = matrix[ 1] + matrix[ 2]*y, matrix[ 1]*x + matrix[ 2]
  matrix[ 5], matrix[ 6] = matrix[ 5] + matrix[ 6]*y, matrix[ 5]*x + matrix[ 6]
  matrix[ 9], matrix[10] = matrix[ 9] + matrix[10]*x, matrix[ 9]*y + matrix[10]
  matrix[13], matrix[14] = matrix[13] + matrix[14]*x, matrix[13]*y + matrix[14]
  lgshear(x, y)
end

local function translate(x, y)
  matrix[4] = matrix[4] + matrix[1]*x + matrix[2]*y
  matrix[8] = matrix[8] + matrix[5]*x + matrix[6]*y
  matrix[12] = matrix[12] + matrix[9]*x + matrix[10]*y
  matrix[16] = matrix[16] + matrix[11]*x + matrix[12]*y
  lgtranslate(x, y)
end

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

return {getMatrix=getMatrix, xform = xform, origin=origin,
        scale=scale, rotate=rotate, shear=shear, translate=translate}
Inverting the matrix is left as an exercise to the reader ;)

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)
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.
Oh, great thanks! :)

Re: Is there a way to get current transformation?

Posted: Mon Oct 17, 2016 11:46 pm
by pgimeno
I've updated my previous post on the LÖVE transformation tracker, to simplify the matrix and eliminate calculations that are unnecessary for 2D, and to include a backward transformation.

However, for those interested in a patch for LÖVE to get the current transformation matrix, here's a link: https://bitbucket.org/pgimeno/love/comm ... at=default

(the developers have anticipated that it's not likely to be included in any upcoming version, see this thread: https://bitbucket.org/rude/love/pull-re ... ction/diff)

Re: Is there a way to get current transformation?

Posted: Tue Oct 18, 2016 12:08 am
by slime
pgimeno wrote:
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.
You can choose to use a custom transformation matrix in a vertex shader, if you want.