项目实战:Qt+OSG爆破动力学仿真三维引擎测试工具v1.1.0(加载.K模型,子弹 ...

王國慶  金牌会员 | 2024-9-28 03:09:28 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 858|帖子 858|积分 2578

若该文为原创文章,转载请注明出处
本文章博客所在: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

  1. #ifndef OSGWIDGET_H
  2. #define OSGWIDGET_H
  3. #include <QWidget>
  4. #include "OsgViewerWidget.h"
  5. #include "MyManipulator.h"
  6. #include "osg/PolygonMode"
  7. class AnimationPathCameraMainpulator;
  8. namespace Ui {
  9. class OsgWidget;
  10. }
  11. class OsgWidget : public QWidget
  12. {
  13.     Q_OBJECT
  14. public:
  15.     // 模型结构体
  16.     struct Element_Shell    // *ELEMENT_SHELL
  17.     {
  18.         Element_Shell() {
  19.         }
  20.         qint64 eid;         // 单元id
  21.         qint64 pid;         // 材料id
  22.         qint64 n1;          // 节点1,定义几何形状
  23.         qint64 n2;          // 节点2,定义几何形状
  24.         qint64 n3;          // 节点3,定义几何形状
  25.         qint64 n4;          // 节点4,定义几何形状
  26.         qint64 n5;          // 厚度,额外的节点在标准的LS-DYNA四边形壳单元定义中是没有意义的。
  27.         qint64 n6;          // 积分点数,额外的节点在标准的LS-DYNA四边形壳单元定义中是没有意义的。
  28.         qint64 n7;          // 额外的节点在标准的LS-DYNA四边形壳单元定义中是没有意义的。
  29.         qint64 n8;          // 额外的节点在标准的LS-DYNA四边形壳单元定义中是没有意义的。
  30.     };
  31.     struct Part             // *PART
  32.     {
  33.         Part() {
  34.         }
  35.         qint64 pid;         // 部件的id号,唯一
  36.         qint64 secid;       // 有*section关键字定义的section的id号
  37.         QList<Element_Shell> listElementShell;  // 部件片元
  38.         qint64 mid;         // 部件的材料号
  39.         qint64 eosid;       // 部件所属材料涉及的状态方程号,由*EOS关键字定义
  40.         qint64 hgid;        // 沙漏或体积粘性参数编号,由*HOURGLASS关键字定义,取0表示将采用默认的数值:
  41.         qint64 grav;        // 仅对实体单元有效,取0表示对所有PART进行重力初始化,取1表示仅对当前材料初始化
  42.         qint64 adpopt;      // 标识该部件是否采用自适应网格划分,取0表示不采用
  43.         qint64 tmid;        // 标识该部件是否采用自适应网格划分,取0表示不采用
  44.     };
  45.     struct Node {
  46.         Node() {
  47.         }
  48.         qint64 nid;         // 结点号,唯一
  49.         double x;           // 三维x坐标(全局)
  50.         double y;           // 三维y坐标(全局)
  51.         double z;           // 三维z坐标(全局)
  52.         int tc;             // 平动自由度受约束状态,枚举值:0-无平动约束,1-X方向平动约束,2-Y方向平动约束
  53.         int rc;             // 转动自由度收约束状态,枚举值:0-无转动约束,1-X方向转动约束,2-Y方向转动约束
  54.     };
  55.     struct K_Mode
  56.     {
  57.         K_Mode() {}
  58.         QList<Part> listPart;
  59.         QList<Node> listNode;
  60.         QHash<int, Node> hashNid2Node;
  61.     };
  62.     // 添加模型
  63.     K_Mode kMode;
  64. public:
  65.     explicit OsgWidget(QWidget *parent = 0);
  66.     ~OsgWidget();
  67. public:
  68.     bool getFixXAxis() const;               // 获取X轴固定状态
  69.     bool getFixYAxis() const;               // 获取Y轴固定状态
  70.     bool getFixZAxis() const;               // 获取Z轴固定状态
  71.     void getCenter(double &x, double &y, double &z);
  72.                                             // 获取引擎中心点坐标
  73.     void getPersonPoint(double &x, double &y, double &z);
  74.                                             // 获取初始化人眼的角度(看向引擎中心点)
  75. public:
  76.     void setFixXAxis(bool fixXAxis);        // 设置固定X轴
  77.     void setFixYAxis(bool fixYAxis);        // 设置固定Y轴
  78.     void setFixZAxis(bool fixZAxis);        // 设置固定Z轴
  79.     void setCenter(double x, double y, double z);
  80.                                             // 设置引擎中心点坐标
  81.     void setPersonPoint(double x, double y, double z);
  82.     void setEnablePolygonMode(bool enable);
  83.     void startAnimation();
  84.     void pauseAnimation();
  85.     void stopAnimation();
  86. public:
  87.     bool loadKFile(QString filePath);
  88.     bool loadK2File(QString filePath, int num, int x, int y, int z);
  89.     void clear();
  90.     void resetCoordinate();
  91. protected:
  92.     void initOsg();                 // osg初始化
  93.     void loadNode(osg::ref_ptr<osg::Node> pNode);
  94.                                     // 加载场景根节点
  95. protected:
  96.     osg::ref_ptr<osg::Node> createScene();          // 创建总场景
  97.     osg::ref_ptr<osg::Node> createAnimation();      // 创建动画
  98. protected:
  99.     void resizeEvent(QResizeEvent *event);
  100.     void keyPressEvent(QKeyEvent* event);
  101.     void keyReleaseEvent(QKeyEvent* event);
  102.     void mousePressEvent(QMouseEvent* event);
  103.     void mouseReleaseEvent(QMouseEvent* event);
  104.     void mouseDoubleClickEvent(QMouseEvent* event);
  105.     void mouseMoveEvent(QMouseEvent* event);
  106.     void wheelEvent(QWheelEvent* event);
  107.     void timerEvent(QTimerEvent *event);
  108. private:
  109.     Ui::OsgWidget *ui;
  110. private:
  111.     OsgViewerWidget *_pViewer;                  // osg场景嵌入Qt核心类
  112.     osg::ref_ptr<osg::MatrixTransform> _pRoot;  // osg场景根节点
  113. private:
  114.     float _xDistance;                           // x轴单个tick间距
  115.     int _xTickNumber;                           // x轴tick数(例如:5的时候,是6个,0~5)
  116.     float _yDistance;                           // y轴单个tick间距
  117.     int _yTickNumber;                           // y轴tick数(例如:5的时候,是6个,0~5)
  118.     float _zDistance;                           // z轴单个tick间距
  119.     int _zTickNumber;                           // z轴tick数(例如:5的时候,是6个,0~5)
  120.     QString _zUnit;                             // z轴单位
  121.     float _zTickLabelOffset;                    // z轴坐标偏移
  122.     QString _yUnit;                             // y轴单位
  123.     float _zTickUnitLabelOffset;                // z轴坐标偏移
  124.     QColor _gridColor;                          // 轴颜色
  125.     QColor _labelColor;                         // 轴tickLabel的颜色
  126.     osg::ref_ptr<osg::Node> _pNode;             // 模型
  127.     osg::ref_ptr<osg::Node> _pNode2;             // 子弹
  128.     osg::ref_ptr<MyManipulator> _pManipulator;  // 自定义漫游器
  129.     osg::Vec3d _eyeVect3D;                      // 原始坐标,用于复位原始视角
  130.     osg::Vec3d _centerVect3D;                   // 原始坐标,用于复位原始视角
  131.     osg::Vec3d _upVect3D;                       // 原始坐标,用于复位原始视角
  132.     K_Mode _kMode;
  133.     int _timerId;
  134.     osg::ref_ptr<osg::StateSet> _pStateSet;
  135.     osg::ref_ptr<osg::PolygonMode> _pPolygonMode;
  136.     osg::ref_ptr<osg::Vec3Array> _pVec3Array;   // 炮弹
  137.     bool _animationPausing;
  138. };
  139. #endif // OSGWIDGET_H
复制代码
OsgWidget.cpp

  1. bool OsgWidget::loadK2File(QString filePath, int num, int x, int y, int z)
  2. {
  3.     if(!QFile::exists(filePath))
  4.     {
  5.         LOG << "Not exist file:" << filePath;
  6.         QMessageBox::information(0, "错误", QString("Not exist file: %1").arg(filePath));
  7.         return false;
  8.     }
  9.     QFile file(filePath);
  10.     if(!file.open(QIODevice::ReadOnly))
  11.     {
  12.         LOG << "Failed to open file:" << filePath;
  13.         QMessageBox::information(0, "错误", QString("Failed to open file: %1").arg(filePath));
  14.         return false;
  15.     }
  16.     kMode = K_Mode();
  17.     QTextStream textStream(&file);
  18.     QString context;
  19.     qint64 rowIndex = -1;
  20.     context = textStream.readLine();
  21.     rowIndex++;
  22.     LOG;
  23.     ...
  24.     file.close();
  25.     LOG;
  26.     osg::ref_ptr<osg::Group> pGroup = new osg::Group;
  27.     for(int index = 0; index < num; index++)
  28.     {
  29.         LOG << index;
  30.         // 绘图
  31.         {
  32.             for(int partIndex = 0; partIndex < kMode.listPart.size(); partIndex++)
  33.             {
  34.                 // 创建一个用户保存几何信息的对象
  35.                 osg::ref_ptr<osg::Geometry> pGeometry = new osg::Geometry;
  36.                 // 创建四个顶点的数组
  37.                 osg::ref_ptr<osg::Vec3Array> pVec3Array = new osg::Vec3Array;
  38.                 // 添加四个顶点
  39.                 pGeometry->setVertexArray(pVec3Array.get());
  40.                 // 创建四种颜色的数据
  41.                 osg::ref_ptr<osg::Vec4Array> pVec4Array = new osg::Vec4Array;
  42.                 // 添加四种颜色
  43.                 pGeometry->setColorArray(pVec4Array.get());
  44.                 // 绑定颜色
  45.                 pGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
  46.                 double r, g, b;
  47.                 r = qrand() % 100 * 1.0f / 100;
  48.                 g = qrand() % 100 * 1.0f / 100;
  49.                 b = qrand() % 100 * 1.0f / 100;
  50.                 for(int elementShellIndex = 0; elementShellIndex < kMode.listPart.at(partIndex).listElementShell.size(); elementShellIndex++)
  51.                 {
  52.                     //                               x     y     z
  53.                     pVec3Array->push_back(osg::Vec3(kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n1).x + index * x,
  54.                                                     kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n1).y + index * y,
  55.                                                     kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n1).z + index * z));
  56.                     pVec3Array->push_back(osg::Vec3(kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n2).x + index * x,
  57.                                                     kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n2).y + index * y,
  58.                                                     kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n2).z + index * z));
  59.                     pVec3Array->push_back(osg::Vec3(kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n3).x + index * x,
  60.                                                     kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n3).y + index * y,
  61.                                                     kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n3).z + index * z));
  62.                     pVec3Array->push_back(osg::Vec3(kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n4).x + index * x,
  63.                                                     kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n4).y + index * y,
  64.                                                     kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n4).z + index * z));
  65.                     //                               r    g    b    a(a设置无效,估计需要其他属性配合)
  66.                     pVec4Array->push_back(osg::Vec4(r, g, b, 1.0));
  67.                     pVec4Array->push_back(osg::Vec4(r, g, b, 1.0));
  68.                     pVec4Array->push_back(osg::Vec4(r, g, b, 1.0));
  69.                     pVec4Array->push_back(osg::Vec4(r, g, b, 1.0));
  70.                 }
  71.                 // 注意:此处若不绑定画笔,则表示使用之前绑定的画笔
  72.                 // 为唯一的法线创建一个数组    法线: normal
  73.                 osg::ref_ptr<osg::Vec3Array> pVec3ArrayNormal = new osg::Vec3Array;
  74.                 pGeometry->setNormalArray(pVec3ArrayNormal.get());
  75.                 pGeometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
  76.                 pVec3ArrayNormal->push_back(osg::Vec3(0.0, -1.0, 0.0));
  77.                 // 由保存的数据绘制四个顶点的多边形
  78.                 pGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, kMode.listPart.at(partIndex).listElementShell.size() * 4));
  79.         //            pGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
  80.                 // 向Geode类添加几何体(Drawable)
  81.                 osg::ref_ptr<osg::Geode> pGeode = new osg::Geode;
  82.                 pGeode->addDrawable(pGeometry.get());
  83. #if 0
  84.                 {
  85.                     _pStateSet = pGeometry->getOrCreateStateSet();
  86.     //                _pPolygonMode = new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
  87.                     _pPolygonMode = new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::FILL);
  88.                     _pStateSet->setAttribute(_pPolygonMode, osg::StateAttribute::ON);
  89.                 }
  90. #endif
  91.                 pGroup->addChild(pGeode.get());
  92.             }
  93.         }
  94.     }
  95.     // 始终是灰色,这里需要设置关闭光照:OFF,同时旋转都能看到了(光照关闭,法向量不起作用)
  96.     {
  97.         osg::StateSet *pStateSet = pGroup->getOrCreateStateSet();
  98.     //      pStateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON);
  99.         pStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
  100.     }
  101.     _pNode = pGroup.get();
  102.     if(_pNode.get() == 0)
  103.     {
  104.         return false;
  105.     }
  106.     _pRoot->addChild(_pNode);
  107.     return true;
  108. }
复制代码

工程模板v1.1.0

  


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王國慶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表