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 › Camera Orbit based on mouseX,Y
Page Index Toggle Pages: 1
Camera Orbit based on mouseX,Y (Read 1305 times)
Camera Orbit based on mouseX,Y
Oct 1st, 2007, 7:38am
 
I'm trying to setup camera controls like Maya so the camera can orbit, pan, and zoom. I'm having difficulty with the orbit part- rotating around the y and x axis seems to be doing weird things. There's probably a large misunderstanding on my part about the math.

This code works for rotating around the Y exactly like I want. When I uncomment the X bit, weird stuff happens. If someone could correct my code or point me towards the knowledge I'd appreciate it tremendously!

Thanks.
-shawn

Code:
import processing.opengl.*;
int canvasSize = 512;
int gridLines = 11;
float gridSize = 100;

float x = 0;
float y = 25;
float z = -75;
float x2 = 0;
float y2 = 25;
float z2 = -75;
float rotX = 0;
float rotY = 0;

int mousePressedX, mousePressedY;
int dragLengthX, dragLengthY;

void setup() {
size(canvasSize, canvasSize, OPENGL);
noFill();
noStroke();
}

void draw() {
background(255);

// camera
beginCamera();
if(mousePressed)
camera(x2, y2, z2, 0, 20, 0, 0, -1, 0);
else
camera(x, y, z, 0, 20, 0, 0, -1, 0);
perspective(1.235, 1, .1, 500);
endCamera();

// draw grid
pushMatrix();
translate(-gridSize/2, 0, -gridSize/2);
stroke(200, 100, 100, 50);
strokeWeight(1);
float gridSpacing = gridSize / (float)gridLines;
for (int i=0; i<gridLines+1; i++) {
line(0, 0, i*gridSpacing, gridSize, 0, i*gridSpacing);
line(i*gridSpacing, 0, 0, i*gridSpacing, 0, gridSize);
}
popMatrix();

// draw box
pushMatrix();
translate(0, 25, 0);
noFill();
stroke(0, 0, 0);
box(50, 50, 50);
popMatrix();

// draw one side red
pushMatrix();
noStroke();
fill(220, 5, 15, 50);
beginShape(QUADS);
vertex(-25,0,25);
vertex(-25,50,25);
vertex(25,50,25);
vertex(25,0,25);
endShape();
popMatrix();
}

void mousePressed() {
mousePressedX = mouseX;
mousePressedY = mouseY;
}

void mouseReleased() {
z=z2;
x=x2;
y=y2;
}

void mouseDragged() {
dragLengthX = mouseX - mousePressedX;
dragLengthY = mouseY - mousePressedY;

// rotate around Y axis
rotY = (float)dragLengthX / (float)canvasSize * PI;
z2 = z*cos(rotY) - x*sin(rotY);
x2 = z*sin(rotY) + x*cos(rotY);

// rotate around X axis
//rotX = (float)dragLengthY / (float)canvasSize * PI;
//y2 = y*cos(rotX) - z*sin(rotX);
//z2 = y*sin(rotX) + z*cos(rotX);
}
Re: Camera Orbit based on mouseX,Y
Reply #1 - Oct 1st, 2007, 9:50am
 
You may find it easier to store a "current angle" which you increment/decrement with mouse dragged, and then work out the x/z positions based on that, which is much simpler.
Re: Camera Orbit based on mouseX,Y
Reply #2 - Oct 1st, 2007, 5:03pm
 
you'll need to feed the updated values of x/y/z into subsequent rotations, for example "x=x2; z=z2;".  otherwise you'll be getting the new x from the yrotation, but the z will be overwritten by the xrotation - leaving you with gibberish.
Re: Camera Orbit based on mouseX,Y
Reply #3 - Oct 1st, 2007, 6:06pm
 
Davbol- thanks, that was the rotation issue! Things now work 99% as expected- as for the x rotation- when the camera is looking straight down on the cube, it seems to spin a bit on the Y axis. There seems to be no graceful way to orbit 360 degrees on the X like you can on the Y.

John- not sure exactly what you mean. With the mouse drag I'm going for the distance dragged as a percentage of the screen width/height to determine the amount of rotation. If there is a simpler way do tell!

Code:
import processing.opengl.*;
int canvasSize = 512;
int gridLines = 11;
float gridSize = 100;

float x = 0;
float y = 25;
float z = -75;
float x2,y2,z2;
float x3,y3,z3;
float rotX, rotY;

int mousePressedX, mousePressedY;
int dragLengthX, dragLengthY;

void setup() {
size(canvasSize, canvasSize, OPENGL);
noFill();
noStroke();
x3 = x2 = x;
y3 = y2 = y;
z3 = z2 = z;
}

