I find that the easiest camera control to get good is to just support a rotation around X followed by a rotation around Y; this gives you pitch and yaw. For a model viewer camera, you have a distance from origin as well. Something like this might work:
public class ArcBallCamera {
float pitch;
float yaw;
float distance = 40.0f;
public void update(float dx, float dy) {
yaw += dx;
pitch += dy;
if (pitch > 80.f) pitch = 80.f;
if (pitch < -80.f) pitch = -80.f;
yaw = (float) Math.mod(yaw, 360.f);
}
public void setDistance(float d) {
distance = d;
}
public void loadCameraMatrix(GL gl) {
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glRotatef(yaw, 0, 1, 0);
gl.glRotatef(pitch, 1, 0, 0);
gl.glTranslatef(0, 0, -distance);
}
}
You call update() with dx and dy from mouse movement. You call loadCameraMatrix() to load the camera matrix into the MODELVIEW matrix.