可视化随着微电子技术、光电子技术的发展,计算机的发展已经进入移动时代,因此嵌入式系统的应用领域越来越广泛并且已经成为科学技术发展的新热点。
嵌入式三维地理信息系统是运行在嵌入式硬件平台上的地理信息系统,而地形的三维可视化是三维地形信息系统中最重要的部分。OpenGLEmbedded Subset(OpenGLES)的出现为在嵌入式系统上绘制具有真实感的三维地形提供了极大的便利。
1.嵌入式系统与OpenGLES
1.1嵌入式系统
嵌入式系统(embedded system)是指以应用为中心,计算机技术为基础,并且软硬件可裁剪,适用于应用系统对功能、可靠性、成本、体积、功耗等有严格要求的专用计算机系统,主要由硬件环境、嵌入式操作系统及应用软件系统等组成。嵌入式系统是先进的计算机技术、半导体技术和电子技术和各个行业的具体应用相结合的产物。
嵌入式操作系统是一种实时、支持嵌入式系统应用的操作系统软件,核心通常要求很小,因为硬件的ROM容量有限。一般情况下,它可以分成两类:一类是面向控制、通信等领域的实时操作系统;另一类是面向消费电子产品的非实时操作系统.这类产品包括个人数据助理(PDA)、移动电话、机顶盒等,如Windows CE、PalmOS、嵌入式Linux和EPOC等。本文以Windows CE为基础,结合嵌入式系统3D图形绘制编程接口OpenGLES进行研究。
1.2 OpenGLES
OpenGLES是为嵌入式系统而开发的3D图形绘制编程接口,是在OpenGL上发展出来的,针对嵌入式系统所制定的3D绘图API,能够使3D绘图在不同的移动设备或是嵌入式系统上方便地使用。
OpenGLES主要功能包括:模型绘制、模型变换、颜色模式、光照和材质设置、纹理映射、双缓存动画等。
2.地形三维可视化基础
2.1数字高程模型
地形三维可视化过程中最重要的工作就是获取地形的三维坐标数据信息,并通过透视投影变换,将其转换为屏幕二维坐标。进而显示在屏幕上。目前描述地形一般通过数字高程模型(Digital Elevation Model,DEM)来实现。从数学的角度,高程模型是高程Z关于平面坐标J,r2个自变量的连续函数,数字高程模型只是它的一个有限的离散表示。
DEM格网是最常见的数字地形模型形式,其数据组织可分为两种类型:规则格网(GRID)和不规则三角网(TIN)。GRID型DEM由于是按固定采样间隔、按矩阵排列的数据形式,其主体数据只需记录或存储每个节点的高程即可,存储结构简单,数据处理速度快,因此GRID数据结构适用于嵌入式系统。而不规则三角网TIN不仅要存储每个网点的高程,还要存储其平面的坐标、网点的拓扑关系、三角形及邻接三角形等信息,数据结构比较复杂,处理速度比较慢,不适合在嵌入式系统中应用。
2.2地形三维可视化及实时显示
在这个过程中,首先需要对地形数据进行投影变换,为了逼真地反映地形表面明暗和颜色的变换,需要设置场景的光源位置和光照方向,并且计算节点或者表面的法向,据此来获得屏幕上每个像素的颜色和灰度。此外,还需要对场景进行消隐和裁剪。消隐是为了能够真实表现物体的深度关系;裁剪则是让当前视窗之外的物体不显示,提高程序的运行效率。
在嵌入式地形三维实时显示过程中,为了进一步提高运行效率,往往需要对DEM数据进行一定的简化处理,通常采用一种层次细节(LevelofDetails,LoD)的简化方法。
3.具体实现
3.1开发环境
开发平台选择Windows XP操作系统下的嵌入式集成开发工具EVC软件,它包含了在不同硬件平台下使用SDK和仿真器(PC环境下模拟掌上电脑硬件环境的软件),具体设置如下:
(1)MicrosoftActiveSync;
(2)EmbeddedVisuaIC++4.0;
(3)EmbeddedVisuaIC++4.0ServicePACk4;
(4)MicrosoftPocketPC 2003SDK;
(5)WindowsMobile 2003 secondeditionemula-torimages forpocketPC;
(6)OpenGLESlmplementation。
MicrosoftActiveSync用来实现PC机和WindowsMobile设备的连接,使EVC++4.0编写的应用程序可以同步地在Windows Mobile设备上实现。EVC和Service Pack 4是Microsoft公司推出的Win CE程序可视化开发工具。Microsoft PocketPC 2003SDK是PC机上开发Win CE应用程序的模拟环境,Windows Mobile 2003 second edition emulatorimages forpocket-PC为模拟环境的中文环境。
OpenGL ES Implementation为嵌入式系统上开发三维地形的图形库,需要下载安装,下载解压后为bin文件夹,其安装步骤如下:
(1)找到模拟器安装目录,一般为Windows CEToolswce420POCKETPC 2003(简称/sdk/);
(2)将/bin/include目录下的文件拷贝到/sdk/include/Armv4和sdk/include/Emulator2个目录下;
(3)将/bin/emu/debug/目录下的除libGLES CM.dll的其他文件拷贝到/sdK/lib/emulator目录下;
(4)将bin/arm/release目录下的除libGLES CM.dll的其他文件拷贝到/sdk/lib/Armv4目录下;
(5)需要将/bin/emu/debug/目录下的libGLES CM.dll拷贝到模拟器的/Windows目录下;
(6)第(4)步只是在模拟器的debug环境下,若要在真机上需要装/bin/arm/release/目录下的libGLES CM CM.dll拷贝到真机上。
3.2总体设计
使用Win CE应用程序开发工具EVC++4.0,结合OpenGLES嵌入式图形开发库,开发移动平台三维地形的具体设计流程如图1所示,其设计思路如下:

(1)调入(.DEM)文件格式的网格数据;
(2)利用网格数据生成三维地形模型,并对其进行简化,简化的同时可以实时显示简化后的地形模型,且自动存储简化后的数据文件,以便以后调用;
(3)对其设置网格、分层设色、投影变换和视口变换进行三维地形显示;
(4)采用三维图形处理技术对其设置消隐、光照、纹理贴图、天空盒以达到真实感效果;
(5)利用移动平台上方向键设置旋转、前进、后退等交互功能,或者通过对路径的设置,从而使用户能够在场景中随意漫游,在任意位置、各个角度观察三维地形。
3.3地形建模
本文利用LoD简化在嵌入式系统上实现地形建模,当观察视点的位置和视向发生变化时,根据变化后的位置和视向对每个地形节点进行可见性判断和绘制分辨率的计算,让进入新的视线范围内的节点地形参与地形绘制,同时让那些不在新的视线范围内的地形节点不再参与三维地形的绘制,这样当观察视点发生变化后,视线内的地形也实时发生变化。
此外,要让三维地形适当地显示出来,还需进行投影变换和视口变换。投影变换是生成三维模型的重要基础,一般分为透视投影和正射投影,为增加模型的真实感,采用了透视投影方式。视口是指显示屏幕中的矩形区域,视口变换的目的是将三维空间坐标映射为显示屏幕上的二维平面坐标。
3.4三维地形的真实感
对最后输入的三维地形进行纹理映射和添加天空盒是生成遇真三维地形的必要途径,应用OpenGLES提供的纹理映射技术可把从真实世界中拍摄到的地形的表面细节,采用贴图的方式贴到三维地形的表面,从而使渲染后得到的三维地形模型更贴近真实世界中的地形,作为贴图的纹理可以是正射影像或者数字摄影相片。
用OpenGLES进行纹理映射,首先需要定义纹理内容,包括纹理数据指针、纹理尺寸、类别(灰度或彩色)等,然后设置纹理映射到三维表面的方式,如纹理滤波、重复、颜色融合等;最后定义三维模型顶点的纹理坐标与几何坐标,绘制场景。
天空盒的生成采用了立方体天空盒,通过在立方体盒子的5个不同面上贴上不同的天空纹理来达到逼真的模拟效果。用于天空背景的图片有特殊的要求。四面图的边与顶图的边相连,四面图前后相连。
3.5漫游功能
三维地形的漫游是通过操作方向键模拟在场景中的行走。实现第一人称的漫游基本上有两种方法:移动场景和移动眼坐标(视点坐标)。移动场景相对来说比较简单,只要使用OpenGLES提供的glTranslatef与glRotatef方法相配合即可,但一般只在简单场景和单角色的情况下使用,而且角色的各种计算(如实时坐标、碰撞)不好实现,所以在这里没有使用,而是采取移动观察视点坐标的方法。
移动观察视点坐标的方法非常灵活,它对场景和角色的状态未做任何操作,一般只要设置成跟随主角色移动旋转即可实现第一人称视角视觉效果。通过使用OpenGLES提供的glLookAt方法来实现此功能。其实现代码如下:
首先定义宏:
#define KEY_DOWN(Vk-CODe)((GetAsyncK-eyState(vk_code)&
0x8000)?1:0)
再加入以下代码:
floatspeed=0.2f
//向左向右转
if(KEY-DOWN(VK-SHIFT))speed=speed*4;
if(KEY_DOWN(VK-LEFT)g-Angle-=speed*2;
if(KEY-DOWN(VK-RIGHT))g_Angle+=speed*2;
rad XZ:float(3/13149*g-Angle/180.00;
*角度转化为弧度值,转化公式为:rad=ang*Pl/180。
其中rad表示弧度值,ang表示角度值。g-Angle即为观察视点的视线角度。
if(KEY_DOWN(VK-UP))
(Io.z+=sin(rad_xz)*speed;
Io.x+=cos(rad_xz)*speed;
}//观察视点前移
if(KEY_DOWN(VK-DOWN))
{Io.Z-=sin(rad xz)*speed;
Io.X-=COS(rad-xz)*speed;
}//观察视点后移
//边界检测
if(1o.x<0)工 o.x&rsqu




