Qt利用Coin3D(OpenInventor)进行3d绘图

文章目录

  • 1.安装
    • 1.1.下载coin3d
    • 1.2.下载quarter
    • 1.3.解压并合并
  • 2.在Qt中使用
  • 3.画个网格
  • 4.加载wrl模型
  • 5.画个锤子并旋转
  • 6.加载自定义视口文件

1.安装

1.1.下载coin3d

首先,到官网下载[coin3d/coin]
我是Qt5.15.2+vs2019的,因此我选择这个coin-4.0.2-msvc17-x64.zip
在这里插入图片描述

1.2.下载quarter

到官网下载Coin3D在Qt中的封装库【quarter】
我是Qt5.15.2+vs2019的,因此我选择这个quarter-1.2.1-Qt5.15-msvc17-x64.zip
在这里插入图片描述

1.3.解压并合并

将这两个压缩包放在在同一个文件夹中,先解压coin-4.0.2-msvc17-x64.zip,然后再解压
quarter-1.2.1-Qt5.15-msvc17-x64.zip,此时,我们利用Qt编程所需要的东西全在Coin3D这个文件夹里面了:
在这里插入图片描述

2.在Qt中使用

在Qt工程的pro文件中添加以下语句,路径要根据你的实际路径进行更改

QT += opengl

INCLUDEPATH += C:\Users\Administrator\Desktop\plc\Qt\Coin3D\include
LIBS += -LC:\Users\Administrator\Desktop\plc\Qt\Coin3D\lib \
-lQuarter1
LIBS += -LC:\Users\Administrator\Desktop\plc\Qt\Coin3D\bin

DEFINES += QUARTER_DLL

程序的话,可以参考以下这个【a small, completely stand-alone usage example】

3.画个网格

参考这篇文章【OpenInventor实现场景索引线集管理之SoIndexedLineSet】,弄了个绘制网格的例子:
在这里插入图片描述

#include "mainwindow.h"

#include <QApplication>
#include <QDebug>

#include <Inventor/nodes/SoBaseColor.h>
#include <Inventor/nodes/SoCone.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/VRMLnodes/SoVRMLGroup.h>

#include <Inventor/nodes/SoPointSet.h>
#include <Inventor/nodes/SoCoordinate3.h>
#include <Inventor/nodes/SoIndexedLineSet.h>
#include <Inventor/nodes/SoLineSet.h>

#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoMaterialBinding.h>
#include <Inventor/nodes/SoTransform.h>
#include <Inventor/nodes/SoMatrixTransform.h>


#include <Quarter/Quarter.h>
#include <Quarter/QuarterWidget.h>

#include <QtMath>

using namespace SIM::Coin3D::Quarter;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    // MainWindow w;
    // w.show();

    // Initializes Quarter library (and implicitly also the Coin and Qt
    // libraries).
    Quarter::init();

    // Make a dead simple scene graph by using the Coin library, only
    // containing a single yellow cone under the scene graph root.
    SoSeparator * root = new SoSeparator;
    root->ref();

    // 绘制网格
    {
        // 根节点
        SoSeparator * lineRoot = new SoSeparator();
        lineRoot->ref();

        // 线段集
        SoIndexedLineSet *iLineSet = new SoIndexedLineSet();

        int gridRows = 10;
        int gridCols = 10;

        // 存放点数据的结构
        SbVec3f *points = new SbVec3f[2 * (gridCols + gridCols)];
        // 填充横线
        for(int i = 0; i < gridRows; i++)
        {
            points[i * 2].setValue(0, i, 0);
            points[i * 2 + 1].setValue(gridCols - 1, i, 0);
        }
        // 填充竖线
        for(int i = 0; i < gridCols; i++)
        {
            points[gridRows * 2 + i * 2].setValue(i, 0, 0);
            points[gridRows * 2 + i * 2 + 1].setValue(i, gridRows - 1, 0);
        }

        // 坐标系
        SoCoordinate3 *coord = new SoCoordinate3();
        // 将各个点填充至坐标系中
        coord->point.setValues(0, 2 * (gridCols + gridCols), points);

        // 保存线的索引
        int32_t *nLineSets = new int32_t[3 * (gridCols + gridRows)];
        // 每条线需要三个索引:起点、终点、结束符
        for(int i = 0; i < (gridCols + gridRows); i++)
        {
            nLineSets[3 * i]     = i * 2;
            nLineSets[3 * i + 1] = i * 2 + 1;
            // SO_END_LINE_INDEX的值是-1,-1代表一条索引线结束!!!
            nLineSets[3 * i + 2] = SO_END_LINE_INDEX;
        }
        iLineSet->coordIndex.setValues(0, 3 * (gridCols + gridRows), nLineSets);

        // 默认颜色为绿色,被选中的红色显示
        SbColor *color = new SbColor[2];
        color[0].setValue(1,0,0);
        color[1].setValue(0,1,0);
        SoMaterial *mat = new SoMaterial();
        mat->diffuseColor.setValues(0, 2, color);

        SoMaterialBinding *mb = new SoMaterialBinding;
        // 索引绑定材质!!!
        mb->value = SoMaterialBinding::PER_PART_INDEXED;
        // mb->value = SoMaterialBinding::PER_PART;
        // mb->value = SoMaterialBinding::OVERALL;

        // 设置线段的颜色
        for(int i = 0; i < (gridCols + gridRows); i++)
        {
            // 这里的索引.第一个参数指的是第条线,第二个参数指的是mat->diffuseColor中的第几种材质
            iLineSet->materialIndex.set1Value(i, 0);  // 第i个线段的颜色/
        }
        iLineSet->materialIndex.set1Value(0, 1);  // 第i个线段的颜色/

        // 整体变换
        SbMatrix sbMatrix, tmpMat, tmpMat1;
        sbMatrix.makeIdentity(); // 变成单位矩阵
        // 平移、旋转、缩放需要单独进行,然后相乘
        tmpMat.makeIdentity();
        // tmpMat.setTranslate(SbVec3f(1, 0, 0));
        tmpMat.setRotate(SbRotation(SbVec3f(1, 0, 0),  qDegreesToRadians(90.0)));
        tmpMat1.makeIdentity();
        tmpMat1.setScale(0.1);
        sbMatrix = tmpMat1 * tmpMat; // 越在右边的矩阵,逻辑上是越先被使用的
        SoMatrixTransform *matrix = new SoMatrixTransform;
        // matrix->matrix.setValue(sbMatrix);
        lineRoot->addChild(matrix);

        lineRoot->addChild(coord);      // 组成线的点
        lineRoot->addChild(mat);        // 线的材质
        lineRoot->addChild(mb);         // 绑定材质
        lineRoot->addChild(iLineSet);   // 线

        root->addChild(lineRoot);
    }

    // Create a QuarterWidget for displaying a Coin scene graph
    QuarterWidget * viewer = new QuarterWidget;
    viewer->setSceneGraph(root);

    viewer->viewAll();

    // make the viewer react to input events similar to the good old
    // ExaminerViewer
    viewer->setNavigationModeFile(QUrl("coin:///scxml/navigation/examiner.xml"));
    // viewer->setNavigationModeFile(QUrl("coin:///scxml/navigation/common.xml"));

    viewer->resize(640, 480);
    // Pop up the QuarterWidget
    viewer->show();

    // return a.exec();

    a.exec();

    // Clean up resources.
    root->unref();
    delete viewer;

    Quarter::clean();

    return a.exec();
}

4.加载wrl模型

参考【FengJungle /QtCoin3D_Robot 】,可以加载自己的wrl模型

    // 加载模型
    SoVRMLGroup *model = nullptr;
    {
        SoInput * myInput = new SoInput;
        if(myInput->openFile("lr4-r560.wrl"))
        {
            model = SoDB::readAllVRML(myInput);
            myInput->closeFile();
            delete myInput;
        }
        else
        {
            myInput->closeFile();
            delete myInput;
        }
    }
    if(model != nullptr)
    {
        qDebug() << "num of children:" << model->getNumChildren();
        root->addChild(model);
    }

在这里插入图片描述

5.画个锤子并旋转

在这里插入图片描述

// 绘制锤子
    {
        // 创建一个组合节点,作为锤子的根节点
        SoSeparator* hammerRoot = new SoSeparator;

        // 创建一个旋转节点,用于绕圆柱体的末端旋转锤子
        SoRotation* rotation = new SoRotation;
        rotation->rotation.setValue(SbVec3f(1, 0, 0), M_PI * 0);
        // 将旋转节点添加到组合节点中
        hammerRoot->addChild(rotation);

        QSlider *slider = new QSlider(Qt::Horizontal);
        slider->resize(300, 20);
        QObject::connect(slider, &QSlider::valueChanged, [=](){
            rotation->rotation.setValue(SbVec3f(1, 0, 0), M_PI * ((double)slider->value()) / 100.0); // 绕Z轴旋转45度
        });
        slider->show();


        // 将手柄的位置调整一下,使得旋转中心在手柄末端
        SoTranslation* handleTranslation = new SoTranslation;
        handleTranslation->translation.setValue(0, 5, 0);
        hammerRoot->addChild(handleTranslation);

        // 创建圆柱体节点,作为锤子的手柄
        SoCylinder* handle = new SoCylinder;
        handle->radius = 0.5;
        handle->height = 10;
        hammerRoot->addChild(handle);

        // 将长方体放置在圆柱体的末端
        SoTranslation* headTranslation = new SoTranslation;
        headTranslation->translation.setValue(0, 5, 0);
        hammerRoot->addChild(headTranslation);

        // 创建长方体节点,作为锤子的头部
        SoCube* head = new SoCube;
        head->width = 2;
        head->height = 2;
        head->depth = 2;
        hammerRoot->addChild(head);

        root->addChild(hammerRoot);
    }

