OsgEarth下实现雷达波束扫描飞机动画
作者:互联网
void GraphicsView::addRadar()
{
/****************制作轨迹点数据,测试用**********************/
osg::Vec3d startPoint = osg::Vec3d(115, 18, 100000);//起始位置
queue <PlanePoint> *PlanePP = new queue <PlanePoint>;//飞机用
queue <PlanePoint> *PlanePR = new queue <PlanePoint>;//雷达用
int n = 20;
double Alltime = 10.0;
double Alldis = 10;
double _addtime = Alltime / (double)n;
double _addDis = 5 / (double)n;
double time = 0.0;
osg::Vec3d _add = osg::Vec3d(0.0, 0.0, 0.0);
for (int i = 0; i < n; i++)
{
osg::Vec3d newpoint = startPoint + _add;
PlanePoint *pPP = new PlanePoint();
pPP->point = newpoint;
pPP->time = time;
PlanePP->push(*pPP);
PlanePR->push(*pPP);
_add = _add + osg::Vec3d(_addDis, _addDis, 0.0);
time = time + _addtime;
}
radarGroup = new osg::Group;//初始化雷达节点组
/*添加雷达半球*/
osg::Vec3 radarposition = osg::Vec3(116.7176, 20.699, 10); //0点对应的地球坐标
double radarDistance = 500000;//雷达最大探测距离
//创建精细度对象,精细度越高,细分就越多
osg::Vec3d RWpoint;
m_pMapSRS->transformToWorld(radarposition, RWpoint);
osg::ref_ptr<osg::TessellationHints> hints = new osg::TessellationHints;
hints->setDetailRatio(1.0f);
osg::Geode *geodeR = new osg::Geode;
osg::ShapeDrawable* RadarShp = new osg::ShapeDrawable(new osg::Sphere(RWpoint, radarDistance), hints);
geodeR->addDrawable(RadarShp);
RadarShp->setColor(osg::Vec4(0.0, 0.0, 0.3, 0.2));
//设置雷达罩透明效果
osg::ref_ptr<osg::StateSet> statesetR = geodeR->getOrCreateStateSet();
statesetR->setMode(GL_BLEND, osg::StateAttribute::ON);//Alpha混合开启
statesetR->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);//设置透明渲染元
statesetR->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);
//statesetR->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); //取消深度测试
radarGroup->addChild(geodeR);
/********************加载雷达动画*************************/ {
/****************绘制圆锥,并将顶点平移到0点**********************/
double radarRadius = 10000;//圆锥半径
osg::Cone *Cone = new osg::Cone(osg::Vec3(0, 0, 0), radarRadius, radarDistance);//初始化,cone不能做回调
osg::Matrixd rotMat = osg::Matrixd::rotate(osg::Z_AXIS, osg::Vec3(0, 0, -1));//转180
Cone->setRotation(rotMat.getRotate());
Cone->setCenter(osg::Vec3(0, 0, 3 * radarDistance / 4));//平移,使得0点位于顶点
/****************加载圆锥**********************/
osg::Geode* geode = new osg::Geode;
osg::ShapeDrawable* shpcone = new osg::ShapeDrawable(Cone);
shpcone->setColor(osg::Vec4(0.5, 0.0, 0.0, 0.25));
geode->addDrawable(shpcone);
//设置圆锥透明效果
osg::ref_ptr<osg::StateSet> stateset = geode->getOrCreateStateSet();
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); //取消深度测试
//stateset->setRenderBinDetails(11, "RenderBin");
//试着加回调函数,解决圆锥长度的问题,先将conebufen放到飞机里面去,这样也可以试试雷达,试了好像不行
shpcone->setDataVariance(osg::Object::DYNAMIC);
//DrawableUpdateCallback p;// = new DrawableUpdateCallback();
//shpcone->setUpdateCallback(new DrawableUpdateCallback());
//设置圆锥网格模型
osg::ref_ptr<osg::PolygonMode> polyMode = new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
stateset->setAttribute(polyMode);
/****************加载圆锥1暂时没有找到骨架线和填充同时存在的接口,画两次实现**********************/
osg::Geode* geode1 = new osg::Geode;
osg::ShapeDrawable* shpcone1 = new osg::ShapeDrawable(Cone);
shpcone1->setColor(osg::Vec4(1.0, 0.0, 0.0, 0.25));//
geode1->addDrawable(shpcone1);
//设置圆锥透明效果
osg::ref_ptr<osg::StateSet> stateset2 = geode1->getOrCreateStateSet();
stateset2->setMode(GL_BLEND, osg::StateAttribute::ON);
stateset2->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
stateset2->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); //取消深度测试
//stateset2->setRenderBinDetails(11, "RenderBin2");//优先级,暂时没用
/****************加入平台**********************/
osg::MatrixTransform* mtCone = new osg::MatrixTransform();
//mtCone->addChild(geode);
mtCone->addChild(geode1);
osg::ref_ptr<GeoTransform> pGTRadar = new GeoTransform();//应该是模型移动平台的意思
radarGroup->addChild(pGTRadar);
m_pRoot->addChild(radarGroup);
pGTRadar->addChild(mtCone);
pGTRadar->setPosition(GeoPoint(m_pMapSRS, radarposition, ALTMODE_ABSOLUTE));
/****************生成雷达动画**********************/
osg::AnimationPath* animationPathRadar = rotateCone1(mtCone, m_pMapSRS, radarposition, PlanePR, radarDistance);
mtCone->setUpdateCallback(new osg::AnimationPathCallback(animationPathRadar, 0.0, 1.0));
//mtCone->addUpdateCallback(new RotateCallback(osg::Z_AXIS, 0.01));//直接用,时间可以统一,但是回看怎么操作?自己写?还不如直接用path
}
/*****************添加飞机动画****************/ {
osg::Node* glider = osgDB::readNodeFile("models\\f35c.osgb");
glider->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);
//glider->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); //取消深度测试
if (glider)
{
const osg::BoundingSphere& bs = glider->getBound();
float size = 2000;//
osg::MatrixTransform* planeMT = new osg::MatrixTransform;
planeMT->setDataVariance(osg::Object::STATIC);
planeMT->addChild(glider);
planeMT->setMatrix(planeMT->getMatrix()*osg::Matrix::scale(size, size, size));// *osg::Matrix::translate(-(bs.center()))* osg::Matrix::rotate(osg::DegreesToRadians(90.0 - earthCenter.y()), 0, 1, 0)*osg::Matrixd::translate(bs.center()));// /*osg::Matrix::rotate(osg::DegreesToRadians(90.0), 1, 0, 0) osg::Matrix::rotate(osg::DegreesToRadians(90.0), 0, 1, 0)*osg::Matrix::translate(bs.center()));///*osg::Matrix::rotate(osg::inDegrees(earthCenter.x()), 0.0f, 0.0f, 1.0f)*osg::Matrix::rotate(osg::inDegrees(90.0f - earthCenter.y()), 0.0f, 1.0f, 0.0f)* / );//
osg::ref_ptr<GeoTransform> pGTPlane = new GeoTransform();//
pGTPlane->addChild(planeMT);
radarGroup->addChild(pGTPlane);
osg::AnimationPath* animationPathPlane = createAnimationPath(PlanePP, planeMT);
//动画的关键。依然使用了回调函数,执行完{},再执行它,后面两个参数是干啥用的?
pGTPlane->setUpdateCallback(new osg::AnimationPathCallback(animationPathPlane, 0.0, 1.0));
}
}//飞机添加动画 结束
/***********窗口定位*****************/
osgEarth::Viewpoint vp("", radarposition.x(), radarposition.y(), radarposition.z(), -2.50, 0, 1.5e6);//窗口定位到
(dynamic_cast<osgEarth::Util::EarthManipulator*>(m_pViewer->getCameraManipulator()))->setViewpoint(vp);
}
osg::AnimationPath* GraphicsView::createAnimationPath(queue <PlanePoint> *PlaneP, osg::MatrixTransform *planeMT)//需要改成地球坐标系
{
osg::AnimationPath* animationPath = new osg::AnimationPath;//自动路径
animationPath->setLoopMode(osg::AnimationPath::LOOP);//设置动画模式为循环(LOOP)
/**********获取第一个点************/
osg::Vec3d FEpoint = PlaneP->front().point;
while (!PlaneP->empty())
{
double time = PlaneP->front().time;
osg::Vec3d FWpoint;
m_pMapSRS->transformToWorld(FEpoint, FWpoint);
osg::Vec3d BEpoint = PlaneP->front().point;
osg::Vec3d BWpoint;
m_pMapSRS->transformToWorld(BEpoint, BWpoint);
osg::Vec3 _vector = BWpoint - FWpoint;
osg::Matrixd rotMat = osg::Matrixd::rotate((osg::Y_AXIS), _vector);
//计算对应地面点的指天向量,方法1
GeoPoint localPoint(m_pMapSRS, BEpoint.x(), FEpoint.y(), FEpoint.z());
osg::Vec3d v3HorizonUp;//指天向量
localPoint.createWorldUpVector(v3HorizonUp);
osg::Matrixd rotMatsky = osg::Matrixd::rotate((osg::Z_AXIS), osg::Vec3(v3HorizonUp.x(), v3HorizonUp.y(), v3HorizonUp.z()));
//计算移动向量对应的旋转角
osg::Quat rotation = rotMat.getRotate();
double heading = 0; double pitch = 0; double roll = 0;
QuatToHPR(rotation, heading, pitch, roll);
//计算翻滚向量对应的旋转角,瞎猫碰上死耗子,换地方不行,尤其是在高纬度地区
osg::Quat rotation2 = (osg::Matrix::rotate(osg::DegreesToRadians(90-BEpoint.x()), 1, 0, 0)).getRotate()*(osg::Matrix::rotate(osg::DegreesToRadians(90.0 - BEpoint.y()), 0, 1, 0)).getRotate()*rotMatsky.getRotate();//
double heading2 = 0; double pitch2 = 0; double roll2 = 0;
QuatToHPR(rotation2, heading2, pitch2, roll2);
//取移动向量的偏航角和俯仰角,翻滚向量的翻滚角,合成新的旋转角,并计算对应的矩阵
osg::Quat rotation3 = HPRToQuat(heading, pitch, roll2);//合成旋转角
//将新的坐标和角度压入动画
const osg::BoundingSphere& bs = planeMT->getBound();
//因为起始点用了两次,所以这里插入动画时用了后点,相当于飞机方向用了该点后面飞行路径产生的向量,如果改前点,需要考虑左后一个点的处理,因为后面没有点了
animationPath->insert(time, osg::AnimationPath::ControlPoint(BWpoint, (osg::Matrixd::translate(-bs.center())).getRotate()*rotation3*(osg::Matrixd::translate(bs.center())).getRotate()));
PlaneP->pop();
/*for (int i = 0; i < numSamples; ++i)//步长循环
{
osg::Vec3d oldposition;
m_pMapSRS->transformToWorld(OldEarthPosition, oldposition);
//osg::Vec3 NewEarthPosition(earthPosition + osg::Vec3(yaw, yaw, 0.0f));
osg::Vec3d newposition;
m_pMapSRS->transformToWorld(NewEarthPosition, newposition);//osgearth坐标转osg坐标
//计算飞机移动的向量
double a_x = (newposition.x())- (oldposition.x());
double a_y = (newposition.y())- (oldposition.y());
double a_z =(newposition.z())- (oldposition.z());
//计算将飞机移动到向量osg::Vec3(a_x, a_y, a_z)的旋转矩阵
osg::Matrixd rotMat = osg::Matrixd::rotate((osg::Y_AXIS), osg::Vec3(a_x, a_y, a_z));
//计算对应地面点的指天向量,方法1
GeoPoint localPoint(m_pMapSRS, NewEarthPosition.x(), NewEarthPosition.y(), NewEarthPosition.z());
osg::Vec3d v3HorizonUp;//指天向量
localPoint.createWorldUpVector(v3HorizonUp);
//计算对应地面点的指天向量,方法2
//osg::EllipsoidModel* em = new osg::EllipsoidModel();
//osg::Vec3d v3HorizonUp2=(em->computeLocalUpVector(newposition.x(), newposition.y(), newposition.z()));
//计算将飞机移动到向量v3HorizonUp的旋转矩阵
osg::Matrixd rotMatsky = osg::Matrixd::rotate((osg::Z_AXIS), osg::Vec3(v3HorizonUp.x(), v3HorizonUp.y(), v3HorizonUp.z()));
//计算移动向量对应的旋转角
osg::Quat rotation = rotMat.getRotate();
double heading = 0; double pitch = 0; double roll = 0;
QuatToHPR(rotation, heading, pitch, roll);
//计算翻滚向量对应的旋转角
osg::Quat rotation2 = rotMatsky.getRotate();//
double heading2 = 0; double pitch2 = 0; double roll2 = 0;
QuatToHPR(rotation2, heading2, pitch2, roll2);
//取移动向量的偏航角和俯仰角,翻滚向量的翻滚角,合成新的旋转角,并计算对应的矩阵
osg::Quat rotation3=HPRToQuat(heading, pitch, roll2);//合成旋转角
//将新的坐标和角度压入动画
const osg::BoundingSphere& bs = modelmt->getBound();
animationPath->insert(time, osg::AnimationPath::ControlPoint(newposition, (osg::Matrixd::translate(-bs.center())).getRotate()*rotation3*(osg::Matrixd::translate(bs.center())).getRotate()));
yaw += yaw_delta;
time += time_delta;
//过程记录
/*1得到的不是欧拉角而是四元素,pitch,yaw,roll来自航空界的叫法,翻译为俯仰角,偏航角,翻滚角
2但是对于有缩放和位移的矩阵,不能直接使用上述方法, osg中提供了分解的方法
3欧拉角转四元素 只需要清楚知道旋转的顺序,和旋转轴即可,一般是通过下面这种方式来旋转,即先y轴,再x轴,再z轴
4应该是沿着前进方向逆时针翻滚,就是顺时针旋转,
5翻滚量跟纬度有关,?
6翻滚方向与经度有关,经度递增翻滚逆时针,经度递减翻滚顺时针????
7得到合成的旋转角度,在跨维度90,经度180的时候好像有点问题,暂时用不到,待后续处理
8翻滚角依然有问题,暂时先放一放
*/
/*********绘制轨迹**********/
std::vector<osg::Vec3d> m_vecPoint;
m_vecPoint.push_back(FEpoint);
m_vecPoint.push_back(BEpoint);
createLine(m_vecPoint, radarGroup);
FEpoint = BEpoint;
}
return animationPath;
}
void GraphicsView::removeRadar()
{
if (radarGroup)
{
radarGroup->removeChildren(0, radarGroup->getNumChildren());
}
m_pRoot->removeChild(radarGroup);
}
void GraphicsView::rotateCone(osg::MatrixTransform* mt, const osgEarth::SpatialReference* sr, osg::Vec3d lonlat1, osg::Vec3d lonlat2)// osg与OSGearth坐标不一致,添加矩阵变换函数。lonlat1:雷达波圆锥顶点, lonlat2:目标点
{
// 雷达波模型所在位置
osgEarth::GeoPoint geoPoint1(
sr,
lonlat1.x(),
lonlat1.y(),
lonlat1.z(),
osgEarth::ALTMODE_ABSOLUTE);
osg::Matrixd matrix1;
// 获取雷达波模型从原点变换到lonlat1位置的变换矩阵
geoPoint1.createLocalToWorld(matrix1);
// 经纬度高程到xyz的变换
osg::Vec3d world1, world2;
// geoPoint1.toWorld(world1);//等同于 sr->transformToWorld(lonlat1,world1);
sr->transformToWorld(lonlat2, world2);
// 计算轨迹点在雷达波模型坐标系下的位置
osg::Vec3 point2InRadarCoordinateSystem = world2 * osg::Matrix::inverse(matrix1);
// 在雷达波模型坐标系下,对Z轴进行旋转,与连接原点指向轨迹点方向的矢量重合,计算出此旋转矩阵
osg::Matrixd rotMat = osg::Matrixd::rotate(osg::Z_AXIS, point2InRadarCoordinateSystem - osg::Vec3(0, 0, 0));
// 将计算出的旋转矩阵赋给雷达波模型所在的mt
mt->setMatrix(rotMat);
}
osg::AnimationPath* GraphicsView::rotateCone1(osg::MatrixTransform* mt, const osgEarth::SpatialReference* sr, osg::Vec3d lonlat1, queue <PlanePoint> *PlaneP/*飞机轨迹点*/, double radarDistance)// osg与OSGearth坐标不一致,添加矩阵变换函数。lonlat1:雷达波圆锥顶点, lonlat2:目标点
{
osg::AnimationPath* animationPath = new osg::AnimationPath;//自动路径
animationPath->setLoopMode(osg::AnimationPath::LOOP);//设置动画模式为循环(LOOP)
// 雷达波模型所在位置
osgEarth::GeoPoint geoPoint1(
sr,
lonlat1.x(),
lonlat1.y(),
lonlat1.z(),
osgEarth::ALTMODE_ABSOLUTE);
osg::Matrixd matrix1;
// 获取雷达波模型从原点变换到lonlat1位置的变换矩阵
geoPoint1.createLocalToWorld(matrix1);
while (!PlaneP->empty())
{
osg::Vec3d Epoint = PlaneP->front().point;
double time = PlaneP->front().time;
osg::Vec3d Wpoint;
sr->transformToWorld(Epoint, Wpoint);// 计算轨迹点在雷达波模型坐标系下的位置
osg::Vec3 point2InRadarCoordinateSystem = Wpoint * osg::Matrix::inverse(matrix1);// 在雷达波模型坐标系下,对Z轴进行旋转,与连接原点指向轨迹点方向的矢量重合,计算出此旋转矩阵
osg::Matrixd rotMat = osg::Matrixd::rotate(osg::Z_AXIS, point2InRadarCoordinateSystem - osg::Vec3(0, 0, 0));// 将计算出的旋转矩阵赋给雷达波模型所在的mt
//double newDistance = osgEarth::GeoMath::distance(lonlat1, Epoint, sr);//新的半径
osg::Vec3d wop;
sr->transformToWorld(lonlat1, wop);
double newDistance= sqrt((Wpoint.x() - wop.x())*(Wpoint.x() - wop.x()) + (Wpoint.y() - wop.y())*(Wpoint.y() - wop.y())+ (Wpoint.z() - wop.z())*(Wpoint.z() - wop.z()));
double scale1 = newDistance / radarDistance;
osg::Vec3d scale2 = osg::Vec3d(1, 1, scale1);
animationPath->insert(time, osg::AnimationPath::ControlPoint(lonlat1/*位置不变,没啥用*/, rotMat.getRotate(), scale2));
PlaneP->pop();
//调整雷达波束长度,不起作用,cone只是图形数据,似乎需要再绘制成图形,在这里回调不行
/*double radarDistance = osgEarth::GeoMath::distance(lonlat1, Epoint, sr);
Cone->setHeight(radarDistance);
Cone->setCenter(osg::Vec3(0, 0, 3 * radarDistance / 4));//平移,使得0点位于顶点*/
}
return animationPath;
}
#ifndef RADARMAP_H
#define RADARMAP_H
#include "framehandle.h"
#include "graphicsview.h"
class RadarMap : public QObject
{
Q_OBJECT
public:
RadarMap(GraphicsView* view, QObject *parent = nullptr);
~RadarMap();
void setGeomtry(int x = 20, int y = 20, int width = 320, int height = 180)
{
m_iX = x; m_iY = y; m_iWidth = width; m_iHeight = height;
}
void enableMap();
void disableMap();
private slots:
void slotFrameViewport(const osg::Vec3d& pos);
private:
void createMap();
// 根据世界坐标去经纬度坐标
osg::Vec3d getLonLat(const osg::Vec3d& worldPos);
private:
// 显示的区域
int m_iX;
int m_iY;
int m_iWidth;
int m_iHeight;
// HUD相机
osg::ref_ptr<osg::Camera> m_pHUDCamera;
GraphicsView* m_pOSGViewer;
osg::ref_ptr<osg::Group> m_pGroup;
FrameHandle* m_pFrameHandle;
// 十字架,显示当前视点位置
osg::ref_ptr<osg::Geode> m_pGeodeCross;
osg::ref_ptr<osg::Vec3dArray> m_pVertexCross;
};
#endif // RADARMAP_H
#include "radarmap.h"
RadarMap::RadarMap(GraphicsView* view, QObject* parent/* = nullptr*/)
: m_pOSGViewer(view), QObject(parent)
{
m_pHUDCamera = nullptr;
m_pGroup = new osg::Group;
m_pOSGViewer->getRoot()->addChild(m_pGroup);//添加到大的视图中
m_pFrameHandle = new FrameHandle;
m_pGeodeCross = nullptr;
setGeomtry();
}
RadarMap::~RadarMap()
{
}
void RadarMap::enableMap()
{
if (m_pHUDCamera == nullptr)
{
createMap();
}
m_pGroup->addChild(m_pHUDCamera);
m_pOSGViewer->getOSGViewer()->addEventHandler(m_pFrameHandle);
connect(m_pFrameHandle, SIGNAL(signalFrameViewport(const osg::Vec3d&)),
this, SLOT(slotFrameViewport(const osg::Vec3d&)));
}
void RadarMap::disableMap()
{
if (m_pHUDCamera)
{
m_pGroup->removeChild(m_pHUDCamera);
m_pHUDCamera = nullptr;
disconnect(m_pFrameHandle, SIGNAL(signalFrameViewport(const osg::Vec3d&)),
this, SLOT(slotFrameViewport(const osg::Vec3d&)));
m_pOSGViewer->getOSGViewer()->removeEventHandler(m_pFrameHandle);
}
}
void RadarMap::slotFrameViewport(const osg::Vec3d& pos)
{
if (m_pGeodeCross == nullptr)
{
m_pGeodeCross = new osg::Geode;
osg::ref_ptr<osg::Geometry> pGeometry = new osg::Geometry;
// 使用VBO,每帧实时的修改数据
pGeometry->setUseVertexBufferObjects(true);
m_pVertexCross = new osg::Vec3dArray;
pGeometry->setVertexArray(m_pVertexCross);
osg::ref_ptr<osg::Vec3Array> normal = new osg::Vec3Array;
normal->push_back(osg::Vec3(0, 0, 1));
pGeometry->setNormalArray(normal, osg::Array::BIND_OVERALL);
osg::ref_ptr<osg::Vec4Array> color = new osg::Vec4Array;
color->push_back(osg::Vec4(0.8, 0.8, 0.8, 1));
pGeometry->setColorArray(color, osg::Array::BIND_OVERALL);
pGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, 4));
m_pGeodeCross->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
m_pGeodeCross->getOrCreateStateSet()->setAttribute(
new osg::LineWidth(0.5), osg::StateAttribute::ON);
m_pGeodeCross->addDrawable(pGeometry);
m_pHUDCamera->addChild(m_pGeodeCross);
}
osg::Vec3d mapPos = getLonLat(pos);
// 经纬度是-180~180,-90~90,保证算出的是0~360和0~180
double x = (mapPos.x() + 180.0) * m_iWidth / 360.0;
double y = (mapPos.y() + 90.0) * m_iHeight / 180.0;
// 更新缓冲区数据
m_pVertexCross->clear();
m_pVertexCross->push_back(osg::Vec3d(x, y - 5, 0));
m_pVertexCross->push_back(osg::Vec3d(x, y + 5, 0));
m_pVertexCross->push_back(osg::Vec3d(x - 5, y, 0));
m_pVertexCross->push_back(osg::Vec3d(x + 5, y, 0));
m_pVertexCross->dirty();
}
void RadarMap::createMap()
{
m_pHUDCamera = new osg::Camera;
// 设置投影矩阵
m_pHUDCamera->setProjectionMatrixAsOrtho2D(m_iX, m_iWidth, m_iY, m_iHeight);
// 设置视口矩阵
m_pHUDCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
m_pHUDCamera->setViewMatrix(osg::Matrix::identity());
// 只清除深度缓冲区
m_pHUDCamera->setClearMask(GL_DEPTH_BUFFER_BIT);
// 设置HUD相机在主相机之后渲染
m_pHUDCamera->setRenderOrder(osg::Camera::POST_RENDER);
// HUD相机不获取Event的焦点
m_pHUDCamera->setAllowEventFocus(false);
m_pHUDCamera->setViewport(m_iX, m_iY, m_iWidth, m_iHeight);
// 增加HUD相机的渲染内容,即map
osg::ref_ptr<osg::Geode> pGeode = new osg::Geode;
// 创建纹理
osg::ref_ptr<osg::Geometry> pGeometry = new osg::Geometry;
{
// 顶点
osg::ref_ptr<osg::Vec3Array> verArray = new osg::Vec3Array;
verArray->push_back(osg::Vec3(0, 0, -1));
verArray->push_back(osg::Vec3(m_iWidth, 0, -1));
verArray->push_back(osg::Vec3(m_iWidth, m_iHeight, -1));
verArray->push_back(osg::Vec3(0, m_iHeight, -1));
pGeometry->setVertexArray(verArray);
// 纹理坐标
osg::ref_ptr<osg::Vec2Array> textArray = new osg::Vec2Array;
textArray->push_back(osg::Vec2(0, 0));
textArray->push_back(osg::Vec2(1, 0));
textArray->push_back(osg::Vec2(1, 1));
textArray->push_back(osg::Vec2(0, 1));
pGeometry->setTexCoordArray(0, textArray);
// 法线,指向用户,即y轴
osg::ref_ptr < osg::Vec3Array> normal = new osg::Vec3Array;
normal->push_back(osg::Vec3(0, 1, 0));
pGeometry->setNormalArray(normal);
pGeometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
// 指定绘制方式
pGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
// 纹理图片
osg::ref_ptr<osg::Image> image = osgDB::readImageFile(
"./Images/image_formats/png/world.png");// E:\osg\data\Images\image_formats\png
if (image)
{
osg::ref_ptr<osg::Texture2D> text2D = new osg::Texture2D;
text2D->setImage(image);
text2D->setDataVariance(osg::Object::DYNAMIC);
pGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(
0, text2D, osg::StateAttribute::ON);
}
}
// 创建HUD相机的边框
osg::ref_ptr<osg::Geometry> pGeoBorder = new osg::Geometry;
{
// 顶点
osg::ref_ptr<osg::Vec3Array> verBorder = new osg::Vec3Array;
verBorder->push_back(osg::Vec3(1.0, 1.0, 0));
verBorder->push_back(osg::Vec3(m_iWidth - 1.0, 1.0, 0));
verBorder->push_back(osg::Vec3(m_iWidth - 1.0, m_iHeight - 1.0, 0));
verBorder->push_back(osg::Vec3(1.0, m_iHeight - 1.0, 0));
pGeoBorder->setVertexArray(verBorder);
// 法线
osg::ref_ptr<osg::Vec3Array> normalBorder = new osg::Vec3Array;
normalBorder->push_back(osg::Vec3(0.0, 0.0, 1.0));
pGeoBorder->setNormalArray(normalBorder, osg::Array::BIND_OVERALL);
// 颜色
osg::ref_ptr<osg::Vec4Array> color = new osg::Vec4Array;
color->push_back(osg::Vec4(1, 0.8, 0, 1));
pGeoBorder->setColorArray(color);
pGeoBorder->addPrimitiveSet(new osg::DrawArrays(osg::DrawArrays::LINE_LOOP, 0, 4));
pGeoBorder->getOrCreateStateSet()->setAttribute(new osg::LineWidth(2), osg::StateAttribute::ON);
}
pGeode->addDrawable(pGeometry);
pGeode->addDrawable(pGeoBorder);
pGeode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
m_pHUDCamera->addChild(pGeode);
}
osg::Vec3d RadarMap::getLonLat(const osg::Vec3d& worldPos)
{
osg::Vec3d vecPos = osg::Vec3d();
if (m_pOSGViewer)
{
m_pOSGViewer->getSRS()->getEllipsoid()->convertXYZToLatLongHeight(
worldPos.x(), worldPos.y(), worldPos.z(), vecPos.y(), vecPos.x(), vecPos.z());
vecPos.x() = osg::RadiansToDegrees(vecPos.x());
vecPos.y() = osg::RadiansToDegrees(vecPos.y());
}
return vecPos;
}
时间久了,代码整理的不是很全,请见谅。
标签:动画,double,Vec3d,OsgEarth,Vec3,new,波束,ptr,osg 来源: https://blog.csdn.net/sailingw/article/details/114648871