《电子技术应用》
您所在的位置:首页 > 嵌入式技术 > 设计应用 > 基于OpenGL构建的飞行仿真系统
基于OpenGL构建的飞行仿真系统
赵 颖1,唐绍军2,李中华3
总后勤部后勤科学研究所,北京100071
摘要: 介绍了在Windows系统平台及Visual C++ 6.0的MFC基础类库环境下,采用OpenGL技术与串口通信技术实现的飞行仿真系统的设计思想与程序实现方法。
Abstract:
Key words :

摘  要: 介绍了在Windows系统平台及Visual C++ 6.0的MFC基础类库环境下,采用OpenGL技术与串口通信技术实现的飞行仿真系统的设计思想与程序实现方法。
关键词: 虚拟现实  OpenGL  六维鼠标  串行口

  虚拟现实是一种创建和体验虚拟世界的计算机系统。利用虚拟现实技术,计算机可以产生一个三维的虚拟环境,通过人的视觉、触觉等作用于人[1]。 用户以客观世界的实际动作或以人类熟悉的方式操作虚拟系统,从而实现立体交互,使人产生身临其境的感觉。虚拟现实系统一般由输入设备、输出设备、虚拟环境生成器和高性能的计算机系统四大部分构成。
  目前,OpenGL在虚拟现实领域是功能较强,最具发展前途的实现工具。OpenGL是美国高级图形和高性能计算机系统公司(SGI)所开发的三维图形库,在当前已经成为事实上的高性能图形和交互式视景处理的标准[2]。OpenGL是一个独立的工作平台,用它编写的程序可以在不同的硬件平台(如工作站或个人微机)中使用,也可以在多种操作系统(如Windows系列、OS/2等)下运行。
  经过近几年来的发展,虚拟现实技术及设备被很多领域应用,而飞行仿真是最重要的应用领域之一。本文所研究的飞行仿真系统采用新型六维控制器(六自由度鼠标)作为输入设备,监视器作为输出设备,以OpenGL作虚拟环境生成器,构成一套高性能计算机处理系统来实现高度仿真的飞行模拟器运动。
1  构建应用程序框架
  应用Visual C++ 6.0建立一个基于MFC的应用程序框架,并将VC库文件opengl32.lib、glu32.lib和glaux.lib包含在应用程序中。
  为使OpenGL函数库的调用有效,首先应设置渲染窗口。OpenGL的渲染处理完全不同于Windows的图形设备接口GDI。要使Windows的窗口格式为OpenGL所接受,需进行下列设置。
1.1 建立图形操作描述表
  OpenGL作图窗口必须设置为WM_CLIPSIBLINGS和WM_CLIPCHILDREN风格。
  在Windows98/2000系统下,窗口程序首先要处理设备描述表(Device Contexts,DC),它包括若干在窗口上如何显示图形的信息。而在OpenGL程序中,必须创建图形操作描述表(Rending Context,RC),这是DC中专用于OpenGL的一种。但是RC不同于其他的DC,它只需要一个句柄就可以任意调用OpenGL函数,而其他DC调用每个GDI函数时都需要一个句柄。
  使用时先通过wglCreateContext()函数创建一个RC,然后调用wglMakeCurrent()函数启动它,就可在所定义的窗口内调用OpenGL函数绘制飞行器了。
  m_pDC=new CClientDC(this);
  hrc=wglCreateContext(m_pDC->GetSafeHdc( ));
  wglMakeCurrent(m_pDC->GetSafeHdc( ),hrc);