6.加载自定义视口文件

	QString exePath = QDir::currentPath();
    QString filePath = QString("file:///%1/examiner.xml").arg(exePath);
    viewer->setNavigationModeFile(QUrl(filePath));

更加具体的其他操作还得研究研究。


参考:
【OpenInventor官方文档】
【coin3d】
【FengJungle /QtCoin3D_Robot 】
【OpenInventor实现场景索引线集管理之SoIndexedLineSet】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/733689.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

“脏读”、“幻读”、“不可重复读”

“脏读”、“幻读”、“不可重复读” 1.概念说明 “脏读”、“幻读”、“不可重复读”是数据库事务的概念。 “脏读”是指一个事务中访问到了另外一个事务未提交的数据。 “不可重复读”是指在一个事务内根据同一个条件对数据进行多次查询&#xff0c;但是结果却不一致&…

某程序员:30岁了,老婆管钱,背着我买了50万股票,亏了20w,强制她清仓后又买了36万

“辛辛苦苦攒了几年钱&#xff0c;本想买房买车&#xff0c;结果全被老婆炒股亏掉了&#xff01;” 近日&#xff0c;一位30岁的程序员大哥在网上吐苦水&#xff0c;引发了网友们的热议。 这位程序员大哥和妻子结婚后&#xff0c;一直秉持着“男主外&#xff0c;女主内”的传统…

如何使用gprof对程序进行性能分析

如何使用gprof对程序进行性能分析 目录 1 gprof概述 2 gprof原理简述 3 gprof使用 3.1 gprof使用简述 3.2 gprof使用示例 4 小结 1 gprof概述 gprof 是 一个 GNU 的程序性能分析工具&#xff0c;可以用于分析C\C程序的执行性能。gprof工具可以统计出各个函数的调用次数、执…

修改docker中mongodb容器的时区

假设容器名称为mongodb&#xff0c;设置时区为伤害时区的命令为&#xff1a; docker exec -it mongodb bash -c "ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone"验证时区更改&#xff1a; docker e…

【CT】LeetCode手撕—42. 接雨水

目录 题目1- 思路2- 实现⭐42. 接雨水——题解思路 3- ACM实现 题目 原题连接&#xff1a;42. 接雨水 1- 思路 模式识别&#xff1a;求雨水的面积 ——> 不仅是只求一个比当前元素大的元素&#xff0c;还要求面积 单调栈 应用场景&#xff0c;需要找到左边比当前元素大的…

如何用Spring使用Redis作为消息订阅?

目录 一、Spring 框架介绍二、Redis 框架介绍三、什么是消息订阅四、如何用Spring使用Redis作为消息订阅 一、Spring 框架介绍 Spring 框架是一个开源的 Java 平台&#xff0c;它提供了全面的基础设施支持&#xff0c;以便您可以更容易地开发 Java 应用程序。Spring 处理了基础…

【C++】优先队列的使用及模拟实现

&#x1f497;个人主页&#x1f497; ⭐个人专栏——C学习⭐ &#x1f4ab;点击关注&#x1f929;一起学习C语言&#x1f4af;&#x1f4ab; 目录 导读 一、什么是优先队列 二、优先队列的使用 1. 优先队列的构造 2. 优先队列的基本操作 3. 使用示例 三、优先队列模拟实…

[已解决]ImportError: DLL load failed while importing win32api: 找不到指定的程序。

使用pip install pywin32302安装后import找不到win32api 失败尝试 上网找别人的解决方案&#xff0c;大部分解决方案都是通过复制下面两个dll文件到 下面这个文件夹&#xff0c;并且复制到C:\Windows\System32&#xff0c;从而解决问题&#xff0c;但是我没能成功。 解决方…

web中间件漏洞-Redis漏洞未授权访问漏洞-写webshell、写ssh公钥

