//头文件里

#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. maven编译项目报错,提示找不到符号或程序包XXX不存在

    我的原因是maven依赖的jar包都下载了,但是引用的同一个项目下其他模块jar包找不到 解决方法: 把需要的jar包在pom里添加依赖 再次运行项目,Maven Dependencies下就会多了几 ...

  2. Eloquent JavaScript #08# Bugs and Errors

    索引 Notes strict mode js类型 js测试 Debugging Exceptions finally 异常分支 Exercise Retry The locked box Notes ...

  3. 一个用python简单的封装了aria2的jsonrpc中adduri的脚本

    aria2是一个十分牛逼的下载神器,有时候项目需要一个很牛逼的下载中间件的话,aria2是一个不错的选择.其中支持jsonrpc和websocket的特性尤其诱人.但是python用起来还是有点不爽, ...

  4. 安装python3.7和PyCharm专业版

    安装python3.7 安装PyCharm专业版 1.下载地址http://www.jetbrains.com/pycharm/download/,选择windows下面的Professional,点 ...

  5. python,pycharm安装

    下载python地址:https://www.python.org/downloads/release/python-371/ 安装python ***python安装目录下的scripts加入环境变 ...

  6. 为什么预处理和参数化查询可以防止sql注入呢?

    在传统的写法中,sql查询语句在程序中拼接,防注入(加斜杠)是在php中处理的,然后就发语句发送到mysql中,mysql其实没有太好的办法对传进来的语句判断哪些是正常的,哪些是恶意的,所以直接查询的 ...

  7. CentOS7 彻底关闭 IPV6

    查看服务监听的IP中是否有IPv6格式的地址 netstat -tuln 如果有tcp6协议的就是有打开ip6 编辑/etc/default/grub,在GRUB_CMDLINE_LINUX加上的后面 ...

  8. Codeforces 839A Arya and Bran

    Bran and his older sister Arya are from the same house. Bran like candies so much, so Arya is going ...

  9. C语言动态链表数据结构实现的学生信息项目

    注:此项目来源于吕鑫老师的教程 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <conio.h> u ...

  10. 对象new和不new的理解

    1.现象 在一个线程类[QObject]中声明一个对象QTimer,[不new,直接声明],在槽函数中timer.start() 报警告:不能跨线程调用对象 2.分析 不使用new的方式,直接A a; ...