OpenGL(C语言):用键盘移动形状(失真问题)

时间:2016-05-17 13:38:18

标签: c opengl codeblocks glut

好吧,我们为OpenGL提供了以下C(GLUT项目)。我使用CodeBlocks来编译它(删除了额外的main()函数文件)。 我有一些例子,抱歉,如果我写OpenGL的方式不好。最重要的是让它工作正常。

我需要的结果是:“机器人先生”的所有形状(头部,身体,手部,腿部),通过键盘箭头键移动。它按预期工作,但从某些点开始,然后,一些形状被扭曲。我不知道为什么以及如何解决它。

    #include <GL/glut.h>

GLuint kefali_x1=5, kefali_y1=30, kefali_x2=15, kefali_y2=30, kefali_x3=15, kefali_y3=40, kefali_x4=5,kefali_y4=40;
GLuint soma_x1=0, soma_y1=10, soma_x2=20, soma_y2=10, soma_x3=20, soma_y3=30, soma_x4=0, soma_y4=30;
GLuint podia_x1=10, podia_y1=10, podia_x2=20, podia_y2=0, podia_x3=10, podia_y3=-5, podia_x4=0, podia_y4=0;
GLuint dexi_xeri_x1=20, dexi_xeri_y1=30, dexi_xeri_x2=30, dexi_xeri_y2=27.5, dexi_xeri_x3=20, dexi_xeri_y3=25;
GLuint aristero_xeri_x1=-10, aristero_xeri_y1=27.5, aristero_xeri_x2=0, aristero_xeri_y2=30, aristero_xeri_x3=0, aristero_xeri_y3=25;


// σύνθετο σχήμα
GLuint listID;

void MrRobot(GLsizei displayListID)
{
    glNewList(displayListID,GL_COMPILE);

    //Save current colour state
    glPushAttrib(GL_CURRENT_BIT);

    // σώμα
    glColor3f(0.5,0.5,0.5);
    glBegin(GL_POLYGON);
    glVertex2f(soma_x1,soma_y1);
    glVertex2f(soma_x2,soma_y2);
    glVertex2f(soma_x3,soma_y3);
    glVertex2f(soma_x4,soma_y4);
    glEnd();

    // κεφάλι
    glColor3f(0,0,1);
    glBegin(GL_POLYGON);
    glVertex2f(kefali_x1,kefali_y1);
    glVertex2f(kefali_x2,kefali_y2);
    glVertex2f(kefali_x3,kefali_y3);
    glVertex2f(kefali_x4,kefali_y4);
    glEnd();

    // πόδια
    glColor3f(1,0,0);
    glBegin(GL_TRIANGLE_FAN);
    glVertex2f(podia_x1,podia_y1);
    glVertex2f(podia_x2,podia_y2);
    glVertex2f(podia_x3,podia_y3);
    glVertex2f(podia_x4,podia_y4);
    glEnd();

    // δεξί χέρι
    glColor3f(0,1,0);
    glBegin(GL_TRIANGLES);
    glVertex2f(dexi_xeri_x1,dexi_xeri_y1);
    glVertex2f(dexi_xeri_x2,dexi_xeri_y2);
    glVertex2f(dexi_xeri_x3,dexi_xeri_y3);
    glEnd();

    // αριστερό χέρι
    glColor3f(0,1,0);
    glBegin(GL_TRIANGLES);
    glVertex2f(aristero_xeri_x1,aristero_xeri_y1);
    glVertex2f(aristero_xeri_x2,aristero_xeri_y2);
    glVertex2f(aristero_xeri_x3,aristero_xeri_y3);
    glEnd();

    //Recall saved colour state
    glPopAttrib();

    glEndList();
}

void display()
{
    glClearColor(0,0,0,0);

    glClear(GL_COLOR_BUFFER_BIT);

    glColor3f(1,0,0);

    listID=glGenLists(1);

    MrRobot(listID);

    //Execute the display list (the modelview matrix will be applied)
    glCallList(listID);

    glFlush();
}

