如何纠正改变局部坐标系?
我想出了一个晦涩的解决方案,首先匹配每个坐标系的轴。为了检测哪个轴是哪个轴,我只需对查询方向与变换矩阵的所有轴进行点积,然后选择具有最高abs点积的轴。该符号只是告诉坐标系是否相反(意味着旋转应该相反)。
In C++ and OpenGL样式矩阵看起来像这样:
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
是包含直接变换矩阵和逆变换矩阵的类。这get_axis
只需查看直接矩阵并返回选定的轴方向单位向量即可。这vector_mul
是点积并且vector_ld
只需将 3D 向量填充为x,y,z
坐标。
因为我还得到了全局立方体矩阵,它的轴未与单位矩阵对齐(因为它被旋转,因此视图看起来像上图一样)然后我需要针对特殊向量(初始视图矩阵值)进行此轴匹配在我的情况下它是这个:
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;
}
两个函数都返回哪个轴是哪个x,y,z
如果与单位变换矩阵相比方向相反 (sx,sy,sz)。
切片旋转
这是谜题的核心。它是围绕轴简单旋转切片。这用于动画,因此角度步长很小(我使用 9 度),但整个转弯必须是 90 度,否则魔方会破裂。
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];
// local axis,sign
axises_unit(*r,a[0],a[1],a[2],s[0],s[1],s[2]);
// lang is local signed angle change
lang=ang; if (s[axis]<0) lang=-lang;
// select slice
r->gpos_get(p);
j=round(p[axis]+1.0);
if (j!=slice) continue;
// rotate global position
if (axis==0) vector_rotx(p0,p,+ang);
if (axis==1) vector_roty(p0,p,-ang);
if (axis==2) vector_rotz(p0,p,+ang);
r->gpos_set(p);
// rotate local cube orientation
if (a[axis]==0) r->lrotx(-lang);
if (a[axis]==1) r->lroty(-lang);
if (a[axis]==2) r->lrotz(-lang);
}
}
Where reper::gpos_get
返回矩阵原点作为 3D 向量(点)并且reper::gpos_set
基本上设置新的矩阵位置。这vector_rotx(p0,p,a)
旋转向量p
around p0
和轴x
按角度a
. The +/-
标志只是为了匹配旋转reper
类(我在某处有所不同)。这reper::lrotx
旋转reper
围绕其当地x
轴有关更多信息,请参阅第一个链接。
正如您所看到的,我直接使用每个矩阵原点坐标作为拓扑来选择切片立方体。