osg获取鼠标在三维空间中的点击位置
#pragma once #include <osgGA/TrackballManipulator> #include<osgGA/CameraManipulator> #include<osgGA/GUIActionAdapter> #include <osg/Group> #include <osg/Geode> #include <osg/ShapeDrawable> #include <osgDB/ReadFile> #include <osgViewer/Viewer> #include <osgGA/GUIEventHandler> #include <osgGA/TrackballManipulator> #include <osg/Material> #include <osg/StateSet> #include <osgUtil/LineSegmentIntersector> #include <osgUtil/IntersectVisitor> #include <osg/Texture> #include <osg/Image> #include <osg/ShapeDrawable> #include <osg/Texture2D> #include <osg/BlendFunc> #include <osg/AlphaFunc> #include <iostream> #include<QDebug> #include <QMap> #include <QVector> class VCTrackballManipulator :public osgGA::TrackballManipulator { public: VCTrackballManipulator(); ~VCTrackballManipulator(); void moveToView(const osgGA::GUIEventAdapter &ea); void moveToInit(); void viewTop(); void viewFront(); void viewLeft(); // void performPick(const osgGA::GUIEventAdapter& ea, osgViewer::Viewer& view); osg::ref_ptr<osg::Geode> createRedSphere(const osg::Vec3f& position, float radius); void Pick(float x, float y, osgViewer::Viewer* mViewer); // osg::ref_ptr<osg::Geode> getClickLine() { if (clickLine !=nullptr) { return clickLine; } return nullptr; } QVector<float> getClickLineStartAndEndPointVec() { return clickLineStartAndEndPointVec; } void clearClickLineStartAndEndPointVec() { this->clickLineStartAndEndPointVec.clear(); } void setNodeTexture(osg::Node *nodeParam); void setViewer(osgViewer::Viewer* mViewer) { this->mViewer1 = mViewer; } void computeWorldRayFromWindowPoint(osg::Camera* camera, float x, float y, osg::Vec3& start, osg::Vec3& end) { // 将窗口坐标转换为视口坐标(通常是相同的,除非有视口偏移或缩放) float viewportX = x; float viewportY = camera->getViewport()->height() - y; // 注意Y坐标是反转的 // 获取相机的投影矩阵和逆视图矩阵 osg::Matrix projectionMatrix = camera->getProjectionMatrix(); osg::Matrix viewMatrix = camera->getViewMatrix(); osg::Matrix inverseViewMatrix = osg::Matrix::inverse(viewMatrix); osg::Matrix inverseProjectionMatrix = osg::Matrix::inverse(projectionMatrix); // 将视口坐标转换为裁剪空间坐标(-1 到 1) float nx = (2.0f * viewportX) / camera->getViewport()->width() - 1.0f; float ny = 1.0f - (2.0f * viewportY) / camera->getViewport()->height(); // 计算裁剪空间中的近平面和远平面点 osg::Vec3 nearPoint(nx, ny, -1.0f); osg::Vec3 farPoint(nx, ny, 1.0f); // 使用逆视图矩阵和投影矩阵将裁剪空间点转换为世界空间点 //start = nearPoint * inverseViewMatrix; //end = farPoint * inverseViewMatrix; // 使用逆投影矩阵将裁剪空间点转换为视图空间点 osg::Vec3 viewNearPoint = nearPoint * inverseProjectionMatrix; osg::Vec3 viewFarPoint = farPoint * inverseProjectionMatrix; // 使用逆视图矩阵将视图空间点转换为世界空间点 osg::Vec3 worldNearPoint = viewNearPoint * inverseViewMatrix; osg::Vec3 worldFarPoint = viewFarPoint * inverseViewMatrix; // 现在我们有了从相机位置到点击位置的世界射线 // worldNearPoint 是射线起点(近平面上的点) // worldFarPoint 是射线方向上的一个远点(远平面上的点) // 射线方向可以通过 worldFarPoint - worldNearPoint 得到 osg::Vec3 rayDirection = worldFarPoint - worldNearPoint; rayDirection.normalize(); // 规范化射线方向 // 现在我们有了从相机位置到点击位置的世界射线 start = worldNearPoint; end = worldFarPoint; } protected: bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us) { // switch (ea.getEventType()) { case osgGA::GUIEventAdapter::PUSH: if (ea.getButton()==ea.LEFT_MOUSE_BUTTON) { { // 获取相机 osg::Camera* camera = us.asView()->getCamera(); if (!camera) return false; // 获取鼠标点击的窗口坐标 float x = ea.getX(); float y = ea.getY(); // 计算世界射线 osg::Vec3 start, end; computeWorldRayFromWindowPoint(camera, x, y, start, end); { // 创建一个几何体对象 osg::ref_ptr<osg::Geometry> geom = new osg::Geometry; // 设置顶点模式为线条列表(GL_LINES)或线带(GL_LINE_STRIP) osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array; vertices->push_back(osg::Vec3(start.x(), start.y(), start.z())); // 线的起点 vertices->push_back(osg::Vec3(end.x(), end.y(), end.z())); // 线的终点 // 如果需要绘制多条线段,继续添加顶点... geom->setVertexArray(vertices); // 对于线条列表,每个线段由两个顶点定义 // 对于线带,顶点序列中的连续点将形成线段 osg::ref_ptr<osg::DrawArrays> drawArrays = new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertices->size()); geom->addPrimitiveSet(drawArrays); // osg::ref_ptr<osg::Geode> lineGeodeObj = new osg::Geode(); lineGeodeObj->addChild(geom); clickLine = lineGeodeObj; // this->clearClickLineStartAndEndPointVec(); clickLineStartAndEndPointVec.push_back(start.x()); clickLineStartAndEndPointVec.push_back(start.y()); clickLineStartAndEndPointVec.push_back(start.z()); clickLineStartAndEndPointVec.push_back(end.x()); clickLineStartAndEndPointVec.push_back(end.y()); clickLineStartAndEndPointVec.push_back(end.z()); // } } } break; case osgGA::GUIEventAdapter::RELEASE: if (ea.getButton() == ea.LEFT_MOUSE_BUTTON) { } break; default: break; } if (ea.getHandled()) { return false; } return osgGA::StandardManipulator::handle(ea,us); } private: float ritateAngle1 = 0.0f; double _lastX, _lastY; // 用于记录上一次鼠标位置 bool _dragging; // 标记是否正在拖动旋转 osg::ref_ptr<osg::Geode> clickLine=nullptr; QVector<float> clickLineStartAndEndPointVec; };
###########################
QQ 3087438119