GLUT Tutorials 8: GLUT菜单

Posted flyinggod

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GLUT Tutorials 8: GLUT菜单相关的知识,希望对你有一定的参考价值。

博客转自:https://www.cnblogs.com/yangxi/archive/2011/09/16/2178505.html

弹出式菜单(像点鼠标右键出来的菜单那样的)也是GLUT的一部分,虽然它不能实现我们经常看到的windows系统弹出式菜单的所有的功能,但是它也有很大的作用。给一个程序增加菜单提供了一个比键盘更简单的方法来和程序交互,选择不同选项,而不用去记那些按键。

我们首先要做的是创建菜单,创建菜单函数glutCreateMenu的原型如下:

int glutCreateMenu(void (*func)(int value));
参数:
func:为新建的菜单处理菜单事件的函数名。
这个函数的返回值是菜单的标识符(menu identifier)
我们的程序中,我们可以想设置多少菜单就设置多少菜单。对每个菜单我们要指定一个回调函数,而且我们可以指定相同的函数。下面为菜单增加一些条目(出来个空菜单也没什么用)。
使用的函数是glutAddMenuEntry
void glutAddMenuEntry(char *name,int value);
参数:
 name:菜单名称的字符串。
 value:当你选择菜单里的一项后,这个值就返回给上面的glutCreateMenu里调用的函数。
这个函数根据函数名来看,就是给菜单里添加条目的,可以一直添加(这里有个顺序,自己实验下就明白了的)
好了现在有了一个弹出式菜单。但还有最后一件事要做,就是把菜单和一个鼠标键连接起来(attach)。因为我们必须指定菜单怎么出现,使用GLUT你可以在按下一个鼠标按键后让菜单显示,函数是glutAttachMenu:
void glutAttachMenu(int button);
参数:、
button: 一个整数,指定菜单和哪个鼠标键关联起来,botton 可以去下面的值;
 GLUT_LEFT_BUTTON
 GLUT_MIDDLE_BUTTON
 GLUT_RIGHT_BUTTON

下面就是一个应用了上面所有函数的例子。

#define RED 1
#define GREEN 2
#define BLUE 3
#define WHITE 4

void createGLUTMenus() {
 
         int menu;
 
         // 创建菜单并告诉GLUT,processMenuEvents处理菜单事件。
         menu = glutCreateMenu(processMenuEvents);
         
         //给菜单增加条目
         glutAddMenuEntry("Red",RED);
         glutAddMenuEntry("Blue",BLUE);
         glutAddMenuEntry("Green",GREEN);
         glutAddMenuEntry("White",WHITE);
         
         // 把菜单和鼠标右键关联起来。
         glutAttachMenu(GLUT_RIGHT_BUTTON);
}

注意RED,BLUE,GREEN,和WHITE必须定义为整数,再就是你必须为每个选单(菜单里的条目)定义不同的value,下面我们写处理菜单事件的函数。我们将使用我们的菜单来设置三角形的颜色。函数如下:

void processMenuEvents(int option) {
        //option,就是传递过来的value的值。
         switch (option) {
                 case RED : 
                          red = 1.0; 
                          green = 0.0; 
                          blue = 0.0; break;
                 case GREEN : 
                          red = 0.0; 
                          green = 1.0; 
                          blue = 0.0; break;
                 case BLUE : 
                          red = 0.0; 
                          green = 0.0; 
                          blue = 1.0; break;
                 case WHITE : 
                          red = 1.0; 
                          green = 1.0; 
                          blue = 1.0; break;
         }
}

剩下来的就是把我们的createGLUTMenus函数放到main函数里。下面的代码就是当前的main函数。

void main(int argc, char **argv) {
         glutInit(&argc, argv);
         glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
         glutInitWindowPosition(100,100);
         glutInitWindowSize(320,320);
         glutCreateWindow("SnowMen");
         glutDisplayFunc(renderScene);
         glutIdleFunc(renderScene);
         glutReshapeFunc(changeSize);
 
         //调用我们的函数来创建菜单
         createGLUTMenus();
 
         glutMainLoop();
}

显示效果如下

技术图片

