菜单
GLUT提供了重要的组件--菜单。通常这些菜单都被实现为弹出式菜单。往往在鼠标的某一键被按下时才会出现。定义菜单的三个步骤:
1、确定菜单中有哪些选项,即菜单的每行将显示哪些字符串。
2、菜单的每一行关联一种特定操作。
3、每个菜单与鼠标按键建立关联。
菜单通常在主函数或主函数调用的初始化函数中被创建。GLUT允许创建级联菜单,方法是一个菜单项指向一个子菜单。顶级菜单由如下函数创建:
int glutCreateMenu(void (*f)(int value))
创建一个使用回调函数f的顶级菜单,f由菜单项传入一个整数值value。该函数将为所创建菜单返回一个唯一标示符。
所创建的菜单将称为当前菜单。
void glutSetMenu(int id) //将当前菜单设为标示符为id的菜单
void glutAddMenuEntry(char* name,int value) //为当前项增加一个名称为那么的菜单项, value将被返回给菜单回调函数
void glutAttachMenu(int button) //为当前菜单依附到一个指定的鼠标按钮上 (GLUT_RIGHT_BOTTON、GLUT_MIDDLE_BOTTON、GLUT_LEFT_BOTTON)
void glutAddSubMenu(char* name,int menu)
假如我们想用鼠标右键弹出一个有两个菜单项的菜单:一个可清屏,一个结束程序。则可以在main或者init假如如下代码:
int id=glutCreateMenu(mymenu); glutAddMenuEntry("Clear Screen",1); glutAddMenuEntry("Exit",2); glutAttachMenu(GLUT_LEFT_BUTTON);
mymenu函数定义如下:
void mymenu(int value) { if (value==1) { glClear(GL_COLOR_BUFFER_BIT); glFlush(); } if (value==2) { exit(0); } }
NULL回调函数
将NULL作为回调函数,则可注销原来的回调函数。
子窗口与多窗口
int glutCreateWindow(char* name) //创建一个顶级窗口name,并为其返回一个标示符
int glutDestoryWindow(int id) //销毁标示符为id的顶级窗口
当一个窗口被创建后,它就成了当前窗口。图元都将绘制在当前窗口中。
void glutSetWindow(int id) //将当前窗口设置为标示符为id的窗口。
int glutCreateSubWindow(int parent,int x,int y,int width,int height) //为parent创 建一个子窗口
当子窗口被创建时,它就成为当前窗口。
void glutPostWindowRedisplay(int winid) //通知标示符为winid的窗口重新显示
显示列表
OpenGL中的标准绘图模式称为立即模式。只要各种图元被定义,就立即传入到OpenGL流水线。当屏幕需要重绘时,我们必须重新生成这些图元,然后再次将这些图元传入流水线。因此重新显示的过程可能相当耗时。
保留模式下,图元集合及其他信息可作为对象保存在服务器中,这样避免了代价较高的传输和重新生成的问题。OpenGL通过显示列表来实现这些对象的定义。使用显示列表的4个步骤:
1、打开显示列表
2、为其命名
3、添加命令
4、关闭显示列表
void glNewList(GLuint name,GLenum mode) //创建一个新的显示列表,mode的值(GL_COMPILE、 GL_COMPILE_AND_EXECUTE)
void glEndList() //结束显示列表的定义
GL_COMPILE:将显示列表放在服务器中,但其内容不被显示
GL_COMPILE_AND_EXECUTE:显示列表创建时就被显示。
void glCallList(GLuint name) //执行显示列表name
void glDeleteLists(GLuint first,GLsizei number) //删除由first开始的number个显示列表。
多个显示列表
void glCallLists(GLSizes num,GLenum type,GLvoid * lists)
//依据存储类型为type的数组lists中的整数值执行num个显示列表。当前偏移量被叠加到lists中的每个证书上,这样就得到了所要执行的显示列表的ID
void glListBase(GLuint offset) //设置glCallLists()使用的偏移量,默认为0
GLuint glGenLists(GLsizei n) //返回可用于新显示列表的n个连续整数标示符中的第一个。
显示列表与文本
若能为每一个字符使用一个显示列表,则文本就能高效的得到绘制。若决定用GLUT的10磅大小的罗马位图字体。我们需要256个显示列表。
首先获取256个连续可用的ID:
base=glGenLists(256);
接着为每个字体使用一个显示列表:
for(i=0;i<256;i++)
{
glNewList(base+i,GL_COMPILE);
glutBitMapCharacter(GLUT_BITMAP_TIMES_ROMAN_10,i);
glEndList();
}
然后设置基数列表
glListBase(base);
如想绘制一个字符串
char* text;
glCallLists((GLint)strlen(text),GL_UNSIGNED_BYTE,text);
显示列表和对象
显示列表为用户提供了一种比立即模式更符合面向对象的思想的程序构建方式。显示列表使得新颜色可以与几何实体绑定在一起。显示类表还可以在显示列表中执行其他的显示列表。例如,如要创建一个人物,我们可以把,脸,眼睛,鼻子,嘴巴分开绘制。
glNewList(FACE,GL_COMPILE);
glCallList(EYE);
glCallList(EAR);
glCallList(MOUTH);
glCallList(NOSE);
glEndList();