初识osg

OSG的诞生

在 1997 年时,Don Burns 由于喜欢滑翔机运动且对计算机图形学非常熟悉,在 LINUX 上写了一个控制滑翔
机的小引擎,这便是 OSG 的最初雏形。
后来在 1998 年,Don Burns 在滑翔机爱好者邮件列表中遇到了 Robert Osfield,对 OSG 的命运起到了决定性
的改变。我们现在在邮件列表中也会经常看到 Robert 的名字,从 98 年至今,Robert 一直担当 OSG 开发组
长,权衡 OSG 的各种利弊。

OSG的编译与安装

在Linux下,可直接去osg官方网站http://www.openscenegraph.org/下载压缩源码包编译安装,osg相关包如下:

osg-OpenSceneGraph-3.5.1.tar.gz, osg安装包,通过cmake编译,安装步骤参考目录下README.txt;

OpenSceneGraph-Data-3.0.0.tar.gz, 里面包含很多例子,例如著名的cow.osg;

如果应用需要使用地球或者数字城市,则可去http://osgearth.org/下载 osgearth,里面包含源码和例子.

osg基础

示例一:HelloWorld

 #include <osgDB/ReadFile>
 #include <osgViewer/Viewer>
 int main()
 {
 <span style="white-space:pre">    </span>osgViewer::Viewer viewer;
 <span style="white-space:pre">    </span>viewer.setSceneData(osgDB::readNodeFile("glider.osg"));
 <span style="white-space:pre">    </span>viewer.realize();
 <span style="white-space:pre">    </span>return viewer.run();
 }

编译命令如下:g++ -o main main.cpp -losgDB -losg -losgViewer

下面我们对程序逐行解释:

第 1~2 行:头文件包含,这里osgDB用于读取模型文件,osgViewer用于在代码中使用osgViewer类,在编译时添加-losgViewer -losgDB也是同样的道理。
第 4~5 行:申请一个 viewer,可以理解为申请一个观察器,该观察可以查看模型。
第 6 行:设置观察器 Viewer 中的数据,换句话说,有了观察器, 就需要查看模型,模型可以绝对路径形式存在,比如 viewer.setSceneData(osgDB::readNodeFile("/home/lzn/osg_model/glider.osg"))。

OpenSceneGraph-Data-3.0.0.tar.gz中有提供glider.osg.
第 7 行:可以理解为这是在渲染前的最后一步,会检查和设置图形上下文,屏幕等,使 Viewer 的设置都生效。
第 8 行:渲染,可以用如下代码代替:while(!viewer.done()){viewer.frame();}.意思也就是说,只要 viewer 没有结束,那么就绘制它的每一个帧。
如果需要在运行时查看程序状态,则可修改为:

 #include <osgDB/ReadFile>
 #include <osgViewer/Viewer>
 #include <osgViewer/ViewerEventHandlers>
 #include <osgGA/StateSetManipulator>
 int main()
 {
         osgViewer::Viewer viewer;
         viewer.setSceneData(osgDB::readNodeFile("glider.osg"));
         //添加状态事件
 :        viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
         //窗口大小变化事件
 :        viewer.addEventHandler(new osgViewer::WindowSizeHandler);
 <span style="white-space:pre">    </span>//添加一些常用状态设置
 :        viewer.addEventHandler(new osgViewer::StatsHandler);
         viewer.realize();
         return viewer.run();
 }

编译命令如下:

g++ -o main2 main2.cpp -losg -losgDB -losgViewer -losgGA

第 1 行:添加一个事件句柄,可以理解为添加一个响应,鼠标或是键盘的,这个响应可以看做响应键盘或是鼠标事件,故函数名字叫:addEventHandler[添加事件句柄]
。这个事件是库中自己写好的,叫做状态设置(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet())),其中我们点击 L 键时有操作器
的味道,所以叫状态设置操作器。众所周知,灯光是状态控制的,所以这句话可以控制 L 键开启与关闭灯光,至于为什么定位在 L 键上,怎么搞的,可以查看 StateSetManipulator 源码,我们以后也会写自己的操作器。发现默认的灯光比加强的 L 灯光好看一些,这是这个模型,大多数情况下都不是这样的。
第 2 行:添加的是窗口大小改变的句柄,这里响应的是 F 键,与上面的原理是差不多。在早期版本中,他们是在一起的,至 1.20 以后就把他们分开了。
第 3 行:添加常用的状态操作,这里会响应 S 键,W 键等等,原理与上述两个是一样的。

官方的四个osg程序

osgViewer:这四个程序当中用的最多的 OSG 程序,用于查看模型;

osgVersion:查看osg库版本;

osgArchive:类似于zip,可将多个.osg模型打包成一个.osga的模型压缩包;

osgConv:模型格式转换与压缩,将模型转换成二进制格式IVE,可防止别人查看和修改模型数据;

参考资料<openscenegraph程序设计>

介绍

osgEarth为开发osg应用提供了一个地理空间SDK和地形引擎.

osgEarth的目标:

l 提供基于osg开发3D地理空间应用的支持;

l 直接从数据源可视化地形模型和影像变得更加简单;

l 提供对开放式绘图标准,技术和数据的交互操作;

在很多情形下,osgEarth可以替代离线地形数据库创建工具,你可以通过osgEarth完成如下工作:

获取地形基础地图并快速而流畅的运行

访问开放式标准的地图数据服务,例如WMS和TMS

将基于web服务的影像数据和本地存储的数据整合

在运行时嵌入新的地理空间数据层

超时处理可能改变的数据

集成商业数据源

社区资源

osgEarth是一个自由开源的SDK,任何人斗可以获取源码,同时欢迎和鼓励参与社区的测试,新功能研发和bug修复.

工具

osgEarth自带很多协助处理earth文件和地理空间数据的工具.
osgearth_viewer
从命令行加载并显示一个地图.osgEarth提供的地球操纵器用于控制相机,对地理空间数据的浏览进行了优化.

osgearth_version

显示osgEarth的当前版本号.

osgearth_cache

管理osgEarth的缓存.osgearth_cache较常用的用法:通过非交互方式--seed参数生成缓存信息.

osgearth_cache --seed file.earth

osgearth_package

从earth文件创建一个基于TMS格式,可重复发布的包。

osgearth_package --tms file.earth --out package

osgearth_conv

将瓦片源中到内容拷贝到另一个文件。所有参数以键值对方式出现,需要为每个驱动选项查找头文件。当然,输出驱动必须支持写(通过实现ReadWriteTileSource接口)。"in"属性来自于GDALOptions getConfig方法。"out"属性来自于MBTilesOptions getConfig方法。

osgearth_conv --in driver gdal --in url world.tif --out driver mbtiles --out filename world.db

osgearth_tfs

从特征源(例如shapefile)产生一个TFS数据集。通过将源预处理成网格结构(TFS),可极大提升大数据集的性能。同时,产生的TFS包可由web服务器提供服务。

osgearth_tfs filename

osgearth_backfill

用于后期处理TMS数据集的特殊工具。一些web地图服务在不同缩放比例下会使用完全不同的数据集。例如,当缩放比例达到4级时,可能使用NASA 的BlueMarble,然后陡然切换到地球资源卫星数据。在2D场景下,对于较光滑的地图有效,但是在3D场景下,整张图看起来会很不均匀,因为在不同的LODs下,相邻的瓦片看起来会完全不同。

Osgearth_backfill产生一个TMS数据集(使用osgearth_package或其他工具),然后从指定的查看高度填充较低缩放级别的细节。例如,你可以指定最大缩放级别10,0-9的lods就可以从10级的数据重新生成。

osgearth_boundarygen

产生边界地理信息,可使用osgEarth<mask> 将外部模型数据嵌入地形信息中。

osgearth_boundarygen model_file [options]

osgearth_overlayviewer

调试叠加功能。运行时显示两个窗口,一个显示普通的地图视图,一个显示包含边界的视锥体视图(用于叠加计算)。

osgearth_graticule

加载经纬线

地图

Osgearth提供了大量的地图文件,每个文件都对应某类功能,可通过osgearth_viewer查看运行效果。

