OSG开发笔记(三十):OSG加载动力学仿真K模型文件以及测试Demo


若该文为原创文章,未经允许不得转载
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/142340138
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究

长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…

OSG开发专栏(点击传送门)

上一篇:《OSG开发笔记(二十九):OSG加载模型文件、加载3DMax三维型文件Demo》
下一篇: 持续补充中…


前言

  Osg需要打开模型文件,但是遇到显示动力学仿真的K模型文件,.k文件是一种描述材料属性的文件,比如密度、弹性模量等,该模型文件不是常规中间开放格式,无法直接支持,需要自定义解析并且重建三维模型。


Demo

  实际非常流程,因为视频转gif导致部分看起来不行:
  请添加图片描述

  请添加图片描述

  请添加图片描述


交互流畅性测试

  实际研发需要用不同的策略进行在不影响视觉观感的前提下,进行模型展示优化处理,本次测试直接copy多份模型加载:

  • 172万多个四边形,丝滑
      在这里插入图片描述

  • 344万多个四边形,丝滑
      在这里插入图片描述

  • 518万多个四边形,开始稍微有点卡顿了
      在这里插入图片描述

  • 691万多个四边形,开始更不利索了
      此时翻倍就在加载场景崩溃,这个崩溃确认代码没问题,是运行内存较大了,加大运行时内存配置:

QMAKE_LFLAGS_WINDOWS += /LARGEADDRESSAWARE

  运行成功,交互更卡一点。
  在这里插入图片描述

  更大又不行了:
  在这里插入图片描述


注意

  分析的是本文件解析,可能包含数据格式关键字不全。
  在这里插入图片描述

  实际遇到的为:*TITLE,*PART,*ELEMENT_SHELL,*NODE, *END。
  (PS:以后项目上遇到了再另起篇章补充。)


K文件

概览

  .k文件是一种描述材料属性的文件,比如密度、弹性模量等。
  打开其的软件LS-DYNA和LSPREPOST

  • LS-DYNA
      LS-DYNA程序(最新版本17.2版)是功能齐全的几何非线性(大位移、大转动和大应变)、材料非线性(140多种材料动态模型)和接触非线性(50多种)程序。它以Lagrange算法为主,兼有ALE和Euler算法;以显式求解为主,兼有隐式求解功能;以结构分析为主,兼有热分析、流体-结构耦合功能;以非线性动力分析为主,兼有静力分析功能(如动力分析前的预应力计算和薄板冲压成型后的回弹计算);军用和民用相结合的通用结构分析非线性有限元程序,是显式动力学程序的鼻祖和先驱。
  • LSPREPOST
      lsprepost是一套专为LS-DYNA开发的高级有限元前后处理软件,上线时间是1976年1月1日。
      文件内容概览
      文件整体概览如下:
      在这里插入图片描述

  以上所知,分为六个关键字,分割为五个区域,归属关系如下:
  在这里插入图片描述

关键字:*KEYWORK

关键字:*TITLE

关键字:*PART

  PART关键字来定义部件及其相关特性
  在这里插入图片描述

  第一行为title属性,为标题,没有实际意义。
  在这里插入图片描述

关键字:*ELEMENT_SHELL

  SECTION系列关键字指定所采用的单元算法、积分分规则及各种几何参数(壳单元的厚度、梁单元的截面信息参数等),对不同的单元类型,或者需要相应的SECTION关键字段来定义单元的算法和参数。
  *SECTION_SEHLL定义单壳体单元的特性。这些属性对于模拟如汽车碰撞、航空航天结构、以及任何涉及薄壳结构动态响应的模拟都至关重要。然而,具体到ELEMENT_SHELL属性在K文件中的详细内容和格式,可能因LS-DYNA的版本和具体应用而有所不同。
  在这里插入图片描述

  在这里插入图片描述

关键字:*NODE

  *NODE关键字来定义结构模型的每一节点及其在总体直角坐标系中的坐标及受约束情况,该关键字段包含如下的变量信息:
  在这里插入图片描述
  在这里插入图片描述

  然后部件与node的对应关系,通过索引对应:
  在这里插入图片描述

  解析文件即可。

关键字:*END

  表示文件结束。


测试加载K文件

  在这里插入图片描述

  在这里插入图片描述


Demo关键源码

模型结构体

// 模型结构体
    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;
    };

绘制部分

