传统在游戏中实现大多是插件的方式实现, 比如Unity的Magica Cloth, Unreal 里的 uDraper。大多基于AI的布料解算封装在插件中,

Magica Cloth

Magica Cloth 是一款Unity上的高速布料模拟器,完全使用自己的物理引擎,因此,它完全不会干扰Unity的物理系统。其代码实现基于job system 在CPU上多线程运行。

模块 说明
MagicaPhySicsManager 控制整个系统的管理器; 控制如何更新物理操作; 每个场景都需要一个
MagicaBoneCloth 骨骼布料; 控制骨骼(变形)以执行布料模拟 ;一般用于含有骨骼的头发;加载较快,负载很小
MagicBoneSpring 骨骼; 控制骨骼(变形)进行弹簧仿真;一般用于含有骨头的乳房的弹跳;加载较快,负载很小
MagicaVirtualDeformer 虚拟变形器;通过组合多个渲染变形器执行顶点缩减,并将其重建为一个虚拟网格;在MeshCloth/MeshSpring中,此虚拟器变形,结果反映在没饿过渲染变形器中以变形网格
MagicaMeshCloth 网格布料;在网格顶点上执行布料模拟;因为是以顶点为单位,所以比骨骼布料更加灵活;一般用于控制裙子动作;配合虚拟变形器一起实用;加载较慢,负载很大
MagicaMeshSpring 网格弹簧;在网格点上执行弹簧仿真;适合摇晃的没有绑定骨骼的网格;和虚拟变形器一起使用;负载一般
MagicaSphereCollider 球形碰撞;物理碰撞检测组件
MagicaCapsuleCollider 胶囊碰撞;物理碰撞检测组件
MagicaPlaneCollider 平面碰撞;物理碰撞检测组件;平面被视为无穷远处的平面
MagicaDirectionalWind 平行风
MagicaAreaWind 区域风

uPraper

uPraper虚幻引擎实时布料模拟插件与3D服装设计Unreal 商业插件, 配合 Marvelous Designer 设计好的服装样式, 在Unreal中实时渲染。

Marvelous Designer(简称MD)是一款独立的、专业的3d服装设计软件。要想用好它,需要对服装的布料剪裁有一定的了解,它可以导入其他三维软件的模特模型,导出模拟制作好的衣服模型到其他三维软件。实时布料解算模拟衣服在模特身上的效果。

APEX Cloth

从4.16版的虚幻引擎中,APEX Cloth 已被 NVIDIA的NvCloth解算器取代。这是一个轻巧的服装布料解算器,负责运行布料服装的模拟。该服装布料模拟器集成轻巧且非常可扩展,因为我们现在可以直接访问此数据。与APEX Clothing不同的是,APEX Clothing是一个复杂的SDK,可以一站式地进行服装模拟,同时处理模拟和渲染。

PBD

PBD算法的全称是Position-Base-Dynamic,顾名思义,它是一种计算机视觉方面的动态模拟算法,主要用于各种需要实时模拟的场景。相比起过去的基于真实物理规则的模拟来说,PBD算法具有这样的特征:

1、 直接基于位置而非受力情况来计算位置。计算的结果虽然并不是完全真实的物理模拟,但是可信度很高。

2、 性能更好,而且性能消耗的力度可控,可以根据实际应用中对真实性的需求强度来决定计算量。

3、 实时计算,动态模拟。

从这两个特征看出,PBD算法最适合的就是游戏、电影、VR之类的场景,不需要百分之百的完全真实,而是“看起来像”就可以了。由于PBD算法是一种实时模拟,尤其受到游戏行业的青睐。事实上,目前PBD算法在游戏领域也已经得到了广泛的应用,NVIDIA的Flex引擎包、网易的一些游戏都已经在使用该算法,有兴趣的同学可以自行查阅相关资料。相关背景就不再多做介绍,下面我们来直接进入算法环节。

算法流程
在计算机领域,很多惊艳算法的核心流程都称得上是微言大义,并不冗长,例如蒙特卡洛算法、牛顿迭代法等。PBD算法的流程也十分精炼,一张图搞定:

我们把想要模拟的复杂系统,例如流体、布料、头发等,拆解成一个个质点,质点拆解得越多,消耗的性能就越多,效果也就越逼真,大家可以根据自身的实际需求来进行拆解。x指的是质点i的位置,v指的是质点的初速度,m是质点的质量(并不一定是真实质量,而是在整个系统中的相对值),w是m的倒数。为啥要弄个倒数出来呢,主要是方便计算,把除法变成乘法,而且还可以把一些静止质点视为质量无限大,直接把w设成0即可

游戏里使用的形变体模拟大多以 position-based dynamics (PBD) 技术为主。一个典型的实例是 NVIDIA 的 NvCloth。PBD 的缺点也很明显。当模拟需要的网格规模变大(比如超过 1024 个顶点),PBD 的效率就不再那么优秀了。第二个缺点就是迭代的deltaTime必须很小,模拟效果才是稳定的,否则效果就会崩塌。

PBD的求解往往是基于弹簧质点模型

$Δ_x$是两个长度的差值。如果 $\Delta_x$越大,那么力也就越大。从公式可以看出,如果我们单纯从一个方向看,那么质点所受到的力是相反方向。

布料可以看成多个弹簧组合成的模型, 具体根据质点组合情况分为: Bend spring, Shrear spring, Struct spring, 相关的求解应用在 Fast Simulation MSS 这篇论文。

  • Bend spring: 上下左右跨一个质点连接,用以模拟材料弯曲的力
  • Shear spring: 对角线连接,模拟剪力
  • Struct spring:上下左右相邻质点连接,模拟结构力,如拉伸和收缩

除了上述了几种弹簧力, 模拟布料还需要考虑阻尼、重力、风场等外力的影响。

基于无监督的布料模拟

2022年,从Siggraph上看到一篇基于无监督深度学习的布料模拟Paper: Neural Cloth Simulation。 作者以子空间求解器以动静结合的方式求解。 定义一个蒙皮的3D布料求解器假参数化 $ \theta $ (位姿position和身体形状shape) 和速度构成, 因此可以抽象写成下面公式:

其中速度v 依赖当前和上一次 ${t-1}$的位置, 因此上面的式子可以重写为:$x_t = f(\theta_t, x_{t-1}, x_{t-2})$, 类推 $x_{t-1} = f(\theta_{t-1}, x_{t-2}, x_{t-3})$。 由此可以推导 $x_{t-2}, x_{t-3}$ 等等, 由此可以得到:

由此我们也可以看到时间越早的姿势对当前布料的状态影响越小, 这也允许我们丢弃掉一定时间窗口之外的姿态输入。对于静态部分,则意味着模型完全由$\theta_t$参数化。

基于上面所述,于是设计了一个循环编解码器。该模型以人体运动$\theta_t$作为输入, 将其编码为 $z_t$, 最后解码输出为 $x_t$。 其中编码器被分解为一个静态编码器和一个动态编码器, 如下如所示:

由于是基于无监督学习, 作者设计了几个损失函数, 使训练的过程中,模型能够按照预设的方向进行:

曲度损失函数

作者使用 Adaptive Tearing and Cracking of Thin Sheets 关于三角面之间的夹角定义:

$k_b$为弯曲刚度,l为公共边长度,$\alpha$为两面面积之和,$\phi_t$为二面角,$\phi^R$为布料另外一面的夹角。

碰撞损失函数

在计算机图形学中, 布料和外部的交互就是通过检测和解析碰撞来的。于是作者设计了一个惩罚项来促使布料运动在身体之外。

$k_c$为平衡因子,$d( · ; θ)$为与θ参数化的体网格的符号距离,内部为负值,$\epsilon$为小阈值以保证鲁棒性。

惯性函数 Inertia Loss

基于运动学规律, 运动的物体在受力停止之后,其将保持速度。 在不受力的情况下, 物体的运动将满足下面的表达式:

在受力的情况下,运力的运动将跟物体自身的质量相关, 可以用如下的表达式表达:

M表示为质量矩阵,$Δ_t$为模拟的时间步长,E ( · )为代表潜在的内外受力。 基于实际物体的位置和通过推导公式得到的公式于是定义惯性的损失函数如下:

重力损失

重力损失实现是讲布料的势能作为损失:

此项将顶点按照重力方向运动, 其值的大小由质量和重量加权得到。

运行结果

作者代码实现时, 会做一些预处理, 比如在输入网格前, 现将网格使用拉普拉斯变换对顶点进行平滑处理。 代码最后将运行数据存在numpy里, 然后使用Blender的顶点修改器应用修改的数据, 如果想在引擎中实现效果, 最好将顶点数据存在一张RenterTexture, 运行时通过uv偏移采样数据去修改定点位置。