OpenGL平移和旋转的同时

时间:2016-09-24 13:49:52

标签: c++ opengl graphics

在我的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的调用序列引起的吗?有人可以给我一些帮助吗?

3 个答案:

答案 0 :(得分:1)

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

我使用另外两个标志进行平移和缩放,并在paintGL函数中一起处理所有情况。通过这种方式,我可以应用Translate * Rotate * Scaling转换的教科书顺序。

感谢大家抽出时间发表评论并回答我的问题,我真的很感激!

答案 1 :(得分:0)

您需要具有更新x,y和amp; z值的函数。您只需要创建一个包含x,y和amp; 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;

}

答案 2 :(得分:0)

我确信您已阅读过,开发人员通常会考虑模型,视图和投影矩阵。只是为了说清楚,最好将它们视为:

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的内容,或者这样做无法帮助您解决问题,请发表评论,我会编辑我的答案以尝试提供帮助。