qt使用osg显示pcd点云的例子

osg点云显示类贴出

复制代码
//**********************************************************************
//                       osg仿真显示工具
//                                               @阿甘整理 20250828
//**********************************************************************
#pragma once
#include <QtCore/QtCore>
#include <QtWidgets/QtWidgets>
#include <osgQOpenGL/osgQOpenGLWidget>
#include <osg/Geode>
#include <osg/MatrixTransform>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>

//osg点云显示
class osgCloud : public QWidget
{
    Q_OBJECT
public:
    osgCloud(QWidget* parent = nullptr);
    ~osgCloud(void);
protected slots:
    //OsgQOpenGLWidget延迟加载 测试仿真显示
    void initWindow();
    //测试加载psd
    void loadPcd(void);
public:
    //加载显示点云
    void loadCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr pCloud);
    //保存点云到文件
    void saveCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, const std::string name);
    //清空点云
    void removeAllPointClouds();
private:
    osgQOpenGLWidget* _pOsgQOpenGLWidget;
    osgViewer::Viewer* pViewer;
    osg::ref_ptr<osg::Geode> geode;
    osg::ref_ptr<osg::MatrixTransform> transform;
    QGridLayout* m_mylay;
};

实现部分

复制代码
#include "osgCloud.h"
#include <osg/Node>
#include <osg/LineWidth>
#include <osg/ShapeDrawable>
#include <osg/Geode>
#include <osg/Matrixd>
#include <osg/Camera>
#include <osg/Point>
#include <osg/MatrixTransform>
#include <osg/Geometry>
#include <osg/BlendFunc>
#include <osg/Material>
#include <osg/StateSet>
#include <osgDB/ReadFile>
#include <osgViewer/View>
#include <osgViewer/Viewer>
#include <osgGA/TrackballManipulator>
#include <osgText/Text>
#include <osgUtil/Optimizer>
#include <osg/Multisample>
#pragma execution_character_set("utf-8")
#include <pcl/io/pcd_io.h>
#include <pcl/common/centroid.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/ply_io.h>


osgCloud::osgCloud(QWidget* parent): QWidget(parent)
{
    transform = new osg::MatrixTransform();
    geode = new osg::Geode;
    _pOsgQOpenGLWidget = new osgQOpenGLWidget(parent);
    m_mylay = new QGridLayout(this);
    m_mylay->setSpacing(0);
    m_mylay->setMargin(0);
    m_mylay->setContentsMargins(0, 0, 0, 0);
    m_mylay->addWidget(_pOsgQOpenGLWidget);
    _pOsgQOpenGLWidget->setGeometry(this->geometry());
    //_pOsgQOpenGLWidget延迟加载
    connect(_pOsgQOpenGLWidget, SIGNAL(initialized()), this, SLOT(initWindow()));
}

osgCloud::~osgCloud(void)
{
}

