【问题标题】:OpenGL translation and rotation in the same timeOpenGL 平移和旋转同时进行
【发布时间】:2016-09-24 13:49:52
【问题描述】:

在我的 openGL 项目中,我试图实现以下目标:让对象围绕其原点(其自身世界中的 (0,0,0) 点)旋转并同时平移它。我想出了以下结构:

/***
Install shader and upload data to openGL, initialize and stuffs...
***/
// transfomration matrix is a global variable
// note the transformation matrix eventually will be right multiplied
// by the vertex data in the vertex shader
void keyboard(){
// Inside this function I capture the keyboard input.
// if rotation key is captured, set the rotation flag
// if translation or scaling key is captured, modify the matrix like this
   transformation = glm::translate() * transformation;
}
void paintGL(){
// Inside this function I check if the rotation flag is up and modify the 
// model to wolrd transformation matrix. I choose to modify the transform
// matrix here because I can take use of the main loop to let my object
// continuously rotate unless the flag is off.
   if(rotation flag is set)
       transformation = transformation * glm::rotate() * inverse(transformation)
}
int main(){
    glutInit();
    glutDisplayFunc(paintGL);
    glutKeyboardFunc(keyboard);
    glutMainLoop();
}

现在我的问题是,当我只旋转或只平移或缩放时,程序按预期工作。但是如果我平移对象然后按下旋转,对象会回到它的初始位置然后旋转。或者消失!

我知道顺序很重要,但在我看来,只要我应用逆矩阵,对象就应该回到原来的世界并围绕原点旋转,然后我可以将它翻译回来。我的问题是由键盘和paintGL的调用顺序引起的吗?有人可以帮帮我吗?

【问题讨论】:

  • paintGL,你不应该先逆变换,然后旋转,然后再变换回来吗?
  • @reproduktor 是的,这就是我所做的,如上所述。
  • 对不起,我的错误,我认为 OpenGL 以另一种顺序应用矩阵。无论如何,如果您更改 keyboard 函数中的翻译,您将处理可能已经包含旋转的变换。尝试单独维护平移变换,然后在paintGL中组合平移和旋转。
  • 但你不应该。把倒数放在一边。此外,如果您还想在对象局部坐标系中进行平移,请在右侧乘以glm::translate
  • 但是为了让对象绕其初始原点旋转,我需要先撤消对它所做的一切,对吧?

标签: c++ opengl graphics


【解决方案1】:

按照@reprodukto 的建议,我找到了解决问题的方法。

我使用另外两个标志进行平移和缩放,并在paintGL 函数中一起处理这种情况。这样我就可以套用教科书的平移*旋转*缩放变换的顺序了。

感谢大家花时间评论和回答我的问题,非常感谢!

【讨论】:

    【解决方案2】:

    您需要有一个更新 x,y&z 值的函数。您所需要的只是创建一个包含 x、y 和 z 值的数组,然后您需要将其备份到一个临时数组中。删除旧数组并用新数组替换它。它就像这样。创建一个名为 POINT 的新变量,其中包含您在翻译对象时将使用的 x、y、z 值。

    typedef struct
    {
          GLfloat xyz[3];
    
    }POINT;
    
    void update(GLfloat x, GLfloat y, GLfloat z)
    {
           POINT *point;
           POINT new_point;
             new_point.xyz[0] = x;
             new_point.xyz[1] = y;
             new_point.xyz[2] = z;
           long my_points;
           if(my_points>0)
             point  = new POINT[my_points+1];
           else{
                POINT *temp = new POINT[my_points+1];
             for(long i=0;i<my_points;i++)
                          temp[i] = point[i];
                  delete [] point;
                  point = NULL;
               //Ok here you allocate new memory
                 point = new POINT[my_points+2];
                   for(long i=0;i<my_points;i++)
                        point[i] = temp[i];
                     delete [] temp;
                     temp = NULL;
           }
             point[my_points] = new_point;
    
    }
    

    【讨论】:

    • 我其实用的是新的openGL,顶点信息是先上传到顶点着色器的。目前我不想通过更改对象来执行转换。
    【解决方案3】:

    我相信您已经阅读过,开发人员通常从模型、视图和投影矩阵的角度进行思考。为了清楚起见,最好将这些视为:

    model_to_world 矩阵(将您的模型放置在游戏世界中)

    world_to_camera 矩阵(通过围绕相机移动整个游戏世界来定位您世界中的相机)

    world_to_projection 矩阵(它采用截头锥体形状并将其挤压成立方体,也就是 opengl 用于渲染的立方体,x、y 和 z 方向从 -1 到 +1 的立方体)

    请记住,矩阵可以同时进行平移、缩放和旋转,您可以在将单个矩阵传递到着色器程序之前将模型、视图和投影矩阵相乘一次。

    我不确定你在做什么,但我认为更好的解决方案是这样的:

    glm::mat4 originTransform; // this will initialize a matrix which represents no translation, scaling, or rotation, which will be useful later.
    glm::mat4 localMatrix; // your "model" matrix
    
    localMatrix = glm::translate(originTransform, glm::vec3(2.3f, 0.5f, -1.0f)); // I put in random values to translate by.
    
    // 2nd translation:
    localMatrix = glm::translate(localMatrix, glm::vec3(5.3f, 2.5f, -10.0f)); // Note that I'm inputting the localMatrix now and not the originTransform, otherwise everything that was done to this matrix before would be made irrelevant.
    
    localMatrix = glm::rotate(localMatrix, 90.0f, glm::vec3(1.0f, 0.0f, 0.0f)); // a 90 degree rotation on the x axis. Again, note that this is done on the localMatrix and not the originTransform.
    

    关于视图和投影矩阵,请参考网上教程。

    如果您尝试制作 2D 而不是 3D 的东西,或者如果这不能帮助您解决问题,请发表评论,我将编辑我的答案以提供帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-14
      • 2021-07-23
      相关资源
      最近更新 更多