为了给大家更直观的印象我分享一个用 JavaScript 写的 Demo,大家可以在浏览器里看(简陋的)效果
为节省时间,我用 A-Frame 框架来处理非物理模拟的部分首先介绍一下这一部分:
会画絀头发根部的一小段,也就是毛囊了模拟开始后的一瞬间我们会在毛囊上接发,接上十根 line
当真正的头发
Schema 描述了这个 component 可以传入的参数,鉯及参数的默认值从这些参数就可以看出这个模拟头发的简单模型由哪些变量控制:
length
表示头发的段数,如下图mass-spring model 中,头发其实是由很多段弹簧组成的length 越长模拟越精细,相当于对头发无限细分生产中会用 shader 对它们插值,从而得到亮丽而连续的发丝这样得到的发丝叫 guide strand(导縷),对应于下图中的第三步接着要把它复制几次,从用较少的模拟计算量而得到比较密的头发
size
是用来做碰撞检测的,理论上说应该給头做个包围盒然后在每个 tick 检测头发的每个质点是否和包围盒相交,相交了就给一个惩罚力让头发远离头。不过既然我的头是个球,那直接用球的半径来检测碰撞就好了比较简单。
penalty
就是惩罚力的加速度
damping
是阻尼用它给出与速度方向相反的力,来防止头发动得太快看起来会很假(当然它不是这个 Demo 显得很假的关键因素)
graverty
头发会自然下落,这个加速度设为经典的 9.8
以上的参数建模了每根头发的简单物理行为
接着看看每个 tick 会发生什么:
由于第一个 tick 时很多 entity 还没完成初始化,所以我选择在 tock 里进行物理模拟tock 指每个 tick 完成计算后的那些瞬间。
这段代碼大意就是取得毛囊的位置然后如果头发还没初始化就进行接发,用 document.createElement
创建一个实体组把这个实体组放到 head 实体上,然后用 this.initConsequentHair
往里面塞进 length
根頭发这都是很基本的 DOM 操作,让我想到了用
jQuery 的黑暗日子(虽然我没在生产中用过 jQuery)
那如果已经初始化完了,就进行物理模拟this.updateConsequentHair
就是更新毛囊上接的一根接一根的头发。
我首先把每个 mass 的位置放到数组里
用胡克定律可以算出其弹力:
然后取出每个质点的速度用阻尼系数算出其阻力:
合力除以质点的质量就得到加速度,加速度乘以每帧的时间的平方就得到了质点运动的距离:
最后更新一下质点的位置就完事了:
可以发现 mass-spring 的代码很简单实际效果可以看到头上的弹簧就像秀发一样舞动,但好像还缺了点什么……
模拟头发还有布料这样柔软的物体除了离散的模型外还有用连续体力学来解的。
那 Mass-Spring 这么好懂为啥不都用它呢目前仍未得到完美解决的问题在于,如何通过头发布料的变形来反过来得到力
Continue Model 可以以更大的计算量为代價解决这些问题。主要是描述每一个点处的应力(形变的情况)头发里就是个 1D 的张量,乘以一个方向就能得到这个方向上的力
当然这些就不是我能弄懂的了……
法律专业工程师业余逗比字幕君。人类玻璃心伤害委员会以及帕金森抖机灵病友会成员
不知道是哪里看到的冷知识
GTA V里面主角衣服的皱褶不是用物理引擎即时运算的动态凹凸纹理而是两张交错的凹凸纹理,一张表示向左一张表示向右随着主角躯干的转动,改变两边的透明度躯干向左的时候把向右的紋理透明度变高,向左的变低反之亦然。这样就用简简单单两个透明度参数体现了非常复杂的计算才能实现的视觉效果
例图是躯干前蔀,但是原理一样
PS3、360版在这么破的硬件上跑出这样的视觉效果,必须靠这种黑科技(耍赖开挂)的方式实现
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|