Being new to OpenGL I quickly realized how much more difficult it is to rotate in 3D space than one would think. I checked out tons of tutorials and they suggested quaternions. So I did some research on them and the closest I came to was this:

SurfaceView
Code :
private float angleX;
private float angleY;
private float angleZ;
 
public boolean onTouchEvent(MotionEvent e) {
	switch (e.getAction()) {
		case MotionEvent.ACTION_DOWN:
			oldX = e.getX();
			oldY = e.getY();
			break;
		case MotionEvent.ACTION_MOVE:
			angleY += (oldX - e.getX()) * 0.1;
			angleX += (oldY - e.getY()) * 0.1;
 
			oldX = e.getX();
			oldY = e.getY();
 
			break;
	}
	return true;
}

Renderer
Code :
public void onDrawFrame(GL10 gl) {
	gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
 
	//gl.glMatrixMode(GL10.GL_MODELVIEW);
	//gl.glLoadIdentity();
 
	gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
	gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
 
	Vec3D rotX, rotY, rotZ;
	Quaternion quatX, quatY, quatZ, rotQuat;
	Matrix4x4 m;
 
	float ax = angleX * DEG_TO_RAD;
	float ay = angleY * DEG_TO_RAD;
	float az = angleZ * DEG_TO_RAD;	
 
	rotX = Vec3D.Z_AXIS.copy().rotateX(ax);
	rotY = Vec3D.X_AXIS.copy().rotateY(ay);
	rotZ = Vec3D.X_AXIS.copy().rotateZ(az);
 
	quatX = new Quaternion(1, new Vec3D(0, 0, 0));
	quatX.set(rotX.dot(Vec3D.Z_AXIS.copy()), rotX.cross(Vec3D.Z_AXIS.copy()));
 
	quatY = new Quaternion(1, new Vec3D(0, 0, 0));
	quatY.set(rotY.dot(Vec3D.X_AXIS.copy()), rotY.cross(Vec3D.X_AXIS.copy()));
 
	quatZ = new Quaternion(1, new Vec3D(0, 0, 0));
	quatZ.set(rotZ.dot(Vec3D.X_AXIS.copy()), rotZ.cross(Vec3D.X_AXIS.copy()));
 
	rotQuat = quatX.multiply(quatY).multiply(quatZ);
	m = rotQuat.toMatrix4x4();
 
	FloatBuffer rotMatrix;
	rotMatrix = ByteBuffer.allocateDirect(4 * 4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
	rotMatrix.put(
		new float[] {
				(float)m.matrix[0][0], (float)m.matrix[0][1], (float)m.matrix[0][2], (float)m.matrix[0][3],
				(float)m.matrix[1][0], (float)m.matrix[1][1], (float)m.matrix[1][2], (float)m.matrix[1][3],
				(float)m.matrix[2][0], (float)m.matrix[2][1], (float)m.matrix[2][2], (float)m.matrix[2][3],
				(float)m.matrix[3][0], (float)m.matrix[3][1], (float)m.matrix[3][2], (float)m.matrix[3][3]
		}
	);
	rotMatrix.flip();
 
	gl.glPushMatrix();
	gl.glTranslatef(0, 0, -3.0f);
	gl.glMultMatrixf(rotMatrix);
	gl.glTranslatef(0, 0, 3.0f);
 
	object.draw(gl);
 
	gl.glPopMatrix();
}

When I run this code, I get a slightly better effect than using 3 separate glRotatef calls. Before, when I rotated the object about an axis over 180 degrees, the other axis would be reversed to the viewer since, to my understanding, the axes are relative to the object. With this code, rotating about the y-axis works the way I want it to regardless of the orientation: it rotates relative to the user. However, I still have a problem when the rotation on the y-axis is greater than 180: the x-axis rotates the opposite way that it intuitively should to the user.

What could I change to fix this problem? Thanks