2016-05-17 78 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; 
}