FAQ
Cover
This is the archive Discourse for the Processing (ALPHA) software.
Please visit the new Processing forum for current information.

   Processing 1.0 _ALPHA_
   Programming Questions & Help
   Programs
(Moderators: fry, REAS)
   remaping mouse to matrix transformations
« Previous topic | Next topic »

Pages: 1 
   Author  Topic: remaping mouse to matrix transformations  (Read 1134 times)
pitaru

WWW Email
remaping mouse to matrix transformations
« on: Aug 26th, 2003, 8:56pm »

I've taken the 'handles' example from the 'examples/GUI' folder, and added one line at top of loop():
 
   rotate(PI/4);
 
(see the code here: http://pitaru.com/processing/handles_rotate )
 
My question - How do i remap the mouse to properly interact with the sliders?
 
benelek

35160983516098 WWW Email
Re: remaping mouse to matrix transformations
« Reply #1 on: Aug 27th, 2003, 8:14am »

you can use objectX and screenX, etc, to determine the real-screen position of the handles, as opposed to their coordinate positions on the matrix.
 
pitaru

WWW Email
Re: remaping mouse to matrix transformations
« Reply #2 on: Aug 27th, 2003, 2:53pm »

Yep, it would seem that simple, but i just can't get it to work. Once you have the rotated handle coordinates, there's still the issue of making the handles follow the unrotated screen mouse coordinates. How do i find out where the mouseX/Y are on the transformed coordiantes?  
 
what am i missing here?
Is this much simpler than I'm making it to be?
 
toxi

WWW
Re: remaping mouse to matrix transformations
« Reply #3 on: Aug 27th, 2003, 4:00pm »

hey amit,
 
the reason why this still doesn't work is because the example is hardcoded to only use the absolute horizontal mouse position for the sliders.
 
to get this working aligned to any arbitrary axis/orientation we need to use both mouseX and mouseY and change the slider value relative to how much the mouse has moved in meantime.
 
here's the fixed version, the changes are commented and are in the update() and overRect() functions:
 
Code:
// Handles
// by REAS <http://www.groupc.net>
 
// Click and drag the white boxes to change their position.
 
// Created 10 February 2003
 
Handle[] handles;
int num;
 
void setup()
{
  size(200, 200);
  background(153);
  num = height/15;
  handles = new Handle[num];
  int hsize = 10;
  for(int i=0; i<num; i++) {
    handles[i] = new Handle(width/2, 10+i*15, 50-hsize/2, 10, handles);
  }
}
 
void loop()
{
rotate(PI/4);
  for(int i=0; i<num; i++) {
    handles[i].update();
    handles[i].display();
  }
   
  fill(0);
  rect(0, 0, width/2, height);
}
 
void mouseReleased()  
{
  for(int i=0; i<num; i++) {
    handles[i].release();
  }
}
 
class Handle
{
  int x, y;
  int boxx, boxy;
  int length;
  int size;
  boolean over;
  boolean press;
  boolean locked = false;
  boolean otherslocked = false;
  Handle[] others;
   
  Handle(int _x, int _y, int _l, int _s, Handle[] o)
  {
    x = _x;
    y = _y;
    length = _l;
    size = _s;
    boxx = x+length - size/2;
    boxy = y - size/2;
    others = o;
  }
   
  void update()  
  {
    boxx = x+length;
    boxy = y - size/2;
     
    for(int i=0; i<others.length; i++) {
 if(others[i].locked == true) {
   otherslocked = true;
   break;
 } else {
   otherslocked = false;
 }  
    }
     
    if(otherslocked == false) {
 over();
 press();
    }
     
    // this code block now uses X/Y changes
    // instead of absolute coordinates
    if(press) {
 length = lock(length+(int)(mouseX-pmouseX)+(mouseY-pmouseY), 0, width/2-size-1);
    }
  }
   
  void over()
  {
    over=overRect(boxx, boxy, size, size);
  }
   
  void press()
  {
    if(over && mousePressed || locked) {
 press = true;
 locked = true;
    } else {
 press = false;
    }
  }
   
  void release()
  {
    locked = false;
  }
   
  void display()  
  {
    line(x, y, x+length, y);
    fill(255);
    stroke(0);
    rect(boxx, boxy, size, size);
    if(over || press) {
 line(boxx, boxy, boxx+size, boxy+size);
 line(boxx, boxy+size, boxx+size, boxy);
    }
 
  }
}
 
// new rollover function takes any matrix transformations into account
boolean overRect(int x, int y, int w, int h)  
{
  float sx=screenX(x+w/2,y+h/2,0);
  float sy=screenY(x+w/2,y+h/2,0);
  return (mouseX>=sx-w/2 && mouseX<=sx+w/2 && mouseY>=sy-h/2 && mouseY<=sy+h/2);
}
 
int lock(int val, int minv, int maxv)  
{  
  return  min(max(val, minv), maxv);  
}
 

http://toxi.co.uk/
pitaru

WWW Email
Re: remaping mouse to matrix transformations
« Reply #4 on: Aug 27th, 2003, 4:34pm »

Thanks toxi, yet i'm still not clear about a couple of things. I wrote this quick example of a movable-button-object to make the subject more generic for everyone. The questions are in the code, marked out...
 
 
// code..
 
 
btn b1;
 
void setup(){
  size(200,200);
  background(255);
  smooth();
  noStroke();
 
  b1 = new btn(150,150);
 
}
 
void loop(){
  translate(100,100);
  rotateZ(PI/4);
  translate(-100,-100);
  b1.update();
}
 
class btn {
 
  int x,y;
  int wh = 10;
  boolean drag = false;
 
  public btn(int _x, int _y){
    x = _x;
    y = _y;
  }
 
  void update(){
   
//////////////////////////////////////////////////////////////////////// /////////////////////
// Rollover - taking matrix into account ( i'm using object instead of screen... is this ok?)
//////////////////////////////////////////////////////////////////////// /////////////////////
    float xo = objectX(x,y,0);
    float yo = objectY(x,y,0);
    if (mouseX > xo- wh/2  && mouseX < xo+wh- wh/2 && mouseY > yo- wh/2 && mouseY < yo+wh- wh/2){
 fill(0,255,0);
 if (mousePressed){
   drag = true;
 }
    } else {
     fill(255,0,0);
    }
 
    if (drag){
 fill(0,255,0);
 
/////////////////////////////////////////////////////
// so .. what do we do here? (Obviously not this ...)
/////////////////////////////////////////////////////
 x += mouseX - pmouseX ;
 y += mouseY - pmouseY ;
   
     
 if( !mousePressed){
   drag = false;
 }
    }  
 
    rectMode(CENTER_DIAMETER);
    rect(x,y,wh,wh);
  }
 
}
 
toxi

WWW
Re: remaping mouse to matrix transformations
« Reply #5 on: Aug 27th, 2003, 5:06pm »

hmm.. i don't think i'm following now the only thing i could see which is wrong is your use of objectX() instead of screenX() etc. as you don't want the world-space coordinates, but the projected on-screen values.
 
but apart from that, what do *you* see wrong with it? the behaviour caused by the 45 degree Z rotation seems correct to my eyes, also if slightly unintuitive... try to use a X rotation instead, it's more clear.
 

http://toxi.co.uk/
pitaru

WWW Email
Re: remaping mouse to matrix transformations
« Reply #6 on: Aug 27th, 2003, 6:07pm »

Thanks man, lets take a step back -
 
what i see wrong with it is the unintuitive interaction that the rotation is causing. i want to eliminate the behaviour caused by the 45 degree Z rotation (the user should not care if the entire environment is rotated).
 
 
In other words:
 
I want the user to be able to drag 2D objects in a transformed (translate/rotate..) environment, as if they are not transformed at all. In my example above, the user cannot drag the object in a predictable manner, as the object does not 'stay under the cursor' during the dragging.  
 
thanks for staying with me on this
 
skloopy

WWW
Re: remaping mouse to matrix transformations
« Reply #7 on: Aug 27th, 2003, 10:02pm »

Is there some way to multiply the mouseX and Y by the current transform matrix? If you could do that you could find out where the mouse is in the rotated coordinates and then move the square there...
 
Update: Oops you already thought of that.. I'm curious how to do that too
« Last Edit: Aug 27th, 2003, 10:04pm by skloopy »  
toxi

WWW
Re: remaping mouse to matrix transformations
« Reply #8 on: Aug 28th, 2003, 3:11pm »

ok, gotcha mister!
 
as i'm not this fluent in matrix algebra myself, it took me a bit of thinking/researching how to reverse a current transformation in order to map screen space mouse coordinates into the transformed object space. the solution to all this is to temporarily invert bagel's current transform matrix. however this function is not yet "built in", something i hope will change in future as it's very, very helpful for loads of other cases...
 
below is the latest version. to prove this all works, i'm now using a constantly changing rotation offset and your rectangle still sticks to your mouse...
 
hope *that* solves your problem!
 
Code:
btn b1;
 
void setup(){
  size(200,200);
  background(255);
  noStroke();
 
  b1 = new btn(150,150);
}
 
void loop(){
  translate(100,100);
  rotate(millis()*0.001);
  translate(-100,-100);
  b1.update();
}
 
class btn {
 
  int x,y;
  int wh = 30;
  boolean drag = false;
 
  public btn(int _x, int _y){
    x = _x;
    y = _y;
  }
 
  void update(){
 
    float xo = screenX(x,y,0);
    float yo = screenY(x,y,0);
    if (mouseX > xo- wh/2  && mouseX < xo+wh- wh/2 && mouseY > yo- wh/2 && mouseY < yo+wh- wh/2){
 fill(0,255,0);
 if (mousePressed){
   drag = true;
 }
    } else {
 fill(255,0,0);
    }
 
////////////////////////////////////////////////////////////////////////  /////////////////////
    // big changes below...
////////////////////////////////////////////////////////////////////////  /////////////////////
 
    if (drag){
 fill(255,255,0);
 
 // save the current transform
 push();
 
 // invert the current transformation
 // this should be build into bagel really as this comes in handy for many other cases
 invmatrix();
 
 // get the mouse coordinates transformed into the object space
 x=(int)objectX(mouseX,mouseY,0);
 y=(int)objectY(mouseX,mouseY,0);
 
 // restore the previous transform before drawing the object
 pop();
 
 if( !mousePressed){
   drag = false;
 }
    }
 
    rectMode(CENTER_DIAMETER);
    rect(x,y,wh,wh);
  }
 
}
 
// construct the inverse of a matrix
 
void invmatrix(){
  int i,m,p,b;
  int pos,p_oid;
  int p_oid2;
  int n=4;
   
  // put the current transform on the matrixstack so we can work with an array
  push();
   
  // get the reference to the matrix array in bagel
  float[] a=g.matrixStack[g.matrixStackDepth-1];
 
  // do the inversion
  for(i=0;i<n;i++) {
    p_oid2=i*n+i;
    a[p_oid2]=1/a[p_oid2];
    for(m=0; m<n; m++)
    if(m!=i) {
 p_oid=m*n+i;
 a[p_oid]=a[p_oid]*a[p_oid2];
    }
 
    for(m=0; m<n; m++) {
 for(p=0; p<n; p++) {
   if(m!=i){
     if(p!=i){
  pos=m*n+p;
  p_oid=m*n+i;
  p_oid2=i*n+p;
  a[pos]=a[pos]-(a[p_oid]*a[p_oid2]);
     }
   }
 }
    }
 
    p_oid=i*n+i;
    for(p=0;p<n;p++)
    if(p!=i){
 pos=i*n+p;
 a[pos]=-a[p_oid]*a[pos];
    }
  }
   
  // make this inverted transform the current one
  pop();
   
}
« Last Edit: Aug 28th, 2003, 7:00pm by toxi »  

http://toxi.co.uk/
pitaru

WWW Email
Re: remaping mouse to matrix transformations
« Reply #9 on: Sep 1st, 2003, 3:38pm »

brilliant!
 
I think that a simple and useful implementation could be in form of rmouseX/Y (r for remapped?). The method would look something like this...
 
// Return the remapped mouse coordinates
int mouseXt(){
  // save the current transform
  push();
  // invert the current transformation using integrated code from toxi's god-sent post above.
  invmatrix();
  // get the mouse coordinates transformed into the object space
  // Note: how do we enhance the code to deal with all types of transfromtion (see next post)?
  int  x=(int)objectX(mouseX,mouseY, 0);
  // restore the previous transform before drawing the object
  pop();
  return x;
}
 
pitaru

WWW Email
Re: remaping mouse to matrix transformations
« Reply #10 on: Sep 1st, 2003, 3:41pm »

OK, the btn example deals with a rotate() (see loop() of toxi's post). how do we deal with this type of monster?
 
  translate(100,100,50);  
  rotateX(millis()*0.001);    
  scale(0.5);
  translate(-100,-100,50);  
 
-a
 
toxi

WWW
Re: remaping mouse to matrix transformations
« Reply #11 on: Sep 1st, 2003, 11:36pm »

yeah, i know my solution only works with transforms in the XY plane really as it assumes z=0 at the point when you re-translate the mouse position. if you rotate around the X or Y axis, the Z coordinate is always changing and the re-mapped point will be wrong. have to do more digging for that one, but i remember the same problem exists in shockwave3D. i'm not sure there's a trivial solution to this problem, but what do i know...
 

http://toxi.co.uk/
benelek

35160983516098 WWW Email
Re: remaping mouse to matrix transformations
« Reply #12 on: Sep 3rd, 2003, 2:05am »

maybe a method which projects the screen coordinates to the transformed X/Y plane would do the job. This obviously privelidges the X/Y plane abover other planes, and assumes that you're still working on the flat z=0 plane, but it may be somewhere to start from.
 
Pages: 1 

« Previous topic | Next topic »