ARToolkit手札之显示菜单(一)

来源:互联网 发布:梦幻西游129魔化生数据 编辑:程序博客网 时间:2024/05/16 19:13

        本文利用标识卡的旋转角度来控制菜单的输出状态(我是在例子simpleTest.c的基础框架上改写的)。OpenGL并没有直接提供显示文字的功能,并且OpenGL也没有自带专门的字库。因此,要显示文字,就必须依赖Windows操作系统所提供的功能了。

         最常见的方法就是,我们给出一个字符,给出一个显示列表编号,然后Windows操作系统把绘制这个字符的OpenGL命令装到指定的显示列表中,当需要绘制字符的时候,我们只需要调用这个显示列表即可。 

         假如我们要显示的文字是扩展的ASCII字符,则总共只有0~255这256种可能,因此可以预先把所有的字符分别装到对应的显示列表中,然后在需要时调用这些显示列表。

         Windows系统中,可以使用wglUseFontBitmaps()函数来批量的产生显示字符用的显示列表。

函数原型:

BOOL WINAPI wglUseFontBitmaps(HDC hdc,DWORD first,   DWORD count, DWORDlistBase );

函数有四个参数:

第一个参数是hdc,只要知道调用wglGetCurrentDC函数,就可以得到一个HDC(DC的句柄,API中的一个类似指针的数据类型)了。

第二个参数表示第一个要产生的字符,因为我们要产生0到255的字符的显示列表,所以这里填0。

第三个参数表示要产生字符的总个数,因为我们要产生0到255的字符的显示列表,总共有256个字符,所以这里填256。

第四个参数表示第一个字符所对应显示列表的编号。假如这里填1000,则第一个字符的绘制命令将被装到第1000号显示列表,第二个字符的绘制命令将被装到第1001号显示列表,依次类推。我们可以先用glGenLists申请256个连续的显示列表编号,然后把第一个显示列表编号填在这里。

【说明】因为wglUseFontBitmaps()是Windows系统特有的函数,所以在使用前需要加入头文件:#include <windows.h>。

        接下来我们来看一下具体代码:

void Print(const char *str)//输出文字{static int isFirstCall=1;    static GLuint lists; if(isFirstCall)// 如果是第一次调用,执行初始化{isFirstCall=0; //为每一个ASCII字符产生一个显示列表       lists=glGenLists(256);//申请256个连续的显示列表编号wglUseFontBitmaps(wglGetCurrentDC(),0,256,lists);//把每个字符的绘制命令都装到对应的显示列表中   }  //调用每个字符对应的显示列表,绘制每个字符for(;*str!='\0';++str)//glCallList(lists+(*str));glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24,*str );//如果用上面的语句,则输出文字太小,所以用该语句来控制字体大小}

根据标识卡的旋转角度,显示文字,代码如下:

int ShowMenu(char notices[][128],int n,double angle)//显示菜单{int i,nSel=0;glTranslatef( 60.0, 0.0, 0.0 );nSel=(int)(angle/(90/(n-1)))%(n-1);//【当n=4的情况下】angle=[0,29]或90时,nSel=0;angle=[30,59]时,nSel=1;angle=[60,89]时,nSel=2;for(i=0;i<n;i++){glColor3f((float)(i==0||nSel==i-1),(float)(i!=0),0.0f);//设置画刷颜色glRasterPos3f(50.0f,100.0f-i*30.0f,0.0f);//用于显示[字体]时设置字符的起始位置Print(notices[i]);}return nSel;}

还要在声明部分加上下面的代码。

#include<string.h>#include<math.h>int ShowMenu(char notices[][128],int n,double angle);//显示菜单void Print(const char *str);//输出文字

然后在static void mainLoop(void)函数里面加上如下代码:

/* main loop */static void mainLoop(void){    ARUint8         *dataPtr;    ARMarkerInfo    *marker_info;    int             marker_num;    int             j, k;    double angle=0;//添加    int MenuIndex=0;//添加    char notices[4][128]={{"Shape:"},{"Teapot"},{"Cube"},{"Sphere"}};//添加    ……    ……    ……   //显示菜单   angle=atan(-marker_info->line[0][0]/marker_info->line[0][1])/3.1415926*180; //添加   printf("%3.1f\n",angle); //添加   glPushMatrix();//添加   MenuIndex=ShowMenu(notices,4,angle); //添加   glPopMatrix();//添加   draw();   argSwapBuffers();}

最后,将static void draw(void)函数里面行代码注释掉。

//glTranslatef( 0.0, 0.0, 25.0 );//glutSolidCube(50.0);

运行结果如下。

图1【当n=4的情况下】angle在[0,29]之间,nSel=0,菜单切换到”Teapot”


图2【当n=4的情况下】angle在[30,59]之间,nSel=1,菜单切换到”Cube”


图3【当n=4的情况下】angle在[60,89]之间,nSel=2,菜单切换到”Sphere”


原创粉丝点击