1-4期
195人加入学习
(33人评价)
Houdini 影视特效实验班

6个月零基础到入职

价格 ¥ 6198.00
教学计划
承诺服务

在while点云循环里边point.distance是houdini里边默认的一个值,代表零号输入端的点找到的一号输入端的点的距离,如果说零号输入端和一号输入端的点有重合,那么最小值就是0,最大值是我们设定的搜索半径的值

point.distance这个值通过pcimport这个vex语言被储存到我们设定的临时变量found_distance里面,再把这个值重新fit成我们需要的值,并且把这个值作为一个属性,应用到别的节点上

chramp()括号里边第一空是我们要创建的ramp的名称,需要使用引号引起来,第二空必须是一个零到一的值,因为ramp贴图横轴和纵轴的值都是零到一,然后把ramp贴图进行fit,横轴和纵轴零到一的值全部fit成我们需要的值,并且把这个值作为一个属性,应用到别的节点上

[展开全文]

float ramp = fit(found_distance, 0, radius, 1, 0));

这句话是说把零号输入端的点找到的一号输入端的距离重新fit成1到0,然后init_v属性再乘以这个值,会使越接近一号输入端的点的零号输入端上的点上init_v属性的值越高,         但是我认为如果只是想单纯的给init_v属性做扰乱的话,让它的大小不一致,不如直接在下面接一个pointVOP节点来做大小的扰乱,如果是说需要一个由大到小的渐变,才使用这种方法

[展开全文]

在18的版本里面,当碎块做了簇之后,assemble节点不需要勾选create name attribute选项,不然packed物体数量会计算出错  packed的name属性的名称在rbdcluster节点的cluster name prefix选项里面定

[展开全文]

当进行约束的时候不能使用packed物体进行约束,这样会导致约束不够精确,所以需要解包packed物体。 约束是给点与点之间进行连接,依据的是点上的name属性的名称,所以需要保留name属性,这样面层级上的name属性就会相应的转移到点层级上,面层级上的name属性就没用了,为了防止后边计算出错,删掉面层级上的name属性

constraint属性是字符串类型属性,所以需要用单引号引起来,并且是运行在面层级上的属性,在DOP里,glue constraint raletionship节点以及其他约束类型节点都是根据我们设置的constraint_name属性的名称来进行识别的

 

f@strength属性是作为胶水强度的倍增器来使用 

i@break_me属性是后期用来给是否删除约束线做判断条件的,设置的初始数值是0,当这个数值为1的时候,就删除掉这些约束线

 

[展开全文]

在SOPsolve节点里面,第四个节点objectmerge节点是导入约束线,  第一个节点dop import是导入在DOP网络中进行模拟的碎块,每一个作为碰撞的节点都会有一个objid的编号,在geometry spreadsheet面板进行查看,如果创建了地面,那么地面编号为零号,剩下RBDpackedobject节点按照merge的左右顺序进行编号 

objectmask这个参数表示按照编号选择导入哪一个RBDpackedobject节点

约束是不参与动力学模拟的,是永远不动的,如果希望约束跟随碎块的运动而运动,那么需要借助参与刚体模拟中的碎块所产生的一个属性packedfulltransform,这是一个3*3的矩阵,包含参与刚体模拟中的碎块的scale transform rotation信息,可以利用这个信息使约束线随着碎块的运动而运动,而约束线获取碎块的运动依赖的则是name属性 name属性是字符串形式的属性,用s来表示

nametopoint函数是获取点序号,第一空是查找的对象,第二空是具体查找哪些点,在这里,哪一些点有name属性,那么就被查找到,并且把该点所对应的点序号存储起来   

primintrinsic函数是获取参与刚体模拟中的碎块信息,第一空是查找的对象,第二空是查找对象上哪一个属性,第三空是具体哪一些点

因为packedfulltransform是一个矩阵信息,所以需要用一个matrix的变量储存起来

约束线在DOP里边是作为primtive来进行识别的,所以要把@break_me属性从点级别推送到面级别上

 

removeprim函数是删除prim,第一空是要删除的对象,第二空是具体删除哪些面,第三空是如果说这个prim上连接有点,这些点是否删除,1代表删除,0代表不删除

[展开全文]

 

dopimport节点 DOPnetwork表示要导入哪一个DOP网络节点,object mask表示导入该DOP网络节点中的哪一个object对象。可以填写数字,在DOP网络中,每一个object对象都有相对应的objectID编号,数字几就代表导入相对应objectID编号的object对象,如果有多个object对象就用空格隔开数字。相应的表达式则是‘dopobjscreatedby("要导入的object对象的路径")’,同理如果是多个,用空格键隔开

import style要选择 create point to represent object 选项,创建点来表达来代理对象,一个是因为在刚体模拟中,刚体本来就是被当做点来计算,选别的会报错,二个是因为后期要读取这些点的矩阵信息来使静态的碎块动起来

[展开全文]

当速度和角速度都小于某一个数值的时候就让速度和角速度乘一个0.97,以此来拖慢速度和角速度,实现拖拽的作用,这是在DOP网络里,所以实际上是当速度和角速度都小于某一个数值的时候每一帧都会在上移帧的速度和角速度基础上乘以0.97

 

f@cumulative_movement += length(v@v);