osg::ref_ptr<osg::Group> pGroup = new osg::Group;
// 绘图
{
    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
#if 0
            pVec3Array->push_back(osg::Vec3( 1.0, 0.0, 0.0));
            pVec3Array->push_back(osg::Vec3( 3.0, 0.0, 0.0));
            pVec3Array->push_back(osg::Vec3( 3.0, 0.0, 1.0));
            pVec3Array->push_back(osg::Vec3( 1.0, 0.0, 1.0));
#endif
            pVec3Array->push_back(osg::Vec3(kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n1).x,
                                            kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n1).y,
                                            kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n1).z));
            pVec3Array->push_back(osg::Vec3(kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n2).x,
                                            kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n2).y,
                                            kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n2).z));
            pVec3Array->push_back(osg::Vec3(kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n3).x,
                                            kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n3).y,
                                            kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n3).z));
            pVec3Array->push_back(osg::Vec3(kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n4).x,
                                            kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n4).y,
                                            kMode.hashNid2Node.value(kMode.listPart.at(partIndex).listElementShell.at(elementShellIndex).n4).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());

        {
            osg::ref_ptr<osg::StateSet> pStateSet = pGeometry->getOrCreateStateSet();
            osg::ref_ptr<osg::PolygonMode> pPolygonMode = new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
            pStateSet->setAttribute(pPolygonMode);
        }

        pGroup->addChild(pGeode);
    }
}

工程模板:对应版本号v1.32.0

  在这里插入图片描述


入坑

入坑一:绑定颜色不出来

问题

  去掉纹理后颜色不出来,显示一直灰色。

原理

  开启光照,就颜色不出来,需要关闭

解决

// 始终是灰色,这里需要设置关闭光照:OFF
osg::StateSet *pStateSet = pGroup->getOrCreateStateSet();
pStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
//pStateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON);

  在这里插入图片描述

  在这里插入图片描述

  
在这里插入图片描述

入坑二:运行起来就崩溃

问题

  数据都加载绘制时,运行就崩溃

解决过程

  • 步骤一:先减少面数量,发现小于一档数量可以没问题,初步怀疑绘制太多,但是osg本身做深度测试相关很不错,除非时内存爆了,所以应然需要继续。
  • 步骤二:使用绘制四边形的,绘制10000个也会崩,加重了内存怀疑。
  • 步骤三:由于之前对于顶点颜色没有进行全部点绑定,其他的看纹理的方式都是重复的,所以这块就直接只设置了4个点,但本次去掉颜色之后,发现是可以的。
  • 步骤四:将颜色给他赋值上,一个部件一个纯色,把对应绑定点都补上,发现没问题

原因

  就是因为绑定颜色角点,只绑定了四个,按道理来说就算其越界也只是读取的乱值,颜色是乱的,但是点多了就不行了,所以这里还是需要一一对应,不偷懒。

解决

  颜色单独,每一个部件一个颜色,然后循环内一一对应:
  在这里插入图片描述


上一篇:《OSG开发笔记(二十九):OSG加载模型文件、加载3DMax三维型文件Demo》
下一篇: 持续补充中…


本文章博客地址:https://blog.csdn.net/qq21497936/article/details/142340138

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【STL】 set 与 multiset:基础、操作与应用

在 C 标准库中&#xff0c;set 和 multiset 是两个非常常见的关联容器&#xff0c;主要用于存储和管理具有一定规则的数据集合。本文将详细讲解如何使用这两个容器&#xff0c;并结合实例代码&#xff0c;分析其操作和特性。 0.基础操作概览 0.1.构造&#xff1a; set<T&…

解决nginx代理SSE接口的响应没有流式返回

目录 现象原来的nginx配置解决 现象 前后端分离的项目&#xff0c;前端访问被nginx反向代理的后端SSE接口&#xff0c;预期是流式返回&#xff0c;但经常是很久不响应&#xff0c;一响应全部结果一下子都返回了。查看后端项目的日志&#xff0c;响应其实是流式产生的。推测是n…

【BurpSuite】Cross-site scripting (XSS 学徒部分:1-9)

&#x1f3d8;️个人主页&#xff1a; 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 【BurpSuite】Cross-site scripting (XSS 学徒部分:1-9&#xff09; 实验一 Lab: Reflected XSS into HTML context with nothing…

[Redis] 渐进式遍历+使用jedis操作Redis+使用Spring操作Redis

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

javase复习day30综合练习

制造假数据 制造数据 练习一 package Demo1;import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; im…

react hooks--React.memo

基本语法 React.memo 高阶组件的使用场景说明&#xff1a; React 组件更新机制&#xff1a;只要父组件状态更新&#xff0c;子组件就会无条件的一起更新。 子组件 props 变化时更新过程&#xff1a;组件代码执行 -> JSX Diff&#xff08;配合虚拟 DOM&#xff09;-> 渲…

数据结构:二叉树OJ题(基础版)

前言 更完两期二叉树的知识之后&#xff0c;来做几道oj题巩固一下基础 一、翻转二叉树 链接&#xff1a;leetcode链接 还是分治思想&#xff0c;将问题分解成左子树和右子树交换&#xff0c;遇到空树停止 采用递归算法做题 TreeNode* invertTree(TreeNode* root) {if(root …

Golang | Leetcode Golang题解之第409题最长回文串

题目&#xff1a; 题解&#xff1a; func longestPalindrome(s string) int {mp : map[byte]int{}for i : 0; i < len(s); i {mp[s[i]]}res : 0for _, v : range mp {if v&1 1 {res v - 1} else {res v}}if res<len(s) {res}return res }

华为HarmonyOS地图服务 3 - 如何开启和展示“我的位置”?

