//头文件里

#define MANIPULATOR_W 0x01
#define MANIPULATOR_A 0x02
#define MANIPULATOR_S 0x04
#define MANIPULATOR_D 0x08
#define MANIPULATOR_R 0x10
#define MANIPULATOR_F 0x20


#define MANIPULATOR_MAX 127

/*

osgEarth::Map g_map;//这个用自己定义的

osgEarth::ElevationQuery sElevationQuery(g_map);//少的定义

*/

//所有漫游器都必须实现的4个纯虚函数
virtual void setByMatrix(const osg::Matrixd& matrix); //设置相机的位置姿态矩阵
virtual void setByInverseMatrix(const osg::Matrixd& matrix) {} //设置相机的视图矩阵
virtual osg::Matrixd getMatrix() const; //获取相机的姿态矩阵
virtual osg::Matrixd getInverseMatrix() const; //获取相机的视图矩阵 //所有操作在这里响应
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us); void reFreshSawEarth();//在当前经纬度,姿态回正:1.视点向地面 2.头部向正北
void reFreshSawSkyline(osg::Vec3d eye=osg::Vec3d(,,));//在当前经纬度,头部回正:1.视点中心不变 2.头部向天 osg::Vec3d _eye; //视点位置
osg::Quat _rotate; //旋转姿态
osg::Quat _rotateNew; //旋转姿态
osg::ref_ptr<osg::Node> _root; osg::observer_ptr<osg::Node> _node;
osg::observer_ptr<osgEarth::MapNode> _mapNode; osg::ref_ptr<const osgEarth::SpatialReference> _srs; float _speed; //速度
float _speedBase;
float _speedMultiple; //速度倍数
float _timerRoll;
bool _updateAltitude;
bool _updateRollStart; //更新滚转
bool _updateRoll; //更新滚转
bool _openStree;
// Internal event stack comprising last two mouse events.
osg::ref_ptr<const osgGA::GUIEventAdapter> _ga_t1;
osg::ref_ptr<const osgGA::GUIEventAdapter> _ga_t0;
//cpp文件
void setByMatrix(const osg::Matrixd& matrix)//设置相机的位置姿态矩阵
{
gMinpulatorContgrol = ;
_eye = matrix.getTrans();
osg::Vec3d v3Eye, v3Center, v3Up;
v3Eye = _eye;//使用相机实际位置
osg::Vec3d v3EyeLonLat;
_srs->transformFromWorld(v3Eye, v3EyeLonLat);
//先获取当前位置的经纬度,再获取当前正上,正北
osg::Matrix mRealAttitude; if (v3EyeLonLat.z() < )//距离地面1千万米以内需要矫正
//reFreshSawSkyline();
_updateRoll = true;
else
reFreshSawEarth();
} osg::Matrixd getInverseMatrix() const
{
osg::Matrix mat;
mat.setRotate(-_rotate);
mat.preMultTranslate(-_eye);
return mat;
//return osg::Matrixd::inverse(getMatrix());
}void setNode(osg::Node* node)
{
// you can only set the node if it has not already been set, OR if you are setting
// it to NULL. (So to change it, you must first set it to NULL.) This is to prevent
// OSG from overwriting the node after you have already set on manually.
if (node == 0L || !_node.valid())
{
_root = node;
_node = node;
_mapNode = 0L;
_srs = 0L; established(); osg::Matrix matrixGood1;
GeoPoint point1(_srs, , , 10000.0);
point1.createLocalToWorld(matrixGood1); _eye = matrixGood1.getTrans(); osg::Vec3d worldup;
point1.createWorldUpVector(worldup); osg::Matrix mat;
matrixGood1.getRotate().get(mat);
osg::Vec3d eye, center, up;
mat.getLookAt(eye, center, up);
mat.makeLookAt(eye, -worldup, up); _rotate = mat.getRotate(); }
}
void reFreshSawSkyline(osg::Vec3d eye)
{
osg::Vec3d v3Eye;
osg::Vec3d v3EyeLonLat;
v3Eye = _eye;//使用相机实际位置 if (eye != osg::Vec3d(, , ))
{
v3Eye += eye;
} _srs->transformFromWorld(v3Eye, v3EyeLonLat);
//先获取当前位置的经纬度,再获取当前正上,正北 if (v3EyeLonLat.z() < )//距离地面1千万米以内需要矫正
{
osg::Matrix mRealAttitude;
GeoPoint gEyeGeo(_srs, v3EyeLonLat.x(), v3EyeLonLat.y(), v3EyeLonLat.z());
gEyeGeo.createLocalToWorld(mRealAttitude); osg::Vec3d v3HorizonUp;//指天向量
gEyeGeo.createWorldUpVector(v3HorizonUp); _rotate.get(mRealAttitude);//要使用当前相机的姿态
osg::Vec3d theEye,v3Center, v3Up;
mRealAttitude.getLookAt(theEye, v3Center, v3Up);//获取新的位置和姿态
osg::Vec3d v3Direction = v3Center - theEye;
mRealAttitude.makeLookAt(osg::Vec3d(, , ), v3Direction, v3HorizonUp);
_rotate = mRealAttitude.getRotate(); } //_eye = v3Eye;
} void reFreshSawEarth()
{
osg::Vec3d v3Eye, v3Center, v3Up;
v3Eye = _eye;//使用相机实际位置
osg::Vec3d v3EyeLonLat;
_srs->transformFromWorld(v3Eye, v3EyeLonLat);
//先获取当前位置的经纬度,再获取当前正上,正北
osg::Matrix mRealAttitude; if (v3EyeLonLat.z() < )//v3EyeLonLat.z()是眼点实际海拔
v3EyeLonLat.z() = ;//将海拔0以下的物体拉到海拔100米 GeoPoint gEyeGeo(_srs, v3EyeLonLat.x(), v3EyeLonLat.y(), v3EyeLonLat.z());
gEyeGeo.createLocalToWorld(mRealAttitude); osg::Vec3d v3HorizonUp;//指天向量
gEyeGeo.createWorldUpVector(v3HorizonUp); _eye = mRealAttitude.getTrans(); mRealAttitude.getLookAt(v3Eye, v3Center, v3Up);//获取新的位置和姿态 osg::Matrix mDeviationAttitude;//向北位置偏移0.00001纬度,为了计算正北方向
GeoPoint gDeviationEyeGeo(_srs, v3EyeLonLat.x(), v3EyeLonLat.y() + 0.00001, v3EyeLonLat.z());
gDeviationEyeGeo.createLocalToWorld(mDeviationAttitude);
osg::Vec3d v3DeviationNorthPoint = mDeviationAttitude.getTrans();
osg::Vec3d v3NorthHeadUp = v3DeviationNorthPoint - v3Eye;
v3NorthHeadUp.normalize();//指北向量 if (v3EyeLonLat.y() < 89.99999 && v3EyeLonLat.y() > -90.0)
{
mRealAttitude.makeLookAt(osg::Vec3d(, , ), -v3HorizonUp, v3NorthHeadUp);
}
_rotate = mRealAttitude.getRotate();
} bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us)
{
bool handled = false; switch (ea.getEventType())
{
case(osgGA::GUIEventAdapter::FRAME):
{
if (gMinpulatorContgrol & MANIPULATOR_MAX)
{
osg::Vec3d v3Direction; //视点方向
osg::Matrix mCameraQuat;
osg::Vec3d v3Eye, v3Center, v3Up;
_rotate.get(mCameraQuat);
mCameraQuat.getLookAt(v3Eye, v3Center, v3Up);//这里的v3Eye不是实际相机的位置,而是0,0,0
v3Direction = v3Center - v3Eye;
v3Direction.normalize();
/*********************************************************/
osg::Vec3d RealEye = _eye;
osg::Vec3d testHight = v3Direction*;
double _DvalueHight = 0.0;
{
osg::Vec3d testLonLat1, testLonLat2;
_srs->transformFromWorld(RealEye, testLonLat1);
RealEye = _eye;
osg::Vec3d testEye = RealEye + testHight;
_srs->transformFromWorld(testEye, testLonLat2);
_DvalueHight = abs(testLonLat2.z() - testLonLat1.z()); if (_DvalueHight < )//趋近水平使用水平方向
{
testLonLat2.z() = testLonLat1.z();
_srs->transformToWorld(testLonLat2, testEye);
v3Direction = testEye - RealEye;
v3Direction.normalize();
}
} osg::Vec3d v3CrossVector = v3Up^v3Direction;
v3CrossVector.normalize(); /*********************************************************/
//计算地面高度
osg::Vec3d v3EyeLonLat;
v3Eye = _eye;
_srs->transformFromWorld(v3Eye, v3EyeLonLat);
double mAltitude = float height = osg::clampBetween(v3EyeLonLat.z() - mAltitude, 100.0, 1000000.0);
_speed = height / 200.0;//根据离地面高度计算当前速度值
RealEye = _eye;
if (gMinpulatorContgrol & MANIPULATOR_W)
{
RealEye += v3Direction * _speed *_speedMultiple * _speedBase;
_updateAltitude = false;
}if (gMinpulatorContgrol & MANIPULATOR_A)
{
RealEye += v3CrossVector * _speed *_speedMultiple * _speedBase;
_updateAltitude = false;
}if (gMinpulatorContgrol & MANIPULATOR_S)
{
RealEye -= v3Direction * _speed *_speedMultiple * _speedBase;
_updateAltitude = false;
}if (gMinpulatorContgrol & MANIPULATOR_D)
{
RealEye -= v3CrossVector * _speed *_speedMultiple * _speedBase;
_updateAltitude = false;
}if (gMinpulatorContgrol & MANIPULATOR_R)
{
//_eye += v3Up * _speed *_speedMultiple * _speedBase;
v3EyeLonLat.z() += _speed *_speedMultiple * _speedBase;
osg::Vec3d newv3Eye;
_srs->transformToWorld(v3EyeLonLat, newv3Eye);
RealEye = newv3Eye;
_updateAltitude = false;
}if (gMinpulatorContgrol & MANIPULATOR_F)
{
//_eye -= v3Up * _speed *_speedMultiple * _speedBase;
v3EyeLonLat.z() -= _speed *_speedMultiple * _speedBase;
osg::Vec3d newv3Eye;
_srs->transformToWorld(v3EyeLonLat, newv3Eye);
RealEye = newv3Eye;
_updateAltitude = false;
} _eye = RealEye;
//reFreshSawSkyline(RealEye);
} if (_updateRoll)
{
osg::Vec3d v3Eye;
osg::Vec3d v3EyeLonLat;
v3Eye = _eye;//使用相机实际位置
_srs->transformFromWorld(v3Eye, v3EyeLonLat);
//先获取当前位置的经纬度,再获取当前正上,正北 if (v3EyeLonLat.z() < )//距离地面1千万米以内需要矫正
{
osg::Matrix mRealAttitude;
GeoPoint gEyeGeo(_srs, v3EyeLonLat.x(), v3EyeLonLat.y(), v3EyeLonLat.z());
gEyeGeo.createLocalToWorld(mRealAttitude); osg::Vec3d v3HorizonUp;//指天向量
gEyeGeo.createWorldUpVector(v3HorizonUp); _rotate.get(mRealAttitude);//要使用当前相机的姿态
osg::Vec3d theEye, v3Center, v3Up;
mRealAttitude.getLookAt(theEye, v3Center, v3Up);//获取新的位置和姿态
osg::Vec3d v3Direction = v3Center - theEye;
mRealAttitude.makeLookAt(osg::Vec3d(, , ), v3Direction, v3HorizonUp);
_rotateNew = mRealAttitude.getRotate();
_updateRoll = false;
_updateRollStart = true;
_timerRoll = 0.0;
}
else
{
_updateRoll = false;
}
} if (_updateRollStart)
{
_timerRoll += 0.01;
if (_timerRoll > 1.0)
{
_timerRoll = 1.0;
_updateRollStart = false;
}
_rotate.slerp(_timerRoll, _rotate, _rotateNew);
} if (_updateAltitude)
{
//每帧调节高度
osg::Vec3d newEye = _eye;
osg::Vec3d v3EyeLonLat;
_srs->transformFromWorld(newEye, v3EyeLonLat);
double _mAltitude = v3EyeLonLat.z();

         double mAltitude = sElevationQuery.getElevation(GeoPoint(g_map.getSRS(), fLon, fLat, 0, ALTMODE_ABSOLUTE));

      double interprolationAltitude = mAltitude - _mAltitude;
if (interprolationAltitude > )
{
interprolationAltitude /= 10.0;
v3EyeLonLat.z() += interprolationAltitude;
}
else if (interprolationAltitude > 0.1)
{
v3EyeLonLat.z() += 0.1;
}
else
{
_updateAltitude = false;
}
osg::Vec3d FinalEye;
_srs->transformToWorld(v3EyeLonLat, FinalEye);
_eye = FinalEye;
}
}break;
case(osgGA::GUIEventAdapter::PUSH):
{
}break;
case(osgGA::GUIEventAdapter::RELEASE):
{
flushMouseEventStack();
}break;
case(osgGA::GUIEventAdapter::DRAG):
{
if (calcMovement(ea))//根据鼠标在屏幕中的位置调整相机转向
{
//reFreshSawSkyline();
_updateRoll = true;
us.requestRedraw();
return true;
}
};
case(osgGA::GUIEventAdapter::SCROLL)://由于已经每帧都调整姿态,所以手动滚动不需要了
{
osg::Vec3d v3Direction; //视点方向
osg::Matrix mCameraQuat;
osg::Vec3d v3Eye, v3Center, v3Up;
_rotate.get(mCameraQuat);
mCameraQuat.getLookAt(v3Eye, v3Center, v3Up);//这里的v3Eye不是实际相机的位置,而是0,0,0
v3Direction = v3Center - v3Eye;
v3Direction.normalize();
osg::Vec3d v3CrossVector = v3Up^v3Direction;
v3CrossVector.normalize();
switch (ea.getScrollingMotion())
{
case osgGA::GUIEventAdapter::ScrollingMotion::SCROLL_UP:
{
_eye += v3Direction * _speed *_speedMultiple;
//reFreshSawSkyline();
_updateRoll = true;
}break;
case osgGA::GUIEventAdapter::ScrollingMotion::SCROLL_DOWN:
{
_eye -= v3Direction * _speed *_speedMultiple;
//reFreshSawSkyline();
_updateRoll = true;
}break;
}
//reFreshSawSkyline(); return true;
}break;
case (osgGA::GUIEventAdapter::KEYDOWN):
{
if (ea.getKey() == 'r' || ea.getKey() == 'R')//往头部前进
{
gMinpulatorContgrol |= MANIPULATOR_R;
}
if (ea.getKey() == 'f' || ea.getKey() == 'F')//往尾部后退
{
gMinpulatorContgrol |= MANIPULATOR_F;
}
if (ea.getKey() == 'w' || ea.getKey() == 'W' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)//前进
{
gMinpulatorContgrol |= MANIPULATOR_W;
}
if (ea.getKey() == 's' || ea.getKey() == 'S' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Down)//后退
{
gMinpulatorContgrol |= MANIPULATOR_S;
}
if (ea.getKey() == 'a' || ea.getKey() == 'A' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)//左移
{
gMinpulatorContgrol |= MANIPULATOR_A;
}
if (ea.getKey() == 'd' || ea.getKey() == 'D' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)//右移
{
gMinpulatorContgrol |= MANIPULATOR_D;
}
if (ea.getKey() == '-' || ea.getKey() == '_' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Down)//减10倍移动速度
{
_speedBase /= 10.0;
if (_speedBase < 0.1)
{
_speedBase = 0.1;
}
}
if (ea.getKey() == '=' || ea.getKey() == '+' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Up)//加10倍移动速度
{
_speedBase *= 10.0;
if (_speedBase > 1000.0)
{
_speedBase = 1000.0;
}
} if (ea.getKey() == 'h' || ea.getKey() == 'H')//在当前经纬度,姿态回正:1.视点向地面 2.头部向正北
{
reFreshSawEarth();
}
if (ea.getKey() == 'g' || ea.getKey() == 'G')//在当前经纬度,头部回正:1.视点中心不变 2.头部向天
{
reFreshSawSkyline();
}
if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_L || ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_R)
{
_speedMultiple = 10.0;
}
}break;
case (osgGA::GUIEventAdapter::KEYUP):
{
if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_L || ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_R)
{
_speedMultiple = 1.0;
}
if (ea.getKey() == 'a' || ea.getKey() == 'A' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)//左移
{
gMinpulatorContgrol &= ~MANIPULATOR_A;
_updateAltitude = true;
}
if (ea.getKey() == 'd' || ea.getKey() == 'D' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)//右移
{
gMinpulatorContgrol &= ~MANIPULATOR_D;
_updateAltitude = true;
}
if (ea.getKey() == 'w' || ea.getKey() == 'W' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)//前进
{
gMinpulatorContgrol &= ~MANIPULATOR_W;
_updateAltitude = true;
}
if (ea.getKey() == 'q' || ea.getKey() == 'Q' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Up)//往头部前进
{
gMinpulatorContgrol &= ~MANIPULATOR_R;
_updateAltitude = true;
}
if (ea.getKey() == 'e' || ea.getKey() == 'E' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Down)//往尾部后退
{
gMinpulatorContgrol &= ~MANIPULATOR_F;
_updateAltitude = true;
}
if (ea.getKey() == 's' || ea.getKey() == 'S' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Down)//后退
{
gMinpulatorContgrol &= ~MANIPULATOR_S;
_updateAltitude = true;
}
}break;
default:
break;
} return handled;
}

[原][osgEarth]添加自由飞行漫游器的更多相关文章

  1. [osg][osgEarth][原]基于OE自定义自由飞行漫游器(初级版)

    由于受够了OE的漫游器,想搞个可以在全球飞行的漫游器,所以就做了一个: 请无视我的起名规则······ 类头文件:EarthWalkManipulator.h #pragma once //南水之源 ...

  2. [osg][osgEarth][原]基于OE自定义自由飞行漫游器(第二版)

    在初级版上,进行新的漫游方式调整 头文件: #pragma once //南水之源 20180101 #include <osgGA/CameraManipulator> #include ...

  3. [原][osg][osgEarth]EarthManipulator关于oe漫游器的handle部分解读以及修改(仿照谷歌,修改oe漫游器中focal(视角切换)功能 续 二)

    bool EarthManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) ...

  4. [原][osgEarth]在osgearth中添加相机路径动画

    在osg中添加相机动画路径请参考:http://www.cnblogs.com/lyggqm/p/8075277.html 这里的代码是在osgearth中添加相机动画路径漫游器: #include ...

  5. [osgearth][原]仿照谷歌,修改oe漫游器中focal(视角切换)功能

    oe中的视角加速感觉好奇怪,就仿照谷歌方式去改了. 先看看oe原来的漫游器改变视角的接口: void CameraManipulator::setViewpoint(const Viewpoint&a ...

  6. [osg][osgEarth][osgGA][原] EarthManipulator------基于oe的相机漫游器(浅析)

    知识基础:osg漫游器基础 class OSGEARTHUTIL_EXPORT EarthManipulator : public osgGA::CameraManipulator EarthMani ...

  7. [osg][原]自定义osgGA漫游器

    相机矩阵变化基础:http://blog.csdn.net/popy007/article/details/5120158 osg漫游器原理:http://blog.csdn.net/csxiaosh ...

  8. OpenLayers学习笔记(三)— QML与HTML通信之 地图上点击添加自由文本

    实现在地图随意点击,弹出文本输入框,输入任意文字,完成自由文本添加的功能 作者: 狐狸家的鱼 GitHub:八至 本文链接:地图上点击添加自由文本 关于如何QML与HTML通信已经在上一篇文章 QML ...

  9. ArcGIS for qml -添加自由文本

    源码:https://github.com/sueRimn/ArcGIS-for-qml-demos 实现地图上鼠标点击后添加自由文本功能 作者: 狐狸家的鱼 Github: 八至 版权声明:如需转载 ...

随机推荐

  1. QT开发基础教程

    http://www.qter.org/portal.php?mod=view&aid=11

  2. django中的模型详解-1

    在说明django模型之前,首先来说明一下django的生命周期,也就是一个请求到达django是如何处理的.[暂时不包含中间件] 浏览器的请求---->到达django中的urls中找到对应的 ...

  3. leetcode [34] Find First and Last Position of Element in Sorted Array

    Given an array of integers nums sorted in ascending order, find the starting and ending position of ...

  4. git获取一个版本相对于另一个版本新增,修改,删除的文件

    git diff --name-status 00ef237ef0f0a4b8bd9609c2b6d570472028212d abf13b4d58abbb05a7d494cdc205d025978a ...

  5. dell win 10笔记本关闭多媒体键,启用功能键的快捷方式

    自从使用win 10之后,在使用快捷键方面就没有win 7之前来的顺手,比如F8切换投影仪,F5/F6调试等等.特地搜了下,使用Fn+Esc可以在功能键和多媒体键之间切换.

  6. MySql概念(二)

    一.Sql规范? sql是Structured Query Language(结构化查询语言)的缩写.SQL是专为数据库而建立的操作命令集,是一种功能齐全的数据库语言. 在使用它时,只需要发出“做什么 ...

  7. 动态规划之97 Interleaving String

    题目链接:https://leetcode-cn.com/problems/interleaving-string/description/ 参考链接:https://blog.csdn.net/u0 ...

  8. 启动maven的web项目

    一.可以通过在pom中配置tomcat插件. 首先要确保你的仓库里有这个插件,然后按如下配置. <build> <plugins> <!-- 配置Tomcat插件 --& ...

  9. Linux使用——Linux命令——Linux文件压缩和解压使用记录

    一:tar(可压缩可解压) tar命令是Unix/Linux系统中备份文件的可靠方法,几乎可以工作于任何环境中,它的使用权限是所有用户.但是tar本身只是一个文件打包工具,只有和其他工具组合时才具有压 ...

  10. openwrt中在软件包中定义PKG_INSTALL将会发生什么?

    答: 将会使用默认软件包安装方式,相关代码如下 . 在include/package.mk中: Build/Install=$(if $(PKG_INSTALL),$(call Build/Insta ...