需要帮助在 OpenGL 中移动相机

Posted

技术标签:

【中文标题】需要帮助在 OpenGL 中移动相机【英文标题】:need help moving a camera in OpenGL 【发布时间】:2015-11-01 23:54:26 【问题描述】:

我正在开发一个简单的 OpenGL 项目。 我想要一个简单的相机在透视模式下移动。

我一直在阅读有关投影矩阵、gluLookAt 和模型视图矩阵的信息。我一直在阅读,我应该做的就是在投影矩阵中调用透视图,然后在模型视图矩阵中进行所有转换和相机移动。

#include "GLheaders.h"

void drawWorldAxis() 
    glLoadIdentity();
    glBegin(GL_LINES);
    glNormal3f(0, 0, 1);
    glColor3ub(255, 0, 0);
    glVertex3f(0,0,0);
    glVertex3f(1,0,0);
    glColor3ub(0, 255, 0);
    glVertex3f(0,0,0);
    glVertex3f(0,1,0);
    glColor3ub(0, 0, 255);
    glVertex3f(0,0,0);
    glVertex3f(0,0,1);
    glEnd();


void keyboard(unsigned char key, int x, int y) 
    glutPostRedisplay();


static float eye[3] = .5, .5, .5;
#include <stdio.h>
void display() 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(55.0, 1, .1, 10000);



    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    drawWorldAxis();
    printf("eye at <%f, %f, %f>\n", eye[0], eye[1], eye[2]);
    fflush(stdout);
    gluLookAt(eye[0], eye[1], eye[2], 0, 0, 0, 0, 1, 0);

    eye[0] += .1;
    eye[1] += .1;

    glFlush();
    glutSwapBuffers();


void reshape(int w, int h) 
    glViewport(0,0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(55.0, 1, -1, 10000);
    glMatrixMode(GL_MODELVIEW);
    glutPostRedisplay();



int main(int argc, char** argv) 
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE| GLUT_DEPTH);
    glutInitWindowSize(400,400);
    glutCreateWindow("Tiny Test");

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);

    glEnable(GL_NORMALIZE);
    glEnable(GL_DEPTH_TEST);

    glutMainLoop();

    return EXIT_SUCCESS;

我希望这段代码显示代表世界坐标系的 x、y 和 z 轴的三行,并且当按下键时,相机应该移动并开始从越来越大的角度查看原点/坐标轴.

这里出了什么问题?我一直把头撞到墙上,试图弄清楚为什么什么都没有动。只有当我将 gluLookAt 调用放在投影矩阵中时它才会改变,我一直被告知这是一个糟糕的主意。

【问题讨论】:

【参考方案1】:

坐标十字是在你设置lookAt矩阵之前绘制的,因此矩阵没有效果。

您必须更改顺序,以便在绘制时矩阵已经存在:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eye[0], eye[1], eye[2], 0, 0, 0, 0, 1, 0);
drawWorldAxis();
printf("eye at <%f, %f, %f>\n", eye[0], eye[1], eye[2]);
fflush(stdout);

那么还有第二个问题:你正在重置drawWorldAxis第一行的模型矩阵。在这里,您可以删除glLoadIdentity 调用或先将前一个矩阵压入堆栈:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eye[0], eye[1], eye[2], 0, 0, 0, 0, 1, 0);

glPushMatrix();    

drawWorldAxis();

glPopMatrix();

printf("eye at <%f, %f, %f>\n", eye[0], eye[1], eye[2]);
fflush(stdout);

【讨论】:

谢谢!这引导我去我需要去的地方! loadIdentity 也在制作它,所以我没有看到世界轴,因为lookAt 也没有应用于它。清除 loadIdentity,重新排序似乎可以解决问题!【参考方案2】:

感谢@BDL 帮助解决此问题!这是我想要的正确代码

#include "GLheaders.h"

void drawWorldAxis() 
    glBegin(GL_LINES);
    glNormal3f(0, 0, 1);
    glColor3ub(255, 0, 0);
    glVertex3f(0,0,0);
    glVertex3f(1,0,0);
    glColor3ub(0, 255, 0);
    glVertex3f(0,0,0);
    glVertex3f(0,1,0);
    glColor3ub(0, 0, 255);
    glVertex3f(0,0,0);
    glVertex3f(0,0,1);
    glEnd();


void keyboard(unsigned char key, int x, int y) 
    glutPostRedisplay();


static float eye[3] = -.1, -.1, 1;
#include <stdio.h>
void display() 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(55.0, 1, .1, 10000);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    printf("eye at <%f, %f, %f>\n", eye[0], eye[1], eye[2]);
    fflush(stdout);
    gluLookAt(eye[0], eye[1], eye[2], 0, 0, 0, 0, 1, 0);
    drawWorldAxis();

    eye[0] += .1;
    eye[1] += .1;

    glFlush();
    glutSwapBuffers();


void reshape(int w, int h) 
    glViewport(0,0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(55.0, 1, -1, 10000);
    glMatrixMode(GL_MODELVIEW);
    glutPostRedisplay();



int main(int argc, char** argv) 
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE| GLUT_DEPTH);
    glutInitWindowSize(400,400);
    glutCreateWindow("Tiny Test");

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);

    glEnable(GL_NORMALIZE);
    glEnable(GL_DEPTH_TEST);

    glutMainLoop();

    return EXIT_SUCCESS;

【讨论】:

以上是关于需要帮助在 OpenGL 中移动相机的主要内容,如果未能解决你的问题,请参考以下文章

当阴影相机移动时,Opengl es 2.0阴影会闪烁

如何在 C++ 中使用 sdl、opengl 移动相机时修复奇怪的相机旋转

OpenGL模拟波斯王子相机

在OpenGL中平移和移动相机的正确方法?

在OpenGL中从上方移动相机

OpenGL/C++ 中“2D”相机的移动