分享

houdini中不得不掌握的技术集锦(5) Vex编程入门II houdini中重点和难点

 cghunter 2021-04-16

——  微资讯 · 微课程  ——

利用零碎时间,走上超神之路!

原文地址:http://www./cgwiki/index.php?title=HoudiniVex

由CG猎人独家翻译,转载请注明


这个是vex入门基础学习第二篇,紧接第一篇基础入门,这里讲述的是关于旋转的知识点。在copy和instance等很多地方都会用到的技术,比如你是否在在copy拷贝的时候方向不对,或者旋转角度不对等的问题,小编一开始学习都觉得挺难的,特别是设计到四元素 ,其中常用属性是@N,@up,@orient还有各种转换和函数公式。虽然四元素比较难理解,不过houdini有很多简化的效果属性和公式帮你理解和制作,下面让我们一起学习吧。


大纲

    11案例 旋转

        11.1使用sin和cos旋转一个点

        11.2使用sin和cos旋转一个几何体

        11.3旋转成螺旋线

        11.4使用矩阵旋转

        11.5沿着边旋转面

        11.6另外一种方法沿着边旋转面


11案例,旋转

11.1使用sin和cos旋转一个点

假设你在原点有一个点,然后你希望让它围着圆圈转动。sin可以让它在-1-1直接做光滑的波浪运动,cos同样。他们只是相差一个波长。如果你使用时间来驱动,x使用sin函数,y使用cos函数,你会获得一圆形运动.

@P.x+= sin(@Time);@P.y+= cos(@Time);

但是这并不是最终效果,它可以让box圆形运动,但是不会旋转

11.2 使用sin和cos来旋转几何体

问题出在搜哟的点都只获得一相同的旋转值。你需要的做是让每个点的旋转有个偏移值。让你的思绪回到高中数学。如果给定x和y的长度,你可以使用tan函数,返回一个角度值。所以如果把每个点的偏差的角度叠加上时间,看看会发生什么事情。

float angle = atan(@P.x,@P.y); @P.x+= sin(@Time+angle);@P.y+= cos(@Time+angle);模型开始旋转了,不过在旋转的过程中带有奇怪的缩放。所以我们应该是直接设置位置的值而不是叠加他们。float angle = atan(@P.x,@P.y); @P.x= sin(@Time+angle);@P.y= cos(@Time+angle);

已经很接近了,但是如果你对比原来的box,你会发现它有点不一样的缩放。这是因为我们需要获得点的半径(比如,点和原点间的距离)然后乘上这个值获得正确的缩放值。

float angle = atan(@P.x,@P.y);float r = length(@P); @P.x= sin(@Time+angle)*r;@P.y= cos(@Time+angle)*r;

这时候换个猪头模型测试一下,你会发现很奇怪的效果。它在猪鼻子像气球一样膨胀,整个看起来都很奇怪。问题出在radius半径上。我们之前使用的距离是3D坐标的距离,但是实际上我们只需要基于轴旋转的另外两个矢量的半径(假设旋转轴是z轴)如果我们测量长度,值需要使用@P.x,@p.y来求得。

float angle = atan(@P.x,@P.y);float r = length(set(@P.x,@P.y)); @P.x= sin(@Time+angle)*r;@P.y= cos(@Time+angle)*r;

完成,我们所做的是把普通坐标转化为极坐标(angle和r)再次回过头来看看极坐标,还是非常有趣的。

float angle = atan(@P.x,@P.y);float r = length(set(@P.x,@P.y));   @P.x= angle;@P.y= r;@P.z=0;

如果你使用线框形式查看,看起来就像一个圆柱状的uv投射,因为这就是本质东西。奇怪的拉伸是因为当你处理uv的时候你是点需要裂缝,我们在这里不需要这样做。

回到原来的旋转中,如果你把时间这个因数拿出来,用通道替代,我们会过得一个简单的旋转工具

float angle = atan(@P.x,@P.y);float r = length(set(@P.x,@P.y));float amount = ch('amount'); @P.x= sin(amount+angle)*r;@P.y= cos(amount+angle)*r;

点击那个按钮获得滑竿参数呢,滑动测试一下,你会注意到数值为1的时候旋转了30度,这个感觉不对。其实这是因为sin/cos/atan都是以弧度制为单位,如果你假设你的滑竿是角度,那么你需要把它转化为弧度。

float angle = atan(@P.x,@P.y);float r = length(set(@P.x,@P.y));float amount = radians(ch('amount')); @P.x= sin(amount+angle)*r;@P.y= cos(amount+angle)*r;

11.3旋转成螺旋线

现在你可以测试其他奇怪的东西了。这时候可以不用均等地旋转每个点,反而使用半径进行缩放。比如靠近原点的点不旋转,更远的点旋转更厉害,这样你就获得漩涡。如果你加上r那么你就获得一个次级漩涡,所以我添加了另外一个滑竿参数来控制漩涡缩放的强度

float angle = atan(@P.x,@P.y);float r = length(set(@P.x,@P.y));float amount = radians(ch('amount'));float twirl = r*ch('twirl'); @P.x= sin(amount+angle+twirl)*r;@P.y= cos(amount+angle+twirl)*r;

11.4使用matrix旋转

上面都没问题。但是如果你旋转不是完全按照x,y,z等轴的旋转呢,那就有点麻烦。另外一个做旋转的方法就是使用矩阵matrix。你使用houdini,很可能你已经知道矩阵。但是你现在在阅读这篇文章,如果有人让你做matrxi的变形你可能会感到恐慌。别担心,它比听起来简单,下面是制作步骤。

1创建一个矩阵

2旋转这矩阵

3把这个矩阵应用到我们的几何体中

最后一步很简单,要把矩阵运动到一个点上,你直接乘它就是了