Feature_drapped_lines.earth: 显示国界线

Feature_clip_plane.earth: 显示透明地球+国界线

Feature_custom_filters.earth: 根据缩放级别动态显示国名

Feature_drapped_polygons.earth: 相邻国家使用不同颜色显示

Feature_models.earth: 紧贴地表绘制的三维图形

Graticule.earth: 显示经纬线及经纬线位置(包含较清晰高层数据,未穿越云层)

Ldb.earth: 在地球某一高度显示一只静态的飞机

实例

以下地图文件基于osgearth提供的数据,包含一个地球、经纬线、国界线、各国名字。

<!--
osgEarth Sample

Demonstrates feature draping using projective texturing,
i.e. "altitude-clamping: terrain-drape".
-->

<map name="Geometry Rasterizer Demo" type="round" version="2">

    <options>
        <lighting>false</lighting>
        <terrain min_lod="16"/>
    </options>

    <image name="world" driver="gdal">
        <url>../data/world.tif</url>
        <cache_policy usage="no_cache"/>
    </image>

   <model name="world_boundaries" driver="feature_geom">

        <features name="earth" driver="ogr">
            <url>../data/world.shp</url>
            <build_spatial_index>true</build_spatial_index>
        </features>

        <styles>
            <style type="text/css">
                world {
                   stroke:             #ffff00;
                   stroke-width:       5px;
                   altitude-clamping:  terrain-drape;
                }
            </style>
        </styles>

    </model>

    <extensions>
        <graticule>
            <!-- The approximate number of grid lines that you would like to see in your view extent.
                 This number, along with the resolutions list, will be used to select a resolution on each view.
             -->
            <grid_lines>10</grid_lines>

            <!-- The grid resolutions, in degrees that you want to see, all separated by a space and sorted from lowest resolution to highest -->
            <!--
            <resolutions>10 5 2.5 1.25</resolutions>
             -->

            <!-- The grid line color -->
            <color>#f7a73f70</color>

            <!-- The label color -->
            <label_color>#ffff00ff</label_color>

            <!-- Specify the line width -->
            <line_width>2</line_width>
        </graticule>
    </extensions>

    <model name="cities" driver="feature_geom">

        <features name="cities" driver="ogr">
            <url>../data/world.shp</url>

                        <!--Define a ChangeAttributeFilter, which is defined in the osgearth_featurefilter example.  This will change the cntry_name of all countries to osgEarthLand.-->
                        <change_attribute key="cntry_name" value="osgEarthLand"/>
        </features>

        <styles>
            <style type="text/css">
                cities {
                   text-provider:  annotation;
                   text-content:   [cntry_name];
                   text-priority:  [pop_cntry];
                   text-halo:      #3f3f7f;
                   text-align:     center_center;
                   text-declutter: true;
                }
            </style>
        </styles>

    </model>

</map>

第15行加载地球模型,第20行加载国界,第39行加载经纬线,第62行加载国名。

feature_labels.earth

<!--
osgEarth Sample
This shows how to label point features with an attribute.
-->

<map name="Feature Geometry Demo" type="geocentric" version="2">

    <image name="world" driver="gdal">
        <url>../data/world.tif</url>
    </image>

    <model name="cities" driver="feature_geom">

        <features name="cities" driver="ogr">
            <url>../data/world.shp</url>
        </features>

        <styles>
            <style type="text/css">
                cities {
                   text-provider: annotation;
                   text-content:  [cntry_name];
                   text-priority: [pop_cntry];
                   text-halo:     #3f3f7f;
                   text-align:    center_center;
                }
            </style>
        </styles>

    </model>

    <options lighting="false"/>

    <external>
        <decluttering>
            <out_animation_time>  0.0  </out_animation_time>
            <in_animation_time>   0.25 </in_animation_time>
            <min_animation_scale> 0.45 </min_animation_scale>
            <min_animation_alpha> 0.35 </min_animation_alpha>
            <sort_by_priority>    true </sort_by_priority>
        </decluttering>
    </external>

</map>
04-15 20:47