osgGA库提供很多的操作器,本文例子继承了CameraManipulator,利用其矩阵变换和事件处理的接口编写了自己用来实现模拟驾驶效果的操作器DrivingManipulator。
类中的关键函数:
* 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& aa); //事件处理函数
* void updateBoatPosition(const osgGA::GUIEventAdapter& ea); //更新船舶和相机位置
void DrivingManipulator::setByMatrix(const osg::Matrixd& matrix)
{
}
void DrivingManipulator::setByInverseMatrix(const osg::Matrixd& matrix)
{
}
osg::Matrixd DrivingManipulator::getMatrix() const
{
osg::Matrixd mat = _boatPosition->getMatrix();
return osg::Matrixd::rotate(osg::Vec4(1.f, 0.f, 0.f, 1)) *
mat * osg::Matrixd::translate(osg::Vec3d((-67 * cosf(osg::DegreesToRadians(90 - _boatAngle))),
(-67 * sinf(osg::DegreesToRadians(90 - _boatAngle))), 30.5f));
}
osg::Matrixd DrivingManipulator::getInverseMatrix() const
{
osg::Matrixd mat = _boatPosition->getMatrix();
osg::Vec3 position = (new osg::Matrixd(mat))->getTrans();
osg::notify(osg::NOTICE) << "position: " << position << std::endl;
return osg::Matrixd::inverse(osg::Matrixd::rotate(osg::Vec4(1.f, 0.f, 0.f, 1)) *
mat * osg::Matrixd::translate(osg::Vec3d((-67 * cosf(osg::DegreesToRadians(90 - _boatAngle))),
(-67 * sinf(osg::DegreesToRadians(90 - _boatAngle))), 30.5f)));
}
void DrivingManipulator::updateBoatPosition(const osgGA::GUIEventAdapter& ea)
{
osg::notify(osg::NOTICE) << "time: " << ea.time() << std::endl;
float currentTime = ea.time();
//获取世界坐标
osg::Matrixd* mct = getWorldCoords(_boatPosition);
//osg::Matrixd boatMt = _boatPosition->getMatrix();
osg::Vec3 position = mct->getTrans();
//计算船运动后的位置
position += osg::Vec3(_boatSpeed * cosf(osg::DegreesToRadians(90 - _boatAngle)),
_boatSpeed*sinf(osg::DegreesToRadians(90 - _boatAngle)), 0);
//旋转船身
osg::Matrix rot;
rot.makeIdentity();
rot.makeRotate(cosf(currentTime / 10)*osg::DegreesToRadians(0.05f), osg::Vec3f(1.0f, 0.0f, 0.0f), //绕X轴旋转
cosf(currentTime/4)*osg::DegreesToRadians(3.f), osg::Vec3f(0.0f, 1.0f, 0.0f), //绕Y轴旋转
0 - osg::DegreesToRadians(_boatAngle), osg::Vec3f(0.0f, 0.0f, 1.0f)); //绕Z轴旋转
//得到新位置的矩阵
osg::Matrix newMat = rot * osg::Matrix::translate(position);
//更新位置
_boatPosition->setMatrix(newMat);
}
bool DrivingManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
switch (ea.getEventType())
{
case (osgGA::GUIEventAdapter::KEYDOWN) : //处理键盘按钮按下事件
{
if (ea.getKey() == 0xFF52)
{
/*前进*/
_boatSpeed += 0.1;
}
else if (ea.getKey() == 0xFF54)
{
/*后退*/
_boatSpeed -= 0.1;
}
else if (ea.getKey() == 0xFF53)
{
/*右转*/
_boatAngle += 1;
}
else if (ea.getKey() == 0xFF51)
{
/*左转*/
_boatAngle -= 1;
}
break;
}
case (osgGA::GUIEventAdapter::FRAME): //用于更新船和相机的位置
{
updateBoatPosition(ea);
break;
}
default:
break;
}
return true;
}