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

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

时间:2024-09-24 21:21:48浏览次数:9  
标签:int double void qint64 kMode v1.1 linux 测试工具 osg

需求

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

<br>

Demo V1.1.0

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

  请添加图片描述

  请添加图片描述

<br>

Demo v1.0.0

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

<br>

模块化部署

  在这里插入图片描述

<br>

关键源码

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;
}

<br>

工程模板v1.1.0

  在这里插入图片描述

标签:int,double,void,qint64,kMode,v1.1,linux,测试工具,osg
From: https://blog.51cto.com/hongpangzi/12101879

相关文章

  • 【Linux】超时重传机制
    超时重传机制超时重传机制是一种常见的网络协议设计策略,用于确保数据包在不可靠网络中的可靠传输。它特别适用于UDP等不提供内建可靠性保障的协议。以下是超时重传机制的基本概念和实现方法。1.基本概念在数据传输过程中,发送方在发送数据包后启动一个定时器。如果在预设......
  • 【Linux】快速上手shell脚本(适合初学者)
    Shell脚本快速上手什么是Shell脚本?Shell脚本是一种通过命令行界面执行的一系列命令的文本文件,主要用于自动化任务。创建Shell脚本使用文本编辑器(如nano或vim)创建一个以.sh结尾的文件:nanomyscript.sh脚本头部在脚本的第一行指定解释器:#!/bin/bash基本命令ec......
  • linux操作系统和文件系统,命令(上)
    Linux是一个类似于windows的操作系统Linux操作系统的一种主要使用方式是通过终端软件;终端软件里只能使用键盘不能使用鼠标,在终端软件里通过输入命令完成各种任务clear命令可以删除终端窗口里的所有文字信息操作系统里用来管理文件的部分叫文件系统所有文件系统都采用分组方式......
  • 【入门岛·第1关】linux 基础知识
    目录闯关任务完成SSH连接与端口映射并运行hello_world.py闯关任务完成SSH连接与端口映射并运行hello_world.py1在远程主机上建立hello_python.py程序并运行,查看程序运行的端口:importsocketimportreimportgradioasgr#获取主机名defget_hostname():hostname......
  • 【Linux】深度解析与实战应用:GCC/G++编译器入门指南
    ......
  • Linux内核文件系统-虚拟文件系统-索引节点对象
    建议点击这里查看个人主页上的最新原文作者:陈孝松主页:chenxiaosong.com公网主页:replace_with_public_ip_or_delete_this_line哔哩哔哩:陈孝松课程:chenxiaosong.com/courses博客:chenxiaosong.com/blog贡献:chenxiaosong.com/contributions邮箱:chenxiaosong@ch......
  • 【Linux】指令和权限的这些细节,你确定都清楚吗?
    ......
  • ELK-03-skywalking监控linux系统
    文章目录前言一、下载node_exporter二、启动node_exporter三、下载OpenTelemetryCollector四、启动OpenTelemetryCollector4.1将配置文件下载到同级目录4.2启动五、查看总结前言skywalking安装完成后,开始我们的第一个监控-监控linux系统。参考官方文档:https:......
  • Linux便捷查询使用手册 第二章:安装与设置
    目录2.1安装准备2.1.1系统需求2.1.2硬件兼容性检查2.1.3下载安装镜像2.1.4制作启动介质2.2安装过程2.2.1进入安装程序2.2.2选择安装类型2.2.3分区设置2.2.4软件选择2.2.5设置用户和密码2.2.6完成安装2.3网络配置2.3.1网络连接设置2.3.2IP地址配......
  • [Linux]从零开始的Minecraft服务器搭建教程
    一、前言    学习Linux有一段时间了,当然,我们要把学习的知识运用到实际生活中去。最近朋友们都在玩我的世界,网易版的我的世界联机非常不稳定,用起来也算是非常难受了。所以还是准备转战JAVA版。为了联机,可以考虑一个人开一个房间,对外开放端口,不过这样太麻烦了。而且如果......