As a game developer there is just too much darn stuff to learn. You could spend your entire life learning things and never know it all.
It’s a blessing in that you are seldom bored, but also sometimes a curse in that there almost always is a better way to do something, and that you would know about it if you had spent your time learning X instead of Y 😛
I find that you sort of have to triage what you learn and what you choose to keep fresh in your mind, which can be a challenge sometimes. If you can find the commonalities between things that can help some – like understanding how encryption, hashing, pseudo random number generators and chaos theory all overlap – or how skeletal animation blending and audio synthesis are both trying to be continuous waves above all else. Also, if you put in the time investment to learn something to where it becomes intuitive, that frees up neurons to make room for other stuff. But, of course, we have a finite amount of time, so can’t always spend the time needed to get to that level on every single topic.
How about you… do you have to do a juggling act like this to keep sharp and stay effective as a game (or non-game) programmer? I’d be interested to hear how others deal with this sort of thing with such a large knowledge space that we work in.
In any case, I usually work with spherical or polar coordinates only on rare occasions, so whenever i do, the process usually is to google the equations, drop them in, and move on with my life. I was recently implementing an orbit camera for a raytracer on shadertoy.com (Raytraced Refraction) and when my copy/pasting wasn’t working, I was forced to take a deeper look at why it wasn’t working. Amazingly, this time around, it finally clicked and is now an intuitive thing so I figured I’d share the explanation that makes most sense to me in case it helps anyone else.
Converting Polar Coordinates to Cartesian (2D)
Polar coordinates have two components – a distance and an angle – and represent a point in 2d space.
The distance is called the radial coordinate, or the radius and the angle is called the angular coordinate or polar angle.
Just like you probably expect, the angle defines what direction the point is in, and the radius defines how far away it is. Super simple. Below is a picture of a polar coordinate point at (3, 45) where 3 is the distance and 45 is the angle.
So how do we convert that to rectangular coordinates? well, first thing to do is to convert the angle to rectangular coordinates on a unit circle to get a direction vector. Then, you multiply that direction vector by the radius to get the final coordinate.
To convert the angle to a point on a unit circle and get the direction vector it’s super simple…
X = cos(angle) Y = sin(angle)
For every point on the unit circle, it’s X coordinate is the cosine of the angle, and it’s Y coordinate is the sine of the angle.
Looking at the diagram below, see if you can figure out why arccosine only returns an angle between 0 and 180, and why arcsine only returns an angle between -90 and 90 (hint, what if i asked you to tell me what angle gives 0.7 in the x component). Also see if you can understand why sin(x)^2 + cos(x)^2 = 1 (hint: distance formula).
Ok so now that we can get our direction vector, we just need to multiply it by the radius. So… to convert from polar to rectangular (cartesian) coordinates, you do this:
X = cos(angle) * radius Y = sin(angle) * radius
Converting Cartesian to Polar Coordinates (2D)
So how do we convert from rectangular coordinates to polar?
Well, since we have the X and the Y coordinates, and we know that tangent(angle) = Y / X, we can use arctangent to get our angle. Unfortunately atan has a similar problem to asin and acos in that it doesn’t know which quadrant you are talking about. For instance, look at the diagram above again and tell me “which angle gives me a value of 1 when i divide the Y component by the X component?”. The answer is 45 degrees and 225 degrees both. This is because with a positive value of 1, we don’t know if X and Y were both negative, or if they were both positive. Similarly, if i asked which angle gave an answer of -1, we wouldn’t know if it was the X or Y that was negative.
Instead of using atan, we want to use atan2, which takes 2 parameters – Y and X – so that it can figure out the correct angle for you.
Next is the easy part of finding the radius. treating your point as a vector (or continuing to treat it like a vector if it IS a vector), the radius is just the magnitude of the vector (or distance from the origin if you want to think of it in “point” terms instead of vectors).
So, converting rectangular to polar coordinates is done like this:
radius = sqrt(X * X + Y * Y) angle = atan2(Y, X)
Converting Spherical Coordinates to Cartesian (3D)
Spherical coordinates have the same components as polar coordinates, but then an added component: an angle which determines pitch / vertical rotation (think: looking up and looking down, instead of the polar angle which is in charge of looking left and right).
In math, they usually call the radius rho, the polar angle theta, and the azimuth angle phi, so a formal polar coordinate looks like this:
(rho, theta, phi)
For our examples let’s assume that X and Y make up the horizontal plane and that Z is the vertical (3d) axis.
If you are scared to make the jump from 2D polar coordinates to 3D spherical coordinates don’t be! The way to deal with these guys is to break the 3d problem into two 2d problems, using the exact same stuff as described above.
So, the first thing we want to do is completely ignore this new 3rd component phi and think back to our 2d case. We are also going to ignore the radius for now.
XTheta = cos(theta) YTheta = sin(theta)
This is our direction vector on the horizontal plane (same as the 2d case, not accounting for radius yet).
Next we want to pretend like we are looking at our 3d world from the side and use our phi angle to convert from polar to rectangular coordinates:
XPhi = cos(phi) YPhi = sin(phi)
One way to think of what this other angle phi means, is that it is controlling where in the unit sphere the theta circle sits. As the theta circle gets higher or lower on the sphere, it shrinks or grows. It’s only at zero angle that it has a radius of 1.0. So, calculating these values, YPhi represents how high on the sphere the theta circle should sit, and XPhi is how large the circle should be.
So, to combine the X,Y theta values and the X,Y Phi values, we use YPhi as the vertical component, and XPhi as a radius for the theta circle, which we can do like this:
X = XTheta * XPhi Y = YTheta * XPhi Z = YPhi
The above equation will give us a point on a unit sphere, so from here, we need to multiply in the radius and our equation becomes:
X = XTheta * XPhi * radius Y = YTheta * XPhi * radius Z = YPhi * radius
If we put sin and cos back in, instead of xtheta (etc), the equation becomes that familiar, and previously complex equation:
X = cos(theta) * cos(phi) * radius Y = sin(theta) * cos(phi) * radius Z = sin(phi) * radius
Hopefully the equation makes more sense now, and hopefully you can look at that and intuitively understand why those values are what they are.
Converting Cartesian to Spherical Coordinates (3D)
To convert from spherical coordinates to rectangular, the first thing to do is to get the radius, which is done in the exact same way as in 2d. We just take the magnitude of the vector (aka the distance of the point from the origion) and we are done.
To get theta and phi, we do the same thing of separating this 3d problem into two 2d problems.
In fact, to get theta, we do the exact same thing as we do for polar coordinates! We use atan2(Y,X) to get our angle… THAT’S ALL!
So, we have this so far:
radius = sqrt(X * X + Y * Y + Z * Z) theta = atan2(Y, X)
How do we figure out phi? Well, if you said that we should do atan2(Z,Y) or atan2(Z,X) you were pretty close but it’s actually arccos(Z / radius).
The reason for this is because neither X, nor Y is the “X” component of the “phi 2d polar coordinate”. you’d have to take the length of the (X,Y) vector and use that if you wanted to use atan2 to calculate phi. Instead of calculating that vector length, we can instead use a value we already have. cosine is Y / hypotenuse length, and hypotenuse length is the radius (length of our vector), so we might as well use that radius we already have to be able to use arccos.
The final equations for converting rectangular to spherical are:
radius = sqrt(X * X + Y * Y + Z * Z) theta = atan2(Y, X) phi = acos(Z / radius)
More info / alternate forms available on wikipedia here:
From Cartesian to Spherical Coordinates
Spherical Coordinate System
Fantastic Post! I have been working on this problem for months now after also finding that copy and pasting the equations would not work for what I’m trying to do. The solution is so simple and elegant I think it makes up for all the time I wasted barking up the wrong tree! XD
Anyway, keep up the awesome work! This site deserves to be on everyone’s reference list
Thanks! I’m glad you found it useful!
LikeLiked by 1 person
Thank you for this! Managed to get a grip on generating spheres from it! While, I’m still not certain I understand it all, it is a very helpful and easy explanation. In combination with this post: http://snipd.net/2d-and-3d-vector-normalization-and-angle-calculation-in-c it enabled me to do some simple programming for Vuo which’ll come in handy.
While I’m at it, this generates the sphere from the center and folds back over on itself to grow the full thing, at least the one I got from it. Swapping the sin/cos in the spherical to polar calculation sorted it out:
X = sin(theta) * sin(phi) * radius
Y = cos(theta) * sin(phi) * radius
Z = cos(phi) * radius
LikeLiked by 1 person