I'm trying to have a camera orbit a planet in a JOGL solar system model but the planet doesn't want to stay in the center of view. The camera should basically follow a perfect circle around the planet, literally orbiting it on a fixed radius. The planet should appear consistently in the center of the screen but it's not staying there. I've tried to figure out if there's a distance between the calculated position of the planet and the actual position of the planet or if I need to use some trig manipulation but all I get is just a more messed up camera and planet.
==========EDIT==================
I switched to using gluLookAt and made sure that the order of function calling is as follows:
- Projection matrix (gluPerspective, not included in the edit)
- modelview matrix (gluLookAt)
- Transformations (rotate, translate)
- Actually drawing the planet (gluSphere)
But the camera is following an erroneous path as if near the origin. What I'm seeing is (I think) the solar system model from the inside of the sun with the camera's back to the origin.
Here's my display function
public void display(GLAutoDrawable drawable) {
gl = initMatrix(drawable, GL2.GL_MODELVIEW);
// Calculates the orbital and rotational angles of each planet
for(Planet art : artbook) {
orbitPlanet(art);
art.rotate(frameCount);
}
//The planet the camera is tracking is Earth
Planet earth = artbook.get(3);
float planetX = earth.getX(),
planetZ = earth.getZ(),
rotation = earth.getRotation(),
camOffset = 0.1f, //radius of camera's distance from earth
planetRadius;
//determine and set the camera coordinates, focal point
float camX = planetX + (float) (camOffset * Math.cos(rotation)),
camZ = planetZ + (float) (camOffset * Math.sin(rotation));
System.out.println("Camera located at < " + camX + ", 1, " + camZ + " >");
System.out.println("Camera focused at < " + planetX + ", 1, " + planetZ + " >\n");
glu.gluLookAt(camX, 0.0f, camZ, planetX, 0.0f, planetZ, 0.0f, 1.0f, 0.0f);
//Draw each planet
for(Planet art : artbook) {
returnToOrigin();
gl.glTranslatef(planetX, 0.0f, planetZ); //orbit
gl.glRotatef(-rotation, 0.0f, 1.0f, 0.0f); //rotation
setColor(art);
glu.gluSphere(quad, planetRadius, 10, 10);
}
frameCount += 1;
}
This orbit function finds the current orbital angle the planet makes with the sun
private void orbitPlanet(Planet art) {
float sunRadius = 109.3f,
radius = art.getRadius(),
offset = art.getOffset(),
orbit;
//if the planet isn't the sun, skew the offset
float skew = sunRadius + radius;
if(radius != sunRadius) offset += skew;
//Get the new orbital position of the planet
orbit = art.orbit(frameCount) % 360;
//set the position of the planet
float x = (float) (offset * Math.cos(Math.toRadians(orbit)));
float z = (float) (offset * Math.sin(Math.toRadians(orbit)));
art.setX(x);
art.setZ(z);
}
And here's the Planet class function that determines the orbital angle during a given frame.
public float orbit(float frameCount) {
//find the new orbit angle theta and the delta between the current and new orbit
float theta = frameCount * 1/(this.orbitRate);
this.orbit = theta;
return this.orbit;
}
Orbiting a rotating planet around its axis {0,1,0} that itself is orbiting the sun (at origin {0,0,0}).
The general algorithm would be
then (before going into details) the steps would be as follows:
ProjectionMatrix:
GL_PROJECTIONViewMatrix:
GL_MODELVIEWModelMatrix:
P:
ViewMatrix
Since the camera is orbiting the planet, we need to calculate the position of the planet. For this we assume, that the orbital plane is the xz-plane and y is the up vector.
where
angle: the orbit angle in radians
radius: the distance from the origin to the center of the planet
Now that we have the planet position, which is the target argument to the lookAt function, all that's left is to calculate the eye position. Here we assume again, that the orbital plane is the same as above (xz-plane).
From your description, we know that the camera is orbiting the planet at the same speed of its own rotation around its own axis, therefore we simply reuse the calculated sin/cos values (cx, sz) from said operation and multiply it by the distance to the center of the planet.
but, that is around the origin, we still have to translate it to the actual planet position
ModelMatrix
Since we calculated the planet position manually (see section ViewMatrix), we can leave the rotation portion out and simply translate it to the calculated position.
Example: