VEX —— Matrix

28 篇文章 4 订阅

目录

一,矩阵相关概念

矩阵含义

设置矩阵值 setcomp

常用矩阵相关函数

二,案例

案例:源位置过渡到目标位置

案例:交叉球去穿插

案例:相机投射

案例:路径运动并旋转


参考 https://www.cnblogs.com/vfxJerry/p/12108565.html

一,矩阵相关概念

vex内基于row行vector,vector*matrix==matrix*vector;

向量{x, y, z, w},w=1表示位置,w=0表示方向;

vector3 * matrix4*4, vector3自动转化为vector4(w=1);

  • 3*3矩阵和4*4矩阵之间转换需注意;
  • 创建起始矩阵应是单位矩阵,若为非单位矩阵最后一列应为(0,0,0,1);
  • 矩阵本身即可包含位移、旋转、缩放,旋转和缩放会涉及中心点,所以先后顺序会影响结果;
    • 顺序不影响,4*4中的前3*3矩阵中数值;
    • 如先应用位移,顺序就会影响,4*4中的最后一行位移信息会不一样;

Houdini内主要矩阵类型

  • Identity Matrix,单位矩阵保持不变ident()
  • Translation Matrix,位移矩阵translate()
  • Rotation Matrix,旋转矩阵rotate()

 

矩阵含义

注,可理解为创建新的坐标系相对于世界坐标系,即手搓矩阵,补位(第四列)应为(0,0,0,1);

//表示从世界原点变换到指定位置的坐标
//默认补位都是1
4@m = set(v@x_axis, v@y_axis, v@z_axis, v@P);
@m.xa = @m.ya = @m.za = 0;

设置矩阵值 setcomp

setcomp(@m, 0,0,3);
setcomp(@m, 0,1,3);
setcomp(@m, 0,2,3);

常用矩阵相关函数

ident(),单位矩阵;

translate(),位移矩阵;

rotate(),选择矩阵;

scale(),缩放矩阵;

invert(),反转矩阵;

transpose(),行列交换;

maketransform(),构建3*3/4*4矩阵;

cracktransform(),提取矩阵的位移、旋转或缩放信息;

instance(),实例(使用指定的位置和法线,类似copy);

lookat(),获取朝向矩阵;

slerp(),矩阵或四元数融合;

//变换
4@m=ident();
translate(@m, chv('trans'));
rotate(@m, ch('ang'),4); //x轴1,y轴2,z轴4
scale(@m, chv('scale'));
@P *= @m;
//以m2中心点旋转
matrix m1 = ident();
matrix m2 = detail(1,'xform');
rotate(m1, ch('ang1'), set(1,0,0));
rotate(m2, ch('ang2'), set(0,1,0));
@P *= m1*m2;

二,案例

参考:使用houdini绑定系统里的rigdoctor节点来提取矩阵_哔哩哔哩_bilibili

案例:源位置过渡到目标位置

vector P = point(1, 'P', chi('num'));
vector N = point(1, 'N', chi('num'));
matrix m1 = instance(P, N, chv('scale'));

//方法一,直接插值过渡
@P *= slerp(ident(), m1, ch('bias'));

//方法二,提取各个变换分量,分别插值过渡,最后在合并
vector t,r,s;
cracktransform(0,0,set(0,0,0),m1,t,r,s);
t = lerp(set(0,0,0),t,ch('bias'));
s = lerp(set(1,1,1),s,ch('bias'));
//旋转过渡类似 r = -lerp(set(0,0,0),r,ch('bias'));
vector4 q = eulertoquaternion(radians(r), 0);
vector4 ql = slerp(quaternion(set(0,0,0)),q,ch('bias'));
r = degrees(quaterniontoeuler(ql,0));

@P *= maketransform(0,0,t,r,s);

案例:交叉球去穿插

houdini矩阵使用案例矩阵去除干涉_哔哩哔哩_bilibili

//转化坐标系思路,以相交的切面为新坐标系或以每个球中心点为坐标系
//在copy球前的源点上,记录每个会相交点的坐标系矩阵
i[]@nearpts = nearpoints(0, @P, 1);
pop(@nearpts, 0);

matrix mat[];
foreach(int pt; i[]@nearpts){
    vector P1 = point(0,"P",pt);
    float pscale1 = point(0,"pscale",pt);
    float len = length(@P-P1);
    
    //lenx相交面的中心点到附件点的距离
    if(len < @pscale + pscale1){
        float lenx = len/2 + (pow(@pscale,2)-pow(pscale1,2))/(2*len);
    
        vector x = normalize(P1-@P);
        vector y = set(0,1,0);
        vector z = normalize(cross(x,y));
        vector pos = @P+x*lenx;
        
        matrix m = set(x,y,z,pos);
        m.xa = m.ya = m.za = 0;
    
        append(mat, m);
    }
}

4[]@mat = mat;
//在copy后的球上,应用矩阵
foreach(matrix m; 4[]@mat){
    @P *= invert(m);
    if(@P.x>0){
        //@Cd = 0;
        @P.x = 0;
    }  
    @P *= m;  
}

案例:相机投射

//投射平面变换到相机位置,并-Z轴偏移
matrix cam_matrix = optransform(chsop('path')); //提取obj层级的变换
@P *= cam_matrix;

//1号端口为相交模型
vector cam_pos = set(0,0,0)*cam_matrix;
vector dir = @P-cam_pos;
vector p, uvw;
int prim = intersect(1, cam_pos, dir, p, uvw);

if(prim>-1){
    @P=p;
    @Cd = primuv(1, 'Cd', prim, uvw);    
}
else 
    @Cd = 0;

 

案例:路径运动并旋转

//获取路径参考点的信息
vector x = normalize(point(1, 'tangentu', 0));
vector z = normalize(cross(set(0,1,0), x));
vector y = normalize(cross(x, z));
vector pos = point(1, 'P', 0);

注,方法一与以下其他方法,旋转位置会有偏差;

  • 方法一,是先将所有轴都设置(对齐)为指定的 x/y/z 轴,在旋转y轴;
  • 其他方法都是,先将y轴设置(对齐)为指定y轴,在旋转y轴(或先旋转在对齐);
//方法一,手搓矩阵
//先调整坐标系,在原地旋转,位移
matrix m = set(x, y, z, set(0,0,0));
m.xa = m.ya = m.za = 0;
rotate(m, radians(@Frame*20), y);
translate(m, pos);

@P *= m;
//方法二,四元数或矩阵,也是原地旋转,在位移
//注,可将rot设置为orient属性,在使用copy节点
vector4 rot1 = dihedral(set(0,1,0), y);
vector4 rot2 = quaternion(radians(set(0,1,0)*@Frame*20));
vector4 rot = qmultiply(rot1, rot2); //先rot2,在rot1

@P = qrotate(rot, @P);
@P += pos;
vector4 rot1 = dihedral(set(0,1,0), y);
vector4 rot2 = quaternion(radians(y*@Frame*20));
vector4 rot = qmultiply(rot2, rot1); //先rot1,在rot2

@P = qrotate(rot, @P);
@P += pos;
vector4 q = dihedral(set(0,1,0), y);

matrix m = ident();
rotate(m, radians(@Frame*20), y);
translate(m, pos);

@P = qrotate(q, @P);
@P*=m;
//方法三,maketransform函数,也是原地旋转,在位移
//pr只是调整坐标系
vector4 q = dihedral(set(0,1,0), y);
vector pr = degrees(quaterniontoeuler(q, 0));
vector rot = set(0,1,0)*@Frame*20; 

@P = qrotate(q, @P);
matrix m = maketransform(0,0,0,rot,1,0,pr); //沿新坐标系的y轴旋转
translate(m, pos);
@P *= m;
//方法四,instance函数
//此函数是先计算orient参数,在计算rotate参数,有先后顺序不可写反
vector4 rot1 = dihedral(set(0,1,0), y);
vector4 rot2 = quaternion(radians(set(0,1,0)*@Frame*20));

matrix m = instance(pos, 0, 1, rot1, rot2, 0);
@P *= m;
vector4 rot1 = dihedral(set(0,1,0), y);
vector4 rot2 = quaternion(radians(y*@Frame*20));

matrix m = instance(pos, 0, 1, rot2, rot1, 0);
@P *= m;
vector4 rot1 = dihedral(set(0,1,0), y);
vector4 rot2 = quaternion(radians(set(0,1,0)*@Frame*20));
vector4 orient = qmultiply(rot1, rot2); //先rot2,在rot1

matrix m = instance(pos, 0, 1, 0, orient, 0);
@P *= m;

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值