osgearth_los示例,创建了模型动画路径、透视的用法。透视的顾名思义:两个点连线,从A到B,视线不被遮挡,则绘制绿色,视线被遮挡的部分,则设置为红色。此示例,加载earth文件时,需要加载地形文件。
执行命令:osgearth_losd.exe earth_image\world.earth
圆形内的飞机,整个圆形,如果被遮挡,则绘制红色,不被遮挡,则绘制绿色。直线连接的两个飞机,从左下角的飞机点向右上角的飞机点看去,当被遮挡后,则后面的线都绘制红色。最下面的两个扫描圆形也是如此。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace osgEarth;
using namespace osgEarth::Util;
// 运动路径
osg::AnimationPath* createAnimationPath(const GeoPoint& pos, const SpatialReference* mapSRS, float radius, double looptime)
{
// set up the animation path
osg::AnimationPath* animationPath = new osg::AnimationPath;// 设置动画路径对象
animationPath->setLoopMode(osg::AnimationPath::LOOP);// 循环播放模式
int numSamples = 40;// 采样点数
double delta = osg::PI * 2.0 / (double)numSamples;
//Get the center point in geocentric 获取大地测量坐标系下的中心点
GeoPoint mapPos = pos.transform(mapSRS);
osg::Vec3d centerWorld;
mapPos.toWorld( centerWorld );
// 是否为投影坐标系
bool isProjected = mapSRS->isProjected();
// 设置向上向量
osg::Vec3d up = isProjected ? osg::Vec3d(0,0,1) : centerWorld;
up.normalize();
//Get the "side" vector 获取side向量
osg::Vec3d side = isProjected ? osg::Vec3d(1,0,0) : up ^ osg::Vec3d(0,0,1);
// 时间间隔
double time=0.0f;
double time_delta = looptime/(double)numSamples;
// 第一个位置、第一个旋转矩阵
osg::Vec3d firstPosition;
osg::Quat firstRotation;
for (unsigned int i = 0; i < (unsigned int)numSamples; i++)
{
double angle = delta * (double)i;
osg::Quat quat(angle, up );
osg::Vec3d spoke = quat * (side * radius);
osg::Vec3d end = centerWorld + spoke;
osg::Quat makeUp;
makeUp.makeRotate(osg::Vec3d(0,0,1), up);
osg::Quat rot = makeUp;
animationPath->insert(time,osg::AnimationPath::ControlPoint(end,rot));// 插入时间和控制点
if (i == 0)
{
firstPosition = end;
firstRotation = rot;
}
time += time_delta;
}
animationPath->insert(time, osg::AnimationPath::ControlPoint(firstPosition, firstRotation));// 插入最后一个点
return animationPath; // 返回路径动画
}
// 调用 创建路径动画方法,且将路径动画对象放入 位置矩阵,并为 位置矩阵 设置更新回调
osg::Node* createPlane(osg::Node* node, const GeoPoint& pos, const SpatialReference* mapSRS, double radius, double time)
{
osg::MatrixTransform* positioner = new osg::MatrixTransform;
positioner->addChild( node );
osg::AnimationPath* animationPath = createAnimationPath(pos, mapSRS, radius, time);
positioner->setUpdateCallback( new osg::AnimationPathCallback(animationPath, 0.0, 1.0));
return positioner;
}
// 存储ExtentNode访问器??
class CacheExtentNodeVisitor : public osg::NodeVisitor
{
public:
CacheExtentNodeVisitor(GeoExtent& extent):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ),
_extent(extent)
{
}
void apply(osg::Node& node)
{
TerrainTileNode* tile = dynamic_cast(&node);
if (tile && tile->getKey().valid())
{
if (tile->getKey().getExtent().intersects(_extent) && tile->getKey().getLevelOfDetail() < 11)
{
// Set this tile to not expire.
tile->setMinimumExpirationTime(DBL_MAX);
OE_NOTICE << "Preloading children for " << tile->getKey().str() << std::endl;
tile->loadChildren();
}
}
traverse(node);
}
GeoExtent _extent;
};
int
main(int argc, char** argv)
{
osg::ArgumentParser arguments(&argc,argv);
osgViewer::Viewer viewer(arguments);
// load the .earth file from the command line.
osg::ref_ptr earthNode = osgDB::readNodeFiles( arguments );
if (!earthNode.valid())
{
OE_NOTICE << "Unable to load earth model" << std::endl;
return 1;
}
osg::Group* root = new osg::Group();
osgEarth::MapNode * mapNode = osgEarth::MapNode::findMapNode( earthNode.get() );
if (!mapNode)
{
OE_NOTICE << "Could not find MapNode " << std::endl;
return 1;
}
osgEarth::Util::EarthManipulator* manip = new EarthManipulator();
viewer.setCameraManipulator( manip );
root->addChild( earthNode );
//viewer.getCamera()->addCullCallback( new AutoClipPlaneCullCallback(mapNode));
osg::Group* losGroup = new osg::Group();
losGroup->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);// 渲染方式:透明
losGroup->getOrCreateStateSet()->setAttributeAndModes(new osg::Depth(osg::Depth::ALWAYS, 0, 1, false));
root->addChild(losGroup);
// so we can speak lat/long:
const SpatialReference* mapSRS = mapNode->getMapSRS();
const SpatialReference* geoSRS = mapSRS->getGeographicSRS();// 地理坐标系
//Create a point to point LineOfSightNode.
// 创建 可用于显示点对点视线计算的节点los
LinearLineOfSightNode* los = new LinearLineOfSightNode(
mapNode,
GeoPoint(geoSRS, -121.665, 46.0878, 1258.00, ALTMODE_ABSOLUTE),
GeoPoint(geoSRS, -121.488, 46.2054, 3620.11, ALTMODE_ABSOLUTE) );
losGroup->addChild( los );
//Create an editor for the point to point line of sight that allows you to drag the beginning and end points around.
//This is just one way that you could manipulator the LineOfSightNode.
// 为los添加编辑器
LinearLineOfSightEditor* p2peditor = new LinearLineOfSightEditor( los );
root->addChild( p2peditor );
//Create a relative point to point LineOfSightNode.
// 再创建一个比los低一些的 relativeLOS
LinearLineOfSightNode* relativeLOS = new LinearLineOfSightNode(
mapNode,
GeoPoint(geoSRS, -121.2, 46.1, 10, ALTMODE_RELATIVE),
GeoPoint(geoSRS, -121.488, 46.2054, 10, ALTMODE_RELATIVE) );
losGroup->addChild( relativeLOS );
// 为 relativeLOS 添加编辑器
LinearLineOfSightEditor* relEditor = new LinearLineOfSightEditor( relativeLOS );
root->addChild( relEditor );
//Create a RadialLineOfSightNode that allows you to do a 360 degree line of sight analysis.
// 可用于显示径向视线计算的节点 radial
// radial 允许进行360度视线分析。
RadialLineOfSightNode* radial = new RadialLineOfSightNode( mapNode );
radial->setCenter( GeoPoint(geoSRS, -121.515, 46.054, 847.604, ALTMODE_ABSOLUTE) );
radial->setRadius( 2000 );
radial->setNumSpokes( 100 ); // 设置径向视线计算中的轮辐数。
losGroup->addChild( radial );
// 为 radial 添加编辑器
RadialLineOfSightEditor* radialEditor = new RadialLineOfSightEditor( radial );
losGroup->addChild( radialEditor );
//Create a relative RadialLineOfSightNode that allows you to do a 360 degree line of sight analysis.
RadialLineOfSightNode* radialRelative = new RadialLineOfSightNode( mapNode );
radialRelative->setCenter( GeoPoint(geoSRS, -121.2, 46.054, 10, ALTMODE_RELATIVE) );
radialRelative->setRadius( 3000 );
radialRelative->setNumSpokes(60);
losGroup->addChild( radialRelative );
RadialLineOfSightEditor* radialRelEditor = new RadialLineOfSightEditor( radialRelative );
losGroup->addChild( radialRelEditor );
//Load a plane model. 添加一个飞机模型 cessna赛斯纳,飞行器公司
osg::ref_ptr< osg::Node > plane = osgDB::readRefNodeFile("../data/cessna.osgb.50,50,50.scale");
//Create 2 moving planes 创建两个移动飞机
osg::Node* plane1 = createPlane(plane.get(), GeoPoint(geoSRS, -121.656, 46.0935, 4133.06, ALTMODE_ABSOLUTE), mapSRS, 5000, 40);
osg::Node* plane2 = createPlane(plane.get(), GeoPoint(geoSRS, -121.321, 46.2589, 1390.09, ALTMODE_ABSOLUTE), mapSRS, 3000, 25);
root->addChild( plane1 );
root->addChild( plane2 );
//Create a LineOfSightNode that will use a LineOfSightTether callback to monitor
//the two plane's positions and recompute the LOS when they move
LinearLineOfSightNode* tetheredLOS = new LinearLineOfSightNode( mapNode);
losGroup->addChild( tetheredLOS );
tetheredLOS->setUpdateCallback( new LineOfSightTether( plane1, plane2 ) );
//Create another plane and attach a RadialLineOfSightNode to it using the RadialLineOfSightTether
osg::Node* plane3 = createPlane(plane.get(), GeoPoint(geoSRS, -121.463, 46.3548, 1348.71, ALTMODE_ABSOLUTE), mapSRS, 10000, 5);
losGroup->addChild( plane3 );
RadialLineOfSightNode* tetheredRadial = new RadialLineOfSightNode( mapNode );
tetheredRadial->setRadius( 5000 );
//This RadialLineOfSightNode is going to be filled, so set some alpha values for the colors so it's partially transparent
tetheredRadial->setFill( true );
tetheredRadial->setGoodColor( osg::Vec4(0,1,0,0.3) );
tetheredRadial->setBadColor( osg::Vec4(1,0,0,0.3) );
tetheredRadial->setNumSpokes( 100 );
losGroup->addChild( tetheredRadial );
tetheredRadial->setUpdateCallback( new RadialLineOfSightTether( plane3 ) );
// 设置视角信息
osgEarth::Viewpoint vp;
vp.name() = "Mt Ranier";
vp.focalPoint()->set(geoSRS, -121.488, 46.2054, 0, ALTMODE_ABSOLUTE);
vp.pitch() = -50.0;
vp.range() = 100000;
manip->setHomeViewpoint( vp );// 设置home视角
viewer.setSceneData( root );
// add some stock OSG handlers:
viewer.addEventHandler(new osgViewer::StatsHandler());
viewer.addEventHandler(new osgViewer::WindowSizeHandler());
viewer.addEventHandler(new osgViewer::ThreadingHandler());
viewer.addEventHandler(new osgViewer::LODScaleHandler());
viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
/*
TerrainTileNodeVisitor v;
root->accept(v);
*/
// 下面的节点遍历代码,导致程序容易崩溃,暂时没看出这段代码有什么用,所以先注释掉
// GeoPoint center(geoSRS, -121.656, 46.0935, 4133.06, ALTMODE_ABSOLUTE);
//GeoExtent extent(geoSRS, center.x() - 0.5, center.y() - 0.5, center.x() + 0.5, center.y() + 0.5);
//CacheExtentNodeVisitor v(extent);
//root->accept(v);
while (!viewer.done())
{
viewer.frame();
}
return 0;
}