OpenGL基础图形编程 - OpenGL辅助库的基本使用

来源:互联网 发布:斗鱼抢票软件作者qq 编辑:程序博客网 时间:2024/04/30 14:05
OpenGL是一个开放的系统,它是独立于任何窗口系统或操作系统的。尽管它包含了许多图形函数,但它却没有窗口函数,也没有从键盘和鼠标读取事件的函数,所以要初学者写出一个完整的图形程序是相当困难的。另外,OpenGL图形函数中只提供基本的几何原形:点、线、多边形,因此要创建基本的三维几何体如球、锥体等,也很不容易。而OpenGL辅助库就是为解决这些基本问题专门设计的,它提供了一些基本的窗口管理函数和三维图形绘制函数,能帮助初学者尽快进入OpenGL世界,掌握关键的三维图形技术,体会其中奇妙的乐趣。但是,对于复杂的应用,这些函数远远不够,只能作为参考。

6.1、辅助库函数分类
  这一节内容可以作为手册查阅,初学者不必深究。
  辅助库函数大致分为六类:

  6.1.1 窗口初始化和退出
  相关函数有三个,它们在第一章已提到,这里将详细介绍:

  void auxInitWindow(GLbyte *titleString)

  打开一个由auxInitDisplayMode()和auxInitPosition()指定的窗口。函数参数是窗口标题,窗口背景缺省颜色是RGBA下的黑色或颜色表(color_index)下的0号调色板的颜色。按下Escape键可以完成关掉窗口、结束程序、全部清屏三项功能。

  void auxInitDisplayMode(GLbitfield mask)

  设置窗口显示模式。基本模式有RGBA或颜色表、单或双缓存,也可指定其他附加模式:深度、模板或累积缓存(depth,stencil,and/or accumulation buffer)。参数mask是一组位标志的联合(取或),AUX_RGBA或AUX_INDEX、AUX_SINGLE或AUX_DOUBLE,以及其它有效标志AUX_DEPTH、AUX_STENCIL或AUX_ACCUM。

  void auxInitPosition(GLint x,GLint y,GLsizei width,GLsizei height)

  设置窗口位置及大小。参数(x, y)为窗口的左上角点的屏幕坐标,参数(width, height)为窗口的宽度和高度,单位为象素,缺省值为(0, 0, 100, 100)。

  6.1.2 窗口处理和事件输入
  当窗口创建后,且在进入主函数循环之前,应当登记以下列出的回调函数(callback function):

  void auxReshapeFunc(void(*function)(GLsizei,GLsizei))

  定义窗口改变时形状重定函数。参数function是一个函数指针,这个函数带有两个参数,即窗口改变后的新宽度和新高度。通常,function是glViewport(),显示裁减后的新尺寸,重定义投影矩阵,以便使投影后图像的比例与视点匹配,避免比例失调。若不调用auxReshapeFunc(),缺省重定物体形状的函数功能是调用一个二维的正射投影矩阵。运用辅助库,窗口将在每个事件改变后自动重新绘制。

  void auxKeyFunction(GLint key,void(*function)(void))

  定义键盘响应函数。参数function就是当按下key键时所调用的函数指针,辅助库为参数key定义了几个常量:AUX_0至AUX_9、AUX_A至AUX_Z、AUX_a至AUX_z、AUX_LEFT、AUX_RIGHT、AUX_UP、AUX_DOWN(方向键)、AUX_ESCAPE、AUX_SPACE或AUX_RETURN。

  void auxMouseFunc(GLint button,Glint mode,void(*function)(AUX_EVENTREC *))

  定义鼠标响应函数。参数function就是当鼠标以mode方式作用于button时所调用的函数。参数button有AUX_LEFTBUTTON、AUX_MIDDLEBUTTON或AUX_RIGHTBUTTON(以右手为标准)。参数mode代表鼠标触击状态,击中时为AUX_MOUSEDOWN,释放时为AUX_MOUSEUP。参数function必须带一个参数,它是指向结构AUX_EVENNTREC的指针。当函数auxMouseFunc()被调用时将为这个结构分配相应的内存。通常用法类似如下:

  void function(AUX_EVENTREC *event)
  {
    GLint x,y;
    x=event->data[AUX_MOUSEX];
    y=event->data[AUX_MOUSEY];
    ...
  }

  6.1.3 颜色表装入
  因为OpenGL本身没有窗口系统,所以依赖于窗口系统的颜色映射就没法装入颜色查找表。如果采用颜色表模式,就要用到辅助库提供的用RGB值定义的单个颜色索引函数:

  void auxSetOneColor(GLint index,GLfloat red,GLfloat green,GLfloat blue)

  设置自定义颜色的索引。参数index即索引号,参数red、green、blue分别为红、绿、蓝值,范围在(0~1)内。

  6.1.4 三维物体绘制
  每组三维物体包括两种形式:网状体(wire)和实心体(solid)。网状体没有平面法向,而实心体有,能进行光影计算,有光照时采用实心体模型。下面这些函数的 参数都是定义物体大小的,可以改变。

功能
函数
绘制球
void auxWireSphere(GLdouble radius)
void auxSolidSphere(GLdouble radius)
绘制立方体
void auxWireCube(GLdouble size)
void auxSolidCube(GLdouble size)
绘制长方体
void auxWireBox(GLdouble width,GLdouble height,GLdouble depth)
void auxSolidBox(GLdouble width,GLdouble height,GLdouble depth)
绘制环形圆纹面
void auxWireTorus(GLdouble innerRadius,GLdouble outerRadius)
void auxSolidTorus(GLdouble innerRadius,GLdouble outerRadius)
绘制圆柱
void auxWireCylinder(GLdouble radius,GLdouble height)
void auxSolidCylinder(GLdouble radius,GLdouble height)
绘制二十面体
void auxWireIcosahedron(GLdouble radius)
void auxSolidIcosahedron(GLdouble radius)
绘制八面体
void auxWireOctahedron(GLdouble radius)
void auxSolidOctahedron(GLdouble radius)
绘制四面体
void auxWireTetrahedron(GLdouble radius)
void auxSolidTetrahedron(GLdouble radius)
绘制十二面体
void auxWireDodecahedron(GLdouble radius)
void auxSolidDodecahedron(GLdouble radius)
绘制圆锥
void auxWireCone(GLdouble radius,GLdouble height)
void auxSolidCone(GLdouble radius,GLdouble height)
绘制茶壶
void auxWireTeapot(GLdouble size)
void aucSolidTeapot(GLdouble size)
表6-1

  以上物体均以各自中心为原点绘制,所有坐标都已单位化,可以缩放。

  6.1.5 背景过程管理

  void auxIdleFunc(void *func)

  定义空闲状态执行函数。参数func是一个指针,指向所要执行的函数功能。当它为零时,func执行无效。

  6.1.6 程序运行

  void auxMainLoop(void(*displayFunc)(void))

  定义场景绘制循环函数。displayFunc指针指向场景绘制函数。当窗口需要更新或场景发生改变时,程序便调用它所指的函数,重新绘制场景。

6.2、辅助库应用示例
  下面举一个辅助库的应用例子,testaux.c:

  例6-1 辅助库应用例程 testaux.c

  #include "glos.h"
  #include <GL/gl.h>
  #include <GL/glaux.h>

  void myinit(void);
  void CALLBACK myReshape(GLsizei w,GLsizei h);
  void CALLBACK display(void);

  void myinit(void)
  {
    glClearColor(0.0,0.0,0.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT);
  }

  void CALLBACK myReshape(GLsizei w,GLsizei h)
  {
    glViewport(0,0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if(w<=h)
      glOrtho(-1.5,1.5,-1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w,-10.0,10.0);
    else
      glOrtho(-1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w,-1.5,1.5,-10.0,10.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
  }

  void CALLBACK display(void)
  {
    glColor3f(1.0,1.0,0.0);
    auxWireSphere(1.0);
    glFlush();
  }

  void main(void)
  {
    auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
    auxInitPosition(0,0,500,500);
    auxInitWindow("AUX_SAMPLE");
    myinit();
    auxReshapeFunc(myReshape);
    auxMainLoop(display);
  }


图6-1 网状球体
  以上程序运行结果是在屏幕窗口内绘制一个黄色的网状球体,这个程序充分体现了辅助库的基本应用方法。
  首先,在主函数中用辅助库函数定义一个窗口auxInitWindow(),然后初始化颜色myinit(),这些在第一章中已说明。接下来是两个十分重要的函数auxReshapeFunc()和auxMainLoop(),参数都是一个函数指针,指向的都是回调函数(回调函数定义用CALLBACK说明)。
  前者是窗口形状重定函数,参数指针指向函数myReshape(),它的两个参数就是窗口的新宽度和新高度。然后用glViewport(0, 0, w, h)重定视口,并且在新视口内重新定义投影矩阵,

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  if(w<=h)
    glOrtho(-1.5,1.5,-1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w,-10.0,10.0);
  else
    glOrtho(-1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w,-1.5,1.5,-10.0,10.0);


  即先用glMatrixMode()说明当前矩阵操作与投影有关GL_PROJECTION,再用glLoadIdentity()将矩阵清为单位矩阵,避免受其它矩阵操作的干扰;然后调用glOrtho()对物体进行正射投影,并且用判断语句给出了两种情况,使投影后图像的比例与视点匹配,避免比例失调。
  再下来调用glMatrixMode()将矩阵操作改为对观察物体有关的方式GL_MODELVIEW,同样用glLoadIdentity()清矩阵。后者是主函数循环函数,参数指针指向函数display(),即绘制物体。当窗口需要更新或物体发生改变时,程序便调用它重新绘制。以上例子是辅助库的最基本应用,复杂的应用将在后续的章节中详细介绍。