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

news2024/11/15 19:59:08

若该文为原创文章,转载请注明出处
本文章博客地址: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;         // 单元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

  在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2159309.html

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

相关文章

验收测试:从需求到交付的全程把控!

在软件开发过程中&#xff0c;验收测试是一个至关重要的环节。它不仅是对软件质量的把关&#xff0c;也是对整个项目周期的全程把控。从需求分析到最终的软件交付&#xff0c;验收测试都需要严格进行&#xff0c;以确保软件能够符合预期的质量和性能要求。 一、需求分析阶段 在…

[uni-app]小兔鲜-01项目起步

项目介绍 效果演示 技术架构 创建项目 HBuilderX创建 下载HBuilderX编辑器 HBuilderX/创建项目: 选择模板/选择Vue版本/创建 安装插件: 工具/插件安装/uni-app(Vue3)编译器 vue代码不能直接运行在小程序环境, 编译插件帮助我们进行代码转换 绑定微信开发者工具: 指定微信开…

Linux 基本指令(二)

目录 1. more指令 2. less指令(重要) 3. head指令 4. tail指令 5. date指令 (1)可以通过选项来指定格式&#xff1a; ​编辑 (2)在设定时间方面 (3)时间戳 6. cal指令 7. find指令 8. grep指令 9. alias指令 10. zip指令与unzip指令 (1). zip指令 (2). unzip指令…

链表分割-----------lg

现有一链表的头指针 ListNode* pHead&#xff0c;给一定值x&#xff0c;编写一段代码将所有小于x的结点排在其余结点之前&#xff0c;且不能改变原来的数据顺序&#xff0c;返回重新排列后的链表的头指针。 我们可以假设x为36&#xff0c;则小于36都排在前边&#xff0c;>3…

桌面便签哪个好用?好用的便签软件推荐?

随着信息技术的发展&#xff0c;我们的生活方式也发生了翻天覆地的变化。从纸质笔记本到电子便签&#xff0c;这不仅仅是载体的转换&#xff0c;更是思维习惯的一次革新。在这个数字时代&#xff0c;如何利用科技工具来辅助我们更好地管理时间和信息&#xff0c;成为了值得探讨…

linux环境oracle11.2.0.4打补丁(p31537677_112040_Linux-x86-64.zip)

上传补丁及opatch工具 创建目录并上传opatch工具和补丁包 [oraclerhel64 ~]$ mkdir /u01/psu [oraclerhel64 ~]$ cd /u01/psu [oraclerhel64 psu]$ ll total 514572 -rw-r--r-- 1 oracle oinstall 391781147 Sep 23 17:37 p31537677_112040_Linux-x86-64.zip -rw-r--r-- 1 or…

中电金信 :基于开放架构的私有云建设实践

01开放架构私有云诞生背景 随着国产化创新建设的深化&#xff0c;产业侧行业软件持续进行云原生改造&#xff0c;金融机构拥抱云和容器技术&#xff0c;实现数智化转型已是大势所趋。近年&#xff0c;云原生技术以及架构发展速度更是惊人&#xff0c;私有云开始有了新架构、有了…

idea使用spring initializr快速创建springboot项目

idea使用spring initializr快速创建springboot项目 1.打开idea&#xff0c;新建项目如图&#xff0c;选择好java版本&#xff0c;我这里是17。2.点击next&#xff0c;首先选择springboot版本&#xff0c;我这里选择3.3.4。勾选springweb&#xff0c;它会帮我们下载关于springmv…

【高效且应用广泛的排序 —— 快速排序算法】

高效且应用广泛的排序 —— 快速排序算法 快速排序是一种常用的排序算法&#xff0c;主要采用分治的思想。以下是对快速排序算法的详细介绍及代码示例&#xff1a; 快速排序的基本思路是&#xff0c;每次将一个位置上的数据归位&#xff0c;使得该数左边的所有数据都比该数小…

小程序开发设计-小程序的宿主环境:组件⑦

上一篇文章导航&#xff1a; 小程序开发设计-小程序的宿主环境&#xff1a;宿主环境简介⑥-CSDN博客https://blog.csdn.net/qq_60872637/article/details/142425131?spm1001.2014.3001.5501 注&#xff1a;不同版本选项有所不同&#xff0c;并无大碍。 目录 上一篇文章导航…

