PBD(Position Based Dynamics)学习笔记

本文详细阐述了物理基础建模(Body and Dynamics)中的节点参数、约束函数、速度阻尼处理、碰撞检测与约束解决策略,以及牛顿迭代法在PBD算法中的应用。核心内容涉及节点属性、碰撞检测类型和牛顿迭代法求解动力学问题。

符号说明

仿真物体包括 NNN 个节点和 MMM 个约束。

每个节点 i∈[1,...,N]i\in [1,...,N]i[1,...,N] 包含的参数有质量 mim_imi 、位置 xi\boldsymbol{x_i}xi 和速度 vi\boldsymbol{v_i}vi

每个约束 j∈[1,...,M]j\in[1,...,M]j[1,...,M] 包含的参数有:

  • 基数 njn_jnj
  • 约束函数 Cj:R3nj→RC_j: \mathbb{R}^{3n_j} \rightarrow \mathbb{R}Cj:R3njR
  • 节点编号集合 {i1,...,inj}, ik∈[1,...,N]\{i_1,...,i_{n_j}\}, \ i_k\in[1,...,N]{i1,...,inj}, ik[1,...,N]
  • 刚度参数 kj∈[0,1]k_j\in[0,1]kj[0,1] ,描述约束的强度;
  • 约束类型:等式 或 不等式;
    • 等式表示 Cj(xi1,...,xinj)=0C_j(\boldsymbol{x_{i_1}},...,\boldsymbol{x_{i_{n_j}}})=0Cj(xi1,...,xinj)=0
    • 不等式表示 Cj(xi1,...,xinj)≥0C_j(\boldsymbol{x_{i_1}},...,\boldsymbol{x_{i_{n_j}}})\ge 0Cj(xi1,...,xinj)0

算法流程

首先初始化 xi=xi0\boldsymbol{x_i}=\boldsymbol{x_i^0}xi=xi0vi=vi0\boldsymbol{v_i}=\boldsymbol{v_i^0}vi=vi0ωi=1/mi\omega_i=1/m_iωi=1/mi ,然后在每个 Δt\Delta tΔt 时间内重复一次以下过程:

  1. 处理外力:vi←vi+Δtwifext(xi)\boldsymbol{v_i} \leftarrow \boldsymbol{v_i} + \Delta t w_i f_{ext}(\boldsymbol{x_i})vivi+Δtwifext(xi)
  2. 速度阻尼:dampVelocities(v1,...,vN)dampVelocities(\boldsymbol{v_1},...,\boldsymbol{v_N})dampVelocities(v1,...,vN)
  3. 下一个位置预测:pi←xi+Δtvi\boldsymbol{p_i} \leftarrow \boldsymbol{x_i}+\Delta t \boldsymbol{v_i}pixi+Δtvi
  4. 碰撞检测,生成 McollM_{coll}Mcoll 个碰撞约束:generateCollisionConstraints(xi→pi)generateCollisionConstraints(\boldsymbol{x_i}\rightarrow \boldsymbol{p_i})generateCollisionConstraints(xipi)
  5. 若干次迭代:每次迭代处理一遍所有约束 projectConstraints(C1,...,CM+Mcoll,p1,...,pN)projectConstraints(C_1,...,C_{M+M_{coll}},\boldsymbol{p_1},...,\boldsymbol{p_N})projectConstraints(C1,...,CM+Mcoll,p1,...,pN)
  6. 速度、位置更新:vi←(pi−xi)/Δt\boldsymbol{v_i}\leftarrow (\boldsymbol{p_i}-\boldsymbol{x_i})/\Delta tvi(pixi)/Δtxi←pi\boldsymbol{x_i}\leftarrow \boldsymbol{p_i}xipi
  7. 碰撞节点的速度更新:velocityUpdate(vi,...,vN)velocityUpdate(\boldsymbol{v_i},...,\boldsymbol{v_N})velocityUpdate(vi,...,vN)

流程详细说明

2

由于物体内部的摩擦力、粘性等特性,节点速度变化时会有阻尼。PBD中速度阻尼的计算方法如下:

