注册
登录
Osg需要打开模型文件,但是遇到显示动力学仿真的K模型文件,.k文件是一种描述材料属性的文件,比如密度、弹性模量等,该模型文件不是常规中间开放格式,无法直接支持,需要自定义解析并且重建三维模型。
实际非常流程,因为视频转gif导致部分看起来不行:



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

344万多个四边形,丝滑

518万多个四边形,开始稍微有点卡顿了

691万多个四边形,开始更不利索了
此时翻倍就在加载场景崩溃,这个崩溃确认代码没问题,是运行内存较大了,加大运行时内存配置:
QMAKE_LFLAGS_WINDOWS += /LARGEADDRESSAWARE
运行成功,交互更卡一点。

更大又不行了:

分析的是本文件解析,可能包含数据格式关键字不全。

实际遇到的为:*TITLE,*PART,*ELEMENT_SHELL,*NODE, *END。
(PS:以后项目上遇到了再另起篇章补充。)
.k文件是一种描述材料属性的文件,比如密度、弹性模量等。
打开其的软件LS-DYNA和LSPREPOST

以上所知,分为六个关键字,分割为五个区域,归属关系如下:

PART关键字来定义部件及其相关特性

第一行为title属性,为标题,没有实际意义。

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


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


然后部件与node的对应关系,通过索引对应:

解析文件即可。
表示文件结束。


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