Houdini JoyOfVex 教程02

02

还是01中的话,本文有很多内容来自PB_zz翻译的文档,我有相当一部分其实属于二次创作。
我们在第一节教程里了解了变量,属性,赋值,很显然,第二节就需要运用他们了,而对于编程语言来说,将他们包装为函数,就是最好的运用,这一节我们来讲讲函数。
首先,贴出vex可用的函数列表,版本16.5:
https://www.sidefx.com/docs/houdini/vex/functions/index.html
如需其他版本可到http://www.sidefx.com/docs/自行查找
其实这些直接在houdini帮助文档中查看是一样的,而且帮助文档还能下载案例文件
并且把光标放在函数名上,按F1就能直接调出该函数的帮助文档
我在后期也许也会发掘一些好用的函数并写成教程

length

那么正文开始,第一个函数是length
官方给出的len函数定义为To get the length of a string, or number of items in an array, use len.、
并且返回的是一个float
当我们创建了一个平面一个物体,我们如果需要知道它在x轴在y轴甚至在z轴的距离呢?这个时候就要用到length,我们知道三维物体储存的位置信息其实是一个vector,可以连接transform节点并查看,而在代码中,我们就可以这么利用length

float d = length(@P);
@Cd = d;

这里将物体的位置信息(x,y,z)三个值的长度赋予一个变量d,然后将储存了这三个值的变量d赋值给颜色属性Cd。似乎逻辑没啥毛病?但我们其实会问两个问题,第一,一个vector类型的向量怎么变成了float类型?第二,这么写代码写成了两行,为什么不直接写@Cd=@P;?问题的答案就在下面
我们开篇说过,length函数返回的是float值,和Cd类型不一致,当然不可以直接赋值,而至于为什么一个verctor变成了float,那就是length自己内部的转化啦,它其实返回的是向量的欧拉距离,用官方的栗子来说就是这样:

length({1.0, 0, 0}) == 1.0;
length({1.0, 1.0, 0}) == 1.41421;

那么我们就能理解length函数了。我们来像文档中一样写些代码把:

float d = length(@P);
d *= ch('scale'); 
@Cd = sin(d);

提醒一下,d = ch(‘scale’)等同于d = dch(‘scale’),也就是d乘上scale的数值后重新赋予自身,C/C++的同学想必不会对此感到陌生,而有些语言没有这样的操作方法显得有一些可惜,幸好vex支持。不仅如此,vex还支持前置自增和后置自增,不过想想它是基于c语言的,支持也是很正常的事情。对于前置自增和后置,我们可以用以下代码进行对比,会发现效果不一样:

float x=length(@P);
@Cd= ++x;

float x=length(@P);
@Cd= x++;

最后是length函数的一个演示:
Houdini JoyOfVex 教程02_第1张图片
不过还有一点要注意,Cd的属性值在0-1之间,而sin的值在-1~1之间,所以我们如果在sin(d)后面加一个1,会避免Cd获取负值的情况,然后我们再让赋值式右侧除以2,就能够统一取值了。不过出于一些编程上的原因,建议将除法改为乘法,也就是/2改为*0.5,而d在定义后乘以scale的这一步,也可以直接在定义时就完成。所以我们的代码变为:

float d = length(@P) * ch('scale');
@Cd = (sin(d)+1)*0.5;
或者
@Cd = (sin(length(@P) * ch('scale'))+1)*0.5;

//我这里的代码最终结果与文档不同,有时间会回来思考原因并修改

distance

和长度相关的还有距离。当你使用length(@P)的时候,你实际上实在测量当前点到{0, 0, 0}原点的距离。而distance函数允许你测量任何两个数据间的距离。比如我们把grid连上pointWrangle,然后写上代码:

 float d = distance(@P, {1,0,3} );
d *= ch('scale'); 
@Cd = (sin(d)+1)*0.5;

你会发现,视窗中grid上的黑白圆环图像中心点从原点{0, 0, 0}跑到了{1, 0, 3}这个点。

接下来我们介绍一个新的UI参数创建函数,chv(ch是chanel的缩写,v是vector的缩写),用它来在界面上创建一个向量参数center:

vector center = chv('center');
float d = distance(@P, center );
d *= ch('scale'); 
@Cd = (sin(d)+1)*0.5;

这样你就能使用参数随时手动调整黑白圆环的中心点位置了。也就是调整向量值了。
提示一下,将@P乘以{0.5, 1, 1},你就能让@P.x的值缩小一半。
我们来整理一下代码:

vector pos = @P * chv('fancyscale');//模型上的点位置值缩放后的结果
vector center = chv('center');//中心点位置
float d = distance(pos, center );//计算两点距离
d *= ch('scale');//将距离缩放
@Cd = (sin(d)+1)*0.5;//距离作为sin函数自变量,整个式子把结果值映射到0~1之间

敲黑板!注意了!你的UI创建函数ch和chv里使用的名称不能是相同的,否则只会生成一个UI参数,例如已经写了chv(‘scale’),下面又写ch(‘scale’),这样houdini会根据优先级只生成一个参数,同样的,变量名也不要定义相同的,而且最好这些名称看起来是有意义的,比如是一些单词或者该单词的缩写,而不是随便取个名叫a,b,c,x之类的。

另外你会发现对代码进行修改,但UI界面却不会实时更新,或者说旧的参数它不会自动消失,这时你可以右键点击该参数,选择More-Delete Spare Parameter,这样该参数就被你删除了。或者有一种一刀切的懒方法,你可以点击wrangle节点菜单栏上那个齿轮按钮,在下拉菜单中选择Delete All Spare Parameter,这样所有生成的UI参数就都消失了,然后你再点击代码编辑器右侧的那个创建参数按钮(图标是滑竿和一个加号的那个,上节课讲过),重新生成代码里的参数,当然,图方便的代价就是你之前调好的数值都没啦,全变成了默认值。
接下来我们介绍一个新函数fit,这个函数是专门来做值范围映射的。之前我们是手动将sin的值通过计算映射到0~1之间( @Cd = (sin(d)+1)*0.5;),现在有了fit函数,我们就不用每次都想算法来计算了,这个函数会自动帮你搞定。用法如下:

vector pos = @P * chv('fancyscale');
vector center = chv('center');
float d = distance(pos, center );
d *= ch('scale'); 
@Cd = fit(sin(d),-1,1,0,1);
 /* fit(value, omin, omax, nmin, nmax)  同样可在帮助文档查询,简单来说fit括号里填的就是要修改的数	据,以及旧范围的最小最大,新范围的最小最大。*/

一般来说,三角函数都伴随时间使用的,sin(wt)。houdini里时间的属性是@time,我们把它作为sin的变量的话,点击时间轴的播放按钮,你会发现,sin的数值随时间变化而变化,我们的图像也有了自动交替的黑白变化动画。

vector pos = @P * chv('fancyscale');
vector center = chv('center');
float d = distance(pos, center );
d *= ch('scale'); 
@Cd = fit(sin(d+@Time),-1,1,0,1);

@Time也可以写成@Frame,time是秒的记录,frame是帧的记录。

最后的提示:
如果你要将一个变量乘以5,你可以这样写:
foo = foo * 5;
也可以使用运算符(又译操作符,英文operator)*=:
foo *= 5;
同样的,类似的有+=, -=, /=。另外你可以在一行代码上进行非常多的运算:

foo = (foo * 3 +1) / @Cd.x + @N.y;

不过不建议写太长,分开一步步写更容易理解:

foo *=3; // set range
foo +=1; // make sure values never get below 0
foo /= @Cd.x; // reduce range to within red value
foo += @N.y; // addition normal on y

第二节就这么多,有时候懒得总结或者添加一些东西我就会哗啦啦把文档的翻译复制粘贴,不过我想等我有时间了一定会重新改进原创一遍的,嗯,以我blender宝典更了一章就太监的经验来看,应该是会回来改的
本节写于2020-1-9

你可能感兴趣的:(houdini,vex教程)