• 12
• 10
• 10
• 13
• 10

Rubik's Cube rotation

This topic is 2513 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

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* ...

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...
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

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.

Kev

Share on other sites
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...

Share on other sites
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

Share on other sites

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

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.

Share on other sites
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

Share on other sites
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.)

Share on other sites

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

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.

Share on other sites
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

Share on other sites
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.

Share on other sites
Thanks for the replies guys

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