[原][osgEarth]添加自由飞行漫游器
//头文件里
#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]添加自由飞行漫游器的更多相关文章
- [osg][osgEarth][原]基于OE自定义自由飞行漫游器(初级版)
由于受够了OE的漫游器,想搞个可以在全球飞行的漫游器,所以就做了一个: 请无视我的起名规则······ 类头文件:EarthWalkManipulator.h #pragma once //南水之源 ...
- [osg][osgEarth][原]基于OE自定义自由飞行漫游器(第二版)
在初级版上,进行新的漫游方式调整 头文件: #pragma once //南水之源 20180101 #include <osgGA/CameraManipulator> #include ...
- [原][osg][osgEarth]EarthManipulator关于oe漫游器的handle部分解读以及修改(仿照谷歌,修改oe漫游器中focal(视角切换)功能 续 二)
bool EarthManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) ...
- [原][osgEarth]在osgearth中添加相机路径动画
在osg中添加相机动画路径请参考:http://www.cnblogs.com/lyggqm/p/8075277.html 这里的代码是在osgearth中添加相机动画路径漫游器: #include ...
- [osgearth][原]仿照谷歌,修改oe漫游器中focal(视角切换)功能
oe中的视角加速感觉好奇怪,就仿照谷歌方式去改了. 先看看oe原来的漫游器改变视角的接口: void CameraManipulator::setViewpoint(const Viewpoint&a ...
- [osg][osgEarth][osgGA][原] EarthManipulator------基于oe的相机漫游器(浅析)
知识基础:osg漫游器基础 class OSGEARTHUTIL_EXPORT EarthManipulator : public osgGA::CameraManipulator EarthMani ...
- [osg][原]自定义osgGA漫游器
相机矩阵变化基础:http://blog.csdn.net/popy007/article/details/5120158 osg漫游器原理:http://blog.csdn.net/csxiaosh ...
- OpenLayers学习笔记(三)— QML与HTML通信之 地图上点击添加自由文本
实现在地图随意点击,弹出文本输入框,输入任意文字,完成自由文本添加的功能 作者: 狐狸家的鱼 GitHub:八至 本文链接:地图上点击添加自由文本 关于如何QML与HTML通信已经在上一篇文章 QML ...
- ArcGIS for qml -添加自由文本
源码:https://github.com/sueRimn/ArcGIS-for-qml-demos 实现地图上鼠标点击后添加自由文本功能 作者: 狐狸家的鱼 Github: 八至 版权声明:如需转载 ...
随机推荐
- maven编译项目报错,提示找不到符号或程序包XXX不存在
我的原因是maven依赖的jar包都下载了,但是引用的同一个项目下其他模块jar包找不到 解决方法: 把需要的jar包在pom里添加依赖 再次运行项目,Maven Dependencies下就会多了几 ...
- Eloquent JavaScript #08# Bugs and Errors
索引 Notes strict mode js类型 js测试 Debugging Exceptions finally 异常分支 Exercise Retry The locked box Notes ...
- 一个用python简单的封装了aria2的jsonrpc中adduri的脚本
aria2是一个十分牛逼的下载神器,有时候项目需要一个很牛逼的下载中间件的话,aria2是一个不错的选择.其中支持jsonrpc和websocket的特性尤其诱人.但是python用起来还是有点不爽, ...
- 安装python3.7和PyCharm专业版
安装python3.7 安装PyCharm专业版 1.下载地址http://www.jetbrains.com/pycharm/download/,选择windows下面的Professional,点 ...
- python,pycharm安装
下载python地址:https://www.python.org/downloads/release/python-371/ 安装python ***python安装目录下的scripts加入环境变 ...
- 为什么预处理和参数化查询可以防止sql注入呢?
在传统的写法中,sql查询语句在程序中拼接,防注入(加斜杠)是在php中处理的,然后就发语句发送到mysql中,mysql其实没有太好的办法对传进来的语句判断哪些是正常的,哪些是恶意的,所以直接查询的 ...
- CentOS7 彻底关闭 IPV6
查看服务监听的IP中是否有IPv6格式的地址 netstat -tuln 如果有tcp6协议的就是有打开ip6 编辑/etc/default/grub,在GRUB_CMDLINE_LINUX加上的后面 ...
- 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 ...
- C语言动态链表数据结构实现的学生信息项目
注:此项目来源于吕鑫老师的教程 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <conio.h> u ...
- 对象new和不new的理解
1.现象 在一个线程类[QObject]中声明一个对象QTimer,[不new,直接声明],在槽函数中timer.start() 报警告:不能跨线程调用对象 2.分析 不使用new的方式,直接A a; ...