1. Welcome to the new MacRumors forums. See our announcement and read our FAQ

Quartz Composer 3D Rotation!

Discussion in 'Mac Programming' started by Mydriasis, Jan 29, 2007.

  1. macrumors 6502


    Either this is an increadibly stupid remark by me or I found a really annoying bug.

    If you apply a 3D rotation to any object in QuartzComposer it changes the orientation of the objects axes. That makes sense, and it should do that. But it does it only to those axes that are rendered after the rotation axis (if they are in the same patch, then its X -> Y -> Z).

    To illustrate my problem... I made this really simple little app. Its is just a cube that you can rotate with three sliders representing the X,Y and Z axis.

    Try this... rotate the Y axis by 90° and the see what the other two do... the same thing. The X axis rotates in the original X axis of the Cube and the Z axis in the new Z axis rotated by 90°, which is the same as the X axis.

    Wow, this is really hard to explain... try it out to see what I mean. If you know how to fix it, I would love to know. Thanks.

    BTW splitting the individual axes onto separat patches doesn't work either.

    Attached Files:

  2. macrumors 6502a

    Tried your program and I think it's behaving correctly… it's just Euler type rotations in 3-D aren't unique.

    The rotations ( 90, 90, 0 ) and ( 0, 90, 90 ) are being applied in model coordinates and they are simply mapping the cube to the same orientation.

    b e n
  3. macrumors 6502


    Yes, but the oder matters.

    (90, 90, 0) and (90, 0, 90) are not the same because when you rotate in the X axis by 90° the other two axes (Y and Z) are maped to the new orientation. They are calculated after X. Yet X is not retrospectively recalculated if Y is rotated.
  4. macrumors 6502a

    Sorry I made a mistake, I should have typed (90, 90, 0) and (90, 0, 90) for the rotations as you did. However I'm still pretty sure your program is behaving correctly.

    Imagine the XYZ axis arranged with the origin at the centre of the screen, with positive X going from left to right, positive Y going from bottom to top, and positive Z coming straight out the screen. This coordinate axis does not change, it's fixed even when the rotations are applied.

    Now the order that rotations are applied is Z, Y, and then X. Also these rotations are relative to the axis I've just described, not an imaginary axis attached to the cube.

    It doesn't matter in what order you change the sliders, the rotations are always applied Z, Y then X. Setting the Y slider to 90 then manipulating the X or Z slider gives the illusion that there is something wrong.

    Another way of seeing this is to get hold of a dice and do the rotations by hand. I think you'll find that it will produce exactly the same results, ie you will get to the same face regardless of whether you do (90, 90, 0) and (90, 0, 90) .

    Or another way to see this using your program is:-

    1) Start with all sliders set to 0. Then slide Z to 90 and then slide Y to 90.
    2) Start with all sliders set to 0. Then slide Y to 90 and then slide X to 90.

    You'll get the same results with 1) and 2) but you'll be able to see why.

    Hope this helps and I haven't made things more confusing.

    b e n
  5. macrumors 6502


    No, I am sorry. I think maybe I am explaining it wrong. This is really hard for me :eek:, english is not my native language.

    But the coordinate axes of the cube are not fixed to the display, they are attached to the cube. Thats the whole point.

    That is why I marked the sides with a set color:
    • red for the cubes x axis
    • green for the y axis
    • blue for the z axis
    And to prove my point:
    Start with all the slider set to zero. Then slide the X to 90°, you will now see the green 5 or in other words the cubes Y axis.
    If you now slide the Y axis slider it will rotate on the on the cubes y axis (the stationary Z axis). As is should. Also if you slide the Z axis slider it will rotate on the cubes Z axis (or the stationary's Y axis).

    So far everything works as you would expect it.

    But if you do the example I explained above:
    Start with all sliders set to zero. Then turn Y to 90°.
    If you move the Z slider you will see it turn on the cube's Z axis as it should, but if you move the X slider you will see the cube turn on the stationary's X axis and not the cube's.

    Hopefully I have explained it better, but thanks so much for your help already.:)
  6. macrumors 6502a

    I think I understand where the confusion arises, but in trying to explain I am probably adding to the confusion. My appologise for this!

    Imagine your cube initially alligned to the XYZ axis, ie ( 0,0,0 ) in your program. When you apply a rotation it will rotate the cube relative to these axis in the order Z, Y then X. The rotations only affect the cube, not the axis themeselves. In other words, the rotations do *not* rotate the axis themeselves, ie the axis are *not* fixed to the cube. Sorry that's just the way the rotation matrix works!

    The simplest way to see this is to always move the sliders, starting from (0,0,0), in the order Z, Y and then X. It will make sense if you do this, promise!

    The examples you give highlight the mathematical curiosity that rotations are not unique, ie (90,0,90) has the same affect as (0,90,90). It's just a side product of your user interface that it appears that you are doing an X or Z rotation after a Y rotation. In reality your program (Quartz composer/OpenGL) is always applying the rotations in the order Z, Y and then X.

    Once again, I hope I haven't made things worse. I hope you sort it out soon as thinking about rotations can drive you mad.

    I'll shut up now!

    b e n
  7. macrumors 6502


    Okay thanks,

    I think I am starting to get it. So is there a simple way of rotating the cube in the stationary Z axis from the starting position (0, 90, 0), in simple words turn the red 2 onto its head?

    Other than going all the way to (0, 270, 180) or (180, 270, 0)?

    Again, thanks for you help!!!:)
  8. macrumors 6502a

    Okay, if I understand correctly, what you are wanting to do is achieve a specific view of the cube by following the rotation (0,90,0) with some other rotation.

    So, to get an upside down red '2' you need to perform the rotation (0,0,180) after the (0,90,0) rotation, or in short hand, (0,0,180)*(0,90,0).

    You can get Quartz Composer to do this by putting your cube in a Quartz Composer 3D-Transform patch and setting the z rotation of that patch to 180.

    This is all equivalent to doing a single rotation R where

    R = (0,0,180)*(0,90,0)

    The thing to note is (0,0,180)*(0,90,0) does not equal (0,90,180).

    To work out R by hand you will need to use matricies. In fact you've already found some solutions, ie R = (0,270,180) or (180,270,0).

    By the way when you think of rotations as relative to the cube's own coordinate system, like you were at the start of the thread, you are using Euler angles.

    b e n
  9. macrumors 6502


    Cool thanks,

    well yeah, I was just playing around with Quartz Composer (I had never really used it before).

    I was trying to make a virtual Rubik's Cube. I thought I would be really easy, because I expected the 3D rotation to behave differently.

    I thought I could just add up the individual 90° rotations to get the desired final rotation. But then there are these stupid overlapping situations.

    So here we go, I added two other cubes to the app. They each are within multiple 3D Transformation patches, for seperate axes. The middle one is in the order Z,Y,X and it behaves exactly like the original cube, as you said it would. The right cube is in X,Y,Z order, and behaves differently, again like you said I can now turn the red 2 on its head (when Y=90°). But now I cant rotated in the X axis.

    Is there a way to be able to rotate in any axis from any position. (I know I am annoying, sorry :eek: ) Thanks a bunch!

    Attached Files:

  10. macrumors 6502a

    It sounds to me like you want to be able to manipulate the cube a number of times in sequence, ie rotate it one way first, then another way, and then after that another way and so on. To do this you will need to either:-

    1) Keep track of all the rotations that have occured so far. When the user wants to rotate the cube again, apply all the rotations in sequence and then the new one.

    2) Apply each rotation the user does to the *actual* verticies of the cube, ie *not* it's frame. That way each new rotation really does operate on the cube that is visible.

    3) Or, after each rotation, work out the angles (X,Y,Z) which will take a standard cube, ie from (0,0,0), to the current visible orientation.

    Now 3) is the best because 1) and 2) will, at least in principle, suffer from accumulating errors as the number of rotations increases. In fact 3) isn't that difficult to work out if you stick to rotations of 90 and 180 degrees.

    In any case I think you would have to change your user interface. Perhaps have buttons that rotate the cube by +- 90 degrees about X, Y or Z. That way it will make it easy for you to track the individual rotations the user performs when manipulating the cube.

    hope this helps

    good luck

    b e n
  11. macrumors 6502


    Thanks I'll try them and let you know what worked for me.

    I already have a set up like the one you explain in number 3, my main problem was animating the rotation change. As of now the user is restricted to only applying 90° rotations at a time anyways.

    I think I will have to separat the rotation animation from the acutal rotation position of the cube. And alas, the color of the cube faces as well.

    Thanks for all the help!!! :)

Share This Page