# Matrix in mojo2

#### Wingnut

##### Well-known member
3rd Party Module Dev
Tutorial Author
I have problems understanding matrix handling in Cerberus. I've tried to read the documentation for a few weeks and painstainkinlgy converted the mojo1 example. It's behaving very strange. Any help would be much appreciated!

This is the mojo1 example:
Code:
``````Import mojo

Function Main()
New TransformMapApp
End

Class TransformMapApp Extends App

Field mx#,my#
Field tmx#,tmy#
Field omx#,omy#
Field mapMatrix#[]

Method OnCreate()
' Vertical blanking
SetSwapInterval 1 ; SetUpdateRate 0
PushMatrix
Scale DeviceWidth()/400.0, DeviceHeight()/300.0
mapMatrix = GetMatrix()
PopMatrix
End

Method OnUpdate()
Local coords#[]
mx = MouseX() ; my = MouseY()
PushMatrix
Translate mx,my
Rotate (KeyDown(KEY_LEFT)-KeyDown(KEY_RIGHT))*1.5
Local s# = 1+(KeyDown(KEY_UP) - KeyDown(KEY_DOWN))*.01
Scale s,s
Translate -mx,-my
Transform mapMatrix[0],mapMatrix[1],mapMatrix[2],mapMatrix[3],mapMatrix[4],mapMatrix[5]
coords = InvTransform([mx,my])
tmx = coords[0] ; tmy = coords[1]
If TouchDown(0) Then Translate tmx-omx, tmy-omy
mapMatrix = GetMatrix()
coords = InvTransform([mx,my])
omx = coords[0] ; omy = coords[1]
PopMatrix
End

Method OnRender()
Cls
PushMatrix
Transform mapMatrix[0],mapMatrix[1],mapMatrix[2],mapMatrix[3],mapMatrix[4],mapMatrix[5]
drawMap
DrawText Int(omx)+","+Int(omy),omx,omy-TextHeight()
Local bits#[] = InvTransform([mx,my])
DrawText Int(bits[0])+","+Int(bits[1]),omx,omy-TextHeight()*2
PopMatrix
End

Method drawMap()
For Local x=0 To 400 Step 100
DrawLine x,0,x,300
Next
For Local y=0 To 300 Step 100
DrawLine 0,y,400,y
Next
For Local x=50 To 400 Step 100
For Local y=50 To 300 Step 100
DrawCircle x,y,2
DrawText x+","+y,x+2,y+2
Next
Next
End
End``````

this is mojo2 version that I tried to create, the zoom seem to be stronger at the start and it behaves not the same for some reason
some commands have a very different syntax in mojo2 and this makes me very uncertain what is actually wrong, I tried to find every mojo2 command that does the same as the mojo1.

Everything seems to work fine except the coordinates seem to be x2 zoom, I don't knoe how to put it.
Have a look here what I've got so far:
Code:
``````Import mojo2

Function Main()
New TransformMapApp
End

Class TransformMapApp Extends App

Field canvas:Canvas
Field mx#,my#
Field tmx#,tmy#
Field omx#,omy#
Field mapMatrix#[]
Field gesturing:Bool

Method OnCreate()
canvas = New Canvas()
SetUpdateRate 0
canvas.PushMatrix
canvas.Scale DeviceWidth()/400.0, DeviceHeight()/300.0
canvas.GetMatrix(mapMatrix)
canvas.PopMatrix
End

Method OnUpdate()
Local coords#[]
Local coordsin#[]
mx = TouchX(0) ; my = TouchY(0)
canvas.PushMatrix

canvas.Translate mx,my
canvas.Rotate (KeyDown(KEY_LEFT)-KeyDown(KEY_RIGHT))*1.5
Local s# = 1+(KeyDown(KEY_UP) - KeyDown(KEY_DOWN))*.01
canvas.Scale s,s
canvas.Translate -mx,-my
canvas.Transform mapMatrix[0],mapMatrix[1],mapMatrix[2],mapMatrix[3],mapMatrix[4],mapMatrix[5]

'         coords = InvTransform([mx,my])            ' MOJO1
coordsin[0] = mx ; coordsin[1] = my         ' MOJO2
canvas.TransformCoords(coordsin,coords)  ' MOJO2

tmx = coords[0] ; tmy = coords[1]
If TouchDown(0) Then canvas.Translate tmx-omx, tmy-omy
canvas.GetMatrix(mapMatrix)

'         coords = InvTransform([mx,my])             ' MOJO1
coordsin[0] = mx ; coordsin[1] = my        ' MOJO2
canvas.TransformCoords(coordsin,coords)  ' MOJO2

omx = coords[0] ; omy = coords[1]
canvas.PopMatrix
End

Method OnRender()
canvas.Clear
canvas.PushMatrix
canvas.Transform mapMatrix[0],mapMatrix[1],mapMatrix[2],mapMatrix[3],mapMatrix[4],mapMatrix[5]
drawMap
canvas.DrawText Int(omx)+","+Int(omy),omx,omy-16

Local bitsin#[]
Local bits#[]
'       bits = InvTransform([mx,my])          ' MOJO1
bitsin[0] = mx ; bitsin[1] = my        ' MOJO2
canvas.TransformCoords(bitsin,bits)  ' MOJO2
canvas.DrawText Int(bits[0])+","+Int(bits[1]),omx,omy-16

canvas.PopMatrix
canvas.Flush
End

Method drawMap()
For Local x=0 To 400 Step 100
canvas.DrawLine x,0,x,300
Next
For Local y=0 To 300 Step 100
canvas.DrawLine 0,y,400,y
Next
For Local x=50 To 400 Step 100
For Local y=50 To 300 Step 100
canvas.DrawCircle x,y,2
canvas.DrawText x+","+y,x+2,y+2
Next
Next
End
End``````

Last edited:
Ya I hear ya. Matrix stuff is over my head as well. Not sure but my 2D in 3D tutorial might help.

Also maybe looking at the Vortex2 source code. Or any OpenGL tutorial about matrixes?

Thanks for the idea! This is what I've got now.
Not a perfect replica but most functions are there except the possibility to move using mouse instead of keys and a fixed originpoint set to 100,100.

Code:
``````Import mojo2
#MOJO_AUTO_SUSPEND_ENABLED=False

Function Main()
New MyApp
End Function

Class MyApp Extends App

Field myMatrix : Matrix
Field myPoint : Point
Field myRect : Rectangle
Field origin : Point
Field canvas : Canvas

Method OnCreate()
canvas = New Canvas

SetSwapInterval 1 ; SetUpdateRate 0
myMatrix = New Matrix()
myPoint = New Point()
myRect = New Rectangle(-100,-100,200,200)
origin = New Point(DeviceWidth() / 2.0,DeviceHeight() / 2.0)
End Method

Method OnUpdate()
canvas.Clear 0,0,0

' Translate matrix
If KeyDown(KEY_UP) Then myMatrix.translateBy(0,-1)
If KeyDown(KEY_DOWN) THen myMatrix.translateBy(0,1)
If KeyDown(KEY_LEFT) Then myMatrix.translateBy(-1,0)
If KeyDown(KEY_RIGHT) Then myMatrix.translateBy(1,0)

' Scale matrix
If KeyDown(KEY_N) Then myMatrix.scaleBy(1.01,1.01)
If KeyDown(KEY_M) Then myMatrix.scaleBy(0.99,0.99)

' Rotate matrix
If KeyDown(KEY_Z) Then myMatrix.rotateBy(-1)
If KeyDown(KEY_X) Then myMatrix.rotateBy(1)

End Method

Method OnRender()
canvas.Clear 0,0,0
canvas.PushMatrix
origin.mX = 100 ; origin.mY = 100

canvas.Translate origin.mX,origin.mY
canvas.Transform myMatrix.mA,myMatrix.mB,myMatrix.mC,myMatrix.mD,myMatrix.mTx,myMatrix.mTy
canvas.Translate  -origin.mX,-origin.mY

canvas.DrawRect origin.mX + myRect.mX,origin.mY + myRect.mY,myRect.mWidth,myRect.mHeight

canvas.SetColor 1,1,1
drawMap()

canvas.PopMatrix

myPoint.mX = TouchX() - origin.mX
myPoint.mY = TouchY() - origin.mY

' Inverse matrix
Local invMatrix : Matrix = myMatrix.clone()
invMatrix.invert()

' Transforms point
Local testPoint : Point = invMatrix.transformPoint(myPoint) ' Make the point into the transformed world

' Simple rectangle check as the point has been transformed
If myRect.containsPoint(testPoint) Then canvas.SetColor 1,0,0 Else canvas.SetColor 1,1,1

canvas.DrawText "100,100 is current the set origin marked with a dot above. Scroll using cursor",0,400
canvas.DrawText "scale using n & m         rotate using z & x",0,420
canvas.DrawText "Square sprite collision will be shown in red",0,440
canvas.DrawRect origin.mX,origin.mY,1,1
canvas.DrawText String(origin.mX+Int(testPoint.mX)), 20,10
canvas.DrawText String(origin.mY+Int(testPoint.mY)), 180,10

canvas.Flush
End Method

Method drawMap()
For Local x=0 To 400 Step 100
canvas.DrawLine x,0,x,300
Next
For Local y=0 To 300 Step 100
canvas.DrawLine 0,y,400,y
Next
For Local x=50 To 400 Step 100
For Local y=50 To 300 Step 100
canvas.DrawCircle x,y,2
canvas.DrawText x+","+y,x+2,y+2
Next
Next
End

End Class

Class Point

Field mX : Float
Field mY : Float

Method New(x : Float,y : Float)
Self.mX = x
Self.mY = y
End Method

End Class

Class Rectangle

Field mX : Float
Field mY : Float
Field mWidth : Float
Field mHeight : Float

Method New()
Self.mX = 0
Self.mY = 0
Self.mWidth = 0
Self.mHeight = 0
End Method

Method New(x : Float,y : Float,width : Float,height : Float)
Self.mX = x
Self.mY = y
Self.mWidth = width
Self.mHeight = height
End Method

Method containsXY : Bool(x : Float,y : Float)
Return (x >= mX) And (y >= mY) And (x <= mX + mWidth) And (y <= mY + mHeight)
End Method

Method containsPoint : Bool(point : Point)
Return Self.containsXY(point.mX,point.mY)
End Method

End Class

Class Matrix

Field mA : Float
Field mB : Float
Field mC : Float
Field mD : Float
Field mTx : Float
Field mTy : Float

Method New()
Self.mA = 1.0
Self.mB = 0.0
Self.mC = 0.0
Self.mD = 1.0
Self.mTx = 0.0
Self.mTy = 0.0
End Method

Method New(a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
Self.mA = a
Self.mB = b
Self.mC = c
Self.mD = d
Self.mTx = tx
Self.mTy = ty
End Method

Function setValues(matrix : Matrix,a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
matrix.mA = a
matrix.mB = b
matrix.mC = c
matrix.mD = d
matrix.mTx = tx
matrix.mTy = ty
End Function

Method clone : Matrix()
Return New Matrix(Self.mA,Self.mB,Self.mC,Self.mD,Self.mTx,Self.mTy)
End Method

Method setValues(a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
Self.mA = a
Self.mB = b
Self.mC = c
Self.mD = d
Self.mTx = tx
Self.mTy = ty
End Method

Method concatMatrix : Void(matrix : Matrix)
Local a : Float = matrix.mA * Self.mA  + matrix.mC * Self.mB
Local b : Float = matrix.mB * Self.mA  + matrix.mD * Self.mB
Local c : Float = matrix.mA * Self.mC  + matrix.mC * Self.mD
Local d : Float = matrix.mB * Self.mC  + matrix.mD * Self.mD
Local tx : Float = matrix.mA * Self.mTx + matrix.mC * Self.mTy + matrix.mTx
Local ty : Float = matrix.mB * Self.mTx + matrix.mD * Self.mTy + matrix.mTy
Self.setValues(a,b,c,d,tx,ty)
End Method
'
Method determinant : Float()
Return (Self.mA * Self.mD) - (Self.mC * Self.mB)
End Method

Method translateBy : Void(dx : Float,dy : Float)
Self.mTx = Self.mTx + dx
Self.mTy = Self.mTy + dy
End Method

Method scaleBy : Void(sx : Float,sy : Float)
Self.mA = Self.mA * sx
Self.mB = Self.mB * sy
Self.mC = Self.mC * sx
Self.mD = Self.mD * sy
Self.mTx = Self.mTx * sx
Self.mTy = Self.mTy * sy
End Method

Method scaleBy : Void(scale : Float)
Self.scaleBy(scale,scale)
End Method

Method rotateBy : Void(angle : Float)
Local rotMatrix : Matrix = New Matrix(Cos(angle),Sin(angle),-Sin(angle),Cos(angle),0,0)
Self.concatMatrix(rotMatrix)
End Method

Method identity : Void()
Self.setValues(1.0,0.0,0.0,1.0,0.0,0.0)
End Method

Method invert : Void()
Local det : Float = Self.determinant()
Local a : Float = Self.mD / det
Local b : Float = -Self.mB / det
Local c : Float = -Self.mC / det
Local d : Float = Self.mA / det
Local tx : Float = ((Self.mC * Self.mTy) - (Self.mD * Self.mTx)) / det
Local ty : Float = ((Self.mB * Self.mTx) - (Self.mA * Self.mTy)) / det
Self.setValues(a,b,c,d,tx,ty)
End Method

Method transformPoint : Point(point : Point)
Local x : Float = (Self.mA * point.mX) + (Self.mC * point.mY) + Self.mTx
Local y : Float = (Self.mB * point.mX) + (Self.mD * point.mY) + Self.mTy
Return New Point(x,y)
End Method

End Class``````

Slimmed it down abit and starts to look good but what is still missing is to be able to use the mouse to move it around instead of cursorkeys, and to have the mousepointer to double as the originpoint.

Code:
``````Import mojo2
#MOJO_AUTO_SUSPEND_ENABLED=False

Function Main()
New MyApp
End Function

Class MyApp Extends App

Field myMatrix : Matrix
Field myPoint : Point
Field origin : Point
Field canvas : Canvas

Method OnCreate()
canvas = New Canvas
SetSwapInterval 1 ; SetUpdateRate 0
myMatrix = New Matrix()
myPoint = New Point()
origin = New Point(DeviceWidth() / 2.0,DeviceHeight() / 2.0)
End Method

Method OnUpdate()

' Translate matrix
If KeyDown(KEY_UP) Then myMatrix.translateBy(0,-1)
If KeyDown(KEY_DOWN) THen myMatrix.translateBy(0,1)
If KeyDown(KEY_LEFT) Then myMatrix.translateBy(-1,0)
If KeyDown(KEY_RIGHT) Then myMatrix.translateBy(1,0)

' Scale matrix
If KeyDown(KEY_N) Then myMatrix.scaleBy(1.01,1.01)
If KeyDown(KEY_M) Then myMatrix.scaleBy(0.99,0.99)

' Rotate matrix
If KeyDown(KEY_Z) Then myMatrix.rotateBy(-1)
If KeyDown(KEY_X) Then myMatrix.rotateBy(1)

End Method

Method OnRender()
canvas.Clear 0,0,1
canvas.PushMatrix
'  origin.mX = 100 ; origin.mY = 100
canvas.Translate origin.mX,origin.mY
canvas.Transform myMatrix.mA,myMatrix.mB,myMatrix.mC,myMatrix.mD,myMatrix.mTx,myMatrix.mTy
canvas.Translate -origin.mX,-origin.mY

drawMap()
canvas.PopMatrix

myPoint.mX = TouchX() - origin.mX
myPoint.mY = TouchY() - origin.mY

' Inverse matrix
Local invMatrix : Matrix = myMatrix.clone()
invMatrix.invert()

' Make the point into the transformed world
Local testPoint : Point = invMatrix.transformPoint(myPoint)
canvas.DrawRect origin.mX,origin.mY,1,1
canvas.DrawText String(origin.mX+Int(testPoint.mX)), 20,10
canvas.DrawText String(origin.mY+Int(testPoint.mY)), 180,10

canvas.Flush
End Method

Method drawMap()
For Local x=0 To 400 Step 100
canvas.DrawLine x,0,x,300
Next
For Local y=0 To 300 Step 100
canvas.DrawLine 0,y,400,y
Next
For Local x=50 To 400 Step 100
For Local y=50 To 300 Step 100
canvas.DrawCircle x,y,2
canvas.DrawText x+","+y,x+2,y+2
Next
Next
End

End Class

Class Point

Field mX : Float, mY : Float

Method New(x : Float,y : Float)
mX = x
mY = y
End Method

End Class

Class Matrix

Field mA : Float, mB : Float, mC : Float, mD : Float, mTx : Float, mTy : Float

Method New()
mA = 1.0
mB = 0.0
mC = 0.0
mD = 1.0
mTx = 0.0
mTy = 0.0
End Method

Method New(a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
mA = a
mB = b
mC = c
mD = d
mTx = tx
mTy = ty
End Method

Function setValues(matrix : Matrix,a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
matrix.mA = a
matrix.mB = b
matrix.mC = c
matrix.mD = d
matrix.mTx = tx
matrix.mTy = ty
End Function

Method clone : Matrix()
Return New Matrix(mA,mB,mC,mD,mTx,mTy)
End Method

Method setValues(a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
mA = a
mB = b
mC = c
mD = d
mTx = tx
mTy = ty
End Method

Method concatMatrix : Void(matrix : Matrix)
Local a : Float = matrix.mA * mA  + matrix.mC * mB
Local b : Float = matrix.mB * mA  + matrix.mD * mB
Local c : Float = matrix.mA * mC  + matrix.mC * mD
Local d : Float = matrix.mB * mC  + matrix.mD * mD
Local tx : Float = matrix.mA * mTx + matrix.mC * mTy + matrix.mTx
Local ty : Float = matrix.mB * mTx + matrix.mD * mTy + matrix.mTy
setValues(a,b,c,d,tx,ty)
End Method
'
Method determinant : Float()
Return (mA * mD) - (mC * mB)
End Method

Method translateBy : Void(dx : Float,dy : Float)
mTx = mTx + dx
mTy = mTy + dy
End Method

Method scaleBy : Void(sx : Float,sy : Float)
mA = mA * sx
mB = mB * sy
mC = mC * sx
mD = mD * sy
mTx = mTx * sx
mTy = mTy * sy
End Method

Method scaleBy : Void(scale : Float)
scaleBy(scale,scale)
End Method

Method rotateBy : Void(angle : Float)
Local rotMatrix : Matrix = New Matrix(Cos(angle),Sin(angle),-Sin(angle),Cos(angle),0,0)
concatMatrix(rotMatrix)
End Method

Method identity : Void()
setValues(1.0,0.0,0.0,1.0,0.0,0.0)
End Method

Method invert : Void()
Local det : Float = determinant()
Local a : Float = mD / det
Local b : Float = -mB / det
Local c : Float = -mC / det
Local d : Float = mA / det
Local tx : Float = ((mC * mTy) - (mD * mTx)) / det
Local ty : Float = ((mB * mTx) - (mA * mTy)) / det
setValues(a,b,c,d,tx,ty)
End Method

Method transformPoint : Point(point : Point)
Local x : Float = (mA * point.mX) + (mC * point.mY) + mTx
Local y : Float = (mB * point.mX) + (mD * point.mY) + mTy
Return New Point(x,y)
End Method

End Class``````

Not sure how to make mouse to the origin?

EDIT
Added the possiblity to read the current canvas matrix hardware command into the math version.

[
Code:
``````Import mojo2
#MOJO_AUTO_SUSPEND_ENABLED=Fals

Function Main()
New MyApp
End Function

Class MyApp Extends App

Field myMatrix : Matrix
Field myPoint : Point
Field origin : Point
Field canvas : Canvas
Field ox:Int
Field oy:Int
Field x:Int
Field y:Int
Field d:Int
Field mapMatrix:Float[6]

Method OnCreate()
canvas = New Canvas
SetSwapInterval 1 ; SetUpdateRate 0
myMatrix = New Matrix()
myPoint = New Point()
origin = New Point(DeviceWidth() / 2.0,DeviceHeight() / 2.0)

' canvas.Scale DeviceWidth()/400.0, DeviceHeight()/300.0

' To be used later (just reading the default initial canvas value for now)
' Read the current canvas hardware matrix into numbers
canvas.GetMatrix(mapMatrix)
myMatrix.mA = mapMatrix[0]
myMatrix.mB = mapMatrix[1]
myMatrix.mC = mapMatrix[2]
myMatrix.mD = mapMatrix[3]
myMatrix.mTx = mapMatrix[4]
myMatrix.mTy = mapMatrix[5]

End Method

Method OnUpdate()

ox = x ; oy = y
x = TouchX() ; y = TouchY()
d = TouchDown(0)

' Add mouse/touch drag
If d Then myMatrix.translateBy(x-ox,y-oy)

' Translate matrix
If KeyDown(KEY_UP) Then myMatrix.translateBy(0,-1)
If KeyDown(KEY_DOWN) THen myMatrix.translateBy(0,1)
If KeyDown(KEY_LEFT) Then myMatrix.translateBy(-1,0)
If KeyDown(KEY_RIGHT) Then myMatrix.translateBy(1,0)

' s matrix
If KeyDown(KEY_N) Then myMatrix.sBy(1.01)
If KeyDown(KEY_M) Then myMatrix.sBy(0.99)

' Rotate matrix
If KeyDown(KEY_Z) Then myMatrix.rotateBy(-1)
If KeyDown(KEY_X) Then myMatrix.rotateBy(1)

End Method

Method OnRender()

canvas.Clear 0,0,1

canvas.PushMatrix
' origin.mX = 100 ; origin.mY = 100

' MATH IS DONE!

' if right mousebutton then read current canvas matrix status and overwrite all math numbers before USIGN THEM IN ACTUAL MATRIXSETTINGS
' If MouseDown(1) Then canvas.GetMatrix(mapMatrix) ; myMatrix.mA = mapMatrix[0] ; myMatrix.mB = mapMatrix[1] ; myMatrix.mC = mapMatrix[2] ; myMatrix.mD = mapMatrix[3] ; myMatrix.mTx = mapMatrix[4] ; myMatrix.mTy = mapMatrix[5]
canvas.DrawText String(myMatrix.mA),0,0
canvas.DrawText String(myMatrix.mB),0,10
canvas.DrawText String(myMatrix.mC),0,20
canvas.DrawText String(myMatrix.mD),0,30
canvas.DrawText String(myMatrix.mTx),0,40
canvas.DrawText String(myMatrix.mTy),0,50

' Does not seem to work? It just says 1 0 0 1 0 0 when you move around the matrix?

' NOW SET HARDWARE AND PUT THE NUMBERS INTO ACTION
canvas.Translate origin.mX,origin.mY
' Multiply matrix
canvas.Transform myMatrix.mA,myMatrix.mB,myMatrix.mC,myMatrix.mD,myMatrix.mTx,myMatrix.mTy
canvas.Translate -origin.mX,-origin.mY

' Here you can read matrix
canvas.GetMatrix(mapMatrix)

drawMap()
canvas.PopMatrix
myPoint.mX = x - origin.mX
myPoint.mY = y - origin.mY

' Inverse matrix
Local invMatrix : Matrix = myMatrix.clone()
invMatrix.invert()

' Make the point into the transformed world
Local testPoint : Point = invMatrix.transformPoint(myPoint)
canvas.DrawRect origin.mX,origin.mY,1,1
canvas.DrawText String(origin.mX+Int(testPoint.mX)), 20,10
canvas.DrawText String(origin.mY+Int(testPoint.mY)), 180,10

'     canvas.DrawText String(mapMatrix[0]),0,0
' canvas.DrawText String(mapMatrix[1]),0,10
'    canvas.DrawText String(mapMatrix[2]),0,20
'    canvas.DrawText String(mapMatrix[3]),0,30
'    canvas.DrawText String(mapMatrix[4]),0,40
'    canvas.DrawText String(mapMatrix[5]),0,50

canvas.Flush
End Method

Method drawMap()
For Local x=0 To 400 Step 100
canvas.DrawLine x,0,x,300
Next
For Local y=0 To 300 Step 100
canvas.DrawLine 0,y,400,y
Next
For Local x=50 To 400 Step 100
For Local y=50 To 300 Step 100
canvas.DrawCircle x,y,2
canvas.DrawText x+","+y,x+2,y+2
Next
Next
End

End Class

Class Point

Field mX : Float, mY : Float

Method New(x : Float,y : Float)
mX = x ; mY = y
End Method

End Class

Class Matrix

Field mA : Float, mB : Float, mC : Float, mD : Float, mTx : Float, mTy : Float

Method New()
mA = 1.0 ; mB = 0.0 ; mC = 0.0 ; mD = 1.0 ; mTx = 0.0 ; mTy = 0.0
End Method

Method New(a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
mA = a ; mB = b ; mC = c ; mD = d ; mTx = tx ; mTy = ty
End Method

Function setValues(matrix : Matrix,a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
matrix.mA = a ; matrix.mB = b ; matrix.mC = c ; matrix.mD = d ; matrix.mTx = tx ; matrix.mTy = ty
End Function

Method clone : Matrix()
Return New Matrix(mA,mB,mC,mD,mTx,mTy)
End Method

Method setValues(a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
mA = a ; mB = b ; mC = c ; mD = d ; mTx = tx ; mTy = ty
End Method

Method concatMatrix : Void(matrix : Matrix)
Local a : Float = matrix.mA * mA  + matrix.mC * mB
Local b : Float = matrix.mB * mA  + matrix.mD * mB
Local c : Float = matrix.mA * mC  + matrix.mC * mD
Local d : Float = matrix.mB * mC  + matrix.mD * mD
Local tx : Float = matrix.mA * mTx + matrix.mC * mTy + matrix.mTx
Local ty : Float = matrix.mB * mTx + matrix.mD * mTy + matrix.mTy
setValues(a,b,c,d,tx,ty)
End Method

Method determinant : Float()
Return (mA * mD) - (mC * mB)
End Method

Method translateBy : Void(dx : Float,dy : Float)
mTx = mTx + dx ; mTy = mTy + dy
End Method

Method sBy : Void(s : Float)
mA = mA * s ; mB = mB * s ; mC = mC * s ; mD = mD * s ; mTx = mTx * s ;  mTy = mTy * s
End Method

Method rotateBy : Void(angle : Float)
Local rotMatrix : Matrix = New Matrix(Cos(angle),Sin(angle),-Sin(angle),Cos(angle),0,0)
concatMatrix(rotMatrix)
End Method

Method identity : Void()
setValues(1.0,0.0,0.0,1.0,0.0,0.0)
End Method

Method invert : Void()
Local det : Float = determinant()
Local a : Float = mD / det
Local b : Float = -mB / det
Local c : Float = -mC / det
Local d : Float = mA / det
Local tx : Float = ((mC * mTy) - (mD * mTx)) / det
Local ty : Float = ((mB * mTx) - (mA * mTy)) / det
setValues(a,b,c,d,tx,ty)
End Method

Method transformPoint : Point(point : Point)
Local x : Float = (mA * point.mX) + (mC * point.mY) + mTx
Local y : Float = (mB * point.mX) + (mD * point.mY) + mTy
Return New Point(x,y)
End Method

End Class``````

Last edited:
Digging deeper into matrix commands, now trying to read the current canvas matrix, which is done successfully.

Still need to come up with a practical way to set the origin using mouse, without messing about.

EDIT
Got the idea to use GetMatrix/SetMatrix as this let you do things like matrix multiply and then read the multiplied parameters back, this might be useful if concatMatrix is not enough.

Code:
``````Import mojo2
#MOJO_AUTO_SUSPEND_ENABLED=False

Function Main()
New MyApp
End Function

Class MyApp Extends App

Field myMatrix : Matrix
Field myPoint : Point
Field origin : Point
Field canvas : Canvas
Field ox:Int
Field oy:Int
Field x:Int
Field y:Int
Field d:Int
Field mapMatrix:Float[6]

Method OnCreate()
canvas = New Canvas
SetSwapInterval 1 ; SetUpdateRate 0
myMatrix = New Matrix()
myPoint = New Point()
origin = New Point(DeviceWidth() / 2.0,DeviceHeight() / 2.0)
' canvas.Scale DeviceWidth()/400.0, DeviceHeight()/300.0
' To be used later (just reading the default initial canvas value for now)
' Read the current canvas hardware matrix into numbers
canvas.GetMatrix(mapMatrix)
myMatrix.mA = mapMatrix[0]
myMatrix.mB = mapMatrix[1]
myMatrix.mC = mapMatrix[2]
myMatrix.mD = mapMatrix[3]
myMatrix.mTx = mapMatrix[4]
myMatrix.mTy = mapMatrix[5]
End Method

Method OnUpdate()
ox = x ; oy = y
x = TouchX() ; y = TouchY()
d = TouchDown(0)

' Translate matrix
If d Then myMatrix.translateBy(x-ox,y-oy)

' Scale matrix
If KeyDown(KEY_UP) Then myMatrix.sBy(1.01)
If KeyDown(KEY_DOWN) Then myMatrix.sBy(0.99)

' Rotate matrix
If KeyDown(KEY_LEFT) Then myMatrix.rotateBy(-1)
If KeyDown(KEY_RIGHT) Then myMatrix.rotateBy(1)
End Method

Method OnRender()
canvas.Clear
canvas.PushMatrix
' origin.mX = 100 ; origin.mY = 100
' MATH IS DONE! NOW SET HARDWARE AND PUT THE NUMBERS INTO ACTION!

canvas.Translate origin.mX,origin.mY
' Multiply matrix (might need to mathematically multiply instead for later inverse multiplication)
canvas.Transform myMatrix.mA,myMatrix.mB,myMatrix.mC,myMatrix.mD,myMatrix.mTx,myMatrix.mTy
canvas.Translate -origin.mX,-origin.mY
' ----------------------------------------------------------------------
' Here you can read the current matrix
canvas.GetMatrix(mapMatrix)

' Fails if you try (they are something you multiply, if you read here they become absolute)
' myMatrix.mA = mapMatrix[0] ; myMatrix.mB = mapMatrix[1] ; myMatrix.mC = mapMatrix[2] ; myMatrix.mD = mapMatrix[3] ; myMatrix.mTx = mapMatrix[4] ; myMatrix.mTy = mapMatrix[5]

' Set matrix
canvas.SetMatrix mapMatrix[0], mapMatrix[1], mapMatrix[2], mapMatrix[3], mapMatrix[4], mapMatrix[5]
' canvas.SetMatrix myMatrix.mA,myMatrix.mB,myMatrix.mC,myMatrix.mD, myMatrix.mTx,myMatrix.mTy
'
' Reset matrix so nothing can move
' canvas.SetMatrix 1, 0, 0, 1, 0, 0
' ----------------------------------------------------------------------
drawMap()
canvas.PopMatrix
myPoint.mX = x - origin.mX
myPoint.mY = y - origin.mY

' Inverse matrix
Local invMatrix : Matrix = myMatrix.clone()
invMatrix.invert()

' Make the point into the transformed world
Local testPoint : Point = invMatrix.transformPoint(myPoint)
canvas.DrawRect origin.mX,origin.mY,1,1
canvas.DrawText String(origin.mX+Int(testPoint.mX)), 420,0
canvas.DrawText String(origin.mY+Int(testPoint.mY)), 460,0

canvas.DrawText String(mapMatrix[0]),0,0
canvas.DrawText String(mapMatrix[1]),0,10
canvas.DrawText String(mapMatrix[2]),0,20
canvas.DrawText String(mapMatrix[3]),0,30
canvas.DrawText String(mapMatrix[4]),0,40
canvas.DrawText String(mapMatrix[5]),0,50

canvas.Flush
End Method

Method drawMap()
For Local x=0 To 400 Step 100
canvas.DrawLine x,0,x,300
Next
For Local y=0 To 300 Step 100
canvas.DrawLine 0,y,400,y
Next
For Local x=50 To 400 Step 100
For Local y=50 To 300 Step 100
canvas.DrawCircle x,y,2
canvas.DrawText x+","+y,x-27,y+8
Next
Next
End

End Class

Class Point

Field mX : Float, mY : Float

Method New(x : Float,y : Float)
mX = x ; mY = y
End Method

End Class

Class Matrix

Field mA : Float, mB : Float, mC : Float, mD : Float, mTx : Float, mTy : Float

Method New()
mA = 1.0 ; mB = 0.0 ; mC = 0.0 ; mD = 1.0 ; mTx = 0.0 ; mTy = 0.0
End Method

Method New(a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
mA = a ; mB = b ; mC = c ; mD = d ; mTx = tx ; mTy = ty
End Method

Function setValues(matrix : Matrix,a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
matrix.mA = a ; matrix.mB = b ; matrix.mC = c ; matrix.mD = d ; matrix.mTx = tx ; matrix.mTy = ty
End Function

Method clone : Matrix()
Return New Matrix(mA,mB,mC,mD,mTx,mTy)
End Method

Method setValues(a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
mA = a ; mB = b ; mC = c ; mD = d ; mTx = tx ; mTy = ty
End Method

Method concatMatrix : Void(matrix : Matrix)
Local a : Float = matrix.mA * mA  + matrix.mC * mB
Local b : Float = matrix.mB * mA  + matrix.mD * mB
Local c : Float = matrix.mA * mC  + matrix.mC * mD
Local d : Float = matrix.mB * mC  + matrix.mD * mD
Local tx : Float = matrix.mA * mTx + matrix.mC * mTy + matrix.mTx
Local ty : Float = matrix.mB * mTx + matrix.mD * mTy + matrix.mTy
setValues(a,b,c,d,tx,ty)
End Method

Method determinant : Float()
Return (mA * mD) - (mC * mB)
End Method

Method translateBy : Void(dx : Float,dy : Float)
mTx = mTx + dx ; mTy = mTy + dy
End Method

Method sBy : Void(s : Float)
mA = mA * s ; mB = mB * s ; mC = mC * s ; mD = mD * s ; mTx = mTx * s ;  mTy = mTy * s
End Method

Method rotateBy : Void(angle : Float)
Local rotMatrix : Matrix = New Matrix(Cos(angle),Sin(angle),-Sin(angle),Cos(angle),0,0)
concatMatrix(rotMatrix)
End Method

Method identity : Void()
setValues(1.0,0.0,0.0,1.0,0.0,0.0)
End Method

Method invert : Void()
Local det : Float = determinant()
Local a : Float = mD / det
Local b : Float = -mB / det
Local c : Float = -mC / det
Local d : Float = mA / det
Local tx : Float = ((mC * mTy) - (mD * mTx)) / det
Local ty : Float = ((mB * mTx) - (mA * mTy)) / det
setValues(a,b,c,d,tx,ty)
End Method

Method transformPoint : Point(point : Point)
Local x : Float = (mA * point.mX) + (mC * point.mY) + mTx
Local y : Float = (mB * point.mX) + (mD * point.mY) + mTy
Return New Point(x,y)
End Method

End Class``````

Last edited:
Checked the sourcecode for transform to define a multiply matrix operation, tested

Code:
``````        Method multiplyMatrix:Void(matrix:Matrix)
Local ix:Float = matrix.mA
Local iy:Float = matrix.mB
Local jx:Float = matrix.mC
Local jy:Float = matrix.mD
Local tx:Float = matrix.mTx
Local ty:Float = matrix.mTy
Local ix2:=ix*mA+iy*mC,iy2:=ix*mB+iy*mD
Local jx2:=jx*mA+jy*mC,jy2:=jx*mB+jy*mD
Local tx2:=tx*mA+ty*mC+mTx,ty2:=tx*mB+ty*mD+mTy
setValues ix2,iy2,jx2,jy2,tx2,ty2
End``````

Multiply tested using identity matrix etc
Code:
``````Import mojo2
#MOJO_AUTO_SUSPEND_ENABLED=False

Function Main()
New MyApp
End Function

Class MyApp Extends App

Field myMatrix : Matrix
Field myPoint : Point
Field origin : Point
Field canvas : Canvas
Field ox:Int
Field oy:Int
Field x:Int
Field y:Int
Field d:Int
Field mapMatrix:Float[6]

Method OnCreate()
canvas = New Canvas
SetSwapInterval 1 ; SetUpdateRate 0
myMatrix = New Matrix()
myPoint = New Point()
origin = New Point(DeviceWidth() / 2.0,DeviceHeight() / 2.0)
canvas.GetMatrix(mapMatrix)
myMatrix.mA = mapMatrix[0]
myMatrix.mB = mapMatrix[1]
myMatrix.mC = mapMatrix[2]
myMatrix.mD = mapMatrix[3]
myMatrix.mTx = mapMatrix[4]
myMatrix.mTy = mapMatrix[5]

Local myMatrix2 : Matrix = New Matrix()
myMatrix.multiplyMatrix(myMatrix2)

End Method

Method OnUpdate()
ox = x ; oy = y
x = TouchX() ; y = TouchY() ; d = TouchDown(0)
' Translate matrix
If d Then myMatrix.translateBy(x-ox,y-oy)
' scale matrix
If KeyDown(KEY_UP) Then myMatrix.scaleBy(1.01)
If KeyDown(KEY_DOWN) Then myMatrix.scaleBy(0.99)
' Rotate matrix
If KeyDown(KEY_LEFT) Then myMatrix.rotateBy(-1)
If KeyDown(KEY_RIGHT) Then myMatrix.rotateBy(1)
End Method

Method OnRender()
canvas.Clear
canvas.PushMatrix
' origin.mX = 100 ; origin.mY = 100
canvas.Translate origin.mX,origin.mY
' Multiply matrix (might need to mathematically multiply instead for later inverse multiplication)
canvas.Transform myMatrix.mA,myMatrix.mB,myMatrix.mC,myMatrix.mD,myMatrix.mTx,myMatrix.mTy
canvas.Translate -origin.mX,-origin.mY
' ----------------------------------------------------------------------
' Here you can read the current matrix
canvas.GetMatrix(mapMatrix)
'
' Fails if you try (they are something you multiply, if you read here they become absolute)
' myMatrix.mA = mapMatrix[0] ; myMatrix.mB = mapMatrix[1] ; myMatrix.mC = mapMatrix[2] ; myMatrix.mD = mapMatrix[3] ; myMatrix.mTx = mapMatrix[4] ; myMatrix.mTy = mapMatrix[5]
'
' Set matrix
canvas.SetMatrix mapMatrix[0], mapMatrix[1], mapMatrix[2], mapMatrix[3], mapMatrix[4], mapMatrix[5]
' canvas.SetMatrix myMatrix.mA,myMatrix.mB,myMatrix.mC,myMatrix.mD, myMatrix.mTx,myMatrix.mTy
'
' Reset matrix so nothing can move
' canvas.SetMatrix 1, 0, 0, 1, 0, 0

' Multiply using math, use identity matrix to proove nothing happens
Local testMatrix : Matrix = New Matrix(1,0,0,1,0,0)
myMatrix.multiplyMatrix(testMatrix)

' ----------------------------------------------------------------------
drawMap()
canvas.PopMatrix
myPoint.mX = x - origin.mX
myPoint.mY = y - origin.mY

' Inverse matrix
Local invMatrix : Matrix = myMatrix.clone()
invMatrix.invert()

' Make the point into the transformed world
Local testPoint : Point = invMatrix.transformPoint(myPoint)
canvas.DrawRect origin.mX,origin.mY,1,1
canvas.DrawText String(origin.mX+Int(testPoint.mX)), 420,0
canvas.DrawText String(origin.mY+Int(testPoint.mY)), 460,0

canvas.DrawText String(mapMatrix[0]),0,0
canvas.DrawText String(mapMatrix[1]),0,10
canvas.DrawText String(mapMatrix[2]),0,20
canvas.DrawText String(mapMatrix[3]),0,30
canvas.DrawText String(mapMatrix[4]),0,40
canvas.DrawText String(mapMatrix[5]),0,50

canvas.Flush
End Method

Method drawMap()
For Local x=0 To 400 Step 100
canvas.DrawLine x,0,x,300
Next
For Local y=0 To 300 Step 100
canvas.DrawLine 0,y,400,y ; Next
For Local x=50 To 400 Step 100
For Local y=50 To 300 Step 100
canvas.DrawCircle x,y,2 ; canvas.DrawText x+","+y,x-27,y+8
Next
Next
End

End Class

Class Point

Field mX : Float, mY : Float

Method New(x : Float,y : Float)
mX = x ; mY = y
End Method

End Class

Class Matrix

Field mA : Float, mB : Float, mC : Float, mD : Float, mTx : Float, mTy : Float

Method New()
mA = 1.0 ; mB = 0.0 ; mC = 0.0 ; mD = 1.0 ; mTx = 0.0 ; mTy = 0.0
End Method

Method New(a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
mA = a ; mB = b ; mC = c ; mD = d ; mTx = tx ; mTy = ty
End Method

Function setValues(matrix : Matrix,a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
matrix.mA = a ; matrix.mB = b ; matrix.mC = c ; matrix.mD = d ; matrix.mTx = tx ; matrix.mTy = ty
End Function

Method clone : Matrix()
Return New Matrix(mA,mB,mC,mD,mTx,mTy)
End Method

Method setValues(a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
mA = a ; mB = b ; mC = c ; mD = d ; mTx = tx ; mTy = ty
End Method

Method concatMatrix : Void(matrix : Matrix)
Local a : Float = matrix.mA * mA  + matrix.mC * mB
Local b : Float = matrix.mB * mA  + matrix.mD * mB
Local c : Float = matrix.mA * mC  + matrix.mC * mD
Local d : Float = matrix.mB * mC  + matrix.mD * mD
Local tx : Float = matrix.mA * mTx + matrix.mC * mTy + matrix.mTx
Local ty : Float = matrix.mB * mTx + matrix.mD * mTy + matrix.mTy
setValues(a,b,c,d,tx,ty)
End Method

Method multiplyMatrix:Void(matrix:Matrix)
Local ix:Float = matrix.mA
Local iy:Float = matrix.mB
Local jx:Float = matrix.mC
Local jy:Float = matrix.mD
Local tx:Float = matrix.mTx
Local ty:Float = matrix.mTy
Local ix2:=ix*mA+iy*mC,iy2:=ix*mB+iy*mD
Local jx2:=jx*mA+jy*mC,jy2:=jx*mB+jy*mD
Local tx2:=tx*mA+ty*mC+mTx,ty2:=tx*mB+ty*mD+mTy
setValues ix2,iy2,jx2,jy2,tx2,ty2
End

Method determinant : Float()
Return (mA * mD) - (mC * mB)
End Method

Method translateBy : Void(dx : Float,dy : Float)
mTx = mTx + dx ; mTy = mTy + dy
End Method

Method scaleBy : Void(s : Float)
mA = mA * s ; mB = mB * s ; mC = mC * s ; mD = mD * s ; mTx = mTx * s ;  mTy = mTy * s
End Method

Method rotateBy : Void(angle : Float)
Local rotMatrix : Matrix = New Matrix(Cos(angle),Sin(angle),-Sin(angle),Cos(angle),0,0)
concatMatrix(rotMatrix)
End Method

Method invert : Void()
Local det : Float = determinant()
Local a : Float = mD / det
Local b : Float = -mB / det
Local c : Float = -mC / det
Local d : Float = mA / det
Local tx : Float = ((mC * mTy) - (mD * mTx)) / det
Local ty : Float = ((mB * mTx) - (mA * mTy)) / det
setValues(a,b,c,d,tx,ty)
End Method

Method transformPoint : Point(point : Point)
Local x : Float = (mA * point.mX) + (mC * point.mY) + mTx
Local y : Float = (mB * point.mX) + (mD * point.mY) + mTy
Return New Point(x,y)
End Method

End Class``````

Last edited:
This allows origin point using right mouseclick, but jerks once while you do it, if you've zoomed or rotated already (If this is anywhere close to JS in how it works this is probably because not all matrix actions is not commutative).

EDIT Cleaned it up a bit
All the needed hardware-matrix commands mathematically implemented in 199 LOC Cerberus code.

Code:
``````Import mojo2
#MOJO_AUTO_SUSPEND_ENABLED=False
#HTML5_CONSOLE_SHOW = False

Function Main()
New MyApp
End Function

Class MyApp Extends App

Field myMatrix : Matrix
Field myPoint : Point
Field origin : Point
Field canvas : Canvas
Field ox:Int, oy:Int, x:Int, y:Int, d:Int
Field mapMatrix:Float[6]

Method OnCreate()
canvas = New Canvas
SetSwapInterval 1 ; SetUpdateRate 0
myMatrix = New Matrix()
myPoint = New Point()
origin = New Point(DeviceWidth() / 2.0,DeviceHeight() / 2.0)
canvas.GetMatrix(mapMatrix)

myMatrix.mA = mapMatrix[0] ; myMatrix.mB = mapMatrix[1]
myMatrix.mC = mapMatrix[2] ; myMatrix.mD = mapMatrix[3]
myMatrix.mTx = mapMatrix[4] ; myMatrix.mTy = mapMatrix[5]
Local myMatrix2 : Matrix = New Matrix()
myMatrix.multiplyMatrix(myMatrix2)
End Method

Method OnUpdate()

ox = x ; oy = y ; x = TouchX() ; y = TouchY() ; d = TouchDown(0)

' Translate matrix
If d Then myMatrix.translateBy(x-ox,y-oy)

' Scale matrix
If KeyDown(KEY_UP) Then myMatrix.scaleBy(1.01)
If KeyDown(KEY_DOWN) Then myMatrix.scaleBy(0.99)

' Rotate matrix
If KeyDown(KEY_LEFT) Then myMatrix.rotateBy(-1)
If KeyDown(KEY_RIGHT) Then myMatrix.rotateBy(1)

' ---------------------------------------------------------------------
' Rightclick to set origin on SCREEN not OBJECT
If Not d And MouseDown(1) Then origin.mX = x ; origin.mY = y
'
' Rightclick to set origin on OBJECT not SCREEN
'
' ---------------------------------------------------------------------

End Method

Method OnRender()
canvas.Clear
canvas.PushMatrix
canvas.Translate origin.mX,origin.mY
canvas.Transform myMatrix.mA,myMatrix.mB,myMatrix.mC,myMatrix.mD,myMatrix.mTx,myMatrix.mTy ' Multiply matrix using canvas command
canvas.Translate -origin.mX,-origin.mY

' ----------------------------------------------------------------------
' Read current hardware matrix
canvas.GetMatrix(mapMatrix)
' myMatrix.mA = mapMatrix[0] ; myMatrix.mB = mapMatrix[1] ; myMatrix.mC = mapMatrix[2]
' myMatrix.mD = mapMatrix[3] ; myMatrix.mTx = mapMatrix[4] ; myMatrix.mTy = mapMatrix[5]

' Set matrix (here to the absolute value from the read above, just to prove nothing happens, Matrix stays to whatever it is)
canvas.SetMatrix mapMatrix[0], mapMatrix[1], mapMatrix[2], mapMatrix[3], mapMatrix[4], mapMatrix[5]

' Multiply Matrix (here using identity matrix just to prove nothing happens, Matrix stays to whatever it is)
Local testMatrix : Matrix = New Matrix(1,0,0,1,0,0) ' Create a matrix to multiply myMatrix with
myMatrix.multiplyMatrix(testMatrix)
' ----------------------------------------------------------------------

drawMap()
canvas.PopMatrix

' ----------------------------------------------------------------------
' READ COORDINATE USING MULTIPLICATION OF INVERSE AKA NEGATIVE MATRIX
myPoint.mX = x - origin.mX ; myPoint.mY = y - origin.mY

' Inverse matrix
Local invMatrix : Matrix = myMatrix.clone()
invMatrix.invert()

' Make the point into the transformed world
Local testPoint : Point = invMatrix.transformPoint(myPoint)
canvas.DrawText String(origin.mX+Int(testPoint.mX)), 420,0
canvas.DrawText String(origin.mY+Int(testPoint.mY)), 460,0
' ----------------------------------------------------------------------

canvas.DrawRect origin.mX,origin.mY,1,1
canvas.DrawText String(mapMatrix[0]),0,0
canvas.DrawText String(mapMatrix[1]),0,10
canvas.DrawText String(mapMatrix[2]),0,20
canvas.DrawText String(mapMatrix[3]),0,30
canvas.DrawText String(mapMatrix[4]),0,40
canvas.DrawText String(mapMatrix[5]),0,50
canvas.Flush
End Method

Method drawMap()
For Local x=0 To 400 Step 100 ; canvas.DrawLine x,0,x,300 ; Next ' Draw a grid, horisontal..
For Local y=0 To 300 Step 100 ; canvas.DrawLine 0,y,400,y ; Next ' ..and vertical lines
For Local x=50 To 400 Step 100
For Local y=50 To 300 Step 100
canvas.DrawCircle x,y,2 ; canvas.DrawText x+","+y,x-27,y+8
Next
Next
End

End Class

Class Point

Field mX : Float, mY : Float

Method New(x : Float,y : Float)
mX = x ; mY = y
End Method

End Class

Class Matrix

Field mA : Float, mB : Float, mC : Float, mD : Float, mTx : Float, mTy : Float

Method New(a : Float = 1.0 ,b : Float = 0.0,c : Float = 0.0,d : Float = 1.0,tx : Float = 0.0,ty : Float = 0.0) ' default = identity matrix
mA = a ; mB = b ; mC = c ; mD = d ; mTx = tx ; mTy = ty
End Method

Function setValues(matrix : Matrix,a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
matrix.mA = a ; matrix.mB = b ; matrix.mC = c ; matrix.mD = d ; matrix.mTx = tx ; matrix.mTy = ty
End Function

Method clone : Matrix()
Return New Matrix(mA,mB,mC,mD,mTx,mTy)
End Method

Method setValues(a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
mA = a ; mB = b ; mC = c ; mD = d ; mTx = tx ; mTy = ty
End Method

Method concatMatrix : Void(matrix : Matrix)
Local a : Float = matrix.mA * mA  + matrix.mC * mB
Local b : Float = matrix.mB * mA  + matrix.mD * mB
Local c : Float = matrix.mA * mC  + matrix.mC * mD
Local d : Float = matrix.mB * mC  + matrix.mD * mD
Local tx : Float = matrix.mA * mTx + matrix.mC * mTy + matrix.mTx
Local ty : Float = matrix.mB * mTx + matrix.mD * mTy + matrix.mTy
setValues(a,b,c,d,tx,ty)
End Method

Method multiplyMatrix:Void(matrix:Matrix)
Local ix:Float = matrix.mA,iy:Float = matrix.mB,jx:Float = matrix.mC
Local jy:Float = matrix.mD,tx:Float = matrix.mTx, ty:Float = matrix.mTy
Local ix2:=ix*mA+iy*mC,iy2:=ix*mB+iy*mD
Local jx2:=jx*mA+jy*mC,jy2:=jx*mB+jy*mD
Local tx2:=tx*mA+ty*mC+mTx,ty2:=tx*mB+ty*mD+mTy
setValues ix2,iy2,jx2,jy2,tx2,ty2
End

Method determinant : Float()
Return (mA * mD) - (mC * mB)
End Method

Method translateBy : Void(dx : Float,dy : Float)
mTx = mTx + dx ; mTy = mTy + dy
End Method

Method scaleBy : Void(s : Float)
mA = mA * s ; mB = mB * s ; mC = mC * s ; mD = mD * s ; mTx = mTx * s ;  mTy = mTy * s
End Method

Method rotateBy : Void(angle : Float)
Local rotMatrix : Matrix = New Matrix(Cos(angle),Sin(angle),-Sin(angle),Cos(angle),0,0)
concatMatrix(rotMatrix)
End Method

Method invert : Void()
Local det : Float = determinant()
Local a : Float = mD / det, b : Float = -mB / det
Local c : Float = -mC / det, d : Float = mA / det
Local tx : Float = ((mC * mTy) - (mD * mTx)) / det
Local ty : Float = ((mB * mTx) - (mA * mTy)) / det
setValues(a,b,c,d,tx,ty)
End Method

Method transformPoint : Point(point : Point)
Local x : Float = (mA * point.mX) + (mC * point.mY) + mTx
Local y : Float = (mB * point.mX) + (mD * point.mY) + mTy
Return New Point(x,y)
End Method

End Class``````

Last edited:
Here's a working conversion of Mojo2!

EDIT Added Mousewheel zooming
EDIT commented out Mousewheel as WIP (Mousewheel appearently outputs garbage when you do other things with the touchpad so it's a small project to handle that neatly).

Code:
``````Import mojo2

Function Main()
New TransformMapApp
End

Class TransformMapApp Extends App

Field mx#,my#
Field tmx#,tmy#
Field omx#,omy#
Field mapMatrix:Matrix
Field canvas:Canvas
Field agetmatrix:Float[6]

Method OnCreate()
SetUpdateRate 0
canvas = New Canvas()
mapMatrix = New Matrix()

' Read current matrix, and becuase there's two types currently in use, there's an ugly conversion between 6floatarray to matrix-type
canvas.PushMatrix
canvas.Scale DeviceWidth()/400.0, DeviceHeight()/300.0
canvas.GetMatrix(agetmatrix)
canvas.PopMatrix
mapMatrix.mA = agetmatrix[0] ; mapMatrix.mB = agetmatrix[1]
mapMatrix.mC = agetmatrix[2] ; mapMatrix.mD = agetmatrix[3]
mapMatrix.mTx = agetmatrix[4] ; mapMatrix.mTy = agetmatrix[5]
End

Method OnUpdate()
Local coords:Point
mx = MouseX() ; my = MouseY()
canvas.PushMatrix
canvas.Translate mx,my
canvas.Rotate (KeyDown(KEY_LEFT)-KeyDown(KEY_RIGHT))*1.5
Local s# = 1+(KeyDown(KEY_UP) - KeyDown(KEY_DOWN))*.01

'   s = s + MouseZ() * .03

canvas.Scale s,s
canvas.Translate -mx,-my

canvas.Transform mapMatrix.mA,mapMatrix.mB,mapMatrix.mC,mapMatrix.mD,mapMatrix.mTx,mapMatrix.mTy

Local invMatrix : Matrix = mapMatrix.clone() ; invMatrix.invert()
coords = invMatrix.transformPoint(New Point(mx,my))
tmx = coords.mX ; tmy = coords.mY

If TouchDown(0) Then canvas.Translate tmx-omx, tmy-omy
canvas.GetMatrix(agetmatrix)
mapMatrix.mA = agetmatrix[0]
mapMatrix.mB = agetmatrix[1]
mapMatrix.mC = agetmatrix[2]
mapMatrix.mD = agetmatrix[3]
mapMatrix.mTx = agetmatrix[4]
mapMatrix.mTy = agetmatrix[5]

invMatrix = mapMatrix.clone() ; invMatrix.invert()
coords = invMatrix.transformPoint(New Point(mx,my))
omx = coords.mX ; omy = coords.mY

canvas.PopMatrix
End

Method OnRender()
canvas.Clear
canvas.SetColor 1,1,1
canvas.PushMatrix

canvas.Transform mapMatrix.mA,mapMatrix.mB,mapMatrix.mC,mapMatrix.mD,mapMatrix.mTx,mapMatrix.mTy

drawMap
canvas.DrawText Int(omx)+","+Int(omy),omx,omy-12

canvas.PopMatrix
canvas.Flush
End

Method drawMap()
For Local x=0 To 400 Step 100 ; canvas.DrawLine x,0,x,300 ; Next
For Local y=0 To 300 Step 100 ; canvas.DrawLine 0,y,400,y ; Next
For Local x=50 To 400 Step 100
For Local y=50 To 300 Step 100
canvas.DrawCircle x,y,2 ; canvas.DrawText x+","+y,x+2,y+2
Next
Next
End
End

Class Point

Field mX : Float, mY : Float

Method New(x : Float,y : Float)
mX = x ; mY = y
End Method

End Class

Class Matrix

Field mA : Float, mB : Float, mC : Float, mD : Float, mTx : Float, mTy : Float

Method New(a : Float = 1.0 ,b : Float = 0.0,c : Float = 0.0,d : Float = 1.0,tx : Float = 0.0,ty : Float = 0.0)
mA = a ; mB = b ; mC = c ; mD = d ; mTx = tx ; mTy = ty
End Method

Method clone : Matrix()
Return New Matrix(mA,mB,mC,mD,mTx,mTy)
End Method

Method setValues(a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
mA = a ; mB = b ; mC = c ; mD = d ; mTx = tx ; mTy = ty
End Method

Method concatMatrix : Void(matrix : Matrix)
Local a : Float = matrix.mA * Self.mA  + matrix.mC * Self.mB
Local b : Float = matrix.mB * Self.mA  + matrix.mD * Self.mB
Local c : Float = matrix.mA * Self.mC  + matrix.mC * Self.mD
Local d : Float = matrix.mB * Self.mC  + matrix.mD * Self.mD
Local tx : Float = matrix.mA * Self.mTx + matrix.mC * Self.mTy + matrix.mTx
Local ty : Float = matrix.mB * Self.mTx + matrix.mD * Self.mTy + matrix.mTy
Self.setValues(a,b,c,d,tx,ty)
End Method

Method multiplyMatrix:Void(matrix:Matrix)
Local ix:Float = matrix.mA,iy:Float = matrix.mB,jx:Float = matrix.mC
Local jy:Float = matrix.mD,tx:Float = matrix.mTx, ty:Float = matrix.mTy
Local ix2:=ix*mA+iy*mC,iy2:=ix*mB+iy*mD,jx2:=jx*mA+jy*mC,jy2:=jx*mB+jy*mD,tx2:=tx*mA+ty*mC+mTx,ty2:=tx*mB+ty*mD+mTy
setValues ix2,iy2,jx2,jy2,tx2,ty2
End

Method determinant : Float()
Return (mA * mD) - (mC * mB)
End Method

Method translateBy : Void(dx : Float,dy : Float)
Self.mTx = Self.mTx + dx
Self.mTy = Self.mTy + dy
End Method

Method scaleBy : Void(sx : Float,sy : Float)
Self.mA = Self.mA * sx
Self.mB = Self.mB * sy
Self.mC = Self.mC * sx
Self.mD = Self.mD * sy
Self.mTx = Self.mTx * sx
Self.mTy = Self.mTy * sy
End Method

Method scaleBy : Void(scale : Float)
Self.scaleBy(scale,scale)
End Method

Method rotateBy : Void(angle : Float)
Local rotMatrix : Matrix = New Matrix(Cos(angle),Sin(angle),-Sin(angle),Cos(angle),0,0)
Self.concatMatrix(rotMatrix)
End Method

Method invert : Void()
Local det : Float = determinant()
Local a : Float = mD / det, b : Float = -mB / det, c : Float = -mC / det, d : Float = mA / det
Local tx : Float = ((mC * mTy) - (mD * mTx)) / det, ty : Float = ((mB * mTx) - (mA * mTy)) / det
setValues(a,b,c,d,tx,ty)
End Method

Method transformPoint : Point(point : Point)
Local x : Float = (mA * point.mX) + (mC * point.mY) + mTx, y : Float = (mB * point.mX) + (mD * point.mY) + mTy
Return New Point(x,y)
End Method

End Class``````

Last edited:
Comparing the speed of Cerberus Matrix handling wiith lots of other languages, including Wonkey. Cerberus actually is over 16msec faster so basically one frame ahead. I'm so happy to be able to do a reaction mini-game finally.

I just don't like how this example was written in a mix of OnUpdate and OnRender, both containing PushMatrix PopMatrix etc. It makes the code hard to follow in a way so amm thinking of rewriting it to use only OnRender and put all inputs in variables using OnUpdate, would that be a good idea? OnUpdate for inputs, OnRender for outputs, so to speak? Anyways, it's working fine.

Last edited:
Here's the final one with input and rendering separated sucessfully.

The scale var was initially 0. You can't rely on that onUpdate will run before onRender and set the variable to be used in OnRender so I had to preset the variable to scale to 1 just in case OnRender runs before any inputs is loaded into it.

Code:
``````Import mojo2

Function Main()
New TransformMapApp
End

Class TransformMapApp Extends App

Field mx#,my#
Field tmx#,tmy#
Field omx#,omy#
Field mapMatrix:Matrix
Field canvas:Canvas
Field agetmatrix:Float[6]
Field s:Float = 1
Field r:Float = 0
Field d:Float

Method OnCreate()
SetUpdateRate 0
canvas = New Canvas()
mapMatrix = New Matrix()

' Read current matrix, and becuase there's two types currently in use, there's an ugly conversion between 6floatarray to matrix-type
canvas.PushMatrix
canvas.Scale DeviceWidth()/400.0, DeviceHeight()/300.0
canvas.GetMatrix(agetmatrix)
canvas.PopMatrix
mapMatrix.mA = agetmatrix[0] ; mapMatrix.mB = agetmatrix[1]
mapMatrix.mC = agetmatrix[2] ; mapMatrix.mD = agetmatrix[3]
mapMatrix.mTx = agetmatrix[4] ; mapMatrix.mTy = agetmatrix[5]
End

Method OnUpdate()
d = TouchDown(0)
mx = TouchX(0) ; my = TouchY(0)
r = (KeyDown(KEY_LEFT)-KeyDown(KEY_RIGHT))*1.5
s = 1+(KeyDown(KEY_UP) - KeyDown(KEY_DOWN))*.01
' s = s + MouseZ() * .03
End

Method OnRender()
canvas.Clear

canvas.PushMatrix
canvas.Translate mx,my
canvas.Rotate r
canvas.Scale s,s
canvas.Translate -mx,-my
canvas.Transform mapMatrix.mA,mapMatrix.mB,mapMatrix.mC,mapMatrix.mD,mapMatrix.mTx,mapMatrix.mTy
Local invMatrix : Matrix = mapMatrix.clone() ; invMatrix.invert()
Local coords:Point = invMatrix.transformPoint(New Point(mx,my))
tmx = coords.mX ; tmy = coords.mY
If d Then canvas.Translate tmx-omx, tmy-omy
canvas.GetMatrix(agetmatrix)
mapMatrix.mA = agetmatrix[0]
mapMatrix.mB = agetmatrix[1]
mapMatrix.mC = agetmatrix[2]
mapMatrix.mD = agetmatrix[3]
mapMatrix.mTx = agetmatrix[4]
mapMatrix.mTy = agetmatrix[5]
invMatrix = mapMatrix.clone() ; invMatrix.invert()
coords = invMatrix.transformPoint(New Point(mx,my))
omx = coords.mX ; omy = coords.mY
canvas.PopMatrix

canvas.PushMatrix
canvas.Transform mapMatrix.mA,mapMatrix.mB,mapMatrix.mC,mapMatrix.mD,mapMatrix.mTx,mapMatrix.mTy
drawMap
canvas.DrawText Int(omx)+","+Int(omy),omx,omy-12
canvas.PopMatrix
canvas.Flush
End

Method drawMap()
For Local x=0 To 400 Step 100 ; canvas.DrawLine x,0,x,300 ; Next
For Local y=0 To 300 Step 100 ; canvas.DrawLine 0,y,400,y ; Next
For Local x=50 To 400 Step 100
For Local y=50 To 300 Step 100
canvas.DrawCircle x,y,2 ; canvas.DrawText x+","+y,x+2,y+2
Next
Next
End
End

Class Point

Field mX : Float, mY : Float

Method New(x : Float,y : Float)
mX = x ; mY = y
End Method

End Class

Class Matrix

Field mA : Float, mB : Float, mC : Float, mD : Float, mTx : Float, mTy : Float

Method New(a : Float = 1.0 ,b : Float = 0.0,c : Float = 0.0,d : Float = 1.0,tx : Float = 0.0,ty : Float = 0.0)
mA = a ; mB = b ; mC = c ; mD = d ; mTx = tx ; mTy = ty
End Method

Method clone : Matrix()
Return New Matrix(mA,mB,mC,mD,mTx,mTy)
End Method

Method setValues(a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
mA = a ; mB = b ; mC = c ; mD = d ; mTx = tx ; mTy = ty
End Method

Method concatMatrix : Void(matrix : Matrix)
Local a : Float = matrix.mA * Self.mA  + matrix.mC * Self.mB
Local b : Float = matrix.mB * Self.mA  + matrix.mD * Self.mB
Local c : Float = matrix.mA * Self.mC  + matrix.mC * Self.mD
Local d : Float = matrix.mB * Self.mC  + matrix.mD * Self.mD
Local tx : Float = matrix.mA * Self.mTx + matrix.mC * Self.mTy + matrix.mTx
Local ty : Float = matrix.mB * Self.mTx + matrix.mD * Self.mTy + matrix.mTy
Self.setValues(a,b,c,d,tx,ty)
End Method

Method multiplyMatrix:Void(matrix:Matrix)
Local ix:Float = matrix.mA,iy:Float = matrix.mB,jx:Float = matrix.mC
Local jy:Float = matrix.mD,tx:Float = matrix.mTx, ty:Float = matrix.mTy
Local ix2:=ix*mA+iy*mC,iy2:=ix*mB+iy*mD,jx2:=jx*mA+jy*mC,jy2:=jx*mB+jy*mD,tx2:=tx*mA+ty*mC+mTx,ty2:=tx*mB+ty*mD+mTy
setValues ix2,iy2,jx2,jy2,tx2,ty2
End

Method determinant : Float()
Return (mA * mD) - (mC * mB)
End Method

Method translateBy : Void(dx : Float,dy : Float)
Self.mTx = Self.mTx + dx
Self.mTy = Self.mTy + dy
End Method

Method scaleBy : Void(sx : Float,sy : Float)
Self.mA = Self.mA * sx
Self.mB = Self.mB * sy
Self.mC = Self.mC * sx
Self.mD = Self.mD * sy
Self.mTx = Self.mTx * sx
Self.mTy = Self.mTy * sy
End Method

Method scaleBy : Void(scale : Float)
Self.scaleBy(scale,scale)
End Method

Method rotateBy : Void(angle : Float)
Local rotMatrix : Matrix = New Matrix(Cos(angle),Sin(angle),-Sin(angle),Cos(angle),0,0)
Self.concatMatrix(rotMatrix)
End Method

Method invert : Void()
Local det : Float = determinant()
Local a : Float = mD / det, b : Float = -mB / det, c : Float = -mC / det, d : Float = mA / det
Local tx : Float = ((mC * mTy) - (mD * mTx)) / det, ty : Float = ((mB * mTx) - (mA * mTy)) / det
setValues(a,b,c,d,tx,ty)
End Method

Method transformPoint : Point(point : Point)
Local x : Float = (mA * point.mX) + (mC * point.mY) + mTx, y : Float = (mB * point.mX) + (mD * point.mY) + mTy
Return New Point(x,y)
End Method

End Class``````

Last edited:
If you want to take a 2d Matrix and extract scale from it this is how you do it.

Code:
``````Import mojo2

Function Main()
New TransformMapApp
End

Class TransformMapApp Extends App

Field mx#,my#
Field tmx#,tmy#
Field omx#,omy#
Field mapMatrix:Matrix
Field canvas:Canvas
Field agetmatrix:Float[6]
Field s:Float = 1
Field r:Float = 0
Field d:Float

Method OnCreate()
SetUpdateRate 0
canvas = New Canvas()
mapMatrix = New Matrix()

' Read current matrix, and becuase there's two types currently in use, there's an ugly conversion between 6floatarray to matrix-type
canvas.PushMatrix
canvas.Scale DeviceWidth()/400.0, DeviceHeight()/300.0
canvas.GetMatrix(agetmatrix)
canvas.PopMatrix
mapMatrix.mA = agetmatrix[0] ; mapMatrix.mB = agetmatrix[1]
mapMatrix.mC = agetmatrix[2] ; mapMatrix.mD = agetmatrix[3]
mapMatrix.mTx = agetmatrix[4] ; mapMatrix.mTy = agetmatrix[5]
End

Method OnUpdate()
d = TouchDown(0)
mx = TouchX(0) ; my = TouchY(0)
r = (KeyDown(KEY_LEFT)-KeyDown(KEY_RIGHT))*1.5
s = 1+(KeyDown(KEY_UP) - KeyDown(KEY_DOWN))*.01
' s = s + MouseZ() * .03
End

Method OnRender()
canvas.Clear

canvas.PushMatrix
canvas.Translate mx,my
canvas.Rotate r   ' relative change that are stored
canvas.Scale s,s  ' relative change that are stored
canvas.Translate -mx,-my
canvas.Transform mapMatrix.mA,mapMatrix.mB,mapMatrix.mC,mapMatrix.mD,mapMatrix.mTx,mapMatrix.mTy
Local invMatrix : Matrix = mapMatrix.clone() ; invMatrix.invert()
Local coords:Point = invMatrix.transformPoint(New Point(mx,my))
tmx = coords.mX ; tmy = coords.mY
If d Then canvas.Translate tmx-omx, tmy-omy
canvas.GetMatrix(agetmatrix)
mapMatrix.mA = agetmatrix[0]
mapMatrix.mB = agetmatrix[1]
mapMatrix.mC = agetmatrix[2]
mapMatrix.mD = agetmatrix[3]
mapMatrix.mTx = agetmatrix[4]
mapMatrix.mTy = agetmatrix[5]
invMatrix = mapMatrix.clone() ; invMatrix.invert()
coords = invMatrix.transformPoint(New Point(mx,my))
omx = coords.mX ; omy = coords.mY
canvas.PopMatrix

canvas.PushMatrix
canvas.Transform mapMatrix.mA,mapMatrix.mB,mapMatrix.mC,mapMatrix.mD,mapMatrix.mTx,mapMatrix.mTy

' How to set Matrix in an absolute way using only math and a final SetMatrix hardware command:
' If MouseDown(1)
' ' How set position and scale
' Local tempmatrix : Matrix = New Matrix() ' Identity matrix is the default new matrix when no parameters given
' tempmatrix.translateBy 100,100    ' x & y
' tempmatrix.scaleBy 3.2,3.2        ' Scale
' canvas.SetMatrix tempmatrix.mA,tempmatrix.mB,tempmatrix.mC,tempmatrix.mD,tempmatrix.mTx,tempmatrix.mTy
' Endif

drawMap
canvas.DrawText Int(omx)+","+Int(omy),omx,omy-12
canvas.PopMatrix

' Extract scale & rotation from matric and print them
canvas.DrawText "SCALE = " + (getScaleX(mapMatrix)),0,0 ' any will do as both are the same here
'   canvas.DrawText "ROTATION = " + (getRotation(mapMatrix)),0,20
canvas.Flush
End

Method getScaleX:Float(m:Matrix)
Return Sqrt((m.mA * m.mA) + (m.mC * m.mC))
' Return Sqrt(Pow(m.mA + m.mB, 2))
End

Method getScaleY:Float(m:Matrix)
' Return Sqrt(Pow(m.mC + m.mD, 2))
Return Sqrt((m.mB * m.mB) + (m.mD * m.mD))
End

'Method getRotation:Float(m:Matrix)
'    Return (m.mA / getScaleX(m) )
'    ' Return m.mD / getScaleY(m)

#REM HOW EXTRACT ROTATION
scaleX = Sqrt((a * a) + (c * c))
scaleY = Sqrt((b * b) + (d * d))
sign = Atan(-c / a);
rad  = Acos(a / scaleX)
deg  = rad * degree
if (deg > 90 And sign > 0)
rotation = (360 - deg) * radian
elseif (deg < 90 And sign < 0)
rotation = (360 - deg) * radian
else
EndIf
rotationInDegree = rotation * degree
' EndIf
return dmat
End
#END

Method drawMap()
For Local x=0 To 400 Step 100 ; canvas.DrawLine x,0,x,300 ; Next
For Local y=0 To 300 Step 100 ; canvas.DrawLine 0,y,400,y ; Next
For Local x=50 To 400 Step 100
For Local y=50 To 300 Step 100
canvas.DrawCircle x,y,2 ; canvas.DrawText x+","+y,x+2,y+2
Next
Next
End
End

Class Point

Field mX : Float, mY : Float

Method New(x : Float,y : Float)
mX = x ; mY = y
End Method

End Class

Class Matrix

Field mA : Float, mB : Float, mC : Float, mD : Float, mTx : Float, mTy : Float

Method New(a : Float = 1.0 ,b : Float = 0.0,c : Float = 0.0,d : Float = 1.0,tx : Float = 0.0,ty : Float = 0.0)
mA = a ; mB = b ; mC = c ; mD = d ; mTx = tx ; mTy = ty
End Method

Method clone : Matrix()
Return New Matrix(mA,mB,mC,mD,mTx,mTy)
End Method

Method setValues(a : Float,b : Float,c : Float,d : Float,tx : Float,ty : Float)
mA = a ; mB = b ; mC = c ; mD = d ; mTx = tx ; mTy = ty
End Method

Method concatMatrix : Void(matrix : Matrix)
Local a : Float = matrix.mA * Self.mA  + matrix.mC * Self.mB
Local b : Float = matrix.mB * Self.mA  + matrix.mD * Self.mB
Local c : Float = matrix.mA * Self.mC  + matrix.mC * Self.mD
Local d : Float = matrix.mB * Self.mC  + matrix.mD * Self.mD
Local tx : Float = matrix.mA * Self.mTx + matrix.mC * Self.mTy + matrix.mTx
Local ty : Float = matrix.mB * Self.mTx + matrix.mD * Self.mTy + matrix.mTy
Self.setValues(a,b,c,d,tx,ty)
End Method

Method multiplyMatrix:Void(matrix:Matrix)
Local ix:Float = matrix.mA,iy:Float = matrix.mB,jx:Float = matrix.mC
Local jy:Float = matrix.mD,tx:Float = matrix.mTx, ty:Float = matrix.mTy
Local ix2:=ix*mA+iy*mC,iy2:=ix*mB+iy*mD,jx2:=jx*mA+jy*mC,jy2:=jx*mB+jy*mD,tx2:=tx*mA+ty*mC+mTx,ty2:=tx*mB+ty*mD+mTy
setValues ix2,iy2,jx2,jy2,tx2,ty2
End

Method determinant : Float()
Return (mA * mD) - (mC * mB)
End Method

Method translateBy : Void(dx : Float,dy : Float)
Self.mTx = Self.mTx + dx
Self.mTy = Self.mTy + dy
End Method

Method scaleBy : Void(sx : Float,sy : Float)
Self.mA = Self.mA * sx
Self.mB = Self.mB * sy
Self.mC = Self.mC * sx
Self.mD = Self.mD * sy
Self.mTx = Self.mTx * sx
Self.mTy = Self.mTy * sy
End Method

Method scaleBy : Void(scale : Float)
Self.scaleBy(scale,scale)
End Method

Method rotateBy : Void(angle : Float)
Local rotMatrix : Matrix = New Matrix(Cos(angle),Sin(angle),-Sin(angle),Cos(angle),0,0)
Self.concatMatrix(rotMatrix)
End Method

Method invert : Void()
Local det : Float = determinant()
Local a : Float = mD / det, b : Float = -mB / det, c : Float = -mC / det, d : Float = mA / det
Local tx : Float = ((mC * mTy) - (mD * mTx)) / det, ty : Float = ((mB * mTx) - (mA * mTy)) / det
setValues(a,b,c,d,tx,ty)
End Method

Method transformPoint : Point(point : Point)
Local x : Float = (mA * point.mX) + (mC * point.mY) + mTx, y : Float = (mB * point.mX) + (mD * point.mY) + mTy
Return New Point(x,y)
End Method

End Class``````

Last edited: