We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpOpenGL and 3D Libraries › Drag objects in 3d with the mouse
Page Index Toggle Pages: 1
Drag objects in 3d with the mouse (Read 3747 times)
Drag objects in 3d with the mouse
Sep 1st, 2009, 9:36am
 
Hello,

I am trying to drag vertices of objects in order to edit them as you would do in cinema4d etc. It works- except that there is some scaling I can't get rid of :(

The Sketch uses screenX/screenY to detect if the mouse is over a vertex. When a vertex is clicked, the current mouse coords are projected into the 3d space onto a plane parallel to the viewplane. I use modelX/modelY to figure out the position of this plane. The projection reuses the camera and modelview matrices.

So far everything is fine, only that the projection always has some scaling depending on the z value of the current position in model/world space. It looks like there is a projection matrix missing, so I have been messing around with Processing's projection matrix, but that didn't help.

Can someone figure out what I am missing? Many thanks in andvance...

Code:

/*
click/drag to rotate entire object
click/ drag onto vertices
*/

PGraphics3D p3d;

PMatrix3D proj = new PMatrix3D();
PMatrix3D cam = new PMatrix3D();
PMatrix3D modvw = new PMatrix3D();
PMatrix3D modvwInv = new PMatrix3D();
PMatrix3D screen2Model = new PMatrix3D();

// rotation
float rotX, rotY;

// arrays hold the vertices of 3d object
float[] vertices3D = new float[0];
int[] vertices2D = new int[0];

// index of current mouseover / clicked vertex
int vertexMouseOver = -1;
int vertexKlicked= -1;

// z value in model/world space of current vertex
float zModelMouseOver;
float zModelKlick;

void setup() {
 size(800, 600, P3D);
 p3d = (PGraphics3D)g;
 frameRate(50);
 
 //generate 6 vertices randomly
 for(int i=0;i<18;i++) {
     vertices3D = append(vertices3D, random(-200, 200));
   }
}

void draw() {
 background(255);
 
 // 3d object space begin
 pushMatrix();
 
 //apply mouse rotation and translation to center of screen
 translations();
 
 //get 3d matrices
 proj = p3d.projection.get();
 cam = p3d.camera.get();
 modvw = p3d.modelview.get();
 modvwInv = p3d.modelviewInv.get();
 
 //visualize 3d axes for orientation
 drawAxes3D();
 
 //visualize vertices
 drawVertSphere();
 drawVert();

 hitDetect();
 
 // calculate z value of picked vertex in model(world) space
 if (vertexMouseOver > -1) {
   zModelMouseOver = modelZ(vertices3D[vertexMouseOver], vertices3D[vertexMouseOver+1], vertices3D[vertexMouseOver+2]);
 }
 
 // 3d object space end
 popMatrix();

 drawHitDetect();
}

void mousePressed(){
 if (mouseButton==LEFT && vertexMouseOver>-1)
 {
   vertexKlicked = vertexMouseOver;
   zModelKlick = zModelMouseOver;
   
   // calculate transformation matrix for projecting mouse coords
   // to the plane where the current selected vertex is
   // this doesn't work!
   screen2Model = modvwInv;
   screen2Model.apply(cam);
   //screen2Model.apply(proj);
   screen2Model.translate(0, 0, zModelKlick);
 }
}

void mouseReleased(){
 vertexKlicked = -1;
}

void mouseDragged() {
   if (mouseButton==LEFT && vertexKlicked>-1) {
     float scrn[] = {mouseX, mouseY, 0};
     float model[] = new float[3];
     
     // apply transformation matrices to mouse coords
     screen2Model.mult(scrn, model);
     
     vertices3D[vertexKlicked] = model[0];
     vertices3D[vertexKlicked+1] = model[1];
     vertices3D[vertexKlicked+2] = model[2];
   }
   else {
     // mouse controlled rotation
     float x1 = mouseX-pmouseX;
     float y1 = mouseY-pmouseY;
     rotX += -y1 * 0.01;
     rotY += x1 * 0.01;
   }
}


void translations() {
 translate(width/2, height/2);
 //mouse rotate
 rotateX(rotX);
 rotateY(rotY);
}

void drawAxes3D() {
 stroke(255,0,0);
 line(0,0,0, 100,0,0);
 stroke(0,255,0);
 line(0,0,0, 0,-100,0);
 stroke(0,0,255);
 line(0,0,0, 0,0,100);
}

void drawVertSphere() {
 //3d vertices3D as spheres
 noStroke();
 fill(100);
 sphereDetail(4);
 for(int i=0; i<vertices3D.length; i=i+3)
 {
   pushMatrix();
   translate(vertices3D[i], vertices3D[i+1], vertices3D[i+2]);
   sphere(3);
   popMatrix();
 }
}

void drawVert() {
 noFill();
 stroke(100, 100, 100);
 beginShape();
 for(int i=0; i<vertices3D.length; i=i+3)
 {
   vertex(vertices3D[i], vertices3D[i+1], vertices3D[i+2]);
 }
 endShape();
}

void hitDetect() {
 // mouse hit detection using screnX, screenY
 vertices2D = new int[0];
 vertexMouseOver = -1;
 
 for(int i=0; i<vertices3D.length; i=i+3) {
   int x = int(screenX(vertices3D[i], vertices3D[i+1], vertices3D[i+2]));
   int y = int(screenY(vertices3D[i], vertices3D[i+1], vertices3D[i+2]));
   
   vertices2D = append(vertices2D, x);
   vertices2D = append(vertices2D, y);
   
   if (x > mouseX-3 && x < mouseX+3 && y > mouseY-3 && y < mouseY+3) {
      vertexMouseOver = i;
   }
 }
}

void drawHitDetect() {
  if (vertexKlicked > -1) {
    stroke(255, 0, 0);
    noFill();
    ellipse(vertices2D[vertexKlicked/3*2], vertices2D[vertexKlicked/3*2+1], 30, 30);
  } else if (vertexMouseOver > -1) {
    stroke(100, 100, 100);
    noFill();
    ellipse(vertices2D[vertexMouseOver/3*2], vertices2D[vertexMouseOver/3*2+1], 20, 20);
  }
}
Re: Drag objects in 3d with the mouse
Reply #1 - Oct 2nd, 2009, 3:48pm
 
Hi, I have no idea how to fix your scaling problem, but I wanted to ask where can I see the reference for PGraphics3D?? I didn't find it on the reference page. There also many other functions and built in stuff I don't seem to able to find the documentation for.
A link or something would be very appreciated. Thanx
Re: Drag objects in 3d with the mouse
Reply #2 - Oct 23rd, 2009, 9:30am
 
Not sure how involved you want to get with the camera, but the peasycam library is really good.
Re: Drag objects in 3d with the mouse
Reply #3 - Oct 25th, 2009, 8:45am
 
MeLight
The JavaDocs for Processing can be found here.
http://dev.processing.org/reference/core/index.html

With regard to the scaling problem your post was some time ago so I don't know if you have found a solution but I found if I commented out the line
Code:
screen2Model.translate(0, 0, zModelKlick);

in the mousePressed() method it appears to work.
A simple translation in the z direction is unlikely to work unless we are looking directly down the z axia.
Page Index Toggle Pages: 1