3
\$\begingroup\$

First off, I'm sorry if there are duplicates of this. I did an extensive Google search but was unable to find anything that made sense to me. (I am new to 3D rendering and such.)

I want to make a first person camera that the user can control with the mouse. My current implmentation in Processing looks like this:

PMatrix3D cam;
int oldMouseX=0, oldMouseY=0;
void setup(){
    // ...
    cam = new PMatrix3D();
}
void draw(){
    // ...
    int deltaX=oldMouseX-mouseX;
    int deltaY=oldMouseY-mouseY;
    oldMouseX=mouseX;
    oldMouseY=mouseY;
    cam.rotateY((PI/600)*deltaX);
    cam.rotateX((PI/600)*deltaY);
    PVector x = cam.mult(new PVector(1, 0, 0), new PVector(0, 0, 0));
    PVector y = cam.mult(new PVector(0, 1, 0), new PVector(0, 0, 0));
    PVector d = x.cross(y); d.normalize(); d.mult(R);
    float fov = PI/3.0;
    float cameraZ = (height/2.0) / tan(fov/2.0);
    perspective(fov, float(width)/float(height), cameraZ/10.0, cameraZ*1000.0);
    camera(0, 0, 0, d.x, d.y, d.z, y.x, y.y, y.z);
    // render objects
}

It works well, but there is a problem. When the mouse is moved along the x-axis of the screen, and then the y-axis, or in some way one axis at a time, the camera rolls. I understand that 3D rotation is supposed to work like that, 2 consecutive rotations around 2 axes make a rotation around the third. The problem is that once the camera is in this rolled state, it is difficult to get it to be straight again.

How can I make it so it is easy to point the camera in any direction? Please explain in easy to understand terms, if possible.

Also, I am a bit confused on

cam.rotateY((PI/600)*deltaX);
cam.rotateX((PI/600)*deltaY);

Before, I had it as

cam.rotateX((PI/600)*deltaX);
cam.rotateY((PI/600)*deltaY);

But that cause the x and y axes to be switched. (i.e., moving the mouse horizontally caused the camera to rotate vertically.) Why is this?

\$\endgroup\$

migrated from stackoverflow.com Dec 29 '13 at 8:09

This question came from our site for professional and enthusiast programmers.

  • \$\begingroup\$ Judging by the amount of new posts on Stack Overflow, I think a lot of people have time on their hands to code during Christmas. Especially non Christians. \$\endgroup\$ – DankMemes Dec 24 '13 at 20:24
  • \$\begingroup\$ Well, "Happy Holidays" then :P \$\endgroup\$ – Moo-Juice Dec 24 '13 at 20:25
  • \$\begingroup\$ peasycam is a library for that... If you like :) \$\endgroup\$ – v.k. Dec 25 '13 at 0:09
  • \$\begingroup\$ Thanks! I'll try it. But in the meantime can you explain how this is supposed to work? \$\endgroup\$ – DankMemes Dec 26 '13 at 23:04
  • \$\begingroup\$ it seems you are having a gimbal lock, but I am not 100% sure from your description. Maybe you need to check this gamedev.stackexchange.com/questions/67199/… \$\endgroup\$ – concept3d Dec 29 '13 at 8:47
1
\$\begingroup\$

You can use just the camera() method to change the perspective more easily.

To use it, you probably want two variables: rotationAngle and elevationAngle. Moving the mouse sideways changes rotationAngle between 0 and TWO_PI. You can then set variable centerY to sin(rotationAngle) and centerX to cos(rotationAngle). Moving the mouse up and down would change elevationAngle to anywhere between 0 and PI. Multiply centerX and centerY by sin(elevationAngle) and set centerZ to -cos(elevationAngle). You can then call camera() with the calculated values.

Final code:

float rotationAngle;
float elevationAngle;

float centerX;
float centerY;
float centerZ;

void setup() {
  // ...
}

void draw() {
  // ...
  updateCamera();
  // render objects
}

void updateCamera() {
  rotationAngle = map(mouseX, 0, width, 0, TWO_PI);
  elevationAngle = map(mouseY, 0, height, 0, PI);

  centerX = cos(rotationAngle) * sin(elevationAngle);
  centerY = sin(rotationAngle) * sin(elevationAngle);
  centerZ = -cos(elevationAngle);

  camera(0, 0, 0, centerX, centerY, centerZ, 0, 0, 1);
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.