使用键盘旋转 -- glut / OpenGL

Posted

技术标签:

【中文标题】使用键盘旋转 -- glut / OpenGL【英文标题】:Rotation using keyboard -- glut / OpenGL 【发布时间】:2014-09-25 23:06:17 【问题描述】:

我试图让我的对象根据想要的轴旋转(通过按 x、y、z),然后用同一个键开始/停止旋转。这是我的代码:

#include <glut.h>
#include <stdio.h>

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() 的函数操作,但不确定如何将旋转合并到其中。即使我可以澄清一下我的键盘调用如何/为什么不正确也会很棒!

【问题讨论】:

我建议您查看 this 和 this 教程。实际上,该页面上的所有教程看起来都非常有用。 或者这些教程:ogldev.atspace.co.uk 【参考方案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 上有一篇文章,互联网上还有很多文章。

此外,动画方案被放入空闲功能中,您无法直接控制动画的速度。它完全取决于应用程序的帧速率。还有大量关于如何实现主循环以便精确处理您的逻辑/时间的文章。

【讨论】:

很好的答案,希望这不会导致您的代码只是复制粘贴,这里有很多有用的信息。

以上是关于使用键盘旋转 -- glut / OpenGL的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL和GLUT键盘功能

Mac 上的 OpenGL/GLUT 应用程序无法获得焦点 [关闭]

OpenGL step to step

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

opengl中如何实现图象的缩放

点不会通过 OpenGL 中的键盘输入移动