A Simple Third-Person Camera
degrees polar subject camera rotation using position
The third-person camera is used in video games such as Super Mario 64 or Max Payne. When I was trying to figure out how to calculate the camera’s position, I remembered back to earlier this year in pre-calculus, when my math teacher described an alternative coordinate system known as the polar coordinate system. It works by specifying the distance from the origin or pole, or r, and the angle between the polar axis and the ray that contains the described point, q. Here is an example of a polar graph. The graph is in radians. In the case that you forgot p radians = 180 degrees. The rays coming out of the pole in the middle are different angles. The circles represent the different distances from the pole.
Now think about a third-person camera.
- It should be a set distance from a certain subject. This set distance could of course change if desired.
- It should also be a certain amount along the circumference of a circle that has that subject as its center. The position is based on the subject’s rotation.
- The camera’s distance from the subject, a.k.a. r. You can decide for yourself how far away it is that you want the camera, other variables depend on this value.
- The camera’s position. We are only worrying about x and z. How you calculate this is too easy. You do need to variables one and four to calculate this though.
- The camera’s y-axis or yaw rotation.
- The amount the camera is around the circumference of the imaginary circle going around the subject. In more mathematical terms, q. This explanation is important so I am putting it in bold and explaining it before any other variable. If the polar axis were in the same place as the positive y-axis (90 degrees) than to find this amount you would just add 180 degrees to the amount of the subject’s rotation. However the polar axis is on the positive x-axis. Therefore we must add an additional 90 degrees making the total 270 degrees. Now in OpenGL, you are looking down the negative z-axis. So when you calculate the z-position, you subtract the 270 degrees, rather than adding it.
These next two formulas will calculate variable two, the camera’s position. To convert from polar to rectangular coordinates (x, y) you use the incredibly convenient formulas:
- x = r * cos(q)
- y = r * sin(q)
Here’s some code that calculates the camera’s position:
float camerax = cameradist * cos((yrot + 270.0f) * M_PI / 180) + xpos; float cameraz = cameradist * sin((yrot - 270.0f) * M_PI / 180) + zpos;There are a few things to note about that code.
- The trigonometry functions only take radians, so you must multiply by PI/180 to convert from degrees to radians.
- Because the subject moves around, you need to add the respective subject coordinate to the camera's coordinate.
- Remember to add or subtract 270 degrees.
float camerax = cameradist * sin((yrot) * M_PI / 180) + xpos; float cameraz = cameradist * cos((yrot) * M_PI / 180) + zpos;Variable three, in our case, is easy. We are always going to be looking at the subject’s rear, so the camera’s yaw rotation will be equal to the subject’s yaw rotation.
Variable four was already explained because of how important it was. Now on to drawing using this camera whose position and rotation you just figured out. This section is OpenGL specific.
Assume that you declared DrawObject() and DrawScenery(). Also assume you defined cameradist, and calculated yaw, camerax, and cameraz.
// First I like to draw the subject. Basically you are just drawing the subject directly in front of you glTranslatef(0.0f, 0.0f, -cameradist); DrawObject(); //You reset the view and now any scenery or world that you want to draw is drawn. glLoadIdentity(); glRotatef(360.0f - yaw, 0.0f, 1.0f, 0.0f); glTranslatef(-camerax, 0.0f, -cameraz); DrawScenery();I think that you now have an idea of how to use polar coordinates. If you have any specific questions please post them to the thread linked at the bottom of this page. For more information on the polar coordinate system check out the resources below. Good luck!