用于透视投影的相机旋转

时间:2009-12-22 13:19:01

标签: c++ opengl camera rotation 3d

我刚开始玩OpenGl来渲染一些结构,每个结构都包含多个多边形。 基本上我想执行相当于在世界(结构)坐标中设置(0,0,z)的摄像机并围绕世界轴的x,y和z轴(按此顺序!)旋转它来渲染每个结构的视图(据我所知,通常的做法是使用逆相机矩阵)。因此,据我所知,我需要翻译(到世界原点,即(0,0,-z))* rotateZ rotateY rotateX * translate(重新定义世界原点见下文)

所以我觉得我需要这样的东西:

//Called when the window is resized
void handleResize(int w, int h) {
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(9.148, (double)w / (double)h, 800.0, 1500.0);
}

float _Zangle = 10.0f; 
float _cameraAngle = 90.0f;

//Draws the 3D scene
void drawScene() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
    glLoadIdentity(); //Reset the drawing perspective

    glTranslatef(0.0f, 0.0f, -z); //Move forward Z (mm) units
    glRotatef(-_Zangle, 0.0f, 0.0f, 1.0f); //Rotate "camera" about the z-axis
    glRotatef(-_cameraAngle, 0.0f, 1.0f, 0.0f); //Rotate the "camera" by camera_angle about y-axis
    glRotatef (90.0f,1.0f,0.0f,0.0f); // rotate "camera" by 90 degrees about x-axis
    glTranslatef(-11.0f,189.0f,51.0f); //re-define origin of world coordinates to be (11,-189,-51) - applied to all polygon vertices

glPushMatrix(); //Save the transformations performed thus far

glBegin(GL_POLYGON);


    glVertex3f(4.91892,-225.978,-50.0009);
        glVertex3f(5.73534,-225.978,-50.0009);
        glVertex3f(6.55174,-225.978,-50.0009);
        glVertex3f(7.36816,-225.978,-50.0009);
        .......// etc
glEnd();
glPopMatrix();

然而,当我编译并运行它时,_angle和_cameraAngle似乎被反转,即_angle似乎围绕视口的y轴(垂直)旋转,_cameraAngle绕z轴旋转(进入视口平面)?我做错了什么?

感谢您抽出宝贵时间阅读本文

5 个答案:

答案 0 :(得分:5)

简短的回答是:使用gluLookAt()。此实用程序功能可创建正确的查看矩阵。

更长的答案是每个OpenGL转换调用都使用当前矩阵并将其乘以为完成转换而构建的矩阵。通过调用一系列OpenGL转换函数,您可以构建一个将应用转换组合的转换矩阵。有效地,矩阵将是M = M1 * M2 * M3。 。 。在数学上,变换在上面的等式中从右到左应用。

您的代码无法移动相机。它停留在原点,向下看负z轴。您的变换将模型空间中的所有内容移动到(11,-189,-51),围绕x轴旋转所有内容90度,围绕y轴旋转所有内容90度,围绕z轴旋转所有内容10度,然后进行平移沿z轴的所有-z

编辑:更多信息

我对你想要完成的事情感到有些困惑,但我认为你想要在原点拥有元素,并让相机看看这些元素。眼睛坐标将是您想要相机的位置,中心坐标将是您想要对象的位置。我会用一点三角法来计算相机的位置,然后将它指向原点。

在这种情况下,我通常使用以原点为中心的经度,纬度和高度来跟踪摄像机位置。计算眼睛坐标的x,y,z是simplex = elv * cos(lat)* sin(lon),y = elv * sin(lat),z = elv * cos(lat)* cos(lat)。

我的gluLookAt调用将是gluLookAt(x, y, z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

您可以通过更改gluLookAt的最后三个坐标来旋转相机。

答案 1 :(得分:1)

z轴从显示器的中心进入您。因此,围绕z轴旋转应使相机旋转到位(就像在xy平面上的2D旋转一样)。我不知道,但是这里发生了什么?

答案 2 :(得分:0)

您可能遇到Gimbal Lock。尝试删除其中一个旋转,看看事情是否按预期方式工作。

虽然您无法在OpenGL中实际移动相机,但您可以通过移动其他所有内容来模拟相机运动。这就是你听说逆相机矩阵的原因。我们可以通过(0,0,-10)移动世界上的所有东西,而不是通过(0,0,10)移动相机。如果将它们扩展到矩阵中,您会发现它们彼此相反。

我还注意到,根据提供的代码,您不需要glPushMatrix() / glPopMatrix()来电。也许有些代码没有显示需要它们。

最后,您能否了解一下您要渲染的内容?没有一些上下文,调试旋转可能很难。

答案 3 :(得分:0)

简短的回答:好的提示

更长的答案:是的,矩阵乘法的顺序是明确的......这就是我用反相机矩阵表示将结构的所有世界坐标移动到相机坐标中的意思(因此在我的评论中使用“相机”; - ))而不是实际翻译和旋转相机到世界坐标。

因此,如果我正确地阅读了这些行,你会建议:

void drawScene() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
    glLoadIdentity(); //Reset the drawing perspective
gluLookAt(0.0,0.0,z,11.0,-189.0,-51.0,0.0,1.0,0.0); //eye(0,0,z) look at re-defined world origin(11,-189,-51) and up(0.0,1.0,0.0)

    glRotatef(-_Zangle, 0.0f, 0.0f, 1.0f); //Rotate "camera" (actually structures) about the z-axis
    glRotatef(-_cameraAngle, 0.0f, 1.0f, 0.0f); //Rotate the "camera" (actually structures!) by camera_angle about y-axis
    glRotatef (90.0f,1.0f,0.0f,0.0f); // rotate "camera" (actually structures) by 90 degrees about x-axis


glPushMatrix();

或者我还缺少什么?

答案 4 :(得分:0)

我认为你正在将你的世界的轴与相机的轴混合,

GLRotatef仅使用相机的轴,一旦相机旋转,它们与世界轴不同。