首页/文章列表/文章详情

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

编程知识2422024-09-24评论

需求

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

 

Demo V1.1.0

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

  请添加图片描述

  请添加图片描述

 

Demo v1.0.0

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

 

模块化部署

  在这里插入图片描述

 

关键源码

OsgWidget.h

#ifndefOSGWIDGET_H#defineOSGWIDGET_H#include<QWidget>#include"OsgViewerWidget.h"#include"MyManipulator.h"#include"osg/PolygonMode"classAnimationPathCameraMainpulator;namespace Ui {classOsgWidget;}classOsgWidget:publicQWidget{ Q_OBJECTpublic:// 模型结构体 structElement_Shell// *ELEMENT_SHELL {Element_Shell(){} qint64 eid;// 单元id qint64 pid;// 材料id qint64 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四边形壳单元定义中是没有意义的。 };structPart// *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表示不采用 };structNode{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方向转动约束 };structK_Mode{K_Mode(){} QList<Part> listPart; QList<Node> listNode; QHash<int, Node> hashNid2Node;};// 添加模型 K_Mode kMode;public:explicitOsgWidget(QWidget*parent=0);~OsgWidget();public:boolgetFixXAxis()const;// 获取X轴固定状态 boolgetFixYAxis()const;// 获取Y轴固定状态 boolgetFixZAxis()const;// 获取Z轴固定状态 voidgetCenter(double&x,double&y,double&z);// 获取引擎中心点坐标 voidgetPersonPoint(double&x,double&y,double&z);// 获取初始化人眼的角度(看向引擎中心点)public:voidsetFixXAxis(bool fixXAxis);// 设置固定X轴 voidsetFixYAxis(bool fixYAxis);// 设置固定Y轴 voidsetFixZAxis(bool fixZAxis);// 设置固定Z轴 voidsetCenter(double x,double y,double z);// 设置引擎中心点坐标 voidsetPersonPoint(double x,double y,double z);voidsetEnablePolygonMode(bool enable);voidstartAnimation();voidpauseAnimation();voidstopAnimation();public:boolloadKFile(QString filePath);boolloadK2File(QString filePath,int num,int x,int y,int z);voidclear();voidresetCoordinate();protected:voidinitOsg();// osg初始化 voidloadNode(osg::ref_ptr<osg::Node> pNode);// 加载场景根节点protected: osg::ref_ptr<osg::Node>createScene();// 创建总场景 osg::ref_ptr<osg::Node>createAnimation();// 创建动画protected:voidresizeEvent(QResizeEvent*event);voidkeyPressEvent(QKeyEvent* event);voidkeyReleaseEvent(QKeyEvent* event);voidmousePressEvent(QMouseEvent* event);voidmouseReleaseEvent(QMouseEvent* event);voidmouseDoubleClickEvent(QMouseEvent* event);voidmouseMoveEvent(QMouseEvent* event);voidwheelEvent(QWheelEvent* event);voidtimerEvent(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

boolOsgWidget::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));returnfalse;} 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));returnfalse;} 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 z pVec3Array->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));}// 注意:此处若不绑定画笔,则表示使用之前绑定的画笔 // 为唯一的法线创建一个数组 法线: normal osg::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());#if0{ _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);}#endif pGroup->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){returnfalse;} _pRoot->addChild(_pNode);returntrue;}
 

工程模板v1.1.0

  在这里插入图片描述

博客园

这个人很懒...

用户评论 (0)

发表评论

captcha