Rotating an object from left/right and up/down movements

Hi folks,

I’m writing a game on Android which involves cubes. The user can rotate individual cubes, from his perspective, 90deg left, right, up or down.

Naturally as the shape is rotated, the positions of its axes change, so the next rotation might be about a different axis. For example if the first rotation is “right”, I need to rotate in a positive direction around the Y (vertical) axis. Now the Z axis is where the X axis was, and the X axis is where the Z axis was, but pointing in the opposite direction.

To do this I use a matrix:

  // The matrix used to rotate/tip the shape.  This is updated each time we rotate.
  private int  m_rotationMatrix[][] = { {0, 1, 0},        // User wants to rotate left-right
                                        {1, 0, 0} };      // User wants to rotate up-down

which I update upon each rotation:

    // If we rotated in the x direction, we need to put the z axis where the x axis was
    if (0 != leftRight)
    {
        int newXMatrix[][] = new int[2][3];

        for (int direction=0 ; direction<2 ; ++direction)
        {
            newXMatrix[direction][X_DIMENSION] = m_rotationMatrix[direction][Z_DIMENSION] * (-leftRight);  
            newXMatrix[direction][Y_DIMENSION] = m_rotationMatrix[direction][Y_DIMENSION];          // Unchanged
            newXMatrix[direction][Z_DIMENSION] = m_rotationMatrix[direction][X_DIMENSION] * (leftRight);  
        }

        m_rotationMatrix = newXMatrix;
    }

    // If we rotated in the y direction, we need to put the z axis where the y axis was
    if (0 != upDown)
    {
        int newXMatrix[][] = new int[2][3];

        for (int direction=0 ; direction<2 ; ++direction)
        {
            newXMatrix[direction][X_DIMENSION] = m_rotationMatrix[direction][X_DIMENSION];          // Unchanged
            newXMatrix[direction][Y_DIMENSION] = m_rotationMatrix[direction][Z_DIMENSION] * (upDown); 
            newXMatrix[direction][Z_DIMENSION] = m_rotationMatrix[direction][Y_DIMENSION] * (-upDown);  
        }

        m_rotationMatrix = newXMatrix;
    }

Now if I turn a shape right, right, right, the resulting matrices are exactly as I think they should be:

                   x    y    z
Start:  LeftRight  0    1    0
        UpDown     1    0    0

Right1: LeftRight  0    1    0
        UpDown     0    0    1

Right2: LeftRight  0    1    0
        UpDown    -1    0    0   <-- Looks right to me but doesn't work!

Right3: LeftRight  0    1    0
        UpDown     0    0   -1

When I test the up-down rotation in each case above, it is correct for three sides, but wrong (upside down) in the Right2 case. That is to say, if the user does an “up” rotation, that becomes -90deg on the x-rotation, which I think is correct (x-axis is now pointing left) but it causes the box to turn, from the user’s point of view, downwards.

I can find no such simple problem with the up-down rotation: after any number of up-down rotations, a single left-right rotation works as expected.

For reference my draw() does this:

    // Set drawing preferences
    gl.glFrontFace(GL10.GL_CW);

    // Set this object's rotation and position
    gl.glPushMatrix();
    gl.glTranslatef(m_xPosition, m_yPosition, m_zPosition - m_selectZ);
    gl.glRotatef(m_xRotation, 1, 0, 0);
    gl.glRotatef(m_yRotation, 0, 1, 0);
    gl.glRotatef(m_zRotation, 0, 0, 1);

...blah blah

What is wrong my my rotation please?

Lots of views but no replies. From reading other threads here I don’t believe this is beyond everyone’s expertise :wink: so I wonder if there’s something I can do to enable people to help. I’m stuck so I’d really appreciate it.

Perhaps a slightly different way of coming at the problem: is anyone able to recommend an algorithm which will let me rotate a shape left-right / up-down in any arbitrary order please?

Thanks!
-M.

In case it should be helpful for someone in the future, I found a way to make this work. It feels a bit clunky, and I still don’t understand why the original method didn’t work.

This is how I did it:
Display the shape in its natural orientation.
Every time the user rotates it, add that rotation (using scene axes) to a list of rotations. (Optimise for multiple movements in one direction.)
When drawing, apply each of the rotations in turn, in reverse order.

So for example if the user rotates the shape right, up, right, right, down, we store a list:
Right = rotate around Y axis 90deg
Up = rotate around X axis 90deg
Right, Right = rotate around Y axis 180 deg
Down = rotate around X axis -90deg
On drawing, glRotatef these in reverse order.

It seems inefficient and I feel there ought to be a better way. I’m sure there is. However it works fine.