はじめに
Houdiniを使っているとVEXで回転を記述するためには、QuaternionやMatrixを使う必要がどうしても出てきます。また、平行移動はMatrixの成分を利用して掛け算で行うことができます。
そこでここでは、なるべく簡単にVEXでMatrixを使った回転と平行移動する計算の解説をしていきます。
初期状態
Add SOPで原点にポイントを一つ追加した状態から始めます

VEXで作成したパラメーターについて
詳細
Attribute Wrangleのこのアイコンを押すとパラメータが作れます

作成したパラメーターはRangeが0~1 なので
度数法の表記ではパラメーターの変化が見てわからないので
必要に応じてRangeを-360~360などに変更してください
transform Matrixの作成と確認方法
VEX
//run over points
matrix m = ident(); //単位行列の作成
setpointtransform(0, @ptnum, m); //transform attributeの作成
単位行列はWorld Matrixとも言います
World Matrix とはDCCツール毎に決められた基準の軸のことです
ノードネットワーク
VIsualize Attribute
Style : Axes
Attribute : transform
まずこれでHoudiniの座標系であるY-Up右手座標と一致したMatrixが作成できたのが確認できます。次から、このtransformを使って回転と平行移動を行っていきます
回転
quaternion
//run over points
float angle = radians(chf("angle")); //回転用のパラメータを作成し、ラジアン角angleとして使う
matrix3 m = point(0,"transform",@ptnum); //transform matrixを読み込み
//クォーターニオン
vector4 q = quaternion(angle, set(0,1,0));
matrix3 qm = qconvert(q);
m *= qm;
//変換した行列を反映
setpointtransform(0, @ptnum, m); //変化させた transform Mを反映
組み込み関数 rotate
//run over points
float angle = radians(chf("angle")); //回転用のパラメータを作成し、ラジアン角angleとして使う
matrix3 m = point(0,"transform",@ptnum); //transform matrixを読み込み
//回転行列変換
rotate(m, angle, set(0,1,0)); //Y軸を中心にtransform mをパラメーターの値で回転
//変換した行列を反映
setpointtransform(0, @ptnum, m); //変化させた transform Mを反映
quaternionとrotateの比較
結果は同じなので、組み込み関数rotateを使った方が簡単です
quaternion
vector4 q = quaternion(angle, set(0,1,0));
matrix3 qm = qconvert(q);
m *= qm;
rotate
rotate(m, angle, set(0,1,0));
平行移動
ベクトルの成分分離
//run over points
float translate_x = chf("translate_x"); //平行移動用のパラメータを作成
matrix3 m = point(0,"transform",@ptnum); //transform matrixを読み込み
//vectorの成分分離
vector x_axis = set(m.xx,m.xy,m.xz); //x軸成分のベクトルを抜き出し
vector pos = x_axis*translate_x; //x軸方向への移動値を作成
//移動を反映
setpointattrib(0,"P",@ptnum , pos);
pretranslate
//run over points
float translate_x = chf("translate_x"); //平行移動用のパラメータを作成
matrix3 m = point(0,"transform",@ptnum); //transform matrixを読み込み
matrix M = m*ident();
pretranslate(M,set(translate_x,0,0));
setpointtransform(0, @ptnum, M);
なぜtranslate()ではなく、pretranslate()なのか?
かなり分かりづらいところです
今回の計算は 回転->平行移動の順
これは行列の掛け算の順にすると
Translate * Rotate なのでpretranslate()で回転のmatrix3 transformの前に移動の計算を割り込ませているイメージです
行列の掛け算の順番は前掛けと覚えておくと良いと思います
スケールまで含めると
やりたいこと : スケール->回転->平行移動なら
行列の掛け算順 : Translate x Rotate x Scale
肩ひじ張らずに
思った通りいかなかったら
計算順を逆にするかpreをつけるかすれば良いんじゃないでしょうか![]()
まとめ
行列はある程度の慣れが必要な計算です
今回はワールドからスタートしましたが
ご自身で回転や移動値が入った状態から意図通りの結果になるか
試してみると良いと思います。