在DOP网络里,每一帧都会加上后面设置的速度的模的值,根据后面这句话int bool_A = f@cumulative_movement > chf("cumulative_threshold") ? 1 : 0;是表明一定要有速度之后,才会进行下面的if语句,使碎块进入睡眠状态,避免了刚开始因为碎块都没有动,所以碎块的速度和角速度都为零,小于我们自己设置的阈值,那么所有的碎块就永远都会是睡眠状态

 

@bullet_sleeping是houdini识别的属性,1代表碎块进入睡眠状态,0代表碎块没有进入睡眠状态

[展开全文]

好记性不如烂笔头

for(int i ;i<npoints(0);i++{

vector cd = point(0,"Cd",i);//读取 cd

vector position = point(0,"P",i);//读取@P

 

 

要分清楚 赋值 和读取的  分别

 

pc cloud中  许多情况需要 一个个id来进行 某一个的 操作 也就是我们常用的 for 函数 

或者可以用for each  

定义一个 初始 inter 和一个数组  array

for each (int ps;pts) ;

 

 

组 里面 可以是 float intger vector

pts[0] 

数组 也就相当于一个选集  在一个选集里面进行循环 就需要 在选集数组里面进行迭代了  

比如我们有数组 pts[]  在其中迭代就是 

要设置 for  loop  或者 for each

 for loop (int i ;i<npoints;i++){

读取数值 ;cd p aa(自定义) 

指向数值;a=b  b=c

赋予数值(修改数值);

 

 

}关于之前的疑惑 

如何快速的获得一些数组  比如 

int pts[] = nearpoints() 找到一些符合半径 符合点数量的 点  第0个几何体上  但是并没有说 在哪一个点上执行搜索;

int pts[] = pcfind()

[展开全文]

最后already_taken并没有被写上数字,失败了,还要回去多检查几遍代码。

[展开全文]

pc啊

intial  0

target 1 

if intial can find one oar more target 

we can setdown its ptnum or id

appen it to some of  a groop or array 

 

iin detail mode maybe thee @P @Cd can notwork??  

you must say oh 

 

vector cd = point(0,"Cd",idx)  here the @ptnum is not work?  okay  so 

by the way that use a emmunaate (枚举)

onebyone untail the @ptnum which is  the max number of the points` number+1;because the number is from zero;

 int idx; idx<npoints(0);'idx++

[展开全文]

VOP中mix节点: 设置一个0-1的bias值, 当为0时使用的是input1, 为1时使用的是input2, 中间进行差值(本例中是基于寿命)

[展开全文]

oceanfoam解算器下 downsample为降低分辨率, 降低为2的()次方, 输入1, 即为降低2的1次方

[展开全文]

popinteract节点:

position force为1: 为排斥力

velocity force为1: 让周围粒子找相邻,共享一个相同的速度,这样就可以有这种条状的效果

[展开全文]

在SDF外的数值大于0, 在SDF内侧的数值小于0, 在SDF表面的数值为0

[展开全文]

wavetank设置: velocity标签下,max extrap cells选项, vel场往外推测的最大数量, 这个数值越高,速度匹配越精准,这里使用8, 影响产生多大的波浪,如果想要更大的波浪,就调大这个数值

 

boundary layer:边界缓冲区域,防止流体模拟时在边缘反弹回来

 

surface evaluation:

主要是max resolution设置, 影响精度,但是不需要特别高的精度,默认8就可以

[展开全文]

guiding surface: 动态的碰撞对象,来控制水的运动

 

guiding sink: 如果有的粒子进入到guiding surface场里比较深, 那这个场就会删除这些粒子,只保留一层, 会回流到上面的粒子中去

 

如果洋面太汹涌,打开gas guiding volume中 stick on guiding surface选项, stick scale如果为1, 则粒子完全跟随guiding surface运动, max distance设置为1, 即只有1米深度的粒子跟随

[展开全文]

for(int i = 0; i < npoints(0); i++){
    // 获取当前正在进行迭代的点的属性
    vector current_P = point(0, "P", i);
    int current_id = point(0, "id", i);
    int branch_count_temp = point(0, "branch_count", i);
    int branch_time_temp = point(0, "branch_time", i);
    
    // 设置两个点云查找需要用到的参数,可以推送到界面,方便进行操作
    float seach_radius = chf("seach_radius");
    int max_points = chi("max_points");
    
    // 设置一个点云查找需要用到的临时变量
    int found_ptnum;
    
    // 设置一个点云的handle
    int handle = pcopen(1, "P", current_P, seach_radius, max_points);
    
    // 开始进行点云的查找迭代
    while(pciterate(handle)){
        pcimport(handle, "point.number", found_ptnum);
    }
}

    

 

 

 

     if(branch_count_temp > -1 && branch_count_temp <= branch_time_temp){
        branch_count_temp += 1;
        setpointattrib(0, "branch_count", idx, branch_count_temp, "set");
    }else if(branch_count_temp > -1 && branch_count_temp > branch_time_temp){
        branch_count_temp = -1;
        setpointattrib(0, "branch_count", idx, branch_count_temp, "set");
        
        setpointattrib(0, "Cd", idx, {0,0,0}, "set");
    }

这一整段代码的作用是使分支闪电存在的时间大于我们设定的时间范围之后,让分支闪电消失掉,之所以写在点云查找迭代的前面,也是因为SOPsolve这个节点在DOP网络里粒子系统中的循环,没有要改动的地方,唯一要改的可能就是我们自己设定的分支闪电存在的时间

[展开全文]