void keyboard(unsigned char key,int x, int y)
{
    printf("\nKeyboard event detected. \nCharacter key: %c\nMouse pointer position: x=%d y=%d",key,x,y);

    if (key==GLUT_KEY_UP)
    {
        kefali_y1++;
        kefali_y2++;
        kefali_y3++;
        kefali_y4++;

        soma_y1++;
        soma_y2++;
        soma_y3++;
        soma_y4++;

        podia_y1++;
        podia_y2++;
        podia_y3++;
        podia_y4++;

        dexi_xeri_y1++;
        dexi_xeri_y2++;
        dexi_xeri_y3++;

        aristero_xeri_y1++;
        aristero_xeri_y2++;
        aristero_xeri_y3++;
    }
    if (key==GLUT_KEY_DOWN)
    {
        kefali_y1--;
        kefali_y2--;
        kefali_y3--;
        kefali_y4--;

        soma_y1--;
        soma_y2--;
        soma_y3--;
        soma_y4--;

        podia_y1--;
        podia_y2--;
        podia_y3--;
        podia_y4--;

        dexi_xeri_y1--;
        dexi_xeri_y2--;
        dexi_xeri_y3--;

        aristero_xeri_y1--;
        aristero_xeri_y2--;
        aristero_xeri_y3--;
    }
    if (key==GLUT_KEY_LEFT)
    {
        kefali_x1--;
        kefali_x2--;
        kefali_x3--;
        kefali_x4--;

        soma_x1--;
        soma_x2--;
        soma_x3--;
        soma_x4--;

        podia_x1--;
        podia_x2--;
        podia_x3--;
        podia_x4--;

        dexi_xeri_x1--;
        dexi_xeri_x2--;
        dexi_xeri_x3--;

        aristero_xeri_x1--;
        aristero_xeri_x2--;
        aristero_xeri_x3--;
    }
    if (key==GLUT_KEY_RIGHT)
    {
        kefali_x1++;
        kefali_x2++;
        kefali_x3++;
        kefali_x4++;

        soma_x1++;
        soma_x2++;
        soma_x3++;
        soma_x4++;

        podia_x1++;
        podia_x2++;
        podia_x3++;
        podia_x4++;

        dexi_xeri_x1++;
        dexi_xeri_x2++;
        dexi_xeri_x3++;

        aristero_xeri_x1++;
        aristero_xeri_x2++;
        aristero_xeri_x3++;
    }

    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    glutInit(&argc,argv);
    glutInitWindowPosition(50,50);
    glutInitWindowSize(800,600);
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    glutCreateWindow("MrROBOT");

    glMatrixMode(GL_MODELVIEW);
    gluOrtho2D(-10,50,-10,50);

    glScalef(0.4,0.4,0.4);

    glutDisplayFunc(display);
    glutSpecialFunc(keyboard);
    glutMainLoop();

    return 0;
}

2 个答案:

答案 0 :(得分:1)

  抱歉,如果我写OpenGL的方式不好。最重要的是让它工作正常。

这两者通常是齐头并进的。如果您的(OpenGL)代码不好,您的程序将无法运行&#34;罚款&#34;。编写干净的代码,您的程序有更好的工作机会。

所以这里有几个问题:为什么xyz的大量单独(全局)变量?使用结构!为什么使用显示列表立即绘图?这不是显示列表的用途,所以不要使用它们!为什么要统一改变顶点位置值而不是简单地改变转换?

清洁代码结构就是能够推理程序。如果程序有问题,最好的调试方法之一就是清理代码;如果你不想通过思考来欺骗自己,通常所有不好的事情都会变得清晰。#啊;它只是一个快速的黑客攻击&#34;

这不容易理解吗?它也可以工作

#include <stddef.h>
#include <stdio.h>
#include <GL/glut.h>

float robot_x = 0, robot_y = 0;

typedef GLfloat vec2[2];

enum { kefali_len = 4 };
vec2 const kefali[kefali_len] = { {5, 30}, {15, 30}, {15, 40}, {5, 40} };

enum { soma_len = 4 };
vec2 const soma[soma_len] = { {0, 10}, {20, 10}, {20, 30}, {0, 30} };