void osgCloud::initWindow(void)
{
    //return loadPcd();
    //创建坐标系网格
    auto createInfiniteGrid = [](float gridSize = 1.0f, int gridCount = 20)->osg::ref_ptr<osg::Node>
    {
        osg::Group* root = new osg::Group();
        osg::StateSet* stateset = root->getOrCreateStateSet();

        // 网格线设置(浅灰色细线)
        osg::LineWidth* gridLineWidth = new osg::LineWidth(1.0f);
        stateset->setAttribute(gridLineWidth);

        // 创建XY平面网格
        osg::Geometry* gridGeometry = new osg::Geometry();
        osg::Vec3Array* vertices = new osg::Vec3Array();

        // 生成网格线顶点(双向无限延伸)
        float halfSize = gridSize * gridCount;
        for (int i = -gridCount; i <= gridCount; ++i)
        {
            if (i == 0)
            {
                continue;  //排除掉下x y轴
            }
            float pos = i * gridSize;
            // X方向线
            vertices->push_back(osg::Vec3(-halfSize, pos, 0));
            vertices->push_back(osg::Vec3(halfSize, pos, 0));
            // Y方向线
            vertices->push_back(osg::Vec3(pos, -halfSize, 0));
            vertices->push_back(osg::Vec3(pos, halfSize, 0));
        }

        gridGeometry->setVertexArray(vertices);
        osg::Vec4Array* colors = new osg::Vec4Array();
        colors->push_back(osg::Vec4(0.8f, 0.8f, 0.8f, 0.5f)); // 浅灰色半透明
        gridGeometry->setColorArray(colors);
        gridGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);
        gridGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertices->size()));

        osg::Geode* gridGeode = new osg::Geode();
        gridGeode->addDrawable(gridGeometry);
        root->addChild(gridGeode);

        return root;
    };
    //创建X Y Z坐标系
    auto create3DCoordinateSystem = [](float axisLength = 10.0f)->osg::ref_ptr<osg::Node>
    {
        osg::Group* root = new osg::Group();
        osg::StateSet* stateset = root->getOrCreateStateSet();

        // 设置线宽(加粗效果)
        osg::LineWidth* lineWidth = new osg::LineWidth(1.0f);   //线粗
        stateset->setAttribute(lineWidth);


        // 定义轴半径和箭头尺寸
        //float axisRadius = axisLength * 0.02f;
        //float arrowRadius = axisRadius * 2.0f;
        //float arrowHeight = axisLength * 0.1f;

        // 创建坐标轴函数
        auto createAxis = [&](osg::Vec3 dir, osg::Vec4 color, std::string label)
        {
            osg::Geode* geode = new osg::Geode();
            // 坐标轴线
            osg::Geometry* geom = new osg::Geometry();
            // 禁用光照 就没有旋转到反面变黑色的问题了
            geom->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
            osg::Vec3Array* vertices = new osg::Vec3Array();
            vertices->push_back(dir * -axisLength);
            vertices->push_back(dir * axisLength);
            geom->setVertexArray(vertices);
            osg::Vec4Array* colors = new osg::Vec4Array();
            colors->push_back(color);
            geom->setColorArray(colors);
            geom->setColorBinding(osg::Geometry::BIND_OVERALL);
            geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertices->size()));//2
            geode->addDrawable(geom);
            // 坐标轴标签
            osgText::Text* text = new osgText::Text();
            //text->setFont("arial.ttf");
            text->setCharacterSize(1.0f);
            text->setPosition(dir * (axisLength + 1));
            text->setText(label);
            text->setColor(color);
            text->setAlignment(osgText::Text::CENTER_CENTER);
            geode->addDrawable(text);
            return geode;
        };

        // 创建XYZ三轴
        root->addChild(createAxis(osg::Vec3(2, 0, 0), osg::Vec4(1, 0, 0, 1), "X"));
        root->addChild(createAxis(osg::Vec3(0, 2, 0), osg::Vec4(0, 1, 0, 1), "Y"));
        root->addChild(createAxis(osg::Vec3(0, 0, 2), osg::Vec4(0, 0, 1, 1), "Z"));

        return root;
    };

    pViewer = _pOsgQOpenGLWidget->getOsgViewer();
    pViewer->getCamera()->setClearColor(osg::Vec4(0.2f, 0.2f, 0.2f, 1.0f)); // 浅灰色背景

    transform->addChild(createInfiniteGrid());              //创建网格
    transform->addChild(create3DCoordinateSystem());        //创建xyz坐标轴
    transform->addChild(geode);
    osgGA::TrackballManipulator* manipulator = new osgGA::TrackballManipulator();
    manipulator->setVerticalAxisFixed(false);               // 允许自由旋转
    manipulator->setWheelZoomFactor(-0.1);                  // 反转滚动灵敏度 默认0.1改为-0.1
    pViewer->setCameraManipulator(manipulator);
    //pViewer->setCameraManipulator(new osgGA::TrackballManipulator);
    pViewer->setSceneData(transform);
    pViewer->getCameraManipulator()->setHomePosition(
        osg::Vec3d(8, 8, 8),        // 眼睛位置           数字越大相机越远
        osg::Vec3d(0, 0, 0),        // 观察点(原点)
        osg::Vec3d(0, 1, 0)         // 上方向
    );
    pViewer->home();
}

