YTB 官方MasterClass视频地址
0.简单概述
最基础流程结构:
tip:遇到解算报OpenGL问题 算一下就崩溃 》》》》》》解决办法更新显卡驱动
(第一帧预解算很慢属于正常现象)
一. 理论知识
1.和我们之前学过的解算器相比:
1. MPM很接近flip

2.MPM And FLIP vs PBD

3.MPM vs FEM

支持固体:
弹性和塑性变形
断裂比四面体看起来更加的有机
2.什么是它的多物理支持呢

1. 点之间的约束
支持 固体,颗粒,流体,粘性材质

2.材质
雪/土壤
果冻/橡胶(弹性)
不可压缩液体
》》水
粘性
》》蜂蜜/泥
沙子
》》干沙/湿沙
3.高效处理

4.变形梯度
局部变形的3*3矩阵
我们只需要关注Fe
优点:
捕获旋转,缩放和拉伸
如果只需要方向可以压缩成siyuans
缺点:缓存很重(9浮点)


5.子步骤
- 非常适合精确的碰撞和摩擦
- 速度,刚度和分辨率驱动子步骤
- CFL和材料条件
- 动态子步骤计数
- 最小/最大硬限制



6.OPENGL 加速GPU
- 同时可以在cpu gpu 上运行
- 内存被限制在gpu上

二. 一些有意思的参数
1.sticky


2个 值可以超出1
CFL Condition && Material Condition
CFL Condition 越小 》》允许更少的行进 》》增加Mpm的子步骤
Material Condition 越小 》》 更加关注材料(eg 材料的刚性如何) 》》增加Mpm的子步骤
Substeps min\max 限制subcount 的最大最小值

属性输出:

** jP和jE,变形梯度的塑性与弹性 **
三. 实际实例并查看其它属性
1.雪山
1.摩擦设置
因为现在mpm无法做不同摩擦(指属性区分)
所以现在的办法是分开做:
eg:
山体(主体)小摩擦,雪可以在上面滑动

这些区域摩擦大一些

这个70的数值默认是1.4——因为我们想大块的雪落下而不是细碎的小块
0.2这个数值怎么理解——这个参数使材料爆炸多或者少 eg:你想做一个雪球砸墙被炸开一样 大概需要数值*.34-.4* ,如果你不想让它自行奔溃不产生很大的力量可以 <=.2
2.设置E刚度和pin

第二端口:靠近这里的不希望有太多动态(模拟那种裂开的感觉)

float noise = abs(snoise(@P*0.05+ snoise(@P*0.05, 5, 0.5, 1), 5, 0.5, 1));
@Cd = noise;
@v=abs(float(snoise((@P + {14,52,95}) * 0.025, 5, 0.5, 1))) * {0,-15,0} *3;
float dist = xyzdist(1, @P);
if(dist < 0.5)
i@pintoanimation = 1;
3.输出缓存:
删除区域外

没有缓存速度
后期给的速度
4.包mesh
1.vdb处理


2.优化速度场vdb


5.volume化雪
1.粒子density化