enum { podia_len = 4 };
vec2 const podia[podia_len] = { {10, 10}, {20,  0}, {10, -5}, {0,  0} };

enum { dexi_len = 3 };
vec2 const dexi[dexi_len] = { {20, 30}, {30, 27.5}, {20, 25} };

enum { aristero_len = 3};
vec2 const aristero[aristero_len] = { {-10, 27.5}, {0, 30}, {0, 25} };

static
void draw_vertices2(GLenum mode, vec2 const * const v, size_t n)
{
    size_t i;
    /* use of glBegin + glVertex is outdated since 1997. Whoever teaches
     * is these days should either bring their coursework up to date
     * or consider retirement. */
    glBegin(mode);
    for(i=0; i < n; ++i) {
        glVertex2fv(v[i]);
    }
    glEnd();
}


static
void MrRobot(void)
{
    //Save current colour state
    glPushAttrib(GL_CURRENT_BIT);

    // σώμα
    glColor3f(0.5,0.5,0.5);
    draw_vertices2(GL_POLYGON, soma, soma_len);

    // κεφάλι
    glColor3f(0,0,1);
    draw_vertices2(GL_POLYGON, kefali, kefali_len);
    glBegin(GL_POLYGON);

    // πόδια
    glColor3f(1,0,0);
    draw_vertices2(GL_TRIANGLE_FAN, podia, podia_len);

    // δεξί χέρι
    glColor3f(0,1,0);
    draw_vertices2(GL_TRIANGLES, dexi, dexi_len);

    // αριστερό χέρι
    glColor3f(0,1,0);
    draw_vertices2(GL_TRIANGLES, aristero, aristero_len);

    //Recall saved colour state
    glPopAttrib();
}


static
GLuint generate_display_list_robot(void)
{
    GLuint const list = glGenLists(1);
    if( list ) {
        glNewList(list, GL_COMPILE);
        MrRobot();
        glEndList();
    }
    return list;
}

static GLuint display_list_robot = 0;

static
void display(void)
{
    glClearColor(0,0,0,0);
    glClear(GL_COLOR_BUFFER_BIT);

    glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT) );

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(-10,50,-10,50);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glScalef(0.4,0.4,0.4);

    glPushMatrix();
    glTranslatef(robot_x, robot_y, 0);
    if( display_list_robot ) {
        glCallList(display_list_robot);
    } else {
        MrRobot();
    }
    glPopMatrix();

    glutSwapBuffers();
}

static
void keyboard(int key, int pointer_x, int pointer_y)
{
    fprintf(stderr,
        "\nKeyboard event.\nCharacter: %d\nMouse pointer position: x=%d y=%d",
        (int)key,
        (int)pointer_x,
        (int)pointer_y );

    switch( key ) {
    case GLUT_KEY_UP:    ++robot_y; break;
    case GLUT_KEY_DOWN:  --robot_y; break;
    case GLUT_KEY_RIGHT: ++robot_x; break;
    case GLUT_KEY_LEFT:  --robot_x; break;
    }
    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    size_t i;
    glutInit(&argc,argv);
    glutInitWindowPosition(50,50);
    glutInitWindowSize(800,600);
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
    glutCreateWindow("MrROBOT");

    /* argv[0] is program name */
    for(i = 1; i < argc; ++i) {
        if( 'd' == argv[i][0] ) {
            if( !display_list_robot ) {
                display_list_robot = generate_display_list_robot();
            }
        }
    }

    glutDisplayFunc(display);
    glutSpecialFunc(keyboard);

    glutMainLoop();

    return 0;
}

答案 1 :(得分:0)

您有以下问题阻止您的程序在屏幕上正确绘制所需的形状:

  • 将顶点声明并递增为GLuint数据类型
  • 将它们描绘成GLfloat s,这与上述内容相矛盾,导致未定义的行为

只需更正此类型的每个规范:

glVertex2f(…_xi,…_yi);

glVertex2i(…_xi,…_yi);

这应解决“失真”问题。

请也明白,这个答案并没有解决你的编码风格,这并不好。所以不是教程网站。查看帖子的评论。