While working on code to draw orbits around a sphere, I found a surprising (but correct) result using the rotateX, rotateY, and rotateZ functions, and I am interested if this is or can be better explained somewhere to help users understand the issue.
My use case is to draw a circle around a sphere that is rotated around the Y axis 90 degrees and then tilted to the right by rotating around the Z axis 37 degrees. This would look like the following:
My initial approach is the following:
// Setup a white 3D screen with ortho projection
size(1000, 700, P3D);
background(255);
lights();
noStroke();
ortho();
// Move origin to pivot around the center
// of the screen and draw our sphere
translate(width *0.5, height*0.5, 0);
sphere(280);
// Setup to draw the circle
noFill();
strokeWeight(3);
stroke(0);
// Rotate and draw
rotateY(PI/2);
rotateZ(radians(37));
circle(0, 0, 600);
But my rotation code is wrong. Instead of the inclined circle, I just get a vertical circle, which looks like the rotation around the Z axis didn’t happen. But it actually did happen, just not how I was (incorrectly) expecting. I made what might be a common mistake, and I was certainly confused about what was actually happening.
The process I was thinking of when writing the code was the following:
- Create a circle
- Rotate 90 degrees around Y axis
- Tilt right 37 degrees by rotating around the Z axis.
But that is not at all what I was actually doing, instead the actual steps are:
- Change coordinate system - Y rotation
- Change coordinate system - Z rotation
- Draw circle in the new coordinate system
The right way to achieve the goal is to reverse the order of the rotations:
rotateZ(radians(37));
rotateY(PI/2);
circle(0,0,600);
This makes sense in considering the matrix operations, but it is a bit difficult to explain. I was able to draw my final picture with multiple inclined orbits around a sphere by reversing the order of rotations from my initial intuition:
// Setup a white 3D screen with ortho projection
size(1000, 700, P3D);
background(255);
lights();
noStroke();
ortho();
// Move origin to pivot around the center
// of the screen and draw our sphere
translate(width *0.5, height*0.5, 0);
sphere(280);
// Setup to draw the circle
noFill();
strokeWeight(3);
stroke(0);
for (float r = 0.0; r < 2*PI; r += PI/12) {
pushMatrix();
rotateY(r+PI/6);
rotateZ(radians(37));
rotateY(PI/2);
circle(0, 0, 608);
popMatrix();
}
(can’t include more than one image)