I am making a game that uses the entire planet for its map. I used close technology using this technique , and now I am adding camera controls.
The sphere has sizes from 1 to -1, so each point on the sphere is also a normalized vector. At any time, one of the hexagonal tiles that make up the sphere is the “selected” tile. The player can then move the selection to adjacent tiles using the d-pad. They can also independently rotate the camera around using the analog joystick.
I need to do two things regarding the selected tile and camera. First, I need to be able to switch the selection to the tile closest to the camera. Secondly, I need to focus the camera on a dedicated plate
The sphere is at the origin, and the camera is at the point (0,0,1). The graphics engine allows me to rotate the camera around the X and Y axes, so to solve the first problem, I use quaternions to rotate the point (0,0,1) around the x axis and then the y axis to find the point in 3D space. where the camera is located:
private Quaternion quat = new Quaternion(0,0,0,0); private double[] output = new double[4]; private double[] cam = new double[3]; private double camX = 0; private double camY = 0; private double camZ = 1; private double[] getCamPosition(){ quat.setAxisAngle(1, 0, 0, Math.toRadians(-graphicsEngine.getRotationX())); quat.RotateVector(camX, camY, camZ, output); cam[0] = output[0]; cam[1] = output[1]; cam[2] = output[2]; quat.setAxisAngle(0, 1, 0, Math.toRadians(-graphicsEngine.getRotationY())); quat.RotateVector(cam[0], cam[1], cam[2], output); cam[0] = output[0]; cam[1] = output[1]; cam[2] = output[2]; return cam; }
Then I compare the distances between the centroid of each tile and the camera position and select the tile that is closest to the selected tile.
However, to solve the second problem, I want to do the opposite. I want to take a centroid (which is already in the form of a normalized vector) and find out the rotation around X and the rotation around Y, necessary for the camera to be focused on it.
At the moment, I rotate the camera back (0,0,1), then getting the angle along the X axis and Y axis between (0,0,1) and the centroid and using this to rotate the camera a second time:
private double[] outputArray = new double[2]; public void centreOnSelected(double camX, double camY, double camZ){ selectedTile.getCentroidAngles(outputArray); outputArray[0] -= Math.atan2(camZ, camY); outputArray[1] -= Math.atan2(camX, camZ);
and in selected (tile class)
void getCentroidAngles(double[] outputArray){ outputArray[0] = Math.atan2(centroidZ, centroidY); outputArray[1] = Math.atan2(centroidX, centroidZ); }
The problem is that this will not work (the x axis always seems missing), and I am sure that this is due to the mathematics of obtaining angles and performing rotating
Note: the graphics engine rotates first around the X axis, then around Y:
gl.glRotatef(mRotateX, 1, 0, 0); gl.glRotatef(mRotateY, 0, 1, 0);
The centroids are in the right place, and the camera definitely rotates by the right amount, so I'm sure the problem is not in the graphics engine. This is also not re-positioning the camera (0,0,1), since I checked this by running the program
I also made a video to illustrate the problem:
http://www.youtube.com/watch?v=Uvka7ifZMlE
This listened to me for several days, so any help in getting this fix would be greatly appreciated!
Thanks james