0
\$\begingroup\$

I am implementing a camera in opengl for an android game and am having problems getting the pitch/yaw/roll of the camera correct. I have read many tutorials on quaternions and have implemented a basic camera based on this link.

Everything works well except for when I pitch and yaw I get unwanted roll. I have read things that say I need to apply the pitch/yaw rotation together to prevent this, and other things that said not to track individual changes to angles, but I'm not sure what they mean or how to extend this implementation to mine. I am new to this type of math so any help would be appreciated.

My goal is to have a camera that can rotate similar to how a space ship would rotate - I want the camera to be able to rotate 360 degrees in all directions and turn upside-down - which is why I was rotating the upVector too.

Any suggestions on what I can do to not have the camera roll when rotating around the y and y axes?

Thanks!

Here is the code that translates user input into two angles, and rotates the lookVector, upVector, and rightVector of the camera. My problem is the camera is also rolling when I just pitch and yaw.

// Java
// Camera uses a position vector, lookAt vector, and upVector
// eventually calls Matrix.setLookAtM()

Camera c = mRenderer.theCamera;


// PVector is a class that implements a 3 dimensional vector

float thetaX = getTouchChange(...); // set by the user touching the screen
float thetaY = getTouchChange(...); // set by the user touching the screen

// I keep 3 vectors in the camera class, one points up, one points right,
// and the 3rd is the point I am looking at



///////////////////////////////////////////////
// Pitch - rotate the up and look around right
///////////////////////////////////////////////
// get up and look vectors
PVector lookVector = PVector.sub(c.getLookAtPoint(), c.getLocation());
PVector otherVector = c.getUpDirection();
// get axis
PVector rAxis = c.getRightDirection();
rAxis.normalize();
// rotate look
PVector rotated = Quaternion.rotateVector(lookVector, rAxis, thetaY);
// Add back camera location to convert vector to actual look points
rotated.add(mRenderer.theCamera.getLocation());
c.setLookAtPoint(rotated);
// rotate up
rotated = Quaternion.rotateVector(otherVector, rAxis, thetaY);
rotated.normalize();
c.setUpDirection(rotated);

///////////////////////////////////////////////
// Yaw - rotate the look and right around up 
///////////////////////////////////////////////
// get up and look vectors
lookVector = PVector.sub(c.getLookAtPoint(), c.getLocation());
otherVector = c.getRightDirection();
// get axis
rAxis = c.getUpDirection();
rAxis.normalize();
// rotate look
rotated = Quaternion.rotateVector(lookVector, rAxis, thetaX);
// Add back camera location to convert vector to actual look points
rotated.add(mRenderer.theCamera.getLocation());
c.setLookAtPoint(rotated);
// rotate right
rotated = Quaternion.rotateVector(otherVector, rAxis, thetaX);
rotated.normalize();
c.setRightDirection(rotated);

In my rendering code I update the camera orientation by calling the following

// called in onSurfaceChanged
Matrix.frustumM(m3DProjectionMatrix, 0, -screenRatio, screenRatio, -1, 1, 1, 70);


// called in onDrawFrame
Matrix.setLookAtM(m3DViewMatrix, 0, 
    theCamera.getLocation().x, theCamera.getLocation().y, theCamera.getLocation().z, 
    theCamera.getLookAtPoint().x, theCamera.getLookAtPoint().y, theCamera.getLookAtPoint().z, 
    theCamera.getUpDirection().x, theCamera.getUpDirection().y, theCamera.getUpDirection().z);

Matrix.multiplyMM(m3DMVPMatrix, 0, m3DProjectionMatrix, 0, m3DViewMatrix, 0);

// m3DMVPMatrix is eventually passed to the shader along with the shape data
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I am having the exact same problem with my openGL app in C#. I have been reading about it and some people have suggested that this is actually realistic.

In the local frame of reference changing the x and y axis at the same time will also cause a z rotation. You can test this with a pen. Point it up in the air with the clip facing you. Rotate it so the point is facing you and the clip is pointing down. Then rotate it so the point is facing right and the clip still down. Then rotate it so the point is facing up. The clip is now facing right, that was a z rotation even though in the pens frame of reference you only performed x and y rotations.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .