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

news/2024/9/19 19:59:42/文章来源:https://www.cnblogs.com/qq21497936/p/18419203

前言

  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;         // 单元idqint64 pid;         // 材料idqint64 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 0pVec3Array->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));
#endifpVec3Array->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));}// 注意:此处若不绑定画笔,则表示使用之前绑定的画笔// 为唯一的法线创建一个数组    法线: normalosg::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个点,但本次去掉颜色之后,发现是可以的。
  • 步骤四:将颜色给他赋值上,一个部件一个纯色,把对应绑定点都补上,发现没问题

原因

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

解决

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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

0918高数一千题,多元函数积分学

T17.第一型曲线积分空间形式 用斯托克斯公式化成第二型曲面积分 解第二型曲面积分,用高斯公式或者投影转换法,后者注意正负号,上正下负,前正后负 T18.换路径,但是x=1左半段不能化成lnx算 T19.求偏导就对对应字母求就行,不用对y导x T20.多元极值AC-B2>0A>0,极小 A<…

Dynamic Locomotion in the MIT Cheetah 3 Through Convex Model-Predictive Control

1. Swing Leg Control\(J_i \in R^{3*3}\) 是足端雅可比;\(\tau _{i,ff}\) 是前馈力矩 \(\Lambda \in R^{3*3}\)是操作空间惯性矩阵;\(a_{i,ref} \in R^{3*3}\)是机体坐标系下的参考加速度 q是关节角度;\(C_i \dot{q}_i + G_i\)是科里奥利力和重力 2. Ground Force Control …

多机训练时的环境变量

多机训练时的环境变量 通过设置环境变量配置分布式训练,仅仅是为了在交互式 Python 环境下,方便查看实验效果。如果不是学习、试验目的,而是生产需求,可以直接通过 oneflow.distributed.launch 启动分布式训练,该模块内部根据命令行参数,自动设置了必要的环境变量。 1)M…

[Java基础]Stream流

当我第一次阅读 Java8 中的 Stream API 时,说实话,我非常困惑,因为它的名字听起来与 Java I0 框架中的 InputStream 和 OutputStream 非常类似。但是实际上,它们完全是不同的东西。 Java8 Stream 使用的是函数式编程模式,如同它的名字一样,它可以被用来对集合进行链状流式…

学习高校课程-软件工程-软件工程(ch2)

DEFINING THE DISCIPLINE THE SOFTWARE PROCESS General Principles2.1 DEFINING THE DISCIPLINE definition for software engineering 软件工程的定义 (1) The application of a systematic, disciplined, quantifiable approach to the development, operation, and mainten…

反汇编分析赋值与自增自减

目录++(--)后置的++(--)真的是先使用,后自增吗?后置++和前置++的差别复杂表达式++i+++i+++i贪心法编译器的贪心规则不是保证一定正确的规则赋值的原理 ++(--)后置的++(--)真的是先使用,后自增吗?概念:前置++是先自增,后使用; 后置++是先使用,后自增. 下面从汇编角度看后置++的…

26. 多进程理论、操作

1. 多进程相关理论 1.1 什么是进程 进程是一个正在执行的任务或程序 负责执行任务的是CPU (1)单任务 单核CPU+多道技术  实现多个进程的伪并发 (2)多任务 多个任务并发执行 1.2 进程和程序的区别 程序是代码的集合体 进程是程序的执行过程 1.3 进程的调度算法 (1)先来…

网络基础--UPnP基本原理

网络基础--UPnP基本原理 1、简介 UPnP是通用即插即用(Universal Plug and Play)的缩写,主要用于设备的智能互联互通,使用UPnP协议不需要设备驱动程序,它可以运行在目前几乎所有的操作系统平台上,使得在办公室、家庭和其他公共场所方便地构建设备互联互通成为可能。UPNP为…

VastbaseG100集群部署实操

背景 近日的工作涉及到数据库的集群部署,为了熟悉过程,参考VastgbaseG100官方文档进行部署。 参考文档 https://docs.vastdata.com.cn/zh/docs/VastbaseG100Ver2.2.15/do... 实操 这里采用HAS+DCS+Vastbase的解决方案,详情可参考海量智库第8期|Vastbase G100核心技术介绍之…

网络基础--UPnP基本原理-CSDN博客

网络基础--UPnP基本原理-CSDN博客网络基础--UPnP基本原理-CSDN博客 https://blog.csdn.net/jisuanji111111/article/details/122108226 文章浏览阅读1.4w次,点赞3次,收藏22次。介绍UPNP基本知识点,比较全面。转载自华三文档。_upnp 2024-09-03 13:57:361、简介 UPnP是通用即…

敏捷项目管理工具:团队高效协作的关键

敏捷项目管理:团队高效协作的关键​ 在当今快节奏的市场环境中,企业必须具备快速响应变化的能力。无论是产品研发、软件开发还是市场推广,灵活应对变化和高效管理项目已成为企业成功的关键。于是,敏捷开发这一理念越来越多地被各行业团队采纳,成为了他们高效协作、及时交付…

首个标准+首家通过!大模型媒体处理评估,阿里云智能媒体服务“卓越级”通过

中国信通院近期正式发布《大模型驱动的媒体生产与处理》标准,阿里云智能媒体服务,以“首批首家”通过卓越级评估,并在9大模块50余项测评中表现为“满分”。中国信通院近期正式发布《大模型驱动的媒体生产与处理》标准,阿里云智能媒体服务,以“首批首家”通过卓越级评估,并…