vc++ 6.0下Glut的配置 及 Glut 框架介绍

2014-04-08  16:18:30

一、配置Glut

学习来源: http://blog.sina.com.cn/s/blog_5f0cf7bd0100c9oa.html

亲测可行。

Glut的一般框架:

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(400, 400);
    glutCreateWindow("第一个OpenGL程序");
    glutDisplayFunc(&myDisplay);
    glutMainLoop();
    return 0;
}

1、glutInit,对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次。其格式比较死板,一般照抄这句glutInit(&argc, argv)就可以了。
2、glutInitDisplayMode,设置显示方式,其中GLUT_RGB表示使用RGB颜色,与之对应的还有GLUT_INDEX(表示使用索引颜色)。GLUT_SINGLE表示使用单缓冲,与之对应的还有GLUT_DOUBLE(使用双缓冲)。更多信息,请自己Google。当然以后的教程也会有一些讲解。
3、glutInitWindowPosition,这个简单,设置窗口在屏幕中的位置。
4、glutInitWindowSize,这个也简单,设置窗口的大小。
5、glutCreateWindow,根据前面设置的信息创建窗口。参数将被作为窗口的标题。注意:窗口被创建后,并不立即显示到屏幕上。需要调用glutMainLoop才能看到窗口。
6、glutDisplayFunc,设置一个函数,当需要进行画图时,这个函数就会被调用。(这个说法不够准确,但准确的说法可能初学者不太好理解,暂时这样说吧)。
7、glutMainLoop,进行一个消息循环。(这个可能初学者也不太明白,现在只需要知道这个函数可以显示窗口,并且等待窗口关闭后才会返回,这就足够了。)

 

二、关于Glut

学习来源:http://blog.renren.com/share/230411342/5994614012

 glut这是一套opengl的辅助库, 他使我们能十分简单的设置各种消息处理函数,而且与平台无关,也就是说如果使用glut在windows下编译通过程序无需更改便可在linux,和 mac os下的编译运行,这一点是十分有用的,要知道win32api繁琐的代码走出了windows的窗户可什么也干不了。给glut作了这么多广 告,让我们看看他是怎么用的.

GLUT的基本功能

包括窗口初始化功能、事件处理、窗口和菜单管理、回调函数注册和几何建模功能。

窗口初始化功能,它有4个函数。主要用于处理初始化并以及命令行参数,初始化显示模式,指定窗口左上角在屏幕上的位置和窗口大小,以像素为单位。

事件处理只有一个函数,它用于显示创建的窗口、处理输入的事件、触发回调函数、进入循环直到程序退出。

窗口管理包含18个函数,用于建立、销毁窗口及可能的子窗口,管理和设置窗口的属性。

在 GLUT中有20个回调函数,用于响应用户事件。最重要的回调函数是glutDisplayFunc,当GLUT认为需要重新显示窗口内容时,都将执行这 一函数注册的回调函数。另外一些重要的回调函数注册函数有:函数glutRe-shapeFunc用于注册窗口大小改变这一事件发生时GLUT将调用的函 数。glutKeyboardFunc和glutMouseFunc用于注册键盘和鼠标事件发生时的回调函数。函数glutMotionFunc注册鼠标 移动事件的回调函数。这3个函数用于人机交互处理。在没有其他事件处理时,GLUT将调用函数glutldleFunc注册的函数,而函数 glutTimerFunc则注册处理定时器事件的函数。

OpenGL绘图函数只能生成点、直线、多边形等简单的几何图元,GLUT提供了18个创建三维物体的函数。利用它们可以创建9种三维物体,如圆锥体、立方体、球体等,每一物体有线框和实体2种方式。

我们看到的以glut开头的函数都是 glut库的一部分,如处理参数的,和设置窗口的,我们在这里主要讨论glut支持的各种消息处理

窗口更新的处理函数

    ① 我们知道各种窗口的操作都会引发窗口更新消息,在glut中我们通过

void glutDisplayFunc(void (*func)(void))

                         来设置窗口刷新的消息处理函数,其唯一的参数指定了屏幕刷新时会调用的函数

 

           ② 如果要处理窗口变化的消息我们可以通过设置下面函数来实现

void glutReshapeFunc(void (*func)(int w, int h))

                         这里的func为回调函数,w,h分别为改变后窗口的宽和高

 

          二:对于键盘和鼠标的输入我们可以通过下面两个函数来设置

void glutKeyboardFunc(void (*func)(unsigned char key, int x, int y))