另外两个步骤也很好解释。所以我们需要的就是一个矩阵,和旋转它的方式。这个方式的函数叫做rotate,下面是如何工作

// 创建一个矩阵matrix3 m = ident(); // 旋转矩阵vector axis ={0,0,1};float angle = radians(ch('amount'));  rotate(m, angle, axis); // 把旋转赋予给位置@P *= m;

所以我们创建一个空的矩阵(比如translate/rotate are 0 0 0, scale is 1 1 1),然后我们定义了旋转的 轴向,和旋转的量,然后我们调用旋转函数,这个函数会直接修改之前matrix,该变量为m。最后面我们直接把矩阵叠乘到每个点的位置上

与上面案例类似,你可以叠加乘以一个到轴的距离来制作漩涡效果,然后使用缩放控制强度。

vector axis ={0,0,1};float angle = radians(ch('amount'));angle *= ch('twirl')*length(set(@P.x,@P.y));matrix3 m = ident();  rotate(m, angle, axis); @P *= m;

因为我们可以使用任何我们希望的轴向,一个随机的矢量N或者任意其他属性,都没问题

对于使用matrix来制作旋转的另外一个好处是,它可以直接适配到@orient函数。当你使用copy节点或者instance的时候,当他们发现@orient属性时候,每个被拷贝的物体都会旋转。@orient是一个四元素。一个四个值的矢量,对于我们来说不好理解。但是你可以直接使用quaternion()函数快速把矩阵转化为四元素。

下面是你如何获得一个随机旋转属性,然后应用到copy节点中

vector axis = vector(rand(@ptnum));float angle = radians(ch('amount'));matrix3 m = ident();rotate(m, angle, axis);@orient = quaternion(m);

11.5沿着边旋转面

基于你我们现在所知道的,要沿着边旋转面不会太难(我们假设我们有一个简单的三脚面或者四边面)你把边作为你的旋转轴,和上面一样进行rotate。如果你记得你的矢量数学,要获得两个点间的矢量,直接把这两个点的位置相减。假设我我们要的边的两个点的序号是0和1,我们可以做下面步骤

vector p0 = point(0,'P',0);vector p1 = point(0,'P',1);  vector axis = p0-p1;

然后使用这个矢量创建我们的四元素(上面已经做过一遍)

float angle = ch('angle');matrix3 rotm = ident();rotate(rotm, angle, axis);vector4 orient = quaternion(rotm);

现在如果你直接把这个这些代码赋予给几何体,那么他会旋转,但是是以物体中心旋转,这是不对的。我们要让旋转中心放在边的中点位置。再次回想你高中的矢量数学,我们可以通过叠加两个点的位置然后除以2获得这两点的中间点。

// 获得边的中间点vector pivot =(p0+p1)/2;

从这里开始,vex中有一些不同的方法来做我们想要的效果。在我的这个案例中,我使用instance()函数。这个vex 函数类似与copy节点一样对每个拷贝物体都会基于transformation matrix旋转,这意味着你可以把位置,旋转和轴等适配控制。所以,我们先做一个旋转的四元素,把它作为输入端来沿着我们的轴心进行实例化,然后使用它来移动我们的点。

// 使用orient和pivot和其他默认属性来创建transform matrixvector N =0;// 这个不重要因为我们使用的orient属性vector scale =1;//比如,让它保持默认为1vector postrotation =0;// 也不重要,我们不需要额外的旋转。  matrix m = instance(pivot, N, scale, postrotation, orient, pivot);

@P *= m;// 旋转点的位置

简单极了。如果你有多个面要处理,那么这里还有一些事情要处理。第一步,每个面需要是独立分开的,可以使用fuse节点在unique 模式下来做这个步骤。然后每个面获得它的0和1的点,你可以使用primpoint()函数,这个会返回以面中的点的矩阵,你就可以使用0和1从这个矩阵中获得点。

int points[]= primpoints(0,@primnum);//获得每个prim面中的点的列表 // 从点列表中获得每个面的的第0和第1个点vector p0 = point(0,'P',points[0]);vector p1 = point(0,'P',points[1]);下面是完整的代码int points[]= primpoints(0,@primnum);//获得每个面中的点的的列表 //获得第第一和第二个点的位置vector p0 = point(0,'P',points[0]);vector p1 = point(0,'P',points[1]);  vector axis = p0-p1; float angle = ch('angle');matrix3 rotm = ident();rotate(rotm, angle, axis);vector4 orient = quaternion(rotm); // 获得点的中点位置vector pivot =(p0+p1)/2; //
使用orient和pivot和其他默认属性来创建transform matrix
vector N =0;// not important cos we're using orientvector scale =1;// ie, leave the scale as-isvector postrotation =0;// also not important, we don't need extra rotation on our orient  matrix m = instance(pivot, N, scale, postrotation, orient, pivot); // 旋转点
@P *= m;

11.6 另外一种沿着边旋转面的方法

Jesse 告诉我另外一种方法。我之前说说过直接使用rotate matrix效果不对是因为这是基于原点来进行旋转的。一个简单的方法是先把面移动到原点,旋转完后再移动回之前的位置

// 获得点0和点1的位置vector p0 = point(0,'P',points[0]);vector p1 = point(0,'P',points[1]);  vector axis = p0-p1; float angle = ch('angle');matrix3 rotm = ident();rotate(rotm, angle, axis); // 获得旋转的轴心中点vector pivot =(p0+p1)/2; // 把点移动中心,旋转,然后移动回来 @P -= pivot;@P *= rotm;@P += pivot;

—— CG猎人——

微信号:Hunter_CG

QQ-540710114

为您提供最具前景的咨询与最适合的分类技术与学习教程



运营者微信:carldrifter

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多