一.procedural melting程序化熔化

1.创建volume

1.使用[ isooffset ]转化为volume

2.使用[ volumeresie ]调整volume边界

image-20251124151144367

使用[ bound ]节点,[ getbbox_size() ],[ geobbox_center() ]函数获取边界和中心位置信息.

image-20251124151415680

3.使用[ volume ]创建volume,查看范围

image-20251124151742828

2.solver

image-20251124151832059

1.使用 @ix,@iy,@iz获取volume每个体素对应的索引 index

2.使用[ volumeindex() ]检索对应index的体素值

这里获取每个体素y+1,即上面一个体素的值,如果上面的体素值更大则取代当前体素的值

image-20251124160848476

实现volume向下流动的效果

3.添加并上 当噪波小于阈值的条件。噪波使用vector4作为输入(位置加上时间@Frame)

image-20251124213939390

4.设置地面

当@iy,即y方向索引小于floor值时

获取@ix+1,对应索引的体素位置,计算其到当前体素位置的距离,以此作为半径

设置分辨率,则循环对应的次数,使用每次的角度结合三角函数得到新的位置。

再转换为对应的索引,并检索其值,比较其值,当前值小于则设置为新的值。

image-20251124223826442

二.程序化细胞分裂

1.创建点,设置属性基础“life”

2.slover 段1 每个点的扩散

1.搜索每个点的所有范围内的近点(依据最大搜索距离“maxDist”)

2.遍历近点,获取周围的所有近点(==去掉本身==)的位置,计算其指向当前点的==方向向量“dir”==,计算其到当前点的距离==“dist”==,将距离映射1-0(距离越远影响越小)作为影响因子“mult”,使方向乘以影响因子“mult”,再将其==累加存储到“val”==。

image-20251126213228236

3.设置“count”计数有多少个近点,以此除以“vel”(加权操作)。

4.设置vel乘以“speed”,控制点扩散速度

5.更新每个点位置。

此段即计算每个点被周围近点排斥,直到当前点位置移动到超出“maxdist”,即超出最大搜索范围,此时由于周围无近点,则“vel”为0

3.solver 段2 增加新的点(分裂点)

1.设置条件:

image-20251126215555155

1.当前点的生命值"life"(每个点初始设置为0)大于随机生命值"rdlife"(由@P,@ptnum, @Frame共同产生) .再将其映射到设定的"min/maxlife"区间,使得每个点在给定区间内发生分裂.

2.点数小于设定值"maxPt"(点数过多则不再发生分裂).

3.最小距离(即最近的近点距离)大于最大距离(即搜索距离)的0.5. 即设置在搜索距离的一半以内没有近点(避免过于拥挤).

最小距离"minDist"在近点循环中求出.使用比较法
image-20251126215957352

2.计算分裂新点的位置

image-20251126222000813

1.分裂点的方向以"vel"向量为基础,即向着远离当前点的所有近点的方向(向团体以外扩张).

2.使用[ rand_sphere_uniform() ]获取随机方向的向量(设置乘以0.25,即占四分之一的权重)加到偏移量"offset"中.

3.再设置偏移量为搜索距离"maxDist"的0.01.

3.设置新点,设置新点"life"为0,分裂之后设置当前点"life"为0(重新计时).

4.再设置"life"自加.更新生命值.

image-20251126222026176

4.可视化

1.将点转化为VDB,设置point radius(细胞半径) 一般小于最大搜索距离,设置voxel size要小于半径

image-20251126223336880

2.平滑之后转换为polygon.

3.对于内部的点同样其半径要小于细胞半径

image-20251126223732286

5.效果

三. 反应扩散 reaction diffusion

关于拉普拉斯算子:是==二阶微分算子==,为梯度(直接作用于标量场,得到的梯度是矢量场)的散度(点乘矢量场,得到的散度是标量场)

拉普拉斯算子表示的是 ==与周围平均值的差距==.

image-20251127131509318

1.反应扩散原理

模拟两种虚拟的化学物质

image-20251127152244212

image-20251127153347107

image-20251127163251747 image-20251127154044828

条件与公式解释:

1.原本具有一定浓度的A,B物质.

2.==扩散"diffusion"== A,B都会扩散,A扩散的更快.