1.2 设置像素格式
  像素格式指定设备的绘图属性,包括绘图界面的颜色表示模式、颜色位数、累积缓存区、深度缓存区和模板缓存区的位数。每个OpenGL显示设备都支持某一特定的像素格式。像素格式用PIXELFORMATDESCRIPTOR结构来表示,通过设置这一结构的成员值使之支持OpenGL。建立了图形操作描述表并初始化PIXELFORMATDESCRIPTOR结构后,应以此结构为变量调用ChoosePixelFormat( )函数为设备描述表选择像素格式,最后调用SetPixelFormat( )将其设置为当前像素格式。
  int pixelformat;
  pixelformat=ChoosePixelFormat(m_pDC->GetSafeHdc( ),&pfd);
  SetPixelFormat(m_pDC->GetSafeHdc( ),pixelformat,&pfd);
2  绘制场景
2.1 准备工作
  开始绘制场景之前,需要用背景颜色刷新显存。飞行器在天空的背景中飞行,因此应将清除颜色缓冲区的颜色设为淡蓝色,然后刷新颜色缓冲区和深度缓冲区。
  glClearColor(0.75,0.75,1.0,1.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  准备工作还要考虑计算机屏幕是二维的,要用它显示逼真的三维物体就要用到图形变换技术。同时程序还要保证,当用户随意改变窗口大小时,飞行器不会变形失真。因此需要定义初始的坐标变换。视图类的OnSize事件对这些问题进行处理。
2.2 设置光照效果
  创建三维立体的场景时,添加光线效果对于飞行器的真实感非常重要。OpenGL的光照模型将光照成分划分为四个独立的部分:发射光、环境光、散射光和镜面反射光。OpenGL独立计算这四种光照成分,然后将其结果叠加,从而得到最终的效果。
  设置光照应分二步进行。首先使用glLightfv( )函数设置光源的属性和值,创建系统光源。本文定义了四个GLfloat数组sunposition、suncolor、sunambient和sunspecular,分别作为光源位置、光源的散射光亮度、环境光亮度和镜面反射光亮度的属性值。然后用glEnable(GL_LIGHTING)启动OpenGL的光照处理功能。再用glEnable(GL_LIGHT0)打开设置的光源。
3  绘制飞行器
  飞行器是一个较为复杂的三维图形对象,它需要使用二次曲面和多边形镶嵌工具来创作,并通过OpenGL的纹理映射技术给飞行器穿上漂亮的外衣。
3.1 飞行器构造原理
  按照组成飞行器对象的几何形体的特点,可将飞行器构造用二次曲面(quadric)和多边形(polygon)表示。具体来说,机头用锥形表示;机体是柱形;尾部的发动机用锥形的柱体来表示;飞行器的顶棚可以用一个拉长的球体来表示,把球体的透明度设为0.65,使之具有玻璃的效果,这些部分是二次曲面。例如机体绘制命令为:
  gluCylinder(quadric,0.25,0.25,3.5,20,2);
  而机翼和机尾的各个部分都是多边形的,应使用多边形镶嵌工具来绘制。例如机尾绘制命令为:
  gluTessBeginPolygon(tess,NULL);
  gluTessBeginContour(tess);
  for (i=0;i<6;i ++)
     gluTessVertex(tess,tail[i],tail[i]);
  gluTessEndContour(tess);
  gluTessEndPolygon(tess);
3.2 程序实现方法
  程序实现应用了显示列表技术。OpenGL的显示列表是事先存储的用于稍后执行的一组OpenGL命令序列。分析了飞行器的几何形体构造、设置完绘制命令并进行纹理贴图美化飞行器外表后,就可将各个部分的构造程序代码编辑到显示列表里存储起来了。
  F16Body=glGenLists(1);
   glNewList(F16Body,GL_COMPILE);
  最后调用函数glEndList( ),标志一个显示列表的结束。
  在视图类的DrawScene( )事件的适当位置用函数glCall-List(F16Body)调用显示列表,从而按照预先定义的顺序执行飞行器模型的绘制。
4  六维鼠标控制的飞行仿真系统总体设计
4.1 六维鼠标的工作原理
  现实中飞行器是可以进行三维移动以及三维旋转运动的,因此在飞行仿真系统中就需要一种可以实现上述运动模式的输入控制设备。这里选择了一种新型并联结构六维控制器,即六维鼠标。
  该六维鼠标基于力控制原理,通过集成A/D转换器的动态应变仪与计算机的COM1口(串行口1)相连,采用串行通信机制。操作者握住鼠标,向所要移动或转动的方向用力,鼠标将受到的六维力传递到内部的微型六维力敏感元件,接着通过鼠标内部机制生成与该力成正比的电压信号,并将电压信号放大后采集进计算机,利用力Jacobian矩阵求出鼠标受到的空间作用力情况[3]。六维鼠标的控制系统软件实现将三个力分量分别乘以某个大于零的系数,生成飞行器作空间直线运动的位移分量,从而控制仿真系统中飞行器的平移运动;将三个力矩分量经过一定算法的变换后产生飞行器绕X、Y、Z三个坐标轴转动的角位移,从而控制飞行器的旋转运动, 在算法中应用到了六维鼠标的标定矩阵G6×6。具体变换算法请查阅文献3。图1描述了六维鼠标的工作原理流程。

4.2 仿真系统总体设计
  六维鼠标和计算机之间采用串口通信,所以在程序设计中选用了MSComm控件。该控件通过串行端口传送和接收数据,从而为应用程序实现串行通信功能[4]。MSComm控件将通信的大部分底层操作都封装在控件内部,应用程序只需获取和设置相应的控件属性即可,简化了编程的复杂度。在Visual C++ 6.0中使用该控件的基本流程如图2所示。


  本仿真系统中当控件插入工程后,应将串口初始化及打开命令放在视图类的OnCreate()事件中。在应用程序建立时就打开串口,准备接收鼠标数据。
  应用MSComm控件的OnComm( )事件作为对六维鼠标输入数据的响应事件,并在事件处理中实现对飞行器的运动控制。首先检测串口的GetCommEvent( )事件,如果该事件返回值为2,表示接收缓冲区内的字符数达到Rthreshold值,发生接收事件(comEvReceive)。接下来编写接收数据的过程,实现将鼠标传输的数据转化为三个平移分量(Xp、Yp、Zp)和三个旋转分量(Xr、Yr、Zr)。将Xp、Yp、Zp、Xr、Yr、Zr六个控制变量传递给DrawScene( )函数,在飞行器绘制之前修改视景坐标系,从而控制飞行器的运动。
  glTranslatef(Xp,0.0f,0.0f);
  glTranslatef(0.0f,Yp/10,0.0f);
  glTranslatef(0.0f,0.0f,-Zp);
  glRotated(Xr-37,1.0,0.0,0.0);
  glRotated(Yr-7,0.0,1.0,0.0);
  glRotated(Zr-2,0.0,0.0,1.0);
  glCallList(F16Body);
        系统总体实现流程如图3所示。

5  结  论
  本文所开发的飞行器仿真系统使用Visual C++ 6.0作为软件平台,应用OpenGL来开发具有六维运动能力的飞行模拟器和高度真实感的三维地形,以六维鼠标作为飞行器的控制输入设备,通过串行通信机制控制计算机中的仿真系统。用户通过给六维鼠标施加不同方向、不同大小的力来自由控制系统中飞行模拟器的运动,实现飞行器在虚拟地形环境中的三维移动和三维转动,从而实现对真实世界中飞行器运动的仿真。
参考文献
1   毛玉姣,王梅,陈远.虚拟现实技术及其应用.图书情报知识,1997;(4)
2   戴达强,姜晓彤,朱欣华.OpenGL在图形仿真系统中的应用.现代电子技术,2001;(9)
3   赵现朝,金振林.六维鼠标中力矩与转角转换的一种新方法.  计算机工程,2002;(7)
4   李现勇.Visual C++串口通信技术与工程实践.北京:人民邮电出版社,2002

此内容为AET网站原创,未经授权禁止转载。