项目实战:Qt+OSG爆破动力学仿真三维引擎测试工具v1.1.0(加载.K模型,子弹轨迹模拟动画,支持windows、linux、国产麒麟系统)

若该文为原创文章,转载请注明出处
本文章博客地址:https://hpzwl.blog.csdn.net/article/details/142454993

长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…

Qt开发专栏:项目实战(点击传送门)

OSG开发专栏(点击传送门)


需求

  1.使用osg三维引擎进行动力学模型仿真性能测试;
  2.打开动力学仿真模型文件,.k后缀的模型文件,测试加载解析过程;
  3.解决第三方company的opengl制作的三维引擎,绘制面较多与弹丸路径模拟较卡顿的问题;
  4.测试时,使用的模型为公开模型,基础面数量达到160多万个;
  5.测试时,模拟动画使用的时100万条弹丸路径平行飞射出去;


相关博客

  《OSG开发笔记(三十):OSG加载动力学仿真K模型文件以及测试Demo》:该博文也有针对性性能测试过程


Demo V1.1.0

  1.新增打开双模型,第一个模型在原来的位置,第二个模型在偏移后的位置
  2.优化打开关闭重新打开模型的过程
  3.对于100万线动画射击,用于测试性能
  4.当前模型为160万个面,双模型的时候为320多万个元素基础面
  请添加图片描述
  请添加图片描述

  请添加图片描述

  请添加图片描述
   CSDN粉丝0积分下载:https://download.csdn.net/download/qq21497936/89786375
   QQ群:博客技术大全文首行QQ技术群,点击“文件”搜索“osgKFile”,群内与博文同步更新)


Demo v1.0.0

  测试交互流畅性,交互无延迟!!!
  请添加图片描述


模块化部署

  在这里插入图片描述


关键源码

OsgWidget.h

