船舶模拟驾驶

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;
}

船舶模拟驾驶结果

船舶模拟驾驶结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值