使用 C++ 在 OpenGL 中使用键盘移动 3d 形状

Posted

技术标签:

【中文标题】使用 C++ 在 OpenGL 中使用键盘移动 3d 形状【英文标题】:Moving 3d shapes with keyboard in OpenGL with C++ 【发布时间】:2020-06-10 17:36:52 【问题描述】:

我正在尝试使用箭头和向上翻页、向下翻页键将金字塔和立方体“分别”移动到前后、上下和左右,但我还做不到,没有一个拖曳形状正在移动我的两个问题是:我如何选择我想要移动的这些形状之一,为什么它们都没有移动? 谢谢。

#include <GL/glut.h>
float xmove = 0, ymove = 0, zmove = 0;
float degree = 0;
float xscale = 1, yscale = 1, zscale = 1;
void right(void)

    glLoadIdentity();//koordinat sistemimizetkilenmesin
    xmove += 0.1;

void left(void)

    glLoadIdentity();
    xmove -= 0.1;

void up(void)

    glLoadIdentity();
    ymove += 0.1;

void down(void)

    glLoadIdentity();
    ymove -= 0.1;

void front(void)

    glLoadIdentity();
    zmove -= 0.1;

void back(void)

    glLoadIdentity();
    zmove += 0.1;

void keyboard(int button, int x, int y)

    switch (button)
    
    case GLUT_KEY_LEFT:left(); break;
    case GLUT_KEY_RIGHT:right(); break;
    case GLUT_KEY_UP:up(); break;
    case GLUT_KEY_DOWN:down(); break;
    case GLUT_KEY_PAGE_UP:front(); break;
    case GLUT_KEY_PAGE_DOWN:back(); break;
    glutPostRedisplay();
    

void Settings()

    glClearColor(1,1,1,0);
    glClearDepth(1.0f);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glShadeModel(GL_SMOOTH);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT , GL_NICEST);

void polygons(void)

    glColor3f(1.0, 0.0, 0.0);
    glRotatef(degree, 0.0, 1.0, 0.0);
    glScalef(xscale, yscale, zscale);
    glTranslatef(1.5, 0.0, -8.0);
    glBegin(GL_TRIANGLES);//pyramid
    // fronat face
    glColor3f(1.0f, 0.0f, 0.0f); //red
    glVertex3f(0.0f, 1.0f, 0.0f);
    glColor3f(0.0f, 1.0f, 0.0f); //green
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glColor3f(0.0f, 0.0f, 1.0f); //blue
    glVertex3f(1.0f, -1.0f, 1.0f);
    // down face
    glColor3f(1.0f, 0.0f, 0.0f); //red
    glVertex3f(0.0f, 1.0f, 0.0f);
    glColor3f(0.0f, 0.0f, 1.0f); //blue
    glVertex3f(1.0f, -1.0f, 1.0f);
    glColor3f(0.0f, 1.0f, 0.0f); //green
    glVertex3f(1.0f, -1.0f, -1.0f);
    //back
    glColor3f(1.0f, 0.0f, 0.0f); //red
    glVertex3f(0.0f, 1.0f, 0.0f);
    glColor3f(0.0f, 1.0f, 0.0f); //green
    glVertex3f(1.0f, -1.0f, -1.0f);
    glColor3f(0.0f, 0.0f, 1.0f); //blue
    glVertex3f(-1.0f, -1.0f, -1.0f);
    //left 
    glColor3f(1.0f, 0.0f, 0.0f); //reed
    glVertex3f(0.0f, 1.0f, 0.0f);
    glColor3f(0.0f, 0.0f, 1.0f); //blue
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glColor3f(0.0f, 1.0f, 0.0f); //green
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glEnd();
    glLoadIdentity();
    glTranslatef(-1.5, 0.0, -8.0); 
    glBegin(GL_QUADS); //cubic
    glColor3f(1.0f, 0.0f, 1.0f); //pink
    glVertex3f(1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, 1.0f, 1.0f);
    //down face
    glColor3f(1.0f, 0.5f, 0.0f); //orange
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);
    //front face
    glColor3f(0.0f, 0.0f, 1.0f); //blue
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);
    //back
    glColor3f(1.0f, 1.0f, 0.0f); //yellow
    glVertex3f(1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(1.0f, 1.0f, -1.0f);

    //left
    glColor3f(1.0f, 0.0f, 0.0f); //red
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    //right
    glColor3f(0.0f, 1.0f, 0.0f); //green
    glVertex3f(1.0f, 1.0f, -1.0f);
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);
    glEnd();

