yukamu 发表于 2022-10-20 13:33

GAMES103 作业1

课程网站 GAMES103:基于物理的计算机动画入门 - 计算机图形学与混合现实在线平台
课程资料(包含作业答案)GitHub - indevn/GAMES103: notes and related materials for GAMES103(里面也有讨论群)
我自己写的笔记 GAMES103总结 - 郑kcr的文章 - 知乎 https://zhuanlan.zhihu.com/p/546551742


[*]Unity配合Visual studio 使用
b1gm0use:GAMES103 作业问题整理-开发环境配置

[*]还参考了这个大佬的视频
Games103-作业1-刚体模拟个人实现思路讲解_哔哩哔哩_bilibili
Monobehavior类

https://docs.unity3d.com/cn/2020.3/Manual/class-MonoBehaviour.html


兔子的类继承自这个类,有以下变量


v和w是刚体的速度和角速度。
I_ref是在原点无转动时的inertia
mass是每个顶点的质量。
linea_decay和angular_decay : 这个会在每一帧乘到速度或者加速度上,为了让物体可以不会无限的运动。
restituion ????
Start函数

在Start函数里初始化了转动惯量 Moment of Intertia
这个脚本是在Bunny这个模型的default mesh下面的。首先用这些函数得到mesh的所有顶点。


初始化转动惯量




Update函数

每一帧都会跑一下,核心是这个函数。


如果按r,就会回到原始位置。
如果按l,就会发射兔子。给它一个初始的速度v。
更新位置

使用leapfrog方法


速度是0.5的点,位置是整数点。这样是o(\delta t ^3)的误差。


其实这里什么都没干,相当于是我们初始给了一个速度,我们把这个速度理解成+0.5时刻的速度,然后位置理解成0.0时刻的位置。这样就行了。
x是质心的位置,移动后的位置只需要赋值给transform这个内置变量就可以了。
更新速度

定义一个重力加速度



然后更新速度和角速度


Collision detection

每个质点检查一下是否在平面内部就好

Collision handling

有两种方法,第一种是Penalty based method。这是物理的方法,给质点一个力,由于是刚体,所以这个力就直接换算成作用在物体上就行了。可以使用Quadratic或者log barrier作为进入物体的能量penalty。
第二种是Implus based method。这个方法是非物理的方法,或者说不那么物理,区别于真正的非物理shape matching。其实就是给定进入的速度,返回一个反方向的速度,根据摩擦力之类的限制给出返回的速度大小。


但是由于是刚体,作用在单个质点上的冲量需要换算成作用在物体上的力,然后得到我们对于物体的速度和朝向角度的更新。
这个换算处理并不trivial。这里的做法是,物体的速度变化是固定的,位置仍然是原来的位置。考虑刚体在r_i处受到怎样的冲量才能造成单个质点的速度变化。下面就进行了严格计算




所以第i个质点受到某个速度变化,可以换算成作用在刚体的r_i处的冲量j。再根据这个j来更新刚体的速度和角速度就可以了。
上面的计算过程我完全可以理解,就是说刚体在r_i处的冲量j,也能够造成第i个质点产生完全相同的速度变化。其实没太想明白,i的速度变化为什么不直接换算成作用在r_i处的冲量j , 质量用m_i,然后再计算刚体的速度和角速度?不过也不是很关键,我觉得两个处理都是合理的。只不过后面的显然取决于m_i,但是前者与m_i无关。
Tricky的地方



这里有一个很tricky的地方。看compute the impluse j那个地方。这里r_i是在模型的local coordinate中相对于远点的偏移。所以需要乘上R得到真实space中的r_i。(但是由于没加x,所以并不是质点在真实世界的位置)这里I^{-1}其实是写错了,由于物体发生了旋转,而且我们用的是旋转过后的r_i,所以这里的转动惯量也应该是使用旋转过后的转动惯量。
Shape matching 原理



发生碰撞以后,所有质点自由移动。只需要考虑单质点受到力(penalty method)或者impluse method。然后在下一帧之前,在强制要求物体是刚体。相当于拟合一个最好的刚体位置。
SVD可以进行Polar decomposition。


前面是pure rotation,后面是一个原地的旋转配合scaling。然后求解一个二阶优化问题。这个优化问题结果是质心translation c和转动R。可以先求解不是转动的一般矩阵优化问题,再对矩阵进行polar decomposition得到结果。






Shape matcing 代码解读

对于Shape matching这里保存了所有顶点的坐标,比之前占得内存多很多,我感觉只是为了方便写而已。


V是所有质点的速度,X是world coordinate中质点的位置,Q是local coordinate中质点的位置。在整个模拟过程中Q的位置不会变。


这里把Q的坐标平均值normalize到1。(不太理解为啥要这一步,可能只是这个代码local coordinate的定义方法而已)计算了QQ^t,用来之后计算Shape matching里的新位置。


这个函数用来给定shape matching力计算出的c和R,更新新的位置x和速度v。
注意Rotation是作用在Q上的,所以Q是我们的local coordinate,在模拟过程中由于是刚体这个坐标不会变。
然后根据R和c算出每个顶点的世界坐标x。
新的速度速度根据新坐标x和X的差除以dt来计算。

核心是这个Update函数


在每一帧开始的时候,给速度乘上一个小的衰减系数。然后考虑了重力。并且Update位置。
Projection函数其实是处理Collision
然后根据更新后的位置计算出新的刚体位置和转动




最后更新位置和速度


Get_Roatation矩阵用来计算对这个矩阵进行Polar decomposition,得到转动矩阵。懒得看是咋做的了,大概就是SVD分解。

核心部分就是Collision detection和Handling的部分


大概就是这样,检测和地面进行碰撞,然后使用和上面一样的impulse based method来处理。如果当前位置在地面内,强制设置为地面外。
结果保存成视频gif和asset

保存asset很方便
导出资源包 - Unity 手册
保存视频和gif可以使用插件
大智:Unity编辑器录屏神器:Unity Recorder实战笔记
Unity官方录屏插件Unity Recorder的简单使用
搜索recorder添加package

把视频添加到github readme

How to embed a video into GitHub README.md?
例子
https://github.com/alelievr/Mixture/blob/0.4.0/README.md
页: [1]
查看完整版本: GAMES103 作业1