Hello,

I am developing a rubik's cube game. (http://www.rubiks.com , if you do not know the cube)

I have modeled the whole cube, with its 26 parts as smaller cubes. Now, the problem is to rotate the faces.

My first approach was to create each face as a node, each with 9 parts, and rotate this "face" Node.

The problem is that some pieces (corners) are child of 3 sides at once (front, side and top, for example), which violates the scene graph.

Is there another way to group these objects for rotating?

Or i need to translate and rotate each individual piece (a LOT more work)?

Any ideas and suggestions will be greatly appreciated

Hmm… since there are multiple sets of groups a piece can belong to and rotate with, it seems like any sort of simple grouping is impossible. Perhaps though you could do some trickery like (thinking out loud here):

- Attach all cubes to root

- when a user signifies they want to rotate a section of the whole cube, temporarily attach the 8 or 9 minicubes to a temp parent node. Apply the rotation to the parent, update the geometric state of this temp node, then copy the world transforms of the minicubes to their local transforms.

- Move the minicubes back to reside under root.

Or just apply the rotation to the minicubes themselves… probably more straightforward.

I have tried this… the problem is when rotating a second side. As the rotation stays on the parent "rotating" node, the parts lose their rotation when returning to the root node.

Then you are missing the part of the step where you call updateGS and then manually copy the world fields to local.

OK, my game is (not) working like this:

The simpleUpdate() method checks for rotation command, and if there is one and the cube is not rotating, call turn(). Else, if the cube is rotating, keep rotating until HALF_PI.

Assuming the code:

` `

part.setLocalRotation(part.getWorldRotation());

part.setLocalTranslation(part.getWorldTranslation());

part.updateGeometricState(tpf, true);

With this code: side spins fast and never stops. What value should be the first parameter of updateGeometricState? am i doing it wrong?

Without this code: side turns, but rotation is reset when another node is turn.

Julio,

You should do the rotation transport (from world to local + updateGState) only when your rotation animation ENDS. First do the whole rotation (animation) using the tempNode aproach and after that's finished you can transport the rotation (when HALF_PI is achieved).

A video will make a better description of my problem:

http://video.google.com/videoplay?docid=-6476583369799444280&hl=en

In the video i rotate the up side two times and the down side two times.

First without copying global trans/rot to local, then copying.

(for simplicity, only one face of the cube is show)

Julio,

if you post the source code here we can check it and see how it's possible to make it work properly. You doesn't have to post everything. Try to code a small test, like those found in the jmetest package.

The source code can be foud at:

http://crantz.googlecode.com/svn/trunk/rubico/src/Rubico.java

Its all on simple runnable class.

The methods that move the parts from root to rotating node are:

moveFromRootToRotating() - called when rotation starts

moveFromRotatingToRoot() - called when rotation ends

The U and J keys rotate the cube.

Can you post more details about "call updateGS and then manually copy the world fields to local" ?

1- Shouldn't it be copy first and then updateGS?

2- do i need to transform coords before copy?

3- I am using the "tpf" from simple game as the first parameter to updateGS, is this correct?

Sorry if this is tooo dummy, but it is my first project. I am really reading before posting, but i cannot find this answers anywhere.

I got intrigued by your first post and decided to write a RubikCube myself :). I just have a small approximation problem left to solve and will post my solution here later!

Thank you very much. I am trying to understand the code, specially the rotantion and subrotation nodes.

Would it be possible to send me an email, so i can ask questions about your implementation directly?

my email is "jfaerman at gmail dot com"

jfaerman said:

Thank you very much. I am trying to understand the code, specially the rotantion and subrotation nodes.

Would it be possible to send me an email, so i can ask questions about your implementation directly?

my email is "jfaerman at gmail dot com"

I usually only check my email once a day so i don't mind answering some questions here someone else might have the same questions ;).

The actual small cubes consists of a Node, Box and 1,2 or 3 RoundedBox for the color plate. We can call these Boxnodes for reference, and these are moved around in the scenegraph.

In local space Boxnodes are not translated only rotated. What I have in the scene is one Node representing the whole Cube. Attached to this Node we have 27 nodes translated to be where the small cubes will be. We also have 9 nodes that represent all the rotations we want to do, 3 around the x,y and z axis. Every rotation node also have 9 subnodes translated to the positions where the small cubes will be. So think of it like you have the cube sliced six times, giving 3 slices perpendicular to each axis.

When we want to do a rotation we decide which one of the 9 rotations we want to do. Then just copy 9 Boxnodes from the 27 "real cube" nodes to subnodes of given rotation.

We then rotate the rotation node -pi,-1/2pi, 1/2pi or pi depending on what we want. After the rotation what have happend is that the position of a Boxnode have changed in the original 3x3x3 "visualisation" cube. The BoxNodes also have rotated around their center

We keep the Boxnodes new rotation by setting their worldRotation to their local Rotation and then move them back to the 27 node "real cube".

If you wonder how this copy is made here is one example:

Lets say you see on side of the cube straight on you will have something like this after one type of rotation

1 4 7 3 2 1

2 5 8 => 6 5 4

3 6 9 9 8 7

and if you think of your cube as a Node[3][3][3] array with indexes i,j,k. The position before and after a 1/2pi rotation will be this given indexes.

i=0

0.0 1.0 2.0 0.2 0.1 0.0

0.1 1.1 2.1 => 1.2 1.1 1.0

0.2 1.2 2.2 2.2 2.1 2.0

so when you copy your Boxnodes back in this case you go from i,j,k => i,2-k,j

Doing it this way the positions of the Boxnodes will always be correct no small approximation errors will build up over time from copying world to local translations. This should be done for the Boxnodes rotations to but haven't fixed that yet.

Anything else unclear? :)

Hello all,

I've been reading about jME for hours since yesterday. Actually this is my best reading ATM…

My thesis is about a Rubik's Cube simulator. Or should i say "Simulator and solver of a Rubik's kind puzzles".

I'll check out all this in details soon and come back

But already a few things :

- Puzzle can be 2*2*2, 3*3*3, 4*4*4,...20*20*20, Megaminx, Pyraminx, ... ideally any Rubik's like puzzle (that is, something that has rotating pieces)
- I currently have Java3D code but i'll for sure throw it away
- I dont only need to show a puzzle but also apply scramble/solve it. Solving relies on a custom algorithm yet to develop (see Arnaud Maes, Alan Hansel)
- ... and surely a bunch of other things

Regarding pure data model and operations :

Currently this is implemented as a vector of N (54 in this cases) elements being the colored pieces. I'll migrate this model to vector of oriented pieces instead.

The allowed operations are vectors of permutation (vector of size N containing target indexes of the elements).

I know all this is quite disturbing and/or misplaced but its my first evening here so be tolerant

Sounds like a fun project. Good luck with it.

Interesting but not easy lol, thank you anyway!

I'll keep posting details about progress as i found problems lol

I have tried to develop a solver using only genethic algorithms. Performance was terrible, not going to cut it.

Could you post more details (link, article) of the algorith you are planning to use?

If i can be of any help, please ask

Good luck

One of the ways people have attempted "solving" these is the following.

- Start with the solved puzzle
- Apply a series of valid transformations to it, and store them
- Whenever the user uses a transform store it too
- To solve simply apply the inverse of each transform in reverse order

This serves two purposes, first, the puzzle is always valid, and you don't have to do something special to guarantee it. Second, you already know what the solution is.