扩散部分:扩散速率乘以浓度的二阶微分(拉普拉斯算子,得到浓度与周围浓度平均值的差,即浓度的梯度的散度).当周围的浓度更高时(其得到的散度大于0),则扩散的慢(由高浓度流向低浓度),当前位置浓度增加.
这里"源"与"汇"与散度的定义相反,是因为浓度的梯度是由低浓度指向高浓度.那么散度上,低浓度位置则是一个"源"(大于0).扩散反应中则作为"汇",周围的浓度流入,该点浓度增加.
以其梯度的散度理解时:浓度的梯度由低浓度指向高浓度,其散度在低浓度则为"源"(向外),大于0.
所以拉普拉斯算子衡量了当前位置与周围环境的平均浓度差异.当其 > 0时,表示当前点低于周围平均浓度.周围物质则向该点流入
image-20251127162424777

3. A以给定的==送料"Feed"==速率f,增加浓度; B以给定的==杀死"Kill"==速率,减小浓度.

给定速率f/k与浓度成比例

4.==反应"reaction"==,两个B将一个A转化为B(以A为食物繁殖).

==反应速率 与 反应物浓度的乘积 成正比==
image-20251127163854694
质量作用定理
image-20251127164100315

2.VEX

1.初始条件设置.

设置初始的A,B浓度,f和k值.

image-20251127165046868

2.按距离与总距离之比计算 周围点的权重.

保存属性.

image-20251127170023144

3.solver 段1:

获取属性

image-20251127171033400

4.计算"reaction"反应项,计算"diffusion"扩散项.

这里的扩散项:使用周围点浓度与距离权重的乘积(注意减去该点的自身的浓度).

image-20251127171712434

5.计算最终浓度值,保存属性

image-20251127173951451

6.可视化,设置颜色

image-20251127174028470

3.结果

三.导弹追踪(boids系统)

1.使用噪波生成随机的连续路径

1.这里设置seed值每次循环增加一个较小的值,使其产生的噪波连续,再新的位置添加点

image-20251201101915754

2.使用[ add ]连成为曲线,使用[ orientationalonecurve ]获取"up"和tangent值"N"

image-20251201102115214

2.使目标物体沿曲线移动.这里使用[ primuv() ]函数

1.使用[ primuv() ]函数获取对应uv位置的属性的插值

image-20251201190229037

2.再设置新的点,设置新点的属性.

3.运行在prim,转换为curve之后,只有一个prim

4.为发射器设置朝向

image-20251201190657290

image-20251201190708166

2.solver

这里使用23位置输入的原因在于,只保留在solver中生成的点作为输出

image-20251201190813123

image-20251201191002314

1.设置rocket 位置更新规则

运行在“rocket”组,此时组还未建立,在后面创建组“rocket”,这里的先后顺序并无影响,由于设置的每5帧产生一个rocket,所以group将在第5帧产生。此时再更新rocket的速度

image-20251201191531429

初始情况:可以只设置rocket点的方向(指向目标点),设置加速度作为力,更新速度和位置。

运行于rocket组的每一个点

2.创建rocket点(使用detail只运行一次)

读取输入2的点数(circle的点数)

每多少帧产生一个rocket点(使用取余),再与点数取余(获取circle的点索引,依此循环),设置新的点和属性。

image-20251201191811353

3.只设置加速度容易过调,这里设置最大速度限制

4.设置分离力,使rocket之间相互远离

这里使用近点函数,使其远离周围的点

image-20251201194141629

5.设置爆炸点,当距离过近或者“life”清零时将点重新分组以作处理

image-20251201201602158

四.加权最短路径增长weighted shortest path growth

1.初始设置

1.添加字体,打开text attribute。

textindex 属性:由于我这里加了空格(也算),所以是0,2,4

textsymbol属性:则是记录的字母对应的ASCII码值

image-20251206141927053

image-20251206142210849

2.设置point法线,使用[connectivity] 为prim设置 class 属性

image-20251206142534544

3.使用lab工具中的[straight_skeleton_2D]设置字体形状的骨骼

image-20251206142748155

4.使用sort将prim按照X轴排序.

image-20251206142938474

5.设置[for_each_primtive],以"calss" 作为piece attribute.以此保留每一个字母的第一个prims