void osgCloud::loadPcd(void)
{
    //加载pcd测试
    auto osgPointCloudNode = [&](osgViewer::Viewer * pViewer)
    {
        const std::string pcd_file = "mouse.pcd";
        //osg::ref_ptr<osg::Node> createPointCloudNode(const std::string& pcd_file)
        // 读取PCD文件
        pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
        if (pcl::io::loadPCDFile<pcl::PointXYZ>(pcd_file, *cloud) == -1)
        {
            std::cerr << "无法加载PCD文件: " << pcd_file << std::endl;
            return nullptr;
        }
        // 创建OSG几何体
        osg::ref_ptr<osg::Geometry> geometry(new osg::Geometry);
        osg::ref_ptr<osg::Vec3Array> vertices(new osg::Vec3Array);
        osg::ref_ptr<osg::Vec4Array> colors(new osg::Vec4Array);
        // 填充顶点和颜色数据
        for (const auto& point : cloud->points)
        {
            vertices->push_back(osg::Vec3(point.x, point.y, point.z));
            colors->push_back(osg::Vec4(1.0f, 0.5f, 0.0f, 1.0f)); // 橙色点
        }
        geometry->setVertexArray(vertices);
        geometry->setColorArray(colors);
        geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
        geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, vertices->size()));
        geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);      //禁用光照
        // 创建Geode节点并添加几何体
        osg::ref_ptr<osg::Geode> geode(new osg::Geode);
        geode->addDrawable(geometry);
        pViewer->setCameraManipulator(new osgGA::TrackballManipulator);
        pViewer->setSceneData(geode);
    };
    //测试加载
    pViewer = _pOsgQOpenGLWidget->getOsgViewer();
    //测试加载pcd
    osgPointCloudNode(pViewer);
}

void osgCloud::loadCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr pCloud)
{
    if (pCloud->points.size() != 0)
    {
        //计算点云中心
        Eigen::Vector4f centroid;
        pcl::compute3DCentroid(*pCloud, centroid);
        // 创建OSG几何体
        osg::ref_ptr<osg::Geometry> geometry(new osg::Geometry);
        osg::ref_ptr<osg::Vec3Array> vertices(new osg::Vec3Array);
        osg::ref_ptr<osg::Vec4Array> colors(new osg::Vec4Array);
        osg::Vec3f currpt;
        // 填充顶点和颜色数据
        for (const auto& point : pCloud->points)
        {
            //减去中心坐标使点云居中
            vertices->push_back(osg::Vec3f(point.x - centroid[0], point.y - centroid[1], point.z - centroid[2]));
            colors->push_back(osg::Vec4(1.0f, 0.5f, 0.0f, 1.0f)); // 橙色点
        }
        geometry->setVertexArray(vertices);
        geometry->setColorArray(colors);
        geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
        //设置点大小
        osg::ref_ptr<osg::Point> mypoint = new osg::Point;
        mypoint->setSize(3.0f);
        geometry->getOrCreateStateSet()->setAttribute(mypoint);
        geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, vertices->size()));
        geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);      //禁用光照
        removeAllPointClouds();
        //添加到主视图
        geode->addDrawable(geometry);
        //pViewer->getCameraManipulator()->setHomePosition(
        //    osg::Vec3d(48, 48, 48),        // 眼睛位置           数字越大相机越远
        //    osg::Vec3d(0, 0, 0),        // 观察点(原点)
        //    osg::Vec3d(0, 1, 0)         // 上方向
        //);
        //pViewer->home();
    }
    else {
        QMessageBox::about(this, "error", "error!");
    }
}

void osgCloud::saveCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, const std::string name)
{
    pcl::io::savePCDFileBinary(name, *cloud);
}

void osgCloud::removeAllPointClouds()
{
    if (!geode)
        return;

    // 移除所有Drawable
    geode->removeDrawables(0, geode->getNumDrawables());

    // 若需清空Geometry顶点数据
    for (unsigned int i = 0; i < geode->getNumDrawables(); ++i)
    {
        osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode->getDrawable(i));
        if (geom)
        {
            geom->setVertexArray(new osg::Vec3Array);
            geom->dirtyDisplayList();
        }
    }
}

效果是这样的

相关推荐
2301_8156864540 分钟前
extern
java·开发语言
q***563844 分钟前
Java进阶-SPI机制
java·开发语言
g***B7381 小时前
Rust在网络中的Tokio
开发语言·网络·rust
寻找华年的锦瑟1 小时前
Qt-侧边栏布局
开发语言·qt
156082072191 小时前
QT的ComboBox使用QToolTip显示提示信息
开发语言
tyler-泰勒1 小时前
QT:基础概念操作
开发语言·qt
开始了码1 小时前
QT::对话框:消息对话框6
qt
9***P3341 小时前
Rust在网络中的Rocket
开发语言·后端·rust
大迪吃小迪2 小时前
每秒 400 请求场景下,线程池如何合理配置?
java·开发语言