c++ gluLookAt 的 OpenGL 显示问题

发布于 2024-11-06 08:53:01 字数 2750 浏览 0 评论 0原文

我一直在尝试解决这个程序:

绘制颜色立方体并允许用户适当移动相机以尝试透视观察的程序。立方体也应该旋转。

我已经完成了编码,就在这里。它似乎工作正常,除了 1 个简单的问题:

//Program to draw a color cube and allow the user to move the camera suitably to experiment with perspective viewing
#include <stdio.h>
#include <glut.h>

float v[][3] = {{-1,-1,1},{1,-1,1},{1,1,1},{-1,1,1},{-1,1,-1},{1,1,-1},{1,-1,-1},{-1,-1,-1}};
void drawPolygon(float a[3],float b[3],float c[3],float d[3])
{
    glBegin(GL_POLYGON);
        glVertex3fv(a);
        glVertex3fv(b);
        glVertex3fv(c);
        glVertex3fv(d);
    glEnd();
    glFlush();
}
void drawCube(float v[8][3])
{
    glColor3f(1,0,0);
    drawPolygon(v[0],v[1],v[2],v[3]);
    glColor3f(0,1,0);
    drawPolygon(v[0],v[1],v[6],v[7]);
    glColor3f(0,0,1);
    drawPolygon(v[7],v[6],v[5],v[4]);
    glColor3f(1,1,0);
    drawPolygon(v[2],v[3],v[4],v[5]);
    glColor3f(0,1,1);
    drawPolygon(v[1],v[2],v[5],v[6]);
    glColor3f(1,0,1);
    drawPolygon(v[0],v[3],v[4],v[7]);

    glFlush();
}
void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glColor3f(1,0,0);
    //glRotatef(60,1,1,0);
    drawCube(v);
    glFlush();
}

void reshape(int width,int height)
{
    glViewport(0,0,width,height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-2,2,-2,2,-2,2);
    glMatrixMode(GL_MODELVIEW);
    glutPostRedisplay();
}

