【发布时间】:2021-07-14 16:39:31
【问题描述】:
我正在替换我的项目对 glRotatef 的使用,因为我需要能够转换双矩阵。 glRotated 不是一个选项,因为 OpenGL 不保证存储的矩阵或执行的任何操作都是双精度的。但是,我的新实现只围绕全局轴旋转,并没有给出与 glRotatef 相同的结果。
我查看了 glRotatef 的一些实现(如 OpenGl rotate custom implementation),但没有看到它们在计算旋转矩阵时如何解释初始变换矩阵的局部轴。
我有一个通用的旋转功能,取自https://community.khronos.org/t/implementing-rotation-function-like-glrotate/68603:
typedef double double_matrix_t[16];
void rotate_double_matrix(const double_matrix_t in, double angle, double x, double y, double z,
double_matrix_t out)
{
double sinAngle, cosAngle;
double mag = sqrt(x * x + y * y + z * z);
sinAngle = sin ( angle * M_PI / 180.0 );
cosAngle = cos ( angle * M_PI / 180.0 );
if ( mag > 0.0f )
{
double xx, yy, zz, xy, yz, zx, xs, ys, zs;
double oneMinusCos;
double_matrix_t rotMat;
x /= mag;
y /= mag;
z /= mag;
xx = x * x;
yy = y * y;
zz = z * z;
xy = x * y;
yz = y * z;
zx = z * x;
xs = x * sinAngle;
ys = y * sinAngle;
zs = z * sinAngle;
oneMinusCos = 1.0f - cosAngle;
rotMat[0] = (oneMinusCos * xx) + cosAngle;
rotMat[4] = (oneMinusCos * xy) - zs;
rotMat[8] = (oneMinusCos * zx) + ys;
rotMat[12] = 0.0F;
rotMat[1] = (oneMinusCos * xy) + zs;
rotMat[5] = (oneMinusCos * yy) + cosAngle;
rotMat[9] = (oneMinusCos * yz) - xs;
rotMat[13] = 0.0F;
rotMat[2] = (oneMinusCos * zx) - ys;
rotMat[6] = (oneMinusCos * yz) + xs;
rotMat[10] = (oneMinusCos * zz) + cosAngle;
rotMat[14] = 0.0F;
rotMat[3] = 0.0F;
rotMat[7] = 0.0F;
rotMat[11] = 0.0F;
rotMat[15] = 1.0F;
multiply_double_matrices(in, rotMat, out); // Generic matrix multiplication function.
}
}
我使用与调用 glRotatef 相同的旋转来调用此函数,并以相同的顺序,但结果不同。所有旋转都围绕全局轴完成,而 glRotatef 将围绕in 的局部轴旋转。
例如,我有一架飞机:
然后我向上倾斜 90 度(这给出了 glRotatef 和我的旋转函数的预期结果)并保持转换:
如果我使用 glRotatef (glRotatef(90, 0.0f, 0.0f, 1.0f)) 倾斜 90 度,则平面围绕变换的局部 Z 轴旋转,指向平面的鼻子,这就是我想要的:
但如果我用我的代码 (rotate_double_matrix(in, 90.0f, 0.0, 0.0, 1.0, out)) 倾斜 90 度,我会得到:
平面仍然围绕全局 Z 轴旋转。
如果我更改旋转顺序,也会出现类似问题 - 第一次旋转会产生预期结果,但后续旋转仍会围绕全局轴发生。
glRotatef 如何围绕矩阵的局部轴旋转?我需要在代码中进行哪些更改才能获得相同的结果?我假设rotate_double_matrix 需要以某种方式修改基于in 矩阵传入的x, y, z 值,但我不确定。
【问题讨论】: