项目实战: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.mzph.cn/web/53751.shtml

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

相关文章

数据科学 - 字符文本处理

1. 字符串的基本操作 1.1 结构操作 1.1.1 拼接 • 字符串之间拼接 字符串之间的拼接使用进行字符串的拼接 a World b Hello print(b a) • 列表中的字符串拼接 将以分隔符‘,’为例子 str [apple,banana] print(,.join(str)); • 字符串中选择 通过索引进行切片操…

【网络安全】-访问控制-burp(1~6)

文章目录 前言   1.Lab: Unprotected admin functionality  2.Lab: Unprotected admin functionality with unpredictable URL   3.Lab: User role controlled by request parameter   4.Lab:User role can be modified in user profile  5.Lab: User ID controlled by…

Windows 10 系统安装 FFmpeg 查看、转换、编辑音频文件

1、FFmpeg官网&#xff1a;FFmpeg 点击下载 可以选择下载full版本 下载之后解压到指定目录&#xff0c;在系统环境变量 Path 里面新增环境变量 打开CMD终端运行 ffmpeg -version 查看是否安装成功。 2、基本命令 查看音频基本信息 ffprobe 1.mp3 ##输出 [mp3 000002ab334405…

LLM - 使用 XTuner 指令微调 多模态大语言模型(InternVL2) 教程

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/142528967 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 XTuner…

Spark-RDD持久化

一、Spark的三种持久化机制 1、cache 它是persist的一种简化方式&#xff0c;作用是将RDD缓存到内存中&#xff0c;以便后续快速访问&#xff0c;提高计算效率。cache操作是懒执行的&#xff0c;即执行action算子时才会触发。 2、persist 它提供了不同的存储级别&#xff0…

关于神经网络的一个介绍

这篇文章中&#xff0c;我将简单介绍下与神经网络有关的东西&#xff0c;包括它的基本模型&#xff0c;典型的算法以及与深度学习的联系等内容。 一、神经元 神经网络是由许多个神经元组成的&#xff0c;在生物的神经网络中&#xff0c;就是神经元间相互连接&#xff0c;传递…

高校竞赛管理系统的设计与实现

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统高校竞赛管理系统信息管理难度大&#xff0c;容错率低&am…

Ubuntu 开机自启动 .py / .sh 脚本,可通过脚本启动 roslaunch/roscore等

前言 项目中要求上电自启动定位程序&#xff0c;所以摸索了一种 Ubuntu 系统下开机自启动的方法&#xff0c;开机自启动 .sh 脚本&#xff0c;加载 ROS 环境的同时启动 .py 脚本。在 . py 脚本中启动一系列 ROS 节点。 一、 .sh 脚本的编写 #!/bin/bash # gnome-terminal -- …

Leetcode - 周赛416

目录 一&#xff0c;3295. 举报垃圾信息 二&#xff0c;3296. 移山所需的最少秒数 三&#xff0c;3297. 统计重新排列后包含另一个字符串的子字符串数目 I 四&#xff0c;3298. 统计重新排列后包含另一个字符串的子字符串数目 II 一&#xff0c;3295. 举报垃圾信息 本题就是…

Linux 安装nginx

下载安装 https://nginx.org/en/download.html 解压 tar -zxvf nginx-1.26.2.tar.gz -C /opt chmod 777 -R /opt/nginx-1.26.2/编译 && 安装 # 安装到同目录以免乱套&#xff0c;一定要先创建目录 mkdir /opt/nginx-1.26.2/nginx/# 编译 make # 安装&#xff0c;大…

将Mixamo的模型和动画导入UE5

首先进入Mixamo的官网 , 点击 Character 选择一个模型 (当然你也可以自己上传模型/绑定动画) 然后点击下载 , 这个作为带骨骼的模型 选择FBX格式 , T Pose 直接下载 点击 Animations 选择动画 , 搜索 idle 默认站立动画 点击下载 , 格式选择 FBX , 不带模型只要骨骼 , 帧数选6…

MySQL_表_进阶(2/2)

上一章我们谈了排序子句&#xff0c;使用ORDER BY 字段 DESC/ASC。以及左右连接的多关系查询。 今天&#xff0c;没错&#xff0c;四张表最后两个需求 ✨涉及聚合函数查询与指定别名 四张表&#xff1a; 学院表&#xff1a;(testdb.dept) 课程表&#xff1a;(testdb.course) 选…

Rust编程的if选择语句

【图书介绍】《Rust编程与项目实战》-CSDN博客 《Rust编程与项目实战》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 (jd.com) Rust编程与项目实战_夏天又到了的博客-CSDN博客 Rust语言实现选择结构时&#xff0c;根据某种条件的成立与否而采用不同的程序段进行…

基于nodejs+vue的农产品销售管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

FortiGate 无线组网

无线管理与配置 FortiAP 连接 internal 接口之后自动获得 ip 地址&#xff1a;192.168.1.xxx/24在 FortiGate 中创建 SSIDFortiGate 自动发现 FortiAP&#xff0c;将 FortiAP 添加到 FortiGate将 SSID 和 FortiAP 关联创建防火墙策略 下面我们就来一起看看在 FortiGate 中该如…

ModbusTCP通讯错误的排查

Modbus是一种由MODICON公司开发的工业现场总线协议标准&#xff0c;是一项应用层报文传输协议。该协议用于传输数字和模拟变量[1]。有关该协议的报文具体格式&#xff0c;以及一些基本概念&#xff0c;见[1]。 本文以一个例子&#xff0c;阐述当ModbusTCP通讯出现错误的时候&a…

开源鸿蒙OpenHarmony系统更换开机Logo方法,瑞芯微RK3566鸿蒙开发板

本文适用于开源鸿蒙OpenHarmony系统更换开机Logo&#xff0c;本次使用的是触觉智能的Purple Pi OH鸿蒙开源主板&#xff0c;搭载了瑞芯微RK3566芯片&#xff0c;类树莓派设计&#xff0c;是Laval官方社区主荐的一款鸿蒙开发主板。 介绍 OpenHarmony的品牌标志、版本信息、项目…

计算机毕业设计 基于Hadoop的智慧校园数据共享平台的设计与实现 Python 数据分析 可视化大屏 附源码 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

探索EasyCVR视频融合平台:在视频编解码与转码领域的灵活性优势

随着视频监控技术的飞速发展&#xff0c;各类应用场景对视频数据的处理需求日益复杂多样。从公共安全到智慧城市&#xff0c;再到工业监控&#xff0c;高效、灵活的视频处理能力成为衡量视频融合平台性能的重要标准。在众多解决方案中&#xff0c;EasyCVR视频融合平台凭借其在视…

大觅网之自动化部署(Automated Deployment of Da Mi Network)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…