web中间件漏洞-Redis漏洞未授权访问漏洞 利用redis未授权访问漏洞写webshell 利用redis未授权访问、攻击机向服务器写入webshell 从服务器查看写入的webshell 菜刀连接 利用redis未授权访问漏洞写ssh公钥 kali生成rsa公私钥对 ssh-keygen -t rsa 将公钥id_rsa.pub写入文…

鸿蒙 HarmonyOS NEXT星河版APP应用开发—上篇

一、鸿蒙开发环境搭建 DevEco Studio安装 下载 访问官网&#xff1a;https://developer.huawei.com/consumer/cn/deveco-studio/选择操作系统版本后并注册登录华为账号既可下载安装包 安装 建议&#xff1a;软件和依赖安装目录不要使用中文字符软件安装包下载完成后&#xff0…

HTML(19)——Flex

Flex布局也叫弹性布局&#xff0c;是浏览器提倡的布局模型&#xff0c;非常适合结构化布局&#xff0c;提供了强大的空间分布和对齐能力。 Flex模型不会产生浮动布局中脱标现象&#xff0c;布局网页更简单、更灵活。 Flex-组成 设置方式&#xff1a;给父元素设置display:fle…

以太坊==windows电脑本地搭建一个虚拟的以太坊环境

提供不同的选择&#xff0c;适合不同需求和技术水平的开发者&#xff1a; Geth&#xff1a;适合需要与主网兼容或构建私有网络的开发者。Ganache&#xff1a;适合快速开发和测试智能合约的开发者&#xff0c;特别是初学者。Docker&#xff1a;适合需要快速、可重复搭建环境的开…

四川汇聚荣科技有限公司靠谱吗?

在如今这个信息爆炸的时代&#xff0c;了解一家公司是否靠谱对于消费者和合作伙伴来说至关重要。四川汇聚荣科技有限公司作为一家位于中国西部地区的企业&#xff0c;自然也受到了人们的关注。那么&#xff0c;这家公司究竟如何呢?接下来&#xff0c;我们将从多个角度进行深入…

c语言 课设 atm

功能需求分析 ATM功能主界面:显示所能进行的操作,用户可多次选择。 ATM注册界面:输入用户名,用户密码,确认密码,密码长度不是六位重新输入,两次密码不一致重新输入,输入账号。密码隐藏,实现退格换行对*无影响。多人注册 ATM登录界面:输入账号,密码,三次以内输入…

NettyのFuturePromise、HandlerPipeline、ByteBuf

本篇介绍Netty的剩下三个组件Future&Promise、Handler&Pipeline、ByteBuf 1、Future&Promise Future和Promise都是Netty实现异步的组件。 1.1、JDK中的future 在JDK中也有一个同名的Future&#xff0c;通常是配合多线程的Callable以及线程池的submit()方法使用&am…

Rocky Linux 更换CN镜像地址

官方镜像列表&#xff0c;下拉查找 官方镜像列表&#xff1a;https://mirrors.rockylinux.org/mirrormanager/mirrorsCN 开头的站点。 一键更改镜像地址脚本 以下是更改从默认更改到阿里云地址 cat <<EOF>>/RackyLinux_Update_repo.sh #!/bin/bash # -*- codin…

ChatTTS增强版V3【已开源】,长文本修复,中英混读,导入音色,批量SRT、TXT

ChatTTS增强版V3来啦&#xff01;本次更新增加支持导入SRT、导入音色等功能。结合上次大家反馈的问题&#xff0c;修复了长文本、中英混读等问题。 项目已开源(https://github.com/CCmahua/ChatTTS-Enhanced) 项目介绍 V3 ChatTTS增强版V3&#xff0c;长文本修复&#xff0c…

【职场人】职场进化记:我的“不惹人厌邀功精”之路

刚步入职场的我&#xff0c;就像一张白纸&#xff0c;什么都不懂&#xff0c;只知道埋头苦干。但渐渐地&#xff0c;我发现那些经常“冒泡”的同事似乎总能得到更多的关注和机会。我不禁想&#xff1a;“我是否也要成为那样一个‘邀功精’呢&#xff1f;” 不过&#xff0c;我…

Go自定义数据的序列化流程

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

Apple - Launch Services Programming Guide

本文翻译整理自&#xff1a;Launch Services Programming Guide https://developer.apple.com/library/archive/documentation/Carbon/Conceptual/LaunchServicesConcepts/LSCIntro/LSCIntro.html#//apple_ref/doc/uid/TP30000999-CH201-TP1 文章目录 一、导言谁应该阅读此文档…