#ifndef OSGWIDGET_H
#define OSGWIDGET_H#include <QWidget>
#include "OsgViewerWidget.h"
#include "MyManipulator.h"
#include "osg/PolygonMode"class AnimationPathCameraMainpulator;namespace Ui {
class OsgWidget;
}class OsgWidget : public QWidget
{Q_OBJECT
public:// 模型结构体struct Element_Shell    // *ELEMENT_SHELL{Element_Shell() {}qint64 eid;         // 单元idqint64 pid;         // 材料idqint64 n1;          // 节点1,定义几何形状qint64 n2;          // 节点2,定义几何形状qint64 n3;          // 节点3,定义几何形状qint64 n4;          // 节点4,定义几何形状qint64 n5;          // 厚度,额外的节点在标准的LS-DYNA四边形壳单元定义中是没有意义的。qint64 n6;          // 积分点数,额外的节点在标准的LS-DYNA四边形壳单元定义中是没有意义的。qint64 n7;          // 额外的节点在标准的LS-DYNA四边形壳单元定义中是没有意义的。qint64 n8;          // 额外的节点在标准的LS-DYNA四边形壳单元定义中是没有意义的。};struct Part             // *PART{Part() {}qint64 pid;         // 部件的id号,唯一qint64 secid;       // 有*section关键字定义的section的id号QList<Element_Shell> listElementShell;  // 部件片元qint64 mid;         // 部件的材料号qint64 eosid;       // 部件所属材料涉及的状态方程号,由*EOS关键字定义qint64 hgid;        // 沙漏或体积粘性参数编号,由*HOURGLASS关键字定义,取0表示将采用默认的数值:qint64 grav;        // 仅对实体单元有效,取0表示对所有PART进行重力初始化,取1表示仅对当前材料初始化qint64 adpopt;      // 标识该部件是否采用自适应网格划分,取0表示不采用qint64 tmid;        // 标识该部件是否采用自适应网格划分,取0表示不采用};struct Node {Node() {}qint64 nid;         // 结点号,唯一double x;           // 三维x坐标(全局)double y;           // 三维y坐标(全局)double z;           // 三维z坐标(全局)int tc;             // 平动自由度受约束状态,枚举值:0-无平动约束,1-X方向平动约束,2-Y方向平动约束int rc;             // 转动自由度收约束状态,枚举值:0-无转动约束,1-X方向转动约束,2-Y方向转动约束};struct K_Mode{K_Mode() {}QList<Part> listPart;QList<Node> listNode;QHash<int, Node> hashNid2Node;};// 添加模型K_Mode kMode;public:explicit OsgWidget(QWidget *parent = 0);~OsgWidget();public:bool getFixXAxis() const;               // 获取X轴固定状态bool getFixYAxis() const;               // 获取Y轴固定状态bool getFixZAxis() const;               // 获取Z轴固定状态void getCenter(double &x, double &y, double &z);// 获取引擎中心点坐标void getPersonPoint(double &x, double &y, double &z);// 获取初始化人眼的角度(看向引擎中心点)public:void setFixXAxis(bool fixXAxis);        // 设置固定X轴void setFixYAxis(bool fixYAxis);        // 设置固定Y轴void setFixZAxis(bool fixZAxis);        // 设置固定Z轴void setCenter(double x, double y, double z);// 设置引擎中心点坐标void setPersonPoint(double x, double y, double z);void setEnablePolygonMode(bool enable);void startAnimation();void pauseAnimation();void stopAnimation();public:bool loadKFile(QString filePath);bool loadK2File(QString filePath, int num, int x, int y, int z);void clear();void resetCoordinate();protected:void initOsg();                 // osg初始化void loadNode(osg::ref_ptr<osg::Node> pNode);// 加载场景根节点protected:osg::ref_ptr<osg::Node> createScene();          // 创建总场景osg::ref_ptr<osg::Node> createAnimation();      // 创建动画protected:void resizeEvent(QResizeEvent *event);void keyPressEvent(QKeyEvent* event);void keyReleaseEvent(QKeyEvent* event);void mousePressEvent(QMouseEvent* event);void mouseReleaseEvent(QMouseEvent* event);void mouseDoubleClickEvent(QMouseEvent* event);void mouseMoveEvent(QMouseEvent* event);void wheelEvent(QWheelEvent* event);void timerEvent(QTimerEvent *event);private:Ui::OsgWidget *ui;private:OsgViewerWidget *_pViewer;                  // osg场景嵌入Qt核心类osg::ref_ptr<osg::MatrixTransform> _pRoot;  // osg场景根节点private:float _xDistance;                           // x轴单个tick间距int _xTickNumber;                           // x轴tick数(例如:5的时候,是6个,0~5)float _yDistance;                           // y轴单个tick间距int _yTickNumber;                           // y轴tick数(例如:5的时候,是6个,0~5)float _zDistance;                           // z轴单个tick间距int _zTickNumber;                           // z轴tick数(例如:5的时候,是6个,0~5)QString _zUnit;                             // z轴单位float _zTickLabelOffset;                    // z轴坐标偏移QString _yUnit;                             // y轴单位float _zTickUnitLabelOffset;                // z轴坐标偏移QColor _gridColor;                          // 轴颜色QColor _labelColor;                         // 轴tickLabel的颜色osg::ref_ptr<osg::Node> _pNode;             // 模型osg::ref_ptr<osg::Node> _pNode2;             // 子弹osg::ref_ptr<MyManipulator> _pManipulator;  // 自定义漫游器osg::Vec3d _eyeVect3D;                      // 原始坐标,用于复位原始视角osg::Vec3d _centerVect3D;                   // 原始坐标,用于复位原始视角osg::Vec3d _upVect3D;                       // 原始坐标,用于复位原始视角K_Mode _kMode;int _timerId;osg::ref_ptr<osg::StateSet> _pStateSet;osg::ref_ptr<osg::PolygonMode> _pPolygonMode;osg::ref_ptr<osg::Vec3Array> _pVec3Array;   // 炮弹bool _animationPausing;};#endif // OSGWIDGET_H

OsgWidget.cpp

bool OsgWidget::loadK2File(QString filePath, int num, int x, int y, int z)
{if(!QFile::exists(filePath)){LOG << "Not exist file:" << filePath;QMessageBox::information(0, "错误", QString("Not exist file: %1").arg(filePath));return false;}QFile file(filePath);if(!file.open(QIODevice::ReadOnly)){LOG << "Failed to open file:" << filePath;QMessageBox::information(0, "错误", QString("Failed to open file: %1").arg(filePath));return false;}kMode = K_Mode();QTextStream textStream(&file);QString context;qint64 rowIndex = -1;context = textStream.readLine();rowIndex++;LOG;...file.close();LOG;osg::ref_ptr<osg::Group> pGroup = new osg::Group;for(int index = 0; index < num; index++){LOG << index;// 绘图{for(int partIndex = 0; partIndex < kMode.listPart.size(); partIndex++){// 创建一个用户保存几何信息的对象osg::ref_ptr<osg::Geometry> pGeometry = new osg::Geometry;// 创建四个顶点的数组osg::ref_ptr<osg::Vec3Array> pVec3Array = new osg::Vec3Array;// 添加四个顶点pGeometry->setVertexArray(pVec3Array.get());// 创建四种颜色的数据osg::ref_ptr<osg::Vec4Array> pVec4Array = new osg::Vec4Array;// 添加四种颜色pGeometry->setColorArray(pVec4Array.get());// 绑定颜色pGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);double r, g, b;r = qrand() % 100 * 1.0f / 100;g = qrand() % 100 * 1.0f / 100;b = qrand() % 100 * 1.0f / 100;for(int elementShellIndex = 0; elementShellIndex < kMode.listPart.at(partIndex).listElementShell.size(); elementShellIndex++){//                               x     y     zpVec3Array->push_back(osg::Vec3(kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n1).x + index * x,kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n1).y + index * y,kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n1).z + index * z));pVec3Array->push_back(osg::Vec3(kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n2).x + index * x,kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n2).y + index * y,kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n2).z + index * z));pVec3Array->push_back(osg::Vec3(kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n3).x + index * x,kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n3).y + index * y,kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n3).z + index * z));pVec3Array->push_back(osg::Vec3(kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n4).x + index * x,kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n4).y + index * y,kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n4).z + index * z));//                               r    g    b    a(a设置无效,估计需要其他属性配合)pVec4Array->push_back(osg::Vec4(r, g, b, 1.0));pVec4Array->push_back(osg::Vec4(r, g, b, 1.0));pVec4Array->push_back(osg::Vec4(r, g, b, 1.0));pVec4Array->push_back(osg::Vec4(r, g, b, 1.0));}// 注意:此处若不绑定画笔,则表示使用之前绑定的画笔// 为唯一的法线创建一个数组    法线: normalosg::ref_ptr<osg::Vec3Array> pVec3ArrayNormal = new osg::Vec3Array;pGeometry->setNormalArray(pVec3ArrayNormal.get());pGeometry->setNormalBinding(osg::Geometry::BIND_OVERALL);pVec3ArrayNormal->push_back(osg::Vec3(0.0, -1.0, 0.0));// 由保存的数据绘制四个顶点的多边形pGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, kMode.listPart.at(partIndex).listElementShell.size() * 4));//            pGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));// 向Geode类添加几何体(Drawable)osg::ref_ptr<osg::Geode> pGeode = new osg::Geode;pGeode->addDrawable(pGeometry.get());
#if 0{_pStateSet = pGeometry->getOrCreateStateSet();//                _pPolygonMode = new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);_pPolygonMode = new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::FILL);_pStateSet->setAttribute(_pPolygonMode, osg::StateAttribute::ON);}
#endifpGroup->addChild(pGeode.get());}}}// 始终是灰色,这里需要设置关闭光照:OFF,同时旋转都能看到了(光照关闭,法向量不起作用){osg::StateSet *pStateSet = pGroup->getOrCreateStateSet();//      pStateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON);pStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);}_pNode = pGroup.get();if(_pNode.get() == 0){return false;}_pRoot->addChild(_pNode);return true;
}

工程模板v1.1.0

  在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第24届工博会盛大开启,大腾智能携前沿数字化解决方案亮相

2024年9月24日&#xff0c;第24届中国国际工业博览会(ICIF China 2024)&#xff08;以下简称“工博会”&#xff09;在上海盛大开幕。本届工博会以“新质领航 数字赋能”为主题&#xff0c;覆盖工业自动化、智能制造等多个领域&#xff0c;汇聚全球制造业的精英与前沿技术&…

MySQL连接查询解析与性能优化成本

文章目录 一、连接查询1.连接查询基础1. INNER JOIN内连接2. LEFT JOIN (或 LEFT OUTER JOIN)左外连接3. RIGHT JOIN (或 RIGHT OUTER JOIN)右外连接4. FULL OUTER JOIN 2.连接查询的两种过滤条件3.连接的原理 二、性能优化成本1.基于成本的优化2.调节成本常数(1)mysql.server_…

Tangle解压玩具商标重复维权,尚未TRO,卖家速查

案件基本情况&#xff1a;起诉时间&#xff1a;2024-9-13案件号&#xff1a;2024-cv-61700品牌&#xff1a;Tangle原告&#xff1a;Tangle Inc.原告律所&#xff1a;Boies Schiller Flexner起诉地&#xff1a;佛罗里达州南部法院涉案商标/版权&#xff1a;原告品牌简介&#xf…

linux远程工具MobaXterm的安装和使用

一、安装和运行 1、下载 地址&#xff1a;&#xff08;手机夸克转存后下载是对作者最大的支持&#xff09;https://pan.quark.cn/s/32e1f5e5e95c 2、解压 解压到到常用软件目录下&#xff0c;如C:\Program Files 3、运行 双击MobaXterm_Personal_24.2.exe运行&#xff0c;…

Python 使用selenium 4.25 进行爬虫(1)

都说python做爬虫比较好&#xff0c;于是我跟着大家的脚步学习python进行爬虫&#xff0c;但是调试了半天&#xff0c;出现各种各样的问题&#xff0c;最终都得到实现了&#xff0c;下面我们来看具体的代码&#xff1a; from selenium import webdriver from selenium.webdriv…

【Python报错已解决】TypeError: can only concatenate str (not “int“) to str

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

failed to load steamui.dll的多种处理方法,steamui.dll的作用

在使用Steam平台时&#xff0c;不少玩家可能会遇到“failed to load steamui.dll”这样令人头疼的错误提示。这个错误会阻碍Steam客户端的正常运行&#xff0c;影响我们享受游戏和Steam平台的各种服务。不过&#xff0c;不必过于担心&#xff0c;因为有多种方法可以尝试解决这个…

一招搞定苹果安卓跨系统传输,文件大小再也不是问题

在当今多元化的科技市场中&#xff0c;众多手机品牌竞相推出各自的产品&#xff0c;每个品牌都力图打造独特的用户体验和生态系统。然而&#xff0c;这种品牌之间的多样性也带来了一定的挑战&#xff0c;尤其是在不同品牌体系之间互联互通性方面。由于每个品牌都有自己的操作系…

网站设计中安全方面都需要有哪些考虑

网站设计中的安全性是一个多方面的问题&#xff0c;需要从多个角度进行考虑和实施。以下是一些关键的安全考虑因素&#xff1a; 数据加密&#xff1a; 使用SSL&#xff08;安全套接字层&#xff09;证书来建立加密连接&#xff0c;确保数据在传输过程中不被截获。定期更新SSL证…

神经网络(四):UNet图像分割网络

文章目录 一、简介二、网络结构2.1编码器部分2.2解码器部分2.3完整代码 三、实战案例 一、简介 UNet网络是一种用于图像分割的卷积神经网络&#xff0c;其特点是采用了U型网络结构&#xff0c;因此称为UNet。该网络具有编码器和解码器结构&#xff0c;两种结构的功能如下&#…

【第十七章:Sentosa_DSML社区版-机器学习之异常检测】

【第十七章&#xff1a;Sentosa_DSML社区版-机器学习之异常检测】 机器学习异常检测是检测数据集中的异常数据的算子&#xff0c;一种高效的异常检测算法。它和随机森林类似&#xff0c;但每次选择划分属性和划分点&#xff08;值&#xff09;时都是随机的&#xff0c;而不是根…

LVS-DR实战案例,实现四层负载均衡

环境准备&#xff1a;三台虚拟机&#xff08;NET模式或者桥接模式&#xff09; 192.168.88.200 &#xff08;web1&#xff09;(安装nginx服务器作为测试) 192.168.88.201 &#xff08;服务器&#xff09;&#xff08;用于部署lvs-dr&#xff09; 192.168.88.202 (web2)…

30 | 理论四:如何通过封装、抽象、模块化、中间层等解耦代码?

前面我们讲到&#xff0c;重构可以分为大规模高层重构&#xff08;简称“大型重构”&#xff09;和小规模低层次重构&#xff08;简称“小型重构”&#xff09;。大型重构是对系统、模块、代码结构、类之间关系等顶层代码设计进行的重构。对于大型重构来说&#xff0c;今天我们…

华为静态路由(route-static)

静态路由的组成 在华为路由器中&#xff0c;使用ip route-static命令配置静态路由。 一条静态路由主要包含以下要素&#xff1a; 目的地址&#xff1a;数据包要到达的目标IP地址 子网掩码&#xff1a;用于指定目的地址的网络部分和主机部分 下一跳地址&#xff08;可选&#…

linux之mysql安装

1:mysql安装包下载 下载地址 可私信我直接获取安装包 2:linux下wget命令下载 下载地址 wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.24-linux-glibc2.12-x86_64.tar.gz3:手动安装 将自己的安装包上传到对应的位置 解压 压缩包 使用命令 tar -zxvf mysql-5.7…

Redis面试真题总结(四)

文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ AOF 持久化&#xff1f; AOF&#xff08;Append Only File&#x…

ubuntu安装emqx

目录 1.预先下载好emqx压缩包 2.使用tar命令解压 3.进入bin目录 5.放开访问端口18083 6.从通过ip地址访问emqx后台 7.默认用户名密码为admin/public 8.登录后台 9.资源包绑定在此博文可自取 1.预先下载好emqx压缩包 2.使用tar命令解压 sudo tar -xzvf emqx-5.0.8-el8-…

精密单轴纵切自动车床

精密单轴纵切自动车床&#xff0c;作为现代机械加工领域的重要设备&#xff0c;以其高精度、高效率的特点&#xff0c;广泛应用于各种精密零件的加工制造中。下面&#xff0c;我将从几个方面来详细解析这种车床的特点和应用。 ‌一、定义与特点‌ ‌精密单轴纵切自动车床‌&…

[笔记]2024大厂变频器,电机参数一览

注意中心高&#xff0c;在用铁心规格&#xff0c;功率换算表 温升曲线在预防性维护过程能用到 注意各类电流参数,上面双极对&#xff0c;下面3极对。 另一种极对数 4极对的电机参数可参考&#xff0c;不常用。 emc滤波&#xff0c; Sto,通讯接口 颜色区分的接口设计 一组新强…

灵当CRM index.php接口SQL注入漏洞复现 [附POC]

文章目录 灵当CRM index.php接口SQL注入漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 灵当CRM index.php接口SQL注入漏洞复现 [附POC] 0x01 前言 免责声明&#xff1a;请勿利用文章内的相关技…