GAMES103-基于物理的计算机动画入门 - P4:Lecture 04 Rigid Body Contacts (Lab 1) - GAMES-Webinar - BV12Q4y1S73g
行吧,那反正反正差不多我们就先开始吧,然后呃今天反正呃四个事情吧,第一个事情是我们把作业先交代一下,因为今天算是我们的第一次作业嘛,嗯然后第二个事情是我想把我们上次我们讲的那个刚体模拟。
但是讲的比较时间比较仓促,就是尤其是我看到有一些同学呃好像没有上过大学物理吧,所以说我想把呃,但我们肯定不可能讲的很细,但是我想简单的把基本的概念给大家过一下,就是相当于有一个有一个基本的概念。
尤其是没有上过大学物理的同学,然后呢就是我们今天的一个呃话题了,主要就是讲这个呃缸体碰撞,我们今天主要就是呃来设计这一块,然后先给大家看就是那个作业嘛,哦对了,作业奖品大家都知道吗。
就是根据我们我们根据最后那个呃作业的完成度,我们会有会有奖品奖励啊,然后那个应该是在那个微信群里面就有个公告的,大家应该都看到了,然后给大家看一下那个最后作业做成是一个什么样子。
就是嗯到时候从那个从课程的那个微信群里面,应该大家可以下到一个呃小的一个程序,就是一个unity的一个脚本,然后unity脚本的话,如果说你直接运行它其实是没效果的,但如果说你完成了这个作业之后呢。
呃你运行这个呢,你就可以把这个兔子拿去撞墙啊。
就是比如说这样,然后你按l那个兔子就会撞到墙上,然后掉下来,然后你可以再把它继续做再重置啊,然后就继续,啊继续把这个兔子拿去撞墙,就是最后做出来是这样的一个效果,就线上的同学能看清楚吗,这个动画。
可以啊行,然后这个整个作业其实整个大环境unity的大环境都是已经搭配好了的,呃唯一你需要做的就是把这个脚本完成,就是我们这里到时候会有一个叫做rigid body,rigid body的一个脚本吗。
你的任务是把这个脚本完成啊,然后在这个脚本里面呃,其实我提供了一些呃比较基本的功能是需要你用到的,比如说怎么计算那个inertial矩阵,还有几呃,怎么样计算cross product matrix。
就是我们今天会课上会讲到的一些东西,其实这个脚本里都提供了的,所以说你不需要自己写,你到时候可以去看一下啊,这些功能,然后看看怎么样用到你的这个作业里面,当然你不用那个东西没关系。
如果说你自己什么都想自己写,也没有问题,完全可以啊,这是一个呃,这是这是basic task,然后还有一个高级任务,就是我们一个附加题,附加题呢就是呃实现力的呃。
就是怎么用一个叫做shape match的一个方式来做这个呃钢铁的模拟,那这个这个方式有什么特点,这个方式的特点就是它里面没有任何物理,就是尤其是可能对没有学过大学物理的同学,可能这是一个利好。
就这个方式它跟物理一毛钱关系都没有,他完全就是一个基于图形学,然后基于优化的一个方法,我们也会讨论这个方法,怎么样用那个呃呃这个shape match的这个技术来做模拟,然后呢这是一个附加题。
如果说大家完成这个附加题的话,会有三分,我记得好像是就是额额外的会有三分呃,然后你怎么用这个东西呢,就是你可以到这个default,你把你点这个default,这个default是把你的mesh吗。
然后你看现在我们用的这个脚本叫做rigid barney对吧,在这个地方呃,然后我把它关掉,然后用shape matching,你可以看到就是我重新启动一下啊,重新启动一下。
你就会看到就是用另一种方式去模拟的,就是你可以看到它是用另一种方式去模拟,但是你看这个方式它其实是有点瑕疵的,它它不像那个呃前面那种方式,就是它的整个缸体运动,它是比较在地面运动比较自然的。
就是接触的时候比较自然,他有一点轻微的滑动,大家如果仔细观察到的话,可以看到他最后停下来的时候,其实是稍微有点略带一点滑动的,这个本身是因为shape matched的这种方式导致的。
就是他在处理一些摩擦的时候,它会没有像呃直接做基于物理的那种呃接触的那么呃方式那么好,所以说我们其实今天也会讨论到这个问题,然后大概给大家看一个这样的效果,是这样子的,然后作业是呃两个礼拜。
就是大家有两个礼拜的时间去完成,然后呢呃其实总的来说作业的呃工作量是不高的,就是基本上就如果说你是知道怎么写的话,你知道知道答案的话,其实你呃大概知道怎么个做法的话,其实你一个下午绝对得搞定。
但是呢呃难就难在就是可能就是你不知道,就是说大概大概是一个怎么样的流程,然后或者是有些东西你可能想要进一步的了解,那么你可能需要去花一点时间去把这些文献可能都看一遍,这些东西是要花时间的。
然后对于呃就是之前没有接触过unity的同学来说的话,可能是需要花一点时间去把unity怎么操作的,也需要了解一下这个这个也是可能是一份额外的工作吧,就是尤其是可能之前没做过unity的同学。
那我就建议就是最近一段时间,最近几天可以先把unity下载了,然后起码就是把一些unity的简单的一些呃动画的一些脚本啊,它那个场景怎么搭配啊,这些简单的一些教程先给他看一下。
这样子你起码就是不至于说就是完全一头雾水,不知道从哪里开始,然后呢就是对于对于我知道,我知道有的同学可能是零基础嘛,没有任何图形学基础,但是也不用担心,就是无非就是说时间上花的多,花的少的区别。
就是不见得说就是有基础的同学就会相对来说完全更容易一点,零基础的呃更简单更难一点,不存没有这个存不存在这个问题,只不过就是呃时间上需要多花一点,大家之前有没有用过unity,有用过unity同学吗。
我看看不是很多是吧,有有什么问题吗,有作业这一块,我看看线上,线上没有问题啊,呃unity有什么教程,unity有什么教程,我记得你你去啊,你去搜一下,我记得有很多这种各种各样的教程,关于动画的教程。
基本上你看上两三个,基本上就是挺了解的了哦,或者到时候我可以叫助教,到时候也可以发一些教程给在群里面给大家供参考吧,然后有同学问作业可以用open gl写吗,可以用1a real写吗,可以的。
就是说如果说你自己像就是把这个框架自己写,这个完全没有问题,你也可以用open gl或者是unreal写,只不过这个环境什么的都需要你自己去搭配,可能可能花的时间就会更长一点。
这里的角速度是自己初始化吗,可以你可以自己初始化一个角速度,对然后公式都在ppt里,就是理论上就是ppt涵盖了所有你需要完成作业的内容,就是你不需要理论上是你不需要去参考其他的文献呢。
就所有的东西都在ppt里作业,不用约束,不会穿模吗,其实是有一点穿模的,只是不是不太明显,就是你会看到这个兔子跟地面,就是尤其是耳朵跟地面会有一些轻微的穿模,这个其实跟我们的实现方法是有关系的。
我们到时候今天嗯会慢慢会讨论到这些这些问题啊,这个不影响,就是,这个不会有影响,就是只要你完成的效果是一样的,就可以,好吧没有问题的话,我们就继续往下讲了,就第一个就是我呃。
首先我想首先我想把我们上次讲了什么简单的先回顾一下啊,就上次我们就是给了我最后的时候就给了大家这么两个算法嘛,就是分别对应的就是线性运动跟旋转运动的这两个呃方法嘛对吧,然后左边的这个线性运动就是基于利。
基于牛顿,这个其实跟大家高中物理学过的知识是对应起来的,就如果这个都搞不懂的话,我就建议大家回去把高中在屋里再重新看一下吧,呃然后他一个他这个怎么做呢,就是首先我们根据某一些呃模型,我们计算一个例啊。
对于每个顶点可能都有一个力,那么我们把这些例算一下,有重力有有,比如说用户给他砸了一圈,然后撞在这个兔子上,然后有什么有什么各种各样的力吗,我给他立先算一下,然后完了之后呢,我对力求和对吧。
我把总的力算出来,然后有总的力之后呢,我把那个我根据牛顿定律,我把力除以质量,再乘以时间不长,我就得到了对速度的更新,然后我就把速度更新了一下,然后有了速度,新的速度,更新过后的速度呢。
我把速度乘以时间不长,我得到了对位置的更新,我就把位置更新一下,这个其实就是呃基于咱们高中物理所学过的知识,我做了一个呃简单的一个呃兔子的这个平移运动的一个模型吧。
那么上节课其实这块讲的相对右边这块讲的相对来说比较少,因为呃有些嗯因为时间也比较短,然后我注意到可能大家有的同学可能对大学物理这块没学过,所以说我想把这一块稍微给大家回顾一下。
然后这一块其实跟左边这块其实可以对应起来看,因为左边是呃平移的运动,右边是旋转的运动,然后它左边右边其实都有对应关系的,那么首先第一个呢就是力,咱们左边的时候算的是每一个顶点的力对吧。
我们知道这个历是什么,历史实际上是造成这个物体运动的一种趋势吗,那么右边我们同样也有这么一个东西,只不过这个东西它不是力,它是例句,那么它这个例句呢是呃跟力很像,它是造成物体旋转的一种趋势。
那么公式在这里啊,那么什么是一个物体旋转的趋势呢,呃我觉得大家可以这么小,就是说假如说我有一个陀螺,我这边画了一个陀螺对吧,然后这个这个点呢是它的呃志鑫,然后这个呢是一个我施加力的一个位置。
然后假如说我现在在当前的状态上,我给这个点施加了一个这个方向的力,那么我就会把这个陀螺给转起来嘛对吧,就是大家就想就是我这样子从侧面去推这么一个陀螺,陀螺会呃旋转起来,会造成陀螺的旋转。
那么如果看这个图,看这个示意图,这个陀螺会以一个什么样的方式旋转呢,如果说我从陀螺的上面往下看的话,那么他应该会做一个类似这种样子的旋转,对不对,应该是一种逆时针的旋转。
那么在这里我定义旋转的这个例句的时候,也就是说造成旋转的这种趋势的时候呢,我需要考虑到就是它的旋转轴,这个实际上是我们在决定它的这个旋转方式,因为轴是旋转,对于旋转而言。
它的旋转轴就是相当于决定了它的旋转方式,那么这个力矩的大小呢就决定了这种趋势的大小,就是它这个旋转的造成它这个旋转到底猛不猛对吧,我们就我们就用它这个力矩的大小来描述它这个旋转到底猛还是不猛。
那么根据这种情况呢,首先我们可以看就是我们的旋转轴大概是这么一个方向,它是这么一个旋转嘛,逆时针的这么一个旋转模式嘛,那么我的旋转轴就应该是朝着这个方向的呃,那么很自然就大家会观察到。
就是说呃这个例句的方向啊,它跟我们的力,还有跟我们的这个向量,就是从智星到作用点的这个向量应该都是垂直的,这个当然我就不解释了,就是只是给大家一个直观的一个感受啊。
就是说这个旋转轴应该是跟这两个向量都是垂直的,那么这两个向量分别是什么呢,一个是利对吧,我知道是f i,这个就是利嘛,然后另一个是从志兴到作用点的这个位置,这个向量。
那么这根向量就是呃r大写的r乘以ri,那这里的大写的r呢是描述它陀螺当前姿势的一个矩阵,就是一个某一个旋转矩阵,然后我把这个矩阵乘以这个原来在参照物的状态下的这个笑料。
我就得到了新的从智星到作用点的这个向量的,所以说它是tall,是垂直于这个跟这个的,然后呢呃这里我知道了to的方向,力矩的方向,那么例句的大小跟什么有关呢,首先例句的大小跟这两个向量的大小都有关系。
嗯跟这个有关,很显然因为力越大,我的力矩越大嘛对吧,我力越大,那么理论上我这个产生的力旋转的趋势也呃更激烈一点,然后这个呢是从原点到作用点的距离,理论上我的作用点距离越长越远,那么我产生的力矩也越大。
因为这个就跟杠杆原理一样,我就是我我推的那个点,我跟中心的位置越远,那么我产生了旋转的那个效果也更明显啊,有个同学问,怎么理解这个r这个大写的r就是我们描述当前状态的那个旋转矩阵。
只不过之前我们上节课的时候,我们讨论用quaternion去描述这个当前的姿势嘛,然后一样的道理就是我们这两个其实是可以换算的,就是他俩都可以描述这个当前的姿势,只不过这个地方我用旋转矩阵去描述。
然后呢引擎内部呢我用quorian去描述对,就刚才有个同学就也回答了,就是这个ri是固定的,就是我们这个reference状态下的这个是固定的,而这个r呢是随着时间变化而变化的。
因为我们的cortne随着时间变化而变化,所以我们这个旋转矩阵也随着时间变化而变化,所以说这个最终我们这个食量也就随着时间变化而变化,好了我们现在知道了,说我们的例句跟这两个大小有关。
然后其次呢就是说它跟它的这个sin theta,也就是这两个向量之间的夹角,你有关系,就其实大家可以这么想,就是说理论上我的力如果是垂直于这个方向的话,是不是产生的旋转效果就是最最好的。
当我垂直于这个就像我一个陀螺一样,我当时当当我切着这个他的这个作用点推的时候,它是最能够让它旋转的,如果说我是朝着这个至新推的,那我就产生不了任何旋转,所以说我理论上我这个越接近于90度呃。
我越能够产生旋转,所以说它也是垂直于呃,跟这个sin theta是成比例的,所以说最终我们得到的一个公式就是跟他俩的cross cross product相关。
当然这个东西呢其实在那个我们在学大学物理的时候,其实会学到嘛,就是学旋转的时候学到例句,怎么计算例句的时候应该是会学到的,只是我相当于给大家一个直观的感受,跟这些呃跟这些东西是有关系的。
好我们接下来我们现在有了例句,嗯有同学问这个r是由f引起的吗,不是这个r是一个当前的一个状态,就比如说我这个呃陀螺是歪的倾斜的,那么它可能这个倾斜是之前的运动造成的,这个我不知道。
但是反正就是说当前这个状态下,我这个陀螺倾斜了,跟我的这个reference状态不一样了,那么倾斜之后呢,我怎么去描述这个倾斜呢,我就通过这个大写的r跟这个cturnal来描述他这个当前的这个倾斜的。
这个呃这个状态,然后呢我对有了例句之后呢,我对例句求和,我就可以得到总的例句啊,这个跟这个跟力的方式是一样的,咱们算力的时候也可以求和吗,我算例句的时候其实也是可以求和的,就把总的例句给算出来。
然后有了例句之后呢,我接下来就是要对小速度做一个更新了,那我们在算线性的时候,我们牛顿定律是力除以质量吗,对吧,那我们这边其实也很像,我对例句除以这个inertial,只不过这个我不是真的图啊。
为什么不是真的图,因为我这里的initial它不是一个一个常数,它是一个矩阵,那这个问题我在想可能有的同学就会问,就说为什么这里我不是一个常数,而是一个矩阵对吧,这是因为我们的旋转实际上是跟我的方向。
它的当前的状态旋转轴是有关系的,我这里给大家举个例子,就是说其实为什么是inertial,这个inertial其实就是一种对旋转趋势的抵抗,就大家可以想,比如说我施加一个力在这个兔子上。
然后想让这个呃兔子给转起来吗,那么我赢了,实际上就是在阻止这个旋转产生,或者我尽量让这个旋转变弱,那么假如说我现在有这么一个呃一个兔子对吧,呃我有一个例句,同样的是有一个例句。
只不过这个例句呢左边这个情况呢是朝这个方向的,右边这个情况是朝这个方向的,然后呢假如说我现在这个兔子,我在头部跟尾部呢都装两个很重很重很重的砝码,所以说这两个兔子你可以认为这两个东西非常非常重。
头跟尾都非常重,其他的地方非常轻,那么大家注意啊,这个例句首先大小是一样的,那么它们产生的旋转一不一样,就是旋转的这个大小幅度一不一样,大家觉得,那什么样左边的产生的旋转更猛一点。
还是右边的旋转更猛一点,是不是应该是右边的对吧,因为为什么,因为在右边这种情况下,它这个质量都集中在这个轴上面,所以说当我产生这个我施加这个例句的时候,左右边这种情况它产生的这个抵抗是比较小的。
所以说它的旋转会更快一点,更猛一点,而左边呢质量是远离这个旋转轴的,所以说它产生的旋转会更弱一点,所以说这说明什么,说明同一个物体啊,它能够产生的旋转不只是跟tall的这个大小有关。
它其实跟你这个套的方向也有关系,它产生的抵抗是不一样的,他这种抵抗它这个resistance就是我们所谓的抵抗吧,也就是这个ercial它是跟tall的方向是有关系的。
所以这就是为什么我们的这个我们这个eneral这个像他跟质量不一样,因为我们质量当我们在描述这个物体的质量的时候,它其实永远都是一个常数,它跟你这个力的方向是毫无关系的,对吧,而这个地方呢你的抵抗。
因为你的抵抗是跟这个to的方向有关的啊,所以说我们需要用一个矩阵,用一个inal tensor来描述它这种抵抗,这就是为什么我们不能简单用一个常数的原因,跟这个质量跟线性的运动有差异的。
原因就是旋转的一个比较特殊的性质,它跟状态是有关系的,它跟这个啊不是状态,是这个例句的旋转方式是有关系的,那么怎么计算呢,啊就是这么一个公式了,那这个公式来源我就不讲了,反正就是大家如果感兴趣的话。
可以去呃回去看一下大学,大学物理有这个计算公式吗,还是要到,那个上面也没有,大学物理可能没有,还真没有讲过,这个有讲过不同版本是吗,嗯是有可能的啊,反反反正不管了,反正就是如果说大家只要做作业的话。
就是看这个公式就行了,这个公式其实是就是抄照这个公式就行了啊,这个公式什么意思呢,就是说假如说我这个兔子上有一个点吗,那么这个点假如说是个小的一个呃呃小的一个采样点。
然后这个采样点上面有一个是有个什么质量对吧,这个我们叫做m i,然后呢这个点它对整个indual会贡献这么多,怎么算呢,就是首先我在reference状态下,从原点到这个点有一个向量叫ri嘛。
我刚才讲了吗,这个就是点到顶点的一个向量嘛,然后这个顶点向量它自身的长度的平方,这个东西就是它自身长度的平方乘以identity matrix,减去它自身乘以自身的转置,这个会得到一个举证。
然后这两个相减再乘以质量,然后最后呢把所有的所有的点给它加起来,这里可能有很多很多点嘛,我把所有的点根据这个公式全都加起来,我最终就得到了啊。
这个dual刚才我们说的这个indual test就是这个质量质量取胜啊,当然它不是真的质量,它是一个描述,它是跟质量很像的这么一个矩阵,我们拿来做对这个力的抵抗啊,这力矩的抵抗。
那这里大家注意到就是我这里下面有个下标,有没有,这个是r e f,第四个是斜体,嗯,嗯我看一下哦,对的对的是的,这里是一个type,应该是黑体,我这里这里有点小错误嗯,大家有没有注意到这里。
下面我下面给了个下标,reference就表示是在reference状态下算出来的这个inertial,那为什么这么写呢,是因为当兔子发生旋转的时候,这个in的时候其实会变。
这个也我觉得也相对来说容易理解,对不对,因为为什么会变,因为我这个向量的方向改变了呀,我之前我这个点它这个向量是2i对吧,假如说我这个兔子的姿势发生变化了,假如说我姿势发生变化了,那么他就不是r i了。
而是rotation矩阵乘以r2 了,那么因为我这个向量变掉了,如果说我继续按我刚才这个公式推的话,那我是不是我的inertial也也就变掉了对吧,所以说他这个initial举证了inal txl。
它实际上是跟兔子的姿势是有关系的,你的姿势改变,它的赢得时候也会变,那么有同学可能会问了,就是说我这个东西需不需要每次都重新算啊,我需不需要每次都按照这个公式把这个赢的时候重新算一次啊。
嗯好处好在我们其实不需要,为什么呢,我可以根据rotation矩阵的这个定义,我可以把这个公式给它简化一下啊,怎么简化,首先第一步我看这个是个rotation矩阵,这个是个rotation矩阵对吧。
这个是rotation矩阵的转置对吧,所以说中间一层是不是就抵消掉了,它变成identity了,所以我就抵消掉了,抵消完了之后呢。
我可以把这个rotation跟这个rotation transpose乘到左边跟右边去,为什么我可以做这个事情,因为中间它实际上就是一个实数,实数乘以一个identity matrix。
它其实本质上它就是个identity matrix,只不过用时速给放大了一下,那既然如此,我可以把这个时速挪到公式外面去,跟其实是不影响的对吧,公式里面放在外面是不影响它,本质上就是个identity。
那既然是个identity的话,既然是本质上就是个identity的话,那么我左边乘一个r,右边成一个are transport,它本质上还是一个问题,它本质不影响,所以说我可以对于这个东西而言。
我可以先把中间的这个东西给抠掉,因为它本质上就是identity,完了之后呢,我左边右边再乘以r跟r transpose,我保证最后乘出来的还是这个东西乘以identity。
因为这个乘以这个还是identity,这个rotation乘以rotation,transport还是还是identity,所以说我可以做这个事情,然后完了之后呢,我这边有rotation。
这边也有rotation对吧,我这边有rotation,这边也有rotation,然后这边有rotation transp,我这边也有rotation transpose。
那我就可以把这俩玩意儿给分别给抠出来,放到这个括号的外面,所以我得到了r还有r transport,这下我把它放到括号的外面了,然后呢我可以进一步的把它放在更外面,我就会发现这个里面这个东西啊。
再乘以i呀,它本质上就是i reference对吧,就是这个东西就是就是我们刚才提到的这个东西,那是什么意思呢,这个意思就是说,其实当我的这个兔子的姿势发生改变的时候。
我并不需要对于每个点我都还是按照原来的这个公式,我去把这个赢得手给算一遍,因为这样子算可能比较麻烦,我的点可能很多,计算量可能很大,那我可以把哦,对有的同学说这里多了一个r啊,说的没错,我觉得不好意思。
就多写了一个二,我可以把这个reference下的inertial先给它计算出来,然后呢我就把它当做一个常数了,然后当我真的需要用到的inal的时候呢,我只需要把这个i reference左右相乘。
这个这俩矩阵,我就可以得到当前的这个ineral的这个探索了,当然你如果说不怕计算量大,然后你真的就想每个点重新算的话,你会发现其实就算出来的跟你直接做这个简化的这个计算是一样的。
这个只是相当于就是我们有一个比较快速的,计算量比较低的这么一个计算方式,因为reference我可以事先算好,然后完了之后只要我做两次矩阵乘法,就可以把这个当前的这个inertial给得到了。
有没有什么问题,这里,没有问题吗,啊然后这个就是enoch关于inal这一块,我把inox算出来之后呢,就是根据这个公式,我把那时算出来之后呢,我就可以把它当做一个质量一样的,我可以把它求个逆,求个逆。
完了之后我乘以套,我就得到了对角速度的更新了,有同学问为什么把r消掉之后,又要乘在外面,沉在外面啊,因为乘在外面的原因是,因为我这样子就可以跟右边这个部分组合在一起,然后把它提到括号的外面去了。
当我这边成了r跟r transport之后,我这两形式就比较接近了,r transport对是的,因为因为它是旋转矩阵,所以说our transpose是他的逆,他俩是一样的,这个书写起来特别困难。
好然后我得到了这个得到了这个新的角速度之后呢,最后呢我就可以对cturnia更新一下了,然后呢这个更新方式呢跟我们线性的位置的更新也是一样的,呃然后呢就是我看到有的同学问这个东西到底是怎么来。
这个公式怎么来的吗,这个公式其实在我们上周的那个课后阅读的那个附录里面其实是有的,只不过他那个证明过程还是挺长的,大概有半页多纸啊,所以我就不讲了,如果大家感兴趣。
就想知道为什么就是为什么的同学可以去看一下那个附录,但是就是因为他放在附录里,所以说其实他本来那个那个教程,它其实也是假设默认假设大家就是不需要关心这个为什么来的啊,好吧,然后这个其实是我们上周学的。
我花了半个多小时吧,差不多讲了一下,我们上周学的东西,有问题吗,在在做的有问题吗,没问题啊,然后然后我们今天主要讲今天呢就关于碰撞这一块,我其实想分成三块来讲,就第一块我想讲就是说一个点。
假如说我只有一个点,我先不考虑一个刚体啊,最后一个式子的维度吗,这个是吗,这是quaternion,quaternion的话就是四维四元数,就是四个值,就是24的,但它不是真的思维,它是它是一个四元数。
然后我首先想讲那个呃想讲就是说一个点,就是先咱们先不考虑旋转,就只是讲一个点,我怎么去做碰撞,然后怎么去做碰撞的响应,然后我主要想讲分两个方式方法来讲,一个叫做penalty方法。
一个叫做impulse方法,然后呃我们会讲钢铁就是怎么用impulse的方法来做缸体的碰撞,检测跟碰撞响应,这个其实也是我们作业的要求,就是基于impulse的方法来做碰撞,做钢铁的碰撞。
然后最后我们会讲这个ship match的方法,这是一种比较特殊的,就是跟物理无关的啊,对没有学过大学物理的同学特别友好的这么一个方法,我们也会讲一下,然后首先来讲单点我们来怎么做检测和响应。
就这里我想引入一个概念,就是其实我们之前也讲过,简单的讲过一个概念,什么概念呢,就是叫做sign distance function,就是什么意思,就是说我定义一个函数,这个f函数啊。
它这个y函数呢它是一个距离函数,就是对于每一个点x他都告诉我这个点到某一个面的距离,但这个距离呢它不是一个单纯的一个正数或者是一个非负数啊,它是有符号的。
那这个符号呢就告诉了说我这个x他到底在这个面的内侧还是外侧,比如说我现在假如说我这里有个曲面歪歪扭的曲面对吧,那么我默认我假设上面这个部分是它的外面,然后呢下面部分是它的里面,那么对于每个x呢。
我都有个值,根据这个函数的函数值嘛,那么这个函数值就告诉我们他到这个曲面的距离是多少,同时呢我的符号也告诉我它是里面还是外面,比如说我这里这个外面这个点,它这个就是正的,他的距离就是正的。
它里面这个点它的距离就是负的对吧,然后如果刚好在这个曲面上,那它的值就是刚好等于零,所以叫做有很多有一些呃,有些文献把它这个就叫做zero surface,意思就是取零的时候产生了这个曲面。
那么根据这个定义呢,我其实可以用各种各样的数学公式来描述,一些比较简单的一些物体的表面,比如说我们在呃上上周的时候,我们不是讲过一些呃一些简单的物体,用一些公式去描述物体吗,比如说一个平面那一个平面。
我假如说我有一个p点是在平面内的点,然后n点是平面的normal对吧,我怎么用我刚我刚才这个定义去搞一个距离函数呢,而我可以用x减p dot n来描述我的距离函数。
那这个and呢这个normal呢就告诉了我哪一个哪一个方向是里面,哪一个方向是外面朝着这个normal的方向呢,我就把它叫做外面,我把它叫做normal方向,朝里的呢,我把它叫做里面,就是反方向。
反normal方向就是里面,那么对于x而言,如果说我定义一个向量对吧,然后如果说这个向量跟an是同侧的,那么它就是外面如果是非同侧的,就是里面那里面的时候它就是负的值,外面的时候就正在直。
就是符合我们刚才说正正的是外面,负的是里面的这么一个定义了,所以说它的距离函数就是这么写的,然后对于一个圆或者一个球而言呢,我可以计算一下x到圆心的距离,对吧,我口首先距离计算一下到圆心的距离。
然后再减去半径,然后呢这个东西呢其实就是一个到球面或者圆的这边,这个这个圆弧的这个距离函数,为什么呀,因为如果说我的距离是大于半径的,那我是不是就在外侧,如果说我的距离小于半径,是不是就在内侧。
那距离小于半径,那个减出来就会是一个负值,所以说它就在内侧,然后如果大于半径呢,它减出来是个正的值,就是在外侧,然后同时呢这个函数呢,同时这个函数呢也是圆心到这个表面的这个点的这个距离。
实际上也是到这个这个距离,实际上也是我们这个fix,所以说圆心的到这个语言的这个或者是这个球的表面的函数,我可以用简单的用这个距离减去半径的这个公式来描述啊,然后呢我还可以再扩展吗。
比如说这个稍微复杂一点,比如说我到一个圆柱的距离是多少,到一个圆柱的距离啊,我可以用到这个中心轴的距离减去半径来描述,那左边这个这一块,这个就是到中心轴的距离,然后这个是半径,我减去半径。
最后就得到了它这个距离函数,那我怎么计算到中心轴的距离呢,我这里其实我们之前课上没有讲,但是这个其实本质上就是个勾股定理,就假如说我现在写了一个画一个向量,从p到x的这么一个向量。
然后呢假如说这个x到中心轴的最近点在这个点对吧,假如说这是它的最近点,那么这个距离是不是就是从x到这个点的距离对吧,因为它是最近点嘛,那它的距离就是它到它的距离,那么这个是最近距离。
也就意味着是个直角三角形,直角三角形也就意味着我可以先把这个斜边算出来,斜边长算出来,再把底边长算出来,然后斜边长的平方减去底边长的平方,开个根号就可以得到这个直边长了,那么也就得到了这个距离了。
那么斜边长是什么,斜边长是p减x减p的长度嘛,所以就是x减p的长度的平方,然后底边长是什么,底边长是减p在方向上的投影,所以就是x减p dot m对吧,这个是他的投影,所以我就得到了底边长。
然后这个也开个这个也搞个平方,这样也搞个平方,然后最后我开个根号,我就根据勾股勾股定理,我就得到了到这个点的距离,然后最后减去半径,这个就是它的一个流程,这里是吧,哦对对对是对,你说的很对,哎。
这字体老是容易搞错,其实这里也应该是不要黑体字,这应该是斜体字,大家大家很敏感啊,嗯,好这个就是其实就是呃给大家一些基本的概念,就是根据呃各种各样嗯嗯基本的这些几何形状嘛。
我可以根据一些数学的一些解析的方法,我可以把这个函数搞出来,在现实生活中,咱们有很多物体,它不是一个曲面,它可能是好几个曲面拼接起来的对吧,那怎么把这些距离函数搞一个组合呢。
那我这里就需要用到一些布尔操作了,比如说我假如说我有个小扇子扇醒,然后呢,我这个扇形是怎么搞出来的,它本质上就是一个球面或者一个圆,跟两个直线或者两个平面相交构成的,对不对,它实际上是由三个。
所相交产生的,那么这三个面我其实就有三个距离函数,分别对应不同的曲面,就比如说φ零,我就是这个圆,fine一跟fire就对应这两条直线,那么我怎么来把这个组合起来,然后来做这个距离函数的定义呢。
那我可以首先看一下是什么样的情况,这个x是在这个相交的这个状态内部的,因为这是相交,我是不是要求说我这个x必须在所有的这些面的内部,因为它是相交构成的吗,所以说当当我所有的距离函数都是小于零的时候。
对吧,才是在内部的,这就是相交的这个情况,我怎么来判断是内部还是外部,我利用他们用and这个这个条件语句,就是这个逻辑语句,那么我这个距离函数是什么呢,我这个距离函数就是它们的最大值,为什么是最大值。
因为我这个点到本质上就是到这个面的距离,到这个扇形的轮廓线的这个距离,那他到这个表面的距离是不是就是到最近的那个曲面的距离对吧,因为所有的值都是负的,也就是最接近的那个曲面,所以说我就是用max。
我可以来把这几个这三个这个距离函数组合起来,拼成一个距离函数,那么反过来如果说不满足这个条件,他就是在外侧对吧,就是不满足的话,那么就是显然在外侧,那么这个距离函数是什么呢。
有的同学会想是不是还是max呢,其实不一定了,它其实不一定了,其实如果是在外侧的时候,它这个距离函数有可能跟这个甚至跟这三个函数都毫无关系,但是好处好处在于什么,就是如果说我们只是为了做碰撞检测的话。
我其实并不关心这个距离函数是什么,其实只要我知道在外侧,那么我知道碰撞没有发生,那么这个也就无所谓了对吧,所以说这就是一个好处,就是我可以把这个东西忽略掉,当它在内测的时候,我就用max来做这个检测。
这是他的一个相交的一个状态,那么跟香蕉所对应的另一个可能,那就是它的优点,它的它的合并起来的,它叫什么丙级对吧,那么假如说我有两个球,然后呢我假如说我这两个球呢组成了同一个物体,我想要做香蕉检测。
我怎么做,我怎么来判断它是在这个点是在内侧还是外侧的呢,我不用and了,这次我用all对吧,如果说它小于零或者它小于零,那么就意味着x在必定在某一个球面内,那么这个时候呢就是内侧在在里面了。
但这个情况下有一个小问题,就是说什么就是我这个函数就组合出来的这个距离函数,有可能跟这个范琳跟f一都毫无关系,比如说我这里给大家举个例子,假如说这个这个点x在这个相交区域的比较靠中心的位置。
那么这是φ零,这是f1 ,他们的最近点分别是这里跟这里对吧,但事实上最近点是哪里,重点是这里,对不对,所以说有可能这两个值非常小,但是它实际上到表面的距离是非常远,这是有可能的。
所以说这就是为什么我们只是用一个约,等于就是假设我这个点是比较靠近这个实际的外侧表面的时候,啊,啊这个其实还是比较接近的,但是呢我不能说这是一个正确的一个符号。
不能说等于只是说在表面的外表面比较靠近这个,比如说在这里的时候,就是在这里的时候,我可以认为这个是比较接近于它的值,只是一个近似,然后反过来它就是在外侧的情况,这个时候呢如果是用mini的话。
那么它是等于的,在外侧的时候你可以用mini来表示,这就是香蕉,利用香蕉和利用我的这个交集跟丙级,我们可以对这个距离场来进行一个组合的方式,呃,具体的话就比如说给大家举个例子。
比如说啊比如说一个呃一个正方形对吧,正方形它实际上是由四个边组成的嘛,一个立方体它是由四个面六个面构成的嘛,圆锥对吧,它是有一个一个锥的面,还跟那个底面构成的嘛,就是类似的。
就是我可以根据根据各种各样不同的组合,把这个拼起来,然后对于丙级,其实大家也可以这么想,就是说你其实可以把它认为是两个物体,然后呢你分别对这两个物体做碰撞做处理,然后其实也可以认为是一种操作方式。
然后分别做碰撞检测的话,其实本质上也是一样的,然后这个给大家简单的讲一下这个呃碰撞检测是怎么做的,但是这个这个这个这里面的例子都是相对来说比较简单的,我们回头其实还会有1~2次。
就是专门来讲碰撞怎么处理的,就是讲更复杂的情况,我们怎么处检测碰撞,然后更复杂的情况我们去处理碰撞,这个反正的话我们就简单的先给大家给一个粗略的一个概念,就是我们可以利用这个距离函数我们来做判断。
那么好了,就是假如说我现在有了这个距离函数了啊,啊我做碰撞检测也就容易了对吧,我就只要去看一下这个它是正的是负的就行了,负的呢啊我知道它有碰撞,我就知道没碰撞,那么我就ok但如果负的话。
我就需要对这个碰撞做一个处理吧,那么怎么做处理呢,那就有两种两个基本的套路,一个套路叫做pale,这个什么意思,就是说我首先检测一下有没有碰撞,有碰撞,完了之后呢,我就给这个点施加一个力。
我想把这个点从我们这个物体里面给推出来,这就是一个简单的penalty的模型,那么这个力怎么来定义呢,一个比较简单的方式呢,就是像弹簧那样,我认为这个力的大小跟这个就是这个这个这个进去的这个距离有关。
我进去的越深,我这个力就越大,我进去的越越浅,我的力就越小,所以说这个叫做chaotic penalty,因为它的能量是个chrc形式,它这个力是一个一个线性的形式,那么力的方向是什么。
力的方向就是这个距离函数的gradient,其实就是它的normal,就表面的normal,那我们之前讲过点,什么叫规定的gradient,就是怎么样让这个函数变得变大的一个最好的方向吗。
那么这个方向也就是说朝着这个方向,我可以让这个函数最快的变大,那么是不是也就是normal方向啊,就当我沿着normal推的时候,我是能够最快的这个x给推出来的,那就是normal方向。
所以说我这个normal方向也就是gradient,然后我这个力的大小呢是负的,distance函数为什么是负的,因为这是一个在内侧,在内侧的话,它其实这个距离是负的,所以说负的前面加个负号。
就让它整个东西变正了,因为这个距离在内测的时候负,所以说我这个公式写下来就是乘以这个fix乘以n,然后这个k呢就是我的这个我们叫做paly强度。
碰撞强度嘛就是这个弹簧的本质上这个弹性系数把这个塔给推出来了,这个方式它有一个什么问题,他这个问题大家会注意到,我这个力才会起作用,如果这个点在外面,它其实是不起任何作用的,那么如果说掉进去了。
也就意味着它这个碰撞其实这个穿透已经产生了,那么我必然就会有,对不对,我本身就会有穿透的这种这种这种瑕疵,在我的这个动画里面,那我能不能预先对这个点做一个处理呢。
那么一个简单的想法就是说我可以加一个宽度吗,我不要说我穿进去了,我再给他加里,我可以事先设一个距离范围,比如说我这个假如说我这个东西有一个小的厚度对吧,我叫abc了,然后呢。
这个物体只要调到跟表面在abc的距离范围内,我就给他加力,那么我这个怎么来计算呢,我首先怎么来做这个检测呢,我首先就不是小于零了,我是小于s了,只要小于p4 ,我就认为碰撞已经产生了对吧。
那么小于b c之后呢,我其他的东西都一样,我还是说我的方向是这个gradient这个方向没变,就是还是沿着gradient的方向,只不过我这个对于我这个距离函数而言呢,我前面多了个app了。
然后呢这个就是到艾普斯龙这个表面的这个距离就是ap减去fx了,就不是原来的这个负的把x了,而是减了,那么这样子的话,我就相当于我对这个点做了一个预防措施嘛,就说我不要求说它穿透了。
我在家里只要他靠近物体表面,我就给它加个力,把它给推出来,这个就是实操里面一般来说大家会用的一个套路,会会给他一个小的一个缓冲空间,利用这个缓冲空间,我把这个物体推出来,但是即便你这么做还是有问题。
这个有什么问题呢,跟这个k有关,这个实际上是决定了我们这个力到底有多大的一个很关键的一个因素,如果说你这个k小,那么我当我物体很猛地撞进去的时候,我我就没有办法把它给推出来,就是他会还是会继续往里走。
然后直到这个力足够大了,它才会把它推出来,因为我这个k太小,那么有同学想了,既然k太小不行,会导致这个物体走得太进去对吧,太多是不是可以把这个k搞得超级超级大也不行,为什么。
因为如果说我这个k超级超级大,也就意味着当我模拟的时候,可能当前的时刻,假如说我当前时刻在这里没碰撞,ok那接下来我模拟了一下,比如说跑到这里来了,然后因为我这个k超级超级大。
导致我这个产生的力也超级超级大,那么下一个时刻会发生什么,这个点可能就飞到这个屏幕的外面去了,加飞到这里去了,因为我这个k会可能会过大对吧,这个东西本质上是因为我们在施加这个力的时候。
会有一个叫做overshooting的这么一个问题,当我这个力过大的时候,会有这个over shooting,就是说它这个飞得太远,飞太远的问题,那么怎么来避免这个问题呢,就有一个思路是这么想的。
就是说可不可以不要用一个常数的k,我可不可以把这个k也搞成跟距离的一个产生关系,当这个距离越来越接近的时候,我把这个k越来越大,越来越大,甚至于把这个搞成无穷大。
那么是不是我就可以阻止这个这个这个力不足或者是力过大的情况,那么这个思想呢就是这么一个思想,就叫做log barrier function,这个log barrier这个名字呢。
其实大家可以首先看这个函数是什么样,就是这个我就不开,我就不用k表示,就是用这个肉,这个肉是一个也是一个强度函数,然后呢它是肉除以这个fbx乘以n,这个n是方向吗,这个an是方向,方向没变化。
然后强度呢是肉除以发x那么当这个点他无限的靠近表面的时候,也就意味着我这个力无限的变大对吧,因为这个相当于距离无限小,那么总的力就无限大,如果说这个物体这个点没有很靠近表面的时候。
那么这个力相对来说就会缓很多,所以说它本质上就是利用这个距离到这个物体的距离,到这个表面的距离,可以定义这么一个函数来,来根据我这个实际的距离来不断地放大我这个力的大小啊。
不是简单的单纯的用我们之前用一个线性关系,我现在用这个倒数导数的这么一个倒数的这么一个关系,来定义这个函数,lol function为什么叫log barrier呢,因为这个力可以认为是能量的一个导数。
这是一个log函数的能量的一个导数,fx大概是这个样子,前面好像有个负号吧,是有负号吗,啊有的,具体怎么样,我有点不记得了,反正就是你对它求导,你会发现大家记不记得对log求导,它就会变成log分之一。
就是变成这个东西分之一嘛,一个道理嘛,就是你把这个东西对它求导之后,你就会发现它就会得到这么一个力的方向,这就是他的一个基本思路,就是我可以利用利用这个方式啊,利利用这个呃这个这个这个倒数的方式。
我来定义这个力的大小,然后这个其实这个方式呢就是想的挺好的,但是事实上他还是有蛮多问题的,一个问题就是说其实它也是还是会避免不了over shooting的这个问题。
如果说你这个位置很靠近这个点的表面的话,这个力还是会变成很大很大无限大,还是会overshoot,第二个问题,第二个问题是,如果说他真的穿透了,大家想会发生什么,它会越陷越深,它这个力会错误。
他这个力的方向会他反而会往里走,他会越陷越深,所以说这个方式呢它其实有个前提条件,它是假设这个东西是永远不可能发生的,也就是说穿透是永远都不可能发生的,那么怎么避免穿透,永远都不可能发生呢。
那我就需要用小布长,我需要保证每次呢都往前挪一点,每次都往前挪一点,那么每次的点这个量呢不可能产生穿透,那么这样子的话,用这个方式是可以保证它可能穿透的,但是呢也就带来了很多额外的成本。
就是说我需要用利用小步长来实现,有同学问那个强度怎么调参数,一般来说这个就是个常数,一般来说大家不调这个这强度其实跟就是这个力的衰减的速度,这个程度有关,它其实跟那个大小到没有很强的关系。
他只是跟衰减的程度有关,实际操作中呢有啊就是关于paly呢,有一些有一些简单的回顾一下吧,首先基本上你都需要去调整补偿,调整步长有很多目的啊,就比如说你需要避免over书听。
需要考虑到这个你需要避免穿透在log barry,你用刚才刚才这种log的方式的话,你需要避免穿透,然后最近最近这12年其实有有有一些paper吧。
就是怎么样对log barrier方式这种方式再进做一做进一步的改进的,就比如说我跟log barrier再跟一个buffer加在一起。
就是可以让这个log barrier不不需要就是产生无限的赢影响力,我可以把这个影响力稍微限定一下,然后呢如果你做penalty的方式呢,一般来说做做摩擦会相对来说比较困难一点。
这其实也是它的一个呃一个局限性吧,它也有好处,也不能说它完全不好,它一个好处就是它还是比较容易实现的,因为本质上就是你算了一个力对吧,你算了个力,然后再把这个力加在这个点上。
然后呢就利用刚才我们之前讲的正常的模拟方式,把这个力加在点上,然后根据这个力算各种这样的旋转的角速度也好啊,然后最后就产生模拟小度,本质上本质上就是这么一个过程,同学问显示积分跟影视积分哪个方式更好。
肯定是影视积分更好,对于这个问题而言,其实肯定是影视积分而已而言更好,但是有的时候大家不见得一定会用饮食积分来处理这个碰撞问题,一般来说大家有的时候会对于碰撞问题,大家都会用比较简单的显示来来。
所以说就会存在一些不稳定就overshooting,本质上也是因为不稳定的问题造成的,然后这是一个简单的方法给大家就是稍微简单的介绍一下吧,然后呢我想想看啊,然后是第二种方法,叫做in pose的方法。
impulse的方法其实跟pa的方法有一个很大的不同,in完我们刚才讲in penalty的方法呢,就是说发生碰撞之后呢,我给它施加一个力,对不对,大家注意到施加的这个利益,它不是马上起作用。
是要到下一个时刻才起作用的,也就是它这个效果是滞后的,那么in pos的方法就不这么弄,方法就是想说我不希望我这个碰撞是下一个时刻的起作用,我是现在马上立刻我就要产生效果,那么这个就叫in方法。
简单地说就是说当碰撞检测到了之后,我希望速度跟位置都马上更新,怎么做呢,首先我还是做检测对吧,我首先对x做检测,如果说它小于零,那么我知道这个点落在这个表面的内部了,碰撞发生了。
那么我现在呢假如说我现在想要对位置做更新对吧,那么我怎么更新位置呢,想把这个点挪到这里来,表面点,那么这个表面的这个点它没有碰撞,它在这个表面上,这个点也是距离我们原来这个位置最近的这个点。
那么这就是我的目的,那怎么算呢,就把这个x沿着normal方向移动这么多就可以达到了,那么我就做x6 等于x加上距离的绝对值乘以normal方向,这个是移动的方向,是移动的长度,那绝对值是什么,绝对值。
因为它是负的嘛,所以说就是减负x normal方向等于它的gradient,也就是gradient fbx就是就是这个东西就是x减去fbx乘以它的,利用利用方向跟距离,我可以得到这个点的位置的更新。
那么对于点而言,相对来说比较容易处理一点,那么还得处理它的速度啊,对不对,因为当碰撞发生的时候,不只是说我把它推开来就完事儿了,速度肯定也要发生变化,当碰撞产生的时候,我这个冲量。
我这个冲击我肯定会影响它的速度,接下来看怎么样去改速度,尤其是我怎么样把摩擦也给它考虑进去对吧,首先我们要检测一下速度,首先我们要看这个速度是不是还继续往下的,因为有可能速度已经更新过,已经往上的了。
如果说速度已经往上,已经跟normal方向是同侧的,我就不需要再处理了,这里其实是要做一个检测的,就是说我要判断一下是不是速度,还是继续想要让这个物体越陷越深的对吧,那我这里要再做一个额外的检测。
就是v dom小于零的这么一个检测,如果说我速度继续往下走,那么我把速度分成拆成两半,一个是法向上的速度,一个是向上的速度,分成两个部分,那么这两个速度分别可以用v n陈妍。
就是他在normal方向上的投影,然后这个是投影在normal方向投影,然后这个是乘以normal方向,这个就得到了normal方向的分量,v减去van呢就得到了切方向上的分量,就切平面上的分量。
就首先我把它速度拆成两部分,一个是normal的部分,一个是切平,然后接下来假设normal方向上的分量跟切方向上的分量,我都乘以一个系数,这个系数首先这个normal方向的系数是负的。
这个mu呢是这个mm呢是它的反弹系数,为什么加个负号啊,因为当物体撞在一个表面的时候,它会反弹嘛,所以说它产生了新的normal方向肯定是相反方向的,就本来它是往下掉的,产生碰撞之后它会往上反弹。
所以说这就是引入了一个负号,然后mn呢它是一个系数,弹性系数就等于零跟一之间嘛,超过一,因为我希望能量守恒,我不希望他的速度反弹了之后,速度还比原来大,所以说一般来说就是零跟一之间的这么一个弹的系数。
那么a呢是我的摩擦造成的向上的衰减,我先不考虑它,我先假设有这么一个系数,然后我得到了两个新的之后呢,我把这两个分量加在一起,我就得到了新的速度了,这个就是一个简单的流程。
就是先把它拆成两半方向跟法方向,然后分别做修改,然后完了之后重新组合在一起,我得到了新的速度,好我们现在接下来回过头来看这个a这个a应该怎么算,首先我的a是希望它越小越好的,因为对于摩擦而言。
永远都是希望速度降得越大越好对吧,我a永远是希望这个a越小越好,我尽量能够把这个切方向的速度给给它衰减掉,我能够想到什么样的程度呢,这个a我们假设它要满足一个库伦定律,库伦定律说了个什么事情呢。
就库伦定律说的就是说你切方向的改变,一定是你法向上的改变乘以某一个摩擦系数,t6 减v t是什么呀,根据刚才我们这个a的定义,我们就得到了一减a乘以v t的绝对值,然后normal方向上的变量是什么呀。
就是一加mm乘以van的绝对值,根据我们这个vi 6跟这个vn定义前面乘一个系数,那么我把这个公式整理一下,就可以最终得到了这么一个公式,就a等于这个部分。
这个部分是根据我们前面那个胡克定这个库伦定律所得到的,他这个a它最小最小,当我想要这个a足够最小最小的时候,肯定是这两边相等的时候,那么什么时候相等的,就是这个东西除以这个东西在被一减嘛。
所以说这就是他得到的另一方面,这个a不能比零更小,所以如果说这个a小于零的话,也就意味着这个切方向的速度它反转了,我们知道摩擦力它只能让这个速度变成零,尽量变成零,尽量不够小。
但是摩擦力它不会让前方向的速度反转了,所以你说我这里就是有个跟林要取一个最大值,是这个利用这个公式,就这前面这部分是根据我们的这个库伦定律,我们希望a足够小的这个尽量小的这个定义。
我们可以得到这个零呢是根据摩擦力不可能反转前方向速度,我们得到的这个值就我们就得到了,这个a是根据这个公式计算出来的,这两个其实对应两种不同的摩擦形式,左边是就是取左边的值,那么就是动摩擦。
取右边的值就是静摩擦,就是简单的一个呃,根据我们根据物理的一些摩擦的一些公式,我们可以搞到一个摩擦模型,大概就是这么一个形式,大家有什么问题没有,什么叫为什么可以做建模策,你想如果a等于零的时候。
这个切方向是不是就等于零了,那么也就意味着所有的切方向的,就是的时候也就意味着他这个摩擦力其实可以很强很强,但是我们在摩擦力再强,它也只能让物体停下来,也就是意味着我们就最小就只能取零嗯对。
你觉得应该怎么直观的好吧,然后有同学问这个方法还是上一个方法好,这个方法能做什么改进吗,这个impulse的方法它一个比较好的方法,好的点就是在于它可以比较精确地控制摩擦压力和反弹的位置。
就比如说像你看刚才像现在这个公式嘛,我们可以我们可以精确地控制摩擦效果,比如说我想要做静摩擦效果,我想要这个物体,那它就必然能停下来,但如果做penalty的方式的话,你就很难做到精确的控制。
就有的时候你会看到这个物体它会有一些轻微的穿透,因为你很难保证这个物体完全没有穿透,保证这个物体完美地停下来,而硬泡的方法它就比较容易能够确控制,这个是也是它的一个优点,那么经常见到见到第一种方法。
本质上还是因为第一种方法就是penalty的方法,简单的方法它其实呃虽然说对于点而言会比较容易处理一样,但是有很多情况下in pose的方法它其实处理比较麻烦的。
所以说有的时候大家不愿意用in post方法,大家更多的会考虑用penalty方法,这个方法更简单一点,稳定的参数嘛,就是这个参数是吗,这个一般来说是由用户来来自定义的,这个是自定义的。
一般来说是用到哪个,更多的话,一般in pose用的挺多的,我见过挺多的,然后如果是衣服或者弹性体的话,一般penalty方法会更多一点,相对而言,为什么后面要再乘一个n,是因为如果说你点成完了之后。
这个是一个标量,点是一个标量吗,但是我这个vi它实际上是一个矢量,所以说我需要把它的方向再给他乘上去,是的,你是指呃物理世界吗,其实物理世界其实本质上其实还是一个penalty方法。
就是本质上为什么我们会有碰撞,本质上是因为分子和分子之间会有互斥嘛对吧,分子的这个影响造成的,所以说本质上其实是一个py方法,但不不过现在我们在做penalty方法的时候,他其实并没有办法做得特别完美。
它总归会有很多瑕疵,所以说会很来处理,真实是物理的世界里面,摩擦实际上是由表面的不平整造成的,但是我我们在3d建模的时候,我们没有办法考虑到表面的那么多不平整的因素。
所以说我们需要用各种各样的数学模型去近似它,导致物体撞墙面的局部变形吗,嗯你说哪种方法是不是in pose还是,如果是做谁对,我们等会会讲一个shape match的方法。
到时候会会看到这么一个方法会讨论到的,如果是弹性体的话,是有可能的,钢铁的话不会,现在咱们时间也有限,咱们就先先提问的环节先到这里,然后我希望能把讲一讲,因为后面东西很重要,咱们做做作业需要用的。
首先就是先讲一下,还是先讲一下缸体的这个碰撞吧,还有碰撞响应吧,就这块先过,就首先对于我们这个兔子而言,怎么做碰撞检测呢,我们首先可以计算每一个点的位置,每一个点的位置等于它至新的位置。
从智星到这个点的这个向量,就是我们前面也讲到很多次了,就是r大写的r乘以r i这个点的位置啊,每一个每一个表面点点的位置等于加上智星到这个点的向量,所以就得到了x如果说我要做碰撞检测,我应该怎么做。
我需要把每一个点的位置都算出来,然后遍历一遍,看这个点是不是落在这个曲面的内部,就是利用咱们之前那个fx小于零这么一个公式来,我检测就够了就可以了,当然说对于呃平面而言呢,我这个就比较简单了。
我可以根据这个呃平面的这个方法方向啊,还有根据平面上的这个点的位置,我可以把这个很方便的定义出来,然后我可以做检测,当然之后检测方式并不是一个特别完美的检测方式了啊,我们回头会讲更高几点的。
复杂一点的嗯,对多边形多多面体做检测的方式,但是咱们对于兔子而言,我就来一点,我对每个面,每个点我都计算它这个点的位置,然后跟这个公式,我把点的位置算出来做检测就ok了,这个就是检测的部分。
接下来我们来讲这个碰撞响应的部分啊,碰撞响应呢我们首先来看一下这个速度啊,因为我们碰撞响应里面有一块会涉及到它的速度,我刚才讲知道了,就是说这个点的位置是x y嘛,是x加二乘以ri吗。
那他这个速度是什么点的速度呢,至新的速度,这个v是至新的速度,omega就是它的这个旋转的角速度,product cross product这个点到这个点这个质心到这个点的向量为什么是cross product。
omega,change in cross product,这个其实也是大学物理应该讲到的讲到的东西,那他可以其实可以直观地想,就是说假如说我这是我的旋转轴的话,假如这个omega是我的旋转轴。
那么我根据右手定则,我是朝这个方向旋转,那么我会产生我这个旋转,我旋转会在这个点上产生一个朝这个旋转轴,跟这个旋转的这个轴跟这个都垂直的这么一个方向,这个方向它跟这个轴垂直,同时也跟它这个向量垂直。
所以说它就是一个cross product,我没办法讲太细,这个如果说大家没有学过大学物理的话,可以稍微读一些,这能读得懂吗,就参考一下吧,就是就是参考一下有一些教科参考文献吧。
就是基本上反正就是说我这个点的速度,就是可以根据这个东西算出来的好吧,那么好,我现在有了这个点的位置跟这个碰撞点的速度,那么是不是我直接可以用impulse的方式对这两个点做修改,不行。
因为这两个点这两个点的速度跟这个点的位置,它实际上在我们的模拟状态是不存在的,在模拟缸体的时候,记不记得,我们只有四个变量,分别是治心的位置至新的速度。
还有旋转轴的旋转轴的旋转的这个姿势跟旋转的角速度吗,我们对于每一个点而言,它的这个位置跟他的速度其实都是不存在这样的变量的,所以说我这个修改这个值。
我这个刚才前面我讲的这个in pose的方式去修改它俩的值,这是没有意义的,我改了也是白改了,对不对,怎么办呢,那我本质上我实际上我不能够去修改这两个值,我应该去修改我整个兔子的四个变量。
分别是x b q w q omega这四个变量吗,那我就去修改它,这里呢我还想再偷工减料一下,就是说我不想去修改它的位置跟状态,我只是去对不做一个冲量。
然后呢我希望我这个速度的冲量能够让这个兔子最终被推出来,那其实我对这个前面的这个impulse的方式也做了一个简化,这个原因呢本质上还是因为呃对钢铁而言,如果我直接去对x跟q做修改的话。
它会相对来说比较麻烦一点,所以说我对速度来跟速度和角速度做修改,它会相对来说比较容易一点,其实我们后面再讲约束的时候也会讲到,但是现在就反正就假设我现在只想只想修改,跟这个这是我的最终目的,怎么做呢。
我假设我现在有一个我假设现在有个冲量,然后这个j我是未知的,我不知道这个j是多大的,但是我先看一看这个j加了之后会发生什么啊,如果说我冲我施加了这么一个冲量g之后呢,我的速度呢会变成这个新速度。
这个v6 就是我的新速度等于老的速度加上冲量除以质量,这就是牛顿也是牛顿定律嘛对吧,冲量除以质量等于速度的改变量,omega呢也会发生变化。
omega呢新的omega新的角速度等于老的角速度加上inverse乘以,那这个东西是什么,这个东西实际上就是我的冲量造成的力,去根据我们之前我们例句的计算公式,我其实还是做了同样的计算。
就是这个cross product的例句,这个冲量就得到了这个对吧,再乘以这个这个inverse,然后把它加上去,有了这个新的速度跟新的角速度之后呢,我可以把新的这个点速度给它算出来了。
这个这个点上的速度是什么,速度等于线速度v6 ,omega new product这个东西,这个公式实际上就是我们算点速度的公式,就是我前面就是这个公式,我只是只是相当于我把这个新的速度跟新的角速度。
我给它替换掉,我就得到了,我就得到了这个公式,我现在得到这个新的点速度了,我整理一下对吧,我根据上面的公式给它替换一下,那就是v加上这玩意,然后再加上这个东西替换吧,大家大家回头看ppt。
可以自己自己可以看一下,再整理一下啊,继续整理,怎么整理呢,我把这个我这就是v还有这个omega给他合一下,因为这个v加上omega乘以这个cross这个r i是原来的这个点速度嘛。
就是原来这个点速度嘛,原来的点速度再加上这个东西就得到了新的速度,然后我再给他整理一下,我把这个这个cross product这两段换个位置,当你有两个向量,你做cross product的时候。
你把它前后换个位置,它前面等于加个负号,这个公式到这个公式其实就是多了一个负号啊,多了一个负号,然后我把这个位置跟这个位置给他替换了一下,就后面的跑到前面的,前面的跑到后面了,就是我做了一个事情。
接下来还想对这个公式做简化啊,但是我怎么简化呢,首先我不希望出现cross product这个东西,product的这个东西它其实没有办法跟取证啊,合在一起在于什么。
好处在于cross product的东西,它可以转化成一个矩阵,我们叫做cross matrix,就给大家一个,一个新的定义啊,叫做cross product。
就是cross product这个东西可以写成矩阵的形式,怎么写,我有一个向量,我are cross q对吧,那么按照定义它是这个东西吗,prosperate定义吗。
你完全可以把这个r cross这个玩意儿给它写成一个矩阵,你会发现如果用矩阵向量的这个乘法,这跟这个东西是一样的,左边这个东西跟这个东西是一样的,是等价的这个东西,这个矩阵呢我把它叫做二星号。
我就把它叫做cross cross parametrix,本质上就是我用一个矩阵,我去表达一个product,那这样子我就可以把cross product用矩阵乘法的形式给它替换掉了。
这是一个数学里面的一个小套路,这套路我可以把刚才我们刚才我们这里不是有两个cross product吗,可以利用这个套路,我把它给替换掉,我就得到了啊,这个东西保留不变,减去这个星号。
这就变成一个矩阵了,这个玩意儿就是一个cross product,取证了这个东西也是一个举证了对吧,这里就变成了三个矩阵相乘了,就变成了一个矩阵乘简单的矩阵,矩阵乘法的一个形式了,我再给他整理一下。
再给它整理一下,就得到了什么,得到了,就是v i6 减去v h等于一个矩阵乘以impulse,这个矩阵怎么计算啊,这个矩阵计算方式呢就是一乘以identity,这个东西从哪里来,这个东西从这个地方来。
因为原来是除以m乘以,那如果说我把这个东西前面加个identity,本质上是一样的对吧,我把这个一用identity来替换掉,是一样的,后面这个玩意儿是个矩阵,所以说就变成了i除以m减去后面这个矩阵。
那么我把它给它给它取了个新名字,我把它叫做k这个就是我这里这个k矩阵这个东西有点乱啊,就是但是反正就是给大家简单的就是讲,就是通过我最我最终这里的目的是什么,我这里你的目的就是说我告诉大家什么呢。
就是当我有一个冲量的时候,当我在这个点上施加了一个冲量的时候,会从这个点的速度发生改变,对不对,这个速度的改变量,这个点上的速度的改变量是一个矩阵k乘以这个冲量,这个是可以算出来的,是已知的。
因为这些量变量其实都是已知的,这个j呢这个冲量是我们所不知道的,好处在于什么,好处在于,如果说我能够把这个想要产生的这个速度给它计算出来的话,因为我们本身做in house的方式。
做in pose的方式就是想要这个点上的速度,那可以根据我们之前那些in pose的套路,我可以把这个点的速度给它修,我的话我就可以利用这个公式,我就可以把这个冲量给它算出来。
只要本质上就是我之后只要把这个东西前面乘个k inverse,我就可以把这个in pose给它算出来对吧,算出来之后呢,我就可以再分别的对v跟omega做更新了,刚才有同学问,就是说这个冲量呃。
造成力造成例句怎么理解,就是你可以把这个冲量想象成可以想象成某一个时间乘以一个例吗,t是一个是一一个标量,一个一个是一个时速嘛,你这个力会产生例句对吧,力产生的例句不就是相当于这个例在这里吗。
所以说其实就是我们之前我们模拟这个呃,就是计算那例句的公式,我无非就是相当于我把这个力的部分用这个冲量去给它替换掉,就是可以让它产生力矩,但实际上它这并不是真正的例句,它实际上是例句乘以一个时间。
某一个时间量就是在一个很短很短很小很小的时间,它会对这个速度,其实整个公式其实跟我们之前算那个啊啊,这个公式其实跟我们之前算力矩的公式其实是一样的,无非就是把这个j把这个利用这个j去替换掉。
还有什么问题吗,这个推导过程我是希望大家就是课后能够再看一下的,因为这个确实也公式比较多,可能就来不及,就是细看,但是反正简单的意思就是说,冲量的时候我会造成这个点上这个速度的改变。
产生点的速度的改变之后,我可以利用这个关系,我可以把这个j给它算出来,用v和v6 来求j是吗,我有一个g的时候,我会把这个我会把这个相当于我把这个v跟我们一改都更新了,那我omega更新之后呢。
我自然我这个vi也会变新的了吗,i更新了之后呢,我就会看这个到底会产生多少的变化,我会把这个vi你跟这个vi做个比较,然后这个就是它产生的变化,利用这个变化,我会构造他们他们俩之间的关系,这意思。
就本质上就是说我其实并不知道,其实并没有办法去直接修改这个东西,我想要修改这个东西,但是我没办法,那我我要去修改这个东西呢,我利用这个j去修改它,怎么样去找到这个j呢。
我把这个j跟这个他俩的关系我给他构造出来,就是我其实就本质上我推导了这么多,我其实就是想把这个j跟这个i的关系给他搞出来,会发现他这个东西其实就是k乘以j,vi的改变量其实就是做了这么一个事情。
我就发现其实他俩实际上就是一个线性关系,是一个矩阵的关系,就把这个k算出来,我再把这个delta v i算出来,这个vi可以根据我们之前做那样的那个速度的那个公式,我给他算出来。
然后呢我就把impulse算出来,其实就是一个间接,其实本质上这个方法就是一个间接的过程,就是之前我们算方法的时候,我可以直接去修改这个bi,有个小问题,就是我不能直接去修改这个vi。
这个vi是通过跟omega搞出来的对吧,这个是这个vi是通过v跟omega搞出来的,我怎么样去修改vi呢,我得修改v嘛跟omega嘛,那么就利用这个v跟omega呢。
我间接的我把这个j in pose跟vi的关系给它构造出来,其中我构造出这么一个线性关系出来,我我想给他大家看一下算法,因为可能大家这里有点懵嘛,我给大家看一下算法。
这个通过这个流程看看是不是能够把这个思路理得更清楚一点,把这个分成几个模块,首先第一个模块,同学问是先算vi,就我给大家先看一下算法吧,看完算法可能你就清楚了,这个意思就清楚了,先。
那我去对于每一个顶点,我都把每个顶点的位置给他算出来对吧,我去检测一下它是不是有碰撞,我这个三distant function我去检测一下是不是有碰撞,如果没有碰撞,就任务完成,有碰撞呢。
第一步呢去把这个顶点的这个碰撞产生碰撞,这个碰撞点的这个速度给它算出来,然后呢我去判断一下这个顶点的这个是不是还继续,说还是在继续往下掉的,还是想要继续穿透的,那需要进一步往下处理是呢。
我知道说我这个顶点已经想要离开物体表面了,那么我就ok,但还是继续往下掉,就要把这个vi 6给它算出来,算vi 6呢,我根据前面我们算冲量的这个方式对吧,我把这个分成两部分,首先我把它分成法向量方向。
还有切向量方向的两部分,然后呢我把这个a算出来,关于摩擦的这个系数算出来,然后我得到新的这个normal方向,然后得到新的tan的方向的速度,然后最后我这个vi 6给它算出来,这个其实就是咱们前面呃。
对于一个单个质点我怎么记,就算他这个冲量造成的这个v i6 的这么一个方式,然后我现在把vi就算出来了,然后我就用灰灰色的字颜色来表示,为什么我用灰色的,因为这个东西是不存在的,这个只是个中间变量对吧。
它是中间变量,也就意味着我更新它是毫无意义的,实际上应该更新什么呢,我应该更新v跟欧米伽,我应该更新跟角速度,那我怎么更新呢,我用冲量去更新它,前面讲了这个冲量跟我这个v i6 的变化。
实际上是一个这个线性的关系,所以说这个k我先把这个算出来,我根据前面咱们这个公式,我可以把这个算出来,然后k算出来,完了之后呢,我k inverse乘以这个这个点质点。
这呃这个这个小点上的这个速度的变化量,我就得到了这个重量了,所以说这个就是对于钢铁而言,我计算它冲量的方式,重量之后我回到这个v上,然后我这个v呢利用这个冲量除以m呢,我就得到了新的b啊。
我用利用刚才我们之前的那个公式,我就得到了这个欧米伽,就是这么一个过程,就是先把bi 6得到,先把这个中间变量得到,利用这个我们的这个质点的这个碰撞的方式,我把这个东西得到完了之后呢。
我利用我们之前这个冲量跟速度变化的这个关系啊,我把这个冲量给它换算出来,那要冲量之后呢,我利用这个冲量实际的物理的这个公式,我把这个速度跟给它,计算出来,大家听明白了没有,我在想,下下一页会讲。
这个反正就是大家回如果说不明白的,就是大家回头再想一想,就是说这个大概的基本套路是什么,然后为什么我们要算这个东西啊,因为本质上就是这实际上是个中间变量,我们没法没法去修改这个空间变量。
因为改了也是白改嘛,那么我就要利用这个冲量,我去把这个东西给它估计出,然后利用这个重量,我对速度去进行一个修改,回到刚才这个这个同学问的问题啊,就是说这里面其实是有一些实现的细节的。
就比如说假如说我有好多点对吧,我不是一个点有碰撞,我有好多点碰撞,怎么办,嗯,我们这里可以稍微做一个简化啊,就是我要取他们的平均值就够了,我只要把这些点的位置的平均值给它算出来。
然后利用他们位置的平均值,我做碰撞,碰撞处理,就是他们位置的平均值,当然你也可以试着就是说看看,就是所有的点都去做碰撞,但是我这里就不建议,因为呃有可能会导致它那个冲量过大。
这里的话我会建议用他们的位置的平均值,这里其实应该加一个position,啊嗯还有一个小问题就是呃你有的时候会发现它有的时候停不下来,为什么,因为我始终有一个呃重力在这个物体上。
重力会导致它速度永远都是有一个往下走的一个量,那么产生这个量之后呢,我的冲量又永远都会把它反弹一下,所以说当它在这个物体表面,在这个平面上的时候,它会反复地震荡,这个叫做抖动oscillation。
建议就是说呃大家可以做一个判断,就是当你发现这个物体开始就是静止下来的时候呢,你可以尽量的把这个东西变小,就是相当于这是一个小hack嘛,但是大家可以尝试这个东西,就是可以听上去衰减这个抖动。
就是如果说作业你如果不做这个事情也不要紧啊,但是就是从美观的角度来说,大家可以做这么一个小hike啊,来避免这个抖动的这个小问题,同学问,处理这么多点运行是不是会非常慢,其实不会,这个呃。
因为我我们处理这么多点,其实只是为了检测的时候需要处理这么多点,当你计算碰撞的时候,就是前面这个公式,前面这一页的时候,它其实只是对单个点而在处理的,为什么我们想要取平均值的原因啊。
那我们这里啊为什么不去更新位置对吧,因为首先这个对于位置更新而言,它其实这个问题会复杂很多啊,它是一个非线性的问题啊,我们回头讲约束的时候,我们会再会提到这个处理方式,但是我这里就先略过不讲了。
这一页我也不觉得这个稍微有点复杂,就是多个多个物体之间呃,如果说有多个物体嘛,三个兔子的话,那么就有三个接触点啊,也有三个不同的impulse,那么这个它就不是一个简单的问题,它变成一个信息系统了。
但这个我就暂时不讲,给大家有个概念吧,就是当多点有接触的时候,这个问题会相对来说更复杂,因为它彼此之间会有影响,这个我们上次的这个pp,上次的这个课后的阅读也会讲到这个东西,就是大家就继续,反正读上。
如果说上次没读完的话,可以继续往下读啊,会讲的这个这个其实应该是after碰撞会讲,会讲一些就是关于碰撞冲量的东西,还有一点还有20分钟,我给大家简单讲一下,这个就是shape match嘛。
就是这个附加题这个概念前面我们讲了很多就是关于物理的东西啊,对吧,什么例句啊什么的,手转动你的手啊,还有这个什么角速度啊,乱七八糟的讲了很多很多关于物理的东西。
然后呢这个shape match它其实就很简单,就是他换了个思路去考虑这个问题,就是其实假如说我其实对这个钢琴一无所知,我其实根本就不懂大学物理,我没上过大学物理,那我怎么办。
那我是就想一个很简单的事情嘛,就是假如说我有对吧,假如说我一个方块,我是四个点构成的方块,先假设这个点它它这个物体它不是一个钢铁,我就假设他这每一个点它自己都可以运动,它每个点点都有自己的速度。
每一个点都可以跟物体做碰撞,可以跟物做摩擦,那我就之前我们的这个in pose,质点in pose的方式我都可以处理了嘛,那我简单的做一个处理就完了嘛,那在阶段其实我就做一个非常非常简单的呃。
多个质点的一个模拟,一个po粒子系统对吧,我先先给这么个模拟一下,先模拟这么一步,接下来呢我给他变回一个杠七,是不是就可以让它产生一个钢铁模拟的效果啊,简单地说就是让每一个点都自己动,各种各样的。
你自己动,动完了之后呢,我把它这几个点再给它锯回去,给它重新让它组合成一个钢体,这个就是他这个ship match一个思路,就是说我他自己模拟,然后完了之后给他聚回去,就是让它重新变成一个钢铁。
这个过程中呢最重要的是第二步,就是怎么样让它重新回到一个缸体的状态,前面其实就是做一个简单的例子模拟,没什么可讲的,怎么样实现第二点,这个就是shape match的一个关键点来做这个事情。
我有一个点叫why why i,假如说我现在想要把它去回一个方这么一个形状,那么之前它这个位置是y对吧,然后通过我进行这么一个缸体的这个约束,我可以让它变到,这个c就是智星啊,我之前用x。
不过现在我改成c了,智星加上一个矩阵乘以r i嘛,这个r i就是他原来的那个reference下的状态嘛,这个其实跟之前的公式是一模一样的嘛对吧,那么就是我得到了这么一个共识,是什么意思啊。
就是我希望这个进行约束了之后的这个点的位置,能够跟原来的这个位置约束之前的这个位置足够接近,我希望这个点的位置是足够接近的,但另一方面c这个质心的位置跟这个旋转的这个rotation的这个旋转。
这个举证啊,我是不知道的,这就变成了这个跟这个它是它是未知量,它是已知量了,你这么想就是说假如说我这个点每个点都自己动嘛,自己动就变成了这么一个奇奇怪怪的这么一个梯形嘛对吧,那么变成了这个梯形之后呢。
我想把它给收回去,我把它想,我想把它收回一个方块的形状,那么收回的这个方块的形状呢是通过这个c跟这个二去描述的,那么想要找到这个中心点,至心点跟这个旋转矩阵,这俩是变量。
那么同同时呢我希望这个收的过程呢能够让每一个点啊,这里可能有四个点啊,这里所以说这里就是求和,我希望每一个点都能够跟原来它那个梯形的位置足够近,这样子它相当于收的不至于说收的特别的差异特别大。
我还是尽尽量希望这个收能够跟原来这个梯形能够足够接近的,但是我又希望它是一个方块,因为我原来它就是一个钢铁,它本来就是个方块嘛,所以说我胸c跟这个二去描述的,这就是他这个数学的定义是这样的一个形式。
变成了最后就变成了这么一个优化问题,就是我希望找到这个c跟这个二,这是我的变量,那么去怎么去找这个东西呢,对这个问题再稍微做一些放大,就是我希望这个r不要是旋转矩阵。
因为正常情况下我这个缸体是旋转矩阵嘛,我这个r是一个任意的矩阵,这个可以让我的问题简单很多,我就把它放大放宽了一下,就是问题放宽了一下,我让这个这个这个东西变成了一个任意的矩阵,我把它叫做a。
这个目标函数呢就变成了这么一个函数,就是c加a乘以2a减去y算了,那可以利用求导吗,因为优化问题本质上就是要求它的,让它一阶导等于零嘛对吧,对这个目标函数对cc求到了,那么就得到了括号。
把这个求和里面的东西对对这个对c求导,那么就得到了c加,就是括号里面这个东西c加a乘以2a减y,还有其实就是对c嘛,对c自身求导,那么就是identity matrix那个就消失掉了,所以说你对它求导。
就是里面就是这个东西,大家会发现这个东西其实等于零,为什么求和等于零,为什么,因为a是一个常数矩阵,对a乘以2a求和就是对a乘以求和i就是就怎么写,不太好写啊,这个东西求和,我写的比较丑。
等于a乘以2a,等于零,因为这智星是在reference状态下,它的质心是零点,所以说它的中心点是零点,所以说对于所有的点都求就等于零了,所以说这个东西自然就取消掉,对掉了,得到了c减yi dai。
整理一下就得到了c等于yi求和处理比较容易理解,直观上怎么理解呢,直观上理解就是说我之前的中心点,约束之后的中心点应该是同一个点啊,是说它的质心是一样的,大家能理解这个意思吗。
就是我之前比如说这四个点是个梯形中心,至今在这,那我约束之后把它变成一个钢铁之后,它的质心应该还是在这里,执心怎么得到呢,就是对于每一个顶点,我取它的平均值,把这所有的点我对它做一个平均值求和。
再除以它的数量,得到它的平均值,就是它的执行点,算他的志心,我就得到了c,得到a怎么算a呢,我接下来想要对a,倒了对吧,我c已经得到了,我对a求导,那么对a求导d d a对它求导对吧。
那么就是c加上这个东西,减y就是整个东西,然后a求导,那么就是把i transport提到右边去了,等于这个其实都是我们之前讲的那个ta calculus嘛,就是本质上就是对取证或者对向量求导啊。
实际上是一回事情,大家如果这块不是很熟悉的话,其实你可以一个那的方式就是把整个公式展开了,把xy z全都展开了,然后呢你自己去对于xyz就求导,然后看一看推出来,你会发现就是这么一个形式。
但是反正因为咱们时间有限,我也就呃这里就不展开了,就是反正大家回去可以有时间可以去试一试,然后得到这个之后,你再对a整理一下,你最后就得到了这么一个公式,就是可以对a啊,然后a是一个矩阵吗。
它不是一个矩阵嘛,那怎么把这个a变成一个旋转矩阵啊,啊我可以做一个polity composition pol,就是你可以把一个矩阵拆成两部分,左边这个部分是旋转的部分,右边这个部分是一个对称的矩阵。
我们把它叫做形变的部分,那么这个旋转的矩阵就是对应了我们想要的这个旋转矩阵,就是我算出来a之后,我再把这个r当做我们做一个polc competition,我最后就可以得到这个旋转矩阵,为什么啊。
为什么这个旋转是这个意思,我这里给大家一个直观的感受的吧,之前讲过我的一个性格,composition,可以把一个形变,一个线性形变分解为三个部分,这个大家记得吗,就是分别是旋转缩放跟旋转。
里面呢你可以注意到前两个旋转啊啊前两个形变,就这个旋转它其实是想决定了什么,决定了我这个,方向,比如说我这个方块我想要沿着这个45度角做缩缩放,我怎么做,我先把这个45度角转成我的这轴方向。
然后再做分方,我如果说对她整理一下的话,就是我这边回去的话,就是这里乘以v穿这里乘以v,然后这里乘以uv transpose的话,那这里大家可以看到就是中间啊,我乘以transport v的话。
其实是不影响我刚才这个s b d的本质上是一样的对吧,因为中间乘出来matrix v是旋转矩阵嘛,可以看到前面这个部分是什么,这个东西发生了什么,发生了什么事了,就是他在本地做了一个形变,形变是什么。
是沿着我这45度方向做的一个形变,对不对,我是本地,我就实际上对他做了一个缩放嘛,那我我想要的是45度的缩放,那么我这里就是对45的缩放,我先转45,然后缩放转完了,形变完了之后,我再给他转回来。
转回45度,那么这个东西本质上就是在他本地local给他做了一个形变,这就是为什么说我这个s我如果把它叫做s的话,这就是它的本地形变,而前面这个东西呢就是全局的一个旋转。
本地的这个坐标系到这个世界坐标系的一个旋转,这就是为什么我可以把这个s扔掉啊,保留这个rotation的原因,因为我其实做钢铁的时候,我是不希望它有本地的形变的,缸体理论上不应该有本地形变。
所以说我直接把它扔掉,我保留那个旋转的那个部分,我就可以得到它旋转的分量了,意思怎么做polar decomposition这个东西呃挺麻烦的,但是呢这个在我给你给你们的这个就是package里面。
这个里面我给你这个代码了,反正大家用这个函数就完了。
我怎么写的这个东西我怎么写的,我其实是抄了这篇这个paper里面有讲到怎么做这个polar decomposition,怎么样快速的对3x3矩阵做polo,但是我这里就不展开了。
反正就是大家如果说想对附加题比较感兴趣,想要尝试一下的话啊,可以就是用我给给大家的这个代码里面的这个polc composition,来来对他做做一下分解,pol是唯一的,是的是唯一的。
是unique的,我这里写了吗,唯一,我感兴趣可以把这个paper读一下,我觉得还是挺有意思的。
这个流程是什么样子的啊,我用每个点我都让他自己自顾自的模拟吗,我就不管了,我就每个点都自己模拟,我自己有自己的力,我自己也有自己的质量对吧,我根据牛顿定律,我就每个点都自己有自己的速度。
甚至每个点都有自己的速度,每个点都分别对自己的位置做一个更新,我得到了y,之后呢我就根据我这个刚才我们这个公式,我就把这个c给它算出来,这个c跟a分别就对应的这个质心的一向量跟这个矩阵的呃。
相这个线性的变换的矩阵,然后呢我调用我们之前那个函数,我给你提供的这个函数,我做polly competition,我把这个矩阵给它抠出来啊,那我就把速度跟位置做更新,更新回去,那么速度是等于什么。
这里的速度我是用新的位置,这个实际上我是想要更新得到的新的点的位置啊,是这里新的点的位置减去老的点的位置除以德尔塔t新的速度,这个这个我就不细讲了,反正就是我可以利用这个东西做一个更新。
就是根据两个位置的差除以时间,时间的变量,我可以反向的计算速度,然后得到速度呢,我对位置做更新,这个代码呢就是刚才有个同学问,就说你们你写什么,就其实我只提供了这个东西,这个东西是我提供的。
剩下的都得你们自己写,就你们要把你们要负责把这个简单的例子写,然后你要把这个就是这块也需要写,然后这块其实都是需要写,速度不一样,形状不是会发生变化吗,这个同学那刚才没仔细听啊。
就是这个其实就是这个算法的目的,就是我先让每个点自己变,然后形状发生变化之后呢,我再给它把形状给它变回去,就是我把这个缸体的这个啊缸体的质心跟缸体的旋转给它算出来,然后把这个缸体变回去。
就是先让他自己随便形状随便乱变乱变,完了之后我给他约束,给他强扭回去,就这个意思,这个shape match,呃paper的话,这是一个就是它的优点,就是我们来讨论一下。
就是这个方法为什么要用这个方法吧,就他这个方法有一个什么好处,就是它比较容易实现,因为它本身呃里面没有任何物理对吧,大家可以注意到什么力距角速度什么什么这些东西全没有,然后呢。
其次呢就是它跟一些点的模型,它是比较容易能够结合在一起的,比如说衣服的模拟,还有的模拟,还有流体的,甚至那种粒子法的流体模拟,这个其实都很容易结合在一起,这是他一个很好的优点。
因为这些引擎这些模拟方式都是基于点的,所以说只要把这些点都是按照这种点的方式模拟就行了,其实也可以,啊它的缺点在于什么呢,缺点在于你很难严保证一些约束,比如说我摩擦的一些约束,我很难保证。
而且你这这种约束的方式,你很难保证所有的约束都满足对吧,当你进行一个约束的时候,你可能会把前面的约束给破坏掉,所以说你很难能保证大家都满足,你可能需要迭代的方式去反复的去进行约束。
所以说这个东西就是它的一个缺点嗯,一般来说咱们什么时候用啊,就是当你比如说一些碰撞啊,什么摩擦,这种精度要求不是很高的时候,比如说咱们模拟一件衣服嘛,然后衣服的上面可能有扣子。
或者是比如说你模拟一个皮带嘛,那这些东西这些钢体它可能跟其他物体接触,它不是很频繁,他可能就是偶尔会有一些接触,或者是他们这种接触可能不要求很精确,那么你可以考虑用shape match的方式来模拟。
每个顶点都会有自己的位置跟速度,刚才有个同学问每个顶点是不是有位置跟速度,是的,而且他都会有自己的自身的利,这个是shape match它的呃最早的一个论文之一嘛。
然后其实你可以看到它这个paper当当初他其实是用来做形变体的,但是他也提到了说我可以拿这个方式来做刚体模拟,就是这个方法也可以用,大家如果有时间的话。
可以去读一下这个来参考一下这个ship match的方式,然后今天时间就差不多了,有什么问题我看一下,这个附加题嘛,附加题就是如果说大家这里啊尝试,有时间有余力的话,可以去尝试一下这个方法。
就是paper里面就是讲他他如果做软体的话,它可以慢慢的恢复成那个钢,就是那个有目标形状,它可以不一下子恢复,但是我们如果说钢铁的话,就是给它瞬间恢复成原来的形状,就是钢铁模拟啊,咱们是有助教的。
我是想我是下周如果说有时间的话,可以安排一下答疑,就是如果说大家作业上有什么问题的话,可能会可以安排一下答疑时间,但是我暂时还没有定,到时候跟下周大家实际完成的作业,完成情况,到时候再看吧。
的话没有问题的话,咱们今天就到这里,然后大家如果没有碰unity的,或者是就是对unity了解不深的,大家可以先把unity先试一试,然后对作业可以先可以先玩儿起来看看好吧行。
GAMES103-基于物理的计算机动画入门 - P5:Lecture 05 Physics-based Cloth Simulation - GAMES-Webinar - BV12Q4y1S73g
行我们那个我们就开始吧,今天我们主要讲的就是相当于是一个新的一个话题啊,我们上周还有上上周主要是讲了缸体这一块钢铁的模拟这一块对吧,那我们基本上就告一段落了啊。
其实关于钢铁还有很多其他呃延伸出来的一些话题,比如说我们可以做articulated body,就是类似人体骨骼动画这样的东西,那这个的话呃因为跟约束相关,所以说我们其实也会专门有呃。
有一节课是来讲约束的,但是那个话题咱们就暂时就告一段落,然后呢我们嗯在最早的时候我其实说过嘛,方法上也好啊,然后这个讨论的话题课题也好,所以说呃可能有的同学可能不是很关心钢体这一块,其实也没关系啊。
接下来我们会讨论几个啊,不同的话题,就比如说今天我们主要讨论的这个课题,就是关于衣服模拟这一块,布料模拟这一块,那布料它这个东西它其实跟头发的模拟是有一定的联系的。
因为你可以把布料cross这个东西它想象成因为一个二二维的一个面,在三维中展开的一个状态,那头发是什么样的,头发是一维的一条线对吧,它跟在三维中展开的一个状态,所以说它其实是有一定关系的。
但是头发的模拟它其实又有自己的特点,因为它有的时候他会考虑到自身的一些旋转,就是有的时候它会用那种类似螺旋线的模型,所以说呃相对来说它就比较特殊一点,所以说我们这里其实也哎不往下讨论。
主要还是以呃讨论这个比较通用的这些cross怎么样去model class,怎么样去similate class,那这个class simation其实也是相当于是我的一个老本行。
我做了蛮久的这个这方面的工作啊,然后呢我是想把这个东西分成三节课来讲,三个礼拜来讲,咱们第一天第一天就今天我们主要讲物理仿真模拟,怎么样根据呃能量,然后呢根据这个力的模型,然后推导出呃衣服模拟的方式来。
然后下一周我们会讲约束,就是可能大家比较呃经常听说过的游戏里面用了很多的ppt,我们会下周我们会讨论那个东西,然后我们也会讨论projective dynamics。
就是基于p p t在延伸的跟物理模拟相结合的一种方式,然后我们还会讨论专门一种就是用来处理约束的,叫做constraints dynamics,所以基本上下周我们就是围绕着各种各样的约束来讨论。
怎么样让约束跟模拟相结合,然后最后一周我们会讨论碰撞,为什么要在这个时刻讨论碰撞呢,因为衣服的碰撞其实是最难的,布料的碰撞其实是最难的,你如果能够把cross的碰撞处理好,实际上你做其他模拟的碰撞。
相对来说都会容易很多,所以说实际上我们就这里就我们就重点就想cross怎么处理碰撞的,然后他这些类似的方法你会看到都是可以用在其他的碰撞处理上面的,然后我们会专门讨论这个东西。
当然重点其实关于cross的,我们重点模拟本身呢,我们是头两周,然后最后我们来讨论碰撞好吧,然后今天我们大概是这么一些呃话题吧,但是不一定有时间能够全部都讲完,如果没讲完,咱们就反正就延续到下一周。
首先我们来讲讲弹簧,首先讲假如说我用弹簧去描述一个面料,一个cross呃,我怎么样模拟它对吧,我有两种方式,分别是基于影视的积分,显示的积分跟基于影视的积分,我们来看看这两种方式我们都是分别怎么做的。
然后呢我们来讨论弯曲这个东西,因为对于面料而言,布料而言,它的弯曲非常重要,很多时候我们来判断一个面料它到底是比较挺的还是比较软的,很大程度上都是从他这个弯曲造成的褶皱上来判断的对吧。
那么我们就会讨论到弹簧的弯曲模型,它其实并不是一个很合适的模型,那么还有没有别的模型呃,我们会讨论其他模型,然后类似的我们还会讨论就是弯曲,它在模拟的过程中,它会有一些问题叫做locking。
也是我们也会讨论啊,这些这个问题就是给大家相当于提个醒呃,然后咱们在最后的那就是如果有时间的话,我们会讨论,就是我们上周不是讲了shape match吗,然后这周我们会讲shape match。
就是类似的想法,我们其实也可以拿来做啊,面料的模拟,所以说我也会我们也会简单的讨论一些其他的不基于弹簧的啊,模拟方式啊,其实有很多东西我们跑到后面有限元的时候,我们其实还会讲的更细一点。
但是反正这里就先给大家介绍一个新的方法,那我们先从弹簧讲起啊,呃一个理想的弹簧,这个是咱们在学物理课的时候,学初中物理,高中物理的时候就学过的,就一个理想的弹簧,它是满足胡克定律的对吧。
那么胡克定律他说了一个什么事情呢,胡克定律它本质上就是说弹簧的力它是试图恢复原长的同时呢,它这个弹簧的力跟拉伸的长度有成正比,那么假如说我现在假如说我现在有一根弹簧。
是一个只考虑一个很简单的一维的情况啊,那么弹簧从拴在这个原点,然后弹簧当前的位置是x,那么也就意味着这个弹簧的长度是x对吧,那假如说弹簧的原长是l,那么我这个弹簧的能量。
弹簧的能量就是1/2 k乘以x减l的平方,那这个k呢就是它这个弹簧的弹性系数,这个k然后x减l呢实际上就是我的这个形变的量,就是我这个弹簧被拉了多少,然后我平方一下乘以这个弹簧系数除以二就是能量。
那么力是从哪里来的呢,力是负的,能量对位置的导数,那么能量对未知的导数是什么呀,如果我根据这个定义的话,我会发现我对x求导,那么二跟二抵消掉,我就得到了负的k乘以x减l。
这个其实就是符合我们呃中学时候学物理,它直接给的,一般来说就直接给了这个公式嘛,但是你会发现它其实力跟能量,它其实就是一个简单的啊导数的一个关系,前面加个负号,然后导数的关系,这个是个一维的情况。
那么以此类推,我也可以拓展到二维或者三维的情况,然后这个其实咱们之前呃也讨论过,在我们在第二节课的时候,我们讨论那个数学求导的时候嘛,我们不是用这个东西举过例子吗,啊这里就是给简单简单的给大家回顾一下。
就假如说我有一根弹簧,我连接了两个点,分别是i跟g,然后这根弹簧的原长是l的话,那么我的能量就是二分之k然后这个k呢还是弹性系数对吧,然后乘以呃拉伸量的平方,那拉伸量是什么呀。
拉伸量就是弹簧的长度减去它的延长嘛,所以说这个就是能量的公式,那同样的我的力就是能量对点的位置的求导,那么因为我这里有两个点对吧,我有一个矮点,也有个g点,我有两个顶点,那么也就意味着我分别有两个力。
然后前面加个负号,那么之前我们推过公式,我这里就不重复了,就反正就是负的k乘以这个形变量,然后再乘以这个方向normalize一下,然后也是同样的公式可以推出来,然后呢呃因为牛顿说牛顿他说这个呃。
如果你把这两个顶点加成跟弹簧认为是一个系统的话,它的总的力应该是等于零的对吧,他的这个它是这个作用力跟反作用力吗,所以说f i就等于f j,然后这个大家从这个公式上也可以看到。
这个是刚好是两个是力是相反的,这里我就不细细的就展开这个是怎么过程的,如果说大家呃不太记得这个咱们第二节课的内容,或者是就是呃就是没上第二节课的话,可以回到第二节课的那个最后的呃p p t上。
大家再把这个推导过程再给他看一下,但简单的说就是我把能量有了能量之后,就可以得到两个相对应的力了,就分别作用在i跟j上,这个咱们反正之前就已经讲过了,那么有了这个模型之后对吧。
我们有了这个简单的一根弹簧的模型之后呢,我就可以构造一个呃更复杂一点的模型,比如说我有多根弹簧对吧,那多根弹簧怎么办呢,那么根据物理里面我们所学过的知识,能量和力,它其实是可以叠加的。
那么假如说我这个假如说我这个顶点i它连接了另外四个顶点,然后分别有四根弹簧把它们连接起来,那么我相对应的我就有四个能量对吧,分别是101112跟e3 ,我把它们全部都加在一起,然后呢根据我公司的定义呢。
它这个能量每个能量都是啊他们所相对应的这个能量,然后把它全部加在一起,这个就是d e dx,然后这边有个transport,这个就是梯度的导数嘛,啊这个就是梯度的定义嘛,这个我们之前讨论过。
那么同样的我这个力也可以通过所有的力加合,我把这么多所有的力全都加在一起,那么这个总的合力就是作用在x点上的这个力了,这个就是根据简单的物理加和,我可以把能量和力加在一起。
那么实际的生活中我们是实际的模拟中,我怎么去构造这个网络呢,呃有不同的方式啊,呃有一种方式我们之前也讨论过,就是一个结构化的方式,结构化的方式怎么构造网络呢。
我可以假设说我这个面料这块布它是由方方正正的这些格子所构成的,那么假如说我一个用一个比较正比较一个正规的一个网格来描述的话,那么我分别每一个啊,每一个交叉点就是一个顶点对吧,这个节点。
然后呢我又分别有横的弹簧跟竖弹簧,我有两种弹簧去描述这个面料,它在横向跟纵向上的一个形变,同样我也需要有一些对角上的弹簧,因为这个事我会防止呃,面料它在斜的45度的方向上,它会有一个拉伸。
那么我需要构造类似这种方向上的弹簧,我可以防止斜45度,斜45度上的拉伸对吧,然后两个方向都有,一个是斜45度,一个是斜的135度,我都需要,然后呢再还可以构造什么呢,再还可以构造的一种叫做弯曲的弹簧。
那弯曲的弹簧的意思就是说这个弹簧它有可能会呃翻折嘛对吧,如果说我没有这个弹簧,你可以看到我这个弹簧是可以沿着这个这条线自由的翻折的,那怎么样阻止这个弹簧,这个面料它在这条沿着这条线自由在弯折呢。
我可以在这个方向上再加一根弹簧,同样的我可以在这个方向上再加一根弹簧,我在这个方向上的加一个方向,也就是说对于每一个点我都可以跨过另一个点,另一侧的一个点加一根弹簧,这个就叫做弯曲的嗯。
炭火bending的弹簧,它主要的目的就是防止这个面料,它可以很自由地沿着某一个方向做弯曲,啊这是一种方式,一种结构化的方式,嗯实际中我一般有的时候比较喜欢的就是用稍微简化一点的。
它主要的简化的点在哪里,就是简化一些对角上的弹簧,就是你不需要每一个小格子,你都加两根弹簧,你可以就是形成这种这种网格式的方式,就是每个格子上都是选三四十5度或者135度,就是选选选择一项。
那为什么我不一直都用斜45度或者是斜135度呢,因为你如果是一直都是沿某一个方向的话,容易让你的模拟产生一些偏向性,比如说如果说你一直沿45度,那么它在45度的方向,它的抵抗就会比较强。
而135度它可能就没有什么抵抗,那这种格子的这种错开来的格子的好处在于,它45度跟135度它都能兼顾,它,就是有的时候它它有些格子它有135度,有的格子会有140,有45度。
所以说嗯我是个人比较喜欢这种右右边这种错开来的方式,同时它也让你的弹簧数量减少,当然这是一种结构化的方式啊,还有一种呃也比较常见的就是在可能在很多设计中,我们做出来的mesh。
它有可能不是一个很规则的一个面料的mash,比如说我们在设计衣服的时候,很多它的版型出来的版型它都不是一个规则的一个方块嘛对吧,或者是一个长方形嘛,很多时候它是一个不规则的形状。
那如果说它是一个不规则的形状,那么我很多时候就是要用三角网格,而且是一种非结构化的三角网格来描述它了,那所谓的非结构化就是它是一个很乱的一个,它没有什么结构的这么一个match 3角mesh。
有很多三角形构成对吧,这些三角形就是把这些点都连接在一起,那么如果说我给我的是这么一个三角形网格,我怎么拿来做呃,弹簧系统的模拟呢,那一个简单的思路就是我可以把每条边都认为是一根弹簧嘛,对不对。
那我每条边都产生一根弹簧,那么我把这些边全都用弹簧连接起来,我就构造了这么一个弹簧系统了,当然还不够,为什么,因为我这里其实还是没有对于弯曲的抵抗的,那么怎么样抵抗弯曲呢,其实跟刚才的思路很像。
就是我可以对于每一条内部的边啊,假如说我这是一条内部的边对吧,我都可以构造一根这样子的弹簧,来抵抗弯曲,这根弹簧呢连接了这个内部边所对的这两个点,就分别是这个点,还有这个点,我把它俩连接起来之后呢。
那么是不是也就意味着我这个面料它其实在这个方向上,在这个边的方向上,它就产生抵抗了,他如果想要进行弯曲的话,我就我就会在这个方向上就就有个抵抗对吧。
那么我就可以让这个面料相对来说就是可以由产生弯曲的抵抗,那么这就是在非结构化的呃mesh,非节后的话呢,三角形网格我可以利用内部边所相对的这两个顶点,来构造出一根弯曲弹簧来,当然这根弹簧会很多,为什么。
因为我们有很多内部编码,对于每一条内部边,我都需要加这么跟弹簧,最终就把整个这个弹簧系统,整个弹簧系统的这些弹簧拳都构造出来了,这就是一个简单的一个思路,那么有同学就会问了,就说我怎么样。
假如说给我一个三角形网格对吧,我怎么样去构造这些边呢,怎么样去把这些边从这个三角形网格中给它抠出来的,然后怎么样我利用这些编,我去构造这些弹簧系统的构造,这些弹簧呢这个其实是有一个计算方式的。
我这里就简单的给大家介绍一下,就是在几何上是怎么样处理的,就首先我们来讲一下这个三角形的网格,它是在我们程序里面是怎么样表示的,假如说我有一个非常非常简单的这么一个三角形网格。
我有三个三角形分别连接了这么五个顶点对吧,x0 到x4 ,然后分别对应的是三个三角形,一般来说我最原始的输入啊是由两个列表,两个数组所构成的,第一个数组存的是顶点的位置,比如说我现在有四个顶点。
分别是x0 到x4 嘛,那么我第一个列表我存的就是这五个顶点的3d位置,每一个顶点是一个3d向量,所以说我其实就有五个3d向量存在这个顶点列表里面,这是我的第一个输入。
然后我第二个输入呢存的是三角形的呃,每一个三角形的顶点的索引就什么意思呢,就是我现在有三个三角形对吧,有三个三角形,那么我又分别对应了啊,这个绿颜色,蓝颜色跟橙色的这三个三角形。
然后第一个三角形的是123构成的,只有这三个顶点所构成的分别是一三对吧,那么我在这个列表里面,我存的就是序号一,序号二,序号三,这三个序号就告诉我这个哦,我通过这个顶点的这个位置的信息。
我就知道说它是分别是这三个顶点的位置,然后以此类推,对于蓝色的这个三角形呢是由013构成的,那么我接下来说的就是013,然后橙色的三角形是呃034构成的,所以说我这里存的就是034。
所以说它其实本质上就是每一个三角形,我都存了相应的这三个顶点的序号,在这个顶点列表里的序号,这样子我就知道说他们的3d位置是什么了,这个是一般来说是我们如果给别人给我们数据,给我们三角网格的数据。
一般来说它给我们最原始的数据就是这个东西,那给了这个东西之后,关键问题是我怎么样从里面得到所有的边的信息,我们为了构造这个简单的这种拉伸弹簧,我需要有边的信息对吧,我可以给了边的信息之后。
我就可以用边去描述这些弹簧,但是编得不够,我还需要有内部编的信息,因为我做弯曲的时候,我们刚刚前面讲了嘛,我们如果要做弯曲,我需要用内部边,这样子我可以把呃,比如说我就我就有个内部编对吧。
我可以把这个相相对的这两个顶点给它连接起来,我还需要有内部变的信息,所以说接下来我们就会讨论,怎么样把这些边的信息从这两个数据里面给抠出来,那有一个简单的想法,就是说我每一个三角形呃,相邻的三条边。
那么是不是我直接把这三条边给拿出来,就可以当做三根弹簧了呢,不行为什么,因为对于内部边而言,它是有重复的,比如说我刚才说的这个边对吧,零三这条边它是一条内部边,那么这条内部边它既相邻了1号三角形。
也相邻了2号三角形,也就是意味着,如果说我简单的把每根三角形的三个边全都拿出来的话,那么等于在内部边上我就变成有两根弹簧了,那我不希望这样,我希望内部边上还是有一根弹簧,所以说我这里是需要做一个操作的。
我们叫做呃几何的一些处理,那么怎么做这个处理呢,我先构造一个一个三队,一个一个triple,triple,就是三个数字啊,那么这个triple存了什么东西呢,他存了三个数,前两个数呢是每条边的顶点信息。
然后最后一个数是三角形,就比如说我这0号三角形啊,假如说我0号三角形,它有三条边对吧,分别是1223跟三一,所以说我针对0号三角形,我就分别构造了三条三个triple。
那这个so triple其实你可以认为是一个原始的边,它是一个原始的边,然后每一个边每个三角形呢都会有三个原始的边,所以说你可以看到我这里最终形成了九个原始的变,九个原始的trip。
那么对于0号三角形而言,我就有一二跟零对吧,那么一跟二是它的这个边的信息,就是分别是就是对应的这条边,然后二跟三呢就是接下来是这条边,然后一跟三呢就是内侧的这条边。
然后最后这个数字零呢就是告诉我们这是0号三角形,这个就是对0号三角形,绿颜色的三角形,我就有三条原始的边,然后呢用这个这个这个这样的一个数据结构,我来储存他的信息,那对于蓝色的这个1号三角形。
我也做同样的事情,我有013嘛对吧,然后我就形成了这么一个结构,0113跟零三,然后也是对应的1号三角形,同样的呢我用橙色的部分,我也可以形成这么一个原始编的信息,那有了之后呢,我接下来怎么做呢。
我对他们做一个排序啊,我就对他这些数字做一个排序,那为什么要做这个排序啊,它的原因其实很简单,就是如果说有一条边是内部边,那么它两个顶点它会在这个这个结构里面会重复出现两次,那么我对它进行排序之后呢。
它就会在相邻的位置上,比如说咱们说的这个零三这条边对吧,这是一条内部边对吧,那么它分别出现了两次,那因为开始的时候他在这个位置这里有一个零三,然后这个地方也有一个零三对吧,他出现了两次。
那么我排序之后呢,它就会在相邻的位置出现了,同样的这个还有一条内部边是e3 ,那么他之前呢在这里还有这里对吧,他之前没有香菱,但是我排序之后呢,他就相邻了。
他就在相邻的位置会出现它相邻的位置出现的好处在于什么,好处在于,如果说我对于这些边这些原始边进行排序之后,然后呢我从头到尾检查一次,我就可以把这些重复的边给它剔除掉,因为它永远是相邻的嘛。
我只要往前往后检查一下是不是出现同样的情况,如果说同样的顶点都是一模一样的,我就把它剔除掉,那么以此我就可以把整个边列表给它构造出来,我就把这些重复的部分给它剔除掉就够了,比如说这个我把这个剔除掉。
那么我剩下的就是没有重复的单独的顶点,那么这些顶点就是留下来的,这些顶点呢我就可以拿来当做我的弹簧来模拟了,我就不用担心说在同样的位置,我会产生两根弹簧了,那怎么样得到弯曲弹簧呢。
得到弯曲弹簧的目的实际上是为了有内部的边对吧,怎么样知道内部边其实也很简单,我们刚才剔除的时候,我们会检查重复吗,那么重复的边实际上就是内部边,所以说内部边就是零跟三跟一跟三。
那么有了零跟三跟一跟三之后呢,我就分别通过他的这个三角形的顶点,我再做一次检查,比如说我知道零跟三相邻的是1号三角形呃,和2号三角形,然后我一跟三角形,2号三角形,我就检查这两个顶点哦,分别是一跟四。
那么我就把这个一跟四就连接起来啊,当然你也可以存三角形的信息,比如说我这里存的是三角形的信息,我存的是一跟二相邻,三角形一和三角形二相邻,三角形一跟三角形零相邻,这个也可以。
这个取决于你是想直接存这个弯曲弹簧的顶点,还是你想存三角形的三角形相邻关系,这个都可以,反正就是我这里的话就直接从三角形相邻关系了,这就是一个比较简单的处理,mesh,假如说给了你三角形网格。
你怎么样把这边的信息,还有内部编的信息给它搞出来,然后利用这些得出来的,别的信息我可以构造我的这个整个模拟系统。
那么呃代码大家可以去参考一下,就是我们下次作业的时候,我会给大家,也会给大家一个example的一个代码,大家如果感兴趣的话,可以看一下那个example的代码,就是在这里我就不重复了。
反正就是大家如果感兴趣这个刚才我们前面这个算法是怎么做的,你可以去看一下那个代码。
那有了这个东西之后,有了这些编的信息之后呢,我就可以搞一个模拟系统的啊,怎么模拟呢,首先我是一个做一个简单的一个例子系统,这个粒子系统呢就是对于每个顶点呃,我可以计算每个顶点的力对吧。
每一个顶点i我计算它的力,然后有了力之后呢,我除以质量乘以delta t加上速度就得到了新的速度,然后有了新的速度呢,我乘以达到t加上位置,我得到了新的位置,这个反正就是一个非常标准的一个粒子系统啊。
大家可能之前会看到过,跟那个跟那个我们做钢铁的模拟,其实很像,只不过比钢铁还要简单,因为我这里就没有任何旋转了,我这个每个点它就是一个单纯的一个位置的一个信息,那么对于弹簧系统而言。
我只需要把弹簧系统插入到这个力的计算过程中就够了,那么怎么算力呢,当然这里有很多例了,那我这里再多一个力,就是一个弹簧的力,那么怎么算力呢,对于每一条弹簧,每一条弹簧,这里其实应该叫spring。
不应该叫edge,对于每一根弹簧e呢,我都有一个列表,这个列表呢就是存了这些顶点信息,就是每一根弹簧,每一根边它都连接了两个顶点嘛,那么我就用一个二维数组来定义第一个数字呢。
第一个index呢是它的这个弹簧的index,然后后面的index呢分别就是对应两个顶点,就跟前面我前面给大家的一样,就是这个零跟一对吧,第一根弹簧连接零跟一,第二根弹簧连接了零跟三。
第三根弹簧连接了零跟四,就是这么一个这么一个定义关系吧,每根弹簧都分别连接了两个顶点,那么我首先把这两个顶点的索引给他得到,然后呢我还有另一个列表,这个列表存的是弹簧的原始长度。
一般来说我们这个东西是可以通过预计算给他算出来的,我事先可以把所有的边,所有的弹簧都过一遍,然后呢我把它的初始的这个长度,我假设初始初始的位置是没有形变,是原始位置,那么我把这个初始的长度给它保存下来。
然后保存完了之后呢,我通过这个索引我就可以访问它的原始长度了,然后呢我根据这个咱们这个力的这个公式,我可以把这个力给它算出来,算完力之后呢,我分别加到呃i跟g上面去,那么我就给他算出来了。
这个一般来说就是这么一个流程,当然这个这两个循环它好像有点冲突啊,其实是其实应该是应该是你事先应该定义这么一个数组,你可以事先把这个力定义成一个数组,然后在之前先把所有的力都算出来,就不要在这里计算了。
是先把所有的力算出来,算完之后呢,然后再分批的对每一个顶点进行处理,这样子可能更合理一点,我这样子写可能大家会有些误解啊,其实他应该是最好是应该是分成前后两个部分,第一个部分是历史。
单独先把所有的力全都算起来,保存在一个呃力的一个数组里面,然后算完这个力的数组之后呢,我再把所有的顶点给他过一遍,大概是这么一个流程,我这里回头会把这个p p t稍微改一下,好了。
这个基本上就是一个简单的显示积分,我们做explicit integration呃,进行弹簧系统模拟的一个方式,这个跟我们其实前面的那个缸体其实很像,无非就是多了一个利,多了一个弹簧力。
那么显示积分它其实有一个很严重的问题,就是叫做nerability,然后这个numerical instability,中文就叫做数值上它是不稳定的,那么什么叫做数值上不稳定呢。
我这里给大家这么一个情况啊,就假如说我现在有这么一根弹簧,很简单,一维的情况,非常非常简单的一维情况,不要去想很复杂的情况,假如说我有一个形变,那么我现在弹簧形变了对吧,我根据这个力。
然后我更新他的位置,更新它的速度,更新它的速度,更新他的位置,那么大家想一想,如果说我这个弹性系数非常非常大,如果说我这个k非常非常大,会发生什么,如果k非常大的话。
它会导致我们这个弹簧的利益也会非常非常大,对不对,那么给这个弹簧我施加一个这么大的力,那么会导致什么呢,会导致这个弹簧的这个顶点它会跑得过于远,因为我们正常情况下。
我们讨论弹簧很多都是假设能量守恒嘛对吧,那么弹簧系统理论上这个顶点它不应该它的这个形变的这个长度,它不应该超过原来的这个长度,但是如果说我直接用一个简单的这个显示积分。
我假如说我给它施加一个很大的力的话,那么有可能这个顶点会跑得过远,会跑过头,会跑过跑到另一侧,而且它会跑到更远的一个位置上,那么因为他跑得更远了,我在计算弹簧的力就比原来的力还要大,那么给这么大一个力。
再加上这个顶点的位置的话,那么下一刻呢它又会跑得更加远,那么它有可能就跑到整个跑到屏幕外面去了,也就是说如果说我这么一个弹簧系统,由于我的这个k它过大,由于我这个弹簧系数过大。
会导致我在做影视显示积分的时候,它会反复地超越他自己,它会跑得越来越远,越来越远,越来越远,最终它会跑出整个屏幕,最终它会跑出我们这个整个模拟空间,所以这个问题呢我们就叫做overshooting。
这个overshooting本质上跟我们之前做那个呃,做碰撞的时候产生的overshooting是有差不多意思的,就是当我们这个系数很大的时候,它会跑得过远。
所以说很多时候大家就是为什么不直接用显示积分的原因,就是因为它会产生数值不稳定性,而且呢它一般来说会在两种情况下出现啊,要么是这个stiffness这个k很大,要么呢是你的时间不长很大。
因为为什么时间不长很大也会导致,因为你想看,假如说我让这个位移,就是假如说我让这个顶点是走得更远,我想要模拟的更久,那么在固定k的情况下,它实际上也会跑得更远对吧,那么怎么解决这个问题呢。
一个比较简单的思路呢,就是说呃我可以把这个delta t搞得小啊,有个同学问k大不是弹力大,把他拉回来吗,对是的,就是说你当你k很大的时候,他把它推回来,但是他不只推回来,他还把他推过头了。
而且他不只是推过头了,他还要推得远远的超过原来的位置,他要抄的更过头,对吧,因为这个是一根弹簧,它这个他只是会左右晃吗,那你如果这个k很大的话,他会直接穿过原来的位置,他直接跑到这头去。
它会存在这个问题,那么怎么避免这个问题呢,就是我一个思路,就是我可以把我的时间不长搞得稍微小一点啊,这可以做,但是就是不是一个很好的思路啊,因为你时间不长,搞得越小,你其实整个模拟的效率就会降低吗。
我们一般来说我们还是很在乎模拟效率的,我们希望它这个效率性能上还是要比较高的,所以这就是为什么呃,早年一般来说用显示积分比较多,但是后来用影视积分的相对来说就比较多了。
所以我们接下来会讨论另一种模拟方式,叫做影视的积分,那么影视积分其实我们之前讨论过怎么做影视积分呢,就是假如说我现在有速度跟位置两个变量对吧,那么速度等于这么一个更新的过程。
然后位置等于这么一个更新的过程,然后速度用的是力,位置用的是速度对吧,那么我这里的速度用的力是什么,力是,想要得到的那个新的状态下算出来的力,而这个力呢是我们所没有办法直接计算出来的。
因为它是根据新的时刻,新的状态所算出来的力,它是跟v一跟x一相关的这么一个例,而我们事先并不知道v一跟x一的对吧,所以说它实际上是一个未知的东西,然后x呢是根据v一所算出来的。
那么v一也是一个未知的东西,所以说他俩其实都是未知的,那么怎么来处理这么一个问题呢,嗯我首先我想简单地消一个圆,因为我这里有两个变量,分别是x和v嘛,这两个变量有点太复杂了。
我想稍微把这个问题简单化一下,那么怎么消元呢,首先我这个公式上面这个公式有v1 ,下面这个公式也有v一对吧,那么我首先可以把这个v一先给他弄弄掉,那么第一步我首先把这个v一用上面替代。
如果说我把v一用上面这个公式替代的话,我得到的就是x一等于x0 对吧,x一等于x0 ,加上delta t乘以后面这一坨东西,那么就是delta t乘以b0 ,加上deltp平方乘以m vers乘以2b。
这个角本质上就是这个东西乘以delta t,然后挪到了这边,那我第一个公式我实际上就把v一给消掉了,我得到的只有x一跟f一这两个东西,然后第二个公式呢是下面原来这个公式给他反推了一下。
就是之前我是有了v1 ,我算x一嘛,那么反过来如果说有了x1 ,我怎么算v一呢,我可以用他俩相减再除以deltt来计算对吧,我就得到了x一减x0 除以dl的t这个就得到了v就是反推。
通过这个东西反推我可以得到这个东西,那么对于这这两个公式而言,下面这一步是比较简单的,如果说你已经知道x一的话,下面那个公式很简单,你只要做一个简单的减法,再加一个除法就可以搞定了。
所以说真正的问题就是上面这个公式,就是这个问题,那么这里我要做一个假设,我要假设f这个力呢,它只是关于位置的一个函数,我假设这个力跟速度没有什么关系啊,我假设它只跟位置有关系。
那么什么样的力是跟只跟位置有关系的,比如说重力对不对,重力只跟一个顶点的位置有关系,事实上重力都跟顶点的位置都毫无关系,它跟什么都没有关系,重力实际上只是一个常数,但是我可以认为就是它不依赖于其他变量。
然后弹簧也是这么一种力,叫做holoomic,这种利益就是说只跟位置有关系的利益,就叫做honomic的利益,那么比如说弹簧它也是一种honomic的利益对吧,因为弹簧它只跟这个顶点的位置相关吗。
那么假如说我认为这个力是horroomic的,那么我就变成了这么一个问题了,那么我这个刚才这个例f一啊,我就可以写成一个关于顶点位置的一个函数了对吧,那么这个一呢就跑到这个x一个括号里面去了。
那就是成为了这个x一了,那么这个东西就成了一个什么呀,成了一个一个一个一个公式,一个方程,这个方程呢它是以x一作为未知量的一个这么一个方程,那么我们现在的问题就变成一个解线性方程。
解一个解一个方程的问题了,那么这个方程有什么麻烦的地方在,就是这个力啊,它可能不是线性的,因为我们之前学线性代数,一般来说都是假设一个线性问题对吧,一个线性问题,然后呢我可以利用一些什么消元法。
我可以把这个线性问题解掉,那么这个地方麻烦在麻烦在这个利他可能不是一个线性的力,所以说我们需要有一些特殊的手段去处理这个问题,那么怎么解决这个非线性方程,怎么去解这个非线性的方程啊。
我们首先考虑这么一个事情,我们首先对我们的问题再做一些变换,把它重新给它分装一下,就是之前咱们这个问题就是x一是我的未知量,这是我的未知量对吧,那这个未知量同时出现在公式的左边跟右边,我就没法解了。
那么首先我把这个问题分装一下,我会发现,这个公式呢,它跟这个非线性优化问题是等价的啊,这个是个什么问题呢,就是说我认为x一啊是某一个函数的最小值,那么这个最小这个函数是个什么函数呢。
是二分之l t t分之一乘以这么这么一个东西加上ex,然后这个e呢是这个力的能量,然后呢这个呢用这个下标呢是这个x transport x这么一个形式。
啊我用我用这个形式来啊来来稍微对这个公式做一些简化,就是差不多就是你可以认为这这里面这一坨东西呢就是这个x,然后呢这个符号呢,这这个norm的形式呢就是这个东西乘以m再乘以这个东西。
然后这个m是质量取证,我刚才可能忘了说了,这个是mass matrix,这是一个质量矩阵,一般来说这个质量矩阵就是一个对角矩阵,一般来说它是对角矩阵,然后对角上面就是呃质量的这个值啊,就存在这个对角上。
然后这是一个什么样的系统啊,这是一个三乘n的系统,对吧,你可以看到每一个顶点,每一个每一个x它实际上都是一个三乘以n的一个大的向量,它里面存的就是所有的顶点的信息,就比如说我有很多顶点构成的嘛。
x0 x1 ,然后一直存下来嘛对吧,我们之前不是用顶点列表去存吗,你这个你可以就认为这个x是存了这个所有的这些顶点摆在一起的,这么一个大的向量,然后这个是属于r,然后这个ex就是的能量就是这个力。
每一个力它其实都有一个能量的表达式吗,能量的形式嘛,比如说我这个力有弹簧,那么我这个ex就对应的是弹簧的能量,如果我这个里面有重力,那么我里面就有重势能,我其实就用这个形式就存在这个里面。
然后这个质量矩阵它是一个r3 n的矩阵,3x3,这个大家能理解吗,就是我这里其实是一个线,我这里上面这个公式它实际上是一个一个方程,然后这个方程呢它是一个不是一个方程,它是一个方程组,它是3m的。
它有3n个方程所构成的,因为我里面每一个x它实际上都是一个3n的一个数字,它是一个向量所构成的,这个大家能理解吗,有没有什么问题,我想这停一下,因为我觉得这里还挺关键的啊,对这个怎么来的,我接下来会讲。
但是我想我想确保一下,大家这里其实都都还明白这是什么意思,但是我接下来会讲这个等价是怎么来的,那没问题的话,我就接下来继续往下讲啊,接下来我们就说为什么等价啊,为什么会等价,其实对于优化问题。
只有保守力能用能量对是的,一般来说只有保守conservative的力才能用能量形式,如果是非保守力,比如说摩擦力,一般来说是没有办法用能量来描述的,那我们现在来讲就是为什么这个东西是能力。
是是这两个是等价的啊,对于一个优化问题而言,对于一个这么一个优化问题而言呢,我可以认为x一是什么呀,x一就是当梯度等于零的时候,它的一个解,这个字怎么理解呢,就是你可以想就是如果说我们一个有一个函数吗。
这个函数它一个实数函数,它的最小值就是它的一阶导数为零的时候对吧,如果说我有一个一个函数,它什么样的时候取最小值啊,它的最小值就是一阶导数为零的时候嘛,那它就是没有办法增长。
增长或者没有办法有有有进一步的下降的空间吗,那么一阶函数一阶导数对于这么一个关于顶点位置的而言的,它就变成梯度了,因为梯度本质上就是一阶导数的transport,所以说我就是认为梯度等于零的时候。
就是x一满足这个公式的时候,也就是说x一实际上就是在x一这个位置,在这个x1 ,假如说x一是我这个函数的最小值,那么x一的梯度就等于零,实际上就是这么回事,这两个就是等价的啊,也不是说等价吧。
就是说它必须满足他,如果说x一是它的最小值,那么下面这个条件是必须满足的对吧,那么我怎么求梯度呢,对于这个f而言,我怎么求梯度呢,首先我前面这个部分我要对它求梯度,那么前面这个部分是括号里面的。
这个括号里面的东西乘以m再乘以它自己吗,那么一个东西对它求梯度,那么也就是x穿这个东西求个梯度,哎算了我我就我就我就不写了,这个东西求梯度,那么就是把二放到前面,就是二跟二抵消掉,然后把i放到前面。
然后把这个东西保留,这个是一个简单的求梯度的一个呃东西,反正这里我也就简单的稍微抢一下,大家如果不是很熟悉的话,可以简单的看一下那个calculus这一块,反正就是对前面这个部分求梯度。
我最终就可以得到这个东西,然后对能量求梯度是什么呀,因为能量球气度不就是负的力吗,对不对,因为力是力是负的能量的梯度嘛,那么我对能量且梯度不就是负的力吗,对吧,那然后我再把这个公式稍微整理一下。
我是不是就发现它其实这两个是等价的呀,因为我把这个dt平方乘到这个乘上去,然后再把m inverse乘上去,我其实就等价了,是不是没电了,看一下。
这个插座哦。
就是我利用这个梯度的这个公式等于零的时候的状态,我知道当x一为这个优化问题的解的时候,必然满足梯度等于零这个条件,那么梯度等于零这个条件呢,我对这个f求梯度呢,我就会发现其实最终推出来。
所以公式整理一下之后,你就会发现这两个是等价的,为什么是等于零是吧,因为梯度等于零,你可以一想梯度就是一个函数的一阶导数,我我后面会有,我会给你画个图,我看看能不能理解啊,简单的说我这里做了什么事情。
我就是想把想把这个我们之前的这个方程,这个非线性的方程呢我给它转化成一个优化问题,转化成优化问题的好处在于什么,转化成优化问题的好处在于优化问题,它其实是有很多很多建成的这些数值方法,数值套路的。
我们就可以利用已有的这些数学家给我们提供的这些方式,我们去解这个优化问题,我们就可以就可以把这个优化问题给它解掉,然后这个公式其实我们回头我们讲有限元的时候,其实也会提到,然后大家可以注意到这个东西。
它其实并不限于弹簧系统,其实对于任何的模拟的dynamics,其实都是适用的,如果说你想做饮食积分的话,其实都是适用的,然后有同学会问会不会有多个解是会有出现的。
所以说我接下来会讲会给大家举这么一个简单的小例子啊,然后呢我给大家举一个例子,就是叫做牛顿法,这个牛顿法它全名叫做newton rs the method,但是他们我们一般来说通常见的方法叫做牛顿法。
牛顿法最早发明的原因就是他想要解一个非线性的优化问题,就是x一等于某一个函数的最小值,我想要让这个函数取最小值,我想知道什么样的状态下我能取最小值吗,然后一般来说我们对这个函数是有一定要求的。
一般来说我们是假设它是连续,但是数学家发现其实你不要求他进行满足数学上的那种一阶二阶连续,他有的时候他也可以也可以收敛,它也可以work,可以认为就是lapis continues。
它实际上是一种广义的连续,但是你也可以不用特别纠结说这个什么叫做libertuous continues,反正就是说这个函数的连续,这个也很容易理解,因为它要是不连续,你都你都没有办法求导数。
你都没有办法把这个导数算出来,你后面就没法搞了,那么牛顿法怎么做呢,大家有没有学过牛顿法,我想我想先问一下,以前以前有上过一些数学的课吗,就是牛顿法来解,比如说解一个非线性系统或者是非线性优化问题。
还有下一个,我这里给大家简单的介绍一下,就是这个牛顿法是个什么样的意思啊,就是我这里会做一个一阶的,对于他的一阶导数,我会做一个类似这种近似,就什么意思呢,就是说,对于跟函数而言。
这个其实回答了刚才前面那个同学的问题,就是还是不理解为什么梯度等于零,就是它的最优解了,你可以想象一下,假如说你的函数是fx对吧,那么你的这个函数曲线是这个样子的。
那么它的这个最小值就是它这个最低点对吧,那么最低点它有个什么样的性质呢,就是他这个一阶导数啊,它才是最低点嘛,也就意味着它的一阶导数为零,因为我们一阶导数实际上就是在描述它这根函数的方向。
所以说最小值一个函数的最小值跟它这个一阶导数为零,实际上是一个概念,你可以认为就是一阶导数为零的时候,就是它取最,就是如果说它取最小值的时候,那么你必须是一阶导数为零,那么回到前面的问题。
就是说我们对于一个函数,如果说这个函数它的变量是向量的话,那么我就是不用一阶导数,我用梯度来描述,因为梯度就是它的一阶导数嘛,我现在问题就是变成了我怎么样找到这个阶导数为零的这个解嘛,对吧。
我想要解这个问题怎么解呢,做一个比较简单的一个泰勒展开的一个近似啊,这个x是我不知道的,是我的变量是我的未知量对吧,但是假如说我现在有个当前的位置,我当前在k这个xk是我的当前值。
那么我可以做一个泰勒展开的近似,一阶导数在x的一阶导数等于当前的一阶导数,加上当前的二阶导数乘以x减去当前的位置,就是一个很简单的这个一阶的泰勒展开,那么这个是不是就变成了假如说我要求等于零的话。
那么这个是不是就变成了一个很简单的一个小的方程啊,我是不是就可以把这个x给它解出来了对吧,那怎么解呢,可以分成几步走几,首先我对x有个初始值,我假如说我当前比如说我就x0 ,当前是x0 。
那么我根据这个公式把这个东西,我把它叫做deltx delta x等于零意味着什么,意味着这个东西除以它嘛对吧,前面加个负号嘛,所以就等于负的一阶导数除以二阶导数,如果说你把这个东西。
你把它的一阶导数挪到公式的左边,那么就变成负的一阶导数除以二阶导数,我的改变量我的deltx就是负的一阶导数除以二阶导数,然后再把这个改变量加到这个xk上面,然后再以此做迭代。
我每次比如说我当前比如说初始的位置是,这里是x0 ,根据我这个一阶这个近似的公式,我可以算出一个新的改变量来,新的改变量实际上就是当前这个位置的一阶导数除以二阶导数,前面加个负号。
然后他给我算出来一个新的位置啊,比如说跑到这里来了,然后我再根据这个位置,我再算一个位置,以此类推呢,它最终逐渐逐渐的靠近这个函数的底部,然后找到帮我们找到这个x这个解,这个方法就叫做牛顿法。
大家能理解吗,尤其是没有学过的同学,这个能理解吗,这个地方,就是利用泰勒展开一阶的泰勒展开,可以计算这么一个改变量,然后利用这个改变量来进行一个更新,这个能不能一定收敛,我的答案是不一定牛。
它不保证一定会收敛,但是我们后面我们讲到f有限元的时候,我们会讲到我们可以对牛顿法一些条件上的约束,能够保证他一定会收敛,但之后会讨论到,其实没有学过的同学,我想知道有没有有没有有没有什么问题的,这里。
这是country gradient的是另一种方法,这个我们就暂时这里就不讲contract gradient是吧,实际上就是其实是一回事情,就是你用牛顿法求根跟你做优化是一样的。
因为你做优化本质上就是对它的一阶导数求根,你对一阶导数求跟跟那个跟直接用牛顿法去解线性系统,解解解方程,非线性方程实际上是一回事情,这里就先,x等于argument app是为什么。
你可以认为是他的一个另一种问,就是这个问题的另一种描述方式吗,就是你的优化问题可以是认为他你的优化问题,你的非线性优化问题可以认为跟一阶导数等于零是等价的,然后他一阶导数等于零,就是一个线性的一个公式。
一个方程嘛,那么非线性方程和非线性优化,其实这两个其实你可以认为是有没关系的,就回到刚才前面,前面刚才有同学就问了,就说会不会有多个解,还有就是会不会找到不对的这个问题了,有非线性方程。
然后积分得到f吗,嗯其实我们在做模拟的时候不需要,就是因为我们模拟的时候,我可以直接直接算能量嘛,所以其实并不需要就是说对他做做积分,其实直接就可以写成这个,怎么和从x有关的方式方程变成。
前面这个公式就是回答刚才有个同学问,就是怎么变,就是这两个是等价的吗,说我们之前我们写影视积分的时候,我们是这个共识对吧,那么我直接可以实际上可以把它转化成这么一个写的形式,就是实际上就是同样的问题。
只不过是我换了一种方式,我换了一种表达方式,之前如果说按照直接的显示影视积分的方式呢,我得到的是一个方程组,但是呢我其实也可以把它写成一个非线性优化的这么一个问题,其实就是我只是换了一种写法。
表达式表达方式不明白是吗,就就是就是这个f等于这个,这个是这个其实这样做不是说这样子做能够克服over shooting,而是积分能够克服over shooting。
就是这个方法就是前面这个方法它是能够克服over shooting的,但是你这个前面这个方法呢有存在的问题,就是你怎么样把这个x跟v给他算出来,那后面就是说我们来怎么来把它算出来的。
这个问题其实也是可以解解直接解方程的,实际上是等价的,不过是因为很多时候呃数学家他们在研究的时候就是研究,他们会直接研究就是非线性优化问题吗,很多时候他们都是不是考虑的,单纯的考虑一个解方程组的问题。
解方程组你可以认为是优化问题的一个特例,说我们其实是这里是想把它考虑在一个更加通用,更加广阔的一个数学问题上去来讨论这个问题,当然你如果说解早期的一些论文,其实关于模拟的一些论文。
它其实就是简单那把把他们考作为考虑做一个解方程组的问题的,后来最近几年就是大家因为发现其实更广阔的,我们可以认为是一个优化问题,然后呢我们会有很多优化问题的方式来处理这个问题。
就方法上我们在模拟的方法上,我们就选择就会更多样性了,我还是继续往后讲讲一下吧,如果得不到f的反函数,就没法解,什么叫做f的反函数啊,这里好像没有反函数吧,没有用到反函数,是你对它求导吗。
你只要能对它求导就行,我们要得到f的一阶导数吗,他最小的fx space,我们是我们是不是直接用反函数的求解的方式的,我们实际上你说的那种就是说如果说你有反函数的话,你是可以得到精确解的,它的解析解的。
但是我们这里是用数值的方法,所以说我们是不依赖它的反函数的,我们实际上是把它相当于把它变成一个方程,然后这个方程左右两边都有都有未知量,然后我们是解方程的这种方式来来求解的,我们这里并不需要它的反函数。
我们是通过这种数值方法来求解,明白吗,你是积分的,等cab fx,十积分怎么防止数据怎么证明,这个的话,这个我就我就没法给你证了,这个在那个在一一般来说讲那个数值方法里面。
数值积分里面他们会有更详细的证明的,这个证明证明还挺长的,一般再说它是通过那个物差的衰减来做判定呢,就是为什么会有overshooting,本质上就是误差的误差会越来越大,它会把这个误差放大。
所以说他要证明的就是说这个误差是会长期是会衰减的,x是啥是吗,fx就是这里fx就是这个东西,这个东西是根据我们前面的前面的这个饮食积分的这个公式,所推出来的这个东西,这就是我们的fx,这里。
我最后会给大家一个就是课后的课后的阅读的,可能就是说如果说大家是第一次接触到这个东西的话,确实会有一些有一些就是这里或者那里的问题吧,反正我最后会给大家一个课后阅读的。
这个也是关于呃库拉在那个影视积分里面比较经典的一篇论文,大概90年代一篇论文,大家如果感兴趣的话,可以把那个论文再给他详细的读一下,然后那篇论文呢跟我这里讲的还稍微有点不一样。
那篇论文实际上是以解方程的这种解方程组的这个写法来写的,它并不是能量优化的方式来写的,它实际上是解方程组的方式来写的啊,但是他其实你可以认为是只是做了一次牛顿迭代,因为他把他怎么做的。
他把那个方程给做了一个线性化,对就是buff那个那那篇论文我到时候会给大家呃给大家,然后大家如果感兴趣的话,对一些细节感兴趣的话,可以把这个东西看一下,然后我会把这个数值这里再稍微讲一下,就是。
就是一阶导数等于零啊,它其实导数等于零,它其实既可以是最大值,也可以是最小值,对因为比如说我有一个函数,我很奇怪,等这么一个函数,它在最小值的时候,它的一阶导数等于零,它的切向量切方向等于零嘛。
最大值它其实也等于零,它可能有多个解对吧,那它这个地方它也等于零,我怎么知道说我这个解解出来到底是最大值还是最小值,然后它到底合不合理呢,其实我就需要有一个判定了,用什么东西判定啊,我用它的二阶导数。
我们以前学过,我们在高中里面,我不知道大家记不记得学学高中里面学这个抛物线的时候,阶导数实际上就是它这个二元二次的系数嘛,二阶导数大于零,也就意味着它的开口是向上的,二阶导数小于零。
就意味着它的开口是向是向下的,这个大家记得吗,一个道理就是我们可以用二阶导数,假如说我把这个一阶导数等于零的这个东西给算出来了,那么怎么判断它是最大值还是最小值呢,就用二阶导数。
我看他是开口是向上还是向下的,如果说大于零就是向上的,那么开口向上也就意味着这是一个最小值,然后如果是开口是向下的呢,二阶导数小于零呢,它是一个大致,但这个呢它不见得一定是最大或者最小。
它有可能是一个局部上的一个大值或者局部上的一个小值对吧,比如说两个这个还有这个它都是小值嘛,它都是满足这个条件的,然后这个呢它是满足最大值条件的,所以说很多时候大家一个问题的时候。
有可能你解到的它不是一个最最最最小的值,它有可能只是啊说这个值对吧,它可能不是最小值,这个是最小值,但它是一个local的一个minimal,它是一个小值,但是它是局部的一个小值。
这个东西其实没有一个特别好的方式去处理啊,当我们存在local minimal的时候,其实并没有一个特别好的方式去处理,很多时候大家都是比如说随机扰动啊,或者或者各种各样奇奇怪怪的方式来处理啊。
有的时候我们可以对函数有一些提出一些要求,就假如说我们这个函数满足某些性质的时候还是比较好的,比如说比如说什么呀,比如说我知道一个函数二阶导数永远是大于零的时候,就不管在什么样的点,什么样的位置。
函数它永远它的二阶导数是大于零的,那意味着什么,意味着它就不存在最小值了啊,最大值了,如果说它的二阶导数永远都是大于零的时候,它就不存在最大值了,我刚才说过大值的时候,二阶导数等于小于零。
那如果说它的二阶导数大于零的时候,那它就不存在最大值了嘛,对不对,如果说他不管什么样的位置,它的二阶导数永远都是大于零的,那么它就不存在,如果说它不存在最大值,也就意味着它只有一个最小值。
刚才这个图上画的这样子,对不对,假如说你有两个最小值,那么它中间必然存在着一个最大值吧,它是一个连续函数对吧,它有两个小值,那么中间肯定有一个小山峰嘛,那因为我知道,如果它的二阶导数永远都是大于零的。
那么它就不可能存在一个最大值,那么换句话说永远都是只有一个最小值,它永远都只有一个低谷的,大家其实可以记得这个条件,因为我们回头再讲那个呃,讲我们这个模拟的时候,会回到利用这个条件,利利用这个嗯。
利用这个东西,就是二阶导数永远都是大于零的时候,那它就存在唯一的一个最小值,其实在数学里面是一个比较重要的一个一个信息,我们刚才就讲了一个给大家简单的介绍了一下牛顿法。
然后那我们就可以利用这个牛顿法的思路,我可以扩展到我们刚才这个优化问题上去了对吧,我们优化问题是什么呀,是也是一个函数吗,不过对于这个函数而言,我的变量不是实数的变量,是一个向量了对吧。
我这个x它其实啊这个x它其实是一个一个一个矢量,很多个顶点,很多个顶点所构成的一个矢量,我也可以做一个展开嘛,假如说有当前有一个xk,我就用这个来进四塔,我用的是什么呀。
我是我知道我这个解必须满足一阶导数等于零嘛,它的这个梯度等于零吗,梯度等于什么呢,梯度等于在x点的梯度等于前位置的梯度上,二阶导数乘以它的这个改变量,以此我就可以啊搞这么一个算法对吧,我就不停地迭代。
利用这个公式呢,我可以把这个东西呢也也被这个东西除一除,那么首先我把这个梯度算出来,然后再乘以这个东西的verse,然后前面加个负号,这个东西就相当于就是把整个梯度挪到公式的。
我把整个梯度挪到公式的右边,得到了负的负的梯度乘以这个东西的inverse对吧,那就是得到了这个调查,x dotx就是改变量,然后我把这个deltx加到这个它的这个顶点的位置上。
我就得到了新的顶点的位置,所以说这个东西其实本质上跟我们前面我刚给大家看的这个呃,一维的这个情况是一样的,无非就是说我现在变成了向量的形式,然后这个二阶导数,一阶导数呢变成了一个向量。
一个gradient,然后二阶导数呢它变成了一个矩阵,变成了这个f的和弦矩阵,所以说这个是个矩阵,然后你需要矩阵的逆来把这个问题给他解出来,就是得到我们的解。
这个其实跟我们前面的那个呃一维的牛顿法是一样的,回到模拟问题上去,因为刚才给的大家是一个牛顿法的介绍嘛,那么回到我们前面的那个模拟问题上去,我们模拟问题我们的f是什么,我们的这个f呢是这个公式。
他t平方分之一乘以这个东西加上e e x,这个前面反正我给大家看过了,如果不记得也没关系,反正就是我反正给大家啊,也给大家了,这个就是我的这个目标函数,我想要优化的这个函数。
然后呢我的梯度分别是由两部分构成的,第一部分呢是我前面对他这个求个导,我得到了这个,然后第二部分呢是负的力,这个是呃是能量嘛,是势能吗,主要是能求对x求导,就是得到了负的力,它的和弦又是什么呢。
整个力整个这个目标函数的和也是由两部分构成的,部分其实就是对它求导,对这个规定的求导,那鬼点的求导,第一部分就是要除以deltt的平方,第二部分呢这个合成是能量的合成,这个是它的二阶导数。
是能量对未知的二阶导数,有了这两个东西之后呢,有了这个核实,有了这个二阶导数跟梯度之后呢,我就回到我这个牛顿法上,我其实就把前面的这些东西给替换掉,我就得到了我这个算法。
那我对每个顶点的位置我进行一个初始化,那么一般来说我可以直接就是用一个比如说原来的一个值,或者是原来的值加上一个速度的一个初始速度的一个更新改变量嘛,这个反正就是呃取决于你不同的算法。
你可以对它遵循一个初始化,我需要解这么一个线性方程,这个线性方程呢是我之前那个delta x是我的一个位置的更新的改变量,然后前面的是我这个二阶导数,这个就是我的二阶导数fx 2阶导数。
后面这个东西呢就是我这个fx的一阶导数对吧,这个就是这就是这个东西嘛,这个二阶导数就跑到前面去了,我就把它解解完之后,更新一下顶点位置,最后呢就是把结果传递给呃,然后把这个新的位置跟老的位置的差。
我处理掉,他t得到了速度的更新,这个paper嗯啊我回头再讲那个paper吧,就是那个paper其实beef那个paper呢其实就是做了一次牛顿法,很多早期的论文,他们其实没考虑的那么深啊。
他们一般来说是假设是一个就是一个简单的非线性方程,非线性方程,他把这个非线性方程组呢做了一个线性化之后呢,就把那个线性方程组给它解掉了,其实你可以认为他们这种早期的方式就是做了一次牛顿法,早期的方式。
你如果只是解一次牛顿法,实际上是有可能会出现模拟的很多问题的,它会出现不稳定的问题,是说这里我为什么你们想要讲这个非线性优化,而不是直接讲这个方程,解这个非线性方程也是原因在此,因为化问题做非线性优化。
这种解释它是在一个更高的层次上去理解这个问题,线性方程或者是解非线性方程,它其实是相对来说是一个比较低的层次去理解这个问题,在高层次上理解这个问题之后呢,其实就有助于我们会解释很多模拟中产生的现象。
你的这个方法,这就是为什么我是更倾向于就是呃给大家以这种形式,虽然说会稍微可能就是对于可能第一次接触的同学,在这一块它其实会有点困惑啊,但是我觉得还是有必要讲这个东西的,因为我这里讲的这个东西。
它其实并不只是做弹簧系统,回头如果说你以后想要搞有限元,做有限这种弹性体的模拟,它其实用的方法其实跟这个是一样的,我们回头其实很多物理模拟它其实用的方式本质上都是采用这种方法,无非就是说对于谈光系统。
可能你模拟衣服,模拟布料,那么你这里的e,你这里你的e你这里的f是弹簧的意跟弹簧的f如果做有限元,那么你用到的是有限元的能量跟有限元的这个力,所以说就但是对于不同的系统,相当于你就是采用不同的能量。
采用不同的力,但是本质上你的计算核心你都可可以认为是一个非线性优化问题,是我是我在这里想比较想想讲的一点,咱们咱们作业这一块,因为下次作业这一块呢嗯是分成两部分的,一部分呢是呃p p d。
就是我们下周会讲一个p p t嘛,我们会有一部分作业是用p p t完成的,另一块呢,另一个部分呢实际上可以认为是一个非线性的一个优化,这么一个东西的一个方式,所以说大家到时候大家会尝试着去构造这个。
根据这个弹簧去构造这个gradient,大家会就是说给了你这个假如说你有这么一个弹簧系统之后,你这个鬼一点是怎么算出来的,那我会有一个稍微比较简单的一个方式,来来来做这个迭代更新就不适用牛顿法了。
是一个更简单的一点的方法,到时候反正大家作业里面会尝试一下,然后会对这个会有一个更深刻的体会,因为有的时候其实光是看看论文,我看ppt,看slides,可能就是我猜测就是可能大家有的时候会看的半解。
或者是就是可能只能理解一部分,就是有点似懂非懂的感觉,作业里面反正会给大家就是一个一个实实操的一个一个一个过程,然后大家体会一下怎么去构造这些鬼,怎么构造这个鬼点,然后嗯然后会体会可能会更深一点。
这里呢我是想稍微再讲一下这个东西啊,就是说对于弹簧系统怎么去算喝水,我们之前我们在讲那个调别克的时候,我们其实讲到和神过,就是弹簧系统和神过,讲到和神讲到什么呢。
讲到这个弹簧系统的和声实际上是由所有的弹簧的总的合成所构成的,每一根弹簧呢它都会有这么一个小的子系统对应,其实我这里写的不是很好,就是分别是这里是i嘛,你,可以想象这是个3m的矩阵,横的是有三个元素。
重的也有三个元素嘛,这个地方呢实际上就是一个3x3的矩阵,对应的是i这个顶点所处处在的那三三行跟三列,然后这个呢是对应的是j那个顶点所处在的那个三行跟三列,然后这个呢也是是i跟j这个我其实画的比较简单。
就是我希望大家能够大概体会一下,感受一下这个意思,什么意思呢,因为这个其实写得非常清楚,也是挺公式上写得很很清楚,也是挺麻烦的一个事情,就是反正就是这是一个3n乘以sin的矩阵,我有多少个顶点。
我就是三乘以顶点的数量,然后呢这每一个3x3矩阵就是分别对应i跟g,因为我连接的是i跟g这条边,连接了i跟g嘛,所以说每一个是3x3的,我们之前我们在上讨论数学的时候,我们也讨论过。
就是说这个东西的镇定性啊,是由每一个h的镇定不镇定来决定的,我们只需要看这个h这个矩阵它是不是镇定了就行了,怎么来看呢,就首先h怎么算出来的,是我们之前我们课上第二节课的时候,我们上过的时候。
我们我们我们我们讨论过这个东西啊,但是这里我反正我就直接还给大家,就是如果大家不记得这个h是怎么算出来的话,可以回头看一下,这就是第48页的时候,我们其实之前讨论过这个东西,我主要讨论的不是说这个公式。
我主要是想给大家看一下,这个东西是正定矩阵,那首先公式这个矩阵它实际上是由两个部分构成的,后面你其实可以看到他俩都是镇定的,是一个三维向量吗,你总共有n个顶点,所以是3m吧,它其实是会有。
它是有overlap,就是它会有重叠的,你可以想这个是比如说0123就是0号顶点,345就是1号顶点四五,然后多少,然后678就是3号顶点,就以此这样子排下来,2号顶点就是这样子排下来嘛,能理解吗。
这个矩阵的形式,就是比如说我给大家,我给大家举个简单的例子吧,这是012对吧,假如说我有三个顶点啊,我有一条边是连接零跟一的啊,零跟二的号,假如说我有一条边是连接零跟二的,那么我就是这里有一个东西。
这里有个东西,这里有个东西,每一个都是一个3x3的矩阵,都是一个block,所以说它总共是一个9x9的矩阵,我有很多边,那么就每一条边,它可能都有这么一个东西,然后把它全部都叠加在一起。
为什么是s p d的,为什么是镇定的啊,因为一看就是假如说我有一个v向量,这个向量,也存在这个东西的左右两侧,我假如说我的v存在分别在左边跟右边这里分成了左右边。
发现这个东西本质上就是这个这个norm的平方啊,这个它的x i j的transpose乘以v v transpose乘以x i j,它本质上是一回事情,所以说就是这个东西的平方。
那么这个平方它肯定是大于零的,路边呢如果说你也做同样的事,情,你把v transpose跟v分乘在左边跟右边,你得到的就是这么一个东西,上面这个东西肯定是大于零的,因为有柯西不等式,这也是大于零的。
因为它就是一个东西的平方,所以说这个东西肯定是大于大于等于零的,因为柯西不等式是大于等于零的,这个东西也是s p d,或者是应该实际上应该叫semi positive definite。
不是symmetric,positive definite,这个东西会存在一个问题,问题是什么呀,前面这个系数啊有可能是负的情况下是负的,当你弹簧被压缩的时候,当我的弹簧长度小于圆长的时候。
小于l的时候,也就意味着这个东西大于一,这个东西大于一,那么也就意味着整个东西就可能是负的了,话说呢就是这个弹簧的hash,他说的时候有可能是不镇定的,它拉升的时候,当弹簧拉伸的时候,它是一定是正定的。
但是它压缩的时候就有可能是不正定了,我这里说有可能为什么是有可能啊,因为它其实还是有一些其他项的,比如说我这个a矩阵啊,它其实里面会有一些什么质量的,相对吧,我们之前有个质量矩阵嘛,它其实会有其他项目。
所以说我这里也不能保证它一定是不镇定的,但是它就是有可能会不镇定,刚才说了半天,这个矩阵正定不定,我干嘛要讨论这个东西,费了半天劲,我为什么要讨论矩阵,正定还是不镇定啊。
这个矩阵这个合成矩阵就是它的二阶导数,二阶导数是不是正的,其实跟我们前面讲实数的时候,实数函数的时候,它的二阶导数是不是真的,实际上是一回事情,先讲这个实数函数。
如果说它的二阶导数是它的二阶导数永远是正的话,它存在着唯一解对吧,一个minimal这样的道理,如果说它的二阶导数也就是现在它是一个矩阵了,这个矩阵是正定的话,我的函数也就存在着一个唯一解。
那这就是唯一的了,这其实也是对于弹簧系统来说非常重要的一点,就是如果说他这个呃永远是正的话,永远是镇定的话,又有违姐了,第一项就很大,是不是就可能更镇定啊,是的,这个我觉得这个这个同学问的非常好。
就是说这个如果越小,那么前面就越镇定,这个是不是就更镇定,答案是是是这样的,就是如果说你这个t越小,你就越镇定,可以这么想,t为什么越小t越小,也就意味着你时间不长越小吗,你时间不长越小。
也就意味着它其实每次就动那么一丁点,每次就动那么一丁点,那么跟我做显示积分其实是一样的,就是可以让这个整个系统都会变得更好,那么但是你模拟起来也就会更稳定,其实是只要是一回事情,我们刚才讲了。
就是说嗯如果镇定的时候,它就存在着唯一解,也不能严格的保证,就是他如果不镇定的时候,也未必没有唯一解啊,大家要理解,这个是一个充分,但是是非必要的条件,所以说很多时候我们仅仅只是能够做一个大的判断。
但是也没有办法在实际的模拟中,我能够做什么事情,就是很多时候我做不了什么事情,就只是说简单的我可以做一个判断,但是有一点是可以肯定的,就是生的时候相对来说会稳定很多,而你在压缩的时候。
它会更容易出一些问题,我们刚才讲了,就是说压缩的时候它会有可能会非正定嘛,那么非正定就有可可能会有多个解对吧,那么这个东西怎么用一个现实生活中的一个例子去解释呢,其实我这里可以给大家举一个例子。
可以大家想一想,就是有这么一根弹簧,我给他做一个挤压,我试图的去压他,如果我给他挤压的话,现在什么样的状况,他就会卷,它会蜷起来,对不对,他们会蜷起来的时候,它会他会有两种几种各种不同的可能性吗。
可能性就是它会往上卷起来翘起来,一种可能性它会往下翘起来,其实都有可能对吧,针对着什么,就针对这两种不同的local mini,就是它会有两种不同的状态,模拟状态,这两种状态它其实都是符合要求。
都是符合能量最小化的,我是事先并不知道它会产生是哪种状态的,这就是一个很直观的解释,为什么我们说非正定弹簧系统为什么在挤压的时候会非镇定啊,其实它就是针对的,其实就是这两种状态。
你并不知道它最终会往哪一边翘,也就意味着其实不同的这个方向其实都是可以接受的,这个现象其实在,跟三维里面会出现,但是在一维里面它其实不会出现,因为在一维里面它的导数就是弹性系数对吧,因为在一维里面。
我的这个弹簧能量是这个嘛,它的二阶导数就是k嘛,那肯定是大于零的,所以说一他没有这个问题,但是在二维三维里面,它会有这个镇定跟不正定的一个考量,然后呢就是如果说不镇定怎么办啊,其实镇定其实其实照理说。
如果说你这个呃只是为了构造这个问题的话,其实镇定镇定其实都不是一个很严重的问题,因为哪怕你不镇定,能够解出一个东西来,你总共解出一个东西来的话,你其实对于你整个模拟还是能够有一个结果的。
它其实主要影响的并不是说我们这个解能不能解出来的问题,它主要影响的是对于很多呃算法,很多线性系统就是解方程的这些算法,它可能会有些约束,就有一些线性解信息的方法,他会要求说这个矩阵必须是镇定的。
主要是很多时候他会出于这种算法稳定性的考量,它并不是说这个数学模型上稳定性的考量,它更多是从算法的角度去考虑的,我们比较常见的实操呢就是说我知道说在压缩的情况下,后面这个部分有可能是不镇定吧。
那处理呢我直接把这项给删掉就行了,那我如果说我压缩对吧,我知道这个东西小于零,那我直接把这一项给它抹掉,那么我可以保证前面这个东西肯定是正定的,那么就解决了,当然我说的这个方法是一个比较粗暴的方法了。
然后还有其他的方法,各种各样的方法啊,我这里就不展开了,反正就是大家如果感兴趣的话,可以看一下这篇叫stable,but responsive cross,在这个paper里面其实就讲到了。
就是他还列举了很多各种各样不同的方法,就是说这个矩阵如果不镇定,我应该怎么做,我应该怎么样把这个东西调整一下,能够让他更正定,然后这里我稍微给大家讲一下一些剪线性系统的方法吧,比如说jcb方法。
如果如果说大家学过数值分析的课的话,数值计算的课的话,可能可能有学过啊,如果没有学过也不要紧,因为反正我们作业里面也不会用到这些方法,反正就是给大家简单的呃,就是浏览就大概是这么一个流程。
就是假如说我要解的问题是a deltx等于b结果让dx等于零,我给它一个初值,然后呢我计算它这个recedure,residual是什么,recedure就是b减a x残差,得到之后呢。
我对deltx做更新,就是deltx加上阿尔法乘以啊d然后这个d是a的一脚,inverse乘以recedure,这个就完了,这个反正就是多次迭代,这个就叫做gq币方法。
如果大家对这个东西不是很了解也没关系,反正就是呃把这个算法给给大家看一下啊,大家所学到的教科书里面学到的结构比的方法,一般来说就是阿尔法等于一的情况,一般来说是这样子的,阿尔法等于一的话。
我们一般来说是要求这个是对角占优的呃,然后这个对角占优它其实会存在一些问题,因为很多时候矩阵没有办法保证对角占优嘛,所以这就就是为什么我们一般来说是想要有一个阿尔法值。
因为这个能让我们这个方法能够更多的条件下,更多的情况下有收敛,反正就是我我会比较推荐的就是用一个阿尔法,反正就是给大家简单的了解一下啊,解数值方法啊,之前讲数学的时候也讨论过,就是有两种不同的套路。
一个是直接法,一个是迭代法法呢反正就是对a的约束比较小,基本上能操作,但是一般来说cpu上处理的比较常见一点,迭代法呢就是呃有收敛的问题,而且他有的时候你如果想要得到精确解,它会比较慢。
但是它好在于gpu cpu都能做,而且它实现起来比较容易,所以说一般来说呃如果我自己写,我会比较推荐用用直接法啊,用迭代法,如果说有一些比较现成的数学库的话,那么我会我会建议用啊迭代,我就先跳过吧。
这个这个我会到时候给大家一个作业,这个反正我先跳过了,是这篇paper是我想给大家嗯就是课后阅读的一篇论文,然后这篇论文其实也是对于衣服模拟而言是一个蛮经典的一篇论文。
然后这个是这篇论文是最早用影视积分做衣服模拟的一篇论文,论文它其实没有用弹簧系统,他用的是另一套模型啊,也可以读一读这个paper就是对这个呃稍微有些了解,我觉得这个paper也是挺好的一篇论文。
而且如果说呃你们以后想要做一些衣服模拟的一些呃项目啊,或者改想要进一步了解的话,其实这篇论文基本上也是必读的一篇论文,论文其实就跟我刚才说的前面说的一样,他其实并没有去做,他也没有做非线性方程。
它只是把非线性方程给做了一个线性化操作,其实你读下来之后,你就会发现,它其实跟我做一次牛顿迭代,实际上是等价的,其实这里也说了,他其实等价于你只做一次牛顿迭代啊,大家可以读一读这个paper。
我是比较我比较推荐的,我想先暂停一下,就是大家有什么问题吗,前面我觉得可能,基础比较弱的同学来说,可能会有一些很清楚的地方,后面也是想用作业的方式帮大家把这个就是概念会理一理。
就会把这个嗯这个操作流程搞得更清楚一点,的思路,做钢铁好像不是很常见,好像没有,弹性体有限元,还有这个衣服模拟会更多一点,有解析解对照吗,或者是benchmark嗯,系统应该是有解析解的。
解析解好像没有,如果说一维的话,可能会有,因为一维是一个简单的简谐振动,弹簧的话,它是简谐振动,如果是二维三维的话,它有可能是没有解析解的,同学问,弹簧直线压缩拉伸有可能弹簧会弯吗,弯了怎么计算,嗯。
弹簧是不能弯的,就是它其实没有考虑到任何弹簧的弯曲,我们我们的弹簧系统本质上就是只是考虑两个点相对的位置,所以说我其实并没有考虑任何弯曲,就是弹簧自身的弯曲,我就是假设它永远是一条直线相连的。
这个其实也会导致一些问题,我们其实呃下一次课的时候我会讲,就是如果说嗯就是只是单纯的做这种弹簧的这种模型的话,其实对于弯曲模拟会存在一些很很很大的问题的,泰勒展开线性化,跟这里优化问题是等价的吗。
应对应该是等价的,如果你对影视积分做展开的话,应该是等价的,就是等价到这里面的这个线性方程应该是等价的,通过影视方程回推是通过前面这个就是,回推的吗,是通过这个这个公式得到的,kobe用来计算牛顿迭代。
牛顿迭代的话,其实里面用的方法,各种各样的方法都可以,我这里用jiob只是举了一个例子,并不代表说你就非要用jcb,其实各种各方法其实都是可以的,非线性模型多长耦合,不了解,因为,我想一想。
其实其实你这么想,如果说你所谓的多场是同样都是粒子模型的话,就是类似这种模型,说我模拟呃一块布掉到一个软体啊,那么你完全可以用这个模型来做,如果说你一块布掉到,比如说跟水,比如说跟啊流体相结合。
那么可能你就嗯嗯流体那块肯定就是没法用这个东西做嘛,它它一般来说耦合有很多耦合模型,它是通过分别求解,然后中间加一步耦合过程来实现的,所以说所以说不太一样,我可能没有时间讲吧,那个东西其实。
东西还挺多的,我到时候我怕基础不好的同学可能跟不上,所以说我这里就暂时不抢了,香蕉我其实我没有打算讲啊,我我自相交,我主要还是讲一些比较经典的算法,暂时就暂时不讲了。
讲一些就是适合用来做gpu的子相交的方式,比较基础比较弱的同学有没有什么问题,我也比较担心这个技术稍微有点基础的同学,可能相对来说听起来会嗯,稍微好一点,水拧干是吗。
其实有有不少人做过这个衣衣服吸水拧干啊,就是有一些他们做那种就是衣服的顶点上,它有一些村,比如说假如说你衣服的顶点上,你可以存一些水吗,假如说它像海绵一样,你可以一定的水的量存在那个上面。
然后假如说受到一些什么力什么的,你可以把这些水给它推出来,我我我我我觉得是这样,就是公式太多,有的时候确实会确实会一开始会会会比较懵,所以说可能就基础比较弱的同学。
到时候到时候就是课后把这些公式再给他过一遍,然后大概就是跟着我就是上课的这个讲的流程,然后大概再去理解一下,然后那个然后我前面也说了嘛,反正作业到时候会给大家布置一个跟这个相关的作业。
然后大家从作业里面再去体会一下大概是怎么样做的过程,算是吗,h如果是弹簧系统的话,是是在这里算的,给大家看一下,是,是利用这个东西算的,就是这个弹簧,假如说我有一根弹簧连接两个顶点吗。
然后连接这两个顶点,然后我利用这个公式,我不是可以算出一个3x3的矩阵吗,这是一个3x3的矩阵,3x3的矩阵摆到这个大的这个3x3的这个大矩阵里面去,摆的位置就是通过这个规则来实现的,就是利用这个规则。
你把它摆上去,这样可以不同吗,可以可以不同啊,这个没关系啊,说我们一般来就是对于每个三角形,我对三角形我先算一个质量,因为我三角形的质量我可以认为是跟它的面积相关,然后把这三角形的质量分成三份给它。
分布到那个每个三个顶点上去,然后这样子的话你呃可以得到那个你就可以得到每个点不同的质量了,这个东西是吧嗯不同的方式啊,就有一种方式就在gpu上的话,你可以用解剖比,这就是你可以用直接发帖啊。
反正因为intel的那个mk l的数据库很强大,你可以用直接法解就稍微慢一点,比比你迭代法,这是什么哦,这里给大家写一下,减x j就是这两个点的差,点位置的差,用gpu比较好是吗,都可以。
其实但供了它有一个问题,就是说共轭梯度它的效果其实取决于它的那个preconditioner,如果说你没有preconditioner的话,你用工作梯度它其实效率也不是特别高,如果在gpu上。
你的那个precondition的选择就比较有限了,你在cpu上,你一般来说你可以用那个l会比较常见,就是incomplete lu分解那种会比较常见一点,把求解支持的维度比直接法更大,对是的一。
它有一个内存开销的问题,反的话它内存开销会小很多很多,并不是计算单纯计算量的问题,你还要考虑到内存开销,有解的方程,然后退出fx,然后就转换成数值方法嗯,我这里讲的是一个推导过程啊。
就是你具体你真的模拟的时候,你其实可以完全直接利用这个非线性问题去构造构造啊啊啊,并不需要说真的去,其其其其实其实说的没错,就是说先有解的方程,先有解的方程,然后然后,数学文化数数值优化问题。
而且那个而且我就是这个这个套路啊,它不只限于这个这种饮食积分,因为影视积分也有很多种嘛,我们其实其他的饮食积分也可以利用类似这样的套路,只是他这个是会更复杂一点。
我们这里因为我只是用一个比较简单的欧拉影视积分,所以说它这个这个方程会简单一点,的话会存在无解吗,我觉得不会的,因为这个东西一定是他虽然不一定镇定,但他一定是可逆的,是啊,矩阵就这个矩阵嘛。
因为这个东西它是有这个东西是singular的能量的,喝水是singular的,然后这个这个前面加了一个质量矩阵的话,应该大概率他应该不会是一个singular矩阵,它如果singular的话。
应该就是可以求逆的,求解就是看它能不能求,能不能求逆,就是看它是不是存在呃奇异值为零的情况吗,零的七值的话应该就是可逆的,行了,前面那个,一块是比较简单的,然后到了影视积分这一块。
其实天然的就会更复杂一点,但是也没有办法,因为如果说你是要比较追求高性能的模拟,顶点数量比较多的模拟的话,它就是需要做影视积分的a的对角,a的对角看一下啊,是a的对角。
我有点不太记得半边结构是怎么弄的了,就是你的意思是就是把那个弹簧的系数除二吗,还是怎么样,的时候会用谱衡量吗,我们一般来说不会,因为那个矩阵很大的时候,你其实那个spectrum都没法算算,所以说。
所以说一般来说我们不用那些分析,问你还是很多试错嘛,就是你发现他不收敛了,那么你就把系数相对来说调参就把系数调小一点,然后看它是不是收敛,但是有一点可以肯定的,就是只要只要你不断的调仓。
他肯定是能够找到一个合适的参数,能够让它收敛的,这个还是要保证的,希望就是到时候大家做主,就是有机会的时候把作业做一下,就是第二次作业的时候做一下,然后感受就是这个影视积分大概是一个什么样的一个流程。
其实也并不是我到我到时候作业也并不是真的做影视积分,但是跟影视积分有点像,简单的一种非线性优化的方法,我们回头弹那个有限元的时候,会回来再继续谈非线性优化这一块,对于那种东西而言。
就是有有限元的那个模拟而言,它这种问题会更多一点,所以我们回头会继续弹这个东西的,那那今天就先到这里吧,然后我们下周会把剩下的这些东西讨论掉,然后我们开始讨论这些约束算法,然后那个下周是昨夜。
是下周交嘛,所以说呃我下作业就是衣服的这个模拟的作业啊,也会分配给大家,然后呃反正下然后大家可以开始先把下次的作业给看起来,看看能不能对今天的,因为我知道今天的课会有点难。
所以看看就是呃能不能通过作业把这个东西理解的更深刻一点好吧。
GAMES103-基于物理的计算机动画入门 - P6:Lecture 06 Constrained Approaches: PBD, PD and others (Lab 2) - GAMES-Webinar - BV12Q4y1S73g
行行行行行啊,我们上周呃啊先不说上桌吧,我们先做作业的事情吧,因为今天是那个今天是我们第一次作业交的日子吧,嗯然后我简单看了一下,就是有的同学可能呃时间不太够好,有的同学尤其是有的同学。
我发现都喜欢拖到最后一天,最后两天才开始做作业,嗯所以说我们这边商量了一下,就觉得可以把作业适当的延期呃,但是呢嗯如果说你晚交作业的话,那么每晚一天啊你的成绩会丢20%啊,然后如果说你玩超过五天。
那么你的成绩就不会计入到我们啊计算获奖啊,计算统计这个总拍那个总分的这个理念,但是你还是可以交作业,如果说超过五天你还是可以交作业的啊,我们还是有ta会帮你来看这个你的这个作业的完成情况啊。
但是如果说你想让这次的成绩进入到我们的总分里面的话,那么你就尽量在这五天内啊把作业完成掉,只不过就是说如果你持交啊,持交五天,这五天的时间,你每天都会丢20%的这个成绩啊,这是一点,然后嗯做作业的话。
就是说如果说你有什么问题,可以在咱们微信群里面有那个呃呃圈子嘛,那个小程序嘛,你可以到小程序里面去问呃,问问题啊,然后如果说有一些比较具体的问题,可能就是你觉得可能嗯大家可能不会碰到类似的问题的啊。
或者是你有一些啊有些比较特殊的问题,比如说你自己的代码上有些问题你可以去问助教,就有些这种问题就不需要再啊公开的论坛上问啊,如果说你觉得这个问题可能大家有可能都会碰到过的。
那么你就可以在这个呃公共的那个圈子里面,小程序里面去问这个问题,然后我还是比较希望就是说大家如果有时间的话,就是尽量还是把作业做一下,因为为什么,因为呃我觉得计算机的课都是一样的,就是你如果说不实践。
那么其实是你很难学到干货的,有的时候大家可能听听讲,那可能就是可以听得一知半解,或者是自己觉得很懂了,但是一旦你开始实践,你就会发现会遇到各种各样的问题,所以说一定要我觉得是一定要做作业,一定要写程序。
然后能够帮助你把很多知识理解到位,比如说我其实看到有的同学就是呃一开始问了个问题,然后问着问着,然后他自己就就突然就理解了,其实有很多时候就是这样子,就是作业会逼着你去很深入的去想这个问题。
可能你听ppt听听这个课的时候,可能你没有意识到,但是当你做作业的时候,他会帮助你进一步的去巩固,进一步的去消化这个知识,所以说啊反正希望大家就是把作业也作为一个,我们完成这个课程的一个重要的一个部分。
然后还有一个呃今天开始的时候,我想讲的一个事情,就是我们第二次作业,我们第二次作业跟我们现在讲的这个课啊很有关系,就是我们做布料的衣服的模拟嘛,然后跟上次作业一样,就是我也给大家了,你下下来之后呢。
也会有一个场景叫cross的一个场景,然后你双击这个场景,你打开场景之后,你就会看到这个场景里面它会啊,然后转一下这个视角,到时候你会看到有一块面料,有块布,然后还有一个球。
这个球呢是用来跟这个布做交互的,呃然后我们模拟的目标实际上就是要模拟这个布啊,然后这个布呢会有两个固定点,分别是这个顶点,00号顶点跟20号顶点,因为我们这个不是一个21x21的网格。
总共有441个顶点,我们我们把它设为固定点啊,然后我们模拟模拟的时候呢,就是用户可以拖拽这个小球进行跟这个不进行交互啊,我给大家看一下吧。
啊就首先这个是一个,这是一个结果,这个是用我们今天要讲的一个技术叫做p p t,position based dynamics实现的,然后你可以看到这个啊这个布掉下来,然后你拖这个你可以用鼠标点这个球。
然后跟这个步交互啊,然后你看这个布可以被这个球撞来撞去啊,做一个动画效果啊,然后呢呃你看到这个布它会显得比较有弹性嘛对吧,他被感觉好像就是它不像个布,它有点它它它就会弹,那这个是什么原因呢。
实际上是因为收敛造成的,我们在啊模拟这个p p t的过程中,我们实际上是用一个迭代法,那么我们需要调整这个迭代数量,如果说你想让它更弹一点,那么你就把迭代数量减少,如果说你想让它更看起来更硬一点。
那个更更不谈一点,那么你就要把迭代数量降低啊,这里没有做布料的自相交,因为这个布料自相胶做起来特别麻烦,所以说这里自相交就没有做,就只是做了这个球跟这个呃这个布料之间的相交自相交就没有做。
然后呢这个作业实际上是由两个部分构成的,一个部分呢是这个p p t,然后还有一个部分呢是我们上节课讲的那个影视积分的方法。
那如果说要用饮食积分的方法呢,就是你要换一个脚本,到时候咱们会有两个脚本,分别是一个p p t的脚本,一个是饮食积分弹簧系统的脚本,那如果说你想要用第二个脚本,你就在这里做一个切换就行了。
然后你会看到呃可以采用另一种另一种模拟方式进行模拟,然后这个就是一个用饮食积分我们做的方法,可以看到这个呃也其实也是可以达到一个比较类似的效果啊,然后这个饮食积分这个东西呢。
我主要的目的还是想帮大家巩固一下我们上周学的知识,因为我觉得可能对呃基础呃没有什么基础,没有什么模拟基础的同学或者数学基础的同学来说,可能饮食积分那一块还是呃有点懵的。
所以说我想利用这个机会帮大家巩固一下,我们上周我们做影视积分,学影视积分的那个东西,但是跟上周学的那个东西会稍微有一点不一样,因为我们上周讲影视积分的时候,我们会讲我们需要主要是两个东西嘛。
一个是gradient,一个是梯度嘛,然后另一个是喝水,一个喝神矩阵对吧,但是在实际的开发过程中,你会发现你搞这个harsher啊,所以说我们作业里面我们其实采用了一个比较偷懒的一个近似的方法。
我们没有去真的去搞那个喝水,我们其实用一个简单的一个小矩阵,一个对角矩阵去近似了它这个和声,然后在这种近似下呢,我们的那个线性系统,原来解线性系统的那一步啊。
就会变成一个很简单的一个一个更新的一个操作了,就是个利用梯度,我可以直接的把我的这个更新给它算出来,然后这个我们在作业里的描述里面会具体告诉你,告诉大家呃,怎么样做怎么样做怎么样做啊。
但是呃目前呢当前呢你就先假设这个事,反正就是我给你的这么一个magic equation啊,你就先不要去纠结说这个公式是怎么来的了,我们回头讲那个讲有些圆的时候,我们会具体讲到诶。
这到底是一个什么样的方法,然后为什么这个东西它也能收敛,也能work的,本质的原因是什么啊,反正这个就咱们就先不讲了,这个其实跟我们我其实看到就是上周就是有的同学也问嘛。
就是说为什么呃本来算牛顿法的时候是用到和神对吧,那为什么我们对这个和神呃涂涂改改修修改改,它也能收敛,也能work,其实是一个道理,就很多时候我们做非线性优化的时候,用和弦去解这个问题是一个理想状态。
但是你如果不用和神,你去近似,他用近似的方法去修改,去修改这个合成,然后呢用修改过的这个合成再去啊解线性系统,再去更新这个规则,它其实也是可以收敛的,这个我们其实在后面会嗯。
具体讲就是说他这个收敛的条件是什么啊,这个方法应该叫师,应该换个什么名字什么的,反正我们之后会讲,但是作业里面反正就是嗯给大家这么一个操作的机会,就呃其实其实严格意义上讲也不能把它叫做这个牛顿法了啊。
就反正是是一种方法吧,然后大家可以利用这个机会去呃感受一下饮食积分,大概是一个什么样的一个呃操作流程,其实总体上跟我们上周呃讲的这个影视积分解。
这个cross dynamics的这个方式是基本上是一模一样的,都是一个迭代方法,都是去构造这个gradient,然后利用贵一点的去找到这个对顶点的更新,然后去更新顶点就差不多是一个流程。
所以说希望大家就是嗯就是去把这个作业给看一下,嗯,这个有有没有什么问题,看这个海应该还在模拟,我等会看看看大家有什么问题,没问题吗,这个没有问题的话,我们就没有问题的话,我们就继续往下讲了啊。
把这个停下。
然后我们今天啊就回到我们上周我们讲了,上次没有讲碰撞,对碰撞,没讲碰撞,我是想留到下周去讲的,讲自碰撞,应该说就是跟钢铁的碰撞会比较容易,就是跟其实跟咱们之前讲的那个钢铁碰撞其实是一样的。
所以说这里就是跟那个球的碰撞,做作业的话,咱们就不讲了,然后下周我们会讲那个字碰撞,啊然后回到我们今天这个东西上,就是我们上周讲了弹簧系统,然后我们今天再细细的讲一下,就是说嗯弹簧系统它这个有什么缺陷。
有什么地方我们可以做的更好的,就其中有一个问题,弹簧系统会比较呃严重的一个问题就是弯曲,一个,一个简单的例子就是呃一个简单的例子,我给大家看一个简单的例子,就是假如说我这里有两个三角形对吧。
两个小三角形,然后呢我假设他这个两个三角形,它是一个面片,一个一个布料嘛,然后我假如说我现在用弹簧系统去模拟它这个弯曲,我怎么说我在相对的这两个顶点中间,我给他加一根弹簧,那么这就构成了一个弯曲弹簧。
那这个弯曲弹簧呢它就是阻止这两个小三角形就是翻折的对吧,这个是我们上周讲的,但是这个方式它其实是有一个问题的,这个问题是什么呢,就是说当这两个三角形几乎是平面的时候啊,他略微的弯一点。
这跟弹簧的长度其实是不怎么发生改变的,我在右边给大家画了一个图,大家可以看到把这个设置一下,应该还没全屏呢,就是右边大家可以看到,就假如说我这里是中间有个顶点,然后边上有两个边嘛。
这个你可以把这两条边就是认为是两个三角形对吧,这是一个三角形,就是一个三角形,然后假如说他开始略微的弯曲,那么一点点的话,那么对于这两个顶点而言,几乎就是在往上运动,对不对,很轻微的弯曲的时候。
它几乎就是在往上运动,那么因为它在几乎在往上运动,如果说你去测量这根弹簧的长度的话,它基本也是不变的,那么换句话说呢,如果说你用这个弯曲弹簧去构造这个这个弯曲的这种抵抗的话。
那么当这两个三角形几乎是平面的时候,当这块布几乎是一个平面的时候,它略微弯曲一点,你也是很难去抵抗它这种弯曲的这种抵抗是非常弱的,换句话说,那么这个其实跟咱们真实世界里面的这种很多这种比如说纸啊。
或者是其他这种物体,它这种弯曲的抵抗就不太像了,对不对,因为有的时候你就你想弯曲一点,他其实就想抵抗的就就产生了啊,而这种情况下,因为我是用弹簧,用这个弹簧的长度去描述的。
他这个抵抗就会变得相对来说很弱,那么我到底怎么样应该去构造这种弹簧的抵抗,这种这种弯曲的抵抗呢,那么一个很简单的一个很直观的思路,就是说我可不可以用角度,因为我这里两个面之间。
两个三角形之间其实是有一个夹角的嘛,有个c他角的嘛,那么我是不是可以搞一个模型出来,然后让这个模型呢呃利用这个夹角去搞这么一个弯曲的这个力,那这个就是它这个一个二面角方法的一个简单思路了。
这个这个方法我们把它叫做二面角方法,带hedral angle,那么打hero angle这个二面角方法呢,他把弹簧的力,它而不是把弹簧的力量弯曲的力,这个bending force。
它把弯曲的力呢写成了一个二面角的一个函数,是这个形式,因为咱们有四个顶点吧对吧,对于一个二面角而言,它其实涉及了四个顶点,所以说我其实每一个顶点上我都会有一个力。
然后呢每一个力呢是都是一个关于这个二面角的这么一个函数,这个二面角这个函数本身它其实告诉了我这个弯曲的力的大小,而后面这个部分ui这个部分啊,这个u啊,它其实就告诉了我每一个顶点。
他这个弯曲力所应该处在的方向,那么我们去构造这么一个二面角模型,其实就可以把它拆分为两个步骤,首先我要知道这个如果说我产生了弯曲的力,那么这个弯曲的力对于每一个顶点而言,它应该分别在什么样的方向。
对不对,就由1u2 u3 u4 ,我想要知道这个u应该是什么,但是注意了这几个you呢,它跟这个力的大小没有关系,它只是告诉我说如果说有弯曲的力,它什么方向,然后这是第一步,第二步呢就是我去搞一个函数。
我去描述说这个力的大小跟二面角有什么样的关系就可以了,所以说就简单的说就是把他这个拆分为两个步骤,那么首先第一步我们想要找说我们这个弯曲的力对于每一个顶点而言,都分别应该是在一个什么样的方向上对吧。
那么那个呃这个这个researcher他就他就想首先对于u一跟u2 而言,对于u一跟u2 而言,他们应该分别在这个三角形的法向的方向上,也就是说由一应该在n一的方向对吧,然后u2 呢应该在n2 的方向。
这个也很合理嘛,因为假如说我有这两个小三角形,它们发生弯曲了,那么对于这两个端点,我们怎么样去产生弯曲的力,也应该在这个三角形的法向的方向上,这个直观上是应该是怎么回事对吧,那么这是第一步。
就是我认为他们分别应该在这个法向的方向上,第二步呢就是说弯曲,它原则上是不应该导致u3 u4 这条边发生形变的,因为弯曲我其实只是说想要把这个这两个三角形搞得更平一点,或者是更不平一点嘛对吧。
我实际上是想要把这个三角形这样子转起来,那我不应该让这条边有什么变化,那么换句话说呢,在由三跟由四的,也就是由三跟由四是分别是施加在三跟四这两个顶点上的力吗,那么这两个力的差应该为零,对不对。
那么也就是说由四根由三由四减由三呢,应该是平行,应该是与这个边垂直的,也就是说他在这条边的方向上是不产生任何的力的,在这条边的方向上,这个由三减由四,也就是说他们这个相对的力啊。
他们这个相对的相互的作用力啊,相对的作用力在这条边上应该是为零,那么如果说由四减由三垂直于这条边,那么也就意味着由四根由三,它应该分别垂直于n一跟n2 ,由此减u3 e它也应该垂直于n一跟n哦。
哦不说错了,应该是由这个n跟n2 的线性组合所构成的,对不对,因为n一跟n2 是什么,n一跟n2 是两个三角形的法向量吗,那么n一跟n2 是垂直于这条边的对吧。
n一跟n2 就是这两个法向量是垂直于三四这条边,那么我同时也知道,由四根由三,由四减由三,它这个相对的力也是垂直于这条边,那么也就意味着u4 线由三,它应该是n一跟l2 的线性组合吗。
它应该是这两个这两个力就这两个方向拼起来的,这是我的第二个假设,然后第三个假设是什么呢,我要假设我这个根据牛顿定律啊,我这个总的力的合力应该为零,因为本质上对于这个系统而言,我实际上这些所有的弯曲的力。
它都是它的内力,所以说如果我加在一起,理论上不应该有其他的力,应该总合力它应该是零的对吧,因为所有的内力它加在一起应该是零,所以说由一加油,二加油三,一加油四,它应该等于零,那么也就意味着由三跟由四啊。
这里写错了,应该由三跟由四,它应该是连一跟n2 的线性组合,这个大家能理解吗,就是你如果把有一把由一个由二移到公式的右边去,那么u3 加油四等于负的u一加u2 。
也就意味着由三加油四是由一个加油二的线性组合,而由四减由三也是n1 n2 的线性组合,所以说它由一由三根由四,它也必然是m一跟a2 的线性组合,这个其实是一个一系列的假设,一系列的推理。
这个大家反正呃如果说搞不清楚也不要紧,重要的事就是我们之后会有一些结论了,当然这个结论我其实是直接给大家的,就就就直接跳过了啊,啊这个过程我就不讲了,反正最后就推出来这个u1 u2 u3 u4 。
它分别是这么几个公式构成的,你其实可以看到这个和跟我们前面的那个p p t给的那些东西,是一样的,就是u一可以看到它实际上是在这个n一的方向的,然后u2 是在那的方向的,然后u3 由四。
它分别都是n一方向跟n2 的方向的一个线性组合嘛对吧,然后我没验证过,但是大家回头可以,如果感兴趣可以验证一下,看看是不是这四个东西加起来等于零啊,按照定义它应该是等于零的。
然后这个n呢它其实不是法向量,它其实只是做了一个cross product啊,大家如果记得的话,还记得的话,就cross product会告诉我们这个三角形的方式,normal的方向。
但是如果说你真的要得到法向量,你其实还是要对这个东西做个normalization的啊,这里啊他们就没有做normalization,就是直接做cross product就行了。
你可以认为是一个比较原始的normal,就是没有normalize过的一个normal,得到了这个u1 u2 u3 u4 之后呢,我就完成了第一步,就是我知道了,说我这几个力对吧,我几个弯曲的力。
它们分别处在什么样的方向上,然后接下来我就是要定义一下这个弯曲的力的大小对吧,我要根据我这个角度,我要搞一个大小呃,那么这里我反正也是还是给大家这个公式了,这个我啊我就不解释。
我就不说这个这个公式为什么是这样,为什么是这样的,反正这个论文里面是这么给的啊,我也就是照搬了一下,那么他说什么,他说这个力的这个力的大小啊,其实就是公式的前面这个部分啊是一个常数。
一个系数乘以这个边长的平方除以两个三角形的面积啊,这个这个cross product的这个magnitude,它其实就是两个三角形的面积,再乘以sin,然后这个派减c它除以二,然后这是个平面的情况。
为什么说它是平面的情况,因为当theta等于180度的时候啊,这个力的大小等于零,因为sin派减派等于零嘛,所以说当c塔等于180度的时候,我是没有任何的弯曲的力的,这是一个呃没有力的情况。
相当于是一个静止的情况,然后这个模型呢有一个比较好的优点,就是说我也很容易扩展到非平面的情况,如果说比如说我假如说我想有一个初始的一个角度,有一个初始的二面角,那么我只要有一个c塔零。
然后完了c t0 之后呢,我就引入了一个新的项,就是减去sin这个派减c t0 除以二就行了,跟前面的那个公式也是一样的啊,然后这里其实我跳过了一些细节,就是比如说这些公式是怎么推出来的啊。
啊然后啊就为什么是这个为什么是函数是这个形式啊,啊这个反正这个在paper里面论文里面大家可以看到,如果大家感兴趣的话,可以读一下这个paper,这个其实也是一个一篇满经典的paper啊。
它里面其实不只讲到了这个弯曲模型,它其实还讲到了其他东西,比如说啊就是自拍状是怎么处理的啊,然后他是怎么样做这个积分的,因为这个是一个蛮早期的paper嘛,一个03年的paper。
所以说他们就没有用影视积分,他们采用的是一个比较显示的积分方式,做了这么一个啊力的模型啊,这个lead模型的这个缺点呢呃也比较明显,就首先它其实你看我们整个推导的方式完全是基于力的对吧。
我们假设力应该是一个什么样的形式,力应该是什么样的方向,力应该什么样的大小,我就构造了这个力的模型,这里面其实没有谈到任何关于能量的东西啊,有同学问c塔零是什么。
c塔零就是说假如说你假设这个这个这个面啊,这两个三角形它的静止状态,它不是平面的话,那么c a0 就是它非静止状态下这两个角度,这个角度应该是多少,就是c塔零实际上就是它静止状态的角度。
其实这里面就平面的case,你也可以认为这里其它零是一是180度,只是因为c301 180度的时候,后面这项就等于零了,所以说我们就直接把它剔除掉了,而有的时候比如说这个呃两个三角形,它可能静止的时候。
它中间会有一个非180度的夹角,那么这个时候你就要用c t0 去定义这个啊,这个夹角在静止状态下的角角,我们刚才说这个呃这个模型呢它因为直接是关于力的,没有任何能量嘛。
所以说啊这是一个他做显示积分会比较容易,然后做饮食积分的会也不是说不能做吧,但是会比较麻烦一点,因为你看前面这个模型,其实你要去算它的这个导数还是挺麻烦的,所以说也不是说不能做吧。
但是你如果想要拿它做饮食积分啊,拿它来做求导啊,就会就会麻烦很多,但是我觉得这个是也是一个呃有些系统里面还是比较常见的模型,就是大家用的也很常见的,所以说我是建议大家有时间把这篇paper读一下。
而且这篇paper其实可以从头到尾的去读一下,因为它里面除了关于它的弯曲模型,它其实里面还是有一些蛮有意思的一个设计的,这是一篇paper,然后呢大家就想就说有没有稍微简单一点的弯曲模型啊。
因为前面那个模型虽然说比较直观,就是算力搞了个力的方向,搞了这个力的大小,然后算力它比较直观,但是有没有更简单一点,好操作一点的模型,所以说大家后来又搞了一个模型,这个模型呢它其实是有两个假设的。
他一个第一个假设就是说它假设我这两个三角形啊,啊它也是基于这种呃这种两个三角形,两个相邻三角形的这种模型的啊,他第一个假设是我这两个三角形它静止的时候是应该平面,它比较容易处理这种情况。
就是两个三角形静止的时候是平面状态,对于布料而言,这个问题不大,因为反正我们布料静止的时候就是个平面嘛,所以说我其实这个假设是ok的,然后第二个假设是说我这个三角形啊,它模拟的时候基本上没有什么拉伸。
没有什么形变,它主要是弯曲所产生的一些动画效果,所以说它拉伸是非常小的,这是我的两个假设,在这两个假设的基础上呢,嗯这个模型呢基于拉普拉斯变换呢,他就搞了这么一个能量函数,它定义了这么一个能量函数。
他这个能量函数大家可以看一下,它其实是相当于是一个矢量对吧,一个矢量乘以一个矩阵,再乘以一个矢量,乘以它自己所构成的,然后前面除以1/2,那么这个矢量就是这个矢量是什么呀。
这个矢量就是把这四个顶点按顺序排了一遍吗对吧,这个就很简单,就是顶点全都排了一遍,然后中间是一个矩阵,这个矩阵q我把它写在下面了,就这么一个形式,前面呢是一个常数三除以面积和面积是静止状态的面积。
所以说我直接就把它算出来了,这是个常数前面,然后后面是q乘以q transport,那q是什么呢,q实际上是一个向量啊,然后这个向量是什么向量啊,是一个是一个12x3的一个向量,12x3。
然后这个向量它其实就是由一堆被缩放过了的identity matrix构成的,那每一个identity matrix都是一个3x3的矩阵嘛。
每一个identity matrix单位单位矩阵是个3x3的矩阵,然后每一个矩阵我前面都给他乘一乘一个系数,然后呢下面也是cott和,然后再下面是两个负的cott和,然后下面也是负的cott和。
然后这个这几个角度是什么呀,然后我这个反正这个画在右边了,大家可以看到c他零是啊这个角,所以它一是这个角,所以他二是这个角,所以他算是这个角,啊然后这个是我的这个qua。
这个q这个q是一个我刚才说的是12x3的矩阵吧,所以说这个小q是12x3的矩阵,然后我根据这个公式我计算一下,就可以得到一个12x12的矩阵,所以说这个结果就是一个12x12的矩阵。
啊然后这里的话大家可以看到每个向量都是一个12,12个顶12个元素构成的嘛,对吧,12x1,因为每一个都是一个三维三维向量,然后有四个,所以就是12x1,然后这边是1x12,中间是个12x12的矩阵。
然后我就得到了这么一个能量函数了,然后呢你可以看到这个能量函数是一个什么样的形式啊,它其实如果说你把它变换一下的话,你会发现它其实就是q transpose乘以x,然后这个东西它其实就在计算。
它在估算这两个三角形的拉普拉斯,那么拉普拉斯是一个什么玩意儿呢,它其实就是告诉你这个两个像两个三角形之间的一个曲率,然后呢你平方一下,其实就把这个曲率的大小给算出来。
我们如果说两个三角形是一个完美的平的时候,它的曲率是零,所以说ex应该等于零对吧,那么如果说我这两个三角形开始弯曲了,那么它的这个曲率向量就会越来越大,越来越大,那么最终我这个能量也会越来越大越来越大。
那么产生的力相对应的也会越来越大,越来越大啊,这个其实就是它的一个基本思路吧,然后其实大家可以验证一下,如果都在同在一个平面上,那么这个东西你算出来的这个曲率向量应该是零,然后ex也等于零。
或者是一个客户的思考题吧,就是你可以证明就是利用这个cotent的这个权重,然后把这些呃叠加在一起,然后你会发现这个它的ex等于零,啊然后有同学问这个物理这个能量是物理推出来的吗,嗯其实不是。
这个不能说叫物理推出来的吧,它实际上是根据数学的数学里面的曲率推出来的,它因为我们计算一个平面的曲率啊,尤其是它的这个平均曲率的时候,就是用拉普拉斯变换来算的,所以说它这个东西实际上是通过曲率的定义。
然后根据拉普拉斯平面的那个,他这个曲面的曲率的这个方式来来推导出来的啊,但是如果说你根据更加物理的方式,其实照理说是应该根据测量的方式去做,其实也有一些研究吧,就是说他们设计一些实验。
然后利用这个实验去啊评估这个能量,这个反正我这里就不展开了,因为这个东西其实后来搞这方面的人也不是特别多,因为但我也不知道什么原因吧,反正可能一方面就是测量这方面比较难搞。
然后另一方面就是误差所带来的影响可能也会比较大一点,所以说一般来说后来大家就是基本上还是以这种模型,这种根据曲率搞出来的这种模型跟前面这种二面角模型会为主,content是怎么出来的是吗。
实际上是从那个拉普拉斯算子的那个东西出来的,拉普拉斯就是一个曲率,比如说一个三角形嘛,一个曲面三角形,你可以认为一个三角形网格,它是一个曲面,那么三角形网格的拉普拉斯的那个呃。
那个那个离散拉普拉斯的那个operator,它其实就是contagent weight所拼出来的,所以说他这个东西其实是从那里面推出来的,但这个过程我其实这里也跳过了是吧,反正你有大家有兴趣的话。
可以去看一下那个论文,我印象中那个论文好像也没有推导过程,也很奇怪,他也没有推导过程,反正他就是直接给你了,给你这些权重了啊,其实你可以自己也可以去验证一下,反正我之前是验证过的。
就是你按照这些content的权重,你把它这个假如说这个三角形是个平面啊,这四个顶点是在一个平面上,你会发现这个加起来确实是等于确实是等于零好吧,但反正这里咱们就不展开了。
就反正就是给大家这么一个公式告诉大家啊,其实还有这么一个方式,那我刚才说这个方式比较简单,对不对,之前二面角的意是啥,二面角之前二面角没有意义,这是其实是咱们前面二面角这个模型的一个缺点。
因为它二面角的模型是完全根据立出来的,它的力的模型,所以说它就没有任何的e的这个定义了,这个其实也是kda banding的一个优点,就是它其实是有能量的定义的,而且他其实还有一个更好的优点。
就是它的名字correlic,大家有没有注意到这个公式里面这个q实际上是一个常数矩阵啊,它其实是一个常数矩阵,它跟顶点的位置是没关系的,那既然是个常数矩阵,跟这个顶点的位置没关系。
你就会发现这个e它其实是一个关于x的一个二阶的这么一个方程,一个公式嘛对吧,它是一个扩拽的一个函数,它是一个二次函数,所以说它有一个很大的优点是什么,它的这个力。
它的这个一阶导这个力跟他的喝水都很容易计算,你立怎么算,你只要把这个q乘以这个向量就行了,然后前面加个负号就完了,这个q是一个常数矩阵,我事先计算出来就好了,和成就更简单了,合成直接就是这个q。
它最大的好处就是我如果做影视积分的时候,他就特别方便啊,这些关于这个bending的这些全这些矩阵啊,这些力啊,他都特别容易算,这是它的一个很好的优点。
然后它的缺点呢就是说如果说你这个物体它如果拉伸的很厉害对吧,这个面料如果拉伸的很厉害的话,他这个假设就相对来说就没那么准了,不是说不可以模拟啊,但是它可能它就是存在一些问题,他的他就他的描述。
这个曲率的定义就不是很合理,然后呢还有一个前面咱们前面还讲了一个假设嘛,就是我是假设这两个三角形是平面嘛对吧,那么如果说如果说这个三角形它不是平面怎么办,这两个三角形它不平不平的话,我其实也有一些方法。
比如说论文的作者,他们后来又搞了一个模型,叫做cubic shell,就是他发现如果说不平的情况下,我也可以搞个能量函数,只不过这个能量函数它就不是二次的,它是关于顶点的三次函数了,这是一个。
然后还有一种方式是我们回头会讲的,叫做projective dynamics,但是他这个模型,它这个论文里面其实是可以用到这种方式的啊,但是我们这里就不展开了,有同学问二面角没有,没有能量的话。
是不是不能用影视积分求导啊,影视积分其实还是可以的,还是可以,因为你只要能只要能对利益算他的一阶导数,你还是可以得到它的合成的,只不过他这个推导过程会更麻烦一点,只不过我们就就就假设有一个力吧。
但是我们就不真正的用到这个力,就直接就是对这个呃呃呃呃我们就假设有一个能量,但是我们并不真的去计算这个能量,我们也讲我们也不考虑这个能量是什么形式,我就直接对力求导啊,就可以得到合成,就还是可以做。
只不过就是会麻烦很多啊,也缺乏一些缺乏一些概念上的定义,能量的思想能在缸体上模拟吗,一般来说大家大家不会用能量,因为能量我们这里的能量是什么能量,它其实是弹性能量,那钢铁它没有弹性。
所以就无所谓能量不能量了,这个我是觉得gt其实一般来说不太会用到能量的思想,因为我们做能量的主要的目的就是因为它有弹性嘛,它是有势能吗,所以我们这个e它其实就是势能。
然后这是这篇我刚刚讲了半天的这篇论文啊,叫做cdc bending model for intenable surface,然后这个paper我觉得也是也是也是一个蛮经典的paper吧。
cubic shell其实是啊,就有同学问cubic shell的模型是啥,这个cubic shell基本上就是基于这个paper往下走的,相当于这篇论文也是同一批作者。
他们好像隔了1年就又发表了一篇论文,就是基于这个这个模型,然后又做了一些扩展,然后搞了一个搞了这个模型,反正感兴趣的话可以去读读那个那个paper,反正是同一个组,同一批人写的一篇paper。
好然后我们来讨论一个我个人觉得在布料里面,模拟里面是一个蛮重要的问题啊,真的一个问题叫做locking issu,就是我们之前就讨论了什么,讨论的就是弹簧系统,还是讨论各种弯曲模型对吧。
我们其实都是有一个假设的,我们假设这个布料的拉伸跟布料的弯曲,他应该是不影响互相不影响的关系,那么原则上呢原则上呢如果说一个布料是没有任何拉伸的,就是他是非常非常怎么讲,非常坚挺的啊,不应该叫舰艇。
就是他很stiff对吧,你没有办法去拉伸它,比如说有很多缩汁的面料都是没有什么弹性的,无法拉伸,但是它这个布料还是可以弯曲的,我们在现实生活中,我们见过很多这样的情况对吧,很多缩汁的面料。
这个纸你是很难拉动它,它几乎没有弹性嘛,但是纸张我们照样可以弯曲,但是如果说我们做模拟也会出现这样的现象吗,也是也可以做到这一点吗,大家可以想这两个例子啊,同样都是有这么两个三角形。
我假如说我有一个有块布,我是用这两个三角形构成的,那么我考虑我有两种分别把它弯曲的方式,一种是沿着我中间这条对角线的边弯曲,然后另一个呢是我转了90度,我换了一个角度进行弯曲。
假如说我这个弹簧是非常非常没有弹性的,就非常stiff的,非常刚的弹簧,大家想会发生什么,是不是右边这种情况她就弯曲不了了,因为我中间为什么我右边这个情况会弯曲不了。
因为我中间这根弹簧会把我这两个三角形给顶在那里,我再怎么弯曲,我也弯曲不了对吧,这是一种很奇特的现象,我左边这个情况不存在,为什么,因为我这条中间这条边就是跟我弯曲的边是一致的。
我就可以很自由的对这两个三角形进行翻折,但是右边呢,因为我假设我这个弹簧非常非常的坚挺啊,我想要沿着这个右边的这条边进行弯曲,我会弯曲不动,我会没有办法很自由地去弯曲,会把我这个给卡死在那里。
那么这个我们把它叫做locking issue,就换句话说我整个布料,整个衣服的这个系统啊,他被锁死了,被我这个弹簧系统给锁死了,那么这只是一个表面现象,本质的选项是什么。
本质的现象实际上是由于自由度的丢失所造成的,因为大家可以想就是根据欧拉的一个公式,欧拉公式说你编的数量,这个是所有的边的数量,对于一个manifold,所谓的manifold。
大家可以认为就是一个我们比较常见的一个三角形,相邻三个三角形,这种这种结构叫做manifold,一个三角形相邻三个,或者是就是每一条边上分别相邻一条三角形。
这种比较正规的这么一种三角形网格叫做manifold,但这里我就不展开了,然后man对于manifold而言呢,正常的这种正常的这种三角形网格呢,欧拉定律说。
边的数量等于顶点数量的三倍减三减去所有的边界上的边的数量,那么换句话说,假如说我进行模拟的话,我有多少个变量啊,我有三乘以顶点数量的这么一个变量对吧,这是我的总的变量数,3n n是顶点数量。
但是我编的数量呢同样很多,而且它也是几乎是三个顶,三乘以这个顶点数量,那么真正我的自由度实际上是什么呢,实际上是我的变量减去我的约束,因为我所有的编实际上都是我的约束嘛,那么我的变量减去我的约数。
就是我真正的自由度,我的真正的自由度是什么,我只有三家边界的数量的自由度,所以说换句话说,我其实做这个三角形网格的这个模拟,我的自由度其实是不够的,而且你如果是模拟一块比较比较方块的这种布。
它的自由度会更不够,因为它的边边界上的边的数量会更少,那么怎么样去根本上的解决问题呢,啊以前不说根本上解决问题吧,就是说先说实际上在操作中解决什么问题呢,有很多各种各样的套路啊。
比如说我可以让弹簧压缩的时候,我可以把它的弹性系数搞得小一点,因为我压不动对吧,我这块面料我比如说弯折不动,那我就把弹性系数搞小一点,那么是不是就可以把它弯下去了,对不对,这是一个套路。
然后还有一个套路是什么呢,就是我不要上来就施加弹簧的力,我可以先假设这根弹簧在一定长度范围内,它是可以自由活动的,它是没有任何力的,没有任何能量的,这也是一个套路,但这些套路他其实都不根本的解决问题啊。
然后还有一篇paper是呢说什么呢,就是说我可以帮自由度改一改,我不要把我的自由度定义在顶点上,我把我的自由度定义在边上,就把事情会搞得更复杂了,这就是另一篇paper,这个啊反正我就提这么一句话。
就是给大家提一下,然后我倒是也不建议大家就是呃去花时间去读这个paper,因为这个paper你读完之后,你也会想,就是说其实他这个方法也是很难实际应用在我们的这个模拟中的。
因为当你把自由度定义在边上的时候,又会引入其他的问题,但但是我之所以想这个题这个事情就是想提醒一下大家,就是模拟里面会有这个locking issue。
而且这个locking issue当你在你弹簧的弹性很弱,也就是弹簧很stiff,他很没有弹性的时候,还有当你这个网格的分辨率会很低的时候啊,他这个locking issue会变得很明显。
你会发现这个布它就弯不下去,因为为什么,因为我所有的弹簧都把它撑在那里了,这个是我想提的一点,然后呢其实也没有,我个人觉得其实也没有,目前也没有什么特别完美的解决这个方式,大家都是调参啊。
或者是一些比较high的方式来解决,给大家提个醒好吧,然后这个这个我想跳过了,因为我本来是想再讲一讲shape match,拿来模拟这个布料的这个方式,但是我想这个跳过,如果大家感兴趣的话。
可以回头看一下,我想给大家讲的,今天讲的一个第二个,话题呢就是约束就是约束方法,这个约束方法其实是哦对了,先停一下,就是前面大家有什么问题没有,因为现在要讲一个新的topic了,还在打字吗。
为什么是三家变,locking有几种啊,为什么是三家便,因为这里是3m嘛,总的自由度,总总共的顶点数量是3m,也就是三的顶点数,然后边的数量是约束的数量,所以说自由度是自由度。
是变量的数量减去约束的数量,所以说是三倍的顶点数量减去这个东西,所以说就是三加上这个东西,locking有几种locking,什么叫做几种,其实没有说所谓的locking有几种。
这个locking一首它其实是一个现象,他这个现象就是说你的弯曲实际上是会被你这个拉伸弹簧,拉伸的这个弹性所干扰的,当你这个拉这个弯,这个拉伸的弹性系数很大的时候,它会导致你弯曲会受影响。
会让你觉得好像弯曲很强,事实上它可能弯曲并不是很强,有同学问为什么不用四面体网格,可以用四边形网格,就是如果说你用四边形网格的话,你其实可以一定程度的解决这个问题,是如果说你中间四边形网格。
你中间又加对角对角弹簧的话,它还是会产生这个现象,还是会有这个问题,然后有同学问布的顶点多一点会不会好啊,其实并不会,因为你布的顶点多了,你的边的顶点也会,你的边的数量也会多,因为你顶点多了。
你边也会多,然后最终导致你的约束也会同样也会产生多,为什么帮助帮助edge和edge的区别,就帮助edge就是就是边缘上的edge,就是比如说我给大家举个例子吗,比如说前面这个例子嘛。
就比如说我这这有43条,就有五条边对吧,那么boundary edge就是这四条边就是在边上的边,那中间的这条边呢就是inner edge,就是中间的这条边,有限元其实也会导致同样的问题。
有限元其实也有locking issue,其实道理是一样的,就是你的约束太多,约束太多就会导致你自由度丧失,为什么boundary edge不算自由度啊,不是说不是说不算自由度,而是说根据这个定义。
它这个约束的数量,总共的约束数量是这么多,所以说所以说你这个约束的这么多之后,你用你用顶,你用顶点的数量乘三去减去约束的数量,你就会得这个公式,为什么弯曲跟弹簧的k有关啊。
理论上这就是我们我们在讨论的这个问题,就是理论上它应该是无关的,是因为我们模拟的时候,我们采用了这么一个弹簧系统,它就会导致它相关,因为它会把它锁死,就是你可以看这个图嘛,如果说假如说我想要沿着这条。
你可以想,假如说我要假如说我想要沿沿着这条边弯曲,你会发生什么,你会发生什么,你会发现它弯不下去啊,为什么弯不下去,因为中间的这条边内部的这条边把它给抵住了,不会把它顶在这里,所以说会导致它弯曲不下去。
本身上本质上是因为我们这个数学模型,我们这个呃弹簧系统模型,就是我们模型的一个本质上的一个问题,弹簧这里的约束是12,什么叫做弹簧约束是12啊,就是我这里你看比如说我这里吧,我我我就拿这个例子举好了。
实际上本质上也是因为这个原因,就是我本质上是一个离散的一个模型,它它没有足够的自由度,我举这个例子好了,我有四个顶点对吧,我总共的自由度理论上的自由度应该是12码,然后接下来我有几条边,我有五条边对吧。
所以说减五,所以说我实际的自由度是实际的自由度是七,有同学问为什么加点,比比如说我这里中间加一个点对吧,我中间加一个点的话,我你看我我其实我我加了一个点之后,我我多了三条边,虽然多了一个顶点。
我多了三个自由度,但是我的约束也多了三个,所以说最后得到的还是起,就是其实你加点就是怎么就是光是单纯的加点是没有影响的,但是你分辨率高,你会让顶点更密,这个其实是可以改善的,就是你的顶点数量更多。
你更密了以后它会改善,但不是代表说这个东西不是因为不是因为我的顶点数量多造成的,而是因为我的顶点密排列的密所造成的,中间的弹簧变成两段,可以解决这个问题吗,他如果说你把中间变成两段。
就是比如说你多了以后,他可能在这个状态上不会有问题,但他其他方向又会有问题,就比如说举个例子,比如说我中间加一根弹簧,中间加一个点,变成这个形式对吧,那么你换个方向,比如说我想要沿着这条边怎么办。
他是不是也会存在同样的问题,就是他怎么说呢,就是它没有办法在根本上去解决这个问题,加点也好,还有加鞭也好,他其实没有办法在根本上解决问题,只能零四的解决问题,弹簧的k调小可以解决问题吗。
就是你在视觉上可以解决这个问题啊,视觉上可以解决问题,但是我说的就是它根本上是存在这个问题,就只能说你做一个,比如说模拟一个动画效果啊,你开发一款游戏啊,你就尽量把有些弹簧的弹性速度搞小一点。
可以让这些问题不明显一点,但这个这个问题始终是存在的,明白吗,然后我接下来就想讲这个这一块,我想把这个问题,如果还有别的问题,咱们可以留到课后,然后呢我今天我估计可能就只有点时间就讲第一个东西了。
就是dynamics,然后这个东西跟大家做作业有关,咱们作业里头会用到,所以说我们我们会先把这个东西讲一下,之后有时间我们会讲后面两个东西,projective concert damics。
今天讲的可就这一块讲的这个ppt上讲的东西都是跟约束有关的,那么我们约束想要解决一个什么问题,就是解决一个真实真实世界跟模拟的差异的问题,我们在模拟真实世界,真实世界里面很多面料很多cross。
它其实都是拉伸,其实都是有比较强的抵抗的,你都很难去拉动它,或者说它是一开始比较有弹性,但是拉到一定程度,它就很难再拉动了,但是我们如果做布料模拟呢,你去把这个k你把这个弹性系数搞大呢,会带来一些问题。
对于显示积分而言,会导致这个显示积分不稳定,对于影视积分而言,会导致信息系统叫做econdition,那么这些问题呢虽然说不是说很致命的问题都可以解决,但是他们的问他们的这个难点在于什么。
难点在于这些解决方式最终都会带来很大的计算量,比如说我用显示积分,我可以用小步长,用影视积分我可以搞多迭代,我都可以解决,但是我都要花更多的计算时间吗,大家都在想。
就是哎我有没有什么办法可以就是比较简单的去处理这个问题,这就是大家的一个初衷,不见得不见得这个初衷是能够被完美解决的,但是反正就是大家就是想就是怎么样去处理这个系数很大的时候。
我还可以比较好比较简单的去模拟,那么我们首先来讨论想想,如果说只有一根弹簧,我怎么去构造这么一个模拟方式,假如说我只有一根弹簧对吧,我可以把这根弹簧的长度写成一个约束,这个约束我把它叫做ffix。
这个约束呢本身它是一个函数,那么函数呢你就是实际上就是弹簧的长度减去它的原长嘛,那么这东西等于零,也就是我的这个约束,就是卧室,我是希望这个弹簧的长度刚好等于它的原长的,这就是我的一个一个约束。
那么有了这个约束呢,我接下来我就想要定义一个函数了,这就是我们所谓的一个投影函数,这个函数做了什么事情呢,就是这个函数呢会让我这两个顶点满足我这个月数,这里就举两个例子,假如说这根弹簧啊。
其实不应该叫弹簧了,就是一条边了,假如说我有一条边这两个顶点,它这俩的距离是大于圆长的,它被拉伸了对吧,那么理论上呢我就应该把这两个顶点互相挪近一点,挪对吧,他们互相靠近一点。
那么最终我可以得到两个新的位置,那么这两个新的位置中间的距离可以满足这个我这个约束的要求,就是延长,满足延长长度的要求,这是拉伸的情况的情况也是一样的,只不过我不是把这两个顶点再往彼此靠拢。
反过来我想让这两个顶点互相远离,x j我也往远处走,那么得到了两个新的位置,这个其实就是我所谓的这个投影函数,projection function,想要做的事情就是把这个两个顶点给他,怎么样修改一下。
修改完了之后呢,可以满足我这个需求,那么我可以把这个问题想象成一个投影问题,假如说我现在是一个六维空间,比较高层次一点是一个六维空间,当前的这个顶点位置是六维空间中的一个点。
那么如果说我把满足我这个约束条件的顶点的集合,认为是一个区域的话,这个omega是一个合理区域的话,实际上想要做的投影是什么呢,想要做的就是怎么样去修改这个顶点x,让它落到我这个合理区域里面去。
这个区域这个下面这个红绿蓝颜色的这个合理区域,就是所有满足这个顶点所构成的区域,光是挪还不够对吧,挪到区域里面还不够,我还希望我挪的这个变化量足够少,就是说我不只是想要挪到里面去,我还要挪到最近点。
那么这个图上比较简单,就是这么一个绿颜色的这个位置,这个位置它刚好处在这个边界上,同时它也是离我们的原来的这个点是最接近的,一只就可以一个数学问题了,那个带约数的数学问题了,这怎么想的,就是前面呢。
上面这个东西做的讲了什么,讲了,就是说我挪的这个要足够少,我要尽量想要让这个点结果是足够接近于原来的位置,我想尽量挪的少,同时呢我要求我的结果,我要求我的结果是满足约束的。
也就是说我要保证我的结果是落在这个合理合理区间内的,这个是我们数学上的一个定义啊,就是关于投影的定义就是第一我想要挪,挪完之后,我要满足约束,第二我希望挪的这个改变量足够少,我这搞这么一个投影函数。
那具体的推导过程我就不讲了就不讲了,反正大家如果感兴趣的话,可以去课后可以去呃退退,就是哎到底是一个什么样的流程可以得到这两个结果,是直观上也是比较容易理解这个东西的啊,怎么理解呢。
就是说对于这根边而言,这两个顶点而言,我是希望它的质心是不变的,希望它的质心永远在同样的位置上,这是我的一个前提,志心同样的位置上的前提的情况下呢,我希望i跟g分别朝着志心或者远离至新的方向运动。
也就是说他始终沿着这个原有的这条边是方向上的一道,它运动的量实际上是由他们相对的质量关系所决定的,质量越大,它理论上应该挪得越少,量越小,那它理论上应该挪得越大,基于这些点,基于这些条件。
你其实就可以最后推推推,你就可以推出来这么两个公式了,就基于这个我们前面说的这个质量和这个质心动跟,然后其次就是每一个点挪动的量跟它们的质量相关,就这两个前提条件,然后你可以呃也可以课后做一个验证嘛。
你会发现就是呃这两个顶点相减的位置相减啊,你会发现它刚好等于原长,也就是意味着说我新的这两个点它其实是满足我这个约束的,在来说我们做模拟啊,很多时候我们其实对质量其实倒是没有一个特别强的一个规定啊。
大家比较偷懒,一般来说就直接假设所有的质量都是等于一或者是质量相同,有的时候我其实想要也有,也有一些呃比较极端的情况,比如说我假如说我这是一个固定点对吧,我固定你怎么做,我可以认为这个质量是无穷大的。
当这个质量是无穷大的,那么按照这个公式你就会发现啊,对这个点而言,它就会静止了,它就不会动了,这就是啊质量无穷大,或者是实际实际上你写代码肯定不可能把这个质量写成无穷大。
一般来说就是用一个很大的数字去描述啊,是一种ppt里,这是一种做这个约束里面我可以用的这种模拟方式,作业里面我其实给大家提了一个简单的要求,就比这个还要更简单一点,怎么做呢。
就是直接把定点从更新里面去掉,你就不更新它,你就完了,对不对,很简单,你就你就不要更新它吧,那它就是固定点,如果说你还是想要把这个东西放在这个模拟过程中的。
那么你也可以用这个把质量设为无穷大的这么一个方式,你好,我们这个简单地给大家介绍了一下,就是一根弹簧,假如说我有一根弹簧,一根边,我可以利用这个公式,我去修改顶点的位置,我可以满足我长度约束的要求。
那么我怎么来处理多根弹簧的情况,问题来了,我说我有好多根弹簧,我怎么办,那么有两个方法,这种方法叫做高斯赛德尔方法,赛德尔方法,它这个名字其实是从写信息系统的高赛德尔方法引入过来的,借鉴了那个思想。
但什么意思呢,就是说假如说我有好多弹簧的话,就一根一根一根的弹簧去处理过来就完了,对不对,我这里有两根弹簧,有两个边,分别连接了零一跟二对吧,假如说弹簧现在的长度是二,静止的状态长度应该是一。
我怎么办呢,我就按顺序处理这两根弹簧吧,我先处理上面这根弹簧,上面这根弹簧,我给它搞成长度为一,那么根据我前面假设至心不变原理啊,可以分别把x0 和x一分别往这个智星分别往中间挪,弄完之后呢。
我这个长度就变成一了,我这个上面这个弹簧的问题解决了,接下来我处理下面这根弹簧弹簧,我下面这根弹簧的长度也发生了改变,我变成了25,我之前是二,现在我变成了25,根据我之前说的志心不变的这个简单原理啊。
我就分别把x一和x2 也往智心挪,读完之后呢,下面这根弹簧的长度也是一了啊,然后下面这个弹簧的问题解决了,大家回过头来会发现什么,对不对,你说我还是要回过头来去处理上面那根弹簧的。
我还是按照之心不变的原理,我去挪上面这根弹簧,我把它搞成一,再回过头来我又去处理下面这根弹簧,再把它搞成一,然后以此类推,对于每一根弹簧我都按顺序啊,一个特定的顺序,我把它处理一次,每处理一根弹簧。
我去修改弹簧相连的那两根两个点,然后我再处理下一根弹簧,我再处理下面那一点啊,把它从头到尾处理一遍,那处理一遍,完了还不够,我还要多处理几遍,为什么,因为我光处理一遍。
这跟弹簧的长度没有办法保证都满足吗,我就还要多处理几遍,处理的越多,这个迭代数量越多,你会发现弹簧长度慢慢慢慢的可以收敛,可以逐渐的往这个我们想要的原厂去考对吧,可以尽量满足约束条件。
这个就是一个蛮简单的一个套路,一个高塞德尔的一个方法,处理多根弹簧,我就搞两个循环,两个迭代里面这个循环是循环所有的边,因为每根边说相邻的这两根顶点i跟j呢,我利用之前的公式,我把它新的顶点位置算出来。
把它新的顶点位置算出来之后呢,直接直接去更新这两个顶点的位置,把这个更新给释放给施加出去,然后我就分就是按顺序我把所有的边都处理,然后同样外面我还需要有一个迭代,这个迭代的主要目的就是为了。
我保证我所有的边都是能够相对的比较好的去满足约束的,坏话说回来,我虽然说我可以有这么一个收敛的趋势啊,那边这些边逐渐逐渐的满足这些啊,尽量的去靠近这个圆场,但我是没有办法去严格的保证所有的边都能满足的。
永远都是有一些变,它是不满足的,不在于我做得越多,我迭代数量越多,那么原则上我这些约束就是能够尽量地更好地去满足它越多,那么约束会更好,还有一点我想提的就是说虽然说他较高,塞德尔。
它其实并不是真正的高赛德尔,它其实跟数学里面的高赛德尔实际上是有差异的,我自己发现,一个叫做stochastic,gradient decent,其实更有关系一点。
只不过他这个东西不是stochastic的,它是有顺序的啊,还有一点其实就是刚才有个同学问的了,我觉得其实就把我想说的就就其实就说了,就是其实跟您的顺序是有关的,这边的顺序会影响会造成两个东西。
一真的顺序它有可能会造成artifact,它有可能会造成偏向性,你会发这个发现这个面料它有的时候就是会歪向一边不对称,说跟编的顺序有关,这是第一点,编的顺序它会影响你收敛的速度,有的时候用这种顺序。
你会收敛得更快一点,有的时候用那种顺序会收敛更慢一点,说高塞德尔他其实跟编的顺序也是有很大的关系的,有很大的依赖性的,为什么我作业里面其实是想大家尝试第二种方法的,原因就是不用这种方法。
虽然说这种方法更简单一点,这种方法呢叫做结构比方法,科比方法,它其实这个方法其实主要有两个目的,第一个目的是为了想要减少这种由于编的顺序所造成的这种影响,这是想要让这个方法能够尽量的并行在gpu上。
或者是你在cpu上想要做一些并行计算,那么这个方法其实还是比较合适的一个方法,高赛德尔这个方法不能并行,前面那个方法也可以并行,但是会复杂的很多,会采用一种比如说叫做着色方的方法。
就是把一些边进行分类这种方法,但是我这里就不讲了,方法相对来说就会容易变形很多,这可比的方法其实就是做了一个事情,这个思路是什么呢,思路就是说我每次去计算这个编的更新的时候。
不要把这个更新直接就施加到顶点的位置上去,可以把它先保存下来嘛,对不对,我可以把它统统地保存下来,它保存下来,完了之后呢,然后对于每一个顶点,我可能会得到很多个更新量,对不对。
因为我每一个顶点可能会相邻很多条边,每一条边都会对这个顶点都会有一个更新量,都会告诉他一个更新,我把这些全都加在一起,然后我进行一些取平均值的这么一些计算,做一些取平均值,那么我可以得到一个总的更新。
其实就是一个很简单的思路,就是说我不要说我一条边,我直接就更新顶点,出了一条边,我直接更新顶点,我先把我算出来的那些新位置,我先给它存下来了,我一起更新,这个就是我的思路啊。
然后这里呢xi 6呢它其实就是它其实这并不是真正的新的位置,它其实是一个你看它这个叠加的,它是一个保存所有的更新的和同样的,我还有个and i,它其实是计算了这个更新的数量啊,它是加一的,它是更新数量。
得到了这个和跟数量之后,我再给它取一个加权的平均值,我最终得到它这个结果,高赛点相比一样,它迭代用的越多,它这个约束能够更好地满足,这也是一个它的一个呃呃跟高三的一样的一个一个方式,但他的好处在于。
它这个并行起来会很容易,它没有这些阿里嗯,前面我就讲了,就是说我们有这个约束对吧,有了约束之后呢,我可以定义这个projection投影方式,然后这个投影的这种方式呢不只是为一条边做的。
对这条边呢我也可以做这样的方式,就是分别有两种不同的方式,一种是高塞德尔方式,一种是结构比方式,基于此我就可以开发我们的算法了,第一种算法我们把它叫做position base的dynamics。
dynamics,他其实做了个什么事情呢,它其实就是利用我们前面讲的这些投影的这种方式,他搞了一个算法,前面呢首先我前面这部分呢做正常的模拟,做简单的粒子模拟,对吧。
我假如说就像那个就像我们之前做shape match,大家做作业的时候做钢铁的shape match,很像那个方法,它都可以自由地随便活动,那么对于这些我都做速度跟位置的更新。
这就是第一步自由活动的步骤,第二步呢就是我开始施加我的这个,那这个约束了这些边的长度的约束了对吧,我就是搞了这个过程,首先我给他顶顶点的位置,我先做一个约束,我利用前面的几口比或者是高塞纳的方法。
我对他做了个投影,投影之后,我得到了新的顶点的位置,这就是我新的位置,其次利用这个位置更新的差除以第二的t,我对速度也有了更新,最后呢我把新的顶点的位置赋值给x这个原来的这个顶点的位置,给它覆盖掉。
所以说它其实这个思路其实跟我们呃前面如果说大家做附加题吧,从第一次作业的附加题的shape match的话,会发现它其实跟前面的shaming的思路几乎是一样的,无非就是说我这里的约束啊。
之前咱们ship match的时候是刚体啊,是这些约束,而我们这里呢就变成了这些约束,约束方式上会有些变化,但基本上是一个套路,ppt有一些什么样的特点。
特点就是它这里的这个你如果拿来模拟弹性体或者布料的话,这个方法其实没什么物理,因为咱们正常说物理的时候会有弹性系数,这些不管是弹性系数也好,或者是什么也好。
他反正会有一些量去描述说这个物体到底有没有弹性,做p p t的话,他就没这个东西了,我们自始至终你其实可以看到没有任何关于这个强度的这个概念,弹性强度的概念,如果说你做ppt的话。
他这个模拟的这个弹性是由什么体现的呢,它其实这是有两种方式体现的,它会受两个东西的影响,这东西是你迭代的数量,你前面讲了吗,你迭代数量越多,这个约束就满足的越好,你迭代数量越少,你约束满足的就越差嘛。
所以说你迭代数量越少,如果你这个布料的时候,它就会感觉就会很有弹性,你叠的数量多,那么你这个布料看起来就会没有弹性,就会很stiff,七点,第二点呢就是说它这个东西其实跟你的网格是有很大的关系的。
如果这个网格很小,你的顶点数量很小,你这个没几个三角形,它会很快地收敛,也就意味着你同样的迭代,它会显得,对吧,那如果说你网格很大,你顶点数量很多,你也就意味着你需要用更多的迭代去收敛,那么反过来说。
给你一个固定数量的迭代,你网格变大了,也就意味着这个布会看起来很有弹性,大家做作业的时候就是做第二次作业的时候,大家也可以试一试,我我默认的是我是设了21x21个顶点,可以把这个21x21改一下。
比如说改成11x11,或者改成31x31,然后用同样的迭代数量,你会看这个结果是什么样子,就会感受一下,通过调整网格的密度,还有调整这个迭代数量,其实可以做到一个就是调整它的弹性效果的一个影响。
第二点呢是我呃就是关于速度这一块了,其实嗯有同学就是做作业的时候也会问了,就是说这个速度是更新这一块嘛,其实这个速度更新是很重要的,因为这个速度更新它会影响到我们做dynamics的效果。
这个模拟的动态效果,然后为什么是叠加的,是因为为什么这里是加直接的赋值呢,是因为我这里的x啊是x是已经前面更新过的,x已经被速度更新过的x,这意味着说你当你做x6 减x的时候。
它这里其实是没有考虑到原有的速度的,我的原有速度呢,我就需要把原有的速度给它加上去,主要是因为这个原因,然后然后呢这个方法它其实也是一个相对比较通用的方法,我们其实做可以,我们其实也可以做其他的约束。
比如说三角形的约束,比如说体积的约束,比如说碰撞的约束,其实都是可以用类似的方法去处理的,但是这里我就不展开了,主要的话就是说对于不同的约束,比如说我对于这个体积的约束啊,我其实后面会讲一下。
就是可以就是搞一个它的这么一个函数,然后有了这个函数之后呢,我其实就可以做这样的投影,其实刚才有同学问这个方法的迭代的实质性怎么样嘛,啊其实这也是我想讲的,一就是说这个p p t这个方法它的优缺点。
优点在于它很容易在很容易并行啊,nvidia的这个physics engine,过nvidia游戏里面很常用的nv cross的这种engine啊,它其实都是本质上都是基于p p t的。
游戏里面用到的一些物理的这个布料引擎啊,很多都都是基于这种约束的方法,都是基于这种ppt方法,所以说大家可以看到,其实这种方法用的还是很广泛的,虽然说这个方法它其实不止因为本质上因为它容易实现啊。
本质本质上因为它容易并行,还有一个原因也是因为它本质上它容易实现,你只要定义了约束,你去搞一个类似这种约束的这种函数,然后呢就可以模拟啊,你不需要去纠结说啊,饮食积分。
你看他根本就没有影视的积分概念对吧,它也没有什么合成什么力的概念,就是特别简单,然后呢它的通用性也是比较强的,呃很有时候你可以不只是拿来做布料的模拟啊,弹性体模拟。
甚至于流体的模拟都是可以用类似的方式去解的,所以它很强,在效率上我应该这么讲,就是分辨率比较低的时候是比较有效率的,还是比较快的,那分辨率多低呢,再说我们在处理的时候不到1000个点顶点的网格。
你还是可以一个比较实时的效率去模拟的,但是超过1000个点就会明显下降,我接下来就会讲它的缺点啊,第一个缺点就是它没有什么物理含义啊,整个弹性的这种表现会受格的影响,也会受迭代数量的影响。
这个其实是不太合理的,为什么,因为我们其实正常,假如说去描述一个物理现象,混上这个结果应该跟网格是没有关系的,而且理论上随着你网格越密,你应该会收敛到某一个精确的结果,对于p p t而言。
这种方法而言呢,它就没有一个所谓的精确结果,因为如果说你真的要迭代数量很多很多无穷多的时候会发生什么,会发生所有的边都没有任何拉伸,那么反而会导致locking issue,对不对。
你本质上你是不希望有lock initial的,所以说他没有一个精确解,这个点就是当你分辨率提高的时候,高分辨率的时候它的收敛性会明显下降,会下降得非常明显,你就会发现11x11跟21x21的效率。
其实差距就已经比较明显了,然后有一些解决方式啊,然后有同学问用高阶的积分方式能不能提升pp的效率,我倒是不知道有什么高级的方式,其实这个东西它没有所谓高阶不高阶,因为它本质上它直接就是更新顶点的位置。
甚至你都没有办法用,因为它没有物理含义嘛,甚至你都没有办法用积分的方式去解释它,也就你用高阶的东西,你都没有办法去讲,提升物理,提升它的效率,这一块其实有有一些方法,大家其实研究了一些方法。
方法师就是说你可以去构造一个海ark hy,就是你的有一个网格,那么你可以构造一个低分辨率的网格跟高分辨率的网格,然后你先模拟一下低分辨率,然后把低分辨率的结果传到高分辨率上再去模拟。
然后再到更高分辨率上,就是类似就是层层层模拟的方式,从低分辨率逐步的模拟到高分辨率,这种方式可以做,但是对于p p t而言,会导致更,其他问题,比如说它会导致一些抖动的问题,这个我就不展开了。
比如说我自己也做了一些,这种反正也可以做,但是呢呃路上其实也不见得一定特别理想中,p p t我认为就是我的感受就是它是比较适合低分辨率,就是在游戏开发里面,就是网格里面很多衣服。
它的这个网格都是特别简单的一些网格,那么就是比较适合用p p t的方法,或者说你想要尝试,比如说1000个顶点以上的,可能就是没有那么合适了,它的效率就会相对来说比较弱一点,给大家一个课后阅读啊。
是mt miller在08年的一篇paper叫做hiro ppt,然后他当时是在vidia嘛,所以说你也可以看nvidia的很多物理引擎,基本上都是基于ppt的,还有流体的p p t等等。
各种各样的p p t,反正就是基于这个方法比较常见的一个,一个比较常见的一个实时低精度实时模拟的一个套路,bd它存在了一个这些这个缺乏物理含义的问题,所以说大家就在想说。
我可不可以不让这些投影方式约束方式负担那么重啊,大家就想了个思路,就是说如果说我还是做物理模拟,比如说我用影视积分或者是做有限元模拟对吧,我还是用正常套路,我就是加入一步,就是说我专门用来防止大型变。
让模拟更稳定一点,我如果是出于这个目的,是不是也可以做一些事情,利用我这个我们讨论的这个projection方法来做一些事情,这种方式就是大家就取了个名字叫做limit。
我刚才这个描述其实并不是很准确啊,因为从历史上来讲,string meeting发发现的其实比ppt还要早,strali整个思想它其实在1998年的时候,甚至97年的时候,其实就已经发现了。
而p p t到了差不多2000年的时候,2000多年的时候才发现,你其实可以认为strlimit实际上是一个p的一个改进版,什么事情呢,其实跟大家可以看哦,很像,也是把模拟分成两个步骤,这是做模拟。
然后第二个步骤是做投影对吧,其实跟p p t很像嘛,区别就是在做relimiting的话,你的第一个步骤其实不是简单地做一个粒子系统,第一个步骤里面其实也是做一些正常的模拟的。
比如说我也可以做正常的弹簧系统,做饮食积分或者做有些人我其实都可以做的啊,然后我后面那个部分他其实只是做一个纠错的一个步骤,它其实并不是说我要依赖我后面这些投影的这些东西,我来做动画效果。
我后面这部分仅仅是为了满足一个保证这个模拟稳定的一个目的,大家举一个例子啊,我还是用弹簧来举这个例子,根弹簧弹簧的原长是l对吧,那么我可以定义一个变量叫做stretching ratio,拉伸比例。
拉伸比例,拉伸比例就是弹簧长度除以它的延长,就这个东西是他的拉伸比例,我要求说我的要求是什么呢,我的要是他这个拉伸比例必须在一定范围内,我就跟弹簧不能拉超过一定幅度,也不能压缩超过一定幅度的最大值。
这个sigma最大跟sigma最小就是分别是它的最大跟最小的拉伸比例啊,啊这个之后呢,我也希望构造我的投影函数,对不对,投影函数其实跟我们之前的那个投影函数非常像,区别在于什么。
在于我投影了之后新的位置啊,不是严格的长度等于原长的,而是说我放宽了一下我的要求,我只要求他长度呢是满足我这个约束的这个范围就够了,这个拉比例的范围就够了,所以说我还是希望两个顶点靠近一点。
但是呢他也不要求说靠近到原厂的程度,我只要求靠近,然后满足我这个比例,同样的压缩也是说的时候我希望这两个顶点呢就是远离,但是我也不要求他远离到原长,我只要求就是远离一定长度,满足这一定程度就够了。
其实大家可以发现这个东西实际上就是放宽了的ppt,我把约束给放宽了,我把我的目标也放宽了之后呢,我可以定义我的我投影函数怎么定义呢,我计算一下我的这个拉伸比,我的拉伸比是原长,我是当前长度除以原长。
我计算一下我的目标拉伸比,什么目标拉伸比呢,就是我把这个西格玛,我这个拉伸的笔啊,我用我的这个sm minimal跟sm maximo给他约束一下,就是我把它这个比啊进到这个范围内。
这个就是我的这个范围,我把它限制在这个范围内,限制限制完之后的这个拉伸比就是我想要得到的拉伸比,问这个跟string有什么关系啊。
其实这这stretch ratio这个其实就可以把它认为是一个string,它应该说它减一叫做string,它叫做string,string是什么,ing里面就是说描述形变的一个量。
它其实就是一个描述形变的量,所以说我们这里就是把它叫做string方法,我们接下来得到了一个想要的拉伸比,到拉伸比之后呢,利用这个东西,我把原厂给它替对吧,我原来的圆长是l吗,我想要的长度是l。
那么现在我想要的长度是西格玛,凌晨也要分别放到这个公式里面,然后我就得到了我最终的这两个新的位置了,呃有同学问这个是一维的吗,其实strain它可以是一维的,也可以是二维的,也可以是三维的,对于生而言。
它的string是一维的,我们回头讲有限元的时候,讲到那个三角形四面体的时候,就是是二维的跟三维的,但是反正这个现在咱们先不讲那么多,这里就是一个一维的一个一个量,可以这么认为吧。
就是他其实水里面它其实有有不同的目的吗,目的是我后面会讲,就是说他其实是为了模拟有很多面料,它拉伸到一定程度就会变得很很stiff的情况种方式,然后还有一种方式就是我很多时候形变大的时候。
它会数值上它会不太稳定啊,它会容易发生这种呃,比如说我们做有限元的时候呃,有很多数学模型它在发量很大的时候,它就会变得很不稳定,它会有抖动,甚至它直接会炸掉,所以说我们可以利用string。
我可以让它的拉伸,那么我可以让他模拟会更稳定一点,主要是这种目的,所以它直接的目的是为了限制拉伸带,你也可以认为就是说这个背后的目的有可能是因为本身物理上,本身面料的这个物理属性上有这样的表现。
也可以认为是在数据模拟的过程中,它可能会有一些稳定性的问题,我需要算法上能够让它更稳定一点,就是都是有可能存在的,情况下就是ppt对吧,你可以认为这个就是认为西格玛永远等于一的情况吧。
如果说这个西格玛永远等于一啊,西格玛零永远等于一,就是p p t的方法,就是string可以p p t可以认为是string的一个特例,如果说你不想要做任何约束,你也可以把它搞成正负无穷大是零。
这里啊其实这里应该是零拉伸,你是零,你也可以不对他做任何约束,这是对于一根弹簧,我们前面不是讲了,其实呃还可以有不同的方式嘛,对吧呃就是这个三角形面积,我有一个三角形。
然后这个三角形的面积是a希望三角形的面积呢是落在这个范围内的,做呢我也可以搞数学模型对吧,我可以假设说我希望挪动这四个三个顶点,三个顶点呢我这里写错了,我回头会改一改,这三个点都尽量挪的足够少。
然后同时呢也满足约束嘛,一个数学上的一个要求,实际过程中其实就会发现他这个操作其实非常简单,你理解这个三角形的面积大于或者小于我的这个范围的时候,想要给他计算一个缩放量。
我就把这个三角形给它缩放一下就行了,那么这个缩放量是什么呢,缩放量就是面积,根据这个换算了之后,然后呢他的这个把这个面积呢投影到这个范围内,然后除以原来的面积,这里应该开个根号,这里这里少写了。
应该开个根号,就得到他的这个前后的面积比,这个部分呢就是我想要,面积,然后后面的面积,后面的这个a呢是当前的面积,想要的面积除以当前的面积,开根号呢就会告诉我说。
我到底应该把这个三角形按什么样的比例去缩放,那之后呢我就可以得到我想要理想的这个三角形面积了,就这么一个思路啊,这里应该写个平方,这里回头改一改,其实就是很好,就是这么一个思路。
就是首先我计算一下三面积,我把三角形面积算出来,接下来呢我计算一下我想要的缩放比,之后呢,我把三角形的质心给它算出来,因为我在做缩放的时候,我是希望它的质心是不变的,执行算出来之后呢,我对于每一个顶点。
我按照这个公式对吧,我知心不变,然后至新加上顶点到志鑫的这个时量,按这个比例进行一个缩放,乘以s分别对i j k做一个缩放,得到新的点的位置,这个反正就是给大家看一下。
就是一个比较简单的约束三角形面积的一个思路,就是可以利用这个东西来进行一个操作,的时候有的时候是希望三角形面积啊不会发生很大的改变吗,比如说有个三角形对吧,你不希望这个三角形被压扁。
那么除了对这个三角形的边长有约束以外,你同样也可以对它的面积进行一定的约束,我们接下来讲就是说这个string ming有什么用吗,有一个用处呢是有两个用处啊,出的是稳定性的问题,还有形变的问题。
很多物理模拟它它形变啊,有就问为什么至今不变对吧,因为心不变的目的主要是满足我们数学上顶点运动最少的要求,我们希望所有的顶点它这个运动的量是最少的,然后物理上讲,如果说至心不变。
也就意味着它没有新的动量,你不希望这个物体它约束了以后,他就自己就开始做奇奇怪国外的运动了,我希望它永远是在本地进行了这么一个性别对吧,本地进行了这么一个变形约束,所以说我是希望它的质心是不发生改变的。
但是如果说你根据这个数学公式推啊,你会发现这两个是等价的,就是质心不变,如果说你这个东西你知心不变,其实是两个是一样的,是可以回头回头去推一下,我,其实我我为了背这个课,其实我自己也推了一下。
我发现确实是如此啊,street limit,可以说保证就是说大型变变的时候呃,不发生大型变,我们模拟中不会产生大型变,没有大型变,也就意味着我们整个模拟会更稳定一点啊。
啊我们的这个artifact也会少一点,这是一个啊一个原因,然后这个原因是因为很多布料,比如说像这种布料都会有这种,就是一开始的时候它会比较没有弹性,它会基本上不怎么抵抗拉伸,但是到一定程度之后。
它这个抵抗会迅速的增长,它变得很大,所以说这种非线性的表现呢,我们可以利用stralia,我们可以模拟这样的效果,那么怎么模拟呢,我其实就把这个东西分成两个阶段对吧,第一个阶段如果说拉伸量比较小。
那么我就做正常的物理模拟,然后第二个阶段如果说拉伸量比较大呢,我就做这个relimit,这个其实也是一个比较常见的一个套路,做by physic simulation,嗯,不考虑大型变。
就是说这个前面这个东西主要是因为大型变的时候,数学我如果做物理模拟,它有的时候会有稳定性的问题啊,但是如果说你自己考虑,就说比如说你想要模拟史莱姆对吧,大家知道玩过史莱姆吗。
就是那种特别能拉伸的那种那种,你如果说模拟史莱姆的话,那么确实你需要做大型变,那么你就不需要做strlimit,但是很多时候我说我想模拟肌肉,那肌肉其实也是很少有很大的这种拉伸形变的,那么这种情况下。
你就可以考虑做strlimit,你的这个问题啊,一点就是relimiting,他是可以帮助解决这个locking issue的,为什么,因为当我把整个模拟分成两个阶段的时候。
我前面这个阶段我可以用比较小的弹性系数嘛,那比较小的弹性系数状态的时候,我这个弹簧是可以比较自由的弯曲的,就本质上就相当于我可以把我的弹性系数k给它弄小了,那把弄小了以后呢。
我这个locking issue也会变得不太那么明显一点,这个也是一个原因,少年的一篇paper哦,甚至都不是97年,95年,1995年的一篇paper,很早年的一篇paper。
这个但是我是不建议大家读的啊,这个paper太老了,而且其实这个思想特别简单,基本上基本上这个paper讲的这个思想,所以说我倒是不建议大家,大家有时间的话可以去读读读。
读读这个95年的paper是怎么来描述这个问题的,这一篇比较经典,但是也是比较老的paper,我今天的时间也不多了,所以说我今天就想停到这儿,然后有同刚才说了。
就是说感觉projection感觉约束跟能量挺有关系的嘛,啊所以说其实我们之后我们下次也会讲这个方法,projection project dynamics,就是啊对。
把这个把这个projection的方式,怎么样去跟我们之前这种物理模拟能够跟它结合起来,但是我们今天时间不够,我们就不展开了,看看大家有什么问题,我这里可以回答,吗,p是吗,嗯问一下助教嗯。
大概什么时候能够那个,但是我是想就是p完之后嗯,给同学们就是你的分数就是告诉你哪里做的不对什么的,会告诉大家,然后如果大家想要知道正确答案的话啊,我们会在就是五天以后,大概一周以后嘛。
我们会把正确答案就是你可以发给大家,就是大家如果想要的话,可以问助教,助教可以给大家,然后大家可以看一下正确答案是什么样子,那你可以对你可以加他,可以加他那个,内容是目前的内容已经可以做作业二了。
我们作业二其实就是两块嘛,一个是饮食积分,这个上周讲了,然后还有一块是p p t,然后咱们今天也讲了,其实都是可以做的啊,所以说你只要完成一个,咱们就算你这个作业完成了嗯,算是。
然后如果说你把两个都做完了,就算是就是把附加题也完成了,p p t中怎么控制高度,它其实前面我前面讲了,就是利用两个东西啊,一个东西啊,我刚看到两个因素相关,一个是迭代数量。
一个是网格的密度密度网格的密度一般来说你没法改,就是用迭代数量来控制的,你可以你可以让迭代多一点或者少一点,这样子可以调节钢铁,可以啊,就是如果说你自己有能力的话,可以修改,可以修改一下。
我看到有同学把那什么纹理都换了,这有什么物理含义吗,嗯其实跟那个就是p p d中质量大为一小,这个有什么物理含义吗,这个跟物理里面力的那个相互作用,力的那个物理含义是一样的,就比如说你可以这么想。
就假如说我有一根弹簧,然后一根弹簧连接了两个物体体,两个物体质量不一样对吧,那假如说我就跟弹簧连接着这两个物体的话,那么弹簧的力的大小是一样的,而两个物体受到的位移,它其实等于力除以质量,血量越大。
它的位移就越小,含义是一样的,它其实它的思想是这个,只是它其实真的没有什么物理含义,就是关于弹性那块的物理含义,所以说他尽量想把它搞的物理含义一点,但是我个人觉得在实际操作,其实你你搞那么有物理含义。
其实差别也不是很大,可以用不同的迭代数量吗,啊好像好像就是得所有的都是同样的迭代数量,把所有的点都过一遍,所有的点都过一遍,这样的是呃,有同学说迭代数量控制stiffness有点玄学。
确实它这个东西就是因为它就是没有物理含义,所以说它就是调参有完全完全是肉眼去看嘛,就是你觉得这个好像效果不太好,你就给它系数再调一调,考虑塑性吗,做塑性的这个研究比较少,之前有有一篇做那个内部摩擦力的。
但是大家试一下,我记得印象中也就那一篇论文吧,具体做塑性的论文还是比较少的,问用影视积分求解布料跟球的碰撞是怎么样做的哦,作业里里面我们做碰撞,做球的碰撞是作为一个后期处理的。
就是就是把那个跟球的碰撞是不放在饮食积分里面的,影视积分,你可以认为饮食积分它就只是更新布料,根据布料本身弹簧的呃来更新点的位置,然后更新完了之后呢,你再做碰撞处理,步骤,反弹效果好。
背不平的都不怎么反弹了,好像有可能会,安装处理啊,其实用的是应该是几周前的那个东西吧,就是我们之前讲的那个例子嘛,因为你布料其实本质上就是有很多点构成的。
所以说你其实我们到时候用作业里面用的是粒子的碰撞处理方式,用那个三distance function处理的方式,咱们也没有讲村庄,就是相当于这里就比如说p p t嘛对吧,然后这里再加一个碰撞。
你可以认为雷神也是一个投影方式,然后碰撞在这里处理掉,其实一般来说不用unity,一般来说用那个g l s l又和奔驰要写的比较多一点,用vn一般用gsl gl比较简单一点。
再说如果说你要想要做后期渲染,然后在论文里对吧,你想要做一个比较好的效果,一般来说可能就会用一些离线渲染器啊,用米醋吧,或者是那个呃玛雅玛雅玛雅里面的v锐都挺常见的。
一般来说科研本身一般来说用用open gl,用g l s l用的比较多,是有同学问,就是讲locking issue的时候,中间中是压缩,而不是真的弯曲,对就是因为本质上就是因为我们中间那根弹簧。
它没有办法真的去弯曲嘛,他说嘛他其实我们就只是用根线去描述,但他没有办法真的弯曲,它只能压缩的话,那如果我又不让它压缩,那我整个就弯不下去了,对不对,问题,多个concert一起求解的优化。
就前面说的高塞德尔跟这个比算是多个一起吗,他其实也算是多个一起求解的方式,不算是多个,求一起求解,你说的多个是什么意思,具体是什么意思吗,算是一种多个求解的方式,与球的碰撞用s3 判断。
然后布料的顶点如何更新,就你可以做个简单一点,就是不要做任何摩擦力,就直接把这个顶点从球里面推出来就行了,就直接对零点做一个impulse method。
impulse based method就可以了,如果你要做penalty也可以,直接用impulse直接把它推出来就可以了,就是有限元其实只是一个框架,具体的数值方法,怎么算出来的。
这个阿尔法其实也是调参调出来的,没有算出来,就是调参,我会给你这个参数,好像是0。2吧,反正你可以试试试,不同的参数,把好几个约束都满足了,我感觉做不到,因为数学还没有这个能力做这个事情。
咱们的数学家还不够牛逼,其实都是线性的元素,而一都是说错了,都是非线性的约束,而非线性的约束,它其实本质上是一个非线性优化问题,那目前还没有说什么方法能够一步就把所有的非线性约束都满足。
数学家还不够厉害,我们现在能做,你看为什么我们那么多线性问题研究那么多对吧,线性代数,我们我们数学科要学线性代数,然后解线性系统,线性问题本质上就是因为线性问题是容易的,非线性问题是男的。
线性问题是可以一步解出来的,而非线性是不能一步解出来的,所以说我们线性怎么解,就是把所有的非线性问题都用线性的问题去给它近似一下,然后呢我用线性的问题去解。
其实这就是这是我们所有的非线性优化的问题所做套路,大家解决问题的时候,永远都是想用知道的方法去解决不知道的问题吗,一个套路,其实我可以觉得非线性,其实非线性优化听起来很复杂。
反而是我学过的很多数学里面最容易的一个数学,为什么,因为就是因为非线性太难了,数学家其实也没怎么搞明白,数学没怎么搞明白的,结果就是它其实很多方法其实都特别简单,或者说数学家已经搞得特别简单的呃。
特别搞得特别明白的那种数学反而会很难,因为数学家研究的很深,你就没法搞明,对吧,其实就是这么回事,那没有别的问题,咱们就今天就先到这儿了,然后我们下周会接着这个constrain这一块,接着往下讲。
会讲两个,就是嗯比跟stralia ming相比就更高级一点的方法,但是可能也会更复杂一点的方法,所以说后面啊我就是是有点科普性质为主了,反正大家如果说听不懂的话呢。
就是呃跟着这个后面的paper就是跟着读,看看能不能就是理解一下,然后我为什么我们讲后面那两个高级方法,主要也是因为有些地方他确实是用会用到这些方法,所以说我给大家相当于给大家科普一下。
给大家一个参考啊,算法但是还是要复杂很多的,但是给的给大家科普科普,好吧好吧。
先到这了。
GAMES103-基于物理的计算机动画入门 - P7:Lecture 07 Other Constrained Methods and Finite Element Method I - GAMES-Webinar - BV12Q4y1S73g
行啊,然后回答一下那个同学的问题,就是你可以可以用其他,可以用其他引擎交作业是可以的,我看到有的同学还用自己写的引擎做了作业,啊有回声是吗,我看看啊,回声,现在呢现在有回声吗,现在应该好了吧。
ok然后那个啊因为杭州这边有点疫情,所以说我本来一直想恢复那个恢复那个线下客的,但是因为有疫情的原因,所以说咱们线下客就暂时可能就呃暂时先都取消掉了,还有回声啊,我看看,怎么会还有回声呢。
有吗回声喂喂喂,有回声吗,ok行呃,然后我今天就是想把那个咱们那个呃计划给稍微改一下,因为我本来是想说我们今天上那个呃讲碰撞那一块,但如果说今天咱们讲碰撞,肯定到时候讲不完。
讲不完可能就会影响到下一次课,因为我下一次课是想啊讲那个有限元的,然后我们下次作业也是关于有限元的,所以说如果说咱们下次有限元这个东西讲不完的话,会影响到大家做作业啊。
所以说我就想把我们的计划稍微调整一下啊,就咱们今天会把啊我们上次的那个约束有个尾巴没讲完嘛,所以说我会把约束这一块啊继续讲完,然后就开始讲有限元啊,然后我们这周还有下周,都会讲有限元。
然后呢呃之后我们再会讲碰撞,大概是就是这么个调整一下,就是要把碰撞相当于挪到有限元后面去了啊,这个呃主要是对这个稍微做一些改变,然后那个我们今天主要是想谈那个约束那一块,因为咱们上周讲了约束。
讲了p p t,还有stray limit嘛,就是我们也谈到了,就是说用约束来啊模拟这个衣服啊,面料或者是其他物体的一些一些一些方法呃,然后呢我们也谈到了p p t它存在了一些问题。
比如说呃他这种模拟方式,它其实没有什么物理含义,所以说这周我们会讨论一些,就是怎么样把约束跟就是怎么样用约束可以呃做一些其他方式的模拟,也是约束,但是呢我们会把整个模拟引擎会写的。
跟ppd那种直接拿约束来修改顶点位置的方法,会有一些不一样的点啊,然后这个东西其实也相当于是给大家一个科普,因为呃我个人觉得这一块可能会有一些超前呃,但是呢有很多新的技术。
新的引擎它多多少少会用到这些方法,他也会用到这个方法,所以说我们会今天会稍微呃把这些简单的方法给大家过一遍啊,这是前半部分,然后后半部分呢我们会开始讨论有限元,然后根据我们的进度。
我们看看我们今天能讲多少算多少好吧,然后今天首先第一个就是给大家介绍一个方法,叫做projective dynamics。
这个projective dynamics跟我们上周讲的用约束做p p t的方式,它其实有很多相同点,但是它的不同点呢也很明显,呃,它的不同点主要体现在哪里呢,主要体现在我们用约束来干什么这个事情上。
因为我们上周讲ppt,还有讲relimiting的时候,我们有了这些约束对吧,然后我们根据这些约束定义了一些投影的方式,就是这些投影方式可以让我们满足这些约束嘛,我们用这种投影方式直接去改变顶点的位置。
这个是ppt,那projective dynamics说呢,我不要去把这些projection这些投影方式拿来直接去修改位置,我用它去定义一个能量,那么比如说啊,比如说我这里给大家举个例子啊,看一下。
比如说我现在有个网格对吧,我有啊五条边,然后呢我这对于这五条边呢,我就分别定义了这个这么一个能量函数,假如说我有一条边,这条e这条边是a到g嘛,然后减去减去什么呀,减去它投影之后的状态。
换句话说我这个投影函数我不是拿来直接去修改顶点位置的,我之前我ppt里面我有了这个投影函数之后,我直接把这两个顶点的位置给修改掉了,我现在不修改顶点位置,我只不过把这两个新的顶点位置给它算出来。
然后我利用这两个新的顶点位置,我去重新构造了一个函数来模拟,这个就是我变成了我的这个函数啊,然后这个函数的里面的这个i i knew跟j new呢,就分别对应着我投影之后。
根据我这个约束更新之后的两个新的顶点位置,只不过我不拿直接去修改顶点位置,我定义的这么一个函数,然后我们可以来检查一下哦,这个能量函数它到底是个什么东西,首先我们看如果我们正常投影之后。
这个东西这个我红颜色方框里的这个东西,它是个什么玩意儿,假如说我投影完了之后呢,那么这两个新的顶点位置,它两个距离就应该是圆长了对吧,因为我投影完了之后,我应该理论上我应该完美的满足我这个原厂的要求。
所以说它长度肯定是l e,然后它的方向呢,它的方向肯定还是在这个i j这条边的方向上的,因为我们上周也讲过,我们对于一条边而言,如果说我们呃满足他这个约束,满足这个投影的话。
我肯定是还是在这个边的这个方向上进行移动的,我只不过挪近一点或者挪远一点,但是我始终是沿着这个i j这条边的方向在挪动的,所以说它的方向肯定就是始终还是i减j,然后除以它的这个长度,然后前面乘以l1 。
那么这是它这个我们实际上我们这个能量其实应该是这个样子,那么我们再进一步修改对吧,我可以把首先把前面这个括号里的这个东西啊,我把括号里的这个东西,我前后上下分子分母都乘以一个啊,这个鱼长度。
那么x减x j的长度对吧,我分子分母都乘,然后完了之后呢,我就可以把这个东西给它这个方向,这个东西可以挪到这个括号的外面去了,挪到外面去之后呢,你会发现因为它这个东西本质上就是一个单位向量嘛。
所以说它就是一,所以说整个东西就变成了长度减去原长的平方,这个大家反正把这个公式给稍微整理一下,就是自己体会一下吧,整理之后就会得到这么一个公式,然后你会发现什么。
你会发现它这个能量其实跟弹簧的能量是一样的,也就是说我们其实绕了一大圈,我们搞了这么一个投影,搞了这个约束,搞了这个投影函数,其实搞出来的这个能量函数跟弹簧的能量函数是一模一样的啊。
只不过我把这个投影算出来的这两个新的顶点位置,我把它相当于作为一个中间结果,然后这个中间结果因为我有了这个中间结果,一个二次函数,那么好,我现在有了这个能量对吧,我接下来看看我的力是什么样子的。
我立呢就对我利用这个能量,我把这个能量对x求导吗,那么好,我现在算力对吧,假如说我现在对这个顶点i我要算他的力,那么它的力是什么呢,这个f i呢等于负的能量的梯度,那么我就分我就对这个东西对x求导吗。
我这里做了一个大胆的假设,我等会儿我们会讨论为什么要做这个假设,这个假设有什么呃,有有有有有什么问题或者是没什么问题,我先假设这后面玩这玩意儿,先别管它,先假设它就是不变,是个常数。
那么就变成了真正的变量就在前面这个地方了,这里是唯一有x的地方对吧,那么我就对整个是一个二次的一个chratic的一个函数嘛,我对这个x求导,我就得到了k对吧,前面有负号,负号是根据我的定义来的。
所以说负号不管它,然后前面有个k,然后后面呢就是x减x j减去啊,这个新的这个呃这个两个顶点的位置,这个就是对这个能量对x求了一个档,那么这个力啊,我们再来对这个力做一些调整。
就首先我们刚才知道这个ex 6跟x j new分别是什么对吧,他俩的差等于l e然后乘以啊,就是就是这个方向嘛,这个咱们刚才也说过了,就是根据投影,投影完了之后,这个东西应该等于这个东西。
他应该是满足圆长的,同时它的方向是在这个方向,然后咱们再把这个东西再整理一下,我得到了什么,我得到了圆长啊,长度减去原长乘以方向啊,你如果把这个沉进去之后,你会发现前面这个东西呢。
前半部呢这个东西乘以这个东西抵消,然后前半部就是x减x j x j,所以说这个东西就是这两个就是等价的,大家如果呃没时间看的话,可以回去慢慢推一下,那么你看看这个力是什么呢,利又是什么呢。
诶它这个力它又是弹簧的能量,也就是说我绕了一大圈,我的能量跟弹簧的能量其实是一样的,我根据这个cdc的这个能量,我去对x求导算它的力,我会发现这个算出来的力其实跟弹簧的力诶也是一样的对吧。
换句话说我这个模型,我这个所谓的projective dynamics的整个模型,其实跟正常咱们模拟弹簧系统的力,跟正常模拟弹簧系统的能量是一模一样的,无非是我引入了两个中间变量。
这两个中间变量是根据我的这个投影,我这个约束的投影,我算出来的这两个中间变量,然后我利用这两个中间变量呢,我去构造了一个新的呃力跟新的能量,然后呢我得到了一个结果。
只不过呢这个结果跟我之前的弹簧是一模一样的,那么有同学可能就会问了,我何必多此一举,对不对,我为什么非要去用这个中间结果去构造这个力,构造这个能量,既然他俩跟这个正儿八经的做弹簧模拟都是一模一样的。
我何必这样做呢,原因在于什么,原因在于它的和声会不一样,我这里给大家举个例子啊,我觉得例子可能会比较简单直观一点,咱们有五根弹簧对吧,从0~101121314有五根弹簧,然后呢我构造了一个能量。
分别呢是由五个部分构成的,这五个部分呢就是针对着这五个能量,我搞了这么一个啊,总的这个能量函数对于整个系统而言,搞了这个能量函数吧对吧。
那么这个是我的projective dynamics的这个能量函数,那我的力呢,我对于零这个点的力啊,这个点的力呢我有三条边跟它相连,分别是绿的这几条边,蓝的这条边,还有橙色的这条边。
所以说我就有分别是由三个部分构成的,这个总的力是由三个部分构成的,分别是绿颜色的部分,蓝颜色的部分跟橙色的部分啊,分别对应了这三个不同的能量,然后我这个力怎么算呢,我就对这个东西求导吧。
因为它是一个二次的关于x关于顶点位置的一个二次函数啊,所以说我求导也变得很容易了,我就直接对它求个导,就等于是把这个括号里面的外面的这个二给去掉吗,二跟这个二抵消求导的时候,我们把二取抵消。
然后把这个中间的部分抄一下就可以了,然后为什么这两个位置改变了,是因为我力需要前面加个负号,所以说我前面加个负号之后,就相当于就是把后面的挪到前面,前面的挪到后面,所以说这就形成了一个力的形式。
这个没什么稀奇的啊,那么我们前面也讲了,这个能量跟这个力其实跟弹簧的能量跟力其实算出来的啊是一样的,结果是一样的,那真正特殊的是什么,真正特殊的是我的举证,那么矩阵是什么呢。
我举证就是能量对于顶点的二次导数,那在这里呢我其实是做了一个假设的,跟我们刚才对力求导的时候的假设也是一样的,我的假设是说我的顶点位置,我后面这个新的顶点位置,这个new啊,就是这这些所有的这些像啊。
这些new的这些项都是常数,都是跟x无关的,我认为它是常数,那么因为它是常数对吧,它跟x无关,我知道我的这个能量是关于x01 和x2 x3 的二次函数,也就意味着什么。
也就意味着我的黑神就变得非常简单了,我给大家看这个合成什么样啊,对于x0 而言,最上面这个东西,是什么,它是d e,对于x0 的二阶导数,他是二阶导数,然后我怎么看我这个二阶导数呢。
我看我这个能量里面x0 总共出现了三次嘛,对不对,绿颜色的一次,蓝颜色的一次,橙颜色的一次,总共出现了三次,然后它的二阶导数就是三乘以k乘以identity矩阵,然后呢第二个1号顶点。
1号顶点呢出现了两次,分别对应的是绿颜色的部分跟黄颜色的部分对吧,所以说这里就是22k i,然后第三个也就是x2 x2 呢,它有啊出现了几次,我看一下蓝颜色的出现了一次对吧,黄颜色的也出现了一次。
然后然后紫色的出现了一次,所以说它就是3k啊,然后其实这个东西啊,这个和声啊从这个图上非常容易看出来,怎么看,你看每一个顶点它领了几条边,它相邻的几条边,那么他这个对角上就是几。
比如说这0号景点它相对的三条边,所以就是三,然后下面的x一相邻的两条边就是2x2 相邻的三条边就是三,然后x3 相邻的两条边,那么就是二,然后非对角上非对角上存的是什么呢,非对角上存的是边。
比如说我绿颜色,绿颜色的这条边相邻的是0号定点跟1号定点,那么我零一跟一零的位置,我就存的是-1,然后呢零二,那么我相对应的零跟二这个零二跟二零的这个顶点位置,我存的是负的。
负的k就是相当于你可以根据这个拓扑,根据整个这个图,这个图你可以把它相当于转化成这么一个合适,而且你会看到这个河神其实跟这个,你把这个e这个能量对顶点求二次导数算出来的结果是一样的,利用这个公式。
也就是说其实你用利用这个projective dynamics,它这个特点,你可以假设说它这个东西就是一个关于x关于顶点的一个二次函数,然后因为它是个二次函数,那么它的这个二他这个二阶的这个举证啊。
他这个合成矩阵就变得很简单了,它就变成了一个常数矩阵了,这个其实是project dynamics的关键,就是他绕了这么一大圈啊,根本的目的是什么,根本的目的就是为了利用我的这个假设。
我假设这个能量它是一个顶点位置的二次函数,我构造了一个常数的一个合成矩阵,这实际上是它的一个根本目的,那么有了这个常数矩阵呢,我剩下的部分其实跟我们正常做影视积分的那个模拟方式是一样的。
无非就是说我前面多了一步,就是计算投影的这一步,我计算一下投影计算投影完了之后呢,呃我根据投影算那个力,这个其实不影响啊,就你直接拿去用弹簧的算力,其实也是ok的。
然后呢你前面呢就是呃我们也是呃经常做的嘛,就是质量,然后这是一个合成矩阵,然后只不过这个合成矩阵跟我弹簧模拟的合成矩阵是不一样的,我们正常我们要计算影视积分的时候,我们那个弹簧的系统的这个合成矩阵。
我需要根据实际的顶点位置计算出来的,而这里呢因为我前面做了这么多的假设之后呢,我就假设这个和弦它就是个常数矩阵了,所以说我这个就变成了一个非常简单的一个常数矩阵。
我把这个常数矩阵作为我的这个呃这个这个问题的这个部分,那么为什么要这么做啊,它的原因在于什么,它这个原因在于当你这个取证这么一个矩阵,它是一个常数的时候,是一个常数矩阵的时候,我就可以用直接法去解。
因为我们做直接法,我们用l又分解或者是用kosity分解直接法去解信息系统的时候,它有很大的一部分计算量是花在分解上的,就是我首先给一个矩阵,我要把它分解成下三角跟上三角嘛。
如果大家还记得我们第二节课的时候,我们讲那个写写新系统的时候,我需要把它先分成上下两部分,分成上下两部分之后,完了之后我再用迭代的一个方式,我分别对l跟u做做求解嘛,对吧。
这里的计算量其实主要在前面那个部分,就是分解这个部分上,那如果说我这个矩阵是个常数矩阵的话,也就意味着我只需要分解一次就可以了对吧,我只要把它分解一次,然后分解一次,完了之后,我这个计算量就省下来了。
之后我在模拟的时候,我只要对分解出来的这个结果我就分别迭代求解,这样子的话我就可以让我的整个模拟可以很快的跑起来,这个其实是projective dynamics这个方法,它推出来的主要原因在于此。
他最终的目的就是想要搞这么一个常数矩阵,然后有了这个常数矩阵之后呢,我可以分解一次,分解一次,完了之后我就一劳永逸的哎,我就可以简单求解了,这是它的一个呃根本目的,那么为什么这个方法可以这么做对吧。
因为尤其是大家就是我看有同学也问了嘛,就是说咱们正儿八经的做弹簧系统,正儿八经地去解牛顿法,我需要得到真正的这个弹簧系统的和声,对不对,这个是我们正经的这个牛顿法吗,但是为什么我不去用真正的喝水。
我去用各种各样假的这种合成这个方法,它也可以work对吧,我们其实前面举了很多例子了,我给大家可以回顾一下,就是比如说我们上上周的时候,我们讲说我们对这个合成做一些修改,我强制的让它变成正定的矩阵啊。
这是一个方法,我们其实谈过,但是我没有细谈,我看到有同学也问了,说哎这个方法怎么也会work对吧,为什么我去修改这个和弦,把它硬给它搞成镇定的,这个方法也能收敛,然后咱们作业里其实也是一个新的方法。
对不对,我们作业里甚至都没有去做合成的计算,我直接就是给了大家一个公式,一个魔法公式嘛,然后大家利用这个魔法公式啊去计算这个deltx这个方法居然也work,对不对。
然后呢刚才我们讲project dynamics,大家也看到了,我搞了这么一个常数矩阵,我利用这个常数矩阵,我去解这个东西,它也work,那么事实上呢这个方法它其实是一系列的方法。
我们其实到讲有些人的最后一天的时候,我会给大家谈一谈这个方法为什么会work的,但是简单的说呃,你可以认为就是说我不需要严格的去计算这个合适,我可以做很多近似,然后只要我这个近似是合理的。
我只要我这个进四是正定的啊,我都可以保证它是收敛的,那么这个收敛其实他其其实他这个收敛好不好,取决于你这个和尚到底近似的好不好对吧,我这个如果说我跟这个和尚长得很像,我跟我有个矩阵,我跟和成长的很像。
那么我近似就会更好一点,我的收敛就会更好一点,更快一点,如果说我进四的完全风马牛不相及的,那么我的这个效率就会更低一点,甚至于如果说你不用合成,你直接用一个identity matrix。
用一个单位矩阵,他也能收敛,只不过这样的效率就会很低了啊,我们回头会进一步的去分析这个方法,但是反正就是给大家提一笔,就是只要你去做一些简单的近似,它其实也是一个能够模拟的一个方法,好吧。
然后这个嗯反正就先到此为呃,反正project dynamics我就先到此为止了,这个我就想我就想先不讲了,大家这里有没有什么问题,我感觉讲的可能有点快,我看看,就是简单的说就是我的力,我的我的能量。
我的力其实跟正常的弹簧系统都是没有区别的,唯一的区别就是我的取证,因为我projective dynamics,我做了很多简化,做了很多近似,不是简化,做了近似,导致我估出来的这个河神变得很简单啊。
然后呢我跟呃,然后我就可以很简单的去模拟这个东西,这个反正大家理解吧,我看大家也是啊,也是要理解一下这个东西,做完投影以后在影视积分求解吗,我看一下啊,这里,嗯对于这个而言,其实都不需要。
就是你可以算完投影以后再算力,但是因为这个力对于弹簧系统而言,这个力跟弹簧的力是一样的吗,所以说你直接算利,也可以,直接用弹簧的力算也可以,那对于弹簧系统而言的话,那就完全不需要做任何投影了。
但是有的东西它需要投影,就比如说呃我我刚才就是给大家给大家讲,就是比如说你做shape match的时候,他需要投影,因为shape match他没有办法直接根据像类似弹簧那样可能算个例。
所以说他有投影那一步,其他的其实跟饮食积分是一样的,就是你其实可以甚至你就可以直接理解成我做影视积分,只不过我偷懒,我不直接去算,真的和审,我搞了一个简单的方法,我去估算这个合成。
然后我然后我让这个我假设这个合成是个常数矩阵,所以说我就把整个东西搞得很简单了,大概是这么一个思路,同一个顶点在不同边的投影不同,对是的,就是同一个顶点在不同边的投影是不同的,就比如说这里嘛。
比如说比如说0号顶点对吧,0号顶点它其实就是有三个不同的位置了,就分别对应三条边了,它有三个不同的位置,我这里其实我的这个下标什么的都搞得很乱啊,其实大家反正就是回头可能有时间再仔细看一下。
就大概能理解吧,就是每个顶点它其实对于不同边都有自己的位置,projective dynamics ppt用的多么,效率多少啊,我先回答前面那个问题吧,前面有个同学问有限元的和神,有些人的和声。
咱们呃下下周可能会讲就是怎么样对有限元算算和审,但是那个东西确实是挺复杂的,所以说可能也是有点像科普那样的性质吧,反正给大家大概讲一下这个意思是什么样的意思。
projective dynamics跟ppt在游戏中用的多,游戏里面一般来说用的是p p t为主,呃如果说你要做模拟的话,一般是p p t为主,然后游戏里面用的更多的是骨骼动画。
就是它其实并不是模拟的,它是根据人体,因为一般来说他们一般模拟就是一件衣服穿在人身上,所以说它是根据人体骨骼,它去驱动这个衣服,然后它会采用一种类似混合式的模拟方式,就是一半它是根据个人体骨骼带来的。
然后另一半它是类似一个p p t的这种,然后呢我其实呃p p t其实没有讲太多,就是说游戏里面怎么搞,其实这里面还是有蛮多细节的,其实有一点没有谈到的,就是我们很多模拟方式,它其实都都不是计算为主的。
就大家可能听了这句话觉得很奇怪,就是说什么叫做不是计算为主的,我们这里不是有好多公式吗,好多计算公式吗,对不对,事实上这些计算公式对于我们当代的g p u c p而言,其实都是计算不了太多时间的。
他真正的计算开销,他真正的时间开销在哪里,在内存访问上,因为我你看我们每一次计算这些每一个迭代,我都需要去访问顶点的位置,所以说他很多时候就是在访问main memory或者是gpu memory。
global memory的这个计算成本上的成本上,反而他这个计算过程它其实是很快的,那么对于p p t而言,它其实它的优点并不在于说它这个精准或者是什么。
它这个p p t它这个最大的优点在于它的内存访问非常的少,因为他没有什么所谓的物理,没有什么物理变量,也没有什么啊,什么速度什么它其实都可以暂时忽略不计嘛对吧,他就是直接去修改顶点位置。
也就是说他唯一需要访问的信息就是顶点的位置,而其他的模拟方式,不管是project dis也好,还是其他的方式也好,你都有一些其他的变量,一些物理的变量你需要访问。
所以这就导致了其他方法它的物理它这个内存开销成本会更大一点,就实际上你在做一些比如说你要非常非常高的性能的时候,你反而是需要怎么样去优化你的内存访问,而不是说简单的去。
比如说呃就是把你这个计算方式给它调整,其实这个带来的提升是很少的,真正带来的提升主要是在内存访问上,你怎么样能够让内存访问的更连续,做这个优化也好,其实是一个蛮大的学问。
但是咱们这个课就不深的往下讲了好吧,然后咱们咱们先继续讲吧,这个咱们时间有限,然后有什么问题,咱们可以课后再继续讲,跳跳跳跳跳,然后我们接下来啊,接下来讲一下project dynamics的优缺点吗。
这个是给大家看了一些一个我从那个project dynamics,那个paper里面抠出来的一张图,然后蓝颜色的跟绿颜色的是是牛顿法,分别是用两种不同的方式去求解啊,呃蓝颜色的是用kosi分解。
也就是直接法解线性系统的直接法,然后p c g是那个一个迭代法,然后大家可以看到大概是这么一个呃效率收敛效率,然后红颜色的呢是project dynamics,然后可以看到什么。
可以看到他一开始的时候其实很快,对对对,对,头上那一点时间其实特别快,但是之后呢它这个效率就其实就不如牛顿法了,而且甚至再往后,如果说你的精度要求很高的时候,其实他这个收敛其实就会逐渐放缓。
它的优点主要是跟p p t比吧,跟p p t比,它的优点在于它其实是正常的弹簧系统是一样的,跟正常咱们做物理模拟的这个整个思路其实是一样的,利也好,其实都是一样的,它是有物理含义的。
在cpu上它这个效率是很高的,因为我可以用直接的解析系统的方法去求解嘛,而且我只需要只需要做一次分解就行了,所以说他在cpu上是很合适的嗯他一开始的时候收敛效率很高,大家可以看到啊。
缺点是及pu上它不太合适,因为直接法这种lu分解的方法在gpu上其实是不太合适的,然后它总的这个收敛其实并不是很理想,一开始虽然快,但是之后就下降了,然后呢如果说约束改变,什么叫约束改变。
也就是比如说我这个网格发生变化了对吧,我本来是呃五条弹簧,我现在变成六条弹簧了,或者是我比如说我想把碰撞也作为一种约束加进去,那么它就比较难处理了,因为我的这个矩阵是由我的这个约束形成的嘛。
那我约束改变了我的矩阵也需要变对吧,那么这个相对来说就会变成一个比较麻烦的一个点,这个反正就是给大家科普一下吧,就是大家有时间的话,其实还是可以呃去读一下这个paper。
这个paper paper讲的比较细,我就我就反正给大家介绍一下这个方法,然后第二个方法呃,我其实也想讲的,但是我可能不想花太多时间讲的叫做constrained dynamics。
这个名字其实听着有点费解,因为我们前面讲的这个ppt也好,project dynamics也是用constrain,这个跟前面那些方法有什么本质的区别啊,这个方法的提出,他其实想做一件事情。
就是他想处理非常非常非常stiff的约束,因为我们前面讲p p t还是讲project dynamics,还是讲弹簧系统的时候,我的约束其实我的弹簧也好,我的这个约束也好,其实都是很难严格的保证的。
那么如果说我想要严格的保证呢,我就需要做很多很多次的迭代,因为ppt project namics implicit,这个做这个影视积分弹簧系统,本质上我都需要做很多次迭代。
我才能够产生step的一个效果,那么如果我做很多次迭代,我就不可避免的,我就会有很大的计算量嘛,那么问题在于我有没有什么办法,我可以不需要做好多好多次迭代,我不需要花这么大的计算量。
我也可以很好的去模拟这些很stiff的约束呢,这个其实就是这个方法当初提出的一个呃思路,而且这个方法其实不只是用在呃我们模拟,比如说衣服啊,或者是其他里面,它也可以用,在很多时候。
它其实是用在刚体模拟上,就是咱们做刚体模拟的时候,有一类缸体叫做articulated body,就举个简单例子,就是人体,我可以把人体认为是好多钢体所构成的对吧,我的躯干,我的四肢,我的手臂啊。
然后我的这个头,我的脖子,我每一个地方我认为是个缸体吗,然后呢我缸体和缸体之间我是用关节所连接的,那么这一个关节它其实就是一个约束了对吧,比如说我的这个上臂和下臂,我的我的上臂跟我的我的这个躯干。
我希望通过肩膀这个关节来连接,那么这个关节是个约束,我要求说这个手臂跟去干,必须在这个肩膀的位置,它是重合的,他这个点的位置必须是同一个点,那么这个约束我其实是希望他这个约束是非常非常强的,为什么。
因为当你在模拟人体动画的时候,如果说这个约束不满足,那他这个四肢岂不是就是跟躯干分开来了,那就一点都不合理嘛,对不对,所以说我是希望模拟这个这种缸体,这种多缸体的这种彼此间的约束的时候。
我是希望这个约束是非常非常强的,就说这个方法它其实更多的时候是用在钢铁模拟上,我等会儿会给大家看一个例子,但是咱们这里我还是用弹簧来给大家展示一下,这个方法的思路是什么样子的,那首先假如说我有一根弹簧。
我这根弹簧的原长是l e,然后呢我有一个约束对吧,两个顶点的差的位置差减去l e,这个就是咱们的约束,这个是其实跟咱们之前讲的这个p p t啊,project dnamics啊,其实这个都是一样的。
约束,其实形式是一样的,没有区别的,那么接下来咱们看能量,咱们之前能量形式是这样子的,就是二分之k对吧,乘以这个长度减去原长的平方,咱们之前是这个形式嘛,那我们现在把这个改一改,我们改成什么呢。
我们首先看到这个括号里面这个东西啊,其实就是约束啊,对不对,其实这玩意就是这个fine嘛,翻译嘛对吧,那我可以把这个东西我把它写成一个关于约束的函数,怎么写,我把1/20,首先1/2写在前面。
然后其次呢我把饭给它写成一个大的向量,这个向量呢有多少行,它有一行,这个e是我们所有的约束的数量嘛,然后每一个约束它都有一个约数值对吧,那么也就是相当于这个东西就是一个大的向量吧。
这个就是分别是对应着这所有的编码,这个是f01 这样子,以此类推,我下来我就有好多好多约束到fn f1 ,这个是我的这个所有的约束,就针对的就是相当于我这里原来我是一个求和的过程。
只不过我原来是求和的时候,我有这我有一个和对吧,有有有一个和,那么我现在就把这个所有的这个每一个值我们都列成一个大向量了,然后这个c呢c是k inverse的一个对角矩阵。
我们把它叫做compliant矩阵,它就不是stiffness了,它不是挺度,它是柔软度,它是软度,我们把它叫做软度矩阵啊,compliant matrix。
然后你会发现这个东西跟前面咱们这个能量的呃形式是一样的,只不过呢我换了种写法,我一利用这个约束的这个向量,我写成了这么一个形式,但是大家如果把这两个东西啊乘一乘,这几个东西乘一乘。
你会发现这个东西其实跟这个东西是等价的,那么好,首先我们把这个能量换了种写法,那么接下来呢我们要对立也要换一种写法,因为我们能量写成这种写法了吗,我力也要换一种写法,那么我来怎么算力啊。
我利等于负的能量的梯度对吧,这个是咱们的定义,这个没别的可说的,就是定义,那么能量我原来是写成关于x的函数,所以就本来就是d e d x嘛,那么现在我这个里面因为我换了种写法。
我这个x变成了我约束的一个变量,我这个约束变成了一个顶点的函数了对吧,那么我就可以用偏微分来写,我就写成d e define乘以defy dx,这个是咱们求导的时候的链式法则。
这个大家应该学微积分应该都了解,dee defi乘以defi,dex相当于我这个five,我这个约束成为了我这个能量的一个中间变量,能量函数的一个中间变量,那么好我再往下走,首先我这有两个部分构成。
分别是这个绿颜色跟蓝颜色的部分对吧,呃我要对它做一个转置,那么转置完了之后呢,蓝颜色的东西都到前面了,绿颜色的都到后面了,所以这个东西没什么可说的,那么defi dx我把它叫做一个其叩变矩阵。
就是我这个约束啊,我这个约束对x求导,我把它叫做结构变矩阵,它是一个e乘以sin的矩阵,那么我这边就是蓝颜色的部分,就是j oia是defi d x那么dee defi是什么呀,根据我前面这个定义。
根据我前面这个关于能量,关于fi的定义对吧,我两边都有fine,我认为这个five是一个向量,那么对它求导之后,我就得到了,因为他这里有两出现了两次嘛,所以说跟这个二对掉了,跟二对掉完了之后。
我把他一个去掉,就得到了c inverse乘以反,就是后面这个东西就得到了绿颜色的部分,然后这个负号是从前面抄过来的,ok那我现在就是得到了一个利益的一个新的形式啊,我本来我这个力呢是啊。
直接根据一个公式算出来的,现在我把它写成了负的j q a乘以对inverse乘以y的一个形式了,那我这里再引入一个中间变量,这个中间变量呢我把它叫做拉格朗日算子,就是负的c inverse乘以负i。
这个就是lab的,这个是我从新的引入的一个中间变量,这个是关于约束的一个拉格朗日算子,但是大家如果不知道什么叫拉格朗日算子也没关系,反正就是我引入了这么一个变量,我把这个绿颜色的部分。
然后跟带着负号的绿颜色的部分,我用这个lambda给它替换掉,那么这个说明什么,这说明力我的力啊,就是我的chopian乘以我的lambda,这个是我想要得到的,那么我有了这个东西之后呢。
有了这个东西之后呢,我就想要做影视,我就想要跟我们之前一样,也是继续做影视积分了,只不过我做影视积分的时候呢,我之前我的影视积分是只有一个变量的,我们之前做影视积分就只有x这么一个变量吗。
我现在呢有了这个lamba之后呢,我就有两个变量了,我有x跟lambda,我是由两个变量构成的,这就是为什么我这里叫door variable,就是相当于第二个变量。
那么我怎么去用两个变量去做这个模拟啊,首先我知道根据影视积分啊,我知道说我这个动量是这么更新的对吧,这是动量的一个动量守恒的公式嘛,就是质量乘以新的速度等于质量乘以老的速度,加上时间乘以冲量。
对吧啊不是不是时间乘以冲,就是等于冲量,然后冲量等于什么呢,冲量等于冲量等于时间乘以力嘛对吧,因为我的这个只扣变an transport乘以lambda,这个是力吗。
所以说这个东西其实就是一个动量守恒的一个公式,就是动力就是动量的变化等于冲量,这个东西大家应该没有什么问题吧,这个就是冲量啊,这个东西就是动量守恒,然后这个这个后面这个部分就是力,就是这个力。
ok然后呢,我知道c乘以lambda等于负的法,为什么,因为lambda等于,因为lambda这个lambda好丑啊,lambda等于负的c inverse乘以φ嘛,就是咱们前面讲了吗,这是它的定义吗。
就是这个这个lambda等于负的c lambda等于负的saver fm,就是它定义,所以说我就照抄了这个定义,只不过我这个定义是在新的状态下,也就是未知的状态下为他写出来的,新的状态下写出来的。
然后呢我对这后面这个东西啊,我做一个泰勒展开负的新的约束,等于负的老的约束,这个是原来的约束减去折扣变乘以位置的变化量,然后这个折扣变呢咱们之前也讲过是defi dx,也就是位置的变化量。
然后这个呢等于负的f减去delta t h h q b乘以v6 ,因为位置的变化量等于速度乘以时间嘛,所以说我就有两个公式了,然后呢我把这两个公式合并起来,我就合成了这么一个系统,就是矩阵。
这边是我的举证啊,上面这个公式是质量,质量乘以v6 减去deltt乘以指扣边乘以lambda,new等于b就是第一个公式,下面这个公式呢就这个第一个公式就是变成了我的第一行。
然后下面这个公式变成了我的第二行,就大家如果把这个这两个公式都整理一下的话,就会得到这么一个结果,好然后我们这个事情其实就已经解决了吗,我们本质上我们就是想要得到一个公式去模拟我的这个位置对吧。
只不过我现在不用用位置,我用速度其实也是一样的,那么我这里呢跟我们之前做影视积分不一样的点在哪,我们之前做影视积分,我只有一个变量,我只有v61 个变量或者是x new一个变量,但是我现在有两个变量。
然后我把这两个变量同时的去解出来,就可以得到我的解,这就是首先第一点就是我有一个系统,我们刚才构造了这么一个系统,这个系统是由两个变量构成的,一个是我的这个主变量,我的顶点的位置或者是顶点的速度。
然后我的第二个变量是我的拉格朗日啊,我我我的这个lambda,然后有两个方法,第一个方法是直接法,直接法怎么解啊,我就是有这么个系统之后对吧,我就直接把这个系统给解出来了嘛。
我有各种各样解信息系统的方式,我就直接把这个系统解了就完了嘛,写完之后我就得到新的v跟新的兰姆达,然后我就根据这个新的v我就可以更新顶点的位置了,然后下一个时刻我就继续模拟。
我就得到了更新的v跟线性的level,我就一步一步地往前模拟,这种模拟方式在数学里面叫做prime do,什么意思,就是我两个变量我是一起去解,我同时求解的,这是一种方式。
然后第二种方式呢是我可以做一个校园,我把这个给它消掉,我只算lamba,我如果只算lamba的话,我会得到这么一个系统,然后呢我就把这么一个小的系统给它解出来,写完之后呢,我把这个v给他更新一下。
根据这个第一个公式,我把它更新一下,我就可以得到啊,结果那么这个方法呢就是分次的分两次来求解,第一次呢先把拉姆达算出来,然后再根据lambda把venue算出来,然后取决于你的不同的问题。
不同的这个呃问题,你这个两种方式都可以,但是取决于你不同的问题,你可能采用不同的方式,然后这里我想提一点的,就是说如果是你采用上面那种方式,第一种方式的话,你要特别注意,就是这个矩阵啊。
他有可能不是镇定的,因为我们之前谈过很多次,就是镇定,其实对于呃线性系统来说特别重要,有很多方法啊,不镇定的时候用不了,因因为它不是正定的,所以说它其实有很多方法用不了,用不了。
你必须要采用一些比较特殊的方法,比如说gm r e s这种方法啊,才能够解解这个问题,像常规的,比如说康熙给的gradient的共轭梯度法,你是用不了的,然后后面这个方法其实也有问题。
后面方法有什么问题,就是他这个校园有的时候不是很容易就前面这个东西,这个矩阵不是那么容易构造的,尤其是你这个举证比较复杂,这个质量矩阵比较复杂的时候,你是没法算这个东西的。
而且它这个东西很有可能这个矩阵它不稀疏,他可能会比较密,这就会导致你其实你用第二种方法也不合适,所以说就是各有各的坑嘛,具体反正要看具体问题具体分析,但是我说完坑啊,说完坑了之后,它有什么好处。
它最大的好处在于我可以处理非常非常强的情况,甚至于我可以假设是无穷大的,因为我们之前我们模拟的时候是用k来表示stiffness的对吧,然后k趋向于无穷大,我就没法模拟嘛。
因为我整个系统会变得很stiff嘛,在这个里面我这个c呀,我这个c其实是k分之一identity,所以说如果说我这个k趋向于无穷大,我大不了把这个c搞成零就行了,那我还是可以模拟的。
所以说这种方法它最大的好处就是在于可以处理stiffness,很大的时候就是stiff越大,它这个c越小,这个c越小呢反而会让这个系统会更好。
所以说其实这个方法最大的好处就是它其实跟stiffness的verse相关,而不是跟stiffness相关,当然这个东西其实嗯,给大家一个思路就是如此,就是为了为了处理stephenness很强的情况。
呃,具体的话呃可能是要看到就是某一些paper或者是某一些方法,大家有可能会注意到这个方法是这个方法我自己也从来没用过,我只是反正就是呃了解过这个方法。
然后反正现学现卖就是呃给大家就是希望大家就是有这么一个概念,就是在处理一些强约束的问题的时候,或者是比如说像articulated body的时候,一般来说是采用这种模拟方式。
是采用引入一个新的这个lambda变量,然后用这个lambda变量呢去进行求解,然后这个这个就可以让你的这个系统会能够处理很stiff的情况,模拟是找量纲相同的式子往上靠。
我这个不太明白你这个问题是什么,什么叫做找量纲相同的式子往上靠就行了,要求解位置,我还是先给大家看一下,给大家看一个demo吧,这个是我上课之前用unity做的。
因为unity就有这个功能,就是做articulated body呀,我这里上面不是有个小人儿吗,对吧,这里有个小人,然后我用这个articulate the body模拟了一下。
然后这个结果就是这个样子了,就duang掉到地上,然后就我就就倒地了,然后这个东西就是利用我们刚才说的这个concert dynamics进行模拟的。
然后这种动画它其实有个名字啊,动画叫做这种动画,叫做ragdoll animation,等一下,叫做ragdoll animation,叫做布偶动画,其实就是假设假假设我这个人体它是以好多缸体构成。
然后缸体和缸体之间有一些约束,然后利用这个约束进行模拟,然后我这里其实就想停到这里了,因为后面其实还挺复杂的,我觉得大家有时间的话可以去读一下,其实后面想讲一个什么意思呢,就是说你对于这个公式啊。
我们刚才讲了可以做高斯消元嘛对吧,你如果把这个v消掉了以后,你会得到这么一个关于lambda的式子,然后如果你把lamba消掉,大家猜会发生什么,如果说你对这个式子进行高斯消元,然后把拉姆达消掉。
你会得到一个什么,大家猜猜看,如果说我把lamba做个高斯消元,没错就是就会得到影视积分的式子了,因为la消掉以后,我只有v了嘛对吧,然后你会发现其实它就变成了一个之前我们讨论半天。
讨论了半天做饮食计分的那个事,那就变成一模一样了,然后有篇论文啊,有篇paper,如果大家有时间的话,可以去读一下的,就这篇paper叫做stable concert dynamics。
他其实就说了一件事情,就是说其实你做高斯消元,你把这个拉姆达消掉,你会发现其实这个跟影视积分是一模一样的,但是有一点稍微不一样,就是影视积分里面它其实有一个有一部分和声在高斯消元之后,它是不存在的人。
然后这个paper说他说把这个消失掉的这个东西加回去之后,会发现让concert dynamics变得稳定,然后他其实就paper就讨论了这么一件事情,然后大家反正有兴趣的时候,有兴趣的话。
可以去读一下这个paper,给大家科普一下,好吧,然后这个基本上就是我想讲的,然后反正简单的总结一下吧,就是我们上次讲的ppt跟stray limit。
他们最大的特点就是我们需要构造一个projection函数,对于每个约束而言,我需要构造一个函数,然后我有几科比跟gsl两种方式,低配低分辨率很快,但是高分辨率呢存在各种各样的问题。
然后他也没有什么物理含义,然后project projective dynamics呢它需要做projection,它跟ppt一样,它也需要做projection。
但是呢这些projection呢是把它放到这个能量里面去的,然后在每一次迭代呢,我需要重新计算这个projection,然后呢把这个projection作为一个常数。
然后呢接下来我就做简单的饮食积分求解了,然后这么做的好处在于我的矩阵变成了一个常数矩阵啊,我就可以事先做分解,事先做分解的好处就是我在cpu上可以特别快,但是它本质上它还是有收敛的问题。
它收敛的还是不够快,跟ppt有点像,它还是存在收敛的问题,最后我们就是简单的简单的给大家看了一下concert dynamics,它就是处理非常stiff的问题,它最大的特点在于它不用一个变量啊。
我之前我们所有的模拟都是只有一个变量,一个顶点位置或者是顶点位置的速度,顶点的速度,这里呢我后面我们引入了一个新的变量,叫做do or variable,lamba,这个do variable。
然后有了这个do variable呢,我还可以进行影视积分,然后带来的就是一个系统,就是由两个变量所构成的一个系统,然后存在两种方式去模拟,然后因为这个系统会不镇定。
所以说我的sov我的求解也会存在一些的一些问题,反正反正今天就是嗯给大家科普一下,我知道这里可能就是数学这东西很多,所以说大家有可能就是回头感兴趣的话,需要到课后花一点时间去读一读这些东西。
反正今天就是给大家那个介绍,如果说大家感兴趣的话,可以回头再了解一下啊,有什么问题吗,我想我想看一下,其实最后面这块concert dynamics,我也是ppt的时候,我也是看了半天才写的。
所以说看的有点懵是很正常的,我自己也是看了看了一会儿,应该不是分开建模的,那个有同学问那个小人的身体是不是分开建模的,这个我还真不知道,但是我想应该不是分开建模的,一般来说是一起建模。
但是他会把身体的一些分块,它会把身体分块,会不会是昨夜那个这个其实很简单,unity里面因为它提供了这个功能,你只要创建一个rag doll的一个object。
然后你把身体的每个部分给它复制过去就可以了,所以unity其实帮大家做了很多事情,吧反正就是反正大家有时间的话就是感兴趣,有时间的话可以课后在嗯把这些东西在呃了解一下,通常的骨骼动画是怎么来的。
如果是人体的动画,一般来说有你可以做动动补吗,做motion capture,然后如果说是动画电影的话,一般来说他们的动画就完全是用美术手工的,用那个关键帧做出来的,有时候是这样子的。
然后游戏里面很多它的骨骼动画都是预定义的,就比如说美术它可以用关键帧线预定义好,然后根据你用户的一些选择,你可以比如说控制这个人体的运动吗,比如说让他跳,那么他就呃进行跳的操作,让他跑。
他就进行跑的操作,一般都是用关键帧给他k出来的,有同学问作业实际上是project dynamics吗,也也并不完全是吧,因为咱们并没有用lex那个方式去搞那个搞这个矩阵。
我们的举证跟project dnamics不太一样,但是这个思路其实是比较接近的,就是我反正就是去做一个进四,我搞了一个,反正搞了一个常数矩阵,我去进四了一把,然后利用这个进四我去进行模拟。
然后这一块基本上就约束这一块就到此为止,然后我想给大家讲一下有限元,有限元其实大家大家知道是一个大坑吗,尤其是比如说学机械啊,学土木,学力学的同学可能要啊学蛮久的。
所以说咱们这个东西其实呃一方面也是科普,会有一部分科普的部分,然后另一方面咱们也有作业的部分,咱们有一个作业就是专门去写一个简单的有限元模拟啊,所以给大家就是一些简单的方法,相当于给大家来介绍一下啊。
然后呢我这一块呢其实会分成分成部分来讲,第一部分是讲fm,就是正常大家所知道的有限元,finite element method,还有一个方法呢是图形学里面也很常用的。
叫做final volume master,对于linear element,也就是所谓的三角形或者四面体啊,这个我们把它叫做linear element,这其实是一样的,大家会发现这两个东西是一样的。
就是说我们的作业里面也会让大家去验证一下,就附加题其实就是让大家去验证一下,这两个方法其实是等价的,嗯同学问就是机械里面的有限元跟图形学的有限元有什么区别呢,如如果是linear element的话。
是一样的,我们的方法是一样的,但是在机械里面很多时候他用的不是linear element,比如说咱们一般来说就是用三角形或者是呃四面体吗,二维就是三角形,三维就是四面体。
但机械里面他们有可能会用先行都有的都有限元,或者是用啊,或者是用立方体的有限元,所以说这个东西就不一样,然后还有就是机械里面它有可能会用高阶的有限元,就是它不是li的i的话。
比如说一个三角形就是三个顶点,一个一个一个平面上的一个element,就是一个三角形,但是如果说是一个这lina,比如说是一个二阶的,它有可能会在边上再加额外的控制点,那么就变成六个顶点的约束了。
就是它的它的这个复杂程度会高很多,如果说咱们只考虑li,那么基本上是可以认为是一样的,最后我会讲一个呃弹性模型,因为有些里面比较涉及的比较多,尤其是我们要模拟一些呃人人体肌肉对吧。
很多时候我们要用一些比较呃复杂的模型啊,当然我们作业里面的模型会比较简单,给大家呃给大家简单的介绍一下啊,一个一个方式,但如果大家想尝试高级的啊,model也可以也可以试一下。
一般来说我们图形学里面一般是lina为主吧,比较少用到高阶的,首先啊首先咱们来讲这个f e m这个方法啊,简单的说这个什么是一个f e m,什么是lini f e m。
简单的说就是说我假设这个三角形在内部的形变,它在内部的形变其实是一个均匀的,那什么样是均匀的呢,就比如说我这里有有一个三角形对吧,x0 x1 x2 这三个三角形三个顶点。
把这个状态我叫做reference状态,也就是它没有形变的状态,它是静止的状态,假如说这个三角形发生形变了,它变成了一个呃新的位置,变x0 x1 x这个时候我用小写来表示它的这个形变之后的状态。
大写表示它静止的时候的状态,那么现在它这个形变之后就变成了x0 x一这么一个绿叶子的三角形,我其实就假设说这个三角形里面的每一个点,它的这个映射都可以用这么一个线性公式来描述。
这个x它其实可以是任意的x,它既可以是顶点的x,也可以是三角形内部的x,就假如说我随便找一个点,就是三角形内部蓝颜色的三角形,随便找一个点,我把它叫做x,它映射到的这个位置啊,就是小x与fx。
我可以用这么一个简单的线性公式来描述它这个形变的映射关系,这就是我的一个有限元的一个思路,为什么叫线性的,因为这是一个线性公式嘛对吧,这就是他的一个思路,首先我们来看怎么样去算这个f。
然后这个f是一个矩阵,c是一个矢量向量,f呢就相对应的是什么,是它的形变跟旋转,相对应的是它的平移,因为它的这个位置也会发生改变吗,所以说我既有平移的部分,也有其他变形的部分。
这个f有个名字叫做defamation gradient,叫做形变梯度,那这个deformation gradient是为什么这么叫呢,其实这个f等于dx dx嘛,小x d大x如果大家做一个求导的话。
你会发现这个就是d x d d大x,所以这个我们把它叫做definition vidi,好我们现在第一步就是我们想要知道说给你一个三角形,然后这个三角形的位置发生变化了对吧,第一步我怎么得到这个f。
怎么算这个f,首先我们会发现一个现象是什么现象,就是说假如说我有两个顶点,中间有个向量,我这个三角形内部会有一个向量,从a到b的一个向量对吧,我把它叫做x b a同样的在形变的状态下,我也有一个向量。
就是x只不过这个是小小x,这个是大x分别对应的是形变前跟形变后的向量,就变形之前跟变形之后的向量小ba等于小b减小,a等于f x b加c减f x a加c对吧,这是我知道我们根据这个形变公式。
这个是形变之后的a跟b的位置,这个等于什么呢,等于f乘以ba大ba这就意味着说对于一个向量而言的话,对于一个矢量而言的话,我这个f就可以描述这个矢量的变化了,之前是大ba,然后我把这个大b a乘以。
前面乘一个f,我就可以得到小b a变换之后的状态,以此我就可以得到我这个取证了,这个f取证了怎么算呢,我构造两个句子,构造两条边也是01跟02这两条边,根据我刚才的描述。
我知道f乘以大的一零等于小于零,f乘以大的二零等于小于二零,也就是意味着说利用这个f我可以把两条边变化到两个新的状态上去,对吧,我把这两个公式合并一下,我就得到了f乘以一个矩阵,为什么是一个矩阵。
因为这是一个乘二的矩阵嘛,每一个都是一个二维向量对吧,一零跟大的二零,他们都是二维向量,然后我有两条边,所以说我这是2x2的矩阵,等于另一个2x2的矩阵,后面呢就是,边向量我把它搞成两个矩阵。
那如此之后我就可以得到我的definition规定的了,我就是等于我的边向量矩阵乘以大的边向量矩阵的逆,就得到了defamation gradient,我就是把这个大的变向量矩阵。
我把它沉到公式的右边去了,得到了这个,也就是说我这个deformation规一点的,我其实就可以通过我的边向量矩阵,我可以根据边向量矩阵,我可以把这个给他算出来,我们前面也讲到我这个ation规定的。
我这个f其实描述了他这个他这个变化对吧,我描述了他这个形变一个三角形而言,呃,我其实就把这个位移这项给它抠掉了,我这个其实里面就有啊,那跟位移就是无关的了,问题来了。
我可不可以直接用这个f来描述这个形变呢,不可以,为什么,因为这个里面f它不只有形变,它跟形变有关,但是它里面也有同样也有旋转,因为如果说假如说我这个物体,我这个三角形没有任何的形变。
它只是在做钢铁的运动,在做钢铁运动,那么我这个f它其实里面也是有值的,这个就不太理想了,因为我很多是我想要描述形变,我是希望我这个形变是跟缸体的运动无关的,因为我知道钢铁运动是没有形变的嘛。
那换换句话说,前面已经把平移给去掉了,那接下来我怎么样去把这个旋转也给它去掉,这个是我想要得到的一个目的,为了满足这个目的呢,我就来看一下这个f是个什么玩意儿对吧。
之前讲过f通过s v d我可以把它分成三个部分,对应的是位置调整缩放,也就是形变跟旋转,其中那么其中前面这两个部分都是跟形变有关的,第一个部分它主要的目的是为了调整我形变的方向,我想要沿着对角线形变。
那么我就把它转到转45度对吧,第一个部分它虽然说表面上旋转,它其实是跟形变是有关的,第二部分,第二个这个缩放它也是跟形变有关的,它直接决定了我这个形变的大小是什么,只有最后一个旋转是跟芯片没有关系的。
最后一个旋转是已经形变发生完了之后再去调整这个物体的姿势对吧,我所产生的这个旋转,那所以说这个后面这个u啊其实有不有都无所谓,而且它是跟形变没有关系的,其实我的目的就是想要把这个u给它抠掉。
怎么样把这个u扣掉,这个思路是说我去做s v d,我做完这个s v d之后呢,我把这个u删掉啊,这是一个,但是这个思路听起来就不是那么美好,为什么我得我得要做s v d才行对吧。
那有的同学他不会s v d,那那怎么办,咱们数学家又想了个办法,就哎我可以不做s v d,我可以直接做这么一个事情,直接把f我直接在这里哦,直接把f乘以它自己的转置,我如果说我把f乘以它自己的转置呢。
你就会发现它中间的这个u啊就会对掉了,你会发现这里就变成了v d乘以u transpose,e u d transpose,如果说你做f f transpose f你会发现是这样的。
然后中间这个you呢就对掉了,你剩下的就是v平方,再乘以v transport,然后最后减identity,然后前面乘个1/2,这个就是它的这个呃一个思路。
咱们这个东西呢我把它有个名字叫做green street,green rain,那它是一个对称矩阵,你如果去看一下,你会发现它其实是个对称矩阵嘛,所以说虽然说它是一个2x2的矩阵,它只有三个变量。
你分别把它叫做u u u v跟vv,有同学可能不太了解什么叫做string,然后我这里就给大家讲一讲这个简单地讲一讲这个什么叫做,刚才说追就是我搞了一个东西,我搞了一个数学的一个量。
然后我用这个数学的量去描述这个物体的形变,这个量可以是一个实数,是一个弹簧的话,它就是一个实数,可以是个矩阵,比如说咱们这里三角形的例子,它就是个2x2的矩阵,三的时候它就是个3x3的矩阵对吧。
然后这个string它有什么特点呢,就是首先没有形变的时候啊,在没有形变的时候,它应该是零,你会发现如果说没有形变的时候,也就意味着d跟v都是identity的时候,那么这个东西它就是零了。
然后呢这个rain的大小呢它是跟形变的大小正相关的,你形变越大,你的这个rain也越大,其实它是也是满足的嘛,如果说你这个地越大,你这个green stream它也会变大,所以说它其实就是本质上。
它就是一个描述形变有无跟形变大小的这么一个量,咱们也讲了,就是三个不同的变量,最后也是我们刚才反复强调的,就是它是跟旋转无关的,旋转无关,就是说哪怕你之后再施加什么样的旋转。
我这里后面再给这个物体再怎么转的,这这个算出来的这个green rain它也是一样的,说我额外的再加了一个旋转对吧,假如说我加了个旋转二。
我总的deformation规一点的就会变成r乘以f是之前的形变,而是我额外在做那个旋转,假如说我额外的再把这个物体做了个旋转啊,green rain是什么呀,green rain就是1/2。
然后根据这个公式,我得到了f transpose,r transpose乘以二,f减i中间这个r对调发现这个其实跟之前是一样的对吧,也就是说就说旋转不影响string,这是跟旋转无关的。
也就是说它是描述了形变,就是我给大家引入的这么一个新的概念,叫做关于对于二维二维的情况,就是这样子,好了有了greece string之后呢,有了形变之后呢,我我接下来我就想搞能量了对吧。
咱们之前做模拟的时候,一般来说都是要有个能量嘛,咱们做弹簧系统的时候搞个弹簧能量对吧,有了弹簧能量以后,后面的就好办了,我就可以拿去用能量去算那个算力算和选算各种乱七八糟的东西,我都可以算。
有限元也是一样的,我有了形变之后,我就想利用这个形变能量,那怎么搞呢,对于这个三角形而言呢,定义了一个新的函数,我把它叫做能量密度,单位面积的能量,我把它叫做w,这个东西是rain的一个函数。
总的能量怎么算,总的能量就很简单了,我就密度乘以总面积不就得了嘛对吧,我的三角形面积是a吗,这是reference,因为它是静止状态下算出来的面积,那么就叫a reference。
那我面积乘以我的能量密度,我是不是就得到我的总能量了对吧,那然后这个东西呢就是我string所给的三个变量嘛,我是把这个东西写成string的函数,那么接下来我就把它写成string里面三个变量的函数。
对于这个三角形而言,对于三角形而言,因为我的defamation gradient,我的f是,那么我的rain也是常数,所以说在整个三角形内部啊,它这个这几个app啊一模一样。
然后我现在就有了这个总的这个能量了,那么嗯我照理说我就可以再往下推了嘛,但是我这里想提一笔,我想讲一下,就是我们具体里面具体作业里面想用到一个什么样的能量密度函数吧,我们做这里面用的比较简单。
叫做tv k sva curse of model,这个model其实在做模拟的里面用的并不是很多,尤其是在做一些力学啊里面其实用的并不是很多,但为什么我们图形学里面老喜欢用这个呢。
是因为这个模型特别特别简单,所以说作业里面我也就是沿用了这个模型,就是帮帮大家简单一下作业,简单一下这个作业的工作量嘛,咱们就用这个模型了啊,这个模型什么样呢,就是我这个那是关于这三个东西的函数嘛。
对吧,那么分别就是这个东西的平方加上这个东西的平,这个东西的一对和啊,大家看过就有数了,这里呢有两个变量,一个是lambda,一个是缪啊,它叫做lame parameters。
叫lai参数bk的这么一个模型,啊有了这个模型之后可以求导,我可以对dw对g求导对吧,我分别对它求导,我你可以看到这个东西就等于啊这个东西我就跳过了吧。
反正大家如果说呃w分别对这个呃这这几个变量求导的话,嗯反正大家可以推一下,推出来的是这个样子,比如说你对uu求导,你对求导的话,你这个二跟二对掉对吧,那么就是lambda乘以mu u。
所以说就这个加上加上两倍的meal乘以mal absent u yu,所以说两倍的mu乘以absent u,反正这个就是简单的求导过程,我相信大家如果不过学过微积分,肯定会算,反正这个就是给大家看一下。
你会发现这个东西呢,其实你可以直接的利用这个green rain给它推出来,就是两倍的mu乘以green rain,加上lambda乘以g的,就green rain的trace chidentity。
大家知道是什么吗,trace,我不知道叫什么这个trace啊,g trace就是它的对角的和这个矩阵的对角和就叫trace,你反正就是呃你反正就是可以根据这个公式,反正这也给大家了。
然后大家呃反正就是课后可以去推一下,会发现这个东西就是这样子的啊,这个东西我把它叫做s矩阵啊,其实它是有个名字的,它不是它,它它实际上是有名字的,它叫做second second,the pillar。
cash of stress,我这里少写了个s,名字有点绕口啊,我这里就先不解释,咱们其实下节课就有时间的时候,下节课我们在讲fm的时候会给大家解释这个东西,但是这个这东西到底是什么。
我其实给大家一个直观的概念东西其实是你你这么想,这个东西从什么推出来的,是能量密度对于形变的一个导数吗,我们之前知道就是能量对于位移求导是利,能量对位移求导力是力。
那么能量密度对于形形变本质上也是一种位移嘛,也是描述位移的嘛,它其实算出来的也是力,对不对,也是一个什么力的密度,我这里不是力,它是一个相当于是个力的密度,然后它其实也是跟力有关的。
这个其实就是给大家一个直观的概念,就是其实这个这个矩阵它其实是跟一个力有关的一个东西,只不过具体怎么跟力有关,咱们这里就先啊,等到下节课的时候,咱们会具体分析这个stress,他具体做了一件什么事情。
反正就是心里先把这个stress给大家,好我现在有了这么一个能量的定义,我有了对吧,我知道这个能量是面积乘以这个能量密度的函数嘛,然后我们能量密度的函数我已经有了。
然后能量密度对于这个形变这些变量的这些呃,这个string变量的这些导数我也有了,我是不是就可以算力了,我就可以利用这个我的定义来算力了,那么怎么算力呢,我这个力呢就等于负的能量对在求导嘛对吧。
我这个i顶点的这个力就等于能量对于x求导,然后前面加个负号嘛对吧,然后能量等于面积乘以能量密度嘛,所以说这个就是负的能量密度乘以负的面积乘以能量密度,对这个顶点位置求导。
因为我这个能量密度是关这个string里面三个变量的函数,所以我可以用偏微分做一个替代,我就可以分别w对这个每一个app求导,然后我的后半截呢是ap龙对于顶点位置求导,这个就就就是一个分。
就是很简单的一个呃一个一个链式法则吗,前面这部分咱们其实已经算过了对吧,我们前面讲就是我们就是算那个这其实已经算过了嘛对吧,这些这些项其实都有,其就是在这个stress里面,我给了这个stress之后。
我就可以得到了,绿颜色的这个部分其实我们都是知道的,都是可以算出来的,我们不知道的呢是后面这些部分,灰颜色的这些部分,这个是咱们不知道的,那么接下来我们来看看灰颜色的东西是啥,好不好看。
这个灰颜色的东西怎么推,那我们来看这个这个力是什么呀,这啊不是你这个是defamation gradient,我们这个defamation gradient呢是这个矩阵乘以圆边的矩阵的转置啊。
管他我可以先把它假设成是一个a b c d这么一个矩阵嘛,我就假设a b c d是这个矩阵的变量,我先不管它这里面是啥啊,我就先他是a b c d。
我这个deformation规定的本质上就是这个ax 10加cx 20,第一个力,第一个definition规定的向量,然后第二个向量是b x10 加dx 20,这个其实就是我简单的做了一个矩阵乘。
根据我们的这个green rain的定义啊,我们green rage是这么定义的,我就可以把整个乘起来,我这里就做了一个简单粗暴的一个方法,我就把全部都存起来了,然后得到这个样子,这个样子完了之后呢。
就可以分别对x一跟x2 求导了,那么对x1 ,那么这个东西是,是absaloon uu吗,他对x一求导,也就是它对x一求导,那么得到什么,得到的就是首先这个减1/2给他扔求导的时候。
这个常数部分可以给它扔掉对吧,然后其次呢这里有1/2,但是我这里相当于是一个平方,所以说我这里二也抵消掉了,我就得到了后面这个部分,因为前面这个部分本质上就是a乘以x一减x0 ,对x一求导。
那么我就把a留下,那么我前面就留下a,我乘以后面的这个部分就是做一个简单的求导,这里是探测calculus的东西,这个反正大家如果不太熟悉calculus的话,可以课后在自己课后再推一下这个东西。
就是absaloon,这个是absent vv啊,对x一求导也是一样的道理,就是把b留下,然后乘以后面的这个东西,然后啊对角的对吧,对角是,然后我对他求导是这样子,同样的呢我对这个x2 也可以做求导。
所以说其实我完全可以根据我们的这个定义出发哦,我知道这个green rain里面每一个变量,每一个这个u u u v v v它是什么样子的,然后呢我对这个分别对x一对x2 求导,我可以把整个公式推出来。
所以说其实可以做以前的paper也是这么写的啊,就是早早20年的paper都是这么写的,大家有没有发现这个东西特别复杂呀,一大堆公式,一大堆变量,你如果要自己真的去写这个代码的话。
我感觉大部分时间都在debug,因为你很难这里,如果比如说哪里正负号写错了,或者哪里abcd写错了,你可能得花很多很多时间去debug,比较简单,我就不需要用工具,直接就是首推就可以了呀。
因为这些基本上都是一个二次函数,直接可以推就可以了,在你会发现其实这个东西是可以做简化的,我接下来就是给大家看怎么简化这个式子,既然我们的目的是这个东西啊,首先咱们目的没有变,就是我们要算力。
我们怎么算力呢,我求导对能量求导算力,然后能量呢能量对顶点位置的求导就是力对吧,我这个式子没有变,这个东西利用我们刚才推的这些结论啊,我把它带进去之后得到这么一个东西。
这个反正就是我根据前面这一页抄了一下啊,啊反正就相信我这里没抄错吧,就会得到这么一个冻死,反正就抄了一下,你对这个式子你发现你可以做一些整理,你怎么整理啊,发现这个东西可以写成一个矩阵的乘法,左边是。
然后右边呢是这么一个矢量,然后你把它乘起来,你会发现跟上面是一样的,你再对这个式子再整理一下,你又会发现,等于这么一个东西,这边呢是我们刚才前面这个右边是中间是一个矩阵,然后右边是最,右边是a跟b。
绿色的东西是什么呀,是defamation规一点的,就是我们的矩阵,的东西呢就是我们前面算的这个d w d g那个东西啊,就是那个green rain啊,下次就简单了,其实我们没有必要去啊抄那么多公式。
然后利用那么多公式乘来乘去,乘来乘去,那个太复杂了,我完全可以用矩阵的乘法来替代,第一个顶点x一而言,它的这个力我可以做到这样的简化,我对于x2 而言,我也可以做这样的简化,那么以此类推。
我最终就可以简化成这么一个形式,就是两个力,我这个1号顶点的力跟2号顶点的力,我可以用负的面乘以formation gradient,我的second piero cost of stress。
在所以他圆长的那个编的这个矩阵的inverse,我就可以得到了架子,是不是咱们把这个一堆东西都搞得简单了,就没必要去搞那么一堆求导,求来求去求来求去求导,还是很容易求错。
我完全可以用这么一个简单的公式来替代掉啊,然后有同学可能会问说,王老师,你这里为什么只有两个力啊,只有x一跟x2 啊,为什么不算x0 啊,大家想想x0 怎么算,x0 怎么算,咱们可以利用牛顿定律。
牛顿说了,合力为零嘛,所以说x0 f0 就等于负的x一减x2 ,这个就零的零点点上的力就可以直接这样推出来了,嗯然后有同学问就是只有这个模型是这样的,还是其他模型都这样呃,体也是一样的。
四面体其实也是一样的,就是只要是linuf em都是可以采用这样的套路,大家看一下实践吧啊实践这里没写有没有写伪代码是吧,就反正咱们下节课讲那个第二种方法的时候也会提到。
就实践的话就是这篇论文可能是最近的一篇,讲那个用这种这种有限元的方法模拟衣服的方法,但是他这个方法其实也可以做到四面体的网格上,然后呃怎么样做四面体网格呢,其实基本上是一样的。
只不过你需要把所有的东西都挪到三维上,之前是二维的东西,你都挪到三维上,比如说咱们的deformation gradient,green stress tensor,然后呢立的话那就是有四个力了,对吧。
因为我有四个顶点,所以有四个力,那么对应的是我先算三个,然后最后一个顶点的利,我利用这个负的呃,剩下的其他三个力的和我可以把它算出来,然后这里对就同学说这里是算的顶点的力。
对我们因为我们这里模拟都是呃顶点系统嘛,所以说我们算的都是顶点的力,每个顶点的力把它算出来,我下周讲那个fm的时候,我会给大家哦,fbm的时候我会给大家那个伪代码,所以大家照着伪代码会更容易理解一点。
今天反正具体的内容就先到这儿,然后大家看大家有没有什么问题,内部的力是可以插值的吗,其实我们这里没有说内部的力,我们没有算内部的力,我们有考虑内部的利益,我们只考虑顶点的力,那么顶点的力是怎么来的啊。
其实我们讲下节课讲那个呃final volume method的时候,他就会讲解释力是怎么来的,其实力是积分得来的,就是比如说咱们有个三角形对吧,你可以认为这个三角形我把它分成了三块,不0号顶点吗。
它其实就是这里面会有很多力嘛对吧,我会这里面所有的这个力叠加起来,然后施加在这个顶点上,所咱们刚才那些推出来的东西,你会发现其实跟我假如说做这个力的积分算出来的是一样的。
就是我这里其实也是对他做了一个积分,是s是我的second pikof,stress tensor,就是一个是一个stress tensor,顺,有限元其实也是一样的,就是你构造也是构造力嘛。
首先你构造一个stream啊,这个string会比这个要复杂得多,因为我们这里string就是一个简单的举证了,然后你会构造一些形变模式,形变是来描述这个string,然后把这些形变模式啊写成一个能量。
把这个能量这些形变模式的函数,然后利用这些利用这个能量密度在求导,其实是大概是大概是一个思路,这是初始状态,就是它的静止状态,有限元,就咱们今天讲的这个有限元,其实跟我们之前讲那个弹簧系统啊。
还有其他系统是一样的,就是求导,根据我们求导求力的呃,求能量的导数这样子推出来的,我们其实下节课我们讲那个f e m的时候,就是换了个思路,就是我们用积分就不求导了,而是用积分的形式来除。
是无形变的自由状态,就是没有任何形变的时候的状态,很多时候就是推得很复杂,写代码会发现其实很简单,甚至我觉得这是咱们咱们所有作业里面最简单的一次作业,因为基本上就是矩阵乘来乘去,然后就乘出来了。
这个名字怎么来的吗,我觉得因为是因为你这里有很多单,你可以把这个三角形或者四面体认为是一个最小单元,然后这个单元里面你是假设它的形变是固定的嘛,就有点像有点像咱们说的那种,就是最小分割单位一样。
这里就是认为是形变的最小单位,最早年的像比如说我我这里给大家列的这个09年的这个paper,其实它也是就是没有考虑到后面我这个做的一个简化,你如果不做这些简化的话,就是你不做这些啊,这个简化的话。
其实你直接写那个有限元还是挺复杂的,因为里面有好多好多公式,好多好多变量,推来推去的,很容易犯错,但是有而这个公式之后就就特别简单,简化之后就特别简单了,变得。
对这就是为什么我说这个作业可能是咱们做的最简单的一次作业,虽然说听的很难啊,但是这个作业可能是最简单的一次作业,反正我作业里面会给大家就是一个附加题,就是实现两种不同的方式,然后让大家发现。
其实这两种方式写出来的结果是一样的,模拟的结果是一样的,formula是什么,green formula是那个divergence formula,我不太我不太记得green formula是什么。
其实大家看这一页,就如果说这还是二维的情况,如果是三维的情况是真的很复杂好多好多,因为三维的时候你会有六个变量,string是一个对称矩阵嘛,当2x2的对称矩阵,你是有三个变量的。
但如果是一个3x3的对称矩阵,你是有六个变量,你的公式就会特别特别复杂,大家还有没有什么问题也可以问,就上次大家作业都做完了吗,现在讨论了这个整个有限元,还是做做这个exit的积分啊,如果影视积分的话。
会稍微更复杂一点,就是其实跟咱们做那个弹簧系统模拟是一样的,嗯就是你你算力嘛,然后我们一个单元算算了,立了之后,然后下一个单元再算力,然后所有单元算完了之后,把所有的力加起来,然后就就更新定点位置。
其实是一样的,模拟如果你要衣服模拟的话,对就是2d的这个有限元,但是衣服模拟它有一个比较特殊的点,就是是衣服模拟在三维空间里,它其实它的demation gradient,2x2的矩阵。
它是2x3的矩阵,一要把他的那个衣服的reference状态是二维的,而衣服的实际的状态它是三维的,所以说他需要做一个2x3的一个变换,这个对于衣服而言是一个比较特殊的点,其他都是一样的。
你要做衣服的有限元的话,就这里是一个比较特殊的点,大家看一下早期的paper吧,其实就会发现其实呃每个人写法不一样,我这里不出那种力学里面的paper,我就说图形学里面的paper啊。
比如说嗯最早最早比如说james a brian,在20年前,他他的一些有心人的paper,他甚至都没有用矩阵,他用的是类似爱因斯坦标识的那种方式,就是把整个东西搞得特别特别复杂,和这个矩阵形式之后。
就一下子大家觉得这个东西特别简单,然后就大家都纷纷的后,后面的paper就基本上都是采用类似我的这个课里面的,这就就简单很多了,到那个爱因斯坦那个时候还是没有取证这个概念的,然后爱因斯坦怎么做的呢。
就把那个矩阵每一个里面的元素,所以就特别,gpu功率小有什么建议我我没有什么好的建议啊,就移动平台上它的gpu的性能都是不太一样的,就比如说我们正常的家用的gpu,就是一个并行处理器嘛。
也就是说gpu上它表面上是gpu,但是他其实很多时候它都不是真正的并行,它都是更多是串行,它是伪病型一样,主流的布流布料模拟使用project namics,猫没有。
一般来说我个人觉得现在主有的主要都是用饮食积分,然后饮食积分做那个做,就是各种就是像像我们作业里面用到的这种近似嘛,这种是一个是比较多的,然后另一个布料模拟比较多的,就是做那个做p p t啊。
如果说你你想做低分辨率的,比如说游戏开发,那么一般来说就是做ppt,如果说你想做高精度的高质量的,那么就做弹簧系统,饮食积分这种是比较多的,说移动平台的gpu的话,我觉得一般来说就是p bd。
就是大家可以参考一下那个呃,cross这个是nvidia的一个库,这个库他做了里面做了很多复杂的操作啊,如如果说你把这些复杂操作去掉的话,其实它的效率还是比较高的,就大家可以去参考一下那个库。
别的问题的话,咱们今天就先到这里,那先这样。