5-SOFA可变形的3D物体 5-elasticity.scn

接下来从 rigid case 进入 deformable case(从刚体情况进入可变形情况)

rigid frames → deformable object

一个或多个刚体点/刚体 frame 整体移动→一个 3D 物体可以发生形变

Adding a material law for deformation 现在要给物体加入"材料定律",让它能按照材料属性发生变形。

5-elasticity.scn

XML 复制代码
<?xml version="1.0"?>

<!-- Adding a material law for deformation -->
<Node name="root" dt="0.01" gravity="0 0 0">

    <!-- Needed to use UniformMass / MeshMatrixMass -->
    <RequiredPlugin name="Sofa.Component.Mass"/>

    <!-- Needed to use ConstantForceField -->
    <RequiredPlugin name="Sofa.Component.MechanicalLoad"/>

    <!-- Needed to use MechanicalObject -->
    <RequiredPlugin name="Sofa.Component.StateContainer"/>

    <!-- Needed to use CGLinearSolver -->
    <RequiredPlugin name="Sofa.Component.LinearSolver.Iterative"/>

    <!-- Needed to use EulerImplicitSolver -->
    <RequiredPlugin name="Sofa.Component.ODESolver.Backward"/>

    <!-- Needed to use MeshGmshLoader -->
    <RequiredPlugin name="Sofa.Component.IO.Mesh"/>

    <!-- Needed to use TetrahedronSetTopologyContainer / TetrahedronSetGeometryAlgorithms -->
    <RequiredPlugin name="Sofa.Component.Topology.Container.Dynamic"/>

    <!-- Needed to use TetrahedronFEMForceField -->
    <RequiredPlugin name="Sofa.Component.SolidMechanics.FEM.Elastic"/>

    <DefaultAnimationLoop computeBoundingBox="false"/>

    <MeshGmshLoader name="meshLoaderCoarse" filename="mesh/liver.msh" />

    <!-- Optional: transform the loaded mesh position -->
    <!--
    <TransformEngine name="transformer"
                     input_position="@meshLoaderCoarse.position"
                     translation="0 2 0"
                     rotation="0 0 0" />
    -->

    <Node name="Liver">

        <EulerImplicitSolver />
        <CGLinearSolver iterations="200" tolerance="1e-09" threshold="1e-09"/>

        <TetrahedronSetTopologyContainer name="topo" src="@../meshLoaderCoarse" />

        <TetrahedronSetGeometryAlgorithms template="Vec3d" name="GeomAlgo" />

        <MechanicalObject template="Vec3d"
                          name="MechanicalModel"
                          showObject="1" />

        <TetrahedronFEMForceField name="FEM"
                                  youngModulus="1000"
                                  poissonRatio="0.4" />

        <MeshMatrixMass massDensity="1" />

        <ConstantForceField totalForce="1 0 0" />

    </Node>

</Node>

学习简化版代码:

XML 复制代码
<Node name="root" dt="0.01" gravity="0 0 0">

    <MeshGmshLoader name="meshLoaderCoarse" filename="mesh/liver.msh" />

    <Node name="Liver">

        <EulerImplicitSolver />
        <CGLinearSolver iterations="200" tolerance="1e-09" threshold="1e-09"/>

        <TetrahedronSetTopologyContainer name="topo" src="@../meshLoaderCoarse" />
        <TetrahedronSetGeometryAlgorithms template="Vec3d" name="GeomAlgo" />

        <MechanicalObject template="Vec3d" name="MechanicalModel" showObject="1"/>

        <TetrahedronFEMForceField name="FEM" youngModulus="1000" poissonRatio="0.4" />
        <MeshMatrixMass massDensity="1" />
        <ConstantForceField totalForce="1 0 0" />

    </Node>

</Node>

1.deformable object 可形变物体

在前面 SOFA 场景里,什么东西决定了对象的类型、决定了自由度的性质?

答案是:MechanicalObject 的 template

XML 复制代码
<MechanicalObject template="Rigid3d" ... />

它表示对象是 3D 刚体,状态包含:位置 x y z + 姿态 orientation / quaternion

现在进入可变形物体后,最关键变化是:

XML 复制代码
<MechanicalObject template="Vec3d" name="MechanicalModel" showObject="1"/>

从 Rigid3d 改成 Vec3d,这是从刚体到可变形物体时主要改变的东西之一。

区别是:

(1)Rigid3d:

每个自由度 = 位置 xyz + 姿态 quaternion

适合刚体 frame。

