2016-05-17 38 views
-2

那么,我们有以下用于OpenGL的C(GLUT项目)。我使用CodeBlocks进行编译(删除了额外的main()函数文件)。 我基于一些例子,抱歉,如果我写OpenGL的方式不好。主要的是让它工作正常。OpenGL(C语言):使用键盘移动形状(失真问题)

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

#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; 
} 
+0

你为什么使用显示列表?我的意思是,为什么你要在绘图函数中创建一个显示列表,以便在下一步中调用它?显示列表的目的是用一次又一次使用的东西填充它,保持不变,并可以通过一次调用来调用它。你所做的是创建许多不同的显示列表,并进行更改(并且不删除旧显示列表)。程序中的显示列表除了占用越来越多的资源外没有其他用途。摆脱它! – datenwolf

+0

关于编码风格:你知道什么'struct's,是吗?此外,为什么你有大量的变量,所有这些都会得到相同的变更?你可以使用这三个浮点数并使用变换矩阵完成其余的操作。 – datenwolf

+0

我不同意这个问题必须关闭作为题外话。不管OP的英文多么穷,很明显,期望的行为是绘制两个矩形,两个三角形,一个三角形,并使用箭头键在屏幕上移动形状。这也是数据类型不匹配导致UB打破绘图例程的明显例子。其中一个答案也显示了如何从根本上改善这些示例程序的整体编码。由于我没有足够的特权投票反对结案,这是我表达意见的唯一途径。 – user3078414

回答

0

,可以有以下这防止程序正确绘制所需的形状,在屏幕上的问题:

  • 声明和递增的顶点作为GLuint数据类型
  • 画他们,如果他们GLfloat s,与上述相矛盾,导致未定义的行为

只需更正每个指定这种类型的阳离子:

glVertex2f(…_xi,…_yi); 

glVertex2i(…_xi,…_yi); 

这应该可以解决的 “失真” 的问题。

请理解,这个答案没有解决你的编码风格,这是不好的。 SO不是教程网站。查看您的帖子的评论。

1

对不起,如果我写OpenGL的方式是坏的。主要的是让它工作正常。

这两个通常是齐头并进。如果你的(OpenGL)代码不好,你的程序将无法正常工作。写干净的代码,你的程序有更好的机会正常工作。

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

干净的代码结构就是能够推理程序。如果程序有问题,最好的调试方法之一是清理代码;通常所有不好的事情会变得清晰,如果你不想愚弄自己的想法“啊,这只是一个快速入侵”

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

#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; 
}