//头文件里
#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;
}