osg三維場景中拾取滑鼠在模型表面的點選點
#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 <iostream> class PickHandler : public osgGA::GUIEventHandler { public: PickHandler() {} virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); if (!view) return false; // 檢查是否為滑鼠左鍵點選事件 if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE && ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) { performPick(ea, *view); return true; } return false; } osg::ref_ptr<osg::Geode> createRedSphere(const osg::Vec3f& position, float radius) { // 建立一個球體形狀 osg::ref_ptr<osg::Sphere> sphere = new osg::Sphere(position, radius); // 建立一個形狀繪製物件,並設定其顏色為紅色 osg::ref_ptr<osg::ShapeDrawable> sphereDrawable = new osg::ShapeDrawable(sphere); sphereDrawable->setColor(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); // 紅色(RGBA) // 建立一個地理節點(Geode),並將形狀繪製物件新增到其中 osg::ref_ptr<osg::Geode> sphereGeode = new osg::Geode(); sphereGeode->addDrawable(sphereDrawable); return sphereGeode; } // private: void performPick(const osgGA::GUIEventAdapter& ea, osgViewer::View& view) { // 將滑鼠位置轉換為視窗座標 int x = ea.getX(); int y = ea.getY(); // 建立一個射線相交檢測器 //osgUtil::LineSegmentIntersector* intersector = new osgUtil::LineSegmentIntersector( // osgUtil::IntersectionVisitor::IntersectionType::FIRST, // 使用第一個相交點 // osg::Vec3(x, y, -1.0f), // 射線起點 // osg::Vec3(x, y, 1.0f) // 射線終點 // ); //osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::PROJECTION, x, y); // 執行相交檢測 osgUtil::IntersectionVisitor iv; //bool computeIntersections(float x,float y, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask = 0xffffffff); // 儲存相交結果的容器 osgUtil::LineSegmentIntersector::Intersections intersections; // 執行相交檢測 if (view.computeIntersections(x, y, intersections)) { // 檢查是否有相交點 if (!intersections.empty()) { // 獲取第一個相交點 //const osgUtil::LineSegmentIntersector::Intersection& intersection = intersections[0]; for (const auto& intersection : intersections) { const osg::Vec3& point = intersection.getWorldIntersectPoint(); std::cout << "Intersection point: " << point.x() << " " << point.y() << " " << point.z() << std::endl; osg::ref_ptr<osg::Geode> redSphere = createRedSphere(point, 10.1f); // 半徑為1的紅色球體 view.getSceneData()->asGroup()->addChild(redSphere); break; // 只處理第一個相交點 } //const osg::Vec3& point = intersection.getWorldIntersectPoint(); //std::cout << "Intersection point: " << point << std::endl; } else { std::cout << "No intersection found." << std::endl; } } else { std::cout << "No intersection found." << std::endl; } // 清理資源 //delete intersector; } }; int main(int argc, char** argv) { osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer; // 載入場景 cow.osg excavator.OSGB library.OSGB osg::Node* root = osgDB::readNodeFile("library.OSGB"); if (!root) { std::cerr << "Error loading model" << std::endl; return 1; } viewer->setSceneData(root); // 新增滑鼠拾取事件處理器 viewer->addEventHandler(new PickHandler()); // 開始執行 return viewer->run(); } ////////////////
#######################################