完整代码如下

#include <gl/glut.h>

#define RED 1
#define GREEN 2
#define BLUE 3
#define WHITE 4

//所有的变量被初始化为1,表明三角形最开始是白色的。
float red = 1.0, blue = 1.0, green = 1.0;
static float angle = 0.0, angleX = 0.0, ratio;
// initially define the increase of the angle by 0.05;
float deltaAngle = 0.05;

void renderScene(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glPushMatrix();
    glRotatef(angle, 0.0, 1.0, 0.0);
    glRotatef(angleX, 1.0, 0.0, 0.0);
    glColor3f(red, green, blue);

    glBegin(GL_TRIANGLES);
    glVertex3f(-0.5, -0.5, 0.0);
    glVertex3f(0.5, 0.0, 0.0);
    glVertex3f(0.0, 0.5, 0.0);
    glEnd();
    glPopMatrix();
    // this is the new line
    // previously it was: angle++;
    angle += deltaAngle;
    glutSwapBuffers();
}

void reShape(int w, int h)
{
    // 防止被0除.
    if (h == 0)
        h = 1;

    ratio = 1.0f * w / h;
    //Reset the coordinate system before modifying
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    //设置视口为整个窗口大小
    glViewport(0, 0, w, h);

    //设置可视空间
    gluPerspective(45, ratio, 1, 1000);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, -1.0, 0.0f, 1.0f, 0.0f);
}

void processMenuEvents(int option) 
{
    //option,就是传递过来的value的值。
    switch (option) {
    case RED:
        red = 1.0;
        green = 0.0;
        blue = 0.0; break;
    case GREEN:
        red = 0.0;
        green = 1.0;
        blue = 0.0; break;
    case BLUE:
        red = 0.0;
        green = 0.0;
        blue = 1.0; break;
    case WHITE:
        red = 1.0;
        green = 1.0;
        blue = 1.0; break;
    }
}

void createGLUTMenus() 
{
    int menu;

    // 创建菜单并告诉GLUT,processMenuEvents处理菜单事件。
    menu = glutCreateMenu(processMenuEvents);

    //给菜单增加条目
    glutAddMenuEntry("Red", RED);
    glutAddMenuEntry("Blue", BLUE);
    glutAddMenuEntry("Green", GREEN);
    glutAddMenuEntry("White", WHITE);

    // 把菜单和鼠标右键关联起来。
    glutAttachMenu(GLUT_RIGHT_BUTTON);
}

void main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(320, 320);
    glutCreateWindow("GLUT Tutorial Menu");
    glutDisplayFunc(renderScene);
    glutIdleFunc(renderScene);
    glutReshapeFunc(reShape);

    //调用我们的函数来创建菜单
    createGLUTMenus();

    glutMainLoop();
}

下面我们还来看两个函数,第一个允许我们断开鼠标按键和一个菜单的关联。前面我们用glutAttachMenu来在鼠标和菜单间建立关联,但我们有时候需要断开这种关联。完成这个工作的函数是glutDetachMenu。函数原型如下:

void glutDetachMenu(int button);
参数:
button:要断开的鼠标按键。

Button的取值和glutAttachMenu一样。因此,要是我们想断开关联我们可以这样:

 glutDetachMenu(GLUT_RIGHT_BUTTON);

最后,如果你想恢复被菜单使用了的资源,我们可以销毁(destroy)它,相应的函数是glutDestroyMenu,它的原型如下:

void glutDestroyMenu(int menuIdentifier);
参数:
menuIdentifier:要销毁的菜单的标识符,它必须和函数glutCreateMenu返回的值相同。

好了,到这里你已经知道了基本的在GLUT中建立菜单,下章我们将探索更多的弹出式菜单功能。

以上是关于GLUT Tutorials 8: GLUT菜单的主要内容,如果未能解决你的问题,请参考以下文章

GLUT Tutorials 10: 修改菜单

GLUT Tutorials 1: GLUT简介,体系

GLUT Tutorials 17:子窗口

GLUT Tutorials 17:子窗口的reshape

GLUT Tutorials 18:多窗口的rendering

GLUT Tutorials 12:位图字体