OSG获取鼠标点选事件的位置

原创 2015年07月08日 22:13:36

OSG点选操作的思路是从osgGA::GUIEventHandler继承,并重新实现虚函数virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);。获取到点选信息后,此处我们不进行处理,而是单一的传出去,由外部需要此点选信息的地方进行处理。对于传出信息,我选择了Qt的信号槽操作,因而,在继承osgGA::GUIEventHandler的同时,我们还需要继承QObject。
代码如下:pickhandle.h

class PickHandle : public QObject, public osgGA::GUIEventHandler
{
    Q_OBJECT
public:
    PickHandle(const osgEarth::SpatialReference* srs);
    ~PickHandle();

protected:
    virtual bool handle(const osgGA::GUIEventAdapter& ea,
        osgGA::GUIActionAdapter& aa);

private:
    osg::Vec3d getPos(const osgGA::GUIEventAdapter& ea,
        osgGA::GUIActionAdapter& aa, osg::Vec3d& pos);

signals:
    // 经纬度信息
    void signalPicked(osg::Vec3d pos);
    void signalMoving(osg::Vec3d pos);

    // 世界坐标信息
    void signalPickedXYZ(osg::Vec3d pos);
    void signalMovingXYZ(osg::Vec3d pos);

    void signalRightPicked();

private:
    osg::Vec3d m_vecPostion;
    const osg::EllipsoidModel* m_pEllipsoid;
};

此处提供了世界坐标和经纬度坐标两套信息供外部选择。
实现代码:pickhandle.cpp

PickHandle::PickHandle(const osgEarth::SpatialReference* srs)
{
    m_pEllipsoid = srs->getGeodeticSRS()->getEllipsoid();
}

PickHandle::~PickHandle()
{

}

bool PickHandle::handle(const osgGA::GUIEventAdapter& ea,
    osgGA::GUIActionAdapter& aa)
{
    // 存储经纬度信息
    osg::Vec3d vecPos;
    switch (ea.getEventType())
    {
        // 点击事件
        case osgGA::GUIEventAdapter::PUSH:
        {
            osg::Vec3d pos = getPos(ea, aa, vecPos);
            // 鼠标左键
            if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
            {
                m_vecPostion = pos;
            }
            break;
        }

        // 鼠标移动事件
        case osgGA::GUIEventAdapter::MOVE:
        {
            osg::Vec3d pos = getPos(ea, aa, vecPos);
            emit signalMoving(vecPos);
            emit signalMovingXYZ(pos);
            break;
        }

        // 鼠标释放事件
        case osgGA::GUIEventAdapter::RELEASE:
        {
            osg::Vec3d pos = getPos(ea, aa, vecPos);
            // 鼠标左键
            if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
            {
                // 如果释放的点和点击的点同一,则发送单击事件发生的位置
                if (m_vecPostion == pos && m_vecPostion != osg::Vec3d(0, 0, 0))
                {
                    emit signalPicked(vecPos);
                    emit signalPickedXYZ(pos);
                }
            }
            else if (ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)
            {
                emit signalRightPicked();
            }
            break;
        }
    }

    return false;
}

osg::Vec3d PickHandle::getPos(const osgGA::GUIEventAdapter& ea,
    osgGA::GUIActionAdapter& aa, osg::Vec3d& pos)
{
    pos = osg::Vec3d(0, 0, 0);
    osgViewer::Viewer* pViewer = dynamic_cast<osgViewer::Viewer*>(&aa);
    if (pViewer == NULL)
    {
        return osg::Vec3d(0, 0, 0);
    }
    // 获取当前点
    osgUtil::LineSegmentIntersector::Intersections intersection;
    double x = ea.getX();
    double y = ea.getY();
    pViewer->computeIntersections(ea.getX(), ea.getY(), intersection);
    osgUtil::LineSegmentIntersector::Intersections::iterator iter
        = intersection.begin();
    if (iter != intersection.end())
    {
        m_pEllipsoid->convertXYZToLatLongHeight(
            iter->getWorldIntersectPoint().x(), iter->getWorldIntersectPoint().y(), iter->getWorldIntersectPoint().z(),
            pos.y(), pos.x(), pos.z());
        pos.x() = osg::RadiansToDegrees(pos.x());
        pos.y() = osg::RadiansToDegrees(pos.y());
        return iter->getWorldIntersectPoint();
    }
    return osg::Vec3d(0, 0, 0);
}

我在处理PUSH和RELEASE事件时,只有两者的点完全一致,我才认为发生了点选操作,否则则忽略此事件。

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chlk118/article/details/46809611

OSG中屏幕坐标和世界坐标的转化

屏幕-------->世界 可以使用osgUtil::SceneView::ProjectWindowIntoObject()来计算 bool SceneView::projectWindowInto...
  • wang15061955806
  • wang15061955806
  • 2016-06-08 09:55:43
  • 2363

osg 屏幕坐标和世界坐标转换

//屏幕-〉世界: osgUtil::SceneView::projectWindowIntoObject //或者自己运算 Matrix VPW = camera-〉getViewMatrix() ...
  • zsq306650083
  • zsq306650083
  • 2016-01-22 16:19:17
  • 2554

OSG学习笔记16 - 对点选物体平移(鼠标点选物体)(物体随鼠标移动)(屏幕坐标转世界坐标)

之前的一篇博文是有一篇对点选物体进行平移、缩放旋转。那一篇是很简单的调用了OSG中定义的一些dragger,但这些dragger都有坐标轴或者tapbox等在模型上,与我最近要做的事情的需求不同。网上...
  • u011310341
  • u011310341
  • 2016-11-16 14:42:05
  • 1586

OSG鼠标选择求交

OSG鼠标选择求交 ////求交方法一:(用WINDOW坐标值,在相机下求交)            //osg::ref_ptr picker = new osgUtil::LineSegmen...
  • tmljs1988
  • tmljs1988
  • 2012-07-31 14:25:51
  • 11220

OSG中获取视点的世界坐标

OSG中获取视点的世界坐标: (1)osg::Vec3 vPosEye, vCenter, vUp;      cameraMaster->getViewMatrixAsLookAt( vPosE...
  • tmljs1988
  • tmljs1988
  • 2012-07-31 13:54:36
  • 8875

osg中三维模型的位置变换

对模型的平移和旋转等操作是我们在做三维软件开发时必然会解决的事情。但是由于基本变换默认是以世界坐标系的原点为变换中心,所以我们在进行平移旋转等操作时往往会发现其并非如我们想象的那样去执行。举个简单的例...
  • wxx19945
  • wxx19945
  • 2017-05-30 08:46:08
  • 1076

使用osg获取模型的世界坐标下的包围盒

  • 2011年05月12日 10:36
  • 1.84MB
  • 下载

osg动态修改坐标

osg动态修改坐标
  • HelloEarth_
  • HelloEarth_
  • 2017-11-16 16:52:27
  • 159

OSG中获取任一时刻相机的位置

就是在有漫游器的程序中获取相机任一时刻的位置,有时使用漫游器漫游时需要...
  • u012501459
  • u012501459
  • 2014-07-04 16:15:29
  • 2960

OSG坐标系解释????????

对于下面的代码(选自《OSG海军教程》第十课第一节 使用自定义矩阵来放置相机,但数据有更改): tankXform->setPosition( osg::Vec3(0,60,8) ); // 相机...
  • tmljs1988
  • tmljs1988
  • 2012-05-13 11:23:38
  • 7403
收藏助手
不良信息举报
您举报文章:OSG获取鼠标点选事件的位置
举报原因:
原因补充:

(最多只允许输入30个字)