2.用mesh去clamp density ( 去除边上那些模糊的


6.补充细节的雪(额外加(发射)一层雪)
1.发射源:
// get ptnum from id
int pt = idtopoint(1, @id);
// compute velocity
@v = (@P - vector(point(1, "P", pt))) / @TimeInc;
// compute delta Jp
f@dJp = @Jp - point(1, "Jp", pt);
// prune based on dJp
if(@dJp < 0.01)
removepoint(0, @ptnum);
// prune based on speed
if(length(@v) < 10)
removepoint(0, @ptnum);
// prune based on distance to surface
float dist = 0.15;
float sdf = volumesample(2, "surface", @P);
if( sdf < -dist || sdf > dist)
removepoint(0, @ptnum);
视频 54:56 jp 为 1 表示 那些mpm算出来的粒子没有在变形,没有压缩,没有拉伸
1.也就表示这个值大的话我们肯定需要在发射点出来,如果前后2帧数没变化也就表示他快静止了也不是我们需要的
2.我们也不需要卡在碰撞里面的那些粒子发射


更具djp进行一些修剪
// prune low dJp
if(@dJp < 0.25 || isnan(@dJp))
removepoint(0, @ptnum);
// remap dJp
@dJp = fit(@dJp, 0, 10, 0, 1);
// compute speed
@speed = length(@v);
isnan 1
// spread across vel
vector displace = @v * float(@TimeInc * rand((@ptnum%1856)*25.96));
@P += displace;
// adjust pscale
@pscale *= ch("pscalemult");
创建一个连续发射源(黄色)(蓝色为不太好,不加的情况

进入pop解算
2.汽车轮胎过弯
ps:只记录些容易疏忽的(具体内容可以看工程)
1.输出属性f

这里输出了属性F——目的为碎块做旋转用
输出前做了转换 p@orient = quaternion(3@F);
2.包液体mesh的时候可以输出个density做漫反射用

3.处理碎块的运动
@pscale *= fit01(pow(rand(@id % 7485), 2), 1.0, 1.5) * 2;
i@index = floor(rand(float(@id % 4152)) * 27.0);
matrix3 rot = qconvert(@orient);
rotate(rot, fit01(rand(@id%7745), -3.14, 3.14), normalize(fit01(vector(rand(@id % 6651)), -1, 1)));
rotate(rot, fit01(rand(@id%9531), -3.14, 3.14), normalize(fit01(vector(rand(@id % 1232)), -1, 1)));
@orient = quaternion(rot);
4.实例化我们只需要在渲染里处理就可以

3.飞船砸落
1.为了避免在飞机顶端堆积
ani上加个了个抖动

2.优化
我们不希望打叉的粒子存在(影响渲染时间)——离表面太远or在内部

float dx = primintrinsic(1, "voxelsize", 0);
float sdf = volumesample(1, 0, @P);
float maxdist = dx * 0.35 * 2;
// detect outside of surface
if(inpointgroup(2, "tokill", @ptnum) || sdf > maxdist)
{
@group_tokill = 1;
return;
}
// detect on the edge
if(inpointgroup(2, "edge", @ptnum))
{
@group_edge = 1;
}
else
{
if(abs(sdf) < maxdist)
@group_edge = 1;
}


4.水果爆炸
skin

雪的2倍 意味着材质更加的wiggly摆动 更具有弹性elastically
volume preservation 参数(nu)
0.4 ——类似果冻 有体积压缩 eg:两边施加力的话上下凹凸

0.2 时候
0.4时候
更多的爆炸
加点旋转
uv问题
如果直接transf uv有问题
这里可以通过区域去transfer

找到分开的区域 独自transfer uv
四. 一些细节
1.不可压缩性

这2个不可压缩性 ,看似是实现同样的效果
1.是线性反应体积变化
2.是会用一种力做出反应 (如果体积变化非常非常小,这个参数反应非常激烈)
所以如果你不想要高子步骤,去达到非常高的效果 。你可以吧这个值限制在较低 eg:1 , 1可能会加快解算但是相应的上面的值你得打高来保持不可压缩
2.粒子级碰撞
防止漏

3.加大global sub 防止发射液体时候断层

4.引用体积速度


5.pin 粒子
- 选择粒子 i@pintoanimation = 1;
- 启用source里的pin
动态pin勾选后面的
6.只对指定的面进行碰撞


1.
s@boundtype = "opened";
if(@primnum == 3)
s@boundtype = "closed";
2.
7.如何加快模拟呢
1.比如模拟一个刚性的球
正常可能需要766个子部骤 你可以限制最大的 比如到 300 (不影响最后结果
但是太低的值会影响解算结果

8.雪塌缩抖动问题

1.可以降低这些值
2.也是noise E让他不那么均匀
9.快速移动的物体
需要打高这个值

10.如果你要实时改变E

需要吧这个去掉 (假设材料属性不变)
11.关于沙子

这个值 越小-沙子越平 越大- 沙子堆积越多
cohesion 干湿沙子 越大越湿
注脚的解释
Checks whether a value is not a number. 检查值是否不是数字。
int isnan(float x)
Returns 1 if the given value is not a number.
如果给定值不是数字,则返回 1。
Returns 0 if it is a normal number or infinite.
如果它是正常数字或无限大,则返回 0。 ↩︎
1122

被折叠的 条评论
为什么被折叠?