首先计算系统的质心、角速度:

  • 质心 xc=(Σiximi)/(Σimi)\boldsymbol{x_c}=(\Sigma_i{\boldsymbol{x_i}m_i})/(\Sigma_i{m_i})xc=(Σiximi)/(Σimi)
  • 质心速度 vc=(Σivimi)/(Σimi)\boldsymbol{v_c}=(\Sigma_i{\boldsymbol{v_i}m_i})/(\Sigma_i{m_i})vc=(Σivimi)/(Σimi)
  • 系统角动量 L=Σiri×(mivi)\boldsymbol{L}=\Sigma_i{\boldsymbol{r_i}\times (m_i\boldsymbol{v_i})}L=Σiri×(mivi) ,其中 ri=xi−xc\boldsymbol{r_i}=\boldsymbol{x_i}-\boldsymbol{x_c}ri=xixc
  • 系统转动惯量 I=Σiri~ri~Tmi\boldsymbol{I}=\Sigma_i{\widetilde{\boldsymbol{r_i}}\widetilde{\boldsymbol{r_i}}^Tm_i}I=ΣiririTmi
  • 系统角速度 ω=I−1L\boldsymbol{\omega}=\boldsymbol{I}^{-1}\boldsymbol{L}ω=I1L

然后设定一个全局的参数 kdamping∈[0,1]k_{damping}\in[0,1]kdamping[0,1] ,对于每个节点的速度 vi\boldsymbol{v_i}vi,做如下变换:

  1. Δvi=vc+ω×ri−vi\Delta \boldsymbol{v_i}=\boldsymbol{v_c}+\boldsymbol{\omega}\times\boldsymbol{r_i}-\boldsymbol{v_i}Δvi=vc+ω×rivi
  2. vi←vi+kdampingΔvi\boldsymbol{v_i}\leftarrow\boldsymbol{v_i}+k_{damping}\Delta\boldsymbol{v_i}vivi+kdampingΔvi

从中可看出 kdampingk_{damping}kdamping 描述了阻尼强度,如果 kdamping=1k_{damping}=1kdamping=1,那么系统为刚体;如果 kdamping=0k_{damping}=0kdamping=0,那么每个节点自由运动,不存在阻尼。

4

当某个物体的一个节点从 x\boldsymbol{x}x 运动到 p\boldsymbol{p}p 时,可能与其它物体发生碰撞,这里碰撞有两种类型(原文描述的两种类型为 continuous collision 和 static collision,但我不明白这么命名的原因):

  • x\boldsymbol{x}x 在另一个物体外部而 p\boldsymbol{p}p 在另一个物体内部;
  • x\boldsymbol{x}xp\boldsymbol{p}p 都在另一个物体内部;

对于这两种类型,我们都希望 ppp 能够被约束到另一个物体外部,因此构造如下约束:

  • 对于第一种类型,构造不等式约束 C(p)=(p−qc)⋅ncC(\boldsymbol{p})=(\boldsymbol{p}-\boldsymbol{q_c})\cdot\boldsymbol{n_c}C(p)=(pqc)nc ,刚度参数 k=1k=1k=1
  • 对于第二种类型,构造不等式约束 C(p)=(p−qs)⋅nsC(\boldsymbol{p})=(\boldsymbol{p}-\boldsymbol{q_s})\cdot\boldsymbol{n_s}C(p)=(pqs)ns ,刚度参数 k=1k=1k=1

还有其它很多碰撞检测的约束方法,比如运动节点和运动三角形的。

5

这一步要迭代若干次,因为其本质是用了类似**牛顿迭代法(Newton’s Method / Newton-Raphson Method)**的方法。

