1.基础知识 attributes

1.四种属性类型 attributes

1.point

2.primitive

3.vertex

4.detail

2.数据类型

image-20250730105226376

数组

​ f[]@aval = array(1.2,2.1,4.5);

wrangle

wrangle 中的vex 代码==同时==运行于每个point ,primitive ,vertex,但是==detail只运行一次==

multi threading 多线程 ,vex比python快的原因,vex可以一次将代码应用到所有点

保留属性

image-20250730112116947

global attributes 全局属性

@Frame

@Time seconds

一般将global attribute 存储在detail,

2.组 groups

point ,primitive,vertex存储在对应的类型中,edge无法查看。

1.[==setpointattrib()== ] 设置point属性

image-20250730122519079

image-20250730122840830

1.相比直接设置 i@abc = 100 将所有点设置为同一属性值; setpointattrib(0,"abc",@ptnum,100)函数可以==选择性设置==一部分点的属性值。可控性更高。

2.[==setpointgroup()== ]设置point 组

image-20250730123551059

3.primitive ,vertex 有同样的VEX function

image-20250730124027196

2. 过滤 group 的相关函数 filtered group function

1.查找primitive==是否==在prim group 中

[==inprimgroup()== ]

如果primnum在groupname中,则返回1

image-20250730164543980

2. 查找==有多少个==primitive在prim group 中

[ ==nprimitivesgroup()== ]

image-20250730170127562

3.查找在group中的primitives 的编号, 返回数组

[==expendprimgroup== ]

image-20250730170613184

4.近点函数 查找距离pt(位置)最近的点返回编号,这里可以设定范围为ptgroup,仅查找组内的点

[ ==nearpoint()== ]

image-20250730172120824

geometry 指的是要搜索的几何体

3.参数 parameters

1.创建参数

image-20250731151617423

2. 链接参数

copy parameter -> paste references

使用反引号引用链接即可读取内容

image-20250731160523191

同样可以读取menu value

image-20250731160638609

3.使用 VEX 访问参数

直接复制 使用的chs(),返回的是string类型,所以需要使用反引号,将字符串转换为float值

image-20250731161315064

使用 ch(),函数

image-20250731161526125

可以使用其他类型,这里可以使用chf(),

不同的ch()函数

image-20250731165737437

4.避免修改参数的name导致链接断开,将参数链接到wrangle的新通道,再链接到VEX代码

image-20250731170348519

可以直接创建不同的channel

image-20250731170624698

5.斜坡参数 ==ramp parameter==

image-20250731171305615

channel: 指的是channel name 名称

ramppos: 指的是输入的横坐标x轴的值,即需要评估的值,以返回对应的y轴值。

6. 全局变量 global variables 可以在任何地方任何节点访问

image-20250731172637841

局部变量 local variable 只能再特定节点访问

比如transform ,在reference ->local variable 中查看

image-20250731173134103

SIZEY

image-20250731173235927

同样使用$符号引用

image-20250731173319759

也可以在具体节点的文档查询可用的局部变量

image-20250731173450317

脚本语言 H script 或者叫做 expressions function,可以在参数中直接使用

image-20250731173827890

4.变量和运算符 variables and operations

1.变量 variable

image-20250731190314241

2.运算符 operations

即数学运算

加减乘除以及类型转换

1.字符 运算 strings operation

字符串 相加(只能做加法运算,不能实现减,乘,除)

image-20250731221231041

数字与字符串转换 casting

使用[ atof() ] 函数 将字符串转换为float

只有当变量为数字才生效,否则返回0

image-20250731221538847

使用[ atoi() ] 函数 将字符串转换为integer
使用[ itoa() ] 函数 将integer转换为字符串

image-20250731222449372

没有函数 ==ftoa()== 将==float==转换为字符串
使用[ sprintf() ] 函数 将==任何类型==数据 转换为字符串

第一个参数是要转换的变量的类型,第二个是转换变量

image-20250731222850801

image-20250731223054544

format

image-20250731223140811

向量 运算 vector operation

加,减,乘,除

即==各项==相加,相减,相乘,相除

例如:使用==加法==,使点沿法线移动

image-20250731224204122

==向量vector== 与 ==浮点数float== 运算

会将==float== 或者==integer== 转换为同样大小的==vector== 进行计算

image-20250731224616295

==向量vector== 与 ==其他向量vector== 运算

将==较小的向量vector== 转化为与 ==较大的向量vector== 相同大小的向量==vector==,在多出来的轴增加0

image-20250731225701607

image-20250731230254494

访问向量中的分量

方法一:像访问数组一样
=vector[index];

image-20250731230907795

方法二:使用点运算符
=vector.x;

image-20250731231127957

5.数组 array

a container that can contain multiple items

包含各种数据类型的容器

1.创建数组

创建空数组变量 variable,方括号表示, 存储值放在==大括号中==

大括号只能使用值,不能使用变量variables。

image-20250801101904895

使用[ array() ]函数 才能使用变量variables

image-20250801102316316

创建具体的数组属性 array attributes , ==f[]@name === (方法一)

image-20250801102457788

image-20250801104055285

使用[ setdetailattrib() ] 函数 创建 attributes (方法二)

image-20250801104537571

使用函数[ setdetailattrib() ] 的好处在于可以程序化修改变量名,以便参与循环等等

image-20250801104647109

2.从数组中==获取==值, get item from array

1.使用索引 index ==访问== 数组的值 items

===values[index]==

image-20250801105548618

3.向数组中==添加==值 add items

方法一 : 使用[ push() ] 函数

push(variables name, values );

参数为变量名,值;

image-20250801110147288

方法二 : 使用[ append() ] 函数

以上两种方法需要将variables values 变量值 ==赋值给 一个属性==attributes

使用[ setdetailattrib() ] 函数 则可以直接向==属性attributes== 中==追加==值values

使用==“append”== 模式mode

image-20250801111023507

4.从数组中==删除== 值 remove item

有三种方法 : 一是remove==最后一项==, 二是remove具体的==值values==,三是remove按==索引index==

1.方法一:使用[ pop() ]函数 remove 最后一项

pop(数组名);

image-20250801112453883

2.方法二:使用[ removevalue() ]函数 remove values特定值

removevalues(数组名,特定值);

==注意==:这个函数并不会删除所有相同的值,==只删除第一个值==。

image-20250801112743863

image-20250801112611694

3.方法三:[ removeindex() ] 通过index 删除remove 值values

removeindex(数组名,索引);

image-20250801113204814

5.其他关于数组的函数

1.从一个数组创建重复的数组

1.直接将一个数组 ==赋值== 给新的数组,以创建副本

image-20250801113615551

2. 使用[ set() ] 函数 创建副本

set(数组名);

image-20250801113724697

使用[ set() ] 函数的好处在于 当参数不是数组时,可以将向量vector或者矩阵matrix转化为 数组

image-20250801114211897

获取一个数组中值的==总数==

使用[ len() ] 函数获取 数组长度

len(数组名);

image-20250801121209395

6.字符串 strings

1.声明字符串 declare string

方法一:创建字符串变量并赋值 使用==双引号==

==string sname = "";==

image-20250801143511727

方法二: 创建字符串变量并赋值 使用==单引号==

==string sname = '';==

image-20250801143921421

从[ font ]节点, 访问字符串==属性== string attribute

能够访问detail的函数functions

image-20250801144437986

[ details() ]函数 , 从detail attribute 返回 string

details(surface_node,attribute);
surface_node 指的是节点名, attribute 是属性名

image-20250801144752635

为了将其作用为表达式expression,必须使用==反引号==

`detail(" "," ")`

image-20250801145145278

2. 使用特殊字符 special characters

反斜杠作为转义符escape word \

1. ==\n== 反斜杠n ==换行符==

将双引号转换为字符串

image-20250801150254314

单引号 和 双引号 ==交替使用==也可以实现

image-20250801150422437

其他转义符

image-20250801150658430

3.格式化字符串 formatting string

将值values 格式化为字符串

这里使用[ itoa() ]函数将==整数integer== 转化为字符串string

注意:没有 ==ftoa()==函数 将==浮点数float== 转化为字符串string

image-20250801151332889

需要使用[ sprintf() ]函数 将==float==转化为字符串string

image-20250801152345094

image-20250801152047082

==sprintf("format", ...);==

format

image-20250801152141443

修改VEX精度 precision

image-20250801152631112

[ sprintf() ]函数 可以转化==多个不同类型==的变量

image-20250801153103668

4.字符串操作 string operation

1.字符串==相加== addition ,将字符串连接起来

image-20250801153455395

image-20250801153555059

连接多个字符串

image-20250801154043174

要连接多个不同类型的字符串需要使用[ sprintf() ]函数

5.访问字符串 string access

和访问数组类似

访问字符串中的==单个==字符

要访问字符串中的某个字符,要先计算该字符的索引index

=== variable_name[index];==

image-20250801154610288

检索retrieve ==多个==字符

使用起始索引index_beg,冒号: ,结束索引index_end 的格式

image-20250801155328501

===variable_name[index_beg:index_end];==

6.字符串和数组函数 string & array functions

1.[ join() ] 函数 连接数组中的所有字符串 形成一个字符串

image-20250801160952440

==join(s[],spacer);==
spacer 作为字符串之间的间隔字符串

image-20250801160547489

2.[ find() ]函数 在字符串中搜索字符

在字符串中搜索单个字符 返回index

image-20250801161905559

==find(字符串,字符值);==
haystack 是要搜索的字符串(范围),needle 是要搜索的==字符串值==。
如果搜索多个字符,则只返回第一个字符的index

image-20250801161350182

在数组中搜索单个字符 返回index,不仅可以用于字符

image-20250801162717481

==find(array[],target);==

image-20250801162513263

3.[ split() ]函数 将字符串转化为数组

image-20250801163427654

==split(s,separators);== 返回数组
s 是要拆分的字符串, separators 是分隔符 即使用那些字符将字符串拆分为数组

image-20250801162913093

4.[ len() ]函数 获取字符串长度

image-20250801163812262

len()函数不仅用于数组array[],也用于string,

image-20250801163639898

7.循环 looping

流程图

image-20250801170355684

1. for循环基础 for loop basics

image-20250801170854156

循环创建多个points

[ addpoint() ]函数 创建point,并返回point number

image-20250801171511003

2.在for循环中访问属性 for loop for attributes

在for循环中访问已创建点的attributes

修改每个点的颜色 @CD

image-20250801174758712

[ npoints() ]函数 返回输入geometry 的点数

[==setpointattrib()== ] 函数 设置点属性

3.for循环运用 for loop exercise

1.创建螺旋形状 helix

1.生成points

image-20250801175432909

image-20250801175441973

2.可以使用==三角函数==创建螺旋线

image-20250801175715977
设置步进角θ, i:0-->num θ:0-->iθ
image-20250801175903966

3.设置x,z坐标, x = cos(),z = sin();

image-20250801180325780

image-20250801180516507

4.设置y坐标

image-20250801180628863

image-20250801180701071

5.参数化变量

参数化 步进角 angratio, 步进高度 heightratio

image-20250801180851240

4.while loop

while(){};
只有一个条件,且不能在括号直接创建

1.while loop

image-20250801182202785

2.do while loop

至少运行一次,即使条件不符合
先运行一次,再检查条件,不符合则退出循环

image-20250801184229755

5.while循环运用 while loop exercise

1.创建螺旋形状 helix

以总旋转角度 total rotated angle 为条件

创建变量

image-20250801185350603

创建循环

image-20250801185742832

6.foreach loop

需要与数组一起使用

1.foreach loop

先将values 依次存入数组中

image-20250801190305977

image-20250801190340059

创建foreach loop

val指的是values数组中的每一个值

image-20250801190607125

以数组中的每一个值作为x坐标生成points

image-20250801190754441

image-20250801190833222

7.数组的for循环 for loop for array

使用for循环访问数组值

1.使用for循环依次以 数组中的值 作为点的x坐标生成点

image-20250801191632796

8.foreach 循环运用 for each loop exercise

创建螺旋形状 helix,控制每个点的法线方向

以便于将geometry 复制到点上时 基于法线对齐

1.将基于三角函数生成的position信息依次==存储在数组中==

为了参考第一个点和第二个点之间 创建向量vector,没有数组很难定义当前点current和下一点next位置

image-20250801192518891

2.使用另一个for循环访问(access) 数组中的值

条件中 i<len(positions)-1 ,总数减去1,保证当前点current point 始终有下一个点next point
否则当最后一个点作为当前点时 则没有下一个点了 即保证i+1任然在数组内

3.创建方向向量 ==next - current== = 由==current指向next==的向量

image-20250801193754301

4.使用[ setpointattrib() ]函数 将方向向量存储在点的attributes中

image-20250801193943997

5.结果 使每个box与曲线对齐 ,指向下一个点

image-20250801194038856

6.额外设置up向量

image-20250801194203257

image-20250801194238796

9.嵌套循环 nested loop

在一个循环中创建另一个循环

1.创建nested loop

创建两层

image-20250801194743400

image-20250801194751583

创建三层

image-20250801195139188

10.嵌套循环运用 nested loop exercise

1.创建多个螺旋形状 helix

1.创建变量

image-20250801195628454

2.创建循环

单个helix
image-20250801195737216 image-20250801195800334

3.嵌套循环 用n控制正弦余弦的角度

用stepang = ==$PI*2 / num2==,即以num2 划分360度
在三角函数中 加上==stepang * n== ,即加上偏移值,生成每一个点对应的偏移点

image-20250801200715625

image-20250801200707735

4.利用n,为每条螺旋helix 设置attributes id

image-20250801201035097

image-20250801200953846

8.条件 conditional

1.if else条件 if else conditional

1.simple condition

image-20250802151856197

image-20250802152416646

1.[ font ]节点可视化

image-20250802152337255

image-20250802152342985

2.多于两个条件则增加 ==else if()==

image-20250802152632524

2.单条语句的if条件 single line if conditional

1. 一行语句

image-20250802153056112

2. 三元运算符 ternary operator

1. === 条件 ?"true 的action" : "false 的action" ;==

image-20250802153835656

3.基本比较运算符 base comparison operators

1. 基本比较运算符

image-20250802155349970

image-20250802155740852

4.字符串匹配符 string match operator

1.字符串比较

image-20250802160130746

image-20250802160138060

2. ==~=== 匹配比较运算符 match operator

仅用于字符串匹配

模式一:使用 ==?== 匹配所有==字符==

只匹配单个字符

image-20250802160808295

模式二: 使用 ==*== 匹配所有==字符串==

可以匹配任何长度的字符串

image-20250802161155643

image-20250802161159250

模式三: ==[]== 匹配==选定的字符==

只匹配单个字符

image-20250802161554557

模式四: ==^== 匹配所有字符串时 排除另外一种情况

条件并列使用逗号连接排除的条件( ==,== )

image-20250802162150428

image-20250802162205759

5.运算符逻辑集 logical set

==与或非 and, or , not==

1. 与and , ==&&==

两个条件 ==同时满足== 才成立

image-20250802163125433

image-20250802163130211

2. 或or , ==||==

满足==其中一个条件==即成立

image-20250802163314438

image-20250802163329632

6. 用return==结束进程== ==end process== with return

在if语句中,如果满足条件,则return,以下的语句(s@next += "Not returned.";)不再执行.

image-20250802163958323

image-20250802164002660

7.用break==结束循环== ==end loop process== with break

满足条件则结束循环

只结束循环,以下的语句还是会执行

image-20250802164628264

image-20250802164633637

8.用continue ==结束迭代== ==end loop iteration== with continue

并不结束循环,只结束当前迭代并转到下一个迭代

1.使用continue跳过满足条件的循环迭代

image-20250802165525396

image-20250802165530307

9.条件练习 exercise - conditional with ==attributes==

条件与属性 ==attributes==

1.以时间@Time 为x坐标 创建point

image-20250802170019880

image-20250802170024818

2.基于时间@Time 改变point 大小 pscale

image-20250802170357258

10.条件练习 exercise - conditional with ==group==

条件与组 ==group==

1.依据条件创建组

image-20250802171015194

2.根据group 移动point

[ inpointgroup() ]函数 判断点是否在一个group内

image-20250802171400485

image-20250802171442489

11.条件练习 exercise - conditional with ==array==

条件与数组 ==array==

1.随机生成points,将pt(number)存储到数组pts中

image-20250802171856371

2.根据阈值随机定义一部分points

这里改变颜色和大小属性
使用数组中存储的pt(每个点的number) 来为每个point设置属性

image-20250802172310669

image-20250802172314761

image-20250802172336279

9.函数 function

1.函数类型 function type

不同的contexts 有不同的函数

image-20250802174242302

这里主要在cvex contexts

自定义函数

image-20250802174147405

2. 内置函数 built-in function overview

image-20250802174512360

vex functions

image-20250802174524259

image-20250802174549516

3.无返函数 ==void== function

无返回值,只做某种操作

例如:[ append() ]函数

往数组或者字符串中追加值

image-20250802174909880

image-20250802175350495

这里的 ==&== 符号,带有的参数(作为输出参数)将在运行后==立即更新==

4.返回函数 ==return== function

有返回值

例如:[ len() ]函数

计算数组的长度

image-20250802175741190

image-20250802180053658

5.函数练习1 function exercise 1

[ nearpoint() ]函数

1.找到geometry 中距离pt(自己提供的位置)最近的point

image-20250802180224578

2.VEX

image-20250802180802282

[ point() ]函数 获取第二个输入点的位置
找到距离目标点最近的点 返回ptnum值 存放到npt中

image-20250802181041152

改变所找出的点的属性,例如颜色

image-20250802181347928

image-20250802181353192

6.函数练习2 function exercise 2

更多参数的[ nearpoint() ]函数

image-20250802181638158

1.需要一个搜索范围ptgroup

image-20250802181823332

2.设置搜索距离

image-20250802181922743

