一个极好的OpenGL汉字显示类
作者:Y___Y
联系:yinwei_88@sina.com
笔者通过各方面的资料的收集,终于写出了一个OpenGL汉字显示类(最核心的内容都是从网上和NeHe的教程上找到的,这个类实际上是从各位原创作者“集合”成的,笔者只能算一个收集整理者),很好的解决了2D,3D以及图象,图形汉字(当然也包括字母)的显示。现将其公布出来。
//
GLFont.h文件
#include
<
windows.h
>
#include
"
gl/gl.h
"
#pragma
warning(disable:4244)
//
OpenGL汉字显示类
class
GLfont

...
{
HFONT hFont;
COLORREF cl;
public:
GLfont();
virtual ~GLfont();
void SetTextColor(COLORREF textcolor);//字体颜色设置
void CreateFont(char *facename, int height, int weight, bool italic,bool underline,bool strikeout);
void ShowText(int x, int y, LPCTSTR lpszText);//显示图象2D汉字
void Show2DText(char *str);//显示图形2D汉字
void Show3DText(unsigned char *str);//显示图形3D汉字
}
;

GLfont::GLfont()

...
{
cl=RGB(255,255,255);
}
GLfont::
~
GLfont()

...
{
if(hFont) DeleteObject(hFont);
}

//
只有关闭光照和纹理才能正确显示颜色
void
GLfont::SetTextColor(COLORREF textcolor)
//
字体颜色设置

...
{
cl=textcolor;
}
void
GLfont::CreateFont(
char
*
facename,
int
height,
int
weight,
bool
italic,
bool
underline,
bool
strikeout)

...
{
LOGFONT lf;
lf.lfHeight = height;
lf.lfWidth = 0;
lf.lfEscapement = 0;
lf.lfOrientation = 0;
lf.lfWeight = weight;
lf.lfItalic = italic;
lf.lfUnderline = underline;
lf.lfStrikeOut = strikeout;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfOutPrecision = OUT_TT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = PROOF_QUALITY;
lf.lfPitchAndFamily = VARIABLE_PITCH | TMPF_TRUETYPE | FF_MODERN;
strcpy(lf.lfFaceName,facename);
// 创建字体
hFont = CreateFontIndirect(&lf);
}

//
2D图像汉字只与屏幕相联系,与具体的变换矩阵无关,也就是说不能缩放旋转。
//
x,y是2D图像汉字距屏幕左下角(注意不是左上角)的横向和纵向距离。
void
GLfont::ShowText(
int
x,
int
y, LPCTSTR lpszText)

...
{
// 保存原投影矩阵,将投影矩阵设为平行投影
glMatrixMode( GL_PROJECTION );
glPushMatrix();
glLoadIdentity();
glOrtho( 0, 640, 0, 480, -1, 1 );
// 保存原模型变换矩阵,平移至( x, y )
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
RECT rect;
GetClientRect(GetActiveWindow(),&rect);
glTranslatef((float)x,(float)y,0);
HBITMAP hbitmap;
BITMAP bm;
SIZE size;
UCHAR* pBmpBits;
HFONT hOldFont;
HDC hdc = wglGetCurrentDC();
hOldFont = (HFONT)SelectObject(hdc, hFont);
::GetTextExtentPoint32(hdc, lpszText, strlen(lpszText), &size);
hbitmap = CreateBitmap(size.cx, size.cy,1, 1, NULL);
HDC hMemDC = ::CreateCompatibleDC(hdc);
if(hMemDC)

...{
HBITMAP hPrevBmp = (HBITMAP)SelectObject(hMemDC,hbitmap);
HFONT hPrevFont = (HFONT)SelectObject(hMemDC, hFont);
SetBkColor(hMemDC, RGB(0, 0, 0));
::SetTextColor(hMemDC,RGB(255,255,255));
SetBkMode(hMemDC, OPAQUE);
TextOut(hMemDC, 0, 0, lpszText, strlen(lpszText));
//把GDI位图复制到DIB
SelectObject(hdc,hbitmap);
GetObject(hbitmap, sizeof(bm), &bm);
size.cx = (bm.bmWidth + 31) & (~31);
size.cy = bm.bmHeight;
int bufsize = size.cy * (((bm.bmWidth + 31) & (~31)) /8);
pBmpBits = new UCHAR[bufsize];
memset(pBmpBits, 0, sizeof(UCHAR)*bufsize);
struct

...{
BITMAPINFOHEADER bih;
RGBQUAD col[2];
}
bic;
BITMAPINFO *binf = (BITMAPINFO *)&bic;
binf->bmiHeader.biSize = sizeof(binf->bmiHeader);
binf->bmiHeader.biWidth = bm.bmWidth;
binf->bmiHeader.biHeight = bm.bmHeight;
binf->bmiHeader.biPlanes = 1;
binf->bmiHeader.biBitCount = 1;
binf->bmiHeader.biCompression = BI_RGB;
binf->bmiHeader.biSizeImage = bufsize;
binf->bmiHeader.biXPelsPerMeter = 1;
binf->bmiHeader.biYPelsPerMeter = 1;
binf->bmiHeader.biClrUsed = 0;
binf->bmiHeader.biClrImportant = 0;
::GetDIBits(hdc, hbitmap, 0, bm.bmHeight, pBmpBits, binf,DIB_RGB_COLORS);
SelectObject(hMemDC,hPrevBmp);
}
::DeleteDC(hMemDC);
DeleteObject( hbitmap );
SelectObject(hdc, hOldFont);
//显示文字
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glColor3f(GetRValue(cl)/255.0,GetGValue(cl)/255.0,GetBValue(cl)/255.0);
glRasterPos2i(x,y);
glBitmap(size.cx, size.cy, 0.0, 2.0, size.cx+2.0f, 0.0, pBmpBits);
delete []pBmpBits;//修改
// 恢复投影矩阵和模型变换矩阵
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glColor3f(1.0,1.0,1.0);
}

void
GLfont::Show2DText(
char
*
str)

...
{
char FTextList[255];
GLYPHMETRICSFLOAT gmf[256];
int m_iCount=strlen(str);
GLuint m_listbase;
HDC hDC=wglGetCurrentDC();
glPushMatrix();
SelectObject(hDC,hFont);
int i=0;
int j=0;
int ich,cch;
m_listbase = glGenLists(256);
glColor3f(GetRValue(cl)/255.0,GetGValue(cl)/255.0,GetBValue(cl)/255.0);
while(i<m_iCount)

...{
if(IsDBCSLeadByte(str[i]))

...{
//判断是否为双字节
ich=str[i];

ich=(ich<<8)+256; /**/////256为汉字内码“偏移量”
ich=ich+str[i+1];
i++;i++;
wglUseFontOutlines(hDC,//字体轮廓设备联系DC
ich, //要转换为显示列表的第一个字符
1, //要转换为显示列表的字符数
m_listbase+j,//显示列表的基数
1.0f, //指定与实际轮廓的最大偏移量
0,//0.15f, //在Z轴负方向的值
WGL_FONT_POLYGONS, //指定显示列表线段或多边形
&gmf[j]); //接受字符的地址
FTextList[j]=j;
j++;
}
else

...{
cch=str[i];
i++;
wglUseFontOutlines(hDC, //字体轮廓设备联系DC
cch,//要转换为显示列表的第一个字符
1,//要转换为显示列表的字符数
m_listbase+j,//显示列表的基数
0.0f,//指定与实际轮廓的最大偏移量
0.0,//</