void glutMouseFunc(void (*func)(int button, int state, int x, int y))

                                                            key为键盘按键的ASCII吗                                

                                            x y都表示鼠标的位置,

                                      而button则为GLUT_LEFT_BUTTON或GLUT_RIGHT_BUTTON

                            分别表示左右按键。

                            state为按键的状态,若为按下则为GLUT_DOWN

      当鼠标移动式我们还可以通过下面的函数来设置鼠标移动消息的处理函数

void glutMotionFunc(void (*func)(int x, int y))

                                                                                    X,Y仍然为鼠标的位置

         特殊函数用于完成循环画图(或者说是动画)

                            这里还有一个函数比较特殊

                                               void glutIdleFunc(void (*func)(void)).

                              这里设置的是系统空闲时将会调用的函数

下面我们将看到一个完整的例子,通过输入来控制三维物体的旋转

#include <math.h> 

#include <gl/glut.h> 

#include <gl/gl.h>

#define pi 3.1415926

bool mouseisdown=false;

bool loopr=false;

int mx,my;

int ry=30;

int rx=30;

void timer(int p)

{

     ry-=5;

        glutPostRedisplay();                 //marks the current window as needing to be redisplayed.

     if (loopr)

         glutTimerFunc(200,timer,0);

}

void mouse(int button, int state, int x, int y) 

    if(button == GLUT_LEFT_BUTTON) 

     {

        if(state == GLUT_DOWN) 

         {    mouseisdown=true; loopr=false;}

         else

              mouseisdown=false;

     }

     if (button== GLUT_RIGHT_BUTTON)

         if(state == GLUT_DOWN) 

         {loopr=true; glutTimerFunc(200,timer,0);}

 

void motion(int x, int y) 

    if(mouseisdown==true) 

    { 

        ry+=x-mx;

         rx+=y-my;

         mx=x;

         my=y;

         glutPostRedisplay(); 

    } 

void special(int key, int x, int y)

{

    switch(key)

    {

    case GLUT_KEY_LEFT:

        ry-=5;

        glutPostRedisplay();

        break;

    case GLUT_KEY_RIGHT:

       ry+=5;

        glutPostRedisplay();

        break;

    case GLUT_KEY_UP:

        rx+=5;

        glutPostRedisplay();

        break;

    case GLUT_KEY_DOWN:

        rx-=5;

        glutPostRedisplay();

        break;

    }

}

void display() 

 

         float red[3]={1,0,0}; 

         float blue[3]={0,1,0}; 

         float green[3]={0,0,1}; 

         float yellow[3]={1,1,0};    

 

 

         glClearColor(1,1,1,1); 

         glClear(GL_COLOR_BUFFER_BIT); 

         glLoadIdentity(); 

         glRotatef(ry,0,1,0);       

         glRotatef(rx,1,0,0);

         glColor3fv(green);

         glutWireTeapot(0.5);

        glFlush(); 

int main(int argc, char** argv) 

    glutInit(&argc, argv); 

    glutInitDisplayMode (GLUT_SINGLE| GLUT_RGBA); 

    glutInitWindowSize (400, 400);

    glutInitWindowPosition(100,100);      

    glutCreateWindow ("A TEAPOT");     

 

    glutDisplayFunc (display);     

     glutMouseFunc(mouse);        

     glutMotionFunc(motion); 

     glutSpecialFunc(special);

    glutMainLoop();       

    return 0; 

运行这个程序我们会发现一个茶壶,我们可以通过鼠标和键盘的方向键来控制它的旋转,而按下鼠标右键则可以让这个茶壶自动旋转,这里还有几个函数我们要注意一下

void glutWireTeapot(GLdouble size)在当前的OCS坐标中心画一个以size为大小的茶壶

void glutSpecialFunc(void (*func)( int key, int x, int y))

这个函数与glutKeyboardFunc的区别在于前者是用来响应键盘上的特殊按键,如方向键和控制键等。而后者则是用来响应键盘上的字符按键

