//头文件里

#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. org.springframework.beans.factory.BeanCreationException,Invocation of init method failed,Context initialization failed

    G:\javaanzhuang\apache-tomcat-\bin\catalina.bat run [-- ::,] Artifact ssm_qingmu02_web:war exploded: ...

  2. gcahce事物不够,借助binlog追上

    gcahce事物不够,借助binlog追上 宕机节点以单机集群启动,既自己作为一个集群启动,不过UUID要和旧的集群保持一致: 修复grastate.dat 文件的方式这里略,直接通过wsrep_re ...

  3. k8s device plugin

    基本概念入门: Device Manager Proposal Device plugin offical Doc(中文) device-plugins offical Doc(En) Go thro ...

  4. [c/c++] programming之路(2)、kill QQ,弹出系统对话框,吃内存等

    一.删除文件 二.盗取密码的原理 #include<stdlib.h> //杀掉QQ,然后提示网络故障,请重新登陆,弹出高仿界面,获取账号密码,然后打开QQ进行登录 void main() ...

  5. 【Python043-魔法方法:算术方法2】

    一. 反运算符 当对应的操作数不支持调用时,反运算数被调用(参考资料Lhttps://fishc.com.cn/thread-48793-1-1.html ) 1.对象(a+b)相加,如果对象a有__ ...

  6. topcoder srm 702 div1 -3

    1.给定一个$n*m$的矩阵,里面的数字是1到$n*m$的一个排列.一个$n*m$矩阵$A$对应一个$n*m$ 的01字符串,字符串的位置$i*m+j$为1当且仅当$A_{i,j}=i*m+j+1$. ...

  7. Python3基础 list len 输出元素的个数

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  8. HTTP 压力测试工具

    http_load 程序非常小,解压后也不到100K http_load以并行复用的方式运行,用以测试web服务器的吞吐量与负载.但是它不同于大多数压力测试工 具,它可以以一个单一的进程运行,一般不会 ...

  9. git用法-打补丁【转】

    本文转载自:https://www.cnblogs.com/yandufeng/p/5580765.html 1. git cherry-pick 作用:从一个branch上选择一个commit,添加 ...

  10. android设备如何进入深度休眠还能继续使用定时器【求解】

    经过试验,andriod设备进入深度休眠的时候,定时器是不能使用.但是阻止设备进入深度休眠,可以获取一把锁,但是拿了锁之后,设备不能进入休眠,系统的功耗会增加.怎么能够在系统进入休眠,定时器还能正常工 ...