image-20251206142929399

image-20251206143211180

6.选取每一个prim中的靠左边点(x更小)作为起点.

这里分别 获取每个prim的点列表,获取第一个点和最后一个点的位置,比较谁的x更小,以此作为起点添加新点,再设置属性(将"class","textindex"从prim属性转移到点属性),设置分组为"start".删除原prim

image-20251206143344763

image-20251206143350017

2.scatter point 散布目标点

1.设置isooffset分辨率,这里使用第一个输入的bbox(边界值)

image-20251206161816507

2.设置法线,从geo转移属性到point,这里使用[xyzdist()]函数,寻找到最近几何表面的位置.得到prim和uv,再使用[primuv()]函数在得到的位置插值属性.以此计算最近表面点的N法线和位置P,计算每个点指向近点的向量与法线向量点积,若是小于0,则表示此点在几何表面之外,以此剔除外部的点.

将点对应prim的属性"class"和"textindex"转移到点.

image-20251206161723447

3.使用随机值选取一部分点作为"goal"目标组

image-20251206162536247

3.最短路径算法

1.寻找每个点的近点(这里搜索两个点,但其包含本身,所以只有一个近点),计算到近点的距离.并保存为属性.(==这一步后续第6步才用到,可以放到后面==)

这里不使用[ nearpoint() ],因为其只找一个点这里会找到本身(更适于寻找单纯位置的近点而不是点的近点.使用[ nearpoints() ]可以找到除本身以外的其他近点.

使用[ attributepromote ]函数计算其最大值并保存到detail.

image-20251206175541448A

image-20251206175546485

image-20251206175856003

2.计算骨骼中每个点到==起点的近点==的距离.

1.这里先使用[ findattribval() ]函数寻找与每个点"class"相同的起点(每一个字母(class)对应一个起点.).从输入2中

2.获取该起点的位置.

3.寻找每个起点的近点(其实位置相同,就是本身,由于这里在上一步设置起点时从原骨骼所有点中剥离).==为了获得对应起点在骨骼中的ptnum编号==,以用来计算距离.

4.使用[ surfacedistance() ]函数计算每个点到近点(起点)的距离.第二个参数使用[ itoa() ]函数将近点编号转换为string类型,得到最近点的编号cpt,"edge"指的是测量距离的方法,"edge"或者"surface".

image-20251206181546572 image-20251206180126168

image-20251206180120368

3.计算最短距离"closestdist"和"edgedist"属性

image-20251206191639254

image-20251206191658562

1.使用[ xyzdist() ]函数计算每个点到骨骼上的指定"class"prim组(即每个字母骨骼)中的最近距离.这里第二个参数(string类型)使用表达式,即与当前点"class"相同的组中.由此计算的=="closestdist"属性,每个点到骨骼的距离==

image-20251206192104294

2."edgedist"则是由之前计算的骨骼上每个点到起点的距离"d"属性转换到点上.这里使用[ primuv() ]函数读取每个点到骨骼上最近的位置的"d"值作为"edgedist"属性.

image-20251206192507460

4.将上述两个属性使用[ attributepromote ]计算最大值到detail.

image-20251206192653516

5.将上述两个属性映射到0-1,以方便计算"weight"属性.

image-20251206192738567

6.生成network.网络(可将第1步迁移到这里)

1.使用之前计算的"neardist"作为最大距离,即每个点搜索一个近点的最大距离,保证每个点至少有一个近点.这里加一个小值,如果刚好等于最大搜索距离,则至少有一个点刚好在边界搜索不到近点.

2.同样使用[ nearpoints() ]函数,目标点组设置为"class"相同.

3.对于每个近点,如果当前点编号更小,则连接成线.这是为==防止重复==,每个点连接编号更大的点,单向连接.

image-20251206200358869

image-20251206200353900

image-20251206200639621

image-20251206200648538

7.使用[ findshortpath ]寻找最短路径.

即寻找每个起点到每个终点的最短路径

image-20251206203227607 image-20251206203112093 image-20251206203120976

image-20251206203023140

4.生长动画设置

1.可以使用[carve]节点,但效率较低.这里使用VEX方法

头文件位置,使用[ adjustPrimLength() ]函数.

image-20251206211143460 image-20251206211248267

第三四个参数,当前prim的长度,和目标长度.使用[ measure ]测量

image-20251206211843956

image-20251206212100067

5.规格化closestdist

1.规格化closestdist,计算点到骨骼最近点的距离,再将"close"和"closestdist"属性promote到prim,再计算每个class 的"closestdist"最大值

image-20251206214558980

image-20251206214615290

image-20251206214853227

2.规格化,设置颜色

image-20251206215032240

image-20251206214112770

image-20251206215053276

6.基础信息计算 (计算maxcount)

注意[resample]节点,其" resample by polygon edge "选项,即保留多边形的顶点,==每个prim的每个边会独立采样==.如果在这里使用[fuse]节点,其"fuse snapped points"融合断裂的点会将同一位置的不同点融合,使用[ resample ]节点又可以生成这些点.

image-20251206220156042

1.==计算每个点(或者说位置)在多少个prim中存在==,需要先使用fuse,否则都为1(即每个点都只存在于一个prim中)

image-20251206221148065

image-20251206221140309

2.使用[attribute promote] 计算count的最大值,计算"class"(每个字母)的"count"最大值.

3.计算总的"count"最大值

image-20251209112132598

4.再将"maxcount"属性复制到到每个起点.

image-20251209112237549

7.设置pscale

image-20251209112336064

1.以每个字母的"count"作为pscale数据来源,将其clamp到1-最大值(避免末端太小)再除以最大值,使范围在0-1.

2.再乘以(1-curveu),以curveu作为影响因素.

3.由于变化太大(pscale曲线曲率太大),这里使用[ pow ]降低曲率,使其变化的更加平缓.

image-20251209112344249

五.飞翔的脊柱 Flying spine

1.初始状态设置

1.copy to points,设置点法线

image-20251211111745336

image-20251211111754646

2.设置bend弯曲,对于每个prims,以起点指向终点向量和法线向量的叉乘为轴axis,设置最大角度(每个prim乘以随机值,注意这里使用@P,获取的是prim的中点位置,每个prim的每个点都是一样,所以即使这里在循环中遍历prims的所有点,但是每个点的随机值是一样的,即每个prim的每个点的旋转角度都是相同的。若要为每个点设置不同的旋转值,则海需要加上i,作为rand函数的种子)。

image-20251211123243616

image-20251211123235317

image-20251211124156769

3.这里要设置让每个点旋转都不一样,可以通过控制中心位置的offset。每个点在旋转之前需要先移动坐标系,即以prim的中点(cen,@P)为参考。

在循环遍历prim的每一个点之前,为每个prim的cen点设置一个偏移量,以保证每个prim旋转中心也不同(影响不大其实)。

在循环中,再在cen位置加上noise(此时以“pos”属性,即每个prim中每个点位置为种子,为每个点的旋转中心都生成不同的偏移量。)

image-20251211125157685

image-20251211125205957

2.solver

1.移动“head”头部点。

设置vector4,以“id”属性随机,再加上位置,设置时间“Frame”,作为curlnoise的种植。以此随机移动“head”点。

image-20251211132932066

2.让其他点跟随“head”点移动

1.运行于每一个prim,先获取prim中ptnum列表,获取前一个移动了的点位置(初始状态是平pts[0],即"head"点.后续在循环中替换该点)

2.循环遍历每个点(除去第一个"head"点,他已经移动过了)

3.获取要移动的点"m_pt",和前一个点"p_pt",获取这两个点的原始位置(从输入1中获取)

4.计算原始这两个点的距离.

5.获取要移动的点的当前位置,计算由前一个点指向要移动点的方向,再以此方向乘以原始两点距离获得要移动点的新位置.

6.将新的这个位置设置为上一个点位置.(以进入下一次循环),设置当前要移动点的位置属性.

image-20251211140422539

image-20251211140716129

3.设置spine形状.

image-20251211145911923

image-20251211145929332

使用三角函数依据高度缩放侧边形状.

将高度@P.y映射到0-1,再以其作为角度0-2PI,以此作为cos值,将cos值从-1 -- 1==映射到1-0==(这样映射使得高度由-0.5 到 0.5,对应从0 到 1 再到 0.即需要保证中间可以被变化,两边比例不变.)

以此乘以x,z值.放缩中间的半径粗细

image-20251211150018961

image-20251211150603099

再以1/$SIZEY,缩放,使其y轴为1.以便于后续使用pscale控制每个关节的大小

image-20251211150706519

image-20251211150659761

2.copy到线

1.先设置pscale,使用[ convertline ]将每个prim的每条线段都转化为prim(此节点生成的"restlength"属性 作为"pscale").

2.结果如图,还需要设置"N",来指使方向

image-20251211151901875 image-20251211151907284

3.设置方向"N",以每个prim的两点指向作为"dir".

image-20251211152356573

image-20251211152351263

image-20251211152557472

4.设置翅膀

image-20251211172212253

1.设置基础形状

image-20251211171943393

2.注意再solver中最后的[ orientalonecurve ]不再生成up,否则up翻转变化过快.

3.去点端点

image-20251211172156435

4.先设置"N"在侧边的摆动

这里原本的"N"是切线,所以设置up以切线为轴随时间偏转,在使用"up"与"N"叉乘获得新的"N",作为对齐翅膀的方向.

image-20251211172337166

5.在原位位置生成新的点,并设置其"N"为负的[ reflect ],获得另一边的"N".设置"pscale"属性,"id"属性."up"属性保持不变.

image-20251211172711556

5.效果如图

image-20251211172911911

六.湍流变换 turbulence morphing

1.基础设置和原理

1.按照几何体的高度(@P.y)映射到1-(设定帧范围,)作为偏移值"offset",即设定从上到下,依此偏移多少帧.(这里设定60帧,即最下面的点的"offset"值为60,其60帧再进行操作)

2.将当前帧(@Frame)从 offset(这里从上到下的点"offset"值依此变大) 到 最大帧减去偏移帧范围(也可以不减),映射到0-1.使用fit函数时超出范围则映射为边界值.所以在当前帧到达每个点的"offset"值之前都为0.==这里的f即是每个点根据当前帧从起始帧"offset"到结束帧映射到0-1.==

对应于越上面的点,"offset"值越小,其映射的原始范围越大(offset-$FEND),越早开始移动,且变化缓慢(范围更大比如最上面的点从1-240帧映射到0-1),都是同样的终点,越后面的点"offset"值越大,其开始的值越晚(比如最下面的点从60-240帧映射到0-1),移动迅速.

image-20251212154750178

image-20251212154744332

2.增加细节,设置旋转

1.以"f"乘以2PI乘以圈数作为旋转角度.旋转@P.

image-20251212161118575

2.给"offset"值增加随机值,使其旋转时不过于整齐

image-20251212161716366

3.为旋转轴"axis"添加噪波.

image-20251212163259700

4.结合第二个几何体做变换.

由于两个几何体点数相同,这里可以读取到另一个几何体的所有点位置.同样获取其y轴最值并映射.将新的偏差值"noffset"加到f的起始范围(这里会使两个几何体的每个点映射的正帧围大小一样.比如同样是最上面的点,其偏差值都是1,则其f值都是由当前帧从1--180帧到0-1的映射,最下面的点的f则是当前帧从60--(180+60)帧 到0-1的映射).

另一个几何体的位置npos同样根据f为角度旋转.

再以f为bios插值两个位置的值.

image-20251212171457428

5.以中心位置指向当前位置为方向,为每个点设置向外扩张再收缩(这里使用sin函数,f是0-1, 对应正弦 由0-1-0.)

image-20251212180007602

3.设置拖尾和颜色.

image-20251212180332439

结果如下

7.使用约束的粒子变换

1.关于dop网络中的sopsolver(constrain geometry )

在 Vellum 的 DOP 环境中(或者高级 SOP Solver 接口中),这四个部分分别对应不同的物理数据流。理解它们就像理解一个提线木偶的各个部分。

① Geometry (几何体 / 木偶本体)

  • 是什么: 這是实际渲染出来的东西(布料的 Grid,头发的 Curve,沙粒的 Points)。
  • 包含关键属性:
    • P (位置), v (速度), orient (旋转)。
    • mass (质量) / w (质量倒数)。
    • friction (摩擦力), bounce (弹力)。
  • 在这里做什么:
    • 修改 mass 来让某些部分变重。
    • 修改 v 来制作瞬间的推力(比如爆炸)。
    • 修改 Cd 来做可视化。

② Constraints (约束 / 提线与关节)

  • 是什么: 这是一堆只有线(PolyLines)的几何体。每根线连接 Geometry 中的两个点(或者一个点和空间坐标)。
  • 包含关键属性:
    • restlength (原长):线原本有多长。
    • stiffness (刚度):拉长这根线有多难。
    • damping (阻尼):晃动停止得有多快。
    • breaking (断裂):是否允许断开。
  • 在这里做什么:
    • 这是此节点最常用的地方。比如:if (force > threshold) removeprim(0, @primnum, 1); (如果拉力太大,就删掉这根线/撕裂布料)。
    • 动态变软:随着时间推移,降低 stiffness 模拟冰激凌融化。

③ Impacts (撞击 / 痛感神经)

  • 是什么: 这是一个临时生成的点云。只有当物体发生碰撞(Collision)时,这一帧才会产生数据。
  • 包含关键属性:
    • P:碰撞发生的具体位置。
    • force:撞击力度有多大。
    • normal:撞击的方向。
    • otherobjid:撞了谁。
  • 在这里做什么:
    • 这是触发器。例如:如果检测到 Impacts 里有数据且 force 很大,就触发声音,或者把 Geometry 里的对应区域颜色变红(受伤效果)。

④ Feedbacks (反馈 / 内部应力)

  • 是什么: 这是一个比较高级且容易被忽视的数据流。它记录了约束为了维持现状而施加的力
  • 通俗理解: 如果你用力拉一根橡皮筋,橡皮筋也在用力拉你的手。Feedbacks 记录的就是“橡皮筋拉手的力”。
  • 用途:
    • 通常用于基于应力的断裂(Stress-based Breaking)
    • 虽然我们常在 Constraints 上判断断裂,但有时候需要知道“累积的应力”或解算器内部的反馈力,这时会用到这个数据流。
    • 注意: 在简单的 Vellum 流程中,这个端口经常是空的,除非你在 Solver 设置里专门开启了 Force Feedback 相关的输出选项。

编译块的作用.是加快结算速度.

image-20251212201110561 image-20251212201157171

2.基础设置

1.scatter points

设置属性"cluster",设置分组,设置边界信息(以便于在dop solver中从上到下依此映射"mass"使其从上到下依次"解冻",mass=0则静止(表示质量无限大)).

设置rest也是为了方便映射mass

image-20251212201302672

3.使用[ vellum configure grain ]节点将点配置为可以在vellum中求解的颗粒(就是设置一些属性).

增加了 isgrain, mass, pscale, v,属性

image-20251212201709922

在进行下一步之前将"target"组的"mass"设置为0.让目标点保持不动.

image-20251212201835206

4.使用[ vellumconstraints ]节点设置glue约束.

在这里手动设置由起点到目标点的约束,设置连线,设置分组.使用[attribute transform]将其他的prim(约束属性)转移到新的约束上

约束(prim)上的属性: compressstiffness(压缩刚度),constraint_tag, dampingratio,restlength, restlengthorig, stiffness, type.

image-20251212202147670

image-20251212202155358

5.vellum solver

1.设置popwind

2.设置[ sopsolver(constraints geometry) ]

先设置其从上到下依次"解冻"的效果.

image-20251212202922239

image-20251212202927669

3.设置与目标点的约束逐渐增大,以将点拉向目标位置.

1.这里使用[ expandpointgroup ]函数,获取geometry中的"target"点组中的点编号.以得到其点上的bound属性.

这里再prim中使用@ptnum获取的是对应prims的第一个点(由于rest存在于每一个点,所以这里也可以得到rest属性值).

y值由上到下,映射为1-0,再乘以frame,得到150-0帧.

f值为0-1,上面的点从0 到 $FEND-offset(0-250) 帧从 150/400 到 1.下面的点则从(0-400)帧对应0-1.

image-20251212230238940 image-20251212230046978

image-20251212230113492

4.设置原本的约束"stretch"从保存的"reststiffness"逐渐减小为0.

image-20251212231920254

6.补充知识

1.stiffness指的是约束的强度,将粒子拉回初始静态状态的强度。

八.拼图

1.基本形状

1.依据line 的curveu信息,将其映射为0-1的sin值(塑造拱形)作为高度(这里是z轴作为高),

image-20251214173853772

image-20251214173857028

2.再依据高度映射x(左右)位置,使其圆弧可以向内凹。

image-20251214175559490

想要控制下面的点向中间收缩,先将z轴(即高度)从低到高映射为1-0(越下面的点z值越大),此时如果直接相乘(需要先回中点)越高的点(z值越大)x轴坐标收缩越多越靠中

“xs”:映射高度 所以底部为1,顶部为0.(从1--0--1)

image-20251214192212015

再将其乘以sin(ang),这里乘以sin正弦函数,是为了==提取中间部分==

sin(ang):两端为0,中间(顶端)为1(从0--1--0)

image-20251214192245622

两者相乘使其底部端点为0, 顶部为0,保留中间高度的点插值。

image-20251214192322931

由于这里用乘以x轴坐标来设置位置,所以需要反向,1-xs,使得底步和顶点的值为1,在放缩中保持不变,中间的点被放缩。位于领口处放缩最大。

image-20251214192335471

3.使用[ convertline ]将原始图形转换为line

image-20251214202830135

1.使用 [ resample ]将每个线段设置为和基础图形一样的段数

2.依据基础图形的x和z值,在作为原始图形每个prims的每个点沿切线和up方向的值.

image-20251214202955591

image-20251214202943095

这里的"up"由法线"N"和切线"tan"叉乘得到

新的坐标由起点(每个prims的第一个点)坐标加上沿切线和up方向分量,乘以restlength(每个prim原本的长度,应为这里基础图形长度为1.)

4.设置随机凹槽位置,使用[ sort ]随机排序prims,在使用reverse反转一部分顺序.

注意这里的[ reverse ]设置,首先==这里的"-"不是减号==,==是0到多少==,先执行反引号中的代码,这里的[ opinput() ]函数返回连接到给定输入的节点的名字(这里返回连接到 当前节点(".")的第0个输入的节点的名称,也就是上一个[sort]节点),[ rint() ]函数,四舍五入.

image-20251214203533845

image-20251214202647669

可以使用[ opinputpath() ]函数,直接获取连接节点的绝对路径.

image-20251214204823973

5.使用solver解算器模拟吹散"拼图".

"cen"和"id"属性跟随原始每个"拼图"的,经理过[remesh]之后,原始每个"拼图"属性任然保留.(即使prims数量增多)

image-20251214211641466

这里是依据每个"拼图" 的prims的两个属性不变(中心点位置和id).

2.使用[ pointprims() ]获取每个点的prims的第一个prims编号.

以此获取每个点对应prim的属性(中心点位置,id).

3.依据当前中心点位置"cur_cen"和"id"设置随机的方向,注意这里保留了y轴0-1的范围.使其向上,只在xz方向有正负的随机值.

4.依据不变的原始中心位置"ori_cen"(输入1,始终不变),设置y值为从上到下映射为0-1.开始的t值由当前帧到一半的时间轴映射为0-1,即一半的时间就从上到下全部逐渐扩散条件.

5.设置随机旋转轴(使用[ rand() ]函数,同样依据属性"id".)设置随机旋转角度,依据"vel"速度属性的长度,从0到最大速度映射到0-角度.

6.更新位置的旋转,更新速度属性.更新位置,设置中心位置属性.

image-20251214214225763

6.设置颜色(依据挤出时的分组)

image-20251214215436577

7.结果

九.wiggle pattern with vellum 使用vellum的摆动

1. 为Circe设置hair constraint, 保存原始restlength

image-20251216141847353

image-20251216141854896

2.在solver内设置restlength随时间增长.

3.在将circle使用[ ray ]节点投影到grid上,注意这里要==设置pprevious属性==

image-20251216142106281

1.关于==@pprevious==属性,代表上一个子步结束的位置.(用以计算速度个惯性)

image-20251216141414063 image-20251216141549373

2.关于solver中的==FORCE==和==SOURCE==(output)

image-20251216141710269

十.磁场线模拟

1.设置磁极.

image-20251216213632913

2.计算velocity

image-20251216213646858

文章作者:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 彬的特效学习指南
喜欢就支持一下吧