HoudiniVex笔记_P25_ForceExtended力进阶

原视频:https://www.youtube.com/playlist?list=PLzRzqTjuGIDhiXsP0hN3qBxAZ6lkVfGDI
Bili:Houdini最强VEX算法教程 - VEX for Algorithmic Design_哔哩哔哩_bilibili

Houdini版本:19.5

如有错误,可在评论区指正。

1、本章主要讲引力相关

万有引力公式:

本章主要是根据引力相关进行延伸、拓展等,(l 为距离,direction为运动的方向),

还有个关于万有引力的相关重要知识点: 引力的大小跟这两个物体的质量的乘积成正比,跟它们的距离的二次方成反比。

 2、引力

本小节来实现下引力,总体难度不大,原理如下图,

 eg.①先上结果,主要是根据上面,

②节点连接及设置,更多的是对参数进行设置、调试,

③补充,解算器solver内的attractor_force节点代码如下,

float massM = f@mass;
float massA = point(1, 'mass', 0);

vector attractorPos = point(1, 'P', 0);

float l = distance(@P, attractorPos);

float g = point(1, 'gravitation', 0);

vector v = normalize(attractorPos - @P);    //运动方向

float s = massM * massA * g / (l * l);
s= clamp(s, chf('minforce'), chf('maxforce'));    //谨防出现无穷大或无穷小的力

vector force = v * s;

v@vel += force;
v@vel = normalize(v@vel) * min(length(v@vel), chf('maxspeed')); //对速度进行限制

v@P += v@vel;

 3、多重引力

多个引力体与多个被吸引体。

eg.①先上结果,案例与上面差不多,

②节点连接及设置,可对参数进行设置、调试,看看不同参数的结果,

③补充,解算器solver内的attractor_force节点代码如下,

float massM = f@mass;

//该点受到不同引力体吸引的的总引力
vector totalForce = set(0,0,0);
for(int i=0; i<npoints(1); i++){
    float massA = point(1, 'mass', i);
    
    vector attractorPos = point(1, 'P', i);
    
    float l = distance(@P, attractorPos);
    
    float g = point(1, 'gravitation', i);
    
    vector v = normalize(attractorPos - @P);    //运动方向
    
    float s = massM * massA * g / (l * l);
    s= clamp(s, chf('minforce'), chf('maxforce'));  //谨防出现无穷大或无穷小的力
    
    vector force = v * s;
    totalForce += force;
}

v@vel += totalForce;
v@vel = normalize(v@vel) * min(length(v@vel), chf('maxspeed')); //对速度进行限制

v@P += v@vel;

 4、引力与朝向

与前面相同,这次设置了法线(@N= 速度),以及使引力体动起来。

eg.①先上结果,

②节点连接及设置,
③ 补充,两个解算器内的代码如下, attractor_force节点

//solver5节点内的代码:引力体对象在范围内随机运动
vector pos = @P * 0.01;
vector4 pos4 = set(pos.x, pos.y, pos.z, @Time);

vector f1 = curlnoise(pos4);
vector f2 = set(0,0,0);

//在体积外层,给一个往内的力,把它拉回来
float val = volumesample(1, 'surface', @P);
if(val>0){
    f2 = -volumegradient(1, 'surface', @P);
}

vector force = (f1 + f2) * chf('k');

v@vel += force;
v@vel= normalize(v@vel) * min(length(v@vel), chf('maxvel'));

@P += v@vel;
//    solver4内的attractor_force节点代码
float massM = f@mass;

//该点受到不同引力体吸引的的总引力
vector totalForce = set(0,0,0);
for(int i=0; i<npoints(1); i++){
    float massA = point(1, 'mass', i);
    
    vector attractorPos = point(1, 'P', i);
    
    float l = distance(@P, attractorPos);
    
    float g = point(1, 'gravitation', i);
    
    vector v = normalize(attractorPos - @P);    //运动方向
    
    float s = massM * massA * g / (l * l);
    s= clamp(s, chf('minforce'), chf('maxforce'));    //谨防出现无穷大或无穷小的力
    
    vector force = v * s;
    totalForce += force;
}

v@vel += totalForce;
v@vel = normalize(v@vel) * min(length(v@vel), chf('maxspeed')); //对速度进行限制

v@P += v@vel;

v@N = normalize(v@vel);

5、角向力/旋转力

以力作角度,绕引力体做环绕运动。原理大概如下,

 eg.①老规矩,先上结果,
② 节点连接及设置,

③补充,解算器solver内的angular_force节点代码如下, 

vector posC = point(1, 'P', 0);
float massC = point(1, 'mass', 0);
float massM = f@mass;
float g = point(1, 'gravitation', 0);
float l = distance(@P, posC);

float f = massM * massC * g / (l * l);
f = min(f, chf('maxforce'));

f@ang += f;
f@ang = min(f@ang, chf('maxang'));

matrix mat = ident();
rotate(mat, f@ang, set(0,1,0));

@P -= posC; //要旋转,先归位至轴点。否则默认以(0,0,0)为轴点旋转
@P *= mat;
@P += posC;

6、自转与角运动 

与【5的例子】类似,对被吸引的对象添加自转运动
关于自转,只关注自身,其它的力(如引力)不管,原理大概如下,

 eg.①结果略
② 直接使用【5、角向力/旋转力】的案例,仅对修改部分进行标注,节点连接及设置如下,

③补充,解算器solver内的angular_motion节点代码如下, 

float mass = f@mass;
float g = f@gravitation;  //一个自定义力,或者说是系数

float force = mass * g;
force = min(force, chf('maxforce'));

f@angM += force;
f@angM = min(f@angM, chf('maxang'));

matrix mat = ident();
rotate(mat, f@angM, set(0,1,0));

v@N *= mat;

