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
Before you make a thread asking for help, read this.
User avatar
AnRu
Citizen
Posts: 69
Joined: Sun Oct 27, 2013 1:33 pm
Contact:

Re: Is there a way to get current transformation?

Post 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! :)
User avatar
pgimeno
Party member
Posts: 3550
Joined: Sun Oct 18, 2015 2:58 pm

Re: Is there a way to get current transformation?

Post 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)
User avatar
slime
Solid Snayke
Posts: 3132
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: Is there a way to get current transformation?

Post 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.
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 200 guests