前言

  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加载动力学仿真K模型文件以及测试Demo的更多相关文章

  1. Android开发笔记——以Volley图片加载、缓存、请求及展示为例理解Volley架构设计

    Volley是由Google开源的.用于Android平台上的网络通信库.Volley通过优化Android的网络请求流程,形成了以Request-RequestQueue-Response为主线的网 ...

  2. SpringBoot入门笔记(三)、热加载

    1.配置热加载环境,在pom.xml添加如下代码 <build> <!--springloader plugin --> <plugins> <plugin& ...

  3. Away3D 学习笔记(一): 加载3DS格式的模型文件

    加载外部的3DS文件分为两种: 1: 模型与贴图独立于程序的,也就是从外部的文件夹中读取 private function load3DSFile():Loader3D { loader = new ...

  4. Java开发学习(三十二)----Maven多环境配置切换与跳过测试的三种方式

    一.多环境开发 我们平常都是在自己的开发环境进行开发, 当开发完成后,需要把开发的功能部署到测试环境供测试人员进行测试使用, 等测试人员测试通过后,我们会将项目部署到生成环境上线使用. 这个时候就有一 ...

  5. AngularJS进阶(三十)AngularJS项目开发技巧之图片预加载

    AngularJS项目开发技巧之图片预加载 绪 项目(移动端采用Ionic 框架)开发完毕,测试阶段发现移动APP首页的广告图片(图片由服务器端返回相应url地址)很难加载,主要原因还是网速.如下图左 ...

  6. World Wind Java开发之十二——加载粗制三维模型(ExtrudedPolygon)(转)

    ww可以根据DLG图批量生成假三维模型,这对于小区等特征相似的建筑物模型的构建是非常有用的.下面来看如何一步步实现假三维模型的加载: 1.Shp文件的制作 首先在arcmap下数字化几个建筑物,并新建 ...

  7. Android UI开发第三十九篇——Tab界面实现汇总及比较

    Tab布局是iOS的经典布局,Android应用中也有大量应用,前面也写过Android中TAb的实现,<Android UI开发第十八篇——ActivityGroup实现tab功能>.这 ...

  8. Java开发学习(三十六)----SpringBoot三种配置文件解析

    一. 配置文件格式 我们现在启动服务器默认的端口号是 8080,访问路径可以书写为 http://localhost:8080/books/1 在线上环境我们还是希望将端口号改为 80,这样在访问的时 ...

  9. arcgis三维球中加载2000坐标系出现错误(The tiling scheme of this layer is not supported by SceneView)

    目前我们国家测绘地理信息的坐标体系基准是国家2000坐标系CGCS2000.各类地图组件如OpenLayers.Mapbox.Cesuim和ArcGIS Javascrip等都主要是支持WGS84(w ...

  10. Unity开发实战探讨-资源的加载释放最佳策略简要心得

    Unity开发实战探讨-资源的加载释放最佳策略简要心得 看过我另外一篇关于Unity资源释放随笔<Unity开发实战探讨-资源的加载释放最佳策略>如果觉得略微复杂,那么下面是一些比较简要的 ...

随机推荐

  1. Sonar 扫描之SonarScanner介绍

    Sonar扫描之SonarScanner介绍 SonarScanner用于在构建系统没有指定scanner时使用. 项目配置 在你的项目根目录中创建一个名为 sonar-project.propert ...

  2. DASCTF 2023六月挑战赛|二进制专项 PWN (下)

    DASCTF 2023六月挑战赛|二进制专项 PWN (下) 1.can_you_find_me 检查保护 意料之中 64位ida逆向 只有add,和del功能不能show 先看add吧 最多申请10 ...

  3. 涨见识了!脱离vue项目竟然也可以使用响应式API

    前言 vue3的响应式API大家应该都特别熟悉,比如ref.watch.watchEffect等.平时大家都是在vue-cli或者vite创建的vue项目里面使用的这些响应式API,今天欧阳给大家带来 ...

  4. 8、SpringMVC之RESTful案例

    阅读本文前,需要先阅读SpringMVC之RESTful概述 8.1.前期工作 8.1.1.创建实体类Employee package org.rain.pojo; import java.io.Se ...

  5. 【SpringBoot】16 数据访问P4 整合JPA

    DAO面向SpringData操作 Spring Data 项目的目的是为了简化构建基于 Spring 框架应用的数据访问技术, 包括非关系数据库.Map-Reduce 框架.云数据服务等等: 另外也 ...

  6. 【JavaScript】前端算法题 40道题+解析

    前言 最近练习了一些前端算法题,现在做个总结,以下题目都是个人写法,并不是标准答案,如有错误欢迎指出,有对某道题有新的想法的友友也可以在评论区发表想法,互相学习 题目 题目一: 二维数组中的查找: 在 ...

  7. 【转载】 拒绝遗忘:高效的动态规划算法 —— “到底什么是动态规划”—— An intro to Algorithms: Dynamic Programming

    原文地址(英文): https://medium.freecodecamp.org/an-intro-to-algorithms-dynamic-programming-dd00873362bb   ...

  8. baselines算法库baselines/common/input.py模块分析

    baselines算法库baselines/common/input.py模块代码: import numpy as np import tensorflow as tf from gym.space ...

  9. AQS专题

    1.背景 2.预备知识 2.1.park.unpark.interrupt.isInterrupted.interrupted方法的理解 一:park.unpark 1.park.unpark它不是T ...

  10. ubuntu 安装osx 主题 转自linux公社

    繁體 你好,游客 登录 注册 搜索 首页Linux新闻Linux教程数据库技术Linux编程服务器应用Linux安全Linux下载Linux认证Linux主题Linux壁纸Linux软件数码手机电脑 ...