I think the problem is that your Euler angles are specified in world coordinate system but they have to be specified in camera coordinate system. You need to store in camera class ist coordinate system as a three vectors:
:arrow: look - camera z axis
:arrow: up - camera y axis
:arrow: right - camera x axis
So, rotating along y axis means rotating along camera up vector. Each time camera rotates along one of its vectors you must update the other two. Then you create proper viewing matrix from look, up and right vectors and send it to OpenGL.
Here is an example of rotating along camera Y axis
Code:
procedure TCamera.RotateY(angle : single);
var
rot : TQuaternion;
begin
//create rotation quaternion from angle and camera up (Y) axis
rot := quatFromAxisAngle(fUp,angle);
//rotate look and right vectors
look := rotateVector(rot,look);
right := rotateVector(rot,right); //or right := CrossProduct(look,up);
normalize(look);
normalize(right);
end;
The right, up and look vectors are columns of a rotation matrix.
Here is my code for setting such matrix for OpenGL (including translation)
My code is based on this sample
Code:
procedure TCamera.SetView;
var
viewMat : TMatrix44;
_rp,_lp,_up : single;
begin
_rp := vecDot(fRight,fPos);
_up := vecDot(fUp,fPos);
_lp := vecDot(fLook,fPos);
viewMat[0] := fRight.x; viewMat[1] := fUp.x; viewMat[2] := -fLook.x;
viewMat[4] := fRight.y; viewMat[5] := fUp.y; viewMat[6] := -fLook.y;
viewMat[8] := fRight.z; viewMat[9] := fUp.z; viewMat[10] := -fLook.z;
viewMat[12] := -_rp; viewMat[13] := -_up; viewMat[14] := _lp; viewMat[15] := 1.0;
glMultMatrixf(@viewMat);
end;
Two more things:
1. You may want to get rid of minus signs in the code above.
2. Such camera may not be good for your FPS mode. In this case instead of rotating along up vector you should always rotate along (0,1,0) vector.
(This is how I did my FPS camera)
Bookmarks