使用键盘旋转-glut / OpenGL

 moquan 发布于 2022-12-19 16:48

我试图使我的对象根据所需的轴旋转(通过按x,y,z),然后使用相同的键启动/停止旋转。这是我的代码:

#include 
#include 

static GLfloat spin = 0.0;

void init(void){
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
}

void action(void)
{

}


void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();


glBegin(GL_LINE_LOOP);
glColor3f(1.00, 0.00, 0.00);
glVertex3f(0.00, 0.00, 0.00);
glVertex3f(0.00, 0.00, -1.00);
glVertex3f(0.50, 0.00, -1.00);
glVertex3f(0.75, 0.0, -0.75);
glVertex3f(0.25, 0.25, -1.0);
glVertex3f(0.50, 0.50, -0.50);

glColor3f(0.00, 1.00, 0.00);
glVertex3f(0.00, 0.00, 0.00);
glVertex3f(0.00, 0.00, 1.00);
glVertex3f(0.50, 0.00, 1.00);
glVertex3f(0.75, 0.0, 0.75);
glVertex3f(0.25, 0.25, 1.0);
glVertex3f(0.50, 0.50, 0.50);

glEnd();

glPopMatrix();
glutSwapBuffers();
glFlush();
}

//spin function
void spinDisplay(void){
spin = spin + 0.02;
if (spin > 360.0)
    spin = spin - 360.0;
glutPostRedisplay();
}


void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 0.5, 15.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1.5, 1.5, 1.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

}


//keyboard event handler
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 27: // Escape key
    exit(0);
    break;
case 'x':
    glRotatef(spin, 1.0, 0.0, 0.0);
    break;
case 'y':
    glRotatef(spin, 0.0, 1.0, 0.0);
    break;
case 'z':
    glRotatef(spin, 0.0, 0.0, 1.0);
    break;
case 'r':
    glutIdleFunc(action);
    break;
}
glutPostRedisplay();
}


void mouse(int button, int state, int x, int y){
switch (button){
case GLUT_LEFT_BUTTON:
    if (state == GLUT_DOWN)
        glutIdleFunc(spinDisplay);
    break;
case GLUT_RIGHT_BUTTON:
    if (state == GLUT_DOWN)
        glutIdleFunc(NULL);
    break;
default:
    break;
}
}

int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutKeyboardFunc(keyboard);
glutIdleFunc(action);
glutMainLoop();
return 0;
}

我在键盘功能中具有所需的每个键,但是我想知道glRotatef -即它是否属于该键。我创建了我打算用于调用glutIdleFunc()的函数操作,但是不确定如何将Rotate并入其中。即使我能就为什么/为什么我的键盘通话不正确做出一些澄清,也很棒!

1 个回答
  • 保持状态

    您希望将当前旋转状态写入某个变量。这样,当您要绘制场景时就可以知道它。

    struct rot_state {
      bool rotating;    // animation/movement happening
      float x,y,z;      // current rotation values
      int current_axis; // 0 for x, 1 for y, 2 for z
    }
    

    状态保持当前旋转,程序可以对此进行操作。

    动画

    glutIdleFunc通过增加(设置动画)正确的轴来完成此示例中的所有工作app_state.x += increment; Glut调用每次都无关紧要并处理循环时。因此,它用作动画逻辑的门,然后在帧上强制重画。

    尽管可以做得更好,但我不想掩盖原始代码。

    显示

    在显示框架时,您可以仅使用已有的信息并应用旋转。

    glRotatef(app_state.x, 1, 0, 0);
    glRotatef(app_state.y, 0, 1, 0);
    glRotatef(app_state.z, 0, 0, 1);
    

    #include <glut.h>
    #include <stdio.h>
    
    struct rot_state {
        bool rotating;    // animation/movement happening
        float x,y,z;      // current rotation values
        int current_axis; // 0 for x, 1 for y, 2 for z
    } app_state;
    
    void init(void){
        // Setting up initial app state
        app_state.rotating = false;
        app_state.x = app_state.y = app_state.z = 0.0f;
        app_state.current_axis = 0;
    
        glClearColor(0.0, 0.0, 0.0, 0.0);
        glShadeModel(GL_SMOOTH);
    }
    
    void action(void)
    {
        // Animate the rotation
        float increment = 1.0f;
        switch (app_state.current_axis)
        {
        case 0:
            app_state.x += increment;
            break;
        case 1:
            app_state.y += increment;
            break;
        case 2:
            app_state.z += increment;
            break;
        default:
            break;
        }
    
        glutPostRedisplay();
    }
    
    
    void display(void)
    {
        glClear(GL_COLOR_BUFFER_BIT);
        glPushMatrix();
    
        // Apply the rotations
        glRotatef(app_state.x, 1, 0, 0);
        glRotatef(app_state.y, 0, 1, 0);
        glRotatef(app_state.z, 0, 0, 1);
    
        glBegin(GL_LINE_LOOP);
        glColor3f(1.00, 0.00, 0.00);
        glVertex3f(0.00, 0.00, 0.00);
        glVertex3f(0.00, 0.00, -1.00);
        glVertex3f(0.50, 0.00, -1.00);
        glVertex3f(0.75, 0.0, -0.75);
        glVertex3f(0.25, 0.25, -1.0);
        glVertex3f(0.50, 0.50, -0.50);
    
        glColor3f(0.00, 1.00, 0.00);
        glVertex3f(0.00, 0.00, 0.00);
        glVertex3f(0.00, 0.00, 1.00);
        glVertex3f(0.50, 0.00, 1.00);
        glVertex3f(0.75, 0.0, 0.75);
        glVertex3f(0.25, 0.25, 1.0);
        glVertex3f(0.50, 0.50, 0.50);
    
        glEnd();
    
        glPopMatrix();
        glutSwapBuffers();
        glFlush();
    }
    
    void reshape(int w, int h)
    {
        glViewport(0, 0, (GLsizei)w, (GLsizei)h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glFrustum(-1.0, 1.0, -1.0, 1.0, 0.5, 15.0);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        gluLookAt(1.5, 1.5, 1.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    
    }
    
    //keyboard event handler
    void keyboard(unsigned char key, int x, int y)
    {
        switch (key)
        {
        case 27: // Escape key
            exit(0);
            break;
        case 'x':
            app_state.current_axis = 0;
            break;
        case 'y':
            app_state.current_axis = 1;
            break;
        case 'z':
            app_state.current_axis = 2;
            break;
        case 'r':
            app_state.rotating ^= 1;
            glutIdleFunc(app_state.rotating ? action : NULL);
            break;
        }
        glutPostRedisplay();
    }
    
    
    int main(int argc, char** argv)
    {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
        glutInitWindowSize(500, 500);
        glutInitWindowPosition(100, 100);
        glutCreateWindow(argv[0]);
        init();
        glutReshapeFunc(reshape);
        glutDisplayFunc(display);
        glutKeyboardFunc(keyboard);
        glutIdleFunc(action);
        glutMainLoop();
        return 0;
    }
    

    这应该使您入门。

    注意事项

    请记住,这会强制在对象本地的特定轴上旋转。如果要对旋转进行更多控制,则需要查看一些四元数->矩阵旋转。在Wiki上有一篇文章,在互联网上还有更多文章。

    动画方案也被置于空闲函数中,您无法直接控制动画的速度。它完全取决于应用程序的帧速率。关于如何实现主循环的文章也很多,因此您的逻辑/时间可以得到精确处理。

    2022-12-19 16:49 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有