Rubik's Cube rotation

Started by
9 comments, last by SiCrane 12 years, 11 months ago
Hi guys, so after solving may a problem from reading posts on this forum which Google has suggested to me I have finally decided to become a member in the hope that it's more helpful than other forums I have asked and failed to even get a response *cough* MSDN *cough* ... biggrin.gif

I'l just briefly introduce myself, My name is Kevin, im from University of Derby, UK and I study Computer Games Programming.

Now for the problem:
I have been assigned to create a cross platform framework for the PSP and Direct3D, this I understand, it is all about abstraction and maximising code sharing, my problem is not here. The demo I am creating with my framework is the issue, I wanted to create a simple Rubik's cube where the user can solve it themselves, have no time to work out the algorithm to solve it automatically, (though I can solve a real one myself). Anywho's I'm rambling, My problem is the rotation...

I have a Cube class which stores verts of <-0.5 -0.5 -0.5 > etc to create a cube of width/height/depth of 1, all with the origin as <0 0 0 > I also store a position vector and a rotation vector.

The position being <-1, 1, -1 > (assuming Z goes into the screen) would position the cube as the top left cube of the front face, if you can picture that...
Next i wanted to store the rotations of each axis so for example, if I wish to rotate the front face 180 degrees, the cube i described above would have a rotation of...
< 0, 0, ToRad(180) >
and would then become the bottom right of the front face.

This works fine, until I start trying to rotate around another axis like so:
[media]
[/media]


As you can see, the way directX or any other API handles the rotation is by XYZ thus if i rotate about X first and then Y, its fine, yet if i rotate around Y and then X, the X rotation is reversed (obviously, this makes sense to me). What my problem is, I dont know how to stop it angry.gif

Could somebody please explain a better way of doing this? Am I missing something obvious or is this as tricky as it seems?
To calculate my world matrix I do Scale * Translate * Rotate to achieve the offset and then rotate that offset.

Thanks for reading all this, and please help, I would appreciate it SO much!



Kev
cool.gif
Advertisement
I had a "control template cube", that simply stored the center positions of the unaltered cube elements. I had a "changing cube", that also stored the centers, but the rotations affected it (by recalculating the centers). The control cube is used to determine which centers need to be rotated in the changing cube (by simply looping through all centers and checking their "distances" from the control cube's marked centers (marked by selection). If it's zero (near zero) then the center will be moved). Then I manually applied the rotation to the changing cube's appropriate centers. If you know the positions (and probably the orientations) of the centers, you can apply the transformation to the displayed cube elements separately on-by-one.

I hope that's clear...
So, you mean I apply the rotations to my position vectors?

Sorry that im sounding a bit stupid right now, but this problem has me confused beyond belief. Im not quite understanding your explanation.



Kev
cool.gif

So, you mean I apply the rotations to my position vectors?

Sorry that im sounding a bit stupid right now, but this problem has me confused beyond belief. Im not quite understanding your explanation.



Kev
cool.gif


Yup. Apply the transformations to the position vectors. I did it that way, I couldn1_t think any reasonable way to use the model view for that. You see, every time you rotate a side, the arrangement of the cube changes.
Ok, so if I create a matrix which rotates around the X axis by 1 degree on each update, and then multiply the position vector by this matrix...

I'll let you know how this goes, thank you for replying.



Kev
cool.gif
I do something a little simpler. I only apply rotations to pieces as they rotating. Once the rotation is complete, I reset the model geometry to the original position and swap the textures. (Or to be more precise I swap the indices in a data structure that controls which textures get displayed for each piece.)

Ok, so if I create a matrix which rotates around the X axis by 1 degree on each update, and then multiply the position vector by this matrix...

I'll let you know how this goes, thank you for replying.



Kev
cool.gif


You can decouple the animation from the logical rotation, something like SiCrane suggests. I didn't separate them, I just made sure the vertices are rounded after the animation to make floating point error accumulation.
Making them rounded you mean like keep a track of the animation progress, once it hits or goes past 90 degrees, set it to 90 degrees, stop the animation and round each vert to the nearest whole number, as each vert xyz will then be something like 0.9998f or 0.00002f etc etc...

SiCrane, do you mean like, play the animation but then place the cube back in its original space, but simply rotate it locally so when the next animation plays it will look as though it is not the original cube anymore? If so, I was doing that as one of my ways of testing but that was going wrong still because how i rotate is the problem.

At the moment what i do is at the end of each animation i switch the pointers around in my Cube* cubes [26] array... so if the front face was:

0 1 2
3 4 5
6 7 8

becomes


6 3 0
7 4 1
8 5 2

so i put cubes[0] into cubes[2] etc etc...




Kev
cool.gif
No, what I mean is the moral equivalent of peeling off the stickers and moving those around. At any given time there will be at most three matrices applied to a given piece: the camera, the orientation of the puzzle as a whole and, if a rotation is being animated, the rotation of that side of the puzzle. None of these are specific to a given piece of the puzzle so no rotations are stored per puzzle piece. This way I don't worry about accumulating rotations.
Thanks for the replies guys biggrin.gif

I had some other assignments to finish off for today and now im back on this.

I just got this done:
[media]
[/media]


This is the code I use to do this for the front face, the left is also the same except the obvious axis differences etc...


void Game::FrontRotate(float deltaTime)
{
float rotation = DegreeToRad(90) * deltaTime;
rotCount += rotation;
Matrix rotZ = Matrix::CreateRotationZ(-rotation);

if (rotCount > DegreeToRad(90))
{
rotation -= (rotCount - DegreeToRad(90));
state = ROTATE_NONE;
rotCount = 0.0f;
}

cubes[0]->pos = rotZ * cubes[0]->pos;
cubes[1]->pos = rotZ * cubes[1]->pos;
cubes[2]->pos = rotZ * cubes[2]->pos;
cubes[3]->pos = rotZ * cubes[3]->pos;
cubes[4]->pos = rotZ * cubes[4]->pos;
cubes[5]->pos = rotZ * cubes[5]->pos;
cubes[6]->pos = rotZ * cubes[6]->pos;
cubes[7]->pos = rotZ * cubes[7]->pos;
cubes[8]->pos = rotZ * cubes[8]->pos;

if (state == ROTATE_NONE)
{
Cube* temp;
temp = cubes[0];
cubes[0] = cubes[6];
cubes[6] = cubes[8];
cubes[8] = cubes[2];
cubes[2] = temp;

temp = cubes[1];
cubes[1] = cubes[3];
cubes[3] = cubes[7];
cubes[7] = cubes[5];
cubes[5] = temp;

cubes[0]->RoundPositionValues();
cubes[1]->RoundPositionValues();
cubes[2]->RoundPositionValues();
cubes[3]->RoundPositionValues();
cubes[4]->RoundPositionValues();
cubes[5]->RoundPositionValues();
cubes[6]->RoundPositionValues();
cubes[7]->RoundPositionValues();
cubes[8]->RoundPositionValues();
}
}



I was just wondering now,, how do I get them to rotate properly? Would storing a rotation matrix in each cube be right, and then add the rotZ matrix to that one? Does matrix addition do that or? This is kind of the part that gets me stuck, I feel like such an idiot asking this but I guess I have to swallow my pride to learn.

Thanks for the help



Kev
cool.gif

This topic is closed to new replies.

Advertisement