代码改变世界

GLUI—很好的辅助OPENGL的库

2010-12-01 16:14  bingcaihuang  阅读(2365)  评论(19)    收藏  举报

GLUI   User Interface Library


What is GLUI?

GLUI is a GLUT-based C++ user interface library which provides controls such as buttons, checkboxes, radio buttons, and spinners to OpenGL applications. It is window-system independent, relying on GLUT to handle all system-dependent issues, such as window and mouse management.

Features of the GLUI User Interface Library include:


Complete integration with GLUT toolkit 
Simple creation of a new user interface window with a single line of code 
Support for multiple user interface windows 
Standard user interface controls such as: 
Buttons 
Checkboxes for boolean variables 
Radio Buttons for mutually-exclusive options 
Editable text boxes for inputting text, integers, and floating-point values 
Spinners for interactively manipulating integer and floating-point values 
Static text fields 
Panels for grouping sets of controls 
Separator lines to help visually organize groups of controls 
Controls can generate callbacks when their values change 
Variables can be linked to controls and automatically updated when the value of the control changes ("live variables") 
Controls can be automatically synchronized to reflect changes in live variables 
Controls can trigger GLUT redisplay events when their values change 
Layout and sizing of controls is automatic 
Controls can be grouped into columns 
User can cycle through controls using Tab key 

 

GLUI简介(1)--窗体初始化 /////////////////////////////////////////////////////////////////////////////////////////////////
GLUI包含三个主要的类:
          GLUI_Master_Object
          GLUI
          GLUI_Control
其中有且只有一个全局的GLUI_Master_Object对象GLUI_Master.
    所有的GLUI窗口的创建都必须通过这个对象.这可以让GLUI通过一个全局对象来追踪所有的窗口,方便窗口的管理.


    这里简单介绍一下如何使用GLUI创建和控制窗口.这里介绍的函数都属于GLUI_Master_Object和GLUI类.必须注意,任何GLUI_Master_Object类的成员函数都必须通过全局对象GLUI_Master来调用,而任何GLUI类的成员函数都必须通过GLUI指针来调用,并在使用GLUI指针之前,GLUI指针必须获取GLUI_Master.create_glui()的返回值.
如:
         float version = GLUI_Master.get_version();
         GLUI *glui_window = GLUI_Master.create_glui("GLUI");
         glui_window->add_StaticText("Hello World!");


初始化:首先介绍使用GLUI创建和设置窗口的一下函数.
get_version:
返回当前GLUI的版本.
用法:
float GLUI_Master_Object::get_version(void)
返回值:
GLUI版本号

create_glui:
创建一个新的窗口.
用法:
GLUI *GLUI_Master_Object::create_glui(char *name, int flags = 0, int x = -1, int y = -1)
参数:
name:GLUI窗口的名字.
flags:初始化标记,如果没有给出此参数则默认值为0,被定义为在当前版本中.
x,y:初始化窗口的坐标.此参数可以不给出,因为GLUI可以自动调整窗口大小以适应所有的控件.
返回值:
新的GLUI窗口的指针

create_glui_subwindow:
在已经存在的GLUT窗口中创建一个新的子窗口
用法:
GLUI *GLUI_Master_Object::create_glui_subwindow(int window, int position)
参数:
window:新建GLUI窗口的父窗口(一个已经存在的GLUT窗口)的ID号.
position:子窗口相对于父窗口的位置,可以为以下的值:
           GLUI_SUBWINDOW_RIGHT
           GLUI_SUBWINDOW_LEFT
           GLUI_SUBWINDOW_TOP
           GLUI_SUBWINDOW_BOTTOM
           (注:可以在同一个位置创建任意个数的子窗口,多个相同位置的子窗口会简单的相互叠加,如:两个子窗口都使用了GLUI_SUBWINDOW_TOP参数,这两个子窗口都会定位在父窗口之上,同时,第一个子窗口也会覆盖在第二个子窗口之上.)
返回值:
新建的子窗口的指针.

set_glutIdleFunc:
为GLUI注册一个标准的GLUT空闲回调函数.当GLUI处于空闲时,就会调用该注册的函数.GLUI会截获空闲事件用于自身过程处理,然后才把该事件送给GLUT应用程序.需要注意的是,在注册的空闲回调函数中,当前窗口并没有被定义,所以,如果要在空闲回调函数中向GLUT窗口获取或发送redisplay事件,则必须明确的在回调函数中指定当前窗口.
        如:
                 int main_window;
                 void myGlutIdle(void)//被注册的空闲回调函数
                 {
                    if(glutGetWindow() != main_window)
                    {
                       glutSetWindow(main_window);
                    }
                    glutPostRedisplay();
                 }
