поворот матрицы к кватерниону (и обратно) что не так?

Я скопировал код для преобразования трехмерной матрицы вращения в кватернионы и обратно. Тот же код используется в jMonkey (Я просто переписал его в мой класс C ++). Тем не менее, он не работает должным образом (по крайней мере, не так, как я ожидал.)

например Я сделал этот тест:

matrix (a,b,c):
a : 0.707107 0.000000 0.707107
b : 0.000000 -1.000000 0.000000
c : -0.707107 0.000000 0.707107

>>> ortonormality:
a.a b.b c.c  1.000000 1.000000 1.000000
a.b a.c b.c  0.000000 0.000000 0.000000

>>> matrix -> quat
quat: 0.000000 0.594604 0.000000 0.594604  norm(quat) 0.707107

>>> quat -> matrix
matrix (a,b,c):
a: 0.000000 0.000000 1.000000
b: 0.000000 1.000000 0.000000
c: -1.000000 0.000000 0.000000

Я думаю, что проблема в matrix -> quat потому что я использовал quat -> matrix процедура, и она работала нормально. И это странно, что кватернион из ортонормированной матрицы не унитарен.

matrix -> quat процедура

inline void fromMatrix( TYPE m00, TYPE m01, TYPE m02,    TYPE m10, TYPE m11, TYPE m12,        TYPE m20, TYPE m21, TYPE m22) {
// Use the Graphics Gems code, from
// ftp://ftp.cis.upenn.edu/pub/graphics/shoemake/quatut.ps.Z
TYPE t = m00 + m11 + m22;
// we protect the division by s by ensuring that s>=1
if (t >= 0) { // by w
TYPE s = sqrt(t + 1);
w = 0.5 * s;
s = 0.5 / s;
x = (m21 - m12) * s;
y = (m02 - m20) * s;
z = (m10 - m01) * s;
} else if ((m00 > m11) && (m00 > m22)) { // by x
TYPE s = sqrt(1 + m00 - m11 - m22);
x = s * 0.5;
s = 0.5 / s;
y = (m10 + m01) * s;
z = (m02 + m20) * s;
w = (m21 - m12) * s;
} else if (m11 > m22) { // by y
TYPE s = sqrt(1 + m11 - m00 - m22);
y = s * 0.5;
s = 0.5 / s;
x = (m10 + m01) * s;
z = (m21 + m12) * s;
w = (m02 - m20) * s;
} else { // by z
TYPE s = sqrt(1 + m22 - m00 - m11);
z = s * 0.5;
s = 0.5 / s;
x = (m02 + m20) * s;
y = (m21 + m12) * s;
w = (m10 - m01) * s;
}
}

quat -> matrix процедура

inline void toMatrix( MAT& result) const {
TYPE r2 = w*w + x*x + y*y + z*z;
//TYPE s  = (r2 > 0) ? 2d / r2 : 0;
TYPE s  = 2 / r2;
// compute xs/ys/zs first to save 6 multiplications, since xs/ys/zs
// will be used 2-4 times each.
TYPE xs = x * s;  TYPE ys = y * s;  TYPE zs = z * s;
TYPE xx = x * xs; TYPE xy = x * ys; TYPE xz = x * zs;
TYPE xw = w * xs; TYPE yy = y * ys; TYPE yz = y * zs;
TYPE yw = w * ys; TYPE zz = z * zs; TYPE zw = w * zs;
// using s=2/norm (instead of 1/norm) saves 9 multiplications by 2 here
result.xx = 1 - (yy + zz);
result.xy =     (xy - zw);
result.xz =     (xz + yw);
result.yx =     (xy + zw);
result.yy = 1 - (xx + zz);
result.yz =     (yz - xw);
result.zx =     (xz - yw);
result.zy =     (yz + xw);
result.zz = 1 - (xx + yy);
};

простите за TYPE, VEC, MAT, QUAT это часть класса tepmpltes … должны быть заменены на double, Vec3d, Mat3d, Quat3d или же float, Vec3f, Mat3f, Quat3f,

РЕДАКТИРОВАТЬ:

Я также проверил, получаю ли я такое же поведение напрямую с jMonkey (в случае, если я сделал ошибку в преобразовании Java в C ++). И я делаю — используя этот код:

    Matrix3f Min  = new Matrix3f( 0.707107f, 0.000000f, 0.707107f, 0.000000f, -1.000000f, 0.000000f, -0.707107f,  0.000000f,  0.707107f  );
Matrix3f Mout = new Matrix3f( );
Quaternion q = new Quaternion();
q.fromRotationMatrix(Min);
System.out.println( q.getX()+" "+q.getY()+" "+q.getZ()+" "+q.getW() );
q.toRotationMatrix(Mout);
System.out.println( Mout.get(0,0) +" "+Mout.get(0,1)+" "+Mout.get(0,2) );
System.out.println( Mout.get(1,0) +" "+Mout.get(1,1)+" "+Mout.get(1,2) );
System.out.println( Mout.get(2,0) +" "+Mout.get(2,1)+" "+Mout.get(2,2) );

2

Решение

Ваша матрица:

matrix (a,b,c):
a : 0.707107 0.000000 0.707107
b : 0.000000 -1.000000 0.000000
c : -0.707107 0.000000 0.707107

является ортогональным, но это не матрица вращения. Матрица вращения имеет определитель 1; ваша матрица имеет определитель -1 и, таким образом, является неправильное вращение.

я считать Ваш код, вероятно, правильный, и проблема в ваших данных. Попробуйте это с реальной матрицей вращения.

2

Другие решения


По вопросам рекламы [email protected]