void mouse(int btn,int state,int x,int y)
{
    if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
        glRotatef(2,1,0,0);
    if(btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
        glRotatef(2,0,1,0);
    if(btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
        glRotatef(2,0,0,1);

    glutPostRedisplay();
}
float ex=0,ey=0,ez=-10,cx=0,cy=0,cz=0,ux=0,uy=1,uz=0;
void keyboard(unsigned char key,int x,int y)
{
    if(key == 'x')
        ex += 0.1;
    if(key == 'X')
        ex -= 0.1;
    if(key == 'y')
        ey += 0.1;
    if(key == 'Y')
        ey -= 0.1;
    if(key == 'z')
        ez += 0.1;
    if(key == 'Z')
        ez -= 0.1;
    glMatrixMode(GL_PROJECTION);
    gluLookAt(ex,ey,ez,cx,cy,cz,ux,uy,uz);
    glutPostRedisplay();
}
void main(int argc,char** argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(800,800);
    glutCreateWindow("spin cube");

    glClearColor(1,1,1,0);

    glEnable(GL_DEPTH_TEST);

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

    glutMainLoop();
}

立方体通过鼠标点击旋转

相机按 x/X y/Y z/Z 移动

但问题是,当我第一次按下某个键时,显示消失。然后第二次它带有正确移动的相机。为什么?我希望相机只是移动而不是消失显示。怎么了?

I have been trying to solve this program:

Program to draw a color cube and allow the user to move the camera suitably to experiment with perspective viewing. Also the cube should rotate.

I have completed the coding and here it is. It seems to work fine except for 1 simple problem:

//Program to draw a color cube and allow the user to move the camera suitably to experiment with perspective viewing
#include <stdio.h>
#include <glut.h>

float v[][3] = {{-1,-1,1},{1,-1,1},{1,1,1},{-1,1,1},{-1,1,-1},{1,1,-1},{1,-1,-1},{-1,-1,-1}};
void drawPolygon(float a[3],float b[3],float c[3],float d[3])
{
    glBegin(GL_POLYGON);
        glVertex3fv(a);
        glVertex3fv(b);
        glVertex3fv(c);
        glVertex3fv(d);
    glEnd();
    glFlush();
}
void drawCube(float v[8][3])
{
    glColor3f(1,0,0);
    drawPolygon(v[0],v[1],v[2],v[3]);
    glColor3f(0,1,0);
    drawPolygon(v[0],v[1],v[6],v[7]);
    glColor3f(0,0,1);
    drawPolygon(v[7],v[6],v[5],v[4]);
    glColor3f(1,1,0);
    drawPolygon(v[2],v[3],v[4],v[5]);
    glColor3f(0,1,1);
    drawPolygon(v[1],v[2],v[5],v[6]);
    glColor3f(1,0,1);
    drawPolygon(v[0],v[3],v[4],v[7]);

    glFlush();
}
void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glColor3f(1,0,0);
    //glRotatef(60,1,1,0);
    drawCube(v);
    glFlush();
}

void reshape(int width,int height)
{
    glViewport(0,0,width,height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-2,2,-2,2,-2,2);
    glMatrixMode(GL_MODELVIEW);
    glutPostRedisplay();
}

void mouse(int btn,int state,int x,int y)
{
    if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
        glRotatef(2,1,0,0);
    if(btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
        glRotatef(2,0,1,0);
    if(btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
        glRotatef(2,0,0,1);

    glutPostRedisplay();
}
float ex=0,ey=0,ez=-10,cx=0,cy=0,cz=0,ux=0,uy=1,uz=0;
void keyboard(unsigned char key,int x,int y)
{
    if(key == 'x')
        ex += 0.1;
    if(key == 'X')
        ex -= 0.1;
    if(key == 'y')
        ey += 0.1;
    if(key == 'Y')
        ey -= 0.1;
    if(key == 'z')
        ez += 0.1;
    if(key == 'Z')
        ez -= 0.1;
    glMatrixMode(GL_PROJECTION);
    gluLookAt(ex,ey,ez,cx,cy,cz,ux,uy,uz);
    glutPostRedisplay();
}
void main(int argc,char** argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(800,800);
    glutCreateWindow("spin cube");

    glClearColor(1,1,1,0);

    glEnable(GL_DEPTH_TEST);

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

    glutMainLoop();
}

The cube rotates by mouse clicks

The camera moves by x/X y/Y z/Z

But the problem is that when i first press a key the display vanishes. Then the 2nd time it comes with properly moved camera. Why? I want the camera to just move and not vanish the display. What is wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

甜味超标? 2024-11-13 08:53:01

您的程序中有两个错误:

  • 您将 OpenGL 视为具有持久性的场景图 - 然而 OpenGL 只是绘制图片。
  • 您将视点变换应用于投影矩阵。

两者从根本上来说都是错误的。这是代码的更正版本:

//Program to draw a color cube and allow the user to move the camera suitably to experiment with perspective viewing
#include <stdio.h>
#include <glut.h>

float v[][3] = {{-1,-1,1},{1,-1,1},{1,1,1},{-1,1,1},{-1,1,-1},{1,1,-1},{1,-1,-1},{-1,-1,-1}};
void drawPolygon(float a[3],float b[3],float c[3],float d[3])
{
    glBegin(GL_POLYGON);
        glVertex3fv(a);
        glVertex3fv(b);
        glVertex3fv(c);
        glVertex3fv(d);
    glEnd();
}

void drawCube(float v[8][3])
{
    glColor3f(1,0,0);
    drawPolygon(v[0],v[1],v[2],v[3]);
    glColor3f(0,1,0);
    drawPolygon(v[0],v[1],v[6],v[7]);
    glColor3f(0,0,1);
    drawPolygon(v[7],v[6],v[5],v[4]);
    glColor3f(1,1,0);
    drawPolygon(v[2],v[3],v[4],v[5]);
    glColor3f(0,1,1);
    drawPolygon(v[1],v[2],v[5],v[6]);
    glColor3f(1,0,1);
    drawPolygon(v[0],v[3],v[4],v[7]);
}

float ex=0,ey=0,ez=-10,cx=0,cy=0,cz=0,ux=0,uy=1,uz=0;
void display()
{
    int win_width, win_height;
    win_width = glutGet(GLUT_WINDOW_WIDTH);
    win_height = glutGet(GLUT_WINDOW_HEIGHT);

    glViewport(0,0,width,height);

    glClearColor(1,1,1,0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnable(GL_DEPTH_TEST);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-2,2,-2,2,-2,2);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(ex,ey,ez,cx,cy,cz,ux,uy,uz);

    glRotatef(rot_x,1,0,0);
    glRotatef(rot_y,0,1,0);
    glRotatef(rot_z,0,0,1);

    glColor3f(1,0,0);
    //glRotatef(60,1,1,0);
    drawCube(v);

    glFinish();
}

void mouse(int btn,int state,int x,int y)
{
    if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
        rot_x += 2;

    if(btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
       rot_y += 2;

    if(btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
       rot_z += 2;

    glutPostRedisplay();
}

void keyboard(unsigned char key,int x,int y)
{
    if(key == 'x')
        ex += 0.1;
    if(key == 'X')
        ex -= 0.1;
    if(key == 'y')
        ey += 0.1;
    if(key == 'Y')
        ey -= 0.1;
    if(key == 'z')
        ez += 0.1;
    if(key == 'Z')
        ez -= 0.1;

    glutPostRedisplay();
}

void main(int argc,char** argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(800,800);
    glutCreateWindow("spin cube");

    glutDisplayFunc(display);
    glutMouseFunc(mouse);
    glutKeyboardFunc(keyboard);

    glutMainLoop();
}

There are two mistakes in your program:

  • You're treating OpenGL like a scene graph with persistency – however OpenGL just draws pictures.
  • You apply viewpoint transformation to the projection matrix.

Both is fundamentally wrong. Here's a corrected version of your code:

//Program to draw a color cube and allow the user to move the camera suitably to experiment with perspective viewing
#include <stdio.h>
#include <glut.h>

float v[][3] = {{-1,-1,1},{1,-1,1},{1,1,1},{-1,1,1},{-1,1,-1},{1,1,-1},{1,-1,-1},{-1,-1,-1}};
void drawPolygon(float a[3],float b[3],float c[3],float d[3])
{
    glBegin(GL_POLYGON);
        glVertex3fv(a);
        glVertex3fv(b);
        glVertex3fv(c);
        glVertex3fv(d);
    glEnd();
}

void drawCube(float v[8][3])
{
    glColor3f(1,0,0);
    drawPolygon(v[0],v[1],v[2],v[3]);
    glColor3f(0,1,0);
    drawPolygon(v[0],v[1],v[6],v[7]);
    glColor3f(0,0,1);
    drawPolygon(v[7],v[6],v[5],v[4]);
    glColor3f(1,1,0);
    drawPolygon(v[2],v[3],v[4],v[5]);
    glColor3f(0,1,1);
    drawPolygon(v[1],v[2],v[5],v[6]);
    glColor3f(1,0,1);
    drawPolygon(v[0],v[3],v[4],v[7]);
}

float ex=0,ey=0,ez=-10,cx=0,cy=0,cz=0,ux=0,uy=1,uz=0;
void display()
{
    int win_width, win_height;
    win_width = glutGet(GLUT_WINDOW_WIDTH);
    win_height = glutGet(GLUT_WINDOW_HEIGHT);

    glViewport(0,0,width,height);

    glClearColor(1,1,1,0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnable(GL_DEPTH_TEST);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-2,2,-2,2,-2,2);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(ex,ey,ez,cx,cy,cz,ux,uy,uz);

    glRotatef(rot_x,1,0,0);
    glRotatef(rot_y,0,1,0);
    glRotatef(rot_z,0,0,1);

    glColor3f(1,0,0);
    //glRotatef(60,1,1,0);
    drawCube(v);

    glFinish();
}

void mouse(int btn,int state,int x,int y)
{
    if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
        rot_x += 2;

    if(btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
       rot_y += 2;

    if(btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
       rot_z += 2;

    glutPostRedisplay();
}

void keyboard(unsigned char key,int x,int y)
{
    if(key == 'x')
        ex += 0.1;
    if(key == 'X')
        ex -= 0.1;
    if(key == 'y')
        ey += 0.1;
    if(key == 'Y')
        ey -= 0.1;
    if(key == 'z')
        ez += 0.1;
    if(key == 'Z')
        ez -= 0.1;

    glutPostRedisplay();
}

void main(int argc,char** argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(800,800);
    glutCreateWindow("spin cube");

    glutDisplayFunc(display);
    glutMouseFunc(mouse);
    glutKeyboardFunc(keyboard);

    glutMainLoop();
}
绝不服输 2024-11-13 08:53:01

gluLookAt 不应进入投影矩阵,而应进入模型视图。我还建议您跟踪立方体旋转和眼睛位置,并将它们应用到显示函数中:

//Program to draw a color cube and allow the user to move the camera suitably to experiment with perspective viewing
#include <stdio.h>
#include <glut.h>

float ex=0,ey=0,ez=-10,cx=0,cy=0,cz=0,ux=0,uy=1,uz=0;
float cubex=0,cubey=0,cubez=0;
float v[][3] = {{-1,-1,1},{1,-1,1},{1,1,1},{-1,1,1},{-1,1,-1},{1,1,-1},{1,-1,-1},{-1,-1,-1}};
void drawPolygon(float a[3],float b[3],float c[3],float d[3])
{
    glBegin(GL_POLYGON);
        glVertex3fv(a);
        glVertex3fv(b);
        glVertex3fv(c);
        glVertex3fv(d);
    glEnd();
}
void drawCube(float v[8][3])
{
    glColor3f(1,0,0);
    drawPolygon(v[0],v[1],v[2],v[3]);
    glColor3f(0,1,0);
    drawPolygon(v[0],v[1],v[6],v[7]);
    glColor3f(0,0,1);
    drawPolygon(v[7],v[6],v[5],v[4]);
    glColor3f(1,1,0);
    drawPolygon(v[2],v[3],v[4],v[5]);
    glColor3f(0,1,1);
    drawPolygon(v[1],v[2],v[5],v[6]);
    glColor3f(1,0,1);
    drawPolygon(v[0],v[3],v[4],v[7]);
}
void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(ex,ey,ez,cx,cy,cz,ux,uy,uz);
    glRotatef(cubex, 1, 0, 0);
    glRotatef(cubey, 0, 1, 0);
    glRotatef(cubez, 0, 0, 1);

    glColor3f(1,0,0);
    //glRotatef(60,1,1,0);
    drawCube(v);
    glFinish();
}

void reshape(int width,int height)
{
    glViewport(0,0,width,height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-2,2,-2,2,-2,2);
    glutPostRedisplay();
}

void mouse(int btn,int state,int x,int y)
{
    if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
        cubex += 2;
    if(btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
        cubey += 2;
    if(btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
        cubez += 2;

    glutPostRedisplay();
}

void keyboard(unsigned char key,int x,int y)
{
    if(key == 'x')
        ex += 0.1;
    if(key == 'X')
        ex -= 0.1;
    if(key == 'y')
        ey += 0.1;
    if(key == 'Y')
        ey -= 0.1;
    if(key == 'z')
        ez += 0.1;
    if(key == 'Z')
        ez -= 0.1;
    glutPostRedisplay();
}
void main(int argc,char** argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(800,800);
    glutCreateWindow("spin cube");

    glClearColor(1,1,1,0);

    glEnable(GL_DEPTH_TEST);

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

    glutMainLoop();
}

这并不 100% 相当于您最初想要实现的目标,因为它围绕 x 应用了三个累积的连续旋转, y 轴和 z 轴分别代替增量轴。

此外,您不需要所有的 glFlush 调用,在渲染结束时对 glFinish 的一次调用就足够了,甚至更好;交换到双缓冲渲染并使用 glutSwapBuffers 代替。

gluLookAt shouldn't go in to the projection matrix but into the modelview. I would also suggest that you keep track of your cube rotation and eye position and apply them inside the display function instead:

//Program to draw a color cube and allow the user to move the camera suitably to experiment with perspective viewing
#include <stdio.h>
#include <glut.h>

float ex=0,ey=0,ez=-10,cx=0,cy=0,cz=0,ux=0,uy=1,uz=0;
float cubex=0,cubey=0,cubez=0;
float v[][3] = {{-1,-1,1},{1,-1,1},{1,1,1},{-1,1,1},{-1,1,-1},{1,1,-1},{1,-1,-1},{-1,-1,-1}};
void drawPolygon(float a[3],float b[3],float c[3],float d[3])
{
    glBegin(GL_POLYGON);
        glVertex3fv(a);
        glVertex3fv(b);
        glVertex3fv(c);
        glVertex3fv(d);
    glEnd();
}
void drawCube(float v[8][3])
{
    glColor3f(1,0,0);
    drawPolygon(v[0],v[1],v[2],v[3]);
    glColor3f(0,1,0);
    drawPolygon(v[0],v[1],v[6],v[7]);
    glColor3f(0,0,1);
    drawPolygon(v[7],v[6],v[5],v[4]);
    glColor3f(1,1,0);
    drawPolygon(v[2],v[3],v[4],v[5]);
    glColor3f(0,1,1);
    drawPolygon(v[1],v[2],v[5],v[6]);
    glColor3f(1,0,1);
    drawPolygon(v[0],v[3],v[4],v[7]);
}
void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(ex,ey,ez,cx,cy,cz,ux,uy,uz);
    glRotatef(cubex, 1, 0, 0);
    glRotatef(cubey, 0, 1, 0);
    glRotatef(cubez, 0, 0, 1);

    glColor3f(1,0,0);
    //glRotatef(60,1,1,0);
    drawCube(v);
    glFinish();
}

void reshape(int width,int height)
{
    glViewport(0,0,width,height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-2,2,-2,2,-2,2);
    glutPostRedisplay();
}

void mouse(int btn,int state,int x,int y)
{
    if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
        cubex += 2;
    if(btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
        cubey += 2;
    if(btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
        cubez += 2;

    glutPostRedisplay();
}

void keyboard(unsigned char key,int x,int y)
{
    if(key == 'x')
        ex += 0.1;
    if(key == 'X')
        ex -= 0.1;
    if(key == 'y')
        ey += 0.1;
    if(key == 'Y')
        ey -= 0.1;
    if(key == 'z')
        ez += 0.1;
    if(key == 'Z')
        ez -= 0.1;
    glutPostRedisplay();
}
void main(int argc,char** argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(800,800);
    glutCreateWindow("spin cube");

    glClearColor(1,1,1,0);

    glEnable(GL_DEPTH_TEST);

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

    glutMainLoop();
}

This isn't 100% equivalent to what you were originally trying to achieve since it applies three accumulated consecutive rotations around the x, y and z axis respectively instead of incremental ones.

Also you don't need all the glFlush calls, a single call to glFinish at the end of the rendering should be sufficient, or even better; swap to double buffered rendering and use glutSwapBuffers instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文