用法:
void GLUI_Master_Object::set_glutIdleFunc(void (*f)(void))
参数:
f(void):被注册的空闲回调函数.

set_glutReshapeFunc
set_glutKeyboardFunc
set_glutMouseFunc
set_glutSpecialFunc
用法:
void GLUT_Master_Object::set_glutReshapeFunc(void (*f)(int width, int height));
void GLUT_Master_Object::set_glutKeyboardFunc(void (*f)(unsigned char key, int x, int y));
void GLUT_Master_Object::set_glutMouseFunc(void (*f)(int button, int state, int x,int y));
void GLUI_Master_Object::set_glutSpecialFunc(void (*f)(int key, int x, int y));
参数:
详见glut函数详解(9)--回调API
(这里的回调函数与GLUT中对应的回调函数用法相似)

set_main_gfx_window:
将一个GLUT窗口与一个GLUI窗口捆绑,当这个GLUI窗口中的一个控件的值发生改变,则该GLUT窗口将会被重绘.
用法:
void GLUI::set_main_gfx_window(int window_id);
参数:
window_id:被绑定的GLUT窗口ID,此ID号可在GLUT窗口被创建时获得(即glutCreateWindow()的返回值),或通过glutGetWindow()的返回值获得.


2)--窗体视口管理 ////////////////////////////////////////////////////////////////////////////////////////////////
视口管理:这里介绍使用GLUI结合OpenGL时,如何管理视口.
get_viewport_area:
确定当前窗口可绘区域的位置和尺寸.这个函数一般在使用到GLUI子窗口时使用,因为子窗口必然会占据父窗口的一小块区域,而绘制在父窗口上的图形并不希望被子窗口覆盖,所以可以通过此函数调整视口的大小.此函数应该在GLUT的reshape callback function中调用.
用法:
void GLUI_Master_Object::get_viewport_area(int *x, int *y, int *w, int *h);
参数:
x,y,w,h:该函数被调用后,就可获得当前窗口可绘区域的左上角坐标及其宽度和高度,然后可以根据这些数据通过调用glViewport()设置视口区域.
auto_set_viewport:
自动为当前窗口设置尺寸合适的视口
用法:
void GLUI_Master_Object::auto_set_viewport(void);
例子:

int x, y, w, h;
GLUI_Master.get_viewport_area(&x, &y, &w, &h);
glViewport(x, y, w, h);
以上三句的功能与下面一句等价.
GLUI_Master.auto_set_viewport();


GLUI简介(3)--窗体管理 ///////////////////////////////////////////////////////////////////////////////////////////////////
窗口管理:当窗体创建之后可以通过下列函数对窗体进行管理
/********************************************************************/

get_glut_window_id:
返回一个GLUI窗口的窗口ID
用法:
int GLUI::get_glut_window_id(void);
返回值:
GLUI窗口的ID号


enable,disable:
使GLUI窗口可用或不可用,当一个GLUI窗口不可用时,其上的所有控件都不可用.
用法:
void GLUI::enable(void);
void GLUI::disable(void);

hide:
使GLUI窗口或子窗口隐藏.一个被隐藏的窗口或子窗口不能接受任何用户输入.
用法:
void GLUI::hide(void);

show:
使一个被隐藏的窗口或子窗口可见.
用法:
void GLUI::show(void);

close:
销毁一个GLUI窗口或子窗口.
用法:
void GLUI::close(void);

close_all:
销毁所有的GLUI窗口和子窗口.此函数应该被全局对象所调用如:GLUI_Master.close_all();
用法:
void GLUI_Master_Object::close_all(void);

sync_live:
变量可以与控件相关联,该函数可以使一个GLUI窗口上的所有控件和与这些控件相关联的变量保持同步,也即:读取变量的值,然后根据该值设置与其相关联的控件,使该值在控件上反映出来
用法:
void GLUI::sync_live(void);

sync_live_all:
使所有GLUI窗口上的所有控件与与其相关联的变量保持同步,这个函数必须通过全局对象调用,如:GLUI_Master.sync_live_all();
用法:
void GLUI_Master_Object::sync_live_all(void);

