一、基本定义
旋转矩阵和四元数是描述三维空间旋转的两种方式,旋转矩阵是一个3x3的正交矩阵,而四元数则是一个四元组。旋转矩阵和四元数可以相互转换,且在很多场合下四元数更加高效。
二、旋转矩阵转四元数
对于一个旋转矩阵R,其对应的四元数Q可以通过以下公式得到:
float trace = R[0][0] + R[1][1] + R[2][2]; if (trace > 0) { float s = 0.5f / sqrtf(trace + 1.0f); Q.w = 0.25f / s; Q.x = (R[2][1] - R[1][2]) * s; Q.y = (R[0][2] - R[2][0]) * s; Q.z = (R[1][0] - R[0][1]) * s; } else { if (R[0][0] > R[1][1] && R[0][0] > R[2][2]) { float s = 2.0f * sqrtf(1.0f + R[0][0] - R[1][1] - R[2][2]); Q.w = (R[2][1] - R[1][2]) / s; Q.x = 0.25f * s; Q.y = (R[0][1] + R[1][0]) / s; Q.z = (R[0][2] + R[2][0]) / s; } else if (R[1][1] > R[2][2]) { float s = 2.0f * sqrtf(1.0f + R[1][1] - R[0][0] - R[2][2]); Q.w = (R[0][2] - R[2][0]) / s; Q.x = (R[0][1] + R[1][0]) / s; Q.y = 0.25f * s; Q.z = (R[1][2] + R[2][1]) / s; } else { float s = 2.0f * sqrtf(1.0f + R[2][2] - R[0][0] - R[1][1]); Q.w = (R[1][0] - R[0][1]) / s; Q.x = (R[0][2] + R[2][0]) / s; Q.y = (R[1][2] + R[2][1]) / s; Q.z = 0.25f * s; } }
其中,trace表示旋转矩阵的迹,即R的对角线元素之和。如果trace大于零,则通过s计算出所需的四元数元素值;否则根据R的具体取值选择不同的计算方式。需要注意的是,在计算时需要先将旋转矩阵R正则化。
三、四元数转旋转矩阵
而四元数Q转换成旋转矩阵R可以通过以下公式得到:
float xx = Q.x * Q.x; float xy = Q.x * Q.y; float xz = Q.x * Q.z; float xw = Q.x * Q.w; float yy = Q.y * Q.y; float yz = Q.y * Q.z; float yw = Q.y * Q.w; float zz = Q.z * Q.z; float zw = Q.z * Q.w; R[0][0] = 1.0f - 2.0f * (yy + zz); R[0][1] = 2.0f * (xy - zw); R[0][2] = 2.0f * (xz + yw); R[1][0] = 2.0f * (xy + zw); R[1][1] = 1.0f - 2.0f * (xx + zz); R[1][2] = 2.0f * (yz - xw); R[2][0] = 2.0f * (xz - yw); R[2][1] = 2.0f * (yz + xw); R[2][2] = 1.0f - 2.0f * (xx + yy);
其中,平方项和积项分别表示四元数Q的平方和乘积,通过特定的组合方式得到矩阵元素的取值。
四、四元数的优点
旋转矩阵转四元数和四元数转旋转矩阵的两个过程都可以通过直接计算得到,相对比较高效。另外,与旋转矩阵相比,四元数运算更加直观,更加适合进行蒙太奇拼接、球形插值等场合下的操作。
五、总结
旋转矩阵和四元数都是描述三维空间旋转的方式,两者可以相互转换。旋转矩阵转四元数可以通过判断R的迹进行优化,四元数转旋转矩阵通过特定的组合方式得到矩阵元素的取值。相对于旋转矩阵,四元数更加适合进行蒙太奇拼接、球形插值等操作。