Hello,
I have dig a little bit in matrix for screen coordinates manipulation with modelMatrix() and I am sure one may be interresting of understanding how this is working…
First of all the matrix return by modelMatrix() is a 4 x 4 matrix { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 }
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
representing the transformation made by call to translate() , scale() or rotate() …
Sx Xy Xz 0
Yx Sy Yz 0
Zx Zy Sz 0
Tx Ty Tz 1
or
Xx Xy Xz 0
Yx Yy Yz 0
Zx Zy Zz 0
Tx Ty Tz 1
where Sx, Sy, Sz are the scale applied to each axes (x,y,z)
and Tx Ty Tz are the scale applied to each axes (x,y,z)
For rotation, it is a bit more complex, the matrix indicate the portion of each X,Y,Z to apply to each axes (x,y,z).
You will note that Sx=Xx , Sy=Yy and Sz=Zz this mean that rotation and scale are sharing the same value, so if you have both a scale and a rotation, you can not separate them looking at the matrix.
So the simple translation matrix is a multiplication (*) by this matrix:
0 0 0 0
0 0 0 0
0 0 1 0
Tx Ty Tz 1
The simple scaling matrix is a multiplication by this one:
0 0 0 0
0 0 0 0
0 0 1 0
Tx Ty Tz 1
And the rotation part is done using multiplication by the rotation matrix, for a rotation on z of angle r :
cos r - sin r 0 0
sin r cos r 0 0
0 0 1 0
0 0 0 1
For an easy use, codea as some quick multiplication by each of those using :
m=m:translate(Tx,Ty,Tz)
m=m:scale(Sx,Sy,Sz)
m=m:rotate(r) (for a rotation on axe z, case for a 2D transformation for example)
To convert a World Wx,Wy,Wz coordinate to Screen coordinate X,Y,Z you just need to multiply the matrix returned by modelMatrix() by the 4 dimentions vector (Wx,Wy,Wz,0)
The formula is :
X=WxSx + WyYx + WzZx + Tx
Y=WxXy + WySy + WzZy + Ty
Z=WxXz + WyYz + Wz*Sz + Tz
It works in 2D, but you just have more 0 in the matrix !
The beauty of Matrix is that you just have to multiply then to merge transformation.
The inverse of a Matrix will do a reverse transformation (only if determinant is non null)
If you want to play a little with it in 2D, here is a sample program :
– matrix
-- Use this function to perform your initial setup
function setup()
iparameter("tx",0,100) -- transpose X
iparameter("ty",0,100) -- transpose Y
parameter("sx",0,2,1) -- scale X
parameter("sy",0,2,1) -- scale Y
iparameter("r",0,360) -- rotation around Z
iparameter("mode",0,1,0) -- When 0 show transformation automatic, when 1 show manual calculation
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
-- This sets the line thickness
strokeWidth(5)
-- Do your drawing here
tm=matrix()
tm=tm:translate(tx,ty)
tm=tm:scale(sx,sy)
tm=tm:rotate(r)
if mode==0 then
translate(tx,ty)
scale(sx,sy)
rotate(r)
stroke(255, 221, 0, 255)
line(250,200,400,450)
else
stroke(91, 28, 241, 255)
a=toscreen(tm,vec2(250,200))
b=toscreen(tm,vec2(400,450))
line(a.x,a.y,b.x,b.y)
end
m=modelMatrix()
resetMatrix()
resetStyle()
for i = 1,16 do
text(i.."="..m[i],100,40*i)
text(i.."="..tm[i],200,40*i)
end
end
function toscreen(mat,ve)
x=mat[1]*ve.x+mat[5]*ve.y+mat[13]
y=mat[2]*ve.x+mat[6]*ve.y+mat[14]
return vec2(x,y)
end