void DrawingFunction()//painting

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    gluLookAt(0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    polygons();
    glutSwapBuffers();

void AppearanceAdjustment(int x, int y)

    int aspect = x / y;
    glViewport(0, 0, x, y);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45,aspect,0.1,20);


int main(int argc, char** argv)

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE); 
    glutInitWindowPosition(50, 50);
    glutInitWindowSize(800, 600);
    glutCreateWindow("3d shapes");
    glutDisplayFunc(DrawingFunction);
    glutReshapeFunc(AppearanceAdjustment);
    glutSpecialFunc(keyboard);
    Settings();
    glutMainLoop();
    return 0;

【问题讨论】:

【参考方案1】:

glLoadIdentity() 必须在DrawingFunction 中调用:

void DrawingFunction()//painting

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity(); // <----
    gluLookAt(0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    polygons();
    glutSwapBuffers();

添加一个偏移量数组和一个对象编号:

int object = 0;
float xmove[] 0, 0 ;
float ymove[] 0, 0 ;
float zmove[] 0, 0 ;

添加对象选择按钮并更改所选对象的偏移量。 glutPostRedisplay()必须在switch语句之后执行:

void keyboard(int button, int x, int y)

    switch (button)
    
        case GLUT_KEY_F1: object = 0; break;
        case GLUT_KEY_F2: object = 1; break;
        case GLUT_KEY_LEFT: xmove[object] -= 0.1; break;
        case GLUT_KEY_RIGHT: xmove[object] += 0.1; break;
        case GLUT_KEY_DOWN:  ymove[object] -= 0.1; break;
        case GLUT_KEY_UP: ymove[object] += 0.1; break;
        case GLUT_KEY_PAGE_UP: zmove[object] -= 0.1; break;
        case GLUT_KEY_PAGE_DOWN: zmove[object] += 0.1; break;
    
    glutPostRedisplay();

您必须通过glTranslatef(xmove[i], ymove[i], zmove[i]) 翻译objects 对象。我推荐使用glPushMatrix/glPopMatrix:

void polygons(void)

    glPushMatrix();

    glColor3f(1.0, 0.0, 0.0);
    glRotatef(degree, 0.0, 1.0, 0.0);
    glScalef(xscale, yscale, zscale);
    glTranslatef(1.5, 0.0, -8.0);

    glTranslatef(xmove[0], ymove[0], zmove[0]); // <--- translate pyramid

    // draw pyramid
    glBegin(GL_TRIANGLES);//pyramid
    // [...]
    glEnd();

    glTranslatef(-1.5, 0.0, -8.0); 
    glTranslatef(xmove[1], ymove[1], zmove[1]); // <--- translate cube

    glBegin(GL_QUADS); //cubic
    // [...]
    glEnd();

    glPopMatrix();
 

示例代码:

int object = 0;
float xmove[] 0, 0 ;
float ymove[] 0, 0 ;
float zmove[] 0, 0 ;

float degree = 0;
float xscale = 1, yscale = 1, zscale = 1;

void keyboard(int button, int x, int y)

    switch (button)
    
        case GLUT_KEY_F1: object = 0; break;
        case GLUT_KEY_F2: object = 1; break;
        case GLUT_KEY_LEFT: xmove[object] -= 0.1; break;
        case GLUT_KEY_RIGHT: xmove[object] += 0.1; break;
        case GLUT_KEY_DOWN:  ymove[object] -= 0.1; break;
        case GLUT_KEY_UP: ymove[object] += 0.1; break;
        case GLUT_KEY_PAGE_UP: zmove[object] -= 0.1; break;
        case GLUT_KEY_PAGE_DOWN: zmove[object] += 0.1; break;
    
    glutPostRedisplay();


void Settings()

    glClearColor(1,1,1,0);
    glClearDepth(1.0f);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glShadeModel(GL_SMOOTH);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT , GL_NICEST);


