需求

  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

#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; // 单元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四边形壳单元定义中是没有意义的。
};
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 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());
#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);
}
#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)
{
return false;
}
_pRoot->addChild(_pNode); return true;
}
 

工程模板v1.1.0

  

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

  1. 麒麟系统开发笔记(二):国产麒麟系统搭建Qt开发环境安装Qt5.12

    前言   开发国产应用,使用到银河麒麟V4,V10,本篇以V10记录,参照上一篇可安装V4.V7.V10三个版本,麒麟V4系自带了Qt,麒麟V10没有自带Qt,需要自己编译搭建环境.   银河麒麟V1 ...

  2. xBIM 实战01 在浏览器中加载IFC模型文件

    系列目录    [已更新最新开发文章,点击查看详细]  一.创建Web项目 打开VS,新建Web项目,选择 .NET Framework 4.5  选择一个空的项目 新建完成后,项目结构如下: 二.添 ...

  3. 项目上有红色感叹号, 一般就是依赖包有问题, remove依赖,重新加载,maven的也行可认删除,自己也会得新加载

    项目上的红色叹号, 要下面提示: "Problems"  里的errors  , 看是什么错误,  一般是由于网络等原因,  依赖没有下载完整,  只有文件名字对了,  内容不全, ...

  4. 项目实战:Qt文件改名工具 v1.2.0(支持递归检索,搜索:模糊匹配,前缀匹配,后缀匹配;重命名:模糊替换,前缀追加,后缀追加)

    需求   在整理文件和一些其他头文件的时候,需要对其名称进行整理和修改,此工具很早就应该写了,创业后,非常忙,今天抽空写了一个顺便提供给学习.   工具和源码下载地址   本篇文章的应用包和源码包可在 ...

  5. 记录:拷贝gitblit里的项目使用git命令clone、pull、push等,出现一直在加载,卡住没反应的问题

    俺想克隆别人gitblit里的其中一个版本库(俺在别人gitblit有权限) 懂得git的道友们,都应该知道克隆一个公共项目,随便找到,打开git终端,输入git clone 项目地址就行了 到了俺这 ...

  6. xBIM 实战02 在浏览器中加载IFC模型文件并设置特效

    系列目录    [已更新最新开发文章,点击查看详细]  在模型浏览器中加载模型后,可以对模型做一些特殊操作.下图是常用的设置. 都是通过 xbim-viewer.js 中的 API 来设置以达到一定的 ...

  7. 12 Flutter仿京东商城项目 商品列表页面请求数据、封装Loading Widget、上拉分页加载更多

    ProductList.dart import 'package:flutter/material.dart'; import '../services/ScreenAdaper.dart'; imp ...

  8. webpack+vue项目实战(四,前端与后端的数据交互和前端展示数据)

    地址:https://segmentfault.com/a/1190000010063757 1.前言 今天要做的,就是在上一篇文章的基础上,进行功能页面的开发.简单点说呢,就是与后端的数据交互和怎么 ...

  9. Qt中加载Libevent静态库(通过reimp和rs两条语句将lib转为a)

    文章来源:http://blog.sina.com.cn/s/blog_731bf4c90102wnpr.html 本文仅是个人经验总结,若有错误欢迎指教! 最近要做一个跨平台的项目,同时也涉及到网络 ...

  10. Asp.Net Core 2.0 项目实战(10) 基于cookie登录授权认证并实现前台会员、后台管理员同时登录

    1.登录的实现 登录功能实现起来有哪些常用的方式,大家首先想到的肯定是cookie或session或cookie+session,当然还有其他模式,今天主要探讨一下在Asp.net core 2.0下 ...

随机推荐

  1. 题解:P10677 『STA - R6』inkar-usi

    背景 把人家鸽了,感觉废了. 分析 这道题刚看到题目的时候很多人会想爆搜,但是因为 \(10^3\) 的数据范围,所以应该去想一想是不是有什么性质. 我们稍微想一想就会发现,题目上提到了可以重复走,那 ...

  2. 2023 NOIP 游记

    \(\text{Day -INF}\) 提高 \(135\) 卡线进 \(\text{NOIP}\). 集训两天成绩:\(50 \to 135\). \(\text{Day 1}\) 开赛 \(13\ ...

  3. MySQL 实现 EF Code First TimeStamp/RowVersion 并发控制

    在将项目迁移到MySQL 5.6.10数据库上时,遇到和迁移到PostgreSQL数据库相同的一个问题,就是TimeStamp/RowVersion并发控制类型在非Microsoft SQL Serv ...

  4. Less预处理器的使用

    练习页面: <body> <div class="div1"> <div class="div2"></div> ...

  5. 题解:P10733 [NOISG2019 Prelim] Lost Array

    题解:P10733 [NOISG2019 Prelim] Lost Array 思路 对于任意 \(\min(X_{A_{i}},X_{B_{i}})=C_{i}\). 只要让 \(X_{A_{i}} ...

  6. docker 概念,安装,启动,运行

    docker概念,安装,启动,运行模式 docker的概念 镜像(image) 模板,可以通过模板来创建容器服务,tomcat镜像===>run==>tomacat01容器(提供服务),通 ...

  7. 【Maxwell】01 安装及入门

    官网地址: https://maxwells-daemon.io/ 下载地址(版本发行): https://github.com/zendesk/maxwell/releases 参考教程自尚硅谷视频 ...

  8. 【Java-GUI】10 Swing04

    面板容器: package cn.dzz.swing; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax ...

  9. python3解析wav文件获取dtmf值

    操作系统 :Windows 10_x64 Python版本:3.9.2 从事FreeSwitch相关工作,大概率会遇得到DTMF,DTMF的传递方式有三种: In-band RFC2833 SIP-I ...

  10. 家务机器人(人形机器人)—— Mobile ALOHA: Your Housekeeping Robot

    项目地址: https://mobile-aloha.github.io/ 演示视频地址: https://www.youtube.com/watch?v=HaaZ8ss-HP4 论文地址: http ...