OSG之坐标系节点

553 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 27 天

1 坐标系节点

坐标系节点(osg::CoordinateSystemNode)继承自 osg::Group节点,它的主要作用是使一个场景的 对象关联一个坐标系统。通常的坐标系统类型有WKT、PROJ4和USGS。它通常与osg::EllipsoidModel 节点一起使用,osg:EllipsoidModel 节点(椭圆体模型节点)主要用来模拟天体,如太阳、行星和月亮等,其默认情况下是地球体。

osg::EllipsoidModel 节点还有一个作用就是实现经纬度与坐标之间的转换,这样可以实现天体椭圆体模型子节点的精确定位。当读者建立地球数据库时,这个节点会非常有用,可以根据地球椭圆体模型实现子节点的精确定位。

对于WKT坐标系,可能很多人都不理解,它的定义包括以下几个方面:

  • 一个全局的坐标系统名称。
  • 一个地理坐标系统的名称。
  • 一个数据识别器。
  • 一个椭球体的名称、长半轴、扁率。
  • 本初子午线的名称和它到格林尼治的偏移量。
  • 投影类型(如横轴墨卡托投影)。
  • 投影参数(如中央子午线)。
  • 单位名称,到米或弧度的转换因数。
  • 各轴的名称和顺序。
  • 由授权单位(如EPSG)预先定义的大多数坐标系统的代码。

这样解释可能比较好理解,关于地理坐标系的知识,读者可以查阅相关资料。

osg::GoordinateSystemNode的继承关系图如下图所示。

2.png

2 坐标系节点示例

坐标系节点(osg::CoordinateSystemNode)示例的代码如程序清单所示。

#include <osgViewer/Viewer>

#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/CoordinateSystemNode>
#include <osg/ShapeDrawable>

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

#include <osgUtil/Optimizer>

#include "utility.h"

#include <iostream>


// 绘制一个地球
osg::ref_ptr<osg::Node> createEarth()
{
	// 创建一个球体
	osg::ref_ptr<osg::ShapeDrawable> sd = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0, 0.0, 0.0), osg::WGS_84_RADIUS_POLAR));

	// 添加到叶子节点
	osg::ref_ptr<osg::Geode> geode = new osg::Geode;
	geode->addDrawable(sd.get());

	// 设置纹理
	std::string filename(GetCurrentPath() + "\\Data\\Images\\land_shallow_topo_2048.jpg");
	geode->getOrCreateStateSet()->setTextureAttributeAndModes(0, new osg::Texture2D(osgDB::readImageFile(filename)));

	// 创建坐标系节点
	osg::ref_ptr<osg::CoordinateSystemNode> csn = new osg::CoordinateSystemNode;
	// 设置椭圆体模型,默认的坐标系WGS_84
	csn->setEllipsoidModel(new osg::EllipsoidModel);
	// 添加子节点
	csn->addChild(geode.get());
	return csn.get();
}

int main()
{
	// 创建Viewer对象,场景浏览器
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();

	// 创建场景组根节点
	osg::ref_ptr<osg::Group> root = new osg::Group();

	// 添加到场景
	root->addChild(createEarth());

	// 优化场景数据
	osgUtil::Optimizer optimizer;
	optimizer.optimize(root.get());

	// 设置窗口大小
	setWindowSize(viewer.get(), 600, 500, "CoordinateSystemNode");

	// 设置场景数据
	viewer->setSceneData(root.get());
	// 初始化并创建窗口
	viewer->realize();
	// 开始渲染
	viewer->run();

	return 0;
}

效果图

3.PNG

动态效果图

1.gif

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 27 天