void polygons(void)

    glPushMatrix();

    glColor3f(1.0, 0.0, 0.0);
    glRotatef(degree, 0.0, 1.0, 0.0);
    glScalef(xscale, yscale, zscale);
    glTranslatef(1.5, 0.0, -8.0);

    glTranslatef(xmove[0], ymove[0], zmove[0]); // <--- translate pyramid

    glBegin(GL_TRIANGLES);//pyramid
    // fronat face
    glColor3f(1.0f, 0.0f, 0.0f); //red
    glVertex3f(0.0f, 1.0f, 0.0f);
    glColor3f(0.0f, 1.0f, 0.0f); //green
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glColor3f(0.0f, 0.0f, 1.0f); //blue
    glVertex3f(1.0f, -1.0f, 1.0f);
    // down face
    glColor3f(1.0f, 0.0f, 0.0f); //red
    glVertex3f(0.0f, 1.0f, 0.0f);
    glColor3f(0.0f, 0.0f, 1.0f); //blue
    glVertex3f(1.0f, -1.0f, 1.0f);
    glColor3f(0.0f, 1.0f, 0.0f); //green
    glVertex3f(1.0f, -1.0f, -1.0f);
    //back
    glColor3f(1.0f, 0.0f, 0.0f); //red
    glVertex3f(0.0f, 1.0f, 0.0f);
    glColor3f(0.0f, 1.0f, 0.0f); //green
    glVertex3f(1.0f, -1.0f, -1.0f);
    glColor3f(0.0f, 0.0f, 1.0f); //blue
    glVertex3f(-1.0f, -1.0f, -1.0f);
    //left 
    glColor3f(1.0f, 0.0f, 0.0f); //reed
    glVertex3f(0.0f, 1.0f, 0.0f);
    glColor3f(0.0f, 0.0f, 1.0f); //blue
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glColor3f(0.0f, 1.0f, 0.0f); //green
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glEnd();

    glPopMatrix();
    glPushMatrix();


    glTranslatef(-1.5, 0.0, -8.0); 
    glTranslatef(xmove[1], ymove[1], zmove[1]); // <--- translate cube


    glBegin(GL_QUADS); //cubic
    glColor3f(1.0f, 0.0f, 1.0f); //pink
    glVertex3f(1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, 1.0f, 1.0f);
    //down face
    glColor3f(1.0f, 0.5f, 0.0f); //orange
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);
    //front face
    glColor3f(0.0f, 0.0f, 1.0f); //blue
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);
    //back
    glColor3f(1.0f, 1.0f, 0.0f); //yellow
    glVertex3f(1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(1.0f, 1.0f, -1.0f);

    //left
    glColor3f(1.0f, 0.0f, 0.0f); //red
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, 1.0f);
    //right
    glColor3f(0.0f, 1.0f, 0.0f); //green
    glVertex3f(1.0f, 1.0f, -1.0f);
    glVertex3f(1.0f, 1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, 1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);
    glEnd();

    glPopMatrix();


void DrawingFunction()//painting

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    polygons();
    glutSwapBuffers();


void AppearanceAdjustment(int x, int y)

    int aspect = x / y;
    glViewport(0, 0, x, y);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45,aspect,0.1,20);


int main(int argc, char** argv)

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE); 
    glutInitWindowPosition(50, 50);
    glutInitWindowSize(800, 600);
    glutCreateWindow("3d shapes");
    glutDisplayFunc(DrawingFunction);
    glutReshapeFunc(AppearanceAdjustment);
    glutSpecialFunc(keyboard);
    Settings();
    glutMainLoop();
    return 0;

【讨论】:

对不起,非常感谢先生【参考方案2】:

您需要使用按键来选择类似于触发向上、向下、向左、向右...等功能的形状之一。假设按 a 为第一个形状,然后设置全局 int ishape= 1 或 ishape=2 如果 b 被按下。然后 draw 函数将检查 ishape 的值以查看它应该移动哪个形状。但实际上,每个形状都需要一个移动向量,否则它们的位移会混淆。然后你需要对需要使用移动向量进行位移的形状应用 gltranslate。

【讨论】:

以上是关于使用 C++ 在 OpenGL 中使用键盘移动 3d 形状的主要内容,如果未能解决你的问题,请参考以下文章

鼠标移动opengl

如何在opengl和pygames中使用键盘键移动多维数据集?

OpenGL/Gtkmm 游戏 - 键盘移动

使用 C++ 在 OpenGL 中移动自动旋转的 3d 多边形

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

用C++或者OpenGL或者Ogre实现鼠标移动轨迹