一. 场景介绍 本章节将向您介绍如何开启和展示“我的位置”功能&#xff0c;“我的位置”指的是进入地图后点击“我的位置”显示当前位置点的功能。效果如下&#xff1a; 二. 接口说明 “我的位置”功能主要由MapComponentController的方法实现&#xff0c;更多接口及使用方法…

基于51单片机的手环设计仿真

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于STC89C52单片机&#xff0c;DHT11温湿度采集温湿度&#xff0c;滑动变阻器连接ADC0832数模转换器模拟水位传感器检测水位&#xff0c;通过LCD1602显示信息&#xff0c;然后在程序里设置好是否…

JavaEE: 创造无限连接——网络编程中的套接字

文章目录 Socket套接字TCP和UDP的区别有连接/无连接可靠传输/不可靠传输面向字节流/面向数据报全双工/半双工 UDP/TCP api的使用UDPDatagramSocketDatagramPacketInetSocketAddress练习 TCPServerSocketSocket练习 Socket套接字 Socket是计算机网络中的一种通信机制&#xff0…

代码随想录算法训练营第五十八天 | 拓扑排序精讲-软件构建

目录 软件构建 思路 拓扑排序的背景 拓扑排序的思路 模拟过程 判断有环 写代码 方法一&#xff1a; 拓扑排序 软件构建 题目链接&#xff1a;卡码网&#xff1a;117. 软件构建 文章讲解&#xff1a;代码随想录 某个大型软件项目的构建系统拥有 N 个文件&#xff0c;文…

机器人的动力学——牛顿欧拉,拉格朗日,凯恩

机器人的动力学推导方法有很多&#xff0c;常用得有牛顿&#xff0c;拉格朗日&#xff0c;凯恩等方法&#xff0c;接下来&#xff0c;简单说说他们之间的使用。注&#xff1a;这里不考虑怎么来的&#xff0c;只说怎么应用。 参考1&#xff1a;4-14动力学分析方法-牛顿—欧拉方…

聚焦API安全未来,F5打造无缝集成的解决方案

研究发现&#xff0c;目前超过90%的基于Web的网络攻击都以API端点为目标。随着对API使用需求的增加&#xff0c;这些攻击还会持续增长。现代企业需要一种动态防御策略&#xff0c;在风险升级成代价高昂、令人警惕且往往无法预防的API安全漏洞之前&#xff0c;发现并降低风险。 …

数据库提权【笔记总结】

文章目录 UDF提权以有webshell只有数据库权限条件复现msf工具sql语句提权 MOF提权前言条件复现msf工具php脚本提权 sqlserver提权前言条件xp_cmdshell提权复现 沙盒提权介绍复现 Oracle提权靶场搭建执行任意命令复现 通过注入存储过程提权&#xff08;低权限提升至DBA&#xff…

C++从入门到起飞之——多态 全方位剖析!

&#x1f308;个人主页&#xff1a;秋风起&#xff0c;再归来~&#x1f525;系列专栏&#xff1a;C从入门到起飞 &#x1f516;克心守己&#xff0c;律己则安 目录 1. 多态的概念 2. 多态的定义及实现 2.1 多态的构成条件 2.1.1 实现多态还有两个必须重要条件&…

群晖NAS使用Docker本地部署网页版Ubuntu系统并实现无公网IP远程访问

文章目录 前言1. 下载Docker-Webtop镜像2. 运行Docker-Webtop镜像3. 本地访问网页版Linux系统4. 群晖NAS安装Cpolar工具5. 配置异地访问Linux系统6. 异地远程访问Linux系统7. 固定异地访问的公网地址 前言 本文旨在详细介绍如何在群晖NAS部署docker-webtop&#xff0c;并结合c…

通用接口开放平台设计与实现——(31)API服务线程安全问题确认与修复

背景 在本系列的前面一篇博客评论中&#xff0c;有小伙伴指出&#xff0c;API服务存在线程安全问题&#xff1a; https://blog.csdn.net/seawaving/article/details/122905199#comments_34477405 今天来确认下&#xff0c;线程是否安全&#xff1f;如不安全&#xff0c;如何…

高配小主机加装SSD固态硬盘,我选择性能与设计兼备的希捷酷鱼 530

高配小主机加装SSD固态硬盘&#xff0c;我选择性能与设计兼备的希捷酷鱼 530 哈喽小伙伴们好&#xff0c;我是Stark-C~ 我最近入手了零刻的一款新发布的 GTi12 Ultra高性能迷你主机&#xff0c;其出色的配置与强大的功能让我有了将它用作主力机的打算。不过因为它的高配版本搭…

【记录一下VMware上开虚拟端口映射到公网】

材料 win11 和装在vmware上的ubuntu 步骤一在Ubuntu上配置静态地址&#xff0c;配置如下 vim /etc/netplan/01-network-manager-all.yaml(此文件看系统上对应的是哪个文件&#xff0c;建议先备份)network:version: 2renderer: NetworkManagerethernets:ens33:dhcp4: falseadd…