洞若观火(一)OSG库—三维图形工具包

本文介绍了OpenSceneGraph(OSG)的下载源及如何使用CMake生成VS解决方案。详细步骤包括配置CMake以构建OSG库,然后将库部署到工程中,并展示了如何在QT环境中进行图形显示。此外,还提供了OSGC++示例,包括显示立方体和点云的代码。
摘要由CSDN通过智能技术生成

1. OSG简介

OpenSceneGraph(OSG)是一个开源的跨平台的三维图形工具包,用于实时模拟和视觉仿真应用程序的开发。

1.1 OSG下载

官方库

地址
1OpenSceneGraph官网http://www.openscenegraph.org/
2GitHub 导航页https://github.com/openscenegraph
3GitHub OpenSceneGraphhttps://github.com/openscenegraph/OpenSceneGraph
4OpenSceneGraph官网测试数据OpenSceneGraph-Data-3.4.0.zip

国方扩展库

地址
1GitHub osgQthttps://github.com/openscenegraph/osgQt
2osgQt的具体应用深入浅出(四)osgQt库—OSG扩展库
3osgChina官网http://www.osgchina.org/downloads-son.php?id=34

其他优秀的开源库地址

地址
1GitHub demo-osgpclhttps://github.com/adasta/osgpcl
2GitHub osg-3rdparty-cmakehttps://github.com/bjornblissing/osg-3rdparty-cmake
3freecadhttps://www.freecad.org/

2. OSGCMake生成vs解决方案

  1. 下载OpenSceneGraph(OSG)源码,可参考本文Osg 下载,并安装CMake

  2. 这里将源代码解压后放在了OpenSceneGraph目录下,
    创建目录:build
    创建目录:install
    在这里插入图片描述

  3. 打开cmake-gui软件
    源码目录填写:C:\work\OpenSceneGraph\OpenSceneGraph-master
    构建目录填写:C:\work\OpenSceneGraph\build
    在这里插入图片描述

  4. 点击Configure,在弹出的窗口中选择:
    生成的工程:Visual Studio 16 2019【根据自己电脑安装的vs版本选择,作者安装的为vs2019】
    生成类型:x64
    使用默认的本机编译器
    点击finish完成配置
    在这里插入图片描述

  5. 点击Configure,出现很多红色,修改两处
    BUILD_OSG_EXAMPLES:勾选
    CMAKE_INSTALL_PREFIX:修改为 C:\work\OpenSceneGraph\install
    在这里插入图片描述

  6. 在此点击Configure,如下图
    在这里插入图片描述

  7. 点击Generate,如下图,与上图区别是Open Project处于可点击状态
    在这里插入图片描述

  8. 点击Open Project,通过vs2019打开工程
    在这里插入图片描述

  9. 配置管理器为Release,x64
    在这里插入图片描述

  10. 构建ALL_BUILD,此过程大约需要2小时。
    在这里插入图片描述

  11. build目录下,生成lib和dll如下
    在这里插入图片描述

  12. INSTALL生成库,在install目录下生成我们想要的可添加到工程中的dll和lib
    在这里插入图片描述
    在这里插入图片描述

3. OSG应用

3.1 部署到工程中

cmakelists.txt

