0
votes

I have a number of objects that I am rendering in HTML/CSS/JavaScript. The objects all sit on the surface of an invisible sphere with radius R.

Additionally, the interaction with the user allows this invisible sphere to be rotated arbitrarily.

The obvious solution is spherical co-ordinates assigned to the objects (Theta, Phi, and fixed Radius), which is the converted to Cartesian 3D co-ordinates, and then I can either just drop the depth (Z), or apply some fancy perspective. I will worry about perspective later...

Since I'm working with graphics, X/Y is horizontal/vertical respectively, and Z is depth where +ve is sticking out of the screen and -ve is inside the monitor.

I have a JavaScript array of objects called objects[], each of which has a Theta and Phi. I assume that Theta is rotation about the Y axis, and Phi is rotation about the X axis, such that at Phi = 0 and Theta = 0, we are at (X,Y,Z) = (0,0,R);

Since I'm rotating the invisible sphere, I don't want to have to change the Theta and Phi of each individual objects, which would also just add to numerical instability. Instead, I store a global Theta and Phi which is associated with the rotation of the sphere itself.

Hence, the "effective" Theta and Phi of the points are the Theta and Phi of the points plus the global Theta and Phi.

According to Wikipedia, WolframAlpha, MathWorld, and many other resources, we can find the Cartesian co-ordinates from spherical co-ordinates in the following way:

z = r * sin(phi) * cos(theta);
y = r * sin(phi) * sin(theta);
x = r * cos(phi);

(I've swapped Theta and Phi from Wikipedia as I'm using them backwards, and my X/Y/Z co-ordinates are different too).

I'm not sure why, but when I render these objects they don't look right at all. If you imagine a point on the equator of a sphere with Theta = Pi/4, and you rotate the sphere about the Y axis, the point should only move up and down if projected onto 2D and no perspective transformations are used. However, this isn't at all what happens. The points move from the right to the left side of the screen. The whole thing looks all wrong.

1
I think your coordinates are wrong. Phi is rotation about the z-axis, but theta isn't rotation about the y. It's a little hard to explain in words, so take a look at the Wikipedia picture. Theta is the angle between your Z-axis and your position vector (if that helps).Blender
@Blender It doesn't matter what axes you're rotating about, just as long as you have two angles about two independent axes. The article itself states that different people use spherical co-ordinates in different ways, which is why there are two pictures. But neither of them are practical for graphics since Z isn't up, Y is up.user1002358
The axes are arbitrary, but the rotations are not. It's harder to explain things if you change the coordinate system around, but your phi and theta don't correspond to spherical coordinates.Blender
@Blender OK, I've used the exact equations on Wikipedia. Now I'm look at the sphere from the top-down rather than the side, but that's OK. I have exactly the same result as before.user1002358
It's not the orientation. Your theta just isn't the same theta as the one in the Wikipedia article (yours is assuming rotation about the global y axis, while theta should be rotation about the "local" y axis).Blender

1 Answers

2
votes

Order matters. When you use your equations

z = r * sin(phi) * cos(theta);
y = r * sin(phi) * sin(theta);
x = r * cos(phi);

then you can interpret them as a rotation first by phi about y and second by theta about x (for appropriate choices of angle measurement directions):

(x1, y1, z1) = (r, 0, 0)
(x2, y2, z2) = (x1 * cos(phi) - z1 * sin(phi),
                y1,
                x1 * sin(phi) + z1 * cos(phi))
             = (r * cos(phi), 0, r * sin(phi))
(x3, y3, z3) = (x2,
                y2 * cos(-theta) - z2 * sin(-theta),
                y2 * sin(-theta) + z2 * cos(-theta))
             = (r * cos(phi),
                r * sin(phi) * sin(theta),
                r * sin(phi) * cos(theta))

When you simply add those angles, you end up with a wrong order: rotating first by phi1then by theta1 then by phi2 and then by theta2 about the different axes is not the same as rotating by phi1 + phi2 first and theta1 + theta2 afterwards. You're changing the order between theta1 and phi2, which breaks your 3D position.

Better use rotation matrices, quaternions, a library (like ) which encapsulates this for you, or make sure you properly combine euler angles.