How to fix the local coordinate system?
I come up with an obscure solution where I first map the axis to each coordinate system. To determine which of the axes is that I simply make the point product of the requested direction with respect to all the axes of the transformation matrix and select the one that has the highest abs. The sign simply indicates whether the coordinate system is the opposite (this means that the rotation must be canceled).
On C ++ and OpenGL lines, it looks like this:
void RubiCube::axises_unit(reper &rep,int &x,int &y,int &z,int &sx,int &sy,int &sz) { int i; double p[3],xyz[3][3],a,b; rep.axisx_get(xyz[0]); rep.axisy_get(xyz[1]); rep.axisz_get(xyz[2]); vector_ld(p,1.0,0.0,0.0); for (b=0.0,i=0;i<3;i++) { a=vector_mul(xyz[i],p); if (fabs(a)>=fabs(b)) { x=i; b=a; } } sx=+1; if (b<0) sx=-1; vector_ld(p,0.0,1.0,0.0); for (b=0.0,i=0;i<3;i++) { a=vector_mul(xyz[i],p); if (fabs(a)>=fabs(b)) { y=i; b=a; } } sy=+1; if (b<0) sy=-1; vector_ld(p,0.0,0.0,1.0); for (b=0.0,i=0;i<3;i++) { a=vector_mul(xyz[i],p); if (fabs(a)>=fabs(b)) { z=i; b=a; } } sz=+1; if (b<0) sz=-1; }
Where reper is a class containing a direct and inverting transformation matrix. get_axis just look inside the direct matrix and return the selected vector of the axis direction. vector_mul is a point product, and vector_ld just fills a 3D vector with x,y,z coordinates.
As I also received the global matrix of the cube, which is not axis-aligned to the identity matrix (since it is rotated so that the view looks like the image above). Then I need to execute this axis, corresponding to special vectors (values โโof the matrix of the initial representation) In my case, this:
void RubiCube::axises_obj(reper &rep,int &x,int &y,int &z,int &sx,int &sy,int &sz) { int i; double p[3],xyz[3][3],a,b; rep.axisx_get(xyz[0]); rep.axisy_get(xyz[1]); rep.axisz_get(xyz[2]); vector_ld(p,+0.707,-0.299,-0.641); for (b=0.0,i=0;i<3;i++) { a=vector_mul(xyz[i],p); if (fabs(a)>=fabs(b)) { x=i; b=a; } } sx=+1; if (b<0) sx=-1; vector_ld(p,-0.000,-0.906,+0.423); for (b=0.0,i=0;i<3;i++) { a=vector_mul(xyz[i],p); if (fabs(a)>=fabs(b)) { y=i; b=a; } } sy=+1; if (b<0) sy=-1; vector_ld(p,-0.707,-0.299,-0.641); for (b=0.0,i=0;i<3;i++) { a=vector_mul(xyz[i],p); if (fabs(a)>=fabs(b)) { z=i; b=a; } } sz=+1; if (b<0) sz=-1; }
Both functions return the axis in which x,y,z , and if the direction is opposite (sx, sy, sz) compared to the unit transformation matrix.
Fragment rotation
This is the core of the puzzle. This is a simple rotation of the slice around the axis. This is used for animation, so the angle step is small (I use 9 degrees), but the whole rotation should be 90 degrees, otherwise the Rubic Cube will break.
void RubiCube::cube_rotate(int axis,int slice,double ang) { int j,k,a[3],s[3]; double p[3],p0[3]={0.0,0.0,0.0},lang; reper *r; _redraw=true; for (k=0;k<27;k++) { r=&cube[k];
Where reper::gpos_get returns the beginning of the matrix as a 3D vector (point) and reper::gpos_set basically sets the new position of the matrix. vector_rotx(p0,p,a) rotates the vector p around p0 and the x axis by angle a . The signs +/- should correspond only to rotations of the reper class (I was different somewhere). reper::lrotx rotates reper around its local x axis to learn more about the first link.
As you can see, I use each initial coordinate of the matrix directly as a topology to select slice cubes.