GAMES 图形学系列笔记(二十八)

GAMES103-基于物理的计算机动画入门 - P10:Lecture 10 Surface Waves (Lab 4) - GAMES-Webinar - BV12Q4y1S73g

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

听得见吗,喂喂喂,行,我今天才我才注意到,我前两天才注意到,今天实际上是放假的,不知道有多少同学今天会来啊,来的同学在的同学扣个一好吗,让我看看大概有多少人在,好吧行吧。

还可以还行吧啊反正不在的同学就回头到时候看录播吧,今天咱们嗯今天咱们算是嗯结束了之前讲那个嗯讲弹性体,讲钢铁的课程,然后今天咱们算是开了一个新的章节,就是来啊讲流体这一块啊。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后首先给大家看一下作业是什么样子的,我我在我之前在考虑布置作业的时候,嗯其实呃纠结了蛮久的,因为为什么呢,因为unity它这个功能比较有限,呃本来有很多我们可以在比如说c加加。

或者是在别的引擎上比较容易实现的,或者甚至matlab比较容易实现的东西,你跑到unity上写起来,它效率就不是很高了啊,所以说我后来纠结了一阵子,然后最后我决定给大家布置这么一个作业呃。

首先给大家看一下效果啊,就是我们到时候会有一个水面,然后这个水面上呢会有两个方块对吧,大家看到这里有两个方块,然后呢你可以拖这个方块,然后你就可以产生波的效果啊,然后呢你仔细看的话。

它这个方块是浮动在水面上的,如果说我把这个呃挪进了,我让这个波比较靠近这个另一个方块的话,你会看到这个方块会啊会抖动起来,然后你我也可以拖另一个方块,然后产生这个水花的效果。

这个就是其实这个基本上就是咱们作业的内容啊,然后要做这个作业,我把这个作业分成了几个部分啊,啊大家可以随便玩这个玩这些方块,这个作业有几个内容呃,首先第一个呢是我们要简单的把这个场景给它设置起来,嗯。

在我们的那个代码里面,我给大家了一些比较基本的一些操作已经有了,比如说我已经把这个整个水面给它呃,重新recess过了,recess成我记得好像是128x128吧的一个网格啊。

然后呢我这个场景里面这些方块其实也有了,然后大家的任务呢是要把这个math跟我这个模拟里面,所需要更新的高度场联系在一起,这是第一步啊,然后第二步呢是呃要大家学会怎么样去求解这个高度场的更新啊。

利用我们的这个今天我们要学习的这个啊shelter wave的这个模型,去怎么样去模拟这些波波的这个传递过程,这是第二个部分啊,然后第三个部分呢是我们要写学着写怎么样去利用这些方块的运动。

怎么样去产生新的波,那为什么我们挪动这些方块产生新的波呢,主要的原因是因为我们在挪动这些方块的时候,会导致某些地方的水被排了出来,所以说我们要求解就是怎么样把这些排出来的水正确的啊模拟出来。

然后因为这些水被排出来了之后呢,它就会相应的产生的这个玻璃效果啊,然后最后我们有个附加题,最后的附加题的内容,就是怎么样把我们之前学到的钢铁模拟跟这个作业结合起来,就是去模拟把这个方块模拟成一个钢铁。

然后可以看到它在水面上浮动的效果啊,但是我自己实验就会发现这个东西其实并不是很准确,主要是因为我们自己我们这个shallow wave的模拟,这个模型里面是有一些局限性的,所以说这个是大家需要嗯。

就是需要花时间去把这个问题解决掉的啊,当然这个我们里面就暂时就不讲了嗯,需要大家自己去探索一下这个东西,有什么问题吗,关于这个作业,行对这个这个水面它实际上是一个mh,它是一个网格啊。

是一个128x128的网格,我记得好像,然后它我们我们模拟这个水面,实际上就是在修改这些match上的顶点的位置,这个我们等会儿上课的时候会具体讲那个算法,上一次作业是吗。

我们我们所有的作业其实都跟之前一样,就是你可以晚交五天,就是如果说你晚交五天以内的话,就是会有扣分,但是嗯但是你还是可以交作业,还是会有分数的,对f e m那个很卡,这个这个倒还好。

这个模拟起来还是比较有效率,这个我的电脑啊,这个我电脑是好像是去年的mac吧,去年不是最新的一代,不是用他们那个最新的芯片的,好行吧行吧,那就关于这个作业,咱们就先到这里呃。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

先先先谈到这里,然后今天咱们来讲流体,然后流体这个东西呢嗯他特别有意思啊,因为他本身流体它能够呈现的形态非常多啊,我这里只是给大家举了一些比较简单的例子啊,就是拿水举例,谁举例子。

就比如说你看水滴还有溅出来的水花,水浪等等等等,它们其实呈现的形态都是非常不一样,而且我这里只是用水做例子,那流体里面其实还有烟对吧,还有各种的烟雾效果等等等等,都是非常复杂的。

所以说流体它跟我们之前所说的一些弹性体好,钢琴也好,它有个很大的不同,就是流体它模拟的方式方法也是非常多样的啊,很难说有一种通用的方法,就是各种各样的都可以模拟,都可以很有效率的模拟,应该这么说。

不是说不可以模拟,但是你可能这种方法在模拟某些情况,他就没那么有效率,所以说今天我们想专门来嗯作为一个相当于一个introduction,我们来讨论一个比较简单的一个模拟水面波的一个效果的方法。

然后呢今天呢我们会讲的比较细一点啊,不只是因为我们今天讨论的方法会用在我们的作业上,同时我们今天讨论的一些话题会延续下去,会到下周,还有下下周我们在讨论嗯,其他更通用的这种解流体模拟的方法的时候呢。

这些相关的概念它其实也会存在在我们后面的这个课程里面,所以说我们今天就稍微讲细点,把一些基本的概念呃稍微讲的细一点,我们回头会继续用到这些东西,那么模拟流体它通常有两种方法。

大家有可能以前听说过一种叫做拉格朗日的方法,一种叫做欧拉的方法,那么什么叫做拉格朗日的方法呢,呃简单的说就是我们把物理的参数,我们把物理的变量定义在随着这个物体运动而运动的,这些物质的点上面。

其实大家就可以直观的就是可以把之前我们做的弹性体啊,还有钢铁的模拟,其实都是这种所谓的拉格朗日的模拟方式,因为为什么,因为我们之前我们模拟的时候,我们是把整个物体用很多点去覆盖嘛,对不对。

那这些点它实际上是随着物体的运动而一起运动的对吧,当我们兔子发生了变形,我们的房子发生变形的时候,我们这些点是随着我们这个物体的变形而一起运动的,所以说当我们在这些点上附了各种各样的物理变量的时候。

这些物理变量也就天然地随着我们物体的形变而运动,这个就是所谓的拉格朗日方法,也就换句话说,我们是把物理定义,物理变量是定义在随物体运动而运动的一些物质的点上的,那么大家可以直观的理解呢,怎么理解呢。

就是可以把大家可以把这些点比如说当做一个物体的一个分子嘛,比如说我有个水流对吧,从左往右这样子流动,那么我可以认为每一个点都是一个小小的小的水分子,然后这些水分子呢它可能有一些物理变量。

比如说它有一定的温度啊,它有一定的速度啊等等等等,那当这些小分子在运动的时候,这些物理变量也就随着这些粒子运动而一起运动了,所以说你不需要去额外的去改变这些物理变量啊,就如果就是正常的随着运动。

它就直接被带着走了,就是这个意思,这个叫做拉格朗日方法,就是物质物物就是物理变量,它会被这些点带着一起走,那欧拉方法呢它有点特殊,他不是去划分物质的啊,它是去划分整个空间的,这个空间呢是固定的。

我把整个空间,比如说我可以划分成很多小格子对吧,那假如说有一些水,一些流体啊,从格子里面穿过,那么我在每个格子里面我都会定义一些物理的变量,比如说我在这个格子里面,我会定一些,比如说密度啊啊速度啊。

温度啊等等,那这些变量它不是定义在物质上的,它是定义在这个空间里面的,而这个空间它是固定的,那么换句话说,当我进行模拟,当我这个呃这个水流在流动的时候啊,我需要去改变这些格子里的值,因为当我流动的时候。

这些东西理论上它会被带到别的地方嘛对吧,那么带到别的地方的过程中呢,这些这些格子里面的值它也就会发生改变了,这个其实这个叫做欧拉的方法,就是我是利用一个静止不动的格子去划分我的这个空间,然后我的模拟。

我的动画是通过我修改每一个格子里面的这些物理变量值而产生的,而左边这个拉格朗日的方法呢,它把这些物理变量的附加在一些物质点上,所以说物质点运动的时候,它就会自然的把这些物理变量跟着带着一起走。

你就不需要再去更新它,这个是他俩的一个区别,一个是啊点是在运动的,而另一个呢它是一个用固定的格子去模拟的,这个大家能明白吗,这个大家以前有听有有有接触,有听说过这个这两个区别吗,可以啊。

反正这个左边这个大家左边这个方法呢大家就是可以想象,就是我们之前的钢铁啊,弹性体的模拟,它都是这种拉格朗日的方法,然后右边呢这种方法呢我们今天就会具体的讨论到用到啊。

那么给大家举一个今天我们想要学习的这么一个例子,就叫做高度场,这高度场什么意思呢,就是我利用一个高度的这么一个函数,我去模拟,我去表达一个曲面,一个平面,一个波的一个平面,一个水面,就像这样子。

我的横轴呢是x是位置不同的位置,然后我的纵轴呢就表示在不同的位置上,我的这个高度是什么啊,然后我通过更新这个高度这个函数啊,我通过我改变我这个高度函数。

我就可以产生这个随着时间这个高度变化的这么一个效果,这个是叫做一个高度差,那么在2d里面呢,我们这个高度场的这个函数它是一个一维函数,它表达的是一个二维的面。

当然这个二维的面它不是一个真正意义上的一个任意的一个二维的面,它其实是一个有局限性的,它是一个函数所能够表达的一个二维的面,对吧,换句话说我没有办法表达这种这种形状,为什么。

因为在某些地方它可能会有多个函数值,那这种情况下,我是没有办法用一个我们这个高度场的这么一个函数去表达的,所以说这种这种情况的水面波我就没有办法模拟了,那我能模拟的就是说这种比较简单的呃。

一个位置上只有一个函数值的这种啊这种水面波效果啊,那这里呢在2d上呢,我们一般来说把它叫做1。5d的一个高度,长在3d上呢,我们把它叫做2。5d的一个高度场,其实都是一个意思,就是说我这个高度场。

它描述的是一个2d空间里的一个啊一个水面的效果,但是这个水面效果它不是任意的,他是有一定的这种limitation的,那么我们有高度场之后呢,我也可以呃进一步的去定义对吧。

比如说一个我们所需要的就是一个速度嘛,对不对,因为我们之前在模拟呃弹性体也好,钢铁也好的时候,我们都需要有速度,那么同样的我们在模拟这个呃高度场的这个时候呢,我也需要有速度,那么手,那么什么是速度呢。

我可以在不同的位置上,假如说在某一个点上,我可以定义一个速度,那这个速度呢就告诉我们说我这个水流,假如说我这个我这我这个曲面下面这个面下面都是水,那这个速度就告诉我说我在这个位置上,在这个点上。

我的水是以什么样的速度去穿过这个面的,那这个速度它实际上可以是正的,也可以是负的负的,也就意味着它是往我们的这个反方向在运动的,也就是意味着它水是从右边流到左边去的,那如果是正的速度呢。

就意味着我的这个水它是从左边流到右边去的,所以说我可以利用啊,它这个正负号我可以来决定呃,速度它的这个方向,水流的这个方向,那么利用这个定义呢,我同样我也可以构造一个速度的一个函数。

它同样也是一个速度差啊,它是一个关于位置的一个函数对吧,然后呢在不同的不同的地方呢,我都会有相对应的这个速度的值,它可以是负的,比如说像这里它就是负的值,它也可以是正的值啊。

取决于取决于我们的水流是呃流向到底是从左往右还是从右往左,那么好了,我们现在有了高度场,高度场实际上就是对应着有点像我们之前做那个弹性体,刚体模拟的时候,我们有一个位置嘛对吧。

它这个高度场实际上就是描述的一个状态,然后速度呢它描述的是这个水流,这个高度场下面的这些水,它流动的一个速度,我们有了这两个东西之后呢,我们接下来需要定义分别定义他们两个的更新。

因为我们之前做钢铁弹信息的时候,我们是有了位置,有了速度之后,我们就会有相应的它们的更新函数吗,所以接下来我们也会来看一看我们怎么样去更新高度场,我们怎么样去更新速度场,我们来看这两个东西。

首先我们来看高度场的更新,高度场的更新可以描述为这么一个偏微分的一个方程,这个方程看起来有点复杂哦,但是你可以看它实际上是由两部分构成的,第一部分呢是dh dx,什么叫做dh dx。

就是高度场随时间的变化,对不对,一个函数对时间的导数,也就是什么意思,就是这个函数随时间它的变化,这个叫做dh dd,那么这个方程说我的这个高度随时间的变化,是由右边这个部分所产生的。

分别是高度乘以速度,对顶点的位置求导,那这个怎么去理解这个东西啊,我觉得可以从导数的定义去理解这个东西,假如说我这个顶点的位置,假如说我这个点的位置在x,我当前的位置是x,然后呢。

我给这个x一个很小很小的一个偏移量dx对吧,假如说我给他稍微的往右挪了那么一丁点,那么根据我们微分的定义啊,dh u也就是上面这个东西,这个分母的这个分子的这个东西,d h x u x啊。

就等于h和u在x加dt加dx的这个值减去x x h x乘以ux在x的值,这个是咱们微分的定义啊,就是当你挪动一个非常非常小的一个无限小的一个量的时候,dx一个很小的量的时候。

你这个d这个d h u就可以由这个东西去近似它,那么这两个东西分别是什么东西呢,h我们知道是高度对吧,相当于是这个面的这个高度,u是这个面上的这个水流的速度,那么换句话说,h乘以u就告诉我们什么呀。

h乘以u就告诉我们在单位时间,在某一个时刻里面,单位时间内流过这个橙色的这个面的水的量,对不对,因为速度乘以这个面的这个高度,是不是就产生了这个流速啊,不不不是不是流速是嗯,逃出去的水的数量。

对不对的速度,那么同样咱们黄颜色的这个部分呢,我的高度是h x,然后我的这个留的这个速度呢是u x,我把这两个相乘,我得到了什么,就是我得到了在单位时间内,我有多少的水从左边穿过黄颜色的这个面。

流到了右边,那么这两个稍微一减,我得到了什么,我就得到了这个这个在这个小的这个区间内,我的水量的变化是多少对吧,一边是橙颜色的呢,是我出去的水,然后右边黄颜色的东西呢是进来的水。

那我总共出去的减去进来的,我得到的是我这个水减少了多少,那么我再用这个东西去剪一剪,因为这个是加号嘛,我把我把这个东西挪到了右边,我就变成了减号了对吧,我这个东西实际上我总共得到的就是单位时间内。

我这个小格子里面,我这个小区间里面,我的这个水量总共变化了多少,我一边是出,一边是进,我就把这减一减,我得到了总共的水量有多少变化,然后我知道有多少变化之后呢,我再除以dx。

我就得到了我的这个高度在单位时间内有多少变化,这个其实就是它一个直观的你去理解这个式子的一个含义,嗯,因为这个h乘以u它其实就得到了这个面上的这个啊水量的进出,这个大家理解吗,ok行行。

那么我们我们我们现在有了第一个式子,我们知道了,说呃我这个高度场可以通过我这个第一个式子去更新,那么接下来我们看看速度差,我们应该怎么样去更新速度差,我们速度长呢更新呢由三部分构成了。

第一部分呢叫做adv呃,但是这个东西呢我想我今天先不讲,我们先留到后面的课去讲,咱们先暂时先不考虑它,但是可以给大家一个直观的概念,就是advice,什么叫做advad,意思就是当我水流在流动的时候。

我的速度也应该随着水流一起流动,因为我这里的速度是定义在固定的x上的,我这个x其实并不发生改变的,因为它x不发生改变,所以说我这个速度在下一个时刻的时候,他应该被跑到别的地方去。

它相当于就是会被被这个水流自身的流动所带着走,这个叫做adv,啊但是咱们这里就先简单一点,先忽略它,先不要考虑它,我们下节课以后会会继续讨论这个东西,然后最后这个东西呢是外部的产生的外力。

那这里咱们也简单一点,不考虑它,因为咱们在作业里面也没有这个外力,就不考虑它了啊,什么时候会产生外力呢,比如说我这个这个水水里面有艘船对吧,然后这个船可能有个螺旋桨,它这个螺旋桨会推着这个水啊。

往某个方向推推,那这就是产生了一个外力了,但是咱们的作业里面是没有这个外力的,所以说我们也忽略它,所以说我们就保留中间,最后保留中间这个东西,那中间这个东西是什么呀,我就得到了一个简化的东西。

中间这个东西是什么呢,肉是密度,p是压强啊,换句话说就是压强对位置的导数除以密度,对有同学问,有刚刚同学有个同学问说箱子在水里移动是不是外力嗯。

我们这里其实不是用外力来实现我们这个作业里的这个波波的效果的,我们在作业里面我们是利用压强来实现的,因为当水当箱子挪到不同的位置的时候,它会把其实把水排出嘛,把水推开。

那这个推开的过程我们是用压强来实现的,所以说在这个作业里面,咱们跟外力没有关系啊,等会儿我们后面会讲到就是怎么样去做这个啊,排出水的这个效果,那么我们来理解一下这个式子是怎么产生的啊。

这个式子其实跟咱们前面有点像,就是我们也可以考虑到,假如说有一个很小的区间,这个区间的左边是x,然后曲边的右边是x加上dx,假如说我这个区间非常非常小,无限的小,那么我们这个dp呢就等于橙色的压强对吧。

在右边这个位置的压强减去左边这个位置的压强,那什么意思呢,你可以这么想,就假如说我这里是一个里面有很多水,有有有水,有个小水,有个小水柱,对不对,那么这个小水柱左边有压强,右边有压强。

那么这个小水柱应该怎么运动啊,它是不是应该根据它左右的这个压强的差来运动,对不对,就像一个东西,它左边受力,右边也受力,那么它怎么运动,它就会根据它左右受力的差来运动,如果说右边的力比较大。

那它就应该从右往左运动,那如果说左边的力比较大,它就应该从左往右运动,所以说我这里是减一减,在前面加个负号,因为当你右边的力比较大的时候,我的p我的橙颜色的力比较大的时候,那么我整个东西是正的。

那整个东西是正的呢,前面加个负号,也就意味着我的这个速度会变负对吧,那变负也就意味着是从右往左流动,那反而言之,如果说我黄颜色的东西大,黄颜色的压强大,那么我的这个压强会把这个这个速度从左往右推。

那么会导致这个东西是负的,而这个负的呢前面再加个负号就变正了,也就是意味着我的速度会从左往右,所以说这个公式其实就是很简单的一个意思,就是说我在某一个很小很小的范围内。

我这个速度的变化实际上是由我左右压强的差来产生的啊,然后为什么要除以这个密度呢,是因为我这个产生的这个速度其实跟会跟密度相关嘛,我这个密度越大,它也就越容易推,我密度越小就越难推嘛。

其实就是这么一个意思,大家明白吗,这里,好吧,然后呢嗯可以看到这个如果说这个dp是正的,我的速度就会减弱而变小,要变负,然后如果dp是负的呢,我的这个速度就会变大增大,那么好了,我现在呃就有两个公式了。

对不对,我们刚才讨论了半天,我们最后就得到了这么两个公式,上面这个公式呢是对我的高度随时间的改变进行更新,我们刚才讲了吗,d h d t,然后下面这个公式呢是速度呃,随着时间而更新的这么一个公式。

我就有两个公式,那我这两个公式它比较呃比较复杂对吧,大家可以看到我这里有两个变量,两个两个厂,一个是高度场,一个速度场,它比较复杂,那么有没有办法可以把我这两个公式进一步的简化呢,搞得更简单一点呢。

那么首先我们对上面这个公式展开一下,我可以展开成两个部分啊,因为上面因为上面这个公式它是d h d u嘛,所以说我可以把它变成u乘以d hd加上h乘以du dx,我就分别对h跟u求导。

我根据我们之前嗯微积分里面学过的链式法则,我可以把它拆成两部分,然后接下来呢我把这个部分给它忽略掉,我把这个部分给它忽略掉,为什么可以忽略掉呢,我实际上就是假设啊,在某一个小很小的范围内。

我的高度跟我的位置的基本上是不发生改变的,在一个很小的范围内,我这个高度的变化是非常小的,我实际上是做了这么一个假设,这个其实就是我们公式名字的由来,叫做shallow wave。

为什么叫shallow wave,是因为我假设我的这个水面的,我这个平面上的这个波它都非常非常的小,它都是很小很小的水面波,那么因为很小很小的水面波,我可以认为随着我位置的变化。

我这个dh dx这个量很小,所以说我就把它给忽略掉,我就得到了一个简化版的一个公式,然后完了之后呢,我对第一个公式呢,我对,他再求一次dt,我再求一次dt呢,我就得到了h对时间的二阶导。

加上h乘以du dx dt啊,当然我这里其实还忽略掉了另一项就是dh dt,就du dx乘以d h d t我这个也给他忽略掉了,啊就是就是这么一个式子,我我得到了这个式子,我这里其实还呃还跳了一步。

就是还有一个dh dt乘以du dx,但这个我也我们也给它忽略掉,我就我就得到了这么一个简化的一个模式,然后接下来我对下面这个公式呢,我对它对x求导,我对x求导读到了什么。

我得到了du对dx dt求二阶导等于负的一除以肉乘以dp,对x求二阶导,我得到了这两,那得到这两个公式,我就会发现什么呀,我发现这里有这么一个东西,然后这里也有这么一个东西对吧,那我把他们两个合并起来。

我就可以得到了一个简化版的公式,我最终得到的就是dh对dt的二阶导,等于h除以肉乘以dp对dx的二阶导,然后这个就是我们最终的方程叫做下落位方程,那这个为什么我们要搞这么一大堆这个倒来倒求导导。

来导数倒来倒去呢,最根本的原因呢是我们可以把这个u啊,把速度这个速度长给它干掉,我干掉完了之后呢,我就不要去关心说我这个速度场是什么样子,我只需要有一个高度场,我就可以进行我的模拟了。

这是一个最大的一个好处,就是我可以把我只保留一个速度哦,我只保留一个高度炒这么一个唯一的一个变量啊,我可以把速度这个东西给它干掉,那么好,我们讨论了半天,我们讨论了这么这么多这个微分的这些方程啊。

我们最终得到了这么一个而微分方程呃,但是我们还没有办法拿它来模拟,对不对,因为我们这个模拟引擎是没有办法直接去处理这些微分方程的,我们所要做的呢就是去对它进行求解,对它进行离散化,然后对它进行求解。

那么怎么离散化呢,因为咱们的高度场是什么,我们的高度场是一个关于位置的函数嘛,那么我们的离散化就很简单,我们就把这个x轴我把它分成很多很多的小区间,每一个区间呢都是一个固定的宽度对吧。

我们叫做delta x一个宽度,一个一个宽度,然后呢对应这个区间呢我都有一个高度的值来描述我在这个位置上,我这个波的这个高度是多少,一个比较直观的理解呢,就是说你可以把这个东西想象成很多很多个小格子嘛。

然后呢每一个格子上呢我都会有一个一个水柱啊,这个水柱的高度呢就是我的hi,然后我们的模拟过程呢实际上就去更新这些水柱的高度对吧,我们如果说这里的水比较多,我就把高度搞搞大一点,如果水比较少。

我就把这个高度搞小一点啊,然后通过模拟这个高度的这个水柱的这些高度的变化,我就可以产生模拟的效果,这个就是我们把一个连续的高度函数转化成我们可以进行模拟的啊,一个方式就是把它转化成一个水柱,那么好。

我们现在有高度了,我们现在有一个离散化的这么一个高度场了,就是变成一大堆水柱了,那么我们接下来我们要讨论的是什么呢,是讨论我们前面的这些微分方程的所对应的微分算子,对不对。

我们怎么样把这些微分算子跟我们的这些高度联系在一起,首先我们来考虑的是第一个东西,就是跟时间的导数高度,跟时间的导数,我们首先想我们在模拟的时候,实际上是用一个固定的时间不长做模拟的,对不对。

我的delta t是我的时间不长,然后我当前的时间比如说是t0 ,那么我在前面一个状态,我的时间是t0 减掉的t我的下一个状态呢是t0 加表的题对吧,我之前啊我们之前做各种各样的模拟。

我们都是采用这样的一个模式,那么假如说我保存了在不同的时间上的不同的这个高度值,同一个格子啊,我对于同一个格子我都保存了它的不同的高度值的话,我就可以对我的时间求导了。

那这个值呢是前一个时刻我的这个格子,我的这个水柱的高度值,这个呢是当前时刻我的高度值,然后这个时刻呢是我下一个时刻就还未发生的这个时刻,我的水柱的高度值我分别是多少,我都假如说我都有这些值的话。

都有这些不同的不同时刻上的我高度值的话,我就可以对它求导,那么怎么求导呢,我们接下来要引入一个概念,叫做final difference,所谓的final difference呢。

就是我用一个固定的一个格子,我用一个固定的区间,我对一个函数的导数来进行近似,比如说我在我的这个时间轴上,我有两个时间,t0 跟t0 加dt t对吧,delta t是一个。

假如说它是一个很小很小的一个值,一个很小很小的是个时间的一个呃小小的时间量,那么在这两个时间我都有相对应的函数值,分别是f0 跟f0 加到了t对吧,那么根据泰勒展开。

我知道f t0 加德尔塔t等于f0 加到达t乘以df t0 ,dt加上后面的一堆东西,所以说我可以做一个近似,我可以利用这两个东西的差除以dt来做一个近似啊。

这个近似的结果呢就是我这个函数值在t0 时刻的一阶导数啊,它约等于前面这个函数值减去后面这个函数值除以dt t,这个就叫做forward difference。

它这个difference的意思就是求差对吧,我求了这两个点的两个点之间的函数差,然后我利用这个函数差我来近似他的这个一阶导数,那为什么是forward,因为我是用前面的这个时刻。

我是用前面的这个函数值来求导的,那有forward自然也就有backward对吧,我可以不用前面的时刻的啊函数值,我用后面这个时刻的函数也是,那么根据泰勒展开。

我们同样知道后面这个函数值等于当前的函数值减去dt乘以一阶导数,加上一堆乱七八糟的东西,那我的这个近似方程呢就变成了一阶导数,约等于当前的函数值减去前面这个时刻的函数值除以二的题。

然后这也是一种啊求近似一阶导数的方式,那这两种近似一阶导数的方式都是一阶的,为什么叫一阶呢,因为我我能够产生的我能够产生的误差是什么,我能够产生的是误差,是这个东西和这个东西对吧。

这两个误差呢都是二阶函数,所以说我们的误差呢是二阶的,也就意味着我们的精确度呢是一阶的,这个就叫做final difference,我们回头我们在我们下节课也会继续用到这个概念,我们会经常用到这个概念。

那么好,然后大家就想怎么样能够把它搞进去更精确一点,其实这个东西跟我们之前说的那个呃一阶的就是forward的,叫什么,forward integration。

forward online integration,很像backward,oled integration很小,那么怎么样把它搞得进清晰精确一点呢,就是我同时用到正的跟负的,我同时用到前面的跟后面的。

我就可以给它搞得更精确一点,那么怎么做呢,我知道我的这个前面的这个函数值等于当前的函数值,加上德尔塔t乘一阶导数加上一个二阶的数值误差嘛对吧。

然后后面的这个函数值等于当前的函数值减去delta乘以一阶函数,加上一个二阶的一个这么一个东西,然后如果说我把这两个东西剪一剪,会发生什么,我会发现这个东西会抵消掉,然后这个东西它也会抵消掉。

二阶的部分它也会抵消掉,因为二阶的东西是一模一样的,所以我就得到了这么一个方程,我怎么样去近似t0 时刻的二阶导数啊,我把前面的这个函数值减去后面的函数值啊,前面的减后面,然后再除以两倍的deltt。

因为我在前面减后面的时候,我整个跨度就不是dt t了,是二dt t对吧,所以我就除以2。22倍的的题,然后这个东西呢就给了我一阶函数的近似了,然后就这个就叫做central defense,它是二阶的。

这个是我们想要我们所要用到的就是二阶的这么一个方式,嗯有了这个central dience difference这个方法之后,呃,我就我们就可以搞各种各样的花样对吧,比如说呃在这里我们做的是一阶导数。

我们刚才算的是一阶导数,那么同样的我们可以把这个东西扩展到二阶导数上去,对吧,比如说我想要知道当前这个时间的h的二阶导数,我该怎么做。

这个因为我们之前的那个shallow wave的公式里面用到这个东西了,所以说我们想要知道二阶导数怎么说,那么怎么得到二阶导数呢,首先我可以利用前面减后面的方式。

我首先把中间这两个位置的一阶导数给它算出来,就是正-0。5的这个位置给它算出来,那么正0。5的这个位置啊,它的一阶导数等于前面的函数值减去中间的函数值除以dt,然后-0。

5的这个函数值的一阶导数的位置呢,一阶导数等于,中间的函数值减去后面的函数值,出一道的题,啊然后这两个正-0。5的这个一阶导数的函数值,它是通过central difference得到的。

因为我们最终给出的是中间的一阶导数,然后有了这两个中间的一阶导数呢,我再做一次,我就得到了二阶导数对吧,那么这个上面这个东西呢是分子的部分呢,是两个一阶导数相减,然后除以掉到t。

然后这个时候我中间的这个时刻刚好是在正-0。5的中间嘛,所以说我也是利用了centre difference,我就刚好完美的得到了我中间的这个位置的二阶导数了,那么我们把前面这个式子分别的带进去啊。

把这个东西带进去,然后我最终得到的是啊t加dt t的函数值,加上t t0 减掉的函数值,减去两倍的t0 的函数值除以得到t的平方是二阶导数,然后大家如果看一下这个式子的话。

其实你会发现其实本质上就是什么,本质上就是对于中间这个点而言,对于中间这个函数值而言,其实就是他的邻居减去了两倍的他自己对吧,就是他的邻居减他自己,它呢是-2,有个-2的系数,然后它呢是有一的系数。

一的系数分别去跟它相减,然后这个东西呢也有一个名字叫做拉普拉斯,来plash,顾名思义呢,其实呃也不是说顾名思义吧,就是直观上理解你就可以理解成我每个人我的邻居对吧,我的邻居加在一起。

然后减去我自己其实就是做了这么一件事情,那么这个就是高度关于时间的函数,对这个其实就是一个一-21,其实就是一个一维的一个拉普拉斯算子啊,我们有了二阶导数,那么同样我有时我有高度对时间的导数呢。

我也可以利用同样的方式呢,我对压强也求二阶导数,因为咱们之前我们的shadow wave里面也有压强跟位置的二阶导数嘛,我也需要有这么一个东西,嘛我也需要计算这么一个东西,那怎么计算呢,我就首先分别。

假如说我想要知道这个这个位置上的这个压强的二阶导数啊,那我首先,在这个位置跟这个位置,也就是这两个中间位置,我分别利用我们之前所说的这个啊删除difference的方法,我把这个正-0。

5的位置的这个压强的一阶导数给它算出来,完了之后呢,我利用我们刚才的方式,同样的方式我这里就不重复了啊,我就可以把我这个压强的二阶导数给它算出来,我得到的就是啊这么一个公式。

简单的说就是两边的压强加起来减去两倍的自己除以dt t dt x的平方,然后有同学问,就是说如果是二维的空间上,是不是就去减去四倍的自己啊,对如果是二维的情况下,就是减去四倍的自己。

因为每一个每一个点都有四个邻居,所以说就减去四倍的自己,但是咱们这里就先不讨论啊,回头给大家看一下四倍的自己的这么一个情况,那么好我们刚才给大家举了central defense的这么一个方式了。

我们接下来就可以把它套到这么一个我们前面的这个公式上了对吧,那么我们前面有这两个呃,离散化了以后的这些二阶导数嘛,那么我把它合在一起,我把这个左边这个东西用这个式子给它替换掉。

右边这个东西用右边这个式子给它替换掉,我最终得到的就是这么一个公式,然后呢我给他再稍微整理整理对吧,因为这因为这个东西呃不是很直观嘛,我给他整理一下,我最终得到的就是这么一个式子。

那这么一个式子是啥意思啊,这么一个式子我什么目的啊,我最终的目的实际上就是要去我更新我的高度啊,那这个东西实际上是我想要得到的下一个时间的高度,对不对,对于这个i这个水柱而言。

这个东西是我下一个时刻的我这个水柱的高度,那么我实际上就可以把右边的这么一个式子给它计算出来,我计算出来完了之后呢,我把它换到左边去,我就可以得到我下一个时间的水柱的高度了,这就是我的这么一个更新函数。

实际上就是我们利用了前面的一大堆啊,这个central的公式我得到了这么一个,最终我得到了一个关于我每一个水柱的这么一个更新函数,这个是我绕了这么一大圈儿,我最终想要做的这么一件事情啊。

有了这个式子之后,我就可以对我这个每一个水柱我都进行一个模拟更新了,那么好这个式子看起来挺不错的啊啊然后似乎也没有那么复杂,呃但是呢我们还有一个小问题需要解决,这个小问题呢其实不只是在这里。

其实在我们整个贯穿整个流体模拟都会出现的一个什么问题,就是体积的问题,什么意思呢,就是我们很多时候在模拟的时候,你会发现这个水它会越来越多或者越来越少,这个就很奇怪了,对不对。

因为在我们在正常的这个真实的世界里面,你不可能说同样的水在没有变化,没有各种各样外在的情况的影响下,它的水会突然变多或者突然变小,但是如果说我们不考虑一些这些特殊的,就不考虑这些呃一些算法的话。

是有可能出现这种变化的,这个就叫做volume preserving,就是我们怎么样能够保证我的一个模拟不导致水,它莫名其妙的变多或者变少,那么换句话说呢,我是想要我这个体积。

我这里面的水的体积是永远都是一个常数啊,在不增加或者减少额外增加减少水的前提下,我这个里面的水,我这个模拟环境里面的水,它始终是应该是一个常数,对不对,那么假设我总共的这个水数量是v。

那么什么是总共的水啊,我把所有的高度加起来,我把所有的高度加起来,我应该是一个常数,那么在上一个时刻,前一个时刻,我的所有的高度加起来是v,我当前时刻我所有的高度加起来也是必对吧。

假设我前面之前我都是满足我这个体积变化啊,体积永远是v的这么一个前提,但是如果说你利用这个公式去进行模拟,会发生什么呢,我们来看一下啊,假如说我用利用前面咱们这个公式进行模拟。

我分别对这个公式的左边跟右边进行求和,啊我这个是得到了,模拟之后的新的时刻的总的体积的速度等于两倍的,当前时刻的体积减去前一个时刻的体积,再加上后面这个一大坨东西,那么前面这个部分实际上就是v。

因为这个部分是v,是两倍的v,然后这个东西也是v,所以说就是两倍的v减去v,那么得到的就是总的体积,然后再加上啊右边这一块东西,那问题就来了,什么问题啊,我没有办法保证这个东西一定是零对吧。

那如果说我没有办法保证这个东西一定是零,也就意味着当我用这个公式去进行模拟的时候,我的体积有可能会变大或者变小,这个具体是变大还是变小就不好说了,取决于这个东西到底是正的还是负的。

但是我这个体积是会随着时间会随着模拟的变化而波动的,那我显然不希望产生这样的问题吗,那怎么样解决呢,有几种方式啊,第一种方式呢是把这个公式修改一下,怎么样修改呢,就是不要用这个hi来作为这个系数。

而是呢把这个东西拆成两个部分,把我们后面这个东西拆成两个部分,分别是pi减一减p i和pi加一减p啊,首先把它拆成两部分,然后拆成两个部分之后,我把这个hi也用这两个东西来替代表,之前呢我的系数是hi。

通过修改呢我变成了hi减一加hi除以二,然后后面的东西呢变成了hi加hr加1÷2,变成了这两个部分,那么如果你对它这个东西再求和,你就会发现我这次呢我可以保证这个东西一定是零的了。

为什么我可以保证这个东西一定为零,是因为你可以做这么一个直观的理解,就是说假如说我这里有两个水柱对吧,假如说我这里有两个水柱,那么这个东西它实际上左边会得到的更新呢是它减它是右边减左边。

而右边得到的根系呢是左边减右边对吧,它分别是左边减右边跟右边减左边来进行更新的,那么我利用这个东西我可以保证什么,我可以保证它们的更新的量都是一模一样的,因为当左边这个东西被右边减左边进行更新的时候。

它乘上的是同一个系数,而右边减左边的时候呢,而左边减右边的时候呢,它也呈现的是同一个系数,直观上你其实可以这么理解啊,就是我这里面的这个东西啊,实际上我换个颜色,我这个东西实际上你可以直观地理解成。

从边上的一个柱子流入的水的量,而后面这个东西呢是从内侧的一个柱子流入的水的量对吧,因为我每个柱子我都有左右两个邻居嘛,那么它左右两个邻居它都会有水分别流入到当前的这个柱子栏对吧,那么我利用这个公式。

我可以保证说我流入的量跟我边上那个柱子流出的量它是等价的,比如说我左边流掉了一个单位的水,那么我右边也会进一个单位的水,那这样子的话我就可以保证我整个体积是守恒的了。

因为我左边流入的流出的量跟右边流入的量它是等价的,所以说这个改动它其实最终的目的是为了保证说我呃每一个格子,它流出的跟每一个格子流入相邻的格子流入的它是等价的,它其实就是做了这么一个改动。

嗯大家如果说想进一步理解的话,可以看一下这篇论文,这篇论文基本上就是把我前面说的这些呃这一大堆话嗯给描述了一下,是还是蛮早的一篇paper吧。

90年的一篇paper叫做rapid stable for dynamics for computer graphics啊,就是啊也是一篇比较经典的关于shadow wave的pap。

那么好我们刚才讲了一种能够保体积的方法,那么还有一种包体积的方法就比较简单了,这个也是咱们作业里面我想让大家尝试的一种方法,就就比较简单了,怎么简单呢,就是我直接简单的粗暴的把这个hi认为是一个常数。

我就直接用一个常数值给它替代掉了,因为如果说我把这个整个用一个常数替代掉呢,你会发现我在对它进行求和的时候呢,它右边呢就变成了这么一个东西,就是压强差的这么一个河了。

那因为压强差左边压强差跟右边的压强差距永远都是左边跟右边,右边减左边嘛,所以说你对它整个进行求和,它最终就会变成零,然后这个就可以保证我整个模拟状态,它的体积是呃不发生改变的。

这个体积是维持在一个常数上,那么好,我们接下来看压强是什么对吧,我们刚才讲了半天压强压强压强,那么压强到底是个什么东西啊,那么压强如果说考虑重力的话,压强等于密度乘以重力加速度乘以高度。

这个是咱们学而物理里面所学到的水的这个压强,密度乘以重力加速度乘以高度,如果说我把这个东西带到我们刚才的这个式子里面,这个模拟更新的式子里面,我们就可以得到啊,这么一个式子。

相当于就是把之前的这些p接下来我全都变成高度的值了啊,然后这个部分呢前面这个系数呢就变成了这么一个东西,那么简单一点,因为这个东西是个常数嘛,我就索性简单一点,我就把它用一个阿尔法来替代了。

啊因为不管什么样的系数,它最后乘出来,最后始终都只有一个值嘛,那我最后就用这个阿尔法去给它替代掉,就变简单了,这是我对呃我的这个模拟公式的又一个简化,好了我们接下来有了这么一个简单的一个模拟公式。

我嗯接下来再怎么给他搞呢,我们在模拟刚体,在模拟弹性的时候,我们有一个单品的一个概念对吧,有个阻尼的概念,流体它同样也有阻尼的概念,只不过流体的阻尼不叫单品,叫viscosity,叫粘滞。

因为我们在真实世界里面,流体它不可能无限制地流下去嘛,它会有一个想让他停下来的趋势,这个趋势跟damping是一样的对吧,那么这里呢怎么样去把这个流动的这个趋势给它停下来呢,我们会发现这个东西啊。

它其实跟动量很像,因为它讲的是当前跟之前的时刻的高度的变化,换句话说它描述的是是随着时间我高度是怎么发,生变化的,所以说它跟我们的动量其实是有很大关系的,所以说这里呢我只要在前面乘一个系数就可以了。

成一个贝塔系数,这个叫做我们这里就把它叫做粘滞系数,然后成了这个粘滞系数呢,我就可以对我整个动画进行一个单品,产生一个单品的效果了,然后大家可以在作业里面也可以尝试一下,通过修改这个系数的大小。

你可以产生不同的这个组组,那个呃年制的效果,如果说是一,如果这个贝塔只是一,那么就没有没有任何粘制,如果这个贝塔是零,那么这个粘滞系数就无限的强,你会发现这个就很不像流体啊,反正大家可以啊尝试一下。

那么好,我们现在似乎把所有的问题都解决了吗,嗯但是还有一个问题,还有几个问题我们没有讨论的,我们还得继续往下讨论哦,什么问题呢,首先我们还没讨论到边界的问题,因为我们整个物体,整个水面它不可能是无限的。

对不对,我们在模拟的时候,它肯定要设定一定的范围,那么它势必就是会有一个边界,我怎么样去处理这个边界呢,啊这是这个算法,那么怎么处理边界呢,有两种处理边界的方式,我们这种处理边界的方式。

我们之后在其他的模拟流体的情况也会碰到啊,那么第一种方式叫做delicate boundary,所谓的ditially的帮助,意思就是说在这个边界外,我假设我的高度都是一个常数,都是某一个常数。

比如说我假设这个地方是我的边界啊,左边的部分边界左边的部分是我正常模拟的区间,正常模拟的的区域,然后我这个边界右边的部分呢是呃这个边界外就是没有定义的。

或者是我可以认为是啊某一个啊某某某一个某一个什么空气墙,你可以这么认为,hi我在这个范围外呢,我假设我这个高度永远都是一个常数大写的hr,那么在这种情况下,如果说我们原来这个式子是啊这样的对吧。

如果大家记得,如果记得这个东西的话,我们之前是呃左边的邻居,这呃加上右边的邻居减去两倍的自己嘛,那么这里就变成了左边的邻居减去自己,加上右边的邻居减去自己对吧。

那么这个邻居右边的邻居呢是大写的h i hi plus one,所以说我就用这个东西替代掉,就变成了这么一个式子,这种边界一般来说是用来模拟开放的一个水面的。

就比如说我现在想要模拟一个很大很大很大的一个海平面海面,然后呢我没有办法去描述这么大一个面嘛,我只能用一个很小的一个相对比较小的一个啊一个范围我来模拟,那么在这个范围外面,我就假设是一个静止的一个海面。

那么这个静止的海面,我假设它的高度就是一个常数,这个就叫做date的bound,这是一种边界条件,然后另一种边界条件呢叫做norman帮主newman帮jy呢。

它的本意呢是说我不去描述边界外的这个高度的值,绝对值,我描述的呢是边界上的一阶导数,什么意思呢,比如说我认为在这个边界上,它的一阶导数是零,换句话说,我认为在这个边界上左右的水面的这个高度是一模一样的。

永远都是维持一模一样的高度的,那么如果说我要维持一模一样的高度,那么也就意味着我hi j跟hi永远都是一模一样的,对不对,因为他俩永远都是一模一样的,那么也就意味着他们就被彻底的永远的抵消掉了。

那么换句话说我要进行模拟更新的时候,我只需要考虑到一侧的邻居就够了,我只需要计计计算这个到hi到一到hi的水流就够了,我不需要考虑啊,从这一侧流入的水,因为这侧是没有任何水流的。

就是嗯就相当于是你可以认为它不是一个空气墙了,它变成一个实体的墙,它会阻碍水流穿过这个实体墙,也就意味着没有水能够啊从这两个柱子之间进行流动,那么因此这是我们帮助,一般来说我们主要是用来模拟强的对吧。

如果说比如说我有个池塘,我想模拟一个小的水池水池,那么这个水池的边界啊,我就可以用诺曼帮主义condition啊来进行描述,那么怎么去实现这个代码呢,嗯我可以这么实现对吧,我可以这么实现。

首先啊我得到了一个新的高度值,我的新的高度值等于hi之前的高度加上beta乘以啊,hi前老的hr,这个老的hr就是上一个时刻的hr,然后呢接下来呢我进一步的对这个新的高度值进行嗯,咱们流体的更新嘛。

但是呢这个过程中呢,我需要把我的边界条件给它加入进去,边界条件呢就是说如果说i减一存在的话,如果这个存在的话,我进行流体的交换,同样如果a加一存在的话,我进行流体的交换。

否则的话呢我就忽略了这个水流的跟某一侧邻居的进行交换了,这个就可以实现我这个诺曼boundary condition,这个就是一个比较简单的实现方式,其实顾名思,其实大家简单的理解就是说。

农民帮助于condition的意思就是我不让我当前的这个高度啊,我不让我这个水柱跟某某一个邻居进行交换,那么如果说它未定义,比如说我这个我定义了一个2d的一个用一个有一个数组来定义。

那如果说我这个访问的时候我越界了对吧,我访问越界了,我就认为这个邻居是在边界外的,那么我自然也就把这个东西给关掉了,那如果说他没有越界,我就进行过相对应的更新,这个是我的一个简单的一个目的。

一个一个简单的一个概念,然后下面的部分呢是啊,就是相当于做一些简单的housekeeping,就是我把这个呃hi当前的高度值付给上一帧的高度值,老的高度值,然后我把这个更新过的高度值付给了当前的高度值。

我就完成了一个更新,好吧,然后有同学问模拟水面附着在球面上,那还有边界吗,这个什么叫做模拟的水面附着在球面上,你的意思是就是这个水面下面还有一个球面吗,还是什么意思啊,这个不太理解。

然后我们接下来看就是我们前面是1。5d的情况,好像地球一样的什么嗯,如果说就如果说你这个水它是完整的覆盖整个球面的话,你是不需要考虑边界的,但是如果说你想要做一个类似地球那样的效果。

就是它会有比如说它会有暗和暗吗,那会稍微复杂一点,因为如果说你要模拟那种情况的话,你需要考虑到在那个边界上,它其实是没有水覆盖的,它实际上是由一个底部所构成的,这种情况它其实并不是边界了。

它是它是额外又需要额外处理的啊,但是我有点有点不太记得他这个处理方式是怎么样的,但是它实际上是会有一些额外处理方式的,你需要你需要特殊处理一下,特需要注意一下,会有点不一样。

因为我们这里的边界实际上是假设,这个边界是一个无限高的这么一个边界,它是水是永远不可能过去的,但是是但是你说的那种是有点像沙滩那种那种边界,它会不一样,然后扩展到2。5d上,也就是扩展到3d上啊。

其实是情况是基本上是一样的啊,只不过我们就不是一个一维的数组,不是用一个一维数组去描述这个高度长了,我们用的是一个二维数组,那二维数组呢我就会有两个index对吧,有i跟j那么同样的呢我会有四个邻居啊。

分别是左右前后的四个邻居,那么我左右前后四个邻居我都都需要进行越界的判断,然后利用这个越界判断,越界判断呢我可以施加我相对应的诺曼帮助,condition。

这个就是把一个比较简单的一个shallow wave模拟的一个框架,是我们这个作业里面啊需要用到的,啊然后这在这里大家有没有什么问题,没问题的话,我们就接下来继续讲,继续讲这个company这个问题啊。

什么叫company caplin的意思呢,就是说当我这个水里面有其他东西的时候,我怎么样处理这个水跟其他物体之间的一个交流对吧,比如说我现在里面有一个有个小方块儿。

我怎么样模拟这个水跟这个小方块之间的这些相互关系对吧,然后这个coupling它其实对于流体而言,它有很多研究的东西啊,它不只是说钢铁,它可以是气泡,比如说水跟空气它也可以有c,然后水跟弹性体。

水跟布之间都可以有company,就是各种各样的卡,然后company呢有有一个有个概念叫做土味卡,什么叫做土味cy,就是说它是这种cy,它是双向的,什么意思,就是我的水流。

我的水会对我这个缸体产生影响,那我们所知的就叫做福利嘛,对不对,我这个东西它会浮在这个水面上,这个就是一个方向的一项的差评,然后另一个方向的company呢是我这个缸体呢会对水流产生影响。

因为当我这个钢铁在这个水里面运动的时候,它会把水给排出去,从它里面的地方排出去,所以说这就是我们想要研究的问题,就是怎么样啊,我们今天所要讨论的问题就是怎么样研究,把水从钢铁所占的这个空间给排出去。

那通过把这个水排出去呢,我就可以产生我们作业里面这个水波水浪的效果,然后福利这个东西呢我们就不讲了啊,我们通过作业里面去,大家会体会一下,就是首先第一个就是你需要知道怎么样进行钢铁模拟。

其次你需要知道怎么样利用我们这个排出去的水,把它转化成福利,这个其实就跟阿基米的定律很像啊,我们后面会有一个小叶来给大家讨论一下,但是我们的关键问题就是怎么样把水从这个空间里面给它排出去。

假如说我知道我这个格子占据了啊这么多空间啊,这个灰颜色的部分是我的这个小方块,我所占用的空间,我想我想要把这个水从这些占用的空间里面给它排出去,排到我这个外面,那么我应该怎么做呢,我怎么排出去呢。

一个简单的想法,一个比较简单粗暴的想法,就说我直接把这个呃格子里的水删掉行不行,那肯定不行,对不对,为什么,因为我如果把这个水删掉了,那我这个总的水不就少了吗,那肯定不合理呀,那不把它删掉。

那我还有一种方式,就是我把它删掉之后,我给它加到周围,邻居的格子上去,这是一个简单的方式,但是呢如果说我这个格子占的空间很大,那么你很你还是很难决定说,我最终我的这个边界上应该加到哪些格子上去。

所以说我们就换了一个思路,怎么怎么来解决这个问题呢,我可以利用我们排开水的这种啊播的这个模拟的效果,我可以来进行一个呃虚拟的一个高度,因为我们之前我们进行这个水流的模拟,我们是利用高度高度差来决定的嘛。

对不对,我们有高度差,然后我们利用这个高度差,我们把这个水从高的地方排到了低的地方,那么我们这里的思路就是什么,我们这里思路就是假如说我有一个虚拟的高度,假如说我这个每一个这个灰颜色的这个上面。

我给它加一个虚拟的高度,不是真的,水啊,我是假设有个虚拟的高度,分别是虚拟的vi跟虚拟的v加一,那么如果说有了这个虚拟的高度之后呢,我进行我正常的模拟,我把这个水排出去,如果说我能达到这个目的。

那么我就可以完成我这个排出,把这个水排出去的这个嗯这个操作了,那么换句话说,我想要知道的就是什么样的这个虚拟的高度,能够满足把定量的水排出去的这个目的,那么首先我假设我想要得到的新的高度是这个东西。

这个东西是什么呢,是当前的高度减去ei,ei呢就是这个高度差啊,然后这个h i real new呢,你可以认为这个东西呢是我想要得到的高度,叫real new,我把它叫做real ne,就是我理想中。

我理想中的这个高度应该是这么高,那么我就得到两个公式,那么第一个公式呢是我这一个左边这一个格子啊,我想要得到的理想高度是这个,那么理想的高度怎么得到呢,是通过我这个更新公式得到的对吧。

因为我们之前有这么一个模拟的更新公式嘛,我把这个公式带进去,那唯一的差别跟之前唯一的差别是什么,唯一的差别是我这里假设我这两个格子都分别有一个虚拟的高度,然后这个分别的虚拟高度分别是vi加一。

就是说hi我假设这个格子我假设它的高度是hi加一,加上vi加一,然后当前这个格子的高度呢,我假设它是vi加上hi,换句话说呢,我是在原来的高度上,我给他额外的拔高了一点,我给他额外的拔高了这么多。

然后呢我想利用这个额外拔高的高度呢,我可以最终产生我想要的高度,那么我把这个公式稍微整理一下,我得到了什么,我得到了新的hi高度,也就是正常咱们做呃shadow wave模拟的新的高度。

加上阿尔法乘以vi加1-2 v,这是第一个公式,是关于i这个位置的高度变化的公式,然后右边那个是关于i加一这个格子上的高度,它呢等于啊把一堆公式带进去,把之前那个公式带进去啊。

然后呢我假设hi跟hi加一都分别被拔高了这么多,所产生的这么一个更新,那么我们再整理整理以后,我们就会发现这个东西等于hi加一六加上阿尔法乘以啊,vi减去两倍的vi加一。

那如果说我们把这两个公式分别进行一些变化,我们把它调整一下呢,我最终得到的呢就是右边这个东西呢,我把它叫做一个边界条件,叫做bi bi加一对吧,就是分别是变成了这么两个公式。

那么这两个公式就形成了一个关于v的一个方程组了,我这里有两个变量,因为我这里有两个未知的高度嘛,虚拟高度吗啊,然后分别是关于vi跟vi加一的这么两个公式,然后呢是这么一个方程组啊。

然后我就可以解这个方程组,我最终把它解出来,那但是呢这里有一个小的挑战,小小的挑战,如果说我们在写这个代码的时候,会有一个小小的挑战,这个小小的挑战是什么。

就是我这个方程组它其实是会随着时间的变化而变化的,因为我这个格子啊,我这个小方块儿啊,它会发生位置的变化,对不对,我的用户,我的这个玩家我可以拖动这个小格子嘛,就是左边右边随便拖嘛。

那我在这个拖动的过程中,我其实我需要解的这些变量也会发生变化,也会有改变,那么所以为了解决这个问题呢,我可以这么假设,我就假设说我这个v i啊跟v i加一啊,它每一个方程啊。

它其实都是用一个拉普拉斯的这么一个算子,就是我们之前说的这个跟拉普拉斯相关的这么一个kernel来定义的,然后呢上面的跟下面的部分呢是已知的,为什么,因为我这里这个柱子对吧。

这个跟这个他都不需要虚拟的高度嘛,所以说他们的值就是礼貌,他们的虚拟高度,他们的虚拟高度v i减一跟vi减二,他们就分别是零,所以说他们就是不需要求解的,不需要虚拟高度,他俩需要虚拟高度,但是没有关系。

我把这四个都作为变量给它扔进去,都作为变量争取之后呢,我这样做的好处在于什么,这样作为好处在于,我这两个方程呢就都可以利用同样的拉普拉斯算子来定义了对吧,因为之前是这里是没有的嘛,这里是零嘛。

但是我这里做了之后呢,我就用同样的拉普拉斯算子来定义了,那么这么做呢就可以让我这个求解方程呢,求解的这个算法可以比较统一,比较标准化啊,这是我们在实现的一个好处,当然可能你做作业。

做作业的时候可能体会不到为什么,因为我给了大家一个库,我给大家,我给了大家一个数学的一个小库,叫做p c g啊,大家如果不知道这个东西也没关系,反正这个东西就是啊传说中的共轭梯度法。

我给大家在在这个代码里面,我提供了这么一个库,然后大家所需要做的是什么,大家所需要做的呢是把边界条件,也就是把这个把这个b给它设置一下,这是大家所要做的第一件事情。

然后大家所说的第二件事情呢是把哪些格子需要求解给它标定一下,这个我把它里面叫做mask,我把它叫做一个mask,在在代码里面叫做一个mask,那这个mask比较容易做。

就是你把这些不需要求解的地方都定义成false,然后你把需要求的地方定义成true就可以了,像这两个格子就是分别是处对吧,因为他们需要求解,它们有相对应的这个呃边界值需要求解,这个是处。

然后其他地方你把它定义成false就可以了,然后完了之后呢,你就调用我提供给大家的这个pc机的这个函数,然后他就会给你返回出这个v的值来,然后返回了这个v的值之后呢。

你就把它带回到啊咱们前面这个公式里面,带回到带回到这个公式里面啊,对这个高度场进行更新,就可以了,然后这里呢我后来发现就是说这里其实是有一个小窍门的,就是这里他其实最好是不要直接把这个算出来的v放进去。

对这个高度进行更新,而是要对这个v乘以一个系数,为什么要乘这个系数,是因为呃如果说你直接模拟的话,它这个你用这个玩家拖动这个小方块特别快的时候,会导致它这个水浪特别特别的大。

为什么会导致这个水量特别大呢,本质上也是因为我们这个求解的这个方式,我们这个求解shallow wave的方式,它是一个显示积分的方式,如果大家看这个公式啊。

我们前面这个公式你会发现其实本质上还是我有一个公式,然后我套公式直接把这个新的高度长给他算出来嘛,所以说它是个显示积分的公式,它不是一个影视积分的公式,那显示积分的公式就会存在一个问题。

就是它会导致它会有不稳定性,所以说如果说你拖动得很快的时候,就会导致它这个水浪水花特别的大,所以说这就是我为什么我这里建议大家,这里在这里算出了这个虚拟的高度值之后,要给它乘一个系数。

成了这个系数之后呢,会让我这个水浪会小很多啊,当然这么做呢它其实并不是物理上并不是正确的啊,但是呢就是这是一个折中的算法,为了能够让我们的效果上看起来更加的合理一点,这个就是我建议大家做的这么一个事情。

好吧就相当于是给我们这个拖动方块的时候产生的水浪水花啊,给它衰减一下,那么好我们前面讲了就是怎么样去模拟这个方块对流体的效果,那么反过来流体对方块会产生一个什么样的效果呢。

我们知道我们这个高度会发生改变,对不对,假如说这个高度这个方块这个格子上的高度,因为方块的变化,方块的影响,这个格子的水变成了这么个高度,变低了,被水被排出去了。

那么我们知道阿基米德定律说阿基米德说这个是物体受到的浮力,等于它排出去水的重量,对不对,那么我知道水被排出去这么多,那么根据我这个高度差,高度的变化乘以这个啊这个格子的宽度,然后再乘以这个密度。

再乘以重力加速度,我就可以得到浮力了,然后这个呢是这个格子产生的浮力,如果说我这个方块儿很大,它可能会覆盖到很多小格子吧,那么每一个格子其实都会对它产生一个福利,所以说大家会考虑啊,就是不同的福利。

不同的格子会产生不同的福利嘛,然后把这些福利都加起来啊,然后呢你也需要考虑到旋转,因为这个这个方块它可能会有旋转,所以说你也需要考虑到例句,这个也是大家在做突围company的时候。

需要考虑到的一个问题,在3d里面,如果说你在做3d的时候呢,这个就不是delta x,它就不是一个格子的宽度了,它是一个格子的面子啊,这个是需要大家稍微做了一个调整呃。

然后我自己在做这个给大家设计这个作业的时候,我发现福利这个东西比较好解决,福利的这个平移比较好解决,但是它的旋转始终始终有一点问题,我没有做得特别好,我后来琢磨。

有可能也是因为本质上我这个模拟的方式是用显示积分所实现的啊,然后一个解决方式呢就是把整个东西改成影视积分啊,这个是可以做的,但是呢我没有做啊,然后大家这个其实也算可能是一个一个bonus吧。

就是说大家如果说有能力呃,去做影视积分的话,大家可以去考虑一下怎么样去做影视积分,关于这个高度场的饮食积分啊,但是反正这个是bonus quit啊,这个反正反正这个是大家探索吧。

我自己也没有把这个东西解决掉,所以说我也不知道大家有没有能力,我希望大家说不定我们中间可能有哪些特别厉害的同学,能够把这个问题解决掉啊,这个反正就是大家自己探索吧。

我自己嗯以前做过一篇关于高度场影视机片的paper啊,所以说我知道这个影视积分是可以做的,然后我在那个paper里面,我有一个demo是做嗯做小船的浮动的一个效果,所以说我知道这个东西肯定是可以做的。

只是这个作业因为我们用了显示积分的,也有可能是因为显示积分的原因,这个效果并不是特别理想啊,所以说反正我把这个东西留给大家去思考,好然后今天我们嗯讲了很多关于呃高度场的这个东西。

然后呢我们这个同时呢我们也讲了这个shallow wave的这个模型啊,他顾名思义呢就是我想要用这个高度场去模拟这个波的效果,然后这个模型它其实是做了大量的简化的。

其实大家呃可以注意到我们在整个课的这个过程中,我不断的做简化对吧,这里也简化一下,那里也简化一下,然后最终我得到了一个非常简单的一个模型,然后呢我们可以做一个相对来说比较简单的模拟。

产生一个水面波的效果啊,但是呢真正的流体力学它其实并不是这么样的,它其实还是有一些比较复杂的内容的,所以说我们之后的课呃,后面的课也会讲,就是我如果说我想要不做这样的简化。

我想要完整完完整整的去相对比较正确的去模拟流体,我应该怎么求解,然后shwave这个模型呢它比较简单,而且它的效率也比较高,大家可以看到在unity,哪怕在unity里面,你也可以很快速的模拟啊。

同样它也可以做copy facts啊,然后呢我记得在游戏里面,在有些游戏引擎里面,它其实也会用到这个方式,如果说大家玩一些游戏,注意到就是比如说你的人物在一个水面上行走啊,它会产生波的效果啊。

这种波很大程度很大概率就是通过shallow wave啊这个模型来模拟的,呃,我记得很早很早,大概十几年前p s的游戏里面其实就用到这个模型了,包括我之前也看过一些p s的playstation上。

他会有有有有,我记得有一个tutorial,他就是也是基于shadow wave做模拟的啊,然后反正这个东西嗯希望大家去实践一下吧,然后我们作业嗯,作业可能迟一点会发给大家啊。

然后大家通过通过作业了解一下shadow wave这个模拟方式,然后我们下周还有下下周呢会讨论呃,更加经典一点的流体力学的模拟方法,当然是反正就留到之后好吧,然后大家有什么问题啊。

我觉得今天的一个课的好处就是在于我们今天讨论的东西,虽然说是简化的,但是有很多概念是可以复制到后面的东西,后面的部分,偷偷拉个lunge,我没有看到,偷偷拉个lg,我这里面有偷偷来个狼,就这个东西吗。

这个有同学问就是说后面有没有时间讲fpm的和神嗯,我估计是没有时间了,我因为我当时做p p t的时候,我我当时做pp的时候没有没有很好地考虑到时间呃,我我也不知道说f e m要讲的多深。

或者是花多少时间,所以说我准备了这个p p t嗯,但是呢我后来发现其实其实没时间讲,所以说所以说就算了,然后如果说以后咱们有时间讲高级课程的话,可能会讲吧,但是这个咱们基础课程就就不讲了。

可能是偷偷拉格朗,这可能要不就是说意思,就是我这个方法就是完全基于拉格朗日的方法吧,因为现在有很多hybrid的方法,就是hybrid的方法,就是想要把这个拉格朗日和欧拉方法相结合嘛。

啊所以说偷偷拉格朗特就是完全基于拉格朗日方法,如果方块的一个角戳入水柱怎么办,因为我们这个东西实际上实际上是一个一个近似的方法,所以说他如果是只是一个角稍微进去的话,取决于我们怎么样去离散。

离散积分这个东西,如果我我们作业里面的做法比较简单,作业里面的做法就是说啊作业里面如果如果没有balance的credit的话,如果你不做boss的话,我假设一个方块就是一个方块。

它是一个横平竖直的方块嘛,然后一个横平竖直的方块的话,你就直接假设我的柱子的终点设一条射线,然后你去判断这个啊这个跟底面的相交的,位置,然后你给它算出这个高度来,所以说不会出现一个角的情况。

如果说正儿八经模拟的话,嗯其实大差不多也是做这种近似,基本上就是因为我是离散化的模型嘛,离散的话的模型我只能说通过采样,我来判断说这个地方有没有有没有被那个东西覆盖,到我们最后一节课会讲。

我们今天我们下节课讲的是那个正常的,我们做欧拉法的模拟,然后下节课讲的是sp,作业可能没时间讲解吧,如果说大家想知道作业的话,可以把那个可以问一下ta,我们的ta会嗯把把正确答案发给大家。

大家可以参考一下正确答案嗯,这种流体跟机械工程的流体力学有什么区别呃,基本上是一样的,模拟的方式基本上是一样的,跟那个跟计算物理里面的用到的流体模拟方式基本上也是一样的。

然后p h还有shwave会不一样,因为据我观察嗯,在工程里面一般来说不太用到这种简化的模型,但是我们下节课讲的那种通用的模型,它基本上是一样的,甚至于早年的时候很多论文都是两边一起的,两边发的。

就这边也发,那边也发,但是这几年因为大家注重的,因为本身流体力学本身也是研究了很多年嘛,所以说大家研究图形学里面,大家研究的重点逐渐转到就是一个是怎么样提高性能。

然后另一个就是说怎么样去模拟一些比较奇怪的一些,我觉得是比较奇怪的一些效果上去了,好吧,那那今天就先到这儿吧,然后咱们下节课会啊,开始讨论,就是讨论一些比较通用的。

包括就是我们流体力学里面的一个经典的一个工程方程,叫做never stop sequation,我们下周会讨论这些东西嗯,可以就是说如果说你要检测方块进入水的时候,你可以用unit可以组建啊。

其实我其实我还是比较建议你们用unity组件的,在这个作业上,但是但是如果说你不做boss credit的话,倒是没有必要,因为你完全可以根据那个方块的位置,你直接把位置减去它的方块的大小。

你可以把这个方块里面给它算出来,会比较简单好吧。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

GAMES103-基于物理的计算机动画入门 - P11:Lecture 11 Incompressible Fluid Dynamics and Eulerian Fluids - GAMES-Webinar - BV12Q4y1S73g

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

行那我们就那个呃开始吧,呃我们还有大概还有两节课的时间啊,主要就是来讲流体这一块啊,然后我们今天主要讲的是那个嗯叫做一呃基于网格的一种方法,基于欧拉的一种方法,我们来讲怎么来做流体模拟。

然后我们下节课有时间的话,我们会讨论一下怎么样用粒子的方法去啊解流体,处理流体问题啊,然后大家可能都知道,这个我们1月份的时候有一个对图形学比较重要的事情,就是有cf的deadline。

所以说我们最近都比较忙,所以所以说我下次下节课的ppt到现在都还没有弄啊,反正就是我就是尽量吧尽量给给同学们啊,把最后一节课上上完,嗯然后嗯然后有什么问题的话。

反正下节课我我也会留出一点时间来回答一些同学们的问题,好吧,然后今天主要讲的是呃基于这种网格的啊,模拟流体的方法,我们首先会讲一下这个网格的表达是怎么样的啊,然后我们会有点延续上上节课的知识。

叫做final difference的知识,我们会讲就是我们有了这个网格之后,我们怎么样可以利用网格去算很多呃,偏微分啊,还有算很多这种微分算子,这个对我们解流体力学就特别有帮助呃。

然后呢我们会讨论这个流体的这个方程叫做nel stokes方程,可能大家或多或少听说过,那么这里我们图形学里面主要解的是叫做incompressible visors的这种啊。

流体所谓的incompressible呢,就是说我假设这个流体是不可压的啊,就比如说像水,你不管怎么压这个水,这个水的体积基本上是固定的嘛对吧,那空气呢我们其实也是做同样的假设。

我们也是假设空气是不可压的啊,当然现实中我们知道这个不管是空气也好,水也好,它其实你给他足够的压强,它其实都是有能力有办法把这个它的体积变小的,但是我们这里呢就主要就是做一个简化。

我们就假设啊这些流体都是完全不可压的了,然后viscus的意思就是说我们会会有一些粘滞啊,我们会讨论这啊,就是navexecution,我们会讨论说我们怎么用啊数值的方法去解这个流体力学的方程啊。

那这个流体力学方程它主要描述的是流体的运动,也就是是流体的速度,说白了就是流体的速度啊,那光有速度不行嘛,对不对,因为光有速度,我们还要描述流体的状态,就像我们之前我们做粒子模拟也好。

做各种各样的形变也好,你光有速度还不够,你还要有顶点的位置吗,所以说同样的在我们解流体里面,我也需要有相对应的东西去描述流体的状态啊,那么我们会讨论水和液体和气体,我们分别应该用什么样的。

有哪些模型去描述这个状态啊,然后怎么样能够跟前面的navs qu结合在一起,嗯然后还有一点我想说的就是说图形学里面用到的这些方法,其实都不是图形学自创的,很多方法都是从流体力学计算。

流体力学里面借鉴过来的,有很多paper都是呃两边发两边引用的嗯,但是最近几年,最近这10年基本上就是这些方法都已经比较固化了啊,所以说啊所以说大家其实在很多啊这种引擎,像胡迪尼啊。

还有很多很多其他的这种工具里面,blender啊,其实都可以看到这些呃,解流体力学,解这个都已经变得很标准的一个操作了,所以说我们今天基本上也是讨论一些比较标准的这种算法。

那首先我们来想讨论的就是这种网格式的这种表达方式,呃,我们上周其实已经见识过了一种表达方式,但是那个实际上并不是真正的一个描描述一个二维或者三体,三维里面的流体,我们实际上是做了一个近似的对吧。

比如说我们二维,我们用一个一维的数组去描述这个网格,就像我们作业里面我们用的是一个二维的一个网格去描述数组,那这么它的好处在于,我们把空间给减小了,那么我们相对应的我们的内存的需求。

我们的这个计算的复杂度也会降低,那么如果说我们不做这样的简化,我们要真真正正的去模拟一个二维或者三维的水应该怎么样呢,那我就应该真正的在这个二维的空间或者三维的空间里面,去定义这么一个网格对吧。

那比如说我想做一个二维的一个流体的模拟,那我就把这个二维的空间用一个2d的一个网格给它覆盖,那比较常见的就是这种regular grade,所谓regular grade就是我里面都是一个正方形啊。

我的这个长跟宽都是一样的,然后呢我就均匀的分布把整个空间给占满,这种是一个比较标准的一个网格啊,当然也有很多变种了,比如说我可以把这种网格跟我们上节课讲的heat field结合在一起,我可以做这种。

还有这种做我可以做这种quite tra或者是binary tree的那种网格,还有呢我可以用不同大小的网格就等等等等,他这种会有很多这种呃不同的模型,但是呢我们这里好想的就是比较标准的。

比较简化的这种规则的这种网格,那么规则的网格它为什么我们呃想要用这种规则网格呢,其实因为它有一个很大的好处在于,如果有了这个规则网格之后,我就可以认为比如说我这里面是一个格子吗。

我认为这个格子里面的物理变量我可以定义在这个格子的中心,我就可以把这个每一个格子都给它附一些值,附一些物理的值了,那这种物理值它可以是一些标量,比如说啊密度啊,颜色啊,压强啊,温度啊等等等等等等。

这些都是标量吗,我可以认为这个格子里的这个密度啊,颜色啊,温度啊,什么都是在这个中心点的这个点上的,当然了,我也可以复制矢量,比如说速度等等等等等等,还有各种各样的其他的。

那么整个二维的网格我就有很多很多的小的这种格子嘛,每一个格子我都有相对应的标量或者矢量的物理的这种值,复制在这个格子上,它整个就构成了一个厂,我们可以把它叫做一个标量场或者一个矢量的厂。

那么这个厂由于它定义在这种规则的格子上,它带来了一个很大的好处,在于我算倒数呃,以及我利用导数进行各种各样的这种微分的这种计算,就变得非常容易了,啊我们比如说我们上节课我们讲过对吧,如果说在时间上。

假如说这个横轴是时间,然后呢我有三个相对应的时刻,分别是t0 减负dt,然后t0 加deltt对吧,我分别有前后两个时刻的这个函数值,然后还有个中间的函数值。

那么我可以利用我们central differency呢,我可以前面讲后面我可以把前面的值减去后面的值,我就可以,然后再除以两倍的跨度,我就可以得到函数值在t0 的一阶导数了。

这个是我们上节课讲过的叫central differen,就是可以利用前面左边前面剪,前面剪后面,或者说右边减左边,然后除以两倍的跨度值,就就是整个跨度值嘛是二代的t嘛,减去跨度值,我可以得到一阶导数。

这个是我们上节课讲的,那对于格子而言,对于这种网格而言,这个东西就变得很非常简单了,对不对,因为我就假设我这个函数值是在这个格子的中间的嘛,那这个格数指的是f i j,我假如说是个二维的对吧。

横横的是i做的是j,那么这个格子是f i j,然后边上这个格子呢是呃f i加1j,因为它是往a方向再多了一个嘛,那我就可以利用我们之前的那个centre difference的公式。

我就可以把中间的这个位置给他导数给他算出来了,那么中间这个位置是i加0。5,所以就是i加0。5的函数的一阶导数等于啊右边减去左边除以跨度,然后这个跨度就是咱们这个格子的宽度是h。

就是大家可以从这个例子上就可以看到它这个网格的这种表达方式,对于我们呃求一阶导数是非常便利的,e而且他不只是在这个位置,它在所有的位置上,如果说你想要算这个对于x对我们横横的方向叫做x啊,这个叫x。

然后我们把zm的叫y,那么我对x求一阶导数就变得很便利,呃同样的道理,比如说我现在我这里想做二阶导数,我想要知道这个二阶导数,那么二阶导数怎么算呢,我可以做两次一阶导数嘛,对不对。

我先把这个点上的一阶导数给他算出来,那是i加0。5,我用右边减左边,我给他算出来啊,然后呢,我现在算这个点上的一阶导数,这是i减0。5对吧,我可以利用右边减左边,也可以把它算出来。

那有了这两个一阶导数之后,分别是在这个不是在中间啊,分别是在这个格子上呃,分别是在这两条边上对吧,分别是在两条边上的一阶导数,我算出来之后,我再给他求一次一阶导数,对他们两个我再求一次一阶导数。

我就刚好完美的得到了ig这个位置上的二阶导数了对吧,因为他俩是一阶导数嘛,然后我对他俩的一阶导数再求一次一阶导数,我就得到了二阶导数,然后呢这个位置刚好又落在中间了。

所以说这里通过我们展开我们得到的这个整个式子,就是左边加右边i减一,加i加一,然后减去两倍的他自己除以h的平方,这个就是我们算二阶导数的公式,利用central difference算二阶导数的公式。

当然这个公式我们其实上节课也讲过啊,其实也讲过,就是利用这个公式算二阶导数,只不过对于格子而言,这个东西就变得啊那处处都可以算了对吧,因为我们整个就是个格子嘛,我们哪里都可以算。

那同样的我刚刚得到了x方向上的二阶导数,我对y方向上的二阶导数我怎么算,一样的道理,只不过我现在就变成了上下的这个方向对吧,然后利用我们的公式,我们得到的是呃上面的这个函数值,加上下面这个函数值。

然后减去两倍的它自己除以h的平方,这个就是我们算y方向上的二阶导数,那有了这个有了前面这个公式,我们知道怎么算二阶导数,分别作为呃x跟y方向,我知道怎么算二阶导数之后,我就可以呃做一些操作嘛。

比如说我想要算拉普拉斯算子怎么算对吧,对于网格上的拉普拉斯算子,拉普拉斯等于什么,拉普拉斯就是两个二阶导数的和,就是分别是x方向的二阶导数,加上y方向上的二阶导数,我把它俩加起来,这个叫做拉普拉斯算子。

然后呢我们利用刚才这个公式呢,我们最后得到的就是上面的加下面的加左边加右边的减去四倍的,他自己出h的平方啊,其实大家简单的直观的理解就是所有的邻居,我把我所有的邻居加在一起,这都是我所有的邻居嘛。

左右前后马上下左右嘛,然后减去四倍的,它自己除以,然后最后除以h的平方,这个我们叫做拉普拉斯算子,就是在这个网格上的一个离散的拉普拉斯算子,就是这个东西,这个是我们可以利用这个网格的这种特殊结构啊。

然后我可以很方便的把这种微分算子,拉普拉斯算子给它描述出来,离散化出来,那么跟上节课我们讲到了边界条件嘛,啊同样的我们在做这种完整的这种网格模拟的时候,我们也需要设置边界条件。

那边界条件跟上节课其实也差不多,就是也有两种边界条件,分别叫做dsent边界条件跟newman边界条件,所谓的derially的编辑条件,就是说我假设外面的这种边界上的这些函数值是已知的给定的。

比如说我这个点对吧,假如说我这些深色的这个格子啊,全都是啊已经已知的了,已经是在隔空间外面的了,已经是在外部了,那么我就假设这个格子里的这个函数值是已知的,比如说是某个常数,我假设它是个常数。

那么在这种情况下呢,我的拉普拉斯就变成了c加上其他邻居减去四倍的他自己了,如果说我想要得到i j的拉普拉斯的话,那么就是相当于这个,而原有的这个左边的这个函数值,我就认为是一个常数c了,我就带进去了。

同样的,如果是newman boundary condition呢,那我就稍微改一改,我就不假设它是一个常数值,而是我假设这个函数值跟我i j的这个值它有某种联系,某种关系。

它可以是个比例或者是一个什么线性函数,或者是某一个函数,不管他,但是我可以认为他俩是有某种关系的,那么比如说我可以认为他俩是相等的对吧,我假如举个例子啊,不一定是boundary no man。

帮助condition都是这个样子,但是比如说我这里假设他俩是相等的,那如果是他俩相等呢,啊这个拉这个拉普拉斯会变成什么样呢,就变成了其他邻居减去三倍的他自己了,为什么,因为他俩永远都相等嘛。

所以说他俩减一减等于零啊,所以就不需要考虑,就变成了其他邻居加在一起,再减去它三倍,它自己除以x的平方啊,所以说整个边界条件跟我们其实上节课我为什么上节课讲hifd的。

主要原因也是这个就是可以帮助我们啊很方便的理解,就是今天这节课里面啊的一些知识,同样的上节课我们讲了这个高度场的边界条件嘛,同样的我们在模拟这个啊这个这个完整的这个流体,就是不用高度常用。

直接用网格去模拟流体的时候,也会存在相应的便捷调节,好了,那么我们接下来看这个一个具体的一个小问题啊,而不是流体的问题,但是是我们一般来说做数值计算啊,里面会通常举的一个例子。

什么例子呢叫做拉普拉斯方程,拉普拉斯方程什么意思呢,其实很简单,就是他说拉普拉斯啊,他这个拉普拉斯永远等于零,当然了,这个f它不是一个函数值,大家要注意到这个f它不是一个函数值。

它是定义在所有的格子上的一个草,明白吗,它是一个草,你换句话说它每一个格子里面都有一个函数值啊,这里有一个这里有一个每个格子里面它都有一个f,然后呢,我要的是什么,我要的是在所有的格子里面。

它这个拉普拉斯都等于零,因为这是离散化的,我就认为所有的格子里面都等于零,如果是一个连续的还一,如果是个连续的问题的话,我就是认为这个空间里面这个求解的这个空间里面任意一点上,他的拉普拉斯等于零。

那因为我们做了离散化了,我就认为每个格子里面他这个拉普拉斯都等于零,那么具体比如说这个格子,我们看这个格子i j对吧,这是我的一个某个格子嘛,任意某一个格子它的编号是i跟j那么对于他而言,他而言。

他的拉普拉斯就等于我们我们我们前面讲了,对吧,我们前面讲了,他这个拉普拉斯,拉普拉斯就等于所有的邻居加在一起减去四倍的自己,除以h的平方嘛,所以这里就是啊所有的邻居加在一起减去四倍的自己啊。

除以这个h的平方,那我这里不除h的平方,因为出不出都无所谓,因为我要求它等于零嘛,所以说我就只考虑说把所有所有的邻居加在一起,减去四倍的时积等于零,然后满足某一个边界条件。

啊然后这里呢边界条件中呢必须要有一个是newman boundary condition,你不能所有的边界条,啊啊啊这里写错了,应该是norman,应该是ds,大家想一想为什么,我可能拼错了。

derrish derrhate,就是如果说这个问题,假如说我考虑我这个我我右边这个问题啊,我就我就用右边这个空间作为我的问题,然后这个小方块啊,这这这这个这个正方体正方形外面,假如说是它的边界的话。

那么这个边界中或者是某一个位置,他必须要有一个ditially的bdi,他不能所有的都是newman帮主,大家大家想想为什么为什么会是这样,假如说我是全部都是no man,帮助会发生什么。

其实你可以这么理解啊,不是体积守恒,是因为这个问题它就会有无穷多的解,因为为什么,因为大家看前面的norman boundary是说什么,norman帮主说的是,我跟我的邻居是同等的值的。

换句话说就是说这个函数这个这个值跟这个值是一样的对吧,那么假如说我得到了一个解,得到了,比如说我把所有的函数值都给它求解出来了,那如果说我把这所有的函数值全都加上某一个常数,是不是也是它的合理解啊。

因为我所有的值都加上c,首先我把你看,我把这些函数值全都加c加c加c,你会发现是不是还是等于零啊,对吧,减去四倍的c是不是还是等于零啊,然后其次如果说我在边界上,我只要求说这两个永远相等的话。

那么等于就是他并没有告诉你这个函数的绝对值是多少,所以说它会有无穷多个解,如果说你把这个方程列出来的话,你会发现它这个矩阵,他这个你你你就是你你会发现它这个矩阵它会是一个不正定的。

它不是它不是一个呃nsingle lar的矩阵,它会变成一个singullar的矩阵,换句话说它这个系统是会存在无穷多个解的,它会singular,所以说大家会发现就是当你构造这么一个信息系统。

如果说如果说你你把这个认为是一个信息系统,关于每一个格子啊,认为是个变量,你把每个格子认为是个变量啊,然后呢你去构造一个信息系统,就这样子,然后前面呢是这个我们公司里面的这些参数右。

然后呢右边呢是我的所有的f i j f,然后右边等于零嘛对吧,然后这个矩阵里面呢就是111,然后对角上是-1对吧,然后一然后如果说你去构造这么个系统的话。

你会最终发现如果说都是如果都是newman帮助condition,你这个会变成singular的矩阵,所以说他会有无穷多个解,它因为它会存在着无穷多个解。

那无穷多个解的原因就是因为你的解空间没有约束它的绝对值,你可以任意的给这个值加上一个常数,把所有的值,我们把这个厂里面的所有的函数值都给它加上一个常数,它还是符合要符合要求的。

所以说这是我们在求解这个这个拉普拉斯,就是边界条件上其实会啊,就是不能全部都是newman boundary condition,这个跟我们上节课的那个高度上有点不一样啊。

因为我们刚上节课的高度上是可以全都是能把bgary的,但是这里不可以,这个大家听明白吗,还是我要我我我停下来再讲一讲,这个其实可能需要有一点那种怎么讲,因为高度场那里它其实并不是拉普拉斯方程。

它是另一套系统了,因为它并不是解拉plus方程,他跟这个问题不一样,这个如果大家学过那个嗯学过数值,数值偏微分的话,其实这个都是数值偏微分里面啊最比较基础的东西,数值偏微分方程,那我就先呃先往下。

然后回头大家有什么问题可以再回过来看这里,然后我们就会构造一个信息系统,然后去解这个信息系统呢,啊就我们就可以用一些比较标准的套路了对吧,比如说比如说信息系统的话。

我们知道可以用jacob迭代的方法去解这个信息系统,那么这就是一个例子,就是我把这个gq币方法用到了这个信息系统里面,我去接他,然后通过迭代,然后最后把它解出来,然后大家注意到这个东西啊。

这个东西它我们其实嗯我们有一个比较直观的理解叫做拉普拉斯平滑,为什么叫拉普拉斯平滑呢,因为当你反复的进行这个操作的时候,你会发现整个东西就变得是平滑,就非常的光滑,非常的这个函数值就是趋向于一样的。

就比如说啊比如说我上面是红颜,我用颜色来说吧,比如说上面是红的对吧,然后下面是绿的,那么你反复的进行这个拉普拉斯操作呢,就相当于红颜色的就慢慢慢慢的往下走,绿颜色慢慢慢慢的往上走。

然后最终这个图片就变得很光滑,然后最终如果说你把这个解完的话,就就是这个dtf等于零,你把整个拉普拉斯方程解完的话,你就会发现整个东西就变得很平滑了,所以说我们一般来说会用这个东西。

利用这个东西啊进行一些,比如说呃图像里面我们做拉普拉斯平滑也是采用这样类似的方式,然后直观上你可以理解他这个拉普拉斯平滑的本质,就是我跟我自己的邻居求平均,比如说你看我这个f f i j就是我自己吗。

然后这些都是他的邻居嘛对吧,然后这个东西这个括号里面得到了什么,就是得到的,得到的是我跟我邻居的差,对吧,因为我跟我邻居的差就是我自己减去我的邻居嘛,然后呢我把这个差加在我自己上。

实际上就是意思就是什么,就是我把我自己的值,我把我自己手上的这个值啊,跟我邻居的这个值靠近,我尽量让我的值跟我的邻居变得一样,那么如果说你这样子反复的迭代,反复的迭代。

是不是就是最后就是大家都是趋向于平均嘛对吧,就是如果说理论上如果说很完美的情况下,那么最后我们所有的值应该都是read,都是一模一样的结果,那因为我这里我强制要求上面是红的,下面是绿的。

我没有办法做到所有的人都一模一样,那么最终的结果就是我整个场,我整个颜色的分布就会变得很很那个很很平滑,可以用八个邻居吗,有同学问可以用八个邻居吗,这个取决于你怎么离散化吧,像这个grade。

我们用的是四个邻居对吧,八个邻居的我还没真没见过,但是如果说比如说你用那种六边形的网格的话,是可以用六个邻居的,就像那种呃mash 3角网格的mesh啊,他每一个点平均下来是有六个民居的,是六个零居的。

这个套路还是比较常见的,但是八个邻居的网格我还嗯没怎么见过吧,一般来说就是四个邻居或者六个邻居比较常见,所以说这个就是拉普拉斯公式,还有跟这个呃拉普拉斯平滑的这么一个呃小关系,嗯然后呢这个整个过程啊。

这个平滑的过程呢在模拟里面啊,当然这个smoothing这个东西,这个名词本身是一个可能跟图片更有关系的一个名词吧,因为就平滑嘛啊如果在模拟里面呢叫做diffusion啊。

这个demo我就我就我就不弄了,因为我因为那个小程序有点问题啊,但是本身就是diffusion,意思就是什么就是扩散,就是在物理里面就是大家可能学过就是一个东西,比如说我有墨水对吧,我墨水滴在水里头。

然后那个墨水的墨水的这个颜料,它会逐渐的扩散到整个啊这整个这个液体的空间里面嘛对吧,这个扩散过程实际上就跟这个smooth是一回事情,当你在做smooth的时候。

本质上也就是你在对这个扩散过程进行时间上的积分,你不断的把这个墨水的颜料扩散到整个空间里面,然后最终最终所有的地方的颜色颜料都会一模一样,就是啊解到最后的结果是,哪怕是等于零的时候。

嗯如果说你做正常的模拟扩散模拟的话,是会有时间上的那个时间,像一般来说在这个前面的系数上,就是如果说你你模拟啊里面会有delta t会跟dtt相关,但是这里没有,因为这里咱们就是直接解这个公式嘛。

它这个这个东西它不是在做模拟,好然后我们前面讲了这个central difference,然后呃讲了这个三central difference in,可以拿来搞这个拉普拉斯算子,然后跟拉普拉斯公式啊。

然后跟这个拉普拉斯平滑跟这个模拟扩散都有关系对吧,那么我们现在来讲一讲一个问题,一个什么问题呢,就是关于一阶导数的问题,因为我们刚才前面其实讲直接就搞二阶导数去了,就讨论二阶导数了。

然后没怎么仔细看一阶导数,但是其实你自己琢磨一下,你会发现这里其实对一阶导图是有一个问题的,这个问题是什么,问题在于我算出来的一阶导数他没有定义在我们格子的中间对吧。

我们之前我们假设所有的物理的这些量都是在各自的呃,就是在这个格子中间的中心点上面,但是如果说我们做central differences的话,那么我算出来的东西它不在格子的中间了。

他在这个格子跟格子之间的这个墙上了,对不对,而我这个墙上呢是没有定义任何变量的,这个就有问题,我算出来的东西我没有办法去进行保存,没有这个格子,那么有同学说这个倒不是,这个为什么是个问题啊。

我还是可以用century ency嘛,对不对,我可以比如说我想要算这个ig上的一阶导数,我可以,我还是可以右边减左边吗,我可以f加一减f减f i加一减去fi减一嘛,对不对,那这个是可以的。

我就是做这个右边键左边的这个操作,但是呢这个有点奇怪,对不对,因为我这里完全忽略了我这个自身的这个函数值,我直接是右边减左边了,这个好像不是很合理啊对吧,因为我直接把自己的函数跳过函数就跳过了,照理说。

我自身的函数值应该是对于我自身的这些物理变量是很有关系的,但是呢我为了算我一阶导数,我反而用我左边跟右边的领取,我直接把自己的函数值根本就没有考虑,这个就有点奇怪了,所以呢大家就想就是我是不是可以。

不要把所有的物理变量都定义在格子的中间,尤其是对于流体模拟而言,我不要把所有的物理变量都定在格子中间,我可以把一部分物理变量定义在墙上,那么什么物理边界定义在墙上呢,这里我给大家告诉大家,就是速度。

那速度它定义在墙上,它有一个什么好处啊,就是我们知道速度它是一个矢量,对不对,它有两部分构成,分别是x方向的速度跟y方向的速度,那么速度定义在墙上,它有个最大的好处,在于我就可以把x定义在这个竖的墙上。

然后把y方向上的速度呢定义在这个横向的墙上,就像这样子,比如说you我认为是x方向的速度嘛,我就直接定义在这个用蓝颜色的表示,我就直接定义在这种树的桥对吧,然后绿颜色的呢是咱们y方向上的速度。

那我把它定义在这个横向的墙上,那么就大家可以直观的理解,就是每一个墙上我都有一个流速嘛,对不对,我这个水是从一个格子流到另一个格子里去的,那么这个水穿过这个墙的这个流速就代表了这个这个方向上的速度。

我们就可以直观的理解,就是相当于这个水哗哗哗的从这个左边游到右边,那么这个u i j就代表了这个流速,那么这个流速可以是正的,也可以是负的对吧,因为它可以从左边流到右边,也可以从右边流到左边。

所以说它可以是啊正的,也可以是负的,那么我就是可以利用这个东西来做这个定义了,那么这种格子,这种网格跟前面咱们那种所有的物理定义,定义在这种中心点的格子有点不一样。

这种格子我们有个名字叫做staggered grade,然后这个在流体里面特别的呃常见,也特别的方便,因为为什么方便,我等会给大家解释啊,为什么这个东西特别方便,但是呢啊这个我想给大家介绍一下。

就是会有一种把这种速度,专门把速度定义在这个墙上的这种表达方式,那么我们接下来就讨论我们利用这种staggered grade这种表达方式,我们可以做什么,对不对。

那么首先我们可以来计算一个格子的水的净流出或者是净流入是多少,如果大家把这个格子当作是一个由四面墙构成的一个区域的话,那么在某一个时间内,在一个单位时间内,我这个区域里面水的增加或者减少。

实际上就是由这四面墙上的速度所决定的,对不对,我这个速度越大,就表示我这个流入的这个格子里的水越多,我这个速度越小,或者是速度是负的,就表示它这个流入的水越少,那么总的流入量是多少呢,净流入量是多少呢。

是ui加1g加上vi加v j加一减去u i j,减去b i g然后这里为什么不都是全加的,是因为左边的墙跟右边的墙是不一样的,同样上面的墙跟下面的墙是也是不一样的。

所以说我实际上是右边加上边减去左边减右边,然后这个就可以得到我的这个总的净流出量,这个应该是净流出量,因为你想想看这个东西越大,u i j加一就这项越大,也就意味着流出的水越多嘛对吧。

然后这个项越大就意味着流净的水越多,然后我减一减,实际上就得到了它的净流出量,那么单位时间的净流出量实际上就是由这个速度,这些这些速度的这些组合来决定的。

所以说我们这个stard grade它有一个很大的好处在于什么,它就比较直观,你就可以想象它这个速度,它定义在这些墙上,就告诉了你这个格子里面,它这个水到底是个怎么个变化,那么好了。

我们前面讲我们要解的这个流体,我们是假设它是incompressible,不可压的,那什么叫做不可压呢,假如说我这么一个空间里面,这个3x3的这个网格里面,每一个地方都有水,都沾了水。

那么不可压也就意味着我每一个格子的净流入和净流出都等于零,也就是说我进来多少水,我出去多少水,我进来多少水,出去多少水,那么这样子的话,我总的变化,我总的水量的变化。

零也就意味着我整个体积是没有发生改变的,这个就叫做divergence free,就是它的这个那么为什么叫做divergence free呢,是因为如果说我们利用前面这个我们这个体积变化的流出。

流入公式等于零来看的话,你会发现,这个东西跟我们的divergence实际上是一回事情,如果说同学们不记得什么是divergence的话,其实这个东西啊。

这个我们用这个倒三角dot这个来表示倒三角dot,意思就是you就是x方向的速度啊,叫u啊,对x求导加上y方向的速度,也就是v对y求导,这个就叫做divergence,就是我这个u v是一个速度嘛对吧。

我这个大写的u我把它叫做速度,它是它是一个向量,它有两部分,上面是小写的u下面是小写的v,然后上面对x求导,下面对y求导,然后我把一阶导,然后我把它加起来,这个就叫做divergence。

然后你就会发现,如果说如果说我们用这种stgrad的话,那么在i j这个地方啊,他的这个一阶导数就比较好算了,为什么,因为刚好我这个左边跟右边都是在墙上吗,都是在墙上的话,我这个左右左右减一减。

我就得到了这个又对x的一阶导数,然后同样的我这个上下减一减,我就得到了v对y方向的一阶导数,然后把它加起来等于零,这个是divergence freed的定义。

然后你就会发现这个东西其实跟上面这个东西是一样的对吧,就是这个是咱们是数学上的这个表达式叫做divergence free,为什么叫divergence free,就是说divergence等于零。

就是divergence等于divergence free,就是没有divergence,然后你会发现跟咱们前面说的这个直观上的这个理解就是净流出,净流入,净流出等于零的这个那个描述其实是等价的。

就是你会发现这个咱们这个微分的这个推导啊,跟我们前面这个直观的理解呢,就是刚好就是match了,所以说divergence free的这个东西就是就是我们数学上写成这样了,兰姆达u等于这个等于零。

这个东西呢你就可以直观地理解为净流入,净流出等于零啊,所以说我就可以保证体积是不发生改变的,它这个水是不可压的,是这么个意思,这个同学们这里理解吗,有没有什么问题,ok行。

然后还有一点我想说的就是我们等会儿要讨论的就是需要用到的,就是binian interpolation,嗯,就是做差值,这个大家这个大家有学过吗,这个101里面,我们在像素里面我们对像素的差值。

对图片做差值啊,有是吧,就是我反正这里反正也重复讲一下吧,那么假如说我想要得到非格子中心的这个对抗拒只会用到,就假如说我们得到想要得到非非像素中心,非格子中心的一个函数值,我怎么做呢。

我就利用这个bina做by ina interpolation,然后把它全都存在一起,然后求和,然后最后就可以得到这个差值啊,然后这是二维的情况,如果是三维的话,那就稍微复杂一点。

我要做trial and interpolation,其实是一个道理,就是不是一个方块了,它变成一个立方体了,不需要就是立方体做差距,但是实际上整个操作是一样的,这个是我们回头会用到的一个东西。

然后还有一个需要用到的需要考虑到,就是说如果说我们速度上他不是在中心点对吧,我们刚才讲了这个速度,它定义在这个墙上嘛,那如果说我要对速度做差值怎么办呢,其实是一样的道理。

只不过就是一假如假如说我这个i j对应的是左边的这个墙,那么我就把这个x减去0。5就行了对吧,就相当于就是把整个输入的这个坐标值啊,我给它偏移一下,偏移0。5,然后把这个值再拿来。

分别找到这个i跟j然后做差值就可以了,就是如果是x方向的,对这个u速度做差值,我要偏移对x偏移0。5,如果说对v方向的速度呢,我就要对y偏移0。5,其实是一个道理,分别对对它偏移0。5。

这个是对对这个速度差值所需要进行的一个特殊处理,好吧,然后这个基本上就是我们需要掌握的一些基础知识吧,因为呃如果说你学过这个很多这种啊数据计算啊,数据偏微分方程的话,这个其实都是一些基础知识啊。

如果说没有可能没有完全零基础的同学的话,这个相当于给大家介绍一下,因为咱们接下来会要用到这些东西,那接下来我们就看这个neequation到底是怎么一回事情。

那么levels coviation它其实是描述了速度场的一个函数,一个公式啊,他最后告诉你的是我的这个速度是怎么更新的,如果大家记得我们以前做这种各种各样的模拟对吧,我们模拟的时候我们会有两个东西。

两个变量分别是速度跟位置对吧,那对于流体而言,它就是速度跟状态,那么对于这两个变量,我其实都有相对应的更新函数,我会有一个函数,我会有一个公式去更新速度,我还有一个公式去更新位置顶点的位置对吧。

那么对于流体而言呢,他这个速度场的更新呢就是这个nest equation了,就是他这两个公式呢实际上就是讲我们的速度应该怎么更新,那它这里其实是不是一个公式啊,它是两个公式。

那这两个公式呢分别讲了什么呢,上面这个公式讲的是incompressibility,我们刚才前面讲的divergence,free condition。

这个东西其实就是说我这个速度长必须是divergence freed,他的divergence必须等于零,这样子的话我整个流体是不可压的啊,所以说他这速度首先应该满足这个条件。

其次呢速度的更新呢是满足于这个动量的这个函数的,他这个说意思就是什么意思,就是我这个速度的更新啊,它是由几部分构成的,水在有这个重力的情况下,它会掉下去,然后呢其次呢它有diffusion啊。

diffusion对应的就是粘滞,因为我们在真实世界里面,它这个水它跟物体运动一样,它会最终它会有一个阻尼嘛对吧,它会最终停滞下来,所以说一样的速度它会有一个diffusion。

这个diffusion本质上就是说我最后的速度,他应该会最终平均下来叫做年制,我们这里是diffusion,然后中间这个是advor,我等会儿会讲什么是ad,还有最后一个呢是一个内部压强的一个一个料。

所以说是由四个部分构成的,整个偏微分的系统是由四个部分构成的,那么怎么去解这么一个系统呢,那么这里我们会用到一个方法叫做method of characteristics,这个方法其实很简单。

他的意思就是说我有一个很长的这么一个偏微分方程,对不对,但是这个偏微方程它是分成好几个部分的,那么我去解这个偏分方程的时候呢,我就可以把它拆分为几个部分去分别的去处理,相当于一个微分方程拆成几个小块。

然后呢每一块呢我去解一下,每一块去解一下,我最后呢就得到了最终解,比如说呢我的假如说我当前的这个速度是you,我当前的这个速度场是u对吧,我去给他更新一下,更新之后的有了,这是我第一步。

然后第二步呢我是用这个第二项我去把这个又给他更新一下,那么得到的呢是前两个更新之后的优,然后第三步呢我用这个拉普拉斯diffusion就这一项啊去对它进行更新,然后最后呢我用这个压强去给它更新。

也就是说我本来呢是一个更新函数对吧,一个更新函数,但这个更新函数咱们看到了很复杂,所以说我可以把它分成四步,我就分别的每一步都对这个u更新一下,更新一下,更新一下,然后更新完了之后呢。

我得到的最终结果呢就是我下一个时刻的速度成,所以就是这么一个概念,就是虽然说我你看我整个公式很复杂,但是我把它拆开来之后,你就会发现其实每一个步骤其实都相对来说啊,没有那么复杂了。

虽然说还是以还是我们还是需要讨论的,但是相对来说没那么复杂了,所以说我们接下来就是把它拆成几部分,然后看每一部分我们怎么样这个速度进行更新,这个就是我们的一个求解的思路,pv分方程的思路。

这个更新起来其实比较简单了对吧,因为我知道速度嘛,我有速度,我有当前的速度,那么按照我们以前的做法,对不对,在这里,假如说我这个y方向是这个上下的方向的话,那么我对应的速度就是v对吧。

这个就是我的这个y方向上的速度,然后这里就得到了我的新的这个v啊,然后这里大家要注意就是我这里更新的时候,我需要对所有的v都更新了,我这里其实是有所有好多好多个这个绿颜色的这个v的速度的。

它对应的都是不同的位置上的这个v,我每一个点都需要对它进行更新,然后呢这里呢我把它叫做new,但事实上大家如果正常模拟的时候,就直接把这个原来的这个v的这个值它覆盖掉就可以了,对我们这个速度上的更新。

其实大家可以看到,其实很简单,直接把这个加上去就行了,同样如果说你对一个比如说你的容器里面啊有流体,然后呢你有一个呃或者是什么进行搅动啊,或者是比如说你有个电吹风对吧,这个电吹风在吹吹这个气。

然后呢你想要给这个一个外部的速度的话,其实一样的道理,你只要在某一某一个位置上对这个u v直接进行这个更新就可以了,一个东西,我们第一步完成了,我们把这个u给他变了,然后我们接下来看第二部。

第二步呢是这个,然后它这个公式是这个样子的啊,然后它这个定义我给我也给大家了,是这个样子的,是you乘以u对x的导数,加上b乘以v对x导数,这个公式呢也比较复杂啊。

然后呢呃大家可能想就是说这个东西其实也不是不可以解对吧,因为毕竟咱们怎么求一阶导数都知道了,我只要把这个东西算出来,我只要把这个东西给他啊,这里这里写错了,应该是y啊,我只要把这个东西算出来。

就是相对应的这一项,然后乘以一个负的deltt,然后加上去加到这个u上去,是不是就可以了,啊这里好像写错了,我看一下,这里可能有些问题,我回头再看一下吧,这个公式有点问题,就是这是一个方式。

就是利用咱们这个求导的方式来来计算的,但是呢这个方式它其实并不是一个特别好的方式,为什么,因为它有可能会造成不稳定性,然后呢我们后来就是很多人就考虑说怎么样让这个东西变得更稳定啊。

因为当你这个时间不长太大的时候,这个东西估算出来的后会不准嘛,对不对,一阶导数可能估算的不准,那么怎么样可以让它更合理一点,更稳定一点的,然后他就在想就是说这个东西到底是个什么东西。

这个其实也是在咱们刚才没有说的对吧,那是个什么东西呢,其实他的意思就是流动的意思,就是对流的意思,导流的意思,大家可以这么理解,就是假如说我这个水是在流动的,我从这个地方这么流过去了对吧。

那么在这个水流流动的过程中,这个速度它实际上是跟着这个水一起在动的,比如说之前上一个时刻,这个顶点的位置在这里,这个水在这里,假如说我有个小的水分子,它在这里是you,那么下一个时刻。

如果说这个小的水分子流到这里了,那么它这个速度是不是就被带到这里了,对不对,他这个速度就会被带到这里,所以说这个点上的速度,就应该由上一个时刻的这个水分子的原来的这个速度来提。

因为咱们的水分子会把这个水的速度给带过去,这个是由于水的流动性,流体的流动性所造成的,那么之前咱们在做这种拉格朗日的这个机,对于拉格朗日的这种模拟,就是换句话说,基于粒子模拟的时候,这个问题不存在。

为什么,因为我所有的速度啊,其他变量就直接定义在这个顶点上,我模拟的时候,我顶点的位置直接发生改变了,那么我自然的这些变量也就被带过去了,就说这个问题是不存在的,但是对于网格模拟这个问题就存在了。

为什么,因因为我这个速度我不是定义在这些水分子可以运动的水分子上的,我的速度是定义在这个绝对的固定的这个墙上的,这个水不管怎么流,这个墙它是不动的,那么换句话说。

我就需要考虑到由于水流的流动所带来的这个速度的变化,这就是所谓的所需要解决的问题,就是因为我这个墙没有动,因为这个墙没有动呢,而这个水在动呢,我就需要考虑到上一个时刻。

我这个水流应该对于这个时刻应该产生多少变化,大家明白这个的意思吗,我不知道我这里有没有解释清楚,就是因为这种欧拉的欧拉aria的这种表达方式,采用固定的这种长的固定位置的这种表达方式。

它所带来的没有办法这个流动性给他描述的问题,明白吗,那么想要解决这个问题怎么做呢,就是有一个思路叫做,seminar method,这个similar mesod的意思就是说我们根据刚才我们这个想法。

就是这个小的水分子从左边从这个x0 留到x一的时候,他会把这个速度从x0 带到x1 ,那么我的想法就是说,假如说这个我当前的这个是x0 ,我想要知道这个点上我的速度是多少,我只要倒推回去,对不对。

我只要倒推回去,我知道哪个水分子能流到这个,刚好留到这个墙上,那么我就用那个水分子的速度给它替换掉就得了,这就是倒推的一个思路,就是我现在想要得到这个墙上的速度啊,我倒推回去,我会看看之前哪一个水分子。

哪个老兄刚好流到这里,然后我给它速度替换掉,怎么做呢,首先x0 等于i减0。5g嘛,然后为什么减0。5,因为我用这个staggd嘛,我得刚好到墙上的这个位置对吧,然后呢我得到这个呃这个点上的速度。

利用这个当前的这个速度啊,得到的是ux 0,或或者不应该叫当前,应该叫上一帧啊,也要上一帧的速度是u x0 ,倒推回去,我得到了x1 ,根据这个咱们这个简单的这个线性的这个公式。

x0 减去掉的题为什么是减,因为我要倒推虚假的t ux 0,我得到了倒推回去,得到了这个这个点,然后呢我把这个点上的速度给它计算出来,算出来完了之后呢,我给他把它替换掉。

这就完成了我这个seminar lounge,这里的x是顶点的位置,是x是点的位置,然后他这里的思路其实就像我刚才说的那样,就是我想要知道哪一个小水分子啊,它刚好流到了这里,它刚好流到这里呢。

我就可以利用它的速度呢,把我现在的这个当前的速度给它替换掉就行了,那怎么找到这个小水分子呢,我利用这钱的速度呢,我给它倒退回去,我给他反向操作,我进行了一波反向操作嘛。

我给他找到之前的那个小水分子的那个位置,可以这个叫做semiconger method,然后如果说对于方向的速度,我也是同样操作对吧,我可以这里应该是v了,可以把这个v速度给它计算出来。

然后给它倒推回去,最终得到了这个v速度其实是一样的方式,一样的做法也是这个叫做sama lmaster,这个是完成了一次更新,然后这个更新方式呢你可以对它做细分。

因为这个更新方式它其实啊准确性是打折扣的,因为为什么,因为如果说你这个时间不长,deltt比较大的话,直接假设他这个线性的这种运动方式,它其实是不是那么准确的嘛对吧,你可以对它做细分。

可以分成几部分来做,这个你可以倒推的时候,你可以倒推几步,然后再给他分别的做,做的这个可以让你的这个呃ction更加准确一点,就是其实其实我这里写的也不太准啊,这个描述并不是特别准确准确的方法。

就是说你把dtt你可以认为是这样的,你把dtt分成几块对吧,你看变成第二台t除以,比如说除以四,然后你给这个利用这个方式呢,你对这个速度更新四次,更新四次,然后你就可以得到一个更新之后的结果。

我回头会把这个ppt再稍微修改一下,然后这个是这个叫做seminar langer,白色的问大家有什么问题啊,有没有什么问题,推的位置如果在边界,我想想一般的做法就是直接把它限定在边界,就是不越界。

就是我给他climb在边界上,但是确实会有这个问题,怎么计算每一个x的u啊,这个就是用我们前面讲的那个差值的方式来计算的,是用百零interpolation,四部的误差是多少,我还真不知道。

但一般来说你这个你的你的步长越小的误差会越小,可能也取决于你的这个时间不长的绝对值吧,这是塞米拉格朗日,它本身,但是它的误差不会导致不稳定性,因为很多时候我们做模拟最在乎的是稳定性。

而不是误差的绝对值大小啊,下面那刚刚叫的好处在于它比较稳定,它不会炸掉,说白了就是嗯它的误差,3米拉格朗者的误差一般来说就是会有模糊的artifact,因为大家可以这么想。

就是它其实每一步他每一步都会用到这个值嘛对吧,每一步做差值的时候,它其实你可以想他这个差值的过程就会取平均吗,差值本身就是在一个取平均的过程,如果你三倍拉格朗者,如果做的不准。

他这个差值的平均会越来越明显,最终它整个速度场就会糊掉,就是哪怕你不做任何的额diffusion,它这个也会导致这种artificial,有同学问差值用四个u算一个u对,就是差值就是用四个u算一个u。

就是我们原来的u,所有的u都是定义在墙上的吗,然后我这个x的这个u它可以是任e的位置吗,这个x可以任意位置嘛,所以说我要利用墙上的我定义的这个u来计算出这个ex的u来,它这个意思。

这就是这就是我们处理这个三倍like longer的这个方式,处理semi laner,完了之后呢,呃第三步,第三步相对来说就比较简单一点了,因为咱们前面啊讲了好多好久好久的拉普什么。

你会发现这个diffusion过程其实就是个拉plus,是关于速度的拉拉速度的拉普拉斯呢其实是由两部分构成的,分别是u的拉普拉斯跟v的拉普拉斯对吧,所以说分别对这个u跟v做一个拉拉就可以了。

然后就是拉普拉斯的这个给他算出来,然后前面乘一个deltt,就是时间不长,再乘以一个年质系数啊,这个其实deusion对应的就是粘滞,我前面拆一个粘滞系数就可以了,然后呢如果说这玩意儿比较大的话呢。

他也会不稳定,跟那个seminar on一样,它也会不稳定,所以说我可以用小步长来做,那小步长怎么做呢,就把它分成两块嘛,就是比如说我给它分成两步,两步做,我就带它除以二,然后先做一次。

算出这个you tap,然后再做一次得到最终结果,当然你也可以用更小更小的不长,这取决于你想分几次来做吧,啊还有一个是你可以利用饮食积分来做,就是之前也有一些paper做饮食积分。

但是我后来觉得我自己觉得没有必要,你搞搞这种饮食积分,你还不如直接分成几次小补偿啊,然后解决其实本质上也是一回事,情,也可以也可以做出类似的效果,然后最后最后一步咱们求解。

最后一步所需要做的就是嗯把这个加强对速度进行更新,对它进行更新呢就是我利用这个压强梯度,负的梯度,这里右方向的呢他他对这个梯度呢就是对x向上的导数。

那么压强在x方向的导数呢就是i j减去pi减1g然后除以h,然后呢v方向的导数呢方向的更新呢就是它减它除以这个好,这里这里还写错了,这里应该有个德尔塔t,这里应该有个det,这里是关于时间的积分啊。

所以说前面前面是要乘一个dtt的,就是比较,简单这个因为我因为呃因为我的压强是定义在压强,是定义在格子的中间的,那我刚好这个速度呢又定义在这个墙上,所以说我两个压强之间的差。

刚好就算出来在这个墙上的压强的一阶导数,然后我利用这个压强的一阶导数,根据gradient定义,我就可以对u v所更新就比较简单,但是呢同学可以注意到,就是咱们那没有讨论到什么是压强这个东西,对不对。

到底什么东西是压强,我们这个其实是没有说的,接下来的问题就是怎么样得到压强,压强是什么,尤其是这个流体内部的压强是什么,是什么原因造成压强的压强导致的原因其实是incompressibility。

不可压的,正因为流体是不可压缩的,所以说当你去有一端给流体一个压力的时候,他这个压力会传导到整个流体上,那么在每一点上都产生压强,而最终这是由于不可压导致的话说如果说这个流体是可压的。

你可以认为它是像棉花一样,可以随便随随便便拿捏的话,你这里捏一下的话,那么也就无所谓压强了,因为其他点完全不受干扰,不受影响,对不对,正因为它是不可压的,所以说会产生压强,那么换句话说呢。

加强的更新就是咱们做这个project的这个更新,会让我们满足我们这个约束条件,认为这个东西跟我们这个divergence free的这个条件啊,跟这个要求是,那换句话说我这个通过我压强更新完了之后。

我应该满足这个不可压的条件,由此呢根据我这个divergence free的定义呢,我知道这个uv这个东西等于这玩意儿嘛对吧,换句话说呢,我这个东西应该是这样子的,这个都是new,我这里其实都少了。

dt回头改一下,那这个东西变成了什么东西,实际上就变成了压强的一个一个方程组,我每一点都有一个压强,而这个压强是不不知道的,我不知道这个压强是多少,但是呢我根据我这个不可压的这个条件呢。

我可以构造一个方程组,把这个解出来,通过整理这个东西呢,我最终就得到了一个方程组啊,关于压强的方程组四pi减去这个周围邻居的,等于这个右边这个东西,当然了我压强也会有边界条件。

比如说呃如果是开放式的压强边界条件,dire帮助呢,我就认为外部是一个压强常数,就是close的压强就等于他自己,就比如说真实真真实的墙,你就可以认为压强是压强。

等于他自己就是nemburon dition,那我就去解这个信息系统吧,这个信息系统解完了之后呢,我就得到了我的这个压强,我再去更新这个速度,我这整个任务就完成了,就是这么基本上就是这么一个过程。

是求解,通过求解压强五让我更新之后的速度满足不可压,divergence free的条件,建的这么一个过程,然后这个过程呢我们通常也叫project projection,做压强投影。

就是利用压强对速度进行一个投影,让我投影之后的速度呢能够是不可压的,就这么一个意思,差不多就是这么一个意思,然后具体大家怎么构造这个拉普拉斯啊,就是通过这个东西来构造这个函数啊什么的。

反正大家啊可以再看看一下我们的这个课后的这个读物吧,但是反正大家可以注意到这个东西其实就是拉普拉斯嘛,大家有没有注意到这个其实就是关于抢到一个拉普拉斯,就是邻居减去他自己的,实际上就是压强的拉普拉斯。

所以说我们前面讲到的很多关于拉普拉斯的东西,其实在这里其实都是有复现了,又又又又又再次出现了,然后这篇paper嗯大家可以参考一下吧,是99年的一篇your stm的一篇叫做stable fits。

这篇paper主要讲的是关于seminar langer做的那个那个东西,但是呢他基本上也把整个就是做project projection这些东西,它其实也也讨论了一下。

啊这个就是关于never stocks,基本上就是关于never stokes的呃,一整个流程就是把整个方程才能拆分成四步,然后分别利用这四步对速度进行更新,最终完成了一个时间不长的一个更新啊。

大家注意到它这个东西是呃显示积分,本质上是显示积分嘛,因为流体一般来说影视积分做的比较少,很少做影视积分,基本上都是以显示积分为主的,然后我们刚才讨论的就是怎么样去对速度进行更新啊。

接下来我们讨论了对吧,因为光是更新速度没有用,咱们进行模拟的时候,速度没有办法直接拿来看嘛,我们真正想要看的是啊,比如说烟啊,比如说水的这种效果,对不对,那怎么样对淹水这种效果进行更新呢。

首先我们来讨论一下烟,比如说air空气模拟怎么样去对烟这种效果进行更新,烟的话一般来说是分成两部分的,每次更新我们都分成两部分,首先我们去把速度进行更新,把这个速度的这个又更新一下。

第二部分呢我们要更新它的物理量,比如说密度,比如说对于烟模拟而言,我就是一个密度,那那如果说是有颜色的烟,那么可能就是一个比如说一个不同不同不同channel的一个密度,同样我还可以更新温度对吧。

比如说我想要做一些火焰的燃烧模拟效果,那我可能要更新火焰的温的这个温度等等等等,我会更新这个这些表,那这些变量是通过什么更新呢,我可以利用seminar lounge更新,为什么,因为我们在做的时候。

本质上就是把这些变量从某从一个地方带到另一个地方的一个过程啊,这些变量其实跟速度一样,都是会被带着走的,所以说我要利用这个,我可以利用我们上就是前面我们讲的三my logger的这种方法。

利用这种小分子的这种模拟的方式,我也可以把这个密度跟啊速度跟温度跟速度一样,都是可以利用,这个主要的其实是一个套路,如果说咱们模拟一个环境啊,如果说你想要模拟一个比较开放的环境的话。

比如说我认为这个空间就是很大的话,那么你就用啊,你想模拟一个在一个封闭的一个环境里面的一个烟雾的效果,比如说我这是一个容器啊,我这个其实都一直在这个容器里面的话。

那么你就用newman把marcondition这个就是其实相当于烟来说就是比较简单了,或者是不是烟,比如说水下通过这个空间里面全部都是水,那么水下的这个模拟效果啊,我其实也是同样的方式。

没有什么本质的区别,水的模拟就会我为什么要单独拎出来讲,因为水跟或者是水下的环境会不一样,因为水这里有一个很严重的问题,就是它是有形状的,在模拟的时候,其实模拟的不只是水。

我其实模拟的是水跟空机器的表面对吧,当然我进行水的模拟的时候,我一般来说我不会同时去模拟空气,我一般来说不会同时模拟空气跟水一起,我一般只会模拟水,但是呢我需要考虑到拖它这个水。

它并不是把整个空间都占满了,它其其实只占了一部分空间,怎么样去模拟,怎么样去表达这个部分的空间的占用呢,水它就需要自己额外的一套表达方式了,有几种表达方式,比如说我可以利用体积的表达方式。

就是我把空间分成很多小格子嘛,每个小格子里面我存的是一个百分比,说50%,那么就意味着我这个里面50%的空间会被水占着,或者60%,那么60%的空间就被水占着,那这个方式叫做of fluid,叫做vf。

这种方式是比较早期的一种方式,大家可以看到它这个名字就很直观,就是说我利用这个格子里面存了多少水来表示,这个名字它虽然很直观,但是他这个方法有个小缺点,什么缺点就是它不精准。

说我告诉你这个格子里面有多少水,但是他并没有告诉说我这个水这个界面到底是什么样子的对吧,因为我很多时候我我做动画,我需要精确的知道说我这个水面到底是一个什么样的状态,没有办法得到这个的信息,换句话说呢。

我需要有一个相对来说比较精准的一个描述,那么还有一种比较常见的这种表达方式,就是用sign distant function,我们之前也讨论过,就是距离场,这种距离场呢就是说我每一个点存的呢。

它不是体积了,它存的是到这个表面的距离,这个格子呢存的呢就是到水面的距离,它把这个距离给它,存在这个格子的中间,我模拟的时候呢,我更新的呢就是这个到水面的距离,当水面波动的时候啊。

我这个距离也会发生改变,然后它也是sin的电方式,也就是说他这个值是有正负号的对吧,比如说表示是在外面负的呢,表示在水面水的里面,然后利用这个距离函数进行变形,然后怎么更新呢,呃有两种方式。

一种是seminar longer,就是跟咱们前面那种方式一样,这种呢就是level set method,然后大家可能我不知道大家有没有听说过这个level side method。

其实就是专门对这个距离函数更新的一种方法,然后这个方法呢叫做距离函数更新的方法叫做levels的mc,但不管说什么样的方法,其实我们在做水的模拟的时候,一般来说都会存在或多或少的问题。

什么问题呢是关于体积的问题,我在模拟过程中,其实体积啊它都会发生改变,改变一般来说我们在模拟有些东西的时候可能不会很明显,但是在你水的时候,如果说你这个水它的这个波动非常剧烈的话。

这个问题可能就会变得很严重了,比如说一杯水,你那只剩半杯了,那这个肯定就不合理,对不对,大家可能会看出破绽来说,你这个水怎么越来越少,越来越少了。

所以说lose以来都是就是我们做模拟里面比较关心的一个问题,就是怎么样避免volume loss或者是volume的变化,还有很多种方式方法了,就比如说有的是采用更加精细气的这种表达方式的。

比如说我加入额外的粒子,我利用粒子去矫正这个啊,这个这这个我们算出来的这个函数啊等等等等,还有各种各样的其他方法,但是我这里就不讲了,反正就是啊有各种矫正的方法,然后这一篇pa这这不是paper。

这是本书啊,叫做leveland methods and dynamic elies services,这个大家啊,我如果说大家呃是无心学,就是对渲染对对对模拟有啊进一步的要求就是需求对。

尤其是对流体这一块特别感兴趣的话,大家可以可以参考这本书啊,因为这本书我觉得写得特别好,它其实里面不光是介绍的leveson的方法,它里面也讲了一些比较经典的流体模拟的方法。

就是我个人觉得还是啊没有参考价值的,这是一本书,然后给咱们今天的课做一个总结吧,啊我们今天主要介绍的这种模拟的方法,是利用这种欧拉式的这种网格进行模拟的方法。

然后这种模拟方法它一个最大的好处就是和先求导对吧,然后我们这里利用的就是central differency求导的方式,这个让我们求导,算这种laua也好,就会变得很方便。

这个操作就变得相对来说比较容易,如果说对于速度的话啊,比较常见,比较建议的是一种staggered规的方法,就换句话说速度不是定义在格子的中间的,我们的速度是定义在墙上的,那这个好处在于。

我们就可以比较直观的理解这个速度是一个什么样的东西了,然后呢我们对于图形学里面,我们呢解的是这个低速的可不可压的这个risk的流体用来模拟水,用来模拟空气,气体都是采用这种模拟方式。

然后呢要解这个奈斯equation呢,我们用到的是method of characteristics,这种这种这种方法呢,它的本e呢就是说我把一个pd,我把一个pv分方程,我把它拆成几部分。

然后每一部分呢都分别对我这个速度进行更新,那么所有的更新完了之后呢,相当于也就是把整个更新结束了,然后如果说要模拟空气跟水,我们还需要额外的对这个力度啊。

或者是对这个呃这个水的这种这个距离厂进行更新对吧,然后对于水的话呢,就是会有volume loss的意思,就是水会变得越来越少,这个是需要解决的一个问题,然后还有一个我没有讨论没有说的问题。

就是说实际在实际图形学中,如果说你需要渲染,你需要把这个我这个模拟的这个数据给它导出来,而我们这个模拟数据它本身是一个体数据,它本身是定义在网格上的,对那怎么样把这个网格数据给它导出来呢。

你需要用一些额外的算法,比如说你需要用一个算法叫做marching cube,就是怎么样把这个提的这个数据给它倒到这个match上,这样子的话你可以生成三角网格,把这个水的这个表面用三角网格来替换掉。

你需要做这种额外的操作,烟的话,烟的模拟就会更复杂一点,烟的渲染会更复杂一点,因为烟你本身它没有一个明确的表面嘛,它本身是一个密度的厂了,你需要用用一些体渲染的一种一些一些一些方式啊。

在有些图形学上是既呃在一些硬件上是有这样的支持的啊,但是在游戏型上通常用的相对来说不是很多啊,用的这种体渲染的方式呃,相对来说会少一点,一般来说是用粒子渲染的方式更为主。

这个基本上就是体现这种grade的方式模拟所所存在的一些优缺点,然后还有一个我想说的是,咱们没有作业,但是呢呃我在知乎上放了一个那个一段代码,这个如果大家会matlab的话。

可以下这个matlab的代码,这个matlab代码基本上就是把咱们这个这节课啊,所用到的这些方法全部都给它实现了一遍,然后matlab本身比较功能比较强大,所以说那个代码也写的比较简单。

因为有很多这种操作,所以说大家可以去参考一下那个麦克雷的代码,然后跟那个跟这个咱们这个课上呢嗯讲的这些东西可以对应起来看啊,这个是我想说的,可以让我可以让回头让助教把他发群里吧。

然后今天咱们的想讨论的内容就到这里,同学们有什么问题,重建都自己做吗,有没有标准的库,但是反正我我自己以前是自己,我是自己做的,这个东西其实自己写代码也比较简单,虽然说有点工作量啊。

但是ming cube这个东西其实自己写还是挺简单的,大家有听说过这个方法吗,cube的意思就是一个cube,一个立方体对吧,然后每一个点上都有个函数值吗,你可以利用这个东西可以得到几个分段。

比如说我这个啊这个是正是负的,这个是正的,这个是正的,这个是正的,所以说我这个cube就会切成这么一个小三角形,它就会生成这个相对应的这么一个小三角形,0102上过是吗。

也会我觉得这个因为是一个比较标准的算法,可能也会有一些现成的库吧,嗯,以前我们以前是自己写的,可以做到matrix,可以啊,诶你们有没有注意到我给大家的那个作业。

就是啊高度场的那个作业就是matrix free,其实我不是要用那个康,用cg用那个共轭梯度法去解那个解一个一个一个方程吗,然后里面有一个矩阵乘法,但那个矩阵乘法就是matrix free。

raid的意思其实就是需要把这个矩阵真的写出来,你只需要解一个,你只要你只要写一个,写一个函数就可以了,然后这个函数只需要把需要把这个矩阵跟向量的乘法给他算出来,就可以了。

cg还有哪些可以做到matrix free,跟cg类似的方法都可以做到matrix free,比如说l b f g s,比如说gm 2应该也可以,因为cg主要是为了对对称矩阵求解嘛。

但是如果说矩阵如果是不对称的话,那么一般来说就是用gm r e s比较多了,跟烟的工作量算最大的了是吗,烟应该还好,烟应该工作量不是很大,然后水的工作量我觉得会大一点,因为水的水它比较复杂。

但你需要考虑到呃,你需要考虑到它这个边界的问题,然后水的边界它还有一个比较恶心的点,在于流体,比较恶心的点在于就是说你做完了之后,你会还会发现有瑕疵对吧,那你还需要解决这些瑕疵。

你就还需要再做一些额外的工作,不是说你直接做完就完事儿了,问你很多时候就是本身的整个模拟框架你可能比较简单,你只要复现一篇论文就行了,20年前的论文就行了,但是你为了解决一些瑕疵,你需要额外做很多工作。

插图怎么做的,论文的插图我一般是用我一般是用ppt做的,可以解吗,有有但有一些就是关于有限元的,就是把那个把流体用那种有限元的方式解的,但是呢有些语言它其实有一个有一些问题。

就是呃就是有些人它没有流动性,就是真实我们真实世界里的水它是可以任意形变的嘛,但是有电源,你没有办法任意形变,如果说你要形变的话,你就需要重新对有些对这个四面体网格进行构造,它这个成本就会很高。

所以后来说用有限元做的会比较少,说大家在处理一些比较小的场景,就比如说小水滴啊,是一些比较比较简单的一些呃水的这种效果的时候,就形变不是很大的时候,大家会用边界圆倒还不有限元的边界,圆的会有一些工作。

跟demo一般就是用渲染呗,视频一般就渲染了,一般用用vr或者是anno都可以,用玛雅一般都是用,我一般都是用玛雅渲染,这种商业软件做的已经很成熟了,完全可以使用,完全可以胜任。

你需要会你需要会调参数啊,就是嗯大家用过渲染引擎吗,大家可能都知道,就是会一回事,然后用得好又是一回事,有些圆不适用于大型片模拟,但是为什么作业里面可以所谓的大芯片模拟是那种永久性的大型变。

就是说你这个形变完了之后,他就不再回来的,就比如说像水啊,它的形变是没有记忆的嘛,所以说你任意形变这种情况下,你就不适用有限量,但是像作业里面,他这种实际上是有记忆的,就是虽然说你形变大。

但是他还是回去的,这边的话你可以你可以用有限元做,这里的形变不算特别大,像那种形变可能是更大的,医学里面说形变大,其实跟工程里面的还不是很一样,因为工程里面啊算大,对于图形学来说不算大。

对于工程里面算大的,其实哪怕是一点点都已经算是很大了,对是啊,昨夜形变大了会崩,那是因为作咱们作业只做了显示积分作业,没有做影视积分啊,影视积分就不会了,同参数换了模型,规则是参数不同,模型也需要调吗。

嗯看你模型的质量,因为有限元,如果你没有做饮食积分的话,其实哪怕你做了饮食积分,也非常依赖模型的质量,所谓的模型质量,就是说你这个里面这个四面体网格里面的四面体是不是比较规则。

是不是接近于正四面体啊的时候,你生成的四面体网格,它里面的四面体有可能是非常窄,非常记得像这种四面体,它如果模拟就会很容易炸啊,如果说你是比较接近于正四面体的,它就不容易炸。

所以说我们在构造四面体网格也是一门学问,就是怎么样去优化那个优化四面媒体的网格,让四面体网格质量尽量好一点,大家如果大家工程里面如果拥有一个库的话,一般都知道一般有tat jin。

还有net jam这种库啊,它会生成网格,但是你其实有的时候还是希望能够进一步额外优化一下的,我们今天就先到这里,然后我们下节课会讲那个。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

GAMES103-基于物理的计算机动画入门 - P12:Lecture 12 SPH and Position-Based Fluids - GAMES-Webinar - BV12Q4y1S73g

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们就开始吧,那个首先咱们现今天已经是最后一节课了,已经不知不觉已经已经过了12周了啊,不知道大家学了多少,也不算开心吧,反正就是嗯反正就是算是告一段落不做,然后那个然后这个最近也比较忙。

因为大家可能知道下周我们下周还有segraph deadline,下周四下周五,然后我们然后接下来又要过年,所以啊所以所以那个哦对说一下作业的事情,就是啊所以说我们的ta我们的t助教可能呃时间比较少。

所以说我们就想把那个咱们最后总评分,还有颁奖啊,还有奖品啊,这些东西可能放在年后了,嗯,然后大家这段时间如果说呃想想补一下作业,过年期间有时间可以补一下作业的话,其实也可以也可以提交作业啊。

只不过就是啊只不过可能就评不了奖了,但是我们到时候会从咱们那个鹅圈子那里,它会有一个小小的电子证书的,你可以拿到一个电子证书,就是啊表示你完成了咱们这个103的作业的成绩。

然后哦我完成了咱们这个103所有的作业啊,然后到时候啊也会把就是答案,就是我们这边的一个相当于完成了一个答案发给大家,然后大家呃可以拿来做参考,其实我其实我一开始在课前。

刚开始咱们刚开始课上课课的时候就说过,就是其实模拟这个东西嗯,他这个涉及的东西跟其他图形学不一样,因为它涉及的面非常广啊,有流体,还有我们一开始讲的一些弹性体啊这些东西啊,其实还有很多很多。

其实咱们这个碰撞没有很深入嘛,怎么碰撞处理,其实也是有很多工作的啊,其实我是觉得很多时候就是做模拟的人,其实大家看一些做模拟的一些工作,其实他们有一些组,他们可能就只是做流体或者只是做某一个方面。

很少有一个组,他呃什么方面都做的,早年的时候早几年的时候有这样的,但是现在这种情况越来越少了,基本上可能就是一些人大家都比较集中的在某在做某一个方面,嗯,主要也是因为问题会变得越来越复杂了。

我今天其实也是想把咱们今天把这个嗯就是流体这一块,相当于最后的一点东西给大家讨论一下,然后完了之后就是呃可能会有点时间,然后我们可以讨论一些就是嗯这个这个之外的东西,不管是学术圈也好,还是工业界也好。

还是比如说游戏啊,或者是影视啊,数字人啊什么的,其实大家有什么问题我们都可以讨论看一下行吧,然后我这个我这个ppt做的也比较仓促,因为嗯都没什么时间搞这个东西。

反正就是我是把我之前我以前之前上课的这个p p t相当于搬过来,然后稍微修改了一下,给大家讲一下,嗯,然后流体我们我们最早的时候讲了嘛,流体因为流体这个现象很复杂,所以说有各种各样模拟的方式。

那么今天咱们就讲一个跟我们上两节课讲了不一样的方式,因为我们上两节课讲的是所谓的欧拉方法对吧,就是把整个空间划分成一些格子,然后利用这个空间里面的格子的里面的物理变量进行模拟啊。

然后呢这个格子本身是不运动的,不管是我们这个高度场的格子也好,还是真的是把整个三维空间划分成三维的这种网格也好,它这个格子是不动的啊,然后呢我们是通过改变那个格子里面存的那些值来进行动画的模拟。

那今天我们讲的这种模拟呢,就更像我们呃这个课前面部分所讨论的那种模拟方式,这个就是拉格朗日的这种视角上的模拟方式,就是利用粒子的方式来进行物理模拟了,那利用粒子来进行流体模拟,它其实嗯有很多种变形啊。

最早的这种最传统的这种方式,就是我们今天所要讨论的这种叫做s p h的方式啊,但是呢这个s p h也有很多很多各种各样的变形,比如说大家可能听说过。

就是利用啊利用这种position base的这种约束进行模拟的,叫做projected project fruit啊,然后还有一种还有这种,就是把这种p h这种方式跟呃弹性体的那种相结合来进行模拟的。

为什么这么做,主要的原因是因为我可以很方便的模拟东西,破碎这种效果叫做paradynamics啊,然后还有一种可能大家也听说过,就是把我们这种粒子的方式呢跟我们前面讲的这种网格的结合起来,就有的模拟的。

有的这种效果,我通过例子来做,然后有的这种比如说可压不可压求解的这种呢,我通过网格来做啊,这种叫做particle in cell。

或者是可能大家更常见的叫做material point method的m p m,这种方法就是基于粒子,它有很多很多各种各样乱七八糟的混合式的方法啊,但是咱们今天就不涉及了。

就今天咱们就是还是从最最这种传统的这种套路来跟大家讲一讲,然后大家如果以后有兴趣的话,可以去扩展看看其他的这种变形的这种粒子的模拟方法,然后这种力变形的这种模拟方法。

它主要的原因是因为它会比如说做一些模拟的效果,比如说大家可能知道啊,做血或者是做沙子的这种模拟效果,你可能要用这种m p m的方法啊,然后如果说比如说你想做一些什么也变形啊,形变啊。

破碎啊啊碎掉啊什么之类的,你可能考虑paradynamics等等等等,就是根据你具体的问题,你可能会采用一些不同的方法,但是咱们这里就不设计了,好吧嗯。

然后首先我们来讲一下这个s p h的这个模型是什么,就是什么叫做其实不叫s p h模型,应该叫做私募式的,就是光滑的平滑的模型,什么叫做一个smooth model。

然后基于这个smooth model呢,我可以怎么样进行流体的模拟,其实这个东西跟我们前面讲的欧拉其实是有一定的共同之处的,就是我们第一步就是想要搞一个模型,然后这个模型能够让我们来计算一些呃。

偏微分或者是一些微分的一些向量,然后我可以利用这些微分向量,我把它应用到流体的方程上去进行求解,基本上就是这么一个总的思路,那么首先我们来看一下这种smooth particle的模型啊。

什么叫做smooth particle的模型呃,首先我们的一个总的思路就是我们要用很多很多这种例子去表达流体,因为在现实生活中,我们的流体实际上是有很多水分子所构成的嘛。

那其实你可以理解为就是我一个例子相当于就是一个水分子对吧,呃然后如果说我有足够足够多的这么多的例子,那么我就可以啊,相当于在嗯通过计算机我可以去模拟现实生活中这个水的现象。

当然说我不可能真的就是去做到几百亿几千亿的这种规模,我肯定我的例子没有那么多,但是我可以把这个大概的趋势给他模拟出来,然后这个例子呢就跟我们之前做各种弹性体什么的一样,就是我每个例子它都有物理变量对吧。

然后这个物理变量就是附在这个例子上的,然后物理变量啊,当这个粒子在运动的时候呢,这些物理变量就也就跟着一起运动了,这个就是拉格朗日视角对吧,这个就跟奥拉视角不一样。

因为欧拉视角下他他的这个科他这个物理变量的位置是不动的,我们这边我们这里它这个每个例子都是可以运动的,那有什么物理变量呢,比如说位置速度啊,质量等等等等啊。

然后呢你如果说做这个呃这种粒子模拟的方法的话呢,你如果在图形学里的话,他其实会遇到一个比较现实的问题,他这个现实的问题就是说你这个表达方式是有很多例子构成的嘛对吧。

但是我通常我的这个我们我们的modern的这种gpu,它是没有办法去直接嗯,他没有办法直接去画这些那个例子的,他没有办法直接去渲染这些例子,那么你如果说没有办法直接渲染的话。

那我一般来说就是需要做一个转化,他需要把这些例子它转化成一个比如说一个三角网格,然后进行再进行一个离线的渲染,一般来说会需要这样子,这个主要是因为我们的现在的硬件呢,不支持这种以粒子的方式渲染所导致。

然后在游戏里面它一般来说讲究的就没有那么多了,因为他没有办法进行这个操作,所以说一般来说游戏里面他可能就直接把这个例子用一种,比如说带纹理的一种,比如说一种球或者一种啊方块来进行描述。

然后但是因为它带纹理,它的纹理会有一些透明贴图嘛,然后它就会看起来会比如说像一个喷泉,或者是像一个水瀑布什么的,一般来说它们就会用这种粒子的表达方式进行模拟,那么好我们首先来看一下呃。

假如说有这么一个场景啊,这个场景里面有好多好多例子对吧,然后每一个例子它都有呃所对应的物理变量,那我这里假设它这个物理变量叫做a啊,然后每个每个例子都有,然后这个物理变量它可以是矢量,也可以是标量。

比如说矢量就是常见的就是速度嘛,标量可以是压强,密度啊,温度啊等等等等,这个我们就反正就是都可以复制,那么我们这个所谓的smooth的模型是什么意思呢,这smoth的模型的意思就是说。

假如说我给我这个空间中某一个位置,比如说这个红颜色的这个位置,我想要知道我在这个位置上,我这个值应该是多少,那么实际上这个问题就变成了一个差值问题,对不对,就是说假如说我空间里面有这么多点这些例子。

每个例子你可以认为是一个连续的一个函数,在这个空间里面的一个采样,在这个位置上的一个采样的一个函数值,我这个函数值应该是多少,我想从周围的这些,一般来说就想周围的这些函数值上给它进行一个估计。

这个就是我想要做的事情,就是所谓的smooth的这么一个interpolation的一个操作,那么怎么做呢,一个简单的思路就是说我在一定范围内,我比如说我设一个半径,在这个半径下呃。

我以这个我这个想要得到的这个点的位置为圆球星,然后我在一定半径内,所有的在这个圆内,在这个球内的所有的例子,我给他求个平均值,是不是就可以对吧,那比如说像我这里就是一个求平均值的方式。

每一个点都有个尺码,我把所有的值加在一起,然后除以除以它们总的数量,就得到了这个我的这个差值,那这里的话你看他这里有总共七个嗯,粒子01234567123456,总共有七个,所以说这里的n就是七。

然后呢我把它全部加在一起,求平均值,那这个方式很简单,但是呢它有一个问题,他有什么问题呢,就是他其实没有考虑到分布对吧,他只是把所有的点加在一起,比如说我这里可以想象成这么一个场景。

假如说我有很多很多红颜色的点,假如说我这个差值的内容就是颜色,然后呢我有很多红颜色的点,大部分点都是红色的,但是有一个点是黄色的对吧,那么因为绝大多数的点是红色的,只有一个是黄色的,如果说我求平均值。

那么大概率我这个中心的这个点,我想要得到的这个差值的,插完以后的这个值应该还是红色的对吧,但是如果说因为种种原因,我在这边多采了几个例子,我这边有很多很多例子。

那么因为这个区域这个小的区域范围内是黄颜色的,所以说这些点也是黄颜色的,然后最后呢就会导致如果说我在进一步的差值的话,我会导致我这个就变成橙色的了,因为我这个黄颜色的点有点多,那么这个东西什么意思呢。

就说我这个取平均的这个方式啊,他其实并没有考虑到我这个例子的分布,因为虽然说我这里有好多好多黄颜色的,但是这些黄颜色它基本上就是在一个很小的区域,对不对。

如果说我认为每一个点它都在空间中占了一定的区域的话,那么黄颜色的区域显然是比较小的,而红颜色占有的这个区域显然是比较大的,那么照理说我虽然说我黄颜色的点多,但是它占的区域小。

那么其实它的贡献应该也小才对,那么我照理说我这个估评估出来的这个差值,照理说应该还是比较倾向于红颜色的,我不应该只是单纯的考虑数量,我还要考虑到他们占了多少的空间。

所以说第二个模型就是我要把它每一个点所占的空间给它考虑进去,那么这里我们就假设说每一个点,每一个例子它都不只是有他这个一个物理的值,同时呢它还有一个另一个值,它表示它所占的体积是多少。

这个呢v呢就是表示它的体积,就是说在这个空间这个区域内,它占了多少体积,然后我们把这个v呢作为一个权重加上去,那么就得到了这个第二个模型,那么这个v呢你就可以认为是他的一个权重对吧。

把它存在这个a的上面,然后把它全部加在一起,然后这里呢an呢是它的这个总和,这里呢我其实就我其实做了一个假设的,我假设这个球的是个单位球,所以说单位总的这个球的体积是一,所以说啊所以说我直接就是这样子。

我直接就出个a就完事了,那么这个模型呢比刚才那个好,因为我考虑到了呃,我每一个例子它所占的体积是多少,我不是说单纯的嗯把那个嗯就是把这个球平均值了,我我加了他的体积,但是呢还有问题。

还有一个问题是什么呢,就是我这个函数它其实并不够斯慕斯,什么叫斯慕斯,smooth的意思就是当我这个点我想要得到的这个差值的这个位置,发生运动的时候,我不希望我出来的结果会很剧烈的变化,对不对。

我希望它是一个比较连续的变化的一个函数,它是连续的慢慢的变的,但是如果说我用我们这套原来的这个差值的这个方式,它显然不存在这样的现象,为什么,因为我这里其实是非常依赖于我这些求里面的点数的。

如果说我这个这个位置发生改变了,那么有可能我会突然的增加我的粒子数或者减少我的粒子数,比如深深像这里,当我这个点从红颜色的这个位置走到这个绿颜色的这个位置的时候呢,我会突然的多了两个例子对吧。

我原来是1234567,本来是七个例子,在这个红颜色的球里面,但是如果说我运动到绿颜色的呢,那么我就多了两个例子,我变成九个例子了,那我如果说再去算这个总的这个和我一下子这个和就变掉了,对不对。

我这个值就变掉了,我这个就瞬间就发生改变了,这个是我不希望的,其实我明明这个位置只是动了一丁点儿,为什么我的这只会发生那么大的变化呢,这个不合理对不对。

这就是为什么我们想要的这个是一个smooth的一个差值的一个过程,它不是一个简单的差值过程,我还希望它是一个能够mooth的差值的过程,我希望它这是一个连续的变化,那么怎么样可以让我这个差值的方式嗯。

smooth呢,那么一个思路是什么呢,就是我还要再去额外的加一个权重,我对于我每个例子我还要去加一个权重,光是有这个体积的权重不够,什么样的权重呢,我其实要把距离考虑进去。

要把这个例子到球心的距离考虑进去,原则上如果说这个例子离这个球星很远对吧,他是在边界上的,他在这个球的边缘,像比如说像我们新来的这两个新来的这两个老兄对吧,他新来的吧,所以说他在边上嘛。

那么理论上我就应该给他的权重要低一点,这样子的话呢,他对总的这个和的贡献就要小一点,那如果说要有的例子,比如说这个例子它很靠近圆球星嘛,那他的贡献就应该照理说应该大一点。

所以说我们这个思路就是再额外的引入一个一个东西,我把它叫做w,这个w是什么呢,w实际上告诉我们的就是一个权重,这个权重是对于每一个粒子到球星的一个权重。

所以说我这里把它叫做w i j就是i和j之间的这么一个关系,就是最后我们给这个g这个例子的一个权重,然后呢这个权重具体的名字叫做smoothing kernel,它是一个kernel函数啊。

然后它就满足呃两个特性,就是我刚才说的,就是如果说距离大,那么它就权重就小,如果说距离小,那么全程就大,所以说我就根据这个进行调整,那么有了这个克隆函数呢,嗯再乘以这个体积呢,再乘以这个物理变量呢。

我就可以得到最终的这么一个表达式了,就是我这个最终的这么一个差值的smooth的一个放心了,那么这个问题解决了吗,好像并没有,对不对,因为我们前面是假设我们有这个k头函数,有这个体积。

ko函数可能比较好搞一点,因为它其实就是一个函数嘛,但是体积这个东西你怎么去搞,因为体积它其实如果说我用例子去做一个表达一个,比如说流体的话,它体积这个东西它其实并不是一个常数啊。

因为它这个流体它这个例子它始终在运动,对不对,他这个分布它有的时候会命,有的会会输,他一直是在运动的过程中,我照理说我不应该用这个一个常数去定义它这个体积,对不对,我应该去动态的计算这个体积。

那我怎么去计算这个体积,那我们去这么一个计算,首先我假设我每一个粒子都有一个质量,我把它叫做i,然后呢我假设我有一个密度叫做density,叫做热爱对吧,然后我们都知道的这个质量它是一个常数,一个例子。

如果说它就是一个真正的一个小水分子的话,它质量肯定是个常数嘛对吧,那么真正的变量是什么呢,真正的变量是体积跟密度这两个东西会发生改变,那这里大家要注意了啊,就是我这里的密度实际上是粒子分布的密度。

它并不是我们所说的水的密度,因为水的密度大家都知道是个常数,但是这里呢我这个肉呢是每个粒子在空间中,它周围的其他例子给它的产生的一个密度的一个值,相当于呃是描述在这个一定范围内。

这些粒子它分布的密度是高还是低,是这么一个密度,那么我们知道假如说我把这个密度认为是也是一个smooth的函数的话,比如说我这个点啊,这个点i我认为它是一个例子。

同时我也认为这个i它是一个我们想要差值的对象,那么我们差值的目标是什么呢,差值的目标就是这个密度,我认为这个i这个例子我们想要差值它的密度,那么它的密度是什么呢,它的密度根据我们前面的那个公式。

就是vj乘以zj乘以克隆函数吧,那这个g是它所有的周围的邻居,对吧,就是按照我们前面这个smooth的定义,应该是这样子的对吧,那么这个就可以让我们得到什么,你可以注意到前面这个部分是v j乘以rj。

那么就等于质量,那么换句话说,我可以通过这个东西把密度给它计算出来,可以利用咱们这个差值的这种私募斯的公式,我可以把密度给它估算出来,因为密度不是我们所定义的一个一成不变的物理量。

我是通过这个私募斯的这个定义,我给它反向的给它搞出来的,那么这个直观上你怎么去理解这个东西啊,你其实可以这么理解,你如果是观察这个东西的话,其实如果说你不考虑这个坑头函数的话。

你暂时把这个坑头函数忽略掉的话,它这个东西是什么,它这个东西就是所有的质量的和,对不对,那什么是质量的,和你去想一想,对于这个particle而言,对于这个例子而言。

它周围所有的粒子的质量和其实就是它的密度,直观上就是我周围的邻居如果都有好多好多,我有好多好多邻居,然后这些好多好多邻居都带了好多好多质量,那我肯定就密度大嘛,对不对,搞得我周围都很挤嘛,很拥挤。

所以我密度大,如果我说我周围没有什么粒子,或者说我周围的粒子密度都很小,质量都很小,那么也就意味着我这个空间就很自由嘛,那我相对应的我这个密度也就小,所以说其实它这个直观上就是这么一个意思。

就是我利用周围的粒子的密度,然后他乘上这个可能函数的权重,我就可以把这个密度给它估算出来了,然后有了密度之后呢,我这个后面的就比较简单了,因为我就可以直接套公式对吧,v j v i就是等于。

而质量除以这个东西,然后就是可以得到它的这个体积了,然后有了这个体积公式呢,我在可以带回到咱们前面的那个公式里面,就是这个东西是我们对于任意一个物理变量,注意这里是任意一个物理变量。

对于任意一个物理变量的话,那么我这个体积是这个东西,就是我们刚才估算的这个东西,那我把他带到这个vj里去,我就得到了我最终的这么一个差值方式,当然实际在你你实际上在计算的过程中。

你可以嗯就是不要把它合并,你可以把它分成两步来做,你首先你把每一个粒子的体积给它进行这么一个估算,利用这个质量分布进行一个估算,嗯然后利用质量分布估算体积,完完事了之后呢。

你在利用咱们前面的这个公式给他,把这个所有的物理量可以给它做一个差值,差不多就是分成两部分来做呃,然后我们我们接下来再来看一下这个克隆函数是什么样子的啊,先先不说克隆函数吧。

就是先说我们我们这么做的好处是什么,我们这么做的一个好处在于我们进行一些各种各样的这种微分啊,这种操作,微分算子的操作就变得很容易了,比如说我想要求梯度对吧,如果说我想要求梯度。

那么如果说我要在这里加个梯度符号的话,会发现你最后就只需要在这个后面这个克隆上加梯度就行了,因为你可以认为这个物理变量它对于在这个例子上,它的物理变量是一个常数。

同时你也认为他这个周围分布的这个体积也是一个常数,如果说他这两个都认为是常数的话,那么最终这个微分算子就会,这个规定就会被施加到这个后面的这个ko上去。

而这个kernel呢它是一个我们已知的一个有解析解的这么一个函数,所以说我直接就可以把这个东西写出来,它会有解析解,它会直接有公式可以套。

这就是它这个p h这种smooth interpolation模型的好处,就是它算梯度的时候啊,你可以直接套公式,你可以直接的认为就是说实际上就是你算梯度的时候,你直接把后面这个东西给它替换掉就行了。

你就用另一个函数,用kernel的gradient的函数作为他这个差值的一个权重就可以了,对有同学问体积为什么认为是常数,它其实这里是其实是做了一个近似的,就是它其实是假设我这个点运动的时候。

它不影响到周围邻居的体积,因为这个g它其实是周围邻居嘛对吧,我这个i算的是我想要得到i这个点上的梯度,这个g呢又是周围邻居,照理说我爱动了,我会影响到周围邻居。

但是我就是认为说我对他的邻居的影响会比较小,所以说我这里就假设我我自己在动的时候,我邻居的这个体积不变,那么我就可以认为邻居体积不变,所以说最终变的就是后面这个东西,它是这么一个思路。

然后同样的我也可以计算laution,laution就是它的二阶导的那个东西嘛,可以最终也可以计算拉普拉升,如果说对一个物理变量做拉普拉的话,那个拉拉最终就会施加到后面的那个w上去。

然后给大家看几个w的的定义吧,就是比较常见的,就比如说啊比如说这个是一种是如果说嗯i你认为i跟这是两个例子,比如说i跟这是两个例子啊,这是一个两个例子,然后这个是x这是x j。

那么你可以先把这个q给他算出来,这个q就是距离除以一个呃一个一个一个某一个单位的一个长度,这个h它叫smoothing lance,它实际上就是个单位长度。

相当于他对这个长度进行一个单位长度的一个normalization,然后完了之后呢,他得到这个q之后呢,他把这个带到这个公式里面,然后就可以计算出一个smoothing kl来了,这个是一种啊。

其实他这个smoko其实有好多种,但是我翻了一下一些paper,然后似乎这个是比较常见的一种,然后这个函数也比较简单,它基本上就是一个多项式函数嘛,它是个三阶函数,所以说它求导也比较简单。

然后它这个函数的样子大概是这个样子的,中间就是我们想要插值的那个点的位置,然后这些黑点你就可以认为是周围的邻居,然后你可以看到它这个就是越靠越靠这个这个边缘,他这个权重就越低,然后越靠中心权重就越大。

就有点像高斯函数,但是他用的不是那种啊指数的那种函数值,它用的是这种多项式的这种函数值,然后这里就是呃就是一些公式呗,就是就是求导嘛,比如说一阶导啊,然后一阶导就是这样子,然后这个这个基本上就是正常的。

我们求导的过程,如果大家自己去推一下的话,会发现其实也是比较简单的,比如说这个地方如果你对q你对q求一阶导,那么你得到的就是啊就是这个东西,然后后面的也是这样的,它是分段函数。

连接体积在dt时间内估算是不变的吗,你可以这么认为,就是他那个呃,就是他他那个连接的那个体积变化量很小,所以说他就直接把它忽略掉,然后这里我就跳过了吧,因为这个这个公司反正很多这个文献上都有。

大家可以参考一下,然后这个是拉拉,如果说你要对这个w这个函数求拉拉的话,它是这么一个东西,然后然后这个d w d q的二阶导,二阶导就是二阶导的这个东西,啊然后反正这个也是多项式函数嘛。

多项这个多项式函数的好处就是在于它求导,它求起导来比较容易,就是它的最大的优点,这也是为什么,而且它计算也很容易,就是做一些乘法就可以了,所以说这也是为什么大家喜欢。

一般来说喜欢用这种多项式函数来定义这个看懂函数的一个原因吧,那么好基本上啊反正就是这个是比较标准的,而且大家而且大家如果说自己要啊,这里写错了,这里应该是应该是正三角,如果说大家要做这个。

那实现这个代码的话,基本上就是套这个公式就行了啊,没必要自己去推这些东西啊,反正就是都是有现成的这种公式函数值给你的,你反正就是根据它这个东西套就行了,需要记住的就是需要记住的。

就是这里就是呃就是利用咱们smoothing这个interpolation的方式啊,你可以去很方便的把这个一阶导和二阶导,可以给他用这个方式给它计算出来,其实本质你可以认为它这个东西是一个函数。

比如说你可以认为是一个一个k i j这么一个新的函数的话,它其实就相当于就是用这个新的这个差值函数来给你做这个计算,然后我们来讲一下流体,就是这个东西怎么搞,在流体上。

尤其是可以大家可以跟前面咱们之前讲的这种模拟,各种各样的那种粒子的这种模拟方式,可以大家可以对应起来看,其实是有很大的相似之处的,就我们做流体的话,我们对于这种流体的例子呢。

就是要考虑到主要就是考虑这三个因素嘛,不限于这三个因素,但主要这三个因素,首先是重力,其次是压强,最后是年制,就是这三个方面,然后重力大家都比较清楚对吧,相当于是个力吗,我可以把这个重力的力给他算出来。

这个大家都清楚,那么接下来我们讲压强就重力,重力咱们就跳过了是吧,也不算跳过吧,就是应该大家都清楚,然后接下来我们讲压强,压强如果说在一个粒子,它在流体里面,它在一个水里面的话,或者是空气里面的话。

压强会对它产生一个力,那么压强的这个力它本质是个什么东西呢,它首先我们考虑到就是首先我们要把它分成两部分,首先怎么计算压强,第二我们怎么样把产生计算出来的压强转化成力,这是我们想要做的。

首先压强我们知道压强其实跟密度是有关系的,对不对,在真实世界里面密度越大,那么压强这个压力也就越大,密度越小,压力也就越小,所以说它跟这个密度的分布是肯定是有关系的,所以说我们首先把密度计算一下。

这个计算其实是我们怎么都需要的,因为我们前面在做体积计算的时候,我们本身就需要计算到这个密度了,然后我们前面也讨论了密度的计算,其实本质上就是把周围邻居的这些所有的粒子的质量加在一起,求一个加权的平均。

这个就是密度,那么有了密度之后呢,一般来说就是利用什么经验公式,我可以对它进行一个压强的转化了,那么经验公式呢也有很多种,这是其中一种就是一个七次函数,我其实也不知道为什么是七次函数。

反正这个是我从一个论文里面给抠出来的啊,他们采用的方式就是利用这么一个七次的这么一个函数,它把压强,他把他把密度转化成了压强这么一个压强值,大概是这么一个东西,然后呢这个constant,还有这个。

啊这个roll constant,还有这个k呢都是常数,然后利用这个公式给它进行一个转化,那么好,我们可以把每一个粒子的压强给他算出来,那么第二个问题就是说有了压强之后,怎么计算压强产生的力了。

那么我们想假如说想象这么一个场景,如果说我周围我有个例子,然后周围全是高压,周围的例子全都是带高压的对吧,你可以想象成一个压力锅,然后这个压力锅里面有一个小的水分子,战战兢兢的小水分子。

那么这个小的水分子会不会有运动,其实它不会有运动,对不对,为什么,因为你可以想象的就是说这些高压的这些邻居啊,都会给这个例子一个例,比如说这个它给它一个力,这个也给他一个例,这个也给他一个力。

这也给他一个力,这个也给他一个理,然后这些力它其实都最终会相互抵消掉,对不对,因为这些力它每一个面上每一个方向它都是高压,那么等于大家都没有高压,大家的利益都是一样的,最终都抵消掉了。

那么压力真正产生的原因是什么呢,是因为压力的不平衡所导致的,比如说我左边是高压对吧,然后右边是低压,那么也就意味着我只在左边,我会有粒子会推这个这些这个压力会推这个例子,而在右边它是没有这个力的。

那么所以说最终我会产生一个总的力,把这个例子往右边去推,就跟大家比如说猛地一下把压力给我打开一样,你猛地一下把压力给我打开,突然压力锅里面的高压碰到了外面的低压,那么这种压力差就会导致。

里面的容器里面的这个水被喷出来对吧,所以说本质上是由于压力的不平衡,压力差导致的压力,而不是单压压力,而不是单纯的因为压压强的高或者是低,所以数学上数学上我们把压力写成这个形式,是负的体积。

我首先要对压力成一个体积,压强的那个规定成一个体积啊,因为体积越大,压力越受到的压力也越大,体积代表着这个水分子在空间占有的面积的的的体积嘛,所以说我希望对它做一个权重。

其次呢是它的压强的gradient,那么什么是压强的规定,压强的gradient其实就是压强的差,gradient实际上代表的就是一阶导数,对不对,那么一阶导数是什么东西呢。

一阶导数实际上就是它的梯度嘛,就是它的这个它的这个差别,所以说我这里gradient实际上就是可以转化成零,那么这里呢大家注意到就是我这里用smooth来加这个东西,为什么我加了这个mooth呢。

是因为我加了这个私募词之后,我就可以利用咱们之前gradient计算的方式呢,我可以对它进行一个进四了,那么首先我假设压强这个东西呢是一个smooth差值得到的一个函数。

那么p i smooth就是周围邻居的压强的这个smooth差值的和,那么我把这个梯度加上去之后,那么我梯度就加在了后面,那么我就可以利用压周围邻居的压强乘以体积,然后再乘以这个kernel的梯度。

然后我就可以把压力给它计算出来,这个就是我压力计算的一个公式,而且大家可以从这个例子上就可以看到啊,为什么我们要做这个smooth interpolation。

为什么我们前面讲了半天这个smooth interpolation,原因就是因为我可以利用这个东西来计算啊,计算梯度,很方便的,把这个梯度给它计算出来,那么好,我们现在有了压力。

那么接下来我们再讲第三个理,对其实有同学说这是一个压强场嘛,对实际上就是你可以认为每一个例子它其实就是代表了一个采样,然后它整个我可以假设这整个空间是一个厂,它有个压强场,所以说我我做这样的假设之后。

然后viscosity其实跟单品有点像,但是跟单品又不一样,因为我们正常理解的单品是什么,单品就是会是一个阻尼对吧,当一个物体在运动的时候,会有一个无形的一个这么一个东西,会想让它尽量的停止下来啊。

尽量的让他把这个能量从动能转化成热能,那么年制这个东西呢跟单品很像,但是呢又跟单品不一样的点在哪里呢,在于他不希望把这个每一个粒子的运动给它停下来,他希望的是什么,他希望的是我们所有的例子。

大家都一起动,都整齐划一的一起动一起运动,比如说我这里给大家看了我这里的所有的例子对吧,每个例子都有自己的运动方式对吧,有的往左,有的往右,那我年制最终想要产生的效果是什么呢。

就是大家都一股脑儿的一起往一个方向运动,这个是我年制想要达到的最终效果,单品呢它是想要最终都变成零,而这年制呢他希望的是都是朝一个方向躲,那么怎么来做这个年纪呢,其实大家可以这么想。

就是粘滞最终的目的就是想要让这些速度之间的差趋向于零,那么数学上我们就用拉拉来定义,因为我们前面也讲过,就是拉拉是什么,拉拉实际上就是在计算每一个点跟周围邻居的差别吗,对不对,我们之前讲了。

有拉拉可以做各种各样smoothing啊,这种操作嘛,那smoothing本质是什么,smoothing的本质就是我希望所有的都一样,这种就是一个很私慕斯的状态。

所以说一个道理就是我想要去smooth我的速度,但本质上斯慕斯速度所产生的效果就是粘滞所产生的效果,那么我这里就可以构造一个力,这个就是我的这个年制的啊产生的力,那么我的粘滞力等于负的一个年制系数。

再乘以质量,再乘以速度的laua,然后我这里速度呢我也假设是一个有个速度的厂,我有个速度场对吧,然后每一个粒子都表示了这个速度长的长里面的一个采样,然后呢我想要计算它的laua呢。

我就可以利用我这个smooth的速度场的这么一个定义,我给大家最终转化成这么一个形式,然后就是就这么个形式,然后注意到大家注意到就是说你这个速度它其实是一个矢量,对不对,速度是一个矢量。

所以说这里实际上是由三个速度所构成的,u v w的三个速度分别是x y z方向的三个速度所构成的,所以说你这里需要做三次,然后拉plus它其实是一个标量。

这个后面这个kernel w的这个kernel的这个拉普拉a它是一个标量,所以说最终他们的标量它的这个维度是吻合的,因为它最终得到的还是一个三维空间的向量,这是他的这个力,然后有了这个东西之后呢。

我们这个算法其实就比较简单了,其实跟我们前面所做的各种各样的粒子模拟的啊,算法基本上是一样的,就首先对于每一个例子啊,我首先计算它周围的邻居,我知道我想要把每一个点周围有哪些邻居给他算出来。

然后利用邻居,我可以把首先我把重力加在这个立场,其次我把压强压力给它加在这个地上,利用前面的公式,然后把粘滞加在这个立场,然后最后呢我就可以对利用我这个力除以质量,我就可以对速度进行更新。

然后我利用我更新完了速度,我对顶点的位置进行更新,然后基本上就是这么一回事,然后我这里呢其实我们这里并没有讲流体力学是一个什么样的形式啊,为什么,因为流体力学。

其实如果说你以这种拉格朗日的这种视角来进行计算的话,它其实牛顿的流体力学它就是可以把它拆分为这么几三大块的啊,然后三大块呢分别就是对应咱们一利用s p h所进行计算的,这三种方式。

所以说基本上就是基本上就是这个这三个东西,然后我们这里其实就跟上节课稍微做了一些简化,就是咱们就不再回到这个流体力学方程去讨论流体力学方程了,我们直接就是啊把这个模拟动画的这个流程给大家。

我们描述一下啊,当然大家如果说对数学这一块比较感兴趣的话,大家也其实可以回过去看论文,看看他们到底是怎么从数学定义出发,然后又一步一步地推到这个呃,就是这个模拟的这个三个力的这个模型上去。

这个反正咱们就不讲,然后做这个模拟的话,他的这个挑战在于什么,其实他这个挑战其实有很多方面,其中有一个是计算上的性能上的方面,他这个性能的方面在于你的计算,neighborhood会是一个挑战。

因为我们在模拟流体的时候,如果说你想要一个比较逼真的效果的话,那那么你可能需要非常非常多的点,你可能要100万甚至好几百万个粒子规模,你才可以把这个水做的稍微比较像模像样一点。

如果说你只是做个几万规模或者是几10万规模的话,你其实你的瑕疵,因为它粒子它这个分布所产生的瑕疵会比较明显的,而我们上节课讲的这种volume的方式,它其实相对来说就会好很多。

你比如说你64x64x64的网格,你这是模拟,其实也挺像的,其实也像模像样的了,但是例子不一样,例子的话如果说你模拟的粒子的数量不够的话,其实就就很不像啊,除非说你是做一些比较简单的场景,比如说瀑布啊。

喷泉啊什么的那种场景器,其实可以就比较简单的可以做了,但是像比如说你想做一个比如说水荡漾啊,然后波浪啊,水浪啊,浪花啊,然后很大的波浪,这种效果的话,你肯定就是要上百万的点,那你上百万的点。

你计算每一个点去计算它周围邻居就会有花计算量,那么穷举显然是不行的对吧,因为穷举你如果是几百万的话,比如说11千万,那么就是呃100淬炼淬炼多少,我都不知道,反正就是很多很多个零吧。

就是你需要找很多很多检测,很多很多穷举肯定是不行的,所以说一般来说我们在计算中,我们也会用到很多这种类似碰撞处理,或者是类似你做光线追踪所会用到的一些方法,比如说在gpu上。

我们一般用到比较多的就是做spatial peditioning对吧,就是把空间进行划分嘛,分成很多格子,然后呢把每一个粒子都存到一个特定的格子里去,然后呢完了之后呢。

我可以就是说我可以根据每一个点所在的格子与它周边的格子,我可以很快的检测,我可以找到说每一个点它周围的呃,有哪些邻居是啊需要检测的,然后呢还有很多其他方法,比如说可以做otree。

做binary tree,这个主要是面向一些不均匀分布的粒子所导致的,然后为什么会做不均匀分布,有同学可能会问,为什么我要不均匀分布,为什么我不可以把所有的例子都搞成一模一样大。

其实有的时候他是会专门为了做某些细节,比如说其实大家可以这么想,就是如果说我想要做一个水花溅起来的效果,对不对,那么你做水花溅起来的效果,那么理论上就是靠近水面的地方,你需要的例子会小一点。

你靠近水水的这个整体的地方,就是水下的地方你可能想要的粒子会大一点,因为那种水下的地方它其实没有什么细节,他都在水里嘛,你这个水其实怎么流动,其实你也看不出差别来,是水面,因为它有浪,它有这个边界。

它有甚至有泡沫,那么他这种这种这种细节就会比较多,所以说你希望在不同的地方,你用不同大小的这些例子啊,这种也是一种模拟方式,叫做adaptive,adaptive的方式啊,这个好像以前也有做。

也有做过这方面的工作的,但是反正啊这种这种像我前面说的,就是做流体的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

就有各种各样形式的东西,啊然后还有一点就是说你需要做这个三维重建,你需要从这个点云里面,从这些点你其实可以认为是个点云嘛,啊做几何的,一般来说把这个叫点云,你需要从这个点云里面把这个三角面片给它搞出来。

这样子才可以做渲染,这个也是也是一个比较复杂的问题,因为为什么复杂,因为如果说你做的比较简单的话,你这个表面就会坑坑洼洼的,一般来说呢你需要对这个坑坑洼洼的表面再做一个平滑。

你想要把这些坑坑洼洼的东西给它抹掉,但是你在抹掉这些坑坑洼洼的同时,也有可能会把一些你想要的细节给它抹掉,所以说你怎么样去进行这个表面的平滑,一般来说呃也不是一般来说吧。

就我见过就是他们所谓的叫做bias的kernel,就是他在平滑这个过程中,他是有方向性的,它是尽量在某一个方向上,就是在平的这个方向上平滑,而在重的方向上尽量不平滑,类似这种点云的话,点云是三维重建。

做几何吗,好像我们之前是不是也有一个102的课,是102102的课吗,就是做几何里面一般会有会讨论这个东西的,203是吗,对,重叠,然后有有一些简单的方法,就是我我知道的一些可能讲的稍微简单一点的方法。

就是先把这些点都变成一个distance function,每一个点上你可以认为是个球,对不对,然后你把这个球的这个distance function,sign distance function。

这个是比较容易计算的,然后你利用这个求函数的这个3d function,你把整个空间的3d方面搞搞出来,搞出来完了之后你用这个sdance function再做一个啊,穿过mesh的转化,就是类似这种。

这个是我见过就是一种一种套路,但是但是这个肯定不是一个最优的套路,跟我想那个几做几何的同学肯定知道最优的套路,这个反正我也就嗯因为就不往这方面讨论了,因为我自己做啊。

这种s p h这种例子的这种也比较少,我自己一般来说不是一般来说不做这个这方面的,主体这块其实我做的总的来说也是相对来说比较少,我只是在我我最早最早的时候,我我是做流体的啊,都是十多年前了。

然后后来不是读完,我基本上后面就不做流体了,就是只只是做一些边边圆圆的流体的工作,后面就基本就是没有在做。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

好吧,然后再然后就讲一下sph这块有有什么工作吧,首先就是你怎么样把这个模拟模拟讲得更有,做得更有效率,其实我觉得很多呃模拟的问题都存在这样的问题,就是怎么样能够高效地去进行模拟啊,尤其是对于游戏而言。

就是怎么样去模拟,能够让你的呃模拟引擎能够适配游戏的这个性能的要求,因为游戏其实对性能的要求非常非常的讲究啊,本身你一个游戏其实只有很少很少的一部分资源能够给模拟器,你正常情况下。

你可能对模拟引擎的开销可能都不足1ms,甚至是0。1ms,你还需要考虑到跨平台,考虑到你这个游戏能够在手机上也可以玩,在基本上也可以玩,你这个游戏呢可能不能只是给开发给土豪,对不对。

你可能要考虑到你这个游戏可能在比较低配置的电脑上,硬件上你也可以跑,所以说你怎么样把模拟搞得更有效率,这个事我觉得是一个永恒的,需要值得的课,需要研究的话题,而且游戏搞完之后。

你还要想就是怎么样能够做得更好的细节,因为当你去提升你的性能的时候,你不免得你需要你的效果打折,怎么样能够尽量的少对你的效果进行打折,同时呢又让你的这个性能更有效率。

这个是我觉得是图形学跟图形学里面的模拟,跟我们其他的工程里面的物理模拟啊,甚至跟影视里面的物理模拟所需的需求的一个很大的差异,因为你看我们工程的搞的同学,可能搞物理的同学对计算量要求不是很严格,对不对。

他们的做计算,比如说做一些什么大气环流的流体计算,直接放在这个超级计算机上去跑,无所谓,有个三天三夜也无所谓,但是咱们做这个物理模拟,我们更多的是想要从实际的一些,尤其是实时的应用场景出发。

所以说这个事我觉得是一个很重要的点,然后对于流体的话,很重要的一点就是说怎么样,可这个是一个很大的挑战,就是你怎么样能够让体积不发生改变,因为当你很多有粒子在运动的时候。

你很难去保证说粒子的运动过程中是不可压的啊,这就是为什么后来嗯后来搞了类似这种混合式的m p m p i c,这种方法,其实本质上就是也是想利用网格进行数值求解,而不是简单的在这个例子的点上进行求解。

然后还有就是说怎么样去处理这个水跟空气之间的界面,这个问题对吧,因为我们在模拟水的时候,有的时候想要是不考虑空气的嘛啊,因为他们空气的密度和水的密度,它的这个差太大了,你没有办法一起去模拟。

那怎么样去更好地处理这些边界,然后还有就是最近几年啊比较常见的,也不算比较常见吧,就是呃有一些同学在搞的怎么样去用ai去驱动这个模拟,怎么样去模拟那个流体,比如说大家可能知道news news啊。

siri他们的那个他们那个组,他们就搞了很多这种基于ai驱动的这种流体模拟的方面的研究吧,总的来说我个人觉得就是嗯ai这一块还是是比较前沿的,就是目前还没有看到,就是能够效果特别好。

然后可以把这个物理引擎替换掉的趋势在,然后其实我是觉得呃我是觉得,但是有两点我想要说的吧,这一点就是说我们物理引擎就是做图形学啊,然后研究物理模拟其实到底是应该研究个什么东西。

其实我觉得有很多同学也很困惑嘛,然后也就是说会觉得你这个模拟其实跟很多啊,模拟领就是很多这种工程领域里面,计算数学里面的模拟很像,对不对,其实我个人是觉得最重要的就是实时性,就是性能。

因为我们图形学最重要的,就是怎么样能够有效地去快速的去进行这个模拟,而我们的评价标准其实更多的是效果上的逼真,不是说这个物理的这个模型或者是这个啊这个过程是否正确啊。

这个其实也是为什么我们能够在效率上做文章的原因,因为我们本质上就是想要在效果跟效率之间达到一个平衡,对不对,怎么样去牺牲一部分效果,然后能够让我们的效率提升,真能够满足实时。

比如说游戏甚至或者是非非游戏,但是比如说做虚虚拟数字人之类的需求,能够让呃用户看不出这个问题来,这个是图形医学需要进行一个研究的问题,如果说单纯的去做某一类的效果啊,说实在的。

我个人觉得我不是很赞同这样的这种研究的理念,因为呃说实在的,我们现在物理模拟其实也已经搞了二三十年了嘛,从图形学最早开始搞物理模拟开始,最少最少也有20多年了,你说什么样的效果是没有做过的。

其实大部分都已经做过了,剩下的可能没有做过的效果,就是非常非常鸡毛蒜皮的一些不常见的效果,觉得其实那个东西也真的没有什么太多的研究价值,对不对,你说为了单纯为了做一个模拟,你去发一篇paper有意义吗。

有意思吗,我觉得更多的我们应该去考虑的是怎么样去进行效果的提升,然后这个其实就是我想说的第二点,就是我觉得很多时候就是工程里面,工业里面所需要的急需解决的问一起啊。

会感受到就是学术圈跟游戏圈在图形学里面其实是有很大的脱节的,你看比如说每年咱们的这个论文,c寡妇的论文,你觉得有多少的是能够实际有产生作用的,或者是有用的,其实很少对吧,那为什么会产生这些现象呢。

我就觉得就其实我觉得我们学术学院的同学就是应该更多的去落地,更多的去看看,去了解学术,从外面学校外面的东西,就是去了解一下,比如做游戏真正想要解决的一个什么什么问题,对不对,做电影特效。

visual effects,他们需要的是一个什么样的工具,比如说像我自己做服装,那么多数字服装,那么你整个服装行业它需要解决的一个什么样的问题,如果去了解这些问题。

你就会发现可能你当时以前所研究的这个问题,根本就不是一个问题,或者是不是最重要的问题,是希望就是因为我们上这个课,我我相信会有很多我们未来能很优秀的同学,能够成为我们图形学的很优秀的人才。

那么我希望你们能够去真正的去解决对于现实的问题,而不是说去在一个象牙塔里面去研究一些可能比比较容易能发paper,但是呢嗯对我们整个社会,这个其实是我想我说的这两点,上完这个课,下一步该干什么。

这个其实很难,因为为什么,因为嗯照理说应该会有一个中级课程吧,嗯但是我不知道就是今年有没有或者是明年有没有什么开中级课程,但是我希望是咱们上完课之后,完这个课之后能够对这个基础有一定的了解啊。

如果说你去看一些论文的话,至少就不会像以前那么吃力了,你会对他这个论文的前因后果会有一个比较清晰的概念,你知道他大概是干什么的,利用这个东西去入门,我相信会对对好一点,我自己其实是其实是也是也是。

其实还是通过上课这种方式来慢慢慢慢入门的,其实你自学不能靠自学,确实是比较难的一个事情,因为因为自学我自己我不知道大家同学们会不会有这样的感觉,就是你自学的话,虽然说你去读那些论文,看得懂。

其实也是看得懂的,也不是看不懂,但关键是什么,关键是你自学的时候,就是你这个论文他可能会有好多好多,对不对,但是你并不知道说这篇论文这个方向可能是一个比较怎么走,什么样的方向。

然后那个想法那个方法呢它会有一个什么样的缺陷,它是一个比如说是一个已经快黄掉的一个方向,对不对,就没有不能告诉你这些东西,你自己去读paper的话,会有这个问题,除非说你自己花时间。

你把每一每一篇paper都去从头到尾实现一遍,但是那也不现实,因为到因为毕竟模拟已经这么多年了,其实有很多很多各种方法,你如果说啊要把每个方法都实现的话,其实非常花时间,我觉得我觉得可以的。

就是就是自学的话,如果唯一可行的,要么就是从早年的一些paper开始看起来,而且就是我我会建议就是会盯着一个方向,比如说你比如说你想做碰撞,那么你就你就专心地做某一类的碰撞,就就盯着这一块看。

会比较容易入门,或者是比如说你想做弹性体,那么你就专盯某一块,比如说gpu,那么你就看gp修这一块的弹性体,会比较容易入门一点啊,就尽量呃不要三心二意吧,就是不要一会看这个流体,一会儿看那个弹形体。

一会儿又去看碰撞,然后一会儿又想看一下碰撞检测,就是嗯不要东打一耙,西打一耙,就是会会专注一点,会相对来说会会,作业做完可以去找工作吗,觉得简单的游戏里面的引擎开发。

我觉得我觉得基本上可以可以去做一些初级的工作吧,我觉得,同学们还有什么问题吗,就是我我我自己是觉得我自己已经不搞流体了吗,所以我自己是觉得流体没什么可研究的,会open机要怎么可视化。

我觉得可能还是学一下open gl吧,我我们那个要入门还是还是比较容易的,但是我觉得可以不用学van,因为walking挺复杂的,open gl会比较容易一点,证书就是在那个那个鹅圈子里面。

是叫鹅圈子吧,那个里面会有,到时候会有一个电子证书给大家,会有一个电子的证书,做到不用约束吗,ai模拟最大的是不够准确,觉得ai最大模拟最大的问题就是说因为ai本质是什么。

他就是想把整个问题投影到一个latin space上去嘛,对不对,这些东西其实本质上就是做一个in space,那么那么衣服,那么模拟就是这种衣服也好,流体也好。

真的是存在在一个latent space上的吗,这个是我所不确定的,因为本身像比如说衣服它的褶皱的形式会非常多,然后流体它的表现形式也非常多,它未必是一个latent space。

你比如说你做一个通用的模拟是合适的,但是在某一些比如说具体的问题上,它有可能是合适的,比如说我们之前做过一个就是就是水花,水花的一个利用ai做一个建模模拟的一个工作,我就是不做任何其他的水。

我就只做水花,然后我就假设水花这个效果,它是在一个lion背上的,是有可能可以做的,ten space,我给大家打一下吧。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

大家没有学过,拉长了体积变小,密度变大,会不会更难弯曲,就不用连线,也是体积,我不太明白这个问题是什么,难不难弯曲,主要是取它的粒子度,就是你有多少根弹簧啊,多少个点啊,这些东西,你们学过。

你们有对ai有一些不说ai吧,最近几年确实是图形学里面搞这个的人挺多的,但是做的好的其实很少,粒子碰到边界怎么处理,就跟我们普通粒子碰到边界处理方式是一样的,就是弹反弹呗,然后或者是给个摩擦力什么的。

嗯,得看你在企业里面是做什么样的项目,如果说你在企业里面做工程的比较偏工程的话,就是说那可能论文就就没有什么机会发,如果是半研究的性质的话,那么就是你你做paper的时间会相对来说多一点吧。

这个要具体看做的好的老师有推荐看的吗,这个你得看是什么方向啊,说你你你看看看做哪个方向的那个的不同的好的老师都不一样,要的,比如说啊比如说dog james啊,斯坦福的dog james嘛。

他们就做那个young base simulation,就是呃做毛衣就现挤的种模拟,课上也没讲过图形学有必要读博吗,对如果说你要做模拟的话,我觉得读个博士还是挺有价值的啊,如果是做渲染,我倒不清楚。

我觉得可能没必要赌博吧,因为大家对图形学的很多认识基本上还是主要是以渲染为主,我觉得就是模拟会比较少,所以说你读不读博,其实可能价值差别不是很不会特别大啊,我觉得可能渲染的那个很多。

可能相对来说跟工业界的应用也没有太大的关系,还是我觉得是有必要读研的,我觉得本科跟读研还是有差距的,但是读博不一定,县级的模拟是复合材料吗,他们其实并没有模拟那个材料,本身。

它就是假设那个毛线的那个每根线是一根曲线,然后它在曲线的这个层次上去做碰撞,然后利用这种碰撞的这种相互交那种呃互相影响,然后来进行毛线的模拟,其实是很吃计算资源的一个模拟方式。

后来不是也有这两也有西瓜论文吗,就是说怎么样对这个模型简化到四面体网格,那种那种有限元网格的模拟上去,就是它基于呃基于这种毛线的那个原有的模拟,然后再映射上去,我觉得是有。

但是我觉得那个方法也是有一些小问题的,吃数学吧,嗯对我觉得我觉得计算机领域里面是比较吃数学的,跟跟其他计算机领域的数学相比是比较迟的,但是总数学我觉得跟在工程里面啊,应该是比较常见的。

或者是物理或者什么的,应该是差不多的,甚至可能有点甚至可能会更浅一点,计算机里面其实整个计算机专业里面其实用的数学都是比较少的,大家有没有觉得就除了图形学啊,搞ai的同学可能用的数学也很少。

因为现在大家都是用很简单的一个标准的一个库,类似tensorflow pytorch什么的套一下,然后调调参数就行了,数学都不需要学,大规模矩阵的求解价值有价值啊。

但是那个毕竟是一个图计算机图形学的问题,那个也有可能是一个数学的问题,通用的问题,cad cad也可以认为是图形学的一部分吧,特定的模拟方向读多少篇论文才算一个整体的认识,十十十几篇吧左右吧。

当然当然不光是读了,就是你还要去自己去实现一些代码,实现一些paper,会比较好,那个因为因为途径学跟那个ai不太一样,因为ai它有这些标准库了之后,有一个比较好好的点,就是绝大多数的代码都开源嘛啊。

然后然后你可以去去看看人家是怎么写的,然后图形学的话,因为年份比较早,然后也没有一个特别的标准,所以说大家每个人都可能都不太一样,所以说你有的时候需要自己去写,你没有那么多开源的资源可以给你。

准确性要求很高,所以最后突破骑士开始图形学这边把模拟效率提高的,其实有的时候对准确性的要求,他未必会在在可视的这个层次上体现,我举个例子,比如说我们做工程里面对吧一个桥梁,然后桥梁它比如说断裂裂了。

那断裂的话,它其实产生的应力应变应力可能很大,但它的应变其实可能会很小,那你去模拟的话,你根本就看不出来这样的效果,你完全就没有必要,你做一个prefracture就完事儿了,在在游戏里面尤其常见。

就没有必要去搞得那么真实,是比如说呃动画里面,比如说一个墙啊,比如说一个一个一个呃,比如说一个角色一拳打在墙上,那个墙碎掉了,你没必要去把那个墙真的去模拟一遍嘛,对不对,你完全可以啊。

先做一些让让美术调一些这个破碎的效果,然后直接给他跑一个破碎的效果就完了,你模拟跟所有的图形学都是一样的呀,就是一般来说conference就是sea graph。

然后journal的话就是talk tog transactional graphics,那个i吹破译tvc机会稍微差一点,这水管服为主吗,又搞一套图图形学标准嗯,我觉得我觉得比较难,因为为什么。

因为因为图形学里面就是模拟里面不说图形学吧,就说模拟里面就是模拟方式实在是太多了,就是不光就你看流体对吧,我们这个这这节课上,整个整个这个课上讲的流体,弹性体,刚体这都不一样,那我就不考虑别的。

我就说流体,那流体还有这种呃例子啊,还有这种网格啊,还有这种各种各样的方法,其实都很多,关键是就是很多时候就是为了我们追求性能,比如说通信学里面为了追求优化或者性能。

会搞各种各样的这种各种各样的这种一hack的一样的东西吧,就比如说我前面说的adaptive的方式,就是你每个例子都不一样,大有的大,有的小,为了细节啊,有的时候也会这样子就会做细分嘛,那你做细分的话。

你这个搞一整套的这种方式就很难啊,一整套标准的这种这种酷就很难来做这个事情,我是觉得这种气氛其实在工程里面也挺常见的,大家如果是工程背景的话,其实也也知道这些东西,你如果用一种标准的这种方式去模拟。

就挺麻烦的,能找到工程性能较好的research做做看嗯,什么意思,是指research topic吗,我觉得模拟还是可能是图形学里面入门入门最难的一个方向,我个人可能觉得。

就是我觉得是最有趣的一个方向啊,人家是不是这么觉得,那没有问题的话嗯,今天就先到这里啊,有什么模拟方向可以推荐做啊,模拟方向可以推荐做,我又不好说是我,我现在我们现在在做的方向。

因为我也我都已经我们都已经在做了,我觉得实时的东西永远是有价值的,就比如说流体嘛,你流体流体实时是一个很难的东西,我觉得如果谁能够把实时的流体做好了,我觉得非常非常有价值,is watton嗯。

他们之前做过一些就是做水面播的,实时的,为游戏做的这种东西,我其实就特别喜欢这种工作,还有就是毛衣吧,毛衣我觉得也特别难做,就是虽然说最近几年也也陆陆续续有做,不知道大家去年有没有有没有看过。

去年ccf有个section,专门做毛衣的设计,但是我觉得我觉得没有做的特别好,我觉得毛衣也也也是一个很难做的东西,然后就先这样吧,然后那个课有些晚,来的晚的同学可能没听到。

就是咱们那个咱们作业就是还是可以继续交,但是啊我我们ta就是不一定有时间会p,就是因为马上要过年了,下个礼拜就是西瓜deadline了,所以说我们会在年后差不多会年后会统一吧,成绩也好给大家。

然后到时候评奖也会呃,也会到,就是奖品寄给大家,然后我们林迪其实是有一个那个营地,是有个奖学金的,就是大家以后如果说大家啊在图形学生进一步研究,然后有一定成果的话。

就是也欢迎大家来评我们的这个奖学金每年都有,然后我们我们年后也会有我们这奖学金的颁奖活动,到时候也是安排在后面的,对还有还有还有证书吗,你可以补交呀。

就是这证书的话就是只要你在我们评奖之前把四次作业都补齐了,就有证书,就是就就就不限时间了,就是时间只是为了打分,就是为了评奖所设立的,但是如果说为了证书的话,只要你在嗯年前,然后把把作业补齐就行,填吧。

反正具体时间我也不知道,得得看看我们助教有没有时间去批改,但是基本上年前应该都可以提交不了了是吗,嗯那我让他们再开一个通道吧,就是不交作业的通道,那我们就先到这里,然后给大家拜个早年吧,嗯大家新年快乐。

祝大家新年快乐,然后就是呃明年可以在图形学上更进一步,然后如果有物理对物理模拟感兴趣的同学,然后进一步提高,那先这样。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

GAMES103-基于物理的计算机动画入门 - P2:Lecture 02 Math Background: Vector, Matrix and Tensor Calculus - GAMES-Webinar - BV12Q4y1S73g

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

行我们今天今天主要来讲一下,就是跟嗯物理模拟相关的一些数学问题,然后呢嗯这些数学问题我觉得主要分成三三类吧,第一类是一些基础知识,就是大家可能嗯以前上高中啊,或者是大学本科的时候,就是上一期数学课。

可能就是已经比较了解的一些基础知识,过一下,然后嗯就是确保大家都是能够就是在这些数学基础上都是比较熟悉的,因为我猜测可能大家有的时候上数学课,有的时候嗯逃课啊,或者是什么种种原因,就是有些东西忘记掉了。

然后我这里其实也是帮大家巩固一下概念,然后第二个呢是主要是嗯讲一些就是图形学里所要用到的,然后呢可能呃有的同学不是特别了解的,所以说这里我也想跟大家来介绍一下这些知识。

然后就是帮助有一部分同学就是呃掌握这些知识,然后如果说你嗯可能在这方面可能欠缺的话,可能就是课后需要呃读一些参考资料,然后稍微对这方面了解一下。

然后最后一点呢就是呃有一些东西可能是嗯大家可能在读书的过程中,然后我这里也会简单的介绍一下,当然我们在后面的课程里面也会把这些知识呃传递给大家。

所以说这里相当于是给大家相当于给一个introduction,能够对大家帮助大家有些初步的了解,然后今天的课主要是分成三块,一个是矢量,然后另一个是矩阵。

然后最后我们来讲一些跟矢量矩阵相关的一些微积分的一些东西好吧,然后咱们首先讲讲史料vector嗯,我相信大家在高中里面,中学里面可能都已经有学过矢量这个概念了,那么什么是矢量呢。

嗯最常见的我们大家在日常生活中用的比较多的,就是把矢量描述成一个在二维或者三维空间中的一个几何体,然后这个几何体呢它有方向的含义,同时它也有大小的含义。

就比如说呃我假如说我在空间中有一个坐标系x y z嘛,然后呢我可以定义一个矢量是从原点到某一个点p点的,那么这个矢量其实就是描述了从原点出发到这个p点的这么一个呃,相对关系,我们把它叫做p。

然后呢呃他这个p在每一个坐标轴上的投影,分别就是p x p y p z对吧,三个方向,那么就分别有三个值来表示这个呃矢量,然后呢它这是在三维空间里的,所以说我们这里写作二三,这个二就表示时速空间嘛。

然后三次方就表示它是一个三维空间了,呃相对应的原点它是一个比较特殊的一个矢量呃,它是000,也就是意味着它在三个方向里面,它的投影都是零,它相当于是一个初始点呃,然后大家一般在呃印象中吧。

很多大家手写的时候,一般来说都写矢量,一般来说都会在上面放一个箭头,对不对,一般来说都是这样的写法,我来给大家画一下,一般都是给上面放个箭头嘛,一般都是这么写的,但是这种写法在印刷体里面。

在论文里面一般来说是不是很常见的,为什么不常见,因为如果说你每个矢量都给它写个箭头的话,会导致你整个论文里面到处都是箭头,特别乱,所以通常我们在论文里面的时候,一般来说都用字体来区分矢量和标量。

那么矢量一般来说我们会用黑体来呃表示,然后标量一般来说我们会用斜体字来表示,所以说大家看到一个字母,首先看它的字体是什么,如果是斜体字,一般来说它意思就是标量,然后如果是黑体字,一般来说就是矢量。

然后为了区分矢量和矩阵,我们还用大写跟小写,这个我们等会儿后面会讲,所以说嗯大家都注意一下,就是一般来说咱们在论文里面的时候,就是要特别注意这个字体,就我们一般来说是用字体去区分的。

而不是说用这个小箭头去区分了,然后呢这个坐标系呢有一个特点,就是它其实是有两种类型的,像这种坐标系跟呃如果大家记得右手定则是什么的话,就是如果说大家把这个手呃,让四个手指从x转到y的话。

那么你的大拇指指向的方向就是z的方向,那么这个就叫做右手系统,右手的坐标系统呃,在图形学里面,一般来说我们做研究,一般来说都是利用右手的这个坐标系来定义的。

然后open gl一般来说一般open gl也是用右手系统的,那么左手系统有没有呢,其实也很常见啊,比如说啊就像这里的话就是一个左手系统了,如果说你用左手嘛对吧,你让x y z是四个手指,是x y z。

然后你的大拇指指向的方向就是呃呃z的方向,然后unity是左手的direct x,direct x是微软的一个图形形引擎,它就是左手的,所以说其实呃在图形学里面,左手跟右手的系统其实都有。

所以说大家呃有的时候要比较留意一下,就是不要默认的就觉得好像都是右手或者都是左手,其实不同的系统它其实用的坐标系是不一样的,好吧,在通信学里面,一般来说我们呃设定呃坐标系的时候。

我们会参考这个屏幕空间呃,如果我们观察我们自己的这个屏幕嘛,一般来说我们的右手方向就是x方向,然后我们头顶的方向就是y方向,那么z方向就有两个方向了对吧,一个是往外的屏幕外的。

就是朝着我们的这个是右手系统,然后朝着屏幕里面的呢就是左手系统呃,左手系统它其实有个什么好处,它的好处在于你想象就是我们空间中的物体,是不是都是在这个屏幕后面的对吧,我们有个三里虚拟空间。

那么这个这些物体其实都在屏幕的后面的,那么在屏幕后面,如果用左手系统,也就意味着它的x y z都是正的值,这是它一个好处,就是所有的值都是正的嘛,那么如果你用右手系统呢,你的物体等于就是在负的z的方向。

所以说它其实不是说不能这样子定义,你可以定义是右手还是左手的,这个反正就是大家就是参考一下,那么我刚才讲到了,我们的矢量是一个3d的,一个在三维空间里面描述一个方向,但是在有的时候呢。

我们其实也并不需要说这个矢量就一定需要有什么几何的含义啊,他完全就是可以是一堆呃数字组合起来的一个结果,我举个例子,比如说呃我想要描述一个物体对吧,假如说我有一个闪电,大家可以看到左边我画了一个闪电嘛。

这个闪电它是由11个顶点构成的,012345678 90 十到14,有11个顶点构成的,那么我可以把这个物体用这个11个点的位置的组合来进行一个描述,那么怎么做呢,我其实就把这11个顶点排成一列。

就像左边这样对吧,我把这个x0 x1 x21 直到x 10,那么这整一个大向量,它其实就可以描述这个物体的形状了,那么当我做动画的时候,如果说比如说我要修改某些点的位置。

那么我就相对应的更改这些点在这个大向量里的这个值,那么我就可以去描述这个呃物体的状态了,那么这个这种情况下呢,这个向量它是一个33维空间里面的一个大向量了,它就不是一个三维空间里的一个向量了。

那么它其实也并没有什么几何的含义,因为大家可以说这个33维空间是个什么几何含义啊,这个我不知道对不对,但是我如果把这些点全都合在一起,我其实可以描述这个物体的状态。

我其实可以拿来做一个相当于一个矢量的一个表示,在这种情况下呢,我们把它叫做stack vector,一般来说我们把它叫做stack vector,就是说这些向量其实是叠在叠加在一起的。

它没有什么几何含义,但是我拿来用它来描述这个物体的状态,有同学问就是x0 x一是不是也是向量对每一个点,每一个x它都是一个向量,都是一个三维向量,然后呢我把这所有的这是11个三维向量合在一起。

就是一个3x11维的向量,所以说它这就是33维的向量好吗,然后呢我们有了向量的定义呢,我们接下来可以呃我们可以来进一步的定义一些数学的计算,比如说我们可以来定义加减法嗯,大家可能在中学里面都学过嘛。

矢量的加减法其实就是对于每一个元素做加减法,所以说呃p加减q就分别是p x加减q x p y加减q y,然后pc加减q z这个大家都知道,这个p加q等于q加x的q加p这个其实大家也知道。

然后几何上是个什么含义呢,几何上呢就是说如果说有个p对吧,有个p向量,然后有个q向量p加q呢,就等于我先从原点出发,然后沿着这个p的向量往前走,走完之后呢,再沿着这个q的方向往前走。

然后这两个叠加在一起,我就得到了p加q,然后同样的如果说我先沿着q走,再沿着p走,我最终也可以达到同样的结果,这个我们刚才也看到了呃,类似的减法,如果说我想要做一个减法,那么我有个q,我有个p。

那么p减q就是p跟q之间的这么一个相对位置,我就可以得到了一个呃相对的一个位移关系,如果说大家不记得的话,我相信大家可能大多数同学应该都还记得这个加减法的一些,所以给大家反正先简单的过一遍,好了。

我们现在有这些呃加减法,然后呃的这些定义之后,我们可以拿来用矢量来做什么,我们一般来说可以用这些3d的矢量来描述点速度力,还有一些线,这些跟所有的跟线有关的表达,我们都是可以用矢量来描述的。

呃举个简单的例子吧,就是假如说我现在有一个点啊,我现在有个点叫p对吧,然后呢我有一个向量啊叫v,然后呢你可以认为说这个p呢是一个小的一个例子,然后呢这个例子呢沿着这个v的方向往前运动。

v可以认为是它的速度,那么我怎么去描述这个粒子的运动呢,呃我可以,嗯等一下我可以把这个运动的这个轨迹呢写成一个公式,叫做pet,卡了吗,现在呢,现在,现在是卡顿还是卡我我我稍微看一下啊,把切到5g吧。

可能是因为网络的原因,现在好了是吧行嗯,可能是网络的原因,那么我可以把这个例子的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

什么毛病,现在呢现在好了吗,好吧,我们继续吧,这个我不知道这边的网怎么回事,反正我现在用5g然后看看5g怎么样啊,我们刚才讲到,我们刚才讲到有一个小例子吗,录播吗,对ok我刚才讲到现在现在有个小例子。

然后这个小例子呢呃它的初始位置是p,然后呢它沿着这个v的方向在运动,它沿着这个速度的方向在运动对吧,那么我可以把这个粒子的运动轨迹描述成ppt,等于p加上时间t乘以速度,这个我想大家都知道。

也就是呃位置等于原始位置加上速度乘以时间吗,那么这个公式呢就给了我们这个把这个位置呢写成了关于时间的函数,这个t就是时间,那么t等于什么,t是什么呢,t呢大于零的时候呢,也就意味着这个例子在往前运动。

然后t小于零的时刻呢,就表示我们倒推回去,在之前的时刻,这个例子是什么样的位置,那么整个公式呢就是实际上就是在描述一个粒子,沿着这个速度往前运动的这么一个公式,那么因为这个东西它其实本质上就是一个线嘛。

所以说我们可以利用同样的公式,我们来定义一条线,比如说这里假如说我有两个点,一个是p点,一个是p点,一个是q点,那么我的这个方向是什么呢,我的方向就是q减p对吧,那么我的这个粒子的运动轨迹呢。

就变成了p t等于p加上t乘以q减p了,那么我就利用这个刚才的这个原来是描述这个粒子运动的,我现在把它来描述一条线了,天然的呢我就有三个部分构成,一个是t小于零的时候,这是什么呢。

就是在p前面的那一段就是t小于零的时候,然后呢第二段呢是零跟一之间,当t在零跟一之间呢,我得到了什么呢,我得到了我得到了中间的这一段,就是p跟q之间的这一段对吧,然后最后一段是什么。

最后一段是t大于一的时候,当t大于一的时候,我得到了什么,我得到了q以外的那一段,所以说我同样一个公式,我可以利用这个公式我来描述不同的几何体,比如说线段,如果说我想要定义的是一个线段的话。

那么我用这个公式我再加一个条件,我要求t在零跟一之间,那么我得到的就是一个线段的定义,如果我想要得到一个射线是什么,假如说我想要得到一个射线,那么我就要求t大于零。

那么我得到的就是从p出发的一条射线对吧,那如果说我想要得到的是一整条完整的线呢,那我对t就不做任何约束就行了,那我就直接利用这个公式,然后t可以取任意的时速,那么我得到的就是一整条完整的线了。

这个就是同样一个公式,我根据t的不同的值范围,我可以拿来定义不同的东西,那么这是一种写法,然后还有一种比较常见的写法,是把这个公式稍微做一下变化,我可以把它写成一减t乘以p加上t乘以q。

那这种情况下你就会发现这个东西呢,它其实本质上就是对p分别对p跟q他做了一个混合嘛,对不对,把它混在一起,然后呢它混合的量是多少呢,是通过这个一减t跟t来决定的,这个1。1减t呢就是p的权重。

t呢就是q的权重,也就是说我是有一个根据t计算出来的权重值,然后我利用这个权重对p跟q做一个混合,我可以得到这个p的位置,这个东西呢我们把它叫做差值呃。

然后呢这个一减t还有这个t呢就是它的一个差值的权重嘛,这个t呢有的时候叫做interpret,这个反正呃大家如果听说过的话,就是呃就就了解,如果说没有听说过的话,反正就是知道这个概念就是给两个点。

然后呢我给他一个权重,我可以利用这个混合的线性的这么一种混合的方式,我可以得到中间的一个结果,好吧,这就是一个线,我们刚才讲了啊加法减法,然后接下来我们讲一个也是比较重要的概念,就是矢量的大小。

数学里面叫做norm,它其实的意思就是说给一个矢量,我怎么去计算它这个矢量的大小,对不对,最常见的我们通常比较见得比较多的叫做euclidian norm,也就是所谓的to nor,怎么计算呢。

就是p x平方加py平方加pc平方,然后开个根号,这个就是to norm对吧,那么为什么叫to no,你看大家留意到这个叫to norm,为什么叫to norm,因为这里都是二嘛,都是平方平方平方。

然后最后开根号,所以叫to norm,相对应的呢,我可以任意取一个值叫p,然后呢我做p次方,然后最后呢呃开辟的根号,这个呢就叫pal呃,根据p的不同的值,我有各种呃norm的写法。

比如说呃one norm这种一norm就是它的绝对值的和嗯,在数学里面它其实还有一个另外一个名字叫做曼哈顿,举例叫my heart distance,它其实就是one no。

这个如果大家做一些有些游戏开发里面可能会用到吧,就是利用这个坐标系之间的差,然后求和来算距离,而不是直接拿来做这个ucla距离呃,然后还有一种呢叫做infinite infinity norm,呃。

什么意思呢,就是假如说这个p趋向于无穷大的时候,发生什么,当p趋向于无穷大的时候,这个计算出来的值实际上就是它们的最大值,这种也是一种比较常见的norm,叫做infinity norm。

当然最常见的应该是to nor,很多时候呃大家不写这个二,就是默认的时候呃,就是直接把这个二去掉啊,然后这种情况下,一般来说大家都是假设它是秃脑,一般来说就是大家默认的就是这个。

the norm有什么用呢,呃比如说我们可以拿来计算两个点之间的距离嘛,对不对,呃,两个点之间它的相对位置可以用一个矢量来描述,就是q减p这个矢量来描述,那么这个矢量的norm也就是它的距离。

我们就可以拿来直接拿来算距离呃,然后如果说一个一个向量,它的norm为一,那么我们把它叫做是一个unit vector,就是一个单位向量,然后如果说一个向量我想要把它变成单位向量,我怎么做呢。

我就把它除以它的norm就可以了,呃为什么,因为呃这个除完之后的这个norm就等于norm除以norm,那么自然也就得到一了对吧,这个就其实一个很简单的操作。

这个我想大家可能都是比较呃了解或者是听说过的嗯,这是一个normalization的一个方式,就是把它变成一个单位向量的一个方式,好了刚才我们讲了这个矢量的加法,减法还有矢量的norm呃。

接下来我们来讲乘法呃,我们先讲一种乘法叫做点乘或者叫做内积,一般数学里面叫做内积,但是我们呃如果是做几何运算的话,有的时候大家就喜欢叫点乘吗,那么点成什么意思呢,就是假如说给你两个向量p和q。

如果说我做一个点乘,我就分别的对他们的xy还有z做乘法,做完乘法以后,我们把它加起来就得到了一个什么,得到了一个标量对吧,我们得到了一个标量值,那么这个就是它的点乘呃。

有的时候大家读一些paper会发现它一般来说不用这个点的方式,一般来说他会用这种方式,一个一个尖括号,然后p a q类似这种形式,其实是一个意思,就是做内积,做点乘的意思,然后如果大家读一些论文呢。

有的时候大家会写这种方式,可能也会比较常见,就写p transport kill,什么意思呢,就是我们会把这个p当作是一个矩阵,然后呢它的转置呢实际上就是把p变成了一个从一个额数的向量。

变成了一个横的向量,然后如果做乘法,做矩阵乘法呢其实跟做点乘,它的结果是一模一样的,所以说这个也是一种写法,虽然说我们现在还没讲到矩阵,但是这个其实跟呃其实就是想利用这个矩阵乘法的这种方式来写点乘。

这个好处在于什么,这个好处在于我们可以把所有的东西都写成矩阵跟向量的乘法,而不需要额外的去定义点乘或者是其他乘法,这个以后大家如果说读一些paper或者是我们以后之后的课程,可能会遇到这种情况。

就是如果他说大家看到这种两个向量,然后中间transports实际上就是我们在做点乘好,这是数学上的定义啊,就是呃写法上的定义,那么几何上它什么意思呢,它的几何上他在算一个事情。

实际上就是说假如说我有两个向量对吧,我分别有这两个向量的大小长度,分别写作p的norm跟q的norm,同时呢我还有一个夹角,这个夹角是p跟q之间的夹角,我把它叫做c塔。

那么这个点成就给了我们p的norm乘以q norm,再乘以cos theta,这个实际上就是它这个点乘在几何上的这么一个含义了,那么根据定义我们有一些呃这个点乘的一些特征,比如说p乘以q等于q乘以p。

这个大家蛮容易从这个定义上去理解的,因为a乘以b等于b乘以a嘛,所以说你把p跟q交换一下位置,它这个结果肯定是一样的,对不对,他满足分配率对吧,p乘以q加r等于p乘以q加上p乘以r。

这个反正跟正常的乘法分配率也是一样的,这个反正从定义出发嘛,我们肯定也就可以得到这样的结果,没有什么特别奇怪的,然后还有一种写法,还有一种呢是比较呃有意思的,我觉得就是怎么样去写nm。

你会发现其实p乘以p dot p,他对他自己做点诚,其实就等于norm的平方,to norm的平方,因为为什么,因为p乘以p自己等于p x平方加p y平方加pc平方吧。

也就是它这个two norm的平方,所以说很多时候有的时候大家想做一些呃关于矢量的积分,微分计算的时候呢,一般来说大家都是利用这个东西去写的,一般来说大家就不用norm的这个定义去写了。

然后可以利用这个点乘啊,还有利用这些矩阵乘法的这种写实写法,然后就是可以做一些呃微积分的计算了,回头我会给大家看一个例子,呃然后最后一点呢就是关于ca的,呃假如说p跟q它的点乘是零的话。

也就意味着这个cos theta等于零,因为我假设这个p跟q都不等于零嘛,他俩都不是零向量吗,他既然都俩不是零向量的话,那么他俩唯一等于零的原因就是因为cos theta等于零对吧。

那么cos theta什么时候等于零呢,肯定就是c它等于90度或者是270度的时候等于零吗,那么什么时候是两个向量的夹角是90度或270度啊,他俩必须是垂直嘛对吧,所以说p跟q点乘为零。

也就意味着p跟q是互为垂直的关系,是正交的关系,这个是一个比较,也是大家用来拿来判定的一个一个标准吧,就是拿来判定就是两个方向是不是垂直的一个标准,就是做一次点乘,看看结果是不是等于零就行了。

好接下来我们可以利用呃点成我们来呃搞些搞些事情呃,首先我们可以来定义一个点到一条线上的投影,假如说我有一个点,我这个点叫q,我把它叫做q,然后呢我有一条线分别通过这个点的原点o当然不一定是o啊。

可以是任意的这个点嗯,还有一个方向v通过这两个向量我来描述这个点,我们刚才讲到这个可以通过一个什么公式,反正一个线性的公式,我们可以描述这个线嘛对吧,我想要知道这个q在这条线段上的投影是什么,是哪个点。

同时呢我也想知道这个投影s到这个原来这个点的距离是什么,这个我把它叫做小s,大家可以注意到我这个写这个两个s的时候,我的字体是可以拿来区分这两个值的不同含义的,黑体字是矢量。

然后斜体字表示大小是一个标量,表示它这个距离,那怎么做呢,我首先来计算这个小s好不好,我首先来计算这个标量是多少,计算这个标量,我知道这个q如果说它的投影是s的话。

那么他这个qs这条线跟我这个线跟原来这条ov这条线,他肯定是垂直的嘛对吧,它肯定是一个垂直关系,所以说这个s呢,这个s呢就是这条矢量,就是q o这条矢量,在这条线段上的投影。

那么已知这条线段q o这条线段它的大小是q减o的norm,那么我再乘以一个cos theta,theta是这两条方向的夹角,我是不是就可以得到s呀,这个就是它的定义吗,斜边乘以cos等于底边嘛。

那么如果说我把这个东西乘以这个矢量v的大小的话,上下都乘以分母,我把这个东西作为一个分母,然后这个东西作为分子,我把它前后都乘以vid norm的话,是不影响结果的对吧,我就两边都乘上下两。

上下都乘以这个venom就行了,那么这个东西是什么,我们刚才讲到,如果说两个矢量相做点乘得到的是什么,得到的是这两个矢量的大小的乘积,再乘以这两个矢量的夹角的cos是不是就是完美的典型的定义啊。

所以说我们得到的就是q减o点乘v除以v norm,那么然后呢这个东西是什么,v除以v的norm是什么,是normalization,是把v变成一个单位向量的normalization,所以这个s。

同样也等于q减o点乘normalize过以后的这个v的向量,换句话说,我们把这个v先normalize一下,normous,完了之后呢,我得到一个q减o的向量。

我把这个q减o的向量跟我这个v向量我做一个点乘,我就可以得到这个这个s我就可以得到这个投影距离了,有了这个投影距离之后,我就可以拿来得到大s怎么得到,我从o出发,我根据这个线段的定义出发吗,我从o出发。

我沿着这个i v方向走,我走多少距离,我走s那么我的这个大的s capital s啊,我这个大写我这个黑体字s等于o加上距离乘以方向,就等于它的这个投影点的位置了,这就是我们来计算。

按这个一个点到一条线段的一个呃呃一条线的这个投影的一个方式,我可以利用这个点称来做这样的计算,好吧有有没有什么问题,大家在这里,没有问题的话,我们就继续往下走,ok。

那我们接下来我们可以利用刚才我们讲的这个东西,我们去定义一个平面,假如说我有个平面,平面中有个点,我把它叫做c点,然后呢平面呢我有一个方向,它这个叫做反向,叫做同时这个n也是一个单位向量。

那么这种向量我就把它叫做norm normal,就是它的法向量就是一个平面,我有产品平面上一个点,同时我还有平面上的一个法向量,利用这两个向量我可以定义一个平面,怎么去定义一个平面呢。

我去我可以搞一个公式,我用这个公式来判定,说给你随便给你一个点啊,给你个p点,我来判定这个p点它跟这个平面是处在一个什么样的关系上,它是在这个平面的上面,还是在这个平面上,还是位于这个平面。

还是说在这个平面的下面,我可以有三个不同的位置,那么怎么得到这三个不同的位置呢,很简单,我有这个向量,从c点出发的到p点的向量,对不对,我把这个向量和法向量做一个点乘,我是不是就可以得到一个距离啊。

就是我们刚才讲的这个投影距离啊,那这个投影距离它其实不是一个我们所谓的一个永远是正的距离,它其实是可正可负的,那么它的这个符号其实就是告诉了我们这个p点的关系,跟这个平面的关系,大家看啊。

假如说这个p点在这个平面上面会发生什么,如果说p点在平面上面的话,那么p减c这个向量跟n向量它其实在同一个面上,同一个方向上,同一个半平面上对吧,那么它这个做点成就会是大于零,也就是在这个平面上面。

如果点乘等于零呢,如果点乘等于零,也就意味着p减c跟n跟法向量它是一个垂直的关系,也就意味着它是刚好位于这个平面的,然后最后如果说p减c跟n的点乘是小于零的,那意味着什么,意味着p在这个平面的下面对吧。

因为p减c它跟a an它不是处在一个半平面上的,所以说它是小于零的,这里应该写小于等于小于它在它下面,所以说我就根据这个公式,根据这个点称,我可以得到三个位置关系,那么我们刚刚讲了。

说我们可以利用这个符号大于零还是小于零,还是等于零,我可以来做一个位置上的判定,那么还有一点比较重要的是,这个s它这个s它其实本质上就是这个p到这个平面的距离吗,对不对,他在这个法向上的投影。

本质上它就是到平面的距离,那么这个距离呢跟我刚才也说了,跟我们平常所说的距离不一样,因为平常我们所说的距离它不可能是负的值,这里呢它是可正可负的,它的绝对值表示的是我们传统意义上的距离。

而它的符号表示了到这个曲面的一个位置关系,所以呢这个东西呢我们叫signed distance,就是有符号的距离,这个我们以后也会讲到,就是我们可以利用这个符号,我们可以利用这个距离来做什么。

做碰撞检测,为什么,因为假如说我跟一个物体发生碰撞,我把它我这个东西跑到物体里面去了,它就符号就会变负,所以说我可以利用这些东西我来做一些检测,我们以后我们嗯讲碰撞啊,讲一些碰撞处理的时候。

我们会讲到就是呃利用这些东西,但是这里大家可以留意一下,就是它是个距离,但它不只是一个单纯的距离,它还有符号,然后符号可以拿来做一个位置的一个判定,那这里给大家一个小提问,大家可以回头想一想。

就是说假如说我不是一个面,我是一个一个盒子对吧,一个盒子有六个面构成,那你怎么来判断一个点是不是在这个盒子的里面呢,这个我想大家呃回头可以去思考一下这个问题,好吧,这个给大家留个小的小小的课后作业。

再给大家举一个例子吧,也是呃我们利用点乘来做的,我们来做一个点跟球的碰撞,假如说我有一个点,我叫p点,然后呢他朝着某个方向运动,这个v呢就是它的速度,就是它的运动方向,它的轨迹呢我们前面也讲了。

就是p t嘛,就是一个线性公式嘛,然后我们这个球呢它不运动啊,我们假设简单一点球不运动,球的圆心呢是c求的半径是r那么我想知道什么时候发生碰撞,有没有发生碰撞,什么时候发生碰撞,我该怎么做啊。

我可以利用一个公式对吧,我假设说会发生碰撞,那么假如说会发生碰撞,那么会有一个什么样的现象呢,就是我这个p t对吧,我这个点在t时刻的这个点的位置到c的距离等于半径,然后呢我两边都搞个平方。

他俩也是相等的,所以说这个必然是成立的嘛,假如说碰撞发生了,这必然是成立的,那么norm的平方to norm的平方是什么呀,to norm的平方就是点乘吗,所以说我把它转化一下。

我就可以写成p减c加t乘以v,点乘p减c加上t乘以v等于r的平方了,这个其实就是利用这个ppt的定义,然后利用这个的定义,我给它给它写成这个点乘的形式,把它给整个给展开了,然后我再进一步展开对吧。

进一步展开呢,我可以利用这个点乘的分配率,我可以写成什么,我可以写成,点乘v再乘以t的平方加上两倍的t p减c,点乘v乘以t加上b减c,点乘b减c减二的平方等于零,这个就是一个比较简单的这个呃。

类似a加b的平方的一个展开,a加b的平方等于a的平方,加b的平方加二ab嘛,这个一样的道理,就是我利用这个分配率,我把整个东西给彻底的展开了,就写成了一个这么一个形式,那么这个公式告诉了我们什么。

这个公式其实告诉了我们这个t啊,这个时间呢它是一个一元二次方程的根,这个t实际上就是我们的未知量,剩下所有的量都是已知的,是已知的,v是已知的,c是已知的,r是已知的,所有的都是已知的。

唯独我们这个t是不知道的,对不对,那我最终就是可以把它做这些点乘,然后做这些计算,最后就写成一个一元二次方程吧,然后一元二次方程它的根有三种可能性,对不对,第一是没有根,没有跟意味着什么。

意味着这个点它就不跟这个球发生碰撞,就是零碰撞没碰撞,然后一个根一个根发生什么,一个人发生的,就是说我这个根这个例子啊,他刚好切着这个平面过去,切着这个球面过去,它是这样子的,它就发生了一次碰撞,在这。

然后最后可能也是最常见的可能性是什么,就是两个根,那么两个根呢,为什么会有两个根呢,因为如果这个点继续往前走走走走走走走走,他就会再次跟这个球面发生碰撞,这就也就意味着它其实会有两个根。

所以说我们可以利用这个一元二次方程,我可以把这个呃根找出来,找完根之后呢,我可以检查一下,说诶哪个根是大于零的,同时也是最小的,那么就是我的解对吧,因为为什么要大于零。

因为我要确保我是在前面发生的碰撞吗,我的例子是往前发生的碰撞,我不是之前发生的碰撞,同时呢我也是要最小的,为什么,因为我是想要找到第一个发生碰撞的时刻对吧,我希望找到的是这个点,而不是这个点。

所以说我可以利用这个1v2 次方程,我对这个t求解,我就可以找到这个点跟这个求发生碰撞的这么一个过程了,好吧,这里就是我反正就是给大家举几个比较简单的例子,我们可以利用这个远程。

我们可以拿来做一些比较基本的这些计算,那么接下来我们讲白点车,我们再来讲另一种乘法,矢量跟矢量的乘法叫做cross product,就是差成,那么差成它的定义是什么样子呢,定义是这个样子的。

这个反正大家我相信我相信大家应该呃之前上一些数学课啊,反正会会学到,我也就不重复了,那么它的几何定义我觉得是比较重要的,就是几何定义是什么,几何定义就是说如果说给了你这个p跟q。

然后同样它的夹角是c塔的话,那么我乘出来的这个向量,注意啊,这个叉乘乘出来的是个向量,它跟点乘不一样,点乘得到的是一个标量,叉乘乘出来的是一个新的向量,这个新的向量它跟p跟q都是垂直的,换句话说。

r点乘p等于零,点乘q也等于零,因为点乘等于零就意味着垂直嘛,所以说第一个第一部分,第一个条件就是说r跟p跟q都是垂直的,第二点r的这个大小的是p的大小乘以q的大小,再乘以sin theta啊。

这个就是r的大小,大家可以看到这个其实跟点成稍微有点像,但是又不一样,因为点乘是cosin set,而差乘它是sin the,就是稍微有点小小的区别,然后第二个有意思的点是什么。

第二个有意思的点是插成它跟顺序有关,如果说你把这个顺序倒一倒的话,那么得到的是一个相反的值,为什么,因为你可以从定义出发嘛,你可以定义出发,你可以看到每一行它是什么。

py乘以q z减去p z乘以q y所以说你把p跟q如果倒一倒的话,他得到的是相反的值,也就是说p cross q等于负的q cross p,这个是大家要注意的,就是差乘它跟顺序有关,它跟你先后顺序有关。

然后插成同样满足分配率,这个跟正常的乘法是一样的,然后呢差乘如果等于零,这意味着什么,如果说两个向量非零向量,它的差乘等于零,注意哦,大家注意我这个零是用黑体字来描述的,它不是正常的零,它是一个黑体的。

黑体的零,意味着这是一个零向量,它是一个向量,它是零向量,如果说两个非零向量,它的差乘等于零向量,那么唯一一种可能呢就是sc它等于零,对吧,那sin theta等于零意味着什么。

意味着ta等于零或180度吗,那么c它等于零或180度,什么意思啊,就是说p跟q它俩是平行的,p和q或者是同方向或者是相反方向,总之他们他们是平行的,只有这种情况下,我的差乘才等于零。

所以我可以利用这个cross product,我可以拿来做一个关于平行不平行的这么一个判定,好我现在有插成了,我现在就给大家举几个例子吧,首先第一个例子我来计算一个三角形,它的面积跟法向。

首先假设我们有个三角形,在一个三维空间里面有个三角形啊,然后这个三角形有三个点构成x0 x一和x2 ,然后呢我特别我特地选了两条边,这两条边分别是零一边跟零二边。

我用x10 x20 来表示这个x110 跟x20 就是x一减x0 ,还有x2 减x0 ,就分别用这两个东西来表示这两条边向量,那如果说我要计算它的法向,我其实就想得到一个方向。

他分别跟这两条边向量是垂直的对吧,那么我们记得我们cross product就可以得到这么一个东西,这点这个东西呢就分别跟这个这两个向量垂直嘛,所以说我就可以利用这个cross product这个特性。

我可以得到一个方向,这个方向能够跟这两条边向量垂直,这就是我们norm的计算方式,当然这不够,为什么,因为我们正常情况下,我们想一个norm,它必须是一个单位向量,所以说做完差乘之后呢。

我要normalize一下,我要除以它的这个大小,我就可以得到这个法向量了,好吧,这就是一个很简单的一个计算三角形的法向量的一个方式,我可以通过插成,然后做一个normalization。

做一个normalization,我就可以得到这个法向量,那么我们讲了这个插成我可以拿来利用这个插成的方向,我拿来定义n,那么接下normal,那么接下来我们来讲一讲,就是差乘的大小是个什么东西。

我们先来看看面积吧,这个面积是什么呀,面积三角形的面积等于什么,三角形的面积等于三角形的底边乘以三角形的高除以二,对不对,大家学过初中几何都知道吗,三角形面积等于边乘高除以二,这个h就是三角形的高。

然后这个x10 的norm就是这个底边的时流量的大小,也就是它的底边的长度,最后除以二,那么我知道这个三角形的底边的norm,这个它的这个长度,接下来我们来看看这个高是什么高,我们可以利用这个sa斜边。

我们来找出来对吧,这条边是这个三角形的斜边,这个斜边的长度呢是二零这条边的norm,所以我们可以利用这个斜边的这个大小长度乘以sin theta,我是不是就可以得到这个三角形的高了对吧。

我就得到三角形的高了,然后呢我们就会发现一个很有意思的现象了,就是这个东西啊,它跟cross product的大小其实是一个东西。

product两个矢量的cross product的大小等于这两个矢量的大小乘积乘以sin theta,所以呢这个东西就是等于一零这个向量。

这个边向量cross product x20 这个变向量它的这个norm它的大小除以二,这个就得到了三角形面积,所以我们利用这个三角形两条边向量,它的这个插成这个cross product。

我们可以达到两个目的,我们可以计算边啊,我们可以拿来计算三角形面积,同时我们也可以计算这个三角形的法向量,我们可以一石二鸟,那么这里有几个点是比较有一点是比较注意的,就是说这个跟顶点的顺序是有关系的。

我们这里呢是假设这个是零,这个点是一个点是二对吧,我们是有这么一个顺序,所以说我们得到的这个norm根据右手法则,如果说我们换一个顺序,比如说这个点是x0 ,但如果说我把这个点做x1 。

然后这个点做x2 的话,那么按照右手法则,我们得到的法向量,我们得到的normal是什么呀,我们得到的normal就是这个方向,对吧,所以说三角形当我们用顶点来定义三角形的时候。

我们不光是需要这个三角形顶点的顶点位置信息,它的这个顺序也是非常重要的,在我们来定义三角形的时候,它这个顺序也是很重要的,这个东西呢我们通常叫做它的拓扑顺序或者是拓扑关系啊,大家要比较留意。

就是说啊在给定三角形的时候,就是不光是顶点位置,它的顺序也很重要,好吧,然后还有一个小的问题,就是说给个三个点,你怎么来判断说这三个点是不在同一条线上。

反正我也想给大家就是作为一个小小小的一个课后思考题吧,就是呃可以考虑一下,利用刚才我们讨论的这些东西,好我们刚才讨论了这个三角形,我们接下来继续讨论三角形,不过这次我们搞的稍微深入一点。

就是给定一个三角形,我们怎么来判断说一个点是不是在这个三角形的里面,它是三角形里面还是三角形的外面,那么做这个判定之前呢,我们首先来考虑一条边,假设我们来考虑这条底边吧,x01 好。

然后这条边呢它其实把这个三角形啊,它把这个空间呢分成两个部分,分别是内跟外对吧,这个地方我把它叫做内边内,然后这边就是y,那么我们来看一下,就是如果说p点是在三角形的这条边的里面,它会发生什么样的现象。

假如说我有一个p点,然后这个p点这边的这条边的里面,那么我会有一个小的三角形,这个三角形啊,这个子三角形呢是由这三条边构成的,x0 p还有x1 p这三条边构成的。

那么如果说我利用cross product来计算这个三角形的这个normal的话,你会发现在这个这条边的里面的时候,他算出来的正常情况下算出来三角形整体的normal会是一个方向,大家用右手定则。

右手定则去判断一下,假如说p是第一个点,零是第二个点,x一是第三个点,那么根据右手定则,我从p出发,然后到x0 ,再到x1 ,然后我的大拇指告诉我的这个还是向上的方向,那么换句话说。

x减x p x0 减p cross x一减p这个三角形的这个子三角形的normal,跟我大三角形的normal是同方向的,这就是一个关于p在这条边内部的一个状态。

那我们来考虑如果说p在这条边的外面是什么样的对吧,我们还是这条边嘛,我们还是这条边,这个笔画的真的是不舒服,现在假如说还是一条边,但是这个p呢现在跑到这条边的外面去了,外侧去了。

这个时候如果说我们还考虑个p x0 x一这个三角形会发生什么,我们根据右手定则,我们从我们的我们的手指从p出发到x0 再到x1 ,那么我们的大拇指给的方向是往下的对吧,也就意味着说。

如果说这个p点是在这条边的外侧,那么根据同样的公式,我们计算出来的这个子三角形对吧,这个小三角形normal跟大三角形的normal是相反的,这个事情就好办了,既然说有这个特性,那我就可以利用这个特性。

我去分别检测三条边嘛,我检测三条边,我看看这个p是不是都是在三条边的内侧,如果说这个p它都是在三条边的内侧,那么也就意味着是在这个三角形的里面,那么这个就是一个测试方法对吧,我首先我有这个p点。

根据这个p点的位置呢,我可以把这个三角形分成三个小三角形对吧,下面一个左边一个右边一个,然后呢根据我刚才这个公式嘛,只不过我把这个公式上面的这个顶点的位置稍微做了一下调整,我可以得到三个公式。

这三个公式呢这个这个东西呢就计算了这个三角形的normal,然后这个公式呢x一减p x2 减p呢就计算了这个三角形的normal,然后这个公式呢就计算了三角形的normal。

然后我分别把三个小三角形的normal算出来,然后我去跟m做一个点乘,我来看看是不是都是同方向的,如果是同方向的,也就意味着我这个p点都在变的内侧,那么也就是意味着说我这个p点是在这个三角形里面了。

否则的话就在三角形的外面,这就是一个方便的用来检测我这个p点是不是处在三角形内部的,这个方式,大家有什么问题吗,我想我想稍微停一下,这个以前大家有学过吗,就是说判断三角形是不是在三角形。

然后利用这个normal方向的这个方式是吗,ok,101学过的是吧行那我那那我就继续往下走,既然101学过这个就应该应该ok,有同学问是不是取决于n方向的定义,不取决于,如果说你m方向如果发生变化。

因为n方向的发生变化,取决于x0 x1 x2 的顺序,如果你把x0 x1 x2 顺序,反转过来它这个公式其实还是成立的,所以说所以说只要你遵循同样的其实只要你遵循同样的这个顺序,这个公式就是成立的。

只不过就是你一定要求是一定是要求是那个一定是要求是啊,同样顺序的,对对对,有有有同学问这四个点是不是在同平面,对我们是假设这四个点是在同一个平面的,这个也是一个很重要的假设,我刚才讲了。

说我们可以利用这个东西来判断这个点是不是在三角形的内部,那么我们接下来看看说我们这个点乘乘出来的这个值是个什么玩意儿,对吧,我们刚刚不只是做了一个呃一个方向的判断吧,我们光光有这个正负号不够。

我们还想看看这个值到底有什么含义,那么这里我们把它除个二,出个二以后会看到,就说因为这个东西它本质上是一个法向量嘛,in它也是一个法向量嘛,那么这个法向量它两种可能性,要么是同方向,那是相反方向对吧。

那么如果同方向我们刚才说了,这个p点肯定是在内部的,那么同方向的情况下,他这个normal呢又是一个绝对a呢,又是一个单位向量,那么也就意味着这个东西乘出来就是cross product的now。

也就是这个cross product的大小,如果是在外侧会发生什么,如果是在外侧会发生的事呢,是我们同样还是可以得到这个perfect的大小,只不过我前面多了个负号吧,我前面也说了,如果说他在外侧的话。

那么它会是负的,那么我们刚才讲了,如果说给了两个向量,它的cross product大小除以二,我得到的是面积,换句话说,我可以把这三把这个点所划分出来的这三个小的三角形的面积给它。

算出来x0 这个东西对吧,是x0 ,我这里是啊,我这里好像写错了啊,我回头会调整一下,就是分别是通过这几个点乘得到的这个a a2 是对的,a2 应该是对的吧,对a2 是对的。

a2 是通过零一跟p算出来的,零一跟p算出来的没错,然后零应该是通过零呃,零应该是通过,这里应该是一,然后这里应该是二啊,这里应该是零,a一呢是通过02p算出来的,对a一是通过零二计算出来的。

然后a0 是通过a0 是通过12p算出来的,a一是通过啊a0 a0 是通过12p算出来的,哎我搞得有点乱,反正就是大家理解这意思就行了,就是啊有三个小的小三角还行,这三个小的三角形。

它的面积呢就分别是这三个顶点,根据这个cross product跟点乘,通过这个and的点乘呢,我就可以把它算出来了,注意了它这个面积啊,它不是我们通常意义上的面积,因为通常意义上我们说面积都是正的嘛。

它实际上也是带符号的对吧,因为我们前面也说了,他这个东西有可能正,有可能负,说它可以是正的面积,也可以是负的面积,是什么样的情况,会有负的面积啊,p跑到外面去的时候,如果p跑到外面去的时候。

你就会发现由这批跟这几个顶点构成的这个小三角形有可能是负面积,不管是正面积还是负面积,我最终其实都可以有一个结论是什么,a0 加a一加a2 等于三角形的面积,大三角形的面积。

这个a呢就是x0 x1 x2 的面积,只不过呢在里面的时候,a0 a1 a都是正的,那么p跑到外面去了,那么可能有的面积就变成负的了,当然有的面积可能就会大于a了。

但是保证了它们的总和加起来都等于a这就是一个我们把它叫做sa,如果说我把这个a0 a1 a2 都分别除以a除以a的面积呢,可以得到三个值,分别叫做b0 b1 b2 ,同时呢它b0 b一加b2 。

它们全部加起来等于一嘛,我要满足这个a0 加a加a2 等于a的这个条件吗,这个叫做berry centric位,这个权重有什么作用啊,这个权重它其实可以像我们前面对线段做差值一样。

我们可以对三角形也做一个差值,这个三角形呢假如说我有三个顶点,i x0 x1 x2 对吧,分别把这个权重放在这个顶点的位置上面,我就可以得到它的这个p的这个点的位置。

这就是我所谓的barry centric interpolation,就是利用这个barry centric权重,我可以拿来做barry centric interpolation。

在图形学里面还是用的比较常见的呃,比如说我们我们在做渲染的时候啊,我们假如说我有个三角形对吧,三角形的三个顶点呢就是分别是三个像素嘛,中间有一个点,这个p的这个像素呢,我想要得得到这个p的颜色。

我该怎么做呢,可以分别计算这三个顶点上的颜色,然后我对这三个顶点上的颜色做一个barry centric interpolation,我就可以得到这个中间点的颜色了,就是一个比较简单的一个套路。

叫做ground shady,ground shading啊,就是啊所谓的girl shading就是分别计算点的顶点的颜色,然后利用三角形顶点像素颜色来决定三角形内部的像素颜色。

其实在传统的图形学的引擎里面,有图形学的这个硬件里面是一个很常见的套路,为什么要做这个事情,是因为早年的时候就是二三十年的时候,二三十年前计算机硬件的这个能力是很弱的,它不像我们现在有gpu。

什么gtx啊,什么各种非常的强大,这个显卡它这计算能力很弱,他没有办法对每一个点颜色的计算,所以呢它是通过这个顶点三角形顶点的颜色计算,然后通过这个差值来得到的。

因为差值的计算量比这个颜色计算的计要来的小得多,这个是一个很常见的一个硬件的套路,当然我们现在其实很少见到这种呃着色方式了,这种设定方式了,因为现在的话嗯嫌卡的这个能力已经很强了。

我们完全可以对每个像素啊,光线追踪都可以对吧,我们可以完全可以有能力对每个像素颜色计算,但是早年的时候通常大家都是用这种方式做的,只不过呃在实践里面。

大家通常来说是不直接拿来算berry centric weight的,为什么,因为百30weight对于每一个每一个pixel如果做计算起来会比较麻烦一点,而且计算量稍微大一点。

通常大家做的一个什么样的方式呢,叫做呃扫描线算法,skyline conversion,什么意思,就是我把这个这一行上的像素啊,说这个像素p在这个位置吗,那我把这一行上的像素都可以拿来一起做计算。

我怎么一起做计算呢,我可以把这个点这个像素算出来,然后我再把这个像素算出来,这个两个像素算出来之后呢,我可以在这个上面做线性差值,就是类似就是用几个线性插值的方式来做三角形内部的差距。

就是大概是这么一个套路,如果说大家大家上一些这个呃图形学的课,然后那个教科书比较老的话,尤其是是老的老版的教科书有可能会讲到这种skyline conversion,但是我这里就不具体展开了。

反正给大家传达的意思就是说给你一个三角形,然后利用这个差值,利用bucentric weight,我可以拿来做各种的差值,我们刚才讲了三角形,现在我们搞的啊啊刚才有个同学问。

就是说权重成立的条件是p在三角形内部吗,嗯不成,不需要p如果在三角形的外部,它也是成立的,p在三角形外部的话,它的权重是有可能会是负的,说p在三角形内部的话,它三个权重都是正的值,都是大于零的值。

但如果在三角形的外面的话,就是有的权重会是负的值,所以说这个其实就是刚才我们讲的,就是利用正负号来判断是否三角形这个点在三角形内部的一个条件,就是利用正负号来这点来判断,我们现在呃搞得更高级一点啊。

我们刚才讲的三角形,接下来我们搞得更高级一些,我们来讲四面体这个这个101有没有讲过,什么呢,我们现在搞得高级一点好不好,我们来讲四面体,四面体是由四个顶点构成的对吧,x01 x2 x3 有四个面构成。

四个顶点构成,说跟三角形相比呢,我们就唉我们搞个高级的东西,我们就多了一条边,我们有三条边了,我们现在分别定义三条边,大家看到分别是一零这条边啊,然后呃二零这条边,三菱这条边,我们有三条边。

然后呢我们先来讨论一下,我们来怎么来计算这个三角形的啊,不是三角形,四面体的体积,我们之前讲三角形,我们不是用面积讨论,说了半天面积嘛,那我们接下来我们就来讨论4g4 面体的体积这个东西。

那怎么来计算这个三角形的体积,我们想利用公式公式呢,就是这个公式就是体的体积等于面积的底面积乘以高除以三,这个公式,等于底面a乘以高除以三,底面是什么呀,底面积呢是x10 ,cross x20 。

the magnitude的除以二嘛,我们刚才讲了三角形面积怎么算,来利用这个东西算不算了,三角形面积我们有底面了,四面体的高是什么,四面体的高,这个x3 这个高啊。

就是三菱这条边normal上的投影嘛,对不对,这个normal怎么算啊,这个normal就是x10 cross x20 ,它的大小对不对,这个就是normal嘛,就是利用这个底面算出来的normal。

这个x30 跟他做一个点乘,我就可以得到他的高了,把这两个乘起来,我得到了什么呀,我这个a有这个大小,它也有差生的大小,只不过一个在分子上,一个在分母上,所以他俩就抵消掉了,对不对,抵消了。

然后这里有个1/2,那么这个1/2就乘到前面的1/3,我就得到了1/6,这个体积等于1/6的x30 乘x10 ,x乘x20 ,这个就是四面体,计算四面体体积的公式,这是一种写法哦。

大家有的时候也会看到另一种写法,这个反正我给大家提一下,就是有的时候大家会看到我具体就不展开为什么了,如果说大家做推导,其实会发现这两个是一样的,就是我把这个三个顶四个顶点啊,把它当做四个向量。

然后给它写成一个行列式的形式,第一个列就是x1 ,最下面是一,第二列是x2 ,最下面是一,第三列是x3 ,然后最后是x0 ,这是一个4x4的行列式对吧,为什么,因为有四个嘛,有四个向量嘛。

每一个向量都是一个三维向量,然后最下面加了个一,所以说它的高呢也是四对吧,所以这是一个4x4的行列式,这个4x4的行列式呢十跟这个点乘叉乘这个玩意儿是一样的,最后你如你如果计算,你会发现这两个是一样的。

然后最后前面有个1/6,所以说我要保留这个1/6,所以说这个也是一种计算体积的写法啊,不同的写法反正就是给大家呃提一下醒,就是如果说大家看到这种形式的话,可以呃讲到这个东西其实就是在计算四面体的体积了。

我这里给大家了一个四面体体积的计算公式吗,可以注意到什么,注意到一点是这个计算公式跟我们前面三角形的计算公式,面积的计算公式其实有一点像像的点在哪里啊,有点像的点在于他们都是带符号的。

前面讲到算三角形面积的时候,我可以是正的面积,也可以是负的面积,四面体的体积呢它同样也可以带负号,它可以是正的,也可以是负的,大家会想说哎这个体积是负的,是个什么状况,是是个什么东西啊。

是怎么会有负的体积,那么这个就给大家举这个给大家看一下是什么样,左边是正的正体积,右边是负体积,体积是什么样的呢,就是说x0 x1 x2 x3 嘛,你根据这个底边这个底面积算出来这个normal啊。

这个x30 这个底底面的normal同侧的,我就把它做作为一个正的这么一个四面体,它是一个正体积的一个四面体,那如果说x3 跟这个x0 x1 x2 算出来的这个normal它是方向的。

那么你算出来的这个体积它就是负的了,把它叫做有的时候也把它叫做一个被反转了的四面体,因为我们正常情况下,我们都是假设四面体都是正体机嘛,如果四面体的体积啊变负的了,那么也就是说这个四面体它给翻过来。

他凹了个面,然后还有一种情况就是灵体机,灵体积意味着什么,灵体机就意味着它它是在同一个面上的,也就意味着它是灵体积的,这就是体积的定义,体积呢它是可正可负可为零的,有了这个体积的定义呢。

都可以跟三角形一样,我可以搞一个bl centric weight了,因为我前面不是讲我们说我们有一个面积,然后三角形面积可正可负,然后我可以利用三角形面积可正可负的这个东西。

我可以拿来算每个点的权重吗,对吧,我可以把利用这个p,我可以把这个p我可以把这个四面体分成四个,然后每一个小四面体就对应着四编码四个四个面嘛,因为四面体有四个面嘛。

那么这个四个面呢跟这个p呢就构成了四个小四面体,这个小四面体,四个小四面体的体积呢就是分别是那个计算公式,分别是通过这个0120123跟p搞在一起的,那有这个小的四面体的体积之后呢,拿来做判定对吧。

p什么时候在这个四面体里面啊,那就必然是这个四个四面体的体积都是为正的时候,这个其实跟我们前面讲的这个三角形那个判定方式是一模一样的,一模一样的,同时我们也知道这个四个体积加起来等于什么。

就整个四面体的体积嘛,所以说我们除以整个四面体的体积,我们就可以得到了这个差值的权重,这个by centric weight了,然后这个weight呢我可以拿来对于每一个顶点呢,我都可以加上这个权重。

我就可以拿来得到这个p的点的位置,所以说其实本质上跟那个三角形其实是一回事情,无非就是说呃我对多了一个点,多了一个点,带来了什么呢,带来了我从这个面面几道体积的转换,然后从面积到体积呢。

我就多了一些计算,但本质上跟三角形,我们计算这个bo src weight是一个概念,是一回事情,这个就是一个你可以认为是一个高级的一个三角形差值的一个版本,只不过是我们现在作用到了这个四面体上。

我利用这个东西我来给大家举一个例子吧,什么意思呢,就是一个点跟三角形碰撞的例子,就是我怎么来判断说我一个点跟三角形呃,有没有发生碰撞吗,那所以我假设这个三角形是静止的,这个点在运动。

这个点的运动方式呢是从p点出发,沿着这个速度的方向,然后运动对吧,然后我想知道有没有发生碰撞,怎么做呢,我把它分成两步做,我想要知道说这个点什么时候跟这个面发生碰撞了,就是这个三角形是落在一个平面上的。

那我想要找到的是这个点跟三角形所在的平面什么时候发生碰撞,那么我这个东西呢我可以利用这个公式吗,这个p t减x0 ,假如说这个p是碰撞的点的话,它落在这个三角形的平面内。

意味着这个四面体就是由一二还有p t这四个这四个点构成的,四面体体积为零,那体积为零的体积公式是什么呀,体积公式是点乘再加差成吗,我就x一乘以across x20 ,然后呢我跟这个ppt减x0 做个点。

这个就是它的体积公式,要求体积等于零,也就是告诉了我发生碰撞的时刻,我把这个东西做一个展开,p等于p减x0 加tp减x0 等于p减x0 加tv对吧,那这个东西呢我可以利用这个分配率。

我可以在啊对这个公式稍微做一下整理,最终就得到了这么一个结果,就是t等于p减x0 点成一堆东西,然后除以v点成这么一堆东西,到了这个t了,到了这个t以后,也就意味着我得到了这个p t。

这个点跟这个平面相交的位置还不够,为什么这个相交点它有可能是在这个三角形里面的,也有可能是在三角形外面的,所以我们接下来我们还要进一步的检查,说这个pt是不是落在这个三角形的里面检查呢。

我们就前面这个例子就是利用这个呃这个by central weight,利用这个三角形的这个子面积啊,这些东西检查,这个我就不重复了,反正大家如果还记得这个前面这个三角形内外的检测是什么样子的话。

这个我们就利用这个套路,我们做检查,就是把它分成两个部分,第一部分呢是利用这个体积公式,我可以计算相交的位置,点面相交的位置,然后第二呢我是检测相交的点是否落在三角形内侧,这个大家有什么问题吗,嗯。

写什么,反正今天时间我就是时间不是很充裕,我就想接下来我把这个稍微再讲一讲,然后可能会留点尾巴,到下次再讲,这里面的插成,这个我的小虎牙,这个问的问题,x1 x2 x3 ,你是指这个吗。

这个需要加括号括号,但是我这里不加,因为为什么,因为点乘,因为点乘只能跟另一个向量所啊,所以说这里其实是有个括号的,只是我这里没有加而已,默认这里是有个括号的,是行列式啊,这里你可以把它认为是行列式啊。

不可以变化,如果你顺序发生变化的话,会导致这个行列式变成负的值,你还记得行列式的定义的话,它其实跟顺序有关的,如果说你把那个两列或者两行发生顺序发生改变的话,它有可能是负的。

所以说尽量大家遵循这个顺序吧,如果说你发生呃发行列式的值为负的话,就有可能有可能是你顺序有问题,接下来讲那个讲讲讲矩阵吧,忘光了也没关系,反正就是给大家提个醒,就是跟行列式是有关系的。

那矩阵矩阵这个东西其实就是把矢量叠在一起啊,就是可以认为是我有一堆呃值,我有一堆时速的值,然后把这个时数值分别用行跟列去描,我们在图形学里用的比较多的可能就是3x3的矩阵了。

那么在这里就是a0 a1 a2 ,这样大家可以看就是呃相当于是三个矢量构成的这么一个矩阵,我们通常是只考虑实数矩阵的,在图形学里面,我们虚数考虑的比较少,也许有吧,但是反正我是没怎么见过时速比较多。

有一些比较简单的定义啊,这些大家如果说学过线性代数,学过矩阵的话,应该都是比较了解的,或者是起码是有概念的,如果没睡过的话,呃也建议大家回头稍微在这方面稍微补一补啊,就是确保大家都是记得。

然后呃几个比较简单的定义,一个是转置transport是什么呢,就是分别把这个零跟一零给换个位置,零二跟二零给换个位置,就是沿着对角上面的跟下面的换个位置,这个就叫转制一个矩阵,如果上下它是一模一样的。

那么我就把它叫做对称矩阵,就是沿着这条对角轴上下,这两个是一样的,这两个是一样的,这两个是一样的,那么我就把它叫做对称矩阵,如果说一个矩阵它早上有直,但是非对角上是没直的,这里全部都是零对吧,对角上啊。

对角的地方都是零,那么我就把它对角矩阵,我就把它叫做对角矩阵,一个比较特殊的对角矩阵,就是如果说对角上全是一的话,就叫做identity matrix,我有点不太记得了。

这个identity matrix,大家大家,单位矩阵反正就是identity,然后跟矩阵之间我可以做乘法,矩阵跟向量之间呢乘法,但是我这里就不细讲,不展开了,因为写来写了一大堆公式。

可能大家也不太记得,或者是大家其实都,所以我就不重复了,反正就是如果说你不太记得这个怎么做乘法的话,呃,要回头补补课,就是知道这个矩阵乘法,还有矩阵向量乘法是怎么做的好吧。

因为乘法呢它其实是有一些规律的,就是有一些呃,有一些有一些细节的,比如说矩阵乘法顺序有关的,乘以b它是不等于b乘以a的,这个大家需要特别注意,就是你不能改变矩阵乘法的顺序,a乘以b再乘以一个x呢。

满足结合律的,就是你可以先对ab做乘法,可以先对bx组乘法,这两个最后乘出来是一样的,就是你想按什么样的这个组合去做乘法,这个没关系,ab的转置等于b的转置乘以a的转置,就是你可以分别对a b做转置。

但是呢你要把它的前后顺序给倒一倒,是一个蛮重要的点,然后如果说一个矩阵它不对称,你要想把它变成对称啊,把它乘以它自己的转制,比如说我有个a不是对称矩阵,我乘以它自己的转制。

那么它的转置等于a的转置乘以a也就是意味着说你乘完之后,这玩意就对称了,这是一个蛮有意思的一个方式,就是你可以把这个呃利用这个呃,你可以把a变成一个对称矩阵,还有一个套路,这个套路不太常见。

但是有的时候大家也做什么套路呢,就是a加上a transpose,其实它其实也是一个对称矩阵,这个转置等于他自己,这也是一个套路啊,给一个单位矩阵一个i identity matrix,你乘以一个向量。

等于这个向量乘了等于没乘,这个就是identity的一个特点,如果说你这个t0 mx跟矩阵相乘,那么也是成了没成,就成了等于没成,还有个东西叫什么呢,叫做逆矩阵,就是inverse。

inverse是什么呢,是等于如果一个矩阵它有inverse,那么它这个矩阵乘以它的verse identity,这乘呢可以左乘,也可以右乘,没关系,就是如果说你乘在左边,乘在右。

你都可以得到identity,这就是他举证的inverse的定义,如果说一个矩阵有inverse的话,它是唯一的,a乘以b的verse呢等于b的verse乘以a的verse,这个跟转职有点像,有点像。

都可以分别对ab做inverse,只不过顺序需要倒一倒一点呢,是不是所有的矩阵都有verse的,这个大家也比较容易理解,就是说举个例子嘛,比如说全是零对吧,你全是零,那你怎么算verse,你再怎么算。

他都不可能等于identity,因为零乘以任何数,零乘以任何数都等于零嘛,所以说你不管怎么去构造这个矩阵,乘出来最后都是零,所以说它是不可逆的,它没有verse。

可能如果大家学过线性代数或者是有一定的这个基础的话,应该是都比较了解的,我觉得这里就不展开了,这里有一个跟图形学相关的,我觉得可能是稍微比较重要一点的点,叫做authorial matrix,正交矩阵。

不能一死,就是说给你一个举证,这个矩阵是由正交的单为向量所构成的,有一个3d的矩阵吗,3x3的矩阵嘛,那么每一个a0 a1 a2 都是正交的单位向量,向量意味着什么,单位向量意味着它乘以它自己。

就是当i等于,这时候就是a0 乘以a0 等于一,a一乘以a一等于一,a2 乘以2=1,所以说它是单位向量,每一个向量乘以它自己点乘它自己等于一,正交意味着什么,这个是单位正交意味着什么。

正交意味着跟a一还有a2 做点乘等于零,因为他俩是垂直的,a一跟a2 做点乘也等于零,因为是垂直的,所以说它就是有这么一个关系,就是i和j相等的时候,乘乘出来的是一,如果是i跟j是不相同的时候,做点乘。

做transport乘出来的是零,一个定义正交矩阵的定义,用这个定义啊,我们会发现一个有意思的现象,就什么现象呢,就是我这个a它的转置相乘会发生什么,我把这个正交矩阵跟它的转置相乘,左边会是三行三行啊。

分别是a0 的转置,a一的转置跟a2 的转置,a是什么,是三列是a0 a1 a2 ,分别是三列十辆,那么最终乘出来的呢,线上呢就是a0 a0 a1 a1 a2 ,非对角上呢就是010212对吧。

然后根据咱们之前的定义啊,对角上的都是一对吧,然后非对角上的全部都是零,矩阵乘以它自己的转置就是identimatrix,就是一个单位单位矩阵,也就意味着如果说一个a sogonal matrix。

它是a sogonal matrix的话,那么它的转置就是等于他自己的逆,这个是一个正交矩阵比较好的一个优点,就是我们算逆会比较容易,因为通常情况下算矩阵的会很麻烦,但正交矩阵对于我们正交矩阵而言。

我算逆,我直接对他搞个转置就行了,矩阵我刚才说了,在图形学里很重要吗,那图形学里为什么很重要呢,因为在图形学里,他这种特殊的东西相关就是旋转相关,旋转相关呢,因为我可以把旋转用正交矩阵去描述。

你去理解这个东西,我想是可以通过这种方式去理解,我一般教课的时候,我会通过这种方式去理解,就是说你在这个三维空间里面有一个物体,比如说我有一个方块,一个立一个立方体,这是他初始的一个状态。

它在这个原始空间里的一个状态,我这个原始空间我可以把它叫做局部空间,就是它自身的一个空间嘛,前后就是z它自身的一个自带的一个局部空间,local space,这个叫local,我把它叫local。

通过这个某一个旋转矩阵啊,我把这个立方体做一个变形,我可以得到一个新的状态,之前这个local space跟xyz是重合的,因为我做了这个旋转之后,我这个立方体的前后左右上下就xyz重合了。

它就分别是三个新的方向,分别是uv跟w对吧,这个就是我新的这个我自身的这个局部空间,在中间的这个word space里面这个的一个状态,那么,a有什么关系呢,现a乘以x,因为a是做旋转的嘛。

那么a乘以原来的x就是原来的这个左右,我是不是就得到u啊,a乘以y我是不是就可以得到v啊,a乘以z我是不是就可以得到w啊,x是什么,x是100,是010,z呢是001。

a乘以identity等于u v w,其实成不成无所谓嘛,所以说也就是意味着a等于u v w,v w是什么呀,u v w是坐标系啊,标系是个什么玩意儿,坐标系它是三个单正交的向量嘛,它是垂直。

同时也是单位向量嘛,所以也就意味着这个a它是一个正交矩阵,是一个a soga matrix,那它本质上这个旋转矩阵就是这个局部坐标系在市中的状态所描述的。

所以这个就是实际上就是旋转矩阵跟旋转跟一个关系的,这个大家如果上过呃基础图形学课的话,应该就是会了解这个概念,这个反正就是我给大家重复一下,就相当于给大家一个呃,一个可能是或者是你没听过这样的解释的话。

可以得到一个新的解释,就是你可以通过这个矩阵可以把这个局部坐标给它抠出来,旋转相关的形变的,还有一种形变叫做放大缩小,叫scaling matrix啊,压缩小,比如说我同样一个立方体。

我现在要沿着x y z做缩放,那我怎么做缩放呢,我可以定一个矩阵叫做d,然后对对角矩阵上的值呢分别就是三个方向的缩放量,这个dx就是x方向的缩放量,就是y方向的缩放量,然后z就是z。

所以说这个scaling matrix呢就跟diagonal matrix有关,是举证啊,可以用矩阵来描述旋转和缩放,这个我想大家嗯有没有有没有学过,之前,如果说大家有一点图形学基础的话。

我想可能应该应该学过这些,是不是,好吧,现在我们来接下来讨论下一个东西,刚才讲了旋转是a soga matrix,对角是sky matrix,那么接下来讨论一个点叫什么和特征值分解。

是不是觉得听了觉得特别慌,反正我以前学线性代数的时候,是听了这个特征值啊,什么东西,反正就觉得特别的头大,其实特别有意思啊,就是他在图形学里面其实是有个非常类似的解释的,那我们先来看看。

来看看这个特征值分解是个什么玩意儿,好不好取证,假如说我有个矩阵a是分解是什么意思啊,就是说这个矩阵可以分成三个部分啊,d还有v的转置,dv它有什么特点啊,它是对角,它是一个对角矩阵,这个d里面的值呢。

这个对角上的值呢就叫做特征值,不叫特征,叫奇异值,不好意思,我搞错了,这个是single value,这个是奇异的value,中文是奇异分解,这个d呢是single value,对对对,气质不好意思。

然后uv呢是matrix,是正交矩阵,什么意思啊,对不对,我我反正我以前学线性代数的时候,就是光学数学课的时候就有点懵对吧,这个东西到底有啥意思,可以这么理解,假如说两个形状,你给一个物体。

假如说我有一个方块儿,通过某一种线性的变换,我通过一个矩阵的线性变换,我得到一个方块的一个新的形变的话,value decomposition,它本质上就说了一件事情,什么呀。

这事情是说什么样的线性的形变,它本质上都用三部分三个操作去描述它,三个操作呢分别是旋转,是v transpose做的是把这个方块呢转到一个,至少我要把它转到一个特定的位置上的。

是因为接下来我要做一个缩放,就是由d表示的,为什么要做这个旋转,是因为在做缩放的时候,我必须沿着坐标轴缩放啊,沿着x跟y缩放,所以说我需要比如说我缩放的时候,我想要演某些非主要走方向的旋转呢。

啊缩放呢我就给它做个旋转,我把它做这个v transport的旋转,我给他转到某个位置上,然后我再做说法,比如我举了一个比较简单的例子,假如说我想要沿着对角方向做缩放嘛对吧,就把它先把这个方块转45度。

我给他转到对角上,我让我的对角跟xyz重叠啊,我在做缩放,那么是不是我就可以呃对角方向上做缩放了对吧,然后做做放,然后最后呢一个旋转我把它转到我想要的位置上去啊。

事实上这个single value decomposition,它其实就说了一件事情,就是说线性变换它可以通过旋转缩放旋转来实现,这个核心是什么,它这个核心是这个scaling啊。

它实际上核心是这个东西,就是缩放啊,就是说不管什么样的这种线性变化,它本质上都是缩放嗯,它这个缩放是可以任意方向的,它可以是有的是x y z方向的,就需要对这个物体做一个调整,然后调整完了以后。

我做缩放,缩放完了之后再给他转到想要的方向上去,这个就完成了我整个线性的这个过程了,这个其实实际上就是singular value decomposition,它的本质我们回头会呃,这是一个二维的例子。

但是四面体的例子是一样的,我对四面体它的形变也是这么一回,我也可以用三维的旋转,三维的缩放,三维的旋转来实现,可以做奇异值分解吗,是的,所有的a都可以做奇异值分解。

所有的a都可以做single vaccommodation,然后这是single videcomposition。

然后value decomposition相关的另一个呢就叫做angle value composition,就是特征值分解,刚才是起止分解,然后现在我们讲的是特征值分,然后这里你那图形学里面呢。

我们一般来说会考虑的稍微简单,那么简单一点点,简单的在哪里,简单的点在于我们只考虑对称矩阵的特征值分解,那么对称矩阵的特征值分解呢什么样子呢,就是可以把它分成ud,还有u verse。

把它想象成value decomposition的一个特例,就是当你这个矩阵是对称的时候啊,就之前它是u跟v嘛对吧,value decompetition是左右是u跟v,中间是d and value呢。

你左边呢跟右边就一模一样了,因为是对称的嘛,只不过呢这里是inverse,不过应不应verse无所谓,为什么,因为有矩阵,这个跟single valley competition是一样的。

那正交矩阵的inverse跟他的transport其实本质上是一回事情,所以说我这里写verse,但是我写transport啊,本质是一回事情,是没有区别的,这个就是它的特征值分解分解。

其实我们在数学书上,其实它的定义会稍微有点有,有的数学书上它一开始定义会稍微有点不一样,它不是这么写的,他是怎么写的,他是这么写的,如果说把you把这个正交矩阵写成一堆向量的话对吧。

ui u0 u1 u2 u3 的话,乘以u i等于什么呀,a乘以u i ud u transport chui,这里我用transport,我这个就不用-1了。

这个不用verse transpose乘以ui,然后u呢它又是正交矩阵,所以说一个正交矩阵你去跟他自己的一个向量相乘,你得到的是什么,得不到得到的不就是一堆零加一个一吗,就是一堆零对吧,上下都是零。

然后i的这个位置呢就是一,因为正交矩阵嘛对吧,这个就是一堆0+1嘛,然后再乘以d再乘以u y是什么呀,这个y这个d是什么呀,d呢是一个对称的一个对角矩阵。

那么一个对角矩阵乘以这个0001得到的就是000,原来这个一的位置给他用dt换掉了,然后你得到的是一堆000,然后中间di然后再乘以这个you呢,你等于就是di乘以ui了,这个ui抠出来。

然后再乘以这个df里面呢di呢我们刚才所讲的叫做特征值,我们就不叫奇异值了,叫做特征升值,然后这个ui叫做特征向量,这个是记得印象中是教科书里面比较常见的写法,就是说a乘以矩阵a乘以一个特征向量。

等于这个特征向量乘以某个特征,这是一个比较常见的写法,这个我印象中式教科书里面是一般来说是这么写的啊,这么定义的,这个就是这跟大家会发现这两个东西其实是一回事情,只不过呢嗯这是叫做写法。

然后这个是跟特征值的,跟那个奇异值的写法是比较相近的一个写法,这后面这个后面这个东西其实在图形学里面嗯用得到不是特别多,所以说反正大家听一听就完了,就是如果说大家觉得这个特别很懵也没什么关系。

反正就是嗯就是我其实就是想跟大家说一下,就是这两个其实定义是一一样的,还想提一点呢,就是说我这里是说的是一个对称矩阵啊,是这样子的啊,其实呢对于非对称的矩阵呢,我其实也可以做特征值分解。

如果说非对阵阵的特征值分解呢,它这个特征向量跟特征值和特征的特征值和特征向量,它有可能不是时速,它有可能是虚数,因为我们图形学里面通常不考虑虚数嘛,所以说我们就呃这个我们就不考虑了。

我们通常就只考虑对称矩阵,还有对证据取证相关的这个特征值分解,然后这个是特征值,跟特征值相关的有一个概念叫做对称且镇定,这个为什么重要,是因为这个东西跟我们处理线性问题,线性系统的时候特别有关系。

就是跟矩阵的一个特定的一个性质有关系啊,叫做镇定的对称,且镇定的镇定呢叫d呢,s p d也就意味着对于任何一个非零的向量,这个向量左右相乘,它都是大于零的,不管什么向量,只要它飞零。

这左右乘乘出来的是什么,乘出来的是一个实数嘛对吧,这个时速这肯定是大于零的,那么我就把它叫做是镇定的,是什么呢,对称半正定义是什么呢,当然它要对称啊,意味着它有可能等于零,相乘,有可能大于等于零。

那么这个东西就叫做半整点,这个是它的定义,大家这个教科书的定义,大家懵不懵啊,反正我以前学线性代数,我我中学大学里面学的时候,我觉得还是挺懵的,接下来我想给大家一个一个直观的感觉。

就是说这个玩意到底是个什么东西,对不对,什么叫做一个镇定,这个东西到底有什么用,给大家一个,就是给大家一个思考,就是说,我有一个数对吧,我一个实数,这个实数是大于零的一个正的实数,那么我把它放在中间。

乘以这个非零的向量是不是肯定大于零啊,对不对,为什么,因为你这个东西本质上就等于呃的平方乘以d嘛,然后v的平方就是v的大小嘛,就magnitude的嘛,然后向量的magnet的肯定是正的。

然后d肯定也是正的,所以说这玩意儿肯定是正的嘛,对不对,d它是个数,它不是一个矩阵嘛,那么我怎么跟这个矩阵联系在一起,对不对,假如说我有一堆时速啊,我不是一个时速,我有一堆时速。

把这些时速呢搞成一个对角矩阵,会发生什么,我如果左右都乘以这个向量,是必然大于等于零的,因为把这个东西展开,你会发现这个东西等于什么,这个东西等于d0 v0 的平方加上d1 v一的平方。

加上第2v2 的平方,加上d3 v3 的平方,然后一堆下去平方那肯定是大于零的,d它也是大于零的,所以说最后加起来肯定都是大于零的,一堆正的数加起来,它不可能是负的值嘛,所以说它必然也是。

因为这个东西等等于就是d i,的平方,然后全都加起来,其他肯定也是大于零的,那么换句话说什么,如果说我有一个对角矩阵啊,然后这个对角矩阵它每一个对角上的这个量它都是正的话,那矩阵它必然也是镇定的。

就是满足我们前面说的这个pd的这个定义的,就是这个镇定的定义的啊,我们再往下走,因为毕竟很多矩阵它都不是一个对角矩阵嘛,很多矩阵它都是奇奇怪怪的。

那么怎么我们把这个东西能够跟各种奇奇怪怪的矩阵联系在一起呢,我们可以这么想,我还是有一堆时速啊,还是有一堆d0 d1 d2 ,一堆正的时速,正实数正数啊,不是我还有一个这个you它是正定的。

当然这个矩阵正定的you,它可以是任意的,就是不管什么样的举证,反正我就是有一个举证嘛,会发生什么,假如说我把一个这么一个形式的话,根据特征值分解。

我可以写成you did you transport的话,是我刚才说的这个正交矩阵嘛,然后这个d呢甚至分解它特征出了,分解特征值分解出来以后会是一堆呃对角矩阵吗,如果说这些特征值都是正的话。

会发生什么看啊,我前后都乘以u乘以u transport,这个回影响这个等式,为什么,因为这个东西是identimatrix,因为u是正交矩阵嘛,对不对,是正交矩阵。

所以说正交他自己的transport等于identity,所以说这个不影响对吧,我们前后都分别先搞这么一个东西之后呢,我把这个东西呢给它拆成两半儿,分别跟前后相结合在一起,那又跟前面那个东西结合了以后。

我就得到了you transport v乘以transport,然后you transpose跟后面这个玩意就抵消掉了对吧,他俩就抵消了,这个u呢跟you transpose他俩也抵消了。

然后最终呢这个中间就是个d了,边呢右边呢就是得到了u transpose乘以v,那么你就得到了这么一个共识,因为我是假设它是一个非零向量,然后如果一个非零向量,一个正交矩阵乘以一个旋转矩阵。

它怎么我都不可能等于零吗,因为一个非零的向量,你给它旋转一下,它怎么都不是,可能是一个非零向量,所以说它肯定也是一个非零向量,也不是一个非零向量对吧,然后d是什么呀,一个对角矩阵。

然后对角上的每一个元素都是正的,那么这个东西我们刚才讲了,必然是大于零的,那什么这说明了一件事情,就是说跟前面刚才这个规律,如果说一个矩阵它的对角元素,一个矩阵,它是一个对角矩阵。

同时它对角元素都是正的,那么它必然是一个正定矩阵这个特点,那一个对称的矩阵,我这个对称矩阵根据这个特征值分解分解出来的特征值也都是正的话,必然也是镇定的,那么这个就是下面一个啊。

解释了就是如果说它是正定的,特征值都是正的,这俩是一回事情,是等价的,所以其实嗯我觉得就是从这个方面去理解,就是说如果说你可以想象一个正的数,我们什么叫一个正的数,这个大家可以理解吗,就是一个正的数。

就是它,非零的数的平移,一个非零数的平方,它必然是大于零的,对不对,那么同样的,如果说一个矩阵,一个对矩阵,它上面所有的东西都是正的,那么它就叫镇定的,那么此类推。

如果说我把这个对角上全都是正的一个矩阵,前后都乘以一个正交矩阵,那么它也是一个正定矩阵,因为是做旋转,是不影响它这个镇定性的,那么累我就可以得到了一个正定矩阵的定义,听起来很听起来挺有意思的。

但是呢我们是不会去通过特征值分解来玩正交性的,为什么,因为我们利用数值计算做特征值分解,一般来说是很慢的,计算量是非常大的,我们通常不会直接去做这个计算,我们可以用一些气他的法则来做这些判定。

比如说如果如果一个矩阵它是对角占优的,那么它一定是正定的,什么叫角占优,对角占优的意思就是它对角上的这个值啊,它是大于非对角上的和的啊,我们这里有个例子,就是我有个矩阵459,对角上是459对吧。

那么检查它每一行我不要求说每一行或者每一列呃,我不要求说每一列上都一样,或者每一行都啊,我只要去满足某一个条件,就我只要要求每一行或者每一列都满足就够了,那么那就假设我是按照每一列的方式去检查它。

那是不是大于3+0啊,不好意思,这里写错四,大于3+0对吧,大于1+3,对不对,大于八对不对,所以说这个矩阵是一个对角占优矩阵,那如果说它是对角占优矩阵,那么,正定矩阵。

这个是它的一个呃比较简单的判定方法,就是判断一个矩阵它是不是正定的,当然他不绝对啊,就是说它不是可逆的,就是一个矩阵是正对角占优的,它是镇定的,但是一个矩阵是正定的,它未必是对角占优的。

它是一个啊一个充要条件,明白吗,就是我们可以利用这个东西做判定,但是它不成立,也不代表说这个矩阵它不是正定的,只是相当于有的时候如果说对角占优的,我们是可以得到一个比较简单的结论的,做一个镇定的矩阵。

它必然是可逆的,为什么,因为a它的逆等于啊这个transpose d u的transpose逆嘛,然后这个逆呢是什么呢,这个正交矩阵的逆就是分别就是它的自己的转置嘛,然后一个对角矩阵它的镍。

因为它对角上的元素都是正的,所以说它也是可逆的,所以说一个sp d矩阵它必然是可逆的哦,就是主要是它的定义,然后嗯里面有有什么样的情况下会讨论会用到这个东西,我们到时候讨论有限元的时候。

还有一些矩阵的和弦的时候,就是矩阵的二次倒的时候,我们有的时候会涉及到这些东西,所以说我这里想把这些概念嗯重复给大家,然后也是希望就是在大家对这个东西有一些印象,就是如果说大家很懵的话呢,也不要紧。

然后再回忆一下,然后如果说大家对这个东西没有概念的时,候,概念的话也可以把这个东西稍微再看一下,好不好,我想我想今天就先到这里,然后我们还有一些呃,还有一些东西没讲,然后我们之后会继续讲这个解线性系统。

还有讲这个呃微积分就是tensor calculus这一块,我们下周会继续讲,然后我们下周剩下的时间我们会开始慢慢慢慢讲,缸体的模拟会逐渐过渡到我们实际的模拟的操作中,我想就先到这里,有没有什么问题。

大家,周一哦对了,还有一件事情,就是我们下周一我是想搞成线下课的,如果说大家想去线下上的话,可以通过微信报名,然后嗯我们房间应该是有40个位置,所以说只要不超过40个人,应该是问题不大。

如果说超过40个人,我们可以临时搬搬凳子或者找其他场地,反正如果大家有兴趣想去线下课的话,可以可以报名参加,然后只是在浙江大学紫金港校区校外,大概步行大概也就234百米的距离,反正很近,如果是浙大同学。

反正在紫金港就很方便,如果是杭州本地或者是杭州周边的同学,如果感兴趣的也可以来好吗,没有什么问题的话,我就光速下播了,好那佳佳,大家恰饭吧。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

GAMES103-基于物理的计算机动画入门 - P3:Lecture 03 Rigid Body Dynamics - GAMES-Webinar - BV12Q4y1S73g

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

是不是我们是不是都是浙大的同学为主啊,浙大同学举下手,让我看一下好吧,那就相当于是基本上是浙大专场,感觉,你们前两周的那个看了吗,还是发水,反正我们今天今天就继续往下讲好吧。

今天主要就是我们上周主要是讲了那个哎这听得清吗,可t吗,我们上周主要讲的那个就数学那一块嘛,但是没讲完,留着点尾巴,所以说我想把剩下的部分讲完,嗯然后讲完数学之后呢,我们会呃讲一下刚体。

然后刚体我主要是想分成两次来讲,我们今天讲一次,主要是讲就是当单个缸体本身的一些运动,比如说位移压旋转啊,然后你怎么样啊,写一个物理引擎,这是这周,然后我们下一周主要是讲碰撞这一块。

就是呃缸体跟别的物体它如果有接触,我怎么样处理钢体跟别的物体之间的接触,然后怎么样能够让钢铁不要跟其他物体发生穿透,就是把它分成两节课来讲啊,但是我不会讲的特别完,因为刚才那个冯旭东你也讲了。

就是就是钢铁,它其实里面还有很多,就是比如说带约束的钢铁,比如说我们做人体,那么人体骨骼的话,它其实可以认为是一种钢铁,但是呢他这种缸体它是由几个缸体构成的,然后这些钢笔之间彼此又有约束。

它是连接在一起的,那这种的话我想到时候我们讲专门会有一节课,讲约束的时候,我们到时候会回过头来讲怎么样处理,就是多个物体之间的约束关系,但是这次呢这周呢还有下一周呢,我们主要是讲单德纲写为单个缸体为主。

听得见吗,有回声是吗,我不是那么处理,我在想是不是因为这个原因,等一下,现在呢,回声好点了吗,等一下我看看是不是因为我这里有两个声音的那个,是不是删掉一个,嗯这个怎么删除啊,我是不是把这个关掉。

会不会就没有回去了,就关掉,那我就把它删了吧,感觉,现在呢现在还有回声吗,哈喽哈喽哈喽好了啊,那可能就是因为有两个麦克风的原因行行,我们上周就是呃呃讲了半天取证,然后讲了一下矩阵的正定这个东西嘛。

然后给大家一个呃一个小quiz,就是你怎么样证明一个矩阵是正定的,就是这里我想给大家举这么一个例子,就是假如说a是symmetric positive definite的,呃。

你怎么证明b然后b是这种样子,a负a负a a它必然也是半正定,那我为什么要举这个例子,是因为等会儿我们会看到,其实我们有很多的矩阵在模拟里面有矩阵是类似这样的形式啊,所以说如果说你要保证b是阵地的。

你只要证明半正定的,你只要保证a是正定的就可,那怎么证明呢,我们可以用定义去证明它,呃我假设啊有一个向量我可以把它拆成两半,一半是x一半是y对吧,这个向量可以是任意的向量,我我并不知道。

我并不知道这个向量是什么样的向量,反正我就有这么一个向量,那么这个向量呢我可以把它分成两部分,x跟y分成x跟y之后呢,我分别在b的左边跟右边,我都把这个向量乘上去,那么按照我镇定的定义,半正定的正义。

我需要证明的是什么,我需要证明的是嗯,我需要证明的是这个东西它必然是大于等于零的,我只要证明这个东西是大于等于零的,那么也就是意味着说b肯定是半正定的了,那么我怎么证明说这个东西不管xy是什么玩意。

我总归是大于等于零的呢,那我可以根据矩阵乘法的规则来说对吧,我根据b的定义,b是呃,这边是a负a负a a然后左边右边分别是x y那我把它乘一下,乘一下,完了以后我得到了什么。

我得到了x transpose乘以a乘以x减y,然后减去y transpose a乘以x减y,大家可以简单的做一个乘法,就会发现,假如说我先把这个矩阵跟右边的相乘,我先把矩阵跟右边的相乘。

我得到了a乘以x减y,对不对,上面第一行我就是a乘以x减y,然后下一行呢是负a乘以x减y,然后完了之后呢,我再跟分别跟xy相乘,我就得到了我这个下面公式的第一行,然后得到下面公式第一行之后呢。

我再去把这两个东西合在一起,我就得到了x减y的transpose乘以a,然后乘以x减y,然后得到这个之后呢,我就知道这个东西肯定是大于等于零的了嘛,对不对,因为这个东西a是正定的,a是正定。

这也就意味着,不管x减y是什么,它永远都是大于等于零的,等于零,什么样的情况等于零,那就是x等于y的时候,它会等于零,否则的话它就永远是大于零的,所以说因为a是正定的,我也就知道了。

这个东西肯定是大于等于零的嘛,所以也就意味着不管我的xy取什么样的值,我都能保证这个东西是大于零的,所以说我就证明这个东西是证明半正定的,这个东西反正就是可以从定义出发嘛,我根据定义。

然后我去构造这样的状态,然后我确保说这个东西乘出来肯定是大于零的,大于等于零的,就是把它当成定理,这个就是给大家举个例子,然后后面我们也会用到类似的矩阵呃,然后当我们讨论到类似的矩阵的时候。

我就默认就是说我只讨论a的正定性就够了,因为根据这个我们刚刚证明过的,就是只要是正定的,那么b也是正定半正定的,嗯好吧,这个反正基本上就是我们就是正定的,关于镇定这一块,我们就讨论到这里呃。

然后接下来我会稍微讲一下线性系统,因为我们很多时候我们处理数学问题呃,不管什么样的数学问题,很多时候最终都会呃涉及一个问题,就是怎么样去解一个线性问题,那什么叫做一个线性问题呢。

它其实本质上就可以写成这个形式,就是ax等于b然后a它是一个矩阵,是一个方块,是一个方块矩阵,然后b呢我们一般把它叫做边界条件或者是boundary vector,就是等于等于的那一个部分。

然后x是我们的位置,我们不知道x是什么,然后我想得到x,我想把它解出来,然后这个东西啊,其实大家从小到大一直都在学这个东西,对不对,小时候就学怎么解这个二元一次方程,然后三元一次方程。

然后老师就教做什么消元法啊什么之类的,然后其实本质上从小到大都在学,然后到了大学里面,其实学线性代数本质上也是想要去处理这个问题,因为线性问题是很多我们科学问题的核心所在,最终都是要解一个线性问题。

那么怎么样去解决线性问题呢,一种比较简单的想法,就是我只要把这个矩阵的逆算出来,我如果能把这个矩阵的逆算出来,我这个问题就解决了嘛,对不对,因为我有了矩阵的逆,我直接做a inverse乘以b。

我做个矩阵乘法,我就可以把x得到了,但问题在于,问题在于a universe这个矩阵的逆这个东西是非常难算的,它不光是非常难算,而且很多时候我们的矩阵它是稀疏的,而矩阵的逆一个稀疏矩阵的逆。

它通常就不是稀疏的,那也就意味着本来我们的内存占有可能比较少,比如说我比如说我有10万的点或者是100万的点,那我构造出来的矩阵可能大部分情况下都是虚数的,那我不需要用很多很多这个内存去存这些值嘛对吧。

因为很多东西都是零嘛,但如果说我要算矩阵的逆,矩阵的逆又不是稀疏的,那我内存开销就一下就变得很大了,那不光是计算的问题,同时它也带来的就是存储的问题,所以通常我们就呃不直接的去计算这个主线的利益。

那我如果不取证直接转矩阵的逆,我怎么来处理这个问题呢,那通常就有两个方法,一个叫做直接法,一个叫做迭代法,直接法呢一般来说就是基于分解l又分解,当然lu分解它有很多变形啊,啊比如说kiosk。

比如说l d l t类似的这种其实都是l u的分解呃,主要的区别在于就是还是内存啊,因为lu分解它相对来说是最佳内存的,然后其次是l d l t,然后还有再其次是killsd。

因为后两者他们是对对称矩阵,它有优越性,因为为什么,因为是一个对称矩阵,对称矩阵就意味着我只要存一半就够了对吧,因为它是一个对称的嘛,上下是一样的,我内存存的时候我只要存一半,那如果非对称。

那我可能就要用lu,那么我需要一个完整的把它记录下来,那什么叫l u分解呢,l分解本质上就是这么个意思,就是假如说我有一个矩阵a呃,然后呢我可以把这个矩阵a呃分成两部分,然后呢一个是分别叫a一个叫u。

然后l呢是我们叫做下三角矩阵,就是它对角线的上面都是零,然后只有下面有直,然后呢u呢它是对角上有直,对角向下面是零,然后对角的上面是有直的,呃这个具体怎么分解我就不讲了啊,因为他这个涉及到它一个算法。

其实还是比较简单的,如果大家呃上过信息代数的,有些课程的话可能有些接触,但是我这里就不展开了,展开的话可能就是要花好几个礼拜的时间来讲这个事情,那我为什么要做这个lu分解对吧。

因为lu分解呢它主要的目的是什么呢,主要的目的是呃,他做了这个lu分解之后呢,我就可以很方便地解这个线性系统了,稍等我看一下,怎么呢怎么做呢,比如说我现在首先我第一步我要解ax等于b对吧。

那我第一步我先解a y等于b,那怎么解l y等于b呢,因为l是一个下三角矩阵嘛,那我对于第一行而言,我是不是就是l00 乘以y0 等于b啊,那就变成一个非常简单的一个小公式了。

l00 乘以y0 等于b了,那么我就直接就可以得到一步就可以到位,我就知道y0 等于b0 除以l00 对吧,那我第一个元素马上就可以得到,然后我做第二个,第二个呢我是l10 乘以y0 。

加上l一乘以y一等于b1 ,那么l0 我刚刚已经解出来了,我l0 已经知道了,那么我就变成了一个只有一个未知量,那么现在我l一就变成未知量,l0 变成已知量了。

那么我就变成b1 b一减去l10 乘以y0 ,然后再除以l1 ,那以此类推,我每解完一行,我就把这行的未知量给得到了,把y0 解出来,再把y一写出来,再把y2 y3 y4 y5 y6 。

就把y每一个y都给它解出来了,对吧,就是一个顺序的关系,那解完l y等于b之后呢,我再回过头来我解x,那这里呢我就是u x等于y是因为你把这两个合在一起。

你就会发现这个是本质上就是l乘以u x等于b那么我先把y解出来,相当于y是一个我的中间结果,我得到这个中间结果之后呢,我再去解x那对于x而言的话,这个u就是一个上三角矩阵。

那我u n n就是我最下面那个东西,就是呃就只有一个,那么我就是u n n乘以x n等于y an对吧,对于这一行而言,我就是一个非常非常简单的一个小小式子,那我就可以得到xn等于y n除以u n n。

然后呢得到x n之后呢,我再去解倒数第二行,我可以把n减一减出来,然后我再减倒数第三行,按顺序,然后最后把所有的x都剪出来,所以说这个就是本质上就是呃lu factorization。

你得到了这个lu分解之后,我可以利用这个下三角矩阵跟上三角矩阵,我按顺序先做一次,我就可以把x求解得到了,这个叫做直接把,因为就相当于就是一步到位,把所有的东西都算出来,嗯那直接法有什么特点啊。

首先第一个特点就是说如果说a是稀疏的,如果说这个矩阵是稀疏的,那么l跟u它就没有那么稀疏了,相对而言它其实还是稀疏的,但是它相对而言没有那么稀疏了,那么它的稀疏性体现在什么呢,它稀疏性其实跟行跟列。

也就是我们的这些每一行每一列的这个未知量的排列顺序是有关系的,就是你换个顺序,有可能它的吸收性就会发生改变,然后呢如果你的顺序好,那么你的l u就会比较实数,如果说你的顺序不是很好。

那么可能你就啊就就很不稀疏,就就变得有很多非零项,这就是为什么我们通常在做计算的时候都是还要再多一步,就除了你要对u之外,我还要有一部叫做permitation,他的意思就是我要把这个顺序给修改一下啊。

我不是说我这个矩阵a给我什么,我就直接拿来算,我是需要把这些行跟列,我要按顺序先重新排列一下,排列完了之后呢,我可以让我的l u更稀疏一点,如果大家用过matlab,然后做lu分解的话。

你会发现它的输出其实是l u和p,然后这个p矩阵就是它的排序矩阵,这个的话我就不展开了,反正如果大会大家会买mate lab的话,可以尝试一下去看看这个,嗯然后第二点第二点就是它的关于它的计算啊。

它的计算实际上是由两部分构成的,一部分呢是分解l又分解,就是说我怎么样去把这个l和u给它搞出来,然后第二部分呢是求解求解,就是说我有了l u之后,我怎么样把最后把x给算出来对吧,那么目前而言呢。

就是说这两部分它其实是可以分开来计算的,你不需要求说这两个东西需要合在一起,你可以把它分开来,那么分开来的好处在于,如果说我解一些数学问题,然后呢我这个a是固定的,我的边界条件,我的b每次可能不一样。

但是我的a是固定的,那我前面分解那块我就可以只做一次了,那我分解那块只做一次,我后面求解sop的那一块,我还是要做很多次,但是分解我起码那块的计算量通常是一个计算量的大头嘛,我可以把这个计算量省掉。

这个也是一个需要额外注意的,因为图形学里面其实它有一些专门的方法,就是专门为了中心设计,就是如果说我假设我的举证固定,那我实际上只要做分解就可以了,那我在计算量上我就可以省掉一大部分。

然后最后一点就是说这个方法它是呃它是比较难并行的,相对而言,因为我们刚才也讲到了嘛,就是你首先要做l u分解,然后做完分解之后,本质上它就是一个比较创新的过程。

嗯但是分解那一块呢好处在于我想还是可以做一点变形的,它也不是说完全不能做变形了,就是可以做一点变形,然后市面上比较呃比较经典的一个库呢。

做这个呃direct solve的这个直接法分解的库呢叫做m k l polio,就是intel m kl的,之前他们收费,然后最近他们已经不收费了,所以说大家如果感兴趣,然后想要试一试。

想自己做解一个线性系统的话,这个是一个我个人认为是一个比较好的选择,然后很多其他的库,比如说像安哥那样的库,它其实也支持mk potio,就是但是你需要做一些对他的库做一些改修改啊,也可以支持这个东西。

这个我就不展开了嗯,大家可以尝试一下感兴趣的,然后direct sober,然后第二种方法解线性系统呢叫做迭代法,那么迭代法是什么样子的,迭代法基本上都是呈现这种形式。

叫做stationary的迭代法怎么样呢,就是说啊每次呢我都把我的x更新一下,假如说我现在有一个x0 ,那么我每次呢都更新一下,我得到x1 ,然后下一个时刻呢我得到x2 ,然后我以此类推,我不断的迭代。

不断的更新更新xx最终我希望我的x啊,就是我想要的ax等于b的那个x,那么我怎么做呢,我怎么迭代呢,一般来说就是这么个形式,就是我的新的x就是下一个x等于现在的这个x加上一个小的长,一个时速的一个系数。

我们这一般叫做relaxation coefficient,然后呢有一个矩阵and inverse乘以residual,residual就是b减ax啊,这个叫做我们的残插入c9 erro。

理论上就是说如果说你的x是你的解,那么这个东西实际上就等于零了,因为x等于b吗,如果说我的x已经完美了,那我这个东西理论上应该是等于零的对吧,当然因为我们在做迭代法。

所以说我们一开始是没有办法保证这个东西等于,如果说等于零,我其实就已经问题解决了嘛,所以说一开始他可能不等于零,不等于零,完了怎么办呢,我就不停的呃更新x就是利用这个公式我去更新它。

然后最终我就把这个x给他解出来了,那么这个东西它为什么会收敛,可以给大家看一下它这个收敛的性质是什么,就是我来看这个下一个residual error是b减x k加一对吧。

这个是下一个residual error,那下一个residual error等于什么呢,下一个residual erro等于b减a xk,也就是上一个recedure,再减去阿尔法乘以a。

然后这个a universe i am inverse,再乘以那个c就完了,这个就是我按照定义嘛,我按照这个刚才我这个x k加一的这个定义,我把它带进去,带进去,完了之后我乘以a然后再啊被剪掉。

然后我就可以得到这么一个公式,那这个公式我可以把它稍微整理一下,因为这边有residual啊,这边也有recedure对吧,那我两边都有recedure,我就可以把它合成一块嘛。

我就变成identity减去阿尔法乘以a乘以averse,然后再乘以b c92 ,那么我就可以以此类推,怎么类推啊,因为这个是k时刻的residual嘛,这个k迭代的recedure。

那我再往前推k减一是不是也要往前乘一个这个东西,k减二是不是也要往前乘一个东西,那我倒推回去,我倒推到最最粗的那个状态,零的那个状态,那么我前面是不是就成了一大堆这个东西啊。

那我也就得到了i减阿尔法a m inverse成的k加一次方,就是把这个东西反复的乘以它自己乘以他自己最后成了k加一次,我就得到这个东西,那么这个东西它其实是一个常数,因为我初值我是固定的。

我有一个初始值吧,那这个是个初始值是固定的,那么也就是说最初的残差它实际上是个常数,它是固定的对吧,那么如果我要收敛,那我要做什么,我要保证这个东西要无限的趋向于零,对不对。

因为只有当这个东西趋向于零了以后,我零乘以这个东西我才趋向于零嘛,我才可以把这个东西最终变成零嘛,我的目的就是要让error等于零,那么我怎么样让这个东西等于零呢,趋向于零呢,我这里就不展开了。

但是它这个东西跟特征值很有关系,那么这里面它有个数学里面有个概念叫做spectral radius,好像叫谱半径是吧啊,我把它算出来,这个东西叫图肝病半径,然后我要这个东西小于一。

我为什么要让它小于一二,因为当它小于一的时候,一个小于一的数,你不断地给它乘以,它自己乘以,它自己乘以它自己它会趋向于零的,比如说0。9对吧,0。9的平方,0。81,0。81,再乘以0。9。

它你乘了好多次之后,它就无限的趋向于零了,所以一个道理对于矩阵而言是一个道理,如果说你矩阵的谱半径也是小于一的,也就意味着矩阵乘以它自己,然后无限的这样子沉下去,它会最终会趋向于一个零矩阵。

所以这个就是判定呃一个矩阵是不是呃,这个系统是不是能够呃用迭代法收敛的一个呃一个特点,当然我们前面也讲过,其实你做特征值是很难计算的,对于一个很大的主角而言,你算特征其实挺麻烦的。

所以说这个是个很多时候只是理论上,理论上special radio小于一我就可以保证了,但事实上我也没法算,这个是其实也是一个一个蛮大的挑战,那么接下来我们看这个其实是我们这个整个计算的核心对吧。

那m呢它有个特点,就是说你必须要是一个比较容易求解的一个m,我才可以拿来拿来用这个迭代法吗,那什么样的am是比较合适的呢,比如说对角,比如说我可以用a的对角,如果是一个对角的话。

它的inverse就是超级容易算,对不对,我直接把每一个对角上每个元素按照分之一就行了,所以说这就是一种方法,其实就是我们如果学数值计算里面的话,这个就叫做jo比呃。

还有一种方法叫做ga die goost ele呢,就是用下三角,就是用a的下三角,这是两种方法,是相对来说比较常见的方法,当然这还没完,这还有别的方法啊。

比如说我可以在这个简单的这个stationary迭代的方法,是让我再加一些额外的方法,比如说共轭梯度法啊,这些就有很多很多方法,这个呃反正我也不展开了,那么迭代法跟直接法它们对比一下有什么样的差别呢。

首先迭代法很容易实现啊,就如果说你自己要写一个求解器,那么呃首推就是做迭代法,如果写直接法的话,可能你要花好几个礼拜,你迭代法你可能一天一个下午就可以写完,就是它很简单,实现起来非常方便。

第二点呢就是说如果说你不需要得到精确解的话,那么迭代法它是相当相当有效的对吧,你只要比如说你跑十个迭代,它比较可控,因为它的计算量跟你的迭代数量有关对吧,你迭代越多,你计算量越大,那么如果你精确解。

你不要求精确解,那么你就直接少少跑几个迭代就可以了,然后其次呢它也相对来说比较容易并行,它有各种各样的并行套路,对于迭代法而言呃,缺点缺点呢,首先第一点就是说它有收敛性的问题。

就是说他不是对于所有的矩阵他都收敛的,那么什么样的矩阵收敛呢,它就有一系列的条件,我们刚才比如说我们刚才讲了,就是他的special radius要小于一,但现实生活中我可能没有办法用这个东西判定。

那么有可能就是用别的方式,比如说比如说对于高斯贝尔而言,这个矩阵就必须是镇定的呃,比如说对于其科比而言,这个矩阵就必须是对角占优的,当然他有的时候不对角占优,他有可能也收敛。

但是这个东西就没有办法直接的判断了,我只能说给一些条件,然后我知道说这种条件下是可以收敛的,然后最后一个呃,对于迭代法院的一个一个问题,就是他如果说你想要得到精确解的话,它就相对来说比较慢了。

因为它迭代就会需要很多次迭代,这个是它的一个一个小问题,好吧,这个我就想把矩阵就先讲到这里,大家有什么问题吗,关于relaxation的一部分,有没有什么可说的呃,什么没没没什么可说的。

这个relaxation很多时候就是手工调,就是阿尔法这个系数嘛对吧,这个阿尔法这个系数很多时候大家都是手工调,他跟我们一维精确性风格里面的一系有关系,如果说你把信息系统认为是一个二次问题。

二次优化问题的话,这个阿尔法其实就是跟line search里面的那个line search的那个阿法是一样的,但是对于解信息系统而言,一般来说大家不会去手工的去展示。

各位max是因为实际上这个阿尔法理论上也应该是个常数嘛,因为它跟这个条件有关,就是说理论上是一个常数,所以一般来说就试错试的,觉得这个阿尔法ok了,我就我就好,要是不崩溃了,我就改小一点啊。

然后我们接下来讲点微积分吧,微积分的定义吧,因为我们回头到时候讲流体的时候,可能会讲到一些很多关于微积分啊,所以说我我这里会给大家过一遍,有可能到时候因为流体我们是放到最后讲的。

就有可能讲到最后大家全忘光了,可能到时候回头还要回来再把这个东西看一下啊,首先首先简单的讲就是一阶导,然后如果说fx是一个实数的函数,然后x它的它的变量是一个矢量的话,那么我们大家都知道。

就是你可以有偏微分嘛对吧,我就df就等于df x d f d x乘以dx,加d f d y乘以d y加d f d d z乘以dc,那么我们一般来说会写成这个形式啊,就是df dx dx的形式。

大家注意一下这个字体,我一般来说我们我上次也讲了,就是我们一般是用字体来区分到底是矢量还是标量的,像这个黑体字就意味着它是一个它是一个矢量对吧,然后这个斜体字就是标量,所以说我对矢量求导。

那么等于这个df分别对它的x y z的每一项求导,所以说就是d f d x d y d f d y d z,然后它是横着写的,大家有大家注意一下,它是横着写的,为什么横着写。

是因为呃你你会发现这个可以写成这个形式,跟矩阵乘法一样的形式,就是这部分是横着的,然后这部分是竖着的,所以说你这样子就可以做这个乘法,但有的时候我们不喜欢写成这个形式,我们就想竖着写,那怎么写呢。

那就用梯度,梯度呢,就是实际上就是他这个一阶导,但是我给他转置了一下,我把它本来是求导求出来的,是横着的嘛,我把它改成竖着,那我就叫梯度的,这个反正大家应该学微积分的时候应该学过吧。

学数学分析的时候应该学过吧,我记得对吧,那么梯度梯度它是什么意思呢,嗯梯度它是这么一个意思,就是你可以这么想,就是假如说f是一个函数,它是定义在一个比如说二维或者三维空间里的话。

那么这个二维空间这里面我就是用一个二维的例子啊,这是一个二维平面,然后这个对于平面里的每一个点x呃,它都有一个函数值嘛对吧,那么如果说我画一个等位线,iso surface iso curve。

就有点像我们学地理的时候会画那种等高线嘛,一个道理就是同样的值我都用一条线把它连起来,那么假如说我现在花了很多等高线吗,iso surface iso curve,那么这个是0f等于零的时候。

这个是f等于一的时候,f等于二的时候,f等于三的时候对吧,就是不同的等高线,那么gradient什么意思呢,gradient就是告诉了你垂直于等高线的那个方向,它其实就给你这个东西。

那这个东西实际上就是让你的这个函数能够最快,这个函数值能够最快上升的那个方向,比如说我现在在这个地方对吧,这个零的这个位置,然后呢它垂直于这个等高线的位置呢,方向呢就是这个方向。

那么沿着这个方向我就很快的就可以让我的这个f它的值往上往上跳,对不对,就有点像爬山一样,当你爬山的时候,你肯定是想沿着最陡的那个方向往上爬,这样子爬得最快的一个道理。

梯度就是告诉了你什么样的方向可以让你的f能够更快,那反过来如果说我想要往下山,我不想我不想爬山,我想下山,那我就反过来,我就沿着f的反方向往下走就行了,这个就是梯度啊,刚才有个同学问。

就是我们需不需要自己解放成呃,反正作业里面是不需要的,因为unity他这个我还不知道unity能不能解方程的,反正我是我们我们到时候作业里面反正是不需要自己解方程的。

但是如果说以后如果说比如说你自己想做些研究啊,或者做些项目什么的,是有可能需要减防车的,像我们这个课里面不会涉及到解放前的工作,然后一阶导可以往下扩展,就是我们刚才讲的是一个实数函数,就是f是一个实数。

那如果说f它本身也是一个矢量,然后它的变量x也是一个史料,那怎么办,比如说假如说我这个f是啊一个三维的一个向量啊,本身这个函数它是一个三维向量,它本质上就是三个函数构成的,分别是f g h对吧。

它本身也是有三个实数函数构成的,那么它的一阶导呢就不再是一个横的向量了,它变成一个矩阵了,因为我分别要对这f g还有h这三个函数都求导,那么每一个函数都给我一行嘛对吧,我第一行就是f的导数。

然后第二行是g的导数,然后第三行呢是a区的导数,然后这就构成了一个矩阵,然后这个矩阵呢叫做杰克比矩阵,就是中文的雅雅克宾举例对雅克宾矩阵嘛就是杰克变矩阵,这就是杰克比矩阵。

然后跟杰克变矩阵相关的呢就是一个叫做divergence,散度,散度是什么,散度就是它这个对角上的和他这个矩阵的trace,我们叫做divergence,然后另一个呢叫做kr,curl是什么呢。

curl呢就是你可以把它想象成,如果说我把这个梯度的这个运算符,你可以认为是一个d f d d g d d h d,你认为它是一个相当于是一个也是一个向量的话,你跟这个f你跟这个啊,你跟这个f相乘。

本质上就是对它这个函数里面的每一个求导,对x求导嘛,那么你就跟cross product一样,就是可以第一行就得到y跟z。

然后h跟g好像是f h z x第三行是这个就是跟cross production有点像,你你如果认为这个微分算子是一个项链,然后你利用类似cross product,就是我们差成那个规则。

你做同样的操作,你可以得到这个q这个是也是一个在流体里面蛮常见的东西,我们一般来说做那个做vertex,就是呃流的水流的漩涡的时候,我们一般来说会用到这个客,但是我这里反正就是跟大家提一个醒。

就是说呃我们会偷做流体的时候,我们会搞到这些divergence跟kl,我到时候也会跟大家提一下,免得到时候大家忘记掉,然后刚才讲了,我们讲了一阶导对吧,我们现在讲二阶导啊,如果说回到回到实数函数嘛。

假如说f是一个实数,我二阶导,那我搞二阶导的话,就呃我的这个这个这个这个东西偏微分就多一点了,因为我可以对x y求导,也可以对x z求导,也可以对y z求导对吧,我就最后就变成一个大矩阵了嘛。

那我这个矩阵呢就是可以啊,就是按照这个x y z的顺序,我可以对他的这个导数做一个排列,我构造这么一个矩阵出来啊,这个我们把它叫做和弦矩阵,然后这个矩阵是对称的,因为求导的顺序是不影响结果的对吧。

你先对x求导,再对y求导,跟你先对y求导,再对x求导的结果是一样的,所以说啊我就有个和尚是这,然后合成矩阵的对角,我们把它叫做拉普拉斯,拉普拉斯啊这个东西,然后我这里其实想提的一点是符号。

因为不同的paper,不同的文献,然后不同的文档,他们其实里面用的符号都有点不太一样啊,就有的人他喜欢用这个类似这种符号梯度dot t度这种符号,有的人喜欢用这个梯度的平方啊。

他认为这个东西就是梯度的平方,所以说他写这种符号,然后有的人呢就把这个梯度给反了,反了就变成了一个正三角,就也有人是用这种符号的,反正就是大家得注意一下,就是你看到这个符号的时候。

就是就会想到这个有可能是关于拉普拉斯,就主要还是因为符号不统一,很多时候大家啊用的符号都不一样好吧,然后嗯这个好,还有一个就是举个例子吧,就是泰勒展开,因为大家都知学过微积分,都知道。

就是我们一个函数可以对它做泰勒展开,对不对,假如说一个函数是个实数,函数变量又是实数,那么这个就是它的泰勒展开怎么弄呢,就是fx 0,假如说我要在x0 这个位置上做泰勒展开啊,fx等于f x0 。

加上df x0 ,dx乘以x减x0 ,这是一阶的部分,然后我还有个二阶的部分,二阶的部分就是二阶导,二阶导乘以1/2,然后x减x的平方,然后呢后面还有三阶导,四阶到五阶导,这个反正大家都知道。

就是你可以把这个函数展开成一堆这个啊,一堆不同那个接的这个形式,那么我们对这种向量函数也可以做类似的泰勒展开,怎么展呢,当这个x是一个向量的时候,那么我等于f x0 ,这个时候x是一个向量了。

加上df dx 0乘以x减x0 ,那这个是什么,这个是它的一阶导,它是一个横着的项链啊,大家还记得吗,这是一个横着的,就是这样子的,然后x1 x0 是个竖着的,所以说一个横着乘以一个竖着的。

就得到了他的得到了一个实数嘛对吧,那么我就实数加实数这个符号,就这个这个它的这个他这个dimension,他这个维度就统一了,二阶导是什么样呢,二阶导是x减x0 的transport乘以合成矩阵。

再乘以x减x那这个是横着的,然后这个是个矩阵,然后最右边是一个数字的,是这样的形式,然后我可以把这个东西重新整理一下,就变成这个形式,然后上一个上一个礼拜,有有的同学不是说觉得镇定这个东西特别的闷嘛。

就不知道镇定一个矩阵正定有什么用吗,其实这里你就会发现镇定有什么用了,因为这个东西跟正定的定义是不是非常像啊,因为我们说一个矩阵正定的时候,我们不是说v transpose a要大于零吗。

我们当时说这个一个矩阵正定义是这个东西吗,它其实就是对应上的,就这个东西呢就是我们的v x减x0 ,就是我们的v我这个h我这个和弦就是我们想要判定的这个矩阵,那如果说这个h是正定的。

也就意味着我这个二阶项必然都是永远大于零的,然后就会对这个函数带来很多有意思的特性,然后当然我们这个我们今天也不讨论,反正以后我们会讨论到优化一些优化问题的时候,我们会回过头来讨论这个东西。

就是给大家呃提个醒,就是当初我们学镇定是有有用的,为什么,因为他跟函数的二阶导是有直接关系的,好吧,好然后再再举两个例子,这个例子是我们到时候我回头也会呃。

我们也回头用到的就是怎么计算一个向量的norm,就是它的大小的导数怎么算啊,首先我用定义我一个矩阵的一个向量,它的这个nm它这个l等于x transport,x transport x开根号对不对。

我跟自己相乘,然后我开个根号,我就得到自己的大小了,那么这是这个是这个矩阵啊,这这不是矩阵这个向量长度的这个定义,那么我利用啊这个微微分它这个呃他这个这个这个这叫什么链式法则,什么啊。

我可以根据这个圈入,我怎么做呢,我首先把这个1/2扣出来,1/52抠出来之后呢,我原来是开根号,我就变成负的1/2了,那我把这个括号里面的全都放在这里面,变成了x transpx的-1/2。

然后再乘以括号里面的东西对x求导,明白吗,这个就是一个圈入,大家有没有问题,这里,这个其实就是我们正常做微积微分的时候,就是对于一个对于一个函数,我可以先把这个函数对x求导偏微分。

然后我再把函数变量里面的东西再给它求导,然后我要对这个括号里面的东西求导,我怎么求,不用定义求对吧,我知道x是什么,我知道x实际上就是x y z嘛。

那么x transpx就是x平方加y平方加z平方嘛对吧,那么你对x求导分别就得到了2x2 y2 z了,也就是意味着也就是这个东西等于2x transport好。

我知道这个东西是2x transport之后我放回去啊,这个东西呢,是什么呀,这个东西是二乘以x长度分之一,因为这个东西是负的1/2,负的1/2就变成了分母。

然后下面这个开根号也就是意味着这个是x的长度,那么我就有二就有二就取消掉对掉,然后最后就得到了x transport除以x的length,这个其实直观上也非常容易理解,为什么。

因为这个东西告诉了你一个向量长度的梯度是什么,因为你把这个东西做一个转置,就是梯度吧,一个长一个向量强度,怎么样能够让他最快的变长或者变短,因为你想要长度变大了,那么怎么样变长。

是不是就是继续沿这个方向继续找,继续沿这个方向长,那怎么样变短了,就是沿这个方向反方向继续缩,所以说这个东西实际上就是把这个方向给normalize了一下,它告诉了你这个方向怎么样能够最快的变长。

能变短,然后刚才有个同学问嘛,就是说呃为什么要做这个quiz,因为我接下来就会给下面这个例子,就是算一根弹簧,我现在把这个式子放在这个右上角,然后我现在假设有这么一根弹簧,弹簧的原长是l。

然后弹簧的能量是什么,是一个函数对吧,它是关于这个位置x的函数,它是1/2,二分之k乘以长度减去l的平方,这个就是弹簧的能量,就是当前长度减去原长的平方,再乘以一个k除以二,那么我现在要算利了。

大家可能知道怎么算力,但是我在想给大家展示一下,就是我们如果用我们刚才ta calculus的方式,怎么去算一根弹簧的力,弹簧的力根据物理的定义呢。

是能量的gradient是gradient的反方向就是负的gradient能量,这个就叫做力,这就是力,那么我对我刚才有这个能弹簧能量的定义对吧,那么我现在就对这个x求导了,因为梯度就是x求导。

那么我接下来就是对梯度求导好吧,那么我对这个求导,我首先把这个二他有这个平方,那么这个二跟这个二相乘抵消掉,然后接下来得到了什么,得到了k乘以长度减l对吧,就得到了这个东西,负号保留。

因为我本来就想需要得到一个负号,所以就有这个负号,然后接下来呢我需要对里面的这个东西求导,对x求导,当然我是梯度,所以说我把这个transpose给它摆上去。

这个t transport的来源在于来源于这个梯度吗,所以我对这个东西求导,那么这个东西什么呀,这个东西我前面不是算过了吗,我刚才这个右上角不是算过了吗。

这个东西就是x transport除以它的长度吗,所以说我把它整理一下,就得到了负的负的k乘以长度减l,然后乘以x除以长度,然后大家会发现,这个公式其实跟我们想象中的弹簧的力的公式是一样的。

就是什么意思呢,就是前面这个东西是弹簧的力的大小,它决定了弹簧力的大小,力的大小跟长度的缩放比例有关,后面那个东西告诉了你弹簧力的方向,然后这个方向是跟弹簧的这个向量的这个方向是一致的。

为因为我的利益永远是希望我的弹簧能够很快的变长,或者很快的变短了,所以说他可能是梯度的方向,所以说这个就是计算了弹簧的力,好我们再往下走啊,我们不满足于利,我们接下来还要再往下走。

我们怎么算这个能量的喝水,因为我们回头如果要做一些高级点的这个模拟的话,弹簧系统模拟的话,我们要它的合成,那么他这个喝水其实数学里面有个名字叫做steffness,矩阵怎么算呢。

和弦等于负的d f d x因为力是有负号的,我这里再把这个负号给扔掉,我就两两抵消掉,我把负号抵消掉,然后呢我对f对x我再去求个导,我就可以继续利用这个我们微积分里面学过的知识吗。

我首先对括号里面这玩球的,我括号里面就玩求导,是不是就是这个右上角这个东西啊对吧,就这个东西了,那我就得到了k乘以x乘以x transport除以的长度的平方,这个是对括号里面求导。

然后括号里面求导完了,我接下来对括号外面求导,因为括号外面它本质上就是最右边这个东西对吧,还有分子跟分母两块,所以我先对分子求导,那么就是加上k乘以长度减l分子求导,x对x求导就是identity。

因为我自己对我自己求导就是一嘛,x对x求导就是一嘛,只不过这个我们现在求导是因为是矢量,所以说求出来的不是一个实数,一identity取证,所以说这里就是identity除以x l。

然后呢接下来我们对分母求导,分母就是长度分之一啊对吧,那么我就长度分之一,我就变成-1,就是负号减去前面那个系数,再乘以分子,保留除以x norm的平方,然后再对x norm求导,x norm求导。

我把这个东西再放进去,就是一堆实际上本质上就是微积分,就是微分里面我们利用这个链式法则,文不大对求导,最后就得到了这个玩意,然后我可以稍微对这个公式整理一下,我就得到了这么一个公式。

所以说这个就是我们对弹簧能量求导,然后就可以得到力,然后再求一次导,我就可以得到一个矩阵,就是我们的stiffness matrix,就是它的合成矩阵,好吧,大家有什么问题吗,什么,物理含义。

就是你可以认为你x是认为是一个二维上的一个点的话,然后你把能量认为是一个相当于一个一个一个米曲面,那么它这个tension phens相当于就是它的这个二阶导,就是这个曲面的二阶导,我们常常看见的是。

比如说一个曲面看有点,那他那个space嘛对,但是这个东西它其实是一见到它是立理解到的处罚,这个其实你可以这么想,就是说而物理含义如果说你可以考虑一维的情况,如果说如果是一维的话,这个东西就是k。

我们正常情况下不是把这个k叫做stiffness嘛,对吧,就是它的这个stephens,中文叫格,就是叫进度系数吗,高中物理还阻尼,也不叫阻尼吧,也不是阻尼吧,胡克星系数对,有点好像叫胡克系数吧。

反正就是这个stiffness,这个就是k嘛对吧,那如果说一维的情况下,你做二阶导,它就是k,因为你可以想象,如果说这个x是实数,那你求二阶导他就是k吗,但是问题是我们现在不是一维,我们是一个高维空。

是个二维空间或者三维空间的时候,你对它的二阶导,它就变成了一个关于k的一个举证了,就是他的跟这个物理稍微有点关系的一个方式,然后这个有篇paper就是2002年的时候。

有一篇paper叫做stable responsive cross,这个里面也会也有引用了,这个就是计算方式,就如果大家想再仔细的看一下这个推导过程的话,可以参考一下这个paper。

有同学问为什么为什么叫tgent,我们刚刚也是讲,就是说为什么叫tgent,好像我们也想不出来为什么叫tgt,就是tgent,它跟可能是跟力有关吧,因为它是力的一阶导,如果说你认为力是一个函数的话。

那么二阶导就是力的函数的切向量,可能是因为这个原因,我们把它叫做tangent def,可能是这样的,然后在我在想再往下一点就是两个点,就是如果说我们有两个点,因为刚才我是一个点吧,x是一个点。

那如果说我有两个点怎么办呢,两个点都是活动点,两个点都是未知量,那么我的这个能量就变成x0 到x一的长度,减去l的平方乘以这个k除以二了,就说我的长度就不再是the norm,而是x0 到x一的。

那么我这里的力呢就是有两个力了,就不是一个力,是两个力,分别是零这个点上的力跟一这个点上的力对吧,你也可以认为我们我们上一节课也讲到了,就是当你有好几个顶点的时候,你可以把这些顶点都合在一起。

变成一个大香料吗,那么这个时候呢,如果说我把这个x都合在一起的话,就变成了一个六维的一个大向量,因为我有两个三维的顶点,那么就是六维的,我这个力也是六维的,就是r6 的,这是六维的。

然后分别上面就是分别就是两个力分别作用在零跟一上的力,然后这个符号大家有的时候会看到就是gradient 0,然后gradient的一什么意思,这个东西实际上就是他对x0 求导。

它对x一求导的意思就是大家想偷工减料,省一下,就是呃就是想写的简单一点,大家就会这么写,就是把这个下标就作为分别对某一项一个x求导,我们一般会这么写,然后这个结果是由两部分构成的。

分别是零上的力跟一上的力,然后呢它分别是f一跟负的f1 ,然后f一就是通过这个东西算出来的,这个我反正我也就不再推了,这个是满足牛顿定律的,就是都是相互的,弹簧给零的力跟弹簧给一的力,它是互相相反的。

然后呢这个东西的合成stiffness就是一个6x6的矩阵了,好这就是为什么我前面想要讲那个呃,刚一开始的时候,我想要举那个例子的原因是,因为他这个矩阵系统就是这个样子,然后它这边是h e对角都是h。

然后非对角就是负的,然后a h e就是我们刚才算出来的那个东西,只不过把换成了x0 x0 解x1 ,就是这点差别,我们回头呃,讲那个弹簧系统的时候,我们会再回到这里,然后会引用这些东西,就是大家呃。

如果说我们回头讲他们系统时候,如果说这里有些什么疑问或者是,有什么想法的话好吧,有没有什么问题,线上的同学呢,没有问题的话,我们没有问题的话,我们就讲那个讲rigid body了,我们还有一个小时。

可能半个多小时的时间吧,我们把rigid body那一块讲一讲,好好翻篇儿了,看一下哦,这个,首先我们来讲一讲什么是睿智的芭蕾,还有什么是rigid body dynamics。

就什么是缸体和缸体的运动学,钢铁的力学。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们现实生活中其实有很多东西都特别硬,特别结实啊,所谓的in特别结实呢,就是说这些东西它其实很少有形变,如果说这种物体呢,我们就把它冲上去,把它叫做钢铁,就是我们默认这些物体没有形变。

形变呢我们就可以利用一些比较特殊的方法来模拟这些物运动,这个就是我们今天所要讲的这个主题啊,然后在动画还有游戏里面,还有很多这种图形学应用里面其实也用的非常多嘛。

说疯狂的小鸟就是一个比较典型的利用钢铁模拟的一个小游戏嘛,只不过他们做的是二维模拟,我们主要讨论的今天还有以后讨论主要都是以三维的,但二维可以认为是三维的一个特例,然后做很多事项,游戏里面。

比如说我们啊这个墙对吧,我把这个墙打穿了,墙打穿了以后,这个墙碎成很多块,然后掉地上了对吧,它本质上也是在做钢琴模拟,所以说失效都需要用到我们钢铁模拟的这个这个技术,那么钢铁模拟它其实非常常见。

非常重要,所以说一般来说在游戏引擎里面都是默认提供的,它其实也有钢铁模拟的这个东西啊,只不过我们到时候就是我们做作业的时候呢,就是不许不用到它自带的那个钢铁模拟,我们要自己来写这么一个东西啊。

就是如果说你自己以后想尝试一下这个,你可以发现这里其实是有一个未知的body这个引擎的,在这里的你只要添加添加一个component就会添加进去。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当然那我们到时候不会用到这个东西,它本质上做了一个什么事情呢,本质上就是说我们要去更新描述物体状态的一个变量啊,比如说我们的时间轴从左到右,我们的时间轴是很多时时刻t0 t1 t2 t3 t4 吧对吧。

很多时刻,然后呢我们的物理引擎呢更新描述这个物体的一个状态量,我这里把它叫做,那么假如说我现在有一个状态量叫做s0 ,对应的是t0 时刻,那么接下来我的游戏引擎呢就可以根据我这个状态量呢去更新。

这个物体在这个游戏里面的画面中的这么一个效果,就比如说我有个兔子对吧,s0 对应的这个兔子就是这个状态,那么接下来呢我如果做模拟模拟引擎呢,把这个s0 更新了,我得到了一个新的状态。

这个新的状态是t一时刻下的状态,那么我这个兔子就动了一下,然后呢下一个时刻呢我再通过模拟引擎得到一个新的状态,我就又兔子更新了一下,我就以此类推,我就每次呢我实际上就是我通过这个更新函数啊方式。

我就不停地更新这个状态,然后有了这个更新以后的状态呢,很多游戏引擎它就可以自动的把这个兔子的这个效果得到了,就是可以不退的往下走了,那么问题在于来了,就是说我怎么样去定义这个状态对吧。

我怎么样去描述这个一个缸体的状态,尤其是钢铁的状态,那么对于缸体而言呢,我像是只允许他做两种运动的,分别是平移和旋转,因为只有这两种运动是不影响一个物体的形变的。

那么通常呢是假设假设我这个兔子在一个prince的状态上,这个参照的一个状态,这个状态呢假设是这个兔子是在它自身的一个状态下,是它的中心就是圆点,比如说它这个左又是x,上下是y,然后前后是z。

就是类似的这样子的,我可以先假设兔子在一个某个参照的一个状态下,我们把它叫做reference reference space,首先我假设兔子是经过某一个旋转,就是它的状态,第一个状态量呢是旋转啊。

那么假设我兔子首先做了一个旋转对吧,这里呢我假设我是用一个旋转矩阵去描述这个旋转的,那么这个旋转矩阵我把它叫做大写的r,那么对于每一个顶点,一个顶点我用小2i来表示,我用这个i顶点来表示。

那么之前这个顶点的位置在这里之后呢,我做一次矩阵乘法,我就可以得到这个旋转之后的位置了,那么就是大写的r乘以2i这是我第一步,我假设这个状态首先是可以用一个旋转去描述这个旋转矩阵。

描述选中这个兔子的姿势对吧,然后接下来我假设有一个平移,平移决定了什么,平a决定了兔子的位置,那假如说它与原来的位置,原点新的位置是x点,这个兔子就从这个a原点跑到了这个x点对吧。

那么对于这个顶点而言呢,它的位置就是中心点,也就是平移的量加上rotation乘以reference space上的位置,说我是假设这个兔子它其实是它的状态,实际上是经过了两部分操作的,一部分呢是旋转。

一部分是平移,在unity里面也是一模一样的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个如果说大家啊用过unity的话,就是如果大家没用过的话,可以我们可以先尝试着先下载下来,因为我们到时候下个礼拜会有作业啊,如果说大家稍微简单地尝试了一下的话。

会发现对于unity而言其实是一模一样的,这个你这个状态栏里面它其实也会有不同的这个变量,分别是对应的是旋转跟position,还有一个放大缩小,但是我们就不做,不考虑放大缩小,这个就不考虑了。

旋转呢其实跟旋转矩阵还有点不太一样,我们回头也会讲这个东西,因为大家会发现它是由三个变量构成的对吧,它不是一个矩阵,我们会都会讲就是旋转,我到底应该怎么样去表示它,我们现在就知道了。

我们知道这个状态实际上本质上就是由旋转跟呃位置,这两个东西是构成的,我只要去修改这两个变量,我就可以让这个物体刚体运动了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们先来先来讲这个平移好吧,先来讲位置,那我位置我可以用这个xx也就是它这个圆,这个兔子至新的这个位置来描述嘛,表表示吗,这个位置比较简单,位置就是个3d向量,我们通常就是用3d向量来表示位置对吧。

假如说它原来的位置是x0 ,根据模拟我得到了一个新的位置,x一得到了一个向外一个位置x2 x3 ,然后依次模拟,然后我这个兔子的就可以沿着这个某一个轨迹在运动了,大家可以看到,虽然我位置改变了。

它这个姿势是不变的,它还是这个正的这个姿势,因为我暂时还没有考虑到旋转,我现在知道位置了,当然不够,为什么,因为在物理模拟里面,我还要去考虑到位置跟时间的关系,那这个时候呢我需要再引入一个变量叫做速度。

所以说我有两个变量,一个是x是位置,还有一个变量是速度,速度就叫做x dot,那时候大家叫dx dt,但是一般来说画一个小点,就他对时间的导数,那么就是跟速也是跟位置有关的,只不过是跟时间的导数。

根据定义速度是什么呀,速度牛顿说,所以说速度新的速度等于之前的那个速度加上量分之一,很有力的时间积分,就这么一个意思,这里我写的比较复杂一点,为什么,因为这个力它可能很复杂,它有可能是时间的函数。

有可能是位置的函数,有可能是速度的函数,所以说这个力本身是通过各种各样的方式给它计算出来,然后呢你根据时间做积分,然后冲量,然后再冲量再去更新速度,就是大概就这么个意思。

就是我们学物理的时候都会应该会学到这个东西,同样的呢,我们有位置,位置呢是位置是速度对于时间的积分,所以说新的位置就等于老的位置,加上时速度从t0 到t一时刻的一个积分,只有两部分构成。

所以说本质上我们在模拟呢就是要写积分,本质上就是要做这么一个积分,这就是为什么我们很多时候讲模拟引擎都在讲时间积分,时间积分为什么,实际上本质上就是这么一回事,就是我们要对时间做一个积分。

接下来我们看怎么样做积分,我们来看几种不同的套路,大家想一想什么是积分啊,假如说我这个横轴是时间,是时间,都是速度啊,我这里先假设是一个比较简单的一维的情况,就是都是速度跟位置都是一维的。

那么我就画一个简单的这么一个二维图来表示,这是时间,纵轴是速度,那速度的积分是什么呀,积分就是面积,就是假如说我这条曲线,我这个曲线是速度的函数的话。

这个积分t0 到t一时刻的积分实际上就是这一块阴影面积,这个函数在这个呃这个函数下面这块阴影面积,这个就是积分的意思,本质上我要去算积分,实际上就是我要去估面积,我想要估计一下这个面积是多少,对不对。

我怎么顾面子呢,比较简单,我们数学家也没什么别的本事啊,就是比较简单,怎么估面积,我就进四,最简单的方式是什么,就是搞一个方块,我就用一个方块去浸死他,这就是一个方块对吧,我用这个方块去进死他。

方块的面积我们都知道怎么算,对不对,就是底乘高吗,这个底是什么呀,这个底就是,就是两个时刻的时间间隔,我们叫时间不长,对叫deltt,就是它这个底面积宽度高呢,这个高就是零时刻的速度。

也就是说我有t0 时刻的速度,我再乘以deltt,我就把这个面积给估出来了,但是呢这个方法好不好呢,不是那么好,对不对,我是不是有误差呀,我这边其实有很大一块面积给漏掉了,我们来看一下泰勒展开。

根据泰勒展开,我们会发现其实我们刚才估的那个东西实际上就是它的一阶部分,这东西实际上就是我们的一阶部分对吧,不题在于一个函数,它做泰勒展开之后,它不只是有一些部分,它还有二阶,它还有三阶,它有四节。

据说呢我们这个方法呢我们把它叫做一阶精确的方法,为什么,因为我们只保留了一阶,我们保证一阶的东西,我们实际上都是估计到的,后面那个二阶三阶的东西呢,我们就是我们的误差,就是我们被我们漏掉的这个部分。

这就是叫做一种试积分,就是我们根据t0 时刻当前这个时刻的速度,我可以把面积给估出来,我把这个积分给估出来,既然有影视积分,那还有一种方式是啊显示积分,不好意思,刚才是显示积分啊,既然有显示积分。

那么还有一种方式就是做影视积分,影视积分那就反一反,我不用t0 时刻的速度,我用t一时刻的速度就换了一个高对吧,我换了一个方盒子,我用这个方盒子呢,我还是有底面积,底面是deltt,是t一时刻的速度。

然后我把它乘一乘,我就得到了这个积分,你说这个方法好不好,这个方法好像也不是那么好对吧,为什么,因为有一大块面积实际上是多余的,我多估了这个面积,如果说你做泰勒展开。

你会发现其实跟之前那个显示积分是一样的,就是估计了一阶的部分,二阶的部分呢我同样也是漏掉了,同样也是有二阶还是三阶的误差在。

所以说这个方法也是一阶first order accurate积分跟显示积分有这两种套路,这两种套路之后呢,很显然大家就会想,就说我是不是可以搞的更精确一点啊,那大家就想既然一个姑姑,一个小姑。

我是不是就可以放在中间了,叫做midpoint的方法,那mile point呢就是假如说我这是t0 ,就t一把我的采样点作为终点t0。5,然后我用这个位置上的速度给我这个方块的高。

然后再乘以这个啊这个宽我得到了b的t乘以v t0。5,这个呢似乎好像比刚才好一点对吧,虽然说我有一块少了,但是我也有一块多了呀,你说这个多了更少的是不是又可以互相抵消掉,其实也就是它这个本意所在。

如果说你做泰勒展开,接下来我们也做泰勒展开,t0 到t一的积分,等于t0 到t0。5的积分,加上t0。5到t一的积分,我把它分成两半,首先对于这两瓣我分别进行泰勒展开,找了这么个东西,还有下面这个东西。

我刚才不是说我有一库有部分面积是多,有部分面积是少,然后他俩互相抵消掉吗,就像这样,就是说变的面积有点多,估了对吧,我这块面积多估了,然后我这块面积少估了嘛,我希望他俩是不是能够互相抵消掉。

那么在泰勒展开里面,你就会发现它二阶的部分其实就可以要消掉了,他俩就抵消掉了,那我得到的就是三阶的误差,还有剩下的部分,也就意味着我的误差实际上是三阶,也就是一阶二阶的部分,我实际上都可以完美的。

所以说他这个方法是二阶准确,point是比这个方法好,比前面我们说的这两种方法好,有的同学可能会进一步问了,就是说我为什么非要用这个方块去估面积,对不对,我是不是可以用别的形状去估面积,是有的。

就比如说大家可以用七星啊,也有类似的方法叫做triple joy的方法,就是梯形法,当然我们这里就不展开了,就是反正就是给大家举这三个简单的例子,都是利用方块去布面积的啊,分别对应了三种不同的高。

分别是t0 的时刻的,t一时刻的,还有t0。50克的不同的积分方式,既然有了这三种积分方式,我们回到我们刚才那个刚才那个问题上啊,就是刚才这个问题上,我现在有速度x还有x这两个变量。

刚才的问题稍微复杂了一点,为什么,因为我有两个变量,我不是一个变量,我有两个变量,那我该怎么做,我们这里我们采用了一种混合式的方式,首先呢可以速度更新一下,我们速度采用的是explicit的方式。

就是说v一等于v0 加上t乘以m verse deltt,就是我这个方块的宽嘛,然后乘以方块的高,这个方块的高就是对立,然后我是用临时刻的力估出来的,这就是为什么把它叫做explicit的原因。

implicit n是呢,是因为我对于位置在做更新的时候,我接下来要用v来做更新了,一我刚才已经算出来了,一半implicit,当然这个虽然叫做implicit。

但是它并不是真正意义上的implicit,为什么,因为在计算这个x的时候,这个v实际上已经得到了,本质上它就已经是个已知量了,它并不是真正我们想象的,它是未知的吃的,是因为如此。

很多时候大家都把它叫做带sainquit,这个在有的文献里面会这么叫,是呢,但是呢它其实还有一个更好更有趣的名字,意思呢就是说你可以把这个v跟x,你其实可以把这个v不要求把它做v1 v0 。

认为这个v是0。5,然后之前那个时刻是负的0。5,然后这个是0。5,这个其实是不影响计算的,计算上是一模一样的,只不过就是我当我在解释这个方法的时候,你认为我的速度跟我的位置是错开的。

如果说我的速度跟位置是错开,有什么好处,就是在于,分别就是midpoint了,因为对于未知而对,因为对于速度而言是0。5跟-0。5的midpoint,对于位置而言呢,0。

5又是一跟零的middle point,本质上这个所谓的三面implicit,它并不是真正的implicit,它本质上是他只是把速度跟位置错开,然后分别做了个midpoint,这个名字为什么叫做lpg。

是因为我认为是两只青蛙,就是形象的解释,就是把速度跟位置当做两只青蛙,这个青蛙速度,这只青蛙呢先从位置的青蛙的背上跳过去,那么把它调到0。5的位置,然后接下来位置又从速度的背上跳过去,跳到一的位置。

然后我以此类推,就是一只青蛙,一只青分别就是从对方的跳过去跳过去,跳过去就是一堆mid point,本质上就是当你有两个变量有速度跟位置的时候,你认为所以速度跟位置是错开的。

然后他俩的积分就是可以用这个midpoint的这种方式来实现,反正就是这个是一个相当于给大家解释一下这个名字的游览啊,方法还是一样的,就是一个方法,这个方法之后呢,我就可以写我的这个更新函数了嘛。

因为我的模拟本质上就是要做更新,下午下午去对,接下来再讲一下力吧,就是我们会涉及到立马这样的力,首先有重力对吧,这个大家可能大家都知道,没学过,知道的,不知道的话就打回中学去学一下物理好吧。

还有一个呢是空气阻力airdg,那一般来说会认为是速度跟速度相关,就是认为这个历史跟速度相关了,然后速度乘以一个系数上去,这个是物理上一般来说对于空气空气阻力一般来说是这么解释的。

如果说我们做模拟的时候,我们也可以稍微搞得简单一点,说你不是很在乎这个能量的守恒,什么动量守恒,能量守恒的话,你可以做一个比较简单的一个操作,什么呢,就是你直接把这个速度乘一个系数,乘一个系数上去。

就把这个速度给变小了嘛,你把这个速度乘以0。99,那么就接下来就变成原来的99%了,那么速度就变小了,那么这种方式会相对来说更简单一点,而且也会更稳定一点,因为有时候你把力定义为一个速度的变量。

然后你在做一些计算的时候会稍微复杂一点啊,如果如果说你不是很对这个这个这方面要求不是很精确的话,那么一个简单的操作,你就直接把这个速度做一些衰减就可以了,这个我后面这个方式是我比较推荐的啊。

但是呢也不排除就是有很多啊,大家读到的时候会发现他们其实更追求这种比较精确的计算,都是都是有的啊,有了这些公式之后呢,我就可以做做计算了,这就是我的更新函数是我的输入,右边是我的输出。

我的输入是速度跟位置,输出是新的速度跟新的位置啊,首先呢我把力算一下,我把每一个顶点的力算出来,爱就表示i丁点这个顶点上的力,那我把这所有的力加起来,我得到了总的这个力对吧,我对力求个和结合之后。

我根据牛顿公式,我得到了新的速度啊,得到新的速度之后呢,我把新的速度乘以dt加上位置,就得到了新的位置,这个就是完成了一个简单的操作,unity里面unity的话,本本身呢它没有定义速度。

你需要自己在脚本里面定义这个速度,但是位置它是有的,它的位置叫做transform position,反正到时候大家作业里面会解释的。

就是说它里面专门有一个变量叫做transform of position,到时候大家去访问这个变量,然后就可以得到他的x,你去更新那个x就可以了,是一个具体的模拟的过程,矢量我们没想质量对吧。

那质量怎么样,质量一般来说你可以自己手工的定义这个东西,反正就是你自己想设一个什么样的值就可以了,取决于你认为这个物体有多大的质量,然后dt呢时间不长吧,在我们的作业里面。

我也是就是想大家就是自己手工的设这个值就完了,也不用太纠结,说去能够跟这个本身模拟的过程相对应啊,跟本身那个动画速度相对的,如果说在游戏开发里面的话,你可能是需要这个deltt能够跟你的帧率。

比如说你的帧率对上,但是在这个里面作业里面,我就希望大家就是手工的去改这个调查题,然后看看用不德德塔t会产生一个什么样的效果,好吧,反正就是这个大家就是自己去尝试一下吧,就是把它当做一个变量。

你可以自己去手工的尝试一下,什么问题吗,那个或者显示或者三代法,它们是可以形容一个一阶欧洲的这样的差异方式的,因为midpoint就是二阶的,然后是二阶精度,是我们对象是二阶超一变量是吗。

对是只有两个变量,你才需要这样子交替的,对对对,线上的同学没有什么问题的话,我就继续往下走了,我稍微等一下,能力的更新需要位置跟速度更新啊,因为利他有可能是速度的函数,就比如说我刚才讲了弹簧。

弹簧的话就是历史位置的函数,空气摩擦就是力跟力是速度的函数,但是如果说你用简单的像我们刚才讲的,就是如果说一个简单的衰减模型的话,你力跟速度无关,那么这种情况下你也可以把这个给划掉,对于缸体而言的话。

其实跟这个甚至都无关,对缸体而言的话,如果只有重力的话,就是完全就是一个常数的力,就是常数的,我只是说这里就是我假设一个比较通用的情况,通用的情况的话,你可以认为历史位置速度的函数。

有同学问质量是不是一个对角矩阵,等会儿我们讲那个旋转的时候,质量是对角矩阵,但是质量是一个矩阵,但是这里的话是一个对角矩阵对,但是你也可以认为是一个实数,因为实数也可以跟一个向量相乘吧。

用速度衰减就不需要再说按那个单品的力,而drag的例子就是空气阻力,就不需要再用那个再用那个算了,如果只用速度出来怎么办,接下来再稍微往下讲一点吧,因为时间也不是很多,我看能讲多少算多少吧。

首先来讲一下旋转,先把旋转的定义先讲一下,就是我们刚才之前讲的就是旋转,可能大家之前学那个图形学101的时候,就知道就是旋转可以用矩阵来表示嘛对吧,然后这个矩阵表示其实在图形学里面也是很常见的。

然后它有一个好处在于当你要选某一个向量的时候啊,比如说你要有个顶点,你想要得到这个顶点旋转之后的位置会比较容易,因为你只要做一个旋转跟呃,只要做一个矩阵跟矢量的乘法就可以了,如果我们在做模拟的话。

我们还要不要用矩阵呢,这个就存疑了,为什么,首先大家看这个矩阵是一个3x3的矩阵,它实际上是由九个变量构成的,你有3x3吗,总共有九个变量是旋转,它并没有九个自由度啊,在做旋转的时候。

我们就只有三个自由度,对不对,分别是左右上下前后的这么转对吧,有三个轴嘛,所以说旋转矩阵在描述旋转的时候,它是有很大的,它不是所有的旋转矩阵都是不是所有的矩阵都是旋转矩阵。

所以说他有redundancy这个东西是一个问题,第二个问题是什么,第二个问题是旋转矩阵,你看到这个旋转矩阵,你也不知道这个东西到底怎么旋转,他很不直观,这个东西它是一堆数字嘛对吧。

它不能够直接地告诉你这个东西到底是怎么旋转的,另一个问题就是说当你去做它的时间,时间微分的时候,当你想要得到它对时间的导数的时候,我们所谓的旋转速度角速度的时候不是那么容易,所以说这是旋转矩阵。

它的一些缺点,第二个方式叫欧拉角角,一般来说我们在做cd设计,在unity的界面上也是采用了这种方式,unity界面大家可以看到是三个角度嘛,三个值嘛,xyz嘛,这三个就是分别对应三个欧拉角度。

它比较直观,它的直观点在哪里呢,就是说他认为旋转三个旋转构成的组成的,那这三个旋转呢就分别对应xy z的旋转,就分别对于三个轴的旋转,你要做一个旋转,你只要需要定义这三个旋转,然后把它组合起来。

就构成一个旋转,里面呢它是这么一个顺序,就是z x y这么一个顺序,如果拿来做模拟也有一些问题,首先它有一个老式叫做电波,等会我给大家举这个例子,就是万向节的一个锁死的一个问题。

然后第二个问题就是如果说你拿来描述它的时间导数,时间导数也不是那么直观,它本质上是三个旋转构成的,而这三个旋转的还都是分别相关的,所以说也不是那种直观一个给大家举个game lock的意思。

就是说假如说我有个小飞机,假如说你本来是有三个旋转轴对吧,分别是x y z,那么大家可以看到下面有个旋转轴,坐上有个旋转轴,然后呢这是一个旋转轴对吧,绿框的这个旋转轴,然后呢最后呢他自身有个旋转轴。

旋转轴分别对应了三个不同,我的旋转模式也就是三个不同的自由的旋转度,然后这三个自由的旋转度呢是不一样的,自由的方式,然后giblock说了个什么事啊,就是说在某个特定的状态下,不再有三个自由度了。

你可能就只有两个,甚至你只有一个自由度,右边这个情况,假如说我这个框变成这个状态的时候,你底座上的这个旋转轴是这个旋转轴对吧,你自身的这个旋转轴也是这个旋转轴,这两个旋转轴是一模一样的。

这意味着你只能绕着这个轴旋转,绕着这个轴旋转这两种旋转模式了,你就不再有三种旋转模式了,会想一想到底是丢掉了哪种旋转模式,但是简单的讲就是game log,就是当在某个特定的情况下。

你的自由度就会降低了,你的旋转自由度就会降低了,这是欧拉角带来的问题,因为此,所以说大家都在想怎么样去解决这个问题,就是引入了一个新的东西,叫做queria,就是四元数。

元素呢最早想要解决一个什么样的问题呢,就想要解决一个怎么样去描述三空间中的一个点的问题,大家都知道虚数跟二维空间是有很大的关系的,因为大家如果学过复变函数的话,大家有没有学过复变函数啊。

有些同学学过是吗啊,不过没学过也不要紧,就是说你可以这么理解,就是说假如说如果你的横轴是实数空间,你的纵轴是虚数空间的话,那么你在这个二维的平面上,你每一个number,你每个虚数啊都可以啊。

每个复数啊都可以描述一个二维空间中的一个点,就就是你的虚数,你的这个复数空间可以跟你这个二维空间对应起来,问题在于,如果说给你一个三维空间,一个点,你可不可以做同样的事情,对不对,很多同学可能就想了。

如果说一个三维空间中,我给一个点,那我用个3d向量是不是就可以了,向量有个问题,什么问题呢,就是我可以做3d向量的加法减法,但是我没有办法定义3d向量里面的这个除法是没有的,我可以简单定一个乘法。

比如说类似cross product,但是你说怎么定义除法,这没法搞,现在想我能不能像虚数复数空间那样子,我可以定义加减乘除,我都给它定义出来,为什么大家搞了这个四元数据的概念。

是最早是由哈密尔顿发现的,有他就是有一天在一个桥上,他就在想这个问题,就是说3d向量,3d向量没有办法表示3d的点,因为我没有办法定义这个除法怎么办呢,哎他就突然想到,既然三个向量不成。

那么三个向量不成,那么我是不是就可以搞四个值xyz w,我再多一个四个数字变成四个数字去描述一个3d空间中的一个点,叙述有点像,只不过呢我不是一个叙述,我有三个叙述。

分别就是i j还有k这里是一一是实数,是一个虚数,这也是一个虚数,k也是一个虚数,我就可以用这张表来描述,除法也可以用来这个表来描述,因为乘法反过来就是除法,所以说我就利用这个东西。

我就定义了乘法和除法的规则,quaternion 4元数的定义,次元书呢它有一些计算公式啊,我这里就给大家看一下,因为到时候可能会需要用到,就是我有一个geria,它有两部分构成的,一个是实数的部分。

实数的部分叫s,部分呢叫v啊,然后虚数的部分呢它是一个向量,它是一个向量,它不是一个值,它是不是一个虚数,它是三个虚数,所以说它是一个向量这个实数,然后v是个虚数向量,跟一个常数的乘法呢。

就是a乘以q等于a乘以ab啊,它就分别做乘法就完了,加减法呢就跟向量的加法减法是一样的,就是分别对虚数和实数的部分做加法减法,这里其实应该多个减法啊,乘法呢是这么定义的啊,如果大家回到那个表上。

根据那个规则,你自己推,你其实也可以得到这个公式,但是我这里反正就给你了,就是这部分就是实数的部分,这是实数的部分,然后这部分是虚数的部分,亮亮的这个呃。

这个库特尼的大小呢就是虚数的部分的平方加上10 15分的平方,就是它的长度,向量长度啊,korn长度,这个其实跟刚才是一模一样的,在unity里面,因为我们到时候回去要做作业的时候用unity。

然后unity里面就是有这个特点吗,我记得她很奇怪,就是unity里面提供了惩罚,它不提供加减法,也不提供这个就其他东西它简单的东西它不提供,但是它乘法倒是提供了,所以说到时候如果说要做那个作业的时候。

做计算的时候呢,就是乘法这块你可以不用自己写,但是减法还有这个乘这个乘以这个向量,这个啊乘以这个实数的这个部分,你需要把这个xyz w这个分别这四个值分别做一些啊。

然后对于unity里面它那个xyz这个v它把它叫做x y z,然后w呢就是这个s在unity里面好,我记得是这么叫的啊,就是分别x y z跟w回头看一下,就是就是跟这个不同的cos的。

有一些排列顺序稍微有点不一样,刚讲了这个口特林的定义,四元素的定义,那接下来我怎么来去表示一个旋转,假如说我有个旋转之后,我会表达叫做v啊,旋转轴,然后我旋转的角度呢是c可以把它写成这个东西。

这个v呢就是它的旋转轴,就是它的虚数的矢量和虚数的向量,实数的这个部分呢就是cosc,它除以二,再除以二,然后呢因为它是个四元数,但旋转是只有三个自由度,对不对,所以说我需要稍微把它自由度给约束一下。

那怎么呢,我就要求它这个长度为一,这就我对库特尼做一个约束,能够保证它表示旋转的一个操作速度为一,那么因为长度为一,然后长度呢分别是这两个的和长度平方和,所以说这也意味着这个v的长度啊。

等于sin平方分之sin的平方,sin theta除以二的平方,你这个学这个向量的长度得是这个啊,这里这里应该有个2x应该是有对的,应该是有的,这个是表示旋转的一个含义,它可以跟它非常直观。

因为我们很多时候讲旋转就是一个一个一个轴绕着一个轴啊,旋转按一个角度做一个旋转嘛对吧,所以说你根据这个轴,你根据这个角度,你就可以把它换算出来,你就可以很方便的得到了,里面呢它也是默认的一个表达方式。

就是虽然说它界面上是采用欧拉角的方式,但它的表达方式是这个,为什么我们在做模拟的时候会相对来说比较简单,因为我直接可以通过这个unity里面自带的一些变量,我就直接可以把这个库存点得到了。

它转成矩阵呢也有一个公式啊,但是这个东这个东西大家不用记,因为反正很多时候我们就是抄公式嘛,那就是直接抄就完了啊,具体到unity里面,我有三种不同的表达方式,分别是矩阵,欧拉角跟呃对吧。

依然是它自带的方式,它内部自带的方式,然后欧拉角是它界面上的方式取证,虽然说它定义了矩阵,但是我还真没看到那个unity里面具体哪里,他自己用到,它倒是不用怎么样在这两者之间做切换,其实很简单。

就是你啊这个它里面有个赋值的一个变量的,你把这个transform,这个transform是它内部关于变形变的一个变量,你把这个里面的关于旋转的里面的欧拉角给它赋个值。

然后呢你再用rotation的那个变量去访问它,你就可以得到它,然后反过来你对rotation赋值,然后你再访问欧拉角那个变量,你就可以得到它,所以说你可以通过赋值来进行这两个值之间的转化。

这个unity里面反正可以做一个简单操作,如果说你有cturn,你怎么得到旋转矩阵啊,你可以有一个函数在unity里面有个matrix,four by four dot rotation。

这个函数你调用这个函数啊,这里可以看到就是你把querion作为变量传进去,你就可以得到,就这就是说因为那些本身自带的这种不同的表达方式的切换,这种机制啊,所以说不需要自己写。

这是一个unity的一个好处,其实这也是为什么我选用unity作为大家作业的一个原因,因为不用unity用别的话,这个东西全得自己写,大家肯定叫苦不迭,叫苦连天对吧,用unity的好处就是接玩都提供了。

反正就用这个功能就完了,给个好处,现在有cturn了,我们知道我们接下来应该用ian去描述这个旋转了对吧,那根据我们之前的那个模拟方式吗,我们之前是更新位置,我现在是更新quaternion一样的。

我通过模拟我得到新的quaternion,然后我去模拟,继续模拟,那么我这个兔子就可以根据不同的状态,我可以得到不同的不同的时刻,我可以得到不同的姿势,把这个模拟结果我完成了,没玩为什么没有玩啊。

一需要知道它对时间的导数对,那么这是什么,这个叫做角速度,旋转速度,里面我们用一个3d的向量omega来表示这个角速度,角速度的大小呢,这个3d向量的大小呢就是它的旋转速度。

速度的这个欧米伽的这个方向呢,就是它的旋转轴,就是它的这个速度的旋转轴,注意到这个表达方式跟coorion非常像,就是是通过这个向量的长度跟向量的这个大小去啊,向量的方向去描述它这个方向和位置的。

这也就是为什么我们喜欢用qian啊去跟这个旋转相关的原因,因为他跟这个角速度的定义是能够比较契合的,我们现在有旋转的这个keria来描述旋转的姿势,然后我们有角速度物来描述水准的速度了。

但是呢我们还得有力跟治疗,对不对,根质量,那对于旋转而言,这个就不叫利根质量了,这个分别叫做例句跟inerti,这是例句呢怎么去计算,例句呢,它是这么计算的,我这里有个顶点。

这个顶点呢是ri乘以rotation matrix,这个ri是它原来的位置,这个ri是它原来的位置,然后根据旋转呢,到原点,从原点出发到顶点的向量变成了大写的r i,大写的i乘以r i。

我这个顶点上收到了一个力,这个力是f i,对于旋转而言,它会产生一个例句,这个例句就是向量cross product fi,这个就是它的例句,例句加在一起就是总的例句,那我就是跟力一样,就是力一样。

我每个顶点会有力,我把所有的力加在一起,我就是总的受力一样的道理,每个顶点我会也会产生例句,我把所有的力例句加在一起,我就可以得到一个总的例句了,这个就是我的总例句痛,那么有的例句我还要有质量,对不对。

因为我们在讨论质量的时候,质量是一个实数,它是一个小数,一个实数,旋转而言,这个力这个力所对应的质量它就不是一个实数了,它是要变成了一个矩阵,你那手举证,然后这个矩阵怎么计算呢呢。

首先我会计算一个reference状态下的参照状态下的矩,这个矩阵ercial,这个ercial呢是每一假如说每一个顶点它都有质量i,每个顶点都有一个mi的质量,乘以它这个向量,transpose。

乘以它自己,也就是这个向量的长度平方乘以identity matrix,减去它自己,可以他自己transpose这个东西最后算出来是一个3x3的矩阵,我把所有3x3的矩阵对于每一个顶点。

我把它全都算出来,然后加在一起,我就得到总的3x3的initial,你的手是什么呀,这个赢得al是reference状态下的,是reference状态下要做一个旋转。

我要分别做rotation transport,然后右边再乘以旋转矩阵,到了这个当前,接下来这个这里我就不解释为什么了,大家可以回去想一想,就是有些感兴趣的同学可以想想为什么是通过这个方式来计算的。

他做了什么事情,他为什么要这么做,但这里我就暂时不写,不解释了,给大家一个思考,得到了一个矩阵,这个矩阵就是对应质量,只不过这个质量它不是一个实数,它变成了一个矩阵,就是我有一个更新法则。

就是物理对于物理而言呢,是质量除以本来是力除以质量,那么对于选手而言呢,就是例句,除赢了,只不过那手是个举证,所以说我不能直接出矩阵嘛,我就变成矩阵的逆,例句拓,这个就是小的更新,然后更新完角速度呢。

我在更新,进queria呢,那我新的qian等于老的quorian,加上这个玩意儿跟老的tan相乘,那其实不是不是cross product,在这里就是一个普通的quernion quorian乘法。

我们刚才tnt tnn乘法吗,这个是cotnt tnt乘法,那我这里实际上是把这个玩意儿也当成,实数的部分是零,部分是第二再t除以二乘以,我们刚才算出来的那个角速度东西,你可以认为是一个eria。

然后这个特点跟后面那个点做一个qun qun乘法,然后再加上去就得到了,里面我们刚才讲了嘛,就是说这个乘法是定义的,但是很奇葩的是啊,这个东加法它不定义,所以说这里大家需要自己改一改,还有一点需要做的。

就是说你算完这个quan之后,你结果它是没有nomalize的,它的这个它这个lance有可能不唯一,这里需要最好是需要对它重新normalize一下,保证这个东西等于一天呐,坏又就是unity呢。

你不做这个东西,也不要紧,因为它内部机制是自动的把它给normalize过的,但是我还是希望他叫normalize school,因为如果你不normalize,有可能你使得时间比较长。

你模拟的时间比较长了之后,它有可能会overflow,因为它本身用浮点来表示这个eria的,它的这个浮点精度有可能会有溢出,所以说希望大家还是尽量把它normalize一下啊,normalize一下。

有可能你直接跑也可以跑啊,我们有状态,我们现在知道我们的状态分别是速度跟位置,速度这变量你需要自己定义,你自己写这个模拟小的这个脚本的时候,你需要自己定义,不需要定义。

因为它这里面在unity里面就是transform,our position,你直接访问这个变量就可以了,速度呢你需要自己定义带关注完,你不需要pton,你不需要。

因为他transform drotation就是cos,就是这个q,就是四个变量分别描述了这个缸体的状态,还需要有一些物理变量对吧,我们模拟的时候还需要有物理变量,分别是质量力,还有talk。

然后这些呢是需要你计算,比如说质量,还有inertial是你需要事先提供的,那么力跟例句呢是需要你在模拟的过程中计算的一些中间变量,你计算完了之后呢,你可以拿来更新状态。

给大家看一下这个模拟器大概是一个什么样的样子嘛,就是左边呢是关于呃平移的运动的更新对吧,我更新我首先算力算完之后呢,首先算力算完力之后呢,对立求和算出总的力,算出历来算完合力了,我更新速度,速度之后呢。

我去更新位置,这个就是我们刚才讲了吗,那么这边呢是我跟当前的当前的位置,我首先得到我的旋转矩阵,取证之后我取证跟ri相乘,我可以得到这个位移的顶点,位移的向量可以去算出来,之后呢我给例句求和。

我可以得到总例句,我可以把这个inn也给它算出来,我根据例句跟inertial的inverse,我可以把这个欧米伽小速度更新,然后根据这个coteria qun相乘的这个法则呢。

我可以把这个cotnt更新,当然最后可能还需要有一部normalization,这个我还需要normalize,尽量大家尽量搞不来,还有一点就是unity一个比较好的优点啊,就是关于举证啊。

有缺点有优点,我先说缺点吧,缺点对于unity它只有4x4的矩阵,它没有3x3的矩阵,也就大家如果想用unity可以做3x3的矩阵,你应该把最后一行跟最后一列填一下,0001001题,把它填一下。

这样子的话就可以把这个3x3的变成4x4的,然后你用4x4的去做计算,好处在于unity提供了一些蛮多的一些操作,比如说inverse算一个矩阵的逆,你不需要自己算,他直接可以通过一个矩阵点英文。

你就可以访问到他的这个矩阵的逆了,这是他的一个好处,但是很多奇葩的地方,比如说矩阵矩阵加法它又不提供,就类似这种,就是大家就会发现很奇怪,就是啊大家以后会留意一下,就是他有矩阵乘法,它有矩阵的逆。

但是他又没有加法,他也没有跟像样小矢量呃,标量相乘的,这些他都又没有大家需要额外注意的一些地方,具体写模拟引擎的时候呢,我其实并不需要说啊,宝宝保存好几个version的,这个v跟x。

还有这个mega跟q的,因为为什么,因为我实际上本质上需要更新这些变量,那更新这些变量,我想只要保保留一个版本就够了,所以说我想只需要vx omega跟q就可以了,那我的输入跟输出分别就是v跟x。

我相当于每次把新的b算出来,我直接把原来的那个给覆盖掉就行,我把新的x算出来,我把这个x比如说像这里x算出来,我把这个覆盖掉就行了对吧,就是把它算出来覆盖掉,算出来覆盖掉就行了,一些时间的细节。

时间的细节啊,有一个就是平移要比旋转要容易,所以说建议大家做作业的时候,比如说大家回头做作业的时候,先写拼音,再写旋转,就是当你写这个旋转的部分的时候啊,你可以先不要去更新速度。

你就先假设omega是个常数,然后你看看你的这个这个物体能不能正确的旋转,比如说绕某一个旋转轴来旋转,绕某一个omega的旋转轴来旋转,你看看这个q的你是不是正确的,做完之后觉得ok之后呢。

你再接下来写就是怎么样去更新欧米伽啊,这个就是就可以把复杂的任务分成几块简单的任务,然后每次去把一个简单的任务完成掉,然后一步步的要把这个代码写出来,就不要上来,就把所有的东西都写出来。

重力是不造成例句的,自由落体的时候,它是不会自发地旋转,或者它已经旋转了,它就会继续旋转下去,它不会例句,所以说如果说你模拟引擎里面没有重力的力,其实你是可以不用去更新米格的,因为它不会自身发生旋转。

空气阻力除外,空气阻力,你这里还是需要操作一下,就是你可以像前面那样,就是把这个东西成一个什么系数,把它衰减一下就行,作业反正就是大家如果做作业的话,就是可以会知道更多细节,我给大家布置一个选读吧。

就是嗯这这篇其实跟我们今天讲的这个内容是比较接近的,就是嗯就是vickbs他们在差不多20年前他们写过一个教程啊,这个教程是比较老了,所以说我倒是不建议大家什么都读全读啊。

但是它里面这部分还是写的比较简单,比较清晰的,大家可以把这一块就是碰撞之前的这块可以先读一下,就是看看人家是怎么写这个啊,就是描述这个缸体运动的,然后怎么样去啊,这个物理公式是怎么推导的。

因为我这个ppt里面毕竟就是信息是有限的,然后如果说大家想了解一些更多的细节的话,可以去参考这个教程,我觉得是一个比较好的一个课后一个选读的读物,什么问题吗,我看一下现实上的同学,了解一下,没事的好吧。

我会下周会大概布置,今天没有,然后我希望下周大概会布置一下吧,跟a相关吗,哪个m,打个m吗,哪一个m会发出来,然后碰撞会我们下周会讲碰撞。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

线性系统哦,前面那个就是新系统那个东西是吧。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对一般来说m都是会跟a相关的,而且理论上其实你这么想,就是说如果完全等于a的话,如果说m等于a的话,其实你一步就搞定了,你一步就把这个问题给解完了吗,因为你m等于a的话。

你其实本质上你就知道a universe怎么解了吗,你知道a universe怎么解,你其实就本来就已经解出来了,但是我们我们没有办法用m就等于a,所以说一般来说我们会希望把m跟a更相关。

就是理论上m跟a越接近a越好,更新角速度的例子,这个我不太清楚,最开始平移后到了世界坐标,我们在讲这个的时候,其实都是假设世界坐标的,就是都是世界坐标的。

只是我相当于我用这个地方其实是局部坐标和世界坐标是重合的,但实际上都是在在做时间坐标,然后这一步呢这一步旋转,这一步是在局部坐标的,然后是变到十字坐标。

因为你旋转是不影响它那个旋转是不影响那个不影响世界坐标的,那个位置的,求是能再求梯度得到力吗,本来就是这样子啊,就是我不太明白这什么意思,就是因为我们算力,通过公式来得到的,就是你如果算出个势能。

它实际上是个数字嘛,你一个数字没办法求导的嘛,对不对,你求导是要用公式来求导的,是根据它的定义来求导的,所以你光是有个势能是不行的,你还是要有公式,你还是要知道这个能量跟位置是一个什么样的关系。

它的解析关系是什么样子的,当然如果说你用数值方法的话是可以的,就是如果说你用数值方法,你可以类似类似利用那种差分的方法是可以的,当然我们一般来说就是如果说我们能解析,我们尽量还是能解析。

因为解析的话它毕竟精确嘛,差分的方法还有的时候会有一些误差什么的,做流体,我们回头讲流体的时候,很多时候用差分,有问题吗,嗯,他在市场上几乎会被鬼微信,后来,对吧对,是会的,但是他们其实可以稍微差不多。

开销是差不多,对它主要原因就是因为你有两个变量,所以导致的,我们今天就先到这里吧,好吧。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值