void glutTimerFunc(int delay, (void (*func)( int parameter),int parameter)

这 个函数相当于win32 api中的timer定时器,也是在delay毫秒后放出一个定时器消息,而这里的func则为这个消息的处理函数,patameter为附加参数。这里 有一点要注意这个函数是一次性的,如果要重复使用可以在func中继续调用glutTimerFunc,而且这个功能是可以叠加的,在opengl内部将 他们看成许多个不同的定时器,这也就是为什么我们在上面的例子中连续按下鼠标右键会加快旋转的速度

键盘和鼠标是图形绘制过程中最主要的两种输入工具。如何通过键盘的按键或鼠标的点击来完成用户想达到的图形显示事件呢?在GLUT库中专门有两个函数来用于接收和响应这两类动作,分别为:
glutKeyboardFunc(void(*func)(unsigned char key, int x, int y))
glutMouseFunc(void(*func)(int button, int state, int x, int y))
这两个函数存在于消息循环中,不断地检查当前是否有键盘敲击或鼠标点击的事件发生,如果有这样的事件发生,则触发func函数,执行一系列的动作。

glutKeyboardFunc(void(*func)(unsigned char key, int x, int y))
此 函数用于接收并响应键盘动作,它需要一个函数的指针作为参数,这个函数func称为回调函数(callback)。通俗点说就是,回调函数并不会主动执 行,而是通过另一个函数来通知它是否执行(比如glutKeyboardFunc函数用来通知func()函数是否执行)。键盘回调函数的定义格式如下:
void func(unsigned char key, int x, int y)
为了让程序更易于理解,常将其函数名命名为myKeyboard:
   void myKeyboard(unsigned char key, int x, int y)   
glutKeyboardFunc(myKeyboard)函数检测到键盘事件后,它先将用户按键盘那一时刻的鼠标位置(xyx表示鼠标相对于窗口的左边框的偏移量;y表示鼠标相对于窗口上边框的偏移量,都以像素为单位,即相当于原点在窗口左上角)和键盘按键时的键值(key,即键盘字母对应的ASCII码值)作为实际参数传送给myKeyboard,然后通知myKeyboard函数立即执行。

glutMouseFunc(void(*func)(int button, int state, int x, int y))
此函数用于接收并响应鼠标动作,同样需要一个回调函数指针作为参数。鼠标回调函数的定义格式如下:
void func(int button, int state, int x, int y)
为了让程序更易于理解,常将其函数名命名为myMouse:
   void myMouse(int button, int state, int x, int y)   
同样,在消息循环过程中,当glutMouseFunc(myMouse)函数检测到有鼠标事件发生后,它先将事件发生那一时刻的鼠标按键(button,说明是左键还是右键),鼠标动作(state,说明是鼠标按下去那一刻,还是按下去后弹上来那一刻),以及按键时鼠标的位置(xyx表示鼠标相对于窗口的左边框的偏移量;y表示鼠标相对于窗口上边框的偏移量,都以像素为单位,即相当于原点在窗口左上角)作为实际参数传递给myMouse,然后通知myMouse执行。
其中button对应的值有:
左键:GLUT_LFET_BUTTON  [0]
中建:GLUT_MIDDLE_BUTTON  [1]
右键:GLUT_RIGHT_BUTTON  [2]
state对应的值有:
按下去:GLUT_DOWN  [0]
弹上来:GLUT_UP  [1]
注:中括号中表示常量所对应的实际数值。

下面讨论回调函数参数中x和y的具体意义,即myKeyboard和myMouse的参数中x和y的值如何映对到窗口的实际坐标位置上。
看下图,假设鼠标或键盘动作产生时,鼠标位置在图中的红色点的位置,它相对于上边框的距离为200像素,相对于左边框的像素为300像素,这样我用x,y 的值表示坐标(300,200)就是现在红色点这个位置吗?显然不是,而我把y替换为z,即窗口高度减去y的值得到(300,400)是否可以映射到实际 坐标位置呢?显然也不是,因为当前的窗口坐标范围是:左下角坐标为(-300,-300);右上角坐标为(300,300),所以(300,200)应处 在窗口的右上方,而(300,400)则跑出了坐标表示的范围,显然这两个坐标都不能与红色点的位置重合。
再考虑,(300,400)是红色点相对于窗口左下角的位置,即可以看做它所对应的原点(0,0)在左下角,而实际坐标中,左下角坐标为 (-300,-300)实际的原点在窗口的中心位置,所以,这个时候,你只需对(x,z)向左和向下进行平移300个单位即可。这样(x-300,z- 300)就得到了(0,100)正好与红色点重合。
我们从上面的分析过程可以得到将x,y转换为实际坐标的值的方法:
   横坐标值:x + 左下角横坐标值   
   纵坐标值:窗口高度 - y + 左下角纵坐标值   

 

 

 

OpenGl学习资料:

http://www.videotutorialsrock.com/

http://bbs.pfan.cn/post-275228.html

posted @ 2014-04-07 22:36  March On  阅读(584)  评论(0编辑  收藏  举报
top last
Welcome user from
(since 2020.6.1)