include_directories(${path}/osg/include)
file(GLOB OSG_LIB ${path}/osg/lib/*.lib)
file(GLOB OSG_DLL ${path}/osg/bin/*.dll)

target_link_libraries(${PROJECT_NAME} PUBLIC ${OSG_LIB})

3.2 基于QT 图形显示

代码中添加以下代码,运行成功而不崩溃,则代表添加成功

osgQOpenGLWidget* osgwidget = new osgQOpenGLWidget();
osgwidget->show();

附录1 OSG C++示例

显示一个立方体

使用OpenSceneGraph创建一个简单的3D场景并显示一个立方体

#include <osg/Geode>
#include <osg/Geometry>
#include <osgViewer/Viewer>

int main() {
    // 创建一个几何体
    osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;

    // 创建一个立方体的顶点数据
    osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
    vertices->push_back(osg::Vec3(-0.5f, -0.5f, 0.0f));
    vertices->push_back(osg::Vec3(0.5f, -0.5f, 0.0f));
    vertices->push_back(osg::Vec3(0.5f, 0.5f, 0.0f));
    vertices->push_back(osg::Vec3(-0.5f, 0.5f, 0.0f));
    geometry->setVertexArray(vertices);

    // 创建一个立方体的颜色数据
    osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
    colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
    geometry->setColorArray(colors, osg::Array::BIND_OVERALL);

    // 创建一个图元集合
    osg::ref_ptr<osg::DrawElementsUInt> primitiveSet = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
    primitiveSet->push_back(0);
    primitiveSet->push_back(1);
    primitiveSet->push_back(2);
    primitiveSet->push_back(3);
    geometry->addPrimitiveSet(primitiveSet);

    // 创建一个Geode节点
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(geometry);

    // 创建一个查看器并设置场景数据
    osgViewer::Viewer viewer;
    viewer.setSceneData(geode);

    // 运行查看器
    return viewer.run();
}

显示点云

#include <osgViewer/Viewer>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/Group>

int main(int argc, char** argv)
{
    // 创建Viewer
    osgViewer::Viewer viewer;

    // 创建根节点
    osg::ref_ptr<osg::Group> root = new osg::Group;

    // 创建几何图形
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    osg::ref_ptr<osg::ShapeDrawable> shapeDrawable = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0, 0, 0), 1.0f));
    geode->addDrawable(shapeDrawable);

    // 将几何图形添加到根节点
    root->addChild(geode);

    // 将根节点设置为场景数据
    viewer.setSceneData(root);

    // 运行Viewer
    return viewer.run();
}

osg 接口实例

  • osg 初始化
    osg .h 定义
//点云可视化参数
osg::ref_ptr<osgViewer::Viewer> osg_viewer;               //参数配置
osg::ref_ptr<osg::Group> osg_group_root;                  //根节点
float osg_size;                                           //osg图形的大小
osg::ref_ptr<osg::MatrixTransform> osg_coordinate_origin; //3D相机坐标系child节点
osg::ref_ptr<osg::MatrixTransform> osg_coordinate ;       //3D相机坐标系child节点
osg::ref_ptr<osg::Geometry> osg_geometry_data;            //点云数据存储节点, xyzrxryrz + rgb
osg::ref_ptr<osg::Geode>    osg_geode_child;     
osgQOpenGLWidget* osg_widget;
boost::shared_ptr<pcl::visualization::PCLVisualizer> pcl_visualizer;

osg 初始化接口

void OsgInit() {
    QSize size = QSize(osg_widget->width(), osg_widget->height());
    
    osg::ref_ptr<osgGA::TrackballManipulator> trackball = new osgGA::TrackballManipulator;
    trackball->setAllowThrow(false);
    trackball->setAutoComputeHomePosition(true);
    trackball->setThreadSafeRefUnref(true);
    
    osg_group_root = new osg::Group();
    osg_viewer = osg_widget->getOsgViewer();
    osg_viewer->getCamera()->setClearColor(osg::Vec4(0.2, 0.2, 0.2, 1));
    osg_viewer->getCamera()->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(size.width())/static_cast<double>(size.height()), 1.0f, 10000.0f );
    osg_viewer->setCameraManipulator(trackball);
    osg_viewer->setRunMaxFrameRate(60);
  
    // 优化场景数据
    osgUtil::Optimizer optimizer;
    optimizer.optimize(osg_group_root.get());
    osg_viewer->setSceneData(osg_group_root.get());  
}
  • osg 画网格
void OsgDrawGrid() {
    //生成网格
    osg::ref_ptr<osg::Geode> grid = new osg::Geode;
    osg::Geometry* geom = new osg::Geometry;
    grid->addChild(geom);
    
    osg::Vec3Array* vertex = new osg::Vec3Array;
    geom->setVertexArray(vertex);
    //沿xy平面画线,间隔500米,从-10000,画到100000
    for (int i = -3; i <= 3; i += 1) {
        vertex->push_back(osg::Vec3( i, -3, 0));
        vertex->push_back(osg::Vec3( i,  3, 0));
        vertex->push_back(osg::Vec3(-3,  i, 0));
        vertex->push_back(osg::Vec3( 3,  i, 0));
    }
    int s = 3; //行列数
    for (int i = -s; i <= s; i += 1) {
        vertex->push_back(osg::Vec3( i, -s, 0));
        vertex->push_back(osg::Vec3( i,  s, 0));
        vertex->push_back(osg::Vec3(-s,  i, 0));
        vertex->push_back(osg::Vec3( s,  i, 0));
    }
    
	  geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertex->size()));
    osg::Vec4Array* color = new osg::Vec4Array();
    color->push_back(osg::Vec4(0.7, 0.7, 0.7, 1.0));
    geom->setColorArray(color, osg::Array::BIND_OVERALL);
    geom->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
    osg_group_root->addChild(grid);  
}
  • osg 画坐标系
void OsgShowCoordinate(const Eigen::Matrix4f& coor_pose) {
    //画基础原点坐标系
    osg::Matrix matrix = osg::Matrix::identity();
    matrix.postMultTranslate(osg::Vec3(0,0,0));
    osg_coordinate_origin = new GeodePosition(matrix, osg_size, "COORDINATE_ORIGIN");    
    osg_group_root->addChild(osg_coordinate_origin);
    
    //转换成m制
    Eigen::Matrix4f pose = coor_pose;
    pose(0,3) = coor_pose(0,3) / 1000.0;
    pose(1,3) = coor_pose(1,3) / 1000.0;
    pose(2,3) = coor_pose(2,3) / 1000.0;
    
    //添加相机坐标系
    osg_group_root->removeChild(osg_coordinate); 
    osg_coordinate = new GeodePosition(pose, osg_size, "COORDINATE");
    osg_group_root->addChild(osg_coordinate);
}
  • osg 画pcl点云图
void OsgShowPclCloud(const pcl::PointCloud<pcl::PointXYZRGB>::Ptr& cloud) {
    //点云可视化
    long size = cloud->size();
    osg::ref_ptr<osg::Vec3Array> coords = new osg::Vec3Array(); //创建顶点数组
    osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(); //创建颜色
    std::vector<std::uint8_t> vec_colors;
    
    for(int i = 0; i < size; i++) {
        coords->push_back(osg::Vec3(cloud->data()[i].x,
                                    cloud->data()[i].y,
                                    cloud->data()[i].z));
        colors->push_back(osg::Vec4f((int)cloud->data()[i].r / 255.0,
                                     (int)cloud->data()[i].g / 255.0,
                                     (int)cloud->data()[i].b / 255.0,
                                     (int)cloud->data()[i].a / 255.0));
    }
    
		//数据清空
    osg_geode_child->removeDrawable(osg_geometry_data.get());
    
    //设置顶点数组
    //osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();
    osg_geometry_data->setVertexArray(coords.get()) ;
    osg_geometry_data->setColorArray(colors.get()) ;
    osg_geometry_data->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
    osg_geometry_data->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS , 0, size)) ; //设置关联方式
    
    //osg::ref_ptr<osg::Geode> geode111 = new osg::Geode() ;
    osg_geode_child->addDrawable(osg_geometry_data.get());
    osg_group_root->addChild(osg_geode_child); 
}
  • pcl 画点云图
void ShowPclCloud(const pcl::PointCloud<pcl::PointXYZRGB>::Ptr& cloud) {
    //pcl窗口显示点云
    if (pcl_visualizer) {
        pcl_visualizer->close();
    }
    
    boost::shared_ptr<pcl::visualization::PCLVisualizer> pcl_visualizer(new pcl::visualization::PCLVisualizer("3D Viewer"));
    pcl_visualizer->addPointCloud<pcl::PointXYZRGB>(cloud);
    pcl_visualizer->setBackgroundColor(0, 0, 0); // 设置点云大小
    pcl_visualizer->addCoordinateSystem(0);

    //可选 可修改背景颜色
    while (!pcl_visualizer->wasStopped()) {
        //调用内部渲染函数,重新渲染输出时间最大不查过time=1000
        pcl_visualizer->spinOnce(1000);
    }
}
  • pcl 保存点云数据
void SavePclCloud(const pcl::PointCloud<pcl::PointXYZRGB>::Ptr& cloud) {
    //创建文件夹路径
    QString file_path_name = "D:/"+ QDateTime::currentDateTime().toString("yyyy_MM_dd_HH_mm_ss") + "_cloud_data";
    QDir dir1(file_path_name);
    if(!dir1.exists()) {
        dir1.mkdir(file_path_name);
    }
    
    //解决中文路径问题
    QTextCodec *code = QTextCodec::codecForName("GB2312");
    std::string name = code->fromUnicode(file_path_name).data();
    QByteArray file_path = name.c_str();
    //保存点云数据
    pcl::io::savePLYFileBinary(file_path.toStdString() + "/cloud.ply", *cloud);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小老鼠不吃猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值