   Getting unwanted roll with my 3D space camera
  Hey guys,Been reading heaps of post hoping to find a solution to my problem so that I don't have to annoy you guys :)While many similar problems to mine are out there, and I even come upon someone with identical problem to mine which he managed to solved but didn't explain how he fixed it.Anyways I have a camera class... it has 6DOF like a spaceship.I am using Direct input (I know Direct Input is bad), and I am using matrices to do all the rotation and translation calculations.The code I have is built upon Frank Luna's and Alan Thorn's example code in their books.Anyways here is the code...MAIN APPLICATION ENTRY// Code omitted...IDirect3DDevice9 *D3DDevice = NULL;Direct3DUtility *direct3DUtility = NULL;Direct3DInput *direct3DInput;//--- Function Prototypes ---//void cleanUp();void getInput();void initStars();void renderGame();void setupGame();void updateGame();int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ){// Code omitted...MSG msg;ZeroMemory( &msg, sizeof( MSG ));while( msg.message != WM_QUIT ){if( PeekMessage( &msg, 0, 0, 0, PM_REMOVE )){TranslateMessage( &msg );DispatchMessage( &msg );}else{updateGame();renderGame();Yield();}}UnregisterClass( baseWindow->getClassName(), hInstance );return 0;}void getInput(){if( direct3DInput->keyDown( DIK_RIGHT )){camera->yaw( 0.025f );}if( direct3DInput->keyDown( DIK_LEFT )){camera->yaw( -0.025f );}if( direct3DInput->keyDown( DIK_UP )){camera->pitch( -0.025f );}if( direct3DInput->keyDown( DIK_DOWN )){camera->pitch( 0.025f );}DIMOUSESTATE2 temp = direct3DInput->getMouseXY();camera->mouseLook( temp.lX * 0.01, temp.lY * 0.01 );camera->updateViewMatrix( &D3DDevice );}void setupGame(){// Code omitted...}void renderGame(){// Code omitted...}void updateGame(){// Code omitted...}void initStars(){// Code omitted...}void cleanUp(){// Code omitted...}CAMERA.H#ifndef CAMERA_H#define CAMERA_H#include <d3dx9.h>class Camera{protected:D3DXVECTOR3 position; // Represent camera position.D3DXVECTOR3 lookAt;// Represent camera lookAt orientation.D3DXVECTOR3 right; // Represent camera right orientation.D3DXVECTOR3 up; //Represent camera up orientation.float pitchAmount; // Rotate around the X axis.float yawAmount;// Rotate arounf the Y axis.float rollAmount; // Rotate around the Z axis.D3DXMATRIX viewTransformMatrix;public:Camera();void updateViewMatrix( IDirect3DDevice9 **D3DDevice );void setPosition( float x, float y, float z );void roll( float angle );void yaw( float angle );void pitch( float angle );void strafe( float amount );void fly( float amount );void mouseStrafe( float xAmount, float yAmount );void mouseLook( float xAmount, float yAmount );void moveForward( float amount );};#endifCAMERA.CPP#include "Camera.h"Camera::Camera(){position = D3DXVECTOR3( 3.0f, 2.0f, -10.0f );right = D3DXVECTOR3( 1.0f, 0.0f, 0.0f );up = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );lookAt = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );D3DXMatrixIdentity( &viewTransformMatrix );rollAmount = yawAmount = pitchAmount = 0.0f;}void Camera::roll( float angle ){D3DXMATRIX matrix; // Matrix to store the rotation.rollAmount += angle;D3DXMatrixRotationAxis( &matrix, &lookAt, angle );D3DXVec3TransformCoord( &up, &up, &matrix );D3DXVec3TransformCoord( &right, &right, &matrix );}void Camera::yaw( float angle ){D3DXMATRIX matrix; // Matrix to store the rotation.yawAmount += angle;D3DXMatrixRotationAxis( &matrix, &up, angle );D3DXVec3TransformCoord( &lookAt, &lookAt, &matrix );D3DXVec3TransformCoord( &right, &right, &matrix );}void Camera::pitch( float angle ){D3DXMATRIX matrix;pitchAmount += angle;D3DXMatrixRotationAxis( &matrix, &right, angle );D3DXVec3TransformCoord( &up, &up, &matrix );D3DXVec3TransformCoord( &lookAt, &lookAt, &matrix );}void Camera::strafe( float amount ){position += right * amount;}void Camera::fly( float amount ){position += up * amount;}void Camera::mouseStrafe( float xAmount, float yAmount ){position += right * xAmount;position += up * yAmount;}void Camera::mouseLook( float xAmount, float yAmount ){yaw( xAmount );pitch( yAmount );}void Camera::moveForward( float amount ){position += lookAt * amount;}void Camera::updateViewMatrix( IDirect3DDevice9 **D3DDevice ){D3DXVec3Normalize( &lookAt, &lookAt );D3DXVec3Cross( &up, &lookAt, &right );D3DXVec3Normalize( &up, &up );D3DXVec3Cross( &right, &up, &lookAt );D3DXVec3Normalize( &right, &right );if( fabs( D3DXVec3Dot( &up, &right )) > 0.01 ){ D3DXVec3Cross( &lookAt, &up, &right );}float x = -D3DXVec3Dot( &right, &position );float y = -D3DXVec3Dot( &up, &position );float z = -D3DXVec3Dot( &lookAt, &position );viewTransformMatrix._11 = right.x; viewTransformMatrix._12 = up.x; viewTransformMatrix._13 = lookAt.x;viewTransformMatrix._21 = right.y; viewTransformMatrix._22 = up.y; viewTransformMatrix._23 = lookAt.y;viewTransformMatrix._31 = right.z; viewTransformMatrix._32 = up.z; viewTransformMatrix._33 = lookAt.z;viewTransformMatrix._41 = x; viewTransformMatrix._42 = y; viewTransformMatrix._43 = z;( *D3DDevice )->SetTransform( D3DTS_VIEW, &viewTransformMatrix );}void Camera::setPosition( float x, float y, float z ){// Empty stub for now}Hmmm.. I have decided not to include my class that handles all the input keyboard/mouse input for now... I don't think it is needed but if further clarification is required I will include also.So after reading heaps, I think my problem is due to the inaccuracy of floating numbers that can occur after many rotations, hence many suggestions has been that you need to normalize your camera's orientation vectors.In my own code I thought I have done this?D3DXVec3Normalize( &lookAt, &lookAt );D3DXVec3Cross( &up, &lookAt, &right );D3DXVec3Normalize( &up, &up );D3DXVec3Cross( &right, &up, &lookAt );D3DXVec3Normalize( &right, &right );if( fabs( D3DXVec3Dot( &up, &right )) > 0.01 ){ D3DXVec3Cross( &lookAt, &up, &right );}If I isolate either the pitch or yaw only then the problem doesn't happen.EXAMPLEvoid Camera::mouseLook( float xAmount, float yAmount ){yaw( xAmount );// pitch( yAmount ); ISOLATE YAW MOVEMENT ONLY}I don't want to use quartenions yet.Thanks guys.. appreciate the assistance.   
  If you are saying that when only performing sequential pitch and yaw rotations you are getting rolling of the camera, than this is completely normal and is what should happen.I posed this for someone to explain in a similar problem a while back, and it seemed to help them, so maybe this will help you understand what is happening:Quote:As I believe was said earlier, if you use a 6 DOF camera, you will get this appearance of rolling. This is supposed to happen.You can do a little experiment to prove it to yourself:1) Hold your right arm out in front of you with palm facing the floor. The tips of your fingers are camera "out", and the top of your hand is camera "up".2) Pitch your "camera" up 90 degrees by bending your elbow. Now your fingertips are pointing towards the ceiling, and your palm is facing in front of you.3) Now yaw your arm 90 degrees to the left, so that your fingertips are pointing to the left, and your palm is still facing front.4) Now pitch your camera back down 90 degrees. Your camera "out" (fingertips) are pointing the same way as when you started, but your "up" has rolled 90 degrees.This should help you understand why your camera is rolling when you're doing "only pitch and yaw"A Similar Thread;  Hehe,This proved that my arms are not flexible!But I managed it, although I did end up with my fingers out and my palm has in fact rotated 90 degrees I am still having hard time visualizing why this would be normal.Any other analogies that may help me understand this better?   ;Quote:Any other analogies that may help me understand this better?I think karwosts' example is about as clear as it gets. If you pitch 90 degrees, then roll 90 degrees, then pitch -90 degrees, you will be pointing in the same direction you were initially, but your up vector will have rotated 90 degrees. In other words, you will have rolled 90 degrees (relatively speaking), even though only yaw and pitch were applied. Note that it might be easier to visualize the effect if you use an object (e.g. a toy car or airplane, if you have one ;), rather than your hand.Note that you don't need quaternions for this. Also, it's not a numerical issue; it is important to normalize your orientation periodically when incremental rotations are used, but that's not why successive yaw and pitch results in perceived roll.If you're looking for a way to have full 6DOF motion but still remain more or less upright, one option would be to add 'auto-leveling' to your simulation (this might be mentioned somewhere in the thread linked to previously).   ;  To get the effect I believe you are after you need to adjust your Yaw function so it rotates around the world up vector, not the up vector of the camera itself.It's as people above have mentioned, changing the pitch will move the camera's up vector so that it's pointing behind you, so when you apply yaw to the vector it will cause your camera to roll.If you apply yaw around the worlds up vector e.g Vector3( 0, 1, 0 ), then you will won't get the roll you are seeing.   ;  Of course you can use that how you wish, but that's your problem.If you think about it, you don't want to rotate around the camera's up vector, what you really want is to rotate around the world.   ;Quote:Original post by jykQuote:Any other analogies that may help me understand this better?I think karwosts' example is about as clear as it gets. If you pitch 90 degrees, then roll 90 degrees, then pitch -90 degrees, you will be pointing in the same direction you were initially, but your up vector will have rotated 90 degrees...I don't know why but when I read this line it immediately made sense to me! I think I was trying to visual too much when I did the arm exercise, and hence the point karwosts was trying to make was lost on me, or it could be that my brain works 24 hours slower than the rest of you guys hehe.Anyways, it does make sense now.Just wanted to say thanks!   