Hi

I have written a first person camera class for android.

The class is really simple , the camera object has its three axes

X,y and Z

and there are functions to create the ModelView matrix ( i.e. calculateModelViewMatrix() ),

rotate the camera along its X and Y axis

and Translate the camera along its Z-axis.

I think that my ModelViewMatrix calulation is correct and i can also translate the camera along the Z-axis.

Rotation along x-axis seems to work but along Y-axis it gives strange results.

Also another problem with the rotation seems to be that instead of the camera being rotated, my 3d model starts to rotate instead along its axis.

I have written another implementation based on the look at point and using the openGL ES's GLU.gluLookAt( ) function to obtain the ModelView matrix but that too seems to suffer from the exactly the same problems.

Any help or ideas on the matter will be greatly appreciated.

Here is what the class looks like:

Code :

package com.droidnova.android.games.vortex; import javax.microedition.khronos.opengles.GL10; import android.util.Log; import com.surrealtech.math.util.Vector3; public class Camera4 implements ICamera { Vector3 _X = new Vector3(1,0,0); // x-axis of the camera frame Vector3 _Y = new Vector3(0,1,0); // y-axis of the camera frame Vector3 _Z = new Vector3(0,0,1); // z-axis of the camera frame Vector3 _T = new Vector3(0,1,2); // translation vector representing the position of camera frame from the world // frame's origin. float[] _matrixModelView = new float[16]; // the model-view matrix that represents the // coordinate transformation between // camera's frame & world frame float[] _matrixRotation = new float[9]; // a temporary matrix to store the rotation // matrix each time it is calculated float[] _vecTemp = new float[3]; // a temporary vector to store results /** * Constructor */ public Camera4(){ } @Override public void applyModelViewTransform(GL10 gl) { this.calculateModelViewMatrix(); gl.glMatrixMode(gl.GL_MODELVIEW); gl.glLoadMatrixf(_matrixModelView, 0); } @Override public void pitch(GL10 gl, float angle) { // calculate the 3-by-3 rotation matrix along the camera's x-axis _matrixRotation = getRotationMatrixAlong(_X, angle); // rotate the camera's y-axis float[] result = this.multiplyMV(_matrixRotation, _Y); _Y.setFloat(result); Log.e(""+this.getClass(), "|Y| = "+_Y.Magnitude()); // rotate the camera's Z-axis result = this.multiplyMV(_matrixRotation, _Z); _Z.setFloat(result); Log.e(""+this.getClass(), "|Z| = "+_Z.Magnitude()); this.applyModelViewTransform(gl); Log.e(""+this.getClass(), "X,Y,Z axes: ("+_X.x + ","+_X.y + "," + _X.z+ ") , ("+_Y.x+","+_Y.y+","+_Y.z+"), (" +_Z.x+","+_Z.y+","+_Z.z+")" ); } @Override public void yaw(GL10 gl, float angle) { // calculate the 3-by-3 rotation matrix along the camera's Y-axis _matrixRotation = getRotationMatrixAlong(_Y, angle); // rotate the camera's x-axis float[] result = this.multiplyMV(_matrixRotation, _X); _X.setFloat(result); _X.Normalise(); Log.e(""+this.getClass(), "|X| = "+_X.Magnitude()); // rotate the camera's Z-axis result = this.multiplyMV(_matrixRotation, _Z); _Z.setFloat(result); _Z.Normalise(); Log.e(""+this.getClass(), "|Z| = "+_Z.Magnitude()); this.applyModelViewTransform(gl); Log.e(""+this.getClass(), "X,Y,Z axes: ("+_X.x + ","+_X.y + "," + _X.z+ ") , ("+_Y.x+","+_Y.y+","+_Y.z+"), (" +_Z.x+","+_Z.y+","+_Z.z+")" ); } @Override public void translateZ(GL10 gl, float dist) { _T.z += dist; this.applyModelViewTransform(gl); } /** * Private method to calculate the model-view matrix based on the camera's frame axes. */ private void calculateModelViewMatrix(){ // 1st column _matrixModelView[0] = _X.x; _matrixModelView[1] = _Y.x; _matrixModelView[2] = _Z.x; _matrixModelView[3] = 0; // 2nd column _matrixModelView[4] = _X.y; _matrixModelView[5] = _Y.y; _matrixModelView[6] = _Z.y; _matrixModelView[7] = 0; // 3rd column _matrixModelView[8] = _X.z; _matrixModelView[9] = _Y.z; _matrixModelView[10] = _Z.z; _matrixModelView[11] = 0; // 4th column _matrixModelView[12] = (_T.x); _matrixModelView[13] = (_T.y); _matrixModelView[14] = (_T.z); _matrixModelView[15] = 1; } /** * * @param r An arbitrary vector in 3D space, representing the rotation axis. * @param angle The angle in degrees. * @return */ private float[] getRotationMatrixAlong(Vector3 r, double angle){ double cos = Math.cos(angle); // argument should be in radians double sin = Math.sin(angle); // argument should be in radians double t = (1-cos); // 1st column _matrixRotation[0] = (float)( cos+ t*(r.x)*(r.x) ); _matrixRotation[1] = (float)( t*(r.x)*(r.y) + r.z*sin ); _matrixRotation[2] = (float)( t*(r.x)*(r.z) - r.y*sin ); // 2nd column _matrixRotation[3] = (float)( t*(r.x)*(r.y) - r.z*sin ); _matrixRotation[4] = (float)( cos+ t*(r.y)*(r.y) ); _matrixRotation[5] = (float)( t*(r.y)*(r.z) + r.x*sin ); // 1st column _matrixRotation[6] = (float)( t*(r.x)*(r.z) + r.y*sin ); _matrixRotation[7] = (float)( t*(r.y)*(r.z) - r.x*sin ); _matrixRotation[8] = (float)( cos+ t*(r.z)*(r.z) ); return _matrixRotation; } /** * Multiply a 3-by-3 matrix with a 3_by_1 vector and return the result * as a 3-by-1 column vector * @param matrix A 3-by-3 matrix. * @param v A 3-by-1 column vector. * @return */ private float[] multiplyMV(float[] matrix, Vector3 v){ _vecTemp[0] = matrix[0]*v.x + matrix[3]*v.y +matrix[6]*v.z; _vecTemp[1] = matrix[1]*v.x + matrix[4]*v.y +matrix[7]*v.z; _vecTemp[2] = matrix[2]*v.x + matrix[5]*v.y +matrix[8]*v.z; return _vecTemp; } }