工程链接

链接:https://pan.baidu.com/s/1PqiAWlzklc8RLa4x57COWQ
提取码:3bzx

这一节有点过于难了…就好像刚讲完十以内的加减法,就出了一道微积分的题。我跟着教程做了三次都没能成功,应该是这个方式在houdini18里不能用了,或者需要另外做调整。

本着负责任的心态应该是研究出哪里应该做调整再写笔记,但是因为实在是有点超纲,另外急着想出一篇笔记,就先用教程中的思路捋一下好了。思路还是值得学习和拓展的。

这节课的内容是手动创建vellum约束,随着点的发射来不断更新约束。大致的流程是:

0.第一帧的时候创建一条线
每一帧:
1.发射新的点
2.设置点的pscale值
3.将新产生的点添加到线上
4.在新的点和上一个点之间创建Distance约束
5.在新的点和上两个点之间创建Bend约束

同时作者非常精辟的解释了什么是Distance约束和Bend约束。

Distance约束就是保持两个点在给定距离方向上远离彼此,可能想象在两个点中间有一个线性的弹簧。所以这种约束只要有两个点就可以创建出来了。

注意除了Distance约束,这种类型的约束还可以叫做Length或者Stretch,然而实际都是这个原理。

Bend约束则是三个点连接的primtives的弯角,很明显这个约束需要三个点实现。

Sop的部分其实没有太多不理解的,pointwrangle那段vex也还好。唯一一个值得注意的是,既然我们已经要自己手动创建约束了,为什么还要使用vellumconstraints呢?

我的理解是vellumconstraints提供了一个容器,一个可能容纳约束的容器,可以将一个普通的primtives识别为约束的容器。

下面就进入Dop层级。

按着视频中的创建顺序捋。

geometrywrangle1的代码:

if(@numprim < 1)
    addprim(0, "polyline");

如果primtive的数量小于1,就创建一个primtive。这里的”polyline”是一个固定的string参数,代表创建的primtive是一个不闭合的线。这个线允许有0个点。

addprim函数具体用法可以在这里查看:https://www.sidefx.com/docs/houdini/vex/functions/addprim.html

注意这个线是创建在了geo上,而不是constraints上。从geometrywrangle1的Bindings属性中就能看到,Geometry的值是Geometry,而不是ConstraintsGeometry。

这个节点还有一个地方很困惑的是,作者将Run Over改为了Detail(only once)。一开始我以为是为了让创建prim的操作只执行一次,但是vex中的if条件函数就已经限制了,如果已经创建了一个prim,就不会再创建了。那放在detail级别下的意义是什么呢?为什么不是prim级别呢?

接着在vellumsource中一顿操作,让这个节点有了一个新功能:将每个新产生的点都放进newborn组中。这段操作就这么简单理解吧。

然后在popwrangle1中,vex代码是addvertex(0,0,@ptnum);用来向刚才创建的prim添加新产生的点。第一个参数自然是指要操作的输入端口,虽然Dopnet节点并没有连接入什么节点。第二个参数0指的是prim的primnum,因为我们只创建了一个prim,primnum自然就是0,后面的@ptum就是每个点自己的编号了。

至此就完成了将不断生成的点添加到prim上的操作。

后面两个添加约束的vex代码好理解,但是对于geometrywrangle的一些其他设置就需要花精力理解了。

首先在Data Bindings中,将Geometry的参数改为了ConstantsGeometry。表示这些操作都是要对约束进行操作的。Input属性中的Input2改为$OBJID/Geometry,引入刚刚在geo中创建的prim进行操作。

int numpts = npoints(1);

if(numpts > 1){
    int id1 = numpts - 2; 
    int id2 = numpts - 1;
    
    float restlength = 0.025;
    
    int newprim = addprim(0,"polyline",id1,id2);
    setprimattrib(0, "restlength", newprim, restlength);
    setprimattrib(0, "restlengthorig", newprim, restlength);
    setprimattrib(0, "type", newprim, "distance");
    setprimattrib(0, "damping", newprim, 0.01);
    setprimattrib(0, "stiffness", newprim, 10000000000.0);
}

这段是geometrywrangle2中创建distance约束的vex代码。

自定义变量numpts,值是当前prim的点数量。得知了点数量,那点数量-1就是最新的点的ptnum,因为ptnum是从0开始计算的嘛。同理点数量-2就是上上个点的ptnum,点数量-3也一样…

接着如果numpts大于1,也就是说已经有了至少2个点,就开始执行里面的命令。

设定两个点的id号,也就是最新的点和它上一个点,因为distance约束只需要两个点就可以。再设定一个叫restlength的变量做备用。

然后在这两个点之间创建新的prim,这个prim就是约束的prim了。然后设定各种约束的属性,这个属性不是随便设置的,具体的可以通过创建一个普通的distance约束来查看需要哪些个参数。这样就实现了创建一个个约束prim。

bend约束也是同理的,只不过要记得需要3个点才能实现bend约束。

然后在vellumsolver的第二个输入点设置点的半径,这影响着vellum计算点之间碰撞穿插的问题。第二个输入点就是在每次模拟之前执行的。

最后gasintermittentsolve1这个节点,是为了保证上面的这些参数每一帧都只执行一次,而不是每个substeps执行一次。

总的来说,这个思路确实值得学习,但是确实也很硬核。一次记不住也没关系,至少捋顺一次,即便忘了,下次用到的时候回来再看一下,也能很快的记起来,并且相信到时候对这个思路的理解就更深了。

(完)

Leave a Reply