void draw() {
background(255);

// camera
beginCamera();
if(mousePressed)
camera(x3, y3, z3, 0, 20, 0, 0, -1, 0);
else
camera(x, y, z, 0, 20, 0, 0, -1, 0);
perspective(1.235, 1, .1, 500);
endCamera();

// draw grid
pushMatrix();
translate(-gridSize/2, 0, -gridSize/2);
stroke(200, 100, 100, 50);
strokeWeight(1);
float gridSpacing = gridSize / (float)gridLines;
for (int i=0; i<gridLines+1; i++) {
line(0, 0, i*gridSpacing, gridSize, 0, i*gridSpacing);
line(i*gridSpacing, 0, 0, i*gridSpacing, 0, gridSize);
}
popMatrix();

// draw box
pushMatrix();
translate(0, 25, 0);
noFill();
stroke(0, 0, 0);
box(50, 50, 50);
popMatrix();

// draw one side red
pushMatrix();
noStroke();
fill(220, 5, 15, 50);
beginShape(QUADS);
vertex(-25,0,25);
vertex(-25,50,25);
vertex(25,50,25);
vertex(25,0,25);
endShape();
popMatrix();
}

void mousePressed() {
mousePressedX = mouseX;
mousePressedY = mouseY;
}

void mouseReleased() {
z=z3;
x=x3;
y=y3;
}

void mouseDragged() {
dragLengthX = mouseX - mousePressedX;
dragLengthY = mouseY - mousePressedY;

// rotate around Y axis
rotY = (float)dragLengthX / (float)canvasSize * PI;
z2 = z*cos(rotY) - x*sin(rotY);
x2 = z*sin(rotY) + x*cos(rotY);
y2 = y;

// rotate around X axis
rotX = (float)dragLengthY / (float)canvasSize * PI;
y3 = y2*cos(rotX) - z2*sin(rotX);
z3 = y2*sin(rotX) + z2*cos(rotX);
x3 = x2;
}
Re: Camera Orbit based on mouseX,Y
Reply #4 - Oct 1st, 2007, 6:52pm
 
Bascally you have currentRotation as a float angle, and then for each pixel dragged, add 0.001 (or subtract) to currentRotation, and then x=radius*cos(currentAngle); and y=radius*sin(currentAngle);
Re: Camera Orbit based on mouseX,Y
Reply #5 - Oct 2nd, 2007, 7:04am
 
Thanks for your patience John! Something like this then:

Code:
import processing.opengl.*;
int canvasSize = 512;
int gridLines = 11;
float gridSize = 100;

float x = 0;
float y = 25;
float z = -75;
float currentAngle = 0;
int mouseXOld, mouseYOld;

void setup() {
size(canvasSize, canvasSize, OPENGL);
noFill();
noStroke();
}

void draw() {
background(255);

// camera
beginCamera();
camera(100*cos(currentAngle), y, 100*sin(currentAngle), 0, 20, 0, 0, -1, 0);
perspective(1.235, 1, .1, 500);
endCamera();

// draw grid
pushMatrix();
translate(-gridSize/2, 0, -gridSize/2);
stroke(200, 100, 100, 50);
strokeWeight(1);
float gridSpacing = gridSize / (float)gridLines;
for (int i=0; i<gridLines+1; i++) {
line(0, 0, i*gridSpacing, gridSize, 0, i*gridSpacing);
line(i*gridSpacing, 0, 0, i*gridSpacing, 0, gridSize);
}
popMatrix();

// draw box
pushMatrix();
translate(0, 25, 0);
noFill();
stroke(0, 0, 0);
box(50, 50, 50);
popMatrix();

// draw one side red
pushMatrix();
noStroke();
fill(220, 5, 15, 50);
beginShape(QUADS);
vertex(-25,0,25);
vertex(-25,50,25);
vertex(25,50,25);
vertex(25,0,25);
endShape();
popMatrix();
}

void mouseDragged() {
if (mouseX - mouseXOld > 0)
currentAngle -= .077;
else
currentAngle += .077;

mouseXOld = mouseX;
}


But what do I do for the rotation around the X axis?
Re: Camera Orbit based on mouseX,Y
Reply #6 - Oct 3rd, 2007, 7:12pm
 
the one place i know that does this is xscreensaver, specifically this file:

http://www.filewatcher.com/p/xscreensaver-4.05.tar.gz.2914308/xscreensaver-4.05/hacks/glx/trackball.c.html

/*
* Ok, simulate a track-ball.  Project the points onto the virtual
* trackball, then figure out the axis of rotation, which is the cross
* product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
* Note:  This is a deformed trackball-- is a trackball in the center,
* but is deformed into a hyperbolic sheet of rotation away from the
* center.  This particular function was chosen after trying out
* several variations.
*
* It is assumed that the arguments to this routine are in the range
* (-1.0 ... 1.0)
*/

which is beyond me 8)

lots of google hits for 'virtual trackball' though, which is what this is.

http://viewport3d.com/trackball.htm is good.
Page Index Toggle Pages: 1