(2)Vec3d:

每个自由度 = 位置 xyz

适合可变形体的网格节点。

对于可变形物体,每个节点只是空间中的一个点,它可以移动,但没有自己的刚体姿态。

所以现在的未知量是:每个 mesh node 的 x、y、z 位置

2.TetrahedronSetTopologyContainer(四面体拓扑容器)

如果我们要做一个普通的 3D 可变形物体,就需要一个真正的 3D 有体积的网格。

前面 liver.msh 文件不只包含点,还包含:points / nodes、edges、triangles、tetrahedra

其中 tetrahedra 是四面体单元,是 3D 体积元素。要在 3D 空间里求解力学平衡方程,需要这些 3D 元素作为空间支撑。

可变形仿真不是让一堆独立点乱飞,而是让一个由四面体连接起来的体积物体发生形变。

之前只关心点,所以用:

XML 复制代码
<PointSetTopologyContainer name="topo" src="@../meshLoaderCoarse" />

现在要做 3D 可变形体,需要完整的四面体拓扑,所以换成:

XML 复制代码
<TetrahedronSetTopologyContainer name="topo" src="@../meshLoaderCoarse" />

它同样从 meshLoaderCoarse 里读取数据,但这次不再只读取点,而是读取完整的拓扑层级:tetrahedra、triangles、edges、points。

这些信息先由 MeshGmshLoader 加载,然后由 TetrahedronSetTopologyContainer 存储。

3.MechanicalObject 仍然不用手写 position

和之前一样,现在也不需要在 MechanicalObject 里手写:position="..."

XML 复制代码
<TetrahedronSetTopologyContainer name="topo" src="@../meshLoaderCoarse" />
<MechanicalObject template="Vec3d" name="MechanicalModel" showObject="1"/>

MechanicalObject 会在同一个 Liver 节点里找到 topology container,然后自动用里面的节点位置初始化自己的 position。

MeshGmshLoader 读 mesh

→ TetrahedronSetTopologyContainer 保存四面体拓扑和点位置

→ MechanicalObject 自动拿这些点位置作为初始状态

4.TetrahedronSetGeometryAlgorithms 工具包

XML 复制代码
<TetrahedronSetGeometryAlgorithms template="Vec3d" name="GeomAlgo" />

它不是主要的物理组件,而是一个 toolkit,工具包 。

它提供几何计算能力,比如:某个四面体的体积是多少、某个三角形的面积是多少、两个点之间的距离是多少。这些几何信息会被后面的物理组件使用。

5.负责物理的组件

后面这两个组件会用到上面的几何算法:

XML 复制代码
<TetrahedronFEMForceField name="FEM" youngModulus="1000" poissonRatio="0.4" />
<MeshMatrixMass massDensity="1" />
(1)MeshMatrixMass(网格质量矩阵组件)
XML 复制代码
<MeshMatrixMass massDensity="1" />

这个组件根据体网格和质量密度,进行空间积分,构建质量矩阵。给它一个 mass density,它就能在整个 3D 域上积分,得到 mass matrix。

UniformMass:

前面那种简单平均分配总质量。

MeshMatrixMass:

根据 3D 网格体积和质量密度,计算更合理的质量分布。

(2)TetrahedronFEMForceField
XML 复制代码
<TetrahedronFEMForceField name="FEM" youngModulus="1000" poissonRatio="0.4" />

TetrahedronFEMForceField 组件 实现的是可变形体的 材料模型 / 本构力学模型。

它定义了:物体如何变形、物体变形后产生什么内部力,这些内部力就是材料本身抵抗变形的力。

  • 刚体以前只有:质量 + 外力 → 整体运动
  • 可变形体现在多了:材料模型 → 产生内部弹性力 → 发生形变但又抵抗形变

这个 constitutive mechanical model(材料本构模型) 是 linear elasticity 线弹性 模型。

线弹性可以理解成,形变不太大时,力和位移/应变近似成线性关系。类似弹簧里的胡克定律:F = kx

力学里还有很多材料模型,比如一些 hyperelastic model,超弹性模型 ,包括 Mooney-Rivlin、Ogden 等,它们属于非线性材料模型。但这里这个不是那些复杂非线性模型,而是 linear elasticity,线弹性模型。

(a).youngModulus 杨氏模量

youngModulus="1000" 这是 杨氏模量。它代表材料有多硬,单位和压力一样,通常是 Pascal/ Pa。

  • Young's modulus 大:材料更硬,不容易变形
  • Young's modulus 小:材料更软,更容易变形