3.也可以直接将group的条件放到函数中

image-20250802182200584

7.函数练习3 function exercise 3

具有多个输出参数output parameter 的函数

1.[ intersect() ]函数 计算与射线ray与geometry第一个交点

相交函数
有三个输出参数 p,u,v 还返回一个int值
image-20250802184511745

参数

image-20250802185051043
orig :射线ray的==原始位置==
dir :==射线的方向== 和 ==最大搜索距离==(vector的长度)
&p :交点的位置
&u,&v,&uvw :交点在相交的primitive的uv坐标
return :相交的==primitive number==

例子:将torus投射到地面,更新point位置到交点intersection位置

image-20250802185922438
创建参数parameter

image-20250802190137836

使用[ intersect() ]函数
image-20250802193247473
更新位置
image-20250802193341114 image-20250802193404033 image-20250802193530345

8.自定义函数 user-defined void function

void function

1.生成螺旋形spiral 点位置 的函数 ==void 无返回值==

1.参数:三个参数来确定螺旋点spiral point的位置 ==角度==,==半径==,==初始位置==

image-20250802195435555

新的位置 :初始位置加上 根据三角函数得到的旋转后的位置 乘半径

image-20250802195820061

生成point

image-20250802200000038

调用函数

image-20250802200316689 image-20250802200341641

将参数设置为可控制的channel

image-20250802200506424

9.自定义返回函数 user-defined return function

return function

1.生成螺旋形spiral 点位置 的函数 ==return 返回位置==

声明return function时最好使用 ==function 关键词== 避免出现未知错误

1.声明函数

image-20250802201722651

2.调用函数

存储生成的点位置,利用生成的位置创建点

image-20250802201903005

image-20250802201943343

3.也可以使用条件设置多个返回值

image-20250802203024770

10.声明输出参数 declare output parameter

为函数创建输出参数

1.生成螺旋形spiral 点位置 的函数 用output parameter输出位置

声明设置:增加输出参数 ==export type name==

更新输出参数值

image-20250802203758797

调用函数

image-20250802203749973

11.导入预安装函数 import preinstalled functions

导入houdini内置的外部函数,houdini引擎安装时提供的文件

1.houdini内置的函数位置

: houdini > vex > include >

image-20250802204203621

2.导入houdini内置函数

1.包含头文件 #include"groom";

2.调用函数控制primitive的长度

image-20250802205206063

12.导入自定义函数 import user-defined functions

导入自己创建的外部文件

1.创建一个include文件夹,将 自定义.h,文件放入

include文件夹要与当前工程文件在一个文件夹
image-20250802205814630

2.导入函数

导入自定义函数时要加路径

image-20250802210015304

3.调用函数

image-20250802210143961

10.体素 volume basics

1. volume基础 basics

在体素voxel中存储属性attributes数据

1.volume类型 type

fog 和 sdf
sdf 提取表面 主要用于建模而不是流体模拟等
image-20250802211854821

fog

2.volume的可视化和修改 visualize and modify ==scalar== volume

标量volume

直接用[volume]节点创建,或者转化

1.创建标量值density volume

image-20250802212433263

2.可视化 [volume visualization]

image-20250802212815858

3.用[volume wrangle]节点 修改density值

image-20250802213106779

为每个voxel设置density值

使用[ noise() ]函数 为每个voxel设置density(根据==@P==)
image-20250802213306403 image-20250802213550456

也可以将volume转换为surfaces

使用[ convert ]节点转换为表面
volume offset
image-20250802213818652

2.volume的可视化和修改 visualize and modify ==vector== volume

向量volume

1.创建向量值velocity volume

image-20250802214104280

vector volume被拆分成 scalar分量 存储

image-20250802214237663

2.可视化 visualization

image-20250802220027569

3.修改volume 值

根据三个channel修改颜色

image-20250802215536187

4.另一种可视化方法

将vector作为方向值,从volume中提取方向extract direction,

使用[ volume trail ]节点

image-20250802220848778

3.surface转换为volume volume frome surface

从geometry shape 创建 volume

1.[ isooffset ]节点

以此创建的volume 任然是box形状,50*50*50的voxel分辨率.只是在geometry以外的体素值存储为0.

image-20250802221633107

2.数学运算

1.检索density值,控制density

image-20250802223154421

2.设置noise

image-20250802223412178

4.volume 属性 volume attributes1

只能从volume wrangle 访问的保留属性 ==preserve attributes==

1. ==位置属性== ==@P==

在每个voxels 的中心位置

依据位置信息设置density

image-20250802224232095

2.每个体素的索引 ==i@ix==, ==i@iy==, ==i@iz==

从原点开始沿x,y,z轴递增,即按照volume的分辨率依次递增

通过访问保留属性 ==i@ix==, ==i@iy==, ==i@iz==,分别获取volume在三个轴的index

image-20250802224632415

3.访问每个轴的分辨率大小 ==i@resx==, ==i@resy==, ==i@resz==

image-20250802225317650

5.volume 函数 volume funcition

使用==volume 函数==可以在其他wrangle类型中访问 基于volume的信息(density,velocity,resolution...)

检索volume,查看volume 函数

image-20250802230105885

1.在volume的特定位置采样density值

image-20250802230342852

1.在volume wrangle中检索

image-20250802230552694
1.创建检索点的位置变量(这里[ add ]节点提供)
2.用[ distance() ]函数 计算(@P,pos)体素与检索点的距离
==注意:==只有==volume wrangle中可以修改==volume值,其他类型的wrangle可以访问但==不能==修改
3.[ volumesample() ]函数,从==scalar volume==中检索==scalar value==
image-20250802231354515

6.==volume 函数2== volume function2

1.检索volume==向量==值

1.[ volumesamplev() ]函数 从==vector volume==中检索==vector value==

image-20250802232612156

2.在point wrangle中从geometry中的每个点采样velocity值

获得特定位置(球体上的每个点)的向量值
image-20250802233222569 image-20250802233242341

3.依据采样的==vector value==移动点的位置

可以实现==按照volume中的向量变形几何体==
image-20250802233449697 image-20250802233619442

4.noise按时间变化

image-20250802233731671

7.volume 函数3 volume function3

1.[ volumepostoindex() ]函数 将位置转换为volume 体素索引

[ volumeindextopos() ]函数 将volume 体素索引 转换为位置

2.根据volume实现几何体的==体素化效果==

1.用[ delete ]节点 删除球体的primitive face,==只保留点==

image-20250802234459483

2. 使用[ volumepostoindex() ]函数 获得几何体每个点在volume中的索引值

检索==position== ,返回三个轴的==索引值==(vector), 检索的是在特定位置 ==最接近的==索引值
image-20250802234620386 image-20250802234914964

3.使用[ volumeindextopos() ]函数 ,将索引值转换为在volume中的位置

将volume 体素的==索引值== 转换为 位置==position==, 获得的是在特定的索引下 ==精确的==体素中心位置(voxels position)

image-20250802235036151

4.以此实现==体素化效果==

image-20250802235845975

5.由于移动后会有很多点在重复位置

使用[ fuse ]节点去除重复点

8.volume debugging

1.调试volume的技巧

在volume的每个体素位置添加point, 在每个点设置volume对应体素的属性
将volume存储在每个voxels的属性转换到对应位置的points上
==相当于将体素转换为对应的点==
这里先读取density到变量d,不能忽略, 直接在@P,位置生成点不起作用
这里类似一种巧合:可能涉及了houdini的VEX代码执行机制,由于volume wrangle主要是处理volume,其机制推断addpoint函数并不需要访问volume数据本身,所以可能并没有将@P设置为每个体素的中心位置。
当使用f@density,读取density的值,其机制判断需要读取体素值,所以计算好每个体素的@P,@density
这是一种编译上的优化处理。
同样适用于SDF
image-20250827171802932 image-20250827193335515

1.在每个体素的位置添加点

image-20250803001504520

2. 使用[split] 节点 分开点和volume

image-20250803001820563

11.字典 dictionary

1.基础 basics

字典中的每个item可以是==任何类型==的数据

1.声明字典 declare dictionary

使用 ==dict== 关键字 ==创建字典==

==dict name = {} ;== 创建dictionary
d@name = ; ==访问属性==

2.存储值

==key 必须是 字符串==

使用[ set() ] 函数 ==set("key" , value)== 可以一次创建多个键值对set("key" , value, "key", value)

image-20250803101757776

使用==dict_name = set();==会覆盖其他值

2.设置字典中的项目 set item to dictionary

1.修改(添加)对应 key 的 value

使用方括号==dict_name["key"] = value;==
image-20250803102300152

3. 删除字典中的项目 remove item from dictionary

==d@== 访问 dictionary attributes
==dict== 创建 dictionary

1.从给定的 index 删除项目

[ removeindex() ] 函数用于数组或者字典

==removeindex(dict_name,"key");== 返回1表示删除成功,返回0 表示没有这个key

4.在字典中查找键 check key in dictionary

1.检查key是否有效

[ isvalidindex() ]函数 检查给定的index是否有效
返回1表示存在于字典中,返回0表示无效,(适用于数组和字符串)
image-20250803105412866

5.访问字典中的项目 access item in dictionary

1.直接访问对应的key,需要知道 ==值的key==,==值的类型==

image-20250803105714610 image-20250803105916715
访问不存在的key时,返回0,或者空字符

2.[ getcomp() ]函数

从vector,==array==,matrix中提取单个组件,也可用于字典
image-20250803110521098

查找key并返回值,第三个参数 即查找失败的默认返回值

image-20250803110640596

6.合并字典 combine dictionary

1.[ insert() ] 函数

向数组或字符串中插入值,可用于字典插入或合并
image-20250803111344780
insert(dict1,dict2; 将dict2 合并到 dict1
image-20250803111738010

7.将字典转换为JSON格式 dictionary to JSON

将 字典值 转换为 字符串
JSON是一种字符串的格式

image-20250803115420673

image-20250803112118065

1.[ json_dumps() ]函数 将==VEX dictionary== 转换为==JSON string==

string json = json_dumps(dict,flags);
flags: 标记 0,1,2,3 表示返回不同的json
image-20250803114355415

转换为单行json字符串

image-20250803114759477

image-20250803114812439

可以通过font查看

image-20250803114921173

转换为==多行json==字符串,改变==标志位flags为1==

image-20250803115042278

将JSON 转换回字典

2.[ json_loads() ] 函数 将==JSON string== 转换为==VEX dictionary==

string json = json_dumps(string json,flags);

访问 json string attributes

创建dictionary

image-20250803115829142

设置为字典attributes以查看

image-20250803120224413

8.运用1 exercise 1

1.用字典控制球体每个点的位置颜色

1.设置scatter的点数与球体点数保持一致

用box的点云控制球体
image-20250803121024869

2.为点云中的每个点创建dictionary

基于点云中点的位置创建颜色信息和比例信息
image-20250803121453218
声明dictionary
image-20250803121524330
存储到每个点的attributes中
image-20250803121617927 image-20250803121649386

3.在球体中引用dictionary信息

image-20250803121948336

9.运用2 exercise 2

1.通过访问字典创建网格

为每个点创建字典

image-20250803124026525

以数组的形式存储所有字典,并存储到detail属性中

image-20250803124400013

image-20250803124611396

检索字典并创建网格点

读取存储在detail属性中的字典数组
设置点属性
image-20250803125346359 image-20250803125530114 image-20250803130912336

12.矢量 vector

具有方向和长度的信息
可以使用向量移动物体,也可以用于控制颜色(rgb)

1.向量加减法

1.向量加法 adding

首尾相加
image-20250803154628857 image-20250803155326527

2.向量减法 subtraction

即加上一个负的向量
image-20250803155617877

3.向量运用1 vector exercise1

1.创建向量用来移动物体

创建一个用来移动的向量

image-20250803160014198

在位置@P加上向量

image-20250803160135290

加法减时,相当于将新向量的原点移动到原向量表示的坐标处,在原位置的基础上按照新向量的方向和长度移动

image-20250803160554283

2.减法

创建随机向量

由于[ rand() ]函数创建的随机值在0到1之间,没有负数,所以只有正方向的向量。要获得所有方向上的随机向量,将得到向量每个轴减去0.5.
image-20250803161002105 image-20250803161011160

3.要得到一个 ==A指向B== 的向量,应该用 ==B - A==

image-20250803161651244

两点位置相减,将原点移动到新点

使用[ addprim() ]函数 连接两点。

image-20250803162155526 image-20250803162214290

4. 向量运用2 vector exercise2

1.在for循环中更新向量,用来反复移动点.

1.获取当前位置,创建循环,在新位置add点

image-20250803162740535

2.将最后一个点移动到新位置

分形fractal shape
image-20250803162908869

3.创建方向向量,加到原位置作为新位置,在新位置生成点,再将新位置更新到原位置,以作为下一次移动的基础

image-20250803163237386 image-20250803163244734

4.增加角度值,使用三角函数更新x,z坐标,以获得螺旋线

image-20250803163724852 image-20250803163841587

5.向量乘法(标量) vector multiplication

1.向量==乘以标量== 只改变大,不改变方向

image-20250803164157546

1.向量==除以标量== 只改变大,不改变方向 与乘法效果相同

6.向量除法(乘除法运用) vector division

当球体在世界坐标系的==原点处(0,0,0)==

1.控制geometry 的 scale

直接在点位置的基础上乘以标量

image-20250803164639194

7.向量运用3 vector exercise3

当球体的中心不再世界坐标系的原点时,以中心点放缩

1.此时的乘法会放缩大小,但是也会往原点移动

image-20250803165136883

直接用球体的位置@P乘以一个标量scale,放缩的时原点到球体位置的向量。所以产生移动。

image-20250803165341041

2.方法:将球体移动到原点中心,scale,再移回原中心位置

image-20250803165847225

8.规格化 和 模(大小) normalization and magnitude

1.规格化 normalize

即只考虑方向,大小始终为1

1.[ normalize() ]函数 归一化向量

image-20250803170611503 image-20250803170620498

2.[ length() ]函数 检索==retrieve==向量的大小

9.向量运用4 vector exercise4

1.生成随机大小的法向向量

image-20250803171408162

2.以此向量移动点,并使向量在随机向量与归一化向量之间切换

image-20250803171528707

==10.点积 dot product==

可以通过两个向量的点乘 来==检查向量之间的夹角==是否垂直,同向或者反向

1.点积定义(数量积或标量积)

代数定义

相乘再相加
image-20250803173340829

几何定义

image-20250803172841207

两向量的点积可以理解为==向量A在向量B上的投影再乘以B的长度==

image-20250803172944427

点乘的结果是投影的大小

image-20250803171732597 image-20250803171847324

2.VEX

1.计算两向量的点积

[ dot() ]函数
image-20250803174636445 image-20250803174643100

2.设置角度channel,利用三角函数更新向量2的x,y值,以此旋转向量2 从0到360度

image-20250803175058618

11.向量运用5 vector exercise5

1.==用点积判断一个点是否在几何体内部==

1.[ nearpoint() ]函数 检索距离最近的点 获取其属性

image-20250803175758083 image-20250803175809125

2.得到 ==当前点== 到 ==曲面上最近点== 的向量(==近点 - 当前点==)

image-20250803180020335 image-20250803180026674

3.计算 近点法向 与 当前点朝向向量 的点积, 以此判断当前点是否在几何内部

image-20250803180317316

4.大于0 则在内侧, 小于0 则在外侧

以此作为条件改变点的属性

image-20250803180450435 image-20250803180706018 image-20250803180719947

==12.叉积 cross product==

叉乘得到的结果是向量 是==两向量所在平面的法线向量,垂直于两向量==

其方向有右手定则确定

1.叉积定义(向量积,叉乘)

叉积仅在三维空间有定义

image-20250803183447003

2.VEX

1.计算两向量的叉乘

[ cross() ] 函数
image-20250803184108806 image-20250803184115132

13.向量运用6 vector exercise 6

1.创建up向量

使用[ copytopoint ]时,==N== 和 ==up== 向量都可以控制几何体方向

1.计算两向量的 叉积

image-20250803185246503 image-20250803185239515
得到旋转矢量

2.将此向量引用到up向量

image-20250803185501813

13.三角函数 trigonometry

1.角/角度 和 弧度 angle / degrees and radians

1.角度与弧度(又称弦度rad)

degrees:==角度== 0到360°

image-20250803190521662

radians: ==弧度== Π表示180°(Π = 3.14159....)

Π = a / d(圆周长 / 直径), 单位弧度 定义为 ==圆弧长度等于半径时的圆心角==
image-20250803191459398
2Πr=a ,所以一个圆完整的弧度为2Π,即360°。Π 表示180°
image-20250803190556069

大多数计算机程序设计使用==弧度==作为计算

2.角度转换 angle conversion functions

1.角度转换为弧度 degrees to radians

[ radians() ]函数 将角度转换为弧度

image-20250803192257669

2.弧度转换为角度 radians to degrees

[ degrees() ]函数 将弧度转换为角度

这里的channel为0到1 , 乘以一个PI,即可通过 0-1 控制 0-PI
image-20250803192618516

3.正弦,余弦,正切 sine ,cosine,tangent

image-20250803205834652

在单位圆上的点

cosθ 表示x轴位置 其值对应在x轴右半边 一四象限为正,左半边 二三象限为负

sinθ 表示y轴位置 其值对应在y轴上半边 一二象限为正,下半边 三四象限为负

1.基于圆 创建点 用三角函数表示

4. 三角函数可视化 visualize trigonometry

1.可视化

创建斜边

image-20250803210915672

创建水平投射线

image-20250803210741064 image-20250803211002005

创建垂直投射线

image-20250803211030756 image-20250803211036743

合并

image-20250803211228506

设置圆

image-20250803211304795

通过设置角度channel控制transform中的旋转角度.

image-20250803211841183 image-20250803211942685

与内置函数[ sin() ],[ cos() ] [ tan() ]计算的结果相比,结果一致

image-20250803212110662 image-20250803212225075

设置半径channel 改变圆半径

改变半径并不改变三角函数值,三角函数表示的时三角形边的关系
image-20250803212423534 image-20250803212509550

5.运用三角函数画圆 exercise - draw circle

可以通过三角函数判断圆上点位置,即可以使用三角函数取圆

1.用三角函数画圆

1.创建for循环,控制循环次数

image-20250803213358029
知道圆的半径,和夹角角度 即可通过三角函数计算圆上点的x,y坐标.
image-20250803213140716

2.创建递进角度 三角函数计算x,y坐标(默认以半径为1) 所以再乘以半径(可变).

2Π / 循环总数 = 每次循环递进的角度 ,再乘以i,每次循环依次递加角度.
image-20250803213606872 image-20250803213923750

6.运用三角函数画圆动画 exercise - circular animation

1. 用三角函数创建绕圈动画

1.设置角度和半径channel控制点在圆上的位置.

image-20250803214709248 image-20250803214825528

7.运用三角函数画波形 exercise - draw wave

1.创建角度变量

只需要对应三角函数的y坐标,x坐标为固定的步进值
此时的角度可以无限扩展 并不需要固定在0-360°
image-20250803215429551

1.wavenum控制波浪的数量,即有多少个360°.

image-20250803215821649

2.x坐标为随循环递增的坐标值,y通过三角函数计算角度得到

设置三种切换
image-20250803220211411

3.依据坐标生成点

image-20250803220354807 image-20250803220848033

8.运用三角函数画波形动画 exercise - wave animation

1.用三角函数波形移动点

1.用三角函数移动一点

image-20250803221237159

2.设置角度,更新y坐标(sin),x坐标仅作为步进值

image-20250803221406105

3.copy to point 移动几何体

9. sine和cosine的范围 range of sine and cosine

10.运用三角函数缩放动画 exercise - scaling animation

1.控制球体的缩放

1.随时间增长作为控制球体比例的的角度的值

image-20250803222626674

2.由于控制的是大小比例,将-1 到 1 的范围重映射到 0.1 到 1

使用[ fit() ] 函数
再乘到P属性
image-20250803222728433 image-20250803222924974

11. 正割,余割,余切secant,cosecant,cotangent

作为(sine,cosine,tangent)逆inverse

VEX并没有对应的函数

1.==余割 cosecant== 与 正弦函数(==sine==) 互为倒数 = 1/sinθ

image-20250803225043516

image-20250803224348130

==余切 cotangent==:与正切函数(==tangent==) 互为倒数 = cosθ/sintθ

image-20250803225014814

2.==正割 secant== :与余弦函数(==cosine==) 互为倒数 = 1/cosθ

image-20250803225349754

==正切 tangent== :与余切函数(==cotangent==) 互为倒数 = sineθ/cosθ

image-20250803225850663

3.VEX

image-20250803225939147

12.反三角函数 inverse trigonometry (to get angle)

通过边==求角度==

1.反函数 可以使用[ degrees() ]函数转换为角度值

[ asin() ]函数 arcsin 即sine函数的反函数 (返回弧度值)

image-20250803230845083

[ acos() ]函数 arccos 即cosine函数的反函数

image-20250803231107065

[ atan() ]函数 arctan 即tangent函数的反函数

image-20250803231435702

但是以上三个函数所得到角度是有限的

值域得不到完整360°
image-20250803232131485
image-20250803232252626

2.[ atan2() ]函数 可以获得完整的360°

0 - 180° - 0
image-20250803232433241

13.运用 3D向量之间的角度 angle between two 3D vectors

1.判断两条线之间的角度

1.通过设置seed为两条线设置随机旋转

2.以其中一个向量作为基本轴,将另一个向量投影到此向量上(点乘)

v dot A :结果即v向量在A上的投影乘以A的长度,这里归一化A向量,则直接得到投影的长度(x)
在根据勾股定理计算对边的长度(y),以此使用[ atan2(y/x) ]函数 得到角度值
image-20250803234646107 image-20250803235047996

3.[ primpoints() ]函数 返回一个primitive 的点列表

image-20250803235736178
获取每个primitive的两个点的位置,再计算方向向量并归一化
image-20250803235931017 image-20250804000110344

4.计算两个向量的点积x ,h

这里点积,定义任意一个向量作为x轴都可以,以dir1为参考轴(归一化),则点积结果为 dir2在dir1上的投影长度 ,相反也一样
image-20250804001019667

14.向量之间画弧 exercise - draw arc between vectors

1.根据测量出的两条线之间的角度值画弧(3D空间)

以两个向量作为虚拟的x,y轴来确定对应的(x',y')坐标

image-20250804003222046

2.向量v1,v2 以v1作为x轴 通过求v1,v2的叉积得到垂直于两个向量的z轴,再求z,v1的叉积得到y轴。

image-20250804003950052

3.求出虚拟的xyz轴

image-20250804004411377

4. 对应的角度值乘以虚拟xyz轴,得到虚拟的xy坐标,

这里以v1向量作为虚拟x轴,求出的虚拟y轴,最终坐标即两个向量相加
image-20250804010241170 image-20250804004933660 image-20250804004940388

14.四元数 quaternion

主要用于3D空间中的==旋转变换== ,主要包含两个信息,==旋转轴rotational axis==,==旋转角度 rotational angle==

image-20250804100739780

向量表示

image-20250804100929401 image-20250804102310657

1.声明四元数 declare quaternion

1.[ quaternion() ] 函数

角度和旋转轴
image-20250804103110029

通过角度和旋转轴创建一个四元数变量

image-20250804103417378

2.使用四元数旋转 rotation with quaternion

1.[ qrotate() ]函数 使用四元数旋转一个向量

返回旋转后的向量
image-20250804103747073

1.VEX

image-20250804104024897 image-20250804104138837

3.运用四元数旋转物体 exercise - rotate object

1.使用四元数旋转几何体以给定的线作为旋转轴

1.检索线的终点获取位置,以此位置向量作为旋转轴

因为线的起点在0点,终点位置即可作为直线的方向向量

2.创建旋转角度,创建四元数

[ quaternion() ]函数 创建四元数

3.利用四元数旋转物体位置

[ qrotate() ]函数 利用四元数旋转向量
image-20250804110821292 image-20250804111008147

4.运用四元数螺旋旋转 exercise - spiral rotate

1.不同角度控制多个对象多个点

1.用ptnum乘以旋转角度,即每个点依次旋转更大的角度,形成螺旋线

image-20250804112105953 image-20250804112218069

5.欧拉转换到四元数 Euler to Quaternion

1.

[ eulertoquaternion() ] 将Euler角度 表示为一个四元数
image-20250804114256020
order
image-20250804114824700

将Euler旋转转变为四元数旋转

image-20250804115219072 image-20250804115318420

6.四元数转换到欧拉 quaternion to euler

1.将四元数转换到欧拉

1.[ quaterniontoeuler() ]函数 创建一个Euler角度来表示四元数

image-20250804115623770

2.转换的角度

image-20250804115839616 image-20250804115911411

得到的角度并不一定等于初始的角度,但是旋转一样

7.四元数混合球面线性插值 quaternion blend with slerp

可以在两个四元数值之间创建平滑的插值

1.使用四元数控制点的法向量旋转

1.在法向量坐标处添加一个点,并连接两点形成线

[ addprim() ]函数将两点连接成polyline
image-20250804120848669 image-20250804121225487

2.将四元数保存到detail属性

image-20250804121315408

3.创建另一个四元数

以用来在两个四元数(或两个角度)之间平滑的线性插值slerp
image-20250804121607360 image-20250804121613194

4.球面线性插值(slerp)

[ slerp() ]函数 基于偏差值bias==混合两个四元数==
image-20250804122049102 image-20250804122323823

5.用slerp混合后的四元数旋转原法线法向量N

再依据坐标创建两端点并来连接成线
image-20250804122526396 image-20250804122656219
并不是直线,而是创造处弧形,对于两个四元数,旋转轴并不相同
image-20250804122731090

8.运用四元数设置旋转动画 exercise - rotational animation

1.基于不同的四元数依次旋转box并slerp

1.检索detail中的iteration属性作为随机种子 来设置旋转角度

image-20250804123649618

2.检索旋转角度,将其转换为四元数

image-20250804124043626

3.基于迭代次数创建属性

访问迭代次数,保存每一次迭代产生的四元数
image-20250804124247027 image-20250804124349564

4.创建变量

1.创建==range==,这里的range是在完整时间轴上每一次旋转的时间长度(所以用总帧数/循环次数)
2.确定当前帧在当前range的位置,用t 0-1 表示
image-20250804124941754
3.确定当前帧所在的range是第几个range,当前帧数/range(0-num(5)之间)%num(取余num,将最后一个值变为0,即范围 0-4.999 取整则为0-4-0 )
一个0-5的数取余5,始终商0,得到原来的数,除了5,5除5商1,得0,这里==取余的作用在于将最后值变为0==
4.确定下一个range的数 即在当前数加1 由于会大于num 所以取余num将大于的变为0
image-20250804132724952

5.通过当前number和下个number值来确定对应的四元数

基于变量t在两个四元数之间slerp,使用插值的四元数旋转物体

image-20250804133113260 image-20250804133436544 image-20250804133608644

9.二面体定向矢量 orient vector with dihedral

使用四元数将一个向量定向到另一个向量

1.用dihedral计算一个四元数将第一个向量旋转到第二个向量

image-20250804134337859

1.获取向量,计算四元数

[ dihedral() ]函数 计算将向量a旋转到向量b的四元数
image-20250804134739744 image-20250804134919849

2.使用求得的四元数旋转物体

image-20250804135103379 image-20250804135128881

10.运用二面体设置动画 exercise - animation with dihedral

1.设置沿着球体表面螺旋上升的点

1.创建一个在时间轴递增的角度

点在当前位置圆的半径r
image-20250804140250884 image-20250804140458245

2.创建螺旋上升线

image-20250804140531842
旋转圈数,用另一个角度控制
image-20250804140735502

3.设置坐标,更新位置 ,使点螺旋沿着球体上升

image-20250804141625105

2.用动画的点移动几何体,并设置朝向

1.检索动画点位置

2.从几何体上得到平滑的法线方向

使用[ uvsample() ]函数 使用uv属性在特定uv坐标处,对属性值进行插值
依据@P属性在特定位置pos处,对属性N插值
image-20250804142413358 image-20250804143057959

3.用[ dihedral() ]函数创建旋转四元数

将几何体从向上旋转到N方向,再将动画的点坐标加到几何体
image-20250804143613954 image-20250804143556615

15.矩阵 matrix

1.基础 basics

矩阵是一个2D数字网格

image-20250804151321681

1.矩阵类型

使用[ set() ] 函数设置矩阵值

2x2,3x3,4x4矩阵
image-20250804151457227 image-20250804151633003 image-20250804151738591 image-20250804151747211

2.声明 declare matrix

使用另外的方法声明矩阵

1.也可以使用大括号为矩阵赋值,但不能使用变量

image-20250804152047101
等效于创建向量
image-20250804152232510 image-20250804152330089

2.单位矩阵 indentity matrix

1.单位矩阵

单位矩阵作为变换的基础
image-20250804152716954

1.创建单位矩阵

[ ident() ]函数 创建单位矩阵
image-20250804152815480 image-20250804152910385

3. 行列式和逆矩阵 determinant and inverse matrix

1.行列式是再方块矩阵上计算的标量

可以用来==检测矩阵是否有逆矩阵==,为0则没有逆矩阵

==矩阵== 乘以他的 ==逆矩阵== 得到 ==单位矩阵==

image-20250804153313016

2.行列式计算

对角线
image-20250804154342632

1.[ determinant() ] 函数 计算矩阵的行列式

2x2,3x3,4x4的方块矩阵
image-20250804154529497 image-20250804154736519 image-20250804154743942
结果为0,表示该矩阵不具有逆矩阵
image-20250804154918190 image-20250804154924039

2.[ invert() ]函数 创建逆矩阵 inverse matrix

返回逆矩阵或者原始矩阵(当行列式为0)

计算结果,可以通过与原矩阵相乘是否为单位矩阵判断是否是逆矩阵

image-20250804155043740 image-20250804155517966

4. 转置矩阵 transpose matrix

将行变成列

image-20250804171943649 image-20250804172122580

1.[ transpose() ]函数 创建一个矩阵的转置矩阵

image-20250804172218925 image-20250804172314029

5.矩阵与标量的乘法 multiplication with scalar

矩阵乘法有三种

matrix x matrix , matrix x scalar , matrix x vector

1. 矩阵 x 标量

1.矩阵的每个值与标量相乘

image-20250804172805936

2.vex

image-20250804172953453 image-20250804173113864

6.矩阵与矩阵的乘法 multiplication with matrix

左乘不同的矩阵表示进行不同的变换操作,不同的顺序结果不同。

4x4矩阵可以声明所有3D旋转,缩放,移动操作

1.矩阵乘法

行乘以列相加得到对应位置的值

image-20250804180415725

3x3矩阵乘法方式相同

不能交换顺序
矩阵相乘,得到矩阵大小为 第一个矩阵行x第二个矩阵列 3x2 2x3 = 3x3

2.vex

image-20250804183224782 image-20250804183233155

7.矩阵与单位矩阵相乘 multiplication with identity matrix

任何矩阵与单位矩阵相乘 结果不变,即使交换顺序,结果任然不变

image-20250804184200472

1.vex

image-20250804184440439 image-20250804184445860

9.与转置矩阵相乘 multiplication with transpose matrix

image-20250804184622554

1.vex

image-20250804184745894 image-20250804184751874

10.矩阵与向量相乘 multiplication with vector

向量在3D空间中通常用来声明方向或者位置,使用矩阵乘法,是将矩阵作为向量的变换

1.理论

1.将矩阵视为1x3 或者 3x1的矩阵 来进行矩阵乘法

在VEX中,使用行向量,但是使用时交换顺序并不影响结果
image-20250804185423454 image-20250804185634622

2.当使用4x4矩阵时==,向量变成 [x, y, z, 0/1]形式==

这里的 0/1 作为声明,为1时表示作为位置值,为0时表示作为方向值
但在VEX中,这个过程被隐藏,可以直接使用向量乘以矩阵

2.vex

image-20250804190811781 image-20250804190816881

11.矩阵平移 translation matrix

使用4x4矩阵进行==translate (平移)==变换

平移矩阵的形式
image-20250804191435559

1.[ translate() ] 函数 通过向量 ==创建平移变换矩阵==

返回的这个矩阵表示一个平移变换
image-20250804191553543
要点
image-20250804194120910

1.通过向量生成一个平移矩阵,乘以位置即可实现变换

==(使用单位矩阵)==

image-20250804192152504

与直接加上向量结果一样,只有进行更多的矩阵转换时,translate才有优势

image-20250804192521753

12.矩阵缩放 scale matrix

使用4x4矩阵进行==scale (缩放)== 变换

缩放矩阵的形式
image-20250804193352774

1.[ scale() ]函数 通过向量 ==创建一个缩放矩阵==

==(使用单位矩阵)==

image-20250804193631928

1.任然与直接乘以scale向量结果一样.

image-20250804194617220

13.旋转矩阵 rotation matrix

使用矩阵进行==rotate (旋转)== 变换

旋转变换时是对坐标系进行变换
2D空间
image-20250804195324137

1.[ rotate() ]函数 ==创建一个旋转矩阵==

==(使用单位矩阵)==

image-20250804195801305

沿着指定方向创建旋转矩阵,并应用到物体上

image-20250804195953858 image-20250804200011857

14.组合变换矩阵 combine transformation matrix

组合平移(translate),缩放(scale),旋转(rotate) 三种变换.

1.组合矩阵

1.创建变量和单位矩阵,控制变换的角度,旋转轴,平移向量,缩放向量

image-20250804200851305

2.创建组合的变换矩阵 应用变换矩阵

image-20250804201137250

应用的顺序不一样,变换结果也不一样

image-20250804201319742

15.VEX函数 创建变换 maketransform VEX function

[ maketransform() ]函数 ==创建组合变换矩阵==

image-20250804212326078
参数 trs:translate,rotate,scale的顺序
参数 xyz:rotate 的顺序
image-20250804212726298
此函数使用的rotate 是角度
image-20250804212849830

1.生成矩阵

image-20250804213038738

此函数会生成矩阵,不需要使用单位矩阵

image-20250804213149274

16.VEX函数 破解转换 cracktransform VEX function

[ cracktransform() ]函数 ==解构组合矩阵==

image-20250804214228854

1.解构矩阵

以此得到平移,旋转,缩放的值

pivot:轴心点,旋转和缩放操作的中心点
image-20250804214642034

注意:需要知道变换的顺序,旋转的顺序,以及轴心点。

17.运用1 基础变换 exercise - basic transformation

1.通过变换矩阵变换box

这里设置缩放的size时使用cos函数,以达到在一个360°以内按照cos波形变换4次

cos函数:1到0,0到-1,-1到0,0到1
image-20250804220246830 image-20250804220322783

依据时间创建动画

image-20250804220734376

18. 运用2 扭曲和弯曲 exercise2 - twisting and bending

1.基于位置为每个点应用不同的变换

1.创建参数

box高度,扭曲角度,创建弯曲半径,弯曲角度,创建单位矩阵
创建根据位置计算的扭曲角度tang,重映射为0到扭曲角度最大扭曲角度
image-20250804221954821

2.以y轴为扭曲轴 扭曲twisting

应用rotate到矩阵
image-20250804222213751 image-20250804222225076

3.按照高度映射为0到PI,以此sin的波形作为放缩值,取max 设置最小值0.01

应用放缩到矩阵,在xz轴缩放
image-20250804222850623 image-20250804223031238

4.创建弯曲角度,按照高度映射为0到最大弯曲角度

应用rotate到矩阵,以z轴作为弯曲轴
image-20250804225306609 image-20250804225358211

5.创建动画

动画弯曲角度bang
设置弯曲角度加上360°递增,前面映射的时每个点根据位置得到不同值,此时加上的值所有点都一样,所以整体旋转
image-20250804225811413
动画扭曲角度tang
使扭曲动画不断旋转
image-20250804230237109 image-20250804230209253

19.运用3 反转变换 exercise 3 - inverse transformation

1.创建最终变换的逆变换并应用到position

==矩阵== 乘以 ==逆矩阵== 等于 ==单位矩阵==

1.[ invert() ]函数 求逆矩阵,应用到position,即可还原变换

image-20250804231001010 image-20250804231005360

20.二面体函数 dihedral VEX function

在四元数,[ dihedral() ]函数 计算使向量a旋转到向量b的四元数

1.利用[ dihedral() ]函数旋转物体

1.检索两条线的方向

2.创建一个3x3 的旋转矩阵,应用矩阵到position

image-20250804231758465 image-20250804231815982

21. lookat函数 lookat VEX function

[ lookat() ]函数 创建一个变换矩阵,该矩阵旋转一个物体使其局部Z轴指向目标位置

image-20250804232042111

z轴负方向约定

image-20250804232746152

1.

[ polyloft ]节点

image-20250804233459771 image-20250804233552054 image-20250804233613171 image-20250804233624253

创建参数

from,to: 从原点 看向 设置点位置
up:
image-20250804233824510

这里第三个参数使用roll(角度值)

roll可以定向旋转,沿着lookat方向
image-20250804234215104 image-20250804234107718 image-20250804234305901

22.实例化函数 instance VEX function

[ instance() ]函数 创建一个实例变换矩阵

类似[ copy to point ]节点
image-20250804234421640

1.实现类似copy节点的功能

image-20250804234809367

1.放缩设置(copy节点)

在z轴上(这里的实例指向-z,即“长度”)设置按照y方向位置的缩放
image-20250804235143001

2.[ instance() ]函数

image-20250804235600347 image-20250804235605467

用矩阵的好处在于可以利用矩阵创建插值以实现动画效果

从原始位置到复制位置插值

23. 运用4 矩阵插值 exercise4 - matrix interpolation

从一个位置到另一个位置,从一个变换到另一个变换

1.由于矩阵没有直接可以使用的插值函数,==先解构变换矩阵==,==再利用每个变换向量插值==

2.对于==旋转==最好使用==四元数插值(slerp球面线性插值)==

3.最后结合所有变换到矩阵,使用新矩阵进行变换

1.VEX

1. 使用[ cracktransform() ]函数 解构最终变换矩阵

这里的变换顺序可以不一样
image-20250805000943972

2.对于translate和scale可以直接使用[ lerp() ]函数 进行线性插值

image-20250805001242949 image-20250805001323757

3.使用四元数插值旋转

1.使用[ eulertoquaternion() ]函数 将当前旋转值==从Euler度数转换为四元数==
使用的弧度值
2.在(0,0,0)和最终角度的四元数之间==slerp==
image-20250805001859489
3.为了创建最终旋转矩阵,再将==四元数转换回Euler角度==
使用[ quaterniontoeuler() ]函数
image-20250805002313945

4.按照解构时的顺序==创建最终变换矩阵==

image-20250805002452077

随着lerpval(插值的步进值)递增,实现由==原位置到新位置的插值变换==

image-20250805002510669 image-20250805002523956

16.几何体函数 geometry functions

1.基础 basic

使用VEX ,add ,delete geometry(point,primitive,vertices)

points, primitives ,vertices 的关系

functions :near point,minpos, intersect, neighbour

1.创建点 create single point

[ addpoint() ]函数 添加一个point

image-20250805092001195 image-20250805092424762

2.create spiral points 创建螺旋形点

创建角度,创建步长,创建循环

使用三角函数更新坐标

image-20250805092934909 image-20250805092943480

3.创建三角形多边形 create triangle polygon

1.用点画圆

image-20250805093638740

2.用点创建三个间隔120°的三角形点

image-20250805093823721 image-20250805093831286

3. [ addprim() ]函数 创建primitive

image-20250805093951947 image-20250805094053803

创建三角形

image-20250805094231871 image-20250805094253214

4.创建圆锥多边形 create cone polygon

1.创建变量:圆锥半径,高度,点数

image-20250805094855088

2.使用for循环 ,创建圆底面点

创建变量,ang: 每次循环递增的角度,使用三角函数 addpoint
image-20250805095336051 image-20250805095341048
要创建圆锥,依次创建从底面到顶点的三角形面
image-20250805095515932
保存创建的ptnumber到数组,以便创建primitive时使用
image-20250805095830986

3.创建生成 primitives 的for循环

获取当前点和下一个点,对下一个点编号取模 以便当i+1超过点数时变回0
image-20250805100327623
使用[ addprim() ]函数 创建多边形,依据三个点number
image-20250805100442267 image-20250805100608097 image-20250805100629433

5.创建直线 create line

创建两个点,添加polyline

image-20250805103645945

polyilne 和polygon的区别在于,polyline是curve geometry,polygon是封闭的face

==polyline== 也可以说是==未封闭的== ==polygon==

6.创建螺旋线 create spiral polyline

将spiral 点连接成polyline
用已创建的点创建polygon

1.先创建一个空的primitive polyline

image-20250805104449919

2.将点添加到空的primitive

使用[ addvertex() ]函数 为primitive添加顶点
image-20250805104624720
image-20250805104828849 image-20250805104846353

也可以使用数组作为参数,用[ addprim() ]函数 生成polyline

将pt保存到数组中
image-20250805105003370

2.删除点 delete points

1.按半径删除point

1.[ removepoint() ]函数 ==删除点==

image-20250805111751650 image-20250805111902769 image-20250805111910910

3.删除primitives delete primitives

1.按半径删除primitives

[ removeprim() ]函数 ==删除primitives==

image-20250805112115279

这里的 andpoints 参数:==为1== 表示删除与此primitive相关,与其他primitives不相关的点 (即==删除创建这些primitives的点==)

image-20250805112547929 image-20250805112600736

为0时,==保留创建这些primitives的点==

image-20250805112642427 image-20250805112649928

4.从primitive获取point信息 points from primitive

从primitive wrangle检索points信息

1.访问primitives,并从primitives中获得相关点

1.访问primitives中的点,创建窗口

image-20250805113608106

2.[ primpoints() ]函数 返回primitive中点的列表(返回列表数组)

image-20250805113721124 image-20250805114024791 image-20250805113932504

3.访问primitives中的点位置,减去primitive中心位置,得到由中心指向点的方向向量

乘以一个数控制其沿着向量的大小
创建新的点
image-20250805114718599 image-20250805114744871

4.保存新点到数组

image-20250805114956232

注意:这里保存到数组中的点编号并不是最终点编号

[addpoint()] ,[ primpoints() ]函数所返回的点都==不一定是最终编号==

image-20250805130305119 image-20250805130321771

5.创建生成新primitives的for循环

从两个数组中,获取点编号,注意==取余数组长度值==,以免i+1超出数组范围
image-20250805115749641

6.删除原始的primitives

这里的@primnum只是原来的
image-20250805115821457 image-20250805115831343

5.从point获取primitive信息 primitives from points

从point wrangle检索primitives 信息

1.获取一个点相关联的primitives的中心坐标,连接成polygon

[ pointprims() ]函数 返回一个点包含的primitives 列表
image-20250805135015618 image-20250805135548712

1.创建循环,==访问每一个primitives==的位置属性(即中心点位置),以此创建新的点

创建 数组 存储创建的新点编号,这里的数组:每一个点一个大小为3的数组,6个点
image-20250805140007677

2.创建循环,==访问数组中的每一个点==,以此3个点创建四面体的侧边

每次以 ==其中两个点== 加上 ==顶点== 创建多边形
image-20250805140554741

3.在访问primitives,创建新的点后 即可删除原来prim

可以放在这里删除,在wrangle中所有代码==同时运行==(使用当前同样的条件)在所有点上,循环中删除prim并不会影响其他点
image-20250805140658589 image-20250805140808703

6.顶点顺序 vertex order

顶点顺序为顺时针向外,逆时针向内

image-20250805141622027 image-20250805141710425

1.计算朝向

1.计算由原点指向面中心点的方向向量,使其==与法线点乘==,如果结果为正则法线方向向外,为负则反向

[ primvertices() ]函数 返回一个primitive的顶点列表
返回的是==linear vertices index== 是按顺序每个顶点的编号,与spreadsheet中的值不一样
image-20250805142447355 image-20250805142931986

2.创建循环 遍历每个primitives的顶点数组,访问顶点

1.使用[ vertexpoint() ]函数 从linear vertex访问点编号,得到对应的点

image-20250805143404048

2.将得到的点编号存储进数组中

这里创建的数组存储着==每个prim==对应的顶点编号(vts[]),和点编号(pts[])
image-20250805143707418

3.使用[ reverse() ]函数 将数组(或者字符串)反转顺序 并返回

image-20250805144025940

反转每个prim的点顺序 即pts[]数组的顺序

使用[ setprimvertex() ]函数 将vertex重新布线到一个不同的点

这里的如果prim是-1,则vtxofprim是linear index,
image-20250805144457894 image-20250805144855023
等效函数[ setvertexpoint() ]
image-20250805145619376

4.遍历pts数组中的所有点,访问对应的点编号和顶点编号,关联对应的顶点和点

使用linear index

image-20250805145804484 image-20250805145810790

使用 primnum

image-20250805145915249 image-20250805145923090

7.连接近点成线 line with nearpoint / nearpoints

1.[ nearpoint() ]函数 搜索近点 返回编号

[ nearpoints() ]函数 搜索所有的近点 返回编号数组

image-20250805165949056 image-20250805171938946

1.搜索最近的的点并连接两点

image-20250805172032006 image-20250805172108103

2.搜索所有的近点并连接

image-20250805172159129 image-20250805172205423

8. 近点网络 network with nearpoints

1.连接点云中最近的点 创建为网络

image-20250805173519781

==消除重复line==,加一个判断条件 即==@ptnum < npt==, 在==每一个点==的近点数组中,小于当前点的编号的点,已经连接过了(本质上是同时运行,只连接大于当前点编号的点就不会重复)

image-20250805173640636 image-20250805174306436

9.最小距离创建凸面 convex with minpos

1.利用[ minpos() ]函数创建类似的凸形(将球体投影到几何上)

[ minpos() ]函数 返回几何体上最近的位置

与[ nearpoint() ]函数 区别在与近点函数搜索的是==最近的点==,minpos搜索的是最近的==表面位置==

image-20250805174625628 image-20250805174532718

2.vex

image-20250805180742258 image-20250805180753012

10.最小距离创建螺旋分支 spiral branch with minpos

minpos 搜索表面,也可以搜索曲线

1.处理几何体

image-20250805181509875 image-20250805181608071

2.在tube上 scatter 点,搜索最近的点并连线

image-20250805181855314 image-20250805181820431

11.简单的相交 simple intersect

1.[ intersect() ]函数 计算射线与几何体的第一个交点

image-20250805182448651

如果射线与primitive相交,这里的变量会被==世界空间==下的交点位置覆盖

也就是说 &p:是交点位置,&uvw:参数化交点位置(可以与uvsample使用)
image-20250805182801909

返回值为primitive number

2.vex

image-20250805185709781 image-20250805185731690

实例化交点,设置点属性,设置点组

image-20250805190710193 image-20250805190715856

12.用交点函数创建阴影 shadow with intersect

image-20250805191217434

1. 基础设置 ,创建参数,创建光线方向

image-20250805191435037

2.使用[ intersect() ]计算交点

image-20250805191745051 image-20250805191828347 image-20250805191920905

13.邻居的多边形模式 polygonal pattern with neighbours

image-20250805192240004

邻居点 :指的是相连接的临近点

1.[ neighbours() ]函数 返回一个点 相邻点编号 的数组

1.检索每个点的邻居点编号,遍历每一个邻居点检索其位置,计算其与当前点的中间位置并设置为新的点

image-20250805193111501

2.创建多边形

1.先创建一个空的poly prim.

image-20250805193432134

2.使用[ addvertex() ]函数 为中间点连接新顶点,将顶点添加到新的prim

3.删除原有顶点

image-20250805194015113 image-20250805194025505

14.随机行走网络 random walk network with neighbours

1.在网格上检索随机点的邻居

1.随机选取网络中的点

2.当所选点不在==遍历过的点数组(conns[])==中时,先创建一个不带任何点的polyline

3.进入创建ployline的循环

1.将当前点加入到conns数组
image-20250805195629776
2.检索当前点的位置,并创建为新点,设置新点的属性以便识别
image-20250805195814237
3.使用[ addvertex() ] 将该点添加到polyline
4.使用[ neighbours() ] 寻找当前点的neighbours(数组)
遍历邻居点,获取邻居点编号,判断邻居点是否在conns数组中,是则将此邻居点变为下一个选取的点,并使用break==退出 遍历邻居点的循环==
image-20250805200821296
设置检查值,如果邻居点没有遍历过,设置为1
5.如果检查值为1,则退出创建polyline的循环
image-20250805201204360

4.创建大循环,随机选取点,以进入创建polylines的循环

image-20250805201936094 image-20250805201955394 image-20250805202020009 image-20250805202055738

17.内在属性 intrinsic attribute

image-20250805204043867

主要有两类,对primitive,和detail的

1.内在属性的类型 type of intrinsic attribute

不同的primitive类型有不同的内在属性

image-20250805204516891

2.primitive的内在属性 primitive intrinsic attribute(==measuredarea==)

1.measurearea

使用[ primintrinsic() ]函数==访问prim的内在属性==

image-20250805205407794 image-20250805205416883

[ measure ]节点 可以获得同样的数据

image-20250805205601949

对比在wrangle中使用内在属性,使用measure所花费的时间更长一些

3.primitive的内在属性 primitive intrinsic attribute(==measuredvolume== )

1.measurevolume

1.使用 [ attributepromote ]节点 计算求和

image-20250805210310939

2.使用[ measure ]节点计算

image-20250805210822793

4.primitive的内在属性 primitive intrinsic attribute(==bounds==)

1.bounds

表示primitive的边界

访问bounds 属性,创建边界框

image-20250805211512320

计算中心点,和尺寸,设置scale属性,以使用copy节点创建边框

image-20250805211654760 image-20250805211740976

5.detail的内在属性 detail intrinsic attribute(==bounds==)

1.bounds

使用[ detailintrinsic() ] 函数 ==访问detail内在属性==

image-20250805212320965

1.同样计算边界的中心点和尺寸

image-20250805212504410 image-20250805212549154

2.copy to point

image-20250805212612227

6.设置primitive内在属性 set primitive intrinsic attribute(==closed== )

1.closed

指示该primitive是否闭合

image-20250805213036459

[ primintrinsic() ]函数读取内在属性

[ setprimintrinsic() ]函数==写入内在属性==

image-20250805213506350

image-20250805213642131

7.primitive的内在属性 primitive intrinsic attribute (==typeid/typename==)

1.typeid,typename

类型id,类型名
houdini中的primitives有大量的几何类型,不同几何类型有不同的内在属性
image-20250805224343197

[ pointprims() ] 返回每个点的prims列表数组

这里只需要数组第一个元素
使用[ primintrisic() ] 读取内在属性 typeid
image-20250805225333274

利用typeid不同,为不同的类型设置不同运动方式

image-20250805225605915 image-20250805225614242

当一个节点中包含多种不同类型的几何体,就可以使用typeid属性,来==修改特定的几何体==

8.packed几何体的内在属性 intrinsic attribute for ==packed geometry==

image-20250805225941537

packed geometry

1. 使用内在属性变换 packed geometry

对packed geometry,变换点就是变换整个几何体

1.创建一个平移矩阵

image-20250805230418482

2.获取prim的点的位置

使用[ primpoint() ]函数 获取对应prim的点编号
检索对应点的位置。

3.变换点位置,由于是在prim下运行,需要[ setpointattrib() ]设置位置

image-20250805231000933

4.访问内在属性中的pivot(轴心点),作为旋转和缩放的轴心点

image-20250805231550429

5.这里使用创建的旋转矩阵旋转P,只针对点,并没有旋转几何体自身

image-20250805231915622 image-20250805232127319

2.访问内在的transform属性(4x4矩阵),将生成的变换矩阵应用到transform矩阵

[ setprimintrinsic ] 更新内在transform属性,即可实现几何体跟随旋转

image-20250805232558003

设置放缩channel

image-20250805232727893

image-20250805232752919

9.packedtransform函数 packedtransform function

[ packedtransform() ] 函数

image-20250805234715838 image-20250805233003021

变换一个 packed primitive

使用一个4x4变换矩阵来变换

即可得到 与使用内在属性transform矩阵 进行变换 一样的结果

image-20250805233149856

10.setpackedtrandform函数 setpackedtransform function

[ setpackedtransform() ] 函数

image-20250805234320574

设置packed primitive 的变换

1.与 packedtransform的 区别在于 setpackedtransform 会先将轴心点放到原点

image-20250805233952732

11.getpackedtransform函数 getpackedtransform function

[ getpackedtransform() ] 函数

image-20250805234412253

获取 packed primitive 的变换

image-20250805235143046

与生成的变换矩阵相比

image-20250805235121579

12.运用 packed geometry变换 exercise - packed geometry transformation

1.打包一个 破碎

image-20250805235642873

上色

image-20250805235716033

2.获取每个primitive的pivot,并以此为旋转中心旋转

生成变换矩阵

使用[ packedtransform() ]函数 需要先平移到0点
image-20250806000240059 image-20250806000244949
再移动回原来位置,在两个平移变换之间旋转变换
image-20250806000411114 image-20250806000417010

旋转:创建随机的旋转轴

image-20250806000604159
[ sample_sphere_uniform() ]函数 在球体表面随机生成点
image-20250806000713289 image-20250806000907489

3.向外平移

创建方向向量,并应用到变换矩阵

image-20250806001717838 image-20250806001752383

设置每个碎片不同的移动速度

即为方向向量添加一个随机乘数
image-20250806001900707 image-20250806001951714

18.随机 randomness

1.使用种子随机 randomness with seed

image-20250806091613851

[ rand() ] 函数

生成的值位于0到1
image-20250806091912882

获取随机值

1.[ rand() ]函数创建一个vector4, 再根据需要的值类型修剪

image-20250806092208243 image-20250806092216494 image-20250806092544236 image-20250806092551765

2. 可变种子值的随机 rand with various seeds

1.使用位置作为种子

image-20250806092935090 image-20250806092940557

使用ptnum属性,也可以为每个点随机不同的颜色

image-20250806093116652

2.为每个面设置颜色

使用primnum作为seed
image-20250806093308004 image-20250806093315979

3.foreach 节点内的随机函数 rand function inside foreach node

1.foreach 循环中为每个pieces设置随机值

使用迭代次数 iteration,区分不同pieces

1.创建metadata,以获取detail属性 iteration

image-20250806093939139 image-20250806094112909 image-20250806094122043
2.设置偏移seed
image-20250806094202526

4.循环中的随机函数 rand function in loop

1.创建循环,生成点,设置随机scale属性

image-20250806101750713

copy to point

image-20250806101836754

5.运用1 exercise - function exercise1

控制百分比

1.按比例选取一部分点

随机值在0到1内平均分配,即可通过选取特定范围的的随机值来选取对应百分比的点云
image-20250806102717336

1.vex

image-20250806103549955 image-20250806103557366

2.检查点数,创建一个detail计数属性

==设置detail属性,使用"add"模式==
image-20250806103747061 image-20250806103819622

6.运用2 exercise - rand function exercise2

基于随机的渐变

1.基于位置设置种子

越往下有更多的机会得到红色值
这里是使用当前高度与随机值相比,高度越高,高于当前位置的随机值就越多
image-20250806104329548 image-20250806104341451

7.运用3 exercise - rand function exercise3

使用ramp控制随机值的生成,来控制渐变

1.使用ramp映射随机值,即可通过控制曲线控制映射

image-20250806111118429 image-20250806111202572

8.运用4 exercise - rand function exercise4

对时间偏移量进行随机

1.使用正弦函数(随机时间偏移)控制scale球体大小

控制pscale属性

1.依据时间轴设置0-360°的递进

image-20250806112033506

2.使用步进值的正弦值,重新映射到新的pscale值

image-20250806112124997 image-20250806112500508

3.为步进值设置随机偏移

image-20250806112439433 image-20250806112448600

4.为周期值设置随机值,以获得不同的动画速度

同样的时间长度,一个点的动画周期越多,动画速度越快
创建随机值时 使用[ ceil() ]函数向上取整,获得1到4的随机周期范围
image-20250806113413364 image-20250806113441629

5. 跟随pscale大小变化 改变颜色

image-20250806113541353 image-20250806113549526

9.非确定性随机 non - deterministic randomness

不需要使用seed值

[ nrandom() ]函数 获取0-1的随机值 不需要seed

可以设置不同的随机方法
image-20250806113928762

1.直接使用

每一次运行会产生不同的随机值
image-20250806114429511 image-20250806114442684

2.nrandom函数运用 nrandom exercise

在for循环内部使用,每次循环会产生不同的随机值

1.使用for循环创建立方体点阵

image-20250806115449836 image-20250806115517087

2.为每个点设置随机颜色,和pscale属性

image-20250806115619145 image-20250806115637610

10.随机函数 random function

[ random() ]函数 基于在1-4D空间中的位置生成随机数

image-20250806115910588
random函数 会将position==向下取整== noise(floor(position))以此获得随机值
同样获得0-1的值,但是整数变化随机

1.通过random改变点的高度

image-20250806121032338 image-20250806121048970

11. 随机分配 random distribution with rand

[ random_brj() ] 生成均匀的随机分布

image-20250806123133229

[ random_sobol() ] 生成均匀的随机分布

image-20250806123150953

1.在直线方向上 随机生成点

1.使用[ rand() ] 来分布点

image-20250806123445792 image-20250806123552314
并非均匀

2.使用[ random_brj() ] 分布点

==不同的种子生成不同的序列,offset提取序列中不同的条目==
所有点使用一个seed值,但offset值依据每个点变化,以此为所有点生成均匀的分布
image-20250806123916685 image-20250806124027505

3.使用[ random_sobol() ] 分布点 生成更加均匀的分布

参数与random_brj函数相同
seed生成不同的序列,offset提取序列中不同的条目
image-20250806124602504 image-20250806124608637

12.向量分布 vector distribution with random_sobol

使用[ random_sobol() ] 随机分布向量

使用[ sample_sphere_uniform() ]函数创建一个方向

1.使用[rand() ]生成随机向量

1.创建循环,生成点

1.使用[ rand() ] 生成随机向量
2.利用随机向量 使用[ sample_sphere_uniform() ]生成随机方向(大小并不一样)
3.以此向量作为坐标生成点
image-20250806125655699 image-20250806125726803
4.连接点到原点
[ addorim() ] 添加polyline
image-20250806125806982 image-20250806125848152

2.使用[ random_sobol() ] 随机分布生成随机向量

image-20250806130133323 image-20250806130140020

19.噪波 noise

noise是梯度噪波,距离越近,值也越接近

image-20250806145850246

不同的噪波使用不同的方法生成数字

1.柏林噪波 perlin nosie

生成1-3D 的noise值 范围为0-1

image-20250806150257844

[ noise() ]函数 基于==perlin噪波==

image-20250806150415433

1.基于位置使用[ nosie() ]

image-20250806151320417 image-20250806151347066

通过改变传入的位置(设置一个==乘数==),即可对特定方向==拉伸==修改

位置信息乘以一个乘数则是对整个噪波的图案的放缩
image-20250806151826411 image-20250806151835914

2.柏林噪波的移动 shifting for perlin noise

在位置上==加上==偏移量

1.

image-20250806154307746

对于2D网格,没有y方向,即可使用y方向上的偏移改变整个图形(作为动画效果)

3.单形噪波 simplex noise

基于perlin噪波的更新版本,非常接近柏林噪波

[ xnoise ]函数 基于==simplex噪波==

image-20250806155138525

比柏林噪波更平滑

1.用法与[ noise() ] 一致

image-20250806155703913

4.运用1 柏林噪波 perlin noise exercise1

1.生成噪波改变网格的y位置

image-20250806160206936 image-20250806160223658

2.将噪波值保存为属性,以设置渐变颜色

image-20250806160419485 image-20250806160320474

3.为每个点设置pscale,

image-20250806160549523
1.这里的噪波值位于大概0.25-0.75之间,不同于[rand()] (0到1之间均匀分布),
image-20250806160911522 image-20250806160646596
2.使用噪波值 重映射pscale
image-20250806161056433

4. copy to point

image-20250806161237661

5.运用2 柏林噪波 perlin noise exercise2

1.创建螺旋线,使用噪波控制最终管道的厚度

在直线上

image-20250806162748127

1.创建spiral

1.依据ptnum , 创建角度(随着ptnum依次增大)
2.创建半径
3.在xz平面旋转,使用三角函数更新xz轴,y轴坐标保持不变
image-20250806162910289 image-20250806162916081

2. 以ptnum 为参数 为每个点创建基于噪波的pscale属性

使用[ polywire ] 节点
使用表达式函数读取pscale ,这里的[ opinput() ]表达式函数 ,==$PT = ptnum==
image-20250806163426406 image-20250806163308065
为pscale创建随机值
image-20250806165303294 image-20250806165313105

3.设置动画在noise设置随时间移动的偏移值

image-20250806165412341

4.使用noise改变颜色

6.运用3 perlin noise exercise3

使用矢量值作为输出

1.使用[ noise() ]改变表面颜色

1.使用[ noise() ]输出向量,为每个点改变颜色

image-20250806165817288 image-20250806165828193
颜色比较淡,在于[ noise() ]函数输出的值范围在0.25到0.75左右,于float输出一致

2.将噪波输出值clamp,并重映射到0-1

image-20250806170221145 image-20250806170230285
对其他几何体也适用
image-20250806170919107

3.动画颜色的变化

1.由于球体的每个坐标轴都被用到,在轴上的设置偏移 只会产生噪波==平移效果==
image-20250806171059424
2.如果想要所有==颜色逐渐变化==,而没有朝向,需要==附加轴来进行偏移==
可以使用==vector4==作为输入,即==为3D坐标添加一个轴==,来动画颜色变化
image-20250806171410985
3.使用vector4作为[ noise() ]的输入,即可通过控制第四个参数的偏移控制颜色渐变(没有方向性)
image-20250806171658391 image-20250806171736626

7.运用4 perlin nosie exercise4

1.使用[ noise() ] 在表面上创造涟漪效果

1.使用位置信息生成vector4向量,再以此为参数生成一个float噪波

将此float噪波作为颜色噪波
image-20250806172848734 image-20250806172853572

2.将此float噪波作为三角函数参数,以此将点沿着法线方向移动

1.将此float值映射为角度
image-20250806173205064
sin函数有负值
image-20250806173256981
2.以此噪波值将点沿着法线移动
image-20250806175856780
设置波浪数量
image-20250806180157922 image-20250806180038471

8.周期噪波 periodic noise

同样基于 perlin 噪波

由于周期性,可以生成无缝的图案模式,以此生成无限大的噪声比例

以一个模式不断重复平铺,边缘处采用梯度平滑值

1.[ pnpise() ]函数

perlin函数有两种形式:其一是在整个N维空间随机变化的非周期性噪波,另一种就是[ pnoise() ]使用的形式,在==给定空间范围==内==重复==的==周期性==形式

image-20250806181239102
px,py,pz,pt指的是周期性平铺的尺寸,pt基于时间

2.使用[ pnoise() ]函数

image-20250806182529613 image-20250806182544132

9.运用 周期噪波 periodic noise exercise

1.创建三维的重复模式

1.使用volum

这里使用P 乘以 tile尺寸的原因在于,当tile尺寸变大时,需要更大的box装原本的tile个数,这里使用点的位置乘以tile尺寸大小,当tile尺寸增大时,整体尺寸变小相同的倍数.
即一个box范围内始终装ts乘ts乘ts个
==P乘以乘数对波形模式产生放缩作用==
image-20250806183500211

注意:是在三维空间给定位置P采样,当坐标P乘以一个数变大时,采样点坐标彼此之间距离变大,即得到更大范围的噪波模式

这里假设有一个固定的噪波场,输入坐标变大,即采样更大范围的噪波场

2.使用[ convertvolume ]节点转换回多边形

image-20250806191716567 image-20250806191709651

3.使用大小为1的box剪切单个模式

image-20250806191859855

4.以此模式在xyz轴重复

创建三层循环(对每一个轴)来生成点阵
image-20250806192311879
copy to point
image-20250806192254553

5.创建vector4,来控制模式变化

控制时间偏移 设置偏移值在时间轴内由0-1变化(FF/ENDF) 创建==可循环的动画==
image-20250806192747753
即可 依据时间轴变化
image-20250806192818107

10.流体噪波 flow noise

noise和periodic noise 混合的噪波 ==flow noise==

[ flownosie() ] 生成1D 或者3D流噪波

image-20250806193418895
区别在于这时非周期noise ,flow参数是周期的(0-1),可以看作是特殊的pnoise
与[pnoise()]相比,相当于px,py,pz为0,pt为1

用于创建一个==非周期性的模式==pattern,但是基于时间回到最初的时间(创建==基于时间的循环==)

flow参数作为重复值(作为基于时间的值重复动画)

1.创建在时间轴上可连接的重复向量场

1.创建volume

创建位置信息,创建shift偏移值
image-20250806194931874

2.使用[ flownoise() ]函数 基于pos,shift生成随机方向向量

image-20250806195111743
设置shift,依据时间轴从0到1变化,最后一帧将与第一帧相连接
image-20250806195241028 image-20250806195434779

3.由于生成的值都在0-1之间

将生成的向量减去0.5,获得全方向的向量
image-20250806195659087 image-20250806195735706

11. 卷曲噪波 curl noise

[curlnoise()] 基于perlin噪波计算==无发散噪波==

只能创建向量值,通常用于创建矢量场相关的值
根据两个perlin noise的导数的叉积计算的无发散矢量场
image-20250806210935928

divergence free vector field 无发散矢量场:

无发散:在矢量场中,散度(divergence)衡量场中某点作为源或者汇的强度,无发散指的是矢量场在任意点都没有源或者汇==.矢量线不会从某点产生或者消失==,而是形成==闭合回路==或者==无限延伸==.
因此:适用于生成自然漩涡结构,创建符合真实流体基本物理规律的流体模拟,烟雾模拟
image-20250806214851912

1.创建向量场

1.以vector4作为输入,生成curl noise向量值

image-20250806211259524
生成的向量场更干净(无发散矢量场)
image-20250806211445196

12. 沃利噪波 worley noise

基于cellular(细胞)的噪波函数

基于空间划分的算法,在空间中随机分布一组特征点(称为种子点或特征点),然后对于空间中的任意位置,==计算其到最近几个特征点的距离==,并用这些距离值来生成纹理。

houdini中有三种内部算法

使用不同的方法计算两点之间的距离(Euclidean,Manhattan,chebyshev)
image-20250806215524701

工作方式:

提供位置信息作为样本,在空间中创建随机的种子位置,对于空间中任意位置,所计算的到最近几个种子点的距离用f1-f4表示,
image-20250806221655246

距离算法:

Euclidean:计算直接距离,所得到的距离渐变是圆形
Manhattan:计算x+y+z,得到距离比Euclidean长
chebyshev:各坐标数值差的最大值
image-20250806222057615

这个算法也可以从特征点而非像素点的角度理解。在那种情况下,算法可以表述为:每个特征点向外扩张生长,直到它碰到其它扩张的区域。这反映了自然界的生长规则。生命的形态是由内部扩张、生长的力量和限制性的外部力量共同决定的。模拟这种行为的算法以 Georgy Voronoi 命名。

1.[ wnoise() ] 函数

image-20250806222311203

1.使用[ wnoise() ]函数

image-20250806222713624 image-20250806222719916

2.依据seed值设置随机颜色

image-20250806223059958

13.运用 worley噪波 worley noise exercise

1.创建海洋外观

1.创建变量

image-20250806225029024

2.使用 [wnoise()]

image-20250806225121003

3.使用组合距离更新点的y值

image-20250806225214850 image-20250806225309699

4.设置偏差值,依据时间从0-1,即可实现首位帧循环

image-20250806225351765

5.更改颜色

image-20250806225557280

14.Manhattan worley噪波 Manhattan worley noise

[ mwnoise() ] 函数

参数与wnoise一样

1.使用[ mwnoise() ] 函数

image-20250806225901243

2.chebyshev worley噪波 chebyshev worley noise

使用[ cwnoise() ] 函数

image-20250806230234810

15.短吻鳄噪波 alligator noise

alligator noise 短吻鳄噪波

[ anoise() ]函数
image-20250806230403274
生成类似worley noise的细胞噪波,更适合创建海洋效果

1.使用[ anoise() ] 函数

创建变量

image-20250806231524125 image-20250806231537122

去掉scale

image-20250806231710157

设置为负

image-20250806231755396

上色

image-20250806232104517

copy to point

image-20250806232233158

16.voronoi 噪波 voronoi noise

1.[ vnoise() ]函数

image-20250806232712293

可以产生抖动,只有F1,F2,可以获取种子点的位置,同样可以设置周期重复

image-20250806232753486

2.VEX

创建参数

使用[ vnoise() ] 函数

使用输出值改变P.y

F1
image-20250806233054248
设置jitter 范围为0-1
image-20250806233200860
F2-F1
image-20250806233254580
使用seed设置颜色
image-20250806233311185
查看position 1 种子点1 (细胞中心点1)
image-20250806233548458 image-20250806233553835

相对比voronoi节点,产生一样的模式

image-20250806233752475

17.运用 vornoni噪波 voronoi nosie exercise

1.使用voronoi 在volume上分区

1.创建两个volume ,seed和density用以分别在体素上存储seed值,和通过voronoi计算得到值density

2.合并

3.VEX

1.更新seed值,
可以通过内置属性查看volume值的最大最小值
image-20250806234352379
2.利用seed在单元格之间创建分区,作为墙壁分区
检查像素点的种子值,边界点的seed不一样
image-20250806234755030
3.先设置density = 0
4.通过体素的index检索值
image-20250806235011396
5.检查x方向上的体素,下一个索引值即使邻居,如果和邻居的seed值不一样,则是设置为边界
image-20250806235145262 image-20250806235330582
6.使用循环检查x正负方向上的体素
image-20250806235603449 image-20250806235907977
7.创建三层循环,以检查y,z正负方向的体素
image-20250806235752974
8.为每个轴并一个条件以不检查最后一个体素以去掉边框,即索引值小于分辨率减1
image-20250806235846789 image-20250807000204528

4.[volumeblur] 平滑volume

image-20250807000300720

5.转换为表面

image-20250807000329269

20.解算基础 solver

基于==帧反馈==的处理系统

image-20250807080139253

1.基础平移 base translation

1.solver

每一帧都以上一帧的位置作为初始位置移动

2.移动和旋转

创建矩阵进行旋转

image-20250807081919653

trail 生成拖尾 polyline

image-20250807082153212 image-20250807082202125

2.基础生长 basic growth

1.

1.先创建一个空的polyline

image-20250807100245115

2.solver

在原来的位置添加点,相当于将原来的点冻结,形成trial尾迹,由于这里的group指定move,代码只影响组中的点,生成的这些点并不影响
image-20250807100746295 image-20250807100944509

3.在物体表面流动的向量 vector flow on object

1.使用[ curlnoise2d() ]函数 控制点在物体表面流动

1.使用[ curlnoise2d() ] 函数 生成 ==2D的curl noise==(2d的无发散噪波)

image-20250807102147535 image-20250807102021487 image-20250807102631329
生成的向量并没有沿着物体表面( ==生成的向量都位于xy平面==)
image-20250807102202583

2.使用[ dihedral() ] 二面体函数 生成将噪波向量旋转到表面的矩阵

z方向相当于这个噪波所在==xy平面的法向==,沿着表面流动的向量应该垂直于==物体的法线方向==,将z方向(xy平面法向)对齐物体法向,则xy平面的向量对齐流动的向量
假设表面切向为T,物体法向为N,N与T垂直.噪波方向为C. Z轴方向与其垂直,则当Z与N平行时,C与T也平行
T ⊥ ==N==, C ⊥ ==Z== ---> 当Z与N平行时, C与T也平行. 即将垂直于噪波的方向对齐到物体法向,噪波也将对齐物体切向 (使用同样的变换)
image-20250807102503513
这里生成对应的旋转矩阵,应用到噪波向量,即可使噪波向量沿着物体表面
image-20250807124604829

3.使用scatter的点在矢量场上采样

1.为每个点设置随机life
image-20250807124842075
2.使用[ ray ]节点,即可从表面上的点位置对向量场采样
image-20250807125337639 image-20250807125120093
3.即使向量场的数量很少,通过采样矢量场的中间位置,可以创建一个平滑的矢量场
image-20250807125222395 image-20250807125231926

4.点移动 解算 solver

1.连接solver
image-20250807125603625
2.更新点的位置(加上法线向量,即噪波)
image-20250807125810881
3.减去生命值,设置条件,生命值小于0时,删除对应点
image-20250807125926234
4.将点投射到表面,采样法线方向
image-20250807130058500 image-20250807130233780
5. 在随机位置生成点,以便总数不变
使用[ uvsample() ] 函数 根据uv属性在物体表面 采样随机位置
image-20250807130521235
依据位置所生成的随机向量(==其值在0-1范围==),将此向量作为uv坐标,在物体的==uv属性==中==查找对应的uv坐标==(ruv),对于点或者顶点属性,从周围点==插值==后返回插值的属性(这里是P,三维位置)
这里的pighead自带二维的uv属性(通常uv坐标只有两个分量,这里第三个分量为0,表示其为二维uv坐标,在houdini中一般存储为vector,即三维向量,对于二维uv并不使用第三个分量),其值==范围为0-1==,这里使用三维向量ruv作为uv坐标查找时,会自动忽略第三个分量
image-20250807132901427
6.为新生成的点设置生命值
image-20250807131125844
当有点死亡时,在表面随机位置生成新的点,保持总数
image-20250807135210783

5.可视化 设置颜色

1.检索的所有点指定距离的所有近点,计数近点数量
image-20250807135544603
2.使用[ attribpromote ]节点 找到最大值,以设置颜色值的范围
image-20250807135714682 image-20250807135729418
3.使用近点数量来设置颜色(衡量点的密度)
image-20250807135800655 image-20250807135949885
==将以上步骤的着色代码放到solver中,加快计算速度==
image-20250807140108133

4.生成拖尾

在当前点位置的法线N反方向添加点,在连接成polyline,设置为同样的颜色
image-20250807140432534
image-20250807140504571

4. 在volume内流动的向量 vector flow inside volume

1.使用[ curlnoise() ]函数 控制点在volume中流动

1.创建volume velocity

image-20250807142550093

2.生成curl noise

1.创建vector4,使用时间控制第四个分量,以此创建动画
image-20250807142815430
2. 用4维向量 生成3D curlnoise,以此更新velocity值
image-20250807142942549 image-20250807143046159
使用[ volumetrail ]节点可视化
image-20250807143135190

3.解算 solver, 基于volume中的velocity向量移动点

image-20250807143251083
1.根据每个点当前的位置从volume中采样一个方向,并以此方向更新点的位置
[ volumesamplev() ]函数 对volume的矢量值采样
image-20250807143721150
image-20250807143810446
超出volume的点将会停止移动
image-20250807143927647
2.将停止移动(或速度很小)的点删除,并在volume内随机随机生成新的点(或者==将其移动到volume中的其他位置==)
rand()生成一个随机向量(值的范围为0-1),所以需要为每个分量减去0.5.==更新当前点的位置到随机位置==
image-20250807144700089 image-20250807144847322

3.创建拖尾

1.以每个点的方向反向创建polyline
image-20250807145235919 image-20250807145225523 image-20250807145311162

4.设置颜色

同样使用近点数量来设置颜色(衡量点的密度)
image-20250807145426536

5. 几何修改 geometrical modification

使用sub solver在给定几何体上雕刻轨迹

实际上仍然是修改点,再用点生成primitives

[ sample_sphere_uniform() ] 函数 给定向量u,在单位球体生成对应的点

将传入参数u的xyz分量分别作为对应==球坐标系==的方位角,极角,半径
如果给定的随机向量u均匀随机(其值为0-1),则生成的向量相对于单位球体内均匀随机

1.球坐标系

image-20250807154258869 image-20250807154335455

2.示例

1.在[ sample_sphere_uniform() ]函数中 u.x对应方位角φ, u.y对应极角θ, u.z对应半径r
image-20250807155841905
2.x轴分量控制方位角(0-360°), y轴分量控制极角(倾角0-180°), z轴分量控制半径

image-20250807155852489

1.使用solver修改球体

image-20250807153630698
在球体上创建路径,再通过路径生成雕刻线条

1. 创建参数

1.基于时间创建x分量,范围为0-1循环,控制方位角,对应范围是0-360°
由于范围是0-360°,可以使用取余使大于1的值变为0,0°与360°是连接的
2.基于时间使用正弦波,映射到0-1,作为y分量
由于y分量控制极角,对应范围为0-180°,无法使用取余获得循环,这里使用重映射的正弦波
image-20250807163401850

2.使用[ sample_sphere_uniform() ]函数 获得对应球面上的点向量dir(设置半径为1)

image-20250807163747063

3.计算 向量dir 到 球体当前点@P 的距离

设置搜索半径rad,限制距离值
将距离值 从0-rad 重映射 到1-0, 球体上到向量点越近的点影响越大
image-20250807164524708

4.使用距离值 在点上以法线方向@N更新位置

image-20250807164546515 image-20250807164740840

6.基础分形 basic fractal

1.类似l-system的分形

设置方向vel ,分组last

image-20250807165445928

2.solver

1.更新点位置,沿着方向val移动,创建新点
2.将两点连接成线
image-20250807165728873
3.将新生成的点加入last分组以作为下一次移动点时的基础,将原本组中的点移除
设置为0移除,设置为1加入
image-20250807165935332
4.设置新点的速度vel
image-20250807170307783
无限向上生长
image-20250807170352151

3.设置分支

image-20250807190904157 image-20250807170531396
1.依据当前帧取余,每一定帧范围生成一次分支,这里每20帧生成一次分支
image-20250807170654228
2.设置循环以生成正负方向的旋转矩阵
image-20250807170752510
3.用旋转矩阵更新速度vel的值(设置绕z轴旋转)
image-20250807170916070
4.以此速度值vel作为位置设置新的点,和线
image-20250807171152262
5.将新点加入到last组中,移除原来的点
image-20250807171430604
6.为新点设置新的vel属性
image-20250807171406574 image-20250807171508783 image-20250807191210931

4.基于三角函数改变旋转轴

image-20250807192828937 image-20250807192908143 image-20250807192941871

7. 链式解算 chained solver

类似弹跳框中的弹跳框
image-20250807193256711

1.创建第一个求解器

1.为primitives添加法线

image-20250807193501517

2.设置弹跳点的属性

image-20250807193644830
1.用rand()生成随机向量,减去0.5
2.将生成的向量归一化,乘以一个速度值,保存到N属性
image-20250807193914378

3.在solver中设置反弹函数

image-20250807194231154
1.设置沿N方向更新点的位置,即向随机生成的向量方向移动
image-20250807194321700

4.确定点是否在盒子内部,使用点乘计算

1.计算点乘: 盒子的法向量N,与点指向其在盒子上投影点的向量dir,大于0则在内测
image-20250807194753283
1.找到最近距离的点
1.使用[ xyzdist() ]函数 查找从点到曲面几何==最近位置==的==距离==.,函数返回的是float距离值
其输出参数prim,uv,则存储着最近位置的primnum,和对应的uv坐标
image-20250807195242882
2.使用[ primuv() ]函数 使用prim,uv坐标 读取属性N 和P
对于点和顶点属性,给定uv坐标处的值将从周围点插值
image-20250807200247713 image-20250807200120759
2.计算点乘判断是否在内部

5.==当检测到点在盒子外侧时== 设置反射方向

先反向,在以盒子法线N为轴旋转180°.得到反射方向
image-20250807201023148
1.通过创建旋转矩阵,以法线norm为轴旋转180°,更新新的N方向.
image-20250807201233758
2.更新新位置(加上新的方向向量)
这里的语句仅在点==刚飞出盒子==的第一帧运行,即检测到点在外测,==将原来的运动方向更新为其反射方向==,设置这一帧的新位置为最近点位置加上新的运动方向.
image-20250807201753267 image-20250807202156954

6.以点为中心 copy球体

image-20250807202715946

2.以反弹的球体作为另一个盒子

在更小的volume球体内部scatter点,以防止超出球体边界
image-20250807203149716

1.设置属性

1.为每个点生成随机方向
image-20250807203328770
2.设置pscale用于点与点之间的碰撞

3.创建新的求解器

image-20250807203831420

4.为每个点设置反射

1.使用[ nearpoints() ]为每个点搜索两个最近点(其中一个是自身)

由于当在==一个点云==中以其中的每个点的位置来搜索,会将这个点本身也算在内
image-20250807205211836

2.当数组长度为2(搜索到除自己意外的最近点)

获取最近点的位置,最大搜索距离设置为2倍pscale(一个pscale是半径,2倍则为直径)
image-20250807205646889

3.设置反射矢量,更新运动方向

使用当前点指向近点作为作为方向矢量dir,先反向 再以此为轴旋转180°, 得到反射向量
更新新的运动方向属性, 更新此时位置:基于近点位置npos,沿dir方向的两倍半径距离,加上新的方向向量
image-20250807210647346

4.在开始移动位置

image-20250807211200246

5.以上一个球体作为边界反弹

1.检测小球是否接触到大球的边界

判断小球在最近点方向上一个半径长度的位置 如果在边框之外即发生碰撞
这里的 normalize(pos-@P)*fpscale,即指向最近点的大小为半径的向量
加上@P (当前小球中心的位置),==ppos即为小球边界点位置向量==.
dir向量则为小球边界点指向大球边界点的向量,在内部时,指向外,外部时,指向内
当判断ppos点处于外侧时,更新位置:基于近点位置,沿dir方向移动一倍半径,加上新的运动向量
image-20250807213302287

6.设置颜色,Alpha

image-20250807215009826

21.half-edge 翼边/半边

将将面视为==每个面都有自己的边==。

image-20250808110629298
1.半边都是定向的,一个起点顶点,一个终点顶点
2.一个顶点只能属于一个prim,所以一个顶点最多只有一个以其作为源的半边
image-20250808103750337
翼边的顺序决定法线方向
可以通过对应两点检索两点之间的翼边,可以通过prim检索翼边,也可以通过当前翼边编号检索下一个翼边,检索共享边
image-20250808104909663

在检索网络中,设置细分等非常有用

1.从点获取翼边1 halt-edge from point1

[ pointhedge() ]函数 从给定点 或者 给定点和终点 来获取翼边

只给定一个点时,==将此点作为源点==,检索其对应的半边
image-20250808105411894

1.使用[ pointhedge() ]函数 ==以单个点(源点)获取半边==

这里的半边的编号是唯一的
image-20250808110939811 image-20250808111008224

2.从半边获取其源点和终点

1.从半边获取其源点

[ hedge_srcpoint() ]函数 ==获取源点==
image-20250808111539849

2.从半边获取其终点

[ hedge_dstpoint() ]函数 ==获取终点==
image-20250808122037799 image-20250808111805810 image-20250808112005360

2.从点获取翼边2 half - edge from point2

1.使用[ pointhedge() ]函数 ==以源点和终点获取半边==

可以只使用一个源点编号
image-20250808113044955 image-20250808113056146

1.[ pointedge ]函数 给定两个端点(无需给定顺序)获取半边

当这两个端点只有一个半边时,不考虑参数顺序。当端点有两个半边时,则考虑参数的顺序

3.检查半边的有效性 check half-edge validity

1.检查半边num是否有效(存在)

[ hedge_isvalid() ] 函数检查半边number是否是有效的半边

image-20250808115350485

4.下一个或前一个半边 next/previous half-edge

[ hedge_next() ]函数 返回下一个半边的编号

image-20250808122004786

[ hedge_prev() ]函数 返回上一个半边的编号

image-20250808122016197

1.获取以每个为源点的半边,找到其下一个半边,再检索下一个半边的起点和终点

image-20250808122250630

2.找到其上一个半边,再检索上一个半边的起点和终点

image-20250808122637762

5.下一个等效的半边 next equivalent half-edge

从一个prim的共享边的半边检索另一个半边

1.检索一个半边的等效半边

[ hedge_nextequiv() ]函数 检索与 给定半边 等效的半边
image-20250808130209111 image-20250808131209370

6.运用 对偶网格 exercise - dual mesh

对偶网格是将原始网格进行拓扑转换得到的新网格

将原始网格的面中心点转换为新网格的顶点,原始网格的顶点对应新网格的面
这里三角面网格的对偶网格是六边形网格
image-20250808131518620

1.vex计算对偶网格

[divide]节点有计算对偶网格功能
image-20250808133455968

1.先找以每个点为起点的半边,计算每个点的邻居数(等于每个点对应的prim数)

2.以此创建循环

1.检测半边的prim,获取其位置信息(prim的位置P,即中心点)
[ hedge_prim() ]函数 返回半边的prim
image-20250808142021888
2.在中心位置添加新点
image-20250808142449175
3.检索当前半边的上一个半边
4.检索前一个半边的共享的另一个半边(这个半边将以当前点为起点),并作为下一次循环的半边
image-20250808142952076 image-20250808143056211

3.连接这些点

1.在循环外先创建一个空的poly
2.循环中将点连接到顶点
image-20250808143244989
3.删除当前点
image-20250808143441691 image-20250808143446982
删除prim: 找到所有点对应的prim,foreach循环遍历数组中的项
image-20250808144442146

7.运用 网格细分 exercise - mesh subdivision

获取一个prim和其相邻prim的中点位置,并与源点连接为三角形

image-20250808145937705

[ primhedge() ]函数 获得prim的其中一个半边

image-20250808161047095

[ pointhedgenext ]函数 返回与给定半边有相同源点的半边(连续调用可以返回此源点对应的所有半边)

image-20250808161622063

1.先获取当前prim上的一个半边

2.不断调用[ hedge_next() ]函数获取当前prim上一个半边的下一个半边

产生顺序

image-20250808162150981

3.设置点

1.先在prim中心添加新的点

image-20250808163007390

2.根据 当前半边 检索等效的半边(共享边的另一侧,即邻居prim的半边)

3.在根据这个==等效半边==使用 [ hedge_prim() ]函数 检索出邻居prims的编号

image-20250808163641154

4.检索邻居prims的位置信息,并添加新的点

image-20250808163922554

5.检索 ==当前半边的源点== (或者等效边的目标点),以此三个点连接为新的prims

使用[ addprim() ]函数 根据三个点创建多边形(直接创建)
image-20250808164206781 image-20250808164530614

4.删除原来的prims

image-20250808164511631 image-20250808164517212

8.运用 网格斜角 exercise - mesh bevel

image-20250808165011542

1.倒角

1.先检索(以当前点为源点)的一个半边

2.计数当前点的邻居数

3.创建循环

1.使用[ hedge_dstpoint() ]函数 检索半边的目标点
image-20250808165950904
2.检索目标点的位置信息
3.创建介于两点之间的位置,使用当前点位置加上指向目标点的向量乘以比例
image-20250808170243182
4.添加新的点
image-20250808170405241
5,检索当前半边的上一个半边,在检索上一个半边的等效半边 以等效半边作为下一次循环的半边
image-20250808170823959

4.添加新的多边形,使用先在循环外添加空的prim,再在循环中添加顶点的方式

因为循环中不能同时得到三个新点的坐标,但循环是按照顺序来的,依次添加顶点
image-20250808171128542

5.删除原来的点和prims

由于代码运行在point上,并不能直接依据primnum删除,需要遍历每个点的prims,再删除
image-20250808171432861 image-20250808171606536

2.创建倒角面

image-20250808171736161

1.检索prim的一个半边

2.创建一个while循环

不断调用[ hedge_next() ]函数获取当前prim上一个半边的下一个半边
image-20250808172042379

3.获取当前半边的源点位置和目标点位置

image-20250808172130875

4.依据倒角时的比例,在两点之间创建两个新的点

image-20250808172343862

5.使用添加顶点的方法添加新的多边形面

image-20250808172546611 image-20250808173731985

3.merge

4.斜角操作可以递归,使用foreach

image-20250808174012496

5.依据面积设置颜色

image-20250808174157655 image-20250808174240284

22.重映射 remapping

使用重映射放缩 remapping with scale

image-20250808182501842

1.使用fit函数重映射 remapping with fit

[ fit() ]函数 将值从 一个区间 映射到 另一个区间

image-20250808183010636

2.使用fit01函数重映射 remapping with fit01

[ fit01() ]函数 将值从 ==0到1== 区间 映射到其他区间

fit01函数 默认值得范围在0-1之间

image-20250808183610452

3.使用fit10函数重映射 remapping wit fit10

[ fit10() ]函数 将值从 ==1到0== 区间 映射到其他区间

image-20250808184106554

4.使用fit11函数重映射 remapping with fit11

[ fit11() ]函数 将值从 ==-1到1== 区间 映射到其他区间

适用于与三角函数一起使用, 其值域范围就在-1到1区间

image-20250808184618967

5.使用efit函数重映射 热mapping with efit

[ efit() ]函数 同样将 一个区间的值 映射到 另一个区间

但与fit()函数的不同在于,fit函数将值钳制在区间内,当给定的数超出范围,得到的值始终是区间的最大/最小值

但是efit()函数是利用两个区间的==映射关系==对超出的部分采用同样的映射 ,当给定的数超出范围时,得到的值按照映射关系无限的线性放大或者缩小

6.运用 重映射噪波 exercise - remapping for nosie

1.使用vector4生成依据时间变化变化的噪波.

image-20250808190508291

2.将噪波值属性promote的到detail 使用maximum/minimum方法,以此获取噪波的范围

3.获取范围

image-20250808190928844

4.重映射噪波值,将点沿法线移动

image-20250808191120743

5.设置颜色值

image-20250808193734127 image-20250808193757300

7.运用 重映射表面距离 exercise - remapping surface dist

使用efit()函数

1.在表面生成以中心点为中心的波浪状曲面

image-20250808194206290

1.找到表面上离参考点最近的点

image-20250808194505881

2.计算 这点 到 表面上其他所有点 的距离(并不是直线距离,而==是在曲面上的距离==)

[ surfacedist() ]函数, 检索 点 到 ==沿着几何曲面==的一组点 的距离
image-20250808194738731 image-20250808195331130 image-20250808195352656

3.映射颜色

image-20250808195746299 image-20250808195823476

4.将距离值作为三角函数的角度

efit()函数并不钳制source value, 就是说当dist的值超出所给定的范围时,将按照线性关系映射值,比如将 0-0.5 映射到 0 - 2PI, 当dist超出0.5 为1时, 将得到4PI.也就是说这里的rangedist控制着正弦波的数量,其范围越大,得到正弦波越少.
image-20250808200202580

5.将正弦值重映射并作为沿法线的高度值

image-20250808201556121 image-20250808201730079

6.将正弦值映射到0-1作为颜色值的乘数

image-20250808201823022 image-20250808201920421

7.为角度加上一个时间偏移,得到动态的正弦波

image-20250808202047486 image-20250808202201467

8.使用ramp重映射 remapping with ramp

1.在网格中检索所有点到中心点的距离

image-20250808202532149

使用attributepromote计算区间

image-20250808202654395

2.使用斜坡映射 ramp remap

1.获取属性基于距离值映射一个高度值作为每个点的高度

image-20250808202926708 image-20250808202947691

2.使用ramp函数,先将高度值映射0-1范围

再使用chramp
image-20250808203200921 image-20250808203207126

3.将重映射的值再次映射到最终值

image-20250808203347482 image-20250808203405221

9.使用lerp插值重映射 remapping with lerp

[ lerp() ]函数 在值之间执行线性插值

image-20250808203634885
这里的amount值在0-1范围内,所以先使用fit()函数将一些值映射到0-1范围,再使用lerp()函数将一个值无缝切换为另一个值

1.在球体的两个位置状态之间无缝切换

image-20250808204116177

1.检索第二个球体的位置信息(由于是同样的球体,有相同的点数).

在两个位置之间插值,使用val控制
更新当前位置到新位置
image-20250808204542239

2.将基于时间正弦波映射到0-1,并作为val控制lerp插值

实现在两个位置之间不断切换的动画
image-20250808204924667

10.运用 使用lerp插值重映射 exercise-remapping with lerp

创建几何体多个状态之间的循环切换动画

1.设置不同状态的球体

1.在空间中散布一些点,设置scale和id属性

将scale重映射,设置范围
image-20250808205641266

2.copy to point获得不同状态的球体

image-20250808205742719

2.移动球体

image-20250808210046683

1.根据球体个数将时间轴划分区域

image-20250808212521424
f:计算当前帧在整个时间轴的位置(这里¥FEND加了1,所以最后一帧并不能到1,接近0.999)
i:计算当前帧所对应的索引值,f乘以点数,再向下取整,得到0到count-1的索引值(这里的f不取1的原因,否则索引值超出)
ff:计算当前帧在划分区域的位置,由于f在0-1,所以将1/count,表示将f的范围按照个数划分成几份,在由f==取余==,则得到值在这个范围内(0-1/count)循环,再乘以count,将值映射回0-1。这个ff则随着时间移动在每一个范围内从0到1变化
使用==当前帧== 取余 ==划分的长度== ,再比上划分长度 即得到当前帧在划分区域的位置比例

2.找到当前帧对应球体的位置

[ findattribval() ] 函数 找到具有特定属性值的点/prim/顶点
image-20250808215911866
1.在第二个输入中找到所有id相同的点。(id为i,即当前帧随对应的索引值)
2.找到每个点对应另一个球体的点的编号,获取其位置
实际上这里通过@ptnum,是找的数组中第多少个元素,由于几何体点数一致,每一个对应的@ptnum都有一个对应的数组元素。
3.更新位置
image-20250808221904330

3.使用slep插值

1.获取下一个球体的位置

使用(i+1)%count,即i为最后一个值,下一个变为0,回到起点形成循环
image-20250808223510471

2.使用ff插值

image-20250808223620057

4.使用斜坡函数重映射ff值,获得变化的动画

image-20250808224005539

5.[ smooth() ]函数 创建缓和的插值

image-20250808224150115 image-20250808224306066

11.uv重映射 UV remapping

1.使用[uv flatten ]节点展uv

打开输出seams属性(可以不用)

image-20250808233331231

[2.uvquickshade]节点查看

3.vex,找到每个点对应的uv坐标

1.获取每个点对应的编号

[ pointvertex() ]函数 提供线性顶点编号
image-20250808234804183

2.使用顶点编号即可获得顶点属性,这里检索uv属性

image-20250808234957361

3.将点移动到uv

image-20250808235046085
由于接缝处连接
image-20250808235057363

4.使用[ edgecusp ]

其工作原理是:检测uv边界,复制共享点,为每一个uv块创建独立的点,并断开拓扑结构
即通过接缝剪开uv
image-20250808235118903 image-20250809001543611

5.在两个位置之间插值

image-20250809001722684 image-20250809001726850

12.运用 uv重映射 exercise-uvremapping

1.获取每个点对应的uv坐标

image-20250809002402177

2.对uv取余x/y,表示将uv划分为几个区域,每个区域的uv值从0-x/y

image-20250809002830582

3.在将其重映射回到0-1范围,即每个区域重复从0到1

image-20250809003145513

4.以uv作为正弦函数的角度(0-PI)获得正弦波值,再以此作为高度值沿法线改变位置

image-20250809004203009

即将整个uv坐标系划分成多个重复的小块,依据当前点新的uv的值来移动点的高度。

23.有向距离场 SDF

SDF用于可视化表面

越靠近表面的值越接近0
image-20250809091106883

1.check SDF values with points

1.使用volume wrangle在当前体素位置创建新的点

1.直接读取体素值

image-20250809091812404 image-20250809091853332

2.删除volume

image-20250809091933375
中心没有点
image-20250809091940097

3.将读取的体素值设置为点的属性

image-20250809092142378 image-20250809092326070
数值大于0则在表面外,小于0则在表面内

4.删除值大于0 的点

image-20250809092609750

5.使用体素值设置颜色可视化

image-20250809093226827

2.使用点检查SDF的梯度 check SDF gradient with points

1.

[ volumegradient() ]函数 计算volume primitive的梯度
image-20250809093616662

计算梯度值并写进点属性中

==梯度==:是从中心点指向外
image-20250809093824950 image-20250809094127660

3.使用fog volume 可视化SDF值 visualize SDF value with Fog volume

1.将SDF转换为fog

使用vdb在球体外没有体素,这里使用isooffset,可以填充边界外
image-20250809111652052

2.复制sdf的值到标准volume

使用[ volumesample() ]函数 采样当前位置的surface值
image-20250809111906182 image-20250809111912245

1.将得到的值更新到density以便查看

image-20250809111946287 image-20250809112036806

2.使用可视化节点

image-20250809112402255

4.使用vex修改SDF basic SDF modification with VEX

image-20250809112726507

修改体素值

SDF表面的体素值为0,所有体素加上一个值,则0值向内移动,表面收缩.反之向外扩张

image-20250809112915435 image-20250809113405594

5.动画化修改SDF animated SDF modification

以y轴作为角度使用三角函数产生波形

角度值乘以PI乘以整数作为波的数量,三角函数值乘以一个数作为移动的距离
image-20250809113700240 image-20250809113832707

2.在角度中添加时间则波形移动

image-20250809114512337

6.使用梯度修改SDF SDF modification with gradient

1.使用[ volumegradient() ] 采样梯度值

image-20250809115448352

计算梯度向量与xz轴的夹角,

image-20250809115639200

1.先将梯度向量值y轴设置为0,再归一化

image-20250809115925125

2.使用[ atan2() ]函数 arctan 获得连续的角度(0-180-0)

image-20250809120036251 image-20250809120736927
这里应该将将z设置为绝对值(-z变为正,即沿着x轴镜像),才能得到0-180°.==将x设置为绝对值,是沿着z轴镜像==(将-x的部分变为正)得到的角度将是正负90°

3.将利用角度产生正弦波,映射到0-1,再使用斜坡重映射,再重映射控制距离,作为移动表面的值

image-20250809122638202 image-20250809123456046

转换为多边形

image-20250809123510397

重映射颜色,基于曲面位置映射颜色

image-20250809123621004 image-20250809123654391

7.SDF碰撞检测 basic collision with SDF

将SDF作为外部信息修改其他几何体

1.获取信息

[ volumesample() ] 采样体素值
[ volumegradient() ] 采样梯度值
image-20250809124922102

2.检查点的位置,并通过梯度方向移动

image-20250809125035571 image-20250809125144142 image-20250809132958106

8.动画化碰撞检测 animated collisionwith SDF

在求解器中检测碰撞

1.设置动画

image-20250809134112570 image-20250809134146323

2.解算器中设置碰撞检测

image-20250809134322380 image-20250809134439520

9.使用SDF梯度的向量动画 vector animation SDF gridient

在volume内生成点,每一帧将点沿着梯度方向移动,知道接触表面删除或者移动到其他地方
将体积作为第三个输入以用来生成随机位置
image-20250809140211923

1.沿着梯度方向移动点

1.采样SDF的体素值和梯度向量

image-20250809140435712

2.当体素值大于等于0时(判断带点在表面以外),将点移动到scatter随机生成的位置

image-20250809140838077 image-20250809140700332
使用梯度方向按一定速度更新位置,保存梯度值为法向N,保存体素值
image-20250809141020508

2.着色

1.使用attributepromote 计算体素值的最小值,以此映射颜色

image-20250809141133495 image-20250809141231921

2.使用法向(梯度方向)创建拖尾

image-20250809141319427 image-20250809141328905
为新点设置颜色
image-20250809141358757 image-20250809141423935

10. 从SDF扩展向量场 extended vector field from SDF

1.生成矢量场

image-20250809141909340

1.生成curl noise

image-20250809142031080
将噪波与梯度方向相加作为新的速度矢量
image-20250809142128895 image-20250809142304370

调整

image-20250809142512437 image-20250809142531887

2.重新采样矢量场velocity

image-20250809142630211 image-20250809142724124

24.力 force

image-20250809163802211

1.重力 gravity force

1.为点添加一个velocity属性

image-20250809164357047

2.创建重力向量gravity存储为属性

3.更新速度

image-20250809164634947

4.更新位置

image-20250809164707374

5.判断是否到达地面

image-20250809164913404

2.弹跳 bouncing

1.设置速度反向,将位置y轴重置到0

image-20250809165302163

2.减小返回的速度值(真实物理世界,有阻力有损耗,返回的速度小于到达的速度)

image-20250809165505872 image-20250809165725809

3. 初始化速度 initial velocity

1.设置初始速度

(更真实的情况这个速度也要有损耗)
image-20250809165849713

2.碰撞反向时,只对速度的y轴反向

image-20250809170126861
如果地面不平整则需要考虑地面的法线方向,以法向作为反向

4. 对多个物体的力 force for multiple objects

1.为多个物体设置初始速度

image-20250809170829749 image-20250809171038658

5. 质量的力 force with mass

mass 质量是物体的==属性==
==weight = force== 重量是地球对物体的引力

F = ma ,

1.为每个球体设置质量属性

image-20250809172537762

2.设置加速度

这里的gravity设置为一个向下的速度,并不是重力加速度,而是作为力,所以增加了质量属性,加速度 acc使用 F/m = a公式
v=at(1a, 2a, 3a....)每一帧的当前速度 ==实际上就是将加速度值累加到速度中==
位置为累加的速度(因为在解算器中,==每一帧走过路程就是一个速度向量==)
image-20250809173136137

6.空气摩擦 air friction

1.设置摩擦

理论上更大的尺寸摩擦力更大
image-20250809175734027

1.摩擦力与速度方向相反乘以一个比例,将摩擦力更新到速度

image-20250809175923019

7.水摩擦力 water friction

1.使用SDF作为水体

image-20250809182515242

2.检测球体是否在水体中

image-20250809182937842
这里是是以速度的反方向为方向乘以一个值作为大小,每一帧都施加同样大小的摩擦力
消除抖动,以当前的速度反方向乘以一个固定比率(即速度是按照比例损耗的),每一帧施加一个上一帧速度固定比例的反方向速度
image-20250809183214092

3.设置以pscale为检测触地条件

image-20250809184254534 image-20250809184359315

8.风力 wind force

1.设置风力

image-20250809184652989

1.将风力添加到速度

image-20250809185429015

9.湍流力 turbulance force

使用volume引入矢量场

1.使用体素位置为基础

1.y轴分量先设置为0
image-20250809190137724

2.沿y轴设置抖动,基于位置的较小随机值,放大噪波,再重新归一化

image-20250809190444638

3.将向量沿y轴旋转90度,使其沿着中心旋转方向(原本的向量取自位置,即由中心向外发散)

image-20250809190603022 image-20250809190839801

2.使用矢量场更新速度

1.在当前点位置采样volume中的速度值

乘以一个放大倍数,加入到速度矢量中
image-20250809191219356

25.力进阶 force extended

1.吸引力算法 attractor force algorithm

image-20250809192125847

1.简单的吸引力 simple attractor force

image-20250809192547930

1.计算公式

image-20250809192929964
==这里加上单位向量v,作为方向==
==两个质点之间的万有引力与距离的平方成反比==
image-20250809205411180

2.设置吸引点和移动点,设置mass属性

使用mass设置pscale
image-20250809203932189
为吸引点设置gravitation 引力属性
image-20250809204027272
为移动点设置val速度属性
image-20250809204305888

3.创建求解器

image-20250809204338394

4.计算需要的信息

1.检索两个物体的质量,计算彼此之间的距离
image-20250809204547057
2.获取吸引点的引力
image-20250809204722983
3.计算速度方向值(==始终由移动点指向吸引点==)
image-20250809204928948

5.计算吸引力

image-20250809205159673
由于当距离很小时过于放大引力,这里设置最大引力限制。
image-20250809205801921
更新force引力

6.使用引力 更新速度和位置

1.访问速度val属性,将引力向量添加到速度向量
2.将速度向量添加到位置
image-20250809210140473

7.调整

1.钳制引力的大小,以免引力太强,或者太弱
image-20250809210517942 image-20250809210712628
2.更新速度之后,钳制速度的最大值
image-20250809211211808

2.多个物体的引力 multiple attracted objects

1.替换单个移动点为多个

1.需要为每个点设置随机的质量mass

image-20250809212252944 image-20250809212306357

2.调整

image-20250809212518533 image-20250809212553606

3.多个吸引点 multiple attractors

1.替换多个引力点

1.为每个引力点设置随机质量mass

image-20250809213044647 image-20250809213103585

2.计算总的引力

1.使用循环访问所有引力点
image-20250809213442231
2.计算总引力:即所有引力的向量累加
image-20250809213510142 image-20250809213519939
3.替换速度
image-20250809213526703

2.调整

4. 朝向吸引物体 attracted object with heading

设置朝向

解算器内更新位置之后,更新移动点的法向为速度方向即可
image-20250809214607836 image-20250809214726441

设置吸引点随机移动

1.使用SDF的梯度值使其不会超出范围

image-20250809214920646

2.随机移动

使用curlnoise 创建一个力
image-20250809215202960
2.创建一个边界力
超出边界时,按照梯度(梯度由内指向外)回到球内
image-20250809215613645
3.计算合力
image-20250809215315755
4.更新速度,位置
image-20250809215710585
5,限制速度大小
image-20250809215834930 image-20250809220014702

5. 角向力算法 angular force algorithm

绕物体旋转的力
image-20250809220930623
通过增加角度θ,增加旋转的速度
image-20250809224520358

计算公式

image-20250809224837665

1.创建旋转点,和中心点

为旋转点设置随机的质量属性mass并作为pscale,设置角度属性 ang

image-20250809231308062

为中心点设置引力属性gravitation,质量属性mass

image-20250809225220051 image-20250809225246286

可视化:copy to point,上色

2.求解旋转力rotational force 和 角力angular force

image-20250809225719478

1.检索所有需要的信息

1.获取中心点位置posC
2.获取中心点质量massC
3.获取中心点引力g
4.计算中心点到当前点距离dist
5.获取当前物体的质量massM
image-20250809230831343

2.计算力

image-20250809230943308
1.限制力f的大小
使用==设定上限== 与 ==当前值== ==取最小值==的方法
image-20250809231049706
2.使用力f 增加角度值
image-20250809231442714
3.限制角度的大小
使用 ==设定最大值== 与 ==当前值== ==取最小值== 的方法
image-20250809231634040

3.设置旋转

1.创建旋转矩阵
image-20250809231835574
2.先将位置移动到以原点为参考,旋转位置之后再移动回原位置(假如中心发生移动)
image-20250809231930881 image-20250809232135665

6.角向运动算法 angular motion algorithm

利用物体自身的中心旋转
使用==角向运动==算法是==旋转物体的法线方向==进行角向运动,角向力则是旋转位置本身
image-20250809233107807

计算公式

只与自身质量mass有关
image-20250809233228328

1.创建起始条件

初始化再设置一个角度2,设置法向N,设置引力系数gravitation
==由于这里将法向量N设置在点上,后续旋转法向量N,再copy物体到点上,则物体将自动对齐法向量N,以此产生绕自己旋转的效果==
image-20250809233951391 image-20250809233624591

2.求解角向运动angular motion

1.获取信息

mass质量,引力系数g

2.计算力和角度,限制大小

使用取最小值的方法
image-20250809234057014

3.旋转法线

1.创建旋转矩阵
2.旋转法线
旋转时,以原点(0,0,0)为中心,旋转操作本身并不考虑向量的位置(默认在起点)。
这里旋转的是向量N(1,0,0),与当前点的位置无关。
向量本身只有方向和大小,并没有位置概念。只是在用法上可以将其作为位置
image-20250809234224581 image-20250809234438423

7.钟摆算法 pendulum algorithm

计算公式

image-20250809235022600 image-20250809235246481

1.单摆 single pendulum

1.创建直线line,分组一个单摆的球体

image-20250810002141097

2.measure节点测量primitive的长度

image-20250810002218260

3.设置初始化角度

1.设置角度
image-20250810002329955
2.旋转
image-20250810002421039 image-20250810002505219

4.设置质量属性mass,pscale属性(与质量相关),设置速度值属性val

image-20250810003336487 image-20250810002743853

2.解算

1.获得信息

1.获取摆的长度l
2.设置引力系数g
3.获取质量mass
image-20250810003004011
4.过滤ball组,只移动球
image-20250810003010352

2.计算力

==这里需要加一个负号==,
image-20250810003151097

3.更新速度,再更新角度

image-20250810003432995

4.更新位置

这里先将向量(0,-1,0)按计算的角度旋转作为方向,再乘以长度,即得到球应该在的位置
image-20250810004320587

5.设置阻尼

按照比例每一帧减小速度
image-20250810005112685

8.多个钟摆 multiple pendulums

1.使用foreach创建多个钟摆

1.获取当前迭代和迭代总数

image-20250810111930483 image-20250810112031157

2.重映射长度,判断当前点是否是ball点,修改位置

image-20250810112236740 image-20250810112410721

3.为每一个钟摆创建初始角度

4.调整解算算法

1.通过获取每一个点的prims,来获取其长度
2.枢纽点,即每个prims的0号点
3.检索枢纽点位置
image-20250810113027898
4.更新位置:使用当前钟摆的枢纽点位置加上旋转的位置
image-20250810113141334 image-20250810113355703

5.调整

重映射摆的长度
image-20250810113619725 image-20250810113639454

9.弹力算法 spring force algorithm

计算公式

image-20250810120158408 image-20250810120628958

1.简单弹力 simple spring

固定一点移动另一点

1.设置分组,属性

image-20250810121013051
创建mass属性,设置目标长度
image-20250810121149897
根据mass设置pscale
image-20250810121355097
设置速度矢量
image-20250810122344550

2.解算器

1.筛选分组,只运行在ball,即固定一个点的弹力
image-20250810121517907
2.计算信息
1.获取 点0 的位置(固定点)pivotpos
2.计算指向固定点的向量v
3.计算长度l
4.获取目标长度tl
5.计算长度差diffl
6.设置刚度n
image-20250810122220114
3.计算force
1.使用force更新速度vel
F = ma,v = at; ==在每一帧上,速度是加速度的累加,也是力的累加,位移是速度矢量的累加==
2.使用速度vel更新位置(由于矢量即表示大小又表示方向,所以==每一帧的位移就是速度矢量==,位置则是速度矢量的累加)
image-20250810122440936
4.设置阻尼
image-20250810123150271 image-20250810123201731

5.调整

1.设置力与距离的平方成正比,(使用平方丢失符号)使用差值除以其绝对值获得原本的符号,乘以0.5,表示值运动一端。
image-20250810123449381
2.添加一个重力f2
image-20250810123822798
3.限制force f1的大小
image-20250810124155814

10.链式弹力 chained spring (rope)

1.创建chains

1.congvertline节点

否则line只有一个prims
image-20250810142847019

2.计算每条line(primes)的长度

image-20250810143024546

3.初始化条件

1.固定端点(设置为pin组)
image-20250810143143064
2.设置每个点有相同的质量mass,设置速度属性
image-20250810151712308
3.使用primitivewrangle为每个prims设置目标长度(使用测量的长度作为原始长度)
image-20250810143416756

4.设置移动handle以此控制一个端点

image-20250810143548924

2.解算

使用prim wrangle

1.访问prims中的点,创建循环遍历每一个点,计算force

1.这里在第一个循环pt1=0,pt2=1;第二个循环pt1=1,pt2=0;
for循环数组中的 i+1取余数组长度,都是避免索引超出数组长度,当取最后一个值时,跳转回0(第一个值)
==这里数组只有两个元素,第二次循环则交换编号==
image-20250810143817202
2.获取两个点的位置和mass属性(这里错误,mass2应该是mass1)
3.计算两个点之间的方向向量
4.计算两点之间的长度
5.获取prim的目标长度属性
6.计算长度差
7.计算力,钳制大小
这里的两次循环:==第一次将由pt1指向pt2的力累加到pt1==,==第二次将由pt2指向pt1的力累加到pt2==
==中间的每一个点有两个方向的力,所以需要累加==
image-20250810152507063

2.使用point wrangle 添加重力, 更新速度

image-20250810152029580

3.更新位置

判断点不不是pin固定点
image-20250810152205834 image-20250810152400768

4.调整

1.计算弹力的公式中不考虑质量,后续加入了质量,重复了
image-20250810154307762
2.

5.加入控制端点

将端点位置更新到控制点位置

image-20250810154541993

26.递归 recursion

不断调用自身
image-20250810160136571

可以用来创建分形

image-20250810155950986

1.houdini中的递归 recursion houdini

1.三个方法

image-20250810160326638

1.使用foreach循环实现递归 recursion with foreach loop

1.添加新点,创建方向属性

image-20250810161959185

创建分组,设置为最后一个点(将其不断移动)

image-20250810162100585

2.foreach number 循环

1.调整为feedback each iteration

image-20250810162244174

2.调整为fetch feedback

image-20250810162327339

3.每一次迭代将last点沿x轴移动一个位置

这里每次迭代,将last点移动一个位置再与原来的点合并
image-20250810162957609

4.加上旋转,向上平移

image-20250810164901132 image-20250810164952466

2.使用foreach和VEX实现递归 recursion with foreach loop + VEX

1.设置旋转距离,旋转角度,旋转高度作为参数

image-20250810192231940

2.添加新的点

将新的点设置为last组,将当前点移除last组

为新点设置dir属性(add的新点没有任何属性)

image-20250810192622167

3.设置旋转

创建旋转矩阵,加上y值

image-20250810195045789

3.使用解算器实现递归 recursion with solver

1.使用同样的VEX代码

4.使用VEX实现递归 recursion with only VEX

1.使用for循环包含所有代码

image-20250810203805643

1.更新位置(在循环中使用pos = @P,只会重复使用第一个点的位置)

不需要分组,每一次循环已经将最后一个点的位置储存在pos中
image-20250810204329578

5.使用foreach生成谢尔宾斯基三角形 sierpinski triangle with foreach loop

1.初始图形(使用circle设置一个三角形)

image-20250810205041448
以每个顶点为枢纽点pivot,将三角形缩小0.5,即可得到周边的三角形

2.使用foreach循环

1.使用foreach prims 访问每一个三角形

2.再其中使用foreach point 访问三角形的每一个点

3.使用transform 设置pivot,来缩放三角形

1.设置pivot

image-20250810210034910 image-20250810210213301

4.理解

主要的for each num设置为feedback,每次迭代作用于上一次的所有三角形(也将是将上一次的所有三角形按照其三个顶点为轴心分别缩放得到三个小三角形),在这个大的反馈循环中,使用foreach prim遍历每一个三角形,再再这个prims循环中使用foreach point遍历每一个三角形的每一个点,以此作为pivot,将每一个三角形以三个点为轴心分别缩放一次。

image-20250810211319501

6.使用forach循环加VEX生成谢尔宾斯基三角形 sierpinski triangle with foreach loop + VEX

使用wrangle可以并行运行,获得更快的计算速度

1.VEX

1.获取每个三角形的三个点

这里的每个三角形都是一个prim,运行在primitive wrangle上
image-20250810213430593

2.循环三个点,使用point()函数获取三个点位置

image-20250810213641767

3.再循环以三个点将当前三角形(三个点位置)缩放一半,得到三个小三角形的位置

image-20250810213924860
vex代码运行再每一个prims上,即处理的是单个三角形
第一层循环,是循环三个点,分别作为pivot,这里的pos位置。第二层循环分别以三个点为pivot,移动三角形三个点的位置(减去pos枢纽点,==得到的是由枢纽点指向顶点的向量==),

注意理解:这里减去之后得到的是由==pos点====位置==指向==npos点位置==的==向量==,缩小一半,其终点在两点的中点,==起点在pos向量终点==,所以需要加上pos向量,将其起点变为pos起点。才能作为位置(由于pos,npos都是作为位置,所以以此为向量,起点在原点)

理解2:位置由起点在原点的向量表示,默认缩放位置时,是缩小这个以原点为起点的向量,当要使用别的位置作为枢纽点缩放时,减去枢纽点向量相当于将枢纽点放回原点,缩放操作后,需要再加上枢纽点位置。

4.创建多边形

添加顶点
image-20250810225201429
删除原prims
image-20250810225253131

7.使用解算器生成谢尔宾斯基三角形 sierpinski triangle with solver

1.直接使用foreach中的VEX代码

solver和foreach 反馈迭代一样,只是==solver以每一帧为一次反馈迭代==

2.设置switch划分时间轴为迭代次数

image-20250810230048744

8.只是用VEX生成谢尔宾斯基三角形 sierpinski triangle with only VEX

使用VEX代码实现递归函数难度大

1.VEX没有嵌套的数组,中有一维数组
2.在一个wrangle中生成的点或者prims,并不能使用primpoints函数再次查询,需要离开当前wrangle节点
3.并不能在函数中创建函数,在函数中调用函数
本质在于递归需要顺序执行,而VEX是并行执行,所有点/prims是同时处理。线程之间无法通信

1.使用VEX递归

image-20250810232335684

1.只需要删除一次原三角形

image-20250810232436851

2.primpoints只能访问单个三角形

image-20250810232532178

3.不能使用点/prims编号进行反馈操作,需要将其转换为位置

创建一个向量数组,存储三角形的三个点位置
image-20250810232937228

4.不能在反馈循环中生成prims,其编号不能用于下次迭代

image-20250810233433777
这里有迭代循环和访问每个点的循环,缺少第二层循环,即访问每个三角形的循环

5.第二层循环需要遍历所有三角形

使用位置数组长度除以3得到三角形的数量
image-20250810233801489

6.创建三角形点位置的索引

image-20250810234134259

7.替换为位置

image-20250810234309994

8.创建新的数组存储所有新三角形的位置

image-20250810234458324

9.在反馈循环最后更新位置数组,作为下一次迭代的位置

image-20250810234751062

10.使用位置信息创建几何体

image-20250810235103445 image-20250810235119676

2.递归执行测试 recursion performance test

方法时间iteration
只使用foreach18s11
==foreach 加上 VEX==0.165s11
==solver==0.19s11
纯VEX10.75s11

9.2D L系统树 2D L-system tree

1.设置end组,作为每一次迭代的点

image-20250811120025655

2.设置属性

设置分支的长度,角度

image-20250811120124831

3.使用foreach feedback loop

image-20250811120302485

point wrangle控制end点

1.设置参数

分支角度
image-20250811120819023

2.循环三次创建三个分支点

创建旋转矩阵,将沿着x方向沿y轴旋转角度a
image-20250811121054532
创建新位置
image-20250811121135120
添加新点
image-20250811121159462 image-20250811121238604
连接点为polyline
image-20250811121259680
重新依据i(0,1,2)为每个分支获取角度,(将0,1,2向负方向移动,得到-1,-,1)
image-20250811121342329 image-20250811121536594

3.选择end点作为下一个分支的点

1.在循环后将生成的点设置为end组
2.将原来的点移除end组
image-20250811121826404
3.更改新的分支的长度属性,角度属性
image-20250811121944871 image-20250811122201416

4.当角度为120,生成了谢尔宾斯基三角形

image-20250811122231327

10.使用foreach循环实现3DL系统树 3D L-system tree with foreach loop

image-20250811122854052

1.创建一条线,分组prims,作为操作的分支

image-20250811123230022

2.设置水平轴

image-20250811123607162

3.创建feedback反馈循环

1.使用primitive wrangle,

2.设置参数

image-20250811124106815
1.创建分支角度
2.设置缩放比例
3.设置角度比例
5.设置最小长度作为结束循环的条件
6.设置分支数
7.创建种子值
image-20250811124236807 image-20250811124255890

3.获取起点终点点号,获取其位置

image-20250811124405950

4.设置起点指向终点 的向量为轴

image-20250811124502282

5.获取水平轴,计算当前的长度

image-20250811124649107

6.以水平方向为轴旋转,移动,添加新的点

以(1,0,0)旋转,即沿着x轴在xy平面旋转
这里是旋转之后再加上原来的分支向量,即将新的分支沿着原分支方向移动到顶点
这里的npos 先加回pos1,得到原位置,再加上pos2-pos1(原来分支的矢量),将顶点沿原分支移动,得到新分支顶点位置。
image-20250811130421857

7.连接新点

image-20250811132647658 image-20250811132717925

4.创建循环来生成分支

1.计算分支的角度

将360°划分为几个分支
image-20250811134600664

2.以垂直方向为轴,旋转分支生成多个分支的位置

添加新的点和线
image-20250811135009846 image-20250811135101266

3.将新的线添加进last组,将原本的线移除last组

image-20250811135157019

5.添加旋转轴属性

注意属性传递问题:新加的线没有任何属性

添加新的水平轴

初始的水平轴为(1,0,0)指向x方向,生成新的分支时,竖直轴为上次分支的指向,以此旋转生成分支,新的水平轴也应该旋转同样的角度,以此对齐新的分支,下一次的分支将沿着新的水平轴旋转角度,形成对称的图形
image-20250811135658554 image-20250811140827986

6.创造停止迭代条件

检查最小分支长度,return将跳过所有代码

image-20250811141658018

7.应用angle ratio每次缩小分支的角度

需要将分支角度设置为可以迭代的属性

image-20250811142720165

2.读取分支角度属性

image-20250811142825502

3.设置更新分支角度属性

这里的属性是以角度存储的,使用时先转换为弧度,保存时再转换为角度
image-20250811143150269

8.引入随机的分支角度

创建垂直方向的上旋转的随机角度(即分支之间的角度),映射到固定可调范围

image-20250811144109706 image-20250811144059586

9.引入随机的水平旋转角度

image-20250811144524951

10.设置pscale,创建厚度

1.创建厚度属性

image-20250811144749465

2.获取分支顶点的厚度属性

image-20250811144857973

3.设置比例减小厚度

image-20250811144942650

4.访问厚度属性

image-20250811145046482 image-20250811145100205 image-20250811145109269

11.着色,依据厚度

image-20250811145138323

11.解算器创建3D l系统树 3D L-system tree with solver

使用solver可以创建更流畅的生长动画

1.将foreach替换为solver

在每一帧,分支立即生成

2.使用carve节点

对primitive切片
image-20250811150230803

12. 递归细分 rectangle subdivision

image-20250811162532060

1.创建prims属性

设置切换属性,每一次迭代切换一个状态
image-20250811162721165

2.创建反馈循环

1.改变点标号顺序

image-20250811162959500
2.使用primitive wrangle分割矩形

2.获取iteration,prim中 的点号

3.设置切换值,每次迭代切换一次

为0,表示选择的位置为横向切割,为1表示竖向切割
image-20250811163405794

4.设置切割的位置

1.设置随机种子,依据迭代次数,和prims
2.创建随机值
3.设置最小比例
4.映射随机值的范围
image-20250811163942911

5.创建两次循环创建两个prims

6.在嵌套一个循环遍历每一个点

1.获取每一个点位置,获取对角点位置用来作为缩放的枢纽点
2.计算从第一个对角点指向其他点的向量odir
image-20250811164618408
3.如果sw=0(沿x方向切),取方向向量的x分量
image-20250811165317898
4.添加顶点,删除原prims
image-20250811165613944
注意理解:这里举例沿x轴横向切时(sw=0),将 由对角点指向其他点的矢量odir 的x分量缩放,(==只缩放x分量,其位置就只在x轴缩放==)。新点的位置为对角点位置加上这个方向向量。
sw=1时,即沿着z轴切,缩放z轴的分量
两次循环中嵌套四次循环(点数,对每个点执行),依次添加顶点,生成多边形
image-20250811165509615 image-20250811165643981

3.使用noise动画化,

1.创建noise(依据每一帧),映射到范围,加入到缩放值

这里的缩放值为0.2,即切割位置在边的比例为0.2到0.8范围,这里加入每一帧noise变化的+-0.2,(由于使用的noise,变化具有连续性)
image-20250811171545091

4.上色

基于面积上色

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