(Processing)How to move a 3D object according to the screen's XY axis, instead of the world's X,Y,Z(PeasyCam)

2.1k views Asked by At

Im writing a 3D sketch in which the user rotates the camera with peasyCam while left clicking and moving the mouse. The thing is that I want to move the objects while right click is pressed so that the user can drag the object across the screen's X and Y axis. Of course I know how to use mouseX and mouseY inputs to modify the translation but only across the 3D space coordinates as it shows on the GIF below:

example code of whats happening in the image:

import peasy.*;
import peasy.org.apache.commons.math.*;
import peasy.org.apache.commons.math.geometry.*;

PeasyCam cam;

float x=15;float y=15; float z=15;
float e;

void setup(){
  size (700,700,P3D);
  cam = new PeasyCam(this, 200);
  cam.setRightDragHandler(null);


}
void draw(){
  background(0);
  pushMatrix();
  translate(5, 5, 0);
  fill(255);
  stroke(255);
  sphere(5);
  popMatrix();
  pushMatrix();
  fill(255,0,0);
  stroke(255,0,0);
  translate(x, y, z);
  sphere(5);
  popMatrix();
  stroke(0,0,255);
  line(5,5,0,x,y,z);
  //obvoiusly not working method
  if(mousePressed && (mouseButton == RIGHT)){
    x= x+(mouseX-pmouseX);
    y= y+(mouseY-pmouseY);
  }
}
void mouseWheel(MouseEvent event) {
  e = event.getCount();
  z=z+e;
  println(e);
}
void mousePressed(){
  if (mouseButton==RIGHT){
    cam.setActive(false);
  }
}
void mouseReleased(){
 cam.setActive(true);
}

What I would need is to be able to drag the sphere only on the screens X/Y axis, at a fixed Z just like image below shows(simple simulation I made of the behaviour im looking for).

PeasyCam is for exploring the 3D space. The question might be difficult to undesrtand. The problem is about moving the object on the 3D world, using the screen/canvas 2D coordinates to make the object follow the cursor's movement. If the mouse goes to the left (x axis decreases), the object should move to the left on the screen, and not just on the worlds X axis. This is how the second example image behaves, but achieved by just simulating the 3D space with no actual rotations to the x,y,z axis.

I've been scratching my head with this thing and I cant seem to figure it out. I wouldn't have asked here otherwise. Thanks in advance guys.

2

There are 2 answers

13
Kevin Workman On

PeasyCam is a library that gives you a camera that by default is controlled by the mouse. This allows you to render 3D scenes and not worry about the camera, since the library handles it for you.

But it sounds like that's not what you want. You want to render a 3D scene and use the mouse to control the position of the shapes in that scene. Basically, your controls are fighting with the default controls provided by the PeasyCam library.

I see that you've already tried disabling the right-click controls here:

cam.setRightDragHandler(null);

So at the very least you probably want to do the same thing with the left drag handler.

But at that point, why are you using the PeasyCam library at all?

And even if you disable the default left controls, you'll notice that the dragging of shapes is "exaggerated" because the camera is closer to the red shape, so moving it a little bit looks like it's moving more. Just like an object right in front of your face looks like it's moving a lot more than an object that's far away.

It sounds like what you really want to do is get rid of the PeasyCam library, and then use standard Processing functions to calculate the position of the spheres based on the user input. Check out the modelX(), modelY(), and modelZ() function in the reference.

Edit: Here is a simple example that shows the model functions in action:

float x;
float y;

void setup() {
  size (700, 700, P3D);
}
void draw() {
  background(0);

  pushMatrix();
  translate(width/2, height/2, 0);
  fill(255);
  stroke(255);
  sphere(5);
  popMatrix();

  fill(255, 0, 0);
  stroke(255, 0, 0);

  if (mousePressed) {
    x= modelX(mouseX, mouseY, 0);
    y= modelY(mouseX, mouseY, 0);
  }
  translate(x, y, 15);
  sphere(5);
}

spheres

0
Jay Babani On

May be you should be looking in beginHUD() and endHUD();

Here is the example code: (Code from https://forum.processing.org/one/topic/2-questions-on-camera-view.html)

import peasy.*;
PeasyCam cam;

void setup() {
  size(300,200,P3D);
  // either put it here like this:
  // cam = new PeasyCam(this, 50, 0, 0, 100);
  cam = new PeasyCam(this, 0, 0, 0, 100);
  cam.setMinimumDistance(50);
  cam.setMaximumDistance(500);
  // or separate like this:
  cam.lookAt(50,0,0);
}

void draw() {
  background(0);

  //3D object
  pushMatrix();
  fill(255,0,0);
  translate(50,0,0);
  rotateX(-.5);
  rotateY(-.5);
  box(30);
  popMatrix();
 
  //2D object that is not affected  by the camera
  cam.beginHUD();
  fill(0,0,255);
  rect(200, height/2 -25 , 50, 50);
  cam.endHUD();
}