【问题标题】:How does glRotatef rotate around local indices?glRotatef 如何围绕本地索引旋转?
【发布时间】: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 值,但我不确定。

【问题讨论】:

    标签: c opengl


    【解决方案1】:

    您可能以错误的顺序将矩阵相乘。尝试改变

    multiply_double_matrices(in, rotMat, out);
    

    multiply_double_matrices(rotMat, in, out);
    

    我永远不记得哪种方式是正确的,而且multiply_double_matrices 有一个合理的机会是倒退的(至少如果我写了它的话:)

    矩阵乘法的顺序。由于rotMat 持有您的轮换,而in 持有迄今为止应用的所有其他矩阵的组合,即“其他所有”,因此以错误的顺序相乘意味着rotMat 被应用一切之后else 而不是 before 一切。 (而且我没有把那部分倒过来!如果您希望 rotMat 成为“栈顶”转换,这意味着您实际上希望它成为处理顶点坐标时的第一个)


    另一种可能性是您将行与列混淆了。 OpenGL矩阵下降,然后跨越,即

    matrix[0]    matrix[4]    matrix[8]    matrix[12]
    matrix[1]    matrix[5]    matrix[9]    matrix[13]
    matrix[2]    matrix[6]    matrix[10]   matrix[14]
    matrix[3]    matrix[7]    matrix[11]   matrix[15]
    

    即使二维数组传统上是跨存储,然后向下存储:

    matrix[0]    matrix[1]    matrix[2]    matrix[3]
    matrix[4]    matrix[5]    matrix[6]    matrix[7]
    matrix[8]    matrix[9]    matrix[10]   matrix[11]
    matrix[12]   matrix[13]   matrix[14]   matrix[15]
    

    弄错了可能会导致外观相似但数学上不同的问题

    【讨论】:

    • 翻转旋转顺序是解决方法。看来我只是想多了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 2011-10-30
    • 2012-05-31
    • 2017-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多