OsgEarth中设置模型运动路径,并绘制雷达扫描、动态实时绘制运动轨迹、跟随彩带

OsgEarth中设置模型运动路径,并绘制雷达扫描、动态实时绘制运动轨迹、跟
随彩带
⼯程结构
#BuildRader/BuildRaderCallback 主要⽤来处理雷达相关操作
#CreateTrackCallback 主要是⽤来实时绘制飞机历史轨迹
#TrailerCallback 主要是飞机飞⾏彩带
#ViewerWidget 主要是窗体相关,并初始化
需求
⾸先我们在场景中加载⼀个机场模型、⼀个飞机模型,将飞机沿着跑道⽅向放置于机场之中,根据我们设置的关键点的位置信息飞机,飞⾏过程中有雷达扫描飞机下⽅,飞机尾带跟随飞机运动,并实时绘制飞机的历史航迹。
加载机场和飞机
void CViewerWidget::addAirport()
{
m_rpCoordSystem =new osg::CoordinateSystemNode;//创建坐标系节点
m_rpCoordSystem->setEllipsoidModel(new osg::EllipsoidModel());//设置设置椭圆体模型
//加载机场
m_rpnodeAirport = osgDB::readNodeFile("D:/Code/src/model/airport.ive");
m_rpmtAirport =new osg::MatrixTransform;
m_rpmtAirport->addChild(m_rpnodeAirport);
m_rpRoot->addChild(m_rpmtAirport);
/
/设置机场矩阵
osg::Matrixd mtTemp;
m_rpCoordSystem->getEllipsoidModel()->computeLocalToWorldTransformFromLatLongHeight(osg::DegreesToRadians(34.3762), osg::DegreesToRadia ns(109.1263),460, mtTemp);
m_rpmtAirport->setMatrix(mtTemp);//根据经、维、⾼得到飞机场想要的矩阵
//加载飞机
m_rpnodeAirFly = osgDB::readNodeFile("D:/Code/src/model/B737.ive");
m_rpmtFlyself =new osg::MatrixTransform;
m_rpmtFlyself->setMatrix(osg::Matrixd::scale(10,10,10)*osg::Matrixd::rotate(3*osg::PI_4,osg::Vec3(0,0,1)));
m_rpmtFlyself->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);//设置属性,光照法线
m_rpmtFlyself->addChild(m_rpnodeAirFly);
m_rpmtFlyself->addChild(m_pBuildRader->BuildRader(500,300).get());
m_rpmtFly =new osg::MatrixTransform;
m_rpmtFly->addChild(m_rpmtFlyself);
m_rpRoot->addChild(m_rpmtFly);
//设置飞机矩阵
m_rpCoordSystem->getEllipsoidModel()->computeLocalToWorldTransformFromLatLongHeight(osg::DegreesToRadians(34.3834), osg::DegreesToRadia ns(109.1347),537, mtTemp);
m_rpmtFly->setMatrix(mtTemp);
}
创建飞机历史航迹
void CViewerWidget::BuildHistoryRoute(osg::MatrixTransform* scaler ,float lineWidth)
{
osg::ref_ptr<osg::Group> rpgroup =new osg::Group;
scaler->addUpdateCallback(new CreateTrackCallback(rpgroup,scaler,lineWidth));
囊袋m_rpRoot->addChild(rpgroup);
}
设置飞机视⾓跟随并设置飞⾏路径
void CViewerWidget::DoAPreLine()
{
osg::ref_ptr<osg::Vec4Array> rpvaTemp =new osg::Vec4Array;
rpvaTemp->push_back(osg::Vec4(109.1347,34.3834,537,50));
rpvaTemp->push_back(osg::Vec4(109.1174,34.3686,567,500));
rpvaTemp->push_back(osg::Vec4(109.1173,34.3685,566,800));
rpvaTemp->push_back(osg::Vec4(108.8794,34.1944,3000,800));
rpvaTemp->push_back(osg::Vec4(107.1302,34.3941,5000,500));
rpvaTemp->push_back(osg::Vec4(108.9387,34.9202,8000,200));
rpvaTemp->push_back(osg::Vec4(109.5066,34.51,3000,200));
rpvaTemp->push_back(osg::Vec4(109.1347,34.3834,537,200));
m_rpAnimationPath =CreateAirPath(rpvaTemp);
}
void CViewerWidget::DoPreLine()
{
m_rpmtFly->setUpdateCallback(new osg::AnimationPathCallback(m_rpAnimationPath,0.0,1.0));
//设置视⾓跟踪
m_rpEarthManipulator->setViewpoint(osgEarth::Viewpoint(109.1347,34.3834,0,24.261,-21.6,1000),5); m_rpEarthManipulator->setTetherNode(m_rpnodeAirFly);
}
创建飞机飞⾏彩带
void CViewerWidget::BuildRibbon(int size, osg::MatrixTransform* scaler ,int ribbonWidth) {
osg::ref_ptr<osg::Geometry> rpgeom =new osg::Geometry;
//设置顶点
osg::ref_ptr<osg::Vec3Array> rpvec3Vertex =new osg::Vec3Array(size);
//设置颜⾊
osg::ref_ptr<osg::Vec4Array> rpvec4Color =new osg::Vec4Array(size);
for(unsigned int i =0;i <size-1;i+=2)
{
(*rpvec3Vertex)[i]= osg::Vec3(0,0,0);
(*rpvec3Vertex)[i+1]= osg::Vec3(0,0,0);
float falpha =sinf(osg::PI *(float)i /(float)size);
(*rpvec4Color)[i]= osg::Vec4(m_vec3RibbonColor,falpha);
(*rpvec4Color)[i+1]= osg::Vec4(m_vec3RibbonColor,falpha);
}
//场景数据动态改变
rpgeom->setDataVariance(osg::Object::DYNAMIC);
/
/禁⽤显⽰列表,动态更新不安全
rpgeom->setUseDisplayList(false);
//使⽤VBO模式
rpgeom->setUseVertexBufferObjects(true);
rpgeom->setVertexArray(rpvec3Vertex);
rpgeom->setColorArray(rpvec4Color);
rpgeom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
rpgeom->addPrimitiveSet(new osg::DrawArrays(GL_QUAD_STRIP,0,size));
osg::ref_ptr<osg::Geode> rpgeode =new osg::Geode;
rpgeode->addDrawable(rpgeom);
//灯光、透明度
rpgeom->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
rpgeom->getOrCreateStateSet()->setMode(GL_BLEND,osg::StateAttribute::ON);
rpgeom->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); scaler->addUpdateCallback(new CTrailerCallback(rpgeom,size,ribbonWidth));
m_rpRoot->addChild(rpgeode);
}
计算飞机飞⾏姿态
//根据输⼊的控制点,输出⼀个路径,格式为(经、纬、⾼、速)
osg::AnimationPath* CViewerWidget::CreateAirPath( osg::Vec4Array* ctrl )
{
osg::ref_ptr<osg::AnimationPath> rpAnimationPath =new osg::AnimationPath;
rpAnimationPath->setLoopMode(osg::AnimationPath::NO_LOOPING);
double dshuiPingAngle=0.0;//⽔平⽅向需要转的⾓度
double dchuiZhiAngle =0.0;//垂直⽅向需要转的⾓度
double time =0;蛭石板
osg::Matrix matrix;
//当前点
osg::Vec3d Vec3positionCur;
//下⼀点
osg::Vec3d Vec3positionNext;
for(osg::Vec4Array::iterator iter = ctrl->begin(); iter != ctrl->end(); iter++)
{
//下⼀个点
osg::Vec4Array::iterator iter2 = iter;
osg::Vec4Array::iterator iter2 = iter;
iter2 ++;
//如果只有两个点
if(iter2 == ctrl->end())
{
break;
}
//将经纬度转换到世界坐标系⾥⾯为了计算竖直⽅向的坐标
double x, y, z;
m_rpCoordSystem->getEllipsoidModel()->convertLatLongHeightToXYZ(osg::DegreesToRadians(iter->y()), osg::DegreesToRadians(iter->x()), iter->z(), x, y, z);
Vec3positionCur = osg::Vec3(x, y, z);
m_rpCoordSystem->getEllipsoidModel()->convertLatLongHeightToXYZ(osg::DegreesToRadians(iter2->y()), osg::DegreesToRadians(iter2->x()), iter2->z( ), x, y, z);
Vec3positionNext = osg::Vec3(x, y, z);
//求出⽔平夹⾓经度相同
if(iter->x()== iter2->x())
{
dshuiPingAngle = osg::PI_2;
}
else
{
dshuiPingAngle =atan((iter2->y()- iter->y())/(iter2->x()- iter->x()));
if(iter2->x()> iter->x())
{
dshuiPingAngle += osg::PI;
}
}
//求垂直夹⾓⾼度⼀致
if(iter->z()== iter2->z())
{
dchuiZhiAngle =0;
}
else
{
//经纬度⼀致,⾼度不⼀致
深水采样器
if(0==sqrt(pow(dGetDis(Vec3positionCur, Vec3positionNext),2))-pow((iter2->z()- iter->z()),2))
{hktv警戒线
dchuiZhiAngle = osg::PI_2;
}
else
{
//求出⾼度差
dchuiZhiAngle =atan((iter2->z()- iter->z())/sqrt(pow(dGetDis(Vec3positionCur, Vec3positionNext),2))-pow((iter2->z()- iter->z()),2));
}
if(dchuiZhiAngle>=osg::PI_2)
{
dchuiZhiAngle = osg::PI_2;
}
if(dchuiZhiAngle <=-osg::PI_2)
{
dchuiZhiAngle =-osg::PI_2;
}
}
//求飞机的变换矩阵
m_rpCoordSystem->getEllipsoidModel()->computeLocalToWorldTransformFromLatLongHeight(osg::DegreesToRadians(iter->y()), osg::DegreesToRadia ns(iter->x()), iter->z(), matrix);
m_quatRotation.makeRotate(0, osg::Vec3(1.0,0.0,0.0), dchuiZhiAngle+osg::PI_2, osg::Vec3(0.0,1.0,0.0), dshuiPingAngle-osg::PI_4, osg::Vec3(0.0,0.0 ,1.0));
matrix.preMultRotate(m_quatRotation);
rpAnimationPath->insert(time, osg::AnimationPath::ControlPoint(Vec3positionCur, Rotate()));
//把下⼀个点的时间求出来
time +=dGetRunTime(Vec3positionCur, Vec3positionNext, iter2->w());
完美分割
}
//只有两个点时
rpAnimationPath->insert(time, osg::AnimationPath::ControlPoint(Vec3positionNext, Rotate()));
lease();
}
double CViewerWidget::dGetRunTime( osg::Vec3d from,osg::Vec3d to,double speed )
{
if(speed ==0)
{
return1000000000;
}
else
{
return dGetDis(from,to)/speed;非安全
}
}
double CViewerWidget::dGetDis( osg::Vec3d from,osg::Vec3d to )
{
return std::sqrt((to.x()- from.x())*(to.x()- from.x())+(to.y()- from.y())*(to.y()- from.y())+(to.z()- from.z())*(to.z()- from.z()));
}
其中飞机飞⾏姿态的计算,如何从当前点到下⼀个点,这⾥输⼊的位置信息osg::Vec4Array* ctrl是经度、维度、⾼度、速度,在这⾥我们需要计算飞机机头左右的转向⾓和飞机机头向上、向下的俯仰⾓,为了⽅便理解,我画了⼀个草图
1. 其中,飞机在A点 ,下⼀个关键点在B点,⾸先,我们要明⽩飞机怎样才能飞到B点,⾸先,飞机机头要进⾏⽔平转向⼀定的⾓度和
AC同向,然后向上垂直转向,和AB同向,这样,才可以按照航迹正确的飞到B点。
2. ⾸先我们计算飞机的⽔平转向的⾓度,⾓度1的tan值等于A B两点的维度差的值/经度差的值,其中要进⾏考虑,经度相同时,成90
度直⾓。
3. 然后计算飞机的垂直转向⾓度,⾸先考虑,经纬度不⼀致,⾼度⼀致,然后考虑经纬度⼀致,⾼度不⼀致,也就是第⼆个点在第⼀个
点正上⽅的特殊情况。⾓度2的tan值就等于A B 两点的⾼度差/距离。
TrailerCallback.h

本文发布于:2024-09-21 03:22:54,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/4/101931.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:飞机   设置   绘制
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议