Lighthouse3d.com >> GLUT Tutorial >> Fonts >> Bitmap Fonts and Orthogonal Projections

一般用法下,位图字体只能以二维的形式显示信息给用户.例如,一个简单的例子,我们想显示应用程序每秒的帧数.这些信息可以驻留在同一个位置,即使用户移动镜头.除此之外,用二维的正交投影比透视投影更容易计算这些位置,因为我们可以指定用像素表示该位置.

实现的基本模式是以之前的方式绘制世界,用透视投影,然后切换到正交投影来绘制文本.执行完最后一步之后我们要恢复到原来的视角,这样下一帧就会正确显示.

接下来我们演示一个渲染函数的模板来大道该效果:

void renderScene() {

// do everything we need to render the world as usual
... setOrthographicProjection(); glPushMatrix();
glLoadIdentity();
renderBitmapString(,,GLUT_BITMAP_HELVETICA_18,"Lighthouse3D");
glPopMatrix(); restorePerspectiveProjection(); glutSwapBuffers();
}

上面有两个新函数: setOrthograpicProjection and restorePerspectiveProjection.第一个函数始于转换矩阵模式到GL_PROJECTION,意味着我们在镜头下工作.然后我们保存之前的设置,在这个例子中是引用自其它某处定义好的透视投影.然后我们用glLoadIdentity函数重置矩阵,并用gluOrtho函数定义一个正交投影.

该函数的参数是表示从x到y轴的范围.然后转换沿着y轴滑动,正值是向下,翻译成原型是到左上角.这样使输出文本到屏幕坐标更简单.

变量w和h在其它地方计算好(见之前changeSize函数).

void setOrthographicProjection() {

    // switch to projection mode
glMatrixMode(GL_PROJECTION); // save previous matrix which contains the
//settings for the perspective projection
glPushMatrix(); // reset matrix
glLoadIdentity(); // set a 2D orthographic projection
gluOrtho2D(, w, , h); // invert the y axis, down is positive
glScalef(, -, ); // mover the origin from the bottom left corner
// to the upper left corner
glTranslatef(, -h, ); // switch back to modelview mode
glMatrixMode(GL_MODELVIEW);
}

一个演示正交投影的快速方法如下.方法是设置投影而无需测量和翻译.

void setOrthographicProjection() {

    // switch to projection mode
glMatrixMode(GL_PROJECTION); // save previous matrix which contains the
//settings for the perspective projection
glPushMatrix(); // reset matrix
glLoadIdentity(); // set a 2D orthographic projection
gluOrtho2D(, w, h, ); // switch back to modelview mode
glMatrixMode(GL_MODELVIEW);
}

该函数非常简单.当我们在设置正交投影前保存透视投影的设置的时候,我们需要做的只是更改矩阵模式到GL_PROJECTION,然后弹出矩阵.然后恢复设置,最后更改矩阵模式回GL_MODELVIEW.

void restorePerspectiveProjection() {

    glMatrixMode(GL_PROJECTION);
// restore previous projection matrix
glPopMatrix(); // get back to modelview mode
glMatrixMode(GL_MODELVIEW);
}

上面这个renderBitmapString函数,上一节介绍过,会连续写入字符,不包含额外的空间,除了文本本身带有空格字符外.为了添加额外的空间,我们必须保持跟踪当然的栅格位置,这样才可以添加额外的空间到x坐标.至少有两种不同的方法来保持跟踪栅格位置.一种是在绘制完一张位图之后计算当前的栅格位置.另一种是专注于请求OpenGL的关于当前栅格位置的状态机器.

第一种方法需要我们知道字符的维度.最大的高度一直保持为一个特殊字体的常量,在多数字体中宽度是可以任意变更的.幸运的是GLUT提供了一个函数来返回字宽.glutBitmapWidth原型如下:

int glutBitmapWidth(void *font, int character);

font - GLUT中的预定义字体之一,见上一节中列出的可选值

character - 我们想要知道字宽的字符

所以,例如我们需要一个函数来写入一个固定每个字符所占像素量的字符串,我们可以如下实现:

void renderSpacedBitmapString(

            float x,
float y,
int spacing,
void *font,
char *string) { char *c;
int x1=x; for (c=string; *c != '\0'; c++) { glRasterPos2f(x1,y);
glutBitmapCharacter(font, *c);
x1 = x1 + glutBitmapWidth(font,*c) + spacing;
}
}

如果我们想要绘制垂直的文本,可以如下实现:

void renderVerticalBitmapString(

            float x,
float y,
int bitmapHeight,
void *font,
char *string) { char *c;
int i; for (c=string,i=; *c != '\0'; i++,c++) { glRasterPos2f(x, y+bitmapHeight*i);
glutBitmapCharacter(font, *c);
}
}