GLUI简介(4)--控件 //////////////////////////////////////////////////////////////////////////////////////////////////
    GLUI中,所有的控件都是源于GLUI_Control类,所以,他们的操作都非常相似.我们有两种方法创建控件:一种是使用add_control()直接将控件放在窗口之上,另一种是使用add_control_to_panel()将控件置于panel之内. panel是一个可以内置其他控件的容器,panel也可以置于另一个panel之内.
    这里介绍的函数可以被许多控件调用,用来改变其属性,因此这里介绍的函数可以称为公共函数.
set_name:
为button,checkbox等控件设置名字.
用法:
void GLUI_Control::set_name(char *name);
参数:
name:控件的名字(即:在控件上或控件旁显示的文字)
set_w, set_h:
设置控件的最小宽度或高度
用法:
void GLUI_Control::set_w(int new_size);
void GLUI_Control::set_h(int new_size);
参数:
new_size:控件的最小宽度或高度.
get, set:
获取或设置控件的当前值.
用法:
int GLUI_Control::get_int_val(void);
float GLUI_Control::get_float_val(void);
void GLUI_Control::get_float_array_val(float *float_array_ptr);
char *GLUI_Control::get_text(void);
void GLUI_Control::set_int_val(int int_val);
void GLUI_Control::set_float_val(float float_val);
void GLUI_Control::set_float_array_val(float *float_array_val);
void GLUI_Control::set_text(char *text);
(根据控件对输入输出数据值类型的要求,选取相应的函数)
disable, enable:
使控件可用或不可用,radio group不可用时,其中的button也不可用,panel不可用时,其中的所有控件都不可用.
用法:
void GLUI_Control::enable(void);
void GLUI_Control::disable(void);
set_alignment:
设置控件的对齐方式(居左,居中,居右)
用法:
void GLUI_Control::set_alignment(int align);
参数:
align:对齐方式.可选下面之一:
       GLUI_ALIGN_CENTER
       GLUI_ALIGN_RIGHT
       GLUI_ALIGN_LEFT


GLUI简介(5)--控件 //////////////////////////////////////////////////////////////////////////
Panels:一个容器,可以内置其他控件,也可以内置另一个panel.
add_panel:
在GLUI窗口上新建一个panel控件.
用法:
GLUI_Panel *GLUI::add_panel(char *name, int tyep = GLUI_PANEL_EMBOSSED);


add_panel_to_panel:
在另一个panel之内新建一个panel控件.
用法:
GLUI_Panel *GLUI::add_panel_to_panel(GLUI_Panel *panel, char *name, int type = GLUI_PANEL_EMBOSSED);

参数:
name:panel控件的名字(可以为空,如若指定了名字,会在panel的左上角显示).
type:panel的样式.
       GLUI_PANEL_EMBOSSED:用内嵌的线条画一个矩形框(默认值).
       GLUI_PANEL_RAISED:用外凸的线条画一个矩形框,不显示名字.
       GLUI_PANEL_NONE:不绘制矩形框,只用来将控件组织成一个控件组.
panel:指向另一个panel控件的指针.新建的panel控件将会置于该panel之中.

返回值:
新建的panel控件的指针.

Rollouts:类似于panel也是一个容器,功能上可以与panel互相替代,不同之处在于该控件可以被折叠起来,此时其内置的控件不可见,只有当其展开后,内置控件才可见.
add_rollout:
在GLUI窗口中新建rollout控件.
用法:
GLUI_Rollout *GLUI::add_rollout(char *name, int open = true);
add_rollout_to_panel:
在另一个已经存在的rollout或panel中新建一个rollout控件.
用法:
GLUI_Rollout *GLUI::add_rollout_to_panel(GLUI_Panel *panel, char *name, int open = true);

参数:
name:控件的名字.
open:如果为true,则rollout初始设置为打开;如果为false,则初始设置为闭合.
panel:指向另一个panel或rollout控件的指针.新建的rollout控件将会置于该panel或rollout之中.
返回值:
新建rollout控件的指针.
Columns:控件在GLUI窗口中的布局是按照控件定义的顺序自上而下放置的,在竖直方向上形成一个控件列,而column则会开辟一个新的控件列(即在旧的控件列的右侧新建一个新的控件列),其后所定义的控件将置于该新建的控件列中(即在新的控件列中自上而下布局),直至新的控件列被创建.
add_column:
在GLUI窗口上新建column.
用法:
void GLUI::add_column(int draw_bar = true);
add_column_to_panel:
在panel中新建column.
用法:
void GLUI::add_column_to_panel(GLUI_Panel *panel, int draw_bar = true);