(b).poissonRatio 泊松比

poissonRatio="0.4" 这是 泊松比。它和材料的横向变形/可压缩性有关。比如你压缩一个方向,另一个方向会膨胀多少。

poissonRatio 控制材料被拉伸/压缩时,横向会怎么变。

6.刚体和可变形体的对比

前面刚体:

XML 复制代码
<MechanicalObject template="Rigid3d" .../>
<UniformMass totalMass="1"/>
<ConstantForceField totalForce="1 0 0 0 0 0"/>

它只有一个刚体 frame。受到力以后不会变形,只会整体运动。

现在可变形体:

XML 复制代码
<TetrahedronSetTopologyContainer .../>
<MechanicalObject template="Vec3d" .../>
<TetrahedronFEMForceField .../>
<MeshMatrixMass .../>
<ConstantForceField totalForce="1 0 0"/>

它是一个 3D mesh。这个网格作为空间积分域,用来计算质量、材料内部力和外力。

ConstantForceField 现在只有 3 个数

  • 前面刚体 Rigid3d 时外力是 totalForce="1 0 0 0 0 0",因为刚体有 3 个平移力 + 3 个力矩
  • 现在 Vec3d 时外力变成 totalForce="1 0 0",因为每个节点只有 x y z 三个平移自由度

没有刚体姿态,也没有力矩自由度。现在没有 frame / orientation 的概念,只有空间中的点,所以 force 自身也只有 X、Y、Z 三个分量。

刚体阶段 可变形体阶段
Rigid3d Vec3d
一个刚体 frame,有位置和姿态 mesh 节点,只有 x/y/z 位置
PointSetTopologyContainer TetrahedronSetTopologyContainer
只用点 用四面体体网格
UniformMass MeshMatrixMass
简单质量 根据质量密度和体积积分质量矩阵
没有材料模型 TetrahedronFEMForceField 定义材料变形规律
totalForce="1 0 0 0 0 0" totalForce="1 0 0"

7.SOFA 不管单位,单位一致性要自己负责

SOFA 不会自动知道你用的是米、毫米、千克还是克,SOFA 只拿数值去计算,所以必须保证所有输入单位是一致的。

比如用国际单位制:

长度:m;质量:kg;时间:s;力:N;杨氏模量:Pa;密度:kg/m³;重力加速度:m/s²

但如果mesh 是毫米单位,又把 Young modulus 当成 Pa 来填,仿真结果就会错。网格单位、杨氏模量、质量密度、重力加速度这些都必须在同一套单位体系里。

所以很多错误都来自 mesh。

因为 mesh 可能来自扫描、MRI、3D scan 或别的软件,里面的尺寸单位有时并不清楚。它可能是毫米,也可能是米,也可能只是某种缩放后的无单位坐标。

所以以后拿到一个 .msh、.obj、.vtk 文件,不要只问"能不能加载",还要问:

这个 mesh 的坐标单位到底是什么?

它的大小是真实尺寸吗?

这会直接影响材料参数、质量、重力和仿真稳定性。

相关推荐
三少爷的鞋6 小时前
AI 时代,我们都将成为通才型开发者:只懂 Android,已经不够了
android
Dovis(誓平步青云)10 小时前
家里设备越来越多,如何用一张空间地图控制灯光和温度![
android·java·前端·javascript·人工智能·电脑
晚风叙码11 小时前
MySQL 数据类型详解:从数值到字符串,一篇讲透
android·mysql·adb
传奇开心果编程12 小时前
【Compose Multiplatform 跨端开发学与练】第3课 布局与组件
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程15 小时前
【Compose Multiplatform 跨端开发学与练】第8课 资源管理与主题
android·windows·学习·ios·kotlin·web·composer
传奇开心果编程16 小时前
【Compose Multiplatform 跨端开发学与练】第9课 测试与调试
android·学习·macos·ios·kotlin·web·composer
传奇开心果编程16 小时前
【Compose Multiplatform 跨端开发学与练】第4课 导航与路由
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程16 小时前
【Compose Multiplatform 跨端开发学与练】第6课 状态管理与架构
android·学习·ui·ios·架构·kotlin·composer
事圆则缓17 小时前
Android AOSP 定制常见概念:源码目录、系统镜像与刷机流程
android
传奇开心果编程17 小时前
【Compose Multiplatform 跨端开发学与练】第2课 Compose 基础语法
android·windows·学习·ui·ios·kotlin·composer