变量bitmapHeight可以很容易计算得出,因为我们知道每个字体的最大高度,就是字体名的最后那串数字.例如GLUT_BITMAP_TIMES_ROMAN_10是占10个像素的高度.

最后一件事是,GLUT提供了另外一个函数来处理位图字体,就是glutBitMapLength函数,它可以以像素为单位计算一个字符串的长度.函数的返回值是字符串中字符的宽度总和.原型如下:

int glutBitmapLength(void *font, char *string);

font -  GLUT中的预定义字体之一,见上一节中列出的可选值

string - 我们想要知道字宽的字符串

[译]GLUT教程 - 位图和正交投影视图的更多相关文章

  1. [译]GLUT教程 - 位图字体

    Lighthouse3d.com >> GLUT Tutorial >> Fonts >> Bitmap Fonts 位图字体一般是二维字体.虽然我们会把它放到三维 ...

  2. [译]GLUT教程(目录)

    http://www.lighthouse3d.com/tutorials/glut-tutorial/ GLUT是OpenGL Utility Toolkit的意思.作者Mark J. Kilgar ...

  3. [译]GLUT教程 - 整合代码5

    Lighthouse3d.com >> GLUT Tutorial >> Extras >> The Code So Far V 该代码与位图字体的代码类似.区别是 ...

  4. [译]GLUT教程 - 渲染到子窗体

    Lighthouse3d.com >> GLUT Tutorial >> Subwindows >> Rendering to Subwindows 先回顾一下之前 ...

  5. [译]GLUT教程 - 整合代码6

    Lighthouse3d.com >> GLUT Tutorial >> Extras >> The Code So Far VI 下面代码以窗体模式启动.你可以在 ...

  6. [译]GLUT教程 - 游戏模式

    Lighthouse3d.com >> GLUT Tutorial >> Extras >> Game Mode 根据GLUT官网的说明,GLUT的游戏模式是为开启 ...

  7. [译]GLUT教程 - 笔划字体

    Lighthouse3d.com >> GLUT Tutorial >> Fonts >> Stroke Fonts 笔划字体是用线条生成的.跟位图字体相反,笔划字 ...

  8. [译]GLUT教程 - 整合代码4

    Lighthouse3d.com >> GLUT Tutorial >> Pop-up Menus >> The Code So Far IV 以下代码使用了位图字 ...

  9. [译]GLUT教程 - glutPostRedisplay函数

    Lighthouse3d.com >> GLUT Tutorial >> Avoiding the Idle Func >> glutPostRedisplay 直 ...

随机推荐

  1. 在apache2.4.6中配置虚拟主机支持web.py

    web.py 是一个简单好用的python web框架. (http://webpy.org/) apache httpd是一款开源配置简单的web容器. (http://apache.org/) 假 ...

  2. POJ3345 Bribing FIPA(树形DP)

    题意:有n个国家,贿赂它们都需要一定的代价,一个国家被贿赂了从属这个国家的国家也相当于被贿赂了,问贿赂至少k个国家的最少代价. 这些国家的从属关系形成一个森林,加个超级根连接,就是一棵树了,考虑用DP ...

  3. 关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-使用工厂创建代理(Using the ProxyFactoryObject to create AOP proxies)

    本文翻译自Spring.NET官方文档Version 1.3.2. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他人提供帮助. 侵删. 如果你正在为你的业务模型使用 ...

  4. sql索引从入门到精通(十亿行数据测试报告)

    原文:sql索引从入门到精通(十亿行数据测试报告) 导读部分 --------------------------------------------------------------------- ...

  5. 64位系统下powerdesigner15连接oracle odbc

    操作系统:win2008 64 Oracle版本:64位11g PowerDesigner版本:15.1 问题描述:因为PowerDesigner是32的程序,连接数据库会默认开启32位的ODBC,因 ...

  6. apache几种限制ip的方法

    参考文档来源:  http://jingyan.baidu.com/article/4b07be3c193d1648b380f3a9.html1.  禁止访问某些文件/目录增加Files选项来控制,比 ...

  7. #define,#undef宏学习

    1.预处理器 1.1预处理符号: __FILE__ :进行编译的源文件名字 __LINE__ :文件当前行的行号 __DATA__ :文件被编译的日期 __TIME__ :文件被编译的时间 __STD ...

  8. OpenGL变换【转】

    http://www.cnblogs.com/hefee/p/3811099.html OpenGL变换 概述 OpenGL变换矩阵 实例:GL_MODELVIEW矩阵 实例:GL_PROJECTIO ...

  9. C++ 模板应用 实现一个Queue 队列

    #include<iostream> using namespace std; template <typename T> class Queue { public: Queu ...

  10. JStorm的搭建文档

    1.下载jstorm的jar包 https://github.com/alibaba/jstorm/releases 2.解压jstorm的包 tar -xvf jstorm-2.4.0.tgz mv ...