参数:
draw_bar:如果为true,则在新建控件列时,会绘制一条竖线将其与原先的控件列区分开;如为false,则只创建控件列,不绘制竖线.
panel:指向一个panel控件的指针.新建的column控件将会置于该panel之中.


Buttons:按钮
add_button:
在GLUI窗口上直接新建按钮.
用法:
GLUI_Button *GLUI::add_button(char *name, int id = -1, GLUI_Update_CB callback = NULL);
add_button_to_panel:在一个已经存在的panel中创建按钮.
用法:
GLUI_Button *GLUI::add_button_to_panel(GLUI_Panel *panel,char *name,int id = -1,GLUI_Update_CB callback = NULL);

参数:
name:按钮的名字,即在按钮上显示的文字.
id:按钮的ID值.如果callback被定义了,则当callback被调用时,id值会作为参数传递给callback.
callback:接受一个整形参数的callback函数.当按钮被触发时,它会被调用.
panel:指向一个panel控件的指针.新建的button控件将会置于该panel之中.

返回值:
新建的按钮控件的指针.
Checkboxes:复选框
add_checkbox:
在GLUI窗口上直接创建新的checkbox.
用法:
GLUI_Checkbox *GLUI::add_checkbox(char *name, int *live_var = NULL, int id = -1,GLUI_Update_CB callback = NULL);
add_checkbox_to_panel:
在已经存在的panel中创建新的checkbox.
用法:
GLUI_Checkbox *GLUI::add_check_to_panel(GLUI_Panel *panel, char *name, int *live_var = NULL, int id = -1, GLUI_Update_CB callback = NULL);

参数:
name:checkbox的名字.
live_var:与控件checkbox相关联的整形指针,当checkbox控件状态发生变化时,该整形值会自动更新.
id:复选框的ID值.如果callback被定义了,则当callback被调用时,id值会作为参数传递给callback.
callback:接受一个整形参数的callback函数.当按复选框触发时,它会被调用.
panel:指向一个panel控件的指针.新建的checkbox控件将会置于该panel之中.

返回值:
新建的checkbox控件的指针.

 


在Visual C++中设置GLUI

 

用glut来管理OpenGL窗口确实十分方便,但glut的功能也十分有限,除了弹出菜单以外就没有什么控件了!而基于glut和c++的glui正可以弥补这个缺陷,它其实是GL窗口组件库.目前最新版本是2.35.

在vc中设置glui:
1.将下载的glui-2.35.zip解压
2.打开msvc文件夹,找到glui.dsw文件,用vc打开,链接编译后,会在msvc文件夹中生成Debug文件夹.
3.在Debug文件夹中,找到glui32.lib,拷贝到C:\Program Files\Microsoft Visual Studio\VC98\Lib(vc的默认安装路径)
注:该文件可保留,下次重装系统时可以直接使用而不用重新编译.
4.解压后的glui-2.35文件夹中,找到include文件夹里的glui.h,将其拷贝到C:\Program Files\Microsoft Visual Studio\VC98\Include\GL.至此,glui设置完成.(不过如果要使用还要设置工程,具体如下)


   在解压后的glui-2.35文件夹中还有个example文件夹,里面是例子,如果直接打开编译就会报错,因为还需要设置工程.选择Project->settings,在弹出对话框中选择General标签,在Microsoft Foundation Classes的下拉菜单中选择Use MFC in a Shared DLL,点击OK.工程设置完毕,重新编译,一切OK!
具体的glui介绍请参看
http://www.cs.unc.edu/~rademach/glui/
http://glui.sourceforge.net/#download 

 

PS1:

当前可能从sourceforge上下载不到glui-2.35(我用迅雷没有找到资源),这时可以到Google上输入“/index of glui 2.35.zip”,可以从某一各学校的实验课程网站上下载到。

PS2:

在编写程序是可能会出现如下的错误:msvcrt.lib(MSVCRT.dll) : error LNK2005: _exit already defined in LIBC.lib(crt0dat.obj)........

解决方案:在vc工程—>设置—>Link—>模块栏里加入msvcrt.lib libc.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 之后就不会有错误了.....