rotateX, rotateY, and rotateZ, Order Matters?

So I'm making an animation, and part of it involved making a function capable of making a cuboid with 6 different colored faces and a specific rotation. The function I wound up creating is as follows:

void colorCuboid(float x, float y, float z, float w, float h, float l, float rotX, float rotY, float rotZ, color left, color right, color top, color bottom, color front, color back) { //centered on (x, y, z)
  float halfW = w / 2;
  float halfH = h / 2;
  float halfL = l / 2;

  pushMatrix();
  translate(x, y, z);
  rotateX(rotX);
  rotateY(rotY);
  rotateZ(rotZ);

  fill(back);
  beginShape(); //back

  vertex(-halfW, -halfH, -halfL);
  vertex(halfW, -halfH, -halfL);
  vertex(halfW, halfH, -halfL);
  vertex(-halfW, halfH, -halfL);
  vertex(-halfW, -halfH, -halfL);

  endShape();

  fill(top);
  beginShape(); //top

  vertex(-halfW, -halfH, -halfL);
  vertex(halfW, -halfH, -halfL);
  vertex(halfW, -halfH, halfL);
  vertex(-halfW, -halfH, halfL);
  vertex(-halfW, -halfH, -halfL);

  endShape();

  fill(left);
  beginShape(); //left

  vertex(-halfW, -halfH, -halfL);
  vertex(-halfW, halfH, -halfL);
  vertex(-halfW, halfH, halfL);
  vertex(-halfW, -halfH, halfL);
  vertex(-halfW, -halfH, -halfL);

  endShape();

  fill(front);
  beginShape(); //front

  vertex(halfW, halfH, halfL);
  vertex(-halfW, halfH, halfL);
  vertex(-halfW, -halfH, halfL);
  vertex(halfW, -halfH, halfL);
  vertex(halfW, halfH, halfL);

  endShape();

  fill(bottom);
  beginShape(); //bottom

  vertex(halfW, halfH, halfL);
  vertex(-halfW, halfH, halfL);
  vertex(-halfW, halfH, -halfL);
  vertex(halfW, halfH, -halfL);
  vertex(halfW, halfH, halfL);

  endShape();

  fill(right);
  beginShape(); //right

  vertex(halfW, halfH, halfL);
  vertex(halfW, -halfH, halfL);
  vertex(halfW, -halfH, -halfL);
  vertex(halfW, halfH, -halfL);
  vertex(halfW, halfH, halfL);

  endShape();

  popMatrix();
}

And you can test it by using this code:

color red = color(255, 0, 0);
color yellow = color(255, 255, 0);
color green = color(0, 255, 0);
color cyan = color(0, 255, 255);
color blue = color(0, 0, 255);
color purple = color(255, 0, 255);

void setup() {
  size(500, 500, P3D);
}

void draw() {
  background(255);
  colorCuboid(width / 2, height / 2, 0, 200, 200, 200, (float(mouseY) / width) * TWO_PI, (float(mouseX) / height) * TWO_PI, 0, red, cyan, green, purple, blue, yellow);
}

But I've noticed that it's rotation behaves really unexpectedly. One such way, in the colorCuboid function, if you change

rotateX(rotX);
rotateY(rotY);
rotateZ(rotZ);

to the locigally equivilant

rotateZ(rotZ);
rotateY(rotY);
rotateX(rotX);

it behaves so much differently in that example sketch.

In addition, if yRot is TWO_PI / 4, xRot and zRot both rotate along the same axis, which is the relative z axis of the cube. (around the axis perpendicular to the blue and yellow faces)

Can anyone give me some insight as to what is happening? Also, can anyone help me get my colorCuboid function to rotate correctly?

Tagged:

Answers

  • edited January 2015

    Hello !

    When you are inside a Matrix (pushMatrix / popMatrix) , each command is applyed once a time, in the order you have defined.

    You get an unexpected result because you start by a translation. It means that you move the "origin" before applying a rotation.

    For example, if you set the Z of an object to 100 before applying a rotation ; it means that you will move the object "around a sphere" with a radius of 100. (your origin is a point on that sphere ; the center of the sphere is the point (0,0,0) .

    To do what you want, just apply the translation AFTER the rotations. Then the rotations will be applyed around the center (0,0,0) and then you ll put the result where you want.

    Good luck !

  • Thanks for the reply tlecoz. I didn't think of trying that. However, your solution a) didn't work and b) doesn't do what I want.

    I'll address point b first. What I want is to put a cube at the (x,y,z) coordinates fed to the program, then rotate around the center of the cube (so that it stays in place). By putting translate after the rotation commands, the cube is still placed at the correct location, but it rotates around (width / 2, height / 2, [0 I believe?]. So that won't work. For an example of what I mean, take that example sketch, modify the colorCuboid function as you said, then feed, say, 100 to the x parameter instead of 0.

    As far as point a is concerned, the wonky, unexpected rotations still happen. For example, if yRot is TWO_PI / 4, rotX and rotZ still do the same thing, and I am still unable to change the z axis rotation.

    Basically, by translating the origin to where I want, then making the cuboid around the origin, rotation means that it will rotate around the origin, which is at the center of the cube and at the point I wanted. But by rotating the origins, then translating using those rotated origins, I'm putting the origin at some odd location in the new rotated space instead of the normal, unrotated space.

    I have a slight hunch that this might be caused by the fact that the rotations are relative to the current space, and that you rotate one axis at a time, instead of simultaneously. So if you rotate +90 degrees on the x axis, then +45 degrees on the y axis, from your perspective, you rotated +90 degrees on the x axis, and then +45 degrees on the z axis. This happens because the relative y axis is now pointed towards you when you rotate it, making it look like the z axis to you. The line

    colorCuboid(0, 0, 0, 200, 200, 200, TWO_PI /4, TWO_PI /8, 0, red, cyan, green, purple, blue, yellow);

    demonstrates this.

    Actually, when typing that, I had an insight as to why the rotX and rotZ do the same thing when yRot is +90 degrees! So it rotates around x, but then when it rotates +90 on the y axis, the relative z axis takes the place that the relative x axis was. So then when I rotate around the z axis, it looks like it did the same thing that rotating around the x axis did!

    However, I have no idea how to fix that. Sure, in the specific scenario above, replacing rotateZ(rotZ) with rotateX(-rotZ) would do what I want, but it wouldn't work for every scenario of y rotation.

    If only the rotations happened simultaneously, so that you could explicitly define the rotations from the viewers standpoint instead of having to deal with all these relative rotations one at a time!

    I really do appreciate your help though. I've been going totally crazy trying to figure this out. Could you perhaps look into it further, and please help me?

  • edited January 2015

    I'm to tired to read... I saw the topic title and quick scanned. I think your dealing with gimbal lock:

    It has to do with eular angles.

  • You're correct! I hadn't heard of gimbal lock before, but that's what's happening. Thank you!

    Now how would I overcome it in processing?

    Thanks again, Wyatt

Sign In or Register to comment.