阿里巴巴首页pc端1688店铺招牌店铺装修教程

1688运营1688批发首页1688装修模板1688店铺怎么装修模板自定义装修代码1688店铺装修模板旺铺装修阿里店铺首页怎么装修1688店铺装修教程视频全屏通栏代码1688店铺装修模板阿里巴巴店铺装修设计 阿里巴巴首页pc端1688店铺招牌店铺装修教程 工具&#xff1a;一秒美工

英特尔:昔日芯片霸主的命运抉择

英特尔&#xff1a;昔日芯片霸主的命运抉择 简介 英特尔的辉煌与困境 高通的崛起与收购意向 英特尔困境的原因 英特尔的未来走向 简介 据美国《华尔街日报》9月20日报道&#xff0c;芯片巨头高通公司近日就收购事宜与英特尔公司进行了接洽。但目前这只是一个意向&#xff…

centos7 docker部署nacos

1. 一行代码安装git yum -y install git 2. 下载最新版nacos源码&#xff1a; git clone https://github.com/nacos-group/nacos-docker.git 进入nacos-docker文件 cd nacos-docker 3.docker安装数据库Mysql8 按这个来就行&#xff0c;非常好 Docker安装mysql8-超详细、每…

828华为云征文|华为云Flexus云服务器X实例 基于CentOS系统镜像快速部署Laravel开源论坛

最近公司可热闹了&#xff01;大家都在为搭建博客论坛系统忙得不可开交&#xff0c;尤其是在选服务器这件事儿上&#xff0c;那叫一个纠结。 同事 A 说&#xff1a;“咱得选个厉害的服务器&#xff0c;不然这论坛以后卡得跟蜗牛爬似的可咋办&#xff1f;” 同事 B 回应道&#…

思维商业篇(5)—发展趋势分析

思维商业篇(5)—发展趋势分析 核心理论 巴菲特曾在《滚雪球》一书中提到他的投资之道其实非常简单&#xff0c;可以总结为两句话&#xff1a;找到足够长的雪道&#xff0c;找到足够湿的雪球。 而发展趋势的分析&#xff0c;正好可以借助巴菲特的这个滚雪球理论。 足够长的雪…

OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【用户态内存调测】

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 基本概念 Debug版本的musl-libc库为用户提供内存泄漏检测、堆内存…

Unity 设计模式 之 行为型模式 -【状态模式】【观察者模式】【备忘录模式】

Unity 设计模式 之 行为型模式 -【状态模式】【观察者模式】【备忘录模式】 目录 Unity 设计模式 之 行为型模式 -【状态模式】【观察者模式】【备忘录模式】 一、简单介绍 二、状态模式&#xff08;State Pattern&#xff09; 1、什么时候使用状态模式 2、使用状态模式的…

Android RecyclerView 实现 GridView ,并实现点击效果及方向位置的显示

效果图 一、引入 implementation com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30 二、使用步骤 1.Adapter public class UnAdapter extends BaseQuickAdapter<UnBean.ResultBean, BaseViewHolder> {private int selectedPosition RecyclerView.NO_POSITIO…

苹果电脑系统重磅更新——macOS Sequoia 15 系统 新功能一 览

有了 macoS Sequoia&#xff0c;你的工作效率将再次提升&#xff1a;快速调整桌面布局&#xff0c;一目了然地浏览网页重点&#xff0c;还可以通过无线镜像功能操控你的iPhone。 下面就来看看几项出色新功能&#xff0c;还有能够全面发挥这些功能的 App 和游戏。 macOS Sequo…

探秘 Web Bluetooth API:连接蓝牙设备的新利器

引言 随着物联网技术的快速发展&#xff0c;蓝牙设备在日常生活中扮演着越来越重要的角色。而在 Web 开发领域&#xff0c;Web Bluetooth API 的出现为我们提供了一种全新的方式来连接和控制蓝牙设备。本文将深入探讨 Web Bluetooth API 的使用方法和原理&#xff0c;帮助开发…