首页 > 代码库 > 我肚子里的墨水——写给3DGIS相关从业人员

我肚子里的墨水——写给3DGIS相关从业人员


作为一名程序员,我已经工作了五年,肚子里的墨水虽然不多,但也是积累了一些,今天倒出来整理一下,仅以经验之谈,供长江后浪拍打。

 

你可能适合阅读:

如果你和我一样,是一名程序员,主要擅长c/c++作为编程语言,从事着三维或者GIS相关的工作,作为一名技术流的探讨者,或者是希望从前辈那里找到点捷径,那么,你可能适合阅读本文。

 

你还是不要浪费时间了:

如果你是个大牛,或者你不喜欢罗嗦的文章,要不然你是个愤青或者大喷,我劝你还是不要浪费时间了

面象对象编程 Cpp

首先,编程语言只是一门工具,没有高低贵贱之分。所以我不想评论 c++/c#/java等各种语言的优劣,只是给学习c++的人员一些忠告。

如果从05年在校开始学习c++算起,已经十年了。但是前三年只能算一年经验,后来跟老师做项目算一年,中途有一年没用c++,纯用idl/matlab等,总结起来也算有六年实战经验了。期间遇到两位良师,减少了很多弯路,目前也算可以做些简单工程的架构。

 

我的学习过程,基本以下六点,就花了我六年时间去学习和摸索

1) 在校学习基本语法,会简单使用vc++生成一个小算法,例如排序等。

很多人说学校学的东西没用,但是基础和理论知识的作用,决不是在你仅完成这基本学习就能领悟的。所以我的建议是,不管你是不是真的理解了,先把体系了解了,至少要知道c++是面象对象的,多态和继承在设计的时候很有用。

2) 初次接触项目开发,使用vs2008生成mfc工程,也就算会写c++了。

开始做项目才知道在学校学的程序真不叫程序,程序只有在解决特定问题的时候才能体现其价值。在这个过程中,很难去纠结写的是好是坏,因为没有经验没有对比,只有是否真的解决问题了,才是成功的。我在老师和师兄的带领下,解决了矢量栅格化的算法,实现了我人生中第一个数字地球的雏形版本。这个过程的重点是,思考问题和解决问题。

3) 开始学习标准c++的写法,脱离windows现成库和工具,使用stl或者boost

如果只会用微软的c++,那只算vc,还不算是学会了c++。完全舍弃微软,是一件很痛苦的事,但是必需经历。首先,必须学习stl标准库中的vector list map string等知识。然后需要学习模板的使用。最后是,第一次学习侯捷翻译的《Effective C++》。这个阶段是才算是真正开始学习c++。

4) 学习大量开源库,形成积累,知道面对问题的时候该选择什么东西来解决

第三点是学习开源库的基础,只有学习了标准c++的写法,才知道原来这个世界上还有那么多现成的开源库供你使用。因为老外并不只用windows,更多用linux或者mac等系统,他们写的代码都是标准c++的,这个必须学。巨人的肩膀,你懂的。

5) 学会抽象问题,设计接口,知道什么是面向对象,从简单的拷贝代码到开始复用代码

学习设计是面向对象的必由之路,当你有三年c++工作经验,如果还不会面向对象设计,那还是别玩c++了。

学习的方法有很多,我提的最重要一点,就是思想。在做每项新任务之前,你要坚定不移要求自己,你现在做的东西,必须可复用,而且要让别人好用,即使是你自己用自己的东西,也要把自己拆成两个人,让自己的A模块让B模块好用,用不要把A和B模块混在一起。

第二点,就是学习现有开源代码的接口设计,而不是实现代码。在每学习一个新开源代码时,先学习架构,在使用别人的接口时思考别人是怎么设计的。

第三点,可以学习下现成的设计模式,如工厂模式、观察者模式、mvc等等。需要强调的一点是,这些模式更多只是在细节上的设计,往往一个工程的设计是多种模式的组合。

6) 学习架构,用已有的积累(自己的经验)和现成的开源代码(别人的经验)以及面临的问题做一次系统性的架构及实现,形成新的经验和积累。

其实所谓架构,只是“集成”罢了。学习架构真不是可以说清楚的,最好的方法,就是有位良师,受到熏陶,否则只能用时间和思考来磨练了。

三维可视化编程 3D

第一次接触三维可视化编程是在大三的一门专业选修课《三维地形可视化》上,后来做了一个三维数字地球,也直接决定了我的职业方向。当时学习的是最基本的opengl编程,工作之后一直是从事三维方面的开发,先后也学习了opengl es/webgl 和direct3dX,同时对一些开源的三维渲染引擎也有所了解,如irrlicht/osg/ogre/prowerVR/ork 等,在此,还需要提一下二维的渲染引擎agg。

 

我的学习过程,也大致可以分为几下几个阶段:

1) opengl入门,固定流水线学习

学习三维,必须从最基础学起。虽然固定流水线有无数的缺点,但是作为学习的基础,还是必须要学习的。不建议跟着书学,建议使用nehe的教程学习,仅学习前15章即可。重点只是掌握所有基本概念。

学习三维很简单,但是入门非常难。门内和门外的差别,就在于你是否真的“领悟”了三维几何(你要画的世界中的实物)到屏幕像素(在屏幕上显示的二维图像)的过程。

渲染流水线的概念至关重要,矩阵变换是这个过程中的数学基础,其他都是浮云。

初学教程的过程很简单,只需要个把月,但是领悟三维的本质,往往需要一两年。希望这一点拨,能够帮你“悟”出来。才算入门。

2) irrlicht入门及精通,跨平台固定流水线学习

在学会了opengl后,用于项目写个一年两年还是可以的,但是要写一辈子,还真是很痛苦。要么自己写一个封装三维的引擎,要么学习一个。我推荐入门者学习irrlicht。

跨平台、小巧是irr最大的特点。缺点太多,但最大的缺点还是固定流水线,跟不上时代进步,注定要被淘汰。

 

插一句,学习irr是我整个编程过程中最重要的一本“武功秘籍”。每个人都应该有他自己的一本秘籍,这本秘籍都会的是你思考的方式。从初学到能够抛弃irr,花了我三四年的时间,感谢它教会了我关于三维引擎的最基本知识,以及c++程序设计的方式。我学习irr的过程是

A) 学习例子和接口文档,学会怎么用。

B) 学习代码,深入学习代码实现。

a) irr::core中的数学库,很有用,

b) 学习irr::video对三维渲染层的抽象,对用户而言,不管你是什么实现,使用的接口方式是统一方便的,而内部却可以使用gl/d3d8/d3d9/gles/gles2等各种渲染器来实现。

c) 学习图片和模型的插件式扩展、学习文件系统等与操作系统相关的跨平台设计和实现

d) 不学习irr::ui界面太丑,简单学习irr::scene中的场景调度

C) 深入浅出,根据需要抽取部分代码,形成自己的需要,学会根据需求来改动代码。

D) 逐渐不使用irr的代码,仅使用一些思想。完全学会了就可以自己写一个三维引擎了。

 

触类旁通,以后在学习每个开源库的过程,基本都需要经历这么四个阶段。

 

3) opengl es2.0可编程流水线学习

学习可编程流水线,是时代发展的需要,学三维,必须学。可编程流水线与固定流水线的差别,就在于写好shder。我没有直接学习opengl2.0,而是由于项目需要,直接学习了它的子集gles2,我学习的教材是《OpenGL ES 2.0 Programming Guide》,全是英文,学习起来是比较痛苦,好在有opengl的基础,学习的过程也不是那么难。

基本上学习了gles2,也就基本学会了gl2,webgl不过是js版本的变种。在此之后,我再学习d3d9里的可编程流水线,也比较简单。

 

在学习gles2的过程中,我还顺便学习了powerVR。它的好处是,写过一遍gles2的代码,就可以直接在windows和android、ios上跑了。这也是我学习gles2的最主要目的。加上项目实践,做了个三维导航电子地图,基本上算是掌握了gles2。

 

4) osg/ogre入门,跨平台三维渲染引擎

我对osg/ogre的学习基本为0,只能算是了解,还不能算是入门。但是对于大家来说,掌握其中一个跨平台的三维渲染引擎,是非常重要的。大家可以把osg/ogre作为我上述第二点学习的替代品,即不学习irr,直接学习osg/ogre。只是要想达到我学习一个开源库的深入浅出,没有个三五年,估计是比较难。

我之所以在学习了irr后,并没有再学习osg/ogre的原因有几点:

A) 我从学习了irr后又自己重新写了一套渲染引擎,不需要使用现有的开源三维引擎,在实际的项目过程中也没有这个需求,没有推动力

B) Osg/ogre过于庞大,需要较多的精力去学习,一直没敢介入,也可以说是最初的选择决定了,男怕入错“行”

因此对于有一定三维经验,有项目需求,且有大量可学习的时间和精力的,需要找一个三维引擎学习的,我还是比较推荐osg/ogre。Osg的体量还是大于ogre,不过osg的资源也远多于ogre。但从设计和学习的角度来讲,我偏向于ogre;从应用和工程的角度上来讲,推荐osg。

 

5) Agg 二维图形渲染引擎

虽然是学习三维,但不得不说,学习二维图形基础也是十分必要的。首推agg。学习agg也是一个需要入门的过程。我学习了一两年,在各项目中也用过多次,但仍然只能算是小试牛刀。

Agg最牛的地方,就是基本都用模板实现了所有图形的构造和光栅化,其反走样效果可谓不要太好哦。2005年写的东西,至今还是广为人用,不得不服。

 

6) 其他涉猎

虽然没有深入学习,但学习了一些基本思想,可供大家参考的有。

Ork,也是很小巧的开源三维渲染引擎,其最大的特点就是把可编程流水线的思想封装成面象对象的设计,其次是它对资源的封装设计也很高明,仍然是不得不服!

WildMagic,又是个神人写的用于教学的开源三维引擎,目前正在改为GTEngine。我觉得最牛不是它的三维图形渲染,而是三维空间计算!数学库,强大到爆。

地理信息系统编程 GIS

说起GIS,那可是我的老本行了。当初报这个专业的时候,仅是因为特别喜欢地理,梦想着以后可以在全球各地旅行,成为一个地理学家。于是就把武汉大学里所有关于地理的专业报了一遍,以为这个以地理开头的专业会很有意思,结果后面的“信息系统”却把我拉进了“程序员”的坑。

既来之,则安之。武大的GIS确实是很牛的,我虽然经常逃课,但专业素养还是在的。所有与程序相关的课程,我基本都是班上最好的。给从事GIS程序开发的后辈们的忠告是:

1) 如果你不想当程序员,就把其他专业知识学好

2) 如果你想学好GIS,那必须学好程序,程序对于GIS来说,很重要

3) 基本程序课程c++/数据结构/软件工程/二维图形学,很重要

4) 专业知识,GIS原理/GIS算法/地图投影/空间数据库/地图符号化,很重要

在校学完了,工作的时候,基本就没什么可学的了,就只剩下用的份。

当然,剩下的就是学习各种开源库了。

 

基本的GIS算法是肯定要会的,其实也就是二维图形学的算法,最基本的像求面积,点在多边形内、线与多边形求交、点线面的栅格化等等,这个如果不会,还是回学校里去吧。

Geos也是必须要学的,就是专门为我们这些搞GIS的人写的,所有高级的、专业的GIS算法在里面都能找到,还不用,太浪费了吧。

GDAL这个必须要用,各种GIS数据读取,基础必备啊。

Proj是必须要学的,投影都不会用,还搞什么GIS。

以上都是基本的库类,简直是开发过程中的神器啊

 

Postgres+postgis数据库是可以选学的,用数据库的话还是推荐一下。

GeoServer也是可以选学的,如果需要用到wms/wfs等数据发布的话。

QGIS也是可以选学的,二维GIS开源可用的就那么几个。

OpenLayers也是可以选学的,web版本的GIS。

再推荐个二维矢量地图的渲染器mapnik,其架构设计很小巧

以上是应用级的神器,不过对我来说,没有什么用。

 

在实际的过程中,有很多专业知识需要查一些文章去深入理解的

空间索引必须要会,所以二叉树、四叉树、八叉树之类的,多少要知道点吧。

金字塔、LOD等知识,也是需要补补的。

 

学习GIS嘛,就是个专业化的过程。专业人就需要有专业知识和专业素养。其实在GIS专业里还有很多很好用的库类,在实际的应用过程中需要慢慢积累。我由于更专注于3DGIS领域,所以对很多2DGIS方面的库没有太多深入。

 

三维地理信息系统可视化编程 3DGIS

关于3DGIS,虽然研究了这么多年,可以算是这方面的一个专家了,但总还是觉得能力有限,有点Hold不住啊。其主要原因在于

1) 我主要专注于三维可视化上,对真正的3DGIS的理解和应用还是有欠缺的

2) 我反复写过三四个3DGIS平台,而且都是从最底层开始写起,与那些大型成熟的3DGIS平台相比,还是太弱了。

3) 我虽然个人能力和专业基础还是不错的,但是团队方面,也还是弱爆了。

 

所以,在我看来,要想完成一个好的3DGIS平台,必须具备的条件是:

1) 足够稳的软件架构

软件架构方面,主要包括了系统服务层、数据层、调度层、渲染层、渲染插件层、GIS插件层、跨平台开发接口层、(选配工具层、网络服务层)、应用层。每个层次都需要专业化的设计。

2) 足够强的团队架构

我想象中的团队架构,应该包含4个层次,首先是总架构师1-2名,然后是核心开发团队3-4名,每名成员要熟悉2-3个专业层次,接着是插件开发团队若干名,最后是二次开发及应用开发团队。其实平台的前期搭建只需要4-5名,即负责架构设计和核心开发;中期这些人员也可承担部分插件开发任务,并增加2-3名外围人员,中后期根据业务发展形成10-20人的技术团队。

3) 足够分的市场结构

这个就不多说了。

 

对于3DGIS开发的学习,我觉得更重要的是一个综合水平的集成,即先包括了前面关于c++/3D/GIS三个方面的学习和基础,然后再通过学习关于3DGIS的专业知识,达到融会贯通的程度。我的学习和开发经历是

1) 最初是2008年在实现第一个三维数字地球的时候,学习了一篇博士论文《全球多分辨率虚拟地形环境关键技术的研究》,作者杜莹(2005),重点实现了地形、影像数据的加载和调度,以及使用opengl固定流水线实现的三维地球绘制。

2) 后来在2010年与另一位老师合作,修改了由他设计的框架三维虚拟地球,期间与另一位博士合作,完成了虚拟三维月球的撞击模拟实验。当时主要是使用irrlicht作为渲染引擎,基于老师现有的框架设计实现。在此期间,学习了irrlicht和agg。

3) 期间花了一个月学习WorldWindC#版本的实现,吸取了其中的部分思想。主要是渲染插件和相对中心的思想。其调度中还有很多细节问题,在此不作多述。在这个过程中,其实也学习了不少现有的商业3DGIS平台,像Uniscope(后来叫Stap),伪景行,google earth / arcgis globe之类的地球,发现在PC端的平台已经有泛滥之势。于是转头做移动终端的3DGIS平台。当时webgl刚出,还考量过是否做html5上的地球,但由于c++的积累,放弃了js的开发,便选定了gles2

4) 2011年,和老师合作实现的跨平台三维数字城市渲染引擎。在此期间,学习了gles2和powerVR,实现了windows/android/ios跨平台的三维城市。

5) 2012年,和四维图新合作实现的跨平台三维导航电子地图引擎

6) 2013年至今,和XX单位合作实现的跨平台二三维一体化渲染框架

 

正如之前所说的,虽然已经有了丰富的经验和一定的积累,手上有多个平台引擎,却没有一个完整的能真正拿得出手的产品。说来惭愧。今天把这些墨水倒出来的一方面原因,是希望如开篇所说的,供长江后浪拍打的。另一方面,是想做一个总结与整理,寻找属于我自己的出路。往往一个程序员,会陷入程序和技术之中,无法自拔。

1) 受生活压力所迫,必须要赚钱,养家糊口。要工作,就难谈理想。

2) 受精力思绪限制,有很多想法无法展开。除了工作外,业余还是希望追求生活品质。因此并不像年轻时那般有精力和时间去做更多有意义的事。

3) 受地域人员的限制,缺乏与志同道合的人一起完成。所谓千军易得,一将难求啊。

4) 总还是希望能留下点什么有用的东西的,比如像学习的经验,学习的笔记,或者思考过的架构和设计,或者是写成觉得不错的代码。分享的前提,是闲得没事干。

 

路还得继续走。船到桥头自然直。

顺其自然,just let it go

 


我肚子里的墨水——写给3DGIS相关从业人员