GAMES401-泛动引擎(PeriDyno)物理仿真编程与实践 - P6:6. 近场动力学(Peridynamics)并行编程与实践 - GAMES-Webinar - BV15M4y1U76M
那个诶大家晚上好啊,那个我看时间也差不多了,这样那我们今天课就开始吧。
然后呃,今天这样,主要还是讲仿真相关的一些技术为主啊,所以就是可能今天的一些数学公式,可还是比较多的,所以这个东西反正这样,但是今天讲的呢,就是后面应该我们也都会就把代码开放出去了。
所以呢就是理论这部分,反正就是如果就暂时听不懂也没有关系啊,就是后面也可以对着,相当于对着代码,我们可以回过来了,然后结合今天讲的内容,我们可以挨个的去看一下,然后今天主要讲的实际上就是经常动力学。
然后呢以及呃呃一些相关的一些理论吧,然后当然这个啊,所以这个计量动力学,整个实际上我觉得相对来说就相对别的呃一些,呃仿真方法还是相对比较年轻的,因为像比如说有电源,到现在可能七八十年了。
然后像s h的话可能也是四五十年,但是呢其实经常动力学这个方法,其实呃发展的比较晚,实际上是应该是算1998年美国的cd,实际上他最早提出了这么一个方法,然后当然早期的方法。
其实他跟就是说跟我们传统理解的,比如跟弹簧系统啊什么可能也差不太多,就是当然这里面它有一套完整的,一套理论体系啊,所以呢又跟弹簧系统整合,是有些本质的一些差别,然后当然后面逐步就是呃完善。
然后呢当然也结合就以前就是单纯考虑,就是说类似弹簧这样的模型的话,那其实有很多问题解决不了,所以后面实际上就逐步的去完善,然后呢基于各种后面也会讲,就基于各种各样的,比如说这种pad那个概念。
然后逐步把这个理论就完善,当然怎么啊,图形这个领域啊,图形其实呃做的就更晚了,差不多是应该是14年最早有一篇,然后当然后面呢我们实际上就呃,一直就是基于这个方向,当然一直在往前推。
然后当然我们这边做的就图形领域,整个做这个方法跟工程里面可能有点差别啊,就是从工程里面的话,主要还是以建模为主,然后但是像图形里边,因为我们很多时候强调的就是说,我们啊强调效率啊,强调效果。
所以这样的话实际上就在图形里面,整个会侧重在呃算法为主,所以今天讲的主要也是呃从算法的角度,然后去看看怎么去,当然基于静养动力学这个模型啊,去比如说去怎么去求解这种啊。
就是比如说布料啊或者烧弹性的那个模型,所以今天主要是车重这一块,然后呢给大家做一下,那个包括这个京东降动力学的一些基础,以及一些比较前沿的一些技术吧,然后整个主要是包含几部分啊。
就是当然首先是这样动力学基础,因为这块主要就大家可能比较陌生啊,所以呢我怀疑花花点时间就跟spa一样啊,就是花点时间,把这个一些基础相关的理论讲一下,然后呢就是呃讲讲就是呃就是投影降动力学。
然后以及里边的一个求解技术,在这里边重点要讲的,实际上今天要讲这个半隐式连带啊,连续迭代这么一个方法,然后这个方法主要也是用来求解,就是说啊这种非线性优化问题的一个,我觉得是一个比较有效。
尤其是在gpu上去呃,并行实现非常方便有效的这么一个一个方法,然后到最后有一些常规品牌一个演示啊,所以呢接下来我们首先来看一下这个呃,静阳动力学的基础,然后啊这里面实际上就要讲一下这个。
因为这里呃我们知道就连续性力学的话,其实发展到现在应该很久了,然后呢其实京港动力学啊,这里有个误区,就是可能会很多人以为这动力学实际上是跟呃,比如跟ph啊,或者跟有限元是一个呃。
一个相当于类似的这么一个方法,但其实本质不是竞技场动力,实际上它是一套新的一个理论,就是它实际上是如果要比较的话啊,相当于要根据说我们传统理解的这种所谓的经,啊。
就连续接力学力学理论要相当跟他做一个对照,所以这里我们先看一下,比如说这个左边这个画的实际上是一个呃,在做连续介质力学分析的时候,通常会比较常见的这么一个模型,就是假设我们就是说相当于是取出里边。
任意一个一个微元,然后连续介质力学它是有什么假设呢,它的假设比如他的内力,它实际上是你发现它整个是施加在一个面上的,就是比如像这里取出一个微圆之后呢,他比如说是个立方体的微圆,然后它有六个面。
这样的话每个面实际上都会施加到一个力,然后也就是说传统电子介质力学里边,它的整个理论基础,就它实际上是建立在接触力的这么一个,基础之上,那接触力代表什么意思,就是呃就是说相当于比如说这里有个微元。
然后它跟它相邻的右边啊,如果也有一个微元,那这样的话实际上他们之间产生力,它实际上它是通过接触产生的,那这个你会发现,如果比如说我们重更微观的去看我们这个啊,这个物质的那个组成啊,比如说到原子层面。
到分子层面,其实我们发现很多实际上是就这个面啊,就这个间就比如这个接触面,这个实际上啊从微观的角度来讲,它实际上是不存在的,就是我们知道微观的层面,比如说你只要所有的呃呃就是物体都是由。
比如说都由分子或原子组成的,那这样的话实际上它们之间并不存在,比如说你这个一个比如说这面的一个定义啊,所以就是说实际上这个传统连这种连续性力学,它实际上是一个理想的一个数学模型。
也就是他把整个比如说我们从宏观的角度来讲,我们就可以比如说那个比如说像分子,你比如他接触力,它的接触的那个相当于作用的一个半径,小到就是我们放大放大放大到一个半径之后。
我们相当于认为它实际上其实就是一个啊,相当于比如说距离无限小的这么一个呃,一个距离,那这样的话其实可以理解可以理想化成,比如说我就是在一个面的一个接触的一个呃,相当于这么一个接触。
所以这个实际上就是一个传统连,连续性力学里面的一个理论基础,然后但是这里边就是呃这样的模型,就是有一个什么好处,当然就是那这样的话,整个后续的比如各种偏微方程,实际上都是基于这个理论推导。
比如说我在上面,因为我们假设实际上都是连续的嘛,所以它这里边核心呢,他认为整个所有的材料都是连续的,所以这样的话,实际上就是我们可以用数学的各种高,数里的那种方法,比如说求他的那个偏导数啊。
比如说一阶二阶的神像,这样的话实际上都可以求偏导,所以这里边就是整个传统的这种方法,实际上比较适合于这种处理,这种连续介质,就是比如说他整个拓扑可能不太发生变化的,这种啊。
比如说就是纯粹的一个弹性的一个模型,那这样的话实际上是比较适合,但是呢实际上就是对于比如说很多场景啊,比如说我们有个布料,我们要撕裂,或者是比如说有个那个火山啊,比如或者山川比较崩塌了。
这个实际上涉及到大量的这种非连续,那非连续的话,实际上这个对于这种传统连接力学里边,其实还是有一定的困难,所以呢呃所以98年的森林提出这个模型,它本质实际上是为了解决,就是这种传统这个连续性力学。
就是在建模这种非连啊,就非连续这个问题,说不太啊就是不太方便的这么一个问题,所以呢提出了一个呃降动力学一个模型,所以这里边实际上就是与传统这个就连接力学,最大的一个区别,就是它实际上就摒弃了。
就是以往就是按照面结出这么一个观念,就是他其实际上就是更像的是,就是说它更像一个分子动力学的一个框架,就是他假设所有的枪都不是一个短程接触力,而是一个长程力,就是比如说就类似于这个原子或者分子。
然后分子之间呢,它实际上是通过,比如说一个长城的吸引力或者排斥异,实际上是来相互作用,所以呢这里边实际上就是这两个最大的区别,其实就是用啊叫一个local,跟当local这么两个术语来表示。
就是以前的local就代表,就相当于你实际上所有的东西,都是建立在你一个微软,就是你可以无限逼近,然后呢啊类似于pv啊,就微积分里面的那个无线可以就是无限,就相当于可以无限的趋近于。
比如说你一个导导数无限趋近于零,这么一个啊概念,就是就是说你去求导啊,求导是求导数,比如用微分的那个形式去表示的时候,你的微元实际上可以无限去定小,然后呢,这样的话,nlogo的。
其实就这里边就可能就存在这么一个呃,偏导的概念,它实际上本质上算的,他也不是说他去算计算这里的导数,它实际上就是说他很多时候算的,不是说我中心点,它那个导数是不是存在,他直接就是相当于他建模。
比如说两个222个布置点之间的一个一个力,或者是直接建模它的一个其他的一个物理量,然后通过这样的整个相当于把原来的这种啊,这是基于这个偏微分方程这样的一个形式,转换成了这种积分方程的这个形式来建模。
这个整个就是介质的这么一个动力学,所以这个实际上就是相当于是这两个方法,一个最大的一个一个区别,然后呢这样的话就是我们来举个例子,就是说比如说对于这个我们描述一个物体的,一个一个形变啊,当然以前的话。
那时间就是你比如说你相当计算某一个点上的,那个,他比如说有个形变的一个行星变一个厂,然后你算算他的那个编导数啊,那这样的话在如果是在这样动力学里边,那它实际上它是通过,就是说他这一点跟sp其实非常像了。
就是它实际上它也有一个支撑域的概念,但这个东西但是跟s p又有不太一样的地方,在于就是说他的那个支撑域不要求符合,就是说你比如说你这个支撑域,靠近这个边界的地方,你的那个支撑位的权重等于零。
它这个其实不限,就是这个没有这个概念,但他同样有一个水平级的概念,就是说你相当于比如说对于他那个,类似于这样的一个范围以内的,任意一个临近的一个点,比如说我们要去描述它的这么一个变化的时候。
实际上就相当于比如这里一个形变,那这样的话它实际上是通过呃,比如说它的中心点以及跟它相邻的两个点,这两个点的一个呃,它上面的这个一个物理量,然后呢利用相当这样连起来的这个一个一个键,就是让后面我们提到。
这实际上就代表一个键,就是利用这个键的,这么像他们对于每个零域,就是每个中心点,它周围所有的那个键,它相当于它的这个变化的这个过程的,这相当于对他的一个描述,比如像这个形变的话。
比如像中心点它有一个u的一个位移,然后呢他领域那个点有个u撇的一个位移,那这样的话实际上对应的这个键的话,这个呃这个键它相当于有一个呃,叫这个相当于这么一个一个位移的一个量。
所以呢当然这里边如果你枚举所有的这个纳,相邻的那个支点啊,这样的话整个比如以它为中心点的,这个所有的它的嗯呃变化的量,实际上都可以通过这种形式给它来表述出来,所以就说它其实并不是通过。
比如说我通过中心点算一个偏导数,或者或者算一个那个呃,比如张亮,然后呢,来表示它的一个连续的一个变化的,这么一个过程,而它实际上就是把它变成了转换成了一个两,两之间,就是中心点跟啊领域点的一个啊变化。
然后这样的话实际上通过离散的,你会发现它实际上更像一种离散的一个表示啊,这样的话就把它转成了,就是一堆的一个领域的一个离散表示,所以呢比如说这里的实际上就是,那如果我们对于每一个键啊。
实际上都有这么一个映射,那这样的话实际上就可以定义成,就相当于把这个整个所有的,就是它跟它相邻的所有的这个,而物质点它的那个形变的关系,实际上就可以描述出来,也就是他们之间就可以存在一个。
一定的对应的关系,就是你这个键,然后呢对应的什么样的一个形变,所以这样的话实际上就代表了一个呃销售形,变态的这么一个变形态的这么一个概念,所以这里面就是整个s降动力进场动力学,它其实最重要的两个概念。
就是一个就是叫,就前面说的一个键的这么一个概念,就是一个bb,然后这个bb直观理解就相当于你,然后呢跟它相邻的这个一个物质点,两个之间的一个点,就是他们之间连起来的这么一个一个键。
就是他们这个实际上就代表一个bd,然后呢对应的每个bug呢,实际上它会有一个映射的一个属性,就是比如说你这个bd对应的,比如说你有个形变,那这样的话实际上它有一个映射的一个函数。
然后这个函数呢相当于它实际上是从一个啊,见到到一个n阶n阶张量的这么一个映射关系,所以这里边实际上就是,也就这里边你发现就是呃,也就相当于你所有的这个bd,然后呢就是你有映射关系之后呢。
所以这样的话你整个所有的这个你的映射,实际上都可以这样用这样的一个函数来表示,所以这个东西跟以前的,就是我们知道的那个函数,可能有有一点不太好理解,是它它的自变量,实际上是相当以中心点为那个起始点的。
这么一个键,而且他的那个因变量是属于,就是说你相当于是一个m j的向量,也就是说这样的话,就比如你一个形变的话,你可以把原来的一个比如球形的一个形状,然后映射成一个椭球的一个形状。
当然这个时候你如果想知道任意点的,比如任意一个键呢它的一个变化,那这样的话,你只要比如说你输入一个他的一个键,那它就可以给你返回,返回一个这样的一个啊映射的一个一个结果。
所以这个呢实际上是构成这样动力学,最重要的一个东西,然后当然这里边你会发现它其实没有啊,导数的概念,就是它整个实际上不需要,比如说你这个东西不需要,比如对他这个中心就是说算一个偏导数。
然后呢这里边其实你还有还可以发现,就是它实际上对整个映射的这个呃连续性,实际上没有要求,就是你比如说像通常,因为如果你按中心点去求导的话,你比如说你可能一定你一定是要。
比如说限制你这个函数可能是一阶可导,至少是连续的,那或者是一阶可导,二阶可导,但是呢以这种方式呢,实际上你会发现他两两之间,可以完全没有任何的那个相互关系,就是比如说你这个键跟这个键。
它们之间可以完全是不连续的,所以这个是这种方法啊比较方便的,然后的一个好比较好的一个地方,当然也是他比如后面可以处理各种各样的,比如这种非连续或者碎裂的啊,这种啊这种问题的一个本质的一个原因啊。
那这里边就举两个例子啊,就是比如说这里这个前面讲那个太,就是呃会有哪哪些就是比较常用的这种类型,就是当然最最典型的,就是类似于s p h d的一个权重函数啊,就是比如说你针对任意一个键。
然后呢他比如说他在计算的时候,他到底它的权重是多少,那这样的话实际上它是从一个啊horizon的这么,一个类似于他的那个领域,然后到它的一个实数空间的这么一个映射,然后这个呢,实际上你发现等效于。
就是s p h里的这么一个权重函数,然后跟那个非常像啊,其实就是因为我把这个建议去呃,算一个他的一个模,就是这样的话,实际上等于它的两个物质点之间的一个,一个距离,然后呢相当于利用它的那个距离。
然后算到一个权重,所以对于这个这个这个标量的一个state,实际上等效率就是一个权重函数,当然这里边其实更重要的,实际上就是比如像这种向量的,就是比如说我从一个原始的,就是v形变的一个空间。
然后变换到一个形变空间的,这样的话实际上它就需要有一个向量态,就是比如说你原始的一个某个向量,它初始的位置是一个什么样子,然后呢对应到这个,比如说你形变之后的一个三维的一个一个空间。
所以这样的话其实就是有一个,比如说你去描述这个变形的时候,比如我定义成就是相当于他如果有形变梯度,然后呢我相当于乘上它的一个键,那这样的话实际上就可以表示成,就。
是当这个实际上就是从比如说假设是从连接历,学历表可能引申出来的这么一个概念,就是这样的话可以通过这个方式来定义,就是如果你比如说你这个时候,你整个是一个这种线性的一个形变,那这样的话。
这个东西整的跟连接这力学历表的那个呃定义,实际上是等效的,当然这个如果你是非连续的,那这个这两个实际上是不一定等效的,然后呢就是整个基于这个太难,其他实际上就构成一个,就是我们所谓的一个代数空间。
然后呢基于这个代数空间,实际上就是也可以进行各种各样的一个,代数运算,然后这里边当然就是要注意的,其实就是这里边比如说它对应的每一个操作,实际上它是要包含所有的那个键,它不是说针对的是某一个键啊。
实际上它相当于要涵盖,就是说你比如说你这个中心点,然后它相邻的所有的那个键,实际上都要涵盖进来,所以呢也就这里边比如说你相当于对于两个泰,你进行求和啊,但是这里还要说一下。
就是一般来说就你看paper的话,就是很多它定义态的话,它实际上会有一个比较特殊的一个标记,就是他用下划线来标记,然后这个主要是为了区别,就是连接的力学里边,一般一般一是这就是它比如说它是用啊。
他不带标记啊,所以这个实际上用这个下标呢,主要是标记那个呃,就是跟连接力学的一些量实际上做区分啊,然后但是后面呢主要是这样,如果是有些呃,实际上很多时候也不会容易引起混淆的情况呢。
就是可能这个下标可能就不标了,然后相当于就我们就知道,这实际上就是一个太主要,后面如果带了一个键的话,实际上它相当于就代表一个一个叫降动力学的,一个td一个概念,然后这样的话其实就是对于所有的。
比如你你两个碳的话,它其实也各种有各种各样的一个操作,就比如说你这里边有两个碳a跟b,然后呢这个time呢,比如说它但这个如果是相加的话,它必须它的那个接触是一样的。
就相当于你如果啊a跟b同时属于n阶太阳,那这样的话实际上这两个就可以直接加和,然后呢另外就是也有组合的这个操作,然后干组合操作,这里要说一下,就是呃这个比较特殊,就是必须得要求这个b是属于一阶态。
也就这个一阶t代表实际上它就是一个向量态,就相当于它是从向量映射到向量的这么一个呃,一个函数,所以这样的话实际上才可以,就是啊这个a跟b进行了一个组合操作,然后当然如果你后面那个不是向量的话。
那这个东西是啊无效的,因为你可以看一下它的整个定义,就是所有的td那个映射,它实际上它的自变量都是键,也就是键,它其实在三维空间里边,他其实对应的是一个三维的一个向量,然后二维空间当然是一个二维向量。
然后当这里边其实呃其他的也是跟很多的,就比如向量的代数啊什么,其实你发现类似的就是比如想怎么就算点击,那算点击的话,实际上这里的就是在两两之间,然后呢两两之间相乘,然后还有内积,内积的话。
实际上就类似于你算啊,这个跟向量里边的那个点击是一样的,就相当于各个元素之间让你把它乘起来,然后相当于求和,就类似这么一个一个操作,然后当然这里边就是因为它整个是一个呃。
实际上也是相当于是整个在他的那个领域里面,要做这个积分啊,所以你发现它实际上是一个连续的,这么一个积分,它不是一个离散的一个求和操作啊,然后当基于这个内积的概念呢。
就是进一步的其实可以定义有它的一个啊长度,它的摩尔以及他的那个方向,然后这个方向跟那个呃,以前理解的那个向量方向可能就有啊,就是可能不太一样了,因为它它这个实际上就是他每一个键。
就是你发现它实际上都有一个方向,就因为它实际上就相当于是它是直接要除的,每一个键的就是它的一个呃膜,所以这里边实际上就是它的整个方向代表的,就是比如你像这里表,它实际上每一个见他其实都会有一个方向。
它不是独立的,就是比如说某只是代表着某一个方向,因为它整个实际上是,所以这个你会发现,它实际上有点类似泛函的概念,它实际上是还是一个函数,它不是一个数,它实际上是一个函数。
然后当然后最后一个这个比较重要,就是在后面讲那个呃,就是讲就是其他的那个,比如怎么求解弹性的时候会用到这个非常多,就是呃就是比如说那个a跟b的二阶张量,然后这里的后面比如说算那个叫shape。
就shape tensor等等,这个会用到这个,然后这个实际上本质上就相当于是a其实也是,就是a实际上是个向量派,然后b实际上有个向量,当然对于特定的一个键的话啊,比如说那实际上是aa的那个。
实际上a跟b实际上就是两个向量,然后相当于用这两个向量的缩,并就是给它组成一个张量,就是组成一个二阶的一个张量,然后利用这个张量呢去描可以描述,比如说我这个本就是比如打个比方中心点的。
在他的一个形变的一个状态,或者那个或者是比如应力的一个,受力的这么一个状态等等啊,然后呢后面就具体讲,就是因为主要这里边,其实这个方法主要是处理固体为主啊,就是所以呢这样的话需要其实啊也等效的。
需要去讲,就是这里比比如他怎么去描述这个一个形变,或者是它的一个受力啊,然后这里呢就是整个也会跟呃连线力学,我们对照着来看啊,就是首先我们看连续机械电力学里边的话,怎么去定义这个一个形变。
它实际上它会用一个二阶张量,就是比如说三维空间的话,实际上是一个3x3的这么一个啊一个矩阵,然后呢这个矩阵呢,当然这里的呃实际上它有九个量啊,但是呢就是很多时候,它因为呃如果比如说我们要求它对称的。
它实际上为它实际上就是不同的量,实际上只有六个,它所以这样的话就整个连续介质力学里边,如果你把一个呃这个,比如你把一个球形的一个微元,你给它做形变之后呢,它会形变成一个椭圆,然后这个是以前的。
就是说那个连建筑力学里边的一个理论基础,然后所以这个当然也是,为什么叫logo这么一个概念,也就是它实际上是没法表示,这种非连续的这么一个形变的,然后但是呢就是在这样动力学里边呢。
如果我们现在用的是一个应变态来表示,因为相当于它来表示的话,那因为他直接是用的是当前的一个位移减去,比如说这个呃,它领域里就相当于跟它相邻的这个点的位移,减去啊,本身的一个位移,所以这样的话。
实际上它实际上直接就是用当前的一个位,置的一个状态来表示它的一个形变的一个结果,所以呢这样的话,对于这个你会发现它实际上是不需要,因为它整个不需要求导,所以就这里边实际上他可以去描述任意的这个。
比如说这种非连续的这个一个形变,比如这里边可能有个尖角,那这样的话,你实际上只需要把这个尖角的这个位移,你独立的给它表示出来,就是比如对于比如说他这个尖角,可能是某一个棒的,它形成了这么一个尖。
那这样的话你对特定的一个尖角,就是你可以用特定的这么一个形象去表示,当然这里边其实你发现就是整个这样的话,其实你也看到了,就是它这个存储空间啊,就是实际上是要比这个连接的力学历本要高的,应该是要高不少。
因为这个这样的话,你其实可以看到他跟s p h其实有点像,因为s p h的话其实也是通过领域来描述,比如说那个一个一个平变,或者是一个其他的一个厂的一个变换,所以说这里边实际上就是。
比如像传统的连接力学里边,我们去描述一个形变的话,它实际上只需要六个量,然后我们就可以把一个他的一个形变,就给它描述出来,但是呢对于这种呃进化动力学的话,它实际上这个你描述的精度。
实际上会跟你啊这么离散了之后,你到底有多少件有关系,就是所以这里说你相当于你的键选的越多,那你能刻画的这个形变的一个模式啊,就是整个会越精细,所以当这样的话,整个进去发现就是存储空间,包括计算量。
就是呃如如果我们现在不考虑啊,就是整个求解的那个,比如说各种啊约束优化,或者那个这个这种方法的一个开销啊,单纯的如果仅仅仅是去看他的,比如存储量,以及它的那个呃领域的这个计算量的话。
实际上是要比啊连续介质力学的这个方法,实际上是要高一些的,那这里有了那个硬件的那个呃太之后呢,实际上就是用力实际上也是类似的,就是呃传统的话,其实相当于是也是用一个二阶的一个张量。
就是它对应的就是相当于是一个3x3的,比,二维空间,实际上是一个3x3的这么一个一个二阶张量,然后当然这里边还有一个本构关系啊,就是呃应力和应变之间的一个关系,像以前实际上是也是用一个线性关系。
就是这个c呢代表的是一个保护关系啊,然后这样的话,如果是比如说硬币和应变在三维空间当中的话,是这样呃,我们假设它实际上都是有九辆,那这样的话这个c实际上包含9x9,他会有三啊81个量。
然后去描述这个应力和应变的这么一个关系,然后呢那到了这个呃就是镜像动力学里边的话,它实际上也是有类似的这么一个概念,就是它相当于是它的应变向量派,跟它的应力向量派之间呢实际上有映射关系,当然这里边啊。
有可能还会跟其他的一些呃量也有关系啊,就比如说我现在应变,比如说它可能是跟啊温度或者是跟压强什么,其实都有关系啊,那这样的话也可以把其他的呃一些量,实际上都建模在这个地方。
然后当然这里边就是我们图形里边,我们暂时应该哎没有考虑,就是说比如说像温度啊等等这些啊,所以这里边实际上简化的,实际上就相当于直接是一个应变向量态,跟一个应力向量派的这么一个一个关系。
然后呢整个其实这样的,因为它整个所有的话也实际上是一个,无论应力应变啊,它其实因为都是用积分的方式来表示的,所以它们之间的那些关系呢,呃也相当于就是呃也不是单纯的就是用这个。
比如说一个张量的这么一个形式啊,它实际上这里边就会有多种状的形式,所以这里边你去怎么建模这个,因为实际上这里边就是无论应力还是用电啊,它实际上都有一个呃一个tai,相当于你有个他的一个建造。
它的最终的一个张量的一个关系,所以这里边就是会包含几种典型的这种模型,就是最简单的实际上就叫bd base,然后这个当然是最早就是西林提出,这个方法的时候的,怎么提出来的这么一个方法。
然后这个方法是代表什么意思,就是相当于比如说你的受力啊,只跟你,比如说只跟比如说这个x跟xp他们进行的受力,也就只跟这两个支点,或者只跟这个键有关系,然后同时它的那个大小相等,方向相反。
那这个呢是最简单的一种呃,例子呢就是说精讲动力学最简单的一个模型,然后呢实际上去掉bd base的那个一个方法,然后他这个方法实际上你发现就跟以前的弹簧,实际上就很像了,因为你知道。
如果这里边比如说你连了很多其他的一个弹簧,那不同弹簧之间它实际上是没有影响的,就是你这个弹簧,比如说你跟它相邻的一根弹簧,你的力度怎么变啊,就是说你的那个表格关系你怎么变,实际上跟其他的弹簧没有关系。
所以这个是最简单的一种一种模型,当然更复杂一点,就当时就是这种方法有什么问题呢,就是之前就做,比如说做这种弹性的一个模拟的时候,发现这个泊松比就是他们无法建模,就是比如说呃因为像这种弹簧模型。
我们知道他整个能模拟的这个泊松比,它是叫0。25的一个泊松比,然后抄其他的那个所有的泊松比,它实际上都是没法模拟出来的,所以呢也就这个方法实际上是有一定的局限,所以就是后来就是考虑到这种方法的。
这些问题呢,就是后来就是在07年的时候,这里实际上就引入了就是叫database的这种方法,然后当database呢这里边实际上就直观的理解,就是你相当于你这个比如x和xp之间的这个呃,受到的这个力呢。
就不光是跟你这个本身这个这两个键之间的,就这两个点之间的一个他之间的那个键有关系,他甚至跟比如说你跟x跟x这个点相邻的,所有的这个键实际上都有关系,所以这样的话,实际上用这种模式呢就可以去建模。
就是说比如说其他的一些补充,比如说这种嗯,比如0。1,0。2等等,就是各种的不同比的现象,应该就可以建模出来,然后这里边就基于t的,其实也有两种的,有两种不同的一个类型,一个叫ordinary。
ordinary代表什么意思呢,就是它整个连线的一个方向,实际上还是沿着这个就是他那个受力的方向啊,它实际上还是沿着这个x跟x撇的这么一个,连线的一个方向,然后这个方向如果是这种方式会有什么好处啊。
就是你会发现它整个角动量肯定是守恒的,当然这个动量呢,其实也可以很容易地保证了守恒,因为这样的话你只需要比如说你把这两个力,你这个加和,然后给他那个两根,就相当于你算x的时候。
你把x撇的那个力你给加上去,也可以保证他的那个角动量守恒,所以啊这角动量和动量,实际都可以很容易的保证手环,当然还有一种就是比较复杂的,就是有可能你这个最后算出来那个力,它实际上并并不一定。
沿着这个x跟x撇的这个一个连接方向,所以对于这样的模型其实比较复杂的地方,就在于就是有可能你可以设计,虽然这个t这个你这个应力啊,你可以随便的去设计,但是呢你有可能设计出来的那个模型。
你可能比如说他的那个角动量不守恒,或者它是它的动量不守恒,那这样的话整个实际上模型可能是从啊,如果是我们是从,就是说从合理性的角度解释的话,可能这个模型实际上并不合理。
所以这里边其实就是其实会有一些限制,当然具体的呃有就说有哪些约束的话,其实之前cing paper也给出了一些,就是呃定义这样的话,就是怎么去约束我们去设计这个设计这个t,然后呢就有了这个。
比如说各种各样的这个力的那个,那就应力的这个呃就是定义之后呢,实际上就是后面那几个动量方程嘛,这个实际上就差不多了,就是实际上你会发现这个跟s h其实也很像啊,就是比如说整个中心点它受到的一个加速度。
其实这个整个实际上就是一个牛顿第定律啊,就是你如果前面再乘上一个呃一个,比如说这个i点的这个一个体积呢,实际上就相当于是一个它的一个质量,然后乘以它的一个加速度,然后呢。
等效率就是它受到的一个啊内力加外力的质和,然后呢这个当然就是离散啊,就是如果离散之后,因为这个呃,虽然他这个连它其实际上也是一个连续空间,然后呢但是实际上计算的时候,我们需要把这个领域做运动比赛啊。
相当于我们有限的点去描述它的这么一个应力,应变的一个状态,所以这个通过离散呢,我们相当于可以把它表示成一个离散方程,所以呢你可以看到就是整个它,比如说它是整个中心点的那个,受力的一个状态啊。
它实际上就是跟他相,跟它相邻的这些键其实都有关系,就是相当于比如跟它相邻的所有的那个键,对这个中心点会施加一个力,然后在这个力的作用下,然后呢产生运动,所以这个实际上是这样动力学的。
这个整个动力学的一个方程,当然这里边就是其实比较复杂的,其实就在于就是因为前面讲的就是这个t啊,这有可能就是比如说就是你你建模的时候,这个呃你没法保证其他角动量守后,动量动量守恒的话。
这个东西实际上去求解的时候可能会比较困难,然后同时呢,就是有可能就是你设计出来的这个东西,因为如果你这里边相当于如果是我们两两间,假设是连的是一个弹簧,那这样的话整个这个球体还是比较方便的。
但是呢这个时候如果我们要建模的这个,超弹性的一个模型,比如说它可能实际上是不是应力和应变之间,它实际上不一定是单纯的一个线性关系啊,所以这样的话,整个怎么去高效的去求解这个方程呢。
实际上就变得非常的一个关键,然后像以前就是工程的领域里边,他解这个东西,因为那个像早呃,差不多56年前吧,因为我们当时看到的时候,基本都是用显示方法去解,所以呢这个时候他其实对他整个时间不长。
因为他其实他的剑非常多啊,就是他整个对时间不长的约束非常的强,就通常可能会要求十的-6,-7,甚至甚至更高的这么一个时间不长的一个约束,也就是这个导致他整个呃相当于进场动力学,整个求解的效率非常的低。
所以呢后来就是这里边实际上就是很关键的一,个,就是我们需要怎么去,相当于比如说我们图形里边,我们希望比如说我们用的是一个大时间不长,那假只要能保证在大时间不长,下面去求解这样一个方程,依然能保证稳定。
所以后面我就主要去讲,就是呃投影这动力学的里边的一些嗯,相关的一些技术,然后呢看看就说我们图形里边怎么去解决,就前面说的那些问题啊,然后这里首先就是我们来看一下,就是呃其实就是比如说像这样的一个嗯。
积分方程,它其实包含两部啊,就是一个呢就是它的一个呃位置的数,就相当于第二个实际上是一个速度更新,速度更新就相当于相当于需要结合,就是说比如上一个时时刻它的一个速度,然后呢结合当前的一个内力外力。
然后呢就根据当前的一个质量,然后呢去更新到它的一个速度,然后这个速度完了之后呢,实际上就可以把它呃,就是进一步的去更新它的一个位置,然后这个当然是比较标准的一个呃,积分的一个形式啊。
然后这个形式就是实际上是可以转换成,如果打个比方,我的内力跟卖力,实际上都可以表示成一个保守力的这么一个,其实假设都是保守力啊,那这样的话实际上这两个保守力,实际上都是可以表示成一个能量的啊。
相对于这个y的一个偏导数的,相当于它的一个导数,所以这样的话实际上对于任何的这种,如果是弹性问题啊,就是不管是线弹,应该是超短性,实际上这样的话实际上都可以表示成一个约束,优化的一个问题。
就是当然这里约束是比如说你要考虑碰撞的,这样的话会有约束,如果你不考虑碰撞的话,实际上完全是一个无约束的这么一个优化问题,所以这里边就是包含两部分,就是这两个可以转换,其实是等效的。
就是相当于第一项是一个动啊,这部分是动量的动量的啊,建模动量的部分,相当于就是你比如说你在积分的时候,你相当于你临时更新了,那么到了某个临时的一个位置,然后呢,这个时候你相当于在最终的位置。
跟他的那个临时的位置之间呢会有一个偏差,所以呢建模的实际上是一个偏差,然后还有一部分就是因为像比如像内力啊,或者外力等等这部分产生的弹性,弹性的一个势能,所以呢整个实际上就是对于这个弹性的,求解的问题。
比如说像前面的那个呃,像动力学这里边的,比如像这个问题啊,他这个问题整个实际上也是完全是,就是我们可以给它转换成一个能量约束的约束,优化的这么一个一个问题,那这样的话。
就是我们实际上就是可以用各种各样的,就是如果我们这个变成了一个优化的问题的话,实际上我们也可以呃用各种各样,就是说整个约就是呃,数值最优化里边的那些方法,然后来来去求解,当然这里边用的最普遍的。
比如如果是非线性问题啊,用的最多的可能大家嗯应该也都听过,就是实际上就是牛顿法,然后牛顿法当然就是啊也非常有效,就是对于解一些啊,因为它整个收敛性非常快,它实际上是二次收敛的。
就是那相当于比如说我们现在已经知道了,它的一个动量的啊,运动控制方程表示成,比如这里假设啊就是f x等于零,那这个时候我们怎么去找,就是说他这个x对它的一个啊,他的根呢怎么去找,那实际上就是相当于我们。
相当于对他第一步需要做一个线性化,然后那个线性化什么概念,实际上就整了,就是一个类似于泰勒展示,就是一阶泰勒展示了,就是我们比如说现在选了一个初始点,是在x0 这个位置。
那这样的话实际上就是用泰勒展示的话,就可以表示成相当于在x0 附近的一个呃,线性近似近似,就是呃就相当于比如它的初始位初始点,然后呢加上它的一个一阶导数,然后呢乘上一个呃不长。
然后再比如说我们这个x最终要解的,实际上相当于是要移动多少位置,然后相当才能保证它相当于跟这个y等于零,这个呃这个相交,所以这样的话实际上整个线性完完了之后呢,实际上就可以得到这个一个新的这么一个。
就是这个点,然后这个点呢你会发现它会啊逐渐的去逼近,比如说我们逐步的去这,当然这个位置直接就这个点就比较简单了,就是比如如果一味的话,你直接可以把通过一项,就是比如把这一项移过来。
然后呢把一导数也除过来,那这样的话,实际上你心的位置实际上就可以很方便的,就是通过这个公式啊,然后给他算出来,就是用x0 减去这个fx 0,除以这个f撇xx这么一个一个函数啊,这个实际上比较简单。
但是呃这个问题在于哪呢,就是牛顿法,为什么之所以大家用的啊,虽然用的比较多,但是呢又很头痛的一个问题在于什么地方,其实本质原因在于这个f撇,就是说白了这个函数f的导数啊,它其实计算如果在低位空间。
实际上是比较比较容易的,比如说你就是一个呃一一元函数,那你这个算这个导数非常简单,或者甚至二元三元,这些都没问题,但是呢,实际上我们很多时候解的是一个,比较大的一个问题,就是可能比如说我们自由度有几万。
几10万甚至几百万的这么一个自由度,那对于这样的一个高自由度的这么一个问题,这个它的整个f1 ,这相当于他这个整个算他的那个梯度啊,头它的梯度算逆,实际上这个东西非常的困难。
就是然后这里边之前这里我用了一张内容,是王老师的一个呃那个报告里的一个slice,然后比如说我们针对那个呃弹性能,就是弹性能,那这样的话,他需要实际上去算一个它的海参矩阵,也就是我们根据这个f要根。
相当于相算它相对于这个x的一个偏导,然后这样的话实际上就得到一个海森矩阵,然后这个海森矩阵呢实际上就会包含很多,像就是就是整个过程,当然你可以用那个嵌入啊,整个可以把他这个逐步的给算出来。
然后当然这里边的问题在于,就是你发现这里面每一项,实际上计算其实都会比较困难,就是整个就是就是当然你如果整个数学啊,或者啥的都非常好的话,那有可能你可以把这个东西很容易就给推出来。
但是我相信大部分同学对这个还是比较难的,尤其是如果是比如说到后面我们是进行动力学,因为前面讲了这样动力学里边会有什么问题,就是它每个键啊,中心,它实际上每个中心点,它会包含非常非常的多的那个键。
那这样的话这里边一展开之后啊,会导致它这个形式非常的困难,然后这个时候如果你要去编程实现的话,就是啊会导致整个就是如果一旦出现问题的话,这个东西实际上也不太好调试,所以这里边实际上你会发现。
就是牛顿这个牛顿法,这个方法其实整个呃它是优点,当然收敛性很好,然后呢当然理论基础也这个非常solid,然后但是呢主要问题还是在于,这个在具体实现的时候,这个包不好算的话,你导致你整个时间比较困难。
同时那就是你这样的话,你整个在gpu上面你怎么去并行业其实并不好,并不好做啊,所以呢这里边实际上有没有一种更好的方法呢,就当然这里边跟牛顿法对应的,实际上也有呃,其他的一类方法,我们叫做连续的带法。
然后这类方法有什么概念呢,就是它实际上就是跟牛顿法有一个本质的区别,就是它实际上就是当这个方法,其实还有一个名字,它叫固定点的迭代,就是它的一个核心思想是什么呢,就是我们有没有可能比如说打个比方啊。
比如我们现在要解的是这个fx等于零,那这样的话就是我们有没有可能,比如说我们去构造一个gx,然后呢比如这里边这个蓝色那个曲线,实际上画的是一个gx的这么一个函数,然后呢。
这个时候呢相当于我们去找原先fx的那个跟,相当于找它的根的这个问题,就变成了我们去找这个gx跟y等于x,就像左边那个实际上是等于x这么一个函数嘛,像这样的话,实际上我们变成了去找这两个函数的交点。
然后这两个如果是等效的话,那这样的话,我们就是如果我们算出这个x等于gx,这个它的一个根之后呢,实际上它实际上也我们也就找到了这个fx的,这么呃它等于零的这么一个根呢,然后这里表情你发现。
如果我们比如说我们把这个gx,我们构造了一个啊特别简单的一个函数,就是说也就算gx非常容易的话,那这样的话我们可以逐步的去,相当于通过这个不断的相当于去迭代就去计算,然后更新这个x,然后最终找到找到。
比如说这个我们最终的这么一个解,所以这个呢是迭代法的这么一个,核心的一个思想,所以呢比如说整个它的过程呢是怎么做呢,就是比如说我们啊有一个初始的一个猜测,比如说我们从x0 开始,然后给他带进去。
带进之后呢,然后他相当于这样的话,就是我们左边是x,右边是x0 ,然后呢我们计算这个gx 0,然后这样的话我们就可以得到下一个x1 ,那x一有了之后呢,我们接着把x一带到这个gx这个函数里头啊。
然后这样的话不断不断的去逼近,最终呢你会发现如果是比较理想的情况,就是这样的话,他其实这个嗯,就这个你会发现这个迭代的这个呃解啊,它这个序列,它实际上最终会逐步的逼近到这个,最终的这个解。
当然这里边实际上就是,他这个毕竟整个是有条件的,就是它有一个收敛的一个条件,就是就这样的一个序列,比如你如果设计出来的这个gx啊,他它的那个一阶导数如果是小于一的,比如像我这里画的那个曲线。
它一导数肯定小于的,因为它整个你发现它实际上是在y等于x,因为y等于x,它的那个导数是等于正好等于一嘛,所以这样的话,如果你的那个理解导数小于,意味着是,就是说你它的斜率要比这个y等于x要平。
所以这样的话对于这种问题,你实际上你只要给的这个初值呃,如果是比较合适的话,它实际上你肯定是可以,说这样的话,你肯定是可以找到一个最终的一个结果,但是呢这里边这个方法的问题在于什么呢。
就是那其实并不是所有的函数,实际上都是可以收敛的,所以这里我举了几个简单的例子啊,就比如像这里边儿嗯,比如gx等于x,那这个是个线性函数,这个百分之百没问题啊,这个就不用面罩了。
然后当然其他的你可以看一下,它实际上它收敛是有条件的,就比如像这个gx等于x平方这么一个函数,你算它的一阶导数之后,它实际上是等于2x,那这里边如果对照前面那个收敛条件的话。
也就是说它只有在00点五之间,00点五之间,它这个函数的导数它其实才可能小于一,然后呢也就大于0。5之后,它实际上都是那个啊相当于是大于一的,所以这个时候你会发现,就是说你如果对于这样的一个问题。
你选的这个不同的那个初始点,会导致它实际上最终有可能收敛,也有可能不收敛,然后这样的话,实际上对于我们比如说去解这个访问问题,这个实际上一般是不可接受的,因为你很难去确保。
就是说你选的初始初始的那个值一定是在,正好是在某个区域以内,这个时间一般做不到的,所以这里边就是对于这种问题的话,实际上就是你会发现,比如说像这个问题,他呃你如果比如说你的这个整个曲线大一的话。
你即使是选了一个跟他离的非常近的一个位置,就是跟x星的非常近的一个位置,但是它米饭它逐步迭代之后,它实际上是在逐渐远离这个呃,比如说它的最终的一个一个解,所以对于这种方法的话。
其实他的那个呃适用性比较局限,就是说他对很多问题它实际上呃不一定有效,当然解决这个非线,就是这种非线性的约束优化问题,当然还有一个呃一类方法,就是所谓的这个投影动力学啊,就图理动力学什么概念。
就是呃还是回到就是说前面讲的那个,就是我们的这个目标函数啊,当然这里边就第一项,这个没问题啊,第一项的话因为其实是一个二次项,然后你线性化之后,你对它对它求偏导之后,它实际上变成一个线性的一个一个像。
然后这里边其实最主要的一个问题就是在于,比如说我们如果是一个呃超弹性的一个函数,这里边有w他可能是二次或者四次的,这个不一定啊,就是他任意的函数形式有可能都有,这样的话其实对于后右门那一项。
它实际上就是整个求解的时候,其实并不太就是用很多标准的,比如说你用cg或者叫kobe,或者那个呃搞塞纳等等各种方法想去解的时候,这样是解不了的,所以呢就整个投影动力学它是什么概念呢。
就是它实际上就对整个问题进行了一个拆分,它相当于他希望是这样,就是我们保留就是呃这个线性的部分,然后呢把线因为整个如果是这样,你如果把非线性的部分,整个放到这个全局去解的话,他这个用牛顿法解。
你会发现就是他整个每次需要去做现金化,然后去做海参几岁,然后这个开销一般来说是呃吃不消的,所以呢这里边就是说他的一个想法,就是有没有可能我们把非线性的部分给他呃,提出来,然后能用更简单的方法去处理。
这个非线性的部分,然后把线性的部分我们还是保留在全局,所以这里边实际上就是它的一个核心的策,略与方言,他就进行了一个拆分,就是分成两部分,当然这个原始方法其实就叫flogo跟local两部分。
然后他的这怎么去理解这个概念呢,其实你发现这是它实际上就把非线性的那部,那个部分实际上就作为了一个约束,就是因为我们知道就是比如弹弹簧,或者是其他的一些弹性材料,它如果是在卫星里面的时候。
它整个能量是等于零,那所以呢就是如果我们把这个整个能量这部分,给它拆出来的话,它实际上它等效于它的形,实际上是一个约束,也就是我们最终就比如说,我们最终恢复到它的背斜面的状态,它实际上是一个呃。
就从这个就是这个函数的角度来讲,它实际上是处在它等于零的这么一个,莱芜的上头,那这个时候就是说那我们这时候就是说,比如说啊,就是我们处在一个呃,未恢复到零的这么一个状态,那我们怎么去建模。
就是说这个未恢复到零的这个状态,他跟那个初始状态的之间的一个差异,然后呢这里就引入了一个什么呢,就是引入了一个距离的这么一个概念,然后这个当然也是一个二次项,为什么叫距离。
他因为本章它实际上还是一个二次项,就是所以这里吧,实际上就是他通过这个距离的引入之后呢,他就把这个线性这部分,那这样的话这部分他解的时候,就后面那部分实际上约束这部分假设是已知的。
然后呢去解的仅仅是前面那部分,然后呢加上对于全部分解完之后,他这样得到了一个新的这个一个y,然后呢有这个y呢,它相当于把这部分在t到啊local,然后local部分是什么概念,就是这个时候呢。
实际上他因为整个local,它实际上就是他有可能只考虑,比如说某个三角形或者某个接触点或者接触对,那这样的话,它的整个自由度会变得非常的一个小,然后所以这样的话整个在于logo这部分。
它通过相当于把这个啊,这个就是说那个自由度啊,或者问题的一个空间给它降下来,然后呢在更小的一个范围里边,对他这个进行啊并行的去求解,所以这个是整个降动力学的一个呃。
就这个是投影动力学的一个核心的一个思想啊,但这里边其实你发现它当然也有一些,有一个问题在于什么,就是你发现它整个global里边,你会发现它要求必须是线性的,就是这里边如果你发现就是说你要把这个东西。
你放在就是非线性的那种,在这里边他这个方法实际上是解不了,所以这里边就是你发现就是那我们就是说啊,当然这里边其实还是这样啊,就是你啊比如说这样我们还回到嗯,就是我们讲一个比如右边这个图的这个问题啊。
然后这个问题呢实际上包含几个东西要解,就是一个呢是啊,他的那个当然是这个一个动动量部分,第二个呢是它整个弹性能,弹性能,还有一部分是接触,如果我们现在假设我们是用。
比如说用那个log barrier这样的一个形式,然后呢,这个形式跟弹性能这个形式有一个本质差别,你会发现它这里有一个log函数,然后这个log函数,诶稍等,呃稍等我一下,那个像我手机稍微有点问题。
行那那我们继续吧,那所以这里边比如打个比方,我们现在这个问题里边,我们如果要引入一个这个我们要去解接触啊,就是像这个多层布料之间,多层布料之间的接触,实际上是比较困难的一个问题。
然后这里如果我们用这个就log的这种形式,就i p c里边这个问题去把它加进来之后呢,你会发现就是呃如果用这样的动力,就是投影动力学这个方法之前,你发现就是这个东西你放在哪可能都不太合适。
就是如果你比如说把这一项,你放在global那个sol里面去解,那这样的话你发现就是因为global投影动力学里边,他其实global shop,它实际上是没法去处理这种非线性的这些项目。
比如你这部分你就放在这里头肯定是不行的,因为它这个东西必须要求,它实际上是一个二次项,那这里还有一种办法,当然你比如说你可以把这个接触的部分,跟这个弹性这部分的能量你放在一起去解。
但是这里边你还会发现一个问题,就是什么呢,就是呃不同的这个问题,它实际上它的那个stephics它实际上会不太一样,就是比如说你对这个这个这两个就是弹性能,跟他的这个比如说接触这个能量。
你如果是对它进行求导,其实你会发现,就是像比如说你这个接触那个能量,你如果比如他接触离得特别近的时候,你会发现它的导数非常的大,那这样的话也就他会严格的去限制,整个他的那个时间不长。
也就是说它会导致本来,比如说我这个弹性的部分,我实际上可能并不需要那么小的时间,不长去去迭代的时候呢,就是就是因为正是因为引入了这个,比如说接触这部分,会导致你相当于整个弹性求解的时候啊。
也不相当于必须得用一个特别小的一个时间,不长去求解,这个实际上会导致整个呃收敛性,可能会进一步的一个会导致它变慢啊,当然各种计算效率啊等等,其实也会受影响,所以呢这样的话就是。
所以这里本章有一个问题就要解决,就是我们啊有没有可能就是把比如说这里边,如果我们把这种呃这种比较特殊的一些呃,就非线性的这个像啊,有没有可能更好的去处理这样的一些项,然后呢。
比如说比如说对于一些比较没有那么棘手的,一些项呢,我们依然可以比如说放在全局里边去解啊,所以这个是我们的一个一个初衷嘛,所以针对这个呢,实际上就是啊这个是我们的一个方法。
就是今天也是今天重点要讲的一个方法,就是叫啊投影降动力学方法,然后这个方法呢什么概念呢,就是呃其实本质还是投影动力学的一个框架,但是呢,这里边我们就需要对这个整个非线性项,进行一个拆分。
就首先我们可以看一下左边那个图,如果是这样,就是我们全局去解的话,其实刚才也讲了,就是因为这个fi跟比如这个b,这个就相当于弹性能跟你的接触能这两个之间,因为它整个stephy不一样的话。
会整个会拖累它整个的一个收敛的一个速度,那这样的话就是我们最理想的情况肯定是这样,就是比如我们把这个接触那部分,因为它可能是一个log函数,然后他非常的陡,那这样的话我们把这部分看看,有没有可能拎出来。
然后呢对于没有那么steve的那部分,我们依然能给它保留在啊原来的这么一个,就是全局的这么一个优化目标函数里头,所以这样的话,实际上你会发现,就把原来这个问题就变成了一个啊,原来一个二次项的问题啊。
这可能就是在global这部分,实际上它就变成了一个呃,超二次项的这么一个东西,所以当然这里边怎么去解这个肯定这样,我们不可能说我们又退回到那个牛顿问题,牛顿法因为牛顿的话去解释当然也可以。
但是呢呃前面讲了这个牛顿法应该就是对于,尤其是对于这个定向动力学这个方法,你要去算他的这个海参矩阵,这还是比较困难,所以呢一般来说并不太适用,所以这里后面我们就要去讲。
就是呃半影是连续迭代方法的这个核心思想,到底是怎么去解,就是整个人如果我们现在这个global的这部分,引入了一些非线性项之后,然后我们怎么用迭代的方法去把这个方法。
就是我们在比如说我们不需要去上海人矩阵,然后很方便的,怎么能把这些呃就是最终的那个结,我们给它在global那边给他解出来,所以后面主要去讲一下,就是呃半影是那个连续迭代。
这个实际上我们今天讲了一个重点,就是啊这里我把那个公式整个稍微简化了一下,就是搬的话这个琐碎那一项太多了,所以我假设就是呃比如它的整个质量是等于一,那所以这样的话,前面你发现这个哪些项就没有了。
就是然后包括h等于一,就是把有些冗余的像啊,我给他都消掉了,然后这里边如果这样的话,整个把这个消掉之后,然后我们还是用那个呃降动力学的那个框架,然后在里边这样的话,其实它会包含两部分能量,这是第一部分。
是那个他前面说的那个是动量的这一项,然后这一项二次项也没任何问题,然后当然后面那项呢,实际上是有可能是非线性的,然后你会发现它实际上跟呃,就是连接的力学里边会有一个本质的一个差别。
就是你会发现它整个基本形式啊,它实际上都是类似于这个,因为它整个是用键表示的,所以呢它实际上它的那个所有的能量,实际上都表示的是一个键上的一个能量,就比如这里y i就是相当于它所有能量。
实际上就是类似于就是可以表示成y i n加一,减去y j n加一的这么一个,它相当于是渐长的一个一个能量,然后呢这里边就是如果我们现在,比如说我们要对它进行去求它的一个呃。
就是最小值就是能量最小的一个问题啊,就是这样的话,实际上第一步肯定是这样,我们需要需要对这个能量相当相对,它这个相对于这个y这个位置,然后相当于对它求一个偏导,然后这样的话我们其实就可以得到。
就是一个呃运动控制,其实是一个运动控制方程,然后就相当于然后这个东西有了之后呢,我们进一步简化一下之后啊,比如说我们把这个y i n加一,把它给它提出来,然后呢把y i因为这个这里有几个。
像是你知道就是这个万爱心,这是已知的这个代表的,比如说我们当前呃,就是就是预测完了之后再得到一个位置,然后呢其他的那个实际上是不知道的,就比如我们这个r哎j n加一。
这个实际上是你发现这个角标要注意一下,就是这里n加一用的,实际上都是一个影视的一个表示,也就是这个是下一个时刻,我们需要知道的一个位置,但是呢我们在当前时的实际并不知道。
所以呢就整个你会发现在后面那个能量项里边,就包含大量的这个影视的一个表示,就是包括r包括那个y等等这个东西,实际上都是一个影视表示,当然这里边其实就如果我们现在打个比方,我们用这个连续迭代法。
就是我们先先简单看一下,如果我们先不考虑搬运时代,我们就是用连续的带法,那这个东西我们看看这个东西能不能解,所以这里边你会发现,如果因为连续迭代法的最核心的就是,我们要构造出一个。
比如x等于gx这样的一个函数,那这样的话我们只要把这个y i n加一,给它挪到这个公式的一个左边,然后后面那所有的那一项我们都给他,索性都给它放到后边,这个形式非常简单啊,就这样的话。
实际上就构造出了一个可以用来做连续迭代的,这么一个一个形式,然后呢这里边就是呃为了标记简单的话,就这里边我把那个ai j哦,这个t可能标错了,这个应该是ai j n,所以呢。
这个整个实际上都给它标记成这么一个形式,然后你发现这个如果用这个去迭代的话,其实呃这个非常适合用gpu并行啊,就是因为你发现它也不存在计算海军矩阵,然后呢,你实际上只需要把当前的这个y。
就是你当前的解给它给它踢进去,然后呢算下一个时刻解,然后呢不断的来回的去迭代,这样的话就是有可能的,只能说有可能你可以得到一个收敛的一个解,但是这个这个实际上是呃有条件的,就是用这样的一个形式去解的话。
就是当我们这个整个给它,呃因为这样你如果把这个东西,你相当于是给他呃处理了之后啊,就是你把那个另外那个这里边有一个,因为最终这个东西你可以看一下这个形式啊,因为它这里边有两个东西。
就是我们这个时候迭代的时候,我们可以做一个处理,就是把这个y j n加一,我们用当前的给他踢进去,那这样的话把右边那一项啊,就y i n加一给他移过,移到左边公式,左边的话,这个东西实际上可以化。
简成这个这么一个形式啊,所以这个形式代表的什么意思呢,就是也就是说你比如说你下一个时刻啊,你比如以i这个呃位置点为例的话,那下一个时刻他的内心的位置,它实际上是由两部分,那相当于它是两部分。
求和就相当于求有一个权重啊,就是求和之后得到的这么一个结果,然后呢这样的话就是它主要包含两部分,一部分呢是比如说它是呃预测之后的这个yi,新的这么一个值,然后呢以及就是说它是呃j他j的那个值。
然后这个j的值,当然这个东西实际上就是你需要把它,比如说根据上一个n的那个时刻给他踢进去了,然后这里边如果我们假设我们现在只有两个点,我们可以看一下,如果只有两个点的话,其实这里边比如左边是一个yi。
然后呢右边是一个y j,然后这样的话如果我们进行一次计算的话,你只是一个什么概念呢,就相当于它实际上就是相当于这两个,就y爱心跟y j跟y j之间的一个差值,所以呢它它相当于会在这两个。
就是y爱心跟y j之间,它实际上会差值得到一个新的yi,但对外界其实也是一样的,然后呢通过这样的一个方式呢,实际上你会发现,如果这个时候,比如说这里我们假设这个ai j大于零,那i g大于零的话。
你你可以看一下,就是首先它后面那一项就是y j这一项,它前面那个系数它肯定是大于零的,那对于左边那一项就是y爱心这一项,它那个权重也是大于零,然后同时你可以看到就是这一项,就是这两个呃系数。
它加起来的和应该正好是等于一,所以这样的话,其实就也就是说新的那个位置铁定会在,就是yi心根上一个时刻的这个y g,y g的那个这两个位置的中心的某一个位置,然后这样的话你你如果是逐步的去插值。
插值插值,这样的话逐步迭代,最终呢他的那个实际上会,理论上应该是会收敛到一个呃极值点,然后也就这个时候对于这种情况,就如果是ai这个大于零的这种情况,那这个对于这种迭代方法肯定是可解的。
就是他也就他肯定是会在这个这两个位置之间,他肯定会找到一个最终的这么一个解,但是呢这里边我们去看另外一个情况,就是如果说比如说a i j这个时候小于零,a i j小于零代表什么意思呢。
就是啊这个y j它这个位置啊,就是这里y j这个位置,他这个位置他前面那个系数,它实际上有可能是小于零的,那小于零代表什么意思啊,就是当然这里边呢实际上会超出一,就是因为你这个a i j小于零的话。
这个一加a i j呃,这个整个分母啊它实际上会小于一,那这样的话整个y i星的这个前面那个系数,它实际上是要大于它,先要大于一,所以这个时候你发现就是说,如果这个时候。
他y爱心跟外界之间再做一个差值的话,他不会跑到这个这两个点的一个中间,他直接会跑到这个,比如说外界的这个右边,然后这个时候你如果逐步的不断的去插值的话,他有可能啊就当然这里边跟这个系数有关系。
如果你这个系数是选择虽然它小于零,但是比较小的话,他有可能也会在外头收敛,但是呢如果你换另外一种情况,你这个系数如果选的不合理啊,就你有可能会导致它逐渐相当于逐渐的偏离。
就是相当于会就是这个新的那个位置啊,或者它相当于会离这个原来的位置越来越远,越来越远,最后呢可能就整个可能,那也就意味着整个你这个解实际上是不收敛的,那所以这个你会发现就是如果用这个迭代法。
就是去解这个问题啊,你会发现它整个呃前面的系数,对于他们那个收敛性的影响会非常的大,所以这样的话其实就是因为我们不可能说,我们就是说我们去不断的去改这个系数,这个其实也不太现实,或者我们去猜某个初始值。
然后保证它这个系数一定大于,这个其实也不太现实,所以这里边我们就用一种什么办法,去解决这个问题,就是实际上这里就要用到一个半影是联,就是今天讲的那个半影是呃,联系迭代的这么一个方法。
然后这个方法的核心思路就是前面讲了,就是呃就是主要原因就在于,就是说他前面那个就是,相当于主要是y i n加一啊,啊这里可能标的是那个t加这个标错了,这个n加一也就是这个y2 n加一。
这个像它前面那个系数的正负,实际上会影响它的一个收敛性,所以这里面实际上整个思路问题,方案其实也非常简单,就是那我们就有没有可能,就是说我们把能收敛类项,我们用影视的去处理,然后呢不能收敛那一项。
我们直接就显示去处理,所以这样的话,我们实际上整个这里边就对它进行了一个拆分,就怎么拆呢,就是我们相当于对于这个ai j n这个像啊,所有的也就是说你不管你这个r,就是因为它这个值啊。
就是这个ai介于n,它实际上也会跟这个r有关系啊,也就是说你不管怎么变,它这个值始终保持正向的这一部分,我们给它拆出来,同时呢比如说他你不管怎么变啊,就是它这个系数是中为负的那一项,相当于也给他拆出来。
然后拆出来完了之后呢,对这两部分我们实际上就分别去说处理,就是对于就是说这个前面是正的那一项,那我们实际上是用这种隐晦的一个办法去处理,隐私办法,处理完了之后呢,将这个实际上就相当于就是隐私方法。
其实你不需要做任何处理啊,就是你相当于整个时间还是保留它的原相,那这样的话就这个y i n加一呢,实际上正好可以移到这个右边,然后呢,就整个去相当于对它做进一步的一个一个计算,然后对于就是后面。
就是他的那个前面系数是负的那一项呢,这个时候我们直接做一个显示的一个处理,就是相当于我们这里y j n加一,因为这两个实际上都是影视的一个表示啊,就相当于下一个时刻的这个位置。
这个时候我们直接用当前时刻的位置,给他踢进去,然后呢,也就这个时候你会发现就是整个就变成了一个,如果这一项你如果把这个移过去之后啊,它实际上就会变成一个这么一个形式,它包含几部分呢。
就是当然这一项是已知的,然后呢这一项呢实际上就是一个影呃,就是所有的y i就是yi,实际上整个都移到了右边,然后呢,你会发现就是当然显示处理类项呢,都保留在公式的一个左边,然后呢。
这样的话其实就是你会发现,就是整个用这个方法去迭代的话,就是因为他这个里边的所有的系数,它实际上现在都是正的,他没有负的那个系数啊,所以这个时候你不论怎么插值,它新的那个值就是他实际上都会包含在这个。
就是说比如说你这项行业了之后,其他人都会包含在一定的范围以内,他不会就是说你逐渐的去远离,比如说你这两个端点,所以这个是整个这个方法的一个呃,最核心的这么一个一个地方。
所以这里后面我就用一个例子来讲一下,就是呃这个方法到底怎么来保证这个收敛性的,就是比如说这里边我们假设有一个呃,不是线性的一个弹簧,就它有两个端点,就是左边的是一个处在零的就可以。
就是说他当左边我们讲是移动的,然后右边呢处在一个一的一个位置,然后我们把右端点给固定,然后呢对于左边那个呃点呢,就是它会受到比如说这样的一个一个弹性力啊,当然这个弹性力我们是不是合理,我们先不管它。
就是我们假设就是说因为后面那个x等于一的,那个位置是固定之后呢,我们给它移进之后,它实际上就变成了这样的一个,就是转成那个呃p p t之后啊,比如说它实际上就变成了这样的运动控制方程。
所以比如左边那个位置,它实际上是需要受到这么一个二次项的一个,一个牵引,然后这里边是这样,就如果比如说你一次项你就很简单,一次项的话,你直接把x网坐标移一下,然后这个实际上就解决了,但是对于二次项的话。
就是我们可以来看一下,就是呃直接用迭代法,就是我们看看它是不是收敛,比如说我们这个时候,我们可以从x0 等于0。5这么一个初值,我们来看一下,就是他他整个他的那个解了一个序列,就是比如x等于0。5。
这个时候它相当于这个时候从这里边开始,然后呢他跟这个y等于x的那个交点,它会处在,比如说这个新的一个,在叫2。25的这么一个位置,然后呢打这样的话,实际上你就可以得到这个新的一个位置,就x1 。
然后x一有了之后,然后进一步的比如把这个再t到这个函数里头,那就可以得到x2 x2 ,你发现它实际上是0。0625,当前面那个公式你如果直接去算啊,它实际上会有两个两个交点,一个呢是处在就是这个位置。
这个位置是正好等于x等于一的这个位置,还有一个位置是处在这个右上角,右上角的话实际上是x等于四,它实际上是有两个解,但是呢其实你会发现啊,就是如果用这种方法,你不断的去迭代的话。
就是你发现他整个呃不断的在震荡,就是你会发现到,最终他其实也没有去往这个中心,就是x等于一或者x等于四的这个位置去收敛,所以这个你会发现就是对于这种非线性的,因为它整个你如果去验证一下。
就是你整个的右边那一项,直接去算他的一个导数的话,它实际上它的那个导数实际上是大于零,大于一的,所以这个也就是其实从理论上就说明,你直接用迭代法去嗯,做这个相当于去求解这个这个公式。
这个整个实际上是行不通的,那后面我们看看就怎么用半隐式迭代的,这个方法去解啊,就半径时迭代连迭代的话,这里面本质上最核心的就需要去拆,就是把右边那个就相当于,比如说我们分解完了之后。
比如说变成了x平方减去4x加上四,那这里边就是主要包含未知量的有两部分,这个四不用管,因为四的话实际上是一个常量,所以这里面实际上是不需要做任何的处理,然后呢另外两部分实际上要处理的就是一个呢。
就是啊这个-4 x,但这里边-4 x要把负放到这里头啊,所以他前面实际上是一个正的,就是它实际上一个四,因为就是你这里边需要对照一下,就这个函数啊,就这个公式,因为这里边他的那整个左边那个位置。
变量是放在最后面的,所以它实际上有个负号,是在待在这个yi的那个前头的,就是所以就哦就这个公式,比如说它实际上带在yi的那个前头,所以这里边就是你要这里面判断哪个是正,哪个是-2的。
就是哪个显示哪个影视的话,要结合左边是我们要求的是哪个,因为我们左边写的是x,所以这样的话实际上右边是负x,那个像的前面那个系数呃,相当于他这个是如果是正的,那我们需要影视处理,然后如果是负的。
那这个x的平方,实际上我们进一步的,实际上实际上等于负x平方,所以这样的话前面有个负x负x的话,实际上它是属于一个负的这么一个直,就如果x等于0~1啊,它实际上等于负的一个值。
所以这里边如果这么去拆的话,其实它会你会发现就是x平方这一项,我们需要一显示处理,然后呢4x就是-4 x这一项呢需要引出处理,那这样的话就是我们在迭代的时候,比如说我们已经知道了就是dk的迭代步。
我们x的那个值,那这样的话,我们需要把这个x k带到这个显示的,这一项里头,然后呢影视这一项,当然这个因为我们现在不知道,所以这个影视那一项,需要移到这个公式的这个右边,然后这样的话以及之后呢。
实际上就可以得到一个线性化之后的,因为这样的话,其实你会发现整个实际上都是线性化了,就是原来这个x平方这项一显示处理之后呢,其实就已经去掉了,就是这样的话,实际上都也变成了一个呃线性函数。
所以这样的话就利用这个公式呢,就可以逐步的就是比如我们x从0。5,x从0。5开始,然后逐步逐步的去,最终你发现它实际上会收敛到x等于一的这么,一个一个解,然后把这个图如果放大的话,我们可以看一下。
就是这个线性化其实代表一个什么意思呢,就是你发现这个如果是按照这个呃,函数去看的话,它其实是相当于一个它是一个梯度,等于啊-4的这么一个啊一条直线,然后这条直线的就代表的比如说我们这里边。
如果我们x0 把他踢进去,那这样的话代表的,就比如这里有一条蓝的这个线,然后呢蓝的这条线跟y等于x,它实际上会求到一个求到一个新的一个交点,然后这个焦点呢,当然这个也是作为下一个迭代的一个起始点。
然后呢这样不断的也就是时间,你会发现它整个实际上是不断的在通过,你和这个因为整个线性化啊,实际上它实际上就是你因为这是一个呃一维的,它实际上是一个县的,就是一这是一个一元函数。
一元函数实际上一个就是一个直线,但如果是比如说多元函数的话,可能是一个超平面,所以你会发现整个过程实际上是,相当于是把原来一个非线性的一个公式,我们可以转转换成了一个超平面。
就是然后呢利用超平面跟这个y等于x,这个这其实也是一个超平面啊,相当于计算他们之间的一个交点,然后呢这个交点序列,它实际上最终的会逐渐的收敛到,我们相当于最终的一个一个解,所以这个是整个方法。
就是用这个最简单的这么一个一个样例啊,我们可以看一下它到底是怎么工作的,那有了这个之后呢,后面我们其实要处理的就是啊,比如说因为我们呃最核心的,实际上我们比如说要去模拟这种材料,当然这不是线性的。
因为线性的话实际上已经做了很多了,然后这里面主要讲的就是啊,这种非线性的这种超弹性的一个材料,那超弹性材料这里边怎么去描述它,这个这个超弹性的材料,当当这里主要是通过他的一个形变梯度。
嗯是看我看群里有人说是看不到鼠标是吗,那我不知道这回能看到了吗,是光标是看不到光标是吧,我看一下啊,我这样我重新投一下吧,行就是这个光标可能比较小,就是,要不这样我看看那个是不是可以画一下,就是。
行我直接用这个简单画一下吧,然后那接下来的话就是我搅搅一下,就是怎么用前面那个方法,然后呢去模拟这个呃,比如去模拟,就说怎么去建模这个超弹性的这种材料,然后当然这里面最核心的就是。
你怎么去模拟这个超弹性材料的形变,然后加上这个连续介质力学历吧,应该都讲,就是比如说我从一个v型面的一个空间,变换到一个就比如这么一个形变空间,那这个形变空间的话。
实际上实际上是可以用一个形变梯度去表示的,就相当于它形变的这个位置,然后呢对他那个初始的这个位置,然后呢做一个呃偏导,然后这样的话其实就可以,它得到它的一个一个形变梯度啊,然后这里边形变梯度有个特点。
就是其实它包含两项,就是就是你会发现就是左边那个,就是如果以这个二维的这个呃形变为例啊,我们可以看一下,其实包含两个概念,就是首先就是它有个旋转,就是相当于你发现比如说它原先的一个轴。
它可能是在这个位置,然后呢,他旋转完了之后的那个新的轴,可能就到这个地方了,然后这样的话当然这两个有可能垂直到,然后在这里边,也就只有一个旋转的这么一个概念,然后呢旋转完了之后呢,其实还有一个概念。
就是他整个你会发现它在不同的方向,它实际上会有一个一个缩放,所以呢整个也就是对于任意的一个形变梯度啊,它其实可以表示成旋转跟缩放的这么一个呃,联合操作,所以当然这里边其实这样。
就是所以这个你说这里边有一个,当然这个是你如果用呃及分解或者用什么,其实写就你对任意一个形变梯度,实际上都可以分解成一个旋转,但这个代表r代表旋转,这个u代表是一个呃缩放的一个矩阵。
然后当然你可以是先缩放再旋转,因为这里对应的这个公式,相当于就是说这个u放在后面的话,它相当于先缩放,就说你比如说先沿着x轴,y轴先给它缩放了,然后再去旋转,当然你也可以,比如说我先把他这个旋转了。
然后呢再去缩放,然后这样的话也是等效的,所以这里边实际上就是对于任意的一个形变,梯度啊,它实际上就可以分解成这两种模式,就两种,一个是旋转的这个变换,第二个呢是一个缩放的一个变换。
那有了这么这么一个概念之后呢,那实际上哦当然这里边再提一下,就是这里边分解出来之后呢,你发现就是呃就是它有两个,就是有几个主轴方向,就是主页面方向,这个就这个不到一啊,叫不到二,所以这里对应到椭圆。
就相当于它的那个最长轴,以及它的那个对对短轴,这样的话其实对应它的一个主页面方向,然后这几个主页面方向呢,后面会就是定义超弹性材料的,会非常有用啊,就是当然三维空间的话,还有一个咱们的三。
就是对应到比如说沿着屏幕这个方向啊,它可能会有一个也是有的一个应变,所以这样的话,实际上对于三维空间有一个叫莱姆的三,就莱姆的一兰姆达姆的三三个主应变的一个呃,方呃变量。
然后呢这三个变量呢实际上就可以用来定义,就是呃任意的这个,比如说我们常见的b s t v k啊,new hook啊等等,任意的这种超弹性材料的一个能量,然后呢也就任意超弹性能量呢。
它实际上可以用这个三个不变量,然后这三个不变量是怎么算的,就是呃因为前面已经知道了,我们就有两个东西,一个是它的一个形变梯度,然后形变梯度用这里有个不太友好的地方,就影片这个有可能他不是对称矩阵。
所以这样的话就是他第一步实际上就是大概,为什么就是说这个公式为什么要这么定义啊,它实际上主要是为了保证,最后这个c实际上是变成一个对称矩阵,然后那这样的话就是比如说,因为你不管任意的矩阵。
乘上一个他的一个转置啊,他这个肯定是变成一个对称矩阵,然后对称矩阵有了之后,对阵矩阵的一个特点是什么呢,就是如果你是一个对称矩阵,然后按照这个那个就是积分解的,分解完了之后,它实际上是可以变成一个旋转。
以及变成一个对对角的一个对角的一个矩阵,所以这是对称矩阵的这么一个好处,然后当然这个分解完了之后呢,也就是说你可以得到它,三个对角线上的一个分量,当然这个对角线的三个分量。
分别对应的就是它的一个三个主应变,就是咱们的一目的二的三,然后用这三个lambda这个呃纸呢,我们其实就可以定义一个材料的一个,三个不变量,然后这为什么这个三个叫不变量呢。
就是因为其实你这三个这个主应变的方向啊,就是你其实不管怎么选啊,其实这个值是不会变的,就是不到1m到2m的三啊,就比如打个比方,你这个时候你不到一,你可以定义在这个地方,但是呢我现在换一个方向。
我不到一可能定义在这,但是呢2/2可以可以给它定义在这个地方,那这个时候你会发现就是把这两个值啊,其实提到这个后面那个公式里边,实际上这个跟你直接用,比如说跟他最长最短的这个人的去定义的时候。
它实际上是一样的,所以这个是读一遍的,一个就是用这个三不量的一个最大的好处,也就是它可以消除这个旋转的一个影响,然后也就是说它具有旋转不变性,那有了这个之后呢,实际上就是我们就可以根据前面的这个呃。
呃就这相当于这样,就是我们已经假设我们现在已经知道了,这个就像这个形这个能量的形式,你其实可以任意设计的,就是你比如你可以设计成就它的平方三次方,这个也没关系啊,当然物理里边就是比较经典的模型。
它其实是有标准形式的,但这不代表就是说你你必须得用那个标准形式,然后当然你也可以任意设计的那个形式,然后那个能量的形式有了之后,然后当然下一步的实际上你就可以呃去算,就是呃,如果现在。
比如说你是基于这样动力学的这么一个方法,那这样的话,实际上你可以就是说根据这个它的能量,相对于它的那个bb的成为一个偏导,那这样的话其实就可以得到,就是比如这一根棒的它的一个呃应力的向量态。
也就要叫他这个不是影响他,他这个相当于他这个棒子,它们受到的一个一个力,然后所有的这个bd,你比如说你都那这个算出来之后,它对应的实际上就是一个应力相反派,所以这里边这个标准的行当。
整个这个推导比较复杂,这个我就不这样了,就是实际上这里有一个paper,大家有感兴趣的话可以看,就是啊对于比如任意的那个嗯弹性的那个energy,然后呢怎么去呃变成这样的一个形式,然后这里边我讲一下。
它其实主要包含几部分,就是一个呢这个是一个权重函数,就是omega,然后这个权重函数当然你可以可以设成一啊,如果是一的话,那就直接可以消掉,然后呢,第二项代表的实际上是他的一个,基尔霍夫的一个张量。
然后这个张量呢代表什么意思,就是相当于就是它是在应对于,就是说比如说我现在在v形变的空间里边,我选择了一个方向,然后基尔霍夫代表的就是说,你如果是v型面的某个方向,它受乘上他这个奇偶负向量的话。
其实就可以告诉你,比如说它在形变空间里边,他受到的这个力到底是多少,呃我看可以发一下那个paper吗,这个这个是指哪个paper,我我问一下啊,你是说这个paper吗,还是还有那个paper。
嗯行那这个到时候这样,我让那个助教直接传到qq群啊,直接传到qq群里吧,所以这里就这样,那我接着继续讲啊,就这里边实际上就包含几项,就是一个就是当然这个是欧米伽,这个是个权重函数,然后这个就非常量。
然后呢还有一项就是这个k代表什么呢,就是这个k当然这个旧货膨胀量啊,实际上是跟他的那个形变梯度是有关系的,就是所以这里边我列了下面列了那个形变梯度,在进场动力学里边是怎么算的。
所以这一项实际上是前面讲的那个呃,叫ted的那个代入上里边实际上是个td,就i跟x的一个二级账量的一个表示形式啊,它所以你可以看一下,它实际上是呃问,就是y跟这个相当于形变之后的那个呃。
为这个相对的一个向量,以及平面之前的一个相对向量的一个并时,它实际上是这么一个定义,然后呢,这里边就是还有最后就是这里边还有这一项,实际上代表的一个叫shape tensor。
然后这个shape tensor代表什么意思啊,就是因为它整个实际上是对于这个v形变空间,就是这里边整个x是v形变空间,里边的那个位置啊,所以它这里边左边内向,就是这两项实际上都是v型变空间的这么一个。
相对的这么一个向量,所以这两个实际上就是你如果直观的去理解,比如说达标,你这里边包含对称的,然后足够的这么一个a一个领域点的话,这个k实际上有可能算出来,有可能是一个单位对调,就对角阵。
单位阵有可能是一个它对角阵,对角相当于是有可能是那个正好是等于,就非对角,正好是有可能等于零,但是呢这个时候如果比如说你可以考虑一下,比如这个时候你少了一把,少了一半之后呢。
你会发现这个东西就可能就不是单位啊,就不是一个标准的一个对角对角阵了,所以你会发现这个k呢,实际上描述的什么意思啊,就是直观直观的理解,实际上是代表着你外形变的一个形状,它其实你可以简单的理解。
它实际上代表的就是,相当于就是说你这个整个这个支撑域,它位形变这么一个一个形状,然后呢,当然他跟这个后面那个整个呃形变之后的,这一项乘上,就它倒数跟这个乘上之后呢,实际上代表了一个形变梯度。
也就这个时候你如果v形变的话,这个他这个f也正好是等于一个呃,单位的这么一个啊对称阵啊,就相当于是相当于是个对角矩阵,然后这里边就是还有一个问题,就是因为后面我们会展示一些那个,布料的一个案例。
然后对于这个,因为比如像三维空间里的三维空间的话,其实就是比如说刚才讲的,就是你这里有可能会出现共线共面的一个情况,比如说这里边我们上下那个红都不要,我们这个时候或者是极端的情况。
我这个时候可能呃不知道什么原因,就比如因为尤其像处理一些碎裂的场景啊,有可能你比如把周围的全全断了,最后可能就只剩一个棒子,那这个时候你如果再去算这个k或者是这个k,当然那个也不影响啊。
就是当你主要去算f的时候,这个时候你会发现,就是他你算出来那个二阶张量,它有可能是一个奇异的一个张量,所以对于这样的问题,比如或者是布料,比如我们布料现在表示的是一个呃三角面片,那这样的话它三角面片啊。
初始的时候有可能是共面的,所有的那个顶点有可能共面的,那这样的话他算出来的包括不论k也好,或者是他的那个f也好,这几个东西啊,它实际上都有可能是奇异的,那如果奇异的话,这个就有问题。
就是你比如你这个k你是直接求逆的话,这个东西肯定是没法解答,那这样的话直接会导致整个数值崩溃的,所以呢实际上这个时候我们在处理布料的时候,或者是处理一些,比如说其他的一些呃起义的这个场景的时候。
这个时候需要额外的做一些处理,比如这个时候我们在做布料的时候呢,我们额外的引入了一个键,就是相当于沿着法线方向,我们也引入了一个虚拟键,比如这个虚拟键的话,这样的话其实啊这个定义当然是下面啊。
类似这样的一个定义啊,就是我们可以根据它的相邻的这个,比如这个中心点相邻的所有的那个建,然后呢根据他们的那个相应的位置,然后呢算一个他的一个法线方向,然后呢,当然这里还有一个类似于厚度这么一个概念。
然后呢在乘上这个相当于方向,乘上这个这个厚度,然后这样的话就得到一个虚拟键,然后把这个虚拟键相当于,你发现它实际上类似于一个补空间,然后把这个补空间给他补,补齐到原来的这么一个定义头之后。
这样的话就可以我们可以保证整个k或者也好,或者整个f也好啊,他相当于不至于出现,比如说最终出现那个企业的这种情况,所以这样的话对于比如说一些极端的,比如说形变也好,或者是啊。
比如像布料这种codimensional这种结构的话,就需要额外的做一个这样的一个处理,然后有了这个处理之后呢,实际上接下来就是呃,我们其实就可以利用前面的这个半隐式,连续迭代的这个方法。
然后呢去求解这个呃整个超弹性材料的这个呃,呃动力学的一个过程,然后这个怎么做呢,就是当然还是从嗯,因为这里边前面讲的就是,这里边最核心的是这样,我们就需要对这个p因为这里边k是常量啊。
就是其实主要啊变的实际上是这个p,因为这个形变梯度是变的,所以这个奇偶和腹胀量是要变的,所以这里边如果我们需要,就是说类似于用前面的这个半影视类别,大的一个方法能用的话,我们最核心的就需要把这一项。
实际上是需要把旧服商量做一个拆分,就是能保证就是说他也就是说他的某一项啊,就是他肯定是永远是正的,有一项永远是负的,那这个呢就是如果你这个时候你啊这样,我先等等,就是这个时候如果你给f不做任何处理的话。
这个实际上是比较困难的,因为这里边f你不会处理的话,相当于它的非对角线上也有值,而非对角线上那些值的话,其实你很难保证它的值一定是正或者一定是负,所以这个时候我们怎么处理呢,就是我们实际上是利用了。
就是这个是之前2004年的一个paper,就是我们假设如果当然这个非就是非线性的啊,这种非各项均值的材料,最后我们先不考虑,就是我们现在假设是呃叫各项同性的均质材料,让同性均质材料有什么特点呢。
就是它的整个基友霍夫张量呢,可以分解成两三部分的一个乘积,就是一部分呢左边左边部分,第一部分是一个旋转,最后一部分也是一个旋转,然后呢整个肌肉恢复张量这部分呢,它实际上可以表示成一个对角矩阵。
就是它最终的话,因为它是代表着一个嗯相当于形变函数的一个,还就形变梯度的这么一个函数啊,然后这但他那个形变梯度呢,你会发现它其实也是一个对角阵,就是正好是它的一个三个主音变呃,一个三个主流片就代表啊。
这里应该是123啊,当然这个012其实反正差不多,就是实际上是正好三个主应变,然后不到1m到2m的三,然后这样的话其实你发现就是应变的话,他铁定是是正的,因为那不可能有负的应变啊。
所以也就这么一拆之后呢,就就变成了什么呢,就是这个奇偶后服张量的话,其实你发现就是当然这个u跟v这俩,我们要给它拎出去了,但是呢就不加量,这部分呢,我们实际上就是因为他有可能是任意的,这里边的函数啊。
就是比如说你可能是莱姆达平方,或者莱姆达的三次方,或者莱姆达减一平方,这个就不一定了,所以这样,但是这里边就是也就这个时候,我们对于对角化处理之后的这个肌肉恢复张量,我们就可以进它对它进行一个拆分。
就拆成了一部分正向,一部分的是负向,就是什么意思,就是也就这一部分,它永远保证它是一个正的这么一个值,然后呢后面那部分呢永远保证是一个负的值,所以这样的话就对于任意的弹性材料。
就是如果你比如说你自己建模,建了一个弹性材料的时候,这个时候你要做的是什么呢,就是你需要相当于结合这个呃,他的那个这个奇偶服装量,就对角化之后的那个基偶和服装量啊,所以相当于需要给它拆成两部分。
拆完之后呢,这个时候就撑架处理就比较直观的,就是相当于要一部分是显示出一波引出,也就这一部分是正的,那内向实际上是整个是要做影视处理,那这样的话就这也就这个相当于是这个yi。
也也就是说这个是我们假设它的未知,当然这个y j其实也是未知啊,然后呢另外一个显示那一项呢,就是也就是如果是对焦负向量是负的那一项,那这个时候我们就需要对它做一个,显示的一个处理。
显示处理呢这里边用到了一个近似,就是相当于我们甲近似,假设认为当然这里应该是一个近似符号啊,近视的假设认为,就是玩这个就是形变之后的那个一个向量近似,可以用他的一个形变梯度乘上与它的一个bd。
可以用它来表示,那这样的话就左边那一项呢,也就是说我们直接就用一个显示的,也就我们用当前的一个呃状态直接给他踢进去,然后这样的话其实最终呢也就可以化简,得到一个类似于。
你看这个这个实际上就是一个固定迭代迭代,就连续迭代法需要的这么一个形式,你可以看到就是它左边那个所有的那个像,实际上都移到了,就是左边我们要去算的,然后呢右边的实际上是其他的那些量。
所以这个其实你会发现,这个形式整的跟在kobe迭代实际上非常的相似,就是也就这个就变成了呃,其实你可以理解为,其实就相当于把一个非线性的一个问题,因为因为我们知道这整个传统的这个非线性的。
就是以前的那个假货币方法,它实际上是解不了非线性问题的,所以通过类似于这样的一个处理之后呢,实际上我们可以把一些非线性的问题,可以用类似于这样的一个迭代的一个方法,让它可以把它解出来。
当然这里边有一个需要注意的是,就是这里边其实呃,你发现这个这个量就是yj这一项,实际上是要显示处理,但是这里边还有一个就是这里所有的系数,这里的所有的系数也就这个时候也是显示处理。
然后但是呢这个显示处理,也就是说你每次迭代完了之后,他这个系数必须得去更新,所以这里边其实像这一项这一项呃,这一项这两项,当然后面的两项是啊,这一项不用啊,四不用,这个a这一项是需要的,也就这几项呢。
实际上它整个系数因为你这么处理之后呢,实际上他每一次迭代它整个y会变,因为它整个也是一个这里的系数,它整个也是一个y的一个函数,所以呢这里边就需要,就是说你因为你一旦码变了之后啊。
你这个yi不管y i y建议你就变了之后,你所有的系数相当于相应的你去把它更新一下,然后这个时候呢,你整个计算的方式就是就比较简单了,当然你可以看这个整个计算的过程,其实他也不需要算海军矩阵。
因为像左边那个,实际上其实就是一个3x3的这么一个矩阵,那这个矩阵就很简单了,3x3你算个例的话,其实基本没有什么开销,然后呢,右边那个呢,实际上就是相当于,他其实整个是一些标准量的那个计算啊。
就你也不需要去算他的一个呃海豚矩阵,所以这个方法你其实你发现最大的一个好处,其实就是非常适合用来做gpu并行,因为因为这个其实跟假货币方法一样的,假货币最大的一个特点。
其实就相当于你可以高效的在gpu上运行实现了,所以这个方法的话其实也是针对,就是说正好是非线性的这种呃目标函数,这样的话你可以用这个方法来相当于做一个呃,呃并行的一个实现。
然后整个双面性验证其实那就比较简单了,就是你其实可以算一下,因为这个ai k的话,实际上正好是等于所有的这些项,给他求和求出来,所以呢你是分母的话,你铁定是要小于分子,所以这么验证的话。
这个收敛性条件肯定是满足的,就这样的话,整个收敛性应该是没有问题的,当然这里边其实最后我还要讲一下,就是可能会有一个什么问题呢,就是嗯因为这个方法其实在于比如说啊,就比如说我们这个时候我们的离的点。
因为我们因为本质还是在解这个呃弹性,那个就或者是规划的问题,就是我们这个时候如果我们的呃那个姐,我们现在离这个最终的那个解啊,离得比较远的时候,这个时候一般是没有问题的,因为比如说像刚才那个迭代。
迭代完了一步之后呢,实际上等效为什么呢,就是我们如果把那个y i k我们再给它移回来,移到再移到右边的话,其实这个等效应,如果我们不做任何的蓝色区的话,这个y i k正好啊yi正好等于一。
所以这个实际上就是对于什么情况,是一般没问题的,就是对于比如说这个你的y i k,这个离这个最极值点,这个离得比较远的时候,一般这个问题不大,这个时候直接你不需要,一般来说不需要做任何处理。
就y i直接等于一就行了,但是呢这个连这个时候我们发现有个问题,就是在当比如说你这个解逐步的靠近这个呃,最终的解的时候,这个时候因为他的那个导数比较平缓啊,然后这里边就会有可能会存在一个问题。
就是他这个时候他的那个估算出来的那个呃,因为它整个实际上是一个线性化的一个过程,就是我们可以回到比如说前面那一页,就是呃就这个这个就看这一页公式,就这一页图,因为它整个是一个线性化的过程。
它线性化完了之后,他的那个斜率就它那个线性的,就比如这个超平面,它那个斜率有可能要远远的要比,就是比如说要比它的目标函数的那个导数啊,它实际上有可能会比他那个导数要要抖,所以这个时候如果就是说直接的。
我们就这个阿尔法等于一的话,有可能会存在一个问题,就是它可能会直接会导致,他整个实际上最终的那个y i i k加一,比如下一个只是它的那个它的目标函数,有可能要比就是前一个值的目标函数。
可能甚至还要很大,这个主要是出现在就是呃,在比较平缓的这个地方,就是它已经是快恢复到,比如说恢复到位形变的一个状态的时候,它有可能会出现这样的问题,然后这种问题会导致有可能。
比如整个形面会有一些轻微的抖动,所以这里边就需要有一个解决,这个我们叫overshooting的这个问题,然后这里边就需要去解决这个overshot的这么一个,一个问题,然后这一边我们这么解的。
实际上就是其实也比较简单,就是呃其实类似于就是我们用它一阶泰勒展开,就是我们其实这里边就需要去估算一下,就是类似于就来search这个方法,我们就需要去估算一下他那个部长。
就是也就是说因为有可能我们发现,就是我们新找的那个位位置其实已经超了,就这样的话,我们比如说我们这两段在这两个中间,我们有没有可能找到,因为比如说这offer等于一的话,他直接就一步就跨到这个位置了。
那这样的话有没有可能,我们在中间的某个位置找到,正好是使得就是说你这个新的那个位置,它的那个解目标函数,那个是要比,相当于是要比上一个个迭代步的那个,目标函数要小的,所以这个其实这里边解决的实际上。
就是这么一个问题,所以这里边其实展开也很简单,就是我们把那个能量还是这个能量函数啊,这个能量函数的话,按他的一阶导数给它展开,展开之后呢,实际上就是呃我们去估算一下,就是它的一个呃最小。
就是我们估算一下它在这个区间里的,到底哪一个值,就是按这个线性来展开之后,到底哪一个它的能量处在最小的这么一个状态,然后当这里边有可能就是某些极端情况,他有可能会超出一二,所以这里就需要做一个那个阶段。
所以这样的话就是也就这里边是额外的,需要做一部这个蓝色曲,当然这个好处就是比起比如像t图现象,因为t图向上,我们知道他是要逐步的去做来search,就是相当于比如你从一开始是,然后不断的二分二分二分。
最终找到一个,当然这个我们这个这样的一个处理的一个办法,好处就在于就是说你实际上不需要你逐步的呃,多次的去尝试一些,就是你可以通过一步的这个蓝search,然后就可以把这个问题解决啊。
这个其实最大的好处在于,就是说你比如说一些实时的一个访问场景啊,就是你可以比较有效的去控制,你每一个纺织布的一个时间开销,因为不然的话,你这个中间比如说你来摄取的时间,你不可控的啊。
导致他有可能会整个帧率,可能跳变的会比较厉害,然后在这里边就是有一个那个呃收敛性分析,当然这里面其实也是有一些,就是就是这个方法目前存在的一些问题,就是当然一个是前面也讲了整个收敛性的啊。
收敛收敛效率的一个问题,当然这个修炼效率主要也是,我们发现整个它虽然可以处理这种非线性的,这个这个优化的这个问题,但是呢他这个整个会跟jacob这个非常的像,所以其实我们整个收敛就收敛测试的时候。
其实也会发现,就是他整个收敛曲线,跟假投币的收敛曲线也会非常像,就是甲壳币收敛曲线,我们知道它有什么特点,就是它一开始会收敛的非常的快,但是呢就到后面的话也逐渐放缓放缓,就是到最后可能会变得非常的缓慢。
就是假科比的一个特点,当我们这个方法其实你发现就是这个呃,这个绿线跟那个黑线啊,然后当然那个黑线是用的那些笔下,血液加速之后的一个结果,所以你发现就是啊,比如相对于那个王宏明老师。
他们那个那个梯度下降的一个方法去比的话,其实整个就是你发现就是尤其主要是看前前半,前半段前一半的话,你会发现它整个学效率就是这个方法比较快,但是呢到后面的话,其实发现就整个会放缓。
当然这是目前呢就收敛性上呢,可能存在的一个一个问题,当然这个实际上对于就这种特性嘛,其实对于也就是对于不同场景,它实际上可能会适应性不一样,就是比如说我们很多时候我们讲,比如说我们实时场景。
我这个时候我们京东可能要求并不需要那么高,那这样的话我一般来说我们可能只需要迭代,前面几十步,十步,20步,这个实际上就可以了,那这样的话就比较适合用这种方法,当然如果我们对于。
比如说他整个精度要求非常高,我们可能要求迭代几百部,甚至更多的这个迭代部署,那这样的话,这个可能就是其他的方法可能会更有效,当然这里边其实还有一个,就是因为这个方法整个也非常适合并行的。
所以呢其实这个也会有一个效率上的一个折中,当然还有一个问题,就是呃目前就是我们这个方法只适用于,就是类似于它能表示成这种,x等于gx减x p这样的啊,这里应该是x撇减x啊,其实其实这个没有关系。
这两个其实换一下都可以,所以呢主要是类似于能表示成这样的形式,实际上是比较合适的,就对于任意的这个g,比如说x等于gx这种形式啊,是不是一定的能用这个方法去去解,目前只能说目前我们不清楚。
当然我觉得就是能解一类问题,就是是不是所有的方法都可以,这个只能说还需要进步的啊去验证,然后当然最后还有一个就是我简单提一下,就是因为这个刚刚讲的是实际上是全局的global的。
然后global的剪完之后,剩下的实际上是要local的,因为local的,我们相当于前面已经打这个接触那部分,比如说像三角面片跟三角面片之间的那个接触,因为接触它有可能是一个log的形式。
或者其他的一些不太光滑的一些函数来表示,那这样的话这一部分呢,我们实际上就放在了一个local step来接,然后当然这里边实际上这个就比较常规了,实际上我们这里边可以用一个标准的一个梯度。
下降的一个一个方法,然后呢这里边当然主要包含两部分,就是一个需要我们去计算它的一个方向,然后方向算完之后呢,我们实际上需要去估算它的一个呃,整个它的一个部长,然后当这两个因为这样。
他这个实际上是呃处在一个local step,所以呢实际上是相当于你可以针对,比如说每个单元或者每个触点,都完全并行的去做这个处理,然后处理完了之后呢,相当于你逐步的再去更新它的一个一个位置。
然后当然这里边可能还有,还有一些其他的一些啊tria,就比如说这个这里我们为了那个防止,就是说它相当于比如说因为这个log log函数嘛,这个时候你如果靠近零的话,它有可能会变得非常大。
那这样的话实际上会影响你怎么收敛性,所以这里反正的话实际上就是有一些呃,其他的处理,就比如我们在这个把它,这个变成了一个类似的平滑函数,也就是说当小于某一个阈值的时候啊,我们给它截断了。
然后这样的话其实可以防止出现那样的情况,然后当整个这个还有一些比如说像ccd啊,就是因为这里边实际上要防止,就是说你呃大部长下来有可能会出现穿透,所以这里边有可能要用一些c c d的一些技术。
所以这里c d的那个方法也很多啊,这里我就不展开了,就大家有兴趣的话可以去看一下,就这个包括那个唐明老师啊,包括那个像iditic c d等等,就各种方法实际上都可以用。
就是也就是说这里边到local step之后,呃,其实这里整个所有的技术都不局限,就是说包括整个求解的话,这里虽然比如说你用梯度下降法,你或者用其他的各种方法,其实也完全也可以啊。
后面这样我就简单先这样做一下展示吧,就是啊包括这个比如这个多层布料,然后呢后面的布料就后面那个场景,实际上我们在呃这样我先说一下,因为主要这周临时可能那个有点事耽误了,本来应该像这些场景。
我们这周呢实际上是打算整个开源都开出去的,但是呢就是因为耽误了事,所以我的打算就是可能等下一次吧,这样的话就是把啊后面这些demo,怎么都我们就开始开出去,所以这样的话就是前面那些理论呢,反正就是呃。
就比如这会儿可能听的没有那么明白,其实也没有关系啊,后面也可以再回来对着这个代码,然后逐步再去看一下,比如说这样,这样的话,比如是一个部分。
就是类似于桌布啊等等,这模拟,当然还有几个就是交交代交互的一些呃展示,当然这里边呃交互的一些场景,可能会有些一个小问题,就是因为前面整个我们现在实现的方法呢,实际上就是跟ib c其实可能差不多。
就是你如果一旦穿越出现穿透之后啊,他有可能回不去,所以这个因为其实也主要是ccd,普遍存在这个问题,就是cd它实际上你已经穿透了之后,他就没法,一般来说很难去判断它到底是不是已经穿透了。
所以这样的话就是对于这种交互问题,就是如果你比如说你事先设好场景,你让他去模拟一遍,这个一般来说问题不大,但是呢对交互的问题呢,就因为比如最简单的你用个鼠标,你不断去拖,这个时候很有可能。
因为你的鼠标的这个交互操作引入,你有可能直接就让他穿了,这个时候再去叫回来的话,会有可能会有一点问题。
当然也有其他的一些场景,然后这个是一些其他一些阅读的一些啊论文啊,就是哦刚才那个有同学提到,就是那个paper是哪一个,就是呃我这样我标一下,其实就是这个就是刚才说的那个就这个paper。
然后有兴趣的话就是呃那个形式,就是那个力的那个形式啊,怎么导出来的时间可以去看这个这个赔本,然后另外两个是我们的自己的一些赔本,然后呃也已经放出去了,然后后面当然也可以结合代码再去看一下。
然后接下来就是我演示一下程序吧,然后因为这个刚才也讲就是,主要就是因为这周有事耽误了,所以有些代码可能还没放出去。
就是还没开源啊,所以这样我以那个呃私有仓的一些demo,我简单的先放一下吧,然后等到下次的话,我们因为前其实前面的话我们已经讲了啊,包括钢体,包括那个流体啊,然后这次主要其实就是针对柔性体以及啊。
当然碎裂的话,我们现在可能目前还呃还不能开源,就是所以主要是想针对柔性底这几块,这样的话就是嗯,因为前面讲的主要也是各个技术的实现嘛,然后但到目前为止可能还没有太,除了第一节课讲了一下框架性的层面啊。
就是因为比如像研究的话,其实很多时候我们也是比如说呃,我们第一步肯定实现为主,然后实现完了之后呢,后续我们可能就需要考虑,比如这个这个东西怎么使用,比如说我们自己写了一个算法模块或者流体,这个模块。
然后呢怎么跟其他的那个模块或者是算法,怎么给他耦合起来,然后呢最后去搭建一些复杂的一些场景,那这样的话就等下次课的话,我结合前面的那几个啊,比如结合钢铁啊,流体啊,跟柔性体这几块啊啊。
这样的话去到时候综合的去搭建一些场景,然后呢到时去演示,怎么去把各个不同的一些仿真技术啊去串起来,因为其实这个东西还是在仿真里,其实还是相对比较比较麻烦,所以这里边可能有些呃一个是框架层面要解决。
第二个当然可能是一些核心技术,我们怎么样去解决啊,所以这个首先第一个是,然后这里边实际上这里有个目录,大家后面应该整个整个上去,实际上就包含我们整个paper里的,所有的一些样例啊。
就是应该都是一对能对上的。
当然现在主要是可能,有些部分代码可能也没有优化,所以呃或者可能没整理的特别完善的话,有些目前就说可能还需要进一步的再整理一下。
嗯然后这个是一个这个是单层的一个布料,然后单层布料的话,其实当当这规模设的比较小了,呃大概是120x120啊,我要没记错的话,所以这样的话相对来说也比较快,然后当然这里边整个瓶颈啊,实际上就说一下。
就是前面当然整个包含global local两部啊,但是呢其实你发现这种场景就是带自碰撞的呃,解决这种连续碰撞的这个问题的场景,他整个瓶颈呢依然在于碰撞的一步,就是它整个仿真计算。
就是整个弹性求解这块应该是非常快的,但是呢因为像尤其是到后面,比如说你涉及到呃已经快接触的时候,这个时候呢会导致他整个时间不长,就是因为这个接触的存在啊,导弹那时间不上会卡的非常的小。
这样的话实际上会影响他整个仿真计算的这么,一个一个效率,所以他现在其实瓶颈里发现,它依然还是在接触和碰撞这一块,然后比如像嗯到这个时候了,这个时候呢实际上很多的呃三角面片,它实际上离得已经非常近了。
就是其实你肉眼可能看的话,其实可能就已经连在一起了,但是呢你实际上去解的时候,你这个时候依然不能让它出现穿透啊,所以这个时候就呃,呃会比较影响这个它的那个一些性能。
然后当然还有其他的一些,比如说像那看啊,这个是类似于布料的那个那个demo,那这个整个也是那个我们罗子祥的工作,然后他应该也在那个助教的一个群里边,然后有问题也可以直接问他。
这笔记本可能还是相对相对比较慢啊。
这个现在用台式机跑的话,最新台式机的话应该还可以,比如这样的这个就是一个类似于布料呃,就是呃其实就是ppt里的那个布料。
跟桌子碰撞的这么一个一个场景,所以这个当然跑起来的话也可以,那这个规模可能相对大一点,就是可能没有那么快啊。
然后可能需要稍微等一下,这样我整个就那个啥了,不跑完了。
然后等后面整个放进去之后,然后大家可以挨个去试一下,然后后面还有其他几个,比如像这个是一个类似于测试这个布料下垂的,然后还有就是多层布料的,比如像这个实际上是一个多层布料的,这么一个场景。
嗯对这个是差不多几层。
我看一下啊,12345对,这个应该跟paper里的一个是对上,就是差不多有六层,不料看对,就这类似这样的一个场景,然后这个后续的话。
反正这个我就我就先不跑了,就是后面的话直接到时候等开完之后,然后大家可以自己去试一下吧,然后其他的,比如说是这里边有一个这个布料旋转的,然后带呃不同的这个嗯可以测试不同厚度的,当然还有就是。
当然这里面可能有些代码可能会稍微整理一下。
那整个价我今天讲的差不多就这些吧,然后呃后续的话这哦另外我可能要讲一下,就是因为后面我刚才也讲了,就是还是先就是后面我们看有没有可能把呃,各种的技术看怎么给它串起来,所以呢后面有可能呃会有一些额外的。
就是我们这边稍微花点时间,当然包括一方面是整个代码能调整一下,第二个呢要整合一下,所以后面这两次课就是在参考之前,因为混动还有两次课,那两次课的话呃周期可能稍微调长一点,因为主要最近可能也有一些别的事。
所以呢后续的那一刻就是最后剩了两次,改成两周一次,就是下次的话就相当于是我说一下,就是嗯下次的话是21号上,然后再下次的话,6月4号正好是上后门的两次啊,然后主要这个时候说一下别的就没啥。
然后看看大家还有有没有什么问题,然后我们也可以讨论一下,行要不我看好像那个直播间应该没啥问题啊,就是今天因为主要还是讲的啊偏理论,所以这样的话就是很多内容可能不是那么快,能接受。
我估计啊就是这个等到后面,然后这样,反正我觉得学计算机的,只要有代码的话,然后结合理论,一般来说解能逐步的入门,就是这样的话,我觉得应该后面有代码之后,可能能进一步的去加深这一部分。
今天讲那些那些理论嗯,行那我们今天的课我们就先到这儿,然后呃后面的反正有什么问题,我们可以呃,我看有说这些代码可以在哪里获取啊。
就今天刚才说的这个今天的这些代码。
刚才讲就是还没有开出去,然后以前的代码呢是这样,就是这个,当然这个是我们的那个,相当于这个是我们的一个类似于文档这样的,一个呃,就是我们这个开源舱呢,就是类似于我们这个项目的这么一个有网站啊。
然后这里边有两个仓,就是一个是github的一个仓,然后github仓呢,当然这个我好像没点代理,可能练不了啊,然后还有一个呢是一个马云的仓,然后马云的仓,当然这两个目前就是这连跪的。
实际上都是我们已经开出去的,然后就上次包括那个缸体的演示,两力以及呃s p h演示的样例,其实都已经开源了,也就是说这里我们课上讲的这个,所有的这个样例,实际上后面实际上我们都是会开源到建立边。
就这两个这两个舱里头,然后当然有些就是有些可能。
后面也会逐步的去完善,当然因为刚才讲的那个这些是在私有仓里边。
这个私有仓因为我们得整理一下,整理完了之后,我们的后续的话会推到这个开源仓,然后就是github开源仓,然后到时候从这里边,就是因为下次课之前,应该这个就到时候给他推上去。
然后这样的话大家可以去试一下啊,行那我看今天也比较晚了,那要不就今天的那个课,我们就到这儿好。
GAMES401-泛动引擎(PeriDyno)物理仿真编程与实践 - P7:7. PeriDyno插件与功能拓展 - GAMES-Webinar - BV15M4y1U76M
没有我看那个时间也差不多了,那这样我们开始了嗯,然后这次是这样,就是嗯主题实际上就是讲一下,那个该拿的那个系统的,然后里头的一个插件机制啊,然后以及就是一些相关的功能吧,然后当然这个今天讲的内容。
可能会相对来说就是会散一点,但是其实你实际上就是目标实际上只有一个,就是因为前面比如说我们实际上也已经讲了,就是说像比如包括像流体啊呀,像总体,当然其实还有一些其他的技术啊,有些没讲的。
比如说这里边那这样的话,我们实际上就比如说把这种呃,各种各样的这种技术啊,然后相当于怎么能给它给它串起来,然后相当于能在一个呃一个整体的框架里边,然后相当于比如说各个模块之间协同起来之后。
然后去比如说搭建一些那复杂的一些场景,实际上,所以今天这个目的,实际上主要是讲究说,怎么利用这个paradio这个框架或者插件套,这套机制,然后相当于就是把各种的那个技术,然后整合到一起。
然后整个今天的那个啊大纲啊,这是今天大纲,所以分几部分,那个当然首先概述,然后呢,实际上这里的比较重要的一个是c加加跟蓝图,然后这个实际上也是那个整个系统啊,就是整个pd那个系统。
现在呃相当于是一个基础性的一个东西,然后里边包含包括反射呀,回调等等,这些会降一下,然后另外就是啊会讲一下,就整个插件的那个设计的一个激励,然后但还有其他功能以及一些反制案例啊。
然后当然这里边其实还是得可能还得说一下,就是因为本身这样就是做仿真,这里的看你怎么做啊,如果比如说前面讲了,你针对的可能只是某个特定算法,其实是这样这种情况的话,比如说你实际上呃你有没有框架。
或者有没有这个引擎,其实可能呃区别不是特别大,然后呢,刚才讲的实际上就是这里的主要的问题在,就如果出现,比如说嗯,很多时候,你实际上你可能相当相当于需要很多的模块,相互依赖,然后呢或者是需要协同开发。
那这样的话就是怎么相当于有这个框架之后,或者有这个引擎之后呢,怎么能更便捷的这个相当于能配合起来使用啊,那所以这里边实际上就是呃接下来要探讨一下,就是因为呃这也是实际上也是我们从啊,过去过去的在研究。
比如到到当然也相当于有一些工程应用啊,这里这个过程中,然后啊就是实际上面临的一些问题,所以实际上本质相当于我们知道,就是从理论创新到应用,实际上它是一个很长的这么一个还有一个流程。
就是当然整个所有的应用,它这个起点它啊都是理论创新,但是理论创新但实际上是他的起点,但不代表就是说最后啊就是他可能就是应用,其实也不一定不一定是他的一个终点,所以这中间实际上面临着很多问题。
需要去解决啊,所以这样就是也结合我们前期的,就是说一些经验嘛,然后这样跟大家可以分享一下,就是这里边可能会存在的一些问题,当然这里总结下来的话,实际上因为呃我画了三个区域。
实际上分别代表的是呃从研究到比如说到研发,然后到最后到应用的这个整个完整的流程,当然它整个有可能是一个迭代子,每个过程,然后呢我们看一下每个每一步啊,实际上有可能会出现什么问题呢。
就是比如像我们原始单位那个整个研究,是我们一个原始创新啊,这个时候呢这个过程中,实际上就是大家对于科高校工科研院所来说,可能主要还是呃发论文为主,然后但是这个时候呢,实际上因为像整个实际上。
对于这个软件工程也好,或这个它实际上除了论文之外啊,它实际上它的整个呃代码呀,这个实际上也是一个非常宝贵的一个资产,所以这样呢就是实际上就是在发论文的同时,实际上理论上就是说。
我们怎么能把这个各种各样的这个各种代码,怎么能给他维护起来,所以像以往的话就是可能存在的问题,就是说我很多时候文章可能发了,但是呢这个代码可能就是啊,有可能当然当时可能还能用完。
但是可有可能过了一阵之后呢,就可能都不一定能在在哪能找着,或者是这样,就是因为我们知道这个整个软件系统的,实际上也会随着这个比如说你底层的库啊,或者是那个各种平台的那个更新。
它实际上很多时候需要不断的去,不应该升级换代,所以这样的话,你如果代码如果长期缺乏维护的话,会导致他整个系统或者整个代码,实际到最后可能就整个运行不来,运行不起,用不起来,相当于。
那当然最后其实际上还有就是你即使比如说,因为当然这个比如说呃比如前任的代码,实际上很多时候留下来之后呢,就是一般来说就是科研的代码,相对来说就是可能并没有那么规范,所以包括整个文档也好。
整个那个注释啊等等啊,这些东西实际上并不那么健全的,这样的话,实际上对于整个这种就是代码资产的传承,这个时间还是挺成问题的,那这样的话也就是说很多你会发现,就是呃就是你很多时候你论文虽然发了。
但是呢你实际上就是啊,真正你的相当于一些就是工程性的,比如你代码性的一些资产,就很有可能就是很难传承下来,当然这个东西实际上即使就是说你很多东西,最后传承下来,但是呢实际上你如果真的。
比如说因为我们如果到工程应用的话,实际上还是有可能比如说还要经历,比如说整个研发的过程啊,就是比如说对原先的一些呃各种的,比如说以往的那个研究代码的话,它可能接口数据啊,这个等等。
可能这个兼容性相对来说都比较差,那这样的话实际上可能需要做各种改造,然后各种测试等等,然后这样的话让他去把这个,整个相当于变得更好用,然后这个过程里边实际上就涉及到,就是因为它实际上你会发现。
它其实不单纯是一个工程问题,因为在如果在这个过程中,你发现就是可能有一些核心的,比如说有些法律,打个比方法律算法,它涉及到一些核心的一些技术的话,其实这个时候如果纯粹依赖的工程改造。
或者是就是另外工程人员去解决这个问题呢,实际上很多时候又又不太合适,所以这样的话实际上就是存在一个,就是说整个这个呃,呃就是说从你相当于说研究的一些呃,工作到呃应用的过程中。
然后其实会出现一些各种的一些问题,当然这个比如说到底谁来解决,其实也是一个问题啊,就是你发现这个当然最理想的肯定是呃,就是说相当于工程人员跟研发人员和研究人员,一起来配合来解决这个问题。
当然最后实际上就是到应用的时候,实际上也会面临其他的这种问题,因为具体用的话,实际上很多时候我们要到实际的场景里面去测,所以这里边可能会涉及到,比如说像性能啊,稳定性啊,可靠性等等,这个东西。
实际上都是呃可能都会有一个这样的一个问题,所以最终实际上就是当然如果在用的过程中,如果发现比如说可能存在一些新的问题,理论这个时候有可能又会回到,比如说我们的原石,我们一开始的那个啊起点。
就比如说我们的研究,从研究的角度可能进一步的说明,说白了就相当于我们又发现一些新的问题,然后需要从研究的角度去解决,所以你会发现整个这个逻辑其实是一个闭环啊,然后当然这个东西它实际上就是你会发现。
它需要不同的角色去参与,但是呢呃这里边实际上就是不同角色,你会发现他们之间配合实际上起来的时候,实际上是有协作成本的,所以呢实际上就是今天要讲的一个主要的一个,一个事情。
就是说那我们是不是有可能就是利用框架也好,或者引擎也好啊,然后呢,就尽可能的有没有可能去降低,整个不同角色之间的一个写作成本,那当然这个成本刚才讲的就是,其实不同的呃阶段,它的它的成本哪个不一样的。
比如说像那个像研究呃,其实他因为研究,整个实际上他面临的是一些不确定性的,一些问题啊,所以这样的话,实际上整个比如说我们像发一个论文的时候,他其实完整的流程就包括比如说像选题嗯,然后呢当然选完题之后。
比如说这个当然这个需求有可能是从应用来的,当然也有可能是,比如说是从比如说最新的一些,其他的一些科研成果里边,我们呃就是发现问题,然后这样的话,然后针对这些问题的话,我们去解决。
然后当然这个选题完了之后呢,可能有技术方案调研啊,算法实现等等,当然整个就是过程中可能就完了,之后大家还有对比啊,这个撰写论文,当然最后当然肯定是希望这些文章能投出去,然后各种投稿修改。
这个可能有可能会比较漫长,然后当然就是个整个时间呢可能也不太确定,所以这个你发现整个研究的成本,其实主要聚焦在实际上不确定性上面,但是最后的话实际上你论文相当于投资之后呢,呃当然你对于这个计算机理来说。
你代码是这样,当然你也可以开源,或者你可以考虑必然,当然这一甚至有可能实际上很多,我觉得也有可能很多时候是这样的,其实可能投完论文之后呢,你会发现,可能这个这个代码可能最后有可能也呃。
就可能就相当于就最后也没有用起来,所以有可能存在这样的一个问题,当然这个比较理想的就是说呢,这个我们已经做完之后,然后到研发的话,实际上可能就涉及到前面讲的,比如说啊数据规范啊,数据规范啊。
接口规范模块改造等等啊,就这些要当做到最后的话啊,有比如说到实际应用的里边,就会有各种应用场景啊,性能稳定性啊,这种模型等等各种测试啊,所以呢这样的话,实际上就是所以针对这些成本啊。
因为这其实每个对于每个角色,他其实他自己的那个领域里边,相对来说应该是比较呃专业的,但是呢就是它有可能如果出现,比如说他啊我们对比如研究人员,他要去解决工程问题的时候。
这个时候呢可能就是其实很多时候是不擅长的,那这样的话实际上引擎要解决的一个核心问题,就是说呢,实际上我们就是有没有可能通过引擎的,能让大家在自己的这个啊熟悉的这个领域里吧,去去深耕。
然后当然就是说比如说不同领域之间的,实际上相当于呃比如说通过这个引擎工具啊,这各种实际上它之间的那个写作,就变得相当于更方便一些,当然这个东西也不是说呃,你也不是说你不能去其他的这个领域里边去啊。
去做啊做事情,当然这个文章就相当于就是你跨领域的话,会出现一个什么问题,就是有可能因为你对别的领域不熟悉的话,会导致就是说你你可能以为是挖到了金子,但是呢,实际上有可能挖的可能就是这几个破石头啊。
所以这样的话实际上整个派单系统里的,实际上需要解决的核心问题,就是说那那相当于就比如说有没有可能是把呃,比如说编程人员或者研究人员,工程人员,或者当然还有设计人员等等啊,这个不同的角色呢。
实际上在相当于在这个系统里面,能够让他更好的信仰去配合下来来用,那这里边就是呃这里设计的,就是那整个派单的系统里面,怎么去解决这个问题,这里是比较核心的,实际上就是c加加跟那蓝图这个这么一个概念。
实际上本质就是通过啊c加加跟蓝图的配合,然后整个让仿真这个流程相当于更灵活,更那更好用,实际上是这么一个一个思想,当然这里边就是呃,许多有些人可能对蓝图是什么不太清楚,所以简单讲一下,实际上就蓝图的话。
如果以前大家用过,比如说用光略或啥的,这个应该就比较熟,它实际上就是一种啊,一种是叫合式化的一个编程界面,就是它实际上跟就是从某种意义上来讲,它实际上跟c加加解决的是一个问题,是一样的问题。
就相当于是通过一个编程式的一个方式,然后呢去完成某个任务,但是大家但是他这个东西实际上是一个呃,就是在可视化的一个方式,所以呢实际上就是对于就是说非这个,比如非计算机专业的,或者是非那个i t专业的。
实际上可能会更友好一些,然后呢这个我们可以看一下,这个整个real这个蓝图,它实际上是怎么演化过来的,就是实际上整个这个蓝图,包括这套这套东西,实际上也是软件工程,然后不断的呃升级改造。
然后逐步演化过来,所以其实你可以看早期的,比如说像u11 u12 里边二呃,那个其实他那个界面系统,其实你发现跟传统软件实际上是比较像的,因为它这个整个实际上,你发现实际上是一个标签系统。
就是呃他比如说针对某个对象,或者某个那个物体,它实际上就会有一个啊,类似你发现这样的一个属性链或者事件液,然后呢,这个东西呢,实际上就是当你发现这样的一个最大问题。
就是它实际上很多的功能实际上是固化在啊,这也就是你相当于先写程序的时候啊,很多时候你需要把这些东西,事先就就需要定制好,那这样的话实际上呃,我就是对于后面如果打个比方,我们比如说想做一些灵活的重组啥。
这个东西可能就会比较麻烦,但是我们知道实际上很多的任务,实际上是他需要不同的对象,或者是不同的组件之间相互配合,然后他们就比如说可能有一些数据传递啊,或者有消息的一些传递等等。
这样的话实际上对于这种这种方式啊,实际上并不太实用,所以到后来的你会发现就是像到u e3 里边,那逐步就已经有,就是现代的那个我们这就是最新看到的那样,让瑞尔蓝图的这么一些呃原型的一些概念了。
它实际上就相当于是通过把不同的一个组件啊,它实际上就是组件化,组件化之后呢,实际上就是不同组件之间呢,再比如通过数据传递啊,然后通过图的这种方式,然后给他给串起来,那这样的话实际上也就是说很多任务流程。
他这个时候你会发现,它实际上呃就不是固定的了,就是它不需要,就是说你相当于整个编程的时候,或者是整个研发的时候把整个任务流程固化,它相当于给后期的一些应用啊,或者后期的一些呃,在设计的话。
实际上提供了一些,就是动态的和配置的一些能力,当然我们看最近的最新的就是从u14 开始啊,u14 开始之后的话,实际上就是看到的呃,最新的这个蓝图的这么一个样子。
然后他这个东西就实际上就已经啊比较方便了,然后整个相当于就是呃,其实对于一些,比如说没有特别复杂的一些任务吧,它实际上就已经完全可以做到,就是说你不依赖于任何的c加加代码。
那这样的话你也可以相当于直接用这个,整个用各种拖拽式的这种界面的那个形式,然后把一些任务去搭建出来,所以这样的话,实际上对于就是说整个比如说你对一些任务,对于这个非计算机领域的这些呃。
这些比如设计人员来使用的话,这实际上是比较方便的,然后当这个整个你发现就是说u u一这套东西,实际上还是呃比较复杂的,就是呃它里边如果大家去看那个基础代码的话,我估计应该没有多少人。
估计能把整个代码都看一遍,因为里面包含的东西太多了,所以呢实际上对于就是整个拍摄单独系统啊,虽然我们实际上也是啊需要去构造,这个当c加加是底层的代码,它其实也是需要去构造这个蓝图。
那这样的话这个蓝图实际上我们是不太可能,就是说我们去构造那么复杂的,因为考虑到这个东西,实际上是一个太阳的一个系统,因为canyon的一个系统,其实最大的呃一个问题,就是他很多时候他的投入。
实际上是就是包括人员,包括资源的投入肯定是这样,肯定是不会说是特别的稳定,那这样的话,实际上我们要解决的,就是说怎么能在一个比较小的一个,维护成本下边,然后相当于能把一套类似的这么这样一套。
这个系统实际上给大家去搭建出来的。
然后当然就是说有道系统之后,它整个蓝图当然有些好处啊,就是比如说像主要是简化任务流程,然后降低研发成本,因为这个东西实际上我们知道,整个呃如果全去依赖,就是编码人员去做处理各种任务的话。
这个东西实际上这个是非常啊,这个相当于非常吃不消的这个东西,所以这样的话,实际上对一些比较简单的这些任务的话,实际上就是我们希望通过这个蓝图呢,来去释放这个比编程人员的一个压力。
然后比如说最简单的打个比方,就是比如说我们设计了一个仿真模块之后,但是呢这个仿真模块呢,实际上他可能在不同的啊参数下跌,实际上可能就是有不同的一些计算结果,那这个时候呃比较简单。
当然以往你如果bi蓝图的话,你可能就这样一种可能就是啊你写一堆脚本,然后呢,每次你可以可以比如读一堆脚本的那个参数,然后当你通过脚本来运行,进行批量的那个去去更改,然后去测试。
但还有一种就是你不断的去改,程序里边的那个参数,但这个东西就c加加的话,整整的,因为它实际上是一个啊,它是一个编译的一个语言,也就是你每次改完之后,你重新再去编这个,实际上这是整个过程。
它实际上会花费比较大的一个开销,然后当然这个还有一个就是呃就是蓝图,一个最最重要的一个作用,时间就是嗯它实际上是和一个团队之间的协作,主要其实尤其是在比如说像呃设计人员,以及就是呃编程人员之间。
就是可以进行一个无缝的一个剪辑,所以那接下来我们来看一下,就是那针对这么庞大的一个系统,就是刚才讲究rea,如果是真的让瑞那样一个庞大系统,实际上这个是不太可行的,所以呢这样,接下来我们看看。
就是presidental里边就是怎么通过,就是就是一个相对的相对轻量的方式啊,然后把这个cr这个蓝图,这整套东西给它构建出来,所以这里吧实际上其实说起来很简单,就是其实主要现在这样。
整个呃pdl里的蓝图实际上主要依赖两个东西,一个是反射,另外一个是红,实际上就依赖这两个东西,然后相当于对于比如说底层的一些对象也好,或者一些属性也好,相当于相当于从整个框架层面。
对它进行统一的一个管理,然后当然有了这两个东西之后呢,实际上整个目的其实也比较简单,实际上就是相当于我们最终目的就是希望啊,实现,就是说这个代码运行逻辑,跟啊界面运行逻辑的一个统一。
但这里边实际上这个东西呃说的有点呃,呃笼统啊,但实际上这里边,因为我们知道这个整个代码运行逻辑,实际上它的功能肯定是远远超过这个整个界面,运行逻辑的,但是呢,这里边因为我们针对的实际上是一个仿真任务。
就是仿真任务呢实际上它本身要比通用编程,它实际上就是它因为它实际上是更特殊的一种,一种任务,所以呢实际上很多时候呢也不需要就做到,就是说呃跟通用的一个编程,就是它实际上不需要具备一个。
通用编程的一个能力,所以这样的话实际上就是针对这个仿真任务,实际上所以整个派单的系统啊,实际上是针对仿真这个特定的一个任务,然后相当于去进行的一些特定的一些设计,然后让他实现了这个呃代码的一个一个逻辑。
就是代码逻辑跟界面的逻辑,实际上看起来差不多是一致的,然后当然这两个逻辑其实从比如说从这个呃,从视角来看,实际上就是这个代码逻辑对应的实际上是我们,比如说是研发人员的一个逻辑。
都会说是程序员的这么一个逻辑啊,然后当然后面整个界面逻辑,实际上对应的是用户的一个逻辑,就是比如说我们实际上现在有很多这个,反应算法,那这样的话实际上我们对于就是后期用的话。
比如说我们可以利用已有的一些算法,然后去构建各种各样的一些仿真任务。
那接下来就是我们看看,就是呃,就是在里边那个蓝图对应的这个c加加的,就是说这两个逻辑啊到底是怎么统一起来,实际上因为上之前第一次课的时候讲了,就是整个pdal实际上它有四层的一个架构。
就是咱最顶层实际上是可以有个场景图,然后场景图呢实际上是有一系列的这个,节点构成的,当然节点里面还有模块,然后那样当然最底层的是,实际上是有这么一个呃field的这么一个概念。
就是它实际上对应的是各种各样的,各种各样的数据,就是这个feel的里边其实是包含呃,因为是这样,主要针对的实际上是不同的功能啊,就是这里边其实主要分为几类,就是一个是控制变量,一个是状态变量。
然后呢当然还有输入跟输出,当然这个节点实际上对应的是这样,就是只是一个就是创建一个cube,这个是在model这个库里头啊,就是啊比如说创建这么一个对象之后,它实际上会生成一个boss。
然后当然对应这里边呢,它主要的对应的控制变量,因为比如说我们一个boss的话,我们需要去控制它的,比如它的边长,然后另外就是它的表面网格,比如说我们想给它剖分成,比如说是三角网格或4k形网格的话。
那这样的话,比如说有还有一个分段数的这么一个概念,所以呢对于这个主要的控制变量,其实就是它这个里边其实是定义了两个,当然这里边其实因为它主要继承呢,还有一个叫prometric。
parametric model这么一个一个父类,然后这个父类里边其实定义了包括像平移,就是缩放,旋转等等啊,就是所以你看后面啊,就是右边那个图,实际上是展示了完整的这个控制变量。
然后这个控制变量整个实际上会,如果你调这个控制变量啊,实际上他会去控制,比如说因为这里边还有一个概念,就是状态变量,什么意思,就是它实际上就是描述这个整个节点,它所需要的一个最小的一个状态集合。
所以这个状态变量,实际上就是用来描述这个节电的一些一些量,然后呢这样的话,实际上整个控制变量实际上就是呃,也就是这些控制变量定义了之后呢,它实际上会去更新这个状态变量,然后利用这些状态变量分析之后呢。
实际上就得到相当于整个你,相当于最终的这个节点应该是一个什么样子,当然这里的还有就是当然像这个模型啊,它实际上还有一个一个输出,比如他输出一个标准的一个啊这个立方体,当然还有就是其他的。
就是比如说你像有些节点啊,为什么后面我看有些节点实际上是会有输入的,所以笼统的讲,实际上就是像pc gal里的这个,整个c加加跟蓝图啊,就是这个层面上来看,其实节点它其实主要它的节点面对应的。
实际上是界面上的这么一个,就是这个是节点编辑器里的一个这么一个图案,然后这个图案就是跟这个c加加整个代码,你会发现其实各种元素实际上都是一一对上的,当然这里包括还有一个就是啊这个状态变量。
然后这个这个quset,然后这个状态变量呢,实际上是在这个右边那个界面里头,就是它下面还有一栏,这个栏杆那个没没显示出来啊,就下面那栏的话,实际上就就会显示这个有这个节点的一个,所有的一个状态变量。
所以你发现就整个就是实际上,比如针对这个一个cube这个节点啊,所以就是啊这个图形化的一个界面,它跟整个c i a底层的那个逻辑啊,这两个东西实际上就是通过这里边,因为这个实际上是一个宏定义。
然后通过这个宏定义呢,实际上是把这整个东西给统一起来了,然后当然这个是一个单独针对的是一个节点。
然后那这样的话如果针对的是一个场景,一个场景的话,实际上就是要呃相对复杂一点,就是因为它实际上一个场景列表可能会包含,就是说呃各种各样的一个节点,然后当然这个节点之间呢又会有一些,比如数据传递。
比如从上一个节点,它需要比如传递数据到下一个节点啊,那这样的话实际上不同节点,它构成了这么一个啊一个,其实这是一个有向无环图,叫做就是然后它相当于它所有的数据流,就是实际上就是从会从前面,然后传到后面。
然后将所有的节点组合起来之后,当然包括中间的那些连线啊,组合起来之后呢,它实际上对应的就是一个场景,当然这个右边那个实际上你看到的是一个呃,是一个图形化的这么一个场景图,然后当然这个左中间那个视口。
是它显示出来的效果,然后对于这个场景呢,它实际上有一个完全一样的一个c加加的一个,代码的这么一个视图,然后这个代码呢,实际上就是它整个实际上就创建一个,那这个代码可能比较小啊。
这样我直接从呃代码里面看一下,然后这个代码在有个叫tot water ping的。
这么一个阳历里头,嗯在就这个,然后你打开这个类的话,你会发现就是呃整个代码也不多,实际上就相当于它因为它整个所有的这个实现,它其实不在这个这个门函数里头,有门函数只是去负责创建这个这个场景。
然后相当于所有整个场景,它包含哪些要素呢,就是首先它是这样需要创建一个场景,当然这里边可能需要设置一下啊,比如你的重力啊,你这个需要设一下,然后这里边有几个节点啊,我简单讲一下。
就是第一个就是因为它整个是一个流体啊,就是留下来的这么一个一个效果,所以呢首先就是这里边就需要创建一个发射器,然后呢需要当然这里边创建出来之后呢,它需要添加到这个场景里边。
然后当然就是每个场景就每个节点呢,同时它会有呃一些属性,就是比如你这个发射器应该放在哪个位置,那这样的话,你可以通过这个去更改它的那个位置,然后这个有了之后呢,他们后面要接一个流体的一个求解器。
然后相当于把发射器里边创建出来的那个例子,然后输送到这个流体的那个求解器里头,然后呢,这里边实际上当然这里这里有一个这个输送的,这个过程啊,这里有一个叫连接的这么一个一个函数,然后这个函数的指令。
跟刚才看到的一个图形化的那个是一模一样的。
就是这里边实际上你会看到这里连过去的话,实际上正好有一个有一根连线,这个代表的就相当于是前一个节点的数据。
要连入到后面那个节点,然后呢这样的话这个流体这个节点,然后实际上就创建了,当然这里边还有一些,就是因为整个实际上你需要把啊,所有的那个就是比如流体,它实际上是一个粒子系统,所以就因为正好是前面讲的那个。
s b h的那些方法,那这样的话你和额外的,你可以加一些辅助的一些额外的模块,然后用于把这个比如说把流体给他渲染出,然后当然这个场景呢还加了一些边界。
就是后面的那些节点啊,后面那三个节点,实际上,而且后面最后一个实际上是一个,留给我回了一个节点,因为它实际上是跟这个表面网格,它会产生一个耦合的一个作用,那这样的话。
实际上就是这个后面那个流过火的节点呢,需要接入一个流体,然后当然还需要接入一个表面网格,然后这里表面网格实际上包含两个,一个是中间的这个一个球的表面两格,然后当然后面底下还有一个平面啊。
然后这两个东西然后呢是合在一起之后。
然后再输送到后面那个节点,所以这个整个后面实际上是在创立边界,然后这个边界实际上就包含一个平面,然后再包含一个一个球,然后打到最后的话,需要把这两个合起来之后,然后传入到这个流过火的这么一个节点。
所以你发现就所有的数据的话也是一样的。
就相当于他实际上都是通过这个connect connect,对应到这个ui里边。
实际上就相当于是你把这个数据从上一个节点。
然后连出来,连接到下一个节点,然后这里我们可以跑起来,可以看一下。
对哦这个好像启动错了。
实际这个就相当于整个场景就跑起来,然后这样的话,实际上你可以看到就是呃这个对应的,实际上是c加代码的,对应的一个核化的一个节点节点图,然后左边那个其实就是呃,最后可视化出来之后的一个效果。
当然当然这里边你点开始之后啊,然后你就可以看到整个流体,其实从上面因为有圆形的一个发射器啊,那圆形发射器里边流出之后呢,然后正好就是沿着这个呃球的那个固壁,然后相当于往下流。
然后到最后他会落到那个呃那个表面上,我看那个直播间里有问qt打的g i g u i,对这个整个goi是用qt打的,对,行这个,那我就先把这个关了,然后大家有兴趣可以自己就可以跑一下。
然后呢接下来就是我大我简单讲一下。
就是这个呃因为前面也讲了,这个实际上整套因为当然你也可以看到,就是实际上整个c加加的代码,就是代码层面的那些指令跟呃,ui层面的一些你看到的一些图源,它实际上是有一个一对应关系的。
那这个这个这个对应关系呢,实际上主要就是通过反射跟呃,一些宏定义来来实现的,那所以接下来讲我主要讲简单讲一下,就是这个反射到底是怎么做的,就是那反射其实就是说呃从概念上来讲,它实际上主要就是针对。
比如说我们动态,就是实际上你程序其实就相当于,你程序跑起来说,需要是相当于整个程序需要具备检测查询,修改自身状态的一种,实际上是这么一种能力,然后这个呃就是通俗的讲了什么意思啊。
实际上就是比如说我们可以看后面那个右边,那个标准的一个c加类,然后这个实际上就是我们之前定义的,就是一个基本的一个集合图源,就是我们比如说我们定义一个一个平面,那这个平面的话实际上就主要包含两个数据。
就是它有一个啊原点,一个法向,但是呢你如果单纯的只是这么定义,一个简单的类的话,对于这个整个框架来说,实际上他是不知道的,就是他其实并不知道你这里边有几个数据,除非是这样,你把这个整个数据结构。
就是如果是大家平时c加的话,就知道就是如果你想用这个数据结构,你这个时候你实际上是必须得把这个它对应的,那个头文件或者是其他文件,你相当于得include到,你相当于要用到它的那个地方。
但这样做的话会有什么问题,就是因为我们知道,就是实际上你相当于嗯,我们知道现在那个现代软件的话,整个它的功能会越来越多,尤其比如像我们做,比如开源的话,其实你是很难控制第三方,也就是很多时候。
比如说第三方的一个呃开发者,他可能写了一个也写了一个类,但是这个时候呢如果他不告诉你的话,你这个时候你是根本不知道,他这个写的类到底什么样的。
也就是说前面你看到的这些ui里边,比如说你相当于点了之后。
它有些属性框啊,这些属性框你要能识别出来,如果单纯的这么定义肯定是不行的,所以这样的话实际上就必须得具备,就比如说你相当于是要有一种能力能够,比如说你知识,比如说我们现在新写了一个类。
那这样的话我们可以知道,比如这个对象到底是什么类型,然后或者是比如这个呃类里的,到底包含了哪些变量和方法,当然还有一个非常重要的一个东西,就是因为这个需要支持,我们动态的去创建这个对象。
这个动态创建对象什么意思呢,就是比如说啊,因为那个我实际上很多时候我们知道,那c加加一般是用,比如说你用new一下,那这个时候一般它是因为整个它实际上是一个,编译型的一个代码,编程的代码。
也就是它意味着,如果你输给这个一个c加加的一个代码,你如果只给他告诉他我们这个类的那个名称,这个时候它实际上是没法创建一个对象,所以这样的话,实际上就必须依赖这个反射的这套机制。
然后相当于把这几个功能能能支持出来,然后当然这个刚才讲的,就是反射到底有什么作用啊,实际上就是一个呢就是刚才讲了,就是呃比如说刚才那个ui的界面里头,实际上我们就可以,比如说我们现在要创建一个q版。
那这样的话,我们实际上只要输入一个cube的一个字符串,那这样的话就可以把这个cube,这个它对应的一个对象给他创建出来,然后呢加入到这个比如这个节点的一个节,节点编辑器里头,然后另外呢。
实际上比如说像比如说一个cube里边,他刚刚讲就是有比如说有它的边长,有分段数,有这个啊缩放平移旋转等等这些属性啊,那这些属性的话,实际上如果我们整个ui系统里边,相当于需要把它这个识别出来的话。
那这样的话也就是说也是相当于需要依赖反射,然后相当于反射能识别到这些属性,然后呢这样最终的话未必说为这个类创建一个,比如它可以调节的这么一个编辑器,然后利用这个编辑器呢。
比如说去更改它的一些自身的一些状态,所以呢主要是反射的话,实际上会有这样的一个好处。
那后面我们看看就是反射整个是怎么来实现呢,就是呃这里以为实际上这样,整个现在python系统里边的话,其实它所有依赖反射的这个这些类啊,它实际上都会啊继承一个公共的一个父类,叫做一个object父类。
因为实际上因为这c加加本身这个语言啊,它实际上是一个编译型的一个语言,就是说它实际上本身它并不支持反射这个特性,因为大家如果用java的话,其实是比较方便的,因为像java里的。
你比如说你这种的那个成员变量啊,函数啊,实际上都是可以,因为它整整个实际上是个解释性的语言,所以它实际上实际上在运动啊,就在执行的时候,他实际上都可以动态的,相当于把这些比如常量变量。
函数和可以给获取到,但是c加加不是c加加的话,需要依赖于自己的一个实现,所以呢也就是说现在整个系统,实际就是你发现这个虽然包含非常多的类啊,但是它实际上会继承自一个公共的这么一个呃,一个父类。
然后这个父类是所有你需要反射的那个类的,一个公共福利,也就一个object,然后当这个object其实它整个里边的话,相当于就是反射到机制啊,它实际上是在这个object。
这个object这个类里边是去实现的,也就是说你实际上后面你不管,你去派生出什么类啊,这你实际上这个时候是不需要去不管,就是说里边这个东西就反射到机制怎么去实现,这个不用管。
也就是这个时候你只需要有依赖一定的规则,就比如依赖和依赖模板编程的一些一些特性,然后呢相当于有些宏定义,然后呢就很就是很方便的,就可以把这个相当于你这个整的,你比如说这个新创建的类啊,包含哪些信息呢。
实际上告诉这个这个父类,然后呢由他来完成,比如各种注册呀,各种那个相当于反射的一些。
相关信息的一些查询,然后呢我们看一看,就是整个其实整个反射的话实际上包含呃,其实就主要其实就针对那个这个object类啊,实际上主要是包含三部,就是因为首先是这样呃。
从框架层面或者从这个object这个类型的角度来讲,它实际上它是需要维护一个所有类的,一个列表的,也就是说它比如说你新增加了一个类啊,他那你其实是这样,你必须得告诉他,你比如说你相当于我新写了一个类。
然后呢这个类里边包含比如到底哪些信息,比如他的那类的名称到底是什么,或者是他以及比如他你得告诉他一个构造函数,然后比如我想创建一个对象的时候,那这样的话他可以去调用那个构造函数。
去创建你的一个派生类的一个对象,所以实际上本所以这样的话,实际上就是整个这个object的最核心的一个地方,就是他会维护一个叫做class,就是class map的这class infmap。
然后这个map,实际上就相当于它是一个整个一个map结构,它会呃相当于它是从一个它的类的名称,到一个一个叫class fr的,这么一个一个映射的一个这么一个关系,然后呢这个表。
然后呢也就比如如果你现在新生成一个类,然后呢这个时候你需要去注册一下,这里边有个注册的一个一个函数,然后这个注册类调用这个注册类之后呢,它实际上会在这个呃类表里头,这个类的那个map里头啊。
实际上就相当于会新增加一个对象进去,然后呢这样的话也就是说你所有的那个类,也就是说你比如说你现在这个系统里边,包含的所有类的话,其实都会统一的存在这个object的这么一个,静态的一个结构里头。
然后这个结构是全局的,然后这个时候你如果在其他的,比如说你任何的地方,然后你如果想嗯去创建一个对象的话,你直接就可以调用这个啊这个结构,然后呢去你的去找相应的构造函数,然后把这个子类构造出来。
所以当然这里边最后的很像,就是你创建一个对象,然后这个对象实际上本质上它实际上是调用的,是子类的这么一个构造函数,然后呢去把这个东西给创建出来,当然这里边后面还有一些其他的一些,像原子操作。
这个主要是为了解决,就是说在多线程环境下边的一个,异常的一个问题啊,然后大家整的其实那个反射,你看这个东西实际上是比较比较简单的。
然后呢对于此类的话,当然这个前面那个是一个object的一个父类,然后当然对于子类,如果我们现在,比如说我们想创建一个自己的一个类,那这里边就需要依赖一个宏定义,然后这里边实际上主要是两个。
一个是一个声明,然后声明前面前面就说了,就相当于实际上就你需要定义一个这么一个,类的信息的一个呃一个静态变量,然后这个静态变量呢需要注册到这个object的这个,它的一个父类里头,然后这个父类相当于。
然后呢,后面如果你比如说你要去创建这个对象的话,实际上这个object就会通过这个字符串,就是通过你的类的那个名称去相当于去,然后再结合,就是说因为这里边你可以看他还有一个实现。
就是说你看那个很多那个类的话,其实主要两个,一个是生命,还有一个是这里有个叫implement the class,其实就这两个,然后呢实现的里边,你会发现它主要一个做的一个事情。
就是你发现它实际上就会创建一个这个,一个叫classing first这么一个对象,然后这个对象里边传入的两个东西,一个呢是它的一个类的一个名称,就是这个name实际上代表类的名称。
然后呢还有一个就是类的对应的一个构造函数,相当,这个也就这个时候你就可以通过这个类的名称,然后呢调用他的那个子类提供的这个构造函数,然后去创建相当于对应的一个子类对象。
所以呢也就是这个对于所有的你要如果是要呃,支持反射反射的这个姊妹啊,所以这样的话就是在头文件里边必须得include,就是相当必须得声明一下这个呃有两个函数,就一个声明,有两个红,一个声明。
还有一个是这个实现,你当这里边整个特性为什么这个可以实现啊,其实这里边还有一个c加加,比较特殊的一个地方,就是因为c加加的所有的这个static变量,就是静态变量。
就是因为像整个刚才说的这个它的一个类的,那个map,它实际上定义的一个是一个静态变量,c加加里,所有的静态变量实际上都会在所有这个相当于,比如说进入main函数之前,它实际上都会初始化完。
所以这样的话实际上什么意思,就是比如说你这里边定义了一个这个静态的,这么一个变量,然后这个变量呢实际上它会在,也就你在执行代码之前呢,事先就告诉这个object的那个父类,然后呢由他完成注册。
然后真正当你运行的时候呢,实际上你整个这个啊它的类表列表,也就这个时候呢实际上就完整的,这就构造出来了。
这样的话实际上你直接执行代码的时候,直接就可以用,然后呢前面实际上是对类的那个注册,当然除了累之外呢,还有一个呢实际上是刚才讲的这个成员变量,因为成员变量的话,实际上你相当于对于比如说一些控制变量。
我相当于需要ui,比如说去调整它的一些属性,那这样的话实际上对于所有的这个成员变量,也是需要去反射,然后成员变量的话,整个实际上是依赖有一个叫fo的,就是f base的这么一个一个父类来完成的。
然后他这个实际上跟整个就是注册类,实际上思想是类似的,其实也是相当于是他需要把自己的一个信息,告诉这个这个父类,然后就告诉这个f base的这个父类,然后呢由他完成注册,比如像这里边针对的控制变量啊。
然后他要输入几个东西,就是你一个你需要输入你的那个类的那个名称,然后你告诉他,这个我这个我相当于声明了这个呃,成员变量到底是叫什么,然后呢另外就是当然还有类型,因为这个是因为针对特定的模块。
比如说我这个是控制,那是参数,诶,不好意思,这个是参数还是说这个是输入,还是说这个是输出,那这样的话需要告诉他我们是什么类型,然后这样最后还有一个就是这个this对应的。
实际上是相当于比如说它的它是node的这个指针,然后这个指针传进之后呢,它实际上可额外的可以针对,就是整个note做一些额外的一个操作,所以呢就是整个你发现这个实际上所有的成员。
就是你需要反射的这个成员变量,实际上也都是依赖于就是这样的一个,宏定义来完成的,所以这里面为什么,你看那个派单那里面好多类似,但会有呃定义,就是各种各样的红啊,这个红主要其实就是为了让底层。
就是相当于你的父类来识别,就是说我这个子类到底是有哪些的啊,成员变量,那当然这个东西如果对,所以这里边实际上到底定义哪些这个呢,实际上就是你写累的时候可能需要注意,就是这个东西并不是说你定义的越多越好。
实际上只需要去暴露,就是必须的那些呃那些成员变量,就这样的话,实际上就是比如对于有些特定成员变量,可能就是只是你内部使用的话,实际上并不需要去暴露出来,然后呃其实说白了ui。
因为这样的ui其实不需要你去控制它,去控制所有的变量,它只需要控制,就是说你对外开放的那些电量实际上就可以了,所以当然这里边其实这么做,就是因为这个整个这个宏定义的那个,这个对象呢。
实际上也是呃放在这个头文件里面,然后它所以它的整个初始化的时候呢,会有一个优先级,就是它的整个构造函数要比,就是在内内的那个构造函数呢,实际上它初始化是要优先级要高,所以就这个时候实际上它放在头文件里。
有个好处,就是所有的那个变量,实际上是在构造函数进去之前,就实际上就把这个所有的那个对象,就已经创建出来了,然后当然比如这个时候你实际上有一些额外的,就这样比较方便的地方,就是这样的话。
你实际上会有一个默认的,比如这个参数它实际上会有一个默认的一个值,然后当然比如说你对特定的类啊,如果你这个时候我想更改它的默认的值的话,这个时候你不需要在这里边改,你直接在你的构造函数里面。
就可以去把这个值啊对它进行更改,然后呢这里边就是还是刚才那个程序啊,就是当然整个前面讲的实际上是一个呃,静态视图,就是静态视图什么意思,就相当于整个我这个场景或者整个节点对应的,到底是应该呃。
这个c加加代码,跟这个蓝图到底是应该怎么对上的,当然这里边还有一个呃非常重要的时间,因为整个仿真跟比如说这个跟cad软件啊或者啥,其实一个最大的一个区别是什么呢,因为它整个实际上是一个时间序列。
就是因为就像刚才比如说我点了一个这个,跑起来就点那个钮之后啊,反正开始之后这个扭之后呢,实际上它整个所有的礼包的那个元素,它实际上有可能会动起来,所以这样的话实际上就是除了这个场景,他这个连接关系啊。
比如他的那个各种的参数,各种的属性之外呢,它实际上还有一个额数据,比如说这个数据传递,这个动态的这个数据流的这么一个过程,然后以及计算模块的一个执行顺序,所以这里边实际上就是你发现就是说这个呃。
除了这个刚才说的场景,这个静态场景要对上之外,还有就是说整个动态的一个运行逻辑,就是ui里边啊,这这个我们看到ui的运行逻辑里边,有可能也是需要跟这个c加加的那个嗯,执行逻辑实际上需要去对上。
那这里边实际上就是我们看一下,就是呃现在其实这样的,现在整个动态逻辑其实主要由三部分来完成,就是其实就是针对刚才界面的话,实际上就是有两个钮,一个呢是重置,重置什么概念呢。
就是相当于比如说我这个点了一下,重置之后,它实际上会把所有的状态变量,恢复到它的一个呃初始的一个一个状态,然后这个时候呢相当于比如说呃。
可刚才那个场景可以再跑一下。
比如说这个场景,然后是这样,就是因为现在看到的只是一个静态场景,所以里边当然还没有各种的数据的计算啊,这些还都没有,然后但是这个点这里有两个钮,一个呢就是三角形的,对应的是法院开始的,就它会从前往后。
然后呢一个时间不一个时间步往前去去运动,然后后面那个是一个重置的一个一个new,然后呢比如说我们现在呃反正开始之后,那这个时候呢比如如果出现,比如说呃,我发现这个可能出水口的那个位置可能不太好。
这样我可能需要调一下这个出水口的位置,那这个时候调完之后呢,我可能需要点一下这个重置,然后呢,这样的话所有的这个节点里边的那个数据啊,嗯它实际上会恢复到一个初始的一个状态。
然后呢去重新开始整个仿真的一个流程。
所以这个对应的实际上就是相当于它的一个。
相当于它的一个两个,就是这里边最就是整个节点里边,最重要的两个机制,就是一个是重置,还有一个是更新,就是点法面开始之后呢,他会每个time step都逐步的去实执行,就是啊里边的一些函数。
当然这里边有三个比较重要的,就因为这几个都是包括这个重置,以及后面的这个相当于这三个函数,实际上都是虚函数,然后再也就我们在去实现子类的时候,就需要去重载这个函数,然后呢去完成。
就是说我们比如自己定义了一些状态,然后这个时候呢就需要去用这些呃,重载的函数去完成更新,然后这里我讲一下,就是为什么就是说这里边设计了呃三个函数。
就是因为正常实际上我们只需要一个update states,其实就可以,但是呢这里边为什么三个呢,其实主要就是呃针对的,实际上是一些耦合的场景,因为耦合场景是这样的,除了整个仿真流程的计算啊。
还有一些比如说我可能是一些数据的预处理,或者一些以及一些数据的预处理,然后那些预处理很多时候呢,它实际上是没法给他标准的一个流程化,所以对于那些操作呢,一般来说就是呃可以,他可以相当于把它放到这个呃玉。
这个叫per data states,以及那个post update states的这两个函数里头,然后这个其实可以看,就比如后面会演示那个流货物和那个场景里边,那个节点,那个节点。
实际上就是按照这种模式来来去操作的,然后当然这两个函数其实会有一个特点,就是因为它整个无论重置也好啊,或者是更新以后,它实际上都相对来说,它整个呃代价相对会比较比较多一些。
因为它这个实际上它因为会调会调用的,比如各种模块啊,这种状态实际上都会重新更新一遍,然而实际上有的时候,比如说我们针对的,可能是一些局部的内容的更新,那这样的话实际上并不需要,就是说我们呃相当于。
比如说我们点一下或者点重置,把所有的数据全都去改一遍,然后呢针对这样的一些需求,比如我们这个时候,如果只仅仅是只是想去更新局部的一些数据,那这样的话其实可以呃,现在pda里头就是有一个回调的函数的。
这么一个机制,这个机制呢就可以用来做,就是比如说一些轻量级的,比如说我可能就是针对的个别数据的更新,那这样的话就可以用回调函数去去完成,那后面我们看一下,就是整个这个回调函数到底什么概念。
就是其实可以看这个图,就是啊,比如说我们现在左边有一个这么一个主程序,然后呃一直在运行,然后呢但是呢就是我们现在有需求,比如我们等等,要主程序触发某个特定事件的时候,我们希望执行他某一个操作。
那这个时候呢,实际上就是可以通过回调函数来完成,就是我们把一个它需要执行的一个操作的,一个对象操作的函数呢作为相当于一个对象,然后呢把它那个指针呢,我们可以呃存到这个主程序里头,然后呢。
这样的话实际上主程序比如触发某个事件之后,这样就可以直接去调用这个回调函数,来完成就特定的一个功能,那这个有什么好处呢,就是因为很多时候这样比如像渲染也好,仿真也好,它实际上它整个实际上是一个呃相处。
一直处在一个不断循环的这么一个状态,然后有时候如果有如果是那样的一种机制呢,它是比如说他要处理的时候,他实际上不断的需要去判断,就是说你是不是需要去处理这个事件,这样的话实际上会导致大量的这个。
可能会是会有很多的这个呃,就是冗余的一个开销,所以所以这个回调函数整个会比较好的地方,就相当于他只在那个触发那一瞬间,然后呢去调用这个函数,也就尽可能的节约了这个讲的计算资源,当然还有其他的。
比如说它实际上就可以把,比如调用者跟被调用者,实际上他们整个可以给他分离开,然后这样的话就是可以由调用被调用者,然后呢去自定义的去处理一些,他想处理的一些行为,然后这里比较典型的一个例子。
实际上就是像比如说在游戏设计里边,就是呃,比如像那个子弹,击中障碍物的这么一个一个场景啊,因为这个场景实际上是非常的呃,他整个其实是非常偶然,然后呢实际上不是说一直在触发这么一个事件。
所以这针对这样的一些特定的,就是偶发的那个时间的话,非常适合用回调函数来来完成,那整个pdl里边的回调机制呢,实际上因为它主要是针对,就是说是因为比如说它一个节点里边,它有有可能会有很多的一些控制变量。
然后呢那这样的话针对比如说特定的控制变量,如果是他变了之后,我们需要更新整个节点内部的一份数据,所以这样的话实际上就整个panipda里头的,他的这个机制呢,实际上就是在每个field里边。
它会存一个就是一个回回调函数的一个列表,然后呢就是一旦比如说比如说我们需要,比如说用这个这个数据分析,就我们需要它执行特定的操作的话,那这样的话我们就会创建一个回调函数。
然后呢把它塞到这个field的那个回调函数里头,回调函数列表里头,然后这个时候呢如果比如说几种场景啊,作为一种呢,比如他数据更改之后,或者是比如它的连接的那个关系变了之后。
这样的话他会去呃去调用这个后面的回调函数。
去处理,就是用户想要的一些一些行为,然后呢这里主要是回调函数,这里边主要有两种啊,就一种呢是呃,实际上是通过成员函数来进行回调,然后通过成员函数会进行回调,什么意思呢。
就是比如像这个这个是这个cube里边用来,比如说这个针对比如说他的那个缩放啊,旋转啊,这个平移等等,这些信息变了之后,我们相当于需要去更新它的一些呃内部数据,那这样的话实际上就是它里边写了一个成员。
成员函数,相当于比如说这些变量变量之后呢,它会对应的去更新它的一个,比如说它的表面网格,它的那个呃立方体的一些信息等等,就这些,那这样的话,实际上就是针对这个成员函数的回调的话。
实际上就需要利用这个s b的一个一个bd,然后相当于把这个成员变量,然后呢以及这个节点的那个指针,然后需要绑到一起之后,生成一个回调函数,然后呢再把这个回调函数的话,要通过这个attach的这个函数。
然后呢,附到每一个这个你需要它毁掉的这么一个那个,控制变量里头,比如这里边这个函数,当然这个你会发现这到底是添加到哪个field里头,这个是需要依赖,就是你这个函数啊到底是需要有哪些参数。
就你比如像这个,它实际上是需要所有这五个参数,实际上都需要,那这样的话,实际上需要把这个回调函数,都塞到这五个fid里头,然后这个时候呢也就它里边任意一个呃,相当于任意一个呃变量,然后发生改变之后呢。
实际上它会都会去调用这个函数。
然后呢去更改它的一个内部的一个状态,那当然还有第二种类型,就是这个直接就可以通过那个叫莱姆的函数,实际上就是c加加里的一个泛函,然后这个函数呢实际上就是会更灵活一些,就是相当于对于有一些。
比如像这里边实际上是针对的,就是呃就是就有个静态版网格加载的,这么一个功能,然后这个功能呢实际上就相当于,比如说我相当于打开一个文件之后,相当于我需要把这个文件载入进来,就针对这样的一个功能。
那这样的话实际上也可以通过,比如说这里写了一个lab的函数,那这个兰姆达函数,它这个兰姆达函数大家就可以自己去看一下,就是怎么定义的,实际上就是它通过一个或,然后里面那个等号代表的。
其实前面的值可以都可以引进来,然后这样把这个栏目的函数,然后作为参数传到这个回调函数里头,然后呢里头呢实际上相当于也可以引用,就是这个类里边的那各种的一个一个对象,然后呢相当于通过它去完成一些操作。
比如它这里边实际上就是呃去获得他的一个,一个几何拓扑的一个信息,然后呢呃呃几何拓扑的一个对象,然后呢相当于把那个文件载进来,然后对这个对象进行一个初始化的,这么一个操作,然后呢这里这个实际上是现在实现。
就是现在支持的两种比较典型的一个回调类型,然后后面我们看一下。
就是呃这个东西到底有什么用啊,就是这到底用能用来干嘛,其实其中第一个呢是这样,我后面举几个实例啊,就第一个的话,实际上主要就是用来比如说像控制一些啊,可见性就是什么概念啊,就是这个场景的话。
我直接打开那个,其实打开这个有gi plug in的这个一个程序吧。
然后这里边因为是集成了各个库里的一些功能。
所以这样的话里边东西相对会多一点。
这这个我们叫那个我先演示一下,就是这个什么意思啊,就是比如说这里边有,我们可以创建一个啊基本的一个,比如基本的一个球体,然后呢这个球体当然可以调一下,然后呢后面是这样。
就是球体呢实际上我们可以给它转成一个,比如说改成一个有呃一个体的一个有限距离场,然后这个时候是这样,因为每项每个节点里边,它实际上都有一个可视化的一个模块,然后呢但是这里边如果是这样。
我直接从前面连到后边,这样的话,实际上就是比如说后面那个数据呢,因为现在需要需要输入一个三角网格,就相当于需要把球的这个数据输入到后面,然后呢作为它的一个输入。
然后最后去构建出来一个远距离场,然后但是后面那个节点呢,实际上现在也带了一个渲染的呃,一个节点相当于通过比如这个把里边的呃,那个远距离厂转换成一个三角网格,就是利用完tube的那个方式。
然后把显示出来,所以这样的话实际上如果你直接去连,那这个时候呢会出现什么问题呢,就是你前面那个节点,它实际上是处于一直处于显示的状态,然后后面那个节点呢它实际上也够出来。
但这两个东西实际上会存在一个遮挡,所以现在我们就是说我们希望是这样,比如我们前面那个节点连到后面之后,那这样的话就比如说我们控制一下,前面那个节点呢,就是它的可视化就给它消失掉。
然后呢去显示后面那个节点,所以对于针对这样一个需求呢,实际上这里边就是写了这么一个回调函数,就是这里边有个volume。
那当当找那个对,找那个类的时候,就是这里边大家也可以看一下,就是因为这里有提示啊,就是他针对的是哪个类,然后它实际上就是呃叫一个volume哦,这个是这是一个volume的generator。
然后这个是在就是volume这个库的下头,然后呢它有一个一个类,然后这个类里边呢,是这这里边就加了一个回调函数,这个回调函数是怎么做的呢,就是实际上就是它回调的是相当于,因为它这里有需要输入一个字面片。
然后呢也就这个时候呢,就是说你如果一旦,比如说前面有这个三角面片输进来了,那这样的话我们希望是把前一个节点呢,它的渲染模块给它关掉,所以这里边实际上,整个这个回调函数做的是这么一个事情啊。
就是输入一个三角面片,然后呢我把它对应的这个啊就输入那个field的,他的那个附节点,它的那个给它显示给它关闭,实际上这么一个一个需求。
所以呢这样的话,其实比如说我们这里边给它连接之后,你可以看到直接就是前面那个就隐藏了,当然这样的话,实际上我们可以通过比如说去调一下,后面那个参数,然后当然这里可能需要重重置一下。
然后这个大家可以看到就是这样的话。
其实就是前面那个实际上并没有显示,就是前面那个初始的那个网格其实已经隐藏了,那这样的话只看到的是后面那个节点,就是创建出来的,它针对的一个t,然后它重构出来的一个表面网格。
所以呢这个是针对就是说这种可见性,就是针对这个比如说这个连连接的那个输入,然后呢做了一些可见性的这么一个事,当然这里边其实有各种其他的一些用途啊。
就是完全也不限于说仅仅是这么一个一个需求。
然后呢这里边这是一个,然后当然还有第二个我们看一下,就是还有一种,比如说前面之前那个讲s t h的时候,就是我们提到就是呃,因为s p h它的对于它的可动函数,实际上是有一个限制。
就是比如像我们去计算s p h里的这个。
一个物理量啊,就是这样,我把后面的先关一下。
行,然后这个地方实际上你可以看到就是像s p h,我们去如果去求他的某个点的一个值的,就是某个点的那个物理量的时候,它实际上是依赖一个呃权重求和这么一个概念,然后呢当然这里边主要几个。
一个是这个每个例子上带的带了一个值,然后还有一个就是权重函数,然后这个权重函数呢,实际上就会有一个什么要求,就是它实际上要求它的整个权重加起来,必须是等于一,然后这个东西其实呃也可以啊,就是一般是这样。
你如果是一种比较简单粗暴的方法,你实际上完全可以在,比如说你每次去计算的时候,你相当于重新给他规划一下,那这样用的一个比较麻烦的地方,就是这样的话,你有可能会导致你实际上就是。
你不因为这个这个权重函数啊,实际上你在很多代码里边实际上都会去实现,那这样的话就会导致你有可能不同的地方,实现的可能并不一致,那这样的话我们有没有可能是,比如说我们在嗯某个地方,统一的对这个进行归一化。
然后呢这后面用的时候呢,实际上直接就用这个统一规划之后的,这么一个一个结果,所以呢这个呢实际上也可以就是依赖这个,就利用这个回调函数去完成啊,当然因为前面这里还讲就是这个空档函数。
实际上它还有很多类型的,所以这里边我们看可以看一下,就是这里边如果依赖回调函数怎么去做,就是啊比如像party system里,有里边有一个叫啊party和proximation的这么一个类。
实际上它整个对应的实际上就是这么这么一个,权重求和这么一个概念,然后在这里边实际上就是针对这个权重函数,归一化的这么一个呃需求,相当于这里边需要去计算一下,它的一个缩放因子,那这样的话其实就是针对。
比如说我们现在输进来之后,有一个比如说它的ex mos max,然后当然包括他的采样的间距啊,然后同时还有一些就是刚才讲,就是实际上你的那个kernel的类型,实际上也可能五花八门,所以这样的话。
实际上你的kernel类型也是需要作为一个参数,然后给他说进来,那这样针对这几个参数的话,实际上这个时候,如果我们一旦这几个参数变了之后,那这样的话,后面可能就需要重新的去计算一下,这个缩放因子。
然后呢,这样的话,实际上就需要只需要就是说把这个回调,就这个章是个成员函数,然后相当于把这个成员函数,然后呢分别输入到这里边的那三个函数里头,然后也就它们的值变了之后呢。
他会去自动的去调用这个函数去进行对这个嗯,相当于对这个ho进行,归一化的这么一个一个操作。
那当然最后还有一个,就是刚刚你看就是比如像那个发射器也好,或者是比如说我们这个时候创建一个cube的话,实际上你可以通过这个,相当于你可以通过整个它的一个标价,就是你选中这个物体或者选中某个节点之后。
它实际上是有一个标价的,然后这个标价如果你去移动的话,就是你会发现就是说它整个后面那个属性页,它实际上就是比如像他那个位置啊,它的旋转缩放啊,其实你可以看到,它实际上是跟着你左边那个操作。
实际上是跟它是联动的,所以呢这个实际上也是需要依赖,就是整个回调函数来完成这个操作,然后当然你看这个视图的话,其实可能只有两部分,就是左视图加60,但实际上整个实现的话,这里边需要依赖三个东西。
一个呢是整个这个啊,这个坐标价就是对应的三个箭头啊,这个实际上一个标价,然后呢这个标价移动了之后呢,它实际上会去设置这个field的这么一个啊,它的一个值就是因为你整个相当于移动之后。
你的这个所有的那个值去更新了,但是这个vg的这个对应的,因为这个整个界面实际上是在qt里面实现的,然后qt里面这个时候你需要让qt去知道,就是说你这个数据更新了之后,我相当于是需要怎么去更新。
我的这个界面里的那个属性,所以这里边实际上就是你可以看一下。
qt里边怎么去做的,就是因为这个对应到qt里边的有个qt g u i,然后呢这里边会有很多的就是标签。
标签属性啊,然后这个标签属性当然对应的,比如这个像三维的啊。
这个int float等等,这些都有,然后呢这样的话实际上你比如说我们点开一个,实际上点开一个这个呃,比如说这个三维向量的这么一个属性框,那这样的话它实际上会有一个,就是这个回调函数。
然后呢相当于这个回调函数实际上是在嗯,相当于在qt的这个界面的这个框架里边。
它相当于是传给了就是就是他的这个field,然后呢也就这个时候field如果只一旦发生改变了,他会去调用这个qt里边传给他,这个时候你会这个qd跟那个整个底层的框架,实际上是两套系统啊。
但是呢但依然可以在界面层面,相当于你把需要啊,就是跟qd相关的一些呃,一些那个功能跟一些函数,实际上可以传到这个底层框架,然后呢由他来完成回调。
所以这样的话实际上就可以很方便的,就是比如说我们可以用这个左边这个呃,各种控件啊,然后来完成一些比较啊方便的一些操操。
交互的操作啊,然后将那接下来还有一个呃一题,就是主要就讲讲就是啊插件相关的一些内容,当然为什么这里边我们说为什么要用那种插件,实际上整个插件对于c加加来说,它实际上插件是其实主要就包含两个。
一个就是整个框架,然后还有就是一堆的dl,实际上就是你直观的去看的话,其实这个东西很简单,然后他这个一个目的,实际上主要就是为了把一个复杂的一个系统,然后呃实际上给它拆拆分。
然后拆分成一些可能一些基本的,比如类似于积木块啊,然后呢这样的话我们比如说啊,这个这不是积分的积木块,然后相当这样的话实际上就在利用,比如说各种这样的积木块,然后再把它拼起来。
然后去构建一个复杂的一些系统,因为你发现就是我们这个系统,如果嗯最后代码量多了之后啊,当然包括现在,其实现在其实代码量也不少,然后你这样的话,如果你每次就都在一个系统里边,然后呢每次可能都要重新编译。
那这个实际上对于这个整个开发的那个成本,实际上还是比较大的,所以呢就是我们有没有可能就是实际上是插件,主要是呃利用这个拆分的几个功能。
然后呢实际上把代码的这个耦合度实际上给他。
实际上把它给它降下来,然后这样的话比较适合于,比如说我们做协同开发,也就这个时候,比如说呃我不同的研发人员,可以呃相当于研发一部分,然后最后到再整合到这个整个应用框架里以后。
去完成这个相当于复杂的一些任务,那所以整个pdd这个系统里边,它这个插件系统是这样的,他当然跟其他的插件系统这个其实差不太多,就是单纯看插件系统,这个实际上差不多的,因为这样比如说他职业主要包含两部分。
一个就是框架层面,还有一个就是plug in的这个呃一些对象,然后所以呢整个这样框架层面呢,就这个是在framework里头啊,它实际上会有一个啊叫插件管理器,然后发现传理器呢。
他会去管理里边的每一个的pin,然后它对应的有bin的一个列表,然后呢当这个时候如果我们针对,比如说我们这个插件的开发人员的,这样的话,实际上我们就可以从这个plugin里边。
他这个时候他有一个entry,然后呢他这个可以从这个安全里边,我们给他继承下来,然后呢去开发各种各样不同的一些插件,比如针对的经济动力学的插件啊,或者针对那个粒子系统。
或者是当然前面演示那个sdf的等等等等啊,这些不同的一些插件,然后当然其实这个刚才讲到,就是本身插件这个东西,实际上是啊为了降低代码的耦合度啊,所以呢这里我简单提一下。
就是实际上就是呃设计模式里的一个概念,就是当这个东西主要是针对的是呃,如果我们希望是成为一名,就是说比如说开源软件的贡献者,就比如我们仅仅是使用者,这个其实没有关系啊,就是因为整个你代码怎么写嗯。
其实只要你自己看着舒服,其实都可以,但是呢如果你作为贡献者的话,这样的话,实际上可能就需要啊符合一定的一些约束,当然这个也是因为我最近在调代码的时候,就发现一些问题。
所以这样的话正好啊这块也简单的说一下,因为这里面实际上主要包含七个原则,实际上抽象的去看这几个,实际上会呃不知道在讲啥,因为这里边实际上比如说这七个的,比如像单性原则,开闭原则等等。
这个还是实际上比较抽象的,所以后面我真结合着具体的一些一些啊,碰到的一些情况,然后简单讲一下,就是这个到底哪个代表什么意思,首先这样就是第一个是单一性原则,这是什么意思呢。
就是一般来说一个类只负责一项职责,然后这样的话,实际上主要是为了降低这个,一个类的一个复杂度,所以这里边就是我举举个例子啊,就是什么样的情况下,其实是属于这个呃就是不太好的这么一个模式。
或者是实际上是跟这个原则违背的,比如像呃前面刚才刚刚演示了一个教育,一个就是相当于用输入一个三角网格,然后呢去创建它的一个体这么一个这么一个类,然后这个类里边呢你其实你现在去看的话。
它实际上还有一个额外的一个控制变量,因为前面讲的就是你实际上每个类,你需要哪些控制变量,这个东西呢尽可能的实际上是呃小,就是然后呢把不需要的那些呢实际给他摘出去,但是这里面会有一个额外的这么一个呃。
控制变量,这个控制变量是用来干嘛的呢,就是呃当然这个只是因为之前测试的时候,为了方便啊,就比如说我们希望这个整个s d f,然后它能动起来,所以这里边就加了一个这么一个控制变量,然后呢,在内部相当于。
比如说我让它整个沿着某一个速度,或者某一个方向,然后让它去不断的去运动,当然这个东西实际上这么设计啊,其实没什么问题,但是呢这个东西呢,就可能会跟整个类的一个初中,它实际上是相违背的。
因为整个初中他实际上只是做一个,比如说我们输入一个三角网格,然后呢相当于输出它的一个呃有向距离场,其实只是这么一个功能,然后当然这个实际上如果更合理的这种做法,比如说我们想保持这个单一职责的。
这个原则的话,那实际上可以把这部分直接移到外头,比如这个像刚才,因为是前面输入了一个三角网格,那这个时候我们实际上是可以去驱动这个,三角网格的运动,然后呢这个相当于3d网格运动完了之后,然后在后边。
然后去更新这个呃,这个相当于他新生成的这么一个s d f,所以这个实际上就对应了一个单一职责原则。
的这么一个概念,然后当然还有第二个是开闭原则,这个就是更抽象了,就是呃字面上的意思是他指的就是对扩展,对扩展开放,对修改关闭,但这个什么意思,其实就说的直观一点,实际上就是相当于你一个类。
你暴露出来的东西,对于比如说你是这个类的实现人员,那这样的话你应该是允许他去改的,但是呢对于比如说你仅仅是一个,其他类的一个使用者,那这样的话实际上就是说你一些内部的细节,你不应该暴露出去。
实际上直观的其实就是这么一个意思啊,所以这里边比如说举个简单例子,就比如像这里边,那还是刚才那个类啊,就是它里边会有一个函数,就是比如说他有一个初始化内部的,就是内部用的一些参数的这么一个函数。
然后呢这个函数实际上你可以设计成单,你可以设成啊,public也好,或者可以设成私有的也好,这个其实都没问题,但是呢这个按照这个原则来讲,就是你设置成public就会有问题。
就是因为这个函数其实对于使用者来说,它实际上并不清楚你这个东西是做什么的,所以这样的话,其实理论上它你是不应该是允许外面的类,其或者其他的类就直接的去调这个函数,因为这实际上是个内部使用的一个一个类。
所以这样针对这个,比如像这种,比如说我们只是在类的内部使用的一些,额数据也好,函数也好,这样的话实际上要给它封装起来,这样的话就不暴露给外表,也就这个时候呢就对对于也就这种函数的话。
对外实际上是关闭的啊,那还有就是像迪米特法则跟接口隔离原则,这两个实际上是一个概念,就是呃一个对象应该是,对其应该是保持最少的了解,或者是这样呃,就是比如说不应该依赖这个不需要的接口啊。
所以这里边针对整个pano这个系统呢,实际上就是嗯讲台讲,实际上就是主要是几个一个人呢,实际上你node对这个state那个依赖,要尽可能的相当于要少,就是因为我们知道那个当你一个node。
你可以定义重复的很多不同的那个,你也可以用一些冗余的space去描述啊,比如说这个你虽然可以比如定义三个边,当然你可以定义比如说边跟边的乘积啊等等,这些都可以啊,你可以随便定义,也也可以用来描述这个。
比如这个一个立方体,但是呢这里边实际上是最佳的一个状态,应该是就是说你的状态实际上是描述这个呃,这个比如这个box最小的一个集合,然后当然就把一些这样,不如就冗余的这些这些变量的形象。
就不需要给它定义在里头,然后这样,当然这里也体现在比如说像low的跟嗯模块,这个比如说model模块以及对控制变量的一些依赖,以及对输入接口,当然这个输入接口就很重要了,因为输入接口的话。
你这个时候如果你有冗余的输入接口的话,这样的话直接就导致有可能就比如说呃,你相当于有些模块,它实际上有些接口是实际上用不到的,那这样的话它缺接口的话,直接就可能导致整个后边,整个模块实际上都没法执行。
所以也就这个时候其实对于整个节点也好,模块也好,你相当于需要设计的一些输入接口,以及输出接口,这个是要非常的注意,就是不能轻易的,比如说去改变它的输入接口,或者以及当输出相对来说还好。
但是输入的话一般来说不能轻易动啊,然后接下来实际上是依赖倒转,以及这个理氏替换其实也是一个概念,就是什么意思,就是像高层模块,实际上不应该依赖这个底层模块,然后这里我举一个例子。
就像比如说现在整个python底层的话,它的拓扑的话实际上是一个层次化的一个结构,就是比如最顶层的话,实际上是一个电源,然后呢是一个编辑,然后呢是一个三角面片,然后四面四边形网格,然后呢四面体网格等等。
它实际上是一个拓扑层次化的一个结构,然后呢这个时候如果我们定义了一个模块,模块或者节点,它需要输入一个呃三联网格,那这个时候呢实际上就是什么意思,就是这个时候如果你输入一个四边形网格。
或者输入一个六面六面体网格,四面体网格,这个理论上,只要是这个是从三角网格继承下来的,这个时候应该也是可以输入到啊,这个相当于这个节点作为输入的,当然这个现在实际上整个界面里面设计的,其实也是允许的。
就是所以这里边就是要保证,就是这个理事替换原则,那就是什么意思,就是你如果输入的是它的一个子类,那这样的话你也应该能保证,就是说也就是你不管输入任何子类,它的结果应该是是正确的。
就是跟你输入它的那个父类,这是完全是不影响的,所以现在就是说实际上你如果是运行。
比如说这里边的那个程序的话,你会发现就是啊现在有个接口判断。
就是如果是所有的是子类的话,实际上都是可以允许输入,但是呢如果是不是子类或者是呃其他类型的话,这个实际上是不行啊,不行的,这样我简单演示一下这个这个到底什么意思啊。
比如说像这里边我随便可以随便创建几个嗯,比如这个这个是因为是这样,他实际上输入的一个三角网格,当然输入三角网格呢,这个时候如果我比如说啊我这个呃cube,他cube其实可以输出两个,一个三角网格。
四边形网格,当然三角网格就可以传进去,但是呢这个时候如果我输入的是四边形网格,其实也也是被允许的,然后当然这个时候如果我们换一个,就是比如说我这里边创建的是一个呃,其他的一些类型,就是呃。
比如说这里边我创建的是一个粒子采样器,粒子采样器呢它输出的实际上是一个粒子啊,相当于这个典籍实际上是这个三角网格的父类,那这个时候呢实际上是按理说是不允许的,所以这种情况呢就是要得避免。
也就是说这个时候就不能允许它,相当于是把子类的那个对象输入给啊,就父类的对象输入给子类,然后作为传那个输入给它传进去,实际上这么一个概念啊。
当然最后一个是这个合成复用的一个原则,就是啊这个主要是其实这个东西,其实最后那个原则其实属于呃比较模糊的,因为很多时候其实可能没有那么明确啊,然后当然这里边它其实核心意思就是,你如果你农夫用的地方。
那就是尽可能不要继承,就是当然这里我举了一个例子啊,就是比如说像啊这里边有一个针对刚体系统,查找那个领域的那个就其实做碰撞检测用的,那这里的实际上就依赖两个类,就是一个呢当然有个拓扑结构,还有一个呢。
就是比如说他有一个出力度的化疗检测,那这样的话这两个就是这种做法,当然我比如这个类,我可以完全从这两个类里边继承下来,作为它的一个子类去呃去实现,那这样的话也理论上没问题,但是这个会导致这个问题。
比如说你相当于你这样的话,你存在一个多重继承,你比如说你可以你有可能会继承多个父类,这样的话实际上会导致整个软件系统,它实际上维护起来,它整个那代价实际上是非常的非常的大,所以呢也就是这个代表的。
就是说你实际上就是需要用到别的模块的时候,就是如果能用这个组合的方式的话,相当于尽量用组合,然后也就不要用这种继承啊,这个派生的那个那个那个操作啊,但这里面其实还有一个需要注意的,就是一般来说继承的话。
就是实际上尽可能的,还有一个就是要减少这种啊,多继承的这么一些用的一些场景,就是多数什么概念,就比如一个子类,我可能同时去继承多个负雷,然后这样的话实际上就是呃有可能会导致,整个后面就是子类的话。
它会有可能会相对来说变得比较复杂,然后不太容易维护,所以呢这个也实际上也是一个比较呃。
实际做研发的时候可能需要注意的一些地方,那接下来就是讲完前面那个一些是原则的话,就是后面我们看看,就是呃整个插件到底是怎么实现的,就是这里边当然就是使用的话比较简单。
其实这里边提供其实针对每一个plug int,实际上有两个接口,就是有一个叫一个叫nati static的那个bgin,还有一个就it is dandinologin,然后这两个分别针对这个静态库加载。
以及动态库加载的这么两个接口,然后呢实际上我们现在如果呃,比如说我们现在各种算法都已经写的差不多了,那这个时候呢我们实际上要做的就是嗯,相当于给他把那个插件做一下初始化。
然后这个初始化程过程其实也比较简单,就是相当于从pc entry这个类里边给他啊,继承下来一个子类,然后呢里边相当于给了创建,有个叫有个静态的这个uston这个一个函数,然后需要实现一下。
然后这里边相当于它会创建一个插件的,这么一个静态的一个对象,然后呢还有一个要做的就是,比如如果我们针对的是ui呃,因为这里吧现在这样的就是美的插件,它实际上会对应一套工具架,然后这样的话。
如果有些自定义的一些工具架的话,那这样的话就是需要去重载,这个就有个叫initialize,in action的这么一个呃一个函数,然后相当于去实现一些自定义的一些工具架的,一些一些按钮。
然后这个自定义工具架是什么意思呢,就是比如说你这里边,实际上比如针对那个粒子系统啊,这粒子系统的话,实际上就是呃,我们相当于现在是这样在上面添加了几个,比如说各种快捷快捷的一些钮,然后这扭的话。
实际上就相当于针对对应到代码里的,就需要相当于实际上是针对每一个钮,需要添加它的一个栏目的函数,相当于去创建一个对象,本质上,当然每个钮实际上对应的,实际上都是节点编辑器里边的,一个创建对象的一个过程。
就是点一下的话,跟节点编辑器里边你右键,比如说你创建一个对象,实际上是一个概念,然后当然这里边固化在这里边有个好处呢,就是这样你可以做一些额外的一些操作,比如说我可以定制化的把一些比如像这里边。
比如这个发射器,因为你看发射器的话创建出来它有一个外轮廓,那这样的话实际上你可以把外轮廓的那个呃,就用边框渲染的这么一个模块,然后给它显示出来啊,所以这样的话,实际上整整个插件你一旦加载进来之后呢。
实际上它会自动的就会把这个呃对应的工具架。
里边的一些按钮也相当于给它创建出来,然后当额外的其他还有一些其他的一些功能,然后这些呢实际上就是呃只是为了,就是后面相当于比如我们已经算法整个各种的,比如说已经研发差不多了。
然后呢只是让整个流程变得更好用的话,就是会有额外的一些就在ui层面,怎么让它变得更好用的一些扩展啊,比如说这个像这个标题栏,比如说我们如果是想对一些基本的数据类型,我们这个时候实际上不需要去显示它。
整个标题栏,那这样的话我们可以通过这个重载,每个节点或者每个模块,它的那个呃这个caption visible的函数,然后来相当于去呃。
相当于去控制它的那个标题栏的显示跟呃隐藏,然后当然还有就是各种数据,其实现在实际上是这样的,现在整个不论是节点系统啊,里边的节点还是模块,实际上里边的每一项啊,实际上都是预留了这个自定化自定义的。
这个就是定制化的这么一些空间,所以呢比如说像这个标签,那个比如这个变量,比如变量的名称,那这些的话实际上就是我们可以自己的去,就是因为默认的话是这样的,就是比如像这里的定义一个变量的。
默认呢实际上是跟这个你定义的那个呃,就是代码力的那个名称是一致的,然后这么定义的主要一个好处,其实就是相当于你这样的话比较清晰,就是说你看到界面里边的对应的形变量,你直接可以在代码里面找到。
但是呢这个时候就是这样,如果对于比如说你到最后应用的话,其实这可能就并不直观,那这样的话实际上我们可以对每一个变量,它的那个名称,实际上可以对它进行更改,比如说我们改成比如像自己想要的这种方式。
就比如像这里我们给他,比如这个标量,我们就给他设置成一个,比如说中文的一个这么一个显示标量矢量等等,这些东西,实际上就是通过这个slog name,这么一个函数来去完成,当然其实他的那个所有的包括。
比如像这个标题栏,然后呢像描述信息啊,这个节点类型啊等等啊。
这个实际上都可以去定制化的去去改啊,那当然还有就是这里的,因为是这样,你看看节点的话,实际上主要是两个类型的,一种呢是啊这种小圆点,还有一种是这种啊钻石型的这个节点,然后那个小圆点。
实际上对应的是基本的数据类型,就是像啊控制变量呀,然后包括数组啊,二维数组,一维数组等等,就这些,然后呢这个这个钻石的这个形状,实际上对应的是节点,然后为什么这里要设计这个钻石的,这种数据类型。
其实主要是因为是什么原因啊,就是因为实际上就是像比如说啊,有的时候我们如果做耦合,那我和它实际上它依赖的数据会非常的多,就是比如像这里边要接入一个粒子系统,那这个时候它有可能会包含需要接入。
比如它的位置信息啊,它的速度信息,他的甚至他的那个比如d的性等等啊,那需要都需要求连接的,那这个时候实际上你会发现,整个界面会导致它非常的混乱,所以这样的话实际上就是这里边用这个呃,这个菱形的。
就是这种钻石型的,这个这个方式是相当于整个把它节点导进来,实际上是简化这个呃,整个图就是图形上的一个呈现啊,所以这样的话对于比如说前面,如果这个时候我需要接入一个主体。
需要用到里边它很多的那个状态变量的话,那实际上这样,我只需要把整个节点作为一个整体,然后给他转入到这个后面那个节点。
实际上就其实就可以完成这个操作,所以后面的话我会针对这个去演示一下,就是嗯这种场景啊,就是单主要包含几块,一个是这个实体建模,就是用s d f怎么去嗯,去相当于生成各种各样的这个呃。
就是自定义的去创造一些几何的图案图形,然后后面当然还有流体工布料,然后呢相当于这个也是依赖,就是说怎么依赖这个今天讲的这个插件系统,然后呢,把这个不同的这些啊模块儿给它串到一起。
然后这里边实际上就是我还是用刚才的那个。
就是这里有一个叫q t g,i play in的这么一个一个程序啊,这个呢实际上这里边其实刚刚讲了,就是因为每一个类里的啊,就是那就每一个库里边,每个库里边实际上都会有一个叫initialize。
是什么什么什么这么一个头文件,然后这个头文件的本质,你如果打开进去之后呢,实际上就是初始化这个插件的这么一个一个类,然后呢以及两个api接口,然后当然里边就是啊。
一个呢是它的那个instance这个函数,然后还有一个就是初始化那个,就是工具栏的这么一个一个函数,所以整个呢这样的话,实际上你如果在呃需要静态使用的话,这个时候你相当于需要去在这个main函数里头。
相当于调用一下他的那个呃,初始化的一个一个函数,然后把这个插件给它加载进来,当然这个是静态加载的方式,然后一会儿会演示动态怎么加载,然后静态加载。
比如说这几个加载起来之后呢,就是你可以看到就是。
这样我发现这个直播软件开着的时候,那个程序好像会卡顿,然后这个估计可能是因为那个占用录屏软件,可能也占用gpu了,所以这样我把那个后面程序演示的部分,重新录制,然后演示一下吧。
那还是打开这个有一个叫g i plug in,的这么一个example。
打开之后呢,就这里边首先就先切到这个啊volume这个选项卡,然后呢在这里边我们创建几个实体啊,这个第一步可能要那个先创建两个标准几何题,一个是这个标准的一个cube,然后还有一个标准的球,然后呢。
我们利用这两个基本几何体呢去做一些啊,基基于那个实体的一个融合操作,然后这个球可以稍微调一下,给它调小一点,然后这样的话就变成这么一个形状,然后接下来就是我们需要把这个表面网格,转成一个一个提网格。
然后这里借助这里有个叫vn martree generator,的这么一个一个类,然后他的每个输入实际上是一个三角网格,然后当然这个皮网格的分辨率需要改一下,因为不然的话分别太大的话。
它那个创建出来的那个呃质量不太好,然后这两个生成之后,当然这个现在我还没点重置啊,所以这会儿是没有的,当然我索性先把整个流程建完了,然后我们希望这个每个实体建完之后呢,我把它啊融合到一起。
然后后面有一个布尔操作,然后这个操作呢相当于可以针对呃实体模型,然后呢做比如说坐下的相交,相相相容,相差等等等等操作,当这个选项卡里边有各种操作可以选,然后这个接上之后啊,然后这个时候再点一下重置。
然后这个时候他当然前面两个给它关掉,然后这样的话,实际上你可以看到就是这个球跟这个那box,融合之后的这么一个形状,然后有了这个形状之后,接下来实际上我们就可以跟仿真把它对接起来。
然后这个对接呢实际上需要依赖,当第一步需要的是创建一个一些仿真的,一些基本要素,就是像流体的话,这里会有一个发射器,然后发射器后面需要接一个流体的一个求解器,然后呢把发射器创建出来的例子。
然后输入到这个求解器里头,然后当这个发射器的位置需要调一下,因为他现在是在内部,然后这样的话给他调到外头,然后这样的话就是相当于是从外面发射粒子,然后跟这个这个这个物体的边界,相当于产生作用。
然后呢这部分作用呢有一个叫这里,切到那个volume里头,有一个叫deputy boundary的这么一个一个节点,然后这个节点呢,实际上就是他输入针对这个流体,常见它可以输入一个呃流体,然后呢。
另外就是把刚才创建出来的那个实体模型,也给输进去,然后这样的话,实际上整个场景实际上就搭建完了,这个时候我们去点击一下这里这个绿色的箭头,然后它实际上你可以看到它开始运行。
然后呢因为他这个流体啊把它碰到边界之后,然后它实际上会跟呃受边界的一个约束,然后它整个流体的运动发生改变,然后另外就是你可以也可以看到,就因为它整个形状,是我们过来融合之后的一个形状。
所以它会沿着那个嗯更改之后,那个形状沿它的表面去运动,然后当然这个是一个流体的一个场景,那现在接下来就是,那我们再来看一个布料的一个场景,然后这样的话,实际上当这个整个实体模型可以不变啊。
所以这里我们实际上只需要把这个仿真,这波给它剃掉,就是将我们把那个流体那些节点给他删了,删了之后呢,这个时候我们可以重新的去创建一个呃,比如说我们就想模拟一块一块布,然后这个布呢就是当这个也是一样的。
这是一个求解器,然后他说要需要输入一个三角网格,那这样的话,这里边实际上我们可以创建一个一个平面,然后这个平面呢是这样,它可以调它的一个分段数啊,就是因为正常它实际上只有两个三角面片啊。
然后这样的话调完之后,你可以看到平面实际上就有一系列的三角形柱,四边形啊,当它其实四边形,然后当最终的话会转成一个三角形,然后这个四边形结构的实际上可以,因为它是三角形的一个父子类。
现在所以相当于它可以输入到布料理的,直接作为它的输入进行初始化,然后完了之后呢,这里边就是这个布料的一个数据呢,实际上就可以输入到这里的这个边界,那个aibinary这个节点里面有个三角网格系统。
那么这里这样的话,实际上去在运动过程中,去约束这个布料的一个行为,然后这里我把那个初始的那个关掉之后,然后再重置一下,这样的话这里布料的这个呃,它的数据结构实际上就会生成,然后你可以看到这里吧。
当然它有它的顶点和边啊,你可以看到那完了之后,这个时候整个场景已经重置完了,然后这个时候我再点一下这个网站开始按钮,然后这样的话你可以看到就整个呃这个布料,然后其实跟流体一样呢。
它其实碰到这个障碍物之后,然后发生整个形变的这个过程啊,这个是流体的一个场景,然后最后其实还有。
刚才就是因为他和那个呃插件的那个场景啊。
插件这个场景我再也再演示一下,因为嗯今天讲的主要是一个插件扩展的,所以这样的话实际上很多时候如果我们在外头,比如说我们把各种模块开发完了之后。
然后呢相当于需要以插件的形式最后载进来,当然这里吧我先演示。
就是如果比如这里有一个那个空工程,这个工程是用来专门测试动态加载插件用的,然后实际上因为它里边基本不做。
不进行任何的操作,所以呢如果直接打开的话,这里边是实际上空的。
就是他几乎不加载任何的,跟仿真相关的一些算法,当然这个渲染是因为默认的有一些东西,然后但仿真的所有的选项卡,你发现其实没有。
然后这个时候就是要怎么做呢,如果我们现在mate,比如说已经是开发了一些呃动态库啊,那这样的话实际上就是把这个动态库里的,比如说我们就还是刚才那个,呃粒子系统的这个动态库。
然后这样需要考到这个plugin里头。
然后plugin里头的一个第八个录像,然后这个时候我们再去跑起来的话,实际上这样的话其实你就可以看到,就是嗯这个历史系统相关的这些功能。
实际上就已经被加载到一个g u i里头了。
然后这部分这样的话,实际上你可以看到就是这里边的选项卡,就是跟刚才那个演示的那个界面,实际上是类似的,然后这个时候呢,实际上就是去点那个选项卡里的一些嗯按钮,然后这个时候呢就可以创建类似的。
刚才那样的一个场景,当然这里边没有那加载,没有建模啊,其他的没有加载,所以呢单纯可以演示一下,比如说流体针对流体这个场景,那这样的话其实就创建一个发射器,然后呢比如输入给这个流体的这个啊求解器。
然后这样的话就是比如说我们它再调一下位置,然后再点开始,然后这个时候你可以可以看到这流体啊,就是从发射器里表,然后生成出来的这么一个场景,然后当然就是这个时候,如果你比如说你啊。
自己自研了一些其他的一些库啊,或者其他的算法的话,其实也是通过今天讲的类似这种形式,然后这样的话可以导到这个嗯框架里头,然后呢,跟别的一些算法模块和插件也好像配合起来,来来创建更复杂一些场景。
所以这个我就这样,我相当于再演示一下啊。
我们今天要讲的话差不多是这些。
然后当然后面实际上就是一个小作业,就是因为其实呃一般我们作业不检查,就是大家有兴趣的话可以去做一下,就是你比如说你现在已经实现了一个,任意的一个ui啊,这样的话你可以试试,就是比如说针对这个呃。
你需要的这么一个,就刚才前面演示了一个一个流程。
然后看看怎么比如说把你的算法给他谋划化,然后呢,最后相当于给这个怎么让它变得更好用一些,那整个今天要讲的差不多就这些吧,然后看看有哪些哪些问题吧,然后我看那个直播间里边有问,那个是不是自己做自研引擎。
是不是计算机必学,其实这个倒不一定就是资源引擎,其实主要是这样,就是看你在哪个阶段了,就是你如果仅仅是做一些研究啊,或者是可能就是目的就是发一些论文的话,其实这个不一定需要做自研引擎。
但是呢你如果比如后面,你如果想做一些其他更复杂的一些应用啊,那这样的话其实就有可能会需要,那其他的看看还有还有什么问题啊。
然后整个刚才演示的这几个样例啊,理论上应该是我测过的没问题,所以大家可以就是就按照刚才那个流程,可以去演示一下,就是就是在自己的台基地边,应该考的会比较流程,哦这里有说是打算用自研引擎做游戏。
然后这个呃可能还不太一样,就是因为我们那就知道我们现在做的那个,实际上主要针对仿真的,因为游戏引擎的话实际上跟这个还是不太一样,就是游戏引擎,因为其他涉及的,其实我觉得它涉及的物理实际上是要更简单。
所以它更多的实际上是侧重在其他方面,需要考虑的一些一些内容,然后考虑单机游戏呢大概需要哪选哪些,然后那这个我觉得最基础的应该是呃,就是类似于就是game 10101渲染啊,然后当然编程的是最基本的。
所以这个呢我觉得其实可能需要,那如果是这样,目前18岁的话,我觉得这个可能需要补很多基础知识吧,可能还到不了,就是那今天讲的就是比较就是比较专的一些,比如像房间算法,可能还到不了那个层次。
先看看看还有没有有没有其他问题啊,大学的哪些数学需要学是吧,这个看哪个方向,如果是针对,比如说仅仅是游戏开发,我觉得主要是教同学,然后线性代数,但是高速啊可能也需要学,然后嗯。
因为实际游戏里边其实涉及的物理,可能不会那么复杂,所以呢其实我觉得一些基本的一些数学啊,其实应该就差不多对,然后当然就是一些基本的力学的一些东西,当然这个就可能不需要什么连接件力学,这个其实没关系了。
其实就是一些大学物理里边的一些比较简,单的一些力学,我觉得有个了解应该就可以,因为游戏里面其实无论是比如说你钢铁系统啊,或者啥,其实都会比较简单,就是而且实际上会有很多的trick。
它其实不是那么serious的,物理方面,那现在反正这样就是整个欧为,我们这个其实也是一个开源系统,所以呢里边其实有很多问题呢,其实你会发现啊,就是也在不断的完善,所以就是可能中间的。
有可能中间某个版本可能会有一些小问题,但这个反正也是逐步的在完善的一个过程,行那今天我我看时间也差不多了,那我们的课要不就到这儿啊。
GAMES401-泛动引擎(PeriDyno)物理仿真编程与实践 - P8:8. Vulkan编程原理及通用并行计算 - GAMES-Webinar - BV15M4y1U76M
嗯然后今天呢是这样,就是差不多是我这个最后一次课吧,然后后面就是有蔡老师进一步的会讲一下,就是工程仿真里的一些内容吧,然后今天这一课呢是这样,就是呃其实可以理解为,就是前面七次课的一个番外篇。
就是因为前面呢围绕我们,比如围绕库大,然后包括那个特丹诺引擎里边相关的一些内容,实际上整个是完整的,但是现在呢是这样,其实有可能会面临什么问题,就是可能有些同学打个比方,你可能现在没有英伟达的显卡。
或者是那个呃有种种种种原因吧,可能就用不了这个呃n卡,那这样的话会导致什么一个问题,就是可能就是前面课程里边讲的那些案例啊,或者很多的那个程序,实际上可能都跑不了,所以这样的话实际上就是带来一个问题。
就是说那如果我们脱离这个,比如说脱脱离扩大编程啊,我们还是进一步的想做,比如说一些并行仿真相关的一些呃,就仿真相关的一些并行计算,那还能不能做,然后主要是这样,所以今天呢实际上是针对这个问题。
然后我们主要讲一下,然后第二呢实际上是因为为什么今天讲挖坑啊,因为mark其实是呃最初的话应该是16年的时候,实际上就当时就呃呃当15年是提出来的,然后16年应该是属于正式发布啊。
然后这个瓦肯整个它实际上提出的初衷呢,实际上要整合就是渲染跟访问计算,然后呢用统一的api去去做,然后当然这里边这几年实际上在渲染力,渲染这一块啊,其实啊大家其实常识也比较多。
然后呢也发现挖矿这个还是有它的,这个很多有优势的那个地方,但是实际上在仿真计算领域,这个其实用motion做的其实不太多,所以呢现在实际上就是很多时候呢,就是说比如说我们马克到底他的能力边界。
就是针对仿真计算这个呃这一块啊,就是他的能力边界到底在哪,实际上很多时候不太清楚,然后呢我们目前到底能做哪些啊,跟仿真相关的内容,这个呢实际上很多时候可能不是特别的,就是因为这块其实做的相对比较少啊。
所以这样的话实际上今天呢其实也结合,因为正好华为呢就是我们说华为里头呢,其实之前也做了相关的一些工作,这样的话静好也是结合前期的一些工作,这样给大家做一个分享嘛,然后当然这里边今天讲的很多。
其实因为也是处于,其实很多时候其实处在一个探索的过程,其实很多时候也不是说,今天讲的其实就是一个成熟的解决方案,其实不是的,其实这里边因为啊我觉得瓦肯这个整个,包括整个语言也好。
或者是他其实用在法律这一块啊,其实还有很多需要进一步值得探索的一个地方,所以这样的话其实就是呃有很多,今天讲的可能有后门也不断的,因为其实也是开源的一个呃相当于一个系统吧。
这样的话后面实际上也会不断的进步的,去完善啊,嗯那现在那后面我们就具体来讲讲,就是这块内容吧,然后今天讲的话其实主要是分几块,就是首先简单介绍一下,就是挖坑的一个简介,然后当然以及一些通用名。
是云计算的一些一些概念,然后当然这里边就是会,接下来就是会讲一个比较具体的一个例子,就是说我们怎么用挖矿来写一个,并行计算的程序,这个计算实际上就是呃就跟渲染无关了。
就纯粹是一个通用的一个并计算的一个问题,然后当然这里边就这个过程中,其实就是你发现这是如果纯粹的用原始的那个,挖坑api去做的话,这个东西实际上还是蛮困难的,所以这样的话实际上接下来就是我们会看看。
就是说我们目前就是怎么针对以往这个挖孔,这个编程太复杂了这个问题啊,然后就是啊怎么来简化,就是针对这个计算任务,然后来进一步降低它一个编程的一个复杂度,当然因为整个实际上是呃。
现在实际上包括这个整个挖后端,实际上是内嵌在就是parda这个框架里头啊,所以呢就是这里边后续其实也会讲一下,就是这个挖矿后端是怎么跟pdino,实际上他作为一个那个跟kda类似的后端。
然后怎么跟这个pdl这个框架,然后相相当于怎么对接啊,当然还有一些其他的,就是我们的前期就是呃,就是各种尝试过程中发现了一些问题,然后正好也可以给大家分享一下,然后当然最后还有一些简单的一些。
案例的一个展示,首先我们来看一下就是挖坑,这个呃是一个什么东西啊,就是其实这个东西是这样,就是挖坑,最早实际上刚才提了,就是实际上在gdc 2015的时候,实际上是被提出来的。
然后当然这个正式发布是在2016年,然后他整个实际上因为也是嗯,我们知道他上一代的其实是主要,因为之前一般就主要用欧盟gr嘛,用的实际上比较多的,但是呢欧盟gl实际上还是有很多问题的。
比如说那个呃像多多线程下的一些问题啊,或者以及各种平台,比如移动平台跟pc平台这两个实际上不通的,所以针对等等,当然还有就是整个open g啊,它的呃它它主要是针对还是针对图形渲染的。
他其实针对通用计算这一块呢,实际上是还是比较弱的,所以这样的话实际上瓦肯设计的初衷,实际上就是要把呃渲染跟仿真这两个任务,然后呢实际上是整合到一起,然后相当于用一个通用的api,去解决这两个核心任务。
所以呢实际上他提出来的一个,当时实际上就被誉为是一个叫open g啊,net相当于实际上是下一代图形的一个接口,就是也就相当于是,未来有可能是要替换掉open g啊,但这个东西就是短期内。
我估计这个东西没有那么快了,所以这个实际上也可能会是一个漫长的过程,然后呢逐步的去替换就omg,当然这里边就是本质还是也看,就挖坟到底能解决这个问题,要以往存在问题的解到什么程度啊。
这个实际上当然还有各种硬件厂商的知识等等,这个实际上都相关,所以呢当然这个目标实际上整个需要替换掉,open g r,然后这样的话成为新一代的一个图形,的一个接口标准。
那当然这里面其实还有一个特别有意思的,就是挖坑这个东西啊,因为它特别偏底层,所以整个如果直接用marin去写这个呃,各种的程序的话,这个东西实践起来还是非常的麻烦,不方便,所以呢就是如果对于初学者来说。
所以今天讲的那个实际上不太,今天讲的内容可能不太适合,就是说如果你是一个图形或者啥仿真计算,入门的一个呃一个刚入门的这么一个情况,这样实际上不太适合用welcome去写的,就这个时候肯定还是希望更适合。
就比如你哭大,作为你一个入门的一个基础,然后当然后面其实会讲,就是怎么能尽可能的把这个复杂度也降下来,当然,然后呢挖坑它其实有一些那个特征,当然是因为他这嗯之所以会被认为是,比如说下一代重新api。
它肯定是有遗忘的,就像我们g1 里的一些无法比拟的优势啊,当然比如第一个,它实际上就这里就是一个,实际上是一个统一的api,所以这个统一a b i什么意思,其实主要像以前的open gl。
我们知道它实际上是在pc端跟移动端,实际上是两套api,就是pc端呢实际上叫open gl,然后呢移动端呢是呃open gl,但实际上说温蒂尔的一个子集,就这样的话。
实际上整个实际上兼容性感实际还是成问题,和这样的话,实际上win这个呃这个api呢,实际上就相当于,他实际上用一套统一的api去解决,就是说各种啊移动端也好,p那个pc端也好。
这样的话实际上是各种环境用统一的一套一开,那当然这样的一个好处,就是实际上它可以兼容各种各样的操作系统,比如说像android移动平台或者是windows linux等等啊。
这实际上都统一的用一个api,这样的话实际上如果这个可行的话,那就讲了,对于比如说我们呃写防御算法的研发人员来说,实际上是一个利好,因为这样的话你实际上只需要写一套算法,然后呢,这样的话就可以。
无成本的迁移到任何一个平台去运行,所以这个对于后期比如说你去发布啊,或者对那个呃这个平台迁移,跨平台迁移的时候,这个实际上会比较方便的,当然这个马克还有一个优势,就是它整个就是针对多线程环境。
还是比较友好的,因为以前像open gl或者bd差这个设计的时候,它实际上主要是还是针对那个那单核cpu的,这么一个来考虑,当然另外就是马可,因为它只是整个它的接口啊,更靠近底层。
所以它实际上就是他的所有的api,它的那个调度的一个开销,它实际上是相对来说更低,所以就也就是你如果同样执行同样的任务啊,这样的话,实际上理论上挖坑的效率应该会比open gr,实际上是要高。
当然他因为也更偏偏底层,就所以他其实对整个g p u拥有更呃,更直接的一个掌控能力,然后呢接下来我们看一下,就是我们看看就是给大家科普一下,就是整个gpu的api到底包含哪些东西啊。
就当整个g p u呃api它实际上也是伴随着,就是因为这里其实不光是挖坑啊,其实这个整个在gq i a p i这个家族里面,实际上是比较多的,当然主要其实就两个目的上来讲,就是其实就是不是为了做渲染。
其实就是为了做仿真,当然像挖坑,因为它它目的是渲染跟仿真,相当于兼顾的这么一个api,所以整个所有的那个gpu一拍,它实际上也是伴随着就是gpu的一个发展,然后当然最早的话就是open gl。
当时1992年提出来的,因为当时也是显卡,然后出现了之后呢,然后就相当于比如针对这个啊游戏啊,针对各种的那个三维的一些场景,然后做一些固定的一个一些管线的一些功能。
然后当这个他当时最初提出来的open gl单,主要是应用c来写的,然后呢当然另外就是他其实当早期的那个open gl,实际上是不具备这种可编程管线的,所以呢他很多时候他其实呃像学图形的时候。
为什么会讲那个根管线啊,它其实整个相当于每一步做什么,实际上都是固定的,所以这个是早期的那个呃呃图形api的一个特点,然后当然后面就是想微软的话,后来独立地发展出了像点direct x。
然后他当时在windows 95里面就是引入这个,然后当然因为微软,它实际上主要是他借助它的windows,所以呢就相当于实际上就是啊,它实际上形成了一套独立的一个标准啊。
所以这样的话其实整个它是平行于open g啊,独立发展的这么一个一个api,那当然后面的话实际上就是因为考虑到就是说,如果我们针对的呃,很多时候这样的,就是我们实际上很希望,就是说你这个呃。
a p i具有一定的可编程的能力,那这样的话实际上在第三第九的时候,它实际上就引入了这个角还level的这个cd language,然后这个嗯shader这个引入之后呢,实际上对于某些。
比如像顶点着色器或者片源左侧气,这这这几个阶段啊,就特定的一些阶段,那这样的话可以由用户去自己去设计一些,就是说相当自定义的一些行为,比如说我相当于对比如说这个顶点的一个属性,我可以做一些制定的计算。
那这样的话对于特定阶段的,实际上就具有了一个可编程的一个能力,那当然这一块实际上就是呃就是刚才讲的,就是因为open gl,整个实际上主要最初的话,主要还是针对pc平台啊,所以实际上在03年,包括后面。
因为我们知道那个呃就是二一世纪初的话,实际上最最大的一个变化,实际上你会发现就是各种移动设备啊,就是整个层出不穷,那这样的话实际上就是你所有的那个图,因为我们知道手机其实它也有gpu。
但只是他建个gpu的那个性能相对来说是比较弱,所以呢这样的话实际上你也同样需要兼顾,就是说你这个图形能力,也需要兼顾这个移动设备,所以针对这个移动设备呢。
实际上就是啊这里就发展出了就是open g l e s,它实际上就相当于是这个open gl的一个子集,然后呢,主要专门用来针对这个移动设备的那个,图形渲染,那当然这个同样的就是因为也是需要就是啊对。
比如说像顶点着色器啊,顶点着色器啊,当然后面其实还有几个左侧器啊,这几个一些特定的这个阶啊,这个嗯阶段实际上需要具有,可具备可编程能力的话,实际上open g它实际上也引入了这个着色语言。
就是open g l的这个协定,languy,他这个跟h l s l其实也是一个并行的,就是他这两个其实语法很像啊,就是很多东西其实你发现它是相通的,但是他整个因为它实际上它的那个维护的主体。
是不一样的,欧盟基亚,因为它整个是一个叫chronolop的这个组织,这个那公共组织来维护的,然后像德尔佩x的时间,主要是由微软来维护,他的那个一个语言的一个迭代,然后当然这后面就是因为其实这样的。
早期的刚才也讲了,其实早期的啊其实比如07年之前啊,其实那会儿当然就是呃,其实也具备一定的可编程的一些能力,但是呢实际上早期的图形api,其实主要还是渲染为主,当然也有尝试。
就比如说用可以用特定的shader,然后做一些模拟相关的事情啊,比如像那个文华老师之前在2004年的时候,其实呃也已经做了,比如像那个三维流程的一个模拟,但总的来说就是早期,因为各种比如说配套的工具啊。
这个或者一些调试工具的一个缺失,导致实际上就是嗯就是通用这个像kda以前啊,你如果用这个gpu的api去写一个比较复杂的一个,访问算法的话,这个东西代价还是比较大的。
所以呢实际上就是后就是07年这个扩大,这个就是由英伟达这个提出来之后,实际上这个东西,我觉得可以认为是一个里程碑的这么一个,一个节点啊,因为它整个实际上就是重新定了,就是你这个gpu其实它不是单纯。
就是不是单纯用来做渲染,它完全可以用gpu去做任何的啊,跟渲染无关的,比如完全是一个仿真计算的,一个通用的一个任务,所以这样的话实际上就是后面的就逐渐,就比如这个gpu呢。
你会发现在现在比如各种应用这个压训练啊,等等,各种算法训练,实际上你发现这个实际上就是也是啊,这个07年这个扩大提出来之后,然后对这整了这个你会发现这整个学术界也好,产业界学校实际上产生了很大的变化。
然后当然ka早期就是ta主要其实还是用针对,是计算的,然后当然这个其实早期的版本,包括08年那会,他其实也只支持c,然后后来是逐渐在嗯,应该是没记错的话,可能是5万还是六啊。
就是后面逐渐的这个记不太清楚了,就是后面逐渐的相当于加入了,比如对c加加的一个支持,所以整个它实际上发展到现在的话,其实变得已经变得是比较好用,当然这个整个它各种知识的标准,也是不断的发展和新加17啊。
最新的等等,就各种新的特性呢其实也不断的加,然后当然这个因为这还是跟那个前面就是欧文,g要跟doos其实是一样的,就是嗯因为这个英伟达,那这个扩大实际上主要还是英伟达的护盾,就这样的话。
实际上这个对于整个比如行业标准的话,实际上是缺失的,所以这样的话,实际上在后来在2009年的时候呢,又提出了这个open,就引入loopen cl,然后这个实际上专门是针对这个通用并计算。
然后呢相当于提出来的这么一个通用计算标准,然后这个当然最早是其实open是apple发起的,然后最后呢是后来是,应该是有这个corona group来维护,然后他这个整个里边很多特性。
你发现其实跟古代其实也比较像,当然唯一不一样的地方,其它其实是它整个实际上是呃他不是混编的,它相当于它的呃shader跟它的后续的代码,实际上整个人分离的,当然他整个也是支持这个c或者c加加。
它其实这些是实际上都支持的,但是后面其实你看后面的发展的话,整个现在其实从用户的角度来讲,其实我们cel这个用户群体应该是,目前应该是远远要少于这个扩大的这么一个,用户群体。
然后当然其实像metal的话,其实就后面apple,因为其实针对的其实就是,比如说图形和计算的这两个啊,这两个任务,它实际上就是apple也希望把呃,图形跟计算这两个api融合。
然后呢形成一个统一的这么一个图形接口,所以这样的话,实际上apple在14年的时候就开始就呃发,开始发展他的那个metal,然后当这个metal其实跟dx实际上是一样的,他其实也主要是针对这个v。
就是苹果的这些平台,就是苹果的那mac系统啊等等,然后它实际上是跨平台的能力,其实还相对是不足一些,所以呢到16年的时候,实际上就进一步的就是其实针对,因为其实目标还是一样的,就是需要把渲染跟这个计算。
这两个呃任务实际上是打通,然后用一个统一统一的api去处理,所以这样的话,实际上在16年的时候就发布了这个啊瓦肯,当然这个最早的时候实际上是md发起的,然后后来也是由这个开源组织来维护,然后呢就是挖坑。
其实比起其他的语言,比如比起那个m g l也好,或者c l也,它实际上你会发现它整个更底层更底层,什么意思呢,它实际上会把很多硬件的就gp硬件的那个特性,实际上会暴露出来,这样的话有个好处。
就是它实际上它整个的性能会更高,就是如果你运用得当的话,这个性能实际上可以得到更高效的一个性能,但是呢啊整个带来的一个负面的影响,其实本质上对整个包,可它实际上对于编程人的要求其实同样也很高。
然后呢同时导致就是整个编程的复杂度,其实大幅的一个提升,然后当然目前的话时间挖粉主要还是支持c啊,其实c加加的一些特性啊,比如说那个各种面向对象的封装啊等等啊,这个或继承派生等等这个东西。
目前马可应该是不支持的,然后呢这样我们从那个用前前面来讲啊,其实这个你会发现,就是如果单纯的去做这个并行计算啊,其实你有很多的解决方案,就是你比如说你可以用扩大来做,或者你也可以open cell。
或者你甚至你用win用全部重写一遍,当然也没问题啊,但这里边实际上就是啊,因为为什么这里边有很多的呃这个呃标准,或者是很多api,这个其实一方面是整个是,因为他其实这商业建的考量点我们就不去讨论。
然后当然对于这个研发人员来说,我们其实更关注的应该是就是说,那我们如果针对一个特定的一个呃任务,那我们是需要怎么去选择,就是用什么样的一个语言,是作为一个自己最合适的一个语言。
但这里边实际上就需要考虑很多方面的一个内,容,就是呃这里我列了几个方面,就是以这个kda in cell go mark为例,然后我们看看就是说这三个它其实在不同方面,它的特点啊有什么差异。
这样的话其实你可以结合,就是说你这个不同的呃特点,然后你最后却可以决定,就是说你到底用什么语言去完成,你最终最终的一个并计算的一个任务,所以首先第一个实际上是从实际上,从支持混合编译的这个角度。
这个混合编译这是什么概念,就是我解释一下,就是其实你看以前大家如果写过那个open gl的话,你会发现这是open gl的那个设备端的,那个就是gpu端的那个代码,跟这个厚实的端。
就是你c加加写的那个代码,这两个东西实际上是分离的,它实际上不是在放在一块编译的,然后这个呢实际上在扩大里边是支持的,因为扩大你会发现就是你整个比如说你在呃,有有一个点ceo的这个后缀的文件里面。
你可以同时的写c加加代码以及ko代码,然后这个时候呢,n m c c会帮你去拆分里边的不同的代码,所以这个当然也就这个,实际上是需要去用编译器,编译器层面来协助来完成这个内容,然后当这个有这个的好处。
就是你整个实际上你发现这个代码的,编码的一个复杂度,实际上能大幅度降低,这样的话就是可以,就是就是加快你整个研发算法的一个呃,一个效率,然后像那个open cl,以及包括这个实际上目前应该是不支持。
因为这样的话呃,不支持导致的一个结果,就是相当于你这个时候,你比如说你定义了一个数据结构,那这样的话你可能需要针对,比如说你ccr里的代码,以及你谁都是代码,这个时候你实际上是要维护两份代码。
这样然后同时要保证这两个之间的那个呃,就是结构是要完全一致的,所以这个整合对于代码的维护,实际上是有成本的,然后当然其实其第二个就是因为仿真的话,整个它的算法逻辑实际上会比较复杂。
所以呢就是啊需要有各种各样的调试工具,然后去辅助你来啊支撑,就就相当于是你比如说你这个呃,中间的某一个布,然后可能你需要去看看他输出的一些结果,那这个呢实际上其实也很重要。
就是所以当这个实际上目前应该都支持的,只是说那个呃你如果看裤带的话,可能会更好用一些,当然其实第三点的话其实很重要的,就是如果我们比如说后期我们如果我们想呃,我们写一份代码之后。
然后我们可希望就比如能到多跨平台里边,就是无无差无缝的迁移过去,那这样的话实际上我们就需要考虑,就是说这个这个api的这么一个,跨平台的一个能力啊,然后当然这里边就是我说了一下,就是因为像coda。
因为主要还是依赖于完全依赖于英伟达的显卡,所以这样的话,实际上对于比如说我们现在用的是md的显卡,或者是移动端的一个设备,那这样的话实际上可能没有能用的大显卡,那这样的话实际上你以前写的扩大代码。
可能就啊不能直接用,所以从跨平台的角度来讲,其实ka这个应该是对于平台,或者对硬件的依赖性实际上是比较强的,那这样的话其实像open cl跟瓦肯,其实这两个相对来说话,平台能力更好。
但其实严格来讲应该挖坑其实是最好的,因为它其实支持的平台就是,无论从pc端到移动端,它的那个兼容性应该更广,当然这个其实也带来一个不好的地方,就跟他说,因为很多时候你的这是你的效率啊。
跟你的那个啊就是你的性能跟你的那个复杂度,其实有时候是呃很难折中,就是说这样的话,你如果画平台接的好的话,你有可能整个你对于在不同平台适配的时候,它实际上依然还是会有差异。
所以这个时候就是还应该还是会有一,些额外的工作量需要去去解决啊,那当然还有一个就是整合,就是因为不同的语言,它其实是支持的c或者c加的标准是不一样,就是像库大哥们cl的话,现在应该主要是c和c加加。
其实c加加为什么这里很重要,因为这里边就是像仿真的话,呃,他其实如果单纯用c是不是可以,当然也可以,但是呢问题在于,就是说如果你这个嗯不用不依赖任何的封装的,这些特性的c加特性的话。
它会导致整个代码的复杂度极高,所以这里实际上就是呃,从这个代码简洁的角度来讲,其实这个支持c加加对对象的封装,这个东西实际上是比较重要的,然后当这个目前挖坑实际上不支持,所以如果用mark的话。
其实你许多代码,就是你可能需要退化到这个c的这个,一个一些规范,然后呢还有就是dc加加其实也有很重要的一块,就是比如模板的是不支持啊,这个这个其实模板主要是因为这样,就是很多时候。
我们不希望就是说你类似的代码写多份,然后这样的话其实整个维护的成本比较高,所以这样的话其实如果有模板支持的话,我们可以就是统一维护一份代码,然后这样的话其实用模板的一些策划,各种的其他的一些技术。
然后呢可以整个降低代码维护的成本,所以整个你会发现就是不同的语言之间,它在阶级方面其实会有一些差别,所以呢就是你可以结合自己的需求,如果你仅仅是比如说你想,就是想做一个特定的研究。
然后呢比如就写特定的算法,那这样的话其实你怎么说,你比如你用coda啊,你这可能是最方便的,然后当这个时候你如果要考虑的,比如你需要移动端啊或者跨平台,那这样的话可能扩大你解决不了你的那个需求。
那这个时候你可以考虑用walk,然后呢是不是对某些特定的算法进行重构,然后相当于生成一份,就是说你可以兼容各个平台的一些访问算法,那后面我们就来看一下,就是那我们现在既然就是呃每个语言。
它其实有它不同的特点,然后这样后面我们就看看,就是说用挖坑,如果呃作为我们现在打个码,我们就现在选定想用挖坑来写一个,并行计算的一个程序,那这里边就是呃该怎么做啊,就是这样,我当时第一就这一部分。
我先简单的讲一下,就是如果我们不依赖任何的封装,或者不是依赖于,就是我们家假设用的就是原始的api,然后怎么来做这个事情呢,就这里我写了一个简单简单的任务,就是比如说我们现在已经有两个数组求a跟b。
然后呢实际上就是做的事情也很简单,我们就假设把a跟b然后先求和,然后加到啊,把结果存到c的这么一个数组里头,那这个东西对于如果我们现在是用打个比方,我们现在用扩大来写了,这个其实很简单。
就是嗯我相信比如说对于一位初学者来说,以前可能完全没有接触接触过gpu,可能花个几个小时,这个东西应该也是能写出来的,这个我觉得没任何问题,但是呢这里边的问题在如果打个遍,我们现在是用vn去写。
那这个东西就很难说了,所以这里我写了个一言难尽,其实这里边主要是如果针对是呃,完全的一个挖坑的初学者,或者你可能gpu之前就是可能没有任何的接触,这个时候你如果仅仅是想去实现这个东西啊。
我觉得估计可能得花很久的时间,然后我们后面来看一下,就是为什么这个东西就这么复杂,就是因为这个整个挖坑它实际上前面有提到,就是他因为更偏底层,所以呢他许许多硬件的特性就是本呃,比如像ka它之所以点燃它。
其实本质是它编译器层面,它又给你做了很多的简化的一个工作,但是呢像挖坑,它其实它的编译器的那个能力相对还是比较弱,所以很多时候你需要去自己去,相当于去啊,指定各种各样的一些执行的一个流程。
然后呢这样我所以这里我先简单讲一下,就是welcome它包含哪些东西啊,就是呃你如果现在,比如说你就要想编写一个前面的一个任务啊,当然首先最顶层,它实际上你假设其实就是一个application。
然后呢你application,然后接下来的话你实际上就是要做的第一步,实际上就是你需要创建一个instance,就是当你针对不同任务,你可以创建多个instance啊,这个实际上是一对多的关系。
然后呢有了这个instance之后啊,就是接下来你要做的就是,因为你可能一个就是一个电脑上,或者一个移动设备上,你可能有多个显卡,那这样的话,实际上你这个时候你需要去选择一个显卡。
你具体在相当于要决定在哪个显卡里边,你去具体去执行你的那个计算任务,所以这里面实际上有一个物理的一个设备,这个物理设备对应的实际上就是你的一个呃,一个一个显卡,然后当物理设备选完之后呢。
实际上接下来你实际上计算的时候,你还需要有一个逻辑设备,这个逻辑设备呢,实际上是你就真正执行计算的呃一个地方,然后当然逻辑设备里头会有对应的那个,一个队列,这个队列呢主要有三种啊。
因为整个挖坑它其实主要是会针对,就是他有两类任务吗,它实际上一个是他的渲染任务,第二个呢是啊他的计算任务,所以这样的话实际上就是从队列角度来讲,它实际上会有三个队列,就是有一个图形队列。
还有一个计算队列,当然还有一个是transfer那个队列,然后transfer这个队列主要是针对,就是说比如说你现在有两个数组,你需要进行数据之间的一个拷贝,然后相当于其实是主要针对数据拷贝。
有这么一个一个独立队列,当然现在这样就是你不论是图形队列还好,也还是就是说你的计算队列,实际上它都是可以同时去完成,那个jansfer的这个拷贝的就是这个,所以这个呢实际上是简化了,整个,就一定程度上。
其实简化了整个啊计算的一个流程,那有了这个队列之后,当然下一步实际上你就要去创建各种坑等函数,然后你就去执行可能函数,当然这个东西呢其实你会发现比扩大还要复杂,就是扩大的话,你可能直接写一个客串函数。
然后编译器,然后就帮你转成一个二进制了,这个实际上比较简单,但是呢welcome里边,其实他整个逻辑实际上都需要你自己去创建,就是也就这个时候你需要去,如果你要去呃执行一个额计算的管线的话。
这个时候你呃首先还是还需要去分配一个,你的那个命令的一个command poor,然后当然这里边会有很多command buffer啊,然后这些command buffer呢。
实际上就会去具体的去在这个上面你去记录,就是说你要执行的哪些命令,相当于你这些,比如说你有一些计算的管线,你有一些算的管线,这样的话就需要依赖这个model buffer,然后去完成整个计算的一个过程。
当然这个过程整个行,因为你这个整个pine,它实际上它还有就是他需要输入,比如说各种各样的一些数据啊,就是比如说你输入一个呃呃buffer,或者输入一个那个变量,那这样的话其实你还要额外的指定。
就是你这个buffer到底是啊什么类型,然后呢,各种大小等等这些东西需要都需要去指定,也就是你会发现它整个,但完全它里边,相当于每一步都需要你指定清楚之后,然后挖坑才能真正的去执行你的那个代码。
就这样的话,实际上还有一块就很重要的,就相当于你整个gpu上你创建的,比如说你有global memory啊,你local memory各种memory的话,你实际上也需要就相当于是创建出来之后。
然后呢它是一种代表什么类型,然后他的描述符需要指定清楚之后,然后呢传递给相当于整个计算的那个pi,然后来去执行这个呃这个计算,所以这个实际上你会发现就是从这个won的,这个你看那个呃这个整个对象关系。
你会发现它其实流程还是比较长的,就是因为这个不像,因为像ka里边就是你很多东西它其实是隐藏的,就是比如说你直接如果你不选那个呃device,它其实默认可能就给你选了一个一个零,所以这个时候呢。
实际上你这个时候你不需要关注,就是你即使完全不管任何的其他的部分,你实际上只是单独的你去执行一下kle,它实际上会有很多的默认的一个操作,但是那welcome这很多地方你会发现。
它实际上需要显示的去指定各个部分,所以这样的话就针对就前面的这么一个,简单的一个任务,你发现就是他其实会包含很多步骤,就是啊这里只列了七个,就是我后面逐步的会讲一下,就是到底应该怎么怎么去做啊。
然后当然首先第一步,实际上就是你要创建一个instance,就是你当然整个application,然后你需要去创建一个instance,然后有了之后呢,你要呃前面也提了。
就是你相当于需要创建一个物理设备,然后有物理设备之后,然后当然才是这个一个逻辑设备,然后呢再结合你的队列,然后再去创建各种的啊,就是相当于buffer也好,或者是看那个peline等等啊,就这些对象。
然后呢第二步实际上要做的就是说,因为其实这里面最核心的答案是两个,一个就是你要准备的数据是什么,然后呢第二个就是你的计算程序里的那个代码,就是计算的代码是什么,所以呢实际上就是相当于整个前面的那设备。
初始化完了之后啊,后面第一步要做的其实就相当于是要在呃,就是你的gpu的那个memory上的,你实际上要去分配你所需要的一个数据,然后这个其实跟kda其实也有一定的差别,就是扩大的话,你如果打个比方。
因为这个实际上cpu和gpu的数据,一般是不能直接访问的,就比如我我现在有一部分cbc加加的代码,然后呢,这个时候它实际上是没法直接的去访问,gpu上的一个一个数据,然后反过来也是一样的。
就是你如果是现在,比如说我gpu有有个ko的一个函数,它实际上也是没法直接去访问这个呃,就是你的比如说对应的一个cpu,对应的一个呃内存的一个空间,所以呢就但是像ca的话。
其实会有一个比如说有有拷贝的函数,你这个时候你可以直接把cpu的一块数据,直接拷到这个gpu,然后这样的话gpu实际上就是啊就可以,就是针对就相当于你gpu的代码,直接就可以看到这块考进了一个数据。
但是呢mark有一个特点就是挖坑,他所有的这个数据,它需要通过有一个叫stage buffer的这么一块,一块存储区,需要进行中断,然后这个存储区相当于什么意思呢。
就是啊这个存储其实对于cpu和对于gpu,它实际上都是可见的,所以这个时候呢就是你相当于你cpu跟gpu,它互相之间打交道的话,他不是说你两个直接直接互相打交道。
他而是需要通过这个stating buffer,然后来去做这个一个中转,所以这里怎么做呢,就比如我们现在这个cpu里边,我们分配了一块一块呃空间,那这个时候呢他要映射到。
先映射到这个steady buffer里头,然后这个时候呢就是当然这个steady buffer,它对于gpu来说,如果直接去访问了也可以,但是呢,这个时候他其实整个呃效率还是比较低的,所以这样的话。
其实最好还是说把这个东西要直接考到这个呃,就gpu的一个local的一个memory里头,首先的话其实是利用这个sting buffer,然后进一步再把这个数据考到gpu,然后这个时候。
然后比如说你的gpu kl再去访问这个数据的时候,这个时候会表快,所以这个呢是其实是瓦肯在分配这个这个呃,空间的时候啊,就是跟其他的那个,比如像跟空大可能会有一定差别的一个地方。
然后这个这个有了车后堂,第二步,实际上就是要去准备你的一个计算的一个ko,然后这个kono实际上你用很多号,很多那个写着写都可以写,在这里举了一个就用js写的这么一个eko,然后当然它这里边你会发现。
它其实也需要干几个事情,就是里边一个呢,你需要去指定它输入到底是输入哪些参数,就是其实前面相当于是你前面分配的那个buffer,到底是哪几个,所以第一个就是比如像针对那个两个数组,然后求和。
然后存到第三个数组的话,这样的话实际上它需要进就是输入这三个buff,然后当然你额外的还有个变量啊,就是这个变量实际上是告诉,就是说你这个可能我请问我这个数组里面,一共有多少个元素,然后有了这些之后呢。
当然其实这里面还有一个东西,你看它指定的是一个,就是因为我们知道那个gpu上面的话,整个执行它是以就是我们第二次讲了,它实际上是以block的那个为单位去执行的,所以这样的话。
实际上你需要还需要在这里边去指定一个,block的size,然后当然后面那个代码实际上就比较简单了,就是当然所有的这个啊shader它的入口啊,其实都是有一个叫main的一个函数。
就是相当于它整个就是一个入口函数,然后后面的话其实你会发现,其实这个就跟扩大就比较像了,就是你获取它的一个那个呃全局的一个id,然后当然这个是一个三维的,就如果你现在这个数组是一维的话。
那这个时候你只需要就是你呃,根据它的x就是x的那个大小,然后去相当于把这个呃对应的那个处理的那个,数据的那个位置给他定位出来,然后这样的话你整个去执行计算,然后呢所以这个整个代码实际上比较简单。
然后完了之后,当然你需要额外需要做的,实际上因为这个是一个二进制的代码,就是你如果直接去执行的话,这个执行不了的,所以呢这里边实际上就需要把这个二进制代码,然后呢转就编译成了。
这个叫有个spear v的这么一个呃中间文件。
然后这个中间文件呢是这样,就是它其实是相当于是你的编程语言跟底层,就是ever的这么一个呃,中转其实相当于这就很多,就是这样,你可以看左边那个就是他其实不是单纯的。
比如针对那个js l或者g h l s,来推出这么一个标准,它实际上相当于是可以把很多的这个语言,实际上就相当于都转换成这么一个中间的,这么这么一个标准的二进制文件,然后呢进入这个。
比如说变成这个标准文件之后呢,然后再进一步的就是啊,到就是说在我各种gpu上去执行,所以这样的一个好处就是以前的话,比如说你那左边的这部分,你直接跟比如跟底层的driver直接打交道的话。
这个时候你实际上发现这个整工作量会比较大,因为你比如说你的语言里不断的变,然后当地人driver可能也会变,所以这样的话需要做各种适配,所以有了这么一个speed v的,这么一个中间的一个文件的好处。
就是,相当于实际上你相当于就它形成了一个标准,就相当于你不论是左边也好还是右边好,这样的话,你实际上都是跟中间的这么一个打交道,然后最后呢,相当于就是可以整个就可以简化你的一个呃,一个很多的一个流程啊。
然后呢这个就是完了之后呢,实际上接下来要做的,实际上就是你要去创建那个,因为你整个需要去执行那knel嘛,就是然后这个执行内ko的话,你需要描述就是你到底有哪些参数,就是所以这里边的参数的描述。
实际上它会有一个叫descriptor sets,然后当然还有一个呃,就是还有一部分,就是相当于你整个计算的一个一个排,然后呢这里边我把这个图我来简单解释一下,就是因为整个网可它实际上有两部分任务。
一部分呢是针对他整个渲染的,然后另外一部分实际上是针对这个计算的,然后针对渲染这部分,你会发现它实际上它的步骤非常多啊,就是呃像这个橙色的,这个实际上是一些固定的一些功能,然后当然还有一些那个淡黄。
这个黄色的实际上是一些可编程的一些呃stage,然后这些可变的stage呢,实际上跟这个计算实际上就很像了,就是它实际上相当于你允许你去啊,自己实现一些自定义的一些函数,那当然你看这个呃,这个图。
你发现可能会有一个容易让人形成一个误区,就是你发现这是可能反正你看着就是渲染,你看着比较复杂啊,然后呢你看那个计算的话,你可能发现就只有一块,但这里实际上会有一个误区,就是实际上你会发现这个东西啊。
其实并不,实际上并不是这样的,就是因为反而是这样,就是他为什么渲染会有这么一个长的一个流程,因为它实际上这样的一个好处,就是它很多数据它实际上是给你标准化了之后。
这样的话就是你可以以这个标准啊来准备数据,比如说你转的时候,你需要输入顶点,那这样的话顶点需要哪些数据,然后呢比如需要索引,所以顶点位置,然后呢其他的一些属性,你可以这些标准,然后进行跟这个白天打交道。
这个实际上是减,一定程度是简化了这个这个呃流程,但是呢就是访问计算的话会有一个什么问题,就是访问计算,它实际上针对的是一些通用的一些计算任务,这个时候实际上你没法预见。
就是说因为比如像钢铁啊或者流体里边,你会发现就是很多的数据结构,它其实五花八门,所以这个时候呢你就是呃就是比如这么一个,因为它其实对数据规范它其实没有约束的,所以这个时候你会发现。
就是有就是是不是能适应,就是各种各样的一个数据接口,其实这个东西是那实际上是没有定论的啊,这个东西,所以这个实际上就是其实一定程度上啊,整个实际上是对于仿真来说,实际上反而是增加了这个仿真的复杂度。
因为如果是这里边问题讲,如果你可能只仅仅是写一些简单的shader啊,就是比如说我们现在之间也是独立的,那这个没任何问题,但是呢这个时候,如果我们研发的是一个复杂的一个,物理仿真系统。
那这个不同的模块之间可能是需要去交互,那这样的话你这个数据的标准如果不统一的话,导致各种模块之间可能就没法协同,所以这个呢其实相当于这这里边,所以就后面我们实际上也会讲,就是呃怎么利用这个管线,相当于。
当然我们在这个基础上可能加入一些约束之后,然后怎么把复杂的算法能耦合起来,然后呢,这里边实际上就是整个流程其实就变成,就相当于是一部分,就是你首先你要创建就是各种buffer,buffer创建完了之后。
就是你这个时候其实你去执行之前,你需要因为你的buffer可以很多啊,而且不同的kernel因为是这样的,就不同的那个计算的pine,它依赖的buffer它实际上是不一样的。
所以这样的话实际上你具体执行的时候,你需要告诉这个你的那个pipeline,就是我需要哪些的那个buffer,然后相当于组合到一起,然后输入到这个这个pipeline里头,像这样的话。
实际上就会有一个叫descriptor set的这么一个呃,一个对象,然后这个对象其实就描述相当于,比如说我这个计算的kne,比如他第一个参数,它需要输入什么buffer。
或者是他的那个比如他的类型是什么,它的那个数据大小等等啊,就这些,然后这样的话比如说你一个完整的一个kindle,你需要n个参数,然后这个相当于形成一个this script exce。
然后这个set描述清楚之后呢,这样的话实际上整个计算的时候,它实际上就会根据这个你的这个描述,然后去读对应的这个数据,然后比如说这个时候你你这个ko,你需要比如这里n个,这样的话。
他其实会去找它对应的这个呃一个数据,然后呢真正进入到整个机啊,执行计算的这么一个过程,然后这整个计算的一个pon,其实你会发现它分为几块,就一个,当然就是这里边在整个layout,就相当于你的参数。
输入参数什么的一个描述,当然还有一个就是前面就是你写的一个shader,它实际上编程二进制之后,其实际上是一个spare v的这么一个一个code,所以这样的话实际上主要是由整个计算的。
可能实际上新手是由这两部分来来构成,所以你发现这个实际上是一个多对多的关系,就是你你比如左边你分配一堆buff,然后呢,你同时也有一堆的一堆的计算的一个papi。
那这样的话其实你可以根据你的那个pine,然后呢它的一个需求,然后呢去组合不同的那个要描述符,然后呢去执行不同的一个房间的一个计算任务,然后呢这个有了之后呢,实际上接下来是具体执行的时候。
这里这个时候实际上就需要依赖一个,就是command poor,就是相当于有个命令池的这么一个一个东西,然后这个东西呢它实际上里边最主要的是,你每一次执行。
你需要去相当于有一个command buffer这么一个对象,然后呢它里边具体的时候,你相当于你要去记录它到底啊,相当于这个时候,因为这样你有几部分来一个你的描述符,就相当于你输入法输入哪些参数。
这个需要描述清楚,然后呢你同时要把你的那个pipeline,就是我需要哪个计算和这个需要绑定进来,然后当然还有一些常量啊,然后以及就是说你这个分配的时候。
相当于比如说你dispatch到底是你的block,size到底是多少,然后分成多少这个组,这个时候你用dispatch这个呃api,然后相当于指定清楚。
这个整个就其量就构成了一个corona buffer,然后这样的话你一次执行的,就相当于就把你参数的装配,然后呢整个计算的流程,然后相当于整个都执行了,执行完成怎么这么一个过程,然后呢。
最后当然这个当然这个实际上只是准备啊,就你这command buffer,你你准备完了之后啊,就是你不去调用的话,它实际上不执行了,当然最后一步,实际上就是你有一个提交的一个过程,就是你相当于需要啊。
这就是你如果我们这里已经已经有好几个,hermes buffer人,这个时候呢你比如说你去提交哪个hermes buffer,它就会把对应的里面记录的所有的命令,实际都执行一遍。
所以这里面实际上就整个就是到这呢,实际上就完成了一个,就是前面我们看到了一个简单的这么一个数组,相加的这么一个任务的这么一个,完整的一个流程了,所以这里边我们可以看一下代码。
实际上这个非常的长,其实这个代码就是你虽然看的那个任务很简单,但是你如果去真正去看那个代码的话,这里我写了一个样例,就是如果传说了,相当于纯粹的你去调这个api的话。
就是这里边的话其实差不多呃有几百行代码吧,所以这个其实也比较费劲,就是当总统笼统讲的话,其实有几部分啊,就是你可以看一下,这是这里有个叫welcome native的这个。
因为写这个词主要是为了跟后面有个对照,就是呃,相当于就是我们如果不用任何的那个封装,或者不用任何简化的话,其实它相当于到底要包含哪几个阶段,当然这里边创建instance。
然后完了就是选择一个physical device,然后就逻辑device,然后呢当然这里边就是要分配buffer了,其实你会发现分配buffer其实也很复杂,就这里边当然实际上已经用了一些。
就是辅助的一些工具了,其实这个用这个辅助工具,实际相当相当相当于就是一定程度简化的,这个过程就是你需要分配几个buffer,然后呢当然还要从呃cpu到stin buffer。
然后再从stin buffer,然后再到那个啊gpu buffer等等这些过程,然后完了之后后面就创建那个just dating buffer,再往后的话,就你要创建那个老鼠符以及计算的一个pine。
然后再往后的话实际上就是啊就是command buffer,你要记录就是整个你需要执行的命令,然后需要把它记录下来,所以这个实际上只是一个对照,然后大家感兴趣的话就是可以去看一下。
就是如果你从头去利用api,就welcome a api去弄的话啊,这个是到底包含哪些部分,然后这样的话也可以去感受一下,这个瓦尔肯这个呃这个复杂的这个计算过程啊,然后呢我会讲就是那这个如果嗯针对一个。
就如果是仿真的任务啊,如果你都这么去搞这个,我觉得肯定是不现实的,因为这样的话,你整个因为我们知道仿真这个其实都比较复杂。
就是你要再加上整个编程又那么复杂的话,这个东西肯定是啊铁定是这个没法做的,所以后面的话我主要讲一下,就是那我们怎么来呃,降低这个一个复杂度,实际上这里边主要,其实就相当于对整个挖坑的这个底层呢。
实际上需要因为其实这里也需要结合,因为我们这里面实际上是不针对渲染啊,所以是单纯粹的只针对这个法律,计算的一个任务,然后怎么能让他针对这个特定的这个法,计算的一个任务,然后呢就相当于去简化整个呃仿真的。
就是简化整个研发的一个一个代价,所以这里主要分为几块,就一个呢就是挖坑这个对象,因为前面看这个挖坑对象其实比较多,所以这里实际上要做一定的一个分类跟封装,然后呢,相当于把有些就是可能跟。
相当于你跟你仿真算法无关的一些细节的东西,可能要隐藏起来,但还有一个就是因为实际仿真的话,其实它的涉及的这个计算的kernel它是五花八门,所以这样的话就是怎么能简化整个kernel,调用的一个方式。
那当然最后还有就是数据层面,就是我们怎么给他,因为前面也提了,就是你如果相当于你整个针对这个访问数据,你不做任何的约束的话,就会导致就是说你不同的ko之间,它的数据协同这个非常的一个困难。
所以这样的话就是我们需要针对这个呃,就是各种各样的那个仿真任务,然后呢,看看有没有可能在数据层面做一个一个,统一的一个封装,然后呢这里边我们就是我讲讲,就是说我们现在piano现在集成了。
这个有个叫catalina的这个底,它实际上就相当于是一个挖坑的一个后端,然后呢,相当于对他做的一个类似于各种的一个封装,之后的这么一个这个这是一个结构结构图啊,所以这里面主要引入了几个几个结构。
就是一个整个呢现在是这样,相当于是把呃整个挖孔底层,抽象成了一个y vk system的这么一个类,然后这个类呢实际上进一步的底下就是,当然这个类主要去管理,就比如说像你是创建instance上。
比如说你去选取这个physical device等等啊,就这些其实是相当于去处理这些功能,然后另外呢里边就是像逻辑设备以及它的那个,比如他的这个各种的q的话,实际上这里边就用一个统一的vk。
context的这个去管理,然后当然这里边还有后面最后一个,就是有个v k program,这个v program实际上是呃跟就是kda的那个kl函数,实际上是对标的,就是这样的话。
实际上就是比如说我们在ca里边写一个kernel函,就是gpu上能执行的可能函数,那对应到welcome里边,就是我们实际上等效的,我们要去写一个mickey program这样的一个kernel。
然后呢这个week program其实其它会依赖于一些数据,然后这个数据呢其实这里边呃就抽象成了三类,就是主要是啊他这里是当时用了一个父类啊,都是统一的,是抽象成vk variable。
然后呢这里边针对不同的数据,就是有三个不同的一个呃类的来表示,就是一个呢是wicked device buffer,然后这个呢,实际上比如说你去分配一块大的那个缓存的,这个用这个。
当然还有一个呢就是weekuniform,这个呢是用于那种易变的,但是数据规模比较小的这个数据,比如说你有几个参数,然后呢比如打包,然后需要传递到gpu里头。
那这样的这个时候你实际上可以用wiki uniform,但还有一个vk constant,然后这const呢就是实际上就等于针对,比如说呃我有一些比如像重力这种,你可能实际上是固定的。
这个时候你一般可能不太会变或者时间不长,那这样的话你其实你可以用v constant这个结构,然后呢传到这个vk program里头来去去执行,所以这个实际上整个相当于是该男的那个马可,后端的。
实际上就是针对这个啊welcome的各种对象的,实际上做了这么一个一个处理,然后呢,这样的话去简化它整个这个编程的一个流程了,然后接下来我们就讲一下。
就是那实际上刚才讲的就是vk program这个东西,实际上是跟呃coda的那个kernel,实际上整个是对标的,所以这样的话就是我们怎么去呃,去写一个坑等函数啊,所以像以往比还是针对前面那个。
比如说我们就是一个简单的一个向量求和的,这么一个the kneel,那这个实际上用裤带写的话,其实就两部啊,就是你比如说你首先你声明声明的话,这个时候你需要当然这个gk global有标识符啊。
这个是所有的扩大工作函数,这些都需要的,然后还有一个呢其实就相当于你要去标明,就是你这个kl函数到底需要哪些输入,比如你三个数组a b c,三个数组,然后它分别对应什么类型。
然后那里边的话实际上就是一个简单的指令呢,就是相当于a加b,然后放到c里头,然后这是代码,然后当时执行的时候就调用的时候,它其实有一个特定的一个语法,然后呢这个对标过来,然后到挖坑里头那个怎么做呢。
其实就是前面,因为前面那个直接用裸的a api去写的时候,你发现这个东西太长了,所以这样的话,实际上这里边我们就引入这个v k program,然后这个你发现跟左边那个实际上已经蛮像了。
就是他其实也包含两部分,一个呢就是你相当于有个声明,然后相当于你要声明一个函数,然后这个函数呢它需要输入哪些的形参,然后比如说你这里边一样的对应这个,比如你输入一个float的一个数组。
然后比如a b c3 个数组,然后呢这里边还有,比如说我这个时候还要告诉kernel,比如说我这个数组的长度,那这里的时间,比如我们可以用一个constant,所以你整个你发现这个形参,它实际上是用。
是用一个红红的一个定义来来定义的,然后当这个定义完了之后,也就这个时候呢,他就声明了,就比如我这个kindle,如果你想去调用这个ko的时候,你这个你就必须要输入这个参数。
四个参数就是你相当于有三个呃缓存,然后呢三个buffer,然后呢另外就是一个constant的一个数,然后当然完了之后,这个时候就需要因为整个呃挖坑的话,他的呃shader代码。
实际上跟host代码实际上是分离的,所以这个时候呢实际上还有一个要做的,就是,你相当于需要去载入你的那个a sparv的,生成的这么一个一个文件,然后这样的话,实际上就这个声明工程实际上就完成了。
然后最后到调用的时候呢,实际上这里边有一个比较快捷的一个方式,因为这前面只是一个生命的过程啊,然后你真正如果你要想去执行这个代码的时候,这个时候你相当于只有一个,当然这里有几种模式啊。
我先讲这个模式实际上就有个flash,比如这个你调用一下之后,然后当然其他的几个东西是跟左边类似的,就是你要告诉这个gpu,你需要比如说你的block size多少,比如这里边我们是写了128。
那这个实际上跟前面的那个呃,kl实际上是对应的,然后完了之后呢,就是你相当于就是要对它分组,就是比如你的总的数量是一个nb的数量,然后要分成多少个呃gloop,然后相当于这样的话,就是你要传呃。
这个他因为他despite的时候,他需要知道这个信息,然后去相当于去执行对应的命令,然后后面那几个实际上就是跟你的生命的过程,完全是一一对应的,就相当于你有几个数组,需要传递给这个执行的一个过程。
然后呢这里边其实除了就前面那个里边列的,就是像比如像有buffer啊,像有那个constant,所以这里边还有一些其他的,因为这里边其实主要是针对,比如说我们现在做的,如果是一个二维的一个高度场。
或者一个三维的欧拉网格,那这样的话实际上也需要,比如说其他的一些这个数据结构的一个支持,所以这里边实际上就是你会发现,整个从数据层面,就是它形参的层面里边就是会有一个统一,就是它当然针对底层的时间的话。
实际上是对应的,就是比如像constant,它对应的是一个vk constant的这么一个结构,然后呢就是uniform,它对应的实际上是一个vk uniform的一个形,一个结构。
当然这里边实际上就是前面几种,因为它整个还是相对来说比较简单,因为它实际上它的数据类型是比较单一的,但这里面比较麻烦的是什么呢,就是比如像那个流体里边可能会有涉及到,就是说我们的领域列表。
那这个时候呢它实际上不是一块buffer,它可能需要几块buffer组合到一起,然后来统一的去定义这个结构,然后这一块呢实际上呃,其实也可以定义这么一个红,但是呢这一块实际上就是。
因为前面讲这个现在整个猫肯它跟c加加,它实际上是不是混编的,所以呢会导致整个他这个调用的过程是这样啊,没有那么方便,所以这一块实际上我们还在进一步的尝试。
就看看有没有可能更简单的去处理这个问题啊,然后呢整个miki program,它整个运行机制的话会有两种,一种是这个啊,即使模式就是前面看到那个flash,然后它整个你如果看里边代码的话。
它其实就会分两个过程,就是首先你要创建就是整个command buffer,然后完了之后呢,你再去再去执行,就是你相当于是要提交你的那个q然后去执行,所以这个实际上这个指令包含了整个两个过程。
但是这里边直接这么做会有什么问题,就是因为这样的话,他每次都会去,相当于是把这个你的实参需要,都都是都需要重新更新一遍,然后但这个呢我们发现其实还是有开销的,所以这个对于比如说呃我们写反算法的时候。
有时候比如说我们要循环很多次,那这样的话我每次都重新往里写了,都还实际上存在大量的这个逻辑计算,所以对于这种任务呢,实际上这里边其实额外的还有一种模式,就是叫缓存模式。
那这样呢实际上你可以比如说我们这个记录呃,command buffer的时候,我们可以只记录一次,然后呢相当于真正执行的时候,相当于我们重复利用你记录的这些行参啊,就这些参数的那个数据。
然后这样的话就是可以降低整个执行的一个,一个一个代价。
就是当然这里还有一个办法,就是因为就是对于比如说仿真的任务来说,就是比如像这里是一个弹性体求解的这么一个,也可能比如它可能分为好几个kne,然后这几个ko呢要交替的去执行。
那这样的话单个v k program。
实际上是没法解决这个问题的,所以这里边实际上我们就引入了一个v k,multiprogram的这么一个结构,然后这个结构呢,实际上它可以就是呃把不同的kernel,然后呢呃将组合到一起,然后呢。
相当于把这个不同program的那个它的执行的命令,进入到同一个command buffer,然后这个时候相当于你比如写的时候,当然这个时候只需要写一次。
然后呢同时就把你各种各样的这个呃command buffer,然后就组合到一起,就比如这里边你啊调用的时候,你可能要循环十次,然后这样的话,每次你可能都需要去创建一个dispatch的,这个命令。
然后这样的话把这个整个组合到一个,command buffer之后,然后呢去统一执行,然后这个呢实际上就主要是可以解决,就是说我不也是其实跟前面一样的,就是你如果多个坑洞。
然后呢不断的需要来回切换command buffer。
然后导致它性能低下的这么一个问题,然后这里边就是那我看一下,就是如果按照这种方式让我们看一下,就是啊最后我们要去写一个。
比如说写一个前面那两个数字相加的,这么一个任务啊,我们看看最后怎么做的,其实这里边代码你可以看其实就比较少了,就是嗯主要分几块,就当这第一个是这样,你所有的这个程序进来之后。
你必须有一个就是有一个vk system,他的那个有instance,然后你必须得初始化,然后这个初始化就相当于帮你是做完了所有,就比如说你physical device的选取啊。
就是逻逻辑设备的生成等等这些过程,然后这个完了之后呢,当然后面就是主要两块啊,就是一个你要去创建那个所有的那个buffer,然后这个buffer你会发现就是跟以前呃,就是互打后端。
其实你发现这个接口是一样的,就是因为车其实也包含两个,这个是有个叫dr,然后后面是cr c r,实际上你分配在实际上是cpu上的那个那个内存,然后呢dna,就因为这里边我们用的是一个挖坑后端。
所以这个的话它实际上用的是welcome的api,直接就相当于在gpu上的会去会去创建,开辟出这么一个八分,然后这个完了之后,当然这里边就是也就是因为这里也不需要。
就是像上一个就是这里native玩native的那个,直接裸a api写的那个那么麻烦,就是这里边时间就可以直接就把数据,当然这里边实际上内部实现啊,他也是用了staging buffer。
但是这里边就相当于把各种的细节,就给你隐藏出来了,然后完了之后整个调用的话,这个就比较简单,你发现就是其实就两步,一个呢就是你声明一个kernel,然后当这里面声明的时候。
你需要去标明就是我到底需要哪些啊行参,然后呢当然这个完了之后呢,就需要把那个shader的那个啊s p a文件,就是相当于给它载进来,然后最后的话就有一个执行,然后当然这里边有一个。
这里边相当于你计算完了之后啊,你相当于可以把那个数据你在好不带输出,因为这里边实际前面初始化的话,实际上是1001234的这么一个,线性的一个初始化,所以这样这个函数你直接呃运行的话,其实他会打出。
就是02468的这么一个一个结果。
所以这样的话,整个是相当于验证了整个计算的一个呃。
正确性啊,然后当然这个你其实你可以对照的就是看呃,之前的mark native的这个程序,你会发现这两个实际上诶一边这边的话,差不多是300多万代码吧,然后到这儿的话,实际上如果你依赖。
就是利用这个can lider这个封装之后呢,实际上你可以极大的缩短,整个代码的一个一个复杂度。
当然这里边其实还有一个你会发现,就是在这个时候,我们之前就是因为主要是这个,其实这样这个程序主要是针对这次课,我专门准备的,就是呃相当于其实也是为了就是相当于看看,就到底。
如果是我们纯粹的用markepi去写一个这么一个,简单的程序,到底开销怎么样,所以这个实际上之前我去写这个东西,其实花了好多时间,而且主要是因为这样,它里面包含的那个步骤比较多,所以呢特别容易。
其实还有一个问题,其实特别容易出错,所以这样的话,你整个实际上你的调试过程,实际上也都比较困难,所以这里整个你会发现就是当c呢,其实因为是一样的,就是你可能花不了几分钟。
但是呢你整个就是host的端这部分,你要去啊准备各种的一个呃,相当于这个对应的一些流程的话,其实会非常耗时间,所以这样的话其实可以依赖,就是我们这个相对封装之后的这个,然后这样的话。
其实可以极大的把这个时间给压缩下来,然后这样的话就是你,比如说你去研发复杂的一些算法的时候,其实这个也可以,对于整个你提升这个效率还是非常有帮助的,然后当然这块讲完之后,后面其实主要就讲一下。
就是因为呃现在实际上banner里程这样的话,实际上会有两个后端,一个是那个呃coda的,还有一个rock,然后因为这里边实际上就是我们还是希望做到,就这个整个框架啊,这个跟后端是无关的,所以这样的话。
实际上我们不管比如接入什么后端,实际上比如说像刺客讲的那个蓝图,实际上就直接可以用起来,所以呢针对这个需求呢,实际上我们后来在引擎架构里边,实际上做了一定的调整。
就是主要是针对这个framework这个库,这个库因为实际上是主要定了引擎架构,所以呢这对于这个库里面的,实际上是把跟gpu相gpu相关的,所有的后端的东西实际上就摘出来了。
所以这样的话就把就是说你跟gpu相关的,比如你挖矿后端或者扩大后端的这些呢,实际上都给他放到了,就是比如像这个core里边,或者是他的那个toology里,所以这样的话就整个架构跟底层。
实际上就是彻底的就是呃解耦了,也就是说比较适合,就是那这样的话我们后面去拓展算法也好,就是我们比如说我们增加新的这个,后端的数据结构,这个就完全不影响整个引擎,引擎框架的这么一个一个调整。
然后这里边呢具体怎么做呢,其实主要是两块,一个呢是呃我们相当于这个整个gpu的后端,实际上要跟计算的那个后端,实际上接口要啊要统一起来,因为这个要相当于跟那个框架要能对接的话,因为框架其实现在是这样。
它识别的是呃field field,当然这里面包含很多类了,就是比如像那个变量啊,数组啊等等,但它这里边实际上它其实并不关注,就说你这个数据你是用扩大分配的数据,还是用market api分配的数据。
所以这样的话,实际上这里边就是左边那个,实际上就相当于是会跟这个具体的gpu,后端其实是相关的,所以呢这里边中间实际上我们实现了一个思路,就相当于在这个你后端跟引擎框架之间的,实际上就引入了一个中间层。
就是利用中间层去屏蔽掉底层的这个细节,比如这里举一个例子的话,实际上就是比如像这个针对这个数组的这个,array的这么一个结构,那这个结构相当于其实到引擎的这个架构,这一段的话。
实际上它有一个fa的这么一个field,然后但是那个这到底层的话,其实他会有各种的,比如说像呃coda的那个内存分显存分配啊,然后mark的那个buffer的开闭等等,这些细节的话。
实际上都隐藏在这个啊底层,所以然后相当于对于它实际上通过这个varray,数据结构呢,实际上统一的利用统一的接口,然后暴露给这个引擎,所以这样的话其实就完全可以避免啊。
就是比如说我这个新进来一个后端之后啊,然后呢需要不断的去调整,这个引擎架构的这么一个问题,然后当然这是计算的这一块,然后呢除了这一块呢,其实还有一个要解决,就是因为呃引擎那个其实有几个任务。
当然一个是计算一个,但还有一个是渲染相关的,所以这一块呢,实际上也是跟前面的思路是类似的,就是我们相当于,比如说我们现在实际上主要有一个,就是javengine的这么一个一个渲染引擎。
然后这个引擎呢它也不是直接的跟walking backend,以及或者是put on那个bend直接打交道,而是利用一个gpu 8分这么一个中间的一个结构,然后呢去屏蔽掉底层的。
就是相当于跟硬件相关的一些api的一些信息,所以这样的话直接就是也可以比较方便的,去各种去拓展,比如说你去拓展底层,或者你去拓展,比如说我这个时候,我现在可可能会有一个新的这个这样引擎。
比如我现在想用vt k,或者想用ava去去做的话,这个时候呢实际上也是一样的,就是我们可以统一的用这个gpu buffer,然后去打交道,所以这里边就是其实现在这样,另外两个其实也有一些尝试。
就比如我们前面讲,刚刚讲,就是我们如果是现在不想用罗文件来做渲染的,我们比如说我们继承一个,比如用v t k我们是不是可以做,或者说直接用那个挖坑来做,也是不是也可以,当然更极端的。
就比如我们现在整个访问计算,整个访问计算的话,可能就还是利用原先的这个api,然后呢我们现在比如说我们想用unreal去,诶不好意思啊,整个用用成略去相当于去做渲染,那这样的话实际上就是比较方便的。
可以用来做各种各样的那个一个拓展啊。
然后到最后的话,这里我呃分享一下,就其他的一些问题,就是呃就是瓦肯,其实这样就是按照从我们目前的一个感受来讲,其实他还是能做很多各种各样的复杂的,一些法律任务,但是呢其实他主要其实他还是前面提的问题。
就是他其实在研发反而上涨的时候,他整个相对来说会比较复杂,就是呃其实主要是研发成本比较高,所以这样的话其实这里边就需要注意一些问题,就是如果真正你利用就完分期的话,一个其实这个最严重的一个问题。
就是它整个对齐的问题,因为像ka的话,其实整个它编译器里边应该是默认的给你解决,这个对齐问题了,但是呢就是你如果是用挖on去写的话,它这个东西,你实际上需要需要研发人员自己去解决,这个对齐问题。
这个什么意思呢,就是比如说你这里创建了一个结构,然后呢就是前面那几个结构啊,就是他其实就是呃都比如都是16字节对齐的,然后这个时候你如果比如说你后面有两个,你定义了两个,结果,他这两个其实都是四字节啊。
然后这个时候啊,当然还有一个比如后面有个类型的,他其实也是四字节,但是呢这个时候其实如果你后面那个拍定,因为这个后面拍的那个零嘛,其实主要是用来呃,主要是为了对齐用的。
就如果你这里不相当于不加这个东西呢,就会导致就是说你如果是从cpu里边,你拷贝一份数据过去之后,就因为你后面因为在gpu端其实是这样,它默认的实际上就是16字节对齐,所以这里边实际上你是16字节。
16字节,16字节,然后到这里边其实也是16字节,然后在cpu端其实不是cpu端的话,它其实是一个紧致排列的,就会也就是这个什么什么意思,就是你相当于这个pd,如果你不填的话。
这个就会导致你一个position 0,直接就会跟到这个c type后头,这个时候你直接考到gpu的话,这个会导致整个呃各种数据是这样的出错的,所以你实际上需要去显示的去处理这些比较呃。
这个是比较麻烦的一些问题,然后还有一个问题,其实就是因为呃其实这样挖坑,因为它整个不支持混编嘛,所以这样的话他其实呃你在cpu端跟gpu端的话,实际上是两两套代码,就是比如说我这里有个触点。
它其实就是我们之前做钢筋动力学的时候,其实这两个东西它实际上是完全,其实内容是一样的,但是呢因为它声明在不同的一个地方,所以这样的话,实际上我们需要去定义两个这样的一个结构。
然后导致就是如果我们比如说我们后期,比如说因为呃一些新的需求啊,如果因为一些新的需求的话,啊我看直播间里有问那个是不是扬了吧,对主要是那个呃上周末开始,然后不知道那个因为家里边好像都有症状了。
也不知道是不是痒了,就是所以今天嗓子有点有点不太舒服,所以这样的话其实会后面会有一个什么问题,就是,就是如果比如说你这个我们这个代码呢更新了,然后比如说我们后端里边,有可能要增加了一个数据结构。
这个时候其实你对应的你要在呃device device端,相当于也是一样的,你需要去加这样的一个结构,这个时候其实会导致很多时候,你如果是相互依赖比较多的话,这个时候很容易出错,所以呢咳咳咳咳咳。
所以这个实际上就是对于就这种啊,不是不支持混合编译的这种api,其实对于呃去研发这个大型的这个一些呃,复杂的系统的话,时间还是不太适用了,所以我目前的感受啊,我觉得瓦肯其实主要还适合。
比如说我们个别的shader呃,或者个别的计算步骤,然后我们相当于对他去做做加速,加速的时候其实比较有用。
那当然还有其他的一些问题啊,这个我说一下,这是,也是因为其实本质就是挖坑,这个它比如说它不支持c加加,然后呢还有就是其实还有一个比较特殊的,就是他因为现在不支持flow的原子操作啊。
这个呢其实对于整个仿真的影响会非常的大,就是仿真,因为比如像做钢铁碰碰撞也好,或者就是做其他的一些流体啊,比如说欧拉流体这个操作非常的关键,就是因为很多时候我们是这样,因为如果没有这个操作的时候。
这个时候我们一种替代办法是,我们可以对它进行排序,用排序其实也可以解决这个问题,但是呢会导致你整个研发的成本非常的高,当然还有就是其他的像比如说高级的,像一些模板啊,模板就是不支持啊。
会导致就是你很多代码,你可能得呃重复的去写很多遍,然后这样的话整个维护起来也比较费劲啊,然后另外就是呃其实瓦肯还有一个比较呃,就是比较棘手的一个问题,实际上就是因为不同厂商。
对于walking的那个特性,它其实支持的啊五花八门,就是千差万别啊,就是所以呢就有可能导致,其实虽然说那个瓦肯的初衷很美好,就是他实际上为了解决卡平台,但是呢如果你不同不同的那个芯片。
或者不同的那个厂商的支持的那个标准,他如果有差异的话,也就是这个时候,你虽然你是用一个写了一份代码,然后这个时候你去跨平台,比如说你从pc端直接移到移动端的话,这个时候其实并没有那么容易。
就是很多时候你还是要针对这个不同的平台,然后去做适配,做去做优化,那当然最后最后我想说的,其实就是你整个性能跟灭绝,性能发现还是呃比较难兼顾的,因为mark整个它其实更偏底层。
所以它性能其实还是比较的比较的高,但是呢整个它呃写起来的话,我觉得还是比较比较麻烦,所以这样的话实际上就是就具体用的时候,我觉得还是需要考虑这个,就是看你需要快速的去呃创建一个仿真算法。
然后看你这也就是你看你是那个效率优先,还是说你是你是性能优先,其实你需要去考虑这些问题啊,然后当然这里边其实前面前期的话,其实也有一些尝试,就是因为整个因为挖坑其实会更偏底层。
所以这样的话实际上我们之前在呃,跟比如说跟kda的thrust做对比的时候,其实发现就是整个是这样,就是它在不同的规模下面,其实它的整个性能你会发现其实不太一样了,就是呃我们之前的测试是这样。
当然这个其实也跟我们整个就是,因为实际上是这样的,整个你创建呃,就是pipeline也好,或者你是去更新他的那个描述符,这个实际上都是有开销的,所以这个时候你会发现。
如果你的整个计算规模是比较小的时候啊,比如说我们这十的-3,十的-4等等这个量级的时候,你会发现整个挖坑它虽然是更偏硬件底层,但是它整个计算的效率,实际上实际上是不如这个苦打的,然后当然只有当它。
比如说它是它的规模达到一定程度以上之后啊,就你会发现它整个挖坑,因为它更偏底层的那个特性,就是也就是它整个那个计算密集度上去之后,这样的话才能保证,就是整个挖坑,实际上是要比扩大的那个效率更高。
所以这个我们之前比如像那个reduction,或者是这个skin等等啊,就这各种算法,但还有排序啊,其实基本也都是这个结论,当然排序的话相对来说好一点,因为这个其实也会跟那个算法其实是有关系的。
所以总的来说其实当然我们从嗯这个对比来看,总的来说实际上是mark,应该它的性能上来说应该是比coda要更优,但是呢其实前面也提到了,就是他整个呃算法的一个复杂度,就是你去写一个算法,复杂度其实要更高。
所以这个所有熟练的话,实际上真正到具体常用的时候。
还要需要去权衡,就是你到底是用什么去开发。
然后然后另外一个就是我演示一下,就是因为这里实际上搭了一个,简单的一个样例啊,就是主要也是为了去展示,就是呃相当于比如说一个呢是呃,我们渲染跟仿真之间一个要协同,第二个呢就是怎么跟这个之前讲了。
这个蓝图系统,看看能不能对上,所以这里实际上写了一个简单的一个样例,就是这里有一个叫s t h的那个呃一个目录。
然后下面你打开的话就是这样的话,直接就可以去跑这个样例,然后这个因为纯粹是为了展示用的,所以里边其实有呃,里边现在还缺不少东西,就是因为现在仅仅是一个一个发射器。
然后对于这个场景的话,就是这样的话,实际上跟之前用ka写的实际上是一样的,就是你可以看到就是它包含啊一个发射器,然后呢后面有个流体修改器,当然这里的流水求解器,我现在只只写了一个积分的一个一个模块。
然后其他的模块现在没加,所以当然这里面你如果直接运行起来之后哦,我发现可能又跟那个啥一样了,就是我发现开着直播的话,我这个程序好像就跑不了,就很奇怪啊,我再试一下啊,好可以了对。
所以这样的话就是你可以看到,就是从发射器里边,然后生成粒子,然后当然这个经过这个求解,去进行一定的处理之后,然后这样的话就可以看到这个场景,所以这个场景实际上简单验证了,就整个就是从当然从后端的对接。
然后呢以及到跟蓝图整个引擎蓝图的对接,这个流程整个是验验证通的,但是呢就当这里边其实功能性还不多啊,就当这里边其实你可以看上半拖把的话,实际上也只只加了,就是一个发射器跟一个求解器。
当然这里边其实也有具备一些呃,其他一些能力,就是比如说我现在再创建一个发射器,当然这些实际上是没问题的,所以你发现就整个这样的话,其实一个好处,就是你实际上是整个引擎跟底层的后端,实际上是完全是解耦的。
这样的话就是你可以各种的后端,你对所以这样的话你比如重置之后,然后你这样你可以呃有两个发射器,然后去生成一个这个粒子,所以就这个时候你可以就是比较方便的去拓展,到。
就是说我们在不改动引擎架构的那个前提下。
然后去拓展各种多后端,当然这里面还有一些其他的一些呃场景啊,我说一下,就当然这个也主要是为了辅助,如果大家有兴趣啊,想去呃基瓦肯去写一些算法的话,就是因为这里边其实是需要依赖,一些渲染的模块。
比如像这里有就点。
比如点线面的这些比较基本的。
当然这个实际上整个也是用的是walking的,那个后端,然后这个比如说点点的点了一个渲染。
但是后面还有啊面的以及这个线框的。
这个我就我就不一一演示了。
哦当然这里我得讲一下,就是因为这里边时间挖孔,后端的话大家得记得,就是这里边必须得选瓦尔肯的这个后端,它才能编译生成。
不然的话这个东西生成的还是扩大的,就是扩大的话,你看不到这些挖坑后端的这个样例。
然后呢其他的还有一些呃样例。
这个呢是这样,因为这个是之前因为这些项目,就这些案例我没有开源出去啊,这个其实也是之前啊为了验证,就是说我们比如说我们用马肯去呃,去做仿真任务,到底能能出能做到什么程度,所以呢之前其实也尝试了。
比如像缸体啊,然后呢泉水波啊,但还有弹性体等等,这个时间我们也都尝试了,就至少反正从目前的角度来讲,应该是很多法律任务都能做,只是说这个呃,相当于只是说看到底有多少代价去去完成。
这样的一个仿真的一个任务。
当然最后的话其实有一些,其他额外的一些那个材料,大家有兴趣的话,其实跟mark相关的可以去看一下,但这里之后我再做个广告,就是呃因为我估计快也快到那个保研季了,所以这样就是如果大家对这个。
反正这个方向感兴趣的,就是然后呢今年也要保研了,当然这个长期有效,就是你后面如果呃比如明年看到了,其实你比如说想做这个方向的啊,也可以联系我,这样的话其实就是呃也可以继续,比如到研究生阶段。
我们继续来做这个方向,然后呢因为整个名额还是有限,所以呢就是呃真正感兴趣的人,其实还是希望就是能尽快的联系,那这样的话就是呃我觉得就前期的话,因为很多时候更呃相当于就是更保险一些。
因为到后面的话都时候就不太确定了,所以这里是做一个简单的一个广告,然后呃其他的看看大家有什么问题,然后我们可以讨论一下,那当然后面的话其实就是呃,再往后应该是蔡老师,然后继续讲。
就是从工程工业法人的角度,就工程法人角度来讲,就是一些法律相关的一些内容吧,然后我就报段话要讲的,基本就是到这就应该就结束了,今天因为讲的可能其实这样的,今天讲的其实不太适合初学者。
就是嗯很多东西其实可能是需要等,你就整个比如说仿真也好,或者是并行计算也好,有一定了解之后,然后其实才可能能意识到,这里的那到底是是真正需要解决哪些问题,所以就是还是还是一样,就是一开始我说的就是。
你如果是一个入门的一个同学的话,其实你不呃其实你不需要来看这个,就这一期你可以不看的,就直接用扩大入门,然后当然后面的呃这些你可以作为扩展内容,然后去了解,然后大家可以看看,比如说其他的除了扩大之外啊。
当然你可以去了解到底其他的还有哪些api,然后可以来做这个跟仿真相关的一些内容,行,那要差不多的话,那我们今天就到这儿,然后反正后面有那个什么问题的话,大家有问题也可以联系我,邮箱好。