0 引 言
随着现代城市的不断拓展延伸,城市空间多层次、立体模式管理逐渐成为城市规划管理的发展趋势[1],实现城市空间信息管理模式从二维到三维的转变,三维虚拟城市技术,已经成为人们关注和研究的热点[2]。
三维虚拟系统具有多维信息处理、表达和分析的特点,在空间信息的社会化服务中,三维虚拟城市的应用有着越来越明显的优越性和不可替代性[3]。
文中采用了一种新的模式进行三维虚拟城市的设计,采用三维算法初步建模,Photoshop 进行贴图加工,3DMAX 进行图形的渲染,三维引擎Unity3D 技术实现三维虚拟城市。 该方式制作过程简洁,三维引擎技术编程难度低,能高效率、高质量完成三维虚拟城市的建设。 整个建设过程包括地理信息数据采集、三维算法建模、3DMAX 后期渲染以及三维引擎技术编程[4]。
1 三维虚拟城市实现设计
首先,获取地理信息数据。 包括数字高程数据、建筑物类型(如草地、水域、道路等)的矢量数据、数字遥感影像图数据以及地理坐标等[5]。
其次,使用三维建模算法,生成三维数字模型,包括不规则三角网 TIN(顾及地性线)、规则格网 DEM等[6。
第三,进行精细处理,包括建筑物点投影变换和裁剪处理、光照模型选择、建筑物要素叠加、点坐标变换、消隐与纹理映射等[7]。
第四,三维模型制作,使用 3DMAX 和 Photoshop工具,对粗糙模型进行加工和渲染,得到高逼真的三维模型。
最后,三维模型的导入,将三维模型根据地理坐标依次导入到Unity3D 中,进行虚拟技术的开发。具体系统实现设计如图 1 所示。
2 数据采集与处理
数据的收集与处理,主要包括基础数据准备、实地采集和后期处理。
基础数据准备主要是收集整理乐山某区域的1: 2000 地形图和高程点,以及最新的航空影像。 通过地形图与影像图的对比和实地考察,划分区域分布图和编号图,用于指导实地数据采集和三维模型建设[8]。
区域分布图分为基础模型、标准模型和精细模型三个级别,编号图主要是依据道路和景点的分布划分编号,作为模型和纹理命名的依据。需要对前期准备和实地采集的数据进行处理[9],如照片的整理、纹理的收集、属性的汇编,然后建立分片景区照片库、通用纹理库、属性记录表等。 例如树的采集,按照树的种类建立照片库,对照片进行处理后,按照树的种类建立通用纹理库[10]。
地形模型建模采用高精度数字高程模型( DEM)和高分辫率数字正射影像(DOM),制作高精度地形模型[11]。 根据划定的建模范围,将 DEM 裁切出来,同时结合航空影像,通过 GIS 软件将 DEM 和 DOM 转换到统一坐标系,保证两者坐标一致,将 DEM 和 DOM 数据导入专业软件中,自动生成地形模型,将生成的地形模型转换为三维建模软件(如 3DSMAX)兼容的格式,进行纹理映射,生成高精度地形模型。 这种建模方式的主要特点是建模快速、高程精确、模型真实。
对于细节要求高的地形实体,如植被、景观路等,主要是根据地形图等高线、高程点以及特征点线,通过三维建模软件,可采用两种方式建模。 一是以 1: 2000 地形图和航空影像作为参考,先勾勒出整个建模范围的道路,以道路作为控制,建立每个景点或者街坊,通过点的高度来表现地形的起伏;也可通过地形图,先在 CAD 勾勒出道路、建筑或人工湖、花坛等封闭的线,参考高程点,在 CAD 调节线中点的高度,然后导入 3DSMAX 中形成面,后者更方便,更准确。 主要特点是表现细腻、色彩美观协调,能够细致表现对象变化细节。
3 三维模型建立
模型的建立是整个虚拟系统的重要部分,因此在该过程中工作量较大,工作较繁琐。 主要实现过程:建筑物形状分析、建筑物分类和纹理贴图处理[12]。
3. 1 建筑物形状分析
建筑模型屋顶建模难度较大,因为屋顶的形状各有不同,都是由一些简单的几何体组成,因此可总结出该区域建筑物屋顶的大体几何体模型如图 2 所示。
3. 2 三维模型分类
为了便于系统模型和场景的建立,对场景和建筑物进行了分区,在建模过程中可以方便建筑物与场景地形坐标进行对应,同时也方便多场景的集成。 具体分区如图 3 所示。
3. 3 纹理贴图处理
为了保证模型的高精度和高质量,在建模之前必须要确定各模型的材质,因此首先用相机拍摄一系列的照片来提取材质,建模过程中进行纹理贴图和实体对比[13]。 具体流程如图 4 所示。
4 实现方法
本系统的业务逻辑处理用 C#、Javascript 技术实现,使用Unity3D 引擎开发平台进行开发。 实现中最主要的技术是:场景漫游技术、物理效应仿真技术和场景切换技术[14]。
4. 1 场景漫游技术
场景漫游技术主要包括键盘控制和鼠标控制,能让用户在虚拟城市系统中前后左右任意方向行走。 同时能控制运动的速度。 内容描述如下:
该段代码实现的功能就是按键盘上面的 W、S、A、D 键 能 实 现 前 后 左 右 的 移 动。 先 定 义 两 个 变 量MoveSpeed(移动速度)和 RotateSpeed(旋转速度),接下来进入函数入口 Update,如果按 W 键时程序就回运行 forward*deltaTime*MoveSpeed;也就是摄像机向前移动 MoveSpeed,因为 MoveSpeed 的初始值为 5,所以移动的速度为 5,以此类推,当按下 S 键的时候,程序运行 forward*deltaTime*-MoveSpeed,这时运动的方向为一个负值所以表现出来的就是往后退。 速度也为5;当按下 A 键时程 序运行 up * deltaTime * - RotateSpeed 此时摄像机会往左边旋转,其旋转速度为20;当按下 D 键时程序运行 up * deltaTime * RotateSpeed 此时摄像机会往右边旋转,其旋转速度为20。
4. 2 物理效应仿真技术
本系统中物理效应仿真技术主要是实现动画场景的仿真,动画仿真技术包括水池波浪仿真、重力仿真等。 内容描述如下(对水池波浪仿真的描述): Vector4 waveSpeed = mat. GetVector( "WaveSpeed" );
float waveScale = mat. GetFloat( " _WaveScale" );
float t = Time. time / 20. 0f;
Vector4 offset4 = waveSpeed * (t * waveScale);
Vector4 Clamp =new Vector4(Mathf. Repeat(offset4. x,1. 0f), Mathf. Repeat( offset4. y,1. 0f), Mathf. Repeat( offset4. z,1. 0f),Mathf. Repeat(offset4. w,1. 0f));
mat. SetVector( " _WaveOffset" , offsetClamped );
Vector3 scale = new Vector3( 1. 0f/ waveScale, 1. 0f/ waveScale, 1 );
Matrix4x4 Matrix = Matrix4x4. TRS ( new Vector3 ( Clamp. x,Clamped. y,0), Quaternion. identity, scale );
mat. SetMatrix( " _WaveMatrix" , scrollMatrix );
Matrix = Matrix4x4. TRS ( new Vector3 ( Clamp. z, Clamp. w,0), Quaternion. identity, scale * 0. 45f );
mat. SetMatrix( " _WaveMatrix2" , scrollMatrix );
该代码调用了 Unity3D 引擎中的一些动态函数功能进行实现,Vector3、 Vector4、Matrix4x4 为 Unity3D 中提供的一些类型,用于实现实体效果。 设置水波的移动速度随着时间的变化随机变换公式 float t = Time.time / 20. 0f,通过多次实验,设置成 20,水面产生流动和波浪效果使得更生动真实。
4. 3 场景切换技术
虚拟现实技术的主要目标之一是允许用户以尽可能自然的方式与虚拟世界物体直接交互。 若要实现自然、精确的人机交互,就必须解决碰撞等问题,相机加入碰撞能更好地解决模型的穿插问题。 本系统中采用了相机切换技术实现了多个不同场景间的切换。
内容描述如下:
var guiskin : GUISkin; / / 定义 GUI
var cam1 : Camera; / / 定义相机
var cam2 : Camera;
function OnGUI() { / / 调用函数 GUI
GUI. skin = guiskin;
if(GUI. Button(Rect(20,0,100,50)," CAM1" ," button1" )){
cam1. enabled = true;
cam2. enabled = false; / / 按钮事件,点击按钮进入相机一
}
else if ( GUI. Button ( Rect ( 120, 0, 100, 50 )," CAM2 " ,"button9" )){
cam1. enabled = false;
cam2. enabled = true; / / 点击按钮进入相机二
}
else if ( GUI. Button ( Rect ( 120, 0, 100, 50 )," CAM3 " ,"button9" )){
cam1. enabled = false;
cam2. enabled = true; / / 点击按钮进入相机三
}
该段代码主要实现了场景切换的功能,主要利用javascript 脚本编写。 一个场景中设定两个相机这样才不显得那么单调,先建两个 button,一个 button 控制相机一,另一个控制相机二,依次类推所有场景中都要建立两个 button 和两个摄像机,一个摄像机自由浏览场景,另一个相机控制路径浏览模式。