7、单摆运动

原理大概如下,

 eg.在Houdini中实现单摆运动,
①节点连接及设置如下,

②补充,完整代码如下, 

f@ang = radians(chf('ang'));    // 角度随意

vector axis = set(0,0,1);
matrix mat = ident();
rotate(mat, f@ang, axis);

@P *= mat;
f@mass = chf('mass');       // 角度随意
f@pscale = f@mass * 0.2;    // 尺寸随意
float l = prim(0, 'perimeter', 0);
float g = chf('gravity');     //设为0.5/任意值
float mass = f@mass;

float force = -g * mass * sin(f@ang) / l;
f@vel += force;
f@vel *= chf('damping');  //衰减系数(摩擦力之类),设为0.995/任意值

f@ang += f@vel;

vector dir = set(0, -1, 0);
matrix mat = ident();
rotate(mat, f@ang, set(0,0,1));
dir *= mat;

@P = dir * l;

 ③结果略

8、多对象单摆运动

与【7、单摆运动】差不多,这次使用For-each-number循环生成多条单摆线

 eg.①节点连接及设置如下,

 ②完整代码如下,

//  解算器Solver内代码节点的代码

//ball属性的点,代码执行
int prim = pointprims(0, @ptnum)[0];    //该点所在的primitive
int pivotpt = primpoints(0, prim)[0];   //该primitive的第一个点作为轴点

vector pivotPos = point(0, 'P', pivotpt);   //轴点位置

float l = prim(0, 'perimeter', prim);
float g = chf('gravity');     //设为0.5/任意值
float mass = f@mass;

float force = -g * mass * sin(f@ang) / l;
f@vel += force;
f@vel *= chf('damping');  //衰减系数(摩擦力之类),设为0.995/任意值

f@ang += f@vel;

vector dir = set(0, -1, 0);
matrix mat = ident();
rotate(mat, f@ang, set(0,0,1));
dir *= mat;

@P = pivotPos + dir * l;
//    setup节点内代码,循环生成多条线
int ite = detail(1, 'iteration');
int numite = detail(1, 'numiterations');

@P.z = ite; 

float minlen = chf('minlen');
float maxlen = chf('maxlen');

float y = fit(ite, 0, numite-1, 0, $PI * 4);
y = -fit11(sin(y), minlen, maxlen);

if(inpointgroup(0, 'ball', @ptnum) == 1){ //保险起见,加多ball做判断条件
    @P.y = y;
}

 9、弹力

 具有约束性的弹力,就像单摆加了根弹力绳,

受力分析及公式推导大概如下 ,

eg.①在Houdini里实现上面动图的效果,节点连接及设置如下,

②补充,完整代码如下,

//  init6 节点代码

f@mass = chf('amss');     //参数设为1或随意
f@targetlength = chf('target'); //参数设为0.5或随意

f@pscale = f@mass * 0.25;
v@vel = set(0,0,0);
//解算器内的spring_force节点代码

vector pivotPos = point(0, 'P', 0);
vector v = normalize(pivotPos - @P);

float l = distance(pivotPos, @P);
float tl = f@targetlength;
float diffl = l - tl;
float n = chf('stiffness'); //  "绳子"的弹性系数

vector f1 = v * f@mass * (diffl * diffl) * diffl / abs(diffl) * n ;
f1 = normalize(f1) * min(length(f1), chf('maxforce1'));

vector f2 = set(0, -1, 0) * chf('gravity') * f@mass;

v@vel += f1;
v@vel += f2;

v@vel *= chf('dampling');   //摩擦系数

@P += v@vel;

③可以去试试调下参数,感受各个参数对结果的影响。

10、弹力“链”

这次是实现下面这种效果,

受力分析及公式推导大概如下 ,

 eg.①在Houdini里实现上面动图的效果,节点连接及设置如下,

②补充,完整代码如下,

//    init7 节点代码,节点类型为Points

if(@ptnum == 0 || @ptnum == npoints(0) - 1){
    //后面用作固定首末两个点
    setpointgroup(0, 'pin', @ptnum, 1);
}

f@mass = chf('mass');   //设为0.1或随意
v@vel = set(0,0,0);
//    init_prim 节点代码,类型为Primitives
f@targetlength = f@perimeter;
//    spring_force节点代码,节点类型为Primitives

int pts[] = primpoints(0, @primnum);

//每两个点之间的弹力
for(int i=0; i<len(pts); i++){
    int pt1 = pts[i];
    int pt2 = pts[(i+1) % len(pts)];
    
    vector pos1 = point(0, 'P', pt1);
    vector pos2 = point(0, 'P', pt2);
    float mass1 = point(0, 'mass', pt1);
    float mass2 = point(0, 'mass', pt2);
    
    vector v = normalize(pos2 - pos1);
    float l = distance(pos1, pos2);
    float tl = f@targetlength;
    float diffl = l - tl;
    
    float n = chf('stiffness');
    
    vector force = v * (diffl * diffl) * (diffl / abs(diffl)) * n;//  *mass1 * mass2 *    
    force = normalize(force) * min(length(force), chf('maxforce'));
    
    setpointattrib(0, 'vel', pt1, force, 'add'); 
}
//    gravity_force 节点代码,类型为Points

vector force = set(0, -1, 0) * chf('gravity');

v@vel += force * f@mass;
//    update_pos 节点代码,节点类型为Points

if(inpointgroup(0, 'pin', @ptnum) == 0){
    //非首末两个点,位置更新
    v@vel *= chf('dampling');   //摩擦系数
    @P += v@vel;
}else if(@ptnum == 0){  //第一个点,位置更新
    @P = point(1, 'P', 0);
}

没有又找不着翻译,不能倍速看,很烦,只能啃英语生番原速看…

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值