项目实战: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.xdnf.cn/news/148584.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

MongoDB-索引的使用和索引类型

目录 简介创建索引的方式索引的种类单列索引复合索引&#xff08;多列索引&#xff09;多键索引地理空间索引文本搜索索引Hash索引 索引属性 简介 MongoDB的索引种类还是不少的&#xff0c;因为它是个文档数据库&#xff0c;存储的数据种类杂七杂八的&#xff0c;针对MongoDB的…

MySQL学习笔记(持续更新中)

1、Mysql概述 1.1 数据库相关概念 三个概念&#xff1a;数据库、数据库管理系统、SQL 名称全称简称数据库存储数据的仓库&#xff0c;数据是有组织的进行存储DataBase&#xff08;DB&#xff09;数据库管理系统操纵和管理数据库的大型软件DataBase Mangement System&#xf…

输电线塔目标检测数据集yolo格式该数据集包括2644张输电线塔高清图像,该数据集已经过yolo格式标注,具有完整的txt标注文件和yaml配置文件。

输电线塔目标检测数据集yolo格式 该数据集包括2644张输电线塔高清图像&#xff0c;该数据集已经过yolo格式标注&#xff0c;具有完整的txt标注文件和yaml配置文件。 输电线塔目标检测数据集 数据集名称 输电线塔目标检测数据集&#xff08;Transmission Tower Object Detecti…

网页设计html心得

一&#xff0c;认识网页 说到网页&#xff0c;其实大家并不陌生 1.1网页究竟是什么&#xff1f; 网页主要由文字、图像和超链接等元素构成。当然&#xff0c;除了这些元素&#xff0c;网页中还可以包含音频、视频以及Flash等。 1.2网页是如何形成的呢&#xff1f; 1.特殊的…

Spring Boot 中的拦截器 Interceptors

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 前言 Spring Boot中的拦截器&#xff08;Interceptor&#xff09;是一种用于拦截和处理HTTP请求的机制&#xff0c;它基于Spring MVC框架中的HandlerInterceptor接口实现。拦截器允许在请求到达控制器&#…

git笔记之重置本地仓库所有分支和远程保持一致、工作区恢复干净,像刚clone下来一样

git笔记之重置本地仓库所有分支和远程保持一致、工作区恢复干净&#xff0c;像刚clone下来一样 code review! 文章目录 git笔记之重置本地仓库所有分支和远程保持一致、工作区恢复干净&#xff0c;像刚clone下来一样1.实现该功能的 Bash 脚本示例2.改进版&#xff1a;增加了gi…

微软宣布弃用面向企业的WSUS更新服务 仍然保留该服务但不再添加任何新功能

Windows Server Update Services 是微软面向企业推出的一项更新服务&#xff0c;该服务已经存在很多年&#xff0c;允许 IT 管理员控制内网设备的更新节奏。今年早些时候微软宣布将在 2025 年 4 月 18 日开始弃用 WSUS 驱动程序同步功能&#xff0c;因为大约只有 1/3 的 IT 管理…

大模型榜单汇总整理

大型语言模型&#xff08;LLM&#xff09;评估榜单提供了对不同模型性能的标准化比较&#xff0c;涵盖了从通用能力到特定领域应用的多个方面。这些榜单专注于评估模型在特定领域的应用能力&#xff0c;有助于开发者了解模型的优势和局限性&#xff0c;推动语言模型的发展和优化…

前端html+css+js 基础总结

​​​HTML 行级元素 标签分为行级元素与块级元素 行级元素占据区域由其显示内容决定&#xff0c;如span&#xff0c;img(图片)&#xff0c;<a></a>基本格式: <a href"链接" target"_blank"></a>用于跳转到其他网站&#xff0c…

镭射限高防外破预警装置-线路防外破可视化监控,安全尽在掌握中

镭射限高防外破预警装置-线路防外破可视化监控&#xff0c;安全尽在掌握中 在城市化浪潮的汹涌推进中&#xff0c;电力如同现代社会的生命之脉&#xff0c;其安全稳定运行直接关系到每一个人的生活质量和社会的整体发展。然而&#xff0c;随着建设的加速&#xff0c;电力设施通…

论文写作中的常见错误及规避策略

写论文&#xff0c;这个让无数学生闻风丧胆的挑战&#xff0c;可真是让人头大。 不管是初出茅庐的本科毕业论文&#xff0c;还是折腾得人头发都少了的硕士、博士论文&#xff0c;写作过程中的各种翻车场景简直就是论文写作的日常。 别慌&#xff0c;今天我就来当大家的论文救…

基于Python+SQLServer实现(界面)书店销售管理管理子系统

书店销售管理管理子系统 一、设 计 总 说 明 现在社会随着计算机技术迅速发展与技术的逐渐成熟&#xff0c;信息技术已经使人们的生活发生深刻的变化。生活中的各种服务系统也使人们在生活中的联系日常销售活动方式发生了很大的变化&#xff0c;让效率较低的手工操作成为过去…

vue3/Element-Plus/路由的使用

我们来实现一个简单的二级路由 1.准备主页和要配置的组件 主页面 <template><!-- 加载配置路由 --><RouterView></RouterView> </template><style scoped></style>组件1 <template><div>考试组件</div> </t…

【k8s】:DevOps 模式详解

1.什么是DevOps模式&#xff1f; DevOps 是当下非常火爆的一个概念&#xff0c;受到了很多互联网巨头的推崇。那么什么是 DevOps&#xff1f;它的全称是&#xff1a;集成开发与运维。至于它到底是干什么用的&#xff0c;为什么现在这么火爆&#xff0c;还得从源头说起。 1.1 …

vue3 vxe-grid 通过数据库返回的列信息,生成columns,并且其中有一列是img类型,进行slots的格式化处理。

1、一般我们写死的列信息的时候&#xff0c;会这样定义&#xff1a; 2、然后我们在template里面&#xff0c;这样这样写slots格式化部分&#xff1a; 这样表格中就会展示出一张图片&#xff0c;并且&#xff0c;我们点击了可以查看大图。 3、那么我们从数据库中返回的列&#…

二维矩阵的行、列、斜线特征(二维数组)

1. 行特征 二维 n*m 矩阵&#xff0c;用 x[i][j] 表示第 i 行第 j 列的元素。同一行的元素的 i 值是相同的。 例如&#xff0c;上图中绿色格子的数组元素分别是 x[4][1]&#xff0c;x[4][2]&#xff0c;x[4][3]&#xff0c;x[4][4]&#xff0c;x[4][5]&#xff0c;x[4][6]。 …

IDEA明明模块和环境变量配置的是JDK8但是显示别的版本解决方案

IDEA明明模块和环境变量配置的是JDK8但是显示别的版本解决方案 我目前系统中存在JDK8&#xff0c;JDK11,JDK17等多个版本&#xff0c;方便开发使用&#xff0c;但是有些时候也是比较烦人的&#xff0c;因为不同版本的JDK包有所区别。 需要注意的几个地方。方便自己排查一下。

UML——统一建模语言

序言&#xff1a; 是统一建模语言的简称&#xff0c;它是一种由一整套图表组成的标准化建模语言。UML用于帮助系统开发人员阐明&#xff0c;展示&#xff0c;构建和记录软件系统的产出。UML代表了一系列在大型而复杂系统建模中被证明是成功的做法&#xff0c;是开发面向对象软件…

信息安全工程师(14)网络攻击常见技术方法

前言 网络攻击的常见技术方法多种多样&#xff0c;这些方法旨在未经授权地访问、破坏或窃取目标系统的信息。 1. 侦察与信息收集 开放源情报收集&#xff1a;利用搜索引擎、社交媒体等公开渠道获取目标的基本信息。扫描技术&#xff1a;包括端口扫描、服务扫描等&#xff0c;以…

UE学习篇ContentExample解读-----------Blueprint_Mouse_Interaction

文章目录 总览描述&#xff08;Blueprint_Mouse_Interaction&#xff09;阅览解析1、PlayerControler分析2、拖拽球蓝图分析&#xff1a;3、移动的立方体分析&#xff1a; 新概念总结致谢&#xff1a; 总览描述&#xff08;Blueprint_Mouse_Interaction&#xff09; 打开关卡后…