符号说明
仿真物体包括 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:R3nj→R ;
- 节点编号集合 {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=xi0,vi=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 时间内重复一次以下过程:
- 处理外力:vi←vi+Δtwifext(xi)\boldsymbol{v_i} \leftarrow \boldsymbol{v_i} + \Delta t w_i f_{ext}(\boldsymbol{x_i})vi←vi+Δtwifext(xi) ;
- 速度阻尼:dampVelocities(v1,...,vN)dampVelocities(\boldsymbol{v_1},...,\boldsymbol{v_N})dampVelocities(v1,...,vN) ;
- 下一个位置预测:pi←xi+Δtvi\boldsymbol{p_i} \leftarrow \boldsymbol{x_i}+\Delta t \boldsymbol{v_i}pi←xi+Δtvi ;
- 碰撞检测,生成 McollM_{coll}Mcoll 个碰撞约束:generateCollisionConstraints(xi→pi)generateCollisionConstraints(\boldsymbol{x_i}\rightarrow \boldsymbol{p_i})generateCollisionConstraints(xi→pi) ;
- 若干次迭代:每次迭代处理一遍所有约束 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) ;
- 速度、位置更新:vi←(pi−xi)/Δt\boldsymbol{v_i}\leftarrow (\boldsymbol{p_i}-\boldsymbol{x_i})/\Delta tvi←(pi−xi)/Δt ,xi←pi\boldsymbol{x_i}\leftarrow \boldsymbol{p_i}xi←pi ;
- 碰撞节点的速度更新: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=xi−xc ;
- 系统转动惯量 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}ω=I−1L ;
然后设定一个全局的参数 kdamping∈[0,1]k_{damping}\in[0,1]kdamping∈[0,1] ,对于每个节点的速度 vi\boldsymbol{v_i}vi,做如下变换:
- Δvi=vc+ω×ri−vi\Delta \boldsymbol{v_i}=\boldsymbol{v_c}+\boldsymbol{\omega}\times\boldsymbol{r_i}-\boldsymbol{v_i}Δvi=vc+ω×ri−vi;
- vi←vi+kdampingΔvi\boldsymbol{v_i}\leftarrow\boldsymbol{v_i}+k_{damping}\Delta\boldsymbol{v_i}vi←vi+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}x 和 p\boldsymbol{p}p 都在另一个物体内部;
对于这两种类型,我们都希望 ppp 能够被约束到另一个物体外部,因此构造如下约束:
- 对于第一种类型,构造不等式约束 C(p)=(p−qc)⋅ncC(\boldsymbol{p})=(\boldsymbol{p}-\boldsymbol{q_c})\cdot\boldsymbol{n_c}C(p)=(p−qc)⋅nc ,刚度参数 k=1k=1k=1;
- 对于第二种类型,构造不等式约束 C(p)=(p−qs)⋅nsC(\boldsymbol{p})=(\boldsymbol{p}-\boldsymbol{q_s})\cdot\boldsymbol{n_s}C(p)=(p−qs)⋅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=xk−f′(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}p←p+Δ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=−s∇piC(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)=Σj∣∇pjC(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ωi∇piC(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−(1−k)1/ns ,存在线性误差 Δp(1−k)\Delta\boldsymbol{p}(1-k)Δp(1−k) 。
7
这一步是用来更新发生了碰撞的节点的速度的。
如果一个节点发生了碰撞,假设碰撞位置的法向量为 n\boldsymbol{n}n ,那么该节点速度垂直于 n\boldsymbol{n}n 的分量将因为摩擦力而减少,并且由于反弹会产生与 n\boldsymbol{n}n 同方向的速度分量。
本文详细阐述了物理基础建模(Body and Dynamics)中的节点参数、约束函数、速度阻尼处理、碰撞检测与约束解决策略,以及牛顿迭代法在PBD算法中的应用。核心内容涉及节点属性、碰撞检测类型和牛顿迭代法求解动力学问题。
1035

被折叠的 条评论
为什么被折叠?



