第七章opengl文字显示.doc_第1页
第七章opengl文字显示.doc_第2页
第七章opengl文字显示.doc_第3页
第七章opengl文字显示.doc_第4页
第七章opengl文字显示.doc_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

OpenGL文字显示(一)显示英文OpenGL并没有直接提供显示文字的功能,并且,OpenGL也没有自带专门的字库。因此,要显示文字,就必须依赖操作系统所提供的功能了。各种流行的图形操作系统,例如Windows系统和Linux系统,都提供了一些功能,以便能够在OpenGL程序中方便的显示文字。最常见的方法就是,我们给出一个字符,给出一个显示列表编号,然后操作系统由把绘制这个字符的OpenGL命令装到指定的显示列表中。当需要绘制字符的时候,我们只需要调用这个显示列表即可。假如我们要显示的文字全部是ASCII字符,则总共只有0到127这128种可能,因此可以预先把所有的字符分别装到对应的显示列表中,然后在需要时调用这些显示列表。 Windows系统中,可以使用wglUseFontBitmaps函数来批量的产生显示字符用的显示列表。函数有四个参数:第一个参数是HDC,这是WindowsGDI的里的东西,调用wglGetCurrentDC函数,就可以得到一个HDC了。第二个参数表示第一个要产生的字符,因为我们要产生0到127的字符的显示列表,所以这里填0。第三个参数表示要产生字符的总个数,因为我们要产生0到127的字符的显示列表,总共有128个字符,所以这里填128。第四个参数表示第一个字符所对应显示列表的编号。假如这里填1000,则第一个字符的绘制命令将被装到第1000号显示列表,第二个字符的绘制命令将被装到第1001号显示列表,依次类推。我们可以先用glGenLists申请128个连续的显示列表编号,然后把第一个显示列表编号填在这里。我们为了简化view中的代码,特建立字符显示类COpenGLFont(后面给出):#defineMAX_CHAR128wglUseFontBitmaps(wglGetCurrentDC(),0,MAX_CHAR,lists);在字符类中添加显示字符函数:void COpenGLFont:drawString(const char* str) static int isFirstCall = 1;static GLuint lists; if( isFirstCall ) / 如果是第一次调用,执行初始化/ 为每一个ASCII字符产生一个显示列表isFirstCall = 0;/ 申请MAX_CHAR个连续的显示列表编号lists = glGenLists(MAX_CHAR); /编号分别是lists, lists + 1, lists + 2, lists + MAX_CHAR -1/ 把每个字符的绘制命令都装到对应的显示列表中wglUseFontBitmaps(wglGetCurrentDC(), 0, MAX_CHAR, lists); /从基数lists开始依次显示各个字符/ 调用每个字符对应的显示列表,绘制每个字符for(; *str!=0; +str)glCallList(lists + *str);显示列表一旦产生就一直存在(除非调用glDeleteLists销毁),所以我们只需要在第一次调用的时候初始化,以后就可以很方便的调用这些显示列表来绘制字符了。绘制字符的时候,可以先用glColor*等指定颜色,然后用glRasterPos*指定位置,最后调用显示列表来绘制。#includeOpenGLFont.hvoid CMFCOpenGLView:OnDraw(CDC* /*pDC*/)CMFCOpenGLDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;/ TODO: 在此处为本机数据添加绘制代码glClearColor(0.0f,0.0f,0.7f,1.0f); /背景设置glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(0,0,10,0,0, 0,0,1,0);glColor3f(1,0,0);glRasterPos4s(-2,0,0,1); /指定位置COpenGLFont font;font.drawString(chinese character show test!12345);glFinish();SwapBuffers(wglGetCurrentDC();指定字体:在产生显示列表前,Windows允许选择字体。在COpenGLFont类中定义一个selectFont函数来实现它,大家可以看看代码。void COpenGLFont:selectFont(int size, int charset, const char* face) HFONT hFont = CreateFontA(size, /指定字高0,/指定字宽0,/指定角度(1/10度)45, /指定字符的基线与x轴的角度(1/10度)FW_BOLD,/指定字体的重量(FW_BOLD=700)0,/指定是否斜体0,/指定是否有下划线0,/指定是否是StrikeOut字体charset,OUT_DEFAULT_PRECIS, /指定输出精度CLIP_DEFAULT_PRECIS,/指定裁剪精度DEFAULT_QUALITY,/指定输出质量DEFAULT_PITCH | FF_SWISS, /指定字体的定位和外观face);HFONT hOldFont = (HFONT)SelectObject(wglGetCurrentDC(), hFont);DeleteObject(hOldFont);在调用wglUseFontBitmaps之前使用selectFont函数即可指定字体。函数的三个参数分别表示了字体大小、字符集(英文字体ANSI_CHARSET,简体中文字体GB2312_CHARSET,繁体中文字体CHINESEBIG5_CHARSET ,对于中文的Windows系统,也可以直接用DEFAULT_CHARSET表示默认字符集)、字体名称。(二)显示中文原则上,显示中文和显示英文并无不同,同样是把要显示的字符做成显示列表,然后进行调用。但是有一个问题,英文字母很少,最多只有几百个,为每个字母创建一个显示列表,没有问题。但是汉字有非常多个,如果每个汉字都产生一个显示列表,这是不切实际的。我们不能在初始化时就为每个字符建立一个显示列表,那就只有在每次绘制字符时创建它了。当我们需要绘制一个字符时,创建对应的显示列表,等绘制完毕后,再将它销毁。这里还经常涉及到中文乱码的问题,在网上流传的版本中,使用了MultiByteToWideChar这个函数的,基本上都没有出现乱码,所以我们也准备用这个函数。通常我们在C语言里面使用的字符串,如果中英文混合的话,例如“thisis中文字符.”,则英文字符只占用一个字节,而中文字符则占用两个字节。用MultiByteToWideChar函数,可以转化为所有的字符都占两个字节(同时解决了前面所说的乱码问题:))。转化的代码如下:/计算字符的个数/如果是双字节字符的(比如中文字符),两个字节才算一个字符/否则一个字节算一个字符len=0;for(i=0;stri!=0;+i)if(IsDBCSLeadByte(stri)+i;+len;/将混合字符转化为宽字符wstring=(wchar_t*)malloc(len+1)*sizeof(wchar_t);MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,str,-1,wstring,len);wstringlen=L0;/用完后记得释放内存free(wstring);加上前面所讲到的wglUseFontBitmaps函数,即可显示中文字符了。在字体类中添加显示中文字符函数:void COpenGLFont:drawCNString(const char* str) int len, i;wchar_t* wstring;HDC hDC = wglGetCurrentDC();GLuint list = glGenLists(1);/ 计算字符的个数/ 如果是双字节字符的(比如中文字符),两个字节才算一个字符/ 否则一个字节算一个字符len = 0;for(i=0; stri!=0; +i)if( IsDBCSLeadByte(stri) )+i;+len;/ 将混合字符转化为宽字符wstring = (wchar_t*)malloc(len+1) * sizeof(wchar_t);MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstring, len);wstringlen = L0;/ 逐个输出字符for(i=0; ilen; +i)wglUseFontBitmapsW(hDC,wstringi, 1, list);glCallList(list);/ 回收所有临时资源free(wstring);glDeleteLists(list, 1);注意我用了wglUseFontBitmapsW函数,而不是wglUseFontBitmaps。wglUseFontBitmapsW是wglUseFontBitmaps函数的宽字符版本,它认为字符都占两个字节。因为这里使用了MultiByteToWideChar,每个字符其实是占两个字节的,所以应该用wglUseFontBitmapsW。void CMFCOpenGLView:OnDraw(CDC* /*pDC*/)CMFCOpenGLDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;/ TODO: 在此处为本机数据添加绘制代码glClearColor(0.0f,0.0f,0.7f,1.0f); /背景设置glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(0,0,10,0,0, 0,0,1,0);glColor3f(1,0,0);glRasterPos4s(-5,0,0,1); /指定位置COpenGLFont font;font.selectFont(48,DEFAULT_CHARSET, 黑体);font.drawCNString(汉字显示测试!chinese character show test!12345);glFinish();SwapBuffers(wglGetCurrentDC();(三)三维汉字的显示在OpenGL中输出文本有两个函数:wglUseFontBitmaps和wglUseFontOutlines,前者用来输出2维文字,后者用来输出3维文字, 项目需要采用unicode编码方式.void COpenGLFont:draw3DString(_TCHAR* str)GLYPHMETRICSFLOAT pgmf1; DWORD dwChar; int list;HDC hDC=wglGetCurrentDC();for(size_t i=0;i_tcslen(str);i+) dwChar=stri; list=glGenLists(1);/取出一个字符的显示列表wglUseFontOutlines(hDC,/设备环境句柄dwChar,/要转换为显示列表的第一个字符1, /要转换为显示列表的字符数list,/显示列表的基数0.0,/指定与实际轮廓的最大偏移量,显示精度0.5,/在Z轴负方向的值,即厚度0,/填充模式,为填充,为线框NULL/*pgmf*/); /接受字符的地址 /绘制该字符的显示列表glCallList(list); glDeleteLists(list, 1); void CMFCOpenGLView:OnDraw(CDC* /*pDC*/)CMFCOpenGLDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;/ TODO: 在此处为本机数据添加绘制代码glClearColor(0.0f,0.0f,0.7f,1.0f); /背景设置glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);g

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论