牛顿迭代法,用于求解方程 f(x)=0f(x)=0f(x)=0,迭代函数为 xk+1=xk−f(xk)f′(xk)x_{k+1}=x_k-\frac{f(x_k)}{f^{'}(x_k)}xk+1=xkf(xk)f(xk),迭代足够多次时 xxx 接近零点。

而每一次迭代,采取了 Gauss-Seidel method 的思想,即独立地一个个地处理每个约束(Gauss-Seidel method 在求解 Ax=bAx=bAx=b 时,一个个地求取 xix_ixi,并且当前求取的 xix_ixi 会用到后面分量的求取中)。

因此,第5步的过程就是:循环若干次,每次循环时一个个处理所有约束。

约束有两类,一类是固有的 MMM 个约束,另一类是每次碰撞检测生成的 McollM_{coll}Mcoll 个约束,前者需要满足动量和角动量守恒,而后者不用。由于 C(p)C(\boldsymbol{p})C(p) 的值与刚体运动(平移、旋转)无关,也就是说刚体运动对应 p\boldsymbol{p}p 的变化位于 C(p)C(\boldsymbol{p})C(p) 的等值线上,因此梯度 ∇pC(p)\nabla_{\boldsymbol{p}}C(\boldsymbol{p})pC(p) 与刚体运动正交,如果 p\boldsymbol{p}p 的变化 Δp\Delta\boldsymbol{p}Δp 位于 ∇pC(p)\nabla_{\boldsymbol{p}}C(\boldsymbol{p})pC(p) 的方向上,那么自然能保持动量守恒(这里存疑……)。

假设所有节点质量相等,下面说明如何处理一个等式约束 C(p)=C(p1,...,pn)=0C(\boldsymbol{p})=C(\boldsymbol{p_1},...,\boldsymbol{p_n})=0C(p)=C(p1,...,pn)=0

对于当前的 p\boldsymbol{p}p ,我们需要计算一个 Δp\boldsymbol{\Delta p}Δp,使得 C(p+Δp)≈C(p)+∇pC(p)⋅Δp=0C(\boldsymbol{p}+\boldsymbol{\Delta p})\approx C(\boldsymbol{p})+\nabla_{\boldsymbol{p}}C(\boldsymbol{p})\cdot\boldsymbol{\Delta p}=0C(p+Δp)C(p)+pC(p)Δp=0 ,由于 Δp\Delta\boldsymbol{p}Δp 在梯度的方向上,因此可设 Δp=λ∇pC(p)\Delta\boldsymbol{p}=\lambda\nabla_{\boldsymbol{p}}C(\boldsymbol{p})Δp=λpC(p) ,联立求解可得
Δp=−C(p)∣∇pC(p)∣2∇pC(p)(1) \Delta\boldsymbol{p}=-\frac{C(\boldsymbol{p})}{|\nabla_{\boldsymbol{p}}C(\boldsymbol{p})|^2}\nabla_{\boldsymbol{p}}C(\boldsymbol{p}) \tag{1} Δp=pC(p)2C(p)pC(p)(1)
上式就是牛顿迭代法中的一步变化 p←p+Δp\boldsymbol{p}\leftarrow\boldsymbol{p}+\Delta\boldsymbol{p}pp+Δp,而一次迭代需要对所有约束都作这样的计算。

我们将 Δp\Delta\boldsymbol{p}Δp 进行拆分,可以得到与 (1) 等价的式子
Δpi=−s∇piC(p)(2) \Delta\boldsymbol{p}_i=-s\nabla_{\boldsymbol{p}_i}C(\boldsymbol{p}) \tag{2} Δpi=spiC(p)(2)
其中
s=C(p)∣∇pC(p)∣2=C(p)Σj∣∇pjC(p)∣2(3) s=\frac{C(\boldsymbol{p})}{|\nabla_{\boldsymbol{p}}C(\boldsymbol{p})|^2} = \frac{C(\boldsymbol{p})}{\Sigma_j{|\nabla_{\boldsymbol{p}_j}C(\boldsymbol{p})|^2}} \tag{3} s=pC(p)2C(p)=ΣjpjC(p)2C(p)(3)
这么做是为了处理节点质量不相等的情况,当质量不相等时,pi\boldsymbol{p}_ipi 的变化应当与质量成反比。因此考虑质量的倒数 ωi=1/mi\omega_i=1/m_iωi=1/mi ,可得
Δpi=−snωiΣjωj∇piC(p)(4) \Delta\boldsymbol{p}_i=-s\frac{n\omega_i}{\Sigma_j\omega_j}\nabla_{\boldsymbol{p}_i}C(\boldsymbol{p}) \tag{4} Δpi=sΣjωjnωipiC(p)(4)
对于不等式约束,我们只在 C(p)<0C(\boldsymbol{p})<0C(p)<0 时进行迭代变换。

如果再考虑每个约束的刚度参数 kkk,假设需要 nsn_sns 轮迭代(这里或许是:假设还需要 nsn_sns 轮迭代?),我们将位置修正 Δp\Delta\boldsymbol{p}Δp 乘上系数 1−(1−k)1/ns1-(1-k)^{1/n_s}1(1k)1/ns ,存在线性误差 Δp(1−k)\Delta\boldsymbol{p}(1-k)Δp(1k)

7

这一步是用来更新发生了碰撞的节点的速度的。

如果一个节点发生了碰撞,假设碰撞位置的法向量为 n\boldsymbol{n}n ,那么该节点速度垂直于 n\boldsymbol{n}n 的分量将因为摩擦力而减少,并且由于反弹会产生与 n\boldsymbol{n}n 同方向的速度分量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值