How to get translated/rotated coordinates

I’ve written something like this:

function Example:draw()
   pushMatrix()
        translate(self.x, self.y )
        rotate( self.angle ) 
        
        for i = 0, self.width do
            for a = 0, self.height do                
                local bx = i*self.bSize+16
                local by = a*self.bSize+16
                batch:sprite(self.name, bx, by)
			end
        end
    popMatrix()
end

Is there an easy way to get the coordinates (from bx, by) after the rotation?

Not completely clear what you are asking, but it sounds like seperate from drawing you want to know the actual screen coordinates of bx,by, rather than at the moment you have translated and rotated the coordinate space and then drawn them locally to that…

It could be something like:

myVec2 = vec2(bx,by)
myVec2 = myVec2:rotate( self.angle )
myVec2 = myVec2 + vec2(self.x, self.y)

It would be nice if there was a way to return the current angle and translation (and maybe there is, but I’ve never spotted it). As it stands, I find myself frequently pushing and popping the matrix to ensure that I know what my starting angle is before doing another rotation.

@spacemonkey thank you, that is exactly what I was asking for :slight_smile:

.@Mark You can get the current transformation matrix. local m = modelMatrix() returns that (though you might also want to get the viewMatrix() and projectionMatrix() if you truly want to get the screen coordinates). From that you can read off the translation vector and the general transformation, but it won’t necessarily be a simple rotation matrix.

If you know that all you’ve done are 2D rotations, then you could work out what the rotation angle is from the matrix by using inverse tangent of the first two values.

Thanks, Andrew, for giving me one of those head-slapping “oh boy, I’m an idiot because I knew that was there” moments.

In this case, I’m just tossing around all the little 2D actors in “Bull Puckey,” all of whom are potentially spinning, shrinking/growing, and moving around. I have to think that it’s less expensive to work from the existing rotation / translation rather than resetting the matrix between each draw. At the moment, I don’t seem to be performance bound, but as I work toward some puzzles with more elements, I don’t want to get in a position where I have to simplify the layout just to keep framecount in reason.

On the other hand, I would guess that working out the rotation from the existing matrix is more expensive than resetting it.

An alternative would be to wrap the rotate function in something that implemented its own save stack to keep track of the explicit rotation in force. But even then, I’d judge resetMatrix() to be pretty darned fast.

I’m use pushMatrix, translate and rotate draw popMatrix in my 2000 squares dropping thing, and that got poor performance, partly due to physics, but definitely to do with push/pop and drawing…

I did some workaround of putting stationary objects into a sprite which fixes it, but it does 50-100 happily, but get’s slow quick after that.

Maybe this needs some proper testing …

My guess would be that the quickest would be simply to do a resetMatrix() between each object being drawn.

Let’s assume that:

stuff_to_draw = { -- big table of {angle,vector,object}
}

Then we can imagine various ways to implement this. My guess is that the following is fastest:

for k,v in ipairs(stuff_to_draw) do
    resetMatrix()
    rotate(v[1])
    translate(v[2])
    v[3]:draw()
end

If the outer transformation is not the identity, then we can do:

local m = modelMatrix()
for k,v in ipairs(stuff_to_draw) do
    modelMatrix(m)
    rotate(v[1])
    translate(v[2])
    v[3]:draw()
end

I think this would be faster than:

for k,v in ipairs(stuff_to_draw) do
    pushMatrix()
    rotate(v[1])
    translate(v[2])
    v[3]:draw()
   popMatrix()
end

because it doesn’t have to mess with the stack. Both ought to be faster than:

local ang,vect
for k,v in ipairs(stuff_to_draw) do
    ang,vect = relativeTransformation(v[1],v[2])
    rotate(ang)
    translate(vect)
    v[3]:draw()
end

where relativeTranformation is some function that “corrects” the object’s angle and vector against the current transformation matrix.

Dont know if I understand correctly,mbut I sometimes use these function to get the current translate, rotate and scale values:

function pos()
    local m = modelMatrix()
    return m[13], m[14]
end

function rot()
    local m = modelMatrix()
    return math.atan2(m[2],m[1])
end

function scl()
    local m = modelMatrix()
    return math.sqrt(m[1]*m[1]+m[2]*m[2]+m[3]*m[3])
end

.@tnlogy If all you are doing are 2D transformations (and your scales are homogeneous in that you only ever call scale(<number> ) and never scale(<number 1>,<number 2> )) then your scl function could be simplified to just return m[11]/m[16].

If you aren’t keeping to those rules then you can’t condense the model matrix to a single rotation, scale, and translation.

Thanks, nice to know. :slight_smile:

Is there any case when calling:

local m = modelMatrix()
print(m[13], m[14])

,while many transformation has been performed, would still print “0,0”?

I’m getting confused, as I can’t seem to make this simple function work…

@rodolphe m[13],14,15 contain the translation coordinates x,y,z.
So, if you have no translation in x and y, then they both equal 0

yes, ahah, I was calling it after pushMatrix()… :slight_smile: thanks!