项目实战: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

相关文章:
项目实战:Qt+OSG爆破动力学仿真三维引擎测试工具v1.1.0(加载.K模型,子弹轨迹模拟动画,支持windows、linux、国产麒麟系统)
若该文为原创文章,转载请注明出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/142454993 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、Op…...
CSS开发全攻略
目录 一、CSS基础入门(一)CSS概述1.CSS的定义与作用2.CSS的历史与发展3.CSS的核心概念(1)选择器(Selector)(2)声明(Declaration)(3)规…...
OpenCV运动分析和目标跟踪(3)计算图像序列的加权平均值函数accumulateWeighted()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 更新一个运行平均值。 该函数计算输入图像 src 和累积器 dst 的加权和,使得 dst 成为帧序列的运行平均值: dst ( x , y…...
vue3中echarts柱状图横轴文字太多放不下怎么解决
问题:在做数据展示的时候,使用的是echarts,遇到了个问题,就是数据过多,但是设置的x轴的文字名称又太长,往往左边第一个或右边最后一个的名称展示不全,只有半个。 从网上找到了几种办法ÿ…...
Web 开发安全与最佳实践:MVC、会话管理与常见攻击防御
1. 引言 随着 Web 应用的普及,安全问题变得尤为重要。从小型个人网站到复杂的企业级系统,安全漏洞可能导致数据泄露、服务中断甚至经济损失。因此,在 Web 开发中,采用良好的架构设计、会话管理和安全防护机制至关重要。本文将探讨…...
Segformer双显卡推理速度测试
1、4080单显卡和双显卡同步并行推理平均耗时分别为360ms、600ms;双显卡速度明显比单显卡的速度快 2、两个相机间隔500ms的并行推理耗时,单双显卡推理平均耗时为340ms 3、4080双显卡和4070双显卡同步并行推理平均耗时分别为360ms、380ms;4080比4070的速度快20ms...
使用在线电子模拟器 Wokwi 运行 ESP32 示例(Arduino IDE、ESP32C3)
文章目录 Wokwi安装客户端(Mac/Linux)创建 Token ESP32C3 示例demo.ino创建模拟器运行模拟器 Wokwi Wokwi 是一款在线电子模拟器。您可以使用它来模拟 Arduino、ESP32、STM32 以及许多其他流行的主板、部件和传感器。 Github: https://gith…...
vue3+element-plus icons图标选择组件封装
一、最终效果 二、参数配置 1、代码示例 <t-select-icon v-model"selectVlaue" />2、配置参数(Attributes)继承 el-input Attributes 参数说明类型默认值v-model绑定值string-prefixIcon输入框前缀iconstringSearchisShowSearch是否显…...
Spring validation校验框架
第1步:导入依赖 <!-- 校验框架--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId> </dependency> 第2步:为需要校验的参数&…...
UBUNTU20.04安装CH384串口卡驱动
继续上文:统信UOS安装CH384串口卡驱动-CSDN博客 统信UOS系统成功安装CH384串口驱动后,继续在ubuntu20.04下安装驱动,发现一直报错,原因是内核驱动不一致。 解决办法: 1. 下载最新的驱动。CH35XCH384驱动源文件资源-C…...
JWT(JSON Web Tokens) 详细介绍
文章目录 什么是JWT?JWT的组成部分JWT的使用场景优点缺点 Java中如何实现JWT编解码引入JJWT依赖编码JWT解码JWT使用示例 什么是JWT? JWT(JSON Web Tokens)是一种用于双方之间安全传输信息的简洁的、URL安全的令牌标准。JWT可以传递信息,这…...
数据结构练习题————(二叉树)——考前必备合集!
今天在牛客网和力扣上带来了数据结构中二叉树的进阶练习题 1.二叉搜索树与双向链表———二叉搜索树与双向链表_牛客题霸_牛客网 (nowcoder.com) 2.二叉树遍历————二叉树遍历_牛客题霸_牛客网 (nowcoder.com) 3.二叉树的层序遍历————102. 二叉树的层序遍历 - 力扣&am…...
一天认识一个硬件之鼠标
今天来给大家分享一下鼠标的相关内容,先来分享一下什么是鼠标: 鼠标是一种计算机输入设备,用于控制屏幕上的光标移动和进行各种操作。它最早由道格拉斯恩格尔巴特在1963年发明,并在1968年12月9日制成了世界上第一个鼠标。介绍完了…...
Django 请求配置
http请求配置 请求流程 urls.py配置 from first_app import viewsurlpatterns [path(admin/, admin.site.urls),path(test/,views.first_test), ] views.py配置 from django.shortcuts import render,HttpResponse# Create your views here. def first_test(request):prin…...
轮播图组件更加完善版
依然是基于微博语法开发,使用时请注意标签替换 优化了滑动的效果,默认的索引,滑动距离等, 使用方式和以前一样没变,主要修改了组件内部 <template><wbx-view class"" style"width: 100vw;heig…...
cpu路、核、线程
路:主板插口实际插入的 CPU 个数,也可以理解为主板上支持的CPU的数量。每个CPU插槽可以插入一个物理处理器芯片。例如,一台服务器可能有2路或4路插槽,这意味着它最多可以安装2个或4个物理处理器。 核:单块 CPU 上面能…...
鸿蒙开发(NEXT/API 12)【硬件(注册出行业务事件监听)】车载系统
注册出行业务事件监听,用于接收业务发送事件的通知。 接口说明 接口名描述[on] (type: ‘smartMobilityEvent’, smartMobilityTypes: SmartMobilityType[],callback: Callback): void应用注册出行业务事件监听。 开发步骤 导入Car Kit模块。 import { smartMobi…...
安卓中有main函数吗?
在标准的Android应用程序开发中,并不直接使用类似于传统Java或C程序中的main函数入口点。Android应用程序是基于组件的架构,它依赖于几个关键组件来执行不同的任务,这些组件包括Activity、Service、Broadcast Receiver和Content Provider。 …...
js-17-对数组、对象进行浅拷贝和深拷贝
目录 数组一、浅拷贝1. 展开运算符...2. Array.prototype.slice() 二、深拷贝1. JSON方法2. 递归函数 对象一、浅拷贝1. Object.assign()2. 展开运算符... 二、深拷贝1. JSON方法2. 递归函数 自己总结的一些方法,可能有不到位的地方,欢迎指出 数组 一、…...
Ubuntu24.04中安装Electron
1. 安装Nodejs 使用代理服务从github下载并执行Nodejs安装脚本(假设代理服务器为192.168.2.150:10792) curl -x 192.168.2.150:10792 -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash #注意,Nodejs官网的安装命令少了下面这一行: …...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式
简介 在我的 QT/C 开发工作中,合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式:工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...
Python环境安装与虚拟环境配置详解
本文档旨在为Python开发者提供一站式的环境安装与虚拟环境配置指南,适用于Windows、macOS和Linux系统。无论你是初学者还是有经验的开发者,都能在此找到适合自己的环境搭建方法和常见问题的解决方案。 快速开始 一分钟快速安装与虚拟环境配置 # macOS/…...
Java多线程实现之Runnable接口深度解析
Java多线程实现之Runnable接口深度解析 一、Runnable接口概述1.1 接口定义1.2 与Thread类的关系1.3 使用Runnable接口的优势 二、Runnable接口的基本实现方式2.1 传统方式实现Runnable接口2.2 使用匿名内部类实现Runnable接口2.3 使用Lambda表达式实现Runnable接口 三、Runnabl…...
