Sequence of rotation

does the sequence in what i use rotation matter?
like by


from the “UNSANE” confused user:

  • OhKay, thank you very much for confirm,
    even i try already i was not sure if i ended up at the same point.

  • but all this is already inside a push - pop matrix loop
    could this be ?stacked?

  • ? angle understanding? as in processing

    • the x axis goes right,
    • the “y” axis goes down
    • ? the z axis goes into the screen ?
  • does this have consequences for the used angles in the rotation?
    i got already that rotateZ means ( in my bad english ) :
    " rotate X Y plane to the RIGHT ( clockwise ) and not change Z "
    so i used minus angles to go counter clock wise.
    i try to draw it ( and even write some info text to the screen ) still this gives me headake,
    could you take a look? here

Yes, you can stack pus/pop calls. Check this transformation tutorial

You don’t have to undo the operations, just pop the transformation stack.


1 Like

thanks to @TfGuy44 and @kfrajer
i now use push rotate(-a) pop
and also understand the rotate little bit better,
sadly my poor knowledge about astronomy seems to be my problem, not the processing part.
( a elliptic orbit ( not the planets position on the orbit ) around the SUN
should be defined by the elliptic parameters “semi-major-axis” and “eccentricity”
and a 3 angle info about the orientation of the ellipsis ( i could use to do rotate X Y Z the ellipsis prior to find the planet position on that orbit )
but the WIKI planets info and the default picture there does not help me much, after rotateZ( Longitude of ascending node) and rotateY( Inclination) for all planets
a ( final ) rotateX (Argument of perihelion)
looks just wrong)

It does if you are not using translations between the rotations. If not, no. You can try this out with a physical object in your hand to confirm – rotate a stick of butter 90 x, then 90 y, or 90 y then 90 x, and it ends up in the same orientation. If you translate, however,

(See expanded examples below) IN GENERAL everything is order-dependent.

You may want to make sure that you have completely worked out the 2D case, then add another dimension of rotation to tilt the axes.

For example, here is a very very simple toy model which uses pushes and pops, implemented in the 2D case.

float spin;

void setup() {
  size(400, 400);
void draw() {
  spin = (spin + 0.012);

  translate(width/2, height/2);

  // planet
  translate(0, 0);
  rect(0, 0, 50, 50);

  // moon A
    rotate(spin + PI/3);
    translate(100, 0);
    rect(0, 0, 25, 25);

    // moon A sattelite 1
      rotate(spin/2 + PI);
      translate(40, 0);
      rect(0, 0, 12, 12);

    // moon A sattelite 2
      rotate(spin + PI/3);
      translate(50, 0);
      rect(0, 0, 10, 10);

  // moon B
    rotate(spin/2 + PI/5);
    translate(140, 0);
    rect(0, 0, 20, 20);



Notice how each starting angle for a child is relative, rather than absolute.

If you want to get into more detail about debugging your code, you may want to share example code here and describe how specifically you can tell it “looks wrong”, and what part of the code you think is doing that.

1 Like

thanks @jeremydouglass,

  • now understand that rotateX rotateY rotateZ ( without translate … inbetween ) should work in any sequence

  • also that i must use
    push rotate draw pop
    rotate(-x) draw rotate(+x)

  • thanks for the example, nice

  • code, i have my project what is about to test processing 3D view: code and BLOG
    where the SOLARsystem is just one TAB of, for that i have a add BLOG and 2 add test codes
    Kepler orbit and ellipsis_rotation

  • what looks wrong is if i enable
    rotateX ( file:sketch_3D_view_v153 / TAB SOL / line 384 )
    the planets not form a dish anymore,
    as i say i must missunderstand the WIKI planet ellipsis angles somehow.
    add i might have mistake in x or -x ( or rotate(PI)) if the angle definitions are for Perhelion while my x axis is the for the LONG one Aphelion / this i can not see in the WIKI picture about the angles.
    (NOTE this is all about the ellipsis position, NOT about the planet position on the ellipsis, that part (Kepler) works already )

It seems incorrect that translations are independent. Consider the following example that generates different outcomes depending on the rotation order:

void setup() {
  size(400, 400, P3D);

void draw() {
  translate(width/2, height/2);

  // XY order
  //rect(0, 0, 100, 100);
  box(50, 150, 100);
  // YX order
  //rect(0, 0, 100, 100);
  box(50, 150, 100);

The result is visible in the following image:

Hence I believe the reply above by @jeremydouglass and @TfGuy44 to be incorrect. Please correct me if I misunderstood.


You are right – my first paragraph in my answer above is not correct. Apologies – I must blame sleep deprivation or perhaps just foolishness. I’m striking through that paragraph to avoid confusing others.

The key thing is that all matrix operations are always relative, not absolute – they rotate, translate, or scale etc relative to the previous state, not relative to the original frame of reference. For this reason, the only operations that can be moved around in sequence are ones which are commutative. For example, rotation is commutative in 2D and generally not in 3D:

Still, certain sets of operations are order invariant. Here are some examples:

order-independent (commutative)

// 2D translations
translate(x, y);
translate(x2, y2);
// 2D rotation
// 3D translations
translate(x, y, z);
translate(x2, y2, z3);

However, most are not.

order-dependent (not commutative) examples

In general, mixing different operations from scale rotate or translate is almost always order-dependent – unless one of the operation has no effect such as scale(1) or rotate(TWO_PI). Also, 3D rotation is order-dependent.

// mixed translation and rotation
translate(x, y)
// ...does not equal:
// rotate(r);
// translate(x, y)
// 3D mixed translation and rotation
translate(x, y, z)
// does not equal:
// translate(x, y, z)
// rotateX(r);
// 3D rotation
// ...does not equal:
// rotateZ(r2);
// rotateY(r1);
// rotateX(r);