三维校园电子地图(上)
访问734
作者:李纳璺  陈金龙 阮方舟
 
1引言
    随着计算机技术,特别是计算机图形学、三维仿真技术以及虚拟现实技术的飞速发展,传统的
二维电子地图被注入了新的活力,三维电子地图正成为电子地图发展的一个重要方向。传统的二维
电子地图只能以图形和符号的方式来呈现一张地图,这种方式往往不能直观清晰的表示出地图所在
位置的地理环境;采用三维电子地图的方式,建立场景的仿真模型,把现实场景进行虚拟再现,真实、互动、情节化的特点是虚拟现实技术独特的魅力所在。
  如何设计一个仿真度高,并且具备虚拟漫游和智能导航的三维地图引擎,成为三维电子地图研究领域的一个热点问题。本文研究的设计的三维电子地图引擎系统,设计了模型动态加载接口,并具备智能导航和虚拟漫游引擎,实现了三维校园仿真电子地图。它为校园规划建设、游客观光导航、学校对外宣传等方面提供了一个智能化的平台,为广大系统用户提供了极大的便利。开展虚拟校园三维地图仿真引擎系统及相关课题的研究适应了信息社会发展的趋势,具有重要的理论和现实意义。
    本文对从DirectX技术着手,采用Microsoft Visual C#编程语言结合三维图形开发包(Managed DirectX SDK August 2007)在框架中构建的三维校园电子地图程序。该程序实现了桂林电子科技大学的(东区)的三维校园电子地图的功能。除此之外,在可视化的基础上实现了一些虚拟现实的交互操作和空间分析,如:校园景物的查看、校园路径导航、三维动态漫游校园等;给需要了解桂林电子科技大学校园地理信息的用户提供了极大方便。
2 本课题研究的内容
    本课题是一个使用Managed DirectX的三维图形技术实现的一个三维校园电子地图程序,该程序是在框架下建立完成,开发语言为当今最流行的高级语言Microsoft Visual C#。它是以桂林电子科技大学东校区为实景,进行了校园虚拟仿真,建立了具备观光浏览与智能导航为一体的多媒体三维校园电子地图程序。
    本课题主要是研究了三维建模技术在程序中的导入技术、三维模型的优化、虚拟现实技术、Floyd算法实现的智能导航技术、Alpha混合与Alpha测试技术、三维场景中的光照技术、XML技术、用户交互控件技术等等。这些技术将全部应用到三维校园电子地图程序当中,最终展示出集视觉、听觉、用户智能交互于一体的校园仿真三维地图。
开发环境与相关技术简介
3.1 Managed DirectX与托管代码版DirectX 9.0语言支持
(1) Managed DirectX
    DirectX 是一系列低级的应用程序接口(APIs),它用于创建游戏和其他高执行效率的多媒体程序。它包括对高效的2D3D图形、音效和音乐、输入设备、力反馈设备、多媒体流和多人游戏的网络通信程序。三维校园电子地图程序的三维环境漫游引擎的构建就是使用Managed DirectX 9.0的图形
处理技术来完成的。
(2) 托管代码版DirectX 9.0语言支持
    DirectX 9.0下,开发者在使用托管代码的时候,能够利用DirectX的多媒体功能和硬件加速。托管代码版DirectX 9.0允许访问大多数原始的非托管DirectX功能。下面是被DirectX 9.0DirectX 9.0 SDK支持的托管代码语言:
Microsoft Visual C#
Microsoft Visual Basic .NET
Microsoft Visual C++
Microsoft JScript .NET
    在三维校园电子地图程序中,采用的是Microsoft Visual C# 2.0 Microsoft DirectX Software Development Kit(SDK) August2007来开发。
(3) Managed DirectX包含的组件
    托管代码版DirectX 9.0 由以下主要组件构成。
(1) Direct3D Graphics 提供了一个单一的API,你能使用它进行3-D图形编程。
(2) DirectDraw 提供直接的低级访问显存和高速渲染
(3) DirectInput 提供对于多种输入设备的支持,包括对力反馈技术的完全支持。
(4) DirectPlay 提供多人网络游戏的支持。
(5) DirectSound 提供播放和捕捉预录制数码采样的支持。
(6) Audio Video Playback 允许回放和简单控制音频/视频媒体。
(4) Managed DirectX的优点
    通过消除COM 组件对象模型的互通层,托管代码版DirectX 9.0改善了执行性能。托管代码能减少代码体积和提升工作效率。继承于强大易用的Microsoft .NET Framework 公共类型的接口更加直观。托管代码也把你从处理很多内存管理的任务中解放了,这些任务比如释放对象。
    Managed DirectX还提供了简单的3D程序框架,三维校园电子地图就是基于这个框架而开发的一个3D应用程序。使用Managed DirectX很大程度上减少了繁重的初始化操作。由于代码运行于  Microsoft .NET 虚拟机之上,开发的语言为Microsoft Visual C# 所以程序能够自动回收垃圾,避免了内存的泄露,还降低了代码复杂度,便于Web接口的开发。
3.2三维坐标系与几何图形学
    在使用DirectX开发三维校园电子地图程序之前,首先要对3D图形学的数学基础有一定的了解,根据三维校园电子地图程序的需求,需要掌握以下几个方面的知识点:
(1) 向量以及向量的运算;(2) 3D坐标系;(3) 面和顶点法线;(4) 3D物体的构成。
(由于篇幅有限,加上难度不大,以上4点在此不作详细介绍。关于Floyd最短路径算法原理,Alpha混合与测试原理,三维场景中的光照技术类型请读者参考相关书籍)
4  系统总体设计
    三维校园电子地图程序是把桂林电子科技大学东区的校园实景虚拟再现,除能够实现普通地图的功能以外,还能够进行三维的景点观光和智能路径导航等功能。系统总体开发流程框架如图4-1所示:
4-1 系统总体开发流程框架
    构建一个三维校园电子地图系统需要按照以下几个关键步骤来进行程序的开发:
(1) 数据采集:获取校园的相关建筑数据以及地理环境信息;
(2) 平面图制作:从获取的相关数据中提取有用信息,建立校园二维平面图;
(3) 三维模型的建立:建立校园场景中的建筑模型、场景小品模型、天空环境模型和地形模型等;
(4) 开发漫游导航引擎:使用程序来实现模型导入、三维场景的漫游、导航功能。
    三维校园电子地图漫游导航引擎作为该项目的核心部分,它主要实现的目标是:实现将3ds Max建立的模型导入引擎,把所有模型组合成一个校园整体,导入音乐,加载天空、地形以及环境小品等对象,构建成一个集音乐与用户交互的三维校园互动程序。将更加直观的把整个校园场景展示出来,以便于该软件的使用者迅速了解桂林电子科技大学(东区)校园的地理信息。
4.1 相关数据的采集
(重点说明:作为学习或做Demo版,通过实地和GOOGLE卫星图获题材是一种十分可取的方法)
    在开发三维校园电子地图之前,首先要对校园的各方面数据进行收集,由于大量的建筑数据以及校园平面景观布局图纸可以从校方直接获取,也可以通过实地取材和互联网资源来获取相关数据(我们的数据是采取此法)。
    校园建筑的模型比例数据、贴图数据、布局位置全部是通过实地取材得来,由于学校东区面积比较大,建筑复杂多样,导致数据采集工作量很大,用了近两个星期,使用数码相机在校园各个角落获取数码照片近10000张,将校园所有景观囊括在内。建筑轮廓基本是从高层楼顶拍摄,然后通过照片的对比和组合得到建筑的实际外形和轮廓数据,通过互联网的GOOGLE卫星图获取建筑之间的比例数据以及平面布局数据,通过照片的剪切获取景物的纹理贴图数据。
4.2 二维平面图的制作
    校园二维平面图的制作在三维校园电子地图的开发过程中是相当重要的一个环节,二维平面图制作的好坏直接影响到三维立体图的效果。因为三维地图的建模是完全基于二维平面图而建立的,如果二维平面图的比例不正确,就不可能制作出精确的三维地图。制作二维平面图的还有个作用,就是生成导航引擎程序的小地图导航地图功能。可见二维平面图的制作必须准确无误。
    为了控制好二维平面图的比例和相关建筑的位置精确,本系统使用了Google卫星照片来做底图作为二维平面图的绘制参考。然后再使用AutoCAD 2007来绘制线条,这样便能达到精确绘制的目的。
底图是通过Google卫星照片拼接而成,首先在电脑上安装Google_。在搜索框中输入桂林电子科技大学的位置:25°17'5.05"N110°19'53.89"E以获取校园的卫星照片。为了得到清晰的底图,获取图片是采取分次获取,然后使用Photoshop合并成一张完整的桂电东区校园底图。如图4-2所示:
4-2 桂林电子科技大学(东区)卫星图
4.2.1建筑平面框图
获得了校园的平面底图GuetMap.jpg以后,将它导入进AutoCAD 2007作为外部参照的地图,用CAD的直线和曲线绘制工具按照底图建筑的轮廓绘制出外形,就得到一张CAD导出平面图guet.dwg文件。该文件的最终效果如图4-3所示:
4-3 校园平面图
    有了这张平面地图,就能够使用3DMAX导入*.dwg文件作为底图参照,然后绘制出等比例的校园3D模型。
4.3 三维模型的建立(建筑模型和环境小品模型的建立在此不作介绍)
    地形模型建立:桂林电子科技大学整个东区校园的地形样式比较丰富,由山坡、河流、以及高低不同的坡面,这个地形的模型制作加大了难度。在校园东区地形的创作中,我把整个学校当作一个区域,按照CAD地图建立一个大平面,然后在这个大平面上切割出许许多多个小面,再通过多边形修改器来分区修改这些小面。在地形中,比较矮小的坡度(如:路边沿等)则不进行3D建模,而是使用贴图取而代之,这样将会最大程度上减小程序的开销。在实时虚拟系统中,它们应该使用尽可能少的面,获得尽可能少的面的方法是在建立模型时使用合适的方式,当把贴图赋给实时模型时,也应该使用最少的面。所以这类模型在建立时主要用二维的模型结合透明贴图来创造出三维的模型效果,即用贴图来代替细节模型。得出高低不同的坡面以及河流等模型。最终完成的地形图如图4-4所示:
          4-4 地形模型
4.4 三维漫游导航引擎的构建
    创建三维校园电子地图引擎系统是使用C#语言结合Microsoft DirectX SDK来完成的,是基于Microsoft DirectX SDK Sample Framework来建立引擎框架,调用了Microsoft 为我们提供的类库。这些已经完成公用类全部放在 ..\Microsoft DirectX SDK (August 2007\Samples\Managed
\Common文件里面,创建三维校园电子地图程序的时候需要将这些公用类包含到该项目当中,使用这个框架相当于为引擎提供了一个快速开发3D程序的一个空框架,在这个框架中创建三维校园漫游导航的3D程序。为三维校园电子地图程序提供了丰富可利用的3D程序接口。引擎总体框架如图4-5所示。
4-5 引擎总体框架
4.4.1 三维引擎的设计目标
    该三维漫游导航引擎主要具备以下功能:
(1) 能对整个校园模型进行全局俯视以及任意视角的观察,以便让用户更加全面的了解校园每一处的地理信息;
(2) 能够让用户自定义选择所需要加载的三维模型,以便适应显卡配置较低的用户,通过读写XML文件来保存用户的配置信息;
(3) 能够设置不同的分辨率,以满足用户的需求;
(4) 采用FLOYD算法计算校园每两个景点的最短路径,实现校园每一个景观的智能导航功能;
(5) 在导航模式中,实现小地图标示位置功能,让用户快速的了解自己所在校园的具体位置;
(6) 实现用户控制摄影机的移动功能,并且能控制移动的速度;
(7) 实现三维漫游场景的音乐导入,使三维校园程序效果更加丰富;
(8) 实现光照效果,使得场景模型更加富有层次感。
4.4.2 三维地图的程序引擎的框架介绍
    三维校园电子地图的漫游导航引擎是使用Microsoft Visual Studio 2005来进行编码,该项目工程中包含了以下的文件列:
(1) common文件夹:里面包含了Microsoft DirectX SDK Sample Framework的所有类库;
(2) UI文件夹:包含了用户控件的压缩纹理,以及用户控件的一些信息;
(3) Main.cs文件:程序的主入口;
(4) Campus3D.cs文件:控制整个引擎;
(5) BaseLevel.cs文件:层级的基类;
(6) Level.cs文件:控制主层操作级;
(7) Level1.cs文件:控制主层级模型加载;
(8) LoadingLevel.cs文件:读取模型素材层级;
(9) MenuLevel.cs文件:控制菜单层级;
(10) OptionLevel.cs文件:控制配置层级;
(11) MaxObject.cs文件:控制模型对象;
(12) HUD3D.cs文件:控制HUD模型对象;
(13) Background.cs文件:显示背景图片;
(14) PicShow.cs文件:显示小地图;
(15) PointShow.cs文件:显示提示点;
(16) Floyd.cs文件:实现最短路径算法;
(17) Mesh.cs文件:实现X文件加载;
(18) Music.cs文件:实现音乐的加载;
(19) Sound.cs文件:实现音效的加载。
(20) GuetRes文件夹:包含了所有模型的X文件、纹理贴图文件、声音文件、背景图片文件、XML用户配置文件以及场景元素文件,用于存放引擎的所有资源。
4.4.3 引擎的主入口
    Main.cs文件包含了Project类,该类继承了DirectX SDK Sample Framework的两个IFrameworkCallback, IDeviceCreation类,是整个三维校园电子地图程序的入口。主要负责初始化程序中所需要的设备以及处理程序的所有消息,处理3D程序循环体中负责更新程序物体和渲染物体的方法,这两个方法分别是:OnFrameMove()OnFrameRender()。下面对这主要函数的功能做简单的介绍:
(1) OnFrameMove()
    该函数在任何帧发生之前调用,根据程序时间对场景(例如,动画)的位置进行更新。
(2) OnFrameRender()
    绘制场景,在调用返回后DirectX将交换链中的下一个缓冲区的内容显示在屏幕上。
(3) OnCreateDevice()
    该函数用于创建设备,实例化Campus3D类,并且设置层级的光照效果和透明贴图。
(4) IntPtr OnMsgProc()
    处理引擎的控制消息,接收用户发出的消息。
(5) OnResetDevice()
    当窗口发生重置(如窗口分辨率发生变化)时调用,重新设定窗口的宽度和高度,设置设备的渲染状态RenderState,并且触发引擎主控制类的重置函数Campus3D.CurrentLevel.Reset()
    在设备的创建以后,实例化了Campus3D类。这个类是负责处理整个三维校园程序,在该类中的构造函数中设置了程序资源的路径。设置如下:
    Directory.SetCurrentDirectory(Application.StartupPath + "\\GuetRes\\");
该类用来设置创建程序渲染的当前层级CurrentLever,在Campus3D类被初始化的时候就实例化了当前层级为MenuLevel,使得程序一开始运行就进入菜单窗口;
    三维地图漫游导航引擎使用了两种摄像机cameracameraHUD。设置这两种摄像机的作用如下:
(1)  camera
摄像机camera被定义成第一人称摄像机,负责渲染程序的动态主场景;
(2)  cameraHUD
摄像机cameraHUD被定义成球型摄像机,负责渲染用户的菜单和静态的HUD模型;
4.4.4 引擎的层级
    层级在三维电子地图执行的各个阶段中,包含了这个阶段所特有的元素和逻辑的对象。本引擎一共使用了三个层级:菜单层级、设置层级和主程序层级。每个层级往往有自己特定的更新和渲染函数。
    BaseLevel.cs中包含了BaseLevel抽象类,他是整个程序所有层级的基类,其中声明了其派生类所调用的所有方法,它的构造函数用于重置整个层级。它定义的抽象方法主要有以下几个:
protected abstract void InitializeGraphics();  //初始化图形文件
protected abstract void InitializeSounds();    //初始化音效文件
public abstract void Reset();              //用于重置层级
public abstract void Update();              //用于更新层级
public abstract void Render();              //用于渲染层级
public abstract void KeyPressedHandler(KeyEventArgs Key);
  在整个程序中,主要创建了以下几个层级:
(1) LevelLevel1
    这两个层级是程序的核心层级Level继承于BaseLevel,而Level1又继承于LevelLevel1负责加载Level层级中所需要渲染的3D物体以及定义好最短路径的结点矩阵,Level则负责处理程序主层级中的所有逻辑,接收用户发出的操作,并做出相应的处理,是整个程序最核心的部分。
(2) MenuLevel
    该类是负责处理程序开始运行时菜单层级的渲染,包含了所有菜单消息的响应函数,并按照用户选择不同的菜单进入不同的层级。
(3) OptionLevel
    负责处理引擎中的配置层级。
    三维校园电子地图引擎中,层级之间的继承关系如下图4-6所示。
 
4-6 层级的继承关系
4.4.5 引擎的模型对象
    在三维校园电子地图中,所有的三维对象都具备了它本身的一些特有属性和一些公共的属性,它们都按照三维对象的实际需要去创建。
    MaxObject.cs文件中包含了抽象类MaxObject,它是所有3D物体的基类,而且是一个抽象类,用于创建物体,设置物体的变换矩阵。它的构造函数:用于设置物体的位置和旋转角度,并且保存mesh或者动画的引用。
它定义了模型对象的一些公共属性:
public static MeshHolder staticMeshHolder;
public Vector3 Position; //保存物体在世界坐标系中的位置
public Matrix MyTransformation = new Matrix(); //保存变换矩阵(平移和旋转)
public float xAngle, yAngle, zAngle; //保存旋转角度
private Meshes MeshReference = null; //保存mesh的引用
还包含了一些公共的抽象方法:
public abstract void Reset() //用于物体发生变化时重置模型对象;
public virtual void Render() //用于渲染当前的模型对象;
public virtual void Update(Matrix ParentTransformation) //用于更新模型对象;
private void SetupTransformationMatrix(Matrix ParentTransformation) //用于构造进行平移和旋转的变换矩阵。
    派生类ObjSkyObjTreeObjNodeObjPlayerObj以及HUD3D,派生类都是直接继承于MaxObject类。
(1) Obj: 继承于MaxObject类,程序中所有的静态物体都是调用该类来创建,比如说教学楼、图书馆、体育馆等模型。
(2) SkyObj: 继承于MaxObject类,用于创建天空环境的天空盒。在该类里面重写了Rander函数,用于关闭灯光和设置贴图模式,在后面讲对他做详细介绍。
(3) TreeObj: 继承于MaxObject类,用于创建场景中树的模型。
(4) NodeObj: 继承于MaxObject类,用于创建程序中用于计算校园导航时最短路径的所有结点。
(5) PlayerObj: 继承于MaxObject类,用于创建程序中移动的物体,其中HandleMovement()函数实现了该移动物体的具体移动方式。
(6) HUD3D类:继承于MaxObject类,用于创建程序中用于HUD的物体模型。
4.4.6引擎的模型读取
    在三维校园地图引擎中,需要加入很多由3Ds max创建的模型,而这些模型都是在创建以后到处成*.X文件格式,这种格式的文件是能够支持Directx的模型文件,它记录了模型的所有顶点位置和贴图的纹理路径以及模型在世界中的坐标等信息。三维引擎为了得到这些模型的相关数据,就必须得建立相关的文件读取类来读取X文件中的各种模型数据。
    Mesh.cs文件包含了Meshes类,用于加载使用3DMAX导出的*.X模型文件,它将X文件中的纹理以及物体的顶点抽取出来,为3D程序渲染物体提供所需要的资源。
    Meshes类将模型的顶点以及贴图信息成功读取以后,为了方便引擎的调用,将它们的所有网格都保存在MeshHolder这个类里面。该类中使用了一个Meshes的泛型变量列表来保存这些网格的信息。
public List<Meshes> MyMeshes = new List<Meshes>(); //Mesh对象列表
4.4.7 引擎的图片导入
    在三维校园地图程序中,会加载一些背景图片和二维的小地图的图片,这些图片是通过Background.类、PicShow类和PointShow类来实现的。这三个类他们都是用于加载图片,所以函数的实现方式基本一样,只是显示的位置和大小有所不同。
    Background类是用作菜单层级的背景图片显示的,它在所有其它物体之前被渲染,位于屏幕中所有其他物体的后面,不会受到摄像机位置的影响,不会影响程序的进行。它的目的完全用于美化场景。
    这三个类的共同点是:
(1) 使用VertexBuffer对象创建并且分配顶点缓冲区来保存顶点信息;顶点缓冲区必须包含4个顶  点,使用适当的信息来填充缓冲区。
(2) 使用Reset(float x,float y,float Width, float Height)函数来创建位置和纹理坐标,在Render()函数中设置好所要加载的图片和纹理,而后场景渲染在设备调用的BeginSceneEndScene之间完成。
4.4.8 引擎的音乐
    为了丰富三维校园程序,在程序运行时,会加入背景音乐,以更好的渲染出环境的气氛;而加载音乐是通过Music.cs文件中的Music类来实现。
Music类继承于IDisposable类,里面包含了音乐的加载、播放、停止和暂停的控制函数,用以实现背景音乐的播放功能。
三维校园电子地图(下)
访问1138
作者:李纳璺  陈金龙 阮方舟
 
 
三维引擎的功能模块设计
  设计三维校园电子地图引擎系统包含了以下主要功能模块的设计:
(1) 用户交互界面设计;
(2) 智能导航设计;
(3) 模型加载和渲染;
(4) 光照处理;
(5) 天空盒设计;
本节将对这些主要功能和技术的实现进行详细介绍。
5.1 用户交互界面设计
5.1.1 用户界面设计
    用户界面是软件与用户交互的最直接的层,界面的好坏决定用户对软件的第一印象。而且设计良好的用户界面能够引导用户自己完成相应的操作,起到向导的作用。同时界面如同人的面孔,具有吸引用户的直接优势。
    本系统的主菜单界面采用天际蓝作为主调,背景使用桂林电子科技大学东区的标志性建筑物图片加以衬托,中间再使用三维仿真模型场景加以点缀,充分体现了软件的主体内容和风格。主菜单界面如图5-1所示。
 
 
5-1 主菜单界面
程序运行的主界面以三维仿真场景为主,按照三维程序常见的做法,把二维平面地图放置在窗口的左上角,二维图下面放置的则是用户相关操作控件。符合人们的操作习惯,整体效果简洁大方,再加上背景音乐的渲染,有让人置身于其中的感觉。设计主程序界面如图5-2所示。
5-2 主程序界面
5.1.2 用户控件设计
在三维的场景中,要使得程序与用户之间进行互动,就必须得使用到UI用户界面。而由Direct3D进行渲染的三维程序中直接使用Windows的控件明显是不可行的。因此,在三维校园电子地图引擎中的用户控件的创建,我直接调用了DirectX 9.0框架的UI支持,创建了DirectX的用户控件。
在三维校园电子地图引擎中,除了主菜单使用了UI以外,在设置界面也大量的使用了支持DirectxCheckBox控件来设置模型的隐藏和显示;在程序的主层级当中,也使用了ComboBox控件来选取所要寻的景点,还用到了Slider控件来调节移动的速度。
UI的创建过程如下:
(1) Directx示例文件夹中的UI文件夹复制到当前项目中,该文件夹中包含了UI的外观模型与UI的贴图文件,贴图文件如图5-3所示,该图像就是所有用户控件的贴图压缩纹理dxutcontrols.dds;而DXUTShared.fx则是控件的模型数据。
5-3 UI的压缩纹理
(2) UI的外观数据添加到项目当中以后,要在程序中调用这些信息来创建控件。首先要定义一个Dialog对象,然后在这个Dialog对象上加载所需要的控件。
private Dialog Dlg_UI = null; // dialog for standard controls
(3) 下一步骤是建立它需要的控件。这是通过调用诸如AddButton之类的对话框AddXXX方法完成的。这部分代码全部放在InitializeUI()函数中完成,而该函数是在Level类被实例化的时候在构造函数中被调用。
(4) 在定义好需要加载什么类型的控件以后,就需要设置好控件放置在什么位置,这些由ResetUI()函数来完成,代码如下所示:
private void ResetUI(){
    Dlg_UI.SetSize(Project.CurrentWindowWidth, Project.CurrentWindowHeight);
    Dlg_UI.GetControl(cb_mainID).SetLocation(20, 360);
……(由于代码太多,需要请与编辑部联系)
}
(5) 光把UI加入到对话框中还不能使得UI在三维的场景中显示出来,必须得对他进行渲染才能使得已经设置好的控件按照所指定的位置显示出来,渲染控件的代码当然是放在LevelRender()函数中完成了。写法如下:
Dlg_UI.OnRender(elapsedTime);
(6) 制作UI本身就是来接受用户所发出的消息,要求UI 完成的最后一步是将消息传递给控件,这让它们从用户那里接收键盘和鼠标事件。在MsgProc中,程序调用对话框MsgProc方法传递消息。如果对话框的MsgProc 返回true 指明消息已经被处理,程序将noFurtherProcessing 参数设置为true 并立即返回就是非常重要的。没有这样做的话将会导致消息被不止一次的处理。
noFurtherProcessing = Dlg_UI.MessageProc(hWnd, msg, wParam, lParam);
if (noFurtherProcessing)
  return noFurtherProcessing;
添加完成消息传递函数之后,控件就能接收用户发出的消息。
5.2 智能导航设计
智能导航在三维电子地图程序中是难点部分,它将自动的寻出用户所需到达的目的地的最短路径,并且进行跟踪导航。要实现最短路径的搜索功能,本引擎采取基于结点的最短路径算法——弗洛伊德(Floyd)算法。该功能模块的流程图如下图5-4所示:
5-4 智能导航模块流程图
在三维校园电子地图程序中,将Floyd算法运用到各个景点之间来求得他们的最短路径,下面将介绍如何在程序中实现基于Floyd算法的智能导航模块。
(1) Floyd算法是通过邻接矩阵来实现的,因此首先要给每个景点排序,按照校园建筑的分布与坐标,将校园定义了149个结点,他们之间的关系如下表5-1所示:
5-1 邻接矩阵的坐标与邻接点的定义
序号
X坐标
Y坐标
邻接点
0
-96
-4608
1
1
-108
-4500
2
2
-108
-4140
3,18,86
3
576
-4140
4,5,6
4
1836
-4140
8
5
720
-4032
null
……
……
……
……
146
-2096
1824
147
147
-1392
1968
148
148
-1248
1904
149
149
-736
1904
null
 (2) 有了结点的坐标与他们之间的关系列表之后,就能够在程序当中来构造用于Floyd算法的矩阵了。在程序当中,Floyd算法的构造与求值都是在Floyd.cs文件中Floyd类来实现。创建矩阵数组是在Level1类里面完成的,ConstructNodeMatrix()该函数构造出矩阵的数组cost[i, j],而两个顶点之间的权值则是求这两个结点在三维空间坐标系的距离,求法如下:
distance = Vector3.Length(Vector3.Subtract(NodeObjList[n1].Position , NodeObjList[n2].Position));
cost[n1, n2] = cost[n2, n1] = distance;
构造好矩阵数组以后,在ConstructNodeMatrix()实例化Floyd类,并且将构造的数组传入该类,进行最短路径的计算。
Floyd  fd = new Floyd(cost, X, INFINITY);
其中cost表示构造的数组,X为数组的最大值,INFINITY为一个无穷大的数。在Floyd的构造函数中,已经导入了求最短路径的函数ArkyFloyd()求出各点之间的最短路径,然后再通过List<int> OrderByPath(int starNode,List<int> listPath) 函数将输出的结点的顺序调整。到这里实际上已经求出了所有结点之间的最短路径,并且能够按照先后的顺序将它们进行排序。
(3) Level类中,程序将实现最短路径的导航逻辑。由于一开始定义结点时,就给每一个景点定义了一个固定的序号。那么只需要将当前坐标点的序号与目的坐标点的序号传递给Floyd类的GetShortestPath(int starNode, int endNode)函数,就能够得出这两个点之间的最短路径,即为两个景点在校园中的最短路程。
当用户选择好一个景点以后,按“查”按钮,摄像机将进行自动导航,实际上查按钮触发的是PlayerMove(seletedItemsNum)函数,该函数中实现的功能就是将当前摄像机所在的结点和查的目标结点的值传递给Floyd类的GetShortestPath()函数,并且将得到的最短路径结点的列表压入一个队列,以便摄像机智能导航时使用。实现方法如下:
private void PlayerMove(int NodeIndex){
    List<int> listNode = new List<int>();
listNode = fd.GetShortestPath(PlayerCurrentNodeIndex, NodeIndex);
    for (int i = 0; i < listNode.Count; i++)
        qu.Enqueue(listNode[i]);
    v3 = NodeObjList[PlayerCurrentNodeIndex].Position;
}
(4) 有了结点移动队列以后,就能够在Level类的update函数中调用处理摄像机智能移动的函数UpdatePlayerMove()了,该函数每被调用一次就执行摄像机位置的更新,直到摄像机到达第一个目标结点为止,然后设置当前结点为第一个目标结点,第一个目标结点从队列中弹出,继续按照下一个结点的位置移动,直到所有的结点全部移动完成,那么摄像机就到达了目的地了。实现代码如下:
private void UpdatePlayerMove(){
     if (PlayerObj1.Position == v3)
        if (qu.Count > 0) {
              t = qu.Dequeue();
              PlayerObj1.destPos = NodeObjList[t].Position;
              v3 = NodeObjList[t].Position;
              PlayerCurrentNodeIndex = t; //设定移动物体的位置
          }
}
5.3 模型加载和渲染
要将3ds Max制作的教学楼模型导入进程序,并且将它们渲染出来必须经过一系列的代码转换处理,最终显示才能在三维的场景当中。下面将介绍如何把3ds Max制作的建筑模型导入程序,并且渲染到三维场景中的制作过程。
在桂林电子科技大学的三维校园电子地图当中,主要的建筑物有教学楼(如:二教、三教、九教等)还有学生食堂、图书馆等,他们都在校园中有固定的坐标位置。在3ds Max建立模型的时候,一般都是在原点建立模型。如果是这样,在导入进3D引擎的时候就得设定他们的具体坐标,在世界场景中设定了一个相对中心点设定了位移,就相当于多乘了一个矩阵。要在程序中同时渲染所有建筑,就要把每个建筑的位移值乘一次世界矩阵,这样很大程度的增加了程序的运算。为了消除这些运算,而把建筑物放到相应的位置上,那么就需要在建立模型的时候就移动好建筑的位置。
下面将介绍3ds Max制作模型是如何导入程序进行渲染的:
(1) 3ds Max建立好模型以后,将模型组成一个对象,再次导入CAD底图,然后以这张地图为参照来设定建筑物的位置,这样导入程序之后就是已经在该建筑的指定坐标上面了,如图5-5所示;最后再将此模型导出成X文件。
5-5 模型位移放置
(2) 本系统使用3ds Max8的插件PandaDirectXMaxExporter.dle来导出X文件,该X文件中保存了模型的顶点信息和贴图信息等,在三维校园电子地图引擎里面通过Mesh类来获取这些X文件的顶点信息和贴图路径,以提供引擎渲染模型时使用。
(3) 引擎使用LevelMeshHolder来保存所有三维模型的数据,加载方式如下:
LevelMeshHolder.AddMesh("move.x");
有了这些模型的相关数据以后,就能够使用MaxObject的派生类来实力化这些模型,从而得出不同类型的场景模型体,由MaxObject派生出来的类有ObjSkyObjTreeObjNodeObjPlayerObj以及HUD3D。他们分别表示建筑模型对象、天空模型对象、树木模型对象、结点模型对象、操作者模型对象和HUD模型对象。每一个模型对象都有他们特殊的属性,所以区分出这几种派生类。但是,他们都使用一个Render()函数来进行渲染,使用Update()函数来进行模型的相关数据更新。
5.4 光照处理
为了使得三维校园的虚拟场景更加富有层次感,本引擎在程序中添加了光照。引擎在初期调试的时候是采用环境光,渲染的模型如果两个面是相同颜,那么很难辨别模型的交界处,这样看起来就很不真实。在Direct3D一共可以添加8个光源,在引擎中只添加了一个光源,光源的类型是方向光,也就是我们平时所说的平行光。有了平行光照射到模型上,渲染出来的物体就有了明面和暗面,这样渲染模型显得更加真实而富有层次感。
添加光照的方法如下:
在引擎创建好Device以后,调用光照设置函数SetLight()来初始化光照系统。
(1) 在代码中,首先定义了一个v3向量来设置光源的方向,在这里设置的方向为西北方,因为天空盒的太阳所在位置也是这个方向,这样设置能使得场景更加真实。
(2) 设置好光的方向之后,MyDevice.Lights[0].Type = LightType.Directional; 来设置光源的类型为方向光。
(3) 再将Ambient属性设置一个光线亮度值,这个数值决定了光照的暗面的亮度。
(4) 接下来设置Diffuse属性,它决定了光照的颜。
(5) 在函数的最后将设置好的光照Lights[0]开启。
(6) 在场景建立好以后,开启灯光系统,并且关闭没有使用的其它7盏光源。设置代码如下:
Project.MyDevice.RenderState.Lighting = true;
for (int i = 1; i < 8; ++i)
    Project.MyDevice.Lights[i].Enabled = false;
通过这些设置,场景中就成功的添加了一个平行光源,下图5-6是未添加光源和添加光源以后渲染场景的效果。
  (a) 无光照                    (b) 添加平行光
5-6 光照对比
5.5 天空盒设计
在三维程序中,实现天空环境渲染主要采用天空盒和半球面两种方式。采用天空盒方式渲染的模型面要比半球少得多,所以一般都是采用天空盒模型来渲染周围环境,而半球面一般是用在精度比较高的场景中渲染天空。
三维校园电子地图的场景中,除了有地形和建筑物还需要有周围天空环境的烘托,这样才能使得三维环境更加的真实。本系统采用的是天空盒技术制作场景的环境,天空盒是一个长方体,它是由六个面构成一个天空盒,贴上云彩和山水图片,就可以实现一个矩形面的天空。
天空盒是由六张无逢贴图实现的一个盒子模型体,本系统使用的环境贴图如图5-7所示。
5-7 天空盒贴图
3ds Max里面,给天空盒模型贴图时要注意的是贴图贴在长方体的内,所以建立模型时要将长方体的六个面进行一次flip操作,使得图片贴在盒子的内部。如图5-8所建立的是场景中使用的天空盒模型。
 
 
 
 
 
 
 
 
 
 
 
 
5-8 天空盒模型
建立好天空盒模型以后,同样是导出X文件,在程序中,创建天空盒必须得使用桂林电子科技大学是几本SkyObj类来实例化天空模型对象,因为天空环境跟普通模型不一样,它永远是跟随着摄像机移动的,但是他不会随着摄像机的旋转而转动。所以在场景中,人物永远无法走到天空尽头,这样就能创建出一个无边界的广阔环境了。
在渲染天空的时候,不能像普通模型那样去渲染天空,因为场景中添加了光照,直接渲染的话,会出现明显的边界线,对比图如图5-9所示。因此,在渲染天空模型的时候必须关闭光照,待渲染完毕以后,再将灯光开启。渲染时,还需要开启贴图的延展模式,否则在天空盒的接缝处同样会出现边沿线。天空盒的渲染代码如下:
public override void Render()
{
    //设置边沿的伸展模式
    Project.MyDevice.SetSamplerState(0, SamplerStageStates.AddressU, 3);
    Project.MyDevice.SetSamplerState(0, SamplerStageStates.AddressV, 3);
    Project.MyDevice.RenderState.Lighting = false; //关闭光照
    base.Render();
    Project.MyDevice.RenderState.Lighting = true; //打开光照
    Project.MyDevice.SetSamplerState(0, SamplerStageStates.AddressU, 1);
    Project.MyDevice.SetSamplerState(0, SamplerStageStates.AddressV, 1);
}
(a) 有光照渲染                                 (b) 无光照渲染
5-9 有无光照渲染天空的对比
系统测试
在软件工程项目中,在软件项目开发的各个阶段都会采用不同措施来保证软件的质量,但是在软件项目实际开发过程中难免会存在问题。为了避免正式投入使用时产生错误,在软件投入使用前要对项目进行全面的测试。软件测试是根据软件开发各阶段的规格说明和程序内部结构,设计若干测试用例,测试程序的正确性和兼容性。
6.1 测试环境
三维校园电子地图程序是采用Managed DirectX SDK August 2007来开发,使用的DirectX的版本比较新。因此,对进行系统测试的电脑配制要求也比较高。在使用显卡与CPU配置比较低的电脑上运行本程序时,不建议启用渲染所有模型,否则会导致运行画面十分不流畅。为了达到实时的目的,至少要保证图形的刷新频率不低于15/秒,最好高于30/秒。
为了使得程序有更好的运行效果,三维校园电子地图的推荐配置为:
CPU:双核、主频2.7G以上;
显卡:8600GT级、显存256MB以上;
内存:2GB以上
硬盘:大于100MB的空间
在对三维校园电子地图程序测试时,使用了两台不同级别的计算机进行测试,一号测试电脑安装的是Windows XP SP2操作系统,二号测试电脑安装的是Windows Vista操作系统。
(1) 两台计算机上还需要安装支持三维校园程序运行的软件平台:
Microsoft .NET Framework2.0
DirectX_mar2008
(2) 测试计算机的硬件配制:
一号计算机的配置:
CPUIntel 酷睿2双核 E8200 2.7GHz
显卡:Inno3D 8800GT,显存512MB
内存:2GB
二号计算机的配置:
CPUAMD Athlon(tm) 64 X2 TK-55 1.80GHz
显卡:GeForce 7150M /nForce 630M,显存512MB
内存:2GB
6.2 测试结果
(1) 针对程序的各部分功能进行测试,检测程序的每一个功能模块,没有异常产生,程序顺利执行,确保了程序执行的正确性。
(2) 测试软件的智能导航功能,在导航模型中,依次测试了各个景点之间的最短路径导航,测试所有查景点都能到达目的地,而且行走的路线为最短路径,确保了智能导航模块的正确性。
(3) 在设置模式中,设置加载显示的模型,进入程序后,所有模型按照设置的模型显示;重新启动程序,进入设置界面,所有设置与上一次设置结果相同,该功能运行正常。
(4) 测试三维程序在不同配置的电脑上使用不同分辨率运行程序的刷新频率,一号测试电脑能流畅运行各个模块;二号测试电脑在高分辨率下加载所有模型运行程序有延迟现象。具体数据参见下一节测试数据。
(5) 分别使用了一号测试计算机(Windows XP操作系统)和二号测试计算机(Windows Vista操作系统)运行程序,都能够正常执行,系统的兼容性良好。
(6) 运行程序后,程序菜单界面感觉友好、简洁而又美观;程序主界面展示三维校园场景,并在左侧显示平面小地图和操作按钮,符合大众的操作习惯。在控制摄像机的浏览模式下采用常规的三维游戏操作方式,使用键盘的WSADQE键来控制移动,鼠标控制方向,简单易学。
6.3 测试所得实验数据
(1) CPUIntel酷睿2双核E8200主频2.7GHz;显卡为Inno3D 8800GT显存512MB;内存为2GB的一号计算机上测试刷新频率的数据表6-1所示:
 
 
 
 
6-1 一号测试计算机的测试数据
运行分辨率
模型加载状况
刷新频率
运行状况
800*600
加载所有模型
45.8 fps
顺畅运行
不加载树木
59.31 fps
顺畅运行
1024*768
加载所有模型
44.65 fps
顺畅运行
不加载树木
57.55 fps
顺畅运行
1280*960
加载所有模型
44.52 fps
顺畅运行
不加载树木
56.56 fps
顺畅运行
1280*1024
加载所有模型
43.89 fps
顺畅运行
不加载树木
56.12 fps
顺畅运行
(2) CPUAMD Athlon(tm) 64 X2 TK-55主频1.80GHzInno3D 8800GT,显存512MB;内存为2GB的二号测试计算机上测试刷新频率的数据如表6-2所示:
6-2 二号测试计算机的测试数据
运行分辨率
模型加载状况
刷新频率
运行状况
800*600
加载所有模型
18.96 fps
比较卡
不加载树木
52.91 fps
顺畅运行
1024*768
加载所有模型
17.45 fps
比较卡
不加载树木
52.18 fps
顺畅运行
1280*800
加载所有模型
17.71 fps
比较卡
不加载树木
49.72 fps
顺畅运行
1280*1024
加载所有模型
17.11 fps
比较卡
不加载树木
49.64 fps
顺畅运行
从两台配置不同的计算机测试数据表明,三维校园电子地图程序对电脑的配置要求较高,建议使用配备有中高端显卡和双核CPU的电脑来运行该程序,才能渲染出最佳效果的三维校园地图。
结论
本论文从介绍三维电子地图的背景以及发展状况开始,引述了开发三维漫游引擎的几项关键技术;再从整个三维校园电子地图项目的设计总体流程,引擎结构框架,主要功能模块的设计等几个方面详细介绍了整个项目的开发流程以及核心功能的实现。
整个软件项目按照下面的八个流程进行开发:
(1)数据采集;
(2)建立校园平面图;
(3)建立三维场景模型;
(4)设计导航漫游引擎;
(5)建立引擎的框架;
(6)实现各项功能和模块;
(7)优化代码;
(8)系统测试。
在三维校园电子地图引擎中,引入了多方面的技术,使得程序执行效率大副提升,操作更加简单,三维场景内容更加丰富,整体效果更加完美。
通过本论文中的实例可让读者进一步的了解到软件项目开发的全过程。系统而又全面的掌握到了使用Managed DirectX开发三维虚拟现实程序的步骤和关键技术,了解到数据结构中的算法在具体项目当中的实施方案。对开发三维游戏和虚拟现实程序打下了良好的基础。同时也体会到:作为一个比较高水平的程序员,光是会编写程序代码是远远不能满足现代项目开发的需求的。除了编程,还必须掌握相关方面的知识结构。这全靠平时的修炼。
通过此论文和例子,希望能带给读者在软件项目设计开发中更多的帮助!
参考文献
[1]  王德才,杨关胜,孙玉萍.精通DirectX 3D图形与动画程序设计[M]. 北京:人民邮电出版社, 2007109~214.
[2]  严蔚敏,吴伟民. 数据结构[M]. 北京:清华大学,2004156~190.
[3]  黄玉清,郑雨涵. 3ds Max8 游戏设计与制作宝典[M]. 北京:科学出版社,200639~228.
[4]  尚晶晶. DirectX 3D游戏开发技术详解[M]. 北京:人民邮电出版社,2006142~146.
[5]  刘怀亮. 数据结构习题解析与实验指导[M]. 北京:冶金工业出版社,200586~91.
[6]  Tom Miller. Managed DirectX® 9 Kick StartGraphics and Game Programming[M]. Sams PublishingOctober 222003.
[7]  Lynn Thomas Harrison. Introduction to 3D Game Engine Design Using DirectX 9 and C# [M]. New YorkSpringer Verleg2004.
[8]  PRUSINKIEWICZ PLINDENMAYER A. The algorithmicbeauty of plants[M]. New YorkSpringer Verleg, 1990.
[9]  ROSSIGNAC J,BORREL P. Multi-resolution 3D approxima-tion for rendering complex scenes[C].BerlinSpringer-Ver-lag, 1993453~465.
[10]  王卫辰,江晓红. 虚拟校园三维仿真系统的开发及优化[J] .徐州师范大学学报(自然科学版) 2004(03).
[11]  杨艳玲,王浩涌. 虚拟现实(VR)技术在虚拟城市中的应用[J].辽东学院学报(自然科学版) 2006(04).
[12]  徐利明,姜昱明. 可漫游的虚拟场景建模与实现[J]系统仿真学报, 2006,(01).
[13]  金小田,张小敏. 虚拟现实技术在建筑方案优化设计中的应用[J]建筑科学, 2004,(02). 
[14]  黄薇. 立体式虚拟校园的建模技术与数据表现方法[D]华中师范大学,2006.
[15]  肖平. 立体式虚拟校园的场景规划与设计[D]华中师范大学,2006. 
[16]  潘华伟. 基于图象的虚拟场景绘制技术研究与系统实现[D] 湖南大学
[17]  罗杰. 面向建筑的虚拟漫游系统研究与实现[D]. 大庆石油学院
[18]  马学强. 虚拟现实的关键技术研究与实现[D]. 山东科技大学
[19]  喻罡. 基于图象的虚拟场景构造和漫游系统研究[D]. 西安理工大学
[20]  王邯. 基于图像绘制的虚拟校园漫游系统的研究[D]. 华中师范大学
[21]  刘家胜. 三维重建中插值建模及其可视化的研究[D]. 江西师范大学