Sign in to follow this  

Getting the axes of which slice to turn from a Rubick's cube via picking

Recommended Posts

Good morning fellow programmers,

 

this is my first post here, I've been lurking from time to time though.

So, I'm currently programming a Rubick's cube on the PS Vita and one requirement is touch controls.

I have to be able to determine what I'm touching via picking/raycast and then, depending on the dragging movement, turn one of two slices.

So far, I have touch controls implemented and they seem to work in most cases, but sadly not all, hence this thread.

 

There are (for this step) two things you have to look out for when doing touch controls for a rubick's cube.

1) Which slice do you want to turn, as the touch display only has x and y axes?

2) In which direction do you want to turn the selected slice, as a rotation of 180° on one axis needs to flip the finger movement as well?

 

So, I decided to make a vector out of my finger movement, multiply it with the rotation matrix (basically the model matrix) of the cube to clear question 2. The Model Matrix consists of rotations done on the x and y axes.

If I see the front side und move my finger down on a column, then turn the cube on the z axis 180° and then move my finger down again on a column, visually the same movement is done, so this works so far.

 

For question 1, I took the rotated drag vector and made the cross product with the normal of the side I was touching.

Then I looked at which value of the new vector was the biggest (close to 1 or -1) in absolute value and used the actual value to determine one of six values (1 or -1, 2 or -2, 3 or -3) to determine which axis is the turn-axis and in which direction to turn.

 

So, this system works for almost everything but sadly not for everything. When I look at the top side and do a drag movement on the x-axis (of the touch screen), the correct axis gets calculated (normal of top axis is (0, 1, 0) cross sweep on x-axis results in vector on z-axis), but the sign is wrong. If I try to control the very same slice from the right side (needs down or up movement to rotate instead), it works as intended. The rotated drag vector results in the "axis to turn" value -3, which means "the touched z-axis slice needs to rotate forward". When doing the movement on the top though, it results in 3 ("touched z-axis slice needs to rotate backwards"), even though it should be -3 as well. So that means that, the rotated drag vector swaps signs, but I'm not sure where my calculation goes wrong. There is also the case in which I turn a side 90° and not 180°, where the axes don't turn in the wrong direction like before, but instead the wrong slices get rotated!

So when I do a horizontal swipe, the visually vertical slice gets turned and vice versa).

I would also prefer to solve this mathematically with linear algebra, instead of just writing exceptions.

 

Thanks in advance; if anything is unclear about what I am doing, just ask and I will try to explain it better. Have a nice day!

 

Share this post


Link to post
Share on other sites

 

The cube itself is not of fixed orientation though.

So you can rotate the cube freely? 

 

The analog stick of the Vita is used to rotate the cube along the x and y axis (but not the z axis), yes. That is the cause for the point 2) I have written about. Since I can orientate the sides by orienting the cube, the code has to account for it. My code is already capable of that in most cases, but not all cases and I don't know why.

Edited by Quexlaw

Share this post


Link to post
Share on other sites

Hmm.. If you have the camera looking down the world Z axis so world Y is screen space up, world X is screen space right, you can do some dot products against the cube's right and up vectors to work out which way to rotate a slice.
 
E.g

2na1l02.png

 

So I would grab all four direction vectors of the cube, it's +X, -X, +Y, and -Y in world space, 0 out all the Z components and normalise them. Normalise the screen space swipe direction and do a dot product against all the four directions. Whichever one has the highest dot product is the direction to rotate the slice in. 

Edited by yaustar

Share this post


Link to post
Share on other sites

Thanks for the replies, but your suggested method wouldn't work...

If I face the front side, I can turn slices on the x and y axes.

If I face the top side, I can turn slices on the z and x axes.

If I face the right side, I can turn slices on the z and y axes.

 

If I swiped right on the front, the selected slice would have to rotate along the y axis.

If I swiped right on the top, the selected slice would have to rotate along the z axis.

 

With your suggestion, I would only be able to rotate slices along the x or y axes. You might have misunderstood how I rotate: the cube as a whole can be rotated along the x and y axes only, but the slices are of each axis, so depending on which slice is selected, they are rotated on the x, y or z axis.

 

I will try to summarize what I am trying to do:

I have nine slices in total, three for each axis. If you pick on one face (one small square), it belongs to three slices, one of each axis. But you only want to be able to rotate a slice along two of the three axes (the axis which corresponds to the side's normal on which the face is is the one you don't want). However, if you flip the cube on one axis by 180°, so that you look at one side "upside down", the movement of the slice actually should go into the other direction compared to the "downside up" view. Visually it looks the same, that is the point of doing this in the first place.

 

So my way of doing things is the following: I take my drag vector in screen space and multiply it with the model matrix of the cube. I know that I haven't gone the proper way over NDC, Camera Space, World Space, Local Space, but it shouldn't make a difference as I only need a direction. So my result vector is the drag vector in local space.

This vector is used in a cross product to create a vector resembling the axis I want to turn along.

If I look at the front side and swipe right, the model matrix is identity (so the swipe is the x-axis basically), cross the normal (which is the z-axis) I get the y-axis, which is the axis I actually want to turn along.

If I look at the top side and swipe right, the model matrix is a rotation of 90° along the x-axis, so the resulting drag vector is on the x-axis as well (x-Swipe rotated along the x-axis = x-axis).

X-axis cross normal of the top side, which is the y-axis, results in the z-axis, which is correct.

 

However, as I have narrowed down the problem, it is the drag vector which is problematic. I'm using the result of the cross product and look at the absolute biggest value and use the actual value to get the direction. If the result is - Y, I have to turn around y negative. If it is + Y, I have to turn around y positive. The axes get correctly determined always, but the "-Z" or "Z" get mixed up, which can only happen because of the drag vector, as the normal of the side in the cross product stays the same.

 

basically:

axis = cross(modelMatrix * dragVector, normalOfSide);

direction = look at absolute biggest value of axis, then use actual value (-1 or 1 for example) for direction. PROBLEM: the actual value has swapped signs somewhere in the process, should be the cross product.

 

How can I fix this?

Share this post


Link to post
Share on other sites

Does each coloured tile face have a set of local axes that you could use?

No, but I could set up the needed axes for each side if need be (you mean, for example, y and z axes for the right side, correct?), in fact I already did so.

 

EDIT:

Also, whenever I turn one side 90°, the drags go into the wrong direction. If I swipe right, visually the vertical slice gets rotated.

Could this be coming from matrix rotation order? If so, I will change the system so use quaternions.

Edited by Quexlaw

Share this post


Link to post
Share on other sites

Thanks for the input yaustar, but I managed to fix my problem...turns out my calculation was correct, but the Vita touchscreen's y-axis is reversed, which is something I forgot to consider at one point. So I reversed the y-coordinate and everything works fine now! The reason it took so long to find it was that almost all results were correct, so I didn't think the actual input would be wrong. Oh well. Thank you!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this