Transforming mouse coordinates

Monkey Forums/Monkey Programming/Transforming mouse coordinates

Xaron(Posted 2013) [#1]
Hi all,

I'm stuck with the following problem. Assume an image which is rotated, scaled, shifted and displayed that way (the image is centered, so 0,0 are the center coordinates of the image):

PushMatrix()
  Translate( x, y )
  Rotate( angle )
  Scale( s, s )
  DrawImage( img, 0, 0 )


Now I would like to know if the mouse pointer is above that image rectangle or not. For that I need to transform the mouse coordinates to the local space of that image.

I know the transform_mouse example from warpy already even though I still have an error in my code...


Xaron(Posted 2013) [#2]
. sorry double posts!


Xaron(Posted 2013) [#3]
Please forgive my stupidness, but out of warpy's example I try the following:

Import mojo

Class TestApp Extends App
  Field tmx:Float
  Field tmy:Float

  Method OnCreate()
    SetUpdateRate 60
  End
  
  Method OnUpdate()
  End
  
  Method OnRender()
    Cls
    SetColor 255,255,255
    SetFont Null
    
    PushMatrix()
      Translate 100, 100
      Rotate 45
      DrawRect( -25, -25, 50, 50 ) 'This is the same as drawing an image using DrawImage( img, 0, 0 )
      
      Local coords#[]
      
      'get the mouse's screen co-ordinates
      Local mx# = MouseX()
      Local my# = MouseY()
      
      Local m#[] = GetMatrix()

      'OK, how am I supposed to transform the mouse coordinates so they show 0,0 in the centre of that rectangle?    
      'I'd say first I push the matrix onto the stack:
      PushMatrix
        'Now I shift the mouse coordinates
        Translate( mx, my )
        'I apply the same rotation
        Rotate( 45 )
        'And I transform that with the previous matrix I got
        Transform( m[0], m[1], m[2], m[3], m[4], m[5] )
        'Now I have to use the inverse transformation to get the mouse coords in the local space
        coords = InvTransform( [ mx, my ] )
        tmx = coords[0]
        tmy = coords[1]
      PopMatrix
    PopMatrix
    
    DrawText( "x: " + tmx, 10, 10 )
    DrawText( "y: " + tmy, 10, 30 )
  End
End

Function Main()
  New TestApp()
End


So the middle of that rectangle should be something like 0, 0 in mouse coordinates (transformed tmx and tmy) but today is not my math day. So how am I supposed to transform the mouse coordinates so they show 0,0 in the centre of that rectangle?


DruggedBunny(Posted 2013) [#4]
I think this code by NoOdle does what you need...


Xaron(Posted 2013) [#5]
Well indeed, thanks for that! But it's a bit of an overkill for what I need so I'll keep trying. Maybe warpy has an idea of what's going wrong with my code or I just reactivate my rusty math knowledge...


Xaron(Posted 2013) [#6]
Ok, here's the solution, pretty simple:

Import mojo

Class TestApp Extends App
  Field _tmx:Float
  Field _tmy:Float
  Field _mat:Float[]
  Field _mx:Float
  Field _my:Float

  Method OnCreate()
    SetUpdateRate( 30 )
  End
  
  Method OnUpdate()
  End
  
  Method OnRender()
    Cls()
    PushMatrix()
      Translate( 200, 200 )
      Rotate( 30 )
      DrawRect( -25, -25, 50, 50 )
      
      'get the mouse screen coordinates
      _mx = MouseX()
      _my = MouseY()
      
      _mat = GetMatrix()
    PopMatrix()

    PushMatrix()
      'Apply the last saved mapMatrix, that is, all rotations, scalings and translations applied since the program started
      Transform( _mat[0], _mat[1], _mat[2], _mat[3], _mat[4], _mat[5] )
      
      'Work out what coordinate the mouse is pointing at by doing the matrix transformation backwards.
      Local coords:Float[] = InvTransform( [ _mx, _my ] )
      _tmx = coords[0]
      _tmy = coords[1]
    PopMatrix()
    
    DrawText( "mx: " + _mx, 10, 10 )
    DrawText( "my: " + _my, 10, 30 )
    DrawText( "tmx: " + _tmx, 10, 50 )
    DrawText( "tmy: " + _tmy, 10, 70 